diff --git a/desktop/konsoleui.rc b/desktop/konsoleui.rc
--- a/desktop/konsoleui.rc
+++ b/desktop/konsoleui.rc
@@ -25,6 +25,7 @@
+
diff --git a/src/Application.h b/src/Application.h
--- a/src/Application.h
+++ b/src/Application.h
@@ -25,6 +25,7 @@
// Konsole
#include "Profile.h"
+#include "ViewSplitter.h"
namespace Konsole {
class MainWindow;
@@ -68,7 +69,7 @@
private Q_SLOTS:
void createWindow(const Profile::Ptr &profile, const QString &directory);
- void detachView(Session *session);
+ void detachTerminals(ViewSplitter *splitter, QHash sessionsMap);
void toggleBackgroundInstance();
diff --git a/src/Application.cpp b/src/Application.cpp
--- a/src/Application.cpp
+++ b/src/Application.cpp
@@ -43,6 +43,8 @@
#include "ViewManager.h"
#include "SessionController.h"
#include "WindowSystemInfo.h"
+#include "ViewContainer.h"
+#include "TerminalDisplay.h"
using namespace Konsole;
@@ -168,32 +170,37 @@
connect(window, &Konsole::MainWindow::newWindowRequest, this,
&Konsole::Application::createWindow);
- connect(window, &Konsole::MainWindow::viewDetached, this, &Konsole::Application::detachView);
+ connect(window, &Konsole::MainWindow::terminalsDetached, this, &Konsole::Application::detachTerminals);
return window;
}
void Application::createWindow(const Profile::Ptr &profile, const QString &directory)
{
MainWindow *window = newMainWindow();
- ViewManager *viewManager = window->viewManager();
- window->createSession(viewManager->activeContainer(), profile, directory);
+ window->createSession(profile, directory);
finalizeNewMainWindow(window);
}
-void Application::detachView(Session *session)
-{
- MainWindow *currentWindow = qobject_cast(sender());
- MainWindow *window = newMainWindow();
+template
+void detach(Application *application, QObject *sender, const T&& functor) {
+ MainWindow *currentWindow = qobject_cast(sender);
+ MainWindow *window = application->newMainWindow();
ViewManager *manager = window->viewManager();
-
- manager->createView(manager->activeContainer(), session);
-
- // Since user is dragging and dropping, move dnd window to where
- // the user has the cursor (correct multiple monitor setups).
- window->move(QCursor::pos());
- window->resize(currentWindow->geometry().width(), currentWindow->geometry().height());
+ functor(manager);
window->show();
+ window->setGeometry(currentWindow->geometry());
+ window->move(QCursor::pos());
+}
+
+void Application::detachTerminals(ViewSplitter *splitter, QHash sessionsMap)
+{
+ detach(this, sender(), [=](ViewManager *manager) {
+ foreach(TerminalDisplay* terminal, splitter->getTerminalDisplays()) {
+ manager->attachView(terminal, sessionsMap[terminal]);
+ }
+ manager->activeContainer()->addSplitter(splitter);
+ });
}
int Application::newInstance()
@@ -228,8 +235,7 @@
Profile::Ptr newProfile = processProfileChangeArgs(baseProfile);
// create new session
- ViewManager *viewManager = window->viewManager();
- Session *session = window->createSession(viewManager->activeContainer(), newProfile, QString());
+ Session *session = window->createSession(newProfile, QString());
if (m_parser->isSet(QStringLiteral("noclose"))) {
session->setAutoClose(false);
@@ -376,8 +382,7 @@
// Create the new session
Profile::Ptr theProfile = shouldUseNewProfile ? newProfile : baseProfile;
- ViewManager *viewManager = window->viewManager();
- Session *session = window->createSession(viewManager->activeContainer(), theProfile, QString());
+ Session *session = window->createSession(theProfile, QString());
if (m_parser->isSet(QStringLiteral("noclose"))) {
session->setAutoClose(false);
diff --git a/src/DetachableTabBar.h b/src/DetachableTabBar.h
--- a/src/DetachableTabBar.h
+++ b/src/DetachableTabBar.h
@@ -38,7 +38,6 @@
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent*event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
- bool droppedContainerIsNotThis(const QPoint& currentPos) const;
private:
DragType dragType;
diff --git a/src/DetachableTabBar.cpp b/src/DetachableTabBar.cpp
--- a/src/DetachableTabBar.cpp
+++ b/src/DetachableTabBar.cpp
@@ -31,18 +31,6 @@
_originalCursor(cursor())
{}
-bool DetachableTabBar::droppedContainerIsNotThis(const QPoint& currentPos) const
-{
- for(const auto dropWidget : _containers) {
- if (dropWidget->rect().contains(dropWidget->mapFromGlobal(currentPos))) {
- if (dropWidget != parent()) {
- return true;
- }
- }
- }
- return false;
-}
-
void DetachableTabBar::mousePressEvent(QMouseEvent *event)
{
QTabBar::mousePressEvent(event);
@@ -55,16 +43,9 @@
auto widgetAtPos = qApp->topLevelAt(event->globalPos());
if (widgetAtPos != nullptr) {
if (window() == widgetAtPos->window()) {
- if (droppedContainerIsNotThis(event->globalPos())) {
- if (dragType != DragType::WINDOW) {
- dragType = DragType::WINDOW;
- setCursor(QCursor(Qt::DragMoveCursor));
- }
- } else {
- if (dragType != DragType::NONE) {
- dragType = DragType::NONE;
- setCursor(_originalCursor);
- }
+ if (dragType != DragType::NONE) {
+ dragType = DragType::NONE;
+ setCursor(_originalCursor);
}
} else {
if (dragType != DragType::WINDOW) {
@@ -99,14 +80,9 @@
emit detachTab(currentIndex());
}
} else if (window() != widgetAtPos->window()) {
- // splits have a tendency to break, forbid to detach if split and it's the last tab.
if (_containers.size() == 1 || count() > 1) {
emit moveTabToWindow(currentIndex(), widgetAtPos);
}
- } else if (droppedContainerIsNotThis(event->globalPos())){
- if (count() != 1) {
- emit moveTabToWindow(currentIndex(), widgetAtPos);
- }
}
}
diff --git a/src/MainWindow.h b/src/MainWindow.h
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -29,6 +29,7 @@
// Konsole
#include "Profile.h"
+#include "ViewSplitter.h"
class QAction;
class KActionMenu;
@@ -74,21 +75,19 @@
/**
* Create a new session.
*
- * @param tabWidget where the new widget should be added.
* @param profile The profile to use to create the new session.
* @param directory Initial working directory for the new session or empty
* if the default working directory associated with the profile should be used.
*/
- Session *createSession(TabbedViewContainer *tabWidget, Profile::Ptr profile, const QString &directory);
+ Session *createSession(Profile::Ptr profile, const QString &directory);
/**
* create a new SSH session.
*
- * @param tabWidget where the new widget should be added.
* @param profile The profile to use to create the new session.
* @param url the URL representing the new SSH connection
*/
- Session *createSSHSession(TabbedViewContainer *tabWidget, Profile::Ptr profile, const QUrl &url);
+ Session *createSSHSession(Profile::Ptr profile, const QUrl &url);
/**
* Helper method to make this window get input focus
@@ -125,7 +124,7 @@
/**
* Emitted when a view for one session is detached from this window
*/
- void viewDetached(Session *session);
+ void terminalsDetached(ViewSplitter *splitter, QHash sessionsMap);
protected:
// Reimplemented for internal reasons.
@@ -143,14 +142,14 @@
bool focusNextPrevChild(bool next) Q_DECL_OVERRIDE;
private Q_SLOTS:
- void newTab(TabbedViewContainer *tabWidget);
+ void newTab();
void cloneTab();
void newWindow();
void showManageProfilesDialog();
void activateMenuBar();
void showSettingsDialog(const bool showProfilePage = false);
void showShortcutsDialog();
- void newFromProfile(TabbedViewContainer *tabWidget, const Profile::Ptr &profile);
+ void newFromProfile(const Profile::Ptr &profile);
void activeViewChanged(SessionController *controller);
void disconnectController(SessionController *controller);
void activeViewTitleChanged(ViewProperties *);
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -114,8 +114,8 @@
this, &Konsole::MainWindow::newFromProfile);
connect(_viewManager, &Konsole::ViewManager::newViewRequest,
this, &Konsole::MainWindow::newTab);
- connect(_viewManager, &Konsole::ViewManager::viewDetached, this,
- &Konsole::MainWindow::viewDetached);
+ connect(_viewManager, &Konsole::ViewManager::terminalsDetached, this,
+ &Konsole::MainWindow::terminalsDetached);
setCentralWidget(_viewManager->widget());
@@ -230,6 +230,10 @@
if (controller->isValid()) {
guiFactory()->removeClient(controller);
}
+
+ if (_pluggedController == controller) {
+ _pluggedController = nullptr;
+ }
}
void MainWindow::activeViewChanged(SessionController *controller)
@@ -315,7 +319,7 @@
collection->setShortcutsConfigurable(_newTabMenuAction, true);
_newTabMenuAction->setAutoRepeat(false);
connect(_newTabMenuAction, &KActionMenu::triggered,
- this, [this] { newTab(_viewManager->activeContainer());});
+ this, [this] { newTab(); });
collection->addAction(QStringLiteral("new-tab"), _newTabMenuAction);
collection->setShortcutsConfigurable(_newTabMenuAction, true);
@@ -389,7 +393,7 @@
profileListChanged(list->actions());
connect(list, &Konsole::ProfileList::profileSelected, this,
- [this](const Profile::Ptr &profile) { newFromProfile(_viewManager->activeContainer(), profile);});
+ [this](const Profile::Ptr &profile) { newFromProfile(profile);});
connect(list, &Konsole::ProfileList::actionsChanged, this,
&Konsole::MainWindow::profileListChanged);
@@ -458,17 +462,17 @@
Q_FOREACH (const auto &url, urls) {
if (url.isLocalFile()) {
- createSession(_viewManager->activeContainer(), defaultProfile, url.path());
+ createSession(defaultProfile, url.path());
} else if (url.scheme() == QLatin1String("ssh")) {
- createSSHSession(_viewManager->activeContainer(), defaultProfile, url);
+ createSSHSession(defaultProfile, url);
}
}
}
-void MainWindow::newTab(TabbedViewContainer *tabWidget)
+void MainWindow::newTab()
{
Profile::Ptr defaultProfile = ProfileManager::instance()->defaultProfile();
- createSession(tabWidget, defaultProfile, activeSessionDir());
+ createSession(defaultProfile, activeSessionDir());
}
void MainWindow::cloneTab()
@@ -478,15 +482,15 @@
Session *session = _pluggedController->session();
Profile::Ptr profile = SessionManager::instance()->sessionProfile(session);
if (profile) {
- createSession(_viewManager->activeContainer(), profile, activeSessionDir());
+ createSession(profile, activeSessionDir());
} else {
// something must be wrong: every session should be associated with profile
Q_ASSERT(false);
- newTab(_viewManager->activeContainer());
+ newTab();
}
}
-Session *MainWindow::createSession(TabbedViewContainer *tabWidget, Profile::Ptr profile, const QString &directory)
+Session *MainWindow::createSession(Profile::Ptr profile, const QString &directory)
{
if (!profile) {
profile = ProfileManager::instance()->defaultProfile();
@@ -504,12 +508,12 @@
// doesn't suffer a change in terminal size right after the session
// starts. Some applications such as GNU Screen and Midnight Commander
// don't like this happening
- _viewManager->createView(tabWidget, session);
-
+ auto newView = _viewManager->createView(session);
+ _viewManager->activeContainer()->addView(newView);
return session;
}
-Session *MainWindow::createSSHSession(TabbedViewContainer *tabWidget, Profile::Ptr profile, const QUrl &url)
+Session *MainWindow::createSSHSession(Profile::Ptr profile, const QUrl &url)
{
if (!profile) {
profile = ProfileManager::instance()->defaultProfile();
@@ -534,8 +538,8 @@
// doesn't suffer a change in terminal size right after the session
// starts. some applications such as GNU Screen and Midnight Commander
// don't like this happening
- _viewManager->createView(tabWidget, session);
-
+ auto newView = _viewManager->createView(session);
+ _viewManager->activeContainer()->addView(newView);
return session;
}
@@ -708,9 +712,9 @@
}
}
-void MainWindow::newFromProfile(TabbedViewContainer *tabWidget, const Profile::Ptr &profile)
+void MainWindow::newFromProfile(const Profile::Ptr &profile)
{
- createSession(tabWidget, profile, activeSessionDir());
+ createSession(profile, activeSessionDir());
}
void MainWindow::showManageProfilesDialog()
@@ -860,20 +864,20 @@
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
- if (obj == _pluggedController->view()) {
+ if (!_pluggedController.isNull() && obj == _pluggedController->view()) {
switch(event->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
switch(static_cast(event)->button()) {
- case Qt::ForwardButton:
- triggerAction(QStringLiteral("next-view"));
- break;
- case Qt::BackButton:
- triggerAction(QStringLiteral("previous-view"));
- break;
- default: ;
+ case Qt::ForwardButton:
+ triggerAction(QStringLiteral("next-view"));
+ break;
+ case Qt::BackButton:
+ triggerAction(QStringLiteral("previous-view"));
+ break;
+ default: ;
}
- default: ;
+ default: ;
}
}
diff --git a/src/Part.cpp b/src/Part.cpp
--- a/src/Part.cpp
+++ b/src/Part.cpp
@@ -213,7 +213,8 @@
session->setInitialWorkingDirectory(directory);
}
- _viewManager->createView(_viewManager->activeContainer(), session);
+ auto newView = _viewManager->createView(session);
+ _viewManager->activeContainer()->addView(newView);
}
void Part::activeViewChanged(SessionController *controller)
diff --git a/src/SessionController.cpp b/src/SessionController.cpp
--- a/src/SessionController.cpp
+++ b/src/SessionController.cpp
@@ -230,10 +230,6 @@
SessionController::~SessionController()
{
- if (!_view.isNull()) {
- _view->setScreenWindow(nullptr);
- }
-
_allControllers.remove(this);
if (!_editProfileDialog.isNull()) {
@@ -539,11 +535,7 @@
// Close Session
QAction* action = collection->addAction(QStringLiteral("close-session"), this, SLOT(closeSession()));
- if (isKonsolePart()) {
- action->setText(i18n("&Close Session"));
- } else {
- action->setText(i18n("&Close Tab"));
- }
+ action->setText(i18n("&Close Session"));
action->setIcon(QIcon::fromTheme(QStringLiteral("tab-close")));
collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_W);
diff --git a/src/Shortcut_p.h b/src/Shortcut_p.h
--- a/src/Shortcut_p.h
+++ b/src/Shortcut_p.h
@@ -30,9 +30,13 @@
*/
enum Modifier {
#ifdef Q_OS_MACOS
- ACCEL = Qt::META
+ ACCEL = Qt::META,
+ LEFT = Qt::Key_BracketLeft,
+ RIGHT = Qt::Key_BracketRight
#else
- ACCEL = Qt::CTRL
+ ACCEL = Qt::CTRL,
+ LEFT = Qt::Key_Left,
+ RIGHT = Qt::Key_Right
#endif
};
}
diff --git a/src/ViewContainer.h b/src/ViewContainer.h
--- a/src/ViewContainer.h
+++ b/src/ViewContainer.h
@@ -76,6 +76,10 @@
/** Adds a new view to the container widget */
void addView(TerminalDisplay *view, int index = -1);
+ void addSplitter(ViewSplitter *splitter, int index = -1);
+
+ /** splits the currently focused Splitter */
+ void splitView(TerminalDisplay *view, Qt::Orientation orientation);
/** Removes a view from the container */
void removeView(TerminalDisplay *view);
@@ -95,14 +99,10 @@
/** Changes the active view to the last view */
void activateLastView();
- /** Changes the active view to the last used view */
- void activateLastUsedView(bool reverse);
-
- /** Toggle between last two views */
- void toggleLastUsedView();
-
void setCss(const QString& styleSheet = QString());
void setCssFromFile(const QUrl& url);
+
+ ViewSplitter *activeViewSplitter();
/**
* This enum describes the directions
* in which views can be re-arranged within the container
@@ -134,27 +134,33 @@
void currentTabChanged(int index);
void closeCurrentTab();
void wheelScrolled(int delta);
-
+ void currentSessionControllerChanged(SessionController *controller);
void tabDoubleClicked(int index);
void openTabContextMenu(const QPoint &point);
void setNavigationVisibility(ViewManager::NavigationVisibility navigationVisibility);
void moveTabToWindow(int index, QWidget *window);
+ void maximizeCurrentTerminal();
+ void restoreOtherTerminals();
/* return the widget(int index) casted to TerminalDisplay*
*
* The only thing that this class holds are TerminalDisplays, so
* this is the only thing that should be used to retrieve widgets.
*/
- TerminalDisplay *terminalAt(int index);
+ ViewSplitter *viewSplitterAt(int index);
+
+ void connectTerminalDisplay(TerminalDisplay *view);
+ void disconnectTerminalDisplay(TerminalDisplay *view);
+
Q_SIGNALS:
/** Emitted when the container has no more children */
void empty(TabbedViewContainer *container);
/** Emitted when the user requests to open a new view */
- void newViewRequest(TabbedViewContainer *thisContainer);
+ void newViewRequest();
/** Requests creation of a new view, with the selected profile. */
- void newViewWithProfileRequest(TabbedViewContainer *thisContainer, const Profile::Ptr&);
+ void newViewWithProfileRequest(const Profile::Ptr&);
/**
* Emitted when the user requests to move a view from another container
@@ -178,17 +184,9 @@
void viewRemoved(TerminalDisplay *view);
/** detach the specific tab */
- void detachTab(TabbedViewContainer *self, TerminalDisplay *activeView);
+ void detachTab(int tabIdx);
protected:
- /**
- * Rearranges the order of widgets in the container.
- *
- * @param fromIndex Current index of the widget to move
- * @param toIndex New index for the widget
- */
- void moveViewWidget(int fromIndex, int toIndex);
-
// close tabs and unregister
void closeTerminalTab(int idx);
@@ -198,17 +196,14 @@
void konsoleConfigChanged();
private:
- void forgetView(TerminalDisplay *view);
- void updateTabHistory(TerminalDisplay *view, bool remove = false);
+ void forgetView(ViewSplitter *view);
- 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
@@ -47,6 +47,9 @@
#include "SessionController.h"
#include "DetachableTabBar.h"
#include "TerminalDisplay.h"
+#include "ViewSplitter.h"
+#include "MainWindow.h"
+#include "Session.h"
// TODO Perhaps move everything which is Konsole-specific into different files
@@ -59,8 +62,7 @@
_newTabButton(new QToolButton()),
_closeTabButton(new QToolButton()),
_contextMenuTabIndex(-1),
- _navigationVisibility(ViewManager::NavigationVisibility::NavigationNotSet),
- _tabHistoryIndex(-1)
+ _navigationVisibility(ViewManager::NavigationVisibility::NavigationNotSet)
{
setAcceptDrops(true);
@@ -72,9 +74,7 @@
tabBar()->setContextMenuPolicy(Qt::CustomContextMenu);
_newTabButton->setIcon(QIcon::fromTheme(QStringLiteral("document-new")));
_newTabButton->setAutoRaise(true);
- connect(_newTabButton, &QToolButton::clicked, this, [this]{
- emit newViewRequest(this);
- });
+ connect(_newTabButton, &QToolButton::clicked, this, &TabbedViewContainer::newViewRequest);
_closeTabButton->setIcon(QIcon::fromTheme(QStringLiteral("tab-close")));
_closeTabButton->setAutoRaise(true);
@@ -86,9 +86,13 @@
&Konsole::TabbedViewContainer::tabDoubleClicked);
connect(tabBar(), &QTabBar::customContextMenuRequested, this,
&Konsole::TabbedViewContainer::openTabContextMenu);
- connect(tabBarWidget, &DetachableTabBar::detachTab, this, [this](int idx) {
- emit detachTab(this, terminalAt(idx));
+
+#if defined(ENABLE_DETACHING)
+ connect(tabBarWidget, &DetachableTabBar::detachTab, this, [this](int idx) {
+ emit detachTab(idx);
});
+#endif
+
connect(this, &TabbedViewContainer::currentChanged, this, &TabbedViewContainer::currentTabChanged);
// The context menu of tab bar
@@ -107,7 +111,7 @@
auto detachAction = _contextPopupMenu->addAction(
QIcon::fromTheme(QStringLiteral("tab-detach")),
i18nc("@action:inmenu", "&Detach Tab"), this,
- [this] { emit detachTab(this, terminalAt(_contextMenuTabIndex)); }
+ [this] { emit detachTab(_contextMenuTabIndex); }
);
detachAction->setObjectName(QStringLiteral("tab-detach"));
#endif
@@ -129,8 +133,7 @@
auto profileMenu = new QMenu();
auto profileList = new ProfileList(false, profileMenu);
profileList->syncWidgetActions(profileMenu, true);
- connect(profileList, &Konsole::ProfileList::profileSelected, this,
- [this](const Profile::Ptr &profile) { emit newViewWithProfileRequest(this, profile); });
+ connect(profileList, &Konsole::ProfileList::profileSelected, this, &TabbedViewContainer::newViewWithProfileRequest);
_newTabButton->setMenu(profileMenu);
konsoleConfigChanged();
@@ -145,24 +148,33 @@
}
}
-TerminalDisplay *TabbedViewContainer::terminalAt(int index)
+ViewSplitter *TabbedViewContainer::activeViewSplitter()
{
- return qobject_cast(widget(index));
+ return viewSplitterAt(currentIndex());
+}
+
+ViewSplitter *TabbedViewContainer::viewSplitterAt(int index)
+{
+ return qobject_cast(widget(index));
}
void TabbedViewContainer::moveTabToWindow(int index, QWidget *window)
{
- const int id = terminalAt(index)->sessionController()->identifier();
- // This one line here will be removed as soon as I finish my new split handling.
- // it's hacky but it works.
- const auto widgets = window->findChildren();
- const auto currentPos = QCursor::pos();
- for(const auto dropWidget : widgets) {
- if (dropWidget->rect().contains(dropWidget->mapFromGlobal(currentPos))) {
- emit dropWidget->moveViewRequest(-1, id);
- removeView(terminalAt(index));
- }
+ auto splitter = viewSplitterAt(index);
+ auto manager = window->findChild();
+
+ QHash sessionsMap = _connectedViewManager->forgetAll(splitter);
+
+ foreach(TerminalDisplay* terminal, splitter->getTerminalDisplays()) {
+ manager->attachView(terminal, sessionsMap[terminal]);
}
+ auto container = manager->activeContainer();
+ container->addSplitter(splitter);
+
+ auto controller = splitter->activeTerminalDisplay()->sessionController();
+ container->currentSessionControllerChanged(controller);
+
+ forgetView(splitter);
}
void TabbedViewContainer::konsoleConfigChanged()
@@ -235,66 +247,117 @@
const int currentIndex = indexOf(currentWidget());
int newIndex = direction == MoveViewLeft ? qMax(currentIndex - 1, 0) : qMin(currentIndex + 1, count() - 1);
- auto swappedWidget = terminalAt(newIndex);
- auto currentWidget = terminalAt(currentIndex);
- auto swappedContext = swappedWidget->sessionController();
- auto currentContext = currentWidget->sessionController();
+ auto swappedWidget = viewSplitterAt(newIndex);
+ auto swappedTitle = tabBar()->tabText(newIndex);
+ auto swappedIcon = tabBar()->tabIcon(newIndex);
+
+ auto currentWidget = viewSplitterAt(currentIndex);
+ auto currentTitle = tabBar()->tabText(currentIndex);
+ auto currentIcon = tabBar()->tabIcon(currentIndex);
if (newIndex < currentIndex) {
- insertTab(newIndex, currentWidget, currentContext->icon(), currentContext->title());
- insertTab(currentIndex, swappedWidget, swappedContext->icon(), swappedContext->title());
+ insertTab(newIndex, currentWidget, currentIcon, currentTitle);
+ insertTab(currentIndex, swappedWidget, swappedIcon, swappedTitle);
} else {
- insertTab(currentIndex, swappedWidget, swappedContext->icon(), swappedContext->title());
- insertTab(newIndex, currentWidget, currentContext->icon(), currentContext->title());
+ insertTab(currentIndex, swappedWidget, swappedIcon, swappedTitle);
+ insertTab(newIndex, currentWidget, currentIcon, currentTitle);
}
setCurrentIndex(newIndex);
}
+void TabbedViewContainer::addSplitter(ViewSplitter *viewSplitter, int index) {
+ if (index == -1) {
+ index = addTab(viewSplitter, QString());
+ } else {
+ insertTab(index, viewSplitter, QString());
+ }
+ connect(viewSplitter, &ViewSplitter::destroyed, this, &TabbedViewContainer::viewDestroyed);
+ foreach(TerminalDisplay* terminal, viewSplitter->getTerminalDisplays()) {
+ connectTerminalDisplay(terminal);
+ }
+ setCurrentIndex(index);
+}
+
void TabbedViewContainer::addView(TerminalDisplay *view, int index)
{
+ auto viewSplitter = new ViewSplitter();
+ viewSplitter->addTerminalDisplay(view, Qt::Horizontal);
auto item = view->sessionController();
if (index == -1) {
- addTab(view, item->icon(), item->title());
+ index = addTab(viewSplitter, item->icon(), item->title());
} else {
- insertTab(index, view, item->icon(), item->title());
+ insertTab(index, viewSplitter, item->icon(), item->title());
}
- _tabHistory.append(view);
+ connectTerminalDisplay(view);
+ connect(viewSplitter, &ViewSplitter::destroyed, this, &TabbedViewContainer::viewDestroyed);
+ setCurrentIndex(index);
+ emit viewAdded(view);
+}
+
+void TabbedViewContainer::splitView(TerminalDisplay *view, Qt::Orientation orientation)
+{
+ auto viewSplitter = qobject_cast(currentWidget());
+ viewSplitter->addTerminalDisplay(view, orientation);
+ connectTerminalDisplay(view);
+}
+
+void TabbedViewContainer::connectTerminalDisplay(TerminalDisplay *display)
+{
+ auto item = display->sessionController();
+ connect(item, &Konsole::SessionController::focused, this,
+ &Konsole::TabbedViewContainer::currentSessionControllerChanged);
+
connect(item, &Konsole::ViewProperties::titleChanged, this,
&Konsole::TabbedViewContainer::updateTitle);
+
connect(item, &Konsole::ViewProperties::iconChanged, this,
&Konsole::TabbedViewContainer::updateIcon);
+
connect(item, &Konsole::ViewProperties::activity, this,
&Konsole::TabbedViewContainer::updateActivity);
- connect(view, &QWidget::destroyed, this,
- &Konsole::TabbedViewContainer::viewDestroyed);
- emit viewAdded(view);
+}
+
+void TabbedViewContainer::disconnectTerminalDisplay(TerminalDisplay *display)
+{
+ auto item = display->sessionController();
+ disconnect(item, &Konsole::SessionController::focused, this,
+ &Konsole::TabbedViewContainer::currentSessionControllerChanged);
+
+ disconnect(item, &Konsole::ViewProperties::titleChanged, this,
+ &Konsole::TabbedViewContainer::updateTitle);
+
+ disconnect(item, &Konsole::ViewProperties::iconChanged, this,
+ &Konsole::TabbedViewContainer::updateIcon);
+
+ disconnect(item, &Konsole::ViewProperties::activity, this,
+ &Konsole::TabbedViewContainer::updateActivity);
}
void TabbedViewContainer::viewDestroyed(QObject *view)
{
- auto widget = static_cast(view);
+ auto widget = static_cast(view);
const auto idx = indexOf(widget);
removeTab(idx);
forgetView(widget);
}
-void TabbedViewContainer::forgetView(TerminalDisplay *view)
+void TabbedViewContainer::forgetView(ViewSplitter *view)
{
- updateTabHistory(view, true);
- emit viewRemoved(view);
+ Q_UNUSED(view);
if (count() == 0) {
emit empty(this);
}
}
void TabbedViewContainer::removeView(TerminalDisplay *view)
{
- const int idx = indexOf(view);
- disconnect(view, &QWidget::destroyed, this, &Konsole::TabbedViewContainer::viewDestroyed);
- removeTab(idx);
- forgetView(view);
+ /* TODO: This is absolutely the wrong place.
+ * We are removing a terminal display from a ViewSplitter,
+ * this should be inside of the view splitter or something.
+ */
+ view->setParent(nullptr);
}
void TabbedViewContainer::activateNextView()
@@ -316,71 +379,10 @@
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);
-}
-
-// Jump to last view - this allows toggling between two views
-// Using "Last Used Tabs" shortcut will cause "Toggle between two tabs"
-// shortcut to be incorrect the first time.
-void TabbedViewContainer::toggleLastUsedView()
-{
- if (_tabHistory.count() <= 1) {
- return;
- }
-
- setCurrentIndex(indexOf(_tabHistory.at(1)));
-}
-
void TabbedViewContainer::keyReleaseEvent(QKeyEvent* event)
{
- if (_tabHistoryIndex != -1 && event->modifiers() == Qt::NoModifier) {
- _tabHistoryIndex = -1;
- auto *active = qobject_cast(currentWidget());
- if (active != _tabHistory[0]) {
- // Update the tab history now that we have ended the walk-through
- updateTabHistory(active);
- }
- }
-}
-
-void TabbedViewContainer::updateTabHistory(TerminalDisplay* 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;
- }
+ if (event->modifiers() == Qt::NoModifier) {
+ _connectedViewManager->updateTerminalDisplayHistory();
}
}
@@ -396,14 +398,18 @@
if (index >= 0) {
renameTab(index);
} else {
- emit newViewRequest(this);
+ emit newViewRequest();
}
}
void TabbedViewContainer::renameTab(int index)
{
if (index != -1) {
- terminalAt(index)->sessionController()->rename();
+ setCurrentIndex(index);
+ viewSplitterAt(index)
+ -> activeTerminalDisplay()
+ -> sessionController()
+ -> rename();
}
}
@@ -428,9 +434,13 @@
}
#endif
+ /* This needs to nove away fro the tab or to lock every thing inside of it.
+ * for now, disable.
+ * */
+ //
// Add the read-only action
- auto controller = terminalAt(_contextMenuTabIndex)->sessionController();
- auto sessionController = qobject_cast(controller);
+#if 0
+ auto sessionController = terminalAt(_contextMenuTabIndex)->sessionController();
if (sessionController != nullptr) {
auto collection = sessionController->actionCollection();
@@ -448,16 +458,15 @@
}
}
}
-
+#endif
_contextPopupMenu->exec(tabBar()->mapToGlobal(point));
}
void TabbedViewContainer::currentTabChanged(int index)
{
if (index != -1) {
- auto *view = terminalAt(index);
- view->setFocus();
- updateTabHistory(view);
+ auto splitview = qobject_cast(widget(index));
+ auto view = splitview->activeTerminalDisplay();
emit activeViewChanged(view);
setTabActivity(index, false);
} else {
@@ -499,11 +508,17 @@
}
}
+void TabbedViewContainer::currentSessionControllerChanged(SessionController *controller)
+{
+ updateTitle(qobject_cast(controller));
+}
+
void TabbedViewContainer::updateTitle(ViewProperties *item)
{
auto controller = qobject_cast(item);
+ auto topLevelSplitter = qobject_cast(controller->view()->parentWidget())->getToplevelSplitter();
- const int index = indexOf(controller->view());
+ const int index = indexOf(topLevelSplitter);
QString tabText = item->title();
setTabToolTip(index, tabText);
@@ -521,7 +536,10 @@
}
void TabbedViewContainer::closeTerminalTab(int idx) {
- terminalAt(idx)->sessionController()->closeSession();
+ //TODO: This for should probably go to the ViewSplitter
+ for (auto terminal : viewSplitterAt(idx)->findChildren()) {
+ terminal->sessionController()->closeSession();
+ }
}
ViewManager *TabbedViewContainer::connectedViewManager()
@@ -541,3 +559,13 @@
tabBar()->setVisible(false);
}
}
+
+void TabbedViewContainer::maximizeCurrentTerminal()
+{
+ activeViewSplitter()->maximizeCurrentTerminal();
+}
+
+void TabbedViewContainer::restoreOtherTerminals()
+{
+ activeViewSplitter()->restoreOtherTerminals();
+}
diff --git a/src/ViewManager.h b/src/ViewManager.h
--- a/src/ViewManager.h
+++ b/src/ViewManager.h
@@ -44,10 +44,9 @@
/**
* Manages the terminal display widgets in a Konsole window or part.
*
- * When a view manager is created, it constructs a splitter widget ( accessed via
- * widget() ) to hold one or more view containers. Each view container holds
- * one or more terminal displays and a navigation widget ( eg. tabs or a list )
- * to allow the user to navigate between the displays in that container.
+ * When a view manager is created, it constructs a tab widget ( accessed via
+ * widget() ) to hold one or more view splitters. Each view splitter holds
+ * one or more terminal displays and splitters.
*
* The view manager provides menu actions ( defined in the 'konsoleui.rc' XML file )
* to manipulate the views and view containers - for example, actions to split the view
@@ -74,12 +73,6 @@
ViewManager(QObject *parent, KActionCollection *collection);
~ViewManager() Q_DECL_OVERRIDE;
- /**
- * Creates a new view to display the output from and deliver input to @p session.
- * Constructs a new container to hold the views if no container has yet been created.
- */
- void createView(TabbedViewContainer *tabWidget, Session *session);
-
/**
* Applies the view-specific settings associated with specified @p profile
* to the terminal display @p view.
@@ -197,13 +190,20 @@
/** returns the active tab from the view
*/
TabbedViewContainer *activeContainer();
+ TerminalDisplay *createView(Session *session);
+ void attachView(TerminalDisplay *terminal, Session *session);
+
+ /** Reorder the terminal display history list */
+ void updateTerminalDisplayHistory(TerminalDisplay *terminalDisplay = nullptr, bool remove = false);
+ QHash forgetAll(ViewSplitter* splitter);
+ Session* forgetTerminal(TerminalDisplay* terminal);
Q_SIGNALS:
/** Emitted when the last view is removed from the view manager */
void empty();
/** Emitted when a session is detached from a view owned by this ViewManager */
- void viewDetached(Session *session);
+ void terminalsDetached(ViewSplitter *splitter, QHash sessionsMap);
/**
* Emitted when the active view changes.
@@ -244,9 +244,9 @@
void blurSettingChanged(bool);
/** Requests creation of a new view with the default profile. */
- void newViewRequest(TabbedViewContainer *tabWidget);
+ void newViewRequest();
/** Requests creation of a new view, with the selected profile. */
- void newViewWithProfileRequest(TabbedViewContainer *tabWidget, const Profile::Ptr&);
+ void newViewWithProfileRequest(const Profile::Ptr&);
public Q_SLOTS:
/** DBus slot that returns the number of sessions in the current view. */
@@ -316,13 +316,12 @@
// called when the "Split View Left/Right" menu item is selected
void splitLeftRight();
void splitTopBottom();
- void closeActiveContainer();
- void closeOtherContainers();
void expandActiveContainer();
void shrinkActiveContainer();
// called when the "Detach View" menu item is selected
void detachActiveView();
+ void detachActiveTab();
void updateDetachViewState();
// called when a session terminates - the view manager will delete any
@@ -338,7 +337,12 @@
// called when the active view in a ViewContainer changes, so
// that we can plug the appropriate actions into the UI
- void viewActivated(QWidget *view);
+ void viewActivated(TerminalDisplay *view);
+
+ void focusUp();
+ void focusDown();
+ void focusLeft();
+ void focusRight();
// called when "Next View" shortcut is activated
void nextView();
@@ -377,20 +381,18 @@
// switches to the view at visual position 'index'
// in the current container
void switchToView(int index);
+ // gives focus and switches the terminal display, changing tab if needed
+ void switchToTerminalDisplay(TerminalDisplay *terminalDisplay);
// called when a SessionController gains focus
void controllerChanged(SessionController *controller);
- // called when a ViewContainer requests a view be
- // moved
- void containerMoveViewRequest(int index, int sessionControllerId);
-
- void detachView(TabbedViewContainer *container, QWidget *view);
+ /* Detaches the tab at index tabIdx */
+ void detachTab(int tabIdx);
private:
Q_DISABLE_COPY(ViewManager)
- void createView(Session *session, TabbedViewContainer *container, int index);
static const ColorScheme *colorSchemeForProfile(const Profile::Ptr &profile);
void setupActions();
@@ -403,8 +405,6 @@
// creates a new container which can hold terminal displays
TabbedViewContainer *createContainer();
- // removes a container and emits appropriate signals
- void removeContainer(TabbedViewContainer *container);
// creates a new terminal display
// the 'session' is used so that the terminal display's random seed
@@ -415,9 +415,18 @@
// actions associated with that view, and exposes basic information
// about the session ( such as title and associated icon ) to the display.
SessionController *createController(Session *session, TerminalDisplay *view);
+ void removeController(SessionController* controller);
+
+ // Activates a different terminal when the TerminalDisplay
+ // closes or is detached and another one should be focused.
+ // It will activate the last used terminal within the same splitView
+ // if possible otherwise it will focus the last used tab
+ void focusAnotherTerminal(ViewSplitter *toplevelSplitter);
+
+ void activateLastUsedView(bool reverse);
private:
- QPointer _viewSplitter;
+ QPointer _viewContainer;
QPointer _pluggedController;
QHash _sessionMap;
@@ -429,6 +438,8 @@
NewTabBehavior _newTabBehavior;
int _managerId;
static int lastManagerId;
+ QList _terminalDisplayHistory;
+ int _terminalDisplayHistoryIndex;
};
}
diff --git a/src/ViewManager.cpp b/src/ViewManager.cpp
--- a/src/ViewManager.cpp
+++ b/src/ViewManager.cpp
@@ -53,36 +53,25 @@
ViewManager::ViewManager(QObject *parent, KActionCollection *collection) :
QObject(parent),
- _viewSplitter(nullptr),
+ _viewContainer(nullptr),
_pluggedController(nullptr),
_sessionMap(QHash()),
_actionCollection(collection),
_navigationMethod(NoNavigation),
_navigationVisibility(NavigationNotSet),
_newTabBehavior(PutNewTabAtTheEnd),
- _managerId(0)
+ _managerId(0),
+ _terminalDisplayHistoryIndex(-1)
{
- // create main view area
- _viewSplitter = new ViewSplitter(nullptr);
- KAcceleratorManager::setNoAccel(_viewSplitter);
-
- // the ViewSplitter class supports both recursive and non-recursive splitting,
- // in non-recursive mode, all containers are inserted into the same top-level splitter
- // widget, and all the divider lines between the containers have the same orientation
- //
- // the ViewManager class is not currently able to handle a ViewSplitter in recursive-splitting
- // mode
- _viewSplitter->setRecursiveSplitting(false);
- _viewSplitter->setFocusPolicy(Qt::NoFocus);
-
+ _viewContainer = createContainer();
// setup actions which are related to the views
setupActions();
+ /* TODO: Reconnect
// emit a signal when all of the views held by this view manager are destroyed
- connect(_viewSplitter.data(), &Konsole::ViewSplitter::allContainersEmpty,
+ */
+ connect(_viewContainer.data(), &Konsole::TabbedViewContainer::empty,
this, &Konsole::ViewManager::empty);
- connect(_viewSplitter.data(), &Konsole::ViewSplitter::empty, this,
- &Konsole::ViewManager::empty);
// listen for profile changes
connect(ProfileManager::instance(), &Konsole::ProfileManager::profileChanged,
@@ -96,8 +85,6 @@
_managerId = ++lastManagerId;
QDBusConnection::sessionBus().registerObject(QLatin1String("/Windows/")
+ QString::number(_managerId), this);
-
- _viewSplitter->addContainer(createContainer(), Qt::Vertical);
}
ViewManager::~ViewManager() = default;
@@ -109,17 +96,12 @@
QWidget *ViewManager::activeView() const
{
- TabbedViewContainer *container = _viewSplitter->activeContainer();
- if (container != nullptr) {
- return container->currentWidget();
- } else {
- return nullptr;
- }
+ return _viewContainer->currentWidget();
}
QWidget *ViewManager::widget() const
{
- return _viewSplitter;
+ return _viewContainer;
}
void ViewManager::setupActions()
@@ -131,320 +113,371 @@
KActionCollection *collection = _actionCollection;
- QAction *nextViewAction = new QAction(i18nc("@action Shortcut entry", "Next Tab"), this);
- 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 *toggleTwoViewsAction = new QAction(i18nc("@action Shortcut entry", "Toggle Between Two Tabs"), this);
- QAction *nextContainerAction = new QAction(i18nc("@action Shortcut entry",
- "Next View Container"), this);
-
- QAction *moveViewLeftAction = new QAction(i18nc("@action Shortcut entry", "Move Tab Left"), this);
- QAction *moveViewRightAction = new QAction(i18nc("@action Shortcut entry",
- "Move Tab Right"), this);
-
// list of actions that should only be enabled when there are multiple view
// containers open
- QList multiViewOnlyActions;
- multiViewOnlyActions << nextContainerAction;
-
- QAction *splitLeftRightAction = new QAction(QIcon::fromTheme(QStringLiteral("view-split-left-right")),
- i18nc("@action:inmenu", "Split View Left/Right"),
- this);
- collection->setDefaultShortcut(splitLeftRightAction, Konsole::ACCEL + Qt::Key_ParenLeft);
- collection->addAction(QStringLiteral("split-view-left-right"), splitLeftRightAction);
- connect(splitLeftRightAction, &QAction::triggered, this, &Konsole::ViewManager::splitLeftRight);
-
- QAction *splitTopBottomAction = new QAction(QIcon::fromTheme(QStringLiteral("view-split-top-bottom")),
- i18nc("@action:inmenu",
- "Split View Top/Bottom"), this);
- collection->setDefaultShortcut(splitTopBottomAction, Konsole::ACCEL + Qt::Key_ParenRight);
- collection->addAction(QStringLiteral("split-view-top-bottom"), splitTopBottomAction);
- connect(splitTopBottomAction, &QAction::triggered, this, &Konsole::ViewManager::splitTopBottom);
-
- QAction *closeActiveAction = new QAction(i18nc("@action:inmenu Close Active View", "Close Active"), this);
- closeActiveAction->setIcon(QIcon::fromTheme(QStringLiteral("view-close")));
- collection->setDefaultShortcut(closeActiveAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_X);
- closeActiveAction->setEnabled(false);
- collection->addAction(QStringLiteral("close-active-view"), closeActiveAction);
- connect(closeActiveAction, &QAction::triggered, this,
- &Konsole::ViewManager::closeActiveContainer);
-
- multiViewOnlyActions << closeActiveAction;
-
- QAction *closeOtherAction = new QAction(i18nc("@action:inmenu Close Other Views",
- "Close Others"), this);
- collection->setDefaultShortcut(closeOtherAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_O);
- closeOtherAction->setEnabled(false);
- collection->addAction(QStringLiteral("close-other-views"), closeOtherAction);
- connect(closeOtherAction, &QAction::triggered, this,
- &Konsole::ViewManager::closeOtherContainers);
-
- multiViewOnlyActions << closeOtherAction;
-
- // Expand & Shrink Active View
- QAction *expandActiveAction = new QAction(i18nc("@action:inmenu", "Expand View"), this);
- collection->setDefaultShortcut(expandActiveAction,
- Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketRight);
- expandActiveAction->setEnabled(false);
- collection->addAction(QStringLiteral("expand-active-view"), expandActiveAction);
- connect(expandActiveAction, &QAction::triggered, this,
- &Konsole::ViewManager::expandActiveContainer);
-
- multiViewOnlyActions << expandActiveAction;
-
- QAction *shrinkActiveAction = new QAction(i18nc("@action:inmenu", "Shrink View"), this);
- collection->setDefaultShortcut(shrinkActiveAction,
- Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketLeft);
- shrinkActiveAction->setEnabled(false);
- collection->addAction(QStringLiteral("shrink-active-view"), shrinkActiveAction);
- connect(shrinkActiveAction, &QAction::triggered, this,
- &Konsole::ViewManager::shrinkActiveContainer);
-
- multiViewOnlyActions << shrinkActiveAction;
+ QList multiTabOnlyActions;
+ QList multiSplitterOnlyActions;
+
+ // Let's reuse the pointer, no need not to.
+ auto *action = new QAction();
+ action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-left-right")));
+ action->setText(i18nc("@action:inmenu", "Split View Left/Right"));
+ connect(action, &QAction::triggered, this, &ViewManager::splitLeftRight);
+ collection->addAction(QStringLiteral("split-view-left-right"), action);
+ collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::Key_ParenLeft);
+
+ action = new QAction();
+ action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-top-bottom")));
+ action->setText(i18nc("@action:inmenu", "Split View Top/Bottom"));
+ connect(action, &QAction::triggered, this, &ViewManager::splitTopBottom);
+ collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::Key_ParenRight);
+ collection->addAction(QStringLiteral("split-view-top-bottom"), action);
+
+ action = new QAction();
+ action->setText(i18nc("@action:inmenu", "Expand View"));
+ action->setEnabled(false);
+ connect(action, &QAction::triggered, this, &ViewManager::expandActiveContainer);
+ collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketRight);
+ collection->addAction(QStringLiteral("expand-active-view"), action);
+ multiSplitterOnlyActions << action;
+
+ action = new QAction();
+ action->setText(i18nc("@action:inmenu", "Shrink View"));
+ collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketLeft);
+ action->setEnabled(false);
+ collection->addAction(QStringLiteral("shrink-active-view"), action);
+ connect(action, &QAction::triggered, this, &ViewManager::shrinkActiveContainer);
+ multiSplitterOnlyActions << action;
// Crashes on Mac.
#if defined(ENABLE_DETACHING)
- QAction *detachViewAction = collection->addAction(QStringLiteral("detach-view"));
- detachViewAction->setEnabled(true);
- detachViewAction->setIcon(QIcon::fromTheme(QStringLiteral("tab-detach")));
- detachViewAction->setText(i18nc("@action:inmenu", "D&etach Current Tab"));
- // Ctrl+Shift+D is not used as a shortcut by default because it is too close
- // to Ctrl+D - which will terminate the session in many cases
- collection->setDefaultShortcut(detachViewAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_H);
+ connect(this, &ViewManager::splitViewToggle, this, &ViewManager::updateDetachViewState);
- connect(this, &Konsole::ViewManager::splitViewToggle, this,
- &Konsole::ViewManager::updateDetachViewState);
- connect(detachViewAction, &QAction::triggered, this, &Konsole::ViewManager::detachActiveView);
-#endif
+ action = collection->addAction(QStringLiteral("detach-view"));
+ action->setEnabled(true);
+ action->setIcon(QIcon::fromTheme(QStringLiteral("detach-view")));
+ action->setText(i18nc("@action:inmenu", "D&etach Current View"));
- // Next / Previous View , Next Container
- 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("toggle-two-tabs"), toggleTwoViewsAction);
- collection->addAction(QStringLiteral("next-container"), nextContainerAction);
- collection->addAction(QStringLiteral("move-view-left"), moveViewLeftAction);
- collection->addAction(QStringLiteral("move-view-right"), moveViewRightAction);
-
- // Switch to tab N shortcuts
- const int SWITCH_TO_TAB_COUNT = 19;
- for (int i = 0; i < SWITCH_TO_TAB_COUNT; i++) {
- QAction *switchToTabAction = new QAction(i18nc("@action Shortcut entry", "Switch to Tab %1", i + 1), this);
+ connect(action, &QAction::triggered, this, &ViewManager::detachActiveView);
+ multiSplitterOnlyActions << action;
- connect(switchToTabAction, &QAction::triggered, this,
- [this, i]() {
- switchToView(i);
- });
- collection->addAction(QStringLiteral("switch-to-tab-%1").arg(i), switchToTabAction);
- }
-
- foreach (QAction *action, multiViewOnlyActions) {
- connect(this, &Konsole::ViewManager::splitViewToggle, action, &QAction::setEnabled);
- }
+ // Ctrl+Shift+D is not used as a shortcut by default because it is too close
+ // to Ctrl+D - which will terminate the session in many cases
+ collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_H);
+
+ action = collection->addAction(QStringLiteral("detach-tab"));
+ action->setEnabled(true);
+ action->setIcon(QIcon::fromTheme(QStringLiteral("detach-tab")));
+ action->setText(i18nc("@action:inmenu", "D&etach Current Tab"));
+ connect(action, &QAction::triggered, this, &ViewManager::detachActiveTab);
+ multiTabOnlyActions << action;
+ // Ctrl+Shift+D is not used as a shortcut by default because it is too close
+ // to Ctrl+D - which will terminate the session in many cases
+ collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_L);
+#endif
// keyboard shortcut only actions
+ action = new QAction(i18nc("@action Shortcut entry", "Next Tab"), this);
const QList nextViewActionKeys{Qt::SHIFT + Qt::Key_Right, Qt::CTRL + Qt::Key_PageDown};
- collection->setDefaultShortcuts(nextViewAction, nextViewActionKeys);
- connect(nextViewAction, &QAction::triggered, this, &Konsole::ViewManager::nextView);
- _viewSplitter->addAction(nextViewAction);
+ collection->setDefaultShortcuts(action, nextViewActionKeys);
+ collection->addAction(QStringLiteral("next-tab"), action);
+ connect(action, &QAction::triggered, this, &ViewManager::nextView);
+ multiTabOnlyActions << action;
+ // _viewSplitter->addAction(nextViewAction);
+ action = new QAction(i18nc("@action Shortcut entry", "Previous Tab"), this);
const QList previousViewActionKeys{Qt::SHIFT + Qt::Key_Left, Qt::CTRL + Qt::Key_PageUp};
- collection->setDefaultShortcuts(previousViewAction, previousViewActionKeys);
- connect(previousViewAction, &QAction::triggered, this, &Konsole::ViewManager::previousView);
- _viewSplitter->addAction(previousViewAction);
-
- collection->setDefaultShortcut(nextContainerAction, Qt::SHIFT + Qt::Key_Tab);
- connect(nextContainerAction, &QAction::triggered, this, &Konsole::ViewManager::nextContainer);
- _viewSplitter->addAction(nextContainerAction);
-
-#ifdef Q_OS_MACOS
- collection->setDefaultShortcut(moveViewLeftAction,
- Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketLeft);
-#else
- collection->setDefaultShortcut(moveViewLeftAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_Left);
-#endif
- connect(moveViewLeftAction, &QAction::triggered, this,
- &Konsole::ViewManager::moveActiveViewLeft);
- _viewSplitter->addAction(moveViewLeftAction);
-
-#ifdef Q_OS_MACOS
- collection->setDefaultShortcut(moveViewRightAction,
- Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketRight);
-#else
- collection->setDefaultShortcut(moveViewRightAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_Right);
-#endif
- connect(moveViewRightAction, &QAction::triggered, this,
- &Konsole::ViewManager::moveActiveViewRight);
- _viewSplitter->addAction(moveViewRightAction);
-
- 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->setDefaultShortcuts(action, previousViewActionKeys);
+ collection->addAction(QStringLiteral("previous-tab"), action);
+ connect(action, &QAction::triggered, this, &ViewManager::previousView);
+ multiTabOnlyActions << action;
+ // _viewSplitter->addAction(previousViewAction);
+
+ action = new QAction(i18nc("@action Shortcut entry", "Next View Container"), this);
+ connect(action, &QAction::triggered, this, &ViewManager::focusUp);
+ collection->addAction(QStringLiteral("next-container"), action);
+ collection->setDefaultShortcut(action, Qt::SHIFT + Qt::CTRL + Qt::Key_Up);
+ _viewContainer->addAction(action);
+ multiSplitterOnlyActions << action;
+
+ action = new QAction(QStringLiteral("Focus Down"));
+ collection->setDefaultShortcut(action, Qt::SHIFT + Qt::CTRL + Qt::Key_Down);
+ connect(action, &QAction::triggered, this, &ViewManager::focusDown);
+ multiSplitterOnlyActions << action;
+ _viewContainer->addAction(action);
+
+ action = new QAction(i18nc("@action Shortcut entry", "Move Tab Left"), this);
+ collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Konsole::LEFT);
+ connect(action, &QAction::triggered, this, &ViewManager::focusLeft);
+ collection->addAction(QStringLiteral("move-view-left"), action);
+ multiSplitterOnlyActions << action;
+
+ action = new QAction(i18nc("@action Shortcut entry", "Move Tab Right"), this);
+ collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Konsole::RIGHT);
+ connect(action, &QAction::triggered, this, &ViewManager::focusRight);
+ collection->addAction(QStringLiteral("move-view-right"), action);
+ multiSplitterOnlyActions << action;
+
+ action = new QAction(i18nc("@action Shortcut entry", "Switch to Last Tab"), this);
+ connect(action, &QAction::triggered, this, &ViewManager::lastView);
+ collection->addAction(QStringLiteral("last-tab"), action);
+ multiTabOnlyActions << action;
+
+ action = new QAction(i18nc("@action Shortcut entry", "Last Used Tabs"), this);
+ connect(action, &QAction::triggered, this, &ViewManager::lastUsedView);
+ collection->setDefaultShortcut(action, Qt::CTRL + Qt::Key_Tab);
+ collection->addAction(QStringLiteral("last-used-tab"), action);
+ multiTabOnlyActions << action;
+
+ action = new QAction(i18nc("@action Shortcut entry", "Toggle Between Two Tabs"), this);
+ connect(action, &QAction::triggered, this, &Konsole::ViewManager::toggleTwoViews);
+ collection->addAction(QStringLiteral("toggle-two-tabs"), action);
+ multiTabOnlyActions << action;
+
+ action = new QAction(i18nc("@action Shortcut entry", "Last Used Tabs (Reverse)"), this);
+ collection->addAction(QStringLiteral("last-used-tab-reverse"), action);
+ collection->setDefaultShortcut(action, Qt::CTRL + Qt::SHIFT + Qt::Key_Tab);
+ connect(action, &QAction::triggered, this, &ViewManager::lastUsedViewReverse);
+ multiTabOnlyActions << action;
+
+ action = new QAction(i18nc("@action Shortcut entry", "Maximize current Terminal"), this);
+ collection->addAction(QStringLiteral("maximize-current-terminal"), action);
+ collection->setDefaultShortcut(action, Qt::CTRL + Qt::SHIFT + Qt::Key_E);
+ connect(action, &QAction::triggered, _viewContainer, &TabbedViewContainer::maximizeCurrentTerminal);
+ multiSplitterOnlyActions << action;
+ _viewContainer->addAction(action);
+
+ action = new QAction(i18nc("@action Shortcut entry", "Restore other terminals"), this);
+ collection->addAction(QStringLiteral("restore-other-terminals"), action);
+ collection->setDefaultShortcut(action, Qt::CTRL + Qt::SHIFT + Qt::Key_Minus);
+ connect(action, &QAction::triggered, _viewContainer, &TabbedViewContainer::restoreOtherTerminals);
+ multiSplitterOnlyActions << action;
+ _viewContainer->addAction(action);
+
+ // _viewSplitter->addAction(lastUsedViewReverseAction);
+ const int SWITCH_TO_TAB_COUNT = 19;
+ for (int i = 0; i < SWITCH_TO_TAB_COUNT; i++) {
+ action = new QAction(i18nc("@action Shortcut entry", "Switch to Tab %1", i + 1), this);
+ connect(action, &QAction::triggered, this, [this, i]() { switchToView(i); });
+ collection->addAction(QStringLiteral("switch-to-tab-%1").arg(i), action);
+ }
- collection->setDefaultShortcut(lastUsedViewReverseAction, Qt::CTRL + Qt::SHIFT + Qt::Key_Tab);
- connect(lastUsedViewReverseAction, &QAction::triggered, this, &Konsole::ViewManager::lastUsedViewReverse);
- _viewSplitter->addAction(lastUsedViewReverseAction);
+ connect(_viewContainer, &QTabWidget::currentChanged, this, [=](int idx) {
+ auto splitView = _viewContainer->viewSplitterAt(idx);
+ if (!splitView)
+ return;
+ foreach (QAction *action, multiSplitterOnlyActions) {
+ action->setEnabled(splitView->count() > 1);
+ }
+ });
- connect(toggleTwoViewsAction, &QAction::triggered, this, &Konsole::ViewManager::toggleTwoViews);
- _viewSplitter->addAction(toggleTwoViewsAction);
+ auto handleMultiTabActionsLambda = [=]{
+ const int count = _viewContainer->count();
+ foreach(QAction *action, multiTabOnlyActions) {
+ action->setEnabled(count > 1);
+ }
+ };
+ connect(_viewContainer, &TabbedViewContainer::viewAdded, this, handleMultiTabActionsLambda);
+ connect(_viewContainer, &TabbedViewContainer::viewRemoved, this, handleMultiTabActionsLambda);
}
void ViewManager::switchToView(int index)
{
- _viewSplitter->activeContainer()->setCurrentIndex(index);
+ _viewContainer->setCurrentIndex(index);
+}
+
+void ViewManager::switchToTerminalDisplay(Konsole::TerminalDisplay* terminalDisplay)
+{
+ auto splitter = qobject_cast(terminalDisplay->parentWidget());
+ auto toplevelSplitter = splitter->getToplevelSplitter();
+
+ // Focus the TermialDisplay
+ terminalDisplay->setFocus();
+
+ if (_viewContainer->currentWidget() != toplevelSplitter) {
+ // Focus the tab
+ switchToView(_viewContainer->indexOf(toplevelSplitter));
+ }
}
void ViewManager::updateDetachViewState()
{
- Q_ASSERT(_actionCollection);
- if (_actionCollection == nullptr) {
- return;
+ if (_viewContainer && _viewContainer->activeViewSplitter()) {
+ const int splitCount = _viewContainer->activeViewSplitter()->getToplevelSplitter()->count();
+ QAction *detachAction = _actionCollection->action(QStringLiteral("detach-view"));
+ detachAction->setEnabled(splitCount > 1);
}
+}
+
+void ViewManager::focusUp()
+{
+ _viewContainer->activeViewSplitter()->focusUp();
+}
- const bool splitView = _viewSplitter->containers().count() >= 2;
- auto activeContainer = _viewSplitter->activeContainer();
- const bool shouldEnable = splitView
- || ((activeContainer != nullptr)
- && activeContainer->count() >= 2);
+void ViewManager::focusDown()
+{
+ _viewContainer->activeViewSplitter()->focusDown();
+}
- QAction *detachAction = _actionCollection->action(QStringLiteral("detach-view"));
+void ViewManager::focusLeft()
+{
+ _viewContainer->activeViewSplitter()->focusLeft();
+}
- if ((detachAction != nullptr) && shouldEnable != detachAction->isEnabled()) {
- detachAction->setEnabled(shouldEnable);
- }
+void ViewManager::focusRight()
+{
+ _viewContainer->activeViewSplitter()->focusRight();
}
void ViewManager::moveActiveViewLeft()
{
- TabbedViewContainer *container = _viewSplitter->activeContainer();
- Q_ASSERT(container);
- container->moveActiveView(TabbedViewContainer::MoveViewLeft);
+ _viewContainer->moveActiveView(TabbedViewContainer::MoveViewLeft);
}
void ViewManager::moveActiveViewRight()
{
- TabbedViewContainer *container = _viewSplitter->activeContainer();
- Q_ASSERT(container);
- container->moveActiveView(TabbedViewContainer::MoveViewRight);
+ _viewContainer->moveActiveView(TabbedViewContainer::MoveViewRight);
}
void ViewManager::nextContainer()
{
- _viewSplitter->activateNextContainer();
+// _viewSplitter->activateNextContainer();
}
void ViewManager::nextView()
{
- TabbedViewContainer *container = _viewSplitter->activeContainer();
- Q_ASSERT(container);
- container->activateNextView();
+ _viewContainer->activateNextView();
}
void ViewManager::previousView()
{
- TabbedViewContainer *container = _viewSplitter->activeContainer();
- Q_ASSERT(container);
- container->activatePreviousView();
+ _viewContainer->activatePreviousView();
}
void ViewManager::lastView()
{
- TabbedViewContainer *container = _viewSplitter->activeContainer();
- Q_ASSERT(container);
- container->activateLastView();
+ _viewContainer->activateLastView();
+}
+
+void ViewManager::activateLastUsedView(bool reverse)
+{
+ if (_terminalDisplayHistory.count() <= 1) {
+ return;
+ }
+
+ if (_terminalDisplayHistoryIndex == -1) {
+ _terminalDisplayHistoryIndex = reverse ? _terminalDisplayHistory.count() - 1 : 1;
+ } else if (reverse) {
+ if (_terminalDisplayHistoryIndex == 0) {
+ _terminalDisplayHistoryIndex = _terminalDisplayHistory.count() - 1;
+ } else {
+ _terminalDisplayHistoryIndex--;
+ }
+ } else {
+ if (_terminalDisplayHistoryIndex >= _terminalDisplayHistory.count() - 1) {
+ _terminalDisplayHistoryIndex = 0;
+ } else {
+ _terminalDisplayHistoryIndex++;
+ }
+ }
+
+ switchToTerminalDisplay(_terminalDisplayHistory[_terminalDisplayHistoryIndex]);
}
void ViewManager::lastUsedView()
{
- TabbedViewContainer *container = _viewSplitter->activeContainer();
- Q_ASSERT(container);
- container->activateLastUsedView(false);
+ activateLastUsedView(false);
}
void ViewManager::lastUsedViewReverse()
{
- TabbedViewContainer *container = _viewSplitter->activeContainer();
- Q_ASSERT(container);
- container->activateLastUsedView(true);
+ activateLastUsedView(true);
}
void ViewManager::toggleTwoViews()
{
- TabbedViewContainer *container = _viewSplitter->activeContainer();
- Q_ASSERT(container);
- container->toggleLastUsedView();
+ if (_terminalDisplayHistory.count() <= 1) {
+ return;
+ }
+
+ switchToTerminalDisplay(_terminalDisplayHistory.at(1));
}
void ViewManager::detachActiveView()
{
+#if !defined(ENABLE_DETACHING)
+ return;
+#endif
// find the currently active view and remove it from its container
- TabbedViewContainer *container = _viewSplitter->activeContainer();
- detachView(container, container->currentWidget());
+ if ((_viewContainer->findChildren()).count() > 1) {
+ auto activeSplitter = _viewContainer->activeViewSplitter();
+ auto terminal = activeSplitter->activeTerminalDisplay();
+ auto newSplitter = new ViewSplitter();
+ newSplitter->addTerminalDisplay(terminal, Qt::Horizontal);
+ QHash detachedSessions = forgetAll(newSplitter);
+ emit terminalsDetached(newSplitter, detachedSessions);
+ focusAnotherTerminal(activeSplitter->getToplevelSplitter());
+ }
+}
+
+void ViewManager::detachActiveTab()
+{
+ const int currentIdx = _viewContainer->currentIndex();
+ detachTab(currentIdx);
}
-void ViewManager::detachView(TabbedViewContainer *container, QWidget *view)
+void ViewManager::detachTab(int tabIdx)
{
#if !defined(ENABLE_DETACHING)
return;
#endif
-
- auto *viewToDetach = qobject_cast(view);
-
- if (viewToDetach == nullptr) {
- return;
- }
-
- // BR390736 - some instances are sending invalid session to viewDetached()
- Session *sessionToDetach = _sessionMap[viewToDetach];
- if (sessionToDetach == nullptr) {
- return;
+ ViewSplitter* splitter = _viewContainer->viewSplitterAt(tabIdx);
+ QHash detachedSessions = forgetAll(_viewContainer->viewSplitterAt(tabIdx));
+ emit terminalsDetached(splitter, detachedSessions);
+}
+
+QHash ViewManager::forgetAll(ViewSplitter* splitter) {
+ splitter->setParent(nullptr);
+ auto terminals = splitter->getTerminalDisplays();
+ QHash detachedSessions;
+ foreach(TerminalDisplay* terminal, terminals) {
+ Session* session = forgetTerminal(terminal);
+ detachedSessions[terminal] = session;
}
- emit viewDetached(sessionToDetach);
-
- _sessionMap.remove(viewToDetach);
-
- // remove the view from this window
- container->removeView(viewToDetach);
- viewToDetach->deleteLater();
+ return detachedSessions;
+}
- // if the container from which the view was removed is now empty then it can be deleted,
- // unless it is the only container in the window, in which case it is left empty
- // so that there is always an active container
- if (_viewSplitter->containers().count() > 1
- && container->count() == 0) {
- removeContainer(container);
+Session* ViewManager::forgetTerminal(TerminalDisplay* terminal)
+{
+ removeController(terminal->sessionController());
+ auto session = _sessionMap.take(terminal);
+ if (session != nullptr) {
+ disconnect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished);
}
+ _viewContainer->disconnectTerminalDisplay(terminal);
+ updateTerminalDisplayHistory(terminal, true);
+ return session;
}
void ViewManager::sessionFinished()
{
// if this slot is called after the view manager's main widget
// has been destroyed, do nothing
- if (_viewSplitter.isNull()) {
+ if (_viewContainer.isNull()) {
return;
}
auto *session = qobject_cast(sender());
Q_ASSERT(session);
- // close attached views
- QList children = _viewSplitter->findChildren();
+ auto view = _sessionMap.key(session);
+ _sessionMap.remove(view);
- foreach (TerminalDisplay *view, children) {
- if (_sessionMap[view] == session) {
- _sessionMap.remove(view);
- view->deleteLater();
- }
- }
+ // Before deleting the view, let's unmaximize if it's maximized.
+ auto splitter = qobject_cast(view->parentWidget());
+ auto toplevelSplitter = splitter->getToplevelSplitter();
+ toplevelSplitter->restoreOtherTerminals();
+ view->deleteLater();
// Only remove the controller from factory() if it's actually controlling
// the session from the sender.
@@ -454,9 +487,31 @@
// order to prevent BUG: 185466 - disappearing menu popup
emit unplugController(_pluggedController);
}
+
+ updateTerminalDisplayHistory(view, true);
+ focusAnotherTerminal(toplevelSplitter);
}
-void ViewManager::viewActivated(QWidget *view)
+void ViewManager::focusAnotherTerminal(ViewSplitter *toplevelSplitter)
+{
+ auto tabTterminalDisplays = toplevelSplitter->findChildren();
+ if (tabTterminalDisplays.count() > 1) {
+ // Give focus to the last used terminal in this tab
+ for (auto *historyItem : _terminalDisplayHistory) {
+ for (auto *terminalDisplay : tabTterminalDisplays) {
+ if (terminalDisplay == historyItem) {
+ terminalDisplay->setFocus(Qt::OtherFocusReason);
+ return;
+ }
+ }
+ }
+ } else if (_terminalDisplayHistory.count() >= 1) {
+ // Give focus to the last used terminal tab
+ switchToTerminalDisplay(_terminalDisplayHistory[0]);
+ }
+}
+
+void ViewManager::viewActivated(TerminalDisplay *view)
{
Q_ASSERT(view != nullptr);
@@ -478,85 +533,34 @@
void ViewManager::splitView(Qt::Orientation orientation)
{
- TabbedViewContainer *container = createContainer();
-
- if (_viewSplitter->activeContainer()->count()) {
- // get the currently applied profile and use it to create the new tab.
- auto *activeContainer= _viewSplitter->activeContainer();
- auto *currentDisplay = qobject_cast(activeContainer->currentWidget());
- auto profile = SessionManager::instance()->sessionProfile(_sessionMap[currentDisplay]);
+ auto viewSplitter = qobject_cast(_viewContainer->currentWidget());
- // Create a new session with the selected profile.
- auto *session = SessionManager::instance()->createSession(profile);
- session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId()));
-
- createView(session, container, 0);
- }
-
- _viewSplitter->addContainer(container, orientation);
- emit splitViewToggle(_viewSplitter->containers().count() > 0);
-
- // focus the new container
- container->currentWidget()->setFocus();
+ // get the currently applied profile and use it to create the new tab.
+ auto *currentDisplay = viewSplitter->findChild();
+ auto profile = SessionManager::instance()->sessionProfile(_sessionMap[currentDisplay]);
- // ensure that the active view is focused after the split / unsplit
- TabbedViewContainer *activeContainer = _viewSplitter->activeContainer();
- QWidget *activeView = activeContainer != nullptr ? activeContainer->currentWidget() : nullptr;
+ // Create a new session with the selected profile.
+ auto *session = SessionManager::instance()->createSession(profile);
+ session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId()));
- if (activeView != nullptr) {
- activeView->setFocus(Qt::OtherFocusReason);
- }
-}
+ auto terminalDisplay = createView(session);
-void ViewManager::removeContainer(TabbedViewContainer *container)
-{
- // remove session map entries for views in this container
- for(int i = 0, end = container->count(); i < end; i++) {
- auto view = container->widget(i);
- auto *display = qobject_cast(view);
- Q_ASSERT(display);
- _sessionMap.remove(display);
- }
+ _viewContainer->splitView(terminalDisplay, orientation);
- _viewSplitter->removeContainer(container);
- container->deleteLater();
+ emit splitViewToggle(viewSplitter->count() > 0);
- emit splitViewToggle(_viewSplitter->containers().count() > 1);
+ // focus the new container
+ terminalDisplay->setFocus();
}
void ViewManager::expandActiveContainer()
{
- _viewSplitter->adjustContainerSize(_viewSplitter->activeContainer(), 10);
+ _viewContainer->activeViewSplitter()->adjustActiveTerminalDisplaySize(10);
}
void ViewManager::shrinkActiveContainer()
{
- _viewSplitter->adjustContainerSize(_viewSplitter->activeContainer(), -10);
-}
-
-void ViewManager::closeActiveContainer()
-{
- // only do something if there is more than one container active
- if (_viewSplitter->containers().count() > 1) {
- TabbedViewContainer *container = _viewSplitter->activeContainer();
-
- removeContainer(container);
-
- // focus next container so that user can continue typing
- // without having to manually focus it themselves
- nextContainer();
- }
-}
-
-void ViewManager::closeOtherContainers()
-{
- TabbedViewContainer *active = _viewSplitter->activeContainer();
-
- foreach (TabbedViewContainer *container, _viewSplitter->containers()) {
- if (container != active) {
- removeContainer(container);
- }
- }
+ _viewContainer->activeViewSplitter()->adjustActiveTerminalDisplaySize(-10);
}
SessionController *ViewManager::createController(Session *session, TerminalDisplay *view)
@@ -583,13 +587,27 @@
return controller;
}
+// should this be handed by ViewManager::unplugController signal
+void ViewManager::removeController(SessionController* controller)
+{
+ disconnect(controller, &Konsole::SessionController::focused, this,
+ &Konsole::ViewManager::controllerChanged);
+ if (_pluggedController == controller) {
+ _pluggedController = nullptr;
+ }
+ controller->deleteLater();
+}
+
void ViewManager::controllerChanged(SessionController *controller)
{
if (controller == _pluggedController) {
return;
}
- _viewSplitter->setFocusProxy(controller->view());
+ //TODO: Verify This.
+ // _viewSplitter->setFocusProxy(controller->view());
+
+ updateTerminalDisplayHistory(controller->view());
_pluggedController = controller;
emit activeViewChanged(controller);
@@ -600,16 +618,26 @@
return _pluggedController;
}
-void ViewManager::createView(Session *session, TabbedViewContainer *container, int index)
+void ViewManager::attachView(TerminalDisplay *terminal, Session *session)
+{
+ connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished,
+ Qt::UniqueConnection);
+ _sessionMap[terminal] = session;
+ createController(session, terminal);
+ updateDetachViewState();
+ _terminalDisplayHistory.append(terminal);
+}
+
+TerminalDisplay *ViewManager::createView(Session *session)
{
// notify this view manager when the session finishes so that its view
// can be deleted
//
// Use Qt::UniqueConnection to avoid duplicate connection
connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished,
Qt::UniqueConnection);
-
TerminalDisplay *display = createTerminalDisplay(session);
+
const Profile::Ptr profile = SessionManager::instance()->sessionProfile(session);
applyProfileToView(display, profile);
@@ -620,32 +648,22 @@
createController(session, display);
_sessionMap[display] = session;
- container->addView(display, index);
session->addView(display);
+ _terminalDisplayHistory.append(display);
// tell the session whether it has a light or dark background
session->setDarkBackground(colorSchemeForProfile(profile)->hasDarkBackground());
- container->setCurrentWidget(display);
display->setFocus(Qt::OtherFocusReason);
-
updateDetachViewState();
-}
-void ViewManager::createView(TabbedViewContainer *tabWidget, Session *session)
-{
- const int index = _newTabBehavior == PutNewTabAfterCurrentTab ?
- _viewSplitter->activeContainer()->currentIndex() + 1 : -1;
-
- createView(session, tabWidget, index);
+ return display;
}
TabbedViewContainer *ViewManager::createContainer()
{
-
- auto *container = new TabbedViewContainer(this, _viewSplitter);
+ auto *container = new TabbedViewContainer(this, nullptr);
container->setNavigationVisibility(_navigationVisibility);
- //TODO: Fix Detaching.
- connect(container, &TabbedViewContainer::detachTab, this, &ViewManager::detachView);
+ connect(container, &TabbedViewContainer::detachTab, this, &ViewManager::detachTab);
// connect signals and slots
connect(container, &Konsole::TabbedViewContainer::viewAdded, this,
@@ -662,28 +680,14 @@
this, &ViewManager::newViewRequest);
connect(container, &Konsole::TabbedViewContainer::newViewWithProfileRequest,
this, &Konsole::ViewManager::newViewWithProfileRequest);
- connect(container, &Konsole::TabbedViewContainer::moveViewRequest, this,
- &Konsole::ViewManager::containerMoveViewRequest);
connect(container, &Konsole::TabbedViewContainer::viewRemoved, this,
&Konsole::ViewManager::viewDestroyed);
connect(container, &Konsole::TabbedViewContainer::activeViewChanged, this,
&Konsole::ViewManager::viewActivated);
return container;
}
-void ViewManager::containerMoveViewRequest(int index, int id)
-{
- auto *container = qobject_cast(sender());
- auto *controller = qobject_cast(ViewProperties::propertiesById(id));
- Q_ASSERT(container);
- Q_ASSERT(controller);
-
- createView(controller->session(), container, index);
- controller->session()->refresh();
- container->currentWidget()->setFocus();
-}
-
void ViewManager::setNavigationMethod(NavigationMethod method)
{
Q_ASSERT(_actionCollection);
@@ -731,9 +735,8 @@
void ViewManager::containerViewsChanged(TabbedViewContainer *container)
{
- if ((!_viewSplitter.isNull()) && container == _viewSplitter->activeContainer()) {
- emit viewPropertiesChanged(viewProperties());
- }
+ // TODO: Verify that this is right.
+ emit viewPropertiesChanged(viewProperties());
}
void ViewManager::viewDestroyed(QWidget *view)
@@ -753,9 +756,8 @@
}
}
//we only update the focus if the splitter is still alive
- if (!_viewSplitter.isNull()) {
- updateDetachViewState();
- }
+ updateDetachViewState();
+
// The below causes the menus to be messed up
// Only happens when using the tab bar close button
// if (_pluggedController)
@@ -887,18 +889,16 @@
{
QList list;
- TabbedViewContainer *container = _viewSplitter->activeContainer();
+ TabbedViewContainer *container = _viewContainer;
if (container == nullptr) {
return {};
}
- list.reserve(container->count());
+ auto terminalContainers = _viewContainer->findChildren();
+ list.reserve(terminalContainers.size());
- for(int i = 0, end = container->count(); i < end; i++) {
- auto view = container->terminalAt(i);
- ViewProperties *properties = view->sessionController();
- Q_ASSERT(properties);
- list << properties;
+ for(auto terminalDisplay : _viewContainer->findChildren()) {
+ list.append(terminalDisplay->sessionController());
}
return list;
@@ -911,15 +911,17 @@
QSet unique;
int tab = 1;
- TabbedViewContainer *container = _viewSplitter->activeContainer();
+ TabbedViewContainer *container = _viewContainer;
// first: sessions in the active container, preserving the order
Q_ASSERT(container);
if (container == nullptr) {
return;
}
ids.reserve(container->count());
+ //TODO: Handle sessions
+#if 0
auto *activeview = qobject_cast(container->currentWidget());
for (int i = 0, end = container->count(); i < end; i++) {
auto *view = qobject_cast(container->widget(i));
@@ -933,6 +935,7 @@
}
tab++;
}
+#endif
// second: all other sessions, in random order
// we don't want to have sessions restored that are not connected
@@ -948,7 +951,7 @@
TabbedViewContainer *ViewManager::activeContainer()
{
- return _viewSplitter->activeContainer();
+ return _viewContainer;
}
void ViewManager::restoreSessions(const KConfigGroup &group)
@@ -968,7 +971,7 @@
break;
}
- createView(activeContainer(), session);
+ createView(session);
if (!session->isRunning()) {
session->run();
}
@@ -978,14 +981,14 @@
}
if (display != nullptr) {
- _viewSplitter->activeContainer()->setCurrentWidget(display);
+ activeContainer()->setCurrentWidget(display);
display->setFocus(Qt::OtherFocusReason);
}
if (ids.isEmpty()) { // Session file is unusable, start default Profile
Profile::Ptr profile = ProfileManager::instance()->defaultProfile();
Session *session = SessionManager::instance()->createSession(profile);
- createView(activeContainer(), session);
+ createView(session);
if (!session->isRunning()) {
session->run();
}
@@ -1025,7 +1028,7 @@
QHash::const_iterator i;
for (i = _sessionMap.constBegin(); i != _sessionMap.constEnd(); ++i) {
if (i.value()->sessionId() == sessionId) {
- TabbedViewContainer *container = _viewSplitter->activeContainer();
+ TabbedViewContainer *container = activeContainer();
if (container != nullptr) {
container->setCurrentWidget(i.key());
}
@@ -1040,7 +1043,7 @@
session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId()));
- createView(activeContainer(), session);
+ createView(session);
session->run();
return session->sessionId();
@@ -1062,7 +1065,7 @@
session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId()));
- createView(activeContainer(), session);
+ createView(session);
session->run();
return session->sessionId();
@@ -1085,7 +1088,7 @@
session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId()));
- createView(activeContainer(), session);
+ createView(session);
session->run();
return session->sessionId();
@@ -1123,22 +1126,47 @@
void ViewManager::setTabWidthToText(bool setTabWidthToText)
{
- for(auto container : _viewSplitter->containers()) {
- container->tabBar()->setExpanding(!setTabWidthToText);
- container->tabBar()->update();
- }
+ _viewContainer->tabBar()->setExpanding(!setTabWidthToText);
+ _viewContainer->tabBar()->update();
}
void ViewManager::setNavigationVisibility(NavigationVisibility navigationVisibility) {
if (_navigationVisibility != navigationVisibility) {
_navigationVisibility = navigationVisibility;
- for(auto *container : _viewSplitter->containers()) {
- container->setNavigationVisibility(navigationVisibility);
- }
+ _viewContainer->setNavigationVisibility(navigationVisibility);
}
}
void ViewManager::setNavigationBehavior(int behavior)
{
_newTabBehavior = static_cast(behavior);
}
+
+void ViewManager::updateTerminalDisplayHistory(TerminalDisplay* terminalDisplay, bool remove)
+{
+ if (terminalDisplay == nullptr) {
+ if (_terminalDisplayHistoryIndex >= 0) {
+ // This is the case when we finished walking through the history
+ // (i.e. when Ctrl-Tab has been released)
+ terminalDisplay = _terminalDisplayHistory[_terminalDisplayHistoryIndex];
+ _terminalDisplayHistoryIndex = -1;
+ } else {
+ return;
+ }
+ }
+
+ if (_terminalDisplayHistoryIndex >= 0 && !remove) {
+ // Do not reorder the tab history while we are walking through it
+ return;
+ }
+
+ for (int i = 0; i < _terminalDisplayHistory.count(); i++) {
+ if (_terminalDisplayHistory[i] == terminalDisplay) {
+ _terminalDisplayHistory.removeAt(i);
+ if (!remove) {
+ _terminalDisplayHistory.prepend(terminalDisplay);
+ }
+ break;
+ }
+ }
+}
diff --git a/src/ViewSplitter.h b/src/ViewSplitter.h
--- a/src/ViewSplitter.h
+++ b/src/ViewSplitter.h
@@ -26,10 +26,13 @@
#include
#include
+// Konsole
+#include "konsoleprivate_export.h"
+
class QFocusEvent;
namespace Konsole {
-class TabbedViewContainer;
+class TerminalDisplay;
/**
* A splitter which holds a number of ViewContainer objects and allows
@@ -43,7 +46,7 @@
* insert a new view container.
* Containers can only be removed from the hierarchy by deleting them.
*/
-class ViewSplitter : public QSplitter
+class KONSOLEPRIVATE_EXPORT ViewSplitter : public QSplitter
{
Q_OBJECT
@@ -65,10 +68,10 @@
* will be created, into which the container will
* be inserted.
*/
- void addContainer(TabbedViewContainer *container, Qt::Orientation orientation);
+ void addTerminalDisplay(TerminalDisplay *terminalDisplay, Qt::Orientation orientation);
/** Removes a container from the splitter. The container is not deleted. */
- void removeContainer(TabbedViewContainer *container);
+ void removeTerminalDisplay(TerminalDisplay *terminalDisplay);
/** Returns the child ViewSplitter widget which currently has the focus */
ViewSplitter *activeSplitter();
@@ -84,25 +87,25 @@
* mySplitter->activeSplitter()->activeContainer() where mySplitter
* is the ViewSplitter widget at the top of the hierarchy.
*/
- TabbedViewContainer *activeContainer() const;
+ TerminalDisplay *activeTerminalDisplay() const;
- /**
- * Gives the focus to the active view in the specified container
+ /** Makes the current TerminalDisplay expanded to 100% of the view
*/
- void setActiveContainer(TabbedViewContainer *container);
+ void maximizeCurrentTerminal();
- /**
- * Returns a list of the containers held by this splitter
+ /** Restore the sizes of the terminals.
*/
- QList containers() const
- {
- return _containers;
- }
+ void restoreOtherTerminals();
+
+ void handleMinimizeMaximize(bool maximize);
+
+ /** returns the splitter that has no splitter as a parent. */
+ ViewSplitter *getToplevelSplitter();
/**
- * Gives the focus to the active view in the next container
+ * Gives the focus to the active view in the specified container
*/
- void activateNextContainer();
+ void setActiveTerminalDisplay(TerminalDisplay *container);
/**
* Changes the size of the specified @p container by a given @p percentage.
@@ -113,73 +116,21 @@
* The sizes of the remaining containers are increased or decreased
* uniformly to maintain the width of the splitter.
*/
- void adjustContainerSize(TabbedViewContainer *container, int percentage);
+ void adjustActiveTerminalDisplaySize(int percentage);
- /**
- * Gives the focus to the active view in the previous container
- */
- void activatePreviousContainer();
+ void focusUp();
+ void focusDown();
+ void focusLeft();
+ void focusRight();
- /**
- * Specifies whether the view may be split recursively.
- *
- * If this is false, all containers will be placed into the same
- * top-level splitter. Adding a container with an orientation
- * which is different to that specified when adding the previous
- * containers will change the orientation for all dividers
- * between containers.
- *
- * If this is true, adding a container to the view splitter with
- * an orientation different to the orientation of the previous
- * area will result in the previously active container being
- * replaced with a new splitter containing the active container
- * and the newly added container.
- */
- void setRecursiveSplitting(bool recursive);
+ void handleFocusDirection(Qt::Orientation orientation, int direction);
- /**
- * Returns whether the view may be split recursively.
- * See setRecursiveSplitting()
- */
- bool recursiveSplitting() const;
-
-Q_SIGNALS:
- /** Signal emitted when the last child widget is removed from the splitter */
- void empty(ViewSplitter *splitter);
-
- /**
- * Signal emitted when the containers held by this splitter become empty, this
- * differs from the empty() signal which is only emitted when all of the containers
- * are deleted. This signal is emitted even if there are still container widgets.
- *
- * TODO: This does not yet work recursively (ie. when splitters inside splitters have empty containers)
- */
- void allContainersEmpty();
+ void childEvent(QChildEvent* event) override;
-protected:
- //virtual void focusEvent(QFocusEvent* event);
+ QList getTerminalDisplays();
private:
- // Adds container to splitter's internal list and
- // connects signals and slots
- void registerContainer(TabbedViewContainer *container);
- // Removes container from splitter's internal list and
- // removes signals and slots
- void unregisterContainer(TabbedViewContainer *container);
-
void updateSizes();
-
-private Q_SLOTS:
- // Called to indicate that a child ViewContainer is empty
- void containerEmpty(TabbedViewContainer *container);
-
- // Called to indicate that a child ViewSplitter is empty
- // (ie. all child widgets have been deleted)
- void childEmpty(ViewSplitter *splitter);
-
-private:
- QList _containers;
- bool _recursiveSplitting;
};
}
#endif //VIEWSPLITTER_H
diff --git a/src/ViewSplitter.cpp b/src/ViewSplitter.cpp
--- a/src/ViewSplitter.cpp
+++ b/src/ViewSplitter.cpp
@@ -24,49 +24,38 @@
// Qt
#include
+#include
+#include
// Konsole
#include "ViewContainer.h"
+#include "TerminalDisplay.h"
using Konsole::ViewSplitter;
-using Konsole::TabbedViewContainer;
+using Konsole::TerminalDisplay;
+
+//TODO: Connect the TerminalDisplay destroyed signal here.
ViewSplitter::ViewSplitter(QWidget *parent) :
- QSplitter(parent),
- _containers(QList()),
- _recursiveSplitting(true)
+ QSplitter(parent)
{
}
-void ViewSplitter::childEmpty(ViewSplitter *splitter)
+void ViewSplitter::adjustActiveTerminalDisplaySize(int percentage)
{
- delete splitter;
-
- if (count() == 0) {
- emit empty(this);
- }
-}
-
-void ViewSplitter::adjustContainerSize(TabbedViewContainer *container, int percentage)
-{
- int containerIndex = indexOf(container);
-
+ const int containerIndex = indexOf(activeTerminalDisplay());
Q_ASSERT(containerIndex != -1);
QList containerSizes = sizes();
const int oldSize = containerSizes[containerIndex];
- const auto newSize = static_cast(oldSize * (1.0 + percentage / 100.0));
-
+ const int newSize = static_cast(oldSize * (1.0 + percentage / 100.0));
const int perContainerDelta = (count() == 1) ? 0 : ((newSize - oldSize) / (count() - 1)) * (-1);
- for (int i = 0; i < containerSizes.count(); i++) {
- if (i == containerIndex) {
- containerSizes[i] = newSize;
- } else {
- containerSizes[i] = containerSizes[i] + perContainerDelta;
- }
+ for (int& size : containerSizes) {
+ size += perContainerDelta;
}
+ containerSizes[containerIndex] = newSize;
setSizes(containerSizes);
}
@@ -86,194 +75,160 @@
return splitter;
}
-void ViewSplitter::registerContainer(TabbedViewContainer *container)
-{
- _containers << container;
- connect(container, &TabbedViewContainer::empty, this, &ViewSplitter::containerEmpty);
-}
-
-void ViewSplitter::unregisterContainer(TabbedViewContainer *container)
-{
- _containers.removeAll(container);
- disconnect(container, nullptr, this, nullptr);
-}
-
void ViewSplitter::updateSizes()
{
- int space;
-
- if (orientation() == Qt::Horizontal) {
- space = width() / count();
- } else {
- space = height() / count();
- }
-
- QList widgetSizes;
- const int widgetCount = count();
- widgetSizes.reserve(widgetCount);
- for (int i = 0; i < widgetCount; i++) {
- widgetSizes << space;
- }
-
- setSizes(widgetSizes);
-}
-
-void ViewSplitter::setRecursiveSplitting(bool recursive)
-{
- _recursiveSplitting = recursive;
-}
-
-bool ViewSplitter::recursiveSplitting() const
-{
- return _recursiveSplitting;
+ const int space = (orientation() == Qt::Horizontal ? width() : height()) / count();
+ setSizes(QVector(count(), space).toList());
}
-void ViewSplitter::removeContainer(TabbedViewContainer *container)
-{
- Q_ASSERT(containers().contains(container));
-
- unregisterContainer(container);
-}
-
-void ViewSplitter::addContainer(TabbedViewContainer *container, Qt::Orientation containerOrientation)
+void ViewSplitter::addTerminalDisplay(TerminalDisplay *terminalDisplay, Qt::Orientation containerOrientation)
{
ViewSplitter *splitter = activeSplitter();
if (splitter->count() < 2
- || containerOrientation == splitter->orientation()
- || !_recursiveSplitting) {
- splitter->registerContainer(container);
- splitter->addWidget(container);
+ || containerOrientation == splitter->orientation()) {
+ splitter->addWidget(terminalDisplay);
if (splitter->orientation() != containerOrientation) {
splitter->setOrientation(containerOrientation);
}
-
splitter->updateSizes();
} else {
- auto newSplitter = new ViewSplitter(this);
- connect(newSplitter, &Konsole::ViewSplitter::empty, splitter,
- &Konsole::ViewSplitter::childEmpty);
-
- TabbedViewContainer *oldContainer = splitter->activeContainer();
- const int oldContainerIndex = splitter->indexOf(oldContainer);
-
- splitter->unregisterContainer(oldContainer);
-
- newSplitter->registerContainer(oldContainer);
- newSplitter->registerContainer(container);
+ auto newSplitter = new ViewSplitter();
- newSplitter->addWidget(oldContainer);
- newSplitter->addWidget(container);
+ TerminalDisplay *oldTerminalDisplay = splitter->activeTerminalDisplay();
+ const int oldContainerIndex = splitter->indexOf(oldTerminalDisplay);
+ newSplitter->addWidget(oldTerminalDisplay);
+ newSplitter->addWidget(terminalDisplay);
newSplitter->setOrientation(containerOrientation);
newSplitter->updateSizes();
newSplitter->show();
splitter->insertWidget(oldContainerIndex, newSplitter);
}
}
-void ViewSplitter::containerEmpty(TabbedViewContainer * myContainer)
+void ViewSplitter::childEvent(QChildEvent *event)
{
- _containers.removeAll(myContainer);
- if (count() == 0) {
- emit empty(this);
- }
-
- int children = 0;
- foreach (auto container, _containers) {
- children += container->count();
- }
-
- if (children == 0) {
- emit allContainersEmpty();
- }
+ QSplitter::childEvent(event);
- // This container is no more, try to find another container to focus.
- ViewSplitter *currentSplitter = activeSplitter();
- while(qobject_cast(currentSplitter->parent())) {
- currentSplitter = qobject_cast(currentSplitter->parent());
- }
-
- for(auto tabWidget : currentSplitter->findChildren()) {
- if (tabWidget != myContainer && tabWidget->count()) {
- tabWidget->setCurrentIndex(0);
+ if (event->removed()) {
+ if (count() == 0) {
+ deleteLater();
+ }
+ if (!findChild()) {
+ deleteLater();
}
}
}
-void ViewSplitter::activateNextContainer()
+void ViewSplitter::handleFocusDirection(Qt::Orientation orientation, int direction)
{
- TabbedViewContainer *active = activeContainer();
+ auto terminalDisplay = activeTerminalDisplay();
+ auto parentSplitter = qobject_cast(terminalDisplay->parentWidget());
+ auto topSplitter = parentSplitter->getToplevelSplitter();
- int index = _containers.indexOf(active);
+ const auto handleWidth = parentSplitter->handleWidth() <= 1 ? 4 : parentSplitter->handleWidth();
- if (index == -1) {
- return;
- }
+ const auto start = QPoint(terminalDisplay->x(), terminalDisplay->y());
+ const auto startMapped = parentSplitter->mapTo(topSplitter, start);
- if (index == _containers.count() - 1) {
- index = 0;
- } else {
- index++;
+ const int newX = orientation != Qt::Horizontal ? startMapped.x() + handleWidth
+ : direction == 1 ? startMapped.x() + terminalDisplay->width() + handleWidth
+ : startMapped.x() - handleWidth;
+
+ const int newY = orientation != Qt::Vertical ? startMapped.y() + handleWidth
+ : direction == 1 ? startMapped.y() + terminalDisplay->height() + handleWidth
+ : startMapped.y() - handleWidth;
+
+ const auto newPoint = QPoint(newX, newY);
+ auto child = topSplitter->childAt(newPoint);
+
+ if (TerminalDisplay* terminal = qobject_cast(child)) {
+ terminal->setFocus(Qt::OtherFocusReason);
+ } else if (qobject_cast(child)) {
+ auto terminal = qobject_cast(child->parent());
+ terminal->setFocus(Qt::OtherFocusReason);
+ } else if (qobject_cast(child)) {
+ auto targetSplitter = qobject_cast(child->parent());
+ auto terminal = qobject_cast(targetSplitter->widget(0));
+ terminal->setFocus(Qt::OtherFocusReason);
}
+}
- setActiveContainer(_containers.at(index));
+void ViewSplitter::focusUp()
+{
+ handleFocusDirection(Qt::Vertical, -1);
}
-void ViewSplitter::activatePreviousContainer()
+void ViewSplitter::focusDown()
{
- TabbedViewContainer *active = activeContainer();
+ handleFocusDirection(Qt::Vertical, +1);
+}
- int index = _containers.indexOf(active);
+void ViewSplitter::focusLeft()
+{
+ handleFocusDirection(Qt::Horizontal, -1);
+}
- if (index == 0) {
- index = _containers.count() - 1;
- } else {
- index--;
- }
+void ViewSplitter::focusRight()
+{
+ handleFocusDirection(Qt::Horizontal, +1);
+}
- setActiveContainer(_containers.at(index));
+TerminalDisplay *ViewSplitter::activeTerminalDisplay() const
+{
+ auto focusedWidget = qobject_cast(focusWidget());
+ return focusedWidget ? focusedWidget : findChild();
}
-void ViewSplitter::setActiveContainer(TabbedViewContainer *container)
+void ViewSplitter::maximizeCurrentTerminal()
{
- QWidget *activeView = container->currentWidget();
+ handleMinimizeMaximize(true);
+}
- if (activeView != nullptr) {
- activeView->setFocus(Qt::OtherFocusReason);
- }
+void ViewSplitter::restoreOtherTerminals()
+{
+ handleMinimizeMaximize(false);
}
-TabbedViewContainer *ViewSplitter::activeContainer() const
+void ViewSplitter::handleMinimizeMaximize(bool maximize)
{
- if (QWidget *focusW = focusWidget()) {
- TabbedViewContainer *focusContainer = nullptr;
-
- while (focusW != nullptr) {
- foreach (TabbedViewContainer *container, _containers) {
- if (container == focusW) {
- focusContainer = container;
- break;
- }
- }
- focusW = focusW->parentWidget();
+ auto viewSplitter = getToplevelSplitter();
+ auto terminalDisplays = viewSplitter->findChildren();
+ auto currentActiveTerminal = viewSplitter->activeTerminalDisplay();
+ auto method = maximize ? &QWidget::hide : &QWidget::show;
+ for(auto terminal : terminalDisplays) {
+ if (Q_LIKELY(currentActiveTerminal != terminal)) {
+ (terminal->*method)();
}
+ }
+}
- if (focusContainer != nullptr) {
- return focusContainer;
- }
+ViewSplitter *ViewSplitter::getToplevelSplitter()
+{
+ ViewSplitter *current = this;
+ while(qobject_cast(current->parentWidget())) {
+ current = qobject_cast(current->parentWidget());
}
+ return current;
+}
- QList splitters = findChildren();
+QList ViewSplitter::getTerminalDisplays() {
+ auto terminals = QList();
+ auto count = this->count();
+ for(int i=0; i < count; ++i) {
+ auto widget = this->widget(i);
- if (!splitters.isEmpty()) {
- return splitters.last()->activeContainer();
- } else {
- if (!_containers.isEmpty()) {
- return _containers.last();
- } else {
- return nullptr;
+ auto terminal = qobject_cast(widget);
+ if (terminal != nullptr) {
+ terminals.append(terminal);
+ }
+ auto splitter = qobject_cast(widget);
+ if (splitter != nullptr) {
+ terminals.append(splitter->getTerminalDisplays());
}
}
+
+ return terminals;
}