diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp index ed15e460f3..65f2297fce 100644 --- a/src/gui/util/qgridlayoutengine.cpp +++ b/src/gui/util/qgridlayoutengine.cpp @@ -1289,7 +1289,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, if (rowIsIdenticalToPrevious && item != itemAt(row - 1, column, orientation)) rowIsIdenticalToPrevious = false; - if (item) + if (item && !item->isIgnored()) rowIsEmpty = false; } diff --git a/src/gui/util/qgridlayoutengine_p.h b/src/gui/util/qgridlayoutengine_p.h index bf34e816b5..b75312bfe8 100644 --- a/src/gui/util/qgridlayoutengine_p.h +++ b/src/gui/util/qgridlayoutengine_p.h @@ -295,6 +295,7 @@ public: virtual QLayoutPolicy::Policy sizePolicy(Qt::Orientation orientation) const = 0; virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint) const = 0; + virtual bool isIgnored() const { return false; } virtual void setGeometry(const QRectF &rect) = 0; /* diff --git a/src/widgets/graphicsview/qgraphicsgridlayoutengine.cpp b/src/widgets/graphicsview/qgraphicsgridlayoutengine.cpp index 3d9c5d6de5..c9b2ecd62c 100644 --- a/src/widgets/graphicsview/qgraphicsgridlayoutengine.cpp +++ b/src/widgets/graphicsview/qgraphicsgridlayoutengine.cpp @@ -38,9 +38,29 @@ #include "qgraphicslayoutitem_p.h" #include "qgraphicslayout_p.h" #include "qgraphicswidget.h" +#include QT_BEGIN_NAMESPACE +bool QGraphicsGridLayoutEngineItem::isHidden() const +{ + if (QGraphicsItem *item = q_layoutItem->graphicsItem()) + return QGraphicsItemPrivate::get(item)->explicitlyHidden; + return false; +} + +/*! + \internal + + If this returns true, the layout will arrange just as if the item was never added to the layout. + (Note that this shouldn't lead to a "double spacing" where the item was hidden) + ### Qt6: Move to QGraphicsLayoutItem and make virtual +*/ +bool QGraphicsGridLayoutEngineItem::isIgnored() const +{ + return isHidden() && !q_layoutItem->sizePolicy().retainSizeWhenHidden(); +} + /* returns \c true if the size policy returns \c true for either hasHeightForWidth() or hasWidthForHeight() diff --git a/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h b/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h index 4d6bdfce0a..07486514f8 100644 --- a/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h +++ b/src/widgets/graphicsview/qgraphicsgridlayoutengine_p.h @@ -82,6 +82,10 @@ public: return q_layoutItem->effectiveSizeHint(which, constraint); } + bool isHidden() const; + + virtual bool isIgnored() const Q_DECL_OVERRIDE; + virtual void setGeometry(const QRectF &rect) Q_DECL_OVERRIDE { q_layoutItem->setGeometry(rect); diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp index 4a9c3b098e..5bd563e535 100644 --- a/src/widgets/graphicsview/qgraphicswidget.cpp +++ b/src/widgets/graphicsview/qgraphicswidget.cpp @@ -1137,6 +1137,10 @@ QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant & setAttribute(Qt::WA_Resized, false); } } + + // layout size hint only changes if an item changes from/to explicitly hidden state + if (value.toBool() || d->explicitlyHidden) + updateGeometry(); break; case ItemVisibleHasChanged: if (!value.toBool()) { diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp index c90c431d8b..3b55fcd5fc 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp @@ -124,6 +124,7 @@ private slots: void heightForWidthWithSpanning(); void stretchAndHeightForWidth(); void testDefaultAlignment(); + void hiddenItems(); }; class RectWidget : public QGraphicsWidget @@ -3485,6 +3486,94 @@ void tst_QGraphicsGridLayout::testDefaultAlignment() QCOMPARE(w->geometry(), QRectF(0,0,50,50)); QCOMPARE(w2->geometry(), QRectF(0,50,100,100)); } + +static RectWidget *addWidget(QGraphicsGridLayout *grid, int row, int column) +{ + RectWidget *w = new RectWidget; + w->setPreferredSize(20, 20); + grid->addItem(w, row, column); + return w; +} + +static void setVisible(bool visible, QGraphicsWidget **widgets) +{ + for (int i = 0; i < 3; ++i) + if (widgets[i]) widgets[i]->setVisible(visible); +} + +static void setRetainSizeWhenHidden(bool retainSize, QGraphicsWidget **widgets) +{ + QSizePolicy sp = widgets[0]->sizePolicy(); + sp.setRetainSizeWhenHidden(retainSize); + for (int i = 0; i < 3; ++i) + if (widgets[i]) widgets[i]->setSizePolicy(sp); +} + +void tst_QGraphicsGridLayout::hiddenItems() +{ + QGraphicsWidget *widget = new QGraphicsWidget; + QGraphicsGridLayout *layout = new QGraphicsGridLayout(widget); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(2); + + // Create a 3x3 layout + addWidget(layout, 0, 0); + RectWidget *w01 = addWidget(layout, 0, 1); + addWidget(layout, 0, 2); + RectWidget *w10 = addWidget(layout, 1, 0); + RectWidget *w11 = addWidget(layout, 1, 1); + RectWidget *w12 = addWidget(layout, 1, 2); + addWidget(layout, 2, 0); + RectWidget *w21 = addWidget(layout, 2, 1); + addWidget(layout, 2, 2); + + QGraphicsWidget *middleColumn[] = {w01, w11, w21 }; + QGraphicsWidget *topTwoOfMiddleColumn[] = {w01, w11, 0 }; + + // hide and show middle column + QCOMPARE(layout->preferredWidth(), qreal(64)); + setVisible(false, middleColumn); // hide middle column + QCOMPARE(layout->preferredWidth(), qreal(42)); + setVisible(true, middleColumn); // show middle column + QCOMPARE(layout->preferredWidth(), qreal(64)); + setRetainSizeWhenHidden(true, middleColumn); + QCOMPARE(layout->preferredWidth(), qreal(64)); + setVisible(false, middleColumn); // hide middle column + QCOMPARE(layout->preferredWidth(), qreal(64)); + setRetainSizeWhenHidden(false, middleColumn); + QCOMPARE(layout->preferredWidth(), qreal(42)); + setVisible(true, middleColumn); + QCOMPARE(layout->preferredWidth(), qreal(64)); + + // Hide only two items, => column should not collapse + setVisible(false, topTwoOfMiddleColumn); + QCOMPARE(layout->preferredWidth(), qreal(64)); + + + QGraphicsWidget *middleRow[] = {w10, w11, w12 }; + QGraphicsWidget *leftMostTwoOfMiddleRow[] = {w10, w11, 0 }; + + // hide and show middle row + QCOMPARE(layout->preferredHeight(), qreal(64)); + setVisible(false, middleRow); + QCOMPARE(layout->preferredHeight(), qreal(42)); + setVisible(true, middleRow); + QCOMPARE(layout->preferredHeight(), qreal(64)); + setRetainSizeWhenHidden(true, middleColumn); + QCOMPARE(layout->preferredHeight(), qreal(64)); + setVisible(false, middleRow); + QCOMPARE(layout->preferredHeight(), qreal(64)); + setRetainSizeWhenHidden(false, middleRow); + QCOMPARE(layout->preferredHeight(), qreal(42)); + setVisible(true, middleRow); + QCOMPARE(layout->preferredHeight(), qreal(64)); + + // Hide only two items => row should not collapse + setVisible(false, leftMostTwoOfMiddleRow); + QCOMPARE(layout->preferredHeight(), qreal(64)); + +} + QTEST_MAIN(tst_QGraphicsGridLayout) #include "tst_qgraphicsgridlayout.moc" diff --git a/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp index d35667f215..107e3eb48a 100644 --- a/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp @@ -50,6 +50,7 @@ private slots: void compressLayoutRequest(); void automaticReparenting(); void verifyActivate(); + void sizeHintOfHiddenLayout(); void invalidate(); void constructors(); void alternativeLayoutItems(); @@ -279,6 +280,30 @@ void tst_QGraphicsLayout::verifyActivate() } + +void tst_QGraphicsLayout::sizeHintOfHiddenLayout() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + + QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window); + scene.addItem(window); + TestLayout *lout = new TestLayout(window); + lout->setContentsMargins(1,2,2,1); + QGraphicsWidget *w = new QGraphicsWidget; + w->setPreferredSize(20, 20); + w->setMaximumSize(50, 50); + lout->addItem(w); + window->setLayout(lout); + + for (int pass = 0; pass < 3; ++pass) { + QCOMPARE(lout->sizeHint(Qt::MinimumSize), QSizeF(3,3)); + QCOMPARE(lout->sizeHint(Qt::PreferredSize), QSizeF(23,23)); + QCOMPARE(lout->sizeHint(Qt::MaximumSize), QSizeF(53,53)); + window->setVisible(pass % 2); + } +} + static void clearAllCounters(TestGraphicsWidget *widget) { if (!widget) diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp index 7147bb8cce..1513abf0b1 100644 --- a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp @@ -103,6 +103,7 @@ private slots: void testOffByOneInLargerLayout(); void testDefaultAlignment(); void combineSizePolicies(); + void hiddenItems(); // Task specific tests void task218400_insertStretchCrash(); @@ -1721,6 +1722,41 @@ void tst_QGraphicsLinearLayout::combineSizePolicies() QCOMPARE(layout->maximumHeight(), qreal(200)); } +void tst_QGraphicsLinearLayout::hiddenItems() +{ + QGraphicsWidget *widget = new QGraphicsWidget; + QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Horizontal, widget); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(2); + + RectWidget *w1 = new RectWidget; + w1->setPreferredSize(QSizeF(20, 20)); + layout->addItem(w1); + + RectWidget *w2 = new RectWidget; + w2->setPreferredSize(QSizeF(20, 20)); + layout->addItem(w2); + + RectWidget *w3 = new RectWidget; + w3->setPreferredSize(QSizeF(20, 20)); + layout->addItem(w3); + + QCOMPARE(layout->preferredWidth(), qreal(64)); + w2->hide(); + QCOMPARE(layout->preferredWidth(), qreal(42)); + w2->show(); + QCOMPARE(layout->preferredWidth(), qreal(64)); + QSizePolicy sp = w2->sizePolicy(); + sp.setRetainSizeWhenHidden(true); + w2->setSizePolicy(sp); + QCOMPARE(layout->preferredWidth(), qreal(64)); + w2->hide(); + QCOMPARE(layout->preferredWidth(), qreal(64)); + sp.setRetainSizeWhenHidden(false); + w2->setSizePolicy(sp); + QCOMPARE(layout->preferredWidth(), qreal(42)); +} + QTEST_MAIN(tst_QGraphicsLinearLayout) #include "tst_qgraphicslinearlayout.moc"