Commit 60f1fa79 authored by Bob Bai's avatar Bob Bai Committed by Nate Graham
Browse files

Enable closing a tab by middle click

Some discussions at https://phabricator.kde.org/D25484.

This MR adds:

* mouse middle button event handler for closing a tab
* an `undo close tab` action

Test plan:

1. Compile and install.
2. Enable `Open new files in tabs`.
3. Open two documents. They should be opened in two tabs in the same window.
4. Middle click one of the tabs. It should be closed.
5. Choose `File`-`Undo close tab`. The closed tab should be reopened.
6. Middle click one of the tabs. It should be closed.
7. Press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>T</kbd>. The closed tab should be reopened.
parent 4c46aabe
Pipeline #12869 passed with stage
in 10 minutes and 49 seconds
......@@ -12,6 +12,7 @@
#include <qprintdialog.h>
#include <qwidget.h>
#include <qtabwidget.h>
#include <QTabBar>
#include <QStandardPaths>
#include <kconfiggroup.h>
#include <klineedit.h>
......@@ -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"
......@@ -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<QMouseEvent*>(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() );
......
......@@ -21,6 +21,7 @@
#include <QMimeType>
#include <QMimeDatabase>
#include <QAction>
#include <QList>
#include <QtDBus> // 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<TabState> m_tabs;
QList<QUrl> m_closedTabUrls;
QAction* m_nextTabAction;
QAction* m_prevTabAction;
QAction* m_undoCloseTab;
#ifndef Q_OS_WIN
KActivities::ResourceInstance* m_activityResource;
......
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
<kpartgui version="7" name="okular_shell" >
<kpartgui version="8" name="okular_shell" >
<MenuBar>
<Menu name="file" >
<DefineGroup append="open_merge" name="file_open" />
<DefineGroup append="save_merge" name="file_save" />
<DefineGroup append="print_merge" name="file_print" />
<Action name="undo-close-tab" group="file_open" />
</Menu>
<!--Menu name="view" >
<Action name="fullscreen" />
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment