diff --git a/src/ViewContainer.h b/src/ViewContainer.h --- a/src/ViewContainer.h +++ b/src/ViewContainer.h @@ -100,6 +100,9 @@ /** 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 @@ // 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/ViewContainer.cpp b/src/ViewContainer.cpp --- a/src/ViewContainer.cpp +++ b/src/ViewContainer.cpp @@ -58,7 +58,8 @@ _newTabButton(new QToolButton()), _closeTabButton(new QToolButton()), _contextMenuTabIndex(-1), - _navigationVisibility(ViewManager::NavigationVisibility::NavigationNotSet) + _navigationVisibility(ViewManager::NavigationVisibility::NavigationNotSet), + _tabHistoryIndex(-1) { setAcceptDrops(true); @@ -89,7 +90,9 @@ }); 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 @@ } _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::forgetView(QWidget *view) { _navigation.remove(view); + updateTabHistory(view, true); emit viewRemoved(view); if (count() == 0) { emit empty(this); @@ -307,6 +312,62 @@ 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/ViewManager.h b/src/ViewManager.h --- a/src/ViewManager.h +++ b/src/ViewManager.h @@ -344,6 +344,12 @@ // 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(); diff --git a/src/ViewManager.cpp b/src/ViewManager.cpp --- a/src/ViewManager.cpp +++ b/src/ViewManager.cpp @@ -132,6 +132,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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"));