1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** Contact: Qt Software Information ([email protected])
|
---|
5 | **
|
---|
6 | ** This file is part of the QtGui module of the Qt Toolkit.
|
---|
7 | **
|
---|
8 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
9 | ** Commercial Usage
|
---|
10 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
11 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
12 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
13 | ** a written agreement between you and Nokia.
|
---|
14 | **
|
---|
15 | ** GNU Lesser General Public License Usage
|
---|
16 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
17 | ** General Public License version 2.1 as published by the Free Software
|
---|
18 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
19 | ** packaging of this file. Please review the following information to
|
---|
20 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
21 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
22 | **
|
---|
23 | ** In addition, as a special exception, Nokia gives you certain
|
---|
24 | ** additional rights. These rights are described in the Nokia Qt LGPL
|
---|
25 | ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
---|
26 | ** package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you are unsure which license is appropriate for your use, please
|
---|
37 | ** contact the sales department at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include "qgridlayout.h"
|
---|
43 | #include "qapplication.h"
|
---|
44 | #include "qwidget.h"
|
---|
45 | #include "qlist.h"
|
---|
46 | #include "qsizepolicy.h"
|
---|
47 | #include "qvector.h"
|
---|
48 | #include "qvarlengtharray.h"
|
---|
49 | #include "qlayoutengine_p.h"
|
---|
50 | #include "qlayout_p.h"
|
---|
51 |
|
---|
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) {
|
---|
171 | if (index < things.count()) {
|
---|
172 | QGridBox *b = things.at(index);
|
---|
173 | int toRow = b->toRow(rr);
|
---|
174 | int toCol = b->toCol(cc);
|
---|
175 | *row = b->row;
|
---|
176 | *column = b->col;
|
---|
177 | *rowSpan = toRow - *row + 1;
|
---|
178 | *columnSpan = toCol - *column +1;
|
---|
179 | }
|
---|
180 | }
|
---|
181 | void deleteAll();
|
---|
182 |
|
---|
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 | qMemSet(grid.data(), 0, rr * cc * sizeof(QGridBox *));
|
---|
783 |
|
---|
784 | /*
|
---|
785 | Initialize 'sizes' and 'grid' data structures, and insert
|
---|
786 | non-spanning items to our row and column data structures.
|
---|
787 | */
|
---|
788 | for (i = 0; i < n; ++i) {
|
---|
789 | QGridBox * const box = things.at(i);
|
---|
790 | sizes[i].minS = box->minimumSize();
|
---|
791 | sizes[i].hint = box->sizeHint();
|
---|
792 | sizes[i].maxS = box->maximumSize();
|
---|
793 |
|
---|
794 | if (box->hasHeightForWidth())
|
---|
795 | has_hfw = true;
|
---|
796 |
|
---|
797 | if (box->row == box->toRow(rr)) {
|
---|
798 | addData(box, sizes[i], true, false);
|
---|
799 | } else {
|
---|
800 | initEmptyMultiBox(rowData, box->row, box->toRow(rr));
|
---|
801 | has_multi = true;
|
---|
802 | }
|
---|
803 |
|
---|
804 | if (box->col == box->toCol(cc)) {
|
---|
805 | addData(box, sizes[i], false, true);
|
---|
806 | } else {
|
---|
807 | initEmptyMultiBox(colData, box->col, box->toCol(cc));
|
---|
808 | has_multi = true;
|
---|
809 | }
|
---|
810 |
|
---|
811 | for (int r = box->row; r <= box->toRow(rr); ++r) {
|
---|
812 | for (int c = box->col; c <= box->toCol(cc); ++c) {
|
---|
813 | gridAt(grid.data(), r, c, cc) = box;
|
---|
814 | }
|
---|
815 | }
|
---|
816 | }
|
---|
817 |
|
---|
818 | setupSpacings(colData, grid.data(), hSpacing, Qt::Horizontal);
|
---|
819 | setupSpacings(rowData, grid.data(), vSpacing, Qt::Vertical);
|
---|
820 |
|
---|
821 | /*
|
---|
822 | Insert multicell items to our row and column data structures.
|
---|
823 | This must be done after the non-spanning items to obtain a
|
---|
824 | better distribution in distributeMultiBox().
|
---|
825 | */
|
---|
826 | if (has_multi) {
|
---|
827 | for (i = 0; i < n; ++i) {
|
---|
828 | QGridBox * const box = things.at(i);
|
---|
829 |
|
---|
830 | if (box->row != box->toRow(rr))
|
---|
831 | distributeMultiBox(rowData, box->row, box->toRow(rr), sizes[i].minS.height(),
|
---|
832 | sizes[i].hint.height(), rStretch, box->vStretch());
|
---|
833 | if (box->col != box->toCol(cc))
|
---|
834 | distributeMultiBox(colData, box->col, box->toCol(cc), sizes[i].minS.width(),
|
---|
835 | sizes[i].hint.width(), cStretch, box->hStretch());
|
---|
836 | }
|
---|
837 | }
|
---|
838 |
|
---|
839 | for (i = 0; i < rr; i++)
|
---|
840 | rowData[i].expansive = rowData.at(i).expansive || rowData.at(i).stretch > 0;
|
---|
841 | for (i = 0; i < cc; i++)
|
---|
842 | colData[i].expansive = colData.at(i).expansive || colData.at(i).stretch > 0;
|
---|
843 |
|
---|
844 | q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
|
---|
845 |
|
---|
846 | needRecalc = false;
|
---|
847 | }
|
---|
848 |
|
---|
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 | \ingroup appearance
|
---|
984 | \mainclass
|
---|
985 |
|
---|
986 | QGridLayout takes the space made available to it (by its parent
|
---|
987 | layout or by the parentWidget()), divides it up into rows and
|
---|
988 | columns, and puts each widget it manages into the correct cell.
|
---|
989 |
|
---|
990 | Columns and rows behave identically; we will discuss columns, but
|
---|
991 | there are equivalent functions for rows.
|
---|
992 |
|
---|
993 | Each column has a minimum width and a stretch factor. The minimum
|
---|
994 | width is the greatest of that set using setColumnMinimumWidth() and the
|
---|
995 | minimum width of each widget in that column. The stretch factor is
|
---|
996 | set using setColumnStretch() and determines how much of the available
|
---|
997 | space the column will get over and above its necessary minimum.
|
---|
998 |
|
---|
999 | Normally, each managed widget or layout is put into a cell of its
|
---|
1000 | own using addWidget(). It is also possible for a widget to occupy
|
---|
1001 | multiple cells using the row and column spanning overloads of
|
---|
1002 | addItem() and addWidget(). If you do this, QGridLayout will guess
|
---|
1003 | how to distribute the size over the columns/rows (based on the
|
---|
1004 | stretch factors).
|
---|
1005 |
|
---|
1006 | To remove a widget from a layout, call removeWidget(). Calling
|
---|
1007 | QWidget::hide() on a widget also effectively removes the widget
|
---|
1008 | from the layout until QWidget::show() is called.
|
---|
1009 |
|
---|
1010 | This illustration shows a fragment of a dialog with a five-column,
|
---|
1011 | three-row grid (the grid is shown overlaid in magenta):
|
---|
1012 |
|
---|
1013 | \image gridlayout.png A grid layout
|
---|
1014 |
|
---|
1015 | Columns 0, 2 and 4 in this dialog fragment are made up of a
|
---|
1016 | QLabel, a QLineEdit, and a QListBox. Columns 1 and 3 are
|
---|
1017 | placeholders made with setColumnMinimumWidth(). Row 0 consists of three
|
---|
1018 | QLabel objects, row 1 of three QLineEdit objects and row 2 of
|
---|
1019 | three QListBox objects. We used placeholder columns (1 and 3) to
|
---|
1020 | get the right amount of space between the columns.
|
---|
1021 |
|
---|
1022 | Note that the columns and rows are not equally wide or tall. If
|
---|
1023 | you want two columns to have the same width, you must set their
|
---|
1024 | minimum widths and stretch factors to be the same yourself. You do
|
---|
1025 | this using setColumnMinimumWidth() and setColumnStretch().
|
---|
1026 |
|
---|
1027 | If the QGridLayout is not the top-level layout (i.e. does not
|
---|
1028 | manage all of the widget's area and children), you must add it to
|
---|
1029 | its parent layout when you create it, but before you do anything
|
---|
1030 | with it. The normal way to add a layout is by calling
|
---|
1031 | addLayout() on the parent layout.
|
---|
1032 |
|
---|
1033 | Once you have added your layout you can start putting widgets and
|
---|
1034 | other layouts into the cells of your grid layout using
|
---|
1035 | addWidget(), addItem(), and addLayout().
|
---|
1036 |
|
---|
1037 | QGridLayout also includes two margin widths: the margin() and the
|
---|
1038 | spacing(). The margin is the width of the reserved space along
|
---|
1039 | each of the QGridLayout's four sides. The spacing is the width of
|
---|
1040 | the automatically allocated spacing between neighboring boxes.
|
---|
1041 |
|
---|
1042 | The default margin() and spacing() values are provided by the
|
---|
1043 | style. The default margin Qt styles specify is 9 for child
|
---|
1044 | widgets and 11 for windows. The spacing defaults to the same as
|
---|
1045 | the margin width for a top-level layout, or to the same as the
|
---|
1046 | parent layout.
|
---|
1047 |
|
---|
1048 | \sa QBoxLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example}
|
---|
1049 | */
|
---|
1050 |
|
---|
1051 |
|
---|
1052 | /*!
|
---|
1053 | Constructs a new QGridLayout with parent widget, \a parent. The
|
---|
1054 | layout has one row and one column initially, and will expand when
|
---|
1055 | new items are inserted.
|
---|
1056 | */
|
---|
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 | #ifdef QT3_SUPPORT
|
---|
1080 | /*!
|
---|
1081 | \obsolete
|
---|
1082 | Constructs a new QGridLayout with \a nRows rows, \a nCols columns
|
---|
1083 | and parent widget, \a parent. \a parent may not be 0. The grid
|
---|
1084 | layout is called \a name.
|
---|
1085 |
|
---|
1086 | \a margin is the number of pixels between the edge of the widget
|
---|
1087 | and its managed children. \a space is the default number of pixels
|
---|
1088 | between cells. If \a space is -1, the value of \a margin is used.
|
---|
1089 | */
|
---|
1090 | QGridLayout::QGridLayout(QWidget *parent, int nRows, int nCols, int margin,
|
---|
1091 | int space, const char *name)
|
---|
1092 | : QLayout(*new QGridLayoutPrivate, 0, parent)
|
---|
1093 | {
|
---|
1094 | Q_D(QGridLayout);
|
---|
1095 | d->expand(nRows, nCols);
|
---|
1096 | setMargin(margin);
|
---|
1097 | setSpacing(space < 0 ? margin : space);
|
---|
1098 | setObjectName(QString::fromAscii(name));
|
---|
1099 | }
|
---|
1100 |
|
---|
1101 | /*!
|
---|
1102 | \obsolete
|
---|
1103 |
|
---|
1104 | Constructs a new grid with \a nRows rows and \a nCols columns. If
|
---|
1105 | \a spacing is -1, this QGridLayout inherits its parent's
|
---|
1106 | spacing(); otherwise \a spacing is used. The grid layout is called
|
---|
1107 | \a name.
|
---|
1108 |
|
---|
1109 | You must insert this grid into another layout. You can insert
|
---|
1110 | widgets and layouts into this layout at any time, but laying out
|
---|
1111 | will not be performed before this is inserted into another layout.
|
---|
1112 | */
|
---|
1113 | QGridLayout::QGridLayout(QLayout *parentLayout, int nRows, int nCols,
|
---|
1114 | int spacing, const char *name)
|
---|
1115 | : QLayout(*new QGridLayoutPrivate, parentLayout, 0)
|
---|
1116 | {
|
---|
1117 | Q_D(QGridLayout);
|
---|
1118 | d->expand(nRows, nCols);
|
---|
1119 | setSpacing(spacing);
|
---|
1120 | setObjectName(QString::fromAscii(name));
|
---|
1121 | }
|
---|
1122 |
|
---|
1123 | /*!
|
---|
1124 | \obsolete
|
---|
1125 |
|
---|
1126 | Constructs a new grid with \a nRows rows and \a nCols columns. If
|
---|
1127 | \a spacing is -1, this QGridLayout inherits its parent's
|
---|
1128 | spacing(); otherwise \a spacing is used. The grid layout is called
|
---|
1129 | \a name.
|
---|
1130 |
|
---|
1131 | You must insert this grid into another layout. You can insert
|
---|
1132 | widgets and layouts into this layout at any time, but laying out
|
---|
1133 | will not be performed before this is inserted into another layout.
|
---|
1134 | */
|
---|
1135 | QGridLayout::QGridLayout(int nRows, int nCols, int spacing, const char *name)
|
---|
1136 | : QLayout(*new QGridLayoutPrivate, 0, 0)
|
---|
1137 | {
|
---|
1138 | Q_D(QGridLayout);
|
---|
1139 | d->expand(nRows, nCols);
|
---|
1140 | setSpacing(spacing);
|
---|
1141 | setObjectName(QString::fromAscii(name));
|
---|
1142 | }
|
---|
1143 | #endif
|
---|
1144 |
|
---|
1145 |
|
---|
1146 | /*!
|
---|
1147 | \internal (mostly)
|
---|
1148 |
|
---|
1149 | Sets the positioning mode used by addItem(). If \a orient is
|
---|
1150 | Qt::Horizontal, this layout is expanded to \a n columns, and items
|
---|
1151 | will be added columns-first. Otherwise it is expanded to \a n rows and
|
---|
1152 | items will be added rows-first.
|
---|
1153 | */
|
---|
1154 |
|
---|
1155 | void QGridLayout::setDefaultPositioning(int n, Qt::Orientation orient)
|
---|
1156 | {
|
---|
1157 | Q_D(QGridLayout);
|
---|
1158 | if (orient == Qt::Horizontal) {
|
---|
1159 | d->expand(1, n);
|
---|
1160 | d->addVertical = false;
|
---|
1161 | } else {
|
---|
1162 | d->expand(n,1);
|
---|
1163 | d->addVertical = true;
|
---|
1164 | }
|
---|
1165 | }
|
---|
1166 |
|
---|
1167 |
|
---|
1168 | /*!
|
---|
1169 | Destroys the grid layout. Geometry management is terminated if
|
---|
1170 | this is a top-level grid.
|
---|
1171 |
|
---|
1172 | The layout's widgets aren't destroyed.
|
---|
1173 | */
|
---|
1174 | QGridLayout::~QGridLayout()
|
---|
1175 | {
|
---|
1176 | Q_D(QGridLayout);
|
---|
1177 | d->deleteAll();
|
---|
1178 | }
|
---|
1179 |
|
---|
1180 | /*!
|
---|
1181 | \property QGridLayout::horizontalSpacing
|
---|
1182 | \brief the spacing between widgets that are laid out side by side
|
---|
1183 | \since 4.3
|
---|
1184 |
|
---|
1185 | If no value is explicitly set, the layout's horizontal spacing is
|
---|
1186 | inherited from the parent layout, or from the style settings for
|
---|
1187 | the parent widget.
|
---|
1188 |
|
---|
1189 | \sa verticalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
|
---|
1190 | */
|
---|
1191 | void QGridLayout::setHorizontalSpacing(int spacing)
|
---|
1192 | {
|
---|
1193 | Q_D(QGridLayout);
|
---|
1194 | d->horizontalSpacing = spacing;
|
---|
1195 | invalidate();
|
---|
1196 | }
|
---|
1197 |
|
---|
1198 | int QGridLayout::horizontalSpacing() const
|
---|
1199 | {
|
---|
1200 | Q_D(const QGridLayout);
|
---|
1201 | if (d->horizontalSpacing >= 0) {
|
---|
1202 | return d->horizontalSpacing;
|
---|
1203 | } else {
|
---|
1204 | return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing);
|
---|
1205 | }
|
---|
1206 | }
|
---|
1207 |
|
---|
1208 | /*!
|
---|
1209 | \property QGridLayout::verticalSpacing
|
---|
1210 | \brief the spacing between widgets that are laid out on top of each other
|
---|
1211 | \since 4.3
|
---|
1212 |
|
---|
1213 | If no value is explicitly set, the layout's vertical spacing is
|
---|
1214 | inherited from the parent layout, or from the style settings for
|
---|
1215 | the parent widget.
|
---|
1216 |
|
---|
1217 | \sa horizontalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing}
|
---|
1218 | */
|
---|
1219 | void QGridLayout::setVerticalSpacing(int spacing)
|
---|
1220 | {
|
---|
1221 | Q_D(QGridLayout);
|
---|
1222 | d->verticalSpacing = spacing;
|
---|
1223 | invalidate();
|
---|
1224 | }
|
---|
1225 |
|
---|
1226 | int QGridLayout::verticalSpacing() const
|
---|
1227 | {
|
---|
1228 | Q_D(const QGridLayout);
|
---|
1229 | if (d->verticalSpacing >= 0) {
|
---|
1230 | return d->verticalSpacing;
|
---|
1231 | } else {
|
---|
1232 | return qSmartSpacing(this, QStyle::PM_LayoutVerticalSpacing);
|
---|
1233 | }
|
---|
1234 | }
|
---|
1235 |
|
---|
1236 | /*!
|
---|
1237 | This function sets both the vertical and horizontal spacing to
|
---|
1238 | \a spacing.
|
---|
1239 |
|
---|
1240 | \sa setVerticalSpacing(), setHorizontalSpacing()
|
---|
1241 | */
|
---|
1242 | void QGridLayout::setSpacing(int spacing)
|
---|
1243 | {
|
---|
1244 | Q_D(QGridLayout);
|
---|
1245 | d->horizontalSpacing = d->verticalSpacing = spacing;
|
---|
1246 | invalidate();
|
---|
1247 | }
|
---|
1248 |
|
---|
1249 | /*!
|
---|
1250 | If the vertical spacing is equal to the horizontal spacing,
|
---|
1251 | this function returns that value; otherwise it return -1.
|
---|
1252 |
|
---|
1253 | \sa setSpacing(), verticalSpacing(), horizontalSpacing()
|
---|
1254 | */
|
---|
1255 | int QGridLayout::spacing() const
|
---|
1256 | {
|
---|
1257 | int hSpacing = horizontalSpacing();
|
---|
1258 | if (hSpacing == verticalSpacing()) {
|
---|
1259 | return hSpacing;
|
---|
1260 | } else {
|
---|
1261 | return -1;
|
---|
1262 | }
|
---|
1263 | }
|
---|
1264 |
|
---|
1265 | /*!
|
---|
1266 | Returns the number of rows in this grid.
|
---|
1267 | */
|
---|
1268 | int QGridLayout::rowCount() const
|
---|
1269 | {
|
---|
1270 | Q_D(const QGridLayout);
|
---|
1271 | return d->numRows();
|
---|
1272 | }
|
---|
1273 |
|
---|
1274 | /*!
|
---|
1275 | Returns the number of columns in this grid.
|
---|
1276 | */
|
---|
1277 | int QGridLayout::columnCount() const
|
---|
1278 | {
|
---|
1279 | Q_D(const QGridLayout);
|
---|
1280 | return d->numCols();
|
---|
1281 | }
|
---|
1282 |
|
---|
1283 | /*!
|
---|
1284 | \reimp
|
---|
1285 | */
|
---|
1286 | QSize QGridLayout::sizeHint() const
|
---|
1287 | {
|
---|
1288 | Q_D(const QGridLayout);
|
---|
1289 | QSize result(d->sizeHint(horizontalSpacing(), verticalSpacing()));
|
---|
1290 | int left, top, right, bottom;
|
---|
1291 | d->effectiveMargins(&left, &top, &right, &bottom);
|
---|
1292 | result += QSize(left + right, top + bottom);
|
---|
1293 | return result;
|
---|
1294 | }
|
---|
1295 |
|
---|
1296 | /*!
|
---|
1297 | \reimp
|
---|
1298 | */
|
---|
1299 | QSize QGridLayout::minimumSize() const
|
---|
1300 | {
|
---|
1301 | Q_D(const QGridLayout);
|
---|
1302 | QSize result(d->minimumSize(horizontalSpacing(), verticalSpacing()));
|
---|
1303 | int left, top, right, bottom;
|
---|
1304 | d->effectiveMargins(&left, &top, &right, &bottom);
|
---|
1305 | result += QSize(left + right, top + bottom);
|
---|
1306 | return result;
|
---|
1307 | }
|
---|
1308 |
|
---|
1309 | /*!
|
---|
1310 | \reimp
|
---|
1311 | */
|
---|
1312 | QSize QGridLayout::maximumSize() const
|
---|
1313 | {
|
---|
1314 | Q_D(const QGridLayout);
|
---|
1315 |
|
---|
1316 | QSize s = d->maximumSize(horizontalSpacing(), verticalSpacing());
|
---|
1317 | int left, top, right, bottom;
|
---|
1318 | d->effectiveMargins(&left, &top, &right, &bottom);
|
---|
1319 | s += QSize(left + right, top + bottom);
|
---|
1320 | s = s.boundedTo(QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX));
|
---|
1321 | if (alignment() & Qt::AlignHorizontal_Mask)
|
---|
1322 | s.setWidth(QLAYOUTSIZE_MAX);
|
---|
1323 | if (alignment() & Qt::AlignVertical_Mask)
|
---|
1324 | s.setHeight(QLAYOUTSIZE_MAX);
|
---|
1325 | return s;
|
---|
1326 | }
|
---|
1327 |
|
---|
1328 | /*!
|
---|
1329 | \reimp
|
---|
1330 | */
|
---|
1331 | bool QGridLayout::hasHeightForWidth() const
|
---|
1332 | {
|
---|
1333 | return ((QGridLayout*)this)->d_func()->hasHeightForWidth(horizontalSpacing(), verticalSpacing());
|
---|
1334 | }
|
---|
1335 |
|
---|
1336 | /*!
|
---|
1337 | \reimp
|
---|
1338 | */
|
---|
1339 | int QGridLayout::heightForWidth(int w) const
|
---|
1340 | {
|
---|
1341 | Q_D(const QGridLayout);
|
---|
1342 | QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d);
|
---|
1343 | return dat->heightForWidth(w, horizontalSpacing(), verticalSpacing());
|
---|
1344 | }
|
---|
1345 |
|
---|
1346 | /*!
|
---|
1347 | \reimp
|
---|
1348 | */
|
---|
1349 | int QGridLayout::minimumHeightForWidth(int w) const
|
---|
1350 | {
|
---|
1351 | Q_D(const QGridLayout);
|
---|
1352 | QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d);
|
---|
1353 | return dat->minimumHeightForWidth(w, horizontalSpacing(), verticalSpacing());
|
---|
1354 | }
|
---|
1355 |
|
---|
1356 | #ifdef QT3_SUPPORT
|
---|
1357 | /*!
|
---|
1358 | \compat
|
---|
1359 |
|
---|
1360 | Searches for widget \a w in this layout (not including child
|
---|
1361 | layouts). If \a w is found, it sets \c{*}\a{row} and
|
---|
1362 | \c{*}\a{column} to the row and column that the widget
|
---|
1363 | occupies and returns true; otherwise returns false.
|
---|
1364 |
|
---|
1365 | If the widget spans multiple rows/columns, the top-left cell
|
---|
1366 | is returned.
|
---|
1367 |
|
---|
1368 | Use indexOf() and getItemPosition() instead.
|
---|
1369 | */
|
---|
1370 | bool QGridLayout::findWidget(QWidget* w, int *row, int *column)
|
---|
1371 | {
|
---|
1372 | Q_D(QGridLayout);
|
---|
1373 | int index = indexOf(w);
|
---|
1374 | if (index < 0)
|
---|
1375 | return false;
|
---|
1376 | int dummy1, dummy2;
|
---|
1377 | d->getItemPosition(index, row, column, &dummy1, &dummy2);
|
---|
1378 | return true;
|
---|
1379 | }
|
---|
1380 | #endif
|
---|
1381 | /*!
|
---|
1382 | \reimp
|
---|
1383 | */
|
---|
1384 | int QGridLayout::count() const
|
---|
1385 | {
|
---|
1386 | Q_D(const QGridLayout);
|
---|
1387 | return d->count();
|
---|
1388 | }
|
---|
1389 |
|
---|
1390 |
|
---|
1391 | /*!
|
---|
1392 | \reimp
|
---|
1393 | */
|
---|
1394 | QLayoutItem *QGridLayout::itemAt(int index) const
|
---|
1395 | {
|
---|
1396 | Q_D(const QGridLayout);
|
---|
1397 | return d->itemAt(index);
|
---|
1398 | }
|
---|
1399 |
|
---|
1400 | /*!
|
---|
1401 | \since 4.4
|
---|
1402 |
|
---|
1403 | Returns the layout item that occupies cell (\a row, \a column), or 0 if
|
---|
1404 | the cell is empty.
|
---|
1405 |
|
---|
1406 | \sa getItemPosition(), indexOf()
|
---|
1407 | */
|
---|
1408 | QLayoutItem *QGridLayout::itemAtPosition(int row, int column) const
|
---|
1409 | {
|
---|
1410 | Q_D(const QGridLayout);
|
---|
1411 | int n = d->things.count();
|
---|
1412 | for (int i = 0; i < n; ++i) {
|
---|
1413 | QGridBox *box = d->things.at(i);
|
---|
1414 | if (row >= box->row && row <= box->toRow(d->rr)
|
---|
1415 | && column >= box->col && column <= box->toCol(d->cc)) {
|
---|
1416 | return box->item();
|
---|
1417 | }
|
---|
1418 | }
|
---|
1419 | return 0;
|
---|
1420 | }
|
---|
1421 |
|
---|
1422 | /*!
|
---|
1423 | \reimp
|
---|
1424 | */
|
---|
1425 | QLayoutItem *QGridLayout::takeAt(int index)
|
---|
1426 | {
|
---|
1427 | Q_D(QGridLayout);
|
---|
1428 | return d->takeAt(index);
|
---|
1429 | }
|
---|
1430 |
|
---|
1431 | /*!
|
---|
1432 | Returns the position information of the item with the given \a index.
|
---|
1433 |
|
---|
1434 | The variables passed as \a row and \a column are updated with the position of the
|
---|
1435 | item in the layout, and the \a rowSpan and \a columnSpan variables are updated
|
---|
1436 | with the vertical and horizontal spans of the item.
|
---|
1437 |
|
---|
1438 | \sa itemAtPosition(), itemAt()
|
---|
1439 | */
|
---|
1440 | void QGridLayout::getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan)
|
---|
1441 | {
|
---|
1442 | Q_D(QGridLayout);
|
---|
1443 | d->getItemPosition(index, row, column, rowSpan, columnSpan);
|
---|
1444 | }
|
---|
1445 |
|
---|
1446 |
|
---|
1447 | /*!
|
---|
1448 | \reimp
|
---|
1449 | */
|
---|
1450 | void QGridLayout::setGeometry(const QRect &rect)
|
---|
1451 | {
|
---|
1452 | Q_D(QGridLayout);
|
---|
1453 | if (d->isDirty() || rect != geometry()) {
|
---|
1454 | QRect cr = alignment() ? alignmentRect(rect) : rect;
|
---|
1455 | d->distribute(cr, horizontalSpacing(), verticalSpacing());
|
---|
1456 | QLayout::setGeometry(rect);
|
---|
1457 | }
|
---|
1458 | }
|
---|
1459 |
|
---|
1460 | /*!
|
---|
1461 | Returns the geometry of the cell with row \a row and column \a column
|
---|
1462 | in the grid. Returns an invalid rectangle if \a row or \a column is
|
---|
1463 | outside the grid.
|
---|
1464 |
|
---|
1465 | \warning in the current version of Qt this function does not
|
---|
1466 | return valid results until setGeometry() has been called, i.e.
|
---|
1467 | after the parentWidget() is visible.
|
---|
1468 | */
|
---|
1469 | QRect QGridLayout::cellRect(int row, int column) const
|
---|
1470 | {
|
---|
1471 | Q_D(const QGridLayout);
|
---|
1472 | return d->cellRect(row, column);
|
---|
1473 | }
|
---|
1474 | #ifdef QT3_SUPPORT
|
---|
1475 | /*!
|
---|
1476 | \obsolete
|
---|
1477 | Expands this grid so that it will have \a nRows rows and \a nCols
|
---|
1478 | columns. Will not shrink the grid. You should not need to call
|
---|
1479 | this function because QGridLayout expands automatically as new
|
---|
1480 | items are inserted.
|
---|
1481 | */
|
---|
1482 | void QGridLayout::expand(int nRows, int nCols)
|
---|
1483 | {
|
---|
1484 | Q_D(QGridLayout);
|
---|
1485 | d->expand(nRows, nCols);
|
---|
1486 | }
|
---|
1487 | #endif
|
---|
1488 |
|
---|
1489 | /*!
|
---|
1490 | \reimp
|
---|
1491 | */
|
---|
1492 | void QGridLayout::addItem(QLayoutItem *item)
|
---|
1493 | {
|
---|
1494 | Q_D(QGridLayout);
|
---|
1495 | int r, c;
|
---|
1496 | d->getNextPos(r, c);
|
---|
1497 | addItem(item, r, c);
|
---|
1498 | }
|
---|
1499 |
|
---|
1500 | /*!
|
---|
1501 | Adds \a item at position \a row, \a column, spanning \a rowSpan
|
---|
1502 | rows and \a columnSpan columns, and aligns it according to \a
|
---|
1503 | alignment. If \a rowSpan and/or \a columnSpan is -1, then the item
|
---|
1504 | will extend to the bottom and/or right edge, respectively. The
|
---|
1505 | layout takes ownership of the \a item.
|
---|
1506 |
|
---|
1507 | \warning Do not use this function to add child layouts or child
|
---|
1508 | widget items. Use addLayout() or addWidget() instead.
|
---|
1509 | */
|
---|
1510 | void QGridLayout::addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
|
---|
1511 | {
|
---|
1512 | Q_D(QGridLayout);
|
---|
1513 | QGridBox *b = new QGridBox(item);
|
---|
1514 | b->setAlignment(alignment);
|
---|
1515 | d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
|
---|
1516 | invalidate();
|
---|
1517 | }
|
---|
1518 |
|
---|
1519 | /*
|
---|
1520 | Returns true if the widget \a w can be added to the layout \a l;
|
---|
1521 | otherwise returns false.
|
---|
1522 | */
|
---|
1523 | static bool checkWidget(QLayout *l, QWidget *w)
|
---|
1524 | {
|
---|
1525 | if (!w) {
|
---|
1526 | qWarning("QLayout: Cannot add null widget to %s/%s", l->metaObject()->className(),
|
---|
1527 | l->objectName().toLocal8Bit().data());
|
---|
1528 | return false;
|
---|
1529 | }
|
---|
1530 | return true;
|
---|
1531 | }
|
---|
1532 |
|
---|
1533 | /*!
|
---|
1534 | Adds the given \a widget to the cell grid at \a row, \a column. The
|
---|
1535 | top-left position is (0, 0) by default.
|
---|
1536 |
|
---|
1537 | The alignment is specified by \a alignment. The default
|
---|
1538 | alignment is 0, which means that the widget fills the entire cell.
|
---|
1539 |
|
---|
1540 | */
|
---|
1541 | void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
|
---|
1542 | {
|
---|
1543 | if (!checkWidget(this, widget))
|
---|
1544 | return;
|
---|
1545 | if (row < 0 || column < 0) {
|
---|
1546 | qWarning("QGridLayout: Cannot add %s/%s to %s/%s at row %d column %d",
|
---|
1547 | widget->metaObject()->className(), widget->objectName().toLocal8Bit().data(),
|
---|
1548 | metaObject()->className(), objectName().toLocal8Bit().data(), row, column);
|
---|
1549 | return;
|
---|
1550 | }
|
---|
1551 | addChildWidget(widget);
|
---|
1552 | QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
|
---|
1553 | addItem(b, row, column, 1, 1, alignment);
|
---|
1554 | }
|
---|
1555 |
|
---|
1556 | /*!
|
---|
1557 | \overload
|
---|
1558 |
|
---|
1559 | This version adds the given \a widget to the cell grid, spanning
|
---|
1560 | multiple rows/columns. The cell will start at \a fromRow, \a
|
---|
1561 | fromColumn spanning \a rowSpan rows and \a columnSpan columns. The
|
---|
1562 | \a widget will have the given \a alignment.
|
---|
1563 |
|
---|
1564 | If \a rowSpan and/or \a columnSpan is -1, then the widget will
|
---|
1565 | extend to the bottom and/or right edge, respectively.
|
---|
1566 |
|
---|
1567 | */
|
---|
1568 | void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn,
|
---|
1569 | int rowSpan, int columnSpan, Qt::Alignment alignment)
|
---|
1570 | {
|
---|
1571 | Q_D(QGridLayout);
|
---|
1572 | if (!checkWidget(this, widget))
|
---|
1573 | return;
|
---|
1574 | int toRow = (rowSpan < 0) ? -1 : fromRow + rowSpan - 1;
|
---|
1575 | int toColumn = (columnSpan < 0) ? -1 : fromColumn + columnSpan - 1;
|
---|
1576 | addChildWidget(widget);
|
---|
1577 | QGridBox *b = new QGridBox(this, widget);
|
---|
1578 | b->setAlignment(alignment);
|
---|
1579 | d->add(b, fromRow, toRow, fromColumn, toColumn);
|
---|
1580 | invalidate();
|
---|
1581 | }
|
---|
1582 |
|
---|
1583 | /*!
|
---|
1584 | \fn void QGridLayout::addWidget(QWidget *widget)
|
---|
1585 |
|
---|
1586 | \overload
|
---|
1587 | \internal
|
---|
1588 | */
|
---|
1589 |
|
---|
1590 | /*!
|
---|
1591 | Places the \a layout at position (\a row, \a column) in the grid. The
|
---|
1592 | top-left position is (0, 0).
|
---|
1593 |
|
---|
1594 | The alignment is specified by \a alignment. The default
|
---|
1595 | alignment is 0, which means that the widget fills the entire cell.
|
---|
1596 |
|
---|
1597 | A non-zero alignment indicates that the layout should not grow to
|
---|
1598 | fill the available space but should be sized according to
|
---|
1599 | sizeHint().
|
---|
1600 |
|
---|
1601 |
|
---|
1602 | \a layout becomes a child of the grid layout.
|
---|
1603 | */
|
---|
1604 | void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment)
|
---|
1605 | {
|
---|
1606 | Q_D(QGridLayout);
|
---|
1607 | addChildLayout(layout);
|
---|
1608 | QGridBox *b = new QGridBox(layout);
|
---|
1609 | b->setAlignment(alignment);
|
---|
1610 | d->add(b, row, column);
|
---|
1611 | }
|
---|
1612 |
|
---|
1613 | /*!
|
---|
1614 | \overload
|
---|
1615 | This version adds the layout \a layout to the cell grid, spanning multiple
|
---|
1616 | rows/columns. The cell will start at \a row, \a column spanning \a
|
---|
1617 | rowSpan rows and \a columnSpan columns.
|
---|
1618 |
|
---|
1619 | If \a rowSpan and/or \a columnSpan is -1, then the layout will extend to the bottom
|
---|
1620 | and/or right edge, respectively.
|
---|
1621 | */
|
---|
1622 | void QGridLayout::addLayout(QLayout *layout, int row, int column,
|
---|
1623 | int rowSpan, int columnSpan, Qt::Alignment alignment)
|
---|
1624 | {
|
---|
1625 | Q_D(QGridLayout);
|
---|
1626 | addChildLayout(layout);
|
---|
1627 | QGridBox *b = new QGridBox(layout);
|
---|
1628 | b->setAlignment(alignment);
|
---|
1629 | d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
|
---|
1630 | }
|
---|
1631 |
|
---|
1632 | /*!
|
---|
1633 | Sets the stretch factor of row \a row to \a stretch. The first row
|
---|
1634 | is number 0.
|
---|
1635 |
|
---|
1636 | The stretch factor is relative to the other rows in this grid.
|
---|
1637 | Rows with a higher stretch factor take more of the available
|
---|
1638 | space.
|
---|
1639 |
|
---|
1640 | The default stretch factor is 0. If the stretch factor is 0 and no
|
---|
1641 | other row in this table can grow at all, the row may still grow.
|
---|
1642 |
|
---|
1643 | \sa rowStretch(), setRowMinimumHeight(), setColumnStretch()
|
---|
1644 | */
|
---|
1645 | void QGridLayout::setRowStretch(int row, int stretch)
|
---|
1646 | {
|
---|
1647 | Q_D(QGridLayout);
|
---|
1648 | d->setRowStretch(row, stretch);
|
---|
1649 | invalidate();
|
---|
1650 | }
|
---|
1651 |
|
---|
1652 | /*!
|
---|
1653 | Returns the stretch factor for row \a row.
|
---|
1654 |
|
---|
1655 | \sa setRowStretch()
|
---|
1656 | */
|
---|
1657 | int QGridLayout::rowStretch(int row) const
|
---|
1658 | {
|
---|
1659 | Q_D(const QGridLayout);
|
---|
1660 | return d->rowStretch(row);
|
---|
1661 | }
|
---|
1662 |
|
---|
1663 | /*!
|
---|
1664 | Returns the stretch factor for column \a column.
|
---|
1665 |
|
---|
1666 | \sa setColumnStretch()
|
---|
1667 | */
|
---|
1668 | int QGridLayout::columnStretch(int column) const
|
---|
1669 | {
|
---|
1670 | Q_D(const QGridLayout);
|
---|
1671 | return d->colStretch(column);
|
---|
1672 | }
|
---|
1673 |
|
---|
1674 | /*!
|
---|
1675 | Sets the stretch factor of column \a column to \a stretch. The first
|
---|
1676 | column is number 0.
|
---|
1677 |
|
---|
1678 | The stretch factor is relative to the other columns in this grid.
|
---|
1679 | Columns with a higher stretch factor take more of the available
|
---|
1680 | space.
|
---|
1681 |
|
---|
1682 | The default stretch factor is 0. If the stretch factor is 0 and no
|
---|
1683 | other column in this table can grow at all, the column may still
|
---|
1684 | grow.
|
---|
1685 |
|
---|
1686 | An alternative approach is to add spacing using addItem() with a
|
---|
1687 | QSpacerItem.
|
---|
1688 |
|
---|
1689 | \sa columnStretch(), setRowStretch()
|
---|
1690 | */
|
---|
1691 | void QGridLayout::setColumnStretch(int column, int stretch)
|
---|
1692 | {
|
---|
1693 | Q_D(QGridLayout);
|
---|
1694 | d->setColStretch(column, stretch);
|
---|
1695 | invalidate();
|
---|
1696 | }
|
---|
1697 |
|
---|
1698 |
|
---|
1699 |
|
---|
1700 | /*!
|
---|
1701 | Sets the minimum height of row \a row to \a minSize pixels.
|
---|
1702 |
|
---|
1703 | \sa rowMinimumHeight(), setColumnMinimumWidth()
|
---|
1704 | */
|
---|
1705 | void QGridLayout::setRowMinimumHeight(int row, int minSize)
|
---|
1706 | {
|
---|
1707 | Q_D(QGridLayout);
|
---|
1708 | d->setRowMinimumHeight(row, minSize);
|
---|
1709 | invalidate();
|
---|
1710 | }
|
---|
1711 |
|
---|
1712 | /*!
|
---|
1713 | Returns the minimum width set for row \a row.
|
---|
1714 |
|
---|
1715 | \sa setRowMinimumHeight()
|
---|
1716 | */
|
---|
1717 | int QGridLayout::rowMinimumHeight(int row) const
|
---|
1718 | {
|
---|
1719 | Q_D(const QGridLayout);
|
---|
1720 | return d->rowSpacing(row);
|
---|
1721 | }
|
---|
1722 |
|
---|
1723 | /*!
|
---|
1724 | Sets the minimum width of column \a column to \a minSize pixels.
|
---|
1725 |
|
---|
1726 | \sa columnMinimumWidth(), setRowMinimumHeight()
|
---|
1727 | */
|
---|
1728 | void QGridLayout::setColumnMinimumWidth(int column, int minSize)
|
---|
1729 | {
|
---|
1730 | Q_D(QGridLayout);
|
---|
1731 | d->setColumnMinimumWidth(column, minSize);
|
---|
1732 | invalidate();
|
---|
1733 | }
|
---|
1734 |
|
---|
1735 | /*!
|
---|
1736 | Returns the column spacing for column \a column.
|
---|
1737 |
|
---|
1738 | \sa setColumnMinimumWidth()
|
---|
1739 | */
|
---|
1740 | int QGridLayout::columnMinimumWidth(int column) const
|
---|
1741 | {
|
---|
1742 | Q_D(const QGridLayout);
|
---|
1743 | return d->colSpacing(column);
|
---|
1744 | }
|
---|
1745 |
|
---|
1746 | /*!
|
---|
1747 | \reimp
|
---|
1748 | */
|
---|
1749 | Qt::Orientations QGridLayout::expandingDirections() const
|
---|
1750 | {
|
---|
1751 | Q_D(const QGridLayout);
|
---|
1752 | return d->expandingDirections(horizontalSpacing(), verticalSpacing());
|
---|
1753 | }
|
---|
1754 |
|
---|
1755 | /*!
|
---|
1756 | Sets the grid's origin corner, i.e. position (0, 0), to \a corner.
|
---|
1757 | */
|
---|
1758 | void QGridLayout::setOriginCorner(Qt::Corner corner)
|
---|
1759 | {
|
---|
1760 | Q_D(QGridLayout);
|
---|
1761 | d->setReversed(corner == Qt::BottomLeftCorner || corner == Qt::BottomRightCorner,
|
---|
1762 | corner == Qt::TopRightCorner || corner == Qt::BottomRightCorner);
|
---|
1763 | }
|
---|
1764 |
|
---|
1765 | /*!
|
---|
1766 | Returns the corner that's used for the grid's origin, i.e. for
|
---|
1767 | position (0, 0).
|
---|
1768 | */
|
---|
1769 | Qt::Corner QGridLayout::originCorner() const
|
---|
1770 | {
|
---|
1771 | Q_D(const QGridLayout);
|
---|
1772 | if (d->horReversed()) {
|
---|
1773 | return d->verReversed() ? Qt::BottomRightCorner : Qt::TopRightCorner;
|
---|
1774 | } else {
|
---|
1775 | return d->verReversed() ? Qt::BottomLeftCorner : Qt::TopLeftCorner;
|
---|
1776 | }
|
---|
1777 | }
|
---|
1778 |
|
---|
1779 | /*!
|
---|
1780 | \reimp
|
---|
1781 | */
|
---|
1782 | void QGridLayout::invalidate()
|
---|
1783 | {
|
---|
1784 | Q_D(QGridLayout);
|
---|
1785 | d->setDirty();
|
---|
1786 | QLayout::invalidate();
|
---|
1787 | }
|
---|
1788 |
|
---|
1789 | /*!
|
---|
1790 | \fn void QGridLayout::addRowSpacing(int row, int minsize)
|
---|
1791 |
|
---|
1792 | Use addItem(new QSpacerItem(0, minsize), row, 0) instead.
|
---|
1793 | */
|
---|
1794 |
|
---|
1795 | /*!
|
---|
1796 | \fn void QGridLayout::addColSpacing(int col, int minsize)
|
---|
1797 |
|
---|
1798 | Use addItem(new QSpacerItem(minsize, 0), 0, col) instead.
|
---|
1799 | */
|
---|
1800 |
|
---|
1801 | /*!
|
---|
1802 | \fn void QGridLayout::addMultiCellWidget(QWidget *widget, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
|
---|
1803 |
|
---|
1804 | Use an addWidget() overload that allows you to specify row and
|
---|
1805 | column spans instead.
|
---|
1806 | */
|
---|
1807 |
|
---|
1808 | /*!
|
---|
1809 | \fn void QGridLayout::addMultiCell(QLayoutItem *l, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
|
---|
1810 |
|
---|
1811 | Use an addItem() overload that allows you to specify row and
|
---|
1812 | column spans instead.
|
---|
1813 | */
|
---|
1814 |
|
---|
1815 | /*!
|
---|
1816 | \fn void QGridLayout::addMultiCellLayout(QLayout *layout, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0)
|
---|
1817 |
|
---|
1818 | Use an addLayout() overload that allows you to specify row and
|
---|
1819 | column spans instead.
|
---|
1820 | */
|
---|
1821 |
|
---|
1822 | /*!
|
---|
1823 | \fn int QGridLayout::numRows() const
|
---|
1824 |
|
---|
1825 | Use rowCount() instead.
|
---|
1826 | */
|
---|
1827 |
|
---|
1828 | /*!
|
---|
1829 | \fn int QGridLayout::numCols() const
|
---|
1830 |
|
---|
1831 | Use columnCount() instead.
|
---|
1832 | */
|
---|
1833 |
|
---|
1834 | /*!
|
---|
1835 | \fn void QGridLayout::setColStretch(int col, int stretch)
|
---|
1836 |
|
---|
1837 | Use setColumnStretch() instead.
|
---|
1838 | */
|
---|
1839 |
|
---|
1840 | /*!
|
---|
1841 | \fn int QGridLayout::colStretch(int col) const
|
---|
1842 |
|
---|
1843 | Use columnStretch() instead.
|
---|
1844 | */
|
---|
1845 |
|
---|
1846 | /*!
|
---|
1847 | \fn void QGridLayout::setColSpacing(int col, int minSize)
|
---|
1848 |
|
---|
1849 | Use setColumnMinimumWidth() instead.
|
---|
1850 | */
|
---|
1851 |
|
---|
1852 | /*!
|
---|
1853 | \fn int QGridLayout::colSpacing(int col) const
|
---|
1854 |
|
---|
1855 | Use columnSpacing() instead.
|
---|
1856 | */
|
---|
1857 |
|
---|
1858 | /*!
|
---|
1859 | \fn void QGridLayout::setRowSpacing(int row, int minSize)
|
---|
1860 |
|
---|
1861 | Use setRowMinimumHeight(\a row, \a minSize) instead.
|
---|
1862 | */
|
---|
1863 |
|
---|
1864 | /*!
|
---|
1865 | \fn int QGridLayout::rowSpacing(int row) const
|
---|
1866 |
|
---|
1867 | Use rowMinimumHeight(\a row) instead.
|
---|
1868 | */
|
---|
1869 |
|
---|
1870 | /*!
|
---|
1871 | \fn QRect QGridLayout::cellGeometry(int row, int column) const
|
---|
1872 |
|
---|
1873 | Use cellRect(\a row, \a column) instead.
|
---|
1874 | */
|
---|
1875 |
|
---|
1876 | /*!
|
---|
1877 | \fn void QGridLayout::setOrigin(Qt::Corner corner)
|
---|
1878 |
|
---|
1879 | Use setOriginCorner(\a corner) instead.
|
---|
1880 | */
|
---|
1881 |
|
---|
1882 | /*!
|
---|
1883 | \fn Qt::Corner QGridLayout::origin() const
|
---|
1884 |
|
---|
1885 | Use originCorner() instead.
|
---|
1886 | */
|
---|
1887 |
|
---|
1888 |
|
---|
1889 | QT_END_NAMESPACE
|
---|