diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -74,6 +74,7 @@ KeyBindingEditor.cpp KeyboardTranslator.cpp KeyboardTranslatorManager.cpp + ListTabbedSessionsPopup.cpp ProcessInfo.cpp Profile.cpp ProfileList.cpp diff --git a/src/ListTabbedSessionsPopup.h b/src/ListTabbedSessionsPopup.h new file mode 100644 --- /dev/null +++ b/src/ListTabbedSessionsPopup.h @@ -0,0 +1,47 @@ +/* + Copyright 2007-2008 by Robert Knight + Copyright 1997,1998 by Lars Doelle + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. +*/ + + +#ifndef LISTTABBEDSESSIONSPOPUP_H +#define LISTTABBEDSESSIONSPOPUP_H + +#include + +class QFocusEvent; +class QShowEvent; +class QKeyEvent; + +namespace Konsole { + +class ListTabbedSessionsPopup : public QListView +{ + Q_OBJECT +public: + ListTabbedSessionsPopup(QWidget *parent); + void focusNext(); + +protected: + void showEvent(QShowEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; +}; + +} +#endif diff --git a/src/ListTabbedSessionsPopup.cpp b/src/ListTabbedSessionsPopup.cpp new file mode 100644 --- /dev/null +++ b/src/ListTabbedSessionsPopup.cpp @@ -0,0 +1,97 @@ +/* + Copyright 2007-2008 by Robert Knight + Copyright 1997,1998 by Lars Doelle + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. +*/ + + +#include "ListTabbedSessionsPopup.h" + +#include "ViewSplitter.h" +#include "ViewContainer.h" + +#include +#include +#include +#include +#include +#include + +namespace Konsole { + +ListTabbedSessionsPopup::ListTabbedSessionsPopup(QWidget *parent) +{ + auto *window = parent->window(); + auto *itemModel = new QStandardItemModel(); + auto *currentSplitter = qobject_cast(parent); + auto *currentTabWidget = currentSplitter->activeContainer(); + + setParent(window); + + const auto count = currentTabWidget->count(); + for (int i = 0; i < count; i++) { + auto item = new QStandardItem(currentTabWidget->tabIcon(i), currentTabWidget->tabText(i)); + itemModel->appendRow(item); + } + + setModel(itemModel); + resize(window->width() / 4, window->height() / 5); + + move( + window->width() / 2 - width() / 2, + window->height() / 2 - height() /2); + + connect(this, &QListView::activated, this, [=](const QModelIndex& idx) { + if (idx.isValid()) { + currentTabWidget->setCurrentIndex(idx.row()); + } + deleteLater(); + itemModel->deleteLater(); + }); +} + +void ListTabbedSessionsPopup::focusNext() +{ + const int currentIdx = (currentIndex().row() + 1) % model()->rowCount(); + setCurrentIndex(model()->index(currentIdx, 0)); +} + +void ListTabbedSessionsPopup::showEvent(QShowEvent *event) +{ + Q_UNUSED(event); + setFocus(Qt::OtherFocusReason); +} + +void ListTabbedSessionsPopup::focusOutEvent(QFocusEvent *event) +{ + Q_UNUSED(event); + model()->deleteLater(); + deleteLater(); +} + +void ListTabbedSessionsPopup::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Escape) + { + model()->deleteLater(); + deleteLater(); + return; + } + QListView::keyPressEvent(event); +} + +} diff --git a/src/ViewManager.h b/src/ViewManager.h --- a/src/ViewManager.h +++ b/src/ViewManager.h @@ -39,7 +39,7 @@ class SessionController; class ViewProperties; class ViewSplitter; -class TabbedViewContainer; +class ListTabbedSessionsPopup; /** * Manages the terminal display widgets in a Konsole window or part. @@ -198,6 +198,10 @@ */ TabbedViewContainer *activeContainer(); + /** Behaves like a Alt + Tab application switcher + * */ + void displayTabChangeModalDialog(); + Q_SIGNALS: /** Emitted when the last view is removed from the view manager */ void empty(); @@ -429,6 +433,7 @@ NewTabBehavior _newTabBehavior; int _managerId; static int lastManagerId; + QPointer _altTabSwitcher; }; } diff --git a/src/ViewManager.cpp b/src/ViewManager.cpp --- a/src/ViewManager.cpp +++ b/src/ViewManager.cpp @@ -46,6 +46,7 @@ #include "ViewSplitter.h" #include "Enumeration.h" #include "ViewContainer.h" +#include "ListTabbedSessionsPopup.h" using namespace Konsole; @@ -286,7 +287,12 @@ connect(lastViewAction, &QAction::triggered, this, &Konsole::ViewManager::lastView); _viewSplitter->addAction(lastViewAction); - collection->setDefaultShortcut(lastUsedViewAction, Qt::CTRL + Qt::Key_Tab); + QAction* contextSwitcher = new QAction(); + collection->setDefaultShortcut(contextSwitcher, Qt::CTRL + Qt::Key_Tab); + connect(contextSwitcher, &QAction::triggered, this, &Konsole::ViewManager::displayTabChangeModalDialog); + _viewSplitter->addAction(contextSwitcher); + + collection->setDefaultShortcut(lastUsedViewAction, Qt::CTRL + Qt::META + Qt::Key_Tab); connect(lastUsedViewAction, &QAction::triggered, this, &Konsole::ViewManager::lastUsedView); _viewSplitter->addAction(lastUsedViewAction); @@ -303,6 +309,17 @@ _viewSplitter->activeContainer()->setCurrentIndex(index); } +void ViewManager::displayTabChangeModalDialog() +{ + if (_altTabSwitcher) { + _altTabSwitcher->focusNext(); + return; + } + + _altTabSwitcher = new ListTabbedSessionsPopup(_viewSplitter); + _altTabSwitcher->show(); +} + void ViewManager::updateDetachViewState() { Q_ASSERT(_actionCollection);