📄 qgridlayout.cpp
字号:
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_CACHINGvoid 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -