5dd840e80a71a846af3d0a4430745d2177eb182e
[profile/ivi/qtbase.git] / src / widgets / kernel / qgridlayout.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
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
52 QT_BEGIN_NAMESPACE
53
54 struct 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
67 class QGridBox
68 {
69 public:
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
95 private:
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
107 class QGridLayoutPrivate : public QLayoutPrivate
108 {
109     Q_DECLARE_PUBLIC(QGridLayout)
110 public:
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) const {
171         if (index < things.count()) {
172             const 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
183 private:
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
228 void 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
323 QGridLayoutPrivate::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
337 QGridLayoutPrivate::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
353 void QGridLayoutPrivate::deleteAll()
354 {
355     while (!things.isEmpty())
356         delete things.takeFirst();
357     delete hfwData;
358 }
359
360 bool 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 */
370 void 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
394 int 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
410 int 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
420 QSize 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
439 Qt::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
460 QSize QGridLayoutPrivate::sizeHint(int hSpacing, int vSpacing) const
461 {
462     return findSize(&QLayoutStruct::sizeHint, hSpacing, vSpacing);
463 }
464
465 QSize QGridLayoutPrivate::maximumSize(int hSpacing, int vSpacing) const
466 {
467     return findSize(&QLayoutStruct::maximumSize, hSpacing, vSpacing);
468 }
469
470 QSize QGridLayoutPrivate::minimumSize(int hSpacing, int vSpacing) const
471 {
472     return findSize(&QLayoutStruct::minimumSize, hSpacing, vSpacing);
473 }
474
475 void 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
515 void 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
538 void 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
548 void 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
573 void 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
602 static 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
612 static 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
677 static 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
685 void 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
752 void 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     memset(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
849 void 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 */
869 void 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
912 void 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
963 QRect 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     \inmodule QtWidgets
984
985     QGridLayout takes the space made available to it (by its parent
986     layout or by the parentWidget()), divides it up into rows and
987     columns, and puts each widget it manages into the correct cell.
988
989     Columns and rows behave identically; we will discuss columns, but
990     there are equivalent functions for rows.
991
992     Each column has a minimum width and a stretch factor. The minimum
993     width is the greatest of that set using setColumnMinimumWidth() and the
994     minimum width of each widget in that column. The stretch factor is
995     set using setColumnStretch() and determines how much of the available
996     space the column will get over and above its necessary minimum.
997
998     Normally, each managed widget or layout is put into a cell of its
999     own using addWidget(). It is also possible for a widget to occupy
1000     multiple cells using the row and column spanning overloads of
1001     addItem() and addWidget(). If you do this, QGridLayout will guess
1002     how to distribute the size over the columns/rows (based on the
1003     stretch factors).
1004
1005     To remove a widget from a layout, call removeWidget(). Calling
1006     QWidget::hide() on a widget also effectively removes the widget
1007     from the layout until QWidget::show() is called.
1008
1009     This illustration shows a fragment of a dialog with a five-column,
1010     three-row grid (the grid is shown overlaid in magenta):
1011
1012     \image gridlayout.png A grid layout
1013
1014     Columns 0, 2 and 4 in this dialog fragment are made up of a
1015     QLabel, a QLineEdit, and a QListBox. Columns 1 and 3 are
1016     placeholders made with setColumnMinimumWidth(). Row 0 consists of three
1017     QLabel objects, row 1 of three QLineEdit objects and row 2 of
1018     three QListBox objects. We used placeholder columns (1 and 3) to
1019     get the right amount of space between the columns.
1020
1021     Note that the columns and rows are not equally wide or tall. If
1022     you want two columns to have the same width, you must set their
1023     minimum widths and stretch factors to be the same yourself. You do
1024     this using setColumnMinimumWidth() and setColumnStretch().
1025
1026     If the QGridLayout is not the top-level layout (i.e. does not
1027     manage all of the widget's area and children), you must add it to
1028     its parent layout when you create it, but before you do anything
1029     with it. The normal way to add a layout is by calling
1030     addLayout() on the parent layout.
1031
1032     Once you have added your layout you can start putting widgets and
1033     other layouts into the cells of your grid layout using
1034     addWidget(), addItem(), and addLayout().
1035
1036     QGridLayout also includes two margin widths:
1037     the \l{getContentsMargins()}{contents margin} and the spacing().
1038     The contents margin is the width of the reserved space along each
1039     of the QGridLayout's four sides. The spacing() is the width of the
1040     automatically allocated spacing between neighboring boxes.
1041
1042     The default contents margin values are provided by the
1043     \l{QStyle::pixelMetric()}{style}. The default value Qt styles specify
1044     is 9 for child 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 Management}, {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 */
1057 QGridLayout::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 */
1071 QGridLayout::QGridLayout()
1072     : QLayout(*new QGridLayoutPrivate, 0, 0)
1073 {
1074     Q_D(QGridLayout);
1075     d->expand(1, 1);
1076 }
1077
1078
1079
1080
1081 /*!
1082 \internal (mostly)
1083
1084 Sets the positioning mode used by addItem(). If \a orient is
1085 Qt::Horizontal, this layout is expanded to \a n columns, and items
1086 will be added columns-first. Otherwise it is expanded to \a n rows and
1087 items will be added rows-first.
1088 */
1089
1090 void QGridLayout::setDefaultPositioning(int n, Qt::Orientation orient)
1091 {
1092     Q_D(QGridLayout);
1093     if (orient == Qt::Horizontal) {
1094         d->expand(1, n);
1095         d->addVertical = false;
1096     } else {
1097         d->expand(n,1);
1098         d->addVertical = true;
1099     }
1100 }
1101
1102
1103 /*!
1104     Destroys the grid layout. Geometry management is terminated if
1105     this is a top-level grid.
1106
1107     The layout's widgets aren't destroyed.
1108 */
1109 QGridLayout::~QGridLayout()
1110 {
1111     Q_D(QGridLayout);
1112     d->deleteAll();
1113 }
1114
1115 /*!
1116     \property QGridLayout::horizontalSpacing
1117     \brief the spacing between widgets that are laid out side by side
1118     \since 4.3
1119
1120     If no value is explicitly set, the layout's horizontal spacing is
1121     inherited from the parent layout, or from the style settings for
1122     the parent widget.
1123
1124     \sa verticalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
1125 */
1126 void QGridLayout::setHorizontalSpacing(int spacing)
1127 {
1128     Q_D(QGridLayout);
1129     d->horizontalSpacing = spacing;
1130     invalidate();
1131 }
1132
1133 int QGridLayout::horizontalSpacing() const
1134 {
1135     Q_D(const QGridLayout);
1136     if (d->horizontalSpacing >= 0) {
1137         return d->horizontalSpacing;
1138     } else {
1139         return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
1140     }
1141 }
1142
1143 /*!
1144     \property QGridLayout::verticalSpacing
1145     \brief the spacing between widgets that are laid out on top of each other
1146     \since 4.3
1147
1148     If no value is explicitly set, the layout's vertical spacing is
1149     inherited from the parent layout, or from the style settings for
1150     the parent widget.
1151
1152     \sa horizontalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
1153 */
1154 void QGridLayout::setVerticalSpacing(int spacing)
1155 {
1156     Q_D(QGridLayout);
1157     d->verticalSpacing = spacing;
1158     invalidate();
1159 }
1160
1161 int QGridLayout::verticalSpacing() const
1162 {
1163     Q_D(const QGridLayout);
1164     if (d->verticalSpacing >= 0) {
1165         return d->verticalSpacing;
1166     } else {
1167         return qSmartSpacing(this, QStyle::PM_LayoutVerticalSpacing);
1168     }
1169 }
1170
1171 /*!
1172     This function sets both the vertical and horizontal spacing to
1173     \a spacing.
1174
1175     \sa setVerticalSpacing(), setHorizontalSpacing()
1176 */
1177 void QGridLayout::setSpacing(int spacing)
1178 {
1179     Q_D(QGridLayout);
1180     d->horizontalSpacing = d->verticalSpacing = spacing;
1181     invalidate();
1182 }
1183
1184 /*!
1185     If the vertical spacing is equal to the horizontal spacing,
1186     this function returns that value; otherwise it return -1.
1187
1188     \sa setSpacing(), verticalSpacing(), horizontalSpacing()
1189 */
1190 int QGridLayout::spacing() const
1191 {
1192     int hSpacing = horizontalSpacing();
1193     if (hSpacing == verticalSpacing()) {
1194         return hSpacing;
1195     } else {
1196         return -1;
1197     }
1198 }
1199
1200 /*!
1201     Returns the number of rows in this grid.
1202 */
1203 int QGridLayout::rowCount() const
1204 {
1205     Q_D(const QGridLayout);
1206     return d->numRows();
1207 }
1208
1209 /*!
1210     Returns the number of columns in this grid.
1211 */
1212 int QGridLayout::columnCount() const
1213 {
1214     Q_D(const QGridLayout);
1215     return d->numCols();
1216 }
1217
1218 /*!
1219     \reimp
1220 */
1221 QSize QGridLayout::sizeHint() const
1222 {
1223     Q_D(const QGridLayout);
1224     QSize result(d->sizeHint(horizontalSpacing(), verticalSpacing()));
1225     int left, top, right, bottom;
1226     d->effectiveMargins(&left, &top, &right, &bottom);
1227     result += QSize(left + right, top + bottom);
1228     return result;
1229 }
1230
1231 /*!
1232     \reimp
1233 */
1234 QSize QGridLayout::minimumSize() const
1235 {
1236     Q_D(const QGridLayout);
1237     QSize result(d->minimumSize(horizontalSpacing(), verticalSpacing()));
1238     int left, top, right, bottom;
1239     d->effectiveMargins(&left, &top, &right, &bottom);
1240     result += QSize(left + right, top + bottom);
1241     return result;
1242 }
1243
1244 /*!
1245     \reimp
1246 */
1247 QSize QGridLayout::maximumSize() const
1248 {
1249     Q_D(const QGridLayout);
1250
1251     QSize s = d->maximumSize(horizontalSpacing(), verticalSpacing());
1252     int left, top, right, bottom;
1253     d->effectiveMargins(&left, &top, &right, &bottom);
1254     s += QSize(left + right, top + bottom);
1255     s = s.boundedTo(QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX));
1256     if (alignment() & Qt::AlignHorizontal_Mask)
1257         s.setWidth(QLAYOUTSIZE_MAX);
1258     if (alignment() & Qt::AlignVertical_Mask)
1259         s.setHeight(QLAYOUTSIZE_MAX);
1260     return s;
1261 }
1262
1263 /*!
1264     \reimp
1265 */
1266 bool QGridLayout::hasHeightForWidth() const
1267 {
1268     return ((QGridLayout*)this)->d_func()->hasHeightForWidth(horizontalSpacing(), verticalSpacing());
1269 }
1270
1271 /*!
1272     \reimp
1273 */
1274 int QGridLayout::heightForWidth(int w) const
1275 {
1276     Q_D(const QGridLayout);
1277     QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d);
1278     return dat->heightForWidth(w, horizontalSpacing(), verticalSpacing());
1279 }
1280
1281 /*!
1282     \reimp
1283 */
1284 int QGridLayout::minimumHeightForWidth(int w) const
1285 {
1286     Q_D(const QGridLayout);
1287     QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d);
1288     return dat->minimumHeightForWidth(w, horizontalSpacing(), verticalSpacing());
1289 }
1290
1291 /*!
1292     \reimp
1293 */
1294 int QGridLayout::count() const
1295 {
1296     Q_D(const QGridLayout);
1297     return d->count();
1298 }
1299
1300
1301 /*!
1302     \reimp
1303 */
1304 QLayoutItem *QGridLayout::itemAt(int index) const
1305 {
1306     Q_D(const QGridLayout);
1307     return d->itemAt(index);
1308 }
1309
1310 /*!
1311     \since 4.4
1312
1313     Returns the layout item that occupies cell (\a row, \a column), or 0 if
1314     the cell is empty.
1315
1316     \sa getItemPosition(), indexOf()
1317 */
1318 QLayoutItem *QGridLayout::itemAtPosition(int row, int column) const
1319 {
1320     Q_D(const QGridLayout);
1321     int n = d->things.count();
1322     for (int i = 0; i < n; ++i) {
1323         QGridBox *box = d->things.at(i);
1324         if (row >= box->row && row <= box->toRow(d->rr)
1325                 && column >= box->col && column <= box->toCol(d->cc)) {
1326             return box->item();
1327         }
1328     }
1329     return 0;
1330 }
1331
1332 /*!
1333     \reimp
1334 */
1335 QLayoutItem *QGridLayout::takeAt(int index)
1336 {
1337     Q_D(QGridLayout);
1338     return d->takeAt(index);
1339 }
1340
1341 /*!
1342   Returns the position information of the item with the given \a index.
1343
1344   The variables passed as \a row and \a column are updated with the position of the
1345   item in the layout, and the \a rowSpan and \a columnSpan variables are updated
1346   with the vertical and horizontal spans of the item.
1347
1348   \sa itemAtPosition(), itemAt()
1349 */
1350 void QGridLayout::getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan) const
1351 {
1352     Q_D(const QGridLayout);
1353     d->getItemPosition(index, row, column, rowSpan, columnSpan);
1354 }
1355
1356
1357 /*!
1358     \reimp
1359 */
1360 void QGridLayout::setGeometry(const QRect &rect)
1361 {
1362     Q_D(QGridLayout);
1363     if (d->isDirty() || rect != geometry()) {
1364         QRect cr = alignment() ? alignmentRect(rect) : rect;
1365         d->distribute(cr, horizontalSpacing(), verticalSpacing());
1366         QLayout::setGeometry(rect);
1367     }
1368 }
1369
1370 /*!
1371     Returns the geometry of the cell with row \a row and column \a column
1372     in the grid. Returns an invalid rectangle if \a row or \a column is
1373     outside the grid.
1374
1375     \warning in the current version of Qt this function does not
1376     return valid results until setGeometry() has been called, i.e.
1377     after the parentWidget() is visible.
1378 */
1379 QRect QGridLayout::cellRect(int row, int column) const
1380 {
1381     Q_D(const QGridLayout);
1382     return d->cellRect(row, column);
1383 }
1384
1385 /*!
1386     \reimp
1387 */
1388 void QGridLayout::addItem(QLayoutItem *item)
1389 {
1390     Q_D(QGridLayout);
1391     int r, c;
1392     d->getNextPos(r, c);
1393     addItem(item, r, c);
1394 }
1395
1396 /*!
1397     Adds \a item at position \a row, \a column, spanning \a rowSpan
1398     rows and \a columnSpan columns, and aligns it according to \a
1399     alignment. If \a rowSpan and/or \a columnSpan is -1, then the item
1400     will extend to the bottom and/or right edge, respectively. The
1401     layout takes ownership of the \a item.
1402
1403     \warning Do not use this function to add child layouts or child
1404     widget items. Use addLayout() or addWidget() instead.
1405 */
1406 void QGridLayout::addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
1407 {
1408     Q_D(QGridLayout);
1409     QGridBox *b = new QGridBox(item);
1410     b->setAlignment(alignment);
1411     d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
1412     invalidate();
1413 }
1414
1415 /*
1416   Returns true if the widget \a w can be added to the layout \a l;
1417   otherwise returns false.
1418 */
1419 static bool checkWidget(QLayout *l, QWidget *w)
1420 {
1421     if (!w) {
1422         qWarning("QLayout: Cannot add null widget to %s/%s", l->metaObject()->className(),
1423                   l->objectName().toLocal8Bit().data());
1424         return false;
1425     }
1426     return true;
1427 }
1428
1429 /*!
1430     Adds the given \a widget to the cell grid at \a row, \a column. The
1431     top-left position is (0, 0) by default.
1432
1433     The alignment is specified by \a alignment. The default
1434     alignment is 0, which means that the widget fills the entire cell.
1435
1436 */
1437 void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
1438 {
1439     if (!checkWidget(this, widget))
1440         return;
1441     if (row < 0 || column < 0) {
1442         qWarning("QGridLayout: Cannot add %s/%s to %s/%s at row %d column %d",
1443                  widget->metaObject()->className(), widget->objectName().toLocal8Bit().data(),
1444                  metaObject()->className(), objectName().toLocal8Bit().data(), row, column);
1445         return;
1446     }
1447     addChildWidget(widget);
1448     QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
1449     addItem(b, row, column, 1, 1, alignment);
1450 }
1451
1452 /*!
1453     \overload
1454
1455     This version adds the given \a widget to the cell grid, spanning
1456     multiple rows/columns. The cell will start at \a fromRow, \a
1457     fromColumn spanning \a rowSpan rows and \a columnSpan columns. The
1458     \a widget will have the given \a alignment.
1459
1460     If \a rowSpan and/or \a columnSpan is -1, then the widget will
1461     extend to the bottom and/or right edge, respectively.
1462
1463 */
1464 void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn,
1465                             int rowSpan, int columnSpan, Qt::Alignment alignment)
1466 {
1467     Q_D(QGridLayout);
1468     if (!checkWidget(this, widget))
1469         return;
1470     int toRow = (rowSpan < 0) ? -1 : fromRow + rowSpan - 1;
1471     int toColumn = (columnSpan < 0) ? -1 : fromColumn + columnSpan - 1;
1472     addChildWidget(widget);
1473     QGridBox *b = new QGridBox(this, widget);
1474     b->setAlignment(alignment);
1475     d->add(b, fromRow, toRow, fromColumn, toColumn);
1476     invalidate();
1477 }
1478
1479 /*!
1480     \fn void QGridLayout::addWidget(QWidget *widget)
1481
1482     \overload
1483     \internal
1484 */
1485
1486 /*!
1487     Places the \a layout at position (\a row, \a column) in the grid. The
1488     top-left position is (0, 0).
1489
1490     The alignment is specified by \a alignment. The default
1491     alignment is 0, which means that the widget fills the entire cell.
1492
1493     A non-zero alignment indicates that the layout should not grow to
1494     fill the available space but should be sized according to
1495     sizeHint().
1496
1497
1498     \a layout becomes a child of the grid layout.
1499 */
1500 void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment)
1501 {
1502     Q_D(QGridLayout);
1503     addChildLayout(layout);
1504     QGridBox *b = new QGridBox(layout);
1505     b->setAlignment(alignment);
1506     d->add(b, row, column);
1507 }
1508
1509 /*!
1510   \overload
1511     This version adds the layout \a layout to the cell grid, spanning multiple
1512     rows/columns. The cell will start at \a row, \a column spanning \a
1513     rowSpan rows and \a columnSpan columns.
1514
1515     If \a rowSpan and/or \a columnSpan is -1, then the layout will extend to the bottom
1516     and/or right edge, respectively.
1517 */
1518 void QGridLayout::addLayout(QLayout *layout, int row, int column,
1519                                       int rowSpan, int columnSpan, Qt::Alignment alignment)
1520 {
1521     Q_D(QGridLayout);
1522     addChildLayout(layout);
1523     QGridBox *b = new QGridBox(layout);
1524     b->setAlignment(alignment);
1525     d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
1526 }
1527
1528 /*!
1529     Sets the stretch factor of row \a row to \a stretch. The first row
1530     is number 0.
1531
1532     The stretch factor is relative to the other rows in this grid.
1533     Rows with a higher stretch factor take more of the available
1534     space.
1535
1536     The default stretch factor is 0. If the stretch factor is 0 and no
1537     other row in this table can grow at all, the row may still grow.
1538
1539     \sa rowStretch(), setRowMinimumHeight(), setColumnStretch()
1540 */
1541 void QGridLayout::setRowStretch(int row, int stretch)
1542 {
1543     Q_D(QGridLayout);
1544     d->setRowStretch(row, stretch);
1545     invalidate();
1546 }
1547
1548 /*!
1549     Returns the stretch factor for row \a row.
1550
1551     \sa setRowStretch()
1552 */
1553 int QGridLayout::rowStretch(int row) const
1554 {
1555     Q_D(const QGridLayout);
1556     return d->rowStretch(row);
1557 }
1558
1559 /*!
1560     Returns the stretch factor for column \a column.
1561
1562     \sa setColumnStretch()
1563 */
1564 int QGridLayout::columnStretch(int column) const
1565 {
1566     Q_D(const QGridLayout);
1567     return d->colStretch(column);
1568 }
1569
1570 /*!
1571     Sets the stretch factor of column \a column to \a stretch. The first
1572     column is number 0.
1573
1574     The stretch factor is relative to the other columns in this grid.
1575     Columns with a higher stretch factor take more of the available
1576     space.
1577
1578     The default stretch factor is 0. If the stretch factor is 0 and no
1579     other column in this table can grow at all, the column may still
1580     grow.
1581
1582     An alternative approach is to add spacing using addItem() with a
1583     QSpacerItem.
1584
1585     \sa columnStretch(), setRowStretch()
1586 */
1587 void QGridLayout::setColumnStretch(int column, int stretch)
1588 {
1589     Q_D(QGridLayout);
1590     d->setColStretch(column, stretch);
1591     invalidate();
1592 }
1593
1594
1595
1596 /*!
1597     Sets the minimum height of row \a row to \a minSize pixels.
1598
1599     \sa rowMinimumHeight(), setColumnMinimumWidth()
1600 */
1601 void QGridLayout::setRowMinimumHeight(int row, int minSize)
1602 {
1603     Q_D(QGridLayout);
1604     d->setRowMinimumHeight(row, minSize);
1605     invalidate();
1606 }
1607
1608 /*!
1609     Returns the minimum width set for row \a row.
1610
1611     \sa setRowMinimumHeight()
1612 */
1613 int QGridLayout::rowMinimumHeight(int row) const
1614 {
1615     Q_D(const QGridLayout);
1616     return d->rowSpacing(row);
1617 }
1618
1619 /*!
1620     Sets the minimum width of column \a column to \a minSize pixels.
1621
1622     \sa columnMinimumWidth(), setRowMinimumHeight()
1623 */
1624 void QGridLayout::setColumnMinimumWidth(int column, int minSize)
1625 {
1626     Q_D(QGridLayout);
1627     d->setColumnMinimumWidth(column, minSize);
1628     invalidate();
1629 }
1630
1631 /*!
1632     Returns the column spacing for column \a column.
1633
1634     \sa setColumnMinimumWidth()
1635 */
1636 int QGridLayout::columnMinimumWidth(int column) const
1637 {
1638     Q_D(const QGridLayout);
1639     return d->colSpacing(column);
1640 }
1641
1642 /*!
1643     \reimp
1644 */
1645 Qt::Orientations QGridLayout::expandingDirections() const
1646 {
1647     Q_D(const QGridLayout);
1648     return d->expandingDirections(horizontalSpacing(), verticalSpacing());
1649 }
1650
1651 /*!
1652     Sets the grid's origin corner, i.e. position (0, 0), to \a corner.
1653 */
1654 void QGridLayout::setOriginCorner(Qt::Corner corner)
1655 {
1656     Q_D(QGridLayout);
1657     d->setReversed(corner == Qt::BottomLeftCorner || corner == Qt::BottomRightCorner,
1658                    corner == Qt::TopRightCorner || corner == Qt::BottomRightCorner);
1659 }
1660
1661 /*!
1662     Returns the corner that's used for the grid's origin, i.e. for
1663     position (0, 0).
1664 */
1665 Qt::Corner QGridLayout::originCorner() const
1666 {
1667     Q_D(const QGridLayout);
1668     if (d->horReversed()) {
1669         return d->verReversed() ? Qt::BottomRightCorner : Qt::TopRightCorner;
1670     } else {
1671         return d->verReversed() ? Qt::BottomLeftCorner : Qt::TopLeftCorner;
1672     }
1673 }
1674
1675 /*!
1676     \reimp
1677 */
1678 void QGridLayout::invalidate()
1679 {
1680     Q_D(QGridLayout);
1681     d->setDirty();
1682     QLayout::invalidate();
1683 }
1684
1685 QT_END_NAMESPACE