diff options
| -rw-r--r-- | src/dolphintabpage.cpp | 42 | ||||
| -rw-r--r-- | src/dolphintabpage.h | 9 | ||||
| -rw-r--r-- | src/tests/dolphinmainwindowtest.cpp | 48 |
3 files changed, 98 insertions, 1 deletions
diff --git a/src/dolphintabpage.cpp b/src/dolphintabpage.cpp index ca47130c0..f4922bf70 100644 --- a/src/dolphintabpage.cpp +++ b/src/dolphintabpage.cpp @@ -60,7 +60,13 @@ DolphinTabPage::DolphinTabPage(const QUrl &primaryUrl, const QUrl &secondaryUrl, m_secondaryViewContainer->show(); } + // DolphinView::setActive(true) calls setFocus() then emits activated(). + // activated() is connected to slotViewActivated() which toggles + // m_primaryViewActive — correct for user-initiated pane switches, but + // wrong here during construction. Disconnect to prevent the spurious toggle. + disconnectViewActivatedSignals(); m_primaryViewContainer->setActive(true); + connectViewActivatedSignals(); } bool DolphinTabPage::primaryViewActive() const @@ -364,12 +370,22 @@ void DolphinTabPage::restoreState(const QByteArray &state) } stream >> m_primaryViewActive; + // DolphinView::setActive(true) calls setFocus() then emits activated(). + // activated() is connected to slotViewActivated() which toggles + // m_primaryViewActive — correct for user-initiated pane switches, but + // wrong here during session restore. Disconnect to prevent the spurious toggle. + disconnectViewActivatedSignals(); if (m_primaryViewActive) { + if (m_splitViewEnabled) { + m_secondaryViewContainer->setActive(false); + } m_primaryViewContainer->setActive(true); } else { Q_ASSERT(m_splitViewEnabled); + m_primaryViewContainer->setActive(false); m_secondaryViewContainer->setActive(true); } + connectViewActivatedSignals(); QByteArray splitterState; stream >> splitterState; @@ -393,8 +409,16 @@ void DolphinTabPage::setActive(bool active) // we should bypass changing active view in split mode m_active = !m_splitViewEnabled; } - // we want view to fire activated when goes from false to true + // DolphinView::setActive(true) calls setFocus() then emits activated(). + // activated() is connected to slotViewActivated() which toggles + // m_primaryViewActive — correct for user-initiated pane switches, but + // wrong here during tab switch. Disconnect to prevent the spurious toggle. + disconnectViewActivatedSignals(); + if (active && m_splitViewEnabled) { + inactiveViewContainer()->setActive(false); + } activeViewContainer()->setActive(active); + connectViewActivatedSignals(); } void DolphinTabPage::setCustomLabel(const QString &label) @@ -518,6 +542,22 @@ void DolphinTabPage::switchActiveView() } } +void DolphinTabPage::connectViewActivatedSignals() +{ + connect(m_primaryViewContainer->view(), &DolphinView::activated, this, &DolphinTabPage::slotViewActivated); + if (m_secondaryViewContainer) { + connect(m_secondaryViewContainer->view(), &DolphinView::activated, this, &DolphinTabPage::slotViewActivated); + } +} + +void DolphinTabPage::disconnectViewActivatedSignals() +{ + disconnect(m_primaryViewContainer->view(), &DolphinView::activated, this, &DolphinTabPage::slotViewActivated); + if (m_secondaryViewContainer) { + disconnect(m_secondaryViewContainer->view(), &DolphinView::activated, this, &DolphinTabPage::slotViewActivated); + } +} + DolphinViewContainer *DolphinTabPage::createViewContainer(const QUrl &url) const { DolphinViewContainer *container = new DolphinViewContainer(url, m_splitter); diff --git a/src/dolphintabpage.h b/src/dolphintabpage.h index b6135d360..421496ce9 100644 --- a/src/dolphintabpage.h +++ b/src/dolphintabpage.h @@ -204,6 +204,15 @@ private: */ void startExpandViewAnimation(DolphinViewContainer *expandingContainer); + /** + * Connect/disconnect DolphinView::activated → slotViewActivated for all + * current view containers. Used to suppress the signal during programmatic + * activation (tab switch, construction, session restore) so that + * slotViewActivated does not spuriously toggle m_primaryViewActive. + */ + void connectViewActivatedSignals(); + void disconnectViewActivatedSignals(); + private: DolphinTabPageSplitter *m_splitter; diff --git a/src/tests/dolphinmainwindowtest.cpp b/src/tests/dolphinmainwindowtest.cpp index 26bb52a8e..a1727afdb 100644 --- a/src/tests/dolphinmainwindowtest.cpp +++ b/src/tests/dolphinmainwindowtest.cpp @@ -71,6 +71,7 @@ private Q_SLOTS: void testThumbnailAfterRename(); void testViewModeAfterDynamicView(); void testActivationAndTabTitleAfterRenameOpeningFolder(); + void testActiveViewAfterTabSwitchWithSplitView(); void cleanupTestCase(); private: @@ -1292,6 +1293,53 @@ void DolphinMainWindowTest::testActivationAndTabTitleAfterRenameOpeningFolder() QCOMPARE(tabWidget->tabText(1), expectedNewTab1Title); } +// Test that switching tabs does not spuriously toggle which split-view pane is active. +// Regression test for the bug where DolphinTabPage::setActive(true) during tab switch +// caused DolphinView::activated() to reach slotViewActivated(), which toggled +// m_primaryViewActive and connected MainWindow signals to the wrong view container. +void DolphinMainWindowTest::testActiveViewAfterTabSwitchWithSplitView() +{ + m_mainWindow->openDirectories({QUrl::fromLocalFile(QDir::homePath())}, false); + m_mainWindow->show(); + QVERIFY(QTest::qWaitForWindowExposed(m_mainWindow.data())); + QVERIFY(m_mainWindow->isVisible()); + + auto tabWidget = m_mainWindow->findChild<DolphinTabWidget *>("tabWidget"); + QVERIFY(tabWidget); + + // Enable split view on the first tab. After this, the secondary (right) pane + // becomes active via slotViewActivated(), so primaryViewActive() is false. + m_mainWindow->actionCollection()->action(QStringLiteral("split_view"))->trigger(); + QVERIFY(tabWidget->currentTabPage()->splitViewEnabled()); + QVERIFY(!tabWidget->currentTabPage()->primaryViewActive()); + auto firstTabPage = tabWidget->currentTabPage(); + auto firstTabSecondary = firstTabPage->secondaryViewContainer(); + QVERIFY(firstTabSecondary->isActive()); + + // Open a second tab and switch to it. + tabWidget->openNewActivatedTab(QUrl::fromLocalFile(QDir::homePath())); + QCOMPARE(tabWidget->count(), 2); + QCOMPARE(tabWidget->currentIndex(), 1); + + // Spy on activeViewChanged to count emissions during the tab switch back. + QSignalSpy activeViewChangedSpy(tabWidget, &DolphinTabWidget::activeViewChanged); + + // Switch back to the first tab. + tabWidget->setCurrentIndex(0); + QCOMPARE(tabWidget->currentTabPage(), firstTabPage); + + // activeViewChanged must be emitted exactly once — by currentTabChanged itself. + // A spurious second emission would indicate slotViewActivated() fired during + // the programmatic setActive(true) and toggled m_primaryViewActive. + QCOMPARE(activeViewChangedSpy.count(), 1); + + // The secondary pane must still be the designated active one. + QVERIFY(!firstTabPage->primaryViewActive()); + QCOMPARE(firstTabPage->activeViewContainer(), firstTabSecondary); + QVERIFY(firstTabSecondary->isActive()); + QVERIFY(!firstTabPage->primaryViewContainer()->isActive()); +} + void DolphinMainWindowTest::cleanupTestCase() { m_mainWindow->showNormal(); |
