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