diff --git a/autotests/mainshelltest.cpp b/autotests/mainshelltest.cpp index 2d14ed6985d4314ec67fce85ff04e0b9c870bc14..686abf9d95b05cd35097c386e9bec93adc2f71d0 100644 --- a/autotests/mainshelltest.cpp +++ b/autotests/mainshelltest.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -85,6 +86,7 @@ private slots: void testFileRemembersPagePosition(); void test2FilesError_data(); void test2FilesError(); + void testMiddleButtonCloseUndo(); void testSessionRestore_data(); void testSessionRestore(); @@ -599,5 +601,28 @@ void MainShellTest::testSessionRestore() QCOMPARE( shells.size(), useTabsRestore ? numWindows : paths.size() ); } +void MainShellTest::testMiddleButtonCloseUndo() +{ + const QStringList paths = { QStringLiteral(KDESRCDIR "data/file1.pdf"), QStringLiteral(KDESRCDIR "data/file2.pdf") }; + QString serializedOptions; + serializedOptions = ShellUtils::serializeOptions(false, false, false, false, false, QString(), QString()); + + Okular::Settings::self()->setShellOpenFileInTabs(true); + Okular::Status status = Okular::main(paths, serializedOptions); + QCOMPARE(status, Okular::Success); + Shell *s = findShell(); + QVERIFY(s); + + QCOMPARE(s->m_tabWidget->count(), paths.size()); + // Close a tab using middle key + QWidget *firstTab = s->m_tabWidget->tabBar()->tabButton(0, QTabBar::RightSide); + QVERIFY(firstTab); + QTest::mouseClick(firstTab, Qt::MiddleButton); + QCOMPARE(s->m_tabWidget->count(), paths.size() - 1); + // Undo tab close + s->undoCloseTab(); + QCOMPARE(s->m_tabWidget->count(), paths.size()); +} + QTEST_MAIN( MainShellTest ) #include "mainshelltest.moc" diff --git a/shell/shell.cpp b/shell/shell.cpp index 5a7113fa78467a89f2afaa30b0dec77e47675885..80165687c81a0d8c54a825c76cbcf658bfa32599 100644 --- a/shell/shell.cpp +++ b/shell/shell.cpp @@ -171,6 +171,18 @@ bool Shell::eventFilter(QObject *obj, QEvent *event) dEvent->setAccepted(true); return true; } + + // Handle middle button click events on the tab bar + if (obj == m_tabWidget && event->type() == QEvent::MouseButtonRelease) { + QMouseEvent* mEvent = static_cast(event); + if (mEvent->button() == Qt::MiddleButton) { + int tabIndex = m_tabWidget->tabBar()->tabAt(mEvent->pos()); + if (tabIndex != -1) { + closeTab(tabIndex); + return true; + } + } + } return false; } @@ -362,6 +374,13 @@ void Shell::setupActions() actionCollection()->setDefaultShortcuts(m_prevTabAction, KStandardShortcut::tabPrev()); m_prevTabAction->setEnabled( false ); connect( m_prevTabAction, &QAction::triggered, this, &Shell::activatePrevTab ); + + m_undoCloseTab = actionCollection()->addAction(QStringLiteral("undo-close-tab")); + m_undoCloseTab->setText( i18n("Undo close tab") ); + actionCollection()->setDefaultShortcut(m_undoCloseTab, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_T)); + m_undoCloseTab->setIcon(QIcon::fromTheme(QStringLiteral("edit-undo"))); + m_undoCloseTab->setEnabled( false ); + connect( m_undoCloseTab, &QAction::triggered, this, &Shell::undoCloseTab ); } void Shell::saveProperties(KConfigGroup &group) @@ -627,6 +646,7 @@ void Shell::setActiveTab( int tab ) void Shell::closeTab( int tab ) { KParts::ReadWritePart* const part = m_tabs[tab].part; + QUrl url = part->url(); if( part->closeUrl() && m_tabs.count() > 1 ) { if( part->factory() ) @@ -635,6 +655,8 @@ void Shell::closeTab( int tab ) part->deleteLater(); m_tabs.removeAt( tab ); m_tabWidget->removeTab( tab ); + m_undoCloseTab->setEnabled( true ); + m_closedTabUrls.append( url ); if( m_tabWidget->count() == 1 ) { @@ -750,6 +772,23 @@ void Shell::activatePrevTab() setActiveTab( prevTab ); } +void Shell::undoCloseTab() +{ + if ( m_closedTabUrls.isEmpty() ) + { + return; + } + + const QUrl lastTabUrl = m_closedTabUrls.takeLast(); + + if ( m_closedTabUrls.isEmpty() ) + { + m_undoCloseTab->setEnabled(false); + } + + openUrl(lastTabUrl); +} + void Shell::setTabIcon( const QMimeType& mimeType ) { int i = findTabIndex( sender() ); diff --git a/shell/shell.h b/shell/shell.h index 5b8e6cfe3daab2eee1211998c333b3238902a520..10573345ec6aef9609c7dd5513295a6479b6ca02 100644 --- a/shell/shell.h +++ b/shell/shell.h @@ -21,6 +21,7 @@ #include #include #include +#include #include // krazy:exclude=includes @@ -124,6 +125,7 @@ private Q_SLOTS: void closeTab( int tab ); void activateNextTab(); void activatePrevTab(); + void undoCloseTab(); void moveTabData( int from, int to ); void slotFitWindowToPage( const QSize& pageViewSize, const QSize& pageSize ); @@ -168,8 +170,10 @@ private: bool closeEnabled; }; QList m_tabs; + QList m_closedTabUrls; QAction* m_nextTabAction; QAction* m_prevTabAction; + QAction* m_undoCloseTab; #ifndef Q_OS_WIN KActivities::ResourceInstance* m_activityResource; diff --git a/shell/shell.rc b/shell/shell.rc index 93fbc417588312792bab39b693c65e5d414c87c6..4cfa7fd62afe244ac31de36669374017bca7708c 100644 --- a/shell/shell.rc +++ b/shell/shell.rc @@ -1,10 +1,11 @@ - + +