From 0709fdcbb5355d6dea2dd2b0e2ef9a635b698bc5 Mon Sep 17 00:00:00 2001 From: Thomas Surrel Date: Fri, 30 Nov 2018 08:44:43 -0500 Subject: [PATCH] Add Ctrl-Tab to switch tabs in chronological order Summary: This patch adds the possibility to navigate between the last accessed tabs with a keyboard shortcut. Test Plan: Open several tabs, use Ctrl-Tab to switch to the previous used one. Reviewers: #konsole, hindenburg Reviewed By: #konsole, hindenburg Subscribers: hindenburg, ngraham, konsole-devel Tags: #konsole Differential Revision: https://phabricator.kde.org/D16884 --- src/ViewContainer.cpp | 65 +++++++++++++++++++++++++++++++++++++++++-- src/ViewContainer.h | 8 ++++++ src/ViewManager.cpp | 29 +++++++++++++++++++ src/ViewManager.h | 6 ++++ 4 files changed, 106 insertions(+), 2 deletions(-) diff --git a/src/ViewContainer.cpp b/src/ViewContainer.cpp index 146a549e1..992fe35d0 100644 --- a/src/ViewContainer.cpp +++ b/src/ViewContainer.cpp @@ -58,7 +58,8 @@ TabbedViewContainer::TabbedViewContainer(ViewManager *connectedViewManager, QWid _newTabButton(new QToolButton()), _closeTabButton(new QToolButton()), _contextMenuTabIndex(-1), - _navigationVisibility(ViewManager::NavigationVisibility::NavigationNotSet) + _navigationVisibility(ViewManager::NavigationVisibility::NavigationNotSet), + _tabHistoryIndex(-1) { setAcceptDrops(true); @@ -89,7 +90,9 @@ TabbedViewContainer::TabbedViewContainer(ViewManager *connectedViewManager, QWid }); connect(this, &TabbedViewContainer::currentChanged, this, [this](int index) { if (index != -1) { - widget(index)->setFocus(); + QWidget *view = widget(index); + view->setFocus(); + updateTabHistory(view); } else { deleteLater(); } @@ -251,6 +254,7 @@ void TabbedViewContainer::addView(QWidget *view, ViewProperties *item, int index } _navigation[view] = item; + _tabHistory.append(view); connect(item, &Konsole::ViewProperties::titleChanged, this, &Konsole::TabbedViewContainer::updateTitle); connect(item, &Konsole::ViewProperties::iconChanged, this, @@ -274,6 +278,7 @@ void TabbedViewContainer::viewDestroyed(QObject *view) void TabbedViewContainer::forgetView(QWidget *view) { _navigation.remove(view); + updateTabHistory(view, true); emit viewRemoved(view); if (count() == 0) { emit empty(this); @@ -307,6 +312,62 @@ void TabbedViewContainer::activatePreviousView() setCurrentIndex(index == 0 ? count() - 1 : index - 1); } +void TabbedViewContainer::activateLastUsedView(bool reverse) +{ + if (_tabHistory.count() <= 1) { + return; + } + + if (_tabHistoryIndex == -1) { + _tabHistoryIndex = reverse ? _tabHistory.count() - 1 : 1; + } else if (reverse) { + if (_tabHistoryIndex == 0) { + _tabHistoryIndex = _tabHistory.count() - 1; + } else { + _tabHistoryIndex--; + } + } else { + if (_tabHistoryIndex >= _tabHistory.count() - 1) { + _tabHistoryIndex = 0; + } else { + _tabHistoryIndex++; + } + } + + int index = indexOf(_tabHistory[_tabHistoryIndex]); + setCurrentIndex(index); +} + +void TabbedViewContainer::keyReleaseEvent(QKeyEvent* event) +{ + if (_tabHistoryIndex != -1 && event->modifiers() == Qt::NoModifier) { + _tabHistoryIndex = -1; + QWidget *active = currentWidget(); + if (active != _tabHistory[0]) { + // Update the tab history now that we have ended the walk-through + updateTabHistory(active); + } + } +} + +void TabbedViewContainer::updateTabHistory(QWidget* view, bool remove) +{ + if (_tabHistoryIndex != -1 && !remove) { + // Do not reorder the tab history while we are walking through it + return; + } + + for (int i = 0; i < _tabHistory.count(); ++i ) { + if (_tabHistory[i] == view) { + _tabHistory.removeAt(i); + if (!remove) { + _tabHistory.prepend(view); + } + break; + } + } +} + ViewProperties *TabbedViewContainer::viewProperties(QWidget *view) const { Q_ASSERT(_navigation.contains(view)); diff --git a/src/ViewContainer.h b/src/ViewContainer.h index a25965d34..27c78b3a9 100644 --- a/src/ViewContainer.h +++ b/src/ViewContainer.h @@ -100,6 +100,9 @@ public: /** Changes the active view to the last view */ void activateLastView(); + /** Changes the active view to the last used view */ + void activateLastUsedView(bool reverse); + void setCssFromFile(const QUrl& url); /** * This enum describes the directions @@ -186,20 +189,25 @@ protected: // close tabs and unregister void closeTerminalTab(int idx); + + void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE; private Q_SLOTS: void viewDestroyed(QObject *view); void konsoleConfigChanged(); private: void forgetView(QWidget *view); + void updateTabHistory(QWidget *view, bool remove = false); QHash _navigation; + QList _tabHistory; ViewManager *_connectedViewManager; QMenu *_contextPopupMenu; QToolButton *_newTabButton; QToolButton *_closeTabButton; int _contextMenuTabIndex; ViewManager::NavigationVisibility _navigationVisibility; + int _tabHistoryIndex; }; diff --git a/src/ViewManager.cpp b/src/ViewManager.cpp index d569ab6ab..cc491eebb 100644 --- a/src/ViewManager.cpp +++ b/src/ViewManager.cpp @@ -132,6 +132,9 @@ void ViewManager::setupActions() QAction *previousViewAction = new QAction(i18nc("@action Shortcut entry", "Previous Tab"), this); QAction *lastViewAction = new QAction(i18nc("@action Shortcut entry", "Switch to Last Tab"), this); + QAction *lastUsedViewAction = new QAction(i18nc("@action Shortcut entry", "Last Used Tabs"), this); + QAction *lastUsedViewReverseAction = new QAction(i18nc("@action Shortcut entry", + "Last Used Tabs (Reverse)"), this); QAction *nextContainerAction = new QAction(i18nc("@action Shortcut entry", "Next View Container"), this); @@ -218,6 +221,8 @@ void ViewManager::setupActions() collection->addAction(QStringLiteral("next-view"), nextViewAction); collection->addAction(QStringLiteral("previous-view"), previousViewAction); collection->addAction(QStringLiteral("last-tab"), lastViewAction); + collection->addAction(QStringLiteral("last-used-tab"), lastUsedViewAction); + collection->addAction(QStringLiteral("last-used-tab-reverse"), lastUsedViewReverseAction); collection->addAction(QStringLiteral("next-container"), nextContainerAction); collection->addAction(QStringLiteral("move-view-left"), moveViewLeftAction); collection->addAction(QStringLiteral("move-view-right"), moveViewRightAction); @@ -275,6 +280,14 @@ void ViewManager::setupActions() connect(lastViewAction, &QAction::triggered, this, &Konsole::ViewManager::lastView); _viewSplitter->addAction(lastViewAction); + + collection->setDefaultShortcut(lastUsedViewAction, Qt::CTRL + Qt::Key_Tab); + connect(lastUsedViewAction, &QAction::triggered, this, &Konsole::ViewManager::lastUsedView); + _viewSplitter->addAction(lastUsedViewAction); + + collection->setDefaultShortcut(lastUsedViewReverseAction, Qt::CTRL + Qt::SHIFT + Qt::Key_Tab); + connect(lastUsedViewReverseAction, &QAction::triggered, this, &Konsole::ViewManager::lastUsedViewReverse); + _viewSplitter->addAction(lastUsedViewReverseAction); } void ViewManager::switchToView(int index) @@ -342,6 +355,20 @@ void ViewManager::lastView() container->activateLastView(); } +void ViewManager::lastUsedView() +{ + TabbedViewContainer *container = _viewSplitter->activeContainer(); + Q_ASSERT(container); + container->activateLastUsedView(false); +} + +void ViewManager::lastUsedViewReverse() +{ + TabbedViewContainer *container = _viewSplitter->activeContainer(); + Q_ASSERT(container); + container->activateLastUsedView(true); +} + void ViewManager::detachActiveView() { // find the currently active view and remove it from its container @@ -716,6 +743,8 @@ void ViewManager::setNavigationMethod(NavigationMethod method) enableAction(QStringLiteral("next-view")); enableAction(QStringLiteral("previous-view")); enableAction(QStringLiteral("last-tab")); + enableAction(QStringLiteral("last-used-tab")); + enableAction(QStringLiteral("last-used-tab-reverse")); enableAction(QStringLiteral("split-view-left-right")); enableAction(QStringLiteral("split-view-top-bottom")); enableAction(QStringLiteral("rename-session")); diff --git a/src/ViewManager.h b/src/ViewManager.h index 2150f3c11..d928aadbe 100644 --- a/src/ViewManager.h +++ b/src/ViewManager.h @@ -344,6 +344,12 @@ private Q_SLOTS: // called when "Switch to last tab" shortcut is activated void lastView(); + // called when "Switch to last used tab" shortcut is activated + void lastUsedView(); + + // called when "Switch to last used tab (reverse)" shortcut is activated + void lastUsedViewReverse(); + // called when "Next View Container" shortcut is activated void nextContainer();