Changeset View
Changeset View
Standalone View
Standalone View
src/ViewManager.cpp
Show First 20 Lines • Show All 47 Lines • ▼ Show 20 Line(s) | |||||
48 | #include "ViewContainer.h" | 48 | #include "ViewContainer.h" | ||
49 | 49 | | |||
50 | using namespace Konsole; | 50 | using namespace Konsole; | ||
51 | 51 | | |||
52 | int ViewManager::lastManagerId = 0; | 52 | int ViewManager::lastManagerId = 0; | ||
53 | 53 | | |||
54 | ViewManager::ViewManager(QObject *parent, KActionCollection *collection) : | 54 | ViewManager::ViewManager(QObject *parent, KActionCollection *collection) : | ||
55 | QObject(parent), | 55 | QObject(parent), | ||
56 | _viewSplitter(nullptr), | 56 | _viewContainer(nullptr), | ||
57 | _pluggedController(nullptr), | 57 | _pluggedController(nullptr), | ||
58 | _sessionMap(QHash<TerminalDisplay *, Session *>()), | 58 | _sessionMap(QHash<TerminalDisplay *, Session *>()), | ||
59 | _actionCollection(collection), | 59 | _actionCollection(collection), | ||
60 | _navigationMethod(NoNavigation), | 60 | _navigationMethod(NoNavigation), | ||
61 | _navigationVisibility(NavigationNotSet), | 61 | _navigationVisibility(NavigationNotSet), | ||
62 | _newTabBehavior(PutNewTabAtTheEnd), | 62 | _newTabBehavior(PutNewTabAtTheEnd), | ||
63 | _managerId(0) | 63 | _managerId(0), | ||
64 | _terminalDisplayHistoryIndex(-1) | ||||
64 | { | 65 | { | ||
65 | // create main view area | 66 | _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 | 67 | // setup actions which are related to the views | ||
79 | setupActions(); | 68 | setupActions(); | ||
80 | 69 | | |||
70 | /* TODO: Reconnect | ||||
81 | // emit a signal when all of the views held by this view manager are destroyed | 71 | // emit a signal when all of the views held by this view manager are destroyed | ||
82 | connect(_viewSplitter.data(), &Konsole::ViewSplitter::allContainersEmpty, | 72 | */ | ||
73 | connect(_viewContainer.data(), &Konsole::TabbedViewContainer::empty, | ||||
83 | this, &Konsole::ViewManager::empty); | 74 | this, &Konsole::ViewManager::empty); | ||
84 | connect(_viewSplitter.data(), &Konsole::ViewSplitter::empty, this, | | |||
85 | &Konsole::ViewManager::empty); | | |||
86 | 75 | | |||
87 | // listen for profile changes | 76 | // listen for profile changes | ||
88 | connect(ProfileManager::instance(), &Konsole::ProfileManager::profileChanged, | 77 | connect(ProfileManager::instance(), &Konsole::ProfileManager::profileChanged, | ||
89 | this, &Konsole::ViewManager::profileChanged); | 78 | this, &Konsole::ViewManager::profileChanged); | ||
90 | connect(SessionManager::instance(), &Konsole::SessionManager::sessionUpdated, | 79 | connect(SessionManager::instance(), &Konsole::SessionManager::sessionUpdated, | ||
91 | this, &Konsole::ViewManager::updateViewsForSession); | 80 | this, &Konsole::ViewManager::updateViewsForSession); | ||
92 | 81 | | |||
93 | //prepare DBus communication | 82 | //prepare DBus communication | ||
94 | new WindowAdaptor(this); | 83 | new WindowAdaptor(this); | ||
95 | 84 | | |||
96 | _managerId = ++lastManagerId; | 85 | _managerId = ++lastManagerId; | ||
97 | QDBusConnection::sessionBus().registerObject(QLatin1String("/Windows/") | 86 | QDBusConnection::sessionBus().registerObject(QLatin1String("/Windows/") | ||
98 | + QString::number(_managerId), this); | 87 | + QString::number(_managerId), this); | ||
99 | | ||||
100 | _viewSplitter->addContainer(createContainer(), Qt::Vertical); | | |||
101 | } | 88 | } | ||
102 | 89 | | |||
103 | ViewManager::~ViewManager() = default; | 90 | ViewManager::~ViewManager() = default; | ||
104 | 91 | | |||
105 | int ViewManager::managerId() const | 92 | int ViewManager::managerId() const | ||
106 | { | 93 | { | ||
107 | return _managerId; | 94 | return _managerId; | ||
108 | } | 95 | } | ||
109 | 96 | | |||
110 | QWidget *ViewManager::activeView() const | 97 | QWidget *ViewManager::activeView() const | ||
111 | { | 98 | { | ||
112 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 99 | return _viewContainer->currentWidget(); | ||
113 | if (container != nullptr) { | | |||
114 | return container->currentWidget(); | | |||
115 | } else { | | |||
116 | return nullptr; | | |||
117 | } | | |||
118 | } | 100 | } | ||
119 | 101 | | |||
120 | QWidget *ViewManager::widget() const | 102 | QWidget *ViewManager::widget() const | ||
121 | { | 103 | { | ||
122 | return _viewSplitter; | 104 | return _viewContainer; | ||
123 | } | 105 | } | ||
124 | 106 | | |||
125 | void ViewManager::setupActions() | 107 | void ViewManager::setupActions() | ||
126 | { | 108 | { | ||
127 | Q_ASSERT(_actionCollection); | 109 | Q_ASSERT(_actionCollection); | ||
128 | if (_actionCollection == nullptr) { | 110 | if (_actionCollection == nullptr) { | ||
129 | return; | 111 | return; | ||
130 | } | 112 | } | ||
131 | 113 | | |||
132 | KActionCollection *collection = _actionCollection; | 114 | KActionCollection *collection = _actionCollection; | ||
133 | 115 | | |||
134 | QAction *nextViewAction = new QAction(i18nc("@action Shortcut entry", "Next Tab"), this); | | |||
135 | QAction *previousViewAction = new QAction(i18nc("@action Shortcut entry", "Previous Tab"), this); | | |||
136 | QAction *lastViewAction = new QAction(i18nc("@action Shortcut entry", | | |||
137 | "Switch to Last Tab"), this); | | |||
138 | QAction *lastUsedViewAction = new QAction(i18nc("@action Shortcut entry", "Last Used Tabs"), this); | | |||
139 | QAction *lastUsedViewReverseAction = new QAction(i18nc("@action Shortcut entry", | | |||
140 | "Last Used Tabs (Reverse)"), this); | | |||
141 | QAction *toggleTwoViewsAction = new QAction(i18nc("@action Shortcut entry", "Toggle Between Two Tabs"), this); | | |||
142 | QAction *nextContainerAction = new QAction(i18nc("@action Shortcut entry", | | |||
143 | "Next View Container"), this); | | |||
144 | | ||||
145 | QAction *moveViewLeftAction = new QAction(i18nc("@action Shortcut entry", "Move Tab Left"), this); | | |||
146 | QAction *moveViewRightAction = new QAction(i18nc("@action Shortcut entry", | | |||
147 | "Move Tab Right"), this); | | |||
148 | | ||||
149 | // list of actions that should only be enabled when there are multiple view | 116 | // list of actions that should only be enabled when there are multiple view | ||
150 | // containers open | 117 | // containers open | ||
151 | QList<QAction *> multiViewOnlyActions; | 118 | QList<QAction *> multiTabOnlyActions; | ||
152 | multiViewOnlyActions << nextContainerAction; | 119 | QList<QAction *> multiSplitterOnlyActions; | ||
153 | | ||||
154 | QAction *splitLeftRightAction = new QAction(QIcon::fromTheme(QStringLiteral("view-split-left-right")), | | |||
155 | i18nc("@action:inmenu", "Split View Left/Right"), | | |||
156 | this); | | |||
157 | collection->setDefaultShortcut(splitLeftRightAction, Konsole::ACCEL + Qt::Key_ParenLeft); | | |||
158 | collection->addAction(QStringLiteral("split-view-left-right"), splitLeftRightAction); | | |||
159 | connect(splitLeftRightAction, &QAction::triggered, this, &Konsole::ViewManager::splitLeftRight); | | |||
160 | | ||||
161 | QAction *splitTopBottomAction = new QAction(QIcon::fromTheme(QStringLiteral("view-split-top-bottom")), | | |||
162 | i18nc("@action:inmenu", | | |||
163 | "Split View Top/Bottom"), this); | | |||
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 | 120 | | |||
207 | multiViewOnlyActions << shrinkActiveAction; | 121 | // Let's reuse the pointer, no need not to. | ||
122 | auto *action = new QAction(); | ||||
123 | action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-left-right"))); | ||||
124 | action->setText(i18nc("@action:inmenu", "Split View Left/Right")); | ||||
125 | connect(action, &QAction::triggered, this, &ViewManager::splitLeftRight); | ||||
126 | collection->addAction(QStringLiteral("split-view-left-right"), action); | ||||
127 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::Key_ParenLeft); | ||||
128 | | ||||
129 | action = new QAction(); | ||||
130 | action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-top-bottom"))); | ||||
131 | action->setText(i18nc("@action:inmenu", "Split View Top/Bottom")); | ||||
132 | connect(action, &QAction::triggered, this, &ViewManager::splitTopBottom); | ||||
133 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::Key_ParenRight); | ||||
134 | collection->addAction(QStringLiteral("split-view-top-bottom"), action); | ||||
135 | | ||||
136 | action = new QAction(); | ||||
137 | action->setText(i18nc("@action:inmenu", "Expand View")); | ||||
138 | action->setEnabled(false); | ||||
139 | connect(action, &QAction::triggered, this, &ViewManager::expandActiveContainer); | ||||
140 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketRight); | ||||
141 | collection->addAction(QStringLiteral("expand-active-view"), action); | ||||
142 | multiSplitterOnlyActions << action; | ||||
143 | | ||||
144 | action = new QAction(); | ||||
145 | action->setText(i18nc("@action:inmenu", "Shrink View")); | ||||
146 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_BracketLeft); | ||||
147 | action->setEnabled(false); | ||||
148 | collection->addAction(QStringLiteral("shrink-active-view"), action); | ||||
149 | connect(action, &QAction::triggered, this, &ViewManager::shrinkActiveContainer); | ||||
150 | multiSplitterOnlyActions << action; | ||||
208 | 151 | | |||
209 | // Crashes on Mac. | 152 | // Crashes on Mac. | ||
210 | #if defined(ENABLE_DETACHING) | 153 | #if defined(ENABLE_DETACHING) | ||
211 | QAction *detachViewAction = collection->addAction(QStringLiteral("detach-view")); | 154 | connect(this, &ViewManager::splitViewToggle, this, &ViewManager::updateDetachViewState); | ||
212 | detachViewAction->setEnabled(true); | 155 | | ||
213 | detachViewAction->setIcon(QIcon::fromTheme(QStringLiteral("tab-detach"))); | 156 | action = collection->addAction(QStringLiteral("detach-view")); | ||
214 | detachViewAction->setText(i18nc("@action:inmenu", "D&etach Current Tab")); | 157 | action->setEnabled(true); | ||
158 | action->setIcon(QIcon::fromTheme(QStringLiteral("detach-view"))); | ||||
159 | action->setText(i18nc("@action:inmenu", "D&etach Current View")); | ||||
160 | | ||||
161 | connect(action, &QAction::triggered, this, &ViewManager::detachActiveView); | ||||
162 | multiSplitterOnlyActions << action; | ||||
163 | | ||||
215 | // Ctrl+Shift+D is not used as a shortcut by default because it is too close | 164 | // 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 | 165 | // to Ctrl+D - which will terminate the session in many cases | ||
217 | collection->setDefaultShortcut(detachViewAction, Konsole::ACCEL + Qt::SHIFT + Qt::Key_H); | 166 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_H); | ||
218 | 167 | | |||
219 | connect(this, &Konsole::ViewManager::splitViewToggle, this, | 168 | action = collection->addAction(QStringLiteral("detach-tab")); | ||
220 | &Konsole::ViewManager::updateDetachViewState); | 169 | action->setEnabled(true); | ||
221 | connect(detachViewAction, &QAction::triggered, this, &Konsole::ViewManager::detachActiveView); | 170 | action->setIcon(QIcon::fromTheme(QStringLiteral("detach-tab"))); | ||
171 | action->setText(i18nc("@action:inmenu", "D&etach Current Tab")); | ||||
172 | connect(action, &QAction::triggered, this, &ViewManager::detachActiveTab); | ||||
173 | multiTabOnlyActions << action; | ||||
174 | // Ctrl+Shift+D is not used as a shortcut by default because it is too close | ||||
175 | // to Ctrl+D - which will terminate the session in many cases | ||||
176 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Qt::Key_L); | ||||
222 | #endif | 177 | #endif | ||
223 | 178 | | |||
224 | // Next / Previous View , Next Container | 179 | // keyboard shortcut only actions | ||
225 | collection->addAction(QStringLiteral("next-view"), nextViewAction); | 180 | action = new QAction(i18nc("@action Shortcut entry", "Next Tab"), this); | ||
226 | collection->addAction(QStringLiteral("previous-view"), previousViewAction); | 181 | const QList<QKeySequence> nextViewActionKeys{Qt::SHIFT + Qt::Key_Right, Qt::CTRL + Qt::Key_PageDown}; | ||
227 | collection->addAction(QStringLiteral("last-tab"), lastViewAction); | 182 | collection->setDefaultShortcuts(action, nextViewActionKeys); | ||
228 | collection->addAction(QStringLiteral("last-used-tab"), lastUsedViewAction); | 183 | collection->addAction(QStringLiteral("next-tab"), action); | ||
229 | collection->addAction(QStringLiteral("last-used-tab-reverse"), lastUsedViewReverseAction); | 184 | connect(action, &QAction::triggered, this, &ViewManager::nextView); | ||
230 | collection->addAction(QStringLiteral("toggle-two-tabs"), toggleTwoViewsAction); | 185 | multiTabOnlyActions << action; | ||
231 | collection->addAction(QStringLiteral("next-container"), nextContainerAction); | 186 | // _viewSplitter->addAction(nextViewAction); | ||
232 | collection->addAction(QStringLiteral("move-view-left"), moveViewLeftAction); | 187 | | ||
233 | collection->addAction(QStringLiteral("move-view-right"), moveViewRightAction); | 188 | action = new QAction(i18nc("@action Shortcut entry", "Previous Tab"), this); | ||
189 | const QList<QKeySequence> previousViewActionKeys{Qt::SHIFT + Qt::Key_Left, Qt::CTRL + Qt::Key_PageUp}; | ||||
190 | collection->setDefaultShortcuts(action, previousViewActionKeys); | ||||
191 | collection->addAction(QStringLiteral("previous-tab"), action); | ||||
192 | connect(action, &QAction::triggered, this, &ViewManager::previousView); | ||||
193 | multiTabOnlyActions << action; | ||||
194 | // _viewSplitter->addAction(previousViewAction); | ||||
195 | | ||||
196 | action = new QAction(i18nc("@action Shortcut entry", "Next View Container"), this); | ||||
197 | connect(action, &QAction::triggered, this, &ViewManager::focusUp); | ||||
198 | collection->addAction(QStringLiteral("next-container"), action); | ||||
199 | collection->setDefaultShortcut(action, Qt::SHIFT + Qt::CTRL + Qt::Key_Up); | ||||
200 | _viewContainer->addAction(action); | ||||
201 | multiSplitterOnlyActions << action; | ||||
202 | | ||||
203 | action = new QAction(QStringLiteral("Focus Down")); | ||||
204 | collection->setDefaultShortcut(action, Qt::SHIFT + Qt::CTRL + Qt::Key_Down); | ||||
205 | connect(action, &QAction::triggered, this, &ViewManager::focusDown); | ||||
206 | multiSplitterOnlyActions << action; | ||||
207 | _viewContainer->addAction(action); | ||||
208 | | ||||
209 | action = new QAction(i18nc("@action Shortcut entry", "Move Tab Left"), this); | ||||
210 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Konsole::LEFT); | ||||
211 | connect(action, &QAction::triggered, this, &ViewManager::focusLeft); | ||||
212 | collection->addAction(QStringLiteral("move-view-left"), action); | ||||
213 | multiSplitterOnlyActions << action; | ||||
214 | | ||||
215 | action = new QAction(i18nc("@action Shortcut entry", "Move Tab Right"), this); | ||||
216 | collection->setDefaultShortcut(action, Konsole::ACCEL + Qt::SHIFT + Konsole::RIGHT); | ||||
217 | connect(action, &QAction::triggered, this, &ViewManager::focusRight); | ||||
218 | collection->addAction(QStringLiteral("move-view-right"), action); | ||||
219 | multiSplitterOnlyActions << action; | ||||
220 | | ||||
221 | action = new QAction(i18nc("@action Shortcut entry", "Switch to Last Tab"), this); | ||||
222 | connect(action, &QAction::triggered, this, &ViewManager::lastView); | ||||
223 | collection->addAction(QStringLiteral("last-tab"), action); | ||||
224 | multiTabOnlyActions << action; | ||||
225 | | ||||
226 | action = new QAction(i18nc("@action Shortcut entry", "Last Used Tabs"), this); | ||||
227 | connect(action, &QAction::triggered, this, &ViewManager::lastUsedView); | ||||
228 | collection->setDefaultShortcut(action, Qt::CTRL + Qt::Key_Tab); | ||||
229 | collection->addAction(QStringLiteral("last-used-tab"), action); | ||||
230 | multiTabOnlyActions << action; | ||||
231 | | ||||
232 | action = new QAction(i18nc("@action Shortcut entry", "Toggle Between Two Tabs"), this); | ||||
233 | connect(action, &QAction::triggered, this, &Konsole::ViewManager::toggleTwoViews); | ||||
234 | collection->addAction(QStringLiteral("toggle-two-tabs"), action); | ||||
235 | multiTabOnlyActions << action; | ||||
236 | | ||||
237 | action = new QAction(i18nc("@action Shortcut entry", "Last Used Tabs (Reverse)"), this); | ||||
238 | collection->addAction(QStringLiteral("last-used-tab-reverse"), action); | ||||
239 | collection->setDefaultShortcut(action, Qt::CTRL + Qt::SHIFT + Qt::Key_Tab); | ||||
240 | connect(action, &QAction::triggered, this, &ViewManager::lastUsedViewReverse); | ||||
241 | multiTabOnlyActions << action; | ||||
242 | | ||||
243 | action = new QAction(i18nc("@action Shortcut entry", "Maximize current Terminal"), this); | ||||
244 | collection->addAction(QStringLiteral("maximize-current-terminal"), action); | ||||
245 | collection->setDefaultShortcut(action, Qt::CTRL + Qt::SHIFT + Qt::Key_E); | ||||
246 | connect(action, &QAction::triggered, _viewContainer, &TabbedViewContainer::maximizeCurrentTerminal); | ||||
247 | multiSplitterOnlyActions << action; | ||||
248 | _viewContainer->addAction(action); | ||||
249 | | ||||
250 | action = new QAction(i18nc("@action Shortcut entry", "Restore other terminals"), this); | ||||
251 | collection->addAction(QStringLiteral("restore-other-terminals"), action); | ||||
252 | collection->setDefaultShortcut(action, Qt::CTRL + Qt::SHIFT + Qt::Key_Minus); | ||||
253 | connect(action, &QAction::triggered, _viewContainer, &TabbedViewContainer::restoreOtherTerminals); | ||||
254 | multiSplitterOnlyActions << action; | ||||
255 | _viewContainer->addAction(action); | ||||
234 | 256 | | |||
235 | // Switch to tab N shortcuts | 257 | // _viewSplitter->addAction(lastUsedViewReverseAction); | ||
236 | const int SWITCH_TO_TAB_COUNT = 19; | 258 | const int SWITCH_TO_TAB_COUNT = 19; | ||
237 | for (int i = 0; i < SWITCH_TO_TAB_COUNT; i++) { | 259 | 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); | 260 | action = new QAction(i18nc("@action Shortcut entry", "Switch to Tab %1", i + 1), this); | ||
261 | connect(action, &QAction::triggered, this, [this, i]() { switchToView(i); }); | ||||
262 | collection->addAction(QStringLiteral("switch-to-tab-%1").arg(i), action); | ||||
263 | } | ||||
239 | 264 | | |||
240 | connect(switchToTabAction, &QAction::triggered, this, | 265 | connect(_viewContainer, &QTabWidget::currentChanged, this, [=](int idx) { | ||
241 | [this, i]() { | 266 | auto splitView = _viewContainer->viewSplitterAt(idx); | ||
242 | switchToView(i); | 267 | if (!splitView) | ||
268 | return; | ||||
269 | foreach (QAction *action, multiSplitterOnlyActions) { | ||||
270 | action->setEnabled(splitView->count() > 1); | ||||
271 | } | ||||
243 | }); | 272 | }); | ||
244 | collection->addAction(QStringLiteral("switch-to-tab-%1").arg(i), switchToTabAction); | 273 | | ||
274 | auto handleMultiTabActionsLambda = [=]{ | ||||
275 | const int count = _viewContainer->count(); | ||||
276 | foreach(QAction *action, multiTabOnlyActions) { | ||||
277 | action->setEnabled(count > 1); | ||||
278 | } | ||||
279 | }; | ||||
280 | connect(_viewContainer, &TabbedViewContainer::viewAdded, this, handleMultiTabActionsLambda); | ||||
281 | connect(_viewContainer, &TabbedViewContainer::viewRemoved, this, handleMultiTabActionsLambda); | ||||
245 | } | 282 | } | ||
246 | 283 | | |||
247 | foreach (QAction *action, multiViewOnlyActions) { | 284 | void ViewManager::switchToView(int index) | ||
248 | connect(this, &Konsole::ViewManager::splitViewToggle, action, &QAction::setEnabled); | 285 | { | ||
286 | _viewContainer->setCurrentIndex(index); | ||||
249 | } | 287 | } | ||
250 | 288 | | |||
251 | // keyboard shortcut only actions | 289 | void ViewManager::switchToTerminalDisplay(Konsole::TerminalDisplay* terminalDisplay) | ||
252 | const QList<QKeySequence> nextViewActionKeys{Qt::SHIFT + Qt::Key_Right, Qt::CTRL + Qt::Key_PageDown}; | 290 | { | ||
253 | collection->setDefaultShortcuts(nextViewAction, nextViewActionKeys); | 291 | auto splitter = qobject_cast<ViewSplitter*>(terminalDisplay->parentWidget()); | ||
254 | connect(nextViewAction, &QAction::triggered, this, &Konsole::ViewManager::nextView); | 292 | auto toplevelSplitter = splitter->getToplevelSplitter(); | ||
255 | _viewSplitter->addAction(nextViewAction); | | |||
256 | 293 | | |||
257 | const QList<QKeySequence> previousViewActionKeys{Qt::SHIFT + Qt::Key_Left, Qt::CTRL + Qt::Key_PageUp}; | 294 | // Focus the TermialDisplay | ||
258 | collection->setDefaultShortcuts(previousViewAction, previousViewActionKeys); | 295 | terminalDisplay->setFocus(); | ||
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 | 296 | | |||
297 | connect(toggleTwoViewsAction, &QAction::triggered, this, &Konsole::ViewManager::toggleTwoViews); | 297 | if (_viewContainer->currentWidget() != toplevelSplitter) { | ||
298 | _viewSplitter->addAction(toggleTwoViewsAction); | 298 | // Focus the tab | ||
299 | switchToView(_viewContainer->indexOf(toplevelSplitter)); | ||||
299 | } | 300 | } | ||
300 | | ||||
301 | void ViewManager::switchToView(int index) | | |||
302 | { | | |||
303 | _viewSplitter->activeContainer()->setCurrentIndex(index); | | |||
304 | } | 301 | } | ||
305 | 302 | | |||
303 | | ||||
306 | void ViewManager::updateDetachViewState() | 304 | void ViewManager::updateDetachViewState() | ||
307 | { | 305 | { | ||
308 | Q_ASSERT(_actionCollection); | 306 | Q_ASSERT(_actionCollection); | ||
309 | if (_actionCollection == nullptr) { | 307 | if (_actionCollection == nullptr) { | ||
310 | return; | 308 | return; | ||
311 | } | 309 | } | ||
312 | 310 | | |||
311 | #if 0 | ||||
313 | const bool splitView = _viewSplitter->containers().count() >= 2; | 312 | const bool splitView = _viewSplitter->containers().count() >= 2; | ||
maciejn: There is a method ViewSplitter::getTerminalDisplays() which is a lot more complicated than this. | |||||
tcanabrava: nice catch. that's really easy to remove. | |||||
314 | auto activeContainer = _viewSplitter->activeContainer(); | 313 | auto activeContainer = _viewSplitter->activeContainer(); | ||
315 | const bool shouldEnable = splitView | 314 | const bool shouldEnable = splitView | ||
316 | || ((activeContainer != nullptr) | 315 | || ((activeContainer != nullptr) | ||
317 | && activeContainer->count() >= 2); | 316 | && activeContainer->count() >= 2); | ||
318 | 317 | | |||
319 | QAction *detachAction = _actionCollection->action(QStringLiteral("detach-view")); | 318 | QAction *detachAction = _actionCollection->action(QStringLiteral("detach-view")); | ||
320 | 319 | | |||
321 | if ((detachAction != nullptr) && shouldEnable != detachAction->isEnabled()) { | 320 | if ((detachAction != nullptr) && shouldEnable != detachAction->isEnabled()) { | ||
322 | detachAction->setEnabled(shouldEnable); | 321 | detachAction->setEnabled(shouldEnable); | ||
323 | } | 322 | } | ||
323 | #endif | ||||
324 | } | ||||
325 | | ||||
326 | void ViewManager::focusUp() | ||||
327 | { | ||||
328 | _viewContainer->activeViewSplitter()->focusUp(); | ||||
329 | } | ||||
330 | | ||||
331 | void ViewManager::focusDown() | ||||
332 | { | ||||
333 | _viewContainer->activeViewSplitter()->focusDown(); | ||||
334 | } | ||||
335 | | ||||
336 | void ViewManager::focusLeft() | ||||
337 | { | ||||
338 | _viewContainer->activeViewSplitter()->focusLeft(); | ||||
339 | } | ||||
340 | | ||||
341 | void ViewManager::focusRight() | ||||
342 | { | ||||
343 | _viewContainer->activeViewSplitter()->focusRight(); | ||||
324 | } | 344 | } | ||
325 | 345 | | |||
326 | void ViewManager::moveActiveViewLeft() | 346 | void ViewManager::moveActiveViewLeft() | ||
327 | { | 347 | { | ||
328 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 348 | _viewContainer->moveActiveView(TabbedViewContainer::MoveViewLeft); | ||
329 | Q_ASSERT(container); | | |||
330 | container->moveActiveView(TabbedViewContainer::MoveViewLeft); | | |||
331 | } | 349 | } | ||
332 | 350 | | |||
333 | void ViewManager::moveActiveViewRight() | 351 | void ViewManager::moveActiveViewRight() | ||
334 | { | 352 | { | ||
335 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 353 | _viewContainer->moveActiveView(TabbedViewContainer::MoveViewRight); | ||
336 | Q_ASSERT(container); | | |||
337 | container->moveActiveView(TabbedViewContainer::MoveViewRight); | | |||
338 | } | 354 | } | ||
339 | 355 | | |||
340 | void ViewManager::nextContainer() | 356 | void ViewManager::nextContainer() | ||
341 | { | 357 | { | ||
342 | _viewSplitter->activateNextContainer(); | 358 | // _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 | } | 359 | } | ||
344 | 360 | | |||
345 | void ViewManager::nextView() | 361 | void ViewManager::nextView() | ||
346 | { | 362 | { | ||
347 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 363 | _viewContainer->activateNextView(); | ||
348 | Q_ASSERT(container); | | |||
349 | container->activateNextView(); | | |||
350 | } | 364 | } | ||
351 | 365 | | |||
352 | void ViewManager::previousView() | 366 | void ViewManager::previousView() | ||
353 | { | 367 | { | ||
354 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 368 | _viewContainer->activatePreviousView(); | ||
355 | Q_ASSERT(container); | | |||
356 | container->activatePreviousView(); | | |||
357 | } | 369 | } | ||
358 | 370 | | |||
359 | void ViewManager::lastView() | 371 | void ViewManager::lastView() | ||
360 | { | 372 | { | ||
361 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 373 | _viewContainer->activateLastView(); | ||
362 | Q_ASSERT(container); | 374 | } | ||
363 | container->activateLastView(); | 375 | | ||
376 | void ViewManager::activateLastUsedView(bool reverse) | ||||
377 | { | ||||
378 | if (_terminalDisplayHistory.count() <= 1) { | ||||
379 | return; | ||||
380 | } | ||||
381 | | ||||
382 | if (_terminalDisplayHistoryIndex == -1) { | ||||
383 | _terminalDisplayHistoryIndex = reverse ? _terminalDisplayHistory.count() - 1 : 1; | ||||
384 | } else if (reverse) { | ||||
385 | if (_terminalDisplayHistoryIndex == 0) { | ||||
386 | _terminalDisplayHistoryIndex = _terminalDisplayHistory.count() - 1; | ||||
387 | } else { | ||||
388 | _terminalDisplayHistoryIndex--; | ||||
389 | } | ||||
390 | } else { | ||||
391 | if (_terminalDisplayHistoryIndex >= _terminalDisplayHistory.count() - 1) { | ||||
392 | _terminalDisplayHistoryIndex = 0; | ||||
393 | } else { | ||||
394 | _terminalDisplayHistoryIndex++; | ||||
395 | } | ||||
396 | } | ||||
397 | | ||||
398 | switchToTerminalDisplay(_terminalDisplayHistory[_terminalDisplayHistoryIndex]); | ||||
364 | } | 399 | } | ||
365 | 400 | | |||
366 | void ViewManager::lastUsedView() | 401 | void ViewManager::lastUsedView() | ||
367 | { | 402 | { | ||
368 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 403 | activateLastUsedView(false); | ||
369 | Q_ASSERT(container); | | |||
370 | container->activateLastUsedView(false); | | |||
371 | } | 404 | } | ||
372 | 405 | | |||
373 | void ViewManager::lastUsedViewReverse() | 406 | void ViewManager::lastUsedViewReverse() | ||
374 | { | 407 | { | ||
375 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 408 | activateLastUsedView(true); | ||
376 | Q_ASSERT(container); | | |||
377 | container->activateLastUsedView(true); | | |||
378 | } | 409 | } | ||
379 | 410 | | |||
380 | void ViewManager::toggleTwoViews() | 411 | void ViewManager::toggleTwoViews() | ||
381 | { | 412 | { | ||
382 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 413 | if (_terminalDisplayHistory.count() <= 1) { | ||
383 | Q_ASSERT(container); | 414 | return; | ||
384 | container->toggleLastUsedView(); | 415 | } | ||
416 | | ||||
417 | switchToTerminalDisplay(_terminalDisplayHistory.at(1)); | ||||
385 | } | 418 | } | ||
386 | 419 | | |||
387 | void ViewManager::detachActiveView() | 420 | void ViewManager::detachActiveView() | ||
388 | { | 421 | { | ||
389 | // find the currently active view and remove it from its container | 422 | // find the currently active view and remove it from its container | ||
390 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 423 | TabbedViewContainer *container = _viewContainer; | ||
391 | detachView(container, container->currentWidget()); | 424 | if ((container->findChildren<TerminalDisplay*>()).count() > 1) { | ||
425 | detachView(container, container->activeViewSplitter()->activeTerminalDisplay()); | ||||
426 | } | ||||
427 | } | ||||
428 | | ||||
429 | void ViewManager::detachActiveTab() | ||||
430 | { | ||||
431 | const int currentIdx = _viewContainer->currentIndex(); | ||||
432 | detachTab(currentIdx); | ||||
433 | } | ||||
434 | | ||||
435 | void ViewManager::detachTab(int tabIdx) | ||||
436 | { | ||||
437 | #if !defined(ENABLE_DETACHING) | ||||
438 | return; | ||||
439 | #endif | ||||
440 | | ||||
441 | auto splitter = _viewContainer->viewSplitterAt(tabIdx); | ||||
442 | splitter->setParent(nullptr); | ||||
443 | auto terminals = splitter->getTerminalDisplays(); | ||||
444 | QHash<TerminalDisplay*, Session*> detachedSessions; | ||||
445 | foreach(TerminalDisplay* terminal, terminals) { | ||||
446 | auto session = _sessionMap.take(terminal); | ||||
447 | detachedSessions[terminal] = session; | ||||
448 | if (session != nullptr) { | ||||
449 | disconnect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished); | ||||
450 | _viewContainer->disconnectTerminalDisplay(terminal); | ||||
451 | } | ||||
452 | auto controller = terminal->sessionController(); | ||||
453 | controller->deleteLater(); | ||||
454 | updateTerminalDisplayHistory(terminal, true); | ||||
455 | } | ||||
456 | emit tabDetached(splitter, detachedSessions); | ||||
457 | focusAnotherTerminal(splitter); | ||||
392 | } | 458 | } | ||
393 | 459 | | |||
394 | void ViewManager::detachView(TabbedViewContainer *container, QWidget *view) | 460 | void ViewManager::detachView(TabbedViewContainer *container, QWidget *view) | ||
395 | { | 461 | { | ||
396 | #if !defined(ENABLE_DETACHING) | 462 | #if !defined(ENABLE_DETACHING) | ||
397 | return; | 463 | return; | ||
398 | #endif | 464 | #endif | ||
399 | 465 | | |||
400 | auto *viewToDetach = qobject_cast<TerminalDisplay *>(view); | 466 | auto *viewToDetach = qobject_cast<TerminalDisplay *>(view); | ||
401 | 467 | | |||
402 | if (viewToDetach == nullptr) { | 468 | if (viewToDetach == nullptr) { | ||
403 | return; | 469 | return; | ||
404 | } | 470 | } | ||
405 | 471 | | |||
406 | // BR390736 - some instances are sending invalid session to viewDetached() | 472 | // BR390736 - some instances are sending invalid session to viewDetached() | ||
407 | Session *sessionToDetach = _sessionMap[viewToDetach]; | 473 | Session *sessionToDetach = _sessionMap[viewToDetach]; | ||
408 | if (sessionToDetach == nullptr) { | 474 | if (sessionToDetach == nullptr) { | ||
409 | return; | 475 | return; | ||
410 | } | 476 | } | ||
477 | | ||||
478 | disconnect(sessionToDetach, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished); | ||||
479 | | ||||
411 | emit viewDetached(sessionToDetach); | 480 | emit viewDetached(sessionToDetach); | ||
412 | 481 | | |||
413 | _sessionMap.remove(viewToDetach); | 482 | _sessionMap.remove(viewToDetach); | ||
414 | 483 | | |||
484 | // Remove this view from history | ||||
485 | updateTerminalDisplayHistory(viewToDetach, true); | ||||
486 | | ||||
415 | // remove the view from this window | 487 | // remove the view from this window | ||
416 | container->removeView(viewToDetach); | 488 | container->removeView(viewToDetach); | ||
489 | viewToDetach->setScreenWindow(nullptr); | ||||
417 | viewToDetach->deleteLater(); | 490 | viewToDetach->deleteLater(); | ||
418 | 491 | | |||
419 | // if the container from which the view was removed is now empty then it can be deleted, | 492 | focusAnotherTerminal(container->activeViewSplitter()); | ||
420 | // unless it is the only container in the window, in which case it is left empty | | |||
421 | // so that there is always an active container | | |||
422 | if (_viewSplitter->containers().count() > 1 | | |||
423 | && container->count() == 0) { | | |||
424 | removeContainer(container); | | |||
425 | } | | |||
426 | } | 493 | } | ||
427 | 494 | | |||
428 | void ViewManager::sessionFinished() | 495 | void ViewManager::sessionFinished() | ||
429 | { | 496 | { | ||
430 | // if this slot is called after the view manager's main widget | 497 | // if this slot is called after the view manager's main widget | ||
431 | // has been destroyed, do nothing | 498 | // has been destroyed, do nothing | ||
432 | if (_viewSplitter.isNull()) { | 499 | if (_viewContainer.isNull()) { | ||
433 | return; | 500 | return; | ||
434 | } | 501 | } | ||
435 | 502 | | |||
436 | auto *session = qobject_cast<Session *>(sender()); | 503 | auto *session = qobject_cast<Session *>(sender()); | ||
437 | Q_ASSERT(session); | 504 | Q_ASSERT(session); | ||
438 | 505 | | |||
439 | // close attached views | 506 | 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); | 507 | _sessionMap.remove(view); | ||
508 | | ||||
509 | // Before deleting the view, let's unmaximize if it's maximized. | ||||
510 | auto splitter = qobject_cast<ViewSplitter*>(view->parentWidget()); | ||||
511 | auto toplevelSplitter = splitter->getToplevelSplitter(); | ||||
512 | toplevelSplitter->restoreOtherTerminals(); | ||||
445 | view->deleteLater(); | 513 | view->deleteLater(); | ||
446 | } | | |||
447 | } | | |||
448 | 514 | | |||
449 | // Only remove the controller from factory() if it's actually controlling | 515 | // Only remove the controller from factory() if it's actually controlling | ||
450 | // the session from the sender. | 516 | // the session from the sender. | ||
451 | // This fixes BUG: 348478 - messed up menus after a detached tab is closed | 517 | // This fixes BUG: 348478 - messed up menus after a detached tab is closed | ||
452 | if ((!_pluggedController.isNull()) && (_pluggedController->session() == session)) { | 518 | if ((!_pluggedController.isNull()) && (_pluggedController->session() == session)) { | ||
453 | // This is needed to remove this controller from factory() in | 519 | // This is needed to remove this controller from factory() in | ||
454 | // order to prevent BUG: 185466 - disappearing menu popup | 520 | // order to prevent BUG: 185466 - disappearing menu popup | ||
455 | emit unplugController(_pluggedController); | 521 | emit unplugController(_pluggedController); | ||
456 | } | 522 | } | ||
523 | | ||||
524 | updateTerminalDisplayHistory(view, true); | ||||
525 | focusAnotherTerminal(toplevelSplitter); | ||||
526 | } | ||||
527 | | ||||
528 | void ViewManager::focusAnotherTerminal(ViewSplitter *toplevelSplitter) | ||||
529 | { | ||||
530 | auto tabTterminalDisplays = toplevelSplitter->findChildren<TerminalDisplay*>(); | ||||
531 | if (tabTterminalDisplays.count() > 1) { | ||||
532 | // Give focus to the last used terminal in this tab | ||||
533 | for (auto *historyItem : _terminalDisplayHistory) { | ||||
534 | for (auto *terminalDisplay : tabTterminalDisplays) { | ||||
535 | if (terminalDisplay == historyItem) { | ||||
536 | terminalDisplay->setFocus(Qt::OtherFocusReason); | ||||
537 | return; | ||||
538 | } | ||||
539 | } | ||||
540 | } | ||||
541 | } else if (_terminalDisplayHistory.count() >= 1) { | ||||
542 | // Give focus to the last used terminal tab | ||||
543 | switchToTerminalDisplay(_terminalDisplayHistory[0]); | ||||
544 | } | ||||
457 | } | 545 | } | ||
458 | 546 | | |||
459 | void ViewManager::viewActivated(QWidget *view) | 547 | void ViewManager::viewActivated(TerminalDisplay *view) | ||
460 | { | 548 | { | ||
461 | Q_ASSERT(view != nullptr); | 549 | Q_ASSERT(view != nullptr); | ||
462 | 550 | | |||
463 | // focus the activated view, this will cause the SessionController | 551 | // focus the activated view, this will cause the SessionController | ||
464 | // to notify the world that the view has been focused and the appropriate UI | 552 | // to notify the world that the view has been focused and the appropriate UI | ||
465 | // actions will be plugged in. | 553 | // actions will be plugged in. | ||
466 | view->setFocus(Qt::OtherFocusReason); | 554 | view->setFocus(Qt::OtherFocusReason); | ||
467 | } | 555 | } | ||
468 | 556 | | |||
469 | void ViewManager::splitLeftRight() | 557 | void ViewManager::splitLeftRight() | ||
470 | { | 558 | { | ||
471 | splitView(Qt::Horizontal); | 559 | splitView(Qt::Horizontal); | ||
472 | } | 560 | } | ||
473 | 561 | | |||
474 | void ViewManager::splitTopBottom() | 562 | void ViewManager::splitTopBottom() | ||
475 | { | 563 | { | ||
476 | splitView(Qt::Vertical); | 564 | splitView(Qt::Vertical); | ||
477 | } | 565 | } | ||
478 | 566 | | |||
479 | void ViewManager::splitView(Qt::Orientation orientation) | 567 | void ViewManager::splitView(Qt::Orientation orientation) | ||
480 | { | 568 | { | ||
481 | TabbedViewContainer *container = createContainer(); | 569 | auto viewSplitter = qobject_cast<ViewSplitter*>(_viewContainer->currentWidget()); | ||
482 | 570 | | |||
483 | if (_viewSplitter->activeContainer()->count()) { | | |||
484 | // get the currently applied profile and use it to create the new tab. | 571 | // get the currently applied profile and use it to create the new tab. | ||
485 | auto *activeContainer= _viewSplitter->activeContainer(); | 572 | auto *currentDisplay = viewSplitter->findChild<TerminalDisplay*>(); | ||
486 | auto *currentDisplay = qobject_cast<TerminalDisplay*>(activeContainer->currentWidget()); | | |||
487 | auto profile = SessionManager::instance()->sessionProfile(_sessionMap[currentDisplay]); | 573 | auto profile = SessionManager::instance()->sessionProfile(_sessionMap[currentDisplay]); | ||
488 | 574 | | |||
489 | // Create a new session with the selected profile. | 575 | // Create a new session with the selected profile. | ||
490 | auto *session = SessionManager::instance()->createSession(profile); | 576 | auto *session = SessionManager::instance()->createSession(profile); | ||
491 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 577 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
492 | 578 | | |||
493 | createView(session, container, 0); | 579 | auto terminalDisplay = createView(session); | ||
494 | } | | |||
495 | | ||||
496 | _viewSplitter->addContainer(container, orientation); | | |||
497 | emit splitViewToggle(_viewSplitter->containers().count() > 0); | | |||
498 | | ||||
499 | // focus the new container | | |||
500 | container->currentWidget()->setFocus(); | | |||
501 | 580 | | |||
502 | // ensure that the active view is focused after the split / unsplit | 581 | _viewContainer->splitView(terminalDisplay, orientation); | ||
503 | TabbedViewContainer *activeContainer = _viewSplitter->activeContainer(); | | |||
504 | QWidget *activeView = activeContainer != nullptr ? activeContainer->currentWidget() : nullptr; | | |||
505 | | ||||
506 | if (activeView != nullptr) { | | |||
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 | 582 | | |||
521 | _viewSplitter->removeContainer(container); | 583 | emit splitViewToggle(viewSplitter->count() > 0); | ||
522 | container->deleteLater(); | | |||
523 | 584 | | |||
524 | emit splitViewToggle(_viewSplitter->containers().count() > 1); | 585 | // focus the new container | ||
586 | terminalDisplay->setFocus(); | ||||
525 | } | 587 | } | ||
526 | 588 | | |||
527 | void ViewManager::expandActiveContainer() | 589 | void ViewManager::expandActiveContainer() | ||
528 | { | 590 | { | ||
529 | _viewSplitter->adjustContainerSize(_viewSplitter->activeContainer(), 10); | 591 | auto activeSplitter = _viewContainer->activeViewSplitter(); | ||
592 | auto activeTerminalDisplay = activeSplitter->activeTerminalDisplay(); | ||||
593 | activeSplitter->adjustTerminalDisplaySize(activeTerminalDisplay, 10); | ||||
530 | } | 594 | } | ||
531 | 595 | | |||
532 | void ViewManager::shrinkActiveContainer() | 596 | void ViewManager::shrinkActiveContainer() | ||
533 | { | 597 | { | ||
534 | _viewSplitter->adjustContainerSize(_viewSplitter->activeContainer(), -10); | 598 | auto activeSplitter = _viewContainer->activeViewSplitter(); | ||
535 | } | 599 | auto activeTerminalDisplay = activeSplitter->activeTerminalDisplay(); | ||
536 | 600 | activeSplitter->adjustTerminalDisplaySize(activeTerminalDisplay, -10); | |||
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 | } | 601 | } | ||
561 | 602 | | |||
562 | SessionController *ViewManager::createController(Session *session, TerminalDisplay *view) | 603 | SessionController *ViewManager::createController(Session *session, TerminalDisplay *view) | ||
563 | { | 604 | { | ||
564 | // create a new controller for the session, and ensure that this view manager | 605 | // create a new controller for the session, and ensure that this view manager | ||
565 | // is notified when the view gains the focus | 606 | // is notified when the view gains the focus | ||
566 | auto controller = new SessionController(session, view, this); | 607 | auto controller = new SessionController(session, view, this); | ||
567 | connect(controller, &Konsole::SessionController::focused, this, | 608 | connect(controller, &Konsole::SessionController::focused, this, | ||
Show All 16 Lines | |||||
584 | } | 625 | } | ||
585 | 626 | | |||
586 | void ViewManager::controllerChanged(SessionController *controller) | 627 | void ViewManager::controllerChanged(SessionController *controller) | ||
587 | { | 628 | { | ||
588 | if (controller == _pluggedController) { | 629 | if (controller == _pluggedController) { | ||
589 | return; | 630 | return; | ||
590 | } | 631 | } | ||
591 | 632 | | |||
592 | _viewSplitter->setFocusProxy(controller->view()); | 633 | //TODO: Verify This. | ||
634 | // _viewSplitter->setFocusProxy(controller->view()); | ||||
635 | | ||||
636 | updateTerminalDisplayHistory(controller->view()); | ||||
593 | 637 | | |||
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; | 638 | _pluggedController = controller; | ||
595 | emit activeViewChanged(controller); | 639 | emit activeViewChanged(controller); | ||
596 | } | 640 | } | ||
597 | 641 | | |||
598 | SessionController *ViewManager::activeViewController() const | 642 | SessionController *ViewManager::activeViewController() const | ||
599 | { | 643 | { | ||
600 | return _pluggedController; | 644 | return _pluggedController; | ||
601 | } | 645 | } | ||
602 | 646 | | |||
603 | void ViewManager::createView(Session *session, TabbedViewContainer *container, int index) | 647 | void ViewManager::attachView(TerminalDisplay *terminal, Session *session) | ||
648 | { | ||||
649 | createController(session, terminal); | ||||
650 | connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished, Qt::UniqueConnection); | ||||
651 | _sessionMap[terminal] = session; | ||||
652 | updateDetachViewState(); | ||||
653 | _terminalDisplayHistory.append(terminal); | ||||
654 | } | ||||
655 | | ||||
656 | TerminalDisplay *ViewManager::createView(Session *session) | ||||
604 | { | 657 | { | ||
605 | // notify this view manager when the session finishes so that its view | 658 | // notify this view manager when the session finishes so that its view | ||
606 | // can be deleted | 659 | // can be deleted | ||
607 | // | 660 | // | ||
608 | // Use Qt::UniqueConnection to avoid duplicate connection | 661 | // Use Qt::UniqueConnection to avoid duplicate connection | ||
609 | connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished, | 662 | connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished, | ||
610 | Qt::UniqueConnection); | 663 | Qt::UniqueConnection); | ||
611 | | ||||
612 | TerminalDisplay *display = createTerminalDisplay(session); | 664 | TerminalDisplay *display = createTerminalDisplay(session); | ||
665 | | ||||
613 | const Profile::Ptr profile = SessionManager::instance()->sessionProfile(session); | 666 | const Profile::Ptr profile = SessionManager::instance()->sessionProfile(session); | ||
614 | applyProfileToView(display, profile); | 667 | applyProfileToView(display, profile); | ||
615 | 668 | | |||
616 | // set initial size | 669 | // set initial size | ||
617 | const QSize &preferredSize = session->preferredSize(); | 670 | const QSize &preferredSize = session->preferredSize(); | ||
618 | 671 | | |||
619 | display->setSize(preferredSize.width(), preferredSize.height()); | 672 | display->setSize(preferredSize.width(), preferredSize.height()); | ||
620 | createController(session, display); | 673 | createController(session, display); | ||
621 | 674 | | |||
622 | _sessionMap[display] = session; | 675 | _sessionMap[display] = session; | ||
623 | container->addView(display, index); | | |||
624 | session->addView(display); | 676 | session->addView(display); | ||
677 | _terminalDisplayHistory.append(display); | ||||
625 | 678 | | |||
626 | // tell the session whether it has a light or dark background | 679 | // tell the session whether it has a light or dark background | ||
627 | session->setDarkBackground(colorSchemeForProfile(profile)->hasDarkBackground()); | 680 | session->setDarkBackground(colorSchemeForProfile(profile)->hasDarkBackground()); | ||
628 | container->setCurrentWidget(display); | | |||
629 | display->setFocus(Qt::OtherFocusReason); | 681 | display->setFocus(Qt::OtherFocusReason); | ||
630 | | ||||
631 | updateDetachViewState(); | 682 | updateDetachViewState(); | ||
632 | } | | |||
633 | | ||||
634 | void ViewManager::createView(TabbedViewContainer *tabWidget, Session *session) | | |||
635 | { | | |||
636 | const int index = _newTabBehavior == PutNewTabAfterCurrentTab ? | | |||
637 | _viewSplitter->activeContainer()->currentIndex() + 1 : -1; | | |||
638 | 683 | | |||
639 | createView(session, tabWidget, index); | 684 | return display; | ||
640 | } | 685 | } | ||
641 | 686 | | |||
642 | TabbedViewContainer *ViewManager::createContainer() | 687 | TabbedViewContainer *ViewManager::createContainer() | ||
643 | { | 688 | { | ||
644 | 689 | auto *container = new TabbedViewContainer(this, nullptr); | |||
645 | auto *container = new TabbedViewContainer(this, _viewSplitter); | | |||
646 | container->setNavigationVisibility(_navigationVisibility); | 690 | container->setNavigationVisibility(_navigationVisibility); | ||
647 | //TODO: Fix Detaching. | 691 | //TODO: Fix Detaching. | ||
648 | connect(container, &TabbedViewContainer::detachTab, this, &ViewManager::detachView); | 692 | connect(container, &TabbedViewContainer::detachTab, this, &ViewManager::detachTab); | ||
649 | 693 | | |||
650 | // connect signals and slots | 694 | // connect signals and slots | ||
651 | connect(container, &Konsole::TabbedViewContainer::viewAdded, this, | 695 | connect(container, &Konsole::TabbedViewContainer::viewAdded, this, | ||
652 | [this, container]() { | 696 | [this, container]() { | ||
653 | containerViewsChanged(container); | 697 | containerViewsChanged(container); | ||
654 | }); | 698 | }); | ||
655 | 699 | | |||
656 | connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, | 700 | connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, | ||
Show All 12 Lines | |||||
669 | connect(container, &Konsole::TabbedViewContainer::activeViewChanged, this, | 713 | connect(container, &Konsole::TabbedViewContainer::activeViewChanged, this, | ||
670 | &Konsole::ViewManager::viewActivated); | 714 | &Konsole::ViewManager::viewActivated); | ||
671 | 715 | | |||
672 | return container; | 716 | return container; | ||
673 | } | 717 | } | ||
674 | 718 | | |||
675 | void ViewManager::containerMoveViewRequest(int index, int id) | 719 | void ViewManager::containerMoveViewRequest(int index, int id) | ||
676 | { | 720 | { | ||
721 | Q_UNUSED(index); | ||||
722 | | ||||
677 | auto *container = qobject_cast<TabbedViewContainer *>(sender()); | 723 | auto *container = qobject_cast<TabbedViewContainer *>(sender()); | ||
678 | auto *controller = qobject_cast<SessionController *>(ViewProperties::propertiesById(id)); | 724 | auto *controller = qobject_cast<SessionController *>(ViewProperties::propertiesById(id)); | ||
679 | Q_ASSERT(container); | 725 | Q_ASSERT(container); | ||
680 | Q_ASSERT(controller); | 726 | Q_ASSERT(controller); | ||
681 | 727 | | |||
682 | createView(controller->session(), container, index); | 728 | createView(controller->session()); | ||
683 | controller->session()->refresh(); | 729 | controller->session()->refresh(); | ||
684 | container->currentWidget()->setFocus(); | 730 | container->currentWidget()->setFocus(); | ||
685 | } | 731 | } | ||
686 | 732 | | |||
687 | void ViewManager::setNavigationMethod(NavigationMethod method) | 733 | void ViewManager::setNavigationMethod(NavigationMethod method) | ||
688 | { | 734 | { | ||
689 | Q_ASSERT(_actionCollection); | 735 | Q_ASSERT(_actionCollection); | ||
690 | if (_actionCollection == nullptr) { | 736 | if (_actionCollection == nullptr) { | ||
Show All 34 Lines | |||||
725 | } | 771 | } | ||
726 | 772 | | |||
727 | ViewManager::NavigationMethod ViewManager::navigationMethod() const | 773 | ViewManager::NavigationMethod ViewManager::navigationMethod() const | ||
728 | { | 774 | { | ||
729 | return _navigationMethod; | 775 | return _navigationMethod; | ||
730 | } | 776 | } | ||
731 | 777 | | |||
732 | void ViewManager::containerViewsChanged(TabbedViewContainer *container) | 778 | void ViewManager::containerViewsChanged(TabbedViewContainer *container) | ||
733 | { | 779 | { | ||
734 | if ((!_viewSplitter.isNull()) && container == _viewSplitter->activeContainer()) { | 780 | // TODO: Verify that this is right. | ||
hindenburg: container not used | |||||
735 | emit viewPropertiesChanged(viewProperties()); | 781 | emit viewPropertiesChanged(viewProperties()); | ||
736 | } | 782 | } | ||
737 | } | | |||
738 | 783 | | |||
739 | void ViewManager::viewDestroyed(QWidget *view) | 784 | void ViewManager::viewDestroyed(QWidget *view) | ||
740 | { | 785 | { | ||
786 | qDebug() << "TerminalDisplay destroyed"; | ||||
741 | // Note: the received QWidget has already been destroyed, so | 787 | // Note: the received QWidget has already been destroyed, so | ||
742 | // using dynamic_cast<> or qobject_cast<> does not work here | 788 | // using dynamic_cast<> or qobject_cast<> does not work here | ||
743 | // We only need the pointer address to look it up below | 789 | // We only need the pointer address to look it up below | ||
744 | auto *display = reinterpret_cast<TerminalDisplay *>(view); | 790 | auto *display = reinterpret_cast<TerminalDisplay *>(view); | ||
745 | 791 | | |||
746 | // 1. detach view from session | 792 | // 1. detach view from session | ||
747 | // 2. if the session has no views left, close it | 793 | // 2. if the session has no views left, close it | ||
748 | Session *session = _sessionMap[ display ]; | 794 | Session *session = _sessionMap[ display ]; | ||
749 | _sessionMap.remove(display); | 795 | _sessionMap.remove(display); | ||
750 | if (session != nullptr) { | 796 | if (session != nullptr) { | ||
751 | if (session->views().count() == 0) { | 797 | if (session->views().count() == 0) { | ||
752 | session->close(); | 798 | session->close(); | ||
753 | } | 799 | } | ||
754 | } | 800 | } | ||
755 | //we only update the focus if the splitter is still alive | 801 | //we only update the focus if the splitter is still alive | ||
802 | // TODO: Verify. | ||||
803 | #if 0 | ||||
756 | if (!_viewSplitter.isNull()) { | 804 | if (!_viewSplitter.isNull()) { | ||
757 | updateDetachViewState(); | 805 | updateDetachViewState(); | ||
758 | } | 806 | } | ||
807 | #endif | ||||
759 | // The below causes the menus to be messed up | 808 | // The below causes the menus to be messed up | ||
760 | // Only happens when using the tab bar close button | 809 | // Only happens when using the tab bar close button | ||
761 | // if (_pluggedController) | 810 | // if (_pluggedController) | ||
762 | // emit unplugController(_pluggedController); | 811 | // emit unplugController(_pluggedController); | ||
812 | qDebug() << "End of view destroyed"; | ||||
763 | } | 813 | } | ||
764 | 814 | | |||
765 | TerminalDisplay *ViewManager::createTerminalDisplay(Session *session) | 815 | TerminalDisplay *ViewManager::createTerminalDisplay(Session *session) | ||
766 | { | 816 | { | ||
767 | auto display = new TerminalDisplay(nullptr); | 817 | auto display = new TerminalDisplay(nullptr); | ||
768 | display->setRandomSeed(session->sessionId() * 31); | 818 | display->setRandomSeed(session->sessionId() * 31); | ||
769 | 819 | | |||
770 | return display; | 820 | return display; | ||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Line(s) | 924 | while (iter.hasNext()) { | |||
882 | } | 932 | } | ||
883 | } | 933 | } | ||
884 | } | 934 | } | ||
885 | 935 | | |||
886 | QList<ViewProperties *> ViewManager::viewProperties() const | 936 | QList<ViewProperties *> ViewManager::viewProperties() const | ||
887 | { | 937 | { | ||
888 | QList<ViewProperties *> list; | 938 | QList<ViewProperties *> list; | ||
889 | 939 | | |||
890 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 940 | TabbedViewContainer *container = _viewContainer; | ||
891 | if (container == nullptr) { | 941 | if (container == nullptr) { | ||
892 | return {}; | 942 | return {}; | ||
893 | } | 943 | } | ||
894 | 944 | | |||
895 | list.reserve(container->count()); | 945 | auto terminalContainers = _viewContainer->findChildren<TerminalDisplay*>(); | ||
946 | list.reserve(terminalContainers.size()); | ||||
896 | 947 | | |||
897 | for(int i = 0, end = container->count(); i < end; i++) { | 948 | for(auto terminalDisplay : _viewContainer->findChildren<TerminalDisplay*>()) { | ||
898 | auto view = container->terminalAt(i); | 949 | list.append(terminalDisplay->sessionController()); | ||
899 | ViewProperties *properties = view->sessionController(); | | |||
900 | Q_ASSERT(properties); | | |||
901 | list << properties; | | |||
902 | } | 950 | } | ||
903 | 951 | | |||
904 | return list; | 952 | return list; | ||
905 | } | 953 | } | ||
906 | 954 | | |||
907 | void ViewManager::saveSessions(KConfigGroup &group) | 955 | void ViewManager::saveSessions(KConfigGroup &group) | ||
908 | { | 956 | { | ||
909 | // find all unique session restore IDs | 957 | // find all unique session restore IDs | ||
910 | QList<int> ids; | 958 | QList<int> ids; | ||
911 | QSet<Session *> unique; | 959 | QSet<Session *> unique; | ||
912 | int tab = 1; | 960 | int tab = 1; | ||
913 | 961 | | |||
914 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 962 | TabbedViewContainer *container = _viewContainer; | ||
915 | 963 | | |||
916 | // first: sessions in the active container, preserving the order | 964 | // first: sessions in the active container, preserving the order | ||
917 | Q_ASSERT(container); | 965 | Q_ASSERT(container); | ||
918 | if (container == nullptr) { | 966 | if (container == nullptr) { | ||
919 | return; | 967 | return; | ||
920 | } | 968 | } | ||
921 | ids.reserve(container->count()); | 969 | ids.reserve(container->count()); | ||
922 | 970 | | |||
971 | //TODO: Handle sessions | ||||
972 | #if 0 | ||||
hindenburg: I need to test session restores w/ splits. | |||||
923 | auto *activeview = qobject_cast<TerminalDisplay *>(container->currentWidget()); | 973 | auto *activeview = qobject_cast<TerminalDisplay *>(container->currentWidget()); | ||
924 | for (int i = 0, end = container->count(); i < end; i++) { | 974 | for (int i = 0, end = container->count(); i < end; i++) { | ||
925 | auto *view = qobject_cast<TerminalDisplay *>(container->widget(i)); | 975 | auto *view = qobject_cast<TerminalDisplay *>(container->widget(i)); | ||
926 | Q_ASSERT(view); | 976 | Q_ASSERT(view); | ||
927 | 977 | | |||
928 | Session *session = _sessionMap[view]; | 978 | Session *session = _sessionMap[view]; | ||
929 | ids << SessionManager::instance()->getRestoreId(session); | 979 | ids << SessionManager::instance()->getRestoreId(session); | ||
930 | unique.insert(session); | 980 | unique.insert(session); | ||
931 | if (view == activeview) { | 981 | if (view == activeview) { | ||
932 | group.writeEntry("Active", tab); | 982 | group.writeEntry("Active", tab); | ||
933 | } | 983 | } | ||
934 | tab++; | 984 | tab++; | ||
935 | } | 985 | } | ||
986 | #endif | ||||
936 | 987 | | |||
937 | // second: all other sessions, in random order | 988 | // second: all other sessions, in random order | ||
938 | // we don't want to have sessions restored that are not connected | 989 | // we don't want to have sessions restored that are not connected | ||
939 | foreach (Session *session, _sessionMap) { | 990 | foreach (Session *session, _sessionMap) { | ||
940 | if (!unique.contains(session)) { | 991 | if (!unique.contains(session)) { | ||
941 | ids << SessionManager::instance()->getRestoreId(session); | 992 | ids << SessionManager::instance()->getRestoreId(session); | ||
942 | unique.insert(session); | 993 | unique.insert(session); | ||
943 | } | 994 | } | ||
944 | } | 995 | } | ||
945 | 996 | | |||
946 | group.writeEntry("Sessions", ids); | 997 | group.writeEntry("Sessions", ids); | ||
947 | } | 998 | } | ||
948 | 999 | | |||
949 | TabbedViewContainer *ViewManager::activeContainer() | 1000 | TabbedViewContainer *ViewManager::activeContainer() | ||
950 | { | 1001 | { | ||
951 | return _viewSplitter->activeContainer(); | 1002 | return _viewContainer; | ||
952 | } | 1003 | } | ||
953 | 1004 | | |||
954 | void ViewManager::restoreSessions(const KConfigGroup &group) | 1005 | void ViewManager::restoreSessions(const KConfigGroup &group) | ||
955 | { | 1006 | { | ||
956 | QList<int> ids = group.readEntry("Sessions", QList<int>()); | 1007 | QList<int> ids = group.readEntry("Sessions", QList<int>()); | ||
957 | int activeTab = group.readEntry("Active", 0); | 1008 | int activeTab = group.readEntry("Active", 0); | ||
958 | TerminalDisplay *display = nullptr; | 1009 | TerminalDisplay *display = nullptr; | ||
959 | 1010 | | |||
960 | int tab = 1; | 1011 | int tab = 1; | ||
961 | foreach (int id, ids) { | 1012 | foreach (int id, ids) { | ||
962 | Session *session = SessionManager::instance()->idToSession(id); | 1013 | Session *session = SessionManager::instance()->idToSession(id); | ||
963 | 1014 | | |||
964 | if (session == nullptr) { | 1015 | if (session == nullptr) { | ||
965 | qWarning() << "Unable to load session with id" << id; | 1016 | qWarning() << "Unable to load session with id" << id; | ||
966 | // Force a creation of a default session below | 1017 | // Force a creation of a default session below | ||
967 | ids.clear(); | 1018 | ids.clear(); | ||
968 | break; | 1019 | break; | ||
969 | } | 1020 | } | ||
970 | 1021 | | |||
971 | createView(activeContainer(), session); | 1022 | createView(session); | ||
972 | if (!session->isRunning()) { | 1023 | if (!session->isRunning()) { | ||
973 | session->run(); | 1024 | session->run(); | ||
974 | } | 1025 | } | ||
975 | if (tab++ == activeTab) { | 1026 | if (tab++ == activeTab) { | ||
976 | display = qobject_cast<TerminalDisplay *>(activeView()); | 1027 | display = qobject_cast<TerminalDisplay *>(activeView()); | ||
977 | } | 1028 | } | ||
978 | } | 1029 | } | ||
979 | 1030 | | |||
980 | if (display != nullptr) { | 1031 | if (display != nullptr) { | ||
981 | _viewSplitter->activeContainer()->setCurrentWidget(display); | 1032 | activeContainer()->setCurrentWidget(display); | ||
982 | display->setFocus(Qt::OtherFocusReason); | 1033 | display->setFocus(Qt::OtherFocusReason); | ||
983 | } | 1034 | } | ||
984 | 1035 | | |||
985 | if (ids.isEmpty()) { // Session file is unusable, start default Profile | 1036 | if (ids.isEmpty()) { // Session file is unusable, start default Profile | ||
986 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | 1037 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | ||
987 | Session *session = SessionManager::instance()->createSession(profile); | 1038 | Session *session = SessionManager::instance()->createSession(profile); | ||
988 | createView(activeContainer(), session); | 1039 | createView(session); | ||
989 | if (!session->isRunning()) { | 1040 | if (!session->isRunning()) { | ||
990 | session->run(); | 1041 | session->run(); | ||
991 | } | 1042 | } | ||
992 | } | 1043 | } | ||
993 | } | 1044 | } | ||
994 | 1045 | | |||
995 | int ViewManager::sessionCount() | 1046 | int ViewManager::sessionCount() | ||
996 | { | 1047 | { | ||
Show All 23 Lines | 1064 | { | |||
1020 | return -1; | 1071 | return -1; | ||
1021 | } | 1072 | } | ||
1022 | 1073 | | |||
1023 | void ViewManager::setCurrentSession(int sessionId) | 1074 | void ViewManager::setCurrentSession(int sessionId) | ||
1024 | { | 1075 | { | ||
1025 | QHash<TerminalDisplay *, Session *>::const_iterator i; | 1076 | QHash<TerminalDisplay *, Session *>::const_iterator i; | ||
1026 | for (i = _sessionMap.constBegin(); i != _sessionMap.constEnd(); ++i) { | 1077 | for (i = _sessionMap.constBegin(); i != _sessionMap.constEnd(); ++i) { | ||
1027 | if (i.value()->sessionId() == sessionId) { | 1078 | if (i.value()->sessionId() == sessionId) { | ||
1028 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 1079 | TabbedViewContainer *container = activeContainer(); | ||
1029 | if (container != nullptr) { | 1080 | if (container != nullptr) { | ||
1030 | container->setCurrentWidget(i.key()); | 1081 | container->setCurrentWidget(i.key()); | ||
1031 | } | 1082 | } | ||
1032 | } | 1083 | } | ||
1033 | } | 1084 | } | ||
1034 | } | 1085 | } | ||
1035 | 1086 | | |||
1036 | int ViewManager::newSession() | 1087 | int ViewManager::newSession() | ||
1037 | { | 1088 | { | ||
1038 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | 1089 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | ||
1039 | Session *session = SessionManager::instance()->createSession(profile); | 1090 | Session *session = SessionManager::instance()->createSession(profile); | ||
1040 | 1091 | | |||
1041 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 1092 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
1042 | 1093 | | |||
1043 | createView(activeContainer(), session); | 1094 | createView(session); | ||
1044 | session->run(); | 1095 | session->run(); | ||
1045 | 1096 | | |||
1046 | return session->sessionId(); | 1097 | return session->sessionId(); | ||
1047 | } | 1098 | } | ||
1048 | 1099 | | |||
1049 | int ViewManager::newSession(const QString &profile) | 1100 | int ViewManager::newSession(const QString &profile) | ||
1050 | { | 1101 | { | ||
1051 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | 1102 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | ||
1052 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | 1103 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | ||
1053 | 1104 | | |||
1054 | for (const auto &i : profilelist) { | 1105 | for (const auto &i : profilelist) { | ||
1055 | if (i->name() == profile) { | 1106 | if (i->name() == profile) { | ||
1056 | profileptr = i; | 1107 | profileptr = i; | ||
1057 | break; | 1108 | break; | ||
1058 | } | 1109 | } | ||
1059 | } | 1110 | } | ||
1060 | 1111 | | |||
1061 | Session *session = SessionManager::instance()->createSession(profileptr); | 1112 | Session *session = SessionManager::instance()->createSession(profileptr); | ||
1062 | 1113 | | |||
1063 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 1114 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
1064 | 1115 | | |||
1065 | createView(activeContainer(), session); | 1116 | createView(session); | ||
1066 | session->run(); | 1117 | session->run(); | ||
1067 | 1118 | | |||
1068 | return session->sessionId(); | 1119 | return session->sessionId(); | ||
1069 | } | 1120 | } | ||
1070 | 1121 | | |||
1071 | int ViewManager::newSession(const QString &profile, const QString &directory) | 1122 | int ViewManager::newSession(const QString &profile, const QString &directory) | ||
1072 | { | 1123 | { | ||
1073 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | 1124 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | ||
1074 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | 1125 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | ||
1075 | 1126 | | |||
1076 | for (const auto &i : profilelist) { | 1127 | for (const auto &i : profilelist) { | ||
1077 | if (i->name() == profile) { | 1128 | if (i->name() == profile) { | ||
1078 | profileptr = i; | 1129 | profileptr = i; | ||
1079 | break; | 1130 | break; | ||
1080 | } | 1131 | } | ||
1081 | } | 1132 | } | ||
1082 | 1133 | | |||
1083 | Session *session = SessionManager::instance()->createSession(profileptr); | 1134 | Session *session = SessionManager::instance()->createSession(profileptr); | ||
1084 | session->setInitialWorkingDirectory(directory); | 1135 | session->setInitialWorkingDirectory(directory); | ||
1085 | 1136 | | |||
1086 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 1137 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
1087 | 1138 | | |||
1088 | createView(activeContainer(), session); | 1139 | createView(session); | ||
1089 | session->run(); | 1140 | session->run(); | ||
1090 | 1141 | | |||
1091 | return session->sessionId(); | 1142 | return session->sessionId(); | ||
1092 | } | 1143 | } | ||
1093 | 1144 | | |||
1094 | QString ViewManager::defaultProfile() | 1145 | QString ViewManager::defaultProfile() | ||
1095 | { | 1146 | { | ||
1096 | return ProfileManager::instance()->defaultProfile()->name(); | 1147 | return ProfileManager::instance()->defaultProfile()->name(); | ||
Show All 21 Lines | |||||
1118 | 1169 | | |||
1119 | void ViewManager::moveSessionRight() | 1170 | void ViewManager::moveSessionRight() | ||
1120 | { | 1171 | { | ||
1121 | moveActiveViewRight(); | 1172 | moveActiveViewRight(); | ||
1122 | } | 1173 | } | ||
1123 | 1174 | | |||
1124 | void ViewManager::setTabWidthToText(bool setTabWidthToText) | 1175 | void ViewManager::setTabWidthToText(bool setTabWidthToText) | ||
1125 | { | 1176 | { | ||
1126 | for(auto container : _viewSplitter->containers()) { | 1177 | _viewContainer->tabBar()->setExpanding(!setTabWidthToText); | ||
1127 | container->tabBar()->setExpanding(!setTabWidthToText); | 1178 | _viewContainer->tabBar()->update(); | ||
1128 | container->tabBar()->update(); | | |||
1129 | } | | |||
1130 | } | 1179 | } | ||
1131 | 1180 | | |||
1132 | void ViewManager::setNavigationVisibility(NavigationVisibility navigationVisibility) { | 1181 | void ViewManager::setNavigationVisibility(NavigationVisibility navigationVisibility) { | ||
1133 | if (_navigationVisibility != navigationVisibility) { | 1182 | if (_navigationVisibility != navigationVisibility) { | ||
1134 | _navigationVisibility = navigationVisibility; | 1183 | _navigationVisibility = navigationVisibility; | ||
1135 | for(auto *container : _viewSplitter->containers()) { | 1184 | _viewContainer->setNavigationVisibility(navigationVisibility); | ||
1136 | container->setNavigationVisibility(navigationVisibility); | | |||
1137 | } | | |||
1138 | } | 1185 | } | ||
1139 | } | 1186 | } | ||
1140 | 1187 | | |||
1141 | void ViewManager::setNavigationBehavior(int behavior) | 1188 | void ViewManager::setNavigationBehavior(int behavior) | ||
1142 | { | 1189 | { | ||
1143 | _newTabBehavior = static_cast<NewTabBehavior>(behavior); | 1190 | _newTabBehavior = static_cast<NewTabBehavior>(behavior); | ||
1144 | } | 1191 | } | ||
1192 | | ||||
1193 | void ViewManager::updateTerminalDisplayHistory(TerminalDisplay* terminalDisplay, bool remove) | ||||
1194 | { | ||||
1195 | if (terminalDisplay == nullptr) { | ||||
1196 | if (_terminalDisplayHistoryIndex >= 0) { | ||||
1197 | // This is the case when we finished walking through the history | ||||
1198 | // (i.e. when Ctrl-Tab has been released) | ||||
1199 | terminalDisplay = _terminalDisplayHistory[_terminalDisplayHistoryIndex]; | ||||
1200 | _terminalDisplayHistoryIndex = -1; | ||||
1201 | } else { | ||||
1202 | return; | ||||
1203 | } | ||||
1204 | } | ||||
1205 | | ||||
1206 | if (_terminalDisplayHistoryIndex >= 0 && !remove) { | ||||
1207 | // Do not reorder the tab history while we are walking through it | ||||
1208 | return; | ||||
1209 | } | ||||
1210 | | ||||
1211 | for (int i = 0; i < _terminalDisplayHistory.count(); i++) { | ||||
1212 | if (_terminalDisplayHistory[i] == terminalDisplay) { | ||||
1213 | _terminalDisplayHistory.removeAt(i); | ||||
1214 | if (!remove) { | ||||
1215 | _terminalDisplayHistory.prepend(terminalDisplay); | ||||
1216 | } | ||||
1217 | break; | ||||
1218 | } | ||||
1219 | } | ||||
1220 | } |
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.