From cd2a3e970aaeb8f5f92d9c6e52ede7a82f953150 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Tue, 27 Feb 2024 16:42:24 +0100 Subject: Refactor and fix QMainWindow::tabifiedDockWidgets() The method traversed QDockAreaLayoutInfo::item_list, to identify dock widgets tabbed with the QDockWidget argument in a tab bar It relied on bool QDockAreLayoutInfo::tabbed, which is set to true, when a QMainWindowTabBar is to be added to a QDockAreaLayoutInfo. This flag isn't cleared, when the second last dock widget is removed from the tab bar. It can't be replaced by QMainWindowLayout::isDockWidgetTabbed, because the flag also represents intermediate states, where e.g. a dock widget is hovered over, prepares to become a floating tab and then rolls back, because hovering doesn't result in a drop. In that case, tabbed must become true, which the dock widget isn't actually tabbed. Furthermore, the way to traverse item_list didn't find dock widgets in a floating tab. In that case, tabifiedDockWidgets() wrongly returned an empty list. To fix both issues, refactor QMainWindow::tabifiedDockWidgets() to read the list of dock widgets directly from the QMainWindowTabBar. Add tests in tst_QDockWidget::floatingTabs() and updateTabBarOnVisibilityChanged() Fixes: QTBUG-122001 Pick-to: 6.7 6.6 6.5 Change-Id: Ia9eb3711be642101261f34ee447521cc6accc20c Reviewed-by: Volker Hilsheimer --- src/widgets/widgets/qmainwindowlayout.cpp | 52 +++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 13 deletions(-) (limited to 'src/widgets/widgets/qmainwindowlayout.cpp') diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 3933f2a7cd..e17fa28b83 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -1885,6 +1885,7 @@ public: ~QMainWindowTabBar(); QDockWidget *dockAt(int index) const; QList dockWidgets() const; + bool contains(const QDockWidget *dockWidget) const; protected: bool event(QEvent *e) override; void mouseReleaseEvent(QMouseEvent*) override; @@ -1892,6 +1893,17 @@ protected: }; +QMainWindowTabBar *QMainWindowLayout::findTabBar(const QDockWidget *dockWidget) const +{ + for (auto *bar : usedTabBars) { + Q_ASSERT(qobject_cast(bar)); + auto *tabBar = static_cast(bar); + if (tabBar->contains(dockWidget)) + return tabBar; + } + return nullptr; +} + QMainWindowTabBar::QMainWindowTabBar(QMainWindow *parent) : QTabBar(parent), mainWindow(parent) { @@ -1908,6 +1920,15 @@ QList QMainWindowTabBar::dockWidgets() const return docks; } +bool QMainWindowTabBar::contains(const QDockWidget *dockWidget) const +{ + for (int i = 0; i < count(); ++i) { + if (dockAt(i) == dockWidget) + return true; + } + return false; +} + QDockWidget *QMainWindowTabBar::dockAt(int index) const { QMainWindowTabBar *that = const_cast(this); @@ -2011,21 +2032,26 @@ bool QMainWindowTabBar::event(QEvent *e) return true; } +QList QMainWindowLayout::tabifiedDockWidgets(const QDockWidget *dockWidget) const +{ + const auto *bar = findTabBar(dockWidget); + if (!bar) + return {}; + + QList buddies = bar->dockWidgets(); + // Return only other dock widgets associated with dockWidget in a tab bar. + // If dockWidget is alone in a tab bar, return an empty list. + buddies.removeOne(dockWidget); + return buddies; +} + bool QMainWindowLayout::isDockWidgetTabbed(const QDockWidget *dockWidget) const { - for (auto *bar : std::as_const(usedTabBars)) { - // A single dock widget in a tab bar is not considered to be tabbed. - // This is to make sure, we don't drag an empty QDockWidgetGroupWindow around. - // => only consider tab bars with two or more tabs. - if (bar->count() <= 1) - continue; - auto *tabBar = qobject_cast(bar); - Q_ASSERT(tabBar); - const auto dockWidgets = tabBar->dockWidgets(); - if (std::find(dockWidgets.begin(), dockWidgets.end(), dockWidget) != dockWidgets.end()) - return true; - } - return false; + // A single dock widget in a tab bar is not considered to be tabbed. + // This is to make sure, we don't drag an empty QDockWidgetGroupWindow around. + // => only consider tab bars with two or more tabs. + const auto *bar = findTabBar(dockWidget); + return bar && bar->count() > 1; } QTabBar *QMainWindowLayout::getTabBar() -- cgit v1.2.3