From 3385b6c15c2387a52ed8194c5d5eec0d65a91c4e Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Mon, 12 Aug 2019 11:29:45 +0100 Subject: [PATCH] After restoring a placeholder we need to ensure all anchors are bounded We only ensure the ones next to our item are bounded, but there can be indirect ones that were holding items that now must shrink --- src/multisplitter/Anchor.cpp | 16 ++++++++++ src/multisplitter/Anchor_p.h | 2 ++ src/multisplitter/MultiSplitterLayout.cpp | 8 +++++ src/multisplitter/MultiSplitterLayout_p.h | 2 ++ tests/tst_docks.cpp | 37 +++++++++++++++++++++++ 5 files changed, 65 insertions(+) diff --git a/src/multisplitter/Anchor.cpp b/src/multisplitter/Anchor.cpp index cca98daa..7058d744 100644 --- a/src/multisplitter/Anchor.cpp +++ b/src/multisplitter/Anchor.cpp @@ -281,6 +281,22 @@ int Anchor::smallestAvailableItemSqueeze(Anchor::Side side) const return smallest; } +void Anchor::ensureBounded() +{ + if (!isStatic()) { + const QPair bounds = m_layout->boundPositionsForAnchor(this); + if (position() < bounds.first) { + setPosition(bounds.first); + } else if (position() > bounds.second) { + setPosition(bounds.second); + } + } + + for (Item *item : items(Side2)) { + item->anchorAtSide(Side2, orientation())->ensureBounded(); + } +} + int Anchor::length() const { Q_ASSERT(m_to); diff --git a/src/multisplitter/Anchor_p.h b/src/multisplitter/Anchor_p.h index d3a3ea75..08c59487 100644 --- a/src/multisplitter/Anchor_p.h +++ b/src/multisplitter/Anchor_p.h @@ -143,6 +143,8 @@ public: void setVisible(bool); qreal positionPercentage() const { return m_positionPercentage; } + void ensureBounded(); + /** * @brief Sets the new layout. Called when we're dropping a source layout into a target one. * The target one will steal the separators of the source one. diff --git a/src/multisplitter/MultiSplitterLayout.cpp b/src/multisplitter/MultiSplitterLayout.cpp index a9575f81..100436b7 100644 --- a/src/multisplitter/MultiSplitterLayout.cpp +++ b/src/multisplitter/MultiSplitterLayout.cpp @@ -422,6 +422,13 @@ void MultiSplitterLayout::ensureEnoughContentsSize(const QWidgetOrQuick *widget, } } +void MultiSplitterLayout::ensureAnchorsBounded() +{ + // Recursive, goes all the way to right/bottom + m_leftAnchor->ensureBounded(); + m_topAnchor->ensureBounded(); +} + static Anchor::List removeSmallestPath(QVector &paths) { // Removes and returns the smallest list @@ -1576,6 +1583,7 @@ void MultiSplitterLayout::restorePlaceholder(Item *item) } item->endBlockPropagateGeo(); + ensureAnchorsBounded(); updateAnchorFollowing(); } diff --git a/src/multisplitter/MultiSplitterLayout_p.h b/src/multisplitter/MultiSplitterLayout_p.h index e1daca33..252e0687 100644 --- a/src/multisplitter/MultiSplitterLayout_p.h +++ b/src/multisplitter/MultiSplitterLayout_p.h @@ -473,6 +473,8 @@ private: const Item *relativeToItem); + void ensureAnchorsBounded(); + void insertAnchor(Anchor *); void removeAnchor(Anchor *); diff --git a/tests/tst_docks.cpp b/tests/tst_docks.cpp index f027f8e6..298f638f 100644 --- a/tests/tst_docks.cpp +++ b/tests/tst_docks.cpp @@ -306,6 +306,7 @@ private Q_SLOTS: void tst_rectForDropMath_data(); void tst_rectForDropMath(); void tst_crash(); // tests some crash I got + void tst_crash2(); void tst_setFloatingWhenWasTabbed(); void tst_setFloatingWhenSideBySide(); void tst_setFloatingAfterDraggedFromTabToSideBySide(); @@ -2492,6 +2493,41 @@ void TestDocks::tst_crash() } } +void TestDocks::tst_crash2() +{ + EnsureTopLevelsDeleted e; + auto m = new MainWindow("m1"); + auto layout = m->multiSplitterLayout(); + m->show(); + + DockWidget::List docks; + for (int i = 0; i < 3; ++i) + docks << new DockWidget(QString::number(i)); + + QVector locations = {Location_OnLeft, Location_OnLeft, + Location_OnRight}; + + QVector options = { AddingOption_None, AddingOption_None, + AddingOption_StartHidden}; + + QVector floatings = {true, false, false}; + + for (int i = 0; i < 3; ++i) { + + m->addDockWidget(docks[i], locations[i], nullptr, options[i]); + layout->checkSanity(); + + QCOMPARE(layout->m_leftAnchor->cumulativeMinLength(Anchor::Side2), layout->minimumSize().width()); + QCOMPARE(layout->m_topAnchor->cumulativeMinLength(Anchor::Side2), layout->minimumSize().height()); + + docks[i]->setFloating(floatings[i]); + } + + qDeleteAll(docks); + qDeleteAll(DockRegistry::self()->frames()); + delete m; +} + void TestDocks::tst_setFloatingWhenWasTabbed() { // Tests DockWidget::isTabbed() and DockWidget::setFloating(false|true) when tabbed (it should redock) @@ -3966,6 +4002,7 @@ void TestDocks::tst_addToHiddenMainWindow() QVERIFY(!m->isVisible()); d1->setFloating(true); + d2->setFloating(false); delete m; }