diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index a91128ba095..30176edd49a 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -1123,21 +1123,8 @@ void QMainWindow::tabifyDockWidget(QDockWidget *first, QDockWidget *second) QList QMainWindow::tabifiedDockWidgets(QDockWidget *dockwidget) const { - QList ret; - const QDockAreaLayoutInfo *info = d_func()->layout->layoutState.dockAreaLayout.info(dockwidget); - if (info && info->tabbed && info->tabBar) { - for(int i = 0; i < info->item_list.size(); ++i) { - const QDockAreaLayoutItem &item = info->item_list.at(i); - if (item.widgetItem) { - if (QDockWidget *dock = qobject_cast(item.widgetItem->widget())) { - if (dock != dockwidget) { - ret += dock; - } - } - } - } - } - return ret; + Q_D(const QMainWindow); + return d->layout ? d->layout->tabifiedDockWidgets(dockwidget) : QList(); } #endif // QT_CONFIG(tabbar) diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 3933f2a7cd3..e17fa28b832 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() diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h index 48e4d472a5c..25517ccb418 100644 --- a/src/widgets/widgets/qmainwindowlayout_p.h +++ b/src/widgets/widgets/qmainwindowlayout_p.h @@ -448,6 +448,7 @@ public: bool restoreState(QDataStream &stream, const QMainWindowLayoutState &oldState); }; +class QMainWindowTabBar; class Q_AUTOTEST_EXPORT QMainWindowLayout : public QLayout, public QMainWindowLayoutSeparatorHelper @@ -575,7 +576,11 @@ public: #if QT_CONFIG(dockwidget) QPointer currentHoveredFloat; // set when dragging over a floating dock widget void setCurrentHoveredFloat(QDockWidgetGroupWindow *w); +#if QT_CONFIG(tabbar) bool isDockWidgetTabbed(const QDockWidget *dockWidget) const; + QList tabifiedDockWidgets(const QDockWidget *dockWidget) const; + QMainWindowTabBar *findTabBar(const QDockWidget *dockWidget) const; +#endif #endif bool isInApplyState = false; diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp index fc48deec0bb..b24437c6d67 100644 --- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp +++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp @@ -698,6 +698,9 @@ void tst_QDockWidget::updateTabBarOnVisibilityChanged() mw.tabifyDockWidget(dw1, dw2); mw.tabifyDockWidget(dw2, dw3); + const auto list1 = QList{dw1, dw2, dw3}; + QCOMPARE(mw.tabifiedDockWidgets(dw0), list1); + QTabBar *tabBar = mw.findChild(); QVERIFY(tabBar); tabBar->setCurrentIndex(2); @@ -711,6 +714,8 @@ void tst_QDockWidget::updateTabBarOnVisibilityChanged() dw1->hide(); QTRY_COMPARE(tabBar->count(), 2); QCOMPARE(tabBar->currentIndex(), 0); + + QCOMPARE(mw.tabifiedDockWidgets(dw2), {dw3}); } Q_DECLARE_METATYPE(Qt::DockWidgetArea) @@ -1438,6 +1443,9 @@ void tst_QDockWidget::floatingTabs() createFloatingTabs(mainWindow, cent, d1, d2, path1, path2); std::unique_ptr up_mainWindow(mainWindow); + QCOMPARE(mainWindow->tabifiedDockWidgets(d1), {d2}); + QCOMPARE(mainWindow->tabifiedDockWidgets(d2), {d1}); + /* * unplug both dockwidgets, resize them and plug them into a joint floating tab * expected behavior: QDOckWidgetGroupWindow with both widgets is created @@ -1515,6 +1523,9 @@ void tst_QDockWidget::floatingTabs() // Paths must be identical QTRY_COMPARE(layout->layoutState.indexOf(d1), path1); QTRY_COMPARE(layout->layoutState.indexOf(d2), path2); + + QCOMPARE(mainWindow->tabifiedDockWidgets(d1), {}); + QCOMPARE(mainWindow->tabifiedDockWidgets(d2), {}); #else QSKIP("test requires -developer-build option"); #endif // QT_BUILD_INTERNAL