📄 qgridlayout.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qgridlayout.h"#include "qapplication.h"#include "qwidget.h"#include "qlist.h"#include "qsizepolicy.h"#include "qvector.h"#include "qlayoutengine_p.h"#include "qlayout_p.h"/* 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(QWidget *wid) { item_ = new QWidgetItem(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; 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) const; QSize minimumSize(int) const; QSize maximumSize(int) const; Qt::Orientations expandingDirections(int spacing) const; void distribute(QRect, int); 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[r]; } inline int colStretch(int c) const { return cStretch[c]; } inline void setRowSpacing(int r, int s) { expand(r + 1, 0); rSpacing[r] = s; setDirty(); } inline void setColSpacing(int c, int s) { expand(0, c + 1); cSpacing[c] = s; setDirty(); } inline int rowSpacing(int r) const { return rSpacing[r]; } inline int colSpacing(int c) const { return cSpacing[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 space); int heightForWidth(int, int, int); int minimumHeightForWidth(int, int, int); 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 < 0 ? rr-1 : b->torow; int toCol = b->tocol < 0 ? cc-1 : b->tocol; *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, int s); void addHfwData(QGridBox *box, int width); void init(); QSize findSize(int QLayoutStruct::*, int) const; void addData(QGridBox *b, bool r = true, bool c = true); void setSize(int rows, int cols); void setupLayoutData(int space); void setupHfwLayoutData(int space); int rr; int cc; QVector<QLayoutStruct> rowData; QVector<QLayoutStruct> colData; QVector<QLayoutStruct> *hfwData; QVector<int> rStretch; QVector<int> cStretch; QVector<int> rSpacing; QVector<int> cSpacing; QList<QGridBox *> things; int hfw_width; int hfw_height; int hfw_minheight; int nextR; int nextC; uint hReversed : 1; uint vReversed : 1; uint needRecalc : 1; uint has_hfw : 1; uint addVertical : 1;};QGridLayoutPrivate::QGridLayoutPrivate(){ addVertical = false; setDirty(); rr = cc = 0; nextR = nextC = 0; hfwData = 0; hReversed = false; vReversed = false;}#if 0QGridLayoutPrivate::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);}#endifvoid QGridLayoutPrivate::deleteAll(){ while (!things.isEmpty()) delete things.takeFirst(); delete hfwData;}bool QGridLayoutPrivate::hasHeightForWidth(int spacing){ setupLayoutData(spacing); return has_hfw;}/* Assumes that setupLayoutData() has been called, and that qGeomCalc() has filled in colData with appropriate values.*/void QGridLayoutPrivate::recalcHFW(int w, int spacing){ /* Go through all children, using colData and heightForWidth() and put the results in hfwData. */ if (!hfwData) hfwData = new QVector<QLayoutStruct>(rr); setupHfwLayoutData(spacing); QVector<QLayoutStruct> &rData = *hfwData; int h = 0; int mh = 0; int n = 0; for (int r = 0; r < rr; r++) { if (!rData[r].empty) { h += rData[r].sizeHint; mh += rData[r].minimumSize; n++; } } if (n) { h += (n - 1) * spacing; mh += (n - 1) * spacing; } hfw_width = w; hfw_height = qMin(QLAYOUTSIZE_MAX, h); hfw_minheight = qMin(QLAYOUTSIZE_MAX, mh);}int QGridLayoutPrivate::heightForWidth(int w, int margin, int spacing){ setupLayoutData(spacing); if (!has_hfw) return -1; if (w + 2*margin != hfw_width) { qGeomCalc(colData, 0, cc, 0, w+2*margin, spacing); recalcHFW(w+2*margin, spacing); } return hfw_height + 2*margin;}int QGridLayoutPrivate::minimumHeightForWidth(int w, int margin, int spacing){ (void) heightForWidth(w, margin, spacing); return has_hfw ? (hfw_minheight + 2*margin) : -1;}QSize QGridLayoutPrivate::findSize(int QLayoutStruct::*size, int spacer) const{ QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this); that->setupLayoutData(spacer); int w = 0; int h = 0; int n = 0; for (int r = 0; r < rr; r++) if (!rowData[r].empty) { h = h + rowData[r].*size; n++; } if (n) h += (n - 1) * spacer; n = 0; for (int c = 0; c < cc; c++) if (!colData[c].empty) { w = w + colData[c].*size; n++; } if (n) w += (n - 1) * spacer; w = qMin(QLAYOUTSIZE_MAX, w); h = qMin(QLAYOUTSIZE_MAX, h); return QSize(w, h);}Qt::Orientations QGridLayoutPrivate::expandingDirections(int spacing) const{ QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this); that->setupLayoutData(spacing); Qt::Orientations ret; for (int r = 0; r < rr; r++) { if (rowData[r].expansive) { ret |= Qt::Vertical; break; } } for (int c = 0; c < cc; c++) { if (colData[c].expansive) { ret |= Qt::Horizontal; break; } } return ret;}QSize QGridLayoutPrivate::sizeHint(int spacer) const{ return findSize(&QLayoutStruct::sizeHint, spacer);}QSize QGridLayoutPrivate::maximumSize(int spacer) const{ return findSize(&QLayoutStruct::maximumSize, spacer);}QSize QGridLayoutPrivate::minimumSize(int spacer) const{ return findSize(&QLayoutStruct::minimumSize, spacer);}void QGridLayoutPrivate::setSize(int r, int c){ if ((int)rowData.size() < r) { int newR = qMax(r, rr * 2); rowData.resize(newR); rStretch.resize(newR); rSpacing.resize(newR); for (int i = rr; i < newR; i++) { rowData[i].init(); rStretch[i] = 0; rSpacing[i] = 0; } } if ((int)colData.size() < c) { int newC = qMax(c, cc * 2); colData.resize(newC); cStretch.resize(newC); cSpacing.resize(newC); for (int i = cc; i < newC; i++) { colData[i].init(); cStretch[i] = 0; cSpacing[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, bool r, bool c){ QSize hint = box->sizeHint(); QSize minS = box->minimumSize(); QSize maxS = box->maximumSize(); const QWidget *widget = box->item()->widget(); if (box->isEmpty() && widget) return; if (c) { if (!cStretch[box->col]) colData[box->col].stretch = qMax(colData[box->col].stretch, box->hStretch()); colData[box->col].sizeHint = qMax(hint.width(), colData[box->col].sizeHint); colData[box->col].minimumSize = qMax(minS.width(), colData[box->col].minimumSize); qMaxExpCalc(colData[box->col].maximumSize, colData[box->col].expansive, maxS.width(), box->expandingDirections() & Qt::Horizontal); } if (r) { if (!rStretch[box->row]) rowData[box->row].stretch = qMax(rowData[box->row].stretch, box->vStretch()); rowData[box->row].sizeHint = qMax(hint.height(), rowData[box->row].sizeHint); rowData[box->row].minimumSize = qMax(minS.height(), rowData[box->row].minimumSize); qMaxExpCalc(rowData[box->row].maximumSize, rowData[box->row].expansive, maxS.height(), box->expandingDirections() & Qt::Vertical); } if (!box->isEmpty()) { // Empty boxes (i.e. spacers) do not get borders. This is // hacky, but compatible. if (c) colData[box->col].empty = false; if (r) rowData[box->row].empty = false; }}static void distributeMultiBox(QVector<QLayoutStruct> &chain, int spacing, 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++) { w += chain[i].minimumSize; wh += chain[i].sizeHint; max += chain[i].maximumSize; chain[i].empty = false; if (stretchArray[i] == 0) chain[i].stretch = qMax(chain[i].stretch,stretch); } w += spacing * (end - start); wh += spacing * (end - start); max += spacing * (end - start); if (max < minSize) { // implies w < minSize /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -