]> git.lyx.org Git - lyx.git/blob - src/frontends/qt2/QBrowseBox.C
better selection and scrolling behaviour
[lyx.git] / src / frontends / qt2 / QBrowseBox.C
1 /**
2  * \file QBrowseBox.C
3  *
4  * Original file taken from klyx 0.10 sources:
5  *
6  * \author Kalle Dalheimer
7  *
8  * Full author contact details are available in file CREDITS
9  */
10
11 #include <config.h>
12
13 #include <qstring.h>
14 #include <qpixmap.h>
15 #include <qkeycode.h>
16 #include <qpainter.h>
17 #include <qapplication.h>
18 #include <qdrawutil.h>
19 #include <qstyle.h>
20 #include <qimage.h>
21
22 #include "QBrowseBox.h"
23
24 #include <cstdio>
25 #include <cmath>
26
27
28 QBrowseBox::QBrowseBox(int rows, int cols, QWidget* parent, const char* name, WFlags f)
29         : QGridView(parent,name,f)
30 {
31         setNumRows(rows);
32         setNumCols(cols);
33         setCellWidth(width()/cols);
34         setCellHeight(height()/rows);
35
36         texts_   = new QString[rows * cols];
37         pixmaps_ = new QPixmap[rows * cols];
38
39         activecell_.setX(-1);
40         activecell_.setY(-1);
41
42         if (style().inherits("QWindowsStyle"))
43                 setFrameStyle(QFrame::WinPanel | QFrame::Raised);
44         else
45                 setFrameStyle(QFrame::Panel | QFrame::Raised);
46
47         viewport()->setFocusPolicy(QWidget::StrongFocus);
48         // setMouseTracking must be called after setFocusPolicy
49         viewport()->setMouseTracking(true);
50         inloop=false;
51
52 }
53
54
55
56 QBrowseBox::~QBrowseBox()
57 {
58         delete [] texts_;
59         delete [] pixmaps_;
60 }
61
62
63 int QBrowseBox::coordsToIndex(int row, int col)
64 {
65         if (col < 0 || col > numCols() || row < 0 ||  row > numRows())
66                 qDebug("coordsToIndex: invalid coords (%d, %d)\n", row, col);
67         return row + col * numCols();
68 }
69
70
71 void QBrowseBox::insertItem(QString const & text, int row, int col)
72 {
73         texts_[coordsToIndex(row, col)] = text;
74 }
75
76
77 void QBrowseBox::insertItem(char const * text, int row, int col)
78 {
79         insertItem(QString(text), row, col);
80 }
81
82
83 void QBrowseBox::insertItem(QPixmap pixmap, int row, int col)
84 {
85         pixmaps_[coordsToIndex(row, col)] = pixmap;
86 }
87
88
89 void QBrowseBox::insertItem( QPixmap pixmap)
90 {
91         int w = pixmap.width() / numCols();
92         int h = pixmap.height() / numRows();
93
94         for (int row = 0; row < numRows(); ++row)
95                 for (int col = 0; col < numCols(); ++col) {
96                         QPixmap small(w,h);
97                         bitBlt(&small,0,0,&pixmap,col*w,row*h,w,h,Qt::CopyROP,false);
98                         insertItem(small, row, col);
99                 }
100
101         resize(pixmap.width() + (numCols() + 1) * frameWidth(),
102                pixmap.height() + (numRows() + 1) * frameWidth());
103 }
104
105
106 void QBrowseBox::removeItem(int row, int col)
107 {
108         texts_[coordsToIndex(row, col)] = "";
109         pixmaps_[coordsToIndex(row, col)].resize(0, 0);
110 }
111
112
113 void QBrowseBox::clear()
114 {
115         for (int row = 0; row < numRows(); ++row)
116                 for (int col = 0; col < numCols(); ++col)
117                         removeItem(row, col);
118 }
119
120
121 QString QBrowseBox::text(int row, int col)
122 {
123         if (col < 0 || col >= numCols() || row < 0 || row >= numRows())
124                 return "";
125         return texts_[coordsToIndex(row, col)];
126 }
127
128 QPixmap QBrowseBox::pixmap(int row, int col)
129 {
130         if (col < 0 || col >= numCols() || row < 0 || row >= numRows())
131                 return QPixmap();
132         return pixmaps_[coordsToIndex(row, col)];
133 }
134
135 int QBrowseBox::exec(const QPoint& pos)
136 {
137         return exec(pos.x(),pos.y());
138 }
139
140 int QBrowseBox::exec(const QWidget* trigger)
141 {
142         QPoint globalpos = trigger->parentWidget()->mapToGlobal( trigger->pos());
143         // is there enough space to put the box below the trigger?
144         if ( globalpos.y() + trigger->height()+height()+1<
145              QApplication::desktop()->height()) {
146                 // is there enough space to set the box left-justified with the trigger
147                 if (globalpos.x()+width()<QApplication::desktop()->width())
148                         return exec(globalpos.x(),
149                                     globalpos.y()+trigger->height()+1);
150                 else
151                         return exec(globalpos.x()-width()-1,
152                                     globalpos.y()+trigger->height()+1);
153         } else {
154                 if (globalpos.x()+width()<QApplication::desktop()->width())
155                         return exec(globalpos.x(),
156                                     globalpos.y()-height()-1);
157                 else
158                         return exec(globalpos.x()-width()-1,
159                                     globalpos.y()-height()-1);
160         }
161 }
162
163 int QBrowseBox::exec(int x,int y)
164 {
165         firstrelease_ = true;
166         move(x,y);
167         show();
168         repaint();
169         qApp->enter_loop();
170         inloop = true;
171
172         if (activecell_.x()!=-1 && activecell_.y()!=-1 )
173                 return coordsToIndex( activecell_.x(),activecell_.y());
174         else
175                 return -1;
176 }
177
178 void QBrowseBox::keyPressEvent(QKeyEvent * e)
179 {
180         switch(e->key()) {
181         case Key_Up:
182                 moveUp();
183                 break;
184         case Key_Down:
185                 moveDown();
186                 break;
187         case Key_Left:
188                 moveLeft();
189                 break;
190         case Key_Right:
191                 moveRight();
192                 break;
193         case Key_Return:
194                 emit selected(activecell_.x(), activecell_.y());
195                 if ( isVisible() && parentWidget() &&
196                      parentWidget()->inherits("QPopupMenu") )
197                         parentWidget()->close();
198                 else
199                         close();
200                 break;
201         case Key_Escape:
202                 if (inloop)
203                         qApp->exit_loop();
204                 if ( isVisible() && parentWidget() &&
205                      parentWidget()->inherits("QPopupMenu") )
206                         parentWidget()->close();
207         default:
208                 e->ignore();
209         }
210 }
211
212 void QBrowseBox::contentsMouseReleaseEvent(QMouseEvent *)
213 {
214
215         if (firstrelease_)
216                 firstrelease_ = false;
217         else {
218                 emit selected( activecell_.x(), activecell_.y());
219                 if ( isVisible() && parentWidget() &&
220                      parentWidget()->inherits("QPopupMenu") )
221                         parentWidget()->close();
222         }
223 }
224
225 void QBrowseBox::closeEvent(QCloseEvent * e)
226 {
227         e->accept();
228         qApp->exit_loop();
229 }
230
231 void QBrowseBox::paintCell(QPainter * painter, int row, int col)
232 {
233         painter->setClipRect(cellGeometry(row,col));//, QPainter::CoordPainter);
234         bool ispixmap = false;
235
236         if (!pixmaps_[coordsToIndex(row,col)].isNull()) {
237                 painter->drawPixmap(0,0,pixmaps_[coordsToIndex(row, col)]);
238                 ispixmap = true;
239         }
240
241         if (activecell_.x() == row && activecell_.y() == col) {
242                 if (ispixmap)
243                         qDrawShadeRect(painter, 0, 0, cellWidth(),
244                                        cellHeight(), colorGroup(), false, 1);
245                 else
246                         qDrawShadePanel(painter, 0, 0, cellWidth(),
247                                         cellHeight(), colorGroup(), false, 1);
248         } else {
249                 qDrawPlainRect(painter, 0, 0, cellWidth(),
250                                cellHeight(), colorGroup().background(), 1);
251         }
252
253         if (!texts_[coordsToIndex(row, col)].isEmpty()) {
254                 painter->drawText(0, 0, cellWidth(),
255                                   cellHeight(), AlignCenter,
256                                   texts_[coordsToIndex(row, col)]);
257         }
258         painter->setClipping(false);
259 }
260
261
262 void QBrowseBox::resizeEvent(QResizeEvent * e)
263 {
264         QGridView::resizeEvent(e);
265         setCellWidth(contentsRect().width() / numCols());
266         setCellHeight(contentsRect().height() / numRows());
267 }
268
269
270 void QBrowseBox::contentsMouseMoveEvent(QMouseEvent * e)
271 {
272         int x = e->pos().x();
273         int y = e->pos().y();
274
275         int cellx;
276         int celly;
277
278         if (x < 0 || y < 0 || x > width() || y > height()) {
279                 // outside the box
280                 cellx = -1;
281                 celly = -1;
282         } else {
283                 celly = (int)floor( ((double)x) / ((double)cellWidth()) );
284                 cellx = (int)floor( ((double)y) / ((double)cellHeight()) );
285         }
286
287         if (activecell_.x() != cellx || activecell_.y() != celly) {
288                 // mouse has been moved to another cell
289                 int oldactivecellx = activecell_.x();
290                 int oldactivecelly = activecell_.y();
291                 activecell_.setX(cellx);
292                 activecell_.setY(celly);
293                 // remove old highlighting
294                 updateCell(oldactivecellx, oldactivecelly);
295                 // set new highlighting
296                 updateCell(activecell_.x(), activecell_.y());
297         }
298 }
299
300
301 void QBrowseBox::moveLeft()
302 {
303         int const y = activecell_.y();
304
305         if (y>0)
306                 activecell_.setY(y - 1);
307         else if (parentWidget())
308                 QWidget::focusNextPrevChild(false);
309
310         updateCell(activecell_.x(), y);
311         updateCell(activecell_.x(), activecell_.y());
312 }
313
314
315 void QBrowseBox::moveRight()
316 {
317         int const y = activecell_.y();
318
319         if (y < numCols() - 1)
320                 activecell_.setY(y+1);
321
322         updateCell(activecell_.x(), y);
323         updateCell(activecell_.x(), activecell_.y());
324 }
325
326
327 void QBrowseBox::moveUp()
328 {
329         int const x = activecell_.x();
330
331         if (x > 0)
332                 activecell_.setX(x - 1);
333         else if (parentWidget())
334                 QWidget::focusNextPrevChild(false);
335
336         updateCell(x, activecell_.y());
337         updateCell(activecell_.x(), activecell_.y());
338 }
339
340
341 void QBrowseBox::moveDown()
342 {
343         int const x = activecell_.x();
344
345         if (x < numRows() - 1)
346                 activecell_.setX(x + 1);
347
348         updateCell(x, activecell_.y());
349         updateCell(activecell_.x(), activecell_.y());
350 }