From a1cd9a62d1d68d74c059d12c4f2e90b514f36206 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 3 Dec 2013 16:24:23 +0100 Subject: [PATCH] Fix QDockAreaLayoutInfo::updateTabBar() to handle rearranged tabs. Search tabs by id instead of assuming they are in order of the dock widgets. Previously, the algorithm got confused if QTabBar::moveTabs() was called on the QTabBar. Task-number: QTBUG-35148 Change-Id: I5946f0e865623049ee243ff99be07d7015288c15 --- src/widgets/widgets/qdockarealayout.cpp | 62 ++++++++++------------ .../widgets/qmainwindow/tst_qmainwindow.cpp | 26 +++++++++ 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 72a463b..832c247 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -1117,17 +1117,23 @@ void QDockAreaLayoutInfo::setCurrentTab(QWidget *widget) setCurrentTabId(reinterpret_cast(widget)); } +static inline int indexOfTabId(const QTabBar *tb, quintptr id) +{ + const int tabCount = tb->count(); + for (int i = 0; i < tabCount; ++i) { + if (qvariant_cast(tb->tabData(i)) == id) + return i; + } + return -1; +} + void QDockAreaLayoutInfo::setCurrentTabId(quintptr id) { if (!tabbed || tabBar == 0) return; - - for (int i = 0; i < tabBar->count(); ++i) { - if (qvariant_cast(tabBar->tabData(i)) == id) { - tabBar->setCurrentIndex(i); - return; - } - } + const int i = indexOfTabId(tabBar, id); + if (i != -1) + tabBar->setCurrentIndex(i); } #endif // QT_NO_TABBAR @@ -2099,7 +2105,7 @@ bool QDockAreaLayoutInfo::updateTabBar() const bool blocked = tabBar->blockSignals(true); bool gap = false; - int tab_idx = 0; + QVector seenTabs(tabBar->count(), false); for (int i = 0; i < item_list.count(); ++i) { const QDockAreaLayoutItem &item = item_list.at(i); if (item.skip()) @@ -2113,39 +2119,29 @@ bool QDockAreaLayoutInfo::updateTabBar() const QDockWidget *dw = qobject_cast(item.widgetItem->widget()); QString title = dw->d_func()->fixedWindowTitle; - quintptr id = tabId(item); - if (tab_idx == tabBar->count()) { - tabBar->insertTab(tab_idx, title); -#ifndef QT_NO_TOOLTIP - tabBar->setTabToolTip(tab_idx, title); -#endif - tabBar->setTabData(tab_idx, id); - } else if (qvariant_cast(tabBar->tabData(tab_idx)) != id) { - if (tab_idx + 1 < tabBar->count() - && qvariant_cast(tabBar->tabData(tab_idx + 1)) == id) - tabBar->removeTab(tab_idx); - else { - tabBar->insertTab(tab_idx, title); + const quintptr id = tabId(item); + const int tabIdx = indexOfTabId(tabBar, id); // Match the tab by id in case they were rearranged by QTabBar::moveTab() + if (tabIdx >= 0) { + seenTabs[tabIdx] = true; + if (title != tabBar->tabText(tabIdx)) { + tabBar->setTabText(tabIdx, title); #ifndef QT_NO_TOOLTIP - tabBar->setTabToolTip(tab_idx, title); + tabBar->setTabToolTip(tabIdx, title); #endif - tabBar->setTabData(tab_idx, id); } - } - - if (title != tabBar->tabText(tab_idx)) { - tabBar->setTabText(tab_idx, title); + } else { + const int tabPos = tabBar->count(); + tabBar->addTab(title); #ifndef QT_NO_TOOLTIP - tabBar->setTabToolTip(tab_idx, title); + tabBar->setTabToolTip(tabPos, title); #endif + tabBar->setTabData(tabPos, id); } - - ++tab_idx; } - while (tab_idx < tabBar->count()) { - tabBar->removeTab(tab_idx); - } + for (int i = seenTabs.size() - 1; i >= 0; --i) + if (!seenTabs.at(i)) + tabBar->removeTab(i); tabBar->blockSignals(blocked); diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp index e5a9b57..132310e 100644 --- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp +++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp @@ -152,6 +152,7 @@ private slots: void toggleUnifiedTitleAndToolBarOnMac(); #endif void QTBUG21378_animationFinished(); + void QTBUG35148_rearrangeTabbedDockWidgets(); }; // Testing get/set functions @@ -1875,5 +1876,30 @@ void tst_QMainWindow::QTBUG21378_animationFinished() delete mwClickTimer; QVERIFY(true); } + +void tst_QMainWindow::QTBUG35148_rearrangeTabbedDockWidgets() +{ + QMainWindow w; + w.resize(800, 600); + const QString title1 = QStringLiteral("DockWidget1"); + const QString title2 = QStringLiteral("DockWidget2"); + QDockWidget *dw1 = new QDockWidget(title1, &w); + QDockWidget *dw2 = new QDockWidget(title2, &w); + w.addDockWidget(Qt::LeftDockWidgetArea, dw1); + w.addDockWidget(Qt::LeftDockWidgetArea, dw2); + w.tabifyDockWidget(dw1, dw2); + const QList tabList = w.findChildren(); + QVERIFY(!tabList.isEmpty()); + QTabBar *tabBar = tabList.front(); + QCOMPARE(tabBar->tabText(0), title1); + QCOMPARE(tabBar->currentIndex(), 1); // Index is that of QDockWidget added last. + tabBar->moveTab(0, 1); // Flip tabs: DockWidget2 is now at tab 0. + QCOMPARE(tabBar->tabText(0), title2); + QCOMPARE(tabBar->currentIndex(), 0); + tabBar->setCurrentIndex(1); // Switch, causing relayout of tabbar. + tabBar->setCurrentIndex(0); + QCOMPARE(tabBar->tabText(0), title2); // Ensure order is still preserved +} + QTEST_MAIN(tst_QMainWindow) #include "tst_qmainwindow.moc" -- 1.8.3.msysgit.0