source: trunk/src/gui/kernel/qgridlayout.cpp@ 324

Last change on this file since 324 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 55.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qgridlayout.h"
43#include "qapplication.h"
44#include "qwidget.h"
45#include "qlist.h"
46#include "qsizepolicy.h"
47#include "qvector.h"
48#include "qvarlengtharray.h"
49#include "qlayoutengine_p.h"
50#include "qlayout_p.h"
51
52QT_BEGIN_NAMESPACE
53
54struct QGridLayoutSizeTriple
55{
56 QSize minS;
57 QSize hint;
58 QSize maxS;
59};
60
61/*
62 Three internal classes related to QGridLayout: (1) QGridBox is a
63 QLayoutItem with (row, column) information and (torow, tocolumn) information; (3) QGridLayoutData is
64 the internal representation of a QGridLayout.
65*/
66
67class QGridBox
68{
69public:
70 QGridBox(QLayoutItem *lit) { item_ = lit; }
71
72 QGridBox(const QLayout *l, QWidget *wid) { item_ = QLayoutPrivate::createWidgetItem(l, wid); }
73 ~QGridBox() { delete item_; }
74
75 QSize sizeHint() const { return item_->sizeHint(); }
76 QSize minimumSize() const { return item_->minimumSize(); }
77 QSize maximumSize() const { return item_->maximumSize(); }
78 Qt::Orientations expandingDirections() const { return item_->expandingDirections(); }
79 bool isEmpty() const { return item_->isEmpty(); }
80
81 bool hasHeightForWidth() const { return item_->hasHeightForWidth(); }
82 int heightForWidth(int w) const { return item_->heightForWidth(w); }
83
84 void setAlignment(Qt::Alignment a) { item_->setAlignment(a); }
85 void setGeometry(const QRect &r) { item_->setGeometry(r); }
86 Qt::Alignment alignment() const { return item_->alignment(); }
87 QLayoutItem *item() { return item_; }
88 QLayoutItem *takeItem() { QLayoutItem *i = item_; item_ = 0; return i; }
89
90 int hStretch() { return item_->widget() ?
91 item_->widget()->sizePolicy().horizontalStretch() : 0; }
92 int vStretch() { return item_->widget() ?
93 item_->widget()->sizePolicy().verticalStretch() : 0; }
94
95private:
96 friend class QGridLayoutPrivate;
97 friend class QGridLayout;
98
99 inline int toRow(int rr) const { return torow >= 0 ? torow : rr - 1; }
100 inline int toCol(int cc) const { return tocol >= 0 ? tocol : cc - 1; }
101
102 QLayoutItem *item_;
103 int row, col;
104 int torow, tocol;
105};
106
107class QGridLayoutPrivate : public QLayoutPrivate
108{
109 Q_DECLARE_PUBLIC(QGridLayout)
110public:
111 QGridLayoutPrivate();
112
113 void add(QGridBox*, int row, int col);
114 void add(QGridBox*, int row1, int row2, int col1, int col2);
115 QSize sizeHint(int hSpacing, int vSpacing) const;
116 QSize minimumSize(int hSpacing, int vSpacing) const;
117 QSize maximumSize(int hSpacing, int vSpacing) const;
118
119 Qt::Orientations expandingDirections(int hSpacing, int vSpacing) const;
120
121 void distribute(QRect rect, int hSpacing, int vSpacing);
122 inline int numRows() const { return rr; }
123 inline int numCols() const { return cc; }
124 inline void expand(int rows, int cols)
125 { setSize(qMax(rows, rr), qMax(cols, cc)); }
126 inline void setRowStretch(int r, int s)
127 { expand(r + 1, 0); rStretch[r] = s; setDirty(); }
128 inline void setColStretch(int c, int s)
129 { expand(0, c + 1); cStretch[c] = s; setDirty(); }
130 inline int rowStretch(int r) const { return rStretch.at(r); }
131 inline int colStretch(int c) const { return cStretch.at(c); }
132 inline void setRowMinimumHeight(int r, int s)
133 { expand(r + 1, 0); rMinHeights[r] = s; setDirty(); }
134 inline void setColumnMinimumWidth(int c, int s)
135 { expand(0, c + 1); cMinWidths[c] = s; setDirty(); }
136 inline int rowSpacing(int r) const { return rMinHeights.at(r); }
137 inline int colSpacing(int c) const { return cMinWidths.at(c); }
138
139 inline void setReversed(bool r, bool c) { hReversed = c; vReversed = r; }
140 inline bool horReversed() const { return hReversed; }
141 inline bool verReversed() const { return vReversed; }
142 inline void setDirty() { needRecalc = true; hfw_width = -1; }
143 inline bool isDirty() const { return needRecalc; }
144 bool hasHeightForWidth(int hSpacing, int vSpacing);
145 int heightForWidth(int width, int hSpacing, int vSpacing);
146 int minimumHeightForWidth(int width, int hSpacing, int vSpacing);
147
148 inline void getNextPos(int &row, int &col) { row = nextR; col = nextC; }
149 inline int count() const { return things.count(); }
150 QRect cellRect(int row, int col) const;
151
152 inline QLayoutItem *itemAt(int index) const {
153 if (index < things.count())
154 return things.at(index)->item();
155 else
156 return 0;
157 }
158 inline QLayoutItem *takeAt(int index) {
159 QLayoutItem *item = 0;
160 if (index < things.count()) {
161 QGridBox *b = things.takeAt(index);
162 if (b) {
163 item = b->takeItem();
164 delete b;
165 }
166 }
167 return item;
168 }
169
170 void getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan) {
171 if (index < things.count()) {
172 QGridBox *b = things.at(index);
173 int toRow = b->toRow(rr);
174 int toCol = b->toCol(cc);
175 *row = b->row;
176 *column = b->col;
177 *rowSpan = toRow - *row + 1;
178 *columnSpan = toCol - *column +1;
179 }
180 }
181 void deleteAll();
182
183private:
184 void setNextPosAfter(int r, int c);
185 void recalcHFW(int w);
186 void addHfwData(QGridBox *box, int width);
187 void init();
188 QSize findSize(int QLayoutStruct::*, int hSpacing, int vSpacing) const;
189 void addData(QGridBox *b, const QGridLayoutSizeTriple &sizes, bool r, bool c);
190 void setSize(int rows, int cols);
191 void setupSpacings(QVector<QLayoutStruct> &chain, QGridBox *grid[], int fixedSpacing,
192 Qt::Orientation orientation);
193 void setupLayoutData(int hSpacing, int vSpacing);
194 void setupHfwLayoutData();
195 void effectiveMargins(int *left, int *top, int *right, int *bottom) const;
196
197 int rr;
198 int cc;
199 QVector<QLayoutStruct> rowData;
200 QVector<QLayoutStruct> colData;
201 QVector<QLayoutStruct> *hfwData;
202 QVector<int> rStretch;
203 QVector<int> cStretch;
204 QVector<int> rMinHeights;
205 QVector<int> cMinWidths;
206 QList<QGridBox *> things;
207
208 int hfw_width;
209 int hfw_height;
210 int hfw_minheight;
211 int nextR;
212 int nextC;
213
214 int horizontalSpacing;
215 int verticalSpacing;
216 int leftMargin;
217 int topMargin;
218 int rightMargin;
219 int bottomMargin;
220
221 uint hReversed : 1;
222 uint vReversed : 1;
223 uint needRecalc : 1;
224 uint has_hfw : 1;
225 uint addVertical : 1;
226};
227
228void QGridLayoutPrivate::effectiveMargins(int *left, int *top, int *right, int *bottom) const
229{
230 int l = leftMargin;
231 int t = topMargin;
232 int r = rightMargin;
233 int b = bottomMargin;
234#ifdef Q_WS_MAC
235 int leftMost = INT_MAX;
236 int topMost = INT_MAX;
237 int rightMost = 0;
238 int bottomMost = 0;
239
240 QWidget *w = 0;
241 const int n = things.count();
242 for (int i = 0; i < n; ++i) {
243 QGridBox *box = things.at(i);
244 QLayoutItem *itm = box->item();
245 w = itm->widget();
246 if (w) {
247 bool visualHReversed = hReversed != (w->layoutDirection() == Qt::RightToLeft);
248 QRect lir = itm->geometry();
249 QRect wr = w->geometry();
250 if (box->col <= leftMost) {
251 if (box->col < leftMost) {
252 // we found an item even closer to the margin, discard.
253 leftMost = box->col;
254 if (visualHReversed)
255 r = rightMargin;
256 else
257 l = leftMargin;
258 }
259 if (visualHReversed) {
260 r = qMax(r, wr.right() - lir.right());
261 } else {
262 l = qMax(l, lir.left() - wr.left());
263 }
264 }
265 if (box->row <= topMost) {
266 if (box->row < topMost) {
267 // we found an item even closer to the margin, discard.
268 topMost = box->row;
269 if (vReversed)
270 b = bottomMargin;
271 else
272 t = topMargin;
273 }
274 if (vReversed)
275 b = qMax(b, wr.bottom() - lir.bottom());
276 else
277 t = qMax(t, lir.top() - wr.top());
278 }
279 if (box->toCol(cc) >= rightMost) {
280 if (box->toCol(cc) > rightMost) {
281 // we found an item even closer to the margin, discard.
282 rightMost = box->toCol(cc);
283 if (visualHReversed)
284 l = leftMargin;
285 else
286 r = rightMargin;
287 }
288 if (visualHReversed) {
289 l = qMax(l, lir.left() - wr.left());
290 } else {
291 r = qMax(r, wr.right() - lir.right());
292 }
293
294 }
295 if (box->toRow(rr) >= bottomMost) {
296 if (box->toRow(rr) > bottomMost) {
297 // we found an item even closer to the margin, discard.
298 bottomMost = box->toRow(rr);
299 if (vReversed)
300 t = topMargin;
301 else
302 b = bottomMargin;
303 }
304 if (vReversed)
305 t = qMax(t, lir.top() - wr.top());
306 else
307 b = qMax(b, wr.bottom() - lir.bottom());
308 }
309 }
310 }
311
312#endif
313 if (left)
314 *left = l;
315 if (top)
316 *top = t;
317 if (right)
318 *right = r;
319 if (bottom)
320 *bottom = b;
321}
322
323QGridLayoutPrivate::QGridLayoutPrivate()
324{
325 addVertical = false;
326 setDirty();
327 rr = cc = 0;
328 nextR = nextC = 0;
329 hfwData = 0;
330 hReversed = false;
331 vReversed = false;
332 horizontalSpacing = -1;
333 verticalSpacing = -1;
334}
335
336#if 0
337QGridLayoutPrivate::QGridLayoutPrivate(int nRows, int nCols)
338 : rowData(0), colData(0)
339{
340 init();
341 if (nRows < 0) {
342 nRows = 1;
343 addVertical = false;
344 }
345 if (nCols < 0) {
346 nCols = 1;
347 addVertical = true;
348 }
349 setSize(nRows, nCols);
350}
351#endif
352
353void QGridLayoutPrivate::deleteAll()
354{
355 while (!things.isEmpty())
356 delete things.takeFirst();
357 delete hfwData;
358}
359
360bool QGridLayoutPrivate::hasHeightForWidth(int hSpacing, int vSpacing)
361{
362 setupLayoutData(hSpacing, vSpacing);
363 return has_hfw;
364}
365
366/*
367 Assumes that setupLayoutData() has been called, and that
368 qGeomCalc() has filled in colData with appropriate values.
369*/
370void QGridLayoutPrivate::recalcHFW(int w)
371{
372 /*
373 Go through all children, using colData and heightForWidth()
374 and put the results in hfwData.
375 */
376 if (!hfwData)
377 hfwData = new QVector<QLayoutStruct>(rr);
378 setupHfwLayoutData();
379 QVector<QLayoutStruct> &rData = *hfwData;
380
381 int h = 0;
382 int mh = 0;
383 for (int r = 0; r < rr; r++) {
384 int spacing = rData.at(r).spacing;
385 h += rData.at(r).sizeHint + spacing;
386 mh += rData.at(r).minimumSize + spacing;
387 }
388
389 hfw_width = w;
390 hfw_height = qMin(QLAYOUTSIZE_MAX, h);
391 hfw_minheight = qMin(QLAYOUTSIZE_MAX, mh);
392}
393
394int QGridLayoutPrivate::heightForWidth(int w, int hSpacing, int vSpacing)
395{
396 setupLayoutData(hSpacing, vSpacing);
397 if (!has_hfw)
398 return -1;
399 int left, top, right, bottom;
400 effectiveMargins(&left, &top, &right, &bottom);
401
402 int hMargins = left + right;
403 if (w - hMargins != hfw_width) {
404 qGeomCalc(colData, 0, cc, 0, w - hMargins);
405 recalcHFW(w - hMargins);
406 }
407 return hfw_height + top + bottom;
408}
409
410int QGridLayoutPrivate::minimumHeightForWidth(int w, int hSpacing, int vSpacing)
411{
412 (void)heightForWidth(w, hSpacing, vSpacing);
413 if (!has_hfw)
414 return -1;
415 int top, bottom;
416 effectiveMargins(0, &top, 0, &bottom);
417 return hfw_minheight + top + bottom;
418}
419
420QSize QGridLayoutPrivate::findSize(int QLayoutStruct::*size, int hSpacing, int vSpacing) const
421{
422 QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this);
423 that->setupLayoutData(hSpacing, vSpacing);
424
425 int w = 0;
426 int h = 0;
427
428 for (int r = 0; r < rr; r++)
429 h += rowData.at(r).*size + rowData.at(r).spacing;
430 for (int c = 0; c < cc; c++)
431 w += colData.at(c).*size + colData.at(c).spacing;
432
433 w = qMin(QLAYOUTSIZE_MAX, w);
434 h = qMin(QLAYOUTSIZE_MAX, h);
435
436 return QSize(w, h);
437}
438
439Qt::Orientations QGridLayoutPrivate::expandingDirections(int hSpacing, int vSpacing) const
440{
441 QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this);
442 that->setupLayoutData(hSpacing, vSpacing);
443 Qt::Orientations ret;
444
445 for (int r = 0; r < rr; r++) {
446 if (rowData.at(r).expansive) {
447 ret |= Qt::Vertical;
448 break;
449 }
450 }
451 for (int c = 0; c < cc; c++) {
452 if (colData.at(c).expansive) {
453 ret |= Qt::Horizontal;
454 break;
455 }
456 }
457 return ret;
458}
459
460QSize QGridLayoutPrivate::sizeHint(int hSpacing, int vSpacing) const
461{
462 return findSize(&QLayoutStruct::sizeHint, hSpacing, vSpacing);
463}
464
465QSize QGridLayoutPrivate::maximumSize(int hSpacing, int vSpacing) const
466{
467 return findSize(&QLayoutStruct::maximumSize, hSpacing, vSpacing);
468}
469
470QSize QGridLayoutPrivate::minimumSize(int hSpacing, int vSpacing) const
471{
472 return findSize(&QLayoutStruct::minimumSize, hSpacing, vSpacing);
473}
474
475void QGridLayoutPrivate::setSize(int r, int c)
476{
477 if ((int)rowData.size() < r) {
478 int newR = qMax(r, rr * 2);
479 rowData.resize(newR);
480 rStretch.resize(newR);
481 rMinHeights.resize(newR);
482 for (int i = rr; i < newR; i++) {
483 rowData[i].init();
484 rowData[i].maximumSize = 0;
485 rowData[i].pos = 0;
486 rowData[i].size = 0;
487 rStretch[i] = 0;
488 rMinHeights[i] = 0;
489 }
490 }
491 if ((int)colData.size() < c) {
492 int newC = qMax(c, cc * 2);
493 colData.resize(newC);
494 cStretch.resize(newC);
495 cMinWidths.resize(newC);
496 for (int i = cc; i < newC; i++) {
497 colData[i].init();
498 colData[i].maximumSize = 0;
499 colData[i].pos = 0;
500 colData[i].size = 0;
501 cStretch[i] = 0;
502 cMinWidths[i] = 0;
503 }
504 }
505
506 if (hfwData && (int)hfwData->size() < r) {
507 delete hfwData;
508 hfwData = 0;
509 hfw_width = -1;
510 }
511 rr = r;
512 cc = c;
513}
514
515void QGridLayoutPrivate::setNextPosAfter(int row, int col)
516{
517 if (addVertical) {
518 if (col > nextC || (col == nextC && row >= nextR)) {
519 nextR = row + 1;
520 nextC = col;
521 if (nextR >= rr) {
522 nextR = 0;
523 nextC++;
524 }
525 }
526 } else {
527 if (row > nextR || (row == nextR && col >= nextC)) {
528 nextR = row;
529 nextC = col + 1;
530 if (nextC >= cc) {
531 nextC = 0;
532 nextR++;
533 }
534 }
535 }
536}
537
538void QGridLayoutPrivate::add(QGridBox *box, int row, int col)
539{
540 expand(row + 1, col + 1);
541 box->row = box->torow = row;
542 box->col = box->tocol = col;
543 things.append(box);
544 setDirty();
545 setNextPosAfter(row, col);
546}
547
548void QGridLayoutPrivate::add(QGridBox *box, int row1, int row2, int col1, int col2)
549{
550 if (row2 >= 0 && row2 < row1)
551 qWarning("QGridLayout: Multi-cell fromRow greater than toRow");
552 if (col2 >= 0 && col2 < col1)
553 qWarning("QGridLayout: Multi-cell fromCol greater than toCol");
554 if (row1 == row2 && col1 == col2) {
555 add(box, row1, col1);
556 return;
557 }
558 expand(row2 + 1, col2 + 1);
559 box->row = row1;
560 box->col = col1;
561
562 box->torow = row2;
563 box->tocol = col2;
564
565 things.append(box);
566 setDirty();
567 if (col2 < 0)
568 col2 = cc - 1;
569
570 setNextPosAfter(row2, col2);
571}
572
573void QGridLayoutPrivate::addData(QGridBox *box, const QGridLayoutSizeTriple &sizes, bool r, bool c)
574{
575 const QWidget *widget = box->item()->widget();
576
577 if (box->isEmpty() && widget)
578 return;
579
580 if (c) {
581 QLayoutStruct *data = &colData[box->col];
582 if (!cStretch.at(box->col))
583 data->stretch = qMax(data->stretch, box->hStretch());
584 data->sizeHint = qMax(sizes.hint.width(), data->sizeHint);
585 data->minimumSize = qMax(sizes.minS.width(), data->minimumSize);
586
587 qMaxExpCalc(data->maximumSize, data->expansive, data->empty, sizes.maxS.width(),
588 box->expandingDirections() & Qt::Horizontal, box->isEmpty());
589 }
590 if (r) {
591 QLayoutStruct *data = &rowData[box->row];
592 if (!rStretch.at(box->row))
593 data->stretch = qMax(data->stretch, box->vStretch());
594 data->sizeHint = qMax(sizes.hint.height(), data->sizeHint);
595 data->minimumSize = qMax(sizes.minS.height(), data->minimumSize);
596
597 qMaxExpCalc(data->maximumSize, data->expansive, data->empty, sizes.maxS.height(),
598 box->expandingDirections() & Qt::Vertical, box->isEmpty());
599 }
600}
601
602static void initEmptyMultiBox(QVector<QLayoutStruct> &chain, int start, int end)
603{
604 for (int i = start; i <= end; i++) {
605 QLayoutStruct *data = &chain[i];
606 if (data->empty && data->maximumSize == 0) // truly empty box
607 data->maximumSize = QWIDGETSIZE_MAX;
608 data->empty = false;
609 }
610}
611
612static void distributeMultiBox(QVector<QLayoutStruct> &chain, int start, int end, int minSize,
613 int sizeHint, QVector<int> &stretchArray, int stretch)
614{
615 int i;
616 int w = 0;
617 int wh = 0;
618 int max = 0;
619
620 for (i = start; i <= end; i++) {
621 QLayoutStruct *data = &chain[i];
622 w += data->minimumSize;
623 wh += data->sizeHint;
624 max += data->maximumSize;
625 if (stretchArray.at(i) == 0)
626 data->stretch = qMax(data->stretch, stretch);
627
628 if (i != end) {
629 int spacing = data->spacing;
630 w += spacing;
631 wh += spacing;
632 max += spacing;
633 }
634 }
635
636 if (max < minSize) { // implies w < minSize
637 /*
638 We must increase the maximum size of at least one of the
639 items. qGeomCalc() will put the extra space in between the
640 items. We must recover that extra space and put it
641 somewhere. It does not really matter where, since the user
642 can always specify stretch factors and avoid this code.
643 */
644 qGeomCalc(chain, start, end - start + 1, 0, minSize);
645 int pos = 0;
646 for (i = start; i <= end; i++) {
647 QLayoutStruct *data = &chain[i];
648 int nextPos = (i == end) ? minSize : chain.at(i + 1).pos;
649 int realSize = nextPos - pos;
650 if (i != end)
651 realSize -= data->spacing;
652 if (data->minimumSize < realSize)
653 data->minimumSize = realSize;
654 if (data->maximumSize < data->minimumSize)
655 data->maximumSize = data->minimumSize;
656 pos = nextPos;
657 }
658 } else if (w < minSize) {
659 qGeomCalc(chain, start, end - start + 1, 0, minSize);
660 for (i = start; i <= end; i++) {
661 QLayoutStruct *data = &chain[i];
662 if (data->minimumSize < data->size)
663 data->minimumSize = data->size;
664 }
665 }
666
667 if (wh < sizeHint) {
668 qGeomCalc(chain, start, end - start + 1, 0, sizeHint);
669 for (i = start; i <= end; i++) {
670 QLayoutStruct *data = &chain[i];
671 if (data->sizeHint < data->size)
672 data->sizeHint = data->size;
673 }
674 }
675}
676
677static QGridBox *&gridAt(QGridBox *grid[], int r, int c, int cc,
678 Qt::Orientation orientation = Qt::Vertical)
679{
680 if (orientation == Qt::Horizontal)
681 qSwap(r, c);
682 return grid[(r * cc) + c];
683}
684
685void QGridLayoutPrivate::setupSpacings(QVector<QLayoutStruct> &chain,
686 QGridBox *grid[], int fixedSpacing,
687 Qt::Orientation orientation)
688{
689 Q_Q(QGridLayout);
690 int numRows = rr; // or columns if orientation is horizontal
691 int numColumns = cc; // or rows if orientation is horizontal
692
693 if (orientation == Qt::Horizontal) {
694 qSwap(numRows, numColumns);
695 }
696
697 QStyle *style = 0;
698 if (fixedSpacing < 0) {
699 if (QWidget *parentWidget = q->parentWidget())
700 style = parentWidget->style();
701 }
702
703 for (int c = 0; c < numColumns; ++c) {
704 QGridBox *previousBox = 0;
705 int previousRow = -1; // previous *non-empty* row
706
707 for (int r = 0; r < numRows; ++r) {
708 if (chain.at(r).empty)
709 continue;
710
711 QGridBox *box = gridAt(grid, r, c, cc, orientation);
712 if (previousRow != -1 && (!box || previousBox != box)) {
713 int spacing = fixedSpacing;
714 if (spacing < 0) {
715 QSizePolicy::ControlTypes controlTypes1 = QSizePolicy::DefaultType;
716 QSizePolicy::ControlTypes controlTypes2 = QSizePolicy::DefaultType;
717 if (previousBox)
718 controlTypes1 = previousBox->item()->controlTypes();
719 if (box)
720 controlTypes2 = box->item()->controlTypes();
721
722 if ((orientation == Qt::Horizontal && hReversed)
723 || (orientation == Qt::Vertical && vReversed))
724 qSwap(controlTypes1, controlTypes2);
725
726 if (style)
727 spacing = style->combinedLayoutSpacing(controlTypes1, controlTypes2,
728 orientation, 0, q->parentWidget());
729 } else {
730 if (orientation == Qt::Vertical) {
731 QGridBox *sibling = vReversed ? previousBox : box;
732 if (sibling) {
733 QWidget *wid = sibling->item()->widget();
734 if (wid)
735 spacing = qMax(spacing, sibling->item()->geometry().top() - wid->geometry().top() );
736 }
737 }
738 }
739
740 if (spacing > chain.at(previousRow).spacing)
741 chain[previousRow].spacing = spacing;
742 }
743
744 previousBox = box;
745 previousRow = r;
746 }
747 }
748}
749
750//#define QT_LAYOUT_DISABLE_CACHING
751
752void QGridLayoutPrivate::setupLayoutData(int hSpacing, int vSpacing)
753{
754 Q_Q(QGridLayout);
755
756#ifndef QT_LAYOUT_DISABLE_CACHING
757 if (!needRecalc)
758 return;
759#endif
760 has_hfw = false;
761 int i;
762
763 for (i = 0; i < rr; i++) {
764 rowData[i].init(rStretch.at(i), rMinHeights.at(i));
765 rowData[i].maximumSize = rStretch.at(i) ? QLAYOUTSIZE_MAX : rMinHeights.at(i);
766 }
767 for (i = 0; i < cc; i++) {
768 colData[i].init(cStretch.at(i), cMinWidths.at(i));
769 colData[i].maximumSize = cStretch.at(i) ? QLAYOUTSIZE_MAX : cMinWidths.at(i);
770 }
771
772 int n = things.size();
773 QVarLengthArray<QGridLayoutSizeTriple> sizes(n);
774
775 bool has_multi = false;
776
777 /*
778 Grid of items. We use it to determine which items are
779 adjacent to which and compute the spacings correctly.
780 */
781 QVarLengthArray<QGridBox *> grid(rr * cc);
782 qMemSet(grid.data(), 0, rr * cc * sizeof(QGridBox *));
783
784 /*
785 Initialize 'sizes' and 'grid' data structures, and insert
786 non-spanning items to our row and column data structures.
787 */
788 for (i = 0; i < n; ++i) {
789 QGridBox * const box = things.at(i);
790 sizes[i].minS = box->minimumSize();
791 sizes[i].hint = box->sizeHint();
792 sizes[i].maxS = box->maximumSize();
793
794 if (box->hasHeightForWidth())
795 has_hfw = true;
796
797 if (box->row == box->toRow(rr)) {
798 addData(box, sizes[i], true, false);
799 } else {
800 initEmptyMultiBox(rowData, box->row, box->toRow(rr));
801 has_multi = true;
802 }
803
804 if (box->col == box->toCol(cc)) {
805 addData(box, sizes[i], false, true);
806 } else {
807 initEmptyMultiBox(colData, box->col, box->toCol(cc));
808 has_multi = true;
809 }
810
811 for (int r = box->row; r <= box->toRow(rr); ++r) {
812 for (int c = box->col; c <= box->toCol(cc); ++c) {
813 gridAt(grid.data(), r, c, cc) = box;
814 }
815 }
816 }
817
818 setupSpacings(colData, grid.data(), hSpacing, Qt::Horizontal);
819 setupSpacings(rowData, grid.data(), vSpacing, Qt::Vertical);
820
821 /*
822 Insert multicell items to our row and column data structures.
823 This must be done after the non-spanning items to obtain a
824 better distribution in distributeMultiBox().
825 */
826 if (has_multi) {
827 for (i = 0; i < n; ++i) {
828 QGridBox * const box = things.at(i);
829
830 if (box->row != box->toRow(rr))
831 distributeMultiBox(rowData, box->row, box->toRow(rr), sizes[i].minS.height(),
832 sizes[i].hint.height(), rStretch, box->vStretch());
833 if (box->col != box->toCol(cc))
834 distributeMultiBox(colData, box->col, box->toCol(cc), sizes[i].minS.width(),
835 sizes[i].hint.width(), cStretch, box->hStretch());
836 }
837 }
838
839 for (i = 0; i < rr; i++)
840 rowData[i].expansive = rowData.at(i).expansive || rowData.at(i).stretch > 0;
841 for (i = 0; i < cc; i++)
842 colData[i].expansive = colData.at(i).expansive || colData.at(i).stretch > 0;
843
844 q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
845
846 needRecalc = false;
847}
848
849void QGridLayoutPrivate::addHfwData(QGridBox *box, int width)
850{
851 QVector<QLayoutStruct> &rData = *hfwData;
852 if (box->hasHeightForWidth()) {
853 int hint = box->heightForWidth(width);
854 rData[box->row].sizeHint = qMax(hint, rData.at(box->row).sizeHint);
855 rData[box->row].minimumSize = qMax(hint, rData.at(box->row).minimumSize);
856 } else {
857 QSize hint = box->sizeHint();
858 QSize minS = box->minimumSize();
859 rData[box->row].sizeHint = qMax(hint.height(), rData.at(box->row).sizeHint);
860 rData[box->row].minimumSize = qMax(minS.height(), rData.at(box->row).minimumSize);
861 }
862}
863
864/*
865 Similar to setupLayoutData(), but uses heightForWidth(colData)
866 instead of sizeHint(). Assumes that setupLayoutData() and
867 qGeomCalc(colData) has been called.
868*/
869void QGridLayoutPrivate::setupHfwLayoutData()
870{
871 QVector<QLayoutStruct> &rData = *hfwData;
872 for (int i = 0; i < rr; i++) {
873 rData[i] = rowData.at(i);
874 rData[i].minimumSize = rData[i].sizeHint = rMinHeights.at(i);
875 }
876
877 for (int pass = 0; pass < 2; ++pass) {
878 for (int i = 0; i < things.size(); ++i) {
879 QGridBox *box = things.at(i);
880 int r1 = box->row;
881 int c1 = box->col;
882 int r2 = box->toRow(rr);
883 int c2 = box->toCol(cc);
884 int w = colData.at(c2).pos + colData.at(c2).size - colData.at(c1).pos;
885
886 if (r1 == r2) {
887 if (pass == 0)
888 addHfwData(box, w);
889 } else {
890 if (pass == 0) {
891 initEmptyMultiBox(rData, r1, r2);
892 } else {
893 QSize hint = box->sizeHint();
894 QSize min = box->minimumSize();
895 if (box->hasHeightForWidth()) {
896 int hfwh = box->heightForWidth(w);
897 if (hfwh > hint.height())
898 hint.setHeight(hfwh);
899 if (hfwh > min.height())
900 min.setHeight(hfwh);
901 }
902 distributeMultiBox(rData, r1, r2, min.height(), hint.height(),
903 rStretch, box->vStretch());
904 }
905 }
906 }
907 }
908 for (int i = 0; i < rr; i++)
909 rData[i].expansive = rData.at(i).expansive || rData.at(i).stretch > 0;
910}
911
912void QGridLayoutPrivate::distribute(QRect r, int hSpacing, int vSpacing)
913{
914 Q_Q(QGridLayout);
915 bool visualHReversed = hReversed;
916 QWidget *parent = q->parentWidget();
917 if (parent && parent->isRightToLeft())
918 visualHReversed = !visualHReversed;
919
920 setupLayoutData(hSpacing, vSpacing);
921
922 int left, top, right, bottom;
923 effectiveMargins(&left, &top, &right, &bottom);
924 r.adjust(+left, +top, -right, -bottom);
925
926 qGeomCalc(colData, 0, cc, r.x(), r.width());
927 QVector<QLayoutStruct> *rDataPtr;
928 if (has_hfw) {
929 recalcHFW(r.width());
930 qGeomCalc(*hfwData, 0, rr, r.y(), r.height());
931 rDataPtr = hfwData;
932 } else {
933 qGeomCalc(rowData, 0, rr, r.y(), r.height());
934 rDataPtr = &rowData;
935 }
936 QVector<QLayoutStruct> &rData = *rDataPtr;
937 int i;
938
939 bool reverse = ((r.bottom() > rect.bottom()) || (r.bottom() == rect.bottom()
940 && ((r.right() > rect.right()) != visualHReversed)));
941 int n = things.size();
942 for (i = 0; i < n; ++i) {
943 QGridBox *box = things.at(reverse ? n-i-1 : i);
944 int r2 = box->toRow(rr);
945 int c2 = box->toCol(cc);
946
947 int x = colData.at(box->col).pos;
948 int y = rData.at(box->row).pos;
949 int x2p = colData.at(c2).pos + colData.at(c2).size; // x2+1
950 int y2p = rData.at(r2).pos + rData.at(r2).size; // y2+1
951 int w = x2p - x;
952 int h = y2p - y;
953
954 if (visualHReversed)
955 x = r.left() + r.right() - x - w + 1;
956 if (vReversed)
957 y = r.top() + r.bottom() - y - h + 1;
958
959 box->setGeometry(QRect(x, y, w, h));
960 }
961}
962
963QRect QGridLayoutPrivate::cellRect(int row, int col) const
964{
965 if (row < 0 || row >= rr || col < 0 || col >= cc)
966 return QRect();
967
968 const QVector<QLayoutStruct> *rDataPtr;
969 if (has_hfw && hfwData)
970 rDataPtr = hfwData;
971 else
972 rDataPtr = &rowData;
973 return QRect(colData.at(col).pos, rDataPtr->at(row).pos,
974 colData.at(col).size, rDataPtr->at(row).size);
975}
976
977/*!
978 \class QGridLayout
979
980 \brief The QGridLayout class lays out widgets in a grid.
981
982 \ingroup geomanagement
983 \ingroup appearance
984 \mainclass
985
986 QGridLayout takes the space made available to it (by its parent
987 layout or by the parentWidget()), divides it up into rows and
988 columns, and puts each widget it manages into the correct cell.
989
990 Columns and rows behave identically; we will discuss columns, but
991 there are equivalent functions for rows.
992
993 Each column has a minimum width and a stretch factor. The minimum
994 width is the greatest of that set using setColumnMinimumWidth() and the
995 minimum width of each widget in that column. The stretch factor is
996 set using setColumnStretch() and determines how much of the available
997 space the column will get over and above its necessary minimum.
998
999 Normally, each managed widget or layout is put into a cell of its
1000 own using addWidget(). It is also possible for a widget to occupy
1001 multiple cells using the row and column spanning overloads of
1002 addItem() and addWidget(). If you do this, QGridLayout will guess
1003 how to distribute the size over the columns/rows (based on the
1004 stretch factors).
1005
1006 To remove a widget from a layout, call removeWidget(). Calling
1007 QWidget::hide() on a widget also effectively removes the widget
1008 from the layout until QWidget::show() is called.
1009
1010 This illustration shows a fragment of a dialog with a five-column,
1011 three-row grid (the grid is shown overlaid in magenta):
1012
1013 \image gridlayout.png A grid layout
1014
1015 Columns 0, 2 and 4 in this dialog fragment are made up of a
1016 QLabel, a QLineEdit, and a QListBox. Columns 1 and 3 are
1017 placeholders made with setColumnMinimumWidth(). Row 0 consists of three
1018 QLabel objects, row 1 of three QLineEdit objects and row 2 of
1019 three QListBox objects. We used placeholder columns (1 and 3) to
1020 get the right amount of space between the columns.
1021
1022 Note that the columns and rows are not equally wide or tall. If
1023 you want two columns to have the same width, you must set their
1024 minimum widths and stretch factors to be the same yourself. You do
1025 this using setColumnMinimumWidth() and setColumnStretch().
1026
1027 If the QGridLayout is not the top-level layout (i.e. does not
1028 manage all of the widget's area and children), you must add it to
1029 its parent layout when you create it, but before you do anything
1030 with it. The normal way to add a layout is by calling
1031 addLayout() on the parent layout.
1032
1033 Once you have added your layout you can start putting widgets and
1034 other layouts into the cells of your grid layout using
1035 addWidget(), addItem(), and addLayout().
1036
1037 QGridLayout also includes two margin widths: the margin() and the
1038 spacing(). The margin is the width of the reserved space along
1039 each of the QGridLayout's four sides. The spacing is the width of
1040 the automatically allocated spacing between neighboring boxes.
1041
1042 The default margin() and spacing() values are provided by the
1043 style. The default margin Qt styles specify is 9 for child
1044 widgets and 11 for windows. The spacing defaults to the same as
1045 the margin width for a top-level layout, or to the same as the
1046 parent layout.
1047
1048 \sa QBoxLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
1049*/
1050
1051
1052/*!
1053 Constructs a new QGridLayout with parent widget, \a parent. The
1054 layout has one row and one column initially, and will expand when
1055 new items are inserted.
1056*/
1057QGridLayout::QGridLayout(QWidget *parent)
1058 : QLayout(*new QGridLayoutPrivate, 0, parent)
1059{
1060 Q_D(QGridLayout);
1061 d->expand(1, 1);
1062}
1063
1064/*!
1065 Constructs a new grid layout.
1066
1067 You must insert this grid into another layout. You can insert
1068 widgets and layouts into this layout at any time, but laying out
1069 will not be performed before this is inserted into another layout.
1070*/
1071QGridLayout::QGridLayout()
1072 : QLayout(*new QGridLayoutPrivate, 0, 0)
1073{
1074 Q_D(QGridLayout);
1075 d->expand(1, 1);
1076}
1077
1078
1079#ifdef QT3_SUPPORT
1080/*!
1081 \obsolete
1082 Constructs a new QGridLayout with \a nRows rows, \a nCols columns
1083 and parent widget, \a parent. \a parent may not be 0. The grid
1084 layout is called \a name.
1085
1086 \a margin is the number of pixels between the edge of the widget
1087 and its managed children. \a space is the default number of pixels
1088 between cells. If \a space is -1, the value of \a margin is used.
1089*/
1090QGridLayout::QGridLayout(QWidget *parent, int nRows, int nCols, int margin,
1091 int space, const char *name)
1092 : QLayout(*new QGridLayoutPrivate, 0, parent)
1093{
1094 Q_D(QGridLayout);
1095 d->expand(nRows, nCols);
1096 setMargin(margin);
1097 setSpacing(space < 0 ? margin : space);
1098 setObjectName(QString::fromAscii(name));
1099}
1100
1101/*!
1102 \obsolete
1103
1104 Constructs a new grid with \a nRows rows and \a nCols columns. If
1105 \a spacing is -1, this QGridLayout inherits its parent's
1106 spacing(); otherwise \a spacing is used. The grid layout is called
1107 \a name.
1108
1109 You must insert this grid into another layout. You can insert
1110 widgets and layouts into this layout at any time, but laying out
1111 will not be performed before this is inserted into another layout.
1112*/
1113QGridLayout::QGridLayout(QLayout *parentLayout, int nRows, int nCols,
1114 int spacing, const char *name)
1115 : QLayout(*new QGridLayoutPrivate, parentLayout, 0)
1116{
1117 Q_D(QGridLayout);
1118 d->expand(nRows, nCols);
1119 setSpacing(spacing);
1120 setObjectName(QString::fromAscii(name));
1121}
1122
1123/*!
1124 \obsolete
1125
1126 Constructs a new grid with \a nRows rows and \a nCols columns. If
1127 \a spacing is -1, this QGridLayout inherits its parent's
1128 spacing(); otherwise \a spacing is used. The grid layout is called
1129 \a name.
1130
1131 You must insert this grid into another layout. You can insert
1132 widgets and layouts into this layout at any time, but laying out
1133 will not be performed before this is inserted into another layout.
1134*/
1135QGridLayout::QGridLayout(int nRows, int nCols, int spacing, const char *name)
1136 : QLayout(*new QGridLayoutPrivate, 0, 0)
1137{
1138 Q_D(QGridLayout);
1139 d->expand(nRows, nCols);
1140 setSpacing(spacing);
1141 setObjectName(QString::fromAscii(name));
1142}
1143#endif
1144
1145
1146/*!
1147\internal (mostly)
1148
1149Sets the positioning mode used by addItem(). If \a orient is
1150Qt::Horizontal, this layout is expanded to \a n columns, and items
1151will be added columns-first. Otherwise it is expanded to \a n rows and
1152items will be added rows-first.
1153*/
1154
1155void QGridLayout::setDefaultPositioning(int n, Qt::Orientation orient)
1156{
1157 Q_D(QGridLayout);
1158 if (orient == Qt::Horizontal) {
1159 d->expand(1, n);
1160 d->addVertical = false;
1161 } else {
1162 d->expand(n,1);
1163 d->addVertical = true;
1164 }
1165}
1166
1167
1168/*!
1169 Destroys the grid layout. Geometry management is terminated if
1170 this is a top-level grid.
1171
1172 The layout's widgets aren't destroyed.
1173*/
1174QGridLayout::~QGridLayout()
1175{
1176 Q_D(QGridLayout);
1177 d->deleteAll();
1178}
1179
1180/*!
1181 \property QGridLayout::horizontalSpacing
1182 \brief the spacing between widgets that are laid out side by side
1183 \since 4.3
1184
1185 If no value is explicitly set, the layout's horizontal spacing is
1186 inherited from the parent layout, or from the style settings for
1187 the parent widget.
1188
1189 \sa verticalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
1190*/
1191void QGridLayout::setHorizontalSpacing(int spacing)
1192{
1193 Q_D(QGridLayout);
1194 d->horizontalSpacing = spacing;
1195 invalidate();
1196}
1197
1198int QGridLayout::horizontalSpacing() const
1199{
1200 Q_D(const QGridLayout);
1201 if (d->horizontalSpacing >= 0) {
1202 return d->horizontalSpacing;
1203 } else {
1204 return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
1205 }
1206}
1207
1208/*!
1209 \property QGridLayout::verticalSpacing
1210 \brief the spacing between widgets that are laid out on top of each other
1211 \since 4.3
1212
1213 If no value is explicitly set, the layout's vertical spacing is
1214 inherited from the parent layout, or from the style settings for
1215 the parent widget.
1216
1217 \sa horizontalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
1218*/
1219void QGridLayout::setVerticalSpacing(int spacing)
1220{
1221 Q_D(QGridLayout);
1222 d->verticalSpacing = spacing;
1223 invalidate();
1224}
1225
1226int QGridLayout::verticalSpacing() const
1227{
1228 Q_D(const QGridLayout);
1229 if (d->verticalSpacing >= 0) {
1230 return d->verticalSpacing;
1231 } else {
1232 return qSmartSpacing(this, QStyle::PM_LayoutVerticalSpacing);
1233 }
1234}
1235
1236/*!
1237 This function sets both the vertical and horizontal spacing to
1238 \a spacing.
1239
1240 \sa setVerticalSpacing(), setHorizontalSpacing()
1241*/
1242void QGridLayout::setSpacing(int spacing)
1243{
1244 Q_D(QGridLayout);
1245 d->horizontalSpacing = d->verticalSpacing = spacing;
1246 invalidate();
1247}
1248
1249/*!
1250 If the vertical spacing is equal to the horizontal spacing,
1251 this function returns that value; otherwise it return -1.
1252
1253 \sa setSpacing(), verticalSpacing(), horizontalSpacing()
1254*/
1255int QGridLayout::spacing() const
1256{
1257 int hSpacing = horizontalSpacing();
1258 if (hSpacing == verticalSpacing()) {
1259 return hSpacing;
1260 } else {
1261 return -1;
1262 }
1263}
1264
1265/*!
1266 Returns the number of rows in this grid.
1267*/
1268int QGridLayout::rowCount() const
1269{
1270 Q_D(const QGridLayout);
1271 return d->numRows();
1272}
1273
1274/*!
1275 Returns the number of columns in this grid.
1276*/
1277int QGridLayout::columnCount() const
1278{
1279 Q_D(const QGridLayout);
1280 return d->numCols();
1281}
1282
1283/*!
1284 \reimp
1285*/
1286QSize QGridLayout::sizeHint() const
1287{
1288 Q_D(const QGridLayout);
1289 QSize result(d->sizeHint(horizontalSpacing(), verticalSpacing()));
1290 int left, top, right, bottom;
1291 d->effectiveMargins(&left, &top, &right, &bottom);
1292 result += QSize(left + right, top + bottom);
1293 return result;
1294}
1295
1296/*!
1297 \reimp
1298*/
1299QSize QGridLayout::minimumSize() const
1300{
1301 Q_D(const QGridLayout);
1302 QSize result(d->minimumSize(horizontalSpacing(), verticalSpacing()));
1303 int left, top, right, bottom;
1304 d->effectiveMargins(&left, &top, &right, &bottom);
1305 result += QSize(left + right, top + bottom);
1306 return result;
1307}
1308
1309/*!
1310 \reimp
1311*/
1312QSize QGridLayout::maximumSize() const
1313{
1314 Q_D(const QGridLayout);
1315
1316 QSize s = d->maximumSize(horizontalSpacing(), verticalSpacing());
1317 int left, top, right, bottom;
1318 d->effectiveMargins(&left, &top, &right, &bottom);
1319 s += QSize(left + right, top + bottom);
1320 s = s.boundedTo(QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX));
1321 if (alignment() & Qt::AlignHorizontal_Mask)
1322 s.setWidth(QLAYOUTSIZE_MAX);
1323 if (alignment() & Qt::AlignVertical_Mask)
1324 s.setHeight(QLAYOUTSIZE_MAX);
1325 return s;
1326}
1327
1328/*!
1329 \reimp
1330*/
1331bool QGridLayout::hasHeightForWidth() const
1332{
1333 return ((QGridLayout*)this)->d_func()->hasHeightForWidth(horizontalSpacing(), verticalSpacing());
1334}
1335
1336/*!
1337 \reimp
1338*/
1339int QGridLayout::heightForWidth(int w) const
1340{
1341 Q_D(const QGridLayout);
1342 QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d);
1343 return dat->heightForWidth(w, horizontalSpacing(), verticalSpacing());
1344}
1345
1346/*!
1347 \reimp
1348*/
1349int QGridLayout::minimumHeightForWidth(int w) const
1350{
1351 Q_D(const QGridLayout);
1352 QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d);
1353 return dat->minimumHeightForWidth(w, horizontalSpacing(), verticalSpacing());
1354}
1355
1356#ifdef QT3_SUPPORT
1357/*!
1358 \compat
1359
1360 Searches for widget \a w in this layout (not including child
1361 layouts). If \a w is found, it sets \c{*}\a{row} and
1362 \c{*}\a{column} to the row and column that the widget
1363 occupies and returns true; otherwise returns false.
1364
1365 If the widget spans multiple rows/columns, the top-left cell
1366 is returned.
1367
1368 Use indexOf() and getItemPosition() instead.
1369*/
1370bool QGridLayout::findWidget(QWidget* w, int *row, int *column)
1371{
1372 Q_D(QGridLayout);
1373 int index = indexOf(w);
1374 if (index < 0)
1375 return false;
1376 int dummy1, dummy2;
1377 d->getItemPosition(index, row, column, &dummy1, &dummy2);
1378 return true;
1379}
1380#endif
1381/*!
1382 \reimp
1383*/
1384int QGridLayout::count() const
1385{
1386 Q_D(const QGridLayout);
1387 return d->count();
1388}
1389
1390
1391/*!
1392 \reimp
1393*/
1394QLayoutItem *QGridLayout::itemAt(int index) const
1395{
1396 Q_D(const QGridLayout);
1397 return d->itemAt(index);
1398}
1399
1400/*!
1401 \since 4.4
1402
1403 Returns the layout item that occupies cell (\a row, \a column), or 0 if
1404 the cell is empty.
1405
1406 \sa getItemPosition(), indexOf()
1407*/
1408QLayoutItem *QGridLayout::itemAtPosition(int row, int column) const
1409{
1410 Q_D(const QGridLayout);
1411 int n = d->things.count();
1412 for (int i = 0; i < n; ++i) {
1413 QGridBox *box = d->things.at(i);
1414 if (row >= box->row && row <= box->toRow(d->rr)
1415 && column >= box->col && column <= box->toCol(d->cc)) {
1416 return box->item();
1417 }
1418 }
1419 return 0;
1420}
1421
1422/*!
1423 \reimp
1424*/
1425QLayoutItem *QGridLayout::takeAt(int index)
1426{
1427 Q_D(QGridLayout);
1428 return d->takeAt(index);
1429}
1430
1431/*!
1432 Returns the position information of the item with the given \a index.
1433
1434 The variables passed as \a row and \a column are updated with the position of the
1435 item in the layout, and the \a rowSpan and \a columnSpan variables are updated
1436 with the vertical and horizontal spans of the item.
1437
1438 \sa itemAtPosition(), itemAt()
1439*/
1440void QGridLayout::getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan)
1441{
1442 Q_D(QGridLayout);
1443 d->getItemPosition(index, row, column, rowSpan, columnSpan);
1444}
1445
1446
1447/*!
1448 \reimp
1449*/
1450void QGridLayout::setGeometry(const QRect &rect)
1451{
1452 Q_D(QGridLayout);
1453 if (d->isDirty() || rect != geometry()) {
1454 QRect cr = alignment() ? alignmentRect(rect) : rect;
1455 d->distribute(cr, horizontalSpacing(), verticalSpacing());
1456 QLayout::setGeometry(rect);
1457 }
1458}
1459
1460/*!
1461 Returns the geometry of the cell with row \a row and column \a column
1462 in the grid. Returns an invalid rectangle if \a row or \a column is
1463 outside the grid.
1464
1465 \warning in the current version of Qt this function does not
1466 return valid results until setGeometry() has been called, i.e.
1467 after the parentWidget() is visible.
1468*/
1469QRect QGridLayout::cellRect(int row, int column) const
1470{
1471 Q_D(const QGridLayout);
1472 return d->cellRect(row, column);
1473}
1474#ifdef QT3_SUPPORT
1475/*!
1476 \obsolete
1477 Expands this grid so that it will have \a nRows rows and \a nCols
1478 columns. Will not shrink the grid. You should not need to call
1479 this function because QGridLayout expands automatically as new
1480 items are inserted.
1481*/
1482void QGridLayout::expand(int nRows, int nCols)
1483{
1484 Q_D(QGridLayout);
1485 d->expand(nRows, nCols);
1486}
1487#endif
1488
1489/*!
1490 \reimp
1491*/
1492void QGridLayout::addItem(QLayoutItem *item)
1493{
1494 Q_D(QGridLayout);
1495 int r, c;
1496 d->getNextPos(r, c);
1497 addItem(item, r, c);
1498}
1499
1500/*!
1501 Adds \a item at position \a row, \a column, spanning \a rowSpan
1502 rows and \a columnSpan columns, and aligns it according to \a
1503 alignment. If \a rowSpan and/or \a columnSpan is -1, then the item
1504 will extend to the bottom and/or right edge, respectively. The
1505 layout takes ownership of the \a item.
1506
1507 \warning Do not use this function to add child layouts or child
1508 widget items. Use addLayout() or addWidget() instead.
1509*/
1510void QGridLayout::addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
1511{
1512 Q_D(QGridLayout);
1513 QGridBox *b = new QGridBox(item);
1514 b->setAlignment(alignment);
1515 d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
1516 invalidate();
1517}
1518
1519/*
1520 Returns true if the widget \a w can be added to the layout \a l;
1521 otherwise returns false.
1522*/
1523static bool checkWidget(QLayout *l, QWidget *w)
1524{
1525 if (!w) {
1526 qWarning("QLayout: Cannot add null widget to %s/%s", l->metaObject()->className(),
1527 l->objectName().toLocal8Bit().data());
1528 return false;
1529 }
1530 return true;
1531}
1532
1533/*!
1534 Adds the given \a widget to the cell grid at \a row, \a column. The
1535 top-left position is (0, 0) by default.
1536
1537 The alignment is specified by \a alignment. The default
1538 alignment is 0, which means that the widget fills the entire cell.
1539
1540*/
1541void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
1542{
1543 if (!checkWidget(this, widget))
1544 return;
1545 if (row < 0 || column < 0) {
1546 qWarning("QGridLayout: Cannot add %s/%s to %s/%s at row %d column %d",
1547 widget->metaObject()->className(), widget->objectName().toLocal8Bit().data(),
1548 metaObject()->className(), objectName().toLocal8Bit().data(), row, column);
1549 return;
1550 }
1551 addChildWidget(widget);
1552 QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
1553 addItem(b, row, column, 1, 1, alignment);
1554}
1555
1556/*!
1557 \overload
1558
1559 This version adds the given \a widget to the cell grid, spanning
1560 multiple rows/columns. The cell will start at \a fromRow, \a
1561 fromColumn spanning \a rowSpan rows and \a columnSpan columns. The
1562 \a widget will have the given \a alignment.
1563
1564 If \a rowSpan and/or \a columnSpan is -1, then the widget will
1565 extend to the bottom and/or right edge, respectively.
1566
1567*/
1568void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn,
1569 int rowSpan, int columnSpan, Qt::Alignment alignment)
1570{
1571 Q_D(QGridLayout);
1572 if (!checkWidget(this, widget))
1573 return;
1574 int toRow = (rowSpan < 0) ? -1 : fromRow + rowSpan - 1;
1575 int toColumn = (columnSpan < 0) ? -1 : fromColumn + columnSpan - 1;
1576 addChildWidget(widget);
1577 QGridBox *b = new QGridBox(this, widget);
1578 b->setAlignment(alignment);
1579 d->add(b, fromRow, toRow, fromColumn, toColumn);
1580 invalidate();
1581}
1582
1583/*!
1584 \fn void QGridLayout::addWidget(QWidget *widget)
1585
1586 \overload
1587 \internal
1588*/
1589
1590/*!
1591 Places the \a layout at position (\a row, \a column) in the grid. The
1592 top-left position is (0, 0).
1593
1594 The alignment is specified by \a alignment. The default
1595 alignment is 0, which means that the widget fills the entire cell.
1596
1597 A non-zero alignment indicates that the layout should not grow to
1598 fill the available space but should be sized according to
1599 sizeHint().
1600
1601
1602 \a layout becomes a child of the grid layout.
1603*/
1604void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment)
1605{
1606 Q_D(QGridLayout);
1607 addChildLayout(layout);
1608 QGridBox *b = new QGridBox(layout);
1609 b->setAlignment(alignment);
1610 d->add(b, row, column);
1611}
1612
1613/*!
1614 \overload
1615 This version adds the layout \a layout to the cell grid, spanning multiple
1616 rows/columns. The cell will start at \a row, \a column spanning \a
1617 rowSpan rows and \a columnSpan columns.
1618
1619 If \a rowSpan and/or \a columnSpan is -1, then the layout will extend to the bottom
1620 and/or right edge, respectively.
1621*/
1622void QGridLayout::addLayout(QLayout *layout, int row, int column,
1623 int rowSpan, int columnSpan, Qt::Alignment alignment)
1624{
1625 Q_D(QGridLayout);
1626 addChildLayout(layout);
1627 QGridBox *b = new QGridBox(layout);
1628 b->setAlignment(alignment);
1629 d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
1630}
1631
1632/*!
1633 Sets the stretch factor of row \a row to \a stretch. The first row
1634 is number 0.
1635
1636 The stretch factor is relative to the other rows in this grid.
1637 Rows with a higher stretch factor take more of the available
1638 space.
1639
1640 The default stretch factor is 0. If the stretch factor is 0 and no
1641 other row in this table can grow at all, the row may still grow.
1642
1643 \sa rowStretch(), setRowMinimumHeight(), setColumnStretch()
1644*/
1645void QGridLayout::setRowStretch(int row, int stretch)
1646{
1647 Q_D(QGridLayout);
1648 d->setRowStretch(row, stretch);
1649 invalidate();
1650}
1651
1652/*!
1653 Returns the stretch factor for row \a row.
1654
1655 \sa setRowStretch()
1656*/
1657int QGridLayout::rowStretch(int row) const
1658{
1659 Q_D(const QGridLayout);
1660 return d->rowStretch(row);
1661}
1662
1663/*!
1664 Returns the stretch factor for column \a column.
1665
1666 \sa setColumnStretch()
1667*/
1668int QGridLayout::columnStretch(int column) const
1669{
1670 Q_D(const QGridLayout);
1671 return d->colStretch(column);
1672}
1673
1674/*!
1675 Sets the stretch factor of column \a column to \a stretch. The first
1676 column is number 0.
1677
1678 The stretch factor is relative to the other columns in this grid.
1679 Columns with a higher stretch factor take more of the available
1680 space.
1681
1682 The default stretch factor is 0. If the stretch factor is 0 and no
1683 other column in this table can grow at all, the column may still
1684 grow.
1685
1686 An alternative approach is to add spacing using addItem() with a
1687 QSpacerItem.
1688
1689 \sa columnStretch(), setRowStretch()
1690*/
1691void QGridLayout::setColumnStretch(int column, int stretch)
1692{
1693 Q_D(QGridLayout);
1694 d->setColStretch(column, stretch);
1695 invalidate();
1696}
1697
1698
1699
1700/*!
1701 Sets the minimum height of row \a row to \a minSize pixels.
1702
1703 \sa rowMinimumHeight(), setColumnMinimumWidth()
1704*/
1705void QGridLayout::setRowMinimumHeight(int row, int minSize)
1706{
1707 Q_D(QGridLayout);
1708 d->setRowMinimumHeight(row, minSize);
1709 invalidate();
1710}
1711
1712/*!
1713 Returns the minimum width set for row \a row.
1714
1715 \sa setRowMinimumHeight()
1716*/
1717int QGridLayout::rowMinimumHeight(int row) const
1718{
1719 Q_D(const QGridLayout);
1720 return d->rowSpacing(row);
1721}
1722
1723/*!
1724 Sets the minimum width of column \a column to \a minSize pixels.
1725
1726 \sa columnMinimumWidth(), setRowMinimumHeight()
1727*/
1728void QGridLayout::setColumnMinimumWidth(int column, int minSize)
1729{
1730 Q_D(QGridLayout);
1731 d->setColumnMinimumWidth(column, minSize);
1732 invalidate();
1733}
1734
1735/*!
1736 Returns the column spacing for column \a column.
1737
1738 \sa setColumnMinimumWidth()
1739*/
1740int QGridLayout::columnMinimumWidth(int column) const
1741{
1742 Q_D(const QGridLayout);
1743 return d->colSpacing(column);
1744}
1745
1746/*!
1747 \reimp
1748*/
1749Qt::Orientations QGridLayout::expandingDirections() const
1750{
1751 Q_D(const QGridLayout);
1752 return d->expandingDirections(horizontalSpacing(), verticalSpacing());
1753}
1754
1755/*!
1756 Sets the grid's origin corner, i.e. position (0, 0), to \a corner.
1757*/
1758void QGridLayout::setOriginCorner(Qt::Corner corner)
1759{
1760 Q_D(QGridLayout);
1761 d->setReversed(corner == Qt::BottomLeftCorner || corner == Qt::BottomRightCorner,
1762 corner == Qt::TopRightCorner || corner == Qt::BottomRightCorner);
1763}
1764
1765/*!
1766 Returns the corner that's used for the grid's origin, i.e. for
1767 position (0, 0).
1768*/
1769Qt::Corner QGridLayout::originCorner() const
1770{
1771 Q_D(const QGridLayout);
1772 if (d->horReversed()) {
1773 return d->verReversed() ? Qt::BottomRightCorner : Qt::TopRightCorner;
1774 } else {
1775 return d->verReversed() ? Qt::BottomLeftCorner : Qt::TopLeftCorner;
1776 }
1777}
1778
1779/*!
1780 \reimp
1781*/
1782void QGridLayout::invalidate()
1783{
1784 Q_D(QGridLayout);
1785 d->setDirty();
1786 QLayout::invalidate();
1787}
1788
1789/*!
1790 \fn void QGridLayout::addRowSpacing(int row, int minsize)
1791
1792 Use addItem(new QSpacerItem(0, minsize), row, 0) instead.
1793*/
1794
1795/*!
1796 \fn void QGridLayout::addColSpacing(int col, int minsize)
1797
1798 Use addItem(new QSpacerItem(minsize, 0), 0, col) instead.
1799*/
1800
1801/*!
1802 \fn void QGridLayout::addMultiCellWidget(QWidget *widget, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
1803
1804 Use an addWidget() overload that allows you to specify row and
1805 column spans instead.
1806*/
1807
1808/*!
1809 \fn void QGridLayout::addMultiCell(QLayoutItem *l, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
1810
1811 Use an addItem() overload that allows you to specify row and
1812 column spans instead.
1813*/
1814
1815/*!
1816 \fn void QGridLayout::addMultiCellLayout(QLayout *layout, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
1817
1818 Use an addLayout() overload that allows you to specify row and
1819 column spans instead.
1820*/
1821
1822/*!
1823 \fn int QGridLayout::numRows() const
1824
1825 Use rowCount() instead.
1826*/
1827
1828/*!
1829 \fn int QGridLayout::numCols() const
1830
1831 Use columnCount() instead.
1832*/
1833
1834/*!
1835 \fn void QGridLayout::setColStretch(int col, int stretch)
1836
1837 Use setColumnStretch() instead.
1838*/
1839
1840/*!
1841 \fn int QGridLayout::colStretch(int col) const
1842
1843 Use columnStretch() instead.
1844*/
1845
1846/*!
1847 \fn void QGridLayout::setColSpacing(int col, int minSize)
1848
1849 Use setColumnMinimumWidth() instead.
1850*/
1851
1852/*!
1853 \fn int QGridLayout::colSpacing(int col) const
1854
1855 Use columnSpacing() instead.
1856*/
1857
1858/*!
1859 \fn void QGridLayout::setRowSpacing(int row, int minSize)
1860
1861 Use setRowMinimumHeight(\a row, \a minSize) instead.
1862*/
1863
1864/*!
1865 \fn int QGridLayout::rowSpacing(int row) const
1866
1867 Use rowMinimumHeight(\a row) instead.
1868*/
1869
1870/*!
1871 \fn QRect QGridLayout::cellGeometry(int row, int column) const
1872
1873 Use cellRect(\a row, \a column) instead.
1874*/
1875
1876/*!
1877 \fn void QGridLayout::setOrigin(Qt::Corner corner)
1878
1879 Use setOriginCorner(\a corner) instead.
1880*/
1881
1882/*!
1883 \fn Qt::Corner QGridLayout::origin() const
1884
1885 Use originCorner() instead.
1886*/
1887
1888
1889QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.