Changeset View
Changeset View
Standalone View
Standalone View
src/ViewManager.cpp
Show All 18 Lines | |||||
19 | 19 | | |||
20 | // Own | 20 | // Own | ||
21 | #include "ViewManager.h" | 21 | #include "ViewManager.h" | ||
22 | 22 | | |||
23 | #include <config-konsole.h> | 23 | #include <config-konsole.h> | ||
24 | 24 | | |||
25 | // Qt | 25 | // Qt | ||
26 | #include <QStringList> | 26 | #include <QStringList> | ||
27 | #include <QAction> | | |||
28 | #include <QTabBar> | 27 | #include <QTabBar> | ||
29 | 28 | | |||
30 | // KDE | 29 | // KDE | ||
31 | #include <KAcceleratorManager> | 30 | #include <KAcceleratorManager> | ||
32 | #include <KLocalizedString> | 31 | #include <KLocalizedString> | ||
33 | #include <KActionCollection> | 32 | #include <KActionCollection> | ||
34 | #include <KConfigGroup> | 33 | #include <KConfigGroup> | ||
35 | 34 | | |||
Show All 12 Lines | |||||
48 | #include "ViewContainer.h" | 47 | #include "ViewContainer.h" | ||
49 | 48 | | |||
50 | using namespace Konsole; | 49 | using namespace Konsole; | ||
51 | 50 | | |||
52 | int ViewManager::lastManagerId = 0; | 51 | int ViewManager::lastManagerId = 0; | ||
53 | 52 | | |||
54 | ViewManager::ViewManager(QObject *parent, KActionCollection *collection) : | 53 | ViewManager::ViewManager(QObject *parent, KActionCollection *collection) : | ||
55 | QObject(parent), | 54 | QObject(parent), | ||
56 | _viewSplitter(nullptr), | 55 | _viewContainer(nullptr), | ||
57 | _pluggedController(nullptr), | 56 | _pluggedController(nullptr), | ||
58 | _sessionMap(QHash<TerminalDisplay *, Session *>()), | 57 | _sessionMap(QHash<TerminalDisplay *, Session *>()), | ||
59 | _actionCollection(collection), | 58 | _actionCollection(collection), | ||
60 | _navigationMethod(NoNavigation), | 59 | _navigationMethod(NoNavigation), | ||
61 | _navigationVisibility(NavigationNotSet), | 60 | _navigationVisibility(NavigationNotSet), | ||
62 | _newTabBehavior(PutNewTabAtTheEnd), | 61 | _newTabBehavior(PutNewTabAtTheEnd), | ||
63 | _managerId(0) | 62 | _managerId(0), | ||
63 | _terminalDisplayHistoryIndex(-1) | ||||
64 | { | 64 | { | ||
65 | // create main view area | 65 | _viewContainer = createContainer(); | ||
66 | _viewSplitter = new ViewSplitter(nullptr); | | |||
67 | KAcceleratorManager::setNoAccel(_viewSplitter); | | |||
68 | | ||||
69 | // the ViewSplitter class supports both recursive and non-recursive splitting, | | |||
70 | // in non-recursive mode, all containers are inserted into the same top-level splitter | | |||
71 | // widget, and all the divider lines between the containers have the same orientation | | |||
72 | // | | |||
73 | // the ViewManager class is not currently able to handle a ViewSplitter in recursive-splitting | | |||
74 | // mode | | |||
75 | _viewSplitter->setRecursiveSplitting(false); | | |||
76 | _viewSplitter->setFocusPolicy(Qt::NoFocus); | | |||
77 | | ||||
78 | // setup actions which are related to the views | 66 | // setup actions which are related to the views | ||
79 | setupActions(); | 67 | setupActions(); | ||
80 | 68 | | |||
69 | /* TODO: Reconnect | ||||
81 | // emit a signal when all of the views held by this view manager are destroyed | 70 | // emit a signal when all of the views held by this view manager are destroyed | ||
82 | connect(_viewSplitter.data(), &Konsole::ViewSplitter::allContainersEmpty, | 71 | */ | ||
72 | connect(_viewContainer.data(), &Konsole::TabbedViewContainer::empty, | ||||
83 | this, &Konsole::ViewManager::empty); | 73 | this, &Konsole::ViewManager::empty); | ||
84 | connect(_viewSplitter.data(), &Konsole::ViewSplitter::empty, this, | | |||
85 | &Konsole::ViewManager::empty); | | |||
86 | 74 | | |||
87 | // listen for profile changes | 75 | // listen for profile changes | ||
88 | connect(ProfileManager::instance(), &Konsole::ProfileManager::profileChanged, | 76 | connect(ProfileManager::instance(), &Konsole::ProfileManager::profileChanged, | ||
89 | this, &Konsole::ViewManager::profileChanged); | 77 | this, &Konsole::ViewManager::profileChanged); | ||
90 | connect(SessionManager::instance(), &Konsole::SessionManager::sessionUpdated, | 78 | connect(SessionManager::instance(), &Konsole::SessionManager::sessionUpdated, | ||
91 | this, &Konsole::ViewManager::updateViewsForSession); | 79 | this, &Konsole::ViewManager::updateViewsForSession); | ||
92 | 80 | | |||
93 | //prepare DBus communication | 81 | //prepare DBus communication | ||
94 | new WindowAdaptor(this); | 82 | new WindowAdaptor(this); | ||
95 | 83 | | |||
96 | _managerId = ++lastManagerId; | 84 | _managerId = ++lastManagerId; | ||
97 | QDBusConnection::sessionBus().registerObject(QLatin1String("/Windows/") | 85 | QDBusConnection::sessionBus().registerObject(QLatin1String("/Windows/") | ||
98 | + QString::number(_managerId), this); | 86 | + QString::number(_managerId), this); | ||
99 | | ||||
100 | _viewSplitter->addContainer(createContainer(), Qt::Vertical); | | |||
101 | } | 87 | } | ||
102 | 88 | | |||
103 | ViewManager::~ViewManager() = default; | 89 | ViewManager::~ViewManager() = default; | ||
104 | 90 | | |||
105 | int ViewManager::managerId() const | 91 | int ViewManager::managerId() const | ||
106 | { | 92 | { | ||
107 | return _managerId; | 93 | return _managerId; | ||
108 | } | 94 | } | ||
109 | 95 | | |||
110 | QWidget *ViewManager::activeView() const | 96 | QWidget *ViewManager::activeView() const | ||
111 | { | 97 | { | ||
112 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 98 | return _viewContainer->currentWidget(); | ||
113 | if (container != nullptr) { | | |||
114 | return container->currentWidget(); | | |||
115 | } else { | | |||
116 | return nullptr; | | |||
117 | } | | |||
118 | } | 99 | } | ||
119 | 100 | | |||
120 | QWidget *ViewManager::widget() const | 101 | QWidget *ViewManager::widget() const | ||
121 | { | 102 | { | ||
122 | return _viewSplitter; | 103 | return _viewContainer; | ||
123 | } | 104 | } | ||
124 | 105 | | |||
125 | void ViewManager::setupActions() | 106 | void ViewManager::setupActions() | ||
126 | { | 107 | { | ||
127 | Q_ASSERT(_actionCollection); | 108 | Q_ASSERT(_actionCollection); | ||
128 | if (_actionCollection == nullptr) { | 109 | if (_actionCollection == nullptr) { | ||
129 | return; | 110 | return; | ||
130 | } | 111 | } | ||
131 | 112 | | |||
132 | KActionCollection *collection = _actionCollection; | 113 | KActionCollection *collection = _actionCollection; | ||
133 | 114 | | |||
134 | QAction *nextViewAction = new QAction(i18nc("@action Shortcut entry", "Next Tab"), this); | 115 | // Let's reuse the pointer, no need not to. | ||
135 | QAction *previousViewAction = new QAction(i18nc("@action Shortcut entry", "Previous Tab"), this); | 116 | auto *action = new QAction(); | ||
136 | QAction *lastViewAction = new QAction(i18nc("@action Shortcut entry", | 117 | action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-left-right"))); | ||
137 | "Switch to Last Tab"), this); | 118 | action->setText(i18nc("@action:inmenu", "Split View Left/Right")); | ||
138 | QAction *lastUsedViewAction = new QAction(i18nc("@action Shortcut entry", "Last Used Tabs"), this); | 119 | connect(action, &QAction::triggered, this, &ViewManager::splitLeftRight); | ||
139 | QAction *lastUsedViewReverseAction = new QAction(i18nc("@action Shortcut entry", | 120 | collection->addAction(QStringLiteral("split-view-left-right"), action); | ||
140 | "Last Used Tabs (Reverse)"), this); | 121 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::Key_ParenLeft); | ||
141 | QAction *toggleTwoViewsAction = new QAction(i18nc("@action Shortcut entry", "Toggle Between Two Tabs"), this); | 122 | | ||
142 | QAction *nextContainerAction = new QAction(i18nc("@action Shortcut entry", | 123 | action = new QAction(); | ||
143 | "Next View Container"), this); | 124 | action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-top-bottom"))); | ||
144 | 125 | action->setText(i18nc("@action:inmenu", "Split View Top/Bottom")); | |||
145 | QAction *moveViewLeftAction = new QAction(i18nc("@action Shortcut entry", "Move Tab Left"), this); | 126 | connect(action, &QAction::triggered, this, &ViewManager::splitTopBottom); | ||
146 | QAction *moveViewRightAction = new QAction(i18nc("@action Shortcut entry", | 127 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::Key_ParenRight); | ||
147 | "Move Tab Right"), this); | 128 | collection->addAction(QStringLiteral("split-view-top-bottom"), action); | ||
148 | 129 | | |||
149 | // list of actions that should only be enabled when there are multiple view | 130 | action = new QAction(); | ||
150 | // containers open | 131 | action->setText(i18nc("@action:inmenu", "Expand View")); | ||
151 | QList<QAction *> multiViewOnlyActions; | 132 | action->setEnabled(false); | ||
152 | multiViewOnlyActions << nextContainerAction; | 133 | connect(action, &QAction::triggered, this, &ViewManager::expandActiveContainer); | ||
153 | 134 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketRight); | |||
154 | QAction *splitLeftRightAction = new QAction(QIcon::fromTheme(QStringLiteral("view-split-left-right")), | 135 | collection->addAction(QStringLiteral("expand-active-view"), action); | ||
155 | i18nc("@action:inmenu", "Split View Left/Right"), | 136 | _multiSplitterOnlyActions << action; | ||
156 | this); | 137 | | ||
157 | collection->setDefaultShortcut(splitLeftRightAction, Konsole::ACCEL + Qt::Key_ParenLeft); | 138 | action = new QAction(); | ||
158 | collection->addAction(QStringLiteral("split-view-left-right"), splitLeftRightAction); | 139 | action->setText(i18nc("@action:inmenu", "Shrink View")); | ||
159 | connect(splitLeftRightAction, &QAction::triggered, this, &Konsole::ViewManager::splitLeftRight); | 140 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketLeft); | ||
160 | 141 | action->setEnabled(false); | |||
161 | QAction *splitTopBottomAction = new QAction(QIcon::fromTheme(QStringLiteral("view-split-top-bottom")), | 142 | collection->addAction(QStringLiteral("shrink-active-view"), action); | ||
162 | i18nc("@action:inmenu", | 143 | connect(action, &QAction::triggered, this, &ViewManager::shrinkActiveContainer); | ||
163 | "Split View Top/Bottom"), this); | 144 | _multiSplitterOnlyActions << action; | ||
164 | collection->setDefaultShortcut(splitTopBottomAction, Konsole::ACCEL + Qt::Key_ParenRight); | | |||
165 | collection->addAction(QStringLiteral("split-view-top-bottom"), splitTopBottomAction); | | |||
166 | connect(splitTopBottomAction, &QAction::triggered, this, &Konsole::ViewManager::splitTopBottom); | | |||
167 | | ||||
168 | QAction *closeActiveAction = new QAction(i18nc("@action:inmenu Close Active View", "Close Active"), this); | | |||
169 | closeActiveAction->setIcon(QIcon::fromTheme(QStringLiteral("view-close"))); | | |||
170 | collection->setDefaultShortcut(closeActiveAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_X); | | |||
171 | closeActiveAction->setEnabled(false); | | |||
172 | collection->addAction(QStringLiteral("close-active-view"), closeActiveAction); | | |||
173 | connect(closeActiveAction, &QAction::triggered, this, | | |||
174 | &Konsole::ViewManager::closeActiveContainer); | | |||
175 | | ||||
176 | multiViewOnlyActions << closeActiveAction; | | |||
177 | | ||||
178 | QAction *closeOtherAction = new QAction(i18nc("@action:inmenu Close Other Views", | | |||
179 | "Close Others"), this); | | |||
180 | collection->setDefaultShortcut(closeOtherAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_O); | | |||
181 | closeOtherAction->setEnabled(false); | | |||
182 | collection->addAction(QStringLiteral("close-other-views"), closeOtherAction); | | |||
183 | connect(closeOtherAction, &QAction::triggered, this, | | |||
184 | &Konsole::ViewManager::closeOtherContainers); | | |||
185 | | ||||
186 | multiViewOnlyActions << closeOtherAction; | | |||
187 | | ||||
188 | // Expand & Shrink Active View | | |||
189 | QAction *expandActiveAction = new QAction(i18nc("@action:inmenu", "Expand View"), this); | | |||
190 | collection->setDefaultShortcut(expandActiveAction, | | |||
191 | Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketRight); | | |||
192 | expandActiveAction->setEnabled(false); | | |||
193 | collection->addAction(QStringLiteral("expand-active-view"), expandActiveAction); | | |||
194 | connect(expandActiveAction, &QAction::triggered, this, | | |||
195 | &Konsole::ViewManager::expandActiveContainer); | | |||
196 | | ||||
197 | multiViewOnlyActions << expandActiveAction; | | |||
198 | | ||||
199 | QAction *shrinkActiveAction = new QAction(i18nc("@action:inmenu", "Shrink View"), this); | | |||
200 | collection->setDefaultShortcut(shrinkActiveAction, | | |||
201 | Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketLeft); | | |||
202 | shrinkActiveAction->setEnabled(false); | | |||
203 | collection->addAction(QStringLiteral("shrink-active-view"), shrinkActiveAction); | | |||
204 | connect(shrinkActiveAction, &QAction::triggered, this, | | |||
205 | &Konsole::ViewManager::shrinkActiveContainer); | | |||
206 | | ||||
207 | multiViewOnlyActions << shrinkActiveAction; | | |||
208 | 145 | | |||
209 | // Crashes on Mac. | 146 | // Crashes on Mac. | ||
210 | #if defined(ENABLE_DETACHING) | 147 | #if defined(ENABLE_DETACHING) | ||
211 | QAction *detachViewAction = collection->addAction(QStringLiteral("detach-view")); | 148 | action = collection->addAction(QStringLiteral("detach-view")); | ||
212 | detachViewAction->setEnabled(true); | 149 | action->setEnabled(true); | ||
213 | detachViewAction->setIcon(QIcon::fromTheme(QStringLiteral("tab-detach"))); | 150 | action->setIcon(QIcon::fromTheme(QStringLiteral("tab-detach"))); | ||
214 | detachViewAction->setText(i18nc("@action:inmenu", "D&etach Current Tab")); | 151 | action->setText(i18nc("@action:inmenu", "Detach Current &View")); | ||
152 | | ||||
153 | connect(action, &QAction::triggered, this, &ViewManager::detachActiveView); | ||||
154 | _multiSplitterOnlyActions << action; | ||||
155 | | ||||
215 | // Ctrl+Shift+D is not used as a shortcut by default because it is too close | 156 | // Ctrl+Shift+D is not used as a shortcut by default because it is too close | ||
216 | // to Ctrl+D - which will terminate the session in many cases | 157 | // to Ctrl+D - which will terminate the session in many cases | ||
217 | collection->setDefaultShortcut(detachViewAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_H); | 158 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_H); | ||
218 | 159 | | |||
219 | connect(this, &Konsole::ViewManager::splitViewToggle, this, | 160 | action = collection->addAction(QStringLiteral("detach-tab")); | ||
220 | &Konsole::ViewManager::updateDetachViewState); | 161 | action->setEnabled(true); | ||
221 | connect(detachViewAction, &QAction::triggered, this, &Konsole::ViewManager::detachActiveView); | 162 | action->setIcon(QIcon::fromTheme(QStringLiteral("tab-detach"))); | ||
163 | action->setText(i18nc("@action:inmenu", "Detach Current &Tab")); | ||||
164 | connect(action, &QAction::triggered, this, &ViewManager::detachActiveTab); | ||||
165 | _multiTabOnlyActions << action; | ||||
166 | // Ctrl+Shift+D is not used as a shortcut by default because it is too close | ||||
167 | // to Ctrl+D - which will terminate the session in many cases | ||||
168 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_L); | ||||
222 | #endif | 169 | #endif | ||
223 | 170 | | |||
224 | // Next / Previous View , Next Container | 171 | // keyboard shortcut only actions | ||
225 | collection->addAction(QStringLiteral("next-view"), nextViewAction); | 172 | action = new QAction(i18nc("@action Shortcut entry", "Next Tab"), this); | ||
226 | collection->addAction(QStringLiteral("previous-view"), previousViewAction); | 173 | const QList<QKeySequence> nextViewActionKeys{Qt::SHIFT + Qt::Key_Right, Qt::CTRL + Qt::Key_PageDown}; | ||
227 | collection->addAction(QStringLiteral("last-tab"), lastViewAction); | 174 | collection->setDefaultShortcuts(action, nextViewActionKeys); | ||
228 | collection->addAction(QStringLiteral("last-used-tab"), lastUsedViewAction); | 175 | collection->addAction(QStringLiteral("next-tab"), action); | ||
229 | collection->addAction(QStringLiteral("last-used-tab-reverse"), lastUsedViewReverseAction); | 176 | connect(action, &QAction::triggered, this, &ViewManager::nextView); | ||
230 | collection->addAction(QStringLiteral("toggle-two-tabs"), toggleTwoViewsAction); | 177 | _multiTabOnlyActions << action; | ||
231 | collection->addAction(QStringLiteral("next-container"), nextContainerAction); | 178 | // _viewSplitter->addAction(nextViewAction); | ||
232 | collection->addAction(QStringLiteral("move-view-left"), moveViewLeftAction); | 179 | | ||
233 | collection->addAction(QStringLiteral("move-view-right"), moveViewRightAction); | 180 | action = new QAction(i18nc("@action Shortcut entry", "Previous Tab"), this); | ||
181 | const QList<QKeySequence> previousViewActionKeys{Qt::SHIFT + Qt::Key_Left, Qt::CTRL + Qt::Key_PageUp}; | ||||
182 | collection->setDefaultShortcuts(action, previousViewActionKeys); | ||||
183 | collection->addAction(QStringLiteral("previous-tab"), action); | ||||
184 | connect(action, &QAction::triggered, this, &ViewManager::previousView); | ||||
185 | _multiTabOnlyActions << action; | ||||
186 | // _viewSplitter->addAction(previousViewAction); | ||||
187 | | ||||
188 | action = new QAction(i18nc("@action Shortcut entry", "Next View Container"), this); | ||||
189 | connect(action, &QAction::triggered, this, &ViewManager::focusUp); | ||||
190 | collection->addAction(QStringLiteral("next-container"), action); | ||||
191 | collection->setDefaultShortcut(action, Qt::SHIFT + Qt::CTRL + Qt::Key_Up); | ||||
192 | _viewContainer->addAction(action); | ||||
193 | _multiSplitterOnlyActions << action; | ||||
194 | | ||||
195 | action = new QAction(QStringLiteral("Focus Down")); | ||||
196 | collection->setDefaultShortcut(action, Qt::SHIFT + Qt::CTRL + Qt::Key_Down); | ||||
197 | connect(action, &QAction::triggered, this, &ViewManager::focusDown); | ||||
198 | _multiSplitterOnlyActions << action; | ||||
199 | _viewContainer->addAction(action); | ||||
200 | | ||||
201 | action = new QAction(i18nc("@action Shortcut entry", "Move Tab Left"), this); | ||||
202 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Konsole::LEFT); | ||||
203 | connect(action, &QAction::triggered, this, &ViewManager::focusLeft); | ||||
204 | collection->addAction(QStringLiteral("move-view-left"), action); | ||||
205 | _multiSplitterOnlyActions << action; | ||||
206 | | ||||
207 | action = new QAction(i18nc("@action Shortcut entry", "Move Tab Right"), this); | ||||
208 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Konsole::RIGHT); | ||||
209 | connect(action, &QAction::triggered, this, &ViewManager::focusRight); | ||||
210 | collection->addAction(QStringLiteral("move-view-right"), action); | ||||
211 | _multiSplitterOnlyActions << action; | ||||
212 | | ||||
213 | action = new QAction(i18nc("@action Shortcut entry", "Switch to Last Tab"), this); | ||||
214 | connect(action, &QAction::triggered, this, &ViewManager::lastView); | ||||
215 | collection->addAction(QStringLiteral("last-tab"), action); | ||||
216 | _multiTabOnlyActions << action; | ||||
217 | | ||||
218 | action = new QAction(i18nc("@action Shortcut entry", "Last Used Tabs"), this); | ||||
219 | connect(action, &QAction::triggered, this, &ViewManager::lastUsedView); | ||||
220 | collection->setDefaultShortcut(action, Qt::CTRL + Qt::Key_Tab); | ||||
221 | collection->addAction(QStringLiteral("last-used-tab"), action); | ||||
222 | _multiTabOnlyActions << action; | ||||
223 | | ||||
224 | action = new QAction(i18nc("@action Shortcut entry", "Toggle Between Two Tabs"), this); | ||||
225 | connect(action, &QAction::triggered, this, &Konsole::ViewManager::toggleTwoViews); | ||||
226 | collection->addAction(QStringLiteral("toggle-two-tabs"), action); | ||||
227 | _multiTabOnlyActions << action; | ||||
228 | | ||||
229 | action = new QAction(i18nc("@action Shortcut entry", "Last Used Tabs (Reverse)"), this); | ||||
230 | collection->addAction(QStringLiteral("last-used-tab-reverse"), action); | ||||
231 | collection->setDefaultShortcut(action, Qt::CTRL + Qt::SHIFT + Qt::Key_Tab); | ||||
232 | connect(action, &QAction::triggered, this, &ViewManager::lastUsedViewReverse); | ||||
233 | _multiTabOnlyActions << action; | ||||
234 | | ||||
235 | action = new QAction(i18nc("@action Shortcut entry", "Maximize current Terminal"), this); | ||||
236 | collection->addAction(QStringLiteral("maximize-current-terminal"), action); | ||||
237 | collection->setDefaultShortcut(action, Qt::CTRL + Qt::SHIFT + Qt::Key_E); | ||||
238 | connect(action, &QAction::triggered, _viewContainer, &TabbedViewContainer::maximizeCurrentTerminal); | ||||
239 | _multiSplitterOnlyActions << action; | ||||
240 | _viewContainer->addAction(action); | ||||
241 | | ||||
242 | action = new QAction(i18nc("@action Shortcut entry", "Restore other terminals"), this); | ||||
243 | collection->addAction(QStringLiteral("restore-other-terminals"), action); | ||||
244 | collection->setDefaultShortcut(action, Qt::CTRL + Qt::SHIFT + Qt::Key_Minus); | ||||
245 | connect(action, &QAction::triggered, _viewContainer, &TabbedViewContainer::restoreOtherTerminals); | ||||
246 | _multiSplitterOnlyActions << action; | ||||
247 | _viewContainer->addAction(action); | ||||
234 | 248 | | |||
235 | // Switch to tab N shortcuts | 249 | // _viewSplitter->addAction(lastUsedViewReverseAction); | ||
236 | const int SWITCH_TO_TAB_COUNT = 19; | 250 | const int SWITCH_TO_TAB_COUNT = 19; | ||
237 | for (int i = 0; i < SWITCH_TO_TAB_COUNT; i++) { | 251 | for (int i = 0; i < SWITCH_TO_TAB_COUNT; i++) { | ||
238 | QAction *switchToTabAction = new QAction(i18nc("@action Shortcut entry", "Switch to Tab %1", i + 1), this); | 252 | action = new QAction(i18nc("@action Shortcut entry", "Switch to Tab %1", i + 1), this); | ||
239 | 253 | connect(action, &QAction::triggered, this, [this, i]() { switchToView(i); }); | |||
240 | connect(switchToTabAction, &QAction::triggered, this, | 254 | collection->addAction(QStringLiteral("switch-to-tab-%1").arg(i), action); | ||
241 | [this, i]() { | | |||
242 | switchToView(i); | | |||
243 | }); | | |||
244 | collection->addAction(QStringLiteral("switch-to-tab-%1").arg(i), switchToTabAction); | | |||
245 | } | 255 | } | ||
246 | 256 | | |||
247 | foreach (QAction *action, multiViewOnlyActions) { | 257 | auto handleMultiTabActionsLambda = [=]{ | ||
248 | connect(this, &Konsole::ViewManager::splitViewToggle, action, &QAction::setEnabled); | 258 | const int count = _viewContainer->count(); | ||
259 | foreach(QAction *action, _multiTabOnlyActions) { | ||||
260 | action->setEnabled(count > 1); | ||||
249 | } | 261 | } | ||
262 | }; | ||||
263 | connect(_viewContainer, &TabbedViewContainer::viewAdded, this, handleMultiTabActionsLambda); | ||||
264 | connect(_viewContainer, &TabbedViewContainer::viewRemoved, this, handleMultiTabActionsLambda); | ||||
250 | 265 | | |||
251 | // keyboard shortcut only actions | 266 | connect(_viewContainer, &QTabWidget::currentChanged, this, &ViewManager::updateDetachViewState); | ||
252 | const QList<QKeySequence> nextViewActionKeys{Qt::SHIFT + Qt::Key_Right, Qt::CTRL + Qt::Key_PageDown}; | | |||
253 | collection->setDefaultShortcuts(nextViewAction, nextViewActionKeys); | | |||
254 | connect(nextViewAction, &QAction::triggered, this, &Konsole::ViewManager::nextView); | | |||
255 | _viewSplitter->addAction(nextViewAction); | | |||
256 | | ||||
257 | const QList<QKeySequence> previousViewActionKeys{Qt::SHIFT + Qt::Key_Left, Qt::CTRL + Qt::Key_PageUp}; | | |||
258 | collection->setDefaultShortcuts(previousViewAction, previousViewActionKeys); | | |||
259 | connect(previousViewAction, &QAction::triggered, this, &Konsole::ViewManager::previousView); | | |||
260 | _viewSplitter->addAction(previousViewAction); | | |||
261 | | ||||
262 | collection->setDefaultShortcut(nextContainerAction, Qt::SHIFT + Qt::Key_Tab); | | |||
263 | connect(nextContainerAction, &QAction::triggered, this, &Konsole::ViewManager::nextContainer); | | |||
264 | _viewSplitter->addAction(nextContainerAction); | | |||
265 | | ||||
266 | #ifdef Q_OS_MACOS | | |||
267 | collection->setDefaultShortcut(moveViewLeftAction, | | |||
268 | Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketLeft); | | |||
269 | #else | | |||
270 | collection->setDefaultShortcut(moveViewLeftAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_Left); | | |||
271 | #endif | | |||
272 | connect(moveViewLeftAction, &QAction::triggered, this, | | |||
273 | &Konsole::ViewManager::moveActiveViewLeft); | | |||
274 | _viewSplitter->addAction(moveViewLeftAction); | | |||
275 | | ||||
276 | #ifdef Q_OS_MACOS | | |||
277 | collection->setDefaultShortcut(moveViewRightAction, | | |||
278 | Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketRight); | | |||
279 | #else | | |||
280 | collection->setDefaultShortcut(moveViewRightAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_Right); | | |||
281 | #endif | | |||
282 | connect(moveViewRightAction, &QAction::triggered, this, | | |||
283 | &Konsole::ViewManager::moveActiveViewRight); | | |||
284 | _viewSplitter->addAction(moveViewRightAction); | | |||
285 | | ||||
286 | connect(lastViewAction, &QAction::triggered, this, &Konsole::ViewManager::lastView); | | |||
287 | _viewSplitter->addAction(lastViewAction); | | |||
288 | | ||||
289 | collection->setDefaultShortcut(lastUsedViewAction, Qt::CTRL + Qt::Key_Tab); | | |||
290 | connect(lastUsedViewAction, &QAction::triggered, this, &Konsole::ViewManager::lastUsedView); | | |||
291 | _viewSplitter->addAction(lastUsedViewAction); | | |||
292 | | ||||
293 | collection->setDefaultShortcut(lastUsedViewReverseAction, Qt::CTRL + Qt::SHIFT + Qt::Key_Tab); | | |||
294 | connect(lastUsedViewReverseAction, &QAction::triggered, this, &Konsole::ViewManager::lastUsedViewReverse); | | |||
295 | _viewSplitter->addAction(lastUsedViewReverseAction); | | |||
296 | 267 | | |||
297 | connect(toggleTwoViewsAction, &QAction::triggered, this, &Konsole::ViewManager::toggleTwoViews); | 268 | // Initial state | ||
298 | _viewSplitter->addAction(toggleTwoViewsAction); | 269 | handleMultiTabActionsLambda(); | ||
270 | updateDetachViewState(); | ||||
299 | } | 271 | } | ||
300 | 272 | | |||
301 | void ViewManager::switchToView(int index) | 273 | void ViewManager::switchToView(int index) | ||
302 | { | 274 | { | ||
303 | _viewSplitter->activeContainer()->setCurrentIndex(index); | 275 | _viewContainer->setCurrentIndex(index); | ||
276 | } | ||||
277 | | ||||
278 | void ViewManager::switchToTerminalDisplay(Konsole::TerminalDisplay* terminalDisplay) | ||||
279 | { | ||||
280 | auto splitter = qobject_cast<ViewSplitter*>(terminalDisplay->parentWidget()); | ||||
281 | auto toplevelSplitter = splitter->getToplevelSplitter(); | ||||
282 | | ||||
283 | // Focus the TermialDisplay | ||||
284 | terminalDisplay->setFocus(); | ||||
285 | | ||||
286 | if (_viewContainer->currentWidget() != toplevelSplitter) { | ||||
287 | // Focus the tab | ||||
288 | switchToView(_viewContainer->indexOf(toplevelSplitter)); | ||||
289 | } | ||||
304 | } | 290 | } | ||
305 | 291 | | |||
306 | void ViewManager::updateDetachViewState() | 292 | void ViewManager::updateDetachViewState() | ||
307 | { | 293 | { | ||
308 | Q_ASSERT(_actionCollection); | 294 | if (_viewContainer && _viewContainer->activeViewSplitter()) { | ||
309 | if (_actionCollection == nullptr) { | 295 | const int splitCount = _viewContainer | ||
310 | return; | 296 | ->activeViewSplitter() | ||
297 | ->getToplevelSplitter() | ||||
298 | ->findChildren<TerminalDisplay*>() | ||||
maciejn: There is a method ViewSplitter::getTerminalDisplays() which is a lot more complicated than this. | |||||
tcanabrava: nice catch. that's really easy to remove. | |||||
299 | .count(); | ||||
300 | | ||||
301 | foreach (QAction *action, _multiSplitterOnlyActions) { | ||||
302 | action->setEnabled(splitCount > 1); | ||||
303 | } | ||||
304 | } | ||||
311 | } | 305 | } | ||
312 | 306 | | |||
313 | const bool splitView = _viewSplitter->containers().count() >= 2; | 307 | void ViewManager::focusUp() | ||
314 | auto activeContainer = _viewSplitter->activeContainer(); | 308 | { | ||
315 | const bool shouldEnable = splitView | 309 | _viewContainer->activeViewSplitter()->focusUp(); | ||
316 | || ((activeContainer != nullptr) | 310 | } | ||
317 | && activeContainer->count() >= 2); | | |||
318 | 311 | | |||
319 | QAction *detachAction = _actionCollection->action(QStringLiteral("detach-view")); | 312 | void ViewManager::focusDown() | ||
313 | { | ||||
314 | _viewContainer->activeViewSplitter()->focusDown(); | ||||
315 | } | ||||
320 | 316 | | |||
321 | if ((detachAction != nullptr) && shouldEnable != detachAction->isEnabled()) { | 317 | void ViewManager::focusLeft() | ||
322 | detachAction->setEnabled(shouldEnable); | 318 | { | ||
319 | _viewContainer->activeViewSplitter()->focusLeft(); | ||||
323 | } | 320 | } | ||
321 | | ||||
322 | void ViewManager::focusRight() | ||||
323 | { | ||||
324 | _viewContainer->activeViewSplitter()->focusRight(); | ||||
324 | } | 325 | } | ||
325 | 326 | | |||
326 | void ViewManager::moveActiveViewLeft() | 327 | void ViewManager::moveActiveViewLeft() | ||
327 | { | 328 | { | ||
328 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 329 | _viewContainer->moveActiveView(TabbedViewContainer::MoveViewLeft); | ||
329 | Q_ASSERT(container); | | |||
330 | container->moveActiveView(TabbedViewContainer::MoveViewLeft); | | |||
331 | } | 330 | } | ||
332 | 331 | | |||
333 | void ViewManager::moveActiveViewRight() | 332 | void ViewManager::moveActiveViewRight() | ||
334 | { | 333 | { | ||
335 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 334 | _viewContainer->moveActiveView(TabbedViewContainer::MoveViewRight); | ||
336 | Q_ASSERT(container); | | |||
337 | container->moveActiveView(TabbedViewContainer::MoveViewRight); | | |||
338 | } | 335 | } | ||
339 | 336 | | |||
340 | void ViewManager::nextContainer() | 337 | void ViewManager::nextContainer() | ||
341 | { | 338 | { | ||
342 | _viewSplitter->activateNextContainer(); | 339 | // _viewSplitter->activateNextContainer(); | ||
hindenburg: ? | |||||
there's no notion of 'nextContainer' anymore, so I commented that out. I need to see if the call is userfull at all or remove. tcanabrava: there's no notion of 'nextContainer' anymore, so I commented that out. I need to see if the… | |||||
343 | } | 340 | } | ||
344 | 341 | | |||
345 | void ViewManager::nextView() | 342 | void ViewManager::nextView() | ||
346 | { | 343 | { | ||
347 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 344 | _viewContainer->activateNextView(); | ||
348 | Q_ASSERT(container); | | |||
349 | container->activateNextView(); | | |||
350 | } | 345 | } | ||
351 | 346 | | |||
352 | void ViewManager::previousView() | 347 | void ViewManager::previousView() | ||
353 | { | 348 | { | ||
354 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 349 | _viewContainer->activatePreviousView(); | ||
355 | Q_ASSERT(container); | | |||
356 | container->activatePreviousView(); | | |||
357 | } | 350 | } | ||
358 | 351 | | |||
359 | void ViewManager::lastView() | 352 | void ViewManager::lastView() | ||
360 | { | 353 | { | ||
361 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 354 | _viewContainer->activateLastView(); | ||
362 | Q_ASSERT(container); | 355 | } | ||
363 | container->activateLastView(); | 356 | | ||
357 | void ViewManager::activateLastUsedView(bool reverse) | ||||
358 | { | ||||
359 | if (_terminalDisplayHistory.count() <= 1) { | ||||
360 | return; | ||||
361 | } | ||||
362 | | ||||
363 | if (_terminalDisplayHistoryIndex == -1) { | ||||
364 | _terminalDisplayHistoryIndex = reverse ? _terminalDisplayHistory.count() - 1 : 1; | ||||
365 | } else if (reverse) { | ||||
366 | if (_terminalDisplayHistoryIndex == 0) { | ||||
367 | _terminalDisplayHistoryIndex = _terminalDisplayHistory.count() - 1; | ||||
368 | } else { | ||||
369 | _terminalDisplayHistoryIndex--; | ||||
370 | } | ||||
371 | } else { | ||||
372 | if (_terminalDisplayHistoryIndex >= _terminalDisplayHistory.count() - 1) { | ||||
373 | _terminalDisplayHistoryIndex = 0; | ||||
374 | } else { | ||||
375 | _terminalDisplayHistoryIndex++; | ||||
376 | } | ||||
377 | } | ||||
378 | | ||||
379 | switchToTerminalDisplay(_terminalDisplayHistory[_terminalDisplayHistoryIndex]); | ||||
364 | } | 380 | } | ||
365 | 381 | | |||
366 | void ViewManager::lastUsedView() | 382 | void ViewManager::lastUsedView() | ||
367 | { | 383 | { | ||
368 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 384 | activateLastUsedView(false); | ||
369 | Q_ASSERT(container); | | |||
370 | container->activateLastUsedView(false); | | |||
371 | } | 385 | } | ||
372 | 386 | | |||
373 | void ViewManager::lastUsedViewReverse() | 387 | void ViewManager::lastUsedViewReverse() | ||
374 | { | 388 | { | ||
375 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 389 | activateLastUsedView(true); | ||
376 | Q_ASSERT(container); | | |||
377 | container->activateLastUsedView(true); | | |||
378 | } | 390 | } | ||
379 | 391 | | |||
380 | void ViewManager::toggleTwoViews() | 392 | void ViewManager::toggleTwoViews() | ||
381 | { | 393 | { | ||
382 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 394 | if (_terminalDisplayHistory.count() <= 1) { | ||
383 | Q_ASSERT(container); | 395 | return; | ||
384 | container->toggleLastUsedView(); | | |||
385 | } | 396 | } | ||
386 | 397 | | |||
387 | void ViewManager::detachActiveView() | 398 | switchToTerminalDisplay(_terminalDisplayHistory.at(1)); | ||
388 | { | | |||
389 | // find the currently active view and remove it from its container | | |||
390 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | | |||
391 | detachView(container, container->currentWidget()); | | |||
392 | } | 399 | } | ||
393 | 400 | | |||
394 | void ViewManager::detachView(TabbedViewContainer *container, QWidget *view) | 401 | void ViewManager::detachActiveView() | ||
395 | { | 402 | { | ||
396 | #if !defined(ENABLE_DETACHING) | 403 | #if !defined(ENABLE_DETACHING) | ||
397 | return; | 404 | return; | ||
398 | #endif | 405 | #endif | ||
406 | // find the currently active view and remove it from its container | ||||
407 | if ((_viewContainer->findChildren<TerminalDisplay*>()).count() > 1) { | ||||
408 | auto activeSplitter = _viewContainer->activeViewSplitter(); | ||||
409 | auto terminal = activeSplitter->activeTerminalDisplay(); | ||||
410 | auto newSplitter = new ViewSplitter(); | ||||
411 | newSplitter->addTerminalDisplay(terminal, Qt::Horizontal); | ||||
412 | QHash<TerminalDisplay*, Session*> detachedSessions = forgetAll(newSplitter); | ||||
413 | emit terminalsDetached(newSplitter, detachedSessions); | ||||
414 | focusAnotherTerminal(activeSplitter->getToplevelSplitter()); | ||||
415 | updateDetachViewState(); | ||||
416 | } | ||||
417 | } | ||||
399 | 418 | | |||
400 | auto *viewToDetach = qobject_cast<TerminalDisplay *>(view); | 419 | void ViewManager::detachActiveTab() | ||
401 | 420 | { | |||
402 | if (viewToDetach == nullptr) { | 421 | const int currentIdx = _viewContainer->currentIndex(); | ||
403 | return; | 422 | detachTab(currentIdx); | ||
404 | } | 423 | } | ||
405 | 424 | | |||
406 | // BR390736 - some instances are sending invalid session to viewDetached() | 425 | void ViewManager::detachTab(int tabIdx) | ||
407 | Session *sessionToDetach = _sessionMap[viewToDetach]; | 426 | { | ||
408 | if (sessionToDetach == nullptr) { | 427 | #if !defined(ENABLE_DETACHING) | ||
409 | return; | 428 | return; | ||
429 | #endif | ||||
430 | ViewSplitter* splitter = _viewContainer->viewSplitterAt(tabIdx); | ||||
431 | QHash<TerminalDisplay*, Session*> detachedSessions = forgetAll(_viewContainer->viewSplitterAt(tabIdx)); | ||||
432 | emit terminalsDetached(splitter, detachedSessions); | ||||
410 | } | 433 | } | ||
411 | emit viewDetached(sessionToDetach); | | |||
412 | 434 | | |||
413 | _sessionMap.remove(viewToDetach); | 435 | QHash<TerminalDisplay*, Session*> ViewManager::forgetAll(ViewSplitter* splitter) { | ||
436 | splitter->setParent(nullptr); | ||||
437 | QHash<TerminalDisplay*, Session*> detachedSessions; | ||||
438 | foreach(TerminalDisplay* terminal, splitter->findChildren<TerminalDisplay*>()) { | ||||
439 | Session* session = forgetTerminal(terminal); | ||||
440 | detachedSessions[terminal] = session; | ||||
441 | } | ||||
442 | return detachedSessions; | ||||
443 | } | ||||
414 | 444 | | |||
415 | // remove the view from this window | 445 | Session* ViewManager::forgetTerminal(TerminalDisplay* terminal) | ||
416 | container->removeView(viewToDetach); | 446 | { | ||
417 | viewToDetach->deleteLater(); | 447 | removeController(terminal->sessionController()); | ||
418 | 448 | auto session = _sessionMap.take(terminal); | |||
419 | // if the container from which the view was removed is now empty then it can be deleted, | 449 | if (session != nullptr) { | ||
420 | // unless it is the only container in the window, in which case it is left empty | 450 | disconnect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished); | ||
421 | // so that there is always an active container | | |||
422 | if (_viewSplitter->containers().count() > 1 | | |||
423 | && container->count() == 0) { | | |||
424 | removeContainer(container); | | |||
425 | } | 451 | } | ||
452 | _viewContainer->disconnectTerminalDisplay(terminal); | ||||
453 | updateTerminalDisplayHistory(terminal, true); | ||||
454 | return session; | ||||
426 | } | 455 | } | ||
427 | 456 | | |||
428 | void ViewManager::sessionFinished() | 457 | void ViewManager::sessionFinished() | ||
429 | { | 458 | { | ||
430 | // if this slot is called after the view manager's main widget | 459 | // if this slot is called after the view manager's main widget | ||
431 | // has been destroyed, do nothing | 460 | // has been destroyed, do nothing | ||
432 | if (_viewSplitter.isNull()) { | 461 | if (_viewContainer.isNull()) { | ||
433 | return; | 462 | return; | ||
434 | } | 463 | } | ||
435 | 464 | | |||
436 | auto *session = qobject_cast<Session *>(sender()); | 465 | auto *session = qobject_cast<Session *>(sender()); | ||
437 | Q_ASSERT(session); | 466 | Q_ASSERT(session); | ||
438 | 467 | | |||
439 | // close attached views | 468 | auto view = _sessionMap.key(session); | ||
440 | QList<TerminalDisplay *> children = _viewSplitter->findChildren<TerminalDisplay *>(); | | |||
441 | | ||||
442 | foreach (TerminalDisplay *view, children) { | | |||
443 | if (_sessionMap[view] == session) { | | |||
444 | _sessionMap.remove(view); | 469 | _sessionMap.remove(view); | ||
470 | | ||||
471 | // Before deleting the view, let's unmaximize if it's maximized. | ||||
472 | auto splitter = qobject_cast<ViewSplitter*>(view->parentWidget()); | ||||
473 | auto toplevelSplitter = splitter->getToplevelSplitter(); | ||||
474 | toplevelSplitter->restoreOtherTerminals(); | ||||
475 | _viewContainer->removeView(view); | ||||
445 | view->deleteLater(); | 476 | view->deleteLater(); | ||
446 | } | | |||
447 | } | | |||
448 | 477 | | |||
449 | // Only remove the controller from factory() if it's actually controlling | 478 | // Only remove the controller from factory() if it's actually controlling | ||
450 | // the session from the sender. | 479 | // the session from the sender. | ||
451 | // This fixes BUG: 348478 - messed up menus after a detached tab is closed | 480 | // This fixes BUG: 348478 - messed up menus after a detached tab is closed | ||
452 | if ((!_pluggedController.isNull()) && (_pluggedController->session() == session)) { | 481 | if ((!_pluggedController.isNull()) && (_pluggedController->session() == session)) { | ||
453 | // This is needed to remove this controller from factory() in | 482 | // This is needed to remove this controller from factory() in | ||
454 | // order to prevent BUG: 185466 - disappearing menu popup | 483 | // order to prevent BUG: 185466 - disappearing menu popup | ||
455 | emit unplugController(_pluggedController); | 484 | emit unplugController(_pluggedController); | ||
456 | } | 485 | } | ||
486 | | ||||
487 | updateTerminalDisplayHistory(view, true); | ||||
488 | focusAnotherTerminal(toplevelSplitter); | ||||
489 | updateDetachViewState(); | ||||
490 | } | ||||
491 | | ||||
492 | void ViewManager::focusAnotherTerminal(ViewSplitter *toplevelSplitter) | ||||
493 | { | ||||
494 | auto tabTterminalDisplays = toplevelSplitter->findChildren<TerminalDisplay*>(); | ||||
495 | if (tabTterminalDisplays.count() > 1) { | ||||
496 | // Give focus to the last used terminal in this tab | ||||
497 | for (auto *historyItem : _terminalDisplayHistory) { | ||||
498 | for (auto *terminalDisplay : tabTterminalDisplays) { | ||||
499 | if (terminalDisplay == historyItem) { | ||||
500 | terminalDisplay->setFocus(Qt::OtherFocusReason); | ||||
501 | return; | ||||
502 | } | ||||
503 | } | ||||
504 | } | ||||
505 | } else if (_terminalDisplayHistory.count() >= 1) { | ||||
506 | // Give focus to the last used terminal tab | ||||
507 | switchToTerminalDisplay(_terminalDisplayHistory[0]); | ||||
508 | } | ||||
457 | } | 509 | } | ||
458 | 510 | | |||
459 | void ViewManager::viewActivated(QWidget *view) | 511 | void ViewManager::viewActivated(TerminalDisplay *view) | ||
460 | { | 512 | { | ||
461 | Q_ASSERT(view != nullptr); | 513 | Q_ASSERT(view != nullptr); | ||
462 | 514 | | |||
463 | // focus the activated view, this will cause the SessionController | 515 | // focus the activated view, this will cause the SessionController | ||
464 | // to notify the world that the view has been focused and the appropriate UI | 516 | // to notify the world that the view has been focused and the appropriate UI | ||
465 | // actions will be plugged in. | 517 | // actions will be plugged in. | ||
466 | view->setFocus(Qt::OtherFocusReason); | 518 | view->setFocus(Qt::OtherFocusReason); | ||
467 | } | 519 | } | ||
468 | 520 | | |||
469 | void ViewManager::splitLeftRight() | 521 | void ViewManager::splitLeftRight() | ||
470 | { | 522 | { | ||
471 | splitView(Qt::Horizontal); | 523 | splitView(Qt::Horizontal); | ||
472 | } | 524 | } | ||
473 | 525 | | |||
474 | void ViewManager::splitTopBottom() | 526 | void ViewManager::splitTopBottom() | ||
475 | { | 527 | { | ||
476 | splitView(Qt::Vertical); | 528 | splitView(Qt::Vertical); | ||
477 | } | 529 | } | ||
478 | 530 | | |||
479 | void ViewManager::splitView(Qt::Orientation orientation) | 531 | void ViewManager::splitView(Qt::Orientation orientation) | ||
480 | { | 532 | { | ||
481 | TabbedViewContainer *container = createContainer(); | 533 | auto viewSplitter = qobject_cast<ViewSplitter*>(_viewContainer->currentWidget()); | ||
482 | 534 | | |||
483 | if (_viewSplitter->activeContainer()->count()) { | | |||
484 | // get the currently applied profile and use it to create the new tab. | 535 | // get the currently applied profile and use it to create the new tab. | ||
485 | auto *activeContainer= _viewSplitter->activeContainer(); | 536 | auto *currentDisplay = viewSplitter->findChild<TerminalDisplay*>(); | ||
486 | auto *currentDisplay = qobject_cast<TerminalDisplay*>(activeContainer->currentWidget()); | | |||
487 | auto profile = SessionManager::instance()->sessionProfile(_sessionMap[currentDisplay]); | 537 | auto profile = SessionManager::instance()->sessionProfile(_sessionMap[currentDisplay]); | ||
488 | 538 | | |||
489 | // Create a new session with the selected profile. | 539 | // Create a new session with the selected profile. | ||
490 | auto *session = SessionManager::instance()->createSession(profile); | 540 | auto *session = SessionManager::instance()->createSession(profile); | ||
491 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 541 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
492 | 542 | | |||
493 | createView(session, container, 0); | 543 | auto terminalDisplay = createView(session); | ||
494 | } | | |||
495 | | ||||
496 | _viewSplitter->addContainer(container, orientation); | | |||
497 | emit splitViewToggle(_viewSplitter->containers().count() > 0); | | |||
498 | 544 | | |||
499 | // focus the new container | 545 | _viewContainer->splitView(terminalDisplay, orientation); | ||
500 | container->currentWidget()->setFocus(); | | |||
501 | | ||||
502 | // ensure that the active view is focused after the split / unsplit | | |||
503 | TabbedViewContainer *activeContainer = _viewSplitter->activeContainer(); | | |||
504 | QWidget *activeView = activeContainer != nullptr ? activeContainer->currentWidget() : nullptr; | | |||
505 | 546 | | |||
506 | if (activeView != nullptr) { | 547 | updateDetachViewState(); | ||
507 | activeView->setFocus(Qt::OtherFocusReason); | | |||
508 | } | | |||
509 | } | | |||
510 | | ||||
511 | void ViewManager::removeContainer(TabbedViewContainer *container) | | |||
512 | { | | |||
513 | // remove session map entries for views in this container | | |||
514 | for(int i = 0, end = container->count(); i < end; i++) { | | |||
515 | auto view = container->widget(i); | | |||
516 | auto *display = qobject_cast<TerminalDisplay *>(view); | | |||
517 | Q_ASSERT(display); | | |||
518 | _sessionMap.remove(display); | | |||
519 | } | | |||
520 | | ||||
521 | _viewSplitter->removeContainer(container); | | |||
522 | container->deleteLater(); | | |||
523 | 548 | | |||
524 | emit splitViewToggle(_viewSplitter->containers().count() > 1); | 549 | // focus the new container | ||
550 | terminalDisplay->setFocus(); | ||||
525 | } | 551 | } | ||
526 | 552 | | |||
527 | void ViewManager::expandActiveContainer() | 553 | void ViewManager::expandActiveContainer() | ||
528 | { | 554 | { | ||
529 | _viewSplitter->adjustContainerSize(_viewSplitter->activeContainer(), 10); | 555 | _viewContainer->activeViewSplitter()->adjustActiveTerminalDisplaySize(10); | ||
530 | } | 556 | } | ||
531 | 557 | | |||
532 | void ViewManager::shrinkActiveContainer() | 558 | void ViewManager::shrinkActiveContainer() | ||
533 | { | 559 | { | ||
534 | _viewSplitter->adjustContainerSize(_viewSplitter->activeContainer(), -10); | 560 | _viewContainer->activeViewSplitter()->adjustActiveTerminalDisplaySize(-10); | ||
535 | } | | |||
536 | | ||||
537 | void ViewManager::closeActiveContainer() | | |||
538 | { | | |||
539 | // only do something if there is more than one container active | | |||
540 | if (_viewSplitter->containers().count() > 1) { | | |||
541 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | | |||
542 | | ||||
543 | removeContainer(container); | | |||
544 | | ||||
545 | // focus next container so that user can continue typing | | |||
546 | // without having to manually focus it themselves | | |||
547 | nextContainer(); | | |||
548 | } | | |||
549 | } | | |||
550 | | ||||
551 | void ViewManager::closeOtherContainers() | | |||
552 | { | | |||
553 | TabbedViewContainer *active = _viewSplitter->activeContainer(); | | |||
554 | | ||||
555 | foreach (TabbedViewContainer *container, _viewSplitter->containers()) { | | |||
556 | if (container != active) { | | |||
557 | removeContainer(container); | | |||
558 | } | | |||
559 | } | | |||
560 | } | 561 | } | ||
561 | 562 | | |||
562 | SessionController *ViewManager::createController(Session *session, TerminalDisplay *view) | 563 | SessionController *ViewManager::createController(Session *session, TerminalDisplay *view) | ||
563 | { | 564 | { | ||
564 | // create a new controller for the session, and ensure that this view manager | 565 | // create a new controller for the session, and ensure that this view manager | ||
565 | // is notified when the view gains the focus | 566 | // is notified when the view gains the focus | ||
566 | auto controller = new SessionController(session, view, this); | 567 | auto controller = new SessionController(session, view, this); | ||
567 | connect(controller, &Konsole::SessionController::focused, this, | 568 | connect(controller, &Konsole::SessionController::focused, this, | ||
Show All 10 Lines | |||||
578 | // if this is the first controller created then set it as the active controller | 579 | // if this is the first controller created then set it as the active controller | ||
579 | if (_pluggedController.isNull()) { | 580 | if (_pluggedController.isNull()) { | ||
580 | controllerChanged(controller); | 581 | controllerChanged(controller); | ||
581 | } | 582 | } | ||
582 | 583 | | |||
583 | return controller; | 584 | return controller; | ||
584 | } | 585 | } | ||
585 | 586 | | |||
587 | // should this be handed by ViewManager::unplugController signal | ||||
588 | void ViewManager::removeController(SessionController* controller) | ||||
589 | { | ||||
590 | disconnect(controller, &Konsole::SessionController::focused, this, | ||||
591 | &Konsole::ViewManager::controllerChanged); | ||||
592 | if (_pluggedController == controller) { | ||||
593 | _pluggedController = nullptr; | ||||
594 | } | ||||
595 | controller->deleteLater(); | ||||
596 | } | ||||
597 | | ||||
586 | void ViewManager::controllerChanged(SessionController *controller) | 598 | void ViewManager::controllerChanged(SessionController *controller) | ||
587 | { | 599 | { | ||
588 | if (controller == _pluggedController) { | 600 | if (controller == _pluggedController) { | ||
589 | return; | 601 | return; | ||
590 | } | 602 | } | ||
591 | 603 | | |||
592 | _viewSplitter->setFocusProxy(controller->view()); | 604 | updateTerminalDisplayHistory(controller->view()); | ||
593 | 605 | | |||
anthonyfieroni: This should stay, i think. | |||||
this should actually be removed, the current way to deal with the focus is working without the proxies, also, there's no _viewSplitter anymore. tcanabrava: this should actually be removed, the current way to deal with the focus is working without the… | |||||
594 | _pluggedController = controller; | 606 | _pluggedController = controller; | ||
595 | emit activeViewChanged(controller); | 607 | emit activeViewChanged(controller); | ||
596 | } | 608 | } | ||
597 | 609 | | |||
598 | SessionController *ViewManager::activeViewController() const | 610 | SessionController *ViewManager::activeViewController() const | ||
599 | { | 611 | { | ||
600 | return _pluggedController; | 612 | return _pluggedController; | ||
601 | } | 613 | } | ||
602 | 614 | | |||
603 | void ViewManager::createView(Session *session, TabbedViewContainer *container, int index) | 615 | void ViewManager::attachView(TerminalDisplay *terminal, Session *session) | ||
616 | { | ||||
617 | connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished, | ||||
618 | Qt::UniqueConnection); | ||||
619 | _sessionMap[terminal] = session; | ||||
620 | createController(session, terminal); | ||||
621 | updateDetachViewState(); | ||||
622 | _terminalDisplayHistory.append(terminal); | ||||
623 | } | ||||
624 | | ||||
625 | TerminalDisplay *ViewManager::createView(Session *session) | ||||
604 | { | 626 | { | ||
605 | // notify this view manager when the session finishes so that its view | 627 | // notify this view manager when the session finishes so that its view | ||
606 | // can be deleted | 628 | // can be deleted | ||
607 | // | 629 | // | ||
608 | // Use Qt::UniqueConnection to avoid duplicate connection | 630 | // Use Qt::UniqueConnection to avoid duplicate connection | ||
609 | connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished, | 631 | connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished, | ||
610 | Qt::UniqueConnection); | 632 | Qt::UniqueConnection); | ||
611 | | ||||
612 | TerminalDisplay *display = createTerminalDisplay(session); | 633 | TerminalDisplay *display = createTerminalDisplay(session); | ||
634 | | ||||
613 | const Profile::Ptr profile = SessionManager::instance()->sessionProfile(session); | 635 | const Profile::Ptr profile = SessionManager::instance()->sessionProfile(session); | ||
614 | applyProfileToView(display, profile); | 636 | applyProfileToView(display, profile); | ||
615 | 637 | | |||
616 | // set initial size | 638 | // set initial size | ||
617 | const QSize &preferredSize = session->preferredSize(); | 639 | const QSize &preferredSize = session->preferredSize(); | ||
618 | 640 | | |||
619 | display->setSize(preferredSize.width(), preferredSize.height()); | 641 | display->setSize(preferredSize.width(), preferredSize.height()); | ||
620 | createController(session, display); | 642 | createController(session, display); | ||
621 | 643 | | |||
622 | _sessionMap[display] = session; | 644 | _sessionMap[display] = session; | ||
623 | container->addView(display, index); | | |||
624 | session->addView(display); | 645 | session->addView(display); | ||
646 | _terminalDisplayHistory.append(display); | ||||
625 | 647 | | |||
626 | // tell the session whether it has a light or dark background | 648 | // tell the session whether it has a light or dark background | ||
627 | session->setDarkBackground(colorSchemeForProfile(profile)->hasDarkBackground()); | 649 | session->setDarkBackground(colorSchemeForProfile(profile)->hasDarkBackground()); | ||
628 | container->setCurrentWidget(display); | | |||
629 | display->setFocus(Qt::OtherFocusReason); | 650 | display->setFocus(Qt::OtherFocusReason); | ||
651 | // updateDetachViewState(); | ||||
630 | 652 | | |||
631 | updateDetachViewState(); | 653 | return display; | ||
632 | } | | |||
633 | | ||||
634 | void ViewManager::createView(TabbedViewContainer *tabWidget, Session *session) | | |||
635 | { | | |||
636 | const int index = _newTabBehavior == PutNewTabAfterCurrentTab ? | | |||
637 | _viewSplitter->activeContainer()->currentIndex() + 1 : -1; | | |||
638 | | ||||
639 | createView(session, tabWidget, index); | | |||
640 | } | 654 | } | ||
641 | 655 | | |||
642 | TabbedViewContainer *ViewManager::createContainer() | 656 | TabbedViewContainer *ViewManager::createContainer() | ||
643 | { | 657 | { | ||
644 | 658 | auto *container = new TabbedViewContainer(this, nullptr); | |||
645 | auto *container = new TabbedViewContainer(this, _viewSplitter); | | |||
646 | container->setNavigationVisibility(_navigationVisibility); | 659 | container->setNavigationVisibility(_navigationVisibility); | ||
647 | //TODO: Fix Detaching. | 660 | connect(container, &TabbedViewContainer::detachTab, this, &ViewManager::detachTab); | ||
648 | connect(container, &TabbedViewContainer::detachTab, this, &ViewManager::detachView); | | |||
649 | 661 | | |||
650 | // connect signals and slots | 662 | // connect signals and slots | ||
651 | connect(container, &Konsole::TabbedViewContainer::viewAdded, this, | 663 | connect(container, &Konsole::TabbedViewContainer::viewAdded, this, | ||
652 | [this, container]() { | 664 | [this, container]() { | ||
653 | containerViewsChanged(container); | 665 | containerViewsChanged(container); | ||
654 | }); | 666 | }); | ||
655 | 667 | | |||
656 | connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, | 668 | connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, | ||
657 | [this, container]() { | 669 | [this, container]() { | ||
658 | containerViewsChanged(container); | 670 | containerViewsChanged(container); | ||
659 | }); | 671 | }); | ||
660 | 672 | | |||
661 | connect(container, &TabbedViewContainer::newViewRequest, | 673 | connect(container, &TabbedViewContainer::newViewRequest, | ||
662 | this, &ViewManager::newViewRequest); | 674 | this, &ViewManager::newViewRequest); | ||
663 | connect(container, &Konsole::TabbedViewContainer::newViewWithProfileRequest, | 675 | connect(container, &Konsole::TabbedViewContainer::newViewWithProfileRequest, | ||
664 | this, &Konsole::ViewManager::newViewWithProfileRequest); | 676 | this, &Konsole::ViewManager::newViewWithProfileRequest); | ||
665 | connect(container, &Konsole::TabbedViewContainer::moveViewRequest, this, | | |||
666 | &Konsole::ViewManager::containerMoveViewRequest); | | |||
667 | connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, | 677 | connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, | ||
668 | &Konsole::ViewManager::viewDestroyed); | 678 | &Konsole::ViewManager::viewDestroyed); | ||
669 | connect(container, &Konsole::TabbedViewContainer::activeViewChanged, this, | 679 | connect(container, &Konsole::TabbedViewContainer::activeViewChanged, this, | ||
670 | &Konsole::ViewManager::viewActivated); | 680 | &Konsole::ViewManager::viewActivated); | ||
671 | 681 | | |||
672 | return container; | 682 | return container; | ||
673 | } | 683 | } | ||
674 | 684 | | |||
675 | void ViewManager::containerMoveViewRequest(int index, int id) | | |||
676 | { | | |||
677 | auto *container = qobject_cast<TabbedViewContainer *>(sender()); | | |||
678 | auto *controller = qobject_cast<SessionController *>(ViewProperties::propertiesById(id)); | | |||
679 | Q_ASSERT(container); | | |||
680 | Q_ASSERT(controller); | | |||
681 | | ||||
682 | createView(controller->session(), container, index); | | |||
683 | controller->session()->refresh(); | | |||
684 | container->currentWidget()->setFocus(); | | |||
685 | } | | |||
686 | | ||||
687 | void ViewManager::setNavigationMethod(NavigationMethod method) | 685 | void ViewManager::setNavigationMethod(NavigationMethod method) | ||
688 | { | 686 | { | ||
689 | Q_ASSERT(_actionCollection); | 687 | Q_ASSERT(_actionCollection); | ||
690 | if (_actionCollection == nullptr) { | 688 | if (_actionCollection == nullptr) { | ||
691 | return; | 689 | return; | ||
692 | } | 690 | } | ||
693 | KActionCollection *collection = _actionCollection; | 691 | KActionCollection *collection = _actionCollection; | ||
694 | 692 | | |||
Show All 30 Lines | |||||
725 | } | 723 | } | ||
726 | 724 | | |||
727 | ViewManager::NavigationMethod ViewManager::navigationMethod() const | 725 | ViewManager::NavigationMethod ViewManager::navigationMethod() const | ||
728 | { | 726 | { | ||
729 | return _navigationMethod; | 727 | return _navigationMethod; | ||
730 | } | 728 | } | ||
731 | 729 | | |||
732 | void ViewManager::containerViewsChanged(TabbedViewContainer *container) | 730 | void ViewManager::containerViewsChanged(TabbedViewContainer *container) | ||
733 | { | 731 | { | ||
734 | if ((!_viewSplitter.isNull()) && container == _viewSplitter->activeContainer()) { | 732 | // TODO: Verify that this is right. | ||
hindenburg: container not used | |||||
735 | emit viewPropertiesChanged(viewProperties()); | 733 | emit viewPropertiesChanged(viewProperties()); | ||
736 | } | 734 | } | ||
737 | } | | |||
738 | 735 | | |||
739 | void ViewManager::viewDestroyed(QWidget *view) | 736 | void ViewManager::viewDestroyed(QWidget *view) | ||
740 | { | 737 | { | ||
741 | // Note: the received QWidget has already been destroyed, so | 738 | // Note: the received QWidget has already been destroyed, so | ||
742 | // using dynamic_cast<> or qobject_cast<> does not work here | 739 | // using dynamic_cast<> or qobject_cast<> does not work here | ||
743 | // We only need the pointer address to look it up below | 740 | // We only need the pointer address to look it up below | ||
744 | auto *display = reinterpret_cast<TerminalDisplay *>(view); | 741 | auto *display = reinterpret_cast<TerminalDisplay *>(view); | ||
745 | 742 | | |||
746 | // 1. detach view from session | 743 | // 1. detach view from session | ||
747 | // 2. if the session has no views left, close it | 744 | // 2. if the session has no views left, close it | ||
748 | Session *session = _sessionMap[ display ]; | 745 | Session *session = _sessionMap[ display ]; | ||
749 | _sessionMap.remove(display); | 746 | _sessionMap.remove(display); | ||
750 | if (session != nullptr) { | 747 | if (session != nullptr) { | ||
751 | if (session->views().count() == 0) { | 748 | if (session->views().count() == 0) { | ||
752 | session->close(); | 749 | session->close(); | ||
753 | } | 750 | } | ||
754 | } | 751 | } | ||
752 | | ||||
755 | //we only update the focus if the splitter is still alive | 753 | //we only update the focus if the splitter is still alive | ||
756 | if (!_viewSplitter.isNull()) { | | |||
757 | updateDetachViewState(); | 754 | updateDetachViewState(); | ||
758 | } | 755 | | ||
759 | // The below causes the menus to be messed up | 756 | // The below causes the menus to be messed up | ||
760 | // Only happens when using the tab bar close button | 757 | // Only happens when using the tab bar close button | ||
761 | // if (_pluggedController) | 758 | // if (_pluggedController) | ||
762 | // emit unplugController(_pluggedController); | 759 | // emit unplugController(_pluggedController); | ||
763 | } | 760 | } | ||
764 | 761 | | |||
765 | TerminalDisplay *ViewManager::createTerminalDisplay(Session *session) | 762 | TerminalDisplay *ViewManager::createTerminalDisplay(Session *session) | ||
766 | { | 763 | { | ||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Line(s) | 809 | while (iter.hasNext()) { | |||
820 | } | 817 | } | ||
821 | } | 818 | } | ||
822 | } | 819 | } | ||
823 | 820 | | |||
824 | QList<ViewProperties *> ViewManager::viewProperties() const | 821 | QList<ViewProperties *> ViewManager::viewProperties() const | ||
825 | { | 822 | { | ||
826 | QList<ViewProperties *> list; | 823 | QList<ViewProperties *> list; | ||
827 | 824 | | |||
828 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 825 | TabbedViewContainer *container = _viewContainer; | ||
829 | if (container == nullptr) { | 826 | if (container == nullptr) { | ||
830 | return {}; | 827 | return {}; | ||
831 | } | 828 | } | ||
832 | 829 | | |||
833 | list.reserve(container->count()); | 830 | auto terminalContainers = _viewContainer->findChildren<TerminalDisplay*>(); | ||
831 | list.reserve(terminalContainers.size()); | ||||
834 | 832 | | |||
835 | for(int i = 0, end = container->count(); i < end; i++) { | 833 | for(auto terminalDisplay : _viewContainer->findChildren<TerminalDisplay*>()) { | ||
836 | auto view = container->terminalAt(i); | 834 | list.append(terminalDisplay->sessionController()); | ||
837 | ViewProperties *properties = view->sessionController(); | | |||
838 | Q_ASSERT(properties); | | |||
839 | list << properties; | | |||
840 | } | 835 | } | ||
841 | 836 | | |||
842 | return list; | 837 | return list; | ||
843 | } | 838 | } | ||
844 | 839 | | |||
845 | void ViewManager::saveSessions(KConfigGroup &group) | 840 | void ViewManager::saveSessions(KConfigGroup &group) | ||
846 | { | 841 | { | ||
847 | // find all unique session restore IDs | 842 | // find all unique session restore IDs | ||
848 | QList<int> ids; | 843 | QList<int> ids; | ||
849 | QSet<Session *> unique; | 844 | QSet<Session *> unique; | ||
850 | int tab = 1; | 845 | int tab = 1; | ||
851 | 846 | | |||
852 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 847 | TabbedViewContainer *container = _viewContainer; | ||
853 | 848 | | |||
854 | // first: sessions in the active container, preserving the order | 849 | // first: sessions in the active container, preserving the order | ||
855 | Q_ASSERT(container); | 850 | Q_ASSERT(container); | ||
856 | if (container == nullptr) { | 851 | if (container == nullptr) { | ||
857 | return; | 852 | return; | ||
858 | } | 853 | } | ||
859 | ids.reserve(container->count()); | 854 | ids.reserve(container->count()); | ||
860 | 855 | | |||
856 | //TODO: Handle sessions | ||||
857 | #if 0 | ||||
hindenburg: I need to test session restores w/ splits. | |||||
861 | auto *activeview = qobject_cast<TerminalDisplay *>(container->currentWidget()); | 858 | auto *activeview = qobject_cast<TerminalDisplay *>(container->currentWidget()); | ||
862 | for (int i = 0, end = container->count(); i < end; i++) { | 859 | for (int i = 0, end = container->count(); i < end; i++) { | ||
863 | auto *view = qobject_cast<TerminalDisplay *>(container->widget(i)); | 860 | auto *view = qobject_cast<TerminalDisplay *>(container->widget(i)); | ||
864 | Q_ASSERT(view); | 861 | Q_ASSERT(view); | ||
865 | 862 | | |||
866 | Session *session = _sessionMap[view]; | 863 | Session *session = _sessionMap[view]; | ||
867 | ids << SessionManager::instance()->getRestoreId(session); | 864 | ids << SessionManager::instance()->getRestoreId(session); | ||
868 | unique.insert(session); | 865 | unique.insert(session); | ||
869 | if (view == activeview) { | 866 | if (view == activeview) { | ||
870 | group.writeEntry("Active", tab); | 867 | group.writeEntry("Active", tab); | ||
871 | } | 868 | } | ||
872 | tab++; | 869 | tab++; | ||
873 | } | 870 | } | ||
871 | #endif | ||||
874 | 872 | | |||
875 | // second: all other sessions, in random order | 873 | // second: all other sessions, in random order | ||
876 | // we don't want to have sessions restored that are not connected | 874 | // we don't want to have sessions restored that are not connected | ||
877 | foreach (Session *session, _sessionMap) { | 875 | foreach (Session *session, _sessionMap) { | ||
878 | if (!unique.contains(session)) { | 876 | if (!unique.contains(session)) { | ||
879 | ids << SessionManager::instance()->getRestoreId(session); | 877 | ids << SessionManager::instance()->getRestoreId(session); | ||
880 | unique.insert(session); | 878 | unique.insert(session); | ||
881 | } | 879 | } | ||
882 | } | 880 | } | ||
883 | 881 | | |||
884 | group.writeEntry("Sessions", ids); | 882 | group.writeEntry("Sessions", ids); | ||
885 | } | 883 | } | ||
886 | 884 | | |||
887 | TabbedViewContainer *ViewManager::activeContainer() | 885 | TabbedViewContainer *ViewManager::activeContainer() | ||
888 | { | 886 | { | ||
889 | return _viewSplitter->activeContainer(); | 887 | return _viewContainer; | ||
890 | } | 888 | } | ||
891 | 889 | | |||
892 | void ViewManager::restoreSessions(const KConfigGroup &group) | 890 | void ViewManager::restoreSessions(const KConfigGroup &group) | ||
893 | { | 891 | { | ||
894 | QList<int> ids = group.readEntry("Sessions", QList<int>()); | 892 | QList<int> ids = group.readEntry("Sessions", QList<int>()); | ||
895 | int activeTab = group.readEntry("Active", 0); | 893 | int activeTab = group.readEntry("Active", 0); | ||
896 | TerminalDisplay *display = nullptr; | 894 | TerminalDisplay *display = nullptr; | ||
897 | 895 | | |||
898 | int tab = 1; | 896 | int tab = 1; | ||
899 | foreach (int id, ids) { | 897 | foreach (int id, ids) { | ||
900 | Session *session = SessionManager::instance()->idToSession(id); | 898 | Session *session = SessionManager::instance()->idToSession(id); | ||
901 | 899 | | |||
902 | if (session == nullptr) { | 900 | if (session == nullptr) { | ||
903 | qWarning() << "Unable to load session with id" << id; | 901 | qWarning() << "Unable to load session with id" << id; | ||
904 | // Force a creation of a default session below | 902 | // Force a creation of a default session below | ||
905 | ids.clear(); | 903 | ids.clear(); | ||
906 | break; | 904 | break; | ||
907 | } | 905 | } | ||
908 | 906 | | |||
909 | createView(activeContainer(), session); | 907 | createView(session); | ||
910 | if (!session->isRunning()) { | 908 | if (!session->isRunning()) { | ||
911 | session->run(); | 909 | session->run(); | ||
912 | } | 910 | } | ||
913 | if (tab++ == activeTab) { | 911 | if (tab++ == activeTab) { | ||
914 | display = qobject_cast<TerminalDisplay *>(activeView()); | 912 | display = qobject_cast<TerminalDisplay *>(activeView()); | ||
915 | } | 913 | } | ||
916 | } | 914 | } | ||
917 | 915 | | |||
918 | if (display != nullptr) { | 916 | if (display != nullptr) { | ||
919 | _viewSplitter->activeContainer()->setCurrentWidget(display); | 917 | activeContainer()->setCurrentWidget(display); | ||
920 | display->setFocus(Qt::OtherFocusReason); | 918 | display->setFocus(Qt::OtherFocusReason); | ||
921 | } | 919 | } | ||
922 | 920 | | |||
923 | if (ids.isEmpty()) { // Session file is unusable, start default Profile | 921 | if (ids.isEmpty()) { // Session file is unusable, start default Profile | ||
924 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | 922 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | ||
925 | Session *session = SessionManager::instance()->createSession(profile); | 923 | Session *session = SessionManager::instance()->createSession(profile); | ||
926 | createView(activeContainer(), session); | 924 | createView(session); | ||
927 | if (!session->isRunning()) { | 925 | if (!session->isRunning()) { | ||
928 | session->run(); | 926 | session->run(); | ||
929 | } | 927 | } | ||
930 | } | 928 | } | ||
931 | } | 929 | } | ||
932 | 930 | | |||
933 | int ViewManager::sessionCount() | 931 | int ViewManager::sessionCount() | ||
934 | { | 932 | { | ||
Show All 23 Lines | 949 | { | |||
958 | return -1; | 956 | return -1; | ||
959 | } | 957 | } | ||
960 | 958 | | |||
961 | void ViewManager::setCurrentSession(int sessionId) | 959 | void ViewManager::setCurrentSession(int sessionId) | ||
962 | { | 960 | { | ||
963 | QHash<TerminalDisplay *, Session *>::const_iterator i; | 961 | QHash<TerminalDisplay *, Session *>::const_iterator i; | ||
964 | for (i = _sessionMap.constBegin(); i != _sessionMap.constEnd(); ++i) { | 962 | for (i = _sessionMap.constBegin(); i != _sessionMap.constEnd(); ++i) { | ||
965 | if (i.value()->sessionId() == sessionId) { | 963 | if (i.value()->sessionId() == sessionId) { | ||
966 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 964 | TabbedViewContainer *container = activeContainer(); | ||
967 | if (container != nullptr) { | 965 | if (container != nullptr) { | ||
968 | container->setCurrentWidget(i.key()); | 966 | container->setCurrentWidget(i.key()); | ||
969 | } | 967 | } | ||
970 | } | 968 | } | ||
971 | } | 969 | } | ||
972 | } | 970 | } | ||
973 | 971 | | |||
974 | int ViewManager::newSession() | 972 | int ViewManager::newSession() | ||
975 | { | 973 | { | ||
976 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | 974 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | ||
977 | Session *session = SessionManager::instance()->createSession(profile); | 975 | Session *session = SessionManager::instance()->createSession(profile); | ||
978 | 976 | | |||
979 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 977 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
980 | 978 | | |||
981 | createView(activeContainer(), session); | 979 | createView(session); | ||
982 | session->run(); | 980 | session->run(); | ||
983 | 981 | | |||
984 | return session->sessionId(); | 982 | return session->sessionId(); | ||
985 | } | 983 | } | ||
986 | 984 | | |||
987 | int ViewManager::newSession(const QString &profile) | 985 | int ViewManager::newSession(const QString &profile) | ||
988 | { | 986 | { | ||
989 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | 987 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | ||
990 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | 988 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | ||
991 | 989 | | |||
992 | for (const auto &i : profilelist) { | 990 | for (const auto &i : profilelist) { | ||
993 | if (i->name() == profile) { | 991 | if (i->name() == profile) { | ||
994 | profileptr = i; | 992 | profileptr = i; | ||
995 | break; | 993 | break; | ||
996 | } | 994 | } | ||
997 | } | 995 | } | ||
998 | 996 | | |||
999 | Session *session = SessionManager::instance()->createSession(profileptr); | 997 | Session *session = SessionManager::instance()->createSession(profileptr); | ||
1000 | 998 | | |||
1001 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 999 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
1002 | 1000 | | |||
1003 | createView(activeContainer(), session); | 1001 | createView(session); | ||
1004 | session->run(); | 1002 | session->run(); | ||
1005 | 1003 | | |||
1006 | return session->sessionId(); | 1004 | return session->sessionId(); | ||
1007 | } | 1005 | } | ||
1008 | 1006 | | |||
1009 | int ViewManager::newSession(const QString &profile, const QString &directory) | 1007 | int ViewManager::newSession(const QString &profile, const QString &directory) | ||
1010 | { | 1008 | { | ||
1011 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | 1009 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | ||
1012 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | 1010 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | ||
1013 | 1011 | | |||
1014 | for (const auto &i : profilelist) { | 1012 | for (const auto &i : profilelist) { | ||
1015 | if (i->name() == profile) { | 1013 | if (i->name() == profile) { | ||
1016 | profileptr = i; | 1014 | profileptr = i; | ||
1017 | break; | 1015 | break; | ||
1018 | } | 1016 | } | ||
1019 | } | 1017 | } | ||
1020 | 1018 | | |||
1021 | Session *session = SessionManager::instance()->createSession(profileptr); | 1019 | Session *session = SessionManager::instance()->createSession(profileptr); | ||
1022 | session->setInitialWorkingDirectory(directory); | 1020 | session->setInitialWorkingDirectory(directory); | ||
1023 | 1021 | | |||
1024 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 1022 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
1025 | 1023 | | |||
1026 | createView(activeContainer(), session); | 1024 | createView(session); | ||
1027 | session->run(); | 1025 | session->run(); | ||
1028 | 1026 | | |||
1029 | return session->sessionId(); | 1027 | return session->sessionId(); | ||
1030 | } | 1028 | } | ||
1031 | 1029 | | |||
1032 | QString ViewManager::defaultProfile() | 1030 | QString ViewManager::defaultProfile() | ||
1033 | { | 1031 | { | ||
1034 | return ProfileManager::instance()->defaultProfile()->name(); | 1032 | return ProfileManager::instance()->defaultProfile()->name(); | ||
Show All 21 Lines | |||||
1056 | 1054 | | |||
1057 | void ViewManager::moveSessionRight() | 1055 | void ViewManager::moveSessionRight() | ||
1058 | { | 1056 | { | ||
1059 | moveActiveViewRight(); | 1057 | moveActiveViewRight(); | ||
1060 | } | 1058 | } | ||
1061 | 1059 | | |||
1062 | void ViewManager::setTabWidthToText(bool setTabWidthToText) | 1060 | void ViewManager::setTabWidthToText(bool setTabWidthToText) | ||
1063 | { | 1061 | { | ||
1064 | for(auto container : _viewSplitter->containers()) { | 1062 | _viewContainer->tabBar()->setExpanding(!setTabWidthToText); | ||
1065 | container->tabBar()->setExpanding(!setTabWidthToText); | 1063 | _viewContainer->tabBar()->update(); | ||
1066 | container->tabBar()->update(); | | |||
1067 | } | | |||
1068 | } | 1064 | } | ||
1069 | 1065 | | |||
1070 | void ViewManager::setNavigationVisibility(NavigationVisibility navigationVisibility) { | 1066 | void ViewManager::setNavigationVisibility(NavigationVisibility navigationVisibility) { | ||
1071 | if (_navigationVisibility != navigationVisibility) { | 1067 | if (_navigationVisibility != navigationVisibility) { | ||
1072 | _navigationVisibility = navigationVisibility; | 1068 | _navigationVisibility = navigationVisibility; | ||
1073 | for(auto *container : _viewSplitter->containers()) { | 1069 | _viewContainer->setNavigationVisibility(navigationVisibility); | ||
1074 | container->setNavigationVisibility(navigationVisibility); | | |||
1075 | } | | |||
1076 | } | 1070 | } | ||
1077 | } | 1071 | } | ||
1078 | 1072 | | |||
1079 | void ViewManager::setNavigationBehavior(int behavior) | 1073 | void ViewManager::setNavigationBehavior(int behavior) | ||
1080 | { | 1074 | { | ||
1081 | _newTabBehavior = static_cast<NewTabBehavior>(behavior); | 1075 | _newTabBehavior = static_cast<NewTabBehavior>(behavior); | ||
1082 | } | 1076 | } | ||
1077 | | ||||
1078 | void ViewManager::updateTerminalDisplayHistory(TerminalDisplay* terminalDisplay, bool remove) | ||||
1079 | { | ||||
1080 | if (terminalDisplay == nullptr) { | ||||
1081 | if (_terminalDisplayHistoryIndex >= 0) { | ||||
1082 | // This is the case when we finished walking through the history | ||||
1083 | // (i.e. when Ctrl-Tab has been released) | ||||
1084 | terminalDisplay = _terminalDisplayHistory[_terminalDisplayHistoryIndex]; | ||||
1085 | _terminalDisplayHistoryIndex = -1; | ||||
1086 | } else { | ||||
1087 | return; | ||||
1088 | } | ||||
1089 | } | ||||
1090 | | ||||
1091 | if (_terminalDisplayHistoryIndex >= 0 && !remove) { | ||||
1092 | // Do not reorder the tab history while we are walking through it | ||||
1093 | return; | ||||
1094 | } | ||||
1095 | | ||||
1096 | for (int i = 0; i < _terminalDisplayHistory.count(); i++) { | ||||
1097 | if (_terminalDisplayHistory[i] == terminalDisplay) { | ||||
1098 | _terminalDisplayHistory.removeAt(i); | ||||
1099 | if (!remove) { | ||||
1100 | _terminalDisplayHistory.prepend(terminalDisplay); | ||||
1101 | } | ||||
1102 | break; | ||||
1103 | } | ||||
1104 | } | ||||
1105 | } |
There is a method ViewSplitter::getTerminalDisplays() which is a lot more complicated than this. It should probably be simplified to this and used here or removed entirely.