diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/gui/kernel/qgridlayout.cpp | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'src/gui/kernel/qgridlayout.cpp')
-rw-r--r-- | src/gui/kernel/qgridlayout.cpp | 1889 |
1 files changed, 1889 insertions, 0 deletions
diff --git a/src/gui/kernel/qgridlayout.cpp b/src/gui/kernel/qgridlayout.cpp new file mode 100644 index 0000000..f872829 --- /dev/null +++ b/src/gui/kernel/qgridlayout.cpp @@ -0,0 +1,1889 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgridlayout.h" +#include "qapplication.h" +#include "qwidget.h" +#include "qlist.h" +#include "qsizepolicy.h" +#include "qvector.h" +#include "qvarlengtharray.h" +#include "qlayoutengine_p.h" +#include "qlayout_p.h" + +QT_BEGIN_NAMESPACE + +struct QGridLayoutSizeTriple +{ + QSize minS; + QSize hint; + QSize maxS; +}; + +/* + Three internal classes related to QGridLayout: (1) QGridBox is a + QLayoutItem with (row, column) information and (torow, tocolumn) information; (3) QGridLayoutData is + the internal representation of a QGridLayout. +*/ + +class QGridBox +{ +public: + QGridBox(QLayoutItem *lit) { item_ = lit; } + + QGridBox(const QLayout *l, QWidget *wid) { item_ = QLayoutPrivate::createWidgetItem(l, wid); } + ~QGridBox() { delete item_; } + + QSize sizeHint() const { return item_->sizeHint(); } + QSize minimumSize() const { return item_->minimumSize(); } + QSize maximumSize() const { return item_->maximumSize(); } + Qt::Orientations expandingDirections() const { return item_->expandingDirections(); } + bool isEmpty() const { return item_->isEmpty(); } + + bool hasHeightForWidth() const { return item_->hasHeightForWidth(); } + int heightForWidth(int w) const { return item_->heightForWidth(w); } + + void setAlignment(Qt::Alignment a) { item_->setAlignment(a); } + void setGeometry(const QRect &r) { item_->setGeometry(r); } + Qt::Alignment alignment() const { return item_->alignment(); } + QLayoutItem *item() { return item_; } + QLayoutItem *takeItem() { QLayoutItem *i = item_; item_ = 0; return i; } + + int hStretch() { return item_->widget() ? + item_->widget()->sizePolicy().horizontalStretch() : 0; } + int vStretch() { return item_->widget() ? + item_->widget()->sizePolicy().verticalStretch() : 0; } + +private: + friend class QGridLayoutPrivate; + friend class QGridLayout; + + inline int toRow(int rr) const { return torow >= 0 ? torow : rr - 1; } + inline int toCol(int cc) const { return tocol >= 0 ? tocol : cc - 1; } + + QLayoutItem *item_; + int row, col; + int torow, tocol; +}; + +class QGridLayoutPrivate : public QLayoutPrivate +{ + Q_DECLARE_PUBLIC(QGridLayout) +public: + QGridLayoutPrivate(); + + void add(QGridBox*, int row, int col); + void add(QGridBox*, int row1, int row2, int col1, int col2); + QSize sizeHint(int hSpacing, int vSpacing) const; + QSize minimumSize(int hSpacing, int vSpacing) const; + QSize maximumSize(int hSpacing, int vSpacing) const; + + Qt::Orientations expandingDirections(int hSpacing, int vSpacing) const; + + void distribute(QRect rect, int hSpacing, int vSpacing); + inline int numRows() const { return rr; } + inline int numCols() const { return cc; } + inline void expand(int rows, int cols) + { setSize(qMax(rows, rr), qMax(cols, cc)); } + inline void setRowStretch(int r, int s) + { expand(r + 1, 0); rStretch[r] = s; setDirty(); } + inline void setColStretch(int c, int s) + { expand(0, c + 1); cStretch[c] = s; setDirty(); } + inline int rowStretch(int r) const { return rStretch.at(r); } + inline int colStretch(int c) const { return cStretch.at(c); } + inline void setRowMinimumHeight(int r, int s) + { expand(r + 1, 0); rMinHeights[r] = s; setDirty(); } + inline void setColumnMinimumWidth(int c, int s) + { expand(0, c + 1); cMinWidths[c] = s; setDirty(); } + inline int rowSpacing(int r) const { return rMinHeights.at(r); } + inline int colSpacing(int c) const { return cMinWidths.at(c); } + + inline void setReversed(bool r, bool c) { hReversed = c; vReversed = r; } + inline bool horReversed() const { return hReversed; } + inline bool verReversed() const { return vReversed; } + inline void setDirty() { needRecalc = true; hfw_width = -1; } + inline bool isDirty() const { return needRecalc; } + bool hasHeightForWidth(int hSpacing, int vSpacing); + int heightForWidth(int width, int hSpacing, int vSpacing); + int minimumHeightForWidth(int width, int hSpacing, int vSpacing); + + inline void getNextPos(int &row, int &col) { row = nextR; col = nextC; } + inline int count() const { return things.count(); } + QRect cellRect(int row, int col) const; + + inline QLayoutItem *itemAt(int index) const { + if (index < things.count()) + return things.at(index)->item(); + else + return 0; + } + inline QLayoutItem *takeAt(int index) { + QLayoutItem *item = 0; + if (index < things.count()) { + QGridBox *b = things.takeAt(index); + if (b) { + item = b->takeItem(); + delete b; + } + } + return item; + } + + void getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan) { + if (index < things.count()) { + QGridBox *b = things.at(index); + int toRow = b->toRow(rr); + int toCol = b->toCol(cc); + *row = b->row; + *column = b->col; + *rowSpan = toRow - *row + 1; + *columnSpan = toCol - *column +1; + } + } + void deleteAll(); + +private: + void setNextPosAfter(int r, int c); + void recalcHFW(int w); + void addHfwData(QGridBox *box, int width); + void init(); + QSize findSize(int QLayoutStruct::*, int hSpacing, int vSpacing) const; + void addData(QGridBox *b, const QGridLayoutSizeTriple &sizes, bool r, bool c); + void setSize(int rows, int cols); + void setupSpacings(QVector<QLayoutStruct> &chain, QGridBox *grid[], int fixedSpacing, + Qt::Orientation orientation); + void setupLayoutData(int hSpacing, int vSpacing); + void setupHfwLayoutData(); + void effectiveMargins(int *left, int *top, int *right, int *bottom) const; + + int rr; + int cc; + QVector<QLayoutStruct> rowData; + QVector<QLayoutStruct> colData; + QVector<QLayoutStruct> *hfwData; + QVector<int> rStretch; + QVector<int> cStretch; + QVector<int> rMinHeights; + QVector<int> cMinWidths; + QList<QGridBox *> things; + + int hfw_width; + int hfw_height; + int hfw_minheight; + int nextR; + int nextC; + + int horizontalSpacing; + int verticalSpacing; + int leftMargin; + int topMargin; + int rightMargin; + int bottomMargin; + + uint hReversed : 1; + uint vReversed : 1; + uint needRecalc : 1; + uint has_hfw : 1; + uint addVertical : 1; +}; + +void QGridLayoutPrivate::effectiveMargins(int *left, int *top, int *right, int *bottom) const +{ + int l = leftMargin; + int t = topMargin; + int r = rightMargin; + int b = bottomMargin; +#ifdef Q_WS_MAC + int leftMost = INT_MAX; + int topMost = INT_MAX; + int rightMost = 0; + int bottomMost = 0; + + QWidget *w = 0; + const int n = things.count(); + for (int i = 0; i < n; ++i) { + QGridBox *box = things.at(i); + QLayoutItem *itm = box->item(); + w = itm->widget(); + if (w) { + bool visualHReversed = hReversed != (w->layoutDirection() == Qt::RightToLeft); + QRect lir = itm->geometry(); + QRect wr = w->geometry(); + if (box->col <= leftMost) { + if (box->col < leftMost) { + // we found an item even closer to the margin, discard. + leftMost = box->col; + if (visualHReversed) + r = rightMargin; + else + l = leftMargin; + } + if (visualHReversed) { + r = qMax(r, wr.right() - lir.right()); + } else { + l = qMax(l, lir.left() - wr.left()); + } + } + if (box->row <= topMost) { + if (box->row < topMost) { + // we found an item even closer to the margin, discard. + topMost = box->row; + if (vReversed) + b = bottomMargin; + else + t = topMargin; + } + if (vReversed) + b = qMax(b, wr.bottom() - lir.bottom()); + else + t = qMax(t, lir.top() - wr.top()); + } + if (box->toCol(cc) >= rightMost) { + if (box->toCol(cc) > rightMost) { + // we found an item even closer to the margin, discard. + rightMost = box->toCol(cc); + if (visualHReversed) + l = leftMargin; + else + r = rightMargin; + } + if (visualHReversed) { + l = qMax(l, lir.left() - wr.left()); + } else { + r = qMax(r, wr.right() - lir.right()); + } + + } + if (box->toRow(rr) >= bottomMost) { + if (box->toRow(rr) > bottomMost) { + // we found an item even closer to the margin, discard. + bottomMost = box->toRow(rr); + if (vReversed) + t = topMargin; + else + b = bottomMargin; + } + if (vReversed) + t = qMax(t, lir.top() - wr.top()); + else + b = qMax(b, wr.bottom() - lir.bottom()); + } + } + } + +#endif + if (left) + *left = l; + if (top) + *top = t; + if (right) + *right = r; + if (bottom) + *bottom = b; +} + +QGridLayoutPrivate::QGridLayoutPrivate() +{ + addVertical = false; + setDirty(); + rr = cc = 0; + nextR = nextC = 0; + hfwData = 0; + hReversed = false; + vReversed = false; + horizontalSpacing = -1; + verticalSpacing = -1; +} + +#if 0 +QGridLayoutPrivate::QGridLayoutPrivate(int nRows, int nCols) + : rowData(0), colData(0) +{ + init(); + if (nRows < 0) { + nRows = 1; + addVertical = false; + } + if (nCols < 0) { + nCols = 1; + addVertical = true; + } + setSize(nRows, nCols); +} +#endif + +void QGridLayoutPrivate::deleteAll() +{ + while (!things.isEmpty()) + delete things.takeFirst(); + delete hfwData; +} + +bool QGridLayoutPrivate::hasHeightForWidth(int hSpacing, int vSpacing) +{ + setupLayoutData(hSpacing, vSpacing); + return has_hfw; +} + +/* + Assumes that setupLayoutData() has been called, and that + qGeomCalc() has filled in colData with appropriate values. +*/ +void QGridLayoutPrivate::recalcHFW(int w) +{ + /* + Go through all children, using colData and heightForWidth() + and put the results in hfwData. + */ + if (!hfwData) + hfwData = new QVector<QLayoutStruct>(rr); + setupHfwLayoutData(); + QVector<QLayoutStruct> &rData = *hfwData; + + int h = 0; + int mh = 0; + for (int r = 0; r < rr; r++) { + int spacing = rData.at(r).spacing; + h += rData.at(r).sizeHint + spacing; + mh += rData.at(r).minimumSize + spacing; + } + + hfw_width = w; + hfw_height = qMin(QLAYOUTSIZE_MAX, h); + hfw_minheight = qMin(QLAYOUTSIZE_MAX, mh); +} + +int QGridLayoutPrivate::heightForWidth(int w, int hSpacing, int vSpacing) +{ + setupLayoutData(hSpacing, vSpacing); + if (!has_hfw) + return -1; + int left, top, right, bottom; + effectiveMargins(&left, &top, &right, &bottom); + + int hMargins = left + right; + if (w - hMargins != hfw_width) { + qGeomCalc(colData, 0, cc, 0, w - hMargins); + recalcHFW(w - hMargins); + } + return hfw_height + top + bottom; +} + +int QGridLayoutPrivate::minimumHeightForWidth(int w, int hSpacing, int vSpacing) +{ + (void)heightForWidth(w, hSpacing, vSpacing); + if (!has_hfw) + return -1; + int top, bottom; + effectiveMargins(0, &top, 0, &bottom); + return hfw_minheight + top + bottom; +} + +QSize QGridLayoutPrivate::findSize(int QLayoutStruct::*size, int hSpacing, int vSpacing) const +{ + QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this); + that->setupLayoutData(hSpacing, vSpacing); + + int w = 0; + int h = 0; + + for (int r = 0; r < rr; r++) + h += rowData.at(r).*size + rowData.at(r).spacing; + for (int c = 0; c < cc; c++) + w += colData.at(c).*size + colData.at(c).spacing; + + w = qMin(QLAYOUTSIZE_MAX, w); + h = qMin(QLAYOUTSIZE_MAX, h); + + return QSize(w, h); +} + +Qt::Orientations QGridLayoutPrivate::expandingDirections(int hSpacing, int vSpacing) const +{ + QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this); + that->setupLayoutData(hSpacing, vSpacing); + Qt::Orientations ret; + + for (int r = 0; r < rr; r++) { + if (rowData.at(r).expansive) { + ret |= Qt::Vertical; + break; + } + } + for (int c = 0; c < cc; c++) { + if (colData.at(c).expansive) { + ret |= Qt::Horizontal; + break; + } + } + return ret; +} + +QSize QGridLayoutPrivate::sizeHint(int hSpacing, int vSpacing) const +{ + return findSize(&QLayoutStruct::sizeHint, hSpacing, vSpacing); +} + +QSize QGridLayoutPrivate::maximumSize(int hSpacing, int vSpacing) const +{ + return findSize(&QLayoutStruct::maximumSize, hSpacing, vSpacing); +} + +QSize QGridLayoutPrivate::minimumSize(int hSpacing, int vSpacing) const +{ + return findSize(&QLayoutStruct::minimumSize, hSpacing, vSpacing); +} + +void QGridLayoutPrivate::setSize(int r, int c) +{ + if ((int)rowData.size() < r) { + int newR = qMax(r, rr * 2); + rowData.resize(newR); + rStretch.resize(newR); + rMinHeights.resize(newR); + for (int i = rr; i < newR; i++) { + rowData[i].init(); + rowData[i].maximumSize = 0; + rowData[i].pos = 0; + rowData[i].size = 0; + rStretch[i] = 0; + rMinHeights[i] = 0; + } + } + if ((int)colData.size() < c) { + int newC = qMax(c, cc * 2); + colData.resize(newC); + cStretch.resize(newC); + cMinWidths.resize(newC); + for (int i = cc; i < newC; i++) { + colData[i].init(); + colData[i].maximumSize = 0; + colData[i].pos = 0; + colData[i].size = 0; + cStretch[i] = 0; + cMinWidths[i] = 0; + } + } + + if (hfwData && (int)hfwData->size() < r) { + delete hfwData; + hfwData = 0; + hfw_width = -1; + } + rr = r; + cc = c; +} + +void QGridLayoutPrivate::setNextPosAfter(int row, int col) +{ + if (addVertical) { + if (col > nextC || (col == nextC && row >= nextR)) { + nextR = row + 1; + nextC = col; + if (nextR >= rr) { + nextR = 0; + nextC++; + } + } + } else { + if (row > nextR || (row == nextR && col >= nextC)) { + nextR = row; + nextC = col + 1; + if (nextC >= cc) { + nextC = 0; + nextR++; + } + } + } +} + +void QGridLayoutPrivate::add(QGridBox *box, int row, int col) +{ + expand(row + 1, col + 1); + box->row = box->torow = row; + box->col = box->tocol = col; + things.append(box); + setDirty(); + setNextPosAfter(row, col); +} + +void QGridLayoutPrivate::add(QGridBox *box, int row1, int row2, int col1, int col2) +{ + if (row2 >= 0 && row2 < row1) + qWarning("QGridLayout: Multi-cell fromRow greater than toRow"); + if (col2 >= 0 && col2 < col1) + qWarning("QGridLayout: Multi-cell fromCol greater than toCol"); + if (row1 == row2 && col1 == col2) { + add(box, row1, col1); + return; + } + expand(row2 + 1, col2 + 1); + box->row = row1; + box->col = col1; + + box->torow = row2; + box->tocol = col2; + + things.append(box); + setDirty(); + if (col2 < 0) + col2 = cc - 1; + + setNextPosAfter(row2, col2); +} + +void QGridLayoutPrivate::addData(QGridBox *box, const QGridLayoutSizeTriple &sizes, bool r, bool c) +{ + const QWidget *widget = box->item()->widget(); + + if (box->isEmpty() && widget) + return; + + if (c) { + QLayoutStruct *data = &colData[box->col]; + if (!cStretch.at(box->col)) + data->stretch = qMax(data->stretch, box->hStretch()); + data->sizeHint = qMax(sizes.hint.width(), data->sizeHint); + data->minimumSize = qMax(sizes.minS.width(), data->minimumSize); + + qMaxExpCalc(data->maximumSize, data->expansive, data->empty, sizes.maxS.width(), + box->expandingDirections() & Qt::Horizontal, box->isEmpty()); + } + if (r) { + QLayoutStruct *data = &rowData[box->row]; + if (!rStretch.at(box->row)) + data->stretch = qMax(data->stretch, box->vStretch()); + data->sizeHint = qMax(sizes.hint.height(), data->sizeHint); + data->minimumSize = qMax(sizes.minS.height(), data->minimumSize); + + qMaxExpCalc(data->maximumSize, data->expansive, data->empty, sizes.maxS.height(), + box->expandingDirections() & Qt::Vertical, box->isEmpty()); + } +} + +static void initEmptyMultiBox(QVector<QLayoutStruct> &chain, int start, int end) +{ + for (int i = start; i <= end; i++) { + QLayoutStruct *data = &chain[i]; + if (data->empty && data->maximumSize == 0) // truly empty box + data->maximumSize = QWIDGETSIZE_MAX; + data->empty = false; + } +} + +static void distributeMultiBox(QVector<QLayoutStruct> &chain, int start, int end, int minSize, + int sizeHint, QVector<int> &stretchArray, int stretch) +{ + int i; + int w = 0; + int wh = 0; + int max = 0; + + for (i = start; i <= end; i++) { + QLayoutStruct *data = &chain[i]; + w += data->minimumSize; + wh += data->sizeHint; + max += data->maximumSize; + if (stretchArray.at(i) == 0) + data->stretch = qMax(data->stretch, stretch); + + if (i != end) { + int spacing = data->spacing; + w += spacing; + wh += spacing; + max += spacing; + } + } + + if (max < minSize) { // implies w < minSize + /* + We must increase the maximum size of at least one of the + items. qGeomCalc() will put the extra space in between the + items. We must recover that extra space and put it + somewhere. It does not really matter where, since the user + can always specify stretch factors and avoid this code. + */ + qGeomCalc(chain, start, end - start + 1, 0, minSize); + int pos = 0; + for (i = start; i <= end; i++) { + QLayoutStruct *data = &chain[i]; + int nextPos = (i == end) ? minSize : chain.at(i + 1).pos; + int realSize = nextPos - pos; + if (i != end) + realSize -= data->spacing; + if (data->minimumSize < realSize) + data->minimumSize = realSize; + if (data->maximumSize < data->minimumSize) + data->maximumSize = data->minimumSize; + pos = nextPos; + } + } else if (w < minSize) { + qGeomCalc(chain, start, end - start + 1, 0, minSize); + for (i = start; i <= end; i++) { + QLayoutStruct *data = &chain[i]; + if (data->minimumSize < data->size) + data->minimumSize = data->size; + } + } + + if (wh < sizeHint) { + qGeomCalc(chain, start, end - start + 1, 0, sizeHint); + for (i = start; i <= end; i++) { + QLayoutStruct *data = &chain[i]; + if (data->sizeHint < data->size) + data->sizeHint = data->size; + } + } +} + +static QGridBox *&gridAt(QGridBox *grid[], int r, int c, int cc, + Qt::Orientation orientation = Qt::Vertical) +{ + if (orientation == Qt::Horizontal) + qSwap(r, c); + return grid[(r * cc) + c]; +} + +void QGridLayoutPrivate::setupSpacings(QVector<QLayoutStruct> &chain, + QGridBox *grid[], int fixedSpacing, + Qt::Orientation orientation) +{ + Q_Q(QGridLayout); + int numRows = rr; // or columns if orientation is horizontal + int numColumns = cc; // or rows if orientation is horizontal + + if (orientation == Qt::Horizontal) { + qSwap(numRows, numColumns); + } + + QStyle *style = 0; + if (fixedSpacing < 0) { + if (QWidget *parentWidget = q->parentWidget()) + style = parentWidget->style(); + } + + for (int c = 0; c < numColumns; ++c) { + QGridBox *previousBox = 0; + int previousRow = -1; // previous *non-empty* row + + for (int r = 0; r < numRows; ++r) { + if (chain.at(r).empty) + continue; + + QGridBox *box = gridAt(grid, r, c, cc, orientation); + if (previousRow != -1 && (!box || previousBox != box)) { + int spacing = fixedSpacing; + if (spacing < 0) { + QSizePolicy::ControlTypes controlTypes1 = QSizePolicy::DefaultType; + QSizePolicy::ControlTypes controlTypes2 = QSizePolicy::DefaultType; + if (previousBox) + controlTypes1 = previousBox->item()->controlTypes(); + if (box) + controlTypes2 = box->item()->controlTypes(); + + if ((orientation == Qt::Horizontal && hReversed) + || (orientation == Qt::Vertical && vReversed)) + qSwap(controlTypes1, controlTypes2); + + if (style) + spacing = style->combinedLayoutSpacing(controlTypes1, controlTypes2, + orientation, 0, q->parentWidget()); + } else { + if (orientation == Qt::Vertical) { + QGridBox *sibling = vReversed ? previousBox : box; + if (sibling) { + QWidget *wid = sibling->item()->widget(); + if (wid) + spacing = qMax(spacing, sibling->item()->geometry().top() - wid->geometry().top() ); + } + } + } + + if (spacing > chain.at(previousRow).spacing) + chain[previousRow].spacing = spacing; + } + + previousBox = box; + previousRow = r; + } + } +} + +//#define QT_LAYOUT_DISABLE_CACHING + +void QGridLayoutPrivate::setupLayoutData(int hSpacing, int vSpacing) +{ + Q_Q(QGridLayout); + +#ifndef QT_LAYOUT_DISABLE_CACHING + if (!needRecalc) + return; +#endif + has_hfw = false; + int i; + + for (i = 0; i < rr; i++) { + rowData[i].init(rStretch.at(i), rMinHeights.at(i)); + rowData[i].maximumSize = rStretch.at(i) ? QLAYOUTSIZE_MAX : rMinHeights.at(i); + } + for (i = 0; i < cc; i++) { + colData[i].init(cStretch.at(i), cMinWidths.at(i)); + colData[i].maximumSize = cStretch.at(i) ? QLAYOUTSIZE_MAX : cMinWidths.at(i); + } + + int n = things.size(); + QVarLengthArray<QGridLayoutSizeTriple> sizes(n); + + bool has_multi = false; + + /* + Grid of items. We use it to determine which items are + adjacent to which and compute the spacings correctly. + */ + QVarLengthArray<QGridBox *> grid(rr * cc); + qMemSet(grid.data(), 0, rr * cc * sizeof(QGridBox *)); + + /* + Initialize 'sizes' and 'grid' data structures, and insert + non-spanning items to our row and column data structures. + */ + for (i = 0; i < n; ++i) { + QGridBox * const box = things.at(i); + sizes[i].minS = box->minimumSize(); + sizes[i].hint = box->sizeHint(); + sizes[i].maxS = box->maximumSize(); + + if (box->hasHeightForWidth()) + has_hfw = true; + + if (box->row == box->toRow(rr)) { + addData(box, sizes[i], true, false); + } else { + initEmptyMultiBox(rowData, box->row, box->toRow(rr)); + has_multi = true; + } + + if (box->col == box->toCol(cc)) { + addData(box, sizes[i], false, true); + } else { + initEmptyMultiBox(colData, box->col, box->toCol(cc)); + has_multi = true; + } + + for (int r = box->row; r <= box->toRow(rr); ++r) { + for (int c = box->col; c <= box->toCol(cc); ++c) { + gridAt(grid.data(), r, c, cc) = box; + } + } + } + + setupSpacings(colData, grid.data(), hSpacing, Qt::Horizontal); + setupSpacings(rowData, grid.data(), vSpacing, Qt::Vertical); + + /* + Insert multicell items to our row and column data structures. + This must be done after the non-spanning items to obtain a + better distribution in distributeMultiBox(). + */ + if (has_multi) { + for (i = 0; i < n; ++i) { + QGridBox * const box = things.at(i); + + if (box->row != box->toRow(rr)) + distributeMultiBox(rowData, box->row, box->toRow(rr), sizes[i].minS.height(), + sizes[i].hint.height(), rStretch, box->vStretch()); + if (box->col != box->toCol(cc)) + distributeMultiBox(colData, box->col, box->toCol(cc), sizes[i].minS.width(), + sizes[i].hint.width(), cStretch, box->hStretch()); + } + } + + for (i = 0; i < rr; i++) + rowData[i].expansive = rowData.at(i).expansive || rowData.at(i).stretch > 0; + for (i = 0; i < cc; i++) + colData[i].expansive = colData.at(i).expansive || colData.at(i).stretch > 0; + + q->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin); + + needRecalc = false; +} + +void QGridLayoutPrivate::addHfwData(QGridBox *box, int width) +{ + QVector<QLayoutStruct> &rData = *hfwData; + if (box->hasHeightForWidth()) { + int hint = box->heightForWidth(width); + rData[box->row].sizeHint = qMax(hint, rData.at(box->row).sizeHint); + rData[box->row].minimumSize = qMax(hint, rData.at(box->row).minimumSize); + } else { + QSize hint = box->sizeHint(); + QSize minS = box->minimumSize(); + rData[box->row].sizeHint = qMax(hint.height(), rData.at(box->row).sizeHint); + rData[box->row].minimumSize = qMax(minS.height(), rData.at(box->row).minimumSize); + } +} + +/* + Similar to setupLayoutData(), but uses heightForWidth(colData) + instead of sizeHint(). Assumes that setupLayoutData() and + qGeomCalc(colData) has been called. +*/ +void QGridLayoutPrivate::setupHfwLayoutData() +{ + QVector<QLayoutStruct> &rData = *hfwData; + for (int i = 0; i < rr; i++) { + rData[i] = rowData.at(i); + rData[i].minimumSize = rData[i].sizeHint = rMinHeights.at(i); + } + + for (int pass = 0; pass < 2; ++pass) { + for (int i = 0; i < things.size(); ++i) { + QGridBox *box = things.at(i); + int r1 = box->row; + int c1 = box->col; + int r2 = box->toRow(rr); + int c2 = box->toCol(cc); + int w = colData.at(c2).pos + colData.at(c2).size - colData.at(c1).pos; + + if (r1 == r2) { + if (pass == 0) + addHfwData(box, w); + } else { + if (pass == 0) { + initEmptyMultiBox(rData, r1, r2); + } else { + QSize hint = box->sizeHint(); + QSize min = box->minimumSize(); + if (box->hasHeightForWidth()) { + int hfwh = box->heightForWidth(w); + if (hfwh > hint.height()) + hint.setHeight(hfwh); + if (hfwh > min.height()) + min.setHeight(hfwh); + } + distributeMultiBox(rData, r1, r2, min.height(), hint.height(), + rStretch, box->vStretch()); + } + } + } + } + for (int i = 0; i < rr; i++) + rData[i].expansive = rData.at(i).expansive || rData.at(i).stretch > 0; +} + +void QGridLayoutPrivate::distribute(QRect r, int hSpacing, int vSpacing) +{ + Q_Q(QGridLayout); + bool visualHReversed = hReversed; + QWidget *parent = q->parentWidget(); + if (parent && parent->isRightToLeft()) + visualHReversed = !visualHReversed; + + setupLayoutData(hSpacing, vSpacing); + + int left, top, right, bottom; + effectiveMargins(&left, &top, &right, &bottom); + r.adjust(+left, +top, -right, -bottom); + + qGeomCalc(colData, 0, cc, r.x(), r.width()); + QVector<QLayoutStruct> *rDataPtr; + if (has_hfw) { + recalcHFW(r.width()); + qGeomCalc(*hfwData, 0, rr, r.y(), r.height()); + rDataPtr = hfwData; + } else { + qGeomCalc(rowData, 0, rr, r.y(), r.height()); + rDataPtr = &rowData; + } + QVector<QLayoutStruct> &rData = *rDataPtr; + int i; + + bool reverse = ((r.bottom() > rect.bottom()) || (r.bottom() == rect.bottom() + && ((r.right() > rect.right()) != visualHReversed))); + int n = things.size(); + for (i = 0; i < n; ++i) { + QGridBox *box = things.at(reverse ? n-i-1 : i); + int r2 = box->toRow(rr); + int c2 = box->toCol(cc); + + int x = colData.at(box->col).pos; + int y = rData.at(box->row).pos; + int x2p = colData.at(c2).pos + colData.at(c2).size; // x2+1 + int y2p = rData.at(r2).pos + rData.at(r2).size; // y2+1 + int w = x2p - x; + int h = y2p - y; + + if (visualHReversed) + x = r.left() + r.right() - x - w + 1; + if (vReversed) + y = r.top() + r.bottom() - y - h + 1; + + box->setGeometry(QRect(x, y, w, h)); + } +} + +QRect QGridLayoutPrivate::cellRect(int row, int col) const +{ + if (row < 0 || row >= rr || col < 0 || col >= cc) + return QRect(); + + const QVector<QLayoutStruct> *rDataPtr; + if (has_hfw && hfwData) + rDataPtr = hfwData; + else + rDataPtr = &rowData; + return QRect(colData.at(col).pos, rDataPtr->at(row).pos, + colData.at(col).size, rDataPtr->at(row).size); +} + +/*! + \class QGridLayout + + \brief The QGridLayout class lays out widgets in a grid. + + \ingroup geomanagement + \ingroup appearance + \mainclass + + QGridLayout takes the space made available to it (by its parent + layout or by the parentWidget()), divides it up into rows and + columns, and puts each widget it manages into the correct cell. + + Columns and rows behave identically; we will discuss columns, but + there are equivalent functions for rows. + + Each column has a minimum width and a stretch factor. The minimum + width is the greatest of that set using setColumnMinimumWidth() and the + minimum width of each widget in that column. The stretch factor is + set using setColumnStretch() and determines how much of the available + space the column will get over and above its necessary minimum. + + Normally, each managed widget or layout is put into a cell of its + own using addWidget(). It is also possible for a widget to occupy + multiple cells using the row and column spanning overloads of + addItem() and addWidget(). If you do this, QGridLayout will guess + how to distribute the size over the columns/rows (based on the + stretch factors). + + To remove a widget from a layout, call removeWidget(). Calling + QWidget::hide() on a widget also effectively removes the widget + from the layout until QWidget::show() is called. + + This illustration shows a fragment of a dialog with a five-column, + three-row grid (the grid is shown overlaid in magenta): + + \image gridlayout.png A grid layout + + Columns 0, 2 and 4 in this dialog fragment are made up of a + QLabel, a QLineEdit, and a QListBox. Columns 1 and 3 are + placeholders made with setColumnMinimumWidth(). Row 0 consists of three + QLabel objects, row 1 of three QLineEdit objects and row 2 of + three QListBox objects. We used placeholder columns (1 and 3) to + get the right amount of space between the columns. + + Note that the columns and rows are not equally wide or tall. If + you want two columns to have the same width, you must set their + minimum widths and stretch factors to be the same yourself. You do + this using setColumnMinimumWidth() and setColumnStretch(). + + If the QGridLayout is not the top-level layout (i.e. does not + manage all of the widget's area and children), you must add it to + its parent layout when you create it, but before you do anything + with it. The normal way to add a layout is by calling + addLayout() on the parent layout. + + Once you have added your layout you can start putting widgets and + other layouts into the cells of your grid layout using + addWidget(), addItem(), and addLayout(). + + QGridLayout also includes two margin widths: the margin() and the + spacing(). The margin is the width of the reserved space along + each of the QGridLayout's four sides. The spacing is the width of + the automatically allocated spacing between neighboring boxes. + + The default margin() and spacing() values are provided by the + style. The default margin Qt styles specify is 9 for child + widgets and 11 for windows. The spacing defaults to the same as + the margin width for a top-level layout, or to the same as the + parent layout. + + \sa QBoxLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example} +*/ + + +/*! + Constructs a new QGridLayout with parent widget, \a parent. The + layout has one row and one column initially, and will expand when + new items are inserted. +*/ +QGridLayout::QGridLayout(QWidget *parent) + : QLayout(*new QGridLayoutPrivate, 0, parent) +{ + Q_D(QGridLayout); + d->expand(1, 1); +} + +/*! + Constructs a new grid layout. + + You must insert this grid into another layout. You can insert + widgets and layouts into this layout at any time, but laying out + will not be performed before this is inserted into another layout. +*/ +QGridLayout::QGridLayout() + : QLayout(*new QGridLayoutPrivate, 0, 0) +{ + Q_D(QGridLayout); + d->expand(1, 1); +} + + +#ifdef QT3_SUPPORT +/*! + \obsolete + Constructs a new QGridLayout with \a nRows rows, \a nCols columns + and parent widget, \a parent. \a parent may not be 0. The grid + layout is called \a name. + + \a margin is the number of pixels between the edge of the widget + and its managed children. \a space is the default number of pixels + between cells. If \a space is -1, the value of \a margin is used. +*/ +QGridLayout::QGridLayout(QWidget *parent, int nRows, int nCols, int margin, + int space, const char *name) + : QLayout(*new QGridLayoutPrivate, 0, parent) +{ + Q_D(QGridLayout); + d->expand(nRows, nCols); + setMargin(margin); + setSpacing(space < 0 ? margin : space); + setObjectName(QString::fromAscii(name)); +} + +/*! + \obsolete + + Constructs a new grid with \a nRows rows and \a nCols columns. If + \a spacing is -1, this QGridLayout inherits its parent's + spacing(); otherwise \a spacing is used. The grid layout is called + \a name. + + You must insert this grid into another layout. You can insert + widgets and layouts into this layout at any time, but laying out + will not be performed before this is inserted into another layout. +*/ +QGridLayout::QGridLayout(QLayout *parentLayout, int nRows, int nCols, + int spacing, const char *name) + : QLayout(*new QGridLayoutPrivate, parentLayout, 0) +{ + Q_D(QGridLayout); + d->expand(nRows, nCols); + setSpacing(spacing); + setObjectName(QString::fromAscii(name)); +} + +/*! + \obsolete + + Constructs a new grid with \a nRows rows and \a nCols columns. If + \a spacing is -1, this QGridLayout inherits its parent's + spacing(); otherwise \a spacing is used. The grid layout is called + \a name. + + You must insert this grid into another layout. You can insert + widgets and layouts into this layout at any time, but laying out + will not be performed before this is inserted into another layout. +*/ +QGridLayout::QGridLayout(int nRows, int nCols, int spacing, const char *name) + : QLayout(*new QGridLayoutPrivate, 0, 0) +{ + Q_D(QGridLayout); + d->expand(nRows, nCols); + setSpacing(spacing); + setObjectName(QString::fromAscii(name)); +} +#endif + + +/*! +\internal (mostly) + +Sets the positioning mode used by addItem(). If \a orient is +Qt::Horizontal, this layout is expanded to \a n columns, and items +will be added columns-first. Otherwise it is expanded to \a n rows and +items will be added rows-first. +*/ + +void QGridLayout::setDefaultPositioning(int n, Qt::Orientation orient) +{ + Q_D(QGridLayout); + if (orient == Qt::Horizontal) { + d->expand(1, n); + d->addVertical = false; + } else { + d->expand(n,1); + d->addVertical = true; + } +} + + +/*! + Destroys the grid layout. Geometry management is terminated if + this is a top-level grid. + + The layout's widgets aren't destroyed. +*/ +QGridLayout::~QGridLayout() +{ + Q_D(QGridLayout); + d->deleteAll(); +} + +/*! + \property QGridLayout::horizontalSpacing + \brief the spacing between widgets that are laid out side by side + \since 4.3 + + If no value is explicitly set, the layout's horizontal spacing is + inherited from the parent layout, or from the style settings for + the parent widget. + + \sa verticalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing} +*/ +void QGridLayout::setHorizontalSpacing(int spacing) +{ + Q_D(QGridLayout); + d->horizontalSpacing = spacing; + invalidate(); +} + +int QGridLayout::horizontalSpacing() const +{ + Q_D(const QGridLayout); + if (d->horizontalSpacing >= 0) { + return d->horizontalSpacing; + } else { + return qSmartSpacing(this, QStyle::PM_LayoutHorizontalSpacing); + } +} + +/*! + \property QGridLayout::verticalSpacing + \brief the spacing between widgets that are laid out on top of each other + \since 4.3 + + If no value is explicitly set, the layout's vertical spacing is + inherited from the parent layout, or from the style settings for + the parent widget. + + \sa horizontalSpacing, QStyle::pixelMetric(), {QStyle::}{PM_LayoutHorizontalSpacing} +*/ +void QGridLayout::setVerticalSpacing(int spacing) +{ + Q_D(QGridLayout); + d->verticalSpacing = spacing; + invalidate(); +} + +int QGridLayout::verticalSpacing() const +{ + Q_D(const QGridLayout); + if (d->verticalSpacing >= 0) { + return d->verticalSpacing; + } else { + return qSmartSpacing(this, QStyle::PM_LayoutVerticalSpacing); + } +} + +/*! + This function sets both the vertical and horizontal spacing to + \a spacing. + + \sa setVerticalSpacing(), setHorizontalSpacing() +*/ +void QGridLayout::setSpacing(int spacing) +{ + Q_D(QGridLayout); + d->horizontalSpacing = d->verticalSpacing = spacing; + invalidate(); +} + +/*! + If the vertical spacing is equal to the horizontal spacing, + this function returns that value; otherwise it return -1. + + \sa setSpacing(), verticalSpacing(), horizontalSpacing() +*/ +int QGridLayout::spacing() const +{ + int hSpacing = horizontalSpacing(); + if (hSpacing == verticalSpacing()) { + return hSpacing; + } else { + return -1; + } +} + +/*! + Returns the number of rows in this grid. +*/ +int QGridLayout::rowCount() const +{ + Q_D(const QGridLayout); + return d->numRows(); +} + +/*! + Returns the number of columns in this grid. +*/ +int QGridLayout::columnCount() const +{ + Q_D(const QGridLayout); + return d->numCols(); +} + +/*! + \reimp +*/ +QSize QGridLayout::sizeHint() const +{ + Q_D(const QGridLayout); + QSize result(d->sizeHint(horizontalSpacing(), verticalSpacing())); + int left, top, right, bottom; + d->effectiveMargins(&left, &top, &right, &bottom); + result += QSize(left + right, top + bottom); + return result; +} + +/*! + \reimp +*/ +QSize QGridLayout::minimumSize() const +{ + Q_D(const QGridLayout); + QSize result(d->minimumSize(horizontalSpacing(), verticalSpacing())); + int left, top, right, bottom; + d->effectiveMargins(&left, &top, &right, &bottom); + result += QSize(left + right, top + bottom); + return result; +} + +/*! + \reimp +*/ +QSize QGridLayout::maximumSize() const +{ + Q_D(const QGridLayout); + + QSize s = d->maximumSize(horizontalSpacing(), verticalSpacing()); + int left, top, right, bottom; + d->effectiveMargins(&left, &top, &right, &bottom); + s += QSize(left + right, top + bottom); + s = s.boundedTo(QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX)); + if (alignment() & Qt::AlignHorizontal_Mask) + s.setWidth(QLAYOUTSIZE_MAX); + if (alignment() & Qt::AlignVertical_Mask) + s.setHeight(QLAYOUTSIZE_MAX); + return s; +} + +/*! + \reimp +*/ +bool QGridLayout::hasHeightForWidth() const +{ + return ((QGridLayout*)this)->d_func()->hasHeightForWidth(horizontalSpacing(), verticalSpacing()); +} + +/*! + \reimp +*/ +int QGridLayout::heightForWidth(int w) const +{ + Q_D(const QGridLayout); + QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d); + return dat->heightForWidth(w, horizontalSpacing(), verticalSpacing()); +} + +/*! + \reimp +*/ +int QGridLayout::minimumHeightForWidth(int w) const +{ + Q_D(const QGridLayout); + QGridLayoutPrivate *dat = const_cast<QGridLayoutPrivate *>(d); + return dat->minimumHeightForWidth(w, horizontalSpacing(), verticalSpacing()); +} + +#ifdef QT3_SUPPORT +/*! + \compat + + Searches for widget \a w in this layout (not including child + layouts). If \a w is found, it sets \c{*}\a{row} and + \c{*}\a{column} to the row and column that the widget + occupies and returns true; otherwise returns false. + + If the widget spans multiple rows/columns, the top-left cell + is returned. + + Use indexOf() and getItemPosition() instead. +*/ +bool QGridLayout::findWidget(QWidget* w, int *row, int *column) +{ + Q_D(QGridLayout); + int index = indexOf(w); + if (index < 0) + return false; + int dummy1, dummy2; + d->getItemPosition(index, row, column, &dummy1, &dummy2); + return true; +} +#endif +/*! + \reimp +*/ +int QGridLayout::count() const +{ + Q_D(const QGridLayout); + return d->count(); +} + + +/*! + \reimp +*/ +QLayoutItem *QGridLayout::itemAt(int index) const +{ + Q_D(const QGridLayout); + return d->itemAt(index); +} + +/*! + \since 4.4 + + Returns the layout item that occupies cell (\a row, \a column), or 0 if + the cell is empty. + + \sa getItemPosition(), indexOf() +*/ +QLayoutItem *QGridLayout::itemAtPosition(int row, int column) const +{ + Q_D(const QGridLayout); + int n = d->things.count(); + for (int i = 0; i < n; ++i) { + QGridBox *box = d->things.at(i); + if (row >= box->row && row <= box->toRow(d->rr) + && column >= box->col && column <= box->toCol(d->cc)) { + return box->item(); + } + } + return 0; +} + +/*! + \reimp +*/ +QLayoutItem *QGridLayout::takeAt(int index) +{ + Q_D(QGridLayout); + return d->takeAt(index); +} + +/*! + Returns the position information of the item with the given \a index. + + The variables passed as \a row and \a column are updated with the position of the + item in the layout, and the \a rowSpan and \a columnSpan variables are updated + with the vertical and horizontal spans of the item. + + \sa itemAtPosition(), itemAt() +*/ +void QGridLayout::getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan) +{ + Q_D(QGridLayout); + d->getItemPosition(index, row, column, rowSpan, columnSpan); +} + + +/*! + \reimp +*/ +void QGridLayout::setGeometry(const QRect &rect) +{ + Q_D(QGridLayout); + if (d->isDirty() || rect != geometry()) { + QRect cr = alignment() ? alignmentRect(rect) : rect; + d->distribute(cr, horizontalSpacing(), verticalSpacing()); + QLayout::setGeometry(rect); + } +} + +/*! + Returns the geometry of the cell with row \a row and column \a column + in the grid. Returns an invalid rectangle if \a row or \a column is + outside the grid. + + \warning in the current version of Qt this function does not + return valid results until setGeometry() has been called, i.e. + after the parentWidget() is visible. +*/ +QRect QGridLayout::cellRect(int row, int column) const +{ + Q_D(const QGridLayout); + return d->cellRect(row, column); +} +#ifdef QT3_SUPPORT +/*! + \obsolete + Expands this grid so that it will have \a nRows rows and \a nCols + columns. Will not shrink the grid. You should not need to call + this function because QGridLayout expands automatically as new + items are inserted. +*/ +void QGridLayout::expand(int nRows, int nCols) +{ + Q_D(QGridLayout); + d->expand(nRows, nCols); +} +#endif + +/*! + \reimp +*/ +void QGridLayout::addItem(QLayoutItem *item) +{ + Q_D(QGridLayout); + int r, c; + d->getNextPos(r, c); + addItem(item, r, c); +} + +/*! + Adds \a item at position \a row, \a column, spanning \a rowSpan + rows and \a columnSpan columns, and aligns it according to \a + alignment. If \a rowSpan and/or \a columnSpan is -1, then the item + will extend to the bottom and/or right edge, respectively. The + layout takes ownership of the \a item. + + \warning Do not use this function to add child layouts or child + widget items. Use addLayout() or addWidget() instead. +*/ +void QGridLayout::addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment) +{ + Q_D(QGridLayout); + QGridBox *b = new QGridBox(item); + b->setAlignment(alignment); + d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1); + invalidate(); +} + +/* + Returns true if the widget \a w can be added to the layout \a l; + otherwise returns false. +*/ +static bool checkWidget(QLayout *l, QWidget *w) +{ + if (!w) { + qWarning("QLayout: Cannot add null widget to %s/%s", l->metaObject()->className(), + l->objectName().toLocal8Bit().data()); + return false; + } + return true; +} + +/*! + Adds the given \a widget to the cell grid at \a row, \a column. The + top-left position is (0, 0) by default. + + The alignment is specified by \a alignment. The default + alignment is 0, which means that the widget fills the entire cell. + +*/ +void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment) +{ + if (!checkWidget(this, widget)) + return; + if (row < 0 || column < 0) { + qWarning("QGridLayout: Cannot add %s/%s to %s/%s at row %d column %d", + widget->metaObject()->className(), widget->objectName().toLocal8Bit().data(), + metaObject()->className(), objectName().toLocal8Bit().data(), row, column); + return; + } + addChildWidget(widget); + QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget); + addItem(b, row, column, 1, 1, alignment); +} + +/*! + \overload + + This version adds the given \a widget to the cell grid, spanning + multiple rows/columns. The cell will start at \a fromRow, \a + fromColumn spanning \a rowSpan rows and \a columnSpan columns. The + \a widget will have the given \a alignment. + + If \a rowSpan and/or \a columnSpan is -1, then the widget will + extend to the bottom and/or right edge, respectively. + +*/ +void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn, + int rowSpan, int columnSpan, Qt::Alignment alignment) +{ + Q_D(QGridLayout); + if (!checkWidget(this, widget)) + return; + int toRow = (rowSpan < 0) ? -1 : fromRow + rowSpan - 1; + int toColumn = (columnSpan < 0) ? -1 : fromColumn + columnSpan - 1; + addChildWidget(widget); + QGridBox *b = new QGridBox(this, widget); + b->setAlignment(alignment); + d->add(b, fromRow, toRow, fromColumn, toColumn); + invalidate(); +} + +/*! + \fn void QGridLayout::addWidget(QWidget *widget) + + \overload + \internal +*/ + +/*! + Places the \a layout at position (\a row, \a column) in the grid. The + top-left position is (0, 0). + + The alignment is specified by \a alignment. The default + alignment is 0, which means that the widget fills the entire cell. + + A non-zero alignment indicates that the layout should not grow to + fill the available space but should be sized according to + sizeHint(). + + + \a layout becomes a child of the grid layout. +*/ +void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment) +{ + Q_D(QGridLayout); + addChildLayout(layout); + QGridBox *b = new QGridBox(layout); + b->setAlignment(alignment); + d->add(b, row, column); +} + +/*! + \overload + This version adds the layout \a layout to the cell grid, spanning multiple + rows/columns. The cell will start at \a row, \a column spanning \a + rowSpan rows and \a columnSpan columns. + + If \a rowSpan and/or \a columnSpan is -1, then the layout will extend to the bottom + and/or right edge, respectively. +*/ +void QGridLayout::addLayout(QLayout *layout, int row, int column, + int rowSpan, int columnSpan, Qt::Alignment alignment) +{ + Q_D(QGridLayout); + addChildLayout(layout); + QGridBox *b = new QGridBox(layout); + b->setAlignment(alignment); + d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1); +} + +/*! + Sets the stretch factor of row \a row to \a stretch. The first row + is number 0. + + The stretch factor is relative to the other rows in this grid. + Rows with a higher stretch factor take more of the available + space. + + The default stretch factor is 0. If the stretch factor is 0 and no + other row in this table can grow at all, the row may still grow. + + \sa rowStretch(), setRowMinimumHeight(), setColumnStretch() +*/ +void QGridLayout::setRowStretch(int row, int stretch) +{ + Q_D(QGridLayout); + d->setRowStretch(row, stretch); + invalidate(); +} + +/*! + Returns the stretch factor for row \a row. + + \sa setRowStretch() +*/ +int QGridLayout::rowStretch(int row) const +{ + Q_D(const QGridLayout); + return d->rowStretch(row); +} + +/*! + Returns the stretch factor for column \a column. + + \sa setColumnStretch() +*/ +int QGridLayout::columnStretch(int column) const +{ + Q_D(const QGridLayout); + return d->colStretch(column); +} + +/*! + Sets the stretch factor of column \a column to \a stretch. The first + column is number 0. + + The stretch factor is relative to the other columns in this grid. + Columns with a higher stretch factor take more of the available + space. + + The default stretch factor is 0. If the stretch factor is 0 and no + other column in this table can grow at all, the column may still + grow. + + An alternative approach is to add spacing using addItem() with a + QSpacerItem. + + \sa columnStretch(), setRowStretch() +*/ +void QGridLayout::setColumnStretch(int column, int stretch) +{ + Q_D(QGridLayout); + d->setColStretch(column, stretch); + invalidate(); +} + + + +/*! + Sets the minimum height of row \a row to \a minSize pixels. + + \sa rowMinimumHeight(), setColumnMinimumWidth() +*/ +void QGridLayout::setRowMinimumHeight(int row, int minSize) +{ + Q_D(QGridLayout); + d->setRowMinimumHeight(row, minSize); + invalidate(); +} + +/*! + Returns the minimum width set for row \a row. + + \sa setRowMinimumHeight() +*/ +int QGridLayout::rowMinimumHeight(int row) const +{ + Q_D(const QGridLayout); + return d->rowSpacing(row); +} + +/*! + Sets the minimum width of column \a column to \a minSize pixels. + + \sa columnMinimumWidth(), setRowMinimumHeight() +*/ +void QGridLayout::setColumnMinimumWidth(int column, int minSize) +{ + Q_D(QGridLayout); + d->setColumnMinimumWidth(column, minSize); + invalidate(); +} + +/*! + Returns the column spacing for column \a column. + + \sa setColumnMinimumWidth() +*/ +int QGridLayout::columnMinimumWidth(int column) const +{ + Q_D(const QGridLayout); + return d->colSpacing(column); +} + +/*! + \reimp +*/ +Qt::Orientations QGridLayout::expandingDirections() const +{ + Q_D(const QGridLayout); + return d->expandingDirections(horizontalSpacing(), verticalSpacing()); +} + +/*! + Sets the grid's origin corner, i.e. position (0, 0), to \a corner. +*/ +void QGridLayout::setOriginCorner(Qt::Corner corner) +{ + Q_D(QGridLayout); + d->setReversed(corner == Qt::BottomLeftCorner || corner == Qt::BottomRightCorner, + corner == Qt::TopRightCorner || corner == Qt::BottomRightCorner); +} + +/*! + Returns the corner that's used for the grid's origin, i.e. for + position (0, 0). +*/ +Qt::Corner QGridLayout::originCorner() const +{ + Q_D(const QGridLayout); + if (d->horReversed()) { + return d->verReversed() ? Qt::BottomRightCorner : Qt::TopRightCorner; + } else { + return d->verReversed() ? Qt::BottomLeftCorner : Qt::TopLeftCorner; + } +} + +/*! + \reimp +*/ +void QGridLayout::invalidate() +{ + Q_D(QGridLayout); + d->setDirty(); + QLayout::invalidate(); +} + +/*! + \fn void QGridLayout::addRowSpacing(int row, int minsize) + + Use addItem(new QSpacerItem(0, minsize), row, 0) instead. +*/ + +/*! + \fn void QGridLayout::addColSpacing(int col, int minsize) + + Use addItem(new QSpacerItem(minsize, 0), 0, col) instead. +*/ + +/*! + \fn void QGridLayout::addMultiCellWidget(QWidget *widget, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0) + + Use an addWidget() overload that allows you to specify row and + column spans instead. +*/ + +/*! + \fn void QGridLayout::addMultiCell(QLayoutItem *l, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0) + + Use an addItem() overload that allows you to specify row and + column spans instead. +*/ + +/*! + \fn void QGridLayout::addMultiCellLayout(QLayout *layout, int fromRow, int toRow, int fromCol, int toCol, Qt::Alignment align = 0) + + Use an addLayout() overload that allows you to specify row and + column spans instead. +*/ + +/*! + \fn int QGridLayout::numRows() const + + Use rowCount() instead. +*/ + +/*! + \fn int QGridLayout::numCols() const + + Use columnCount() instead. +*/ + +/*! + \fn void QGridLayout::setColStretch(int col, int stretch) + + Use setColumnStretch() instead. +*/ + +/*! + \fn int QGridLayout::colStretch(int col) const + + Use columnStretch() instead. +*/ + +/*! + \fn void QGridLayout::setColSpacing(int col, int minSize) + + Use setColumnMinimumWidth() instead. +*/ + +/*! + \fn int QGridLayout::colSpacing(int col) const + + Use columnSpacing() instead. +*/ + +/*! + \fn void QGridLayout::setRowSpacing(int row, int minSize) + + Use setRowMinimumHeight(\a row, \a minSize) instead. +*/ + +/*! + \fn int QGridLayout::rowSpacing(int row) const + + Use rowMinimumHeight(\a row) instead. +*/ + +/*! + \fn QRect QGridLayout::cellGeometry(int row, int column) const + + Use cellRect(\a row, \a column) instead. +*/ + +/*! + \fn void QGridLayout::setOrigin(Qt::Corner corner) + + Use setOriginCorner(\a corner) instead. +*/ + +/*! + \fn Qt::Corner QGridLayout::origin() const + + Use originCorner() instead. +*/ + + +QT_END_NAMESPACE |