📄 layout.cpp
字号:
splitter->addWidget(w); } else { if (Spacer *spacer = qobject_cast<Spacer*>(w)) layout->addWidget(w, 0, spacer->alignment()); else add_to_box_layout(layout, w); } w->show(); } if (QSplitter *splitter = qobject_cast<QSplitter*>(layoutBase)) { // ### useSplitter?? splitter->setOrientation(Qt::Vertical); } finishLayout(needMove, layout);}class Grid{public: Grid(int rows, int cols); ~Grid(); QWidget* cell(int row, int col) const { return cells[ row * ncols + col]; } void setCell(int row, int col, QWidget* w) { cells[ row*ncols + col] = w; } void setCells(QRect c, QWidget* w) { for (int rows = c.bottom()-c.top(); rows >= 0; rows--) for (int cols = c.right()-c.left(); cols >= 0; cols--) { setCell(c.top()+rows, c.left()+cols, w); } } int numRows() const { return nrows; } int numCols() const { return ncols; } void simplify(); bool locateWidget(QWidget* w, int& row, int& col, int& rowspan, int& colspan);private: void merge(); int countRow(int r, int c) const; int countCol(int r, int c) const; void setRow(int r, int c, QWidget* w, int count); void setCol(int r, int c, QWidget* w, int count); bool isWidgetStartCol(int c) const; bool isWidgetEndCol(int c) const; bool isWidgetStartRow(int r) const; bool isWidgetEndRow(int r) const; bool isWidgetTopLeft(int r, int c) const; void extendLeft(); void extendRight(); void extendUp(); void extendDown(); QWidget** cells; bool* cols; bool* rows; int nrows, ncols;};Grid::Grid(int r, int c) : nrows(r), ncols(c){ cells = new QWidget*[ r * c ]; memset(cells, 0, sizeof(cells) * r * c); rows = new bool[ r ]; cols = new bool[ c ];}Grid::~Grid(){ delete [] cells; delete [] cols; delete [] rows;}int Grid::countRow(int r, int c) const{ QWidget* w = cell(r, c); int i = c + 1; while (i < ncols && cell(r, i) == w) i++; return i - c;}int Grid::countCol(int r, int c) const{ QWidget* w = cell(r, c); int i = r + 1; while (i < nrows && cell(i, c) == w) i++; return i - r;}void Grid::setCol(int r, int c, QWidget* w, int count){ for (int i = 0; i < count; i++) setCell(r + i, c, w);}void Grid::setRow(int r, int c, QWidget* w, int count){ for (int i = 0; i < count; i++) setCell(r, c + i, w);}bool Grid::isWidgetStartCol(int c) const{ int r; for (r = 0; r < nrows; r++) { if (cell(r, c) && ((c==0) || (cell(r, c) != cell(r, c-1)))) { return true; } } return false;}bool Grid::isWidgetEndCol(int c) const{ int r; for (r = 0; r < nrows; r++) { if (cell(r, c) && ((c == ncols-1) || (cell(r, c) != cell(r, c+1)))) return true; } return false;}bool Grid::isWidgetStartRow(int r) const{ int c; for (c = 0; c < ncols; c++) { if (cell(r, c) && ((r==0) || (cell(r, c) != cell(r-1, c)))) return true; } return false;}bool Grid::isWidgetEndRow(int r) const{ int c; for (c = 0; c < ncols; c++) { if (cell(r, c) && ((r == nrows-1) || (cell(r, c) != cell(r+1, c)))) return true; } return false;}bool Grid::isWidgetTopLeft(int r, int c) const{ QWidget* w = cell(r, c); if (!w) return false; return (!r || cell(r-1, c) != w) && (!c || cell(r, c-1) != w);}void Grid::extendLeft(){ int r,c,i; for (c = 1; c < ncols; c++) { for (r = 0; r < nrows; r++) { QWidget* w = cell(r, c); if (!w) continue; int cc = countCol(r, c); int stretch = 0; for (i = c-1; i >= 0; i--) { if (cell(r, i)) break; if (countCol(r, i) < cc) break; if (isWidgetEndCol(i)) break; if (isWidgetStartCol(i)) { stretch = c - i; break; } } if (stretch) { for (i = 0; i < stretch; i++) setCol(r, c-i-1, w, cc); } } }}void Grid::extendRight(){ int r,c,i; for (c = ncols - 2; c >= 0; c--) { for (r = 0; r < nrows; r++) { QWidget* w = cell(r, c); if (!w) continue; int cc = countCol(r, c); int stretch = 0; for (i = c+1; i < ncols; i++) { if (cell(r, i)) break; if (countCol(r, i) < cc) break; if (isWidgetStartCol(i)) break; if (isWidgetEndCol(i)) { stretch = i - c; break; } } if (stretch) { for (i = 0; i < stretch; i++) setCol(r, c+i+1, w, cc); } } }}void Grid::extendUp(){ int r,c,i; for (r = 1; r < nrows; r++) { for (c = 0; c < ncols; c++) { QWidget* w = cell(r, c); if (!w) continue; int cr = countRow(r, c); int stretch = 0; for (i = r-1; i >= 0; i--) { if (cell(i, c)) break; if (countRow(i, c) < cr) break; if (isWidgetEndRow(i)) break; if (isWidgetStartRow(i)) { stretch = r - i; break; } } if (stretch) { for (i = 0; i < stretch; i++) setRow(r-i-1, c, w, cr); } } }}void Grid::extendDown(){ int r,c,i; for (r = nrows - 2; r >= 0; r--) { for (c = 0; c < ncols; c++) { QWidget* w = cell(r, c); if (!w) continue; int cr = countRow(r, c); int stretch = 0; for (i = r+1; i < nrows; i++) { if (cell(i, c)) break; if (countRow(i, c) < cr) break; if (isWidgetStartRow(i)) break; if (isWidgetEndRow(i)) { stretch = i - r; break; } } if (stretch) { for (i = 0; i < stretch; i++) setRow(r+i+1, c, w, cr); } } }}void Grid::simplify(){ extendLeft(); extendRight(); extendUp(); extendDown(); merge();}void Grid::merge(){ int r,c; for (c = 0; c < ncols; c++) cols[c] = false; for (r = 0; r < nrows; r++) rows[r] = false; for (c = 0; c < ncols; c++) { for (r = 0; r < nrows; r++) { if (isWidgetTopLeft(r, c)) { rows[r] = true; cols[c] = true; } } }}bool Grid::locateWidget(QWidget *w, int &row, int &col, int &rowspan, int &colspan){ int r, c, r2, c2; for (c = 0; c < ncols; c++) { for (r = 0; r < nrows; r++) { if (cell(r, c) == w) { row = 0; for (r2 = 1; r2 <= r; r2++) { if (rows[r2-1]) row++; } col = 0; for (c2 = 1; c2 <= c; c2++) { if (cols[c2-1]) col++; } rowspan = 0; for (r2 = r ; r2 < nrows && cell(r2, c) == w; r2++) { if (rows[r2]) rowspan++; } colspan = 0; for (c2 = c; c2 < ncols && cell(r, c2) == w; c2++) { if (cols[c2]) colspan++; } return true; } } } return false;}GridLayout::GridLayout(const QList<QWidget*> &wl, QWidget *p, QDesignerFormWindowInterface *fw, QWidget *lb, const QSize &res) : Layout(wl, p, fw, lb), resolution(res){ grid = 0;}GridLayout::~GridLayout(){ delete grid;}QWidget *GridLayout::widgetAt(QGridLayout *layout, int row, int column) const{ int index = 0; while (QLayoutItem *item = layout->itemAt(index)) { if (item->widget()) { int r, c, rowspan, colspan; layout->getItemPosition(index, &r, &c, &rowspan, &colspan); if (row == r && column == c) return item->widget(); } ++index; } return 0;}void GridLayout::doLayout(){ bool needMove, needReparent; if (!prepareLayout(needMove, needReparent)) return; QDesignerWidgetFactoryInterface *ff = formWindow->core()->widgetFactory(); QGridLayout *layout = static_cast<QGridLayout*>(ff->createLayout(layoutBase, 0, LayoutInfo::Grid)); if (!grid) buildGrid(); foreach (QWidget *w, m_widgets) { int r = 0, c = 0, rs = 0, cs = 0; if (grid->locateWidget(w, r, c, rs, cs)) { if (needReparent && w->parent() != layoutBase) { w->setParent(layoutBase, 0); w->move(QPoint(0,0)); } Qt::Alignment alignment = Qt::Alignment(0); if (Spacer *spacer = qobject_cast<Spacer*>(w)) alignment = spacer->alignment(); if (rs * cs == 1) { add_to_grid_layout(layout, w, r, c, 1, 1, alignment); } else { add_to_grid_layout(layout, w, r, c, rs, cs, alignment); } w->show(); } else { qWarning("ooops, widget '%s' does not fit in layout", w->objectName().toUtf8().constData()); } } QLayoutSupport::createEmptyCells(layout); finishLayout(needMove, layout);}void GridLayout::sort(){ buildGrid();}void GridLayout::buildGrid(){ if (!m_widgets.count()) return;#if 0 QMap<int, int> x_dict; QMap<int, int> y_dict; foreach (QWidget *w, m_widgets) { QRect g = w->geometry(); x_dict.insert(g.left(), g.left()); x_dict.insert(g.right(), g.right()); y_dict.insert(g.top(), g.top()); y_dict.insert(g.bottom(), g.bottom()); } QList<int> x = x_dict.keys(); QList<int> y = y_dict.keys();#else // Pixel to cell conversion: // By keeping a list of start'n'stop values (x & y) for each widget, // it is possible to create a very small grid of cells to represent // the widget layout. // ----------------------------------------------------------------- // We need a list of both start and stop values for x- & y-axis QVector<int> x( m_widgets.count()*2 ); QVector<int> y( m_widgets.count()*2 ); // Using push_back would look nicer, but operator[] is much faster int index = 0; QWidget* w = 0; for (int i = 0; i < m_widgets.size(); ++i) { w = m_widgets.at(i); QRect widgetPos = w->geometry(); x[index] = widgetPos.left(); x[index+1] = widgetPos.right(); y[index] = widgetPos.top(); y[index+1] = widgetPos.bottom(); index += 2; } qSort(x); qSort(y); // Remove duplicate x enteries (Remove next, if equal to current) if ( !x.empty() ) { for (QVector<int>::iterator current = x.begin() ; (current != x.end()) && ((current+1) != x.end()) ; ) if ( (*current == *(current+1)) ) x.erase(current+1); else current++; } // Remove duplicate y enteries (Remove next, if equal to current) if ( !y.empty() ) { for (QVector<int>::iterator current = y.begin() ; (current != y.end()) && ((current+1) != y.end()) ; ) if ( (*current == *(current+1)) ) y.erase(current+1); else current++; }#endif delete grid; grid = new Grid(y.size() - 1, x.size() - 1); // Mark the cells in the grid that contains a widget foreach (QWidget *w, m_widgets) { QRect widgetPos = w->geometry(); QRect c(0, 0, 0, 0); // From left til right (not including) for (int cw=0; cw<x.size(); cw++) { if (x[cw] == widgetPos.left()) c.setLeft(cw); if (x[cw] < widgetPos.right()) c.setRight(cw); } // From top til bottom (not including) for (int ch=0; ch<y.size(); ch++) { if (y[ch] == widgetPos.top() ) c.setTop(ch); if (y[ch] < widgetPos.bottom()) c.setBottom(ch); } grid->setCells(c, w); // Mark cellblock } grid->simplify();}} // namespace qdesigner_internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -