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 | auto terminals = splitter->getTerminalDisplays(); | ||||
438 | QHash<TerminalDisplay*, Session*> detachedSessions; | ||||
439 | foreach(TerminalDisplay* terminal, terminals) { | ||||
440 | Session* session = forgetTerminal(terminal); | ||||
441 | detachedSessions[terminal] = session; | ||||
442 | } | ||||
443 | return detachedSessions; | ||||
444 | } | ||||
414 | 445 | | |||
415 | // remove the view from this window | 446 | Session* ViewManager::forgetTerminal(TerminalDisplay* terminal) | ||
416 | container->removeView(viewToDetach); | 447 | { | ||
417 | viewToDetach->deleteLater(); | 448 | removeController(terminal->sessionController()); | ||
418 | 449 | auto session = _sessionMap.take(terminal); | |||
419 | // if the container from which the view was removed is now empty then it can be deleted, | 450 | if (session != nullptr) { | ||
420 | // unless it is the only container in the window, in which case it is left empty | 451 | 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 | } | 452 | } | ||
453 | _viewContainer->disconnectTerminalDisplay(terminal); | ||||
454 | updateTerminalDisplayHistory(terminal, true); | ||||
455 | return session; | ||||
426 | } | 456 | } | ||
427 | 457 | | |||
428 | void ViewManager::sessionFinished() | 458 | void ViewManager::sessionFinished() | ||
429 | { | 459 | { | ||
430 | // if this slot is called after the view manager's main widget | 460 | // if this slot is called after the view manager's main widget | ||
431 | // has been destroyed, do nothing | 461 | // has been destroyed, do nothing | ||
432 | if (_viewSplitter.isNull()) { | 462 | if (_viewContainer.isNull()) { | ||
433 | return; | 463 | return; | ||
434 | } | 464 | } | ||
435 | 465 | | |||
436 | auto *session = qobject_cast<Session *>(sender()); | 466 | auto *session = qobject_cast<Session *>(sender()); | ||
437 | Q_ASSERT(session); | 467 | Q_ASSERT(session); | ||
438 | 468 | | |||
439 | // close attached views | 469 | 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); | 470 | _sessionMap.remove(view); | ||
471 | | ||||
472 | // Before deleting the view, let's unmaximize if it's maximized. | ||||
473 | auto splitter = qobject_cast<ViewSplitter*>(view->parentWidget()); | ||||
474 | auto toplevelSplitter = splitter->getToplevelSplitter(); | ||||
475 | toplevelSplitter->restoreOtherTerminals(); | ||||
476 | _viewContainer->removeView(view); | ||||
445 | view->deleteLater(); | 477 | view->deleteLater(); | ||
446 | } | | |||
447 | } | | |||
448 | 478 | | |||
449 | // Only remove the controller from factory() if it's actually controlling | 479 | // Only remove the controller from factory() if it's actually controlling | ||
450 | // the session from the sender. | 480 | // the session from the sender. | ||
451 | // This fixes BUG: 348478 - messed up menus after a detached tab is closed | 481 | // This fixes BUG: 348478 - messed up menus after a detached tab is closed | ||
452 | if ((!_pluggedController.isNull()) && (_pluggedController->session() == session)) { | 482 | if ((!_pluggedController.isNull()) && (_pluggedController->session() == session)) { | ||
453 | // This is needed to remove this controller from factory() in | 483 | // This is needed to remove this controller from factory() in | ||
454 | // order to prevent BUG: 185466 - disappearing menu popup | 484 | // order to prevent BUG: 185466 - disappearing menu popup | ||
455 | emit unplugController(_pluggedController); | 485 | emit unplugController(_pluggedController); | ||
456 | } | 486 | } | ||
487 | | ||||
488 | updateTerminalDisplayHistory(view, true); | ||||
489 | focusAnotherTerminal(toplevelSplitter); | ||||
490 | updateDetachViewState(); | ||||
491 | } | ||||
492 | | ||||
493 | void ViewManager::focusAnotherTerminal(ViewSplitter *toplevelSplitter) | ||||
494 | { | ||||
495 | auto tabTterminalDisplays = toplevelSplitter->findChildren<TerminalDisplay*>(); | ||||
496 | if (tabTterminalDisplays.count() > 1) { | ||||
497 | // Give focus to the last used terminal in this tab | ||||
498 | for (auto *historyItem : _terminalDisplayHistory) { | ||||
499 | for (auto *terminalDisplay : tabTterminalDisplays) { | ||||
500 | if (terminalDisplay == historyItem) { | ||||
501 | terminalDisplay->setFocus(Qt::OtherFocusReason); | ||||
502 | return; | ||||
503 | } | ||||
504 | } | ||||
505 | } | ||||
506 | } else if (_terminalDisplayHistory.count() >= 1) { | ||||
507 | // Give focus to the last used terminal tab | ||||
508 | switchToTerminalDisplay(_terminalDisplayHistory[0]); | ||||
509 | } | ||||
457 | } | 510 | } | ||
458 | 511 | | |||
459 | void ViewManager::viewActivated(QWidget *view) | 512 | void ViewManager::viewActivated(TerminalDisplay *view) | ||
460 | { | 513 | { | ||
461 | Q_ASSERT(view != nullptr); | 514 | Q_ASSERT(view != nullptr); | ||
462 | 515 | | |||
463 | // focus the activated view, this will cause the SessionController | 516 | // focus the activated view, this will cause the SessionController | ||
464 | // to notify the world that the view has been focused and the appropriate UI | 517 | // to notify the world that the view has been focused and the appropriate UI | ||
465 | // actions will be plugged in. | 518 | // actions will be plugged in. | ||
466 | view->setFocus(Qt::OtherFocusReason); | 519 | view->setFocus(Qt::OtherFocusReason); | ||
467 | } | 520 | } | ||
468 | 521 | | |||
469 | void ViewManager::splitLeftRight() | 522 | void ViewManager::splitLeftRight() | ||
470 | { | 523 | { | ||
471 | splitView(Qt::Horizontal); | 524 | splitView(Qt::Horizontal); | ||
472 | } | 525 | } | ||
473 | 526 | | |||
474 | void ViewManager::splitTopBottom() | 527 | void ViewManager::splitTopBottom() | ||
475 | { | 528 | { | ||
476 | splitView(Qt::Vertical); | 529 | splitView(Qt::Vertical); | ||
477 | } | 530 | } | ||
478 | 531 | | |||
479 | void ViewManager::splitView(Qt::Orientation orientation) | 532 | void ViewManager::splitView(Qt::Orientation orientation) | ||
480 | { | 533 | { | ||
481 | TabbedViewContainer *container = createContainer(); | 534 | auto viewSplitter = qobject_cast<ViewSplitter*>(_viewContainer->currentWidget()); | ||
482 | 535 | | |||
483 | if (_viewSplitter->activeContainer()->count()) { | | |||
484 | // get the currently applied profile and use it to create the new tab. | 536 | // get the currently applied profile and use it to create the new tab. | ||
485 | auto *activeContainer= _viewSplitter->activeContainer(); | 537 | auto *currentDisplay = viewSplitter->findChild<TerminalDisplay*>(); | ||
486 | auto *currentDisplay = qobject_cast<TerminalDisplay*>(activeContainer->currentWidget()); | | |||
487 | auto profile = SessionManager::instance()->sessionProfile(_sessionMap[currentDisplay]); | 538 | auto profile = SessionManager::instance()->sessionProfile(_sessionMap[currentDisplay]); | ||
488 | 539 | | |||
489 | // Create a new session with the selected profile. | 540 | // Create a new session with the selected profile. | ||
490 | auto *session = SessionManager::instance()->createSession(profile); | 541 | auto *session = SessionManager::instance()->createSession(profile); | ||
491 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 542 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
492 | 543 | | |||
493 | createView(session, container, 0); | 544 | 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 | | ||||
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 | 545 | | |||
506 | if (activeView != nullptr) { | 546 | _viewContainer->splitView(terminalDisplay, orientation); | ||
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 | 547 | | |||
521 | _viewSplitter->removeContainer(container); | 548 | updateDetachViewState(); | ||
522 | container->deleteLater(); | | |||
523 | 549 | | |||
524 | emit splitViewToggle(_viewSplitter->containers().count() > 1); | 550 | // focus the new container | ||
551 | terminalDisplay->setFocus(); | ||||
525 | } | 552 | } | ||
526 | 553 | | |||
527 | void ViewManager::expandActiveContainer() | 554 | void ViewManager::expandActiveContainer() | ||
528 | { | 555 | { | ||
529 | _viewSplitter->adjustContainerSize(_viewSplitter->activeContainer(), 10); | 556 | _viewContainer->activeViewSplitter()->adjustActiveTerminalDisplaySize(10); | ||
530 | } | 557 | } | ||
531 | 558 | | |||
532 | void ViewManager::shrinkActiveContainer() | 559 | void ViewManager::shrinkActiveContainer() | ||
533 | { | 560 | { | ||
534 | _viewSplitter->adjustContainerSize(_viewSplitter->activeContainer(), -10); | 561 | _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 | } | 562 | } | ||
561 | 563 | | |||
562 | SessionController *ViewManager::createController(Session *session, TerminalDisplay *view) | 564 | SessionController *ViewManager::createController(Session *session, TerminalDisplay *view) | ||
563 | { | 565 | { | ||
564 | // create a new controller for the session, and ensure that this view manager | 566 | // create a new controller for the session, and ensure that this view manager | ||
565 | // is notified when the view gains the focus | 567 | // is notified when the view gains the focus | ||
566 | auto controller = new SessionController(session, view, this); | 568 | auto controller = new SessionController(session, view, this); | ||
567 | connect(controller, &Konsole::SessionController::focused, this, | 569 | 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 | 580 | // if this is the first controller created then set it as the active controller | ||
579 | if (_pluggedController.isNull()) { | 581 | if (_pluggedController.isNull()) { | ||
580 | controllerChanged(controller); | 582 | controllerChanged(controller); | ||
581 | } | 583 | } | ||
582 | 584 | | |||
583 | return controller; | 585 | return controller; | ||
584 | } | 586 | } | ||
585 | 587 | | |||
588 | // should this be handed by ViewManager::unplugController signal | ||||
589 | void ViewManager::removeController(SessionController* controller) | ||||
590 | { | ||||
591 | disconnect(controller, &Konsole::SessionController::focused, this, | ||||
592 | &Konsole::ViewManager::controllerChanged); | ||||
593 | if (_pluggedController == controller) { | ||||
594 | _pluggedController = nullptr; | ||||
595 | } | ||||
596 | controller->deleteLater(); | ||||
597 | } | ||||
598 | | ||||
586 | void ViewManager::controllerChanged(SessionController *controller) | 599 | void ViewManager::controllerChanged(SessionController *controller) | ||
587 | { | 600 | { | ||
588 | if (controller == _pluggedController) { | 601 | if (controller == _pluggedController) { | ||
589 | return; | 602 | return; | ||
590 | } | 603 | } | ||
591 | 604 | | |||
592 | _viewSplitter->setFocusProxy(controller->view()); | 605 | //TODO: Verify This. | ||
606 | // _viewSplitter->setFocusProxy(controller->view()); | ||||
607 | | ||||
608 | updateTerminalDisplayHistory(controller->view()); | ||||
593 | 609 | | |||
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; | 610 | _pluggedController = controller; | ||
595 | emit activeViewChanged(controller); | 611 | emit activeViewChanged(controller); | ||
596 | } | 612 | } | ||
597 | 613 | | |||
598 | SessionController *ViewManager::activeViewController() const | 614 | SessionController *ViewManager::activeViewController() const | ||
599 | { | 615 | { | ||
600 | return _pluggedController; | 616 | return _pluggedController; | ||
601 | } | 617 | } | ||
602 | 618 | | |||
603 | void ViewManager::createView(Session *session, TabbedViewContainer *container, int index) | 619 | void ViewManager::attachView(TerminalDisplay *terminal, Session *session) | ||
620 | { | ||||
621 | connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished, | ||||
622 | Qt::UniqueConnection); | ||||
623 | _sessionMap[terminal] = session; | ||||
624 | createController(session, terminal); | ||||
625 | updateDetachViewState(); | ||||
626 | _terminalDisplayHistory.append(terminal); | ||||
627 | } | ||||
628 | | ||||
629 | TerminalDisplay *ViewManager::createView(Session *session) | ||||
604 | { | 630 | { | ||
605 | // notify this view manager when the session finishes so that its view | 631 | // notify this view manager when the session finishes so that its view | ||
606 | // can be deleted | 632 | // can be deleted | ||
607 | // | 633 | // | ||
608 | // Use Qt::UniqueConnection to avoid duplicate connection | 634 | // Use Qt::UniqueConnection to avoid duplicate connection | ||
609 | connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished, | 635 | connect(session, &Konsole::Session::finished, this, &Konsole::ViewManager::sessionFinished, | ||
610 | Qt::UniqueConnection); | 636 | Qt::UniqueConnection); | ||
611 | | ||||
612 | TerminalDisplay *display = createTerminalDisplay(session); | 637 | TerminalDisplay *display = createTerminalDisplay(session); | ||
638 | | ||||
613 | const Profile::Ptr profile = SessionManager::instance()->sessionProfile(session); | 639 | const Profile::Ptr profile = SessionManager::instance()->sessionProfile(session); | ||
614 | applyProfileToView(display, profile); | 640 | applyProfileToView(display, profile); | ||
615 | 641 | | |||
616 | // set initial size | 642 | // set initial size | ||
617 | const QSize &preferredSize = session->preferredSize(); | 643 | const QSize &preferredSize = session->preferredSize(); | ||
618 | 644 | | |||
619 | display->setSize(preferredSize.width(), preferredSize.height()); | 645 | display->setSize(preferredSize.width(), preferredSize.height()); | ||
620 | createController(session, display); | 646 | createController(session, display); | ||
621 | 647 | | |||
622 | _sessionMap[display] = session; | 648 | _sessionMap[display] = session; | ||
623 | container->addView(display, index); | | |||
624 | session->addView(display); | 649 | session->addView(display); | ||
650 | _terminalDisplayHistory.append(display); | ||||
625 | 651 | | |||
626 | // tell the session whether it has a light or dark background | 652 | // tell the session whether it has a light or dark background | ||
627 | session->setDarkBackground(colorSchemeForProfile(profile)->hasDarkBackground()); | 653 | session->setDarkBackground(colorSchemeForProfile(profile)->hasDarkBackground()); | ||
628 | container->setCurrentWidget(display); | | |||
629 | display->setFocus(Qt::OtherFocusReason); | 654 | display->setFocus(Qt::OtherFocusReason); | ||
655 | // updateDetachViewState(); | ||||
630 | 656 | | |||
631 | updateDetachViewState(); | 657 | 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 | } | 658 | } | ||
641 | 659 | | |||
642 | TabbedViewContainer *ViewManager::createContainer() | 660 | TabbedViewContainer *ViewManager::createContainer() | ||
643 | { | 661 | { | ||
644 | 662 | auto *container = new TabbedViewContainer(this, nullptr); | |||
645 | auto *container = new TabbedViewContainer(this, _viewSplitter); | | |||
646 | container->setNavigationVisibility(_navigationVisibility); | 663 | container->setNavigationVisibility(_navigationVisibility); | ||
647 | //TODO: Fix Detaching. | 664 | connect(container, &TabbedViewContainer::detachTab, this, &ViewManager::detachTab); | ||
648 | connect(container, &TabbedViewContainer::detachTab, this, &ViewManager::detachView); | | |||
649 | 665 | | |||
650 | // connect signals and slots | 666 | // connect signals and slots | ||
651 | connect(container, &Konsole::TabbedViewContainer::viewAdded, this, | 667 | connect(container, &Konsole::TabbedViewContainer::viewAdded, this, | ||
652 | [this, container]() { | 668 | [this, container]() { | ||
653 | containerViewsChanged(container); | 669 | containerViewsChanged(container); | ||
654 | }); | 670 | }); | ||
655 | 671 | | |||
656 | connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, | 672 | connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, | ||
657 | [this, container]() { | 673 | [this, container]() { | ||
658 | containerViewsChanged(container); | 674 | containerViewsChanged(container); | ||
659 | }); | 675 | }); | ||
660 | 676 | | |||
661 | connect(container, &TabbedViewContainer::newViewRequest, | 677 | connect(container, &TabbedViewContainer::newViewRequest, | ||
662 | this, &ViewManager::newViewRequest); | 678 | this, &ViewManager::newViewRequest); | ||
663 | connect(container, &Konsole::TabbedViewContainer::newViewWithProfileRequest, | 679 | connect(container, &Konsole::TabbedViewContainer::newViewWithProfileRequest, | ||
664 | this, &Konsole::ViewManager::newViewWithProfileRequest); | 680 | this, &Konsole::ViewManager::newViewWithProfileRequest); | ||
665 | connect(container, &Konsole::TabbedViewContainer::moveViewRequest, this, | | |||
666 | &Konsole::ViewManager::containerMoveViewRequest); | | |||
667 | connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, | 681 | connect(container, &Konsole::TabbedViewContainer::viewRemoved, this, | ||
668 | &Konsole::ViewManager::viewDestroyed); | 682 | &Konsole::ViewManager::viewDestroyed); | ||
669 | connect(container, &Konsole::TabbedViewContainer::activeViewChanged, this, | 683 | connect(container, &Konsole::TabbedViewContainer::activeViewChanged, this, | ||
670 | &Konsole::ViewManager::viewActivated); | 684 | &Konsole::ViewManager::viewActivated); | ||
671 | 685 | | |||
672 | return container; | 686 | return container; | ||
673 | } | 687 | } | ||
674 | 688 | | |||
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) | 689 | void ViewManager::setNavigationMethod(NavigationMethod method) | ||
688 | { | 690 | { | ||
689 | Q_ASSERT(_actionCollection); | 691 | Q_ASSERT(_actionCollection); | ||
690 | if (_actionCollection == nullptr) { | 692 | if (_actionCollection == nullptr) { | ||
691 | return; | 693 | return; | ||
692 | } | 694 | } | ||
693 | KActionCollection *collection = _actionCollection; | 695 | KActionCollection *collection = _actionCollection; | ||
694 | 696 | | |||
Show All 30 Lines | |||||
725 | } | 727 | } | ||
726 | 728 | | |||
727 | ViewManager::NavigationMethod ViewManager::navigationMethod() const | 729 | ViewManager::NavigationMethod ViewManager::navigationMethod() const | ||
728 | { | 730 | { | ||
729 | return _navigationMethod; | 731 | return _navigationMethod; | ||
730 | } | 732 | } | ||
731 | 733 | | |||
732 | void ViewManager::containerViewsChanged(TabbedViewContainer *container) | 734 | void ViewManager::containerViewsChanged(TabbedViewContainer *container) | ||
733 | { | 735 | { | ||
734 | if ((!_viewSplitter.isNull()) && container == _viewSplitter->activeContainer()) { | 736 | // TODO: Verify that this is right. | ||
hindenburg: container not used | |||||
735 | emit viewPropertiesChanged(viewProperties()); | 737 | emit viewPropertiesChanged(viewProperties()); | ||
736 | } | 738 | } | ||
737 | } | | |||
738 | 739 | | |||
739 | void ViewManager::viewDestroyed(QWidget *view) | 740 | void ViewManager::viewDestroyed(QWidget *view) | ||
740 | { | 741 | { | ||
741 | // Note: the received QWidget has already been destroyed, so | 742 | // Note: the received QWidget has already been destroyed, so | ||
742 | // using dynamic_cast<> or qobject_cast<> does not work here | 743 | // using dynamic_cast<> or qobject_cast<> does not work here | ||
743 | // We only need the pointer address to look it up below | 744 | // We only need the pointer address to look it up below | ||
744 | auto *display = reinterpret_cast<TerminalDisplay *>(view); | 745 | auto *display = reinterpret_cast<TerminalDisplay *>(view); | ||
745 | 746 | | |||
746 | // 1. detach view from session | 747 | // 1. detach view from session | ||
747 | // 2. if the session has no views left, close it | 748 | // 2. if the session has no views left, close it | ||
748 | Session *session = _sessionMap[ display ]; | 749 | Session *session = _sessionMap[ display ]; | ||
749 | _sessionMap.remove(display); | 750 | _sessionMap.remove(display); | ||
750 | if (session != nullptr) { | 751 | if (session != nullptr) { | ||
751 | if (session->views().count() == 0) { | 752 | if (session->views().count() == 0) { | ||
752 | session->close(); | 753 | session->close(); | ||
753 | } | 754 | } | ||
754 | } | 755 | } | ||
756 | | ||||
755 | //we only update the focus if the splitter is still alive | 757 | //we only update the focus if the splitter is still alive | ||
756 | if (!_viewSplitter.isNull()) { | | |||
757 | updateDetachViewState(); | 758 | updateDetachViewState(); | ||
758 | } | 759 | | ||
759 | // The below causes the menus to be messed up | 760 | // The below causes the menus to be messed up | ||
760 | // Only happens when using the tab bar close button | 761 | // Only happens when using the tab bar close button | ||
761 | // if (_pluggedController) | 762 | // if (_pluggedController) | ||
762 | // emit unplugController(_pluggedController); | 763 | // emit unplugController(_pluggedController); | ||
763 | } | 764 | } | ||
764 | 765 | | |||
765 | TerminalDisplay *ViewManager::createTerminalDisplay(Session *session) | 766 | TerminalDisplay *ViewManager::createTerminalDisplay(Session *session) | ||
766 | { | 767 | { | ||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Line(s) | 875 | while (iter.hasNext()) { | |||
882 | } | 883 | } | ||
883 | } | 884 | } | ||
884 | } | 885 | } | ||
885 | 886 | | |||
886 | QList<ViewProperties *> ViewManager::viewProperties() const | 887 | QList<ViewProperties *> ViewManager::viewProperties() const | ||
887 | { | 888 | { | ||
888 | QList<ViewProperties *> list; | 889 | QList<ViewProperties *> list; | ||
889 | 890 | | |||
890 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 891 | TabbedViewContainer *container = _viewContainer; | ||
891 | if (container == nullptr) { | 892 | if (container == nullptr) { | ||
892 | return {}; | 893 | return {}; | ||
893 | } | 894 | } | ||
894 | 895 | | |||
895 | list.reserve(container->count()); | 896 | auto terminalContainers = _viewContainer->findChildren<TerminalDisplay*>(); | ||
897 | list.reserve(terminalContainers.size()); | ||||
896 | 898 | | |||
897 | for(int i = 0, end = container->count(); i < end; i++) { | 899 | for(auto terminalDisplay : _viewContainer->findChildren<TerminalDisplay*>()) { | ||
898 | auto view = container->terminalAt(i); | 900 | list.append(terminalDisplay->sessionController()); | ||
899 | ViewProperties *properties = view->sessionController(); | | |||
900 | Q_ASSERT(properties); | | |||
901 | list << properties; | | |||
902 | } | 901 | } | ||
903 | 902 | | |||
904 | return list; | 903 | return list; | ||
905 | } | 904 | } | ||
906 | 905 | | |||
907 | void ViewManager::saveSessions(KConfigGroup &group) | 906 | void ViewManager::saveSessions(KConfigGroup &group) | ||
908 | { | 907 | { | ||
909 | // find all unique session restore IDs | 908 | // find all unique session restore IDs | ||
910 | QList<int> ids; | 909 | QList<int> ids; | ||
911 | QSet<Session *> unique; | 910 | QSet<Session *> unique; | ||
912 | int tab = 1; | 911 | int tab = 1; | ||
913 | 912 | | |||
914 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 913 | TabbedViewContainer *container = _viewContainer; | ||
915 | 914 | | |||
916 | // first: sessions in the active container, preserving the order | 915 | // first: sessions in the active container, preserving the order | ||
917 | Q_ASSERT(container); | 916 | Q_ASSERT(container); | ||
918 | if (container == nullptr) { | 917 | if (container == nullptr) { | ||
919 | return; | 918 | return; | ||
920 | } | 919 | } | ||
921 | ids.reserve(container->count()); | 920 | ids.reserve(container->count()); | ||
922 | 921 | | |||
922 | //TODO: Handle sessions | ||||
923 | #if 0 | ||||
hindenburg: I need to test session restores w/ splits. | |||||
923 | auto *activeview = qobject_cast<TerminalDisplay *>(container->currentWidget()); | 924 | auto *activeview = qobject_cast<TerminalDisplay *>(container->currentWidget()); | ||
924 | for (int i = 0, end = container->count(); i < end; i++) { | 925 | for (int i = 0, end = container->count(); i < end; i++) { | ||
925 | auto *view = qobject_cast<TerminalDisplay *>(container->widget(i)); | 926 | auto *view = qobject_cast<TerminalDisplay *>(container->widget(i)); | ||
926 | Q_ASSERT(view); | 927 | Q_ASSERT(view); | ||
927 | 928 | | |||
928 | Session *session = _sessionMap[view]; | 929 | Session *session = _sessionMap[view]; | ||
929 | ids << SessionManager::instance()->getRestoreId(session); | 930 | ids << SessionManager::instance()->getRestoreId(session); | ||
930 | unique.insert(session); | 931 | unique.insert(session); | ||
931 | if (view == activeview) { | 932 | if (view == activeview) { | ||
932 | group.writeEntry("Active", tab); | 933 | group.writeEntry("Active", tab); | ||
933 | } | 934 | } | ||
934 | tab++; | 935 | tab++; | ||
935 | } | 936 | } | ||
937 | #endif | ||||
936 | 938 | | |||
937 | // second: all other sessions, in random order | 939 | // second: all other sessions, in random order | ||
938 | // we don't want to have sessions restored that are not connected | 940 | // we don't want to have sessions restored that are not connected | ||
939 | foreach (Session *session, _sessionMap) { | 941 | foreach (Session *session, _sessionMap) { | ||
940 | if (!unique.contains(session)) { | 942 | if (!unique.contains(session)) { | ||
941 | ids << SessionManager::instance()->getRestoreId(session); | 943 | ids << SessionManager::instance()->getRestoreId(session); | ||
942 | unique.insert(session); | 944 | unique.insert(session); | ||
943 | } | 945 | } | ||
944 | } | 946 | } | ||
945 | 947 | | |||
946 | group.writeEntry("Sessions", ids); | 948 | group.writeEntry("Sessions", ids); | ||
947 | } | 949 | } | ||
948 | 950 | | |||
949 | TabbedViewContainer *ViewManager::activeContainer() | 951 | TabbedViewContainer *ViewManager::activeContainer() | ||
950 | { | 952 | { | ||
951 | return _viewSplitter->activeContainer(); | 953 | return _viewContainer; | ||
952 | } | 954 | } | ||
953 | 955 | | |||
954 | void ViewManager::restoreSessions(const KConfigGroup &group) | 956 | void ViewManager::restoreSessions(const KConfigGroup &group) | ||
955 | { | 957 | { | ||
956 | QList<int> ids = group.readEntry("Sessions", QList<int>()); | 958 | QList<int> ids = group.readEntry("Sessions", QList<int>()); | ||
957 | int activeTab = group.readEntry("Active", 0); | 959 | int activeTab = group.readEntry("Active", 0); | ||
958 | TerminalDisplay *display = nullptr; | 960 | TerminalDisplay *display = nullptr; | ||
959 | 961 | | |||
960 | int tab = 1; | 962 | int tab = 1; | ||
961 | foreach (int id, ids) { | 963 | foreach (int id, ids) { | ||
962 | Session *session = SessionManager::instance()->idToSession(id); | 964 | Session *session = SessionManager::instance()->idToSession(id); | ||
963 | 965 | | |||
964 | if (session == nullptr) { | 966 | if (session == nullptr) { | ||
965 | qWarning() << "Unable to load session with id" << id; | 967 | qWarning() << "Unable to load session with id" << id; | ||
966 | // Force a creation of a default session below | 968 | // Force a creation of a default session below | ||
967 | ids.clear(); | 969 | ids.clear(); | ||
968 | break; | 970 | break; | ||
969 | } | 971 | } | ||
970 | 972 | | |||
971 | createView(activeContainer(), session); | 973 | createView(session); | ||
972 | if (!session->isRunning()) { | 974 | if (!session->isRunning()) { | ||
973 | session->run(); | 975 | session->run(); | ||
974 | } | 976 | } | ||
975 | if (tab++ == activeTab) { | 977 | if (tab++ == activeTab) { | ||
976 | display = qobject_cast<TerminalDisplay *>(activeView()); | 978 | display = qobject_cast<TerminalDisplay *>(activeView()); | ||
977 | } | 979 | } | ||
978 | } | 980 | } | ||
979 | 981 | | |||
980 | if (display != nullptr) { | 982 | if (display != nullptr) { | ||
981 | _viewSplitter->activeContainer()->setCurrentWidget(display); | 983 | activeContainer()->setCurrentWidget(display); | ||
982 | display->setFocus(Qt::OtherFocusReason); | 984 | display->setFocus(Qt::OtherFocusReason); | ||
983 | } | 985 | } | ||
984 | 986 | | |||
985 | if (ids.isEmpty()) { // Session file is unusable, start default Profile | 987 | if (ids.isEmpty()) { // Session file is unusable, start default Profile | ||
986 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | 988 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | ||
987 | Session *session = SessionManager::instance()->createSession(profile); | 989 | Session *session = SessionManager::instance()->createSession(profile); | ||
988 | createView(activeContainer(), session); | 990 | createView(session); | ||
989 | if (!session->isRunning()) { | 991 | if (!session->isRunning()) { | ||
990 | session->run(); | 992 | session->run(); | ||
991 | } | 993 | } | ||
992 | } | 994 | } | ||
993 | } | 995 | } | ||
994 | 996 | | |||
995 | int ViewManager::sessionCount() | 997 | int ViewManager::sessionCount() | ||
996 | { | 998 | { | ||
Show All 23 Lines | 1015 | { | |||
1020 | return -1; | 1022 | return -1; | ||
1021 | } | 1023 | } | ||
1022 | 1024 | | |||
1023 | void ViewManager::setCurrentSession(int sessionId) | 1025 | void ViewManager::setCurrentSession(int sessionId) | ||
1024 | { | 1026 | { | ||
1025 | QHash<TerminalDisplay *, Session *>::const_iterator i; | 1027 | QHash<TerminalDisplay *, Session *>::const_iterator i; | ||
1026 | for (i = _sessionMap.constBegin(); i != _sessionMap.constEnd(); ++i) { | 1028 | for (i = _sessionMap.constBegin(); i != _sessionMap.constEnd(); ++i) { | ||
1027 | if (i.value()->sessionId() == sessionId) { | 1029 | if (i.value()->sessionId() == sessionId) { | ||
1028 | TabbedViewContainer *container = _viewSplitter->activeContainer(); | 1030 | TabbedViewContainer *container = activeContainer(); | ||
1029 | if (container != nullptr) { | 1031 | if (container != nullptr) { | ||
1030 | container->setCurrentWidget(i.key()); | 1032 | container->setCurrentWidget(i.key()); | ||
1031 | } | 1033 | } | ||
1032 | } | 1034 | } | ||
1033 | } | 1035 | } | ||
1034 | } | 1036 | } | ||
1035 | 1037 | | |||
1036 | int ViewManager::newSession() | 1038 | int ViewManager::newSession() | ||
1037 | { | 1039 | { | ||
1038 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | 1040 | Profile::Ptr profile = ProfileManager::instance()->defaultProfile(); | ||
1039 | Session *session = SessionManager::instance()->createSession(profile); | 1041 | Session *session = SessionManager::instance()->createSession(profile); | ||
1040 | 1042 | | |||
1041 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 1043 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
1042 | 1044 | | |||
1043 | createView(activeContainer(), session); | 1045 | createView(session); | ||
1044 | session->run(); | 1046 | session->run(); | ||
1045 | 1047 | | |||
1046 | return session->sessionId(); | 1048 | return session->sessionId(); | ||
1047 | } | 1049 | } | ||
1048 | 1050 | | |||
1049 | int ViewManager::newSession(const QString &profile) | 1051 | int ViewManager::newSession(const QString &profile) | ||
1050 | { | 1052 | { | ||
1051 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | 1053 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | ||
1052 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | 1054 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | ||
1053 | 1055 | | |||
1054 | for (const auto &i : profilelist) { | 1056 | for (const auto &i : profilelist) { | ||
1055 | if (i->name() == profile) { | 1057 | if (i->name() == profile) { | ||
1056 | profileptr = i; | 1058 | profileptr = i; | ||
1057 | break; | 1059 | break; | ||
1058 | } | 1060 | } | ||
1059 | } | 1061 | } | ||
1060 | 1062 | | |||
1061 | Session *session = SessionManager::instance()->createSession(profileptr); | 1063 | Session *session = SessionManager::instance()->createSession(profileptr); | ||
1062 | 1064 | | |||
1063 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 1065 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
1064 | 1066 | | |||
1065 | createView(activeContainer(), session); | 1067 | createView(session); | ||
1066 | session->run(); | 1068 | session->run(); | ||
1067 | 1069 | | |||
1068 | return session->sessionId(); | 1070 | return session->sessionId(); | ||
1069 | } | 1071 | } | ||
1070 | 1072 | | |||
1071 | int ViewManager::newSession(const QString &profile, const QString &directory) | 1073 | int ViewManager::newSession(const QString &profile, const QString &directory) | ||
1072 | { | 1074 | { | ||
1073 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | 1075 | const QList<Profile::Ptr> profilelist = ProfileManager::instance()->allProfiles(); | ||
1074 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | 1076 | Profile::Ptr profileptr = ProfileManager::instance()->defaultProfile(); | ||
1075 | 1077 | | |||
1076 | for (const auto &i : profilelist) { | 1078 | for (const auto &i : profilelist) { | ||
1077 | if (i->name() == profile) { | 1079 | if (i->name() == profile) { | ||
1078 | profileptr = i; | 1080 | profileptr = i; | ||
1079 | break; | 1081 | break; | ||
1080 | } | 1082 | } | ||
1081 | } | 1083 | } | ||
1082 | 1084 | | |||
1083 | Session *session = SessionManager::instance()->createSession(profileptr); | 1085 | Session *session = SessionManager::instance()->createSession(profileptr); | ||
1084 | session->setInitialWorkingDirectory(directory); | 1086 | session->setInitialWorkingDirectory(directory); | ||
1085 | 1087 | | |||
1086 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | 1088 | session->addEnvironmentEntry(QStringLiteral("KONSOLE_DBUS_WINDOW=/Windows/%1").arg(managerId())); | ||
1087 | 1089 | | |||
1088 | createView(activeContainer(), session); | 1090 | createView(session); | ||
1089 | session->run(); | 1091 | session->run(); | ||
1090 | 1092 | | |||
1091 | return session->sessionId(); | 1093 | return session->sessionId(); | ||
1092 | } | 1094 | } | ||
1093 | 1095 | | |||
1094 | QString ViewManager::defaultProfile() | 1096 | QString ViewManager::defaultProfile() | ||
1095 | { | 1097 | { | ||
1096 | return ProfileManager::instance()->defaultProfile()->name(); | 1098 | return ProfileManager::instance()->defaultProfile()->name(); | ||
Show All 21 Lines | |||||
1118 | 1120 | | |||
1119 | void ViewManager::moveSessionRight() | 1121 | void ViewManager::moveSessionRight() | ||
1120 | { | 1122 | { | ||
1121 | moveActiveViewRight(); | 1123 | moveActiveViewRight(); | ||
1122 | } | 1124 | } | ||
1123 | 1125 | | |||
1124 | void ViewManager::setTabWidthToText(bool setTabWidthToText) | 1126 | void ViewManager::setTabWidthToText(bool setTabWidthToText) | ||
1125 | { | 1127 | { | ||
1126 | for(auto container : _viewSplitter->containers()) { | 1128 | _viewContainer->tabBar()->setExpanding(!setTabWidthToText); | ||
1127 | container->tabBar()->setExpanding(!setTabWidthToText); | 1129 | _viewContainer->tabBar()->update(); | ||
1128 | container->tabBar()->update(); | | |||
1129 | } | | |||
1130 | } | 1130 | } | ||
1131 | 1131 | | |||
1132 | void ViewManager::setNavigationVisibility(NavigationVisibility navigationVisibility) { | 1132 | void ViewManager::setNavigationVisibility(NavigationVisibility navigationVisibility) { | ||
1133 | if (_navigationVisibility != navigationVisibility) { | 1133 | if (_navigationVisibility != navigationVisibility) { | ||
1134 | _navigationVisibility = navigationVisibility; | 1134 | _navigationVisibility = navigationVisibility; | ||
1135 | for(auto *container : _viewSplitter->containers()) { | 1135 | _viewContainer->setNavigationVisibility(navigationVisibility); | ||
1136 | container->setNavigationVisibility(navigationVisibility); | | |||
1137 | } | | |||
1138 | } | 1136 | } | ||
1139 | } | 1137 | } | ||
1140 | 1138 | | |||
1141 | void ViewManager::setNavigationBehavior(int behavior) | 1139 | void ViewManager::setNavigationBehavior(int behavior) | ||
1142 | { | 1140 | { | ||
1143 | _newTabBehavior = static_cast<NewTabBehavior>(behavior); | 1141 | _newTabBehavior = static_cast<NewTabBehavior>(behavior); | ||
1144 | } | 1142 | } | ||
1143 | | ||||
1144 | void ViewManager::updateTerminalDisplayHistory(TerminalDisplay* terminalDisplay, bool remove) | ||||
1145 | { | ||||
1146 | if (terminalDisplay == nullptr) { | ||||
1147 | if (_terminalDisplayHistoryIndex >= 0) { | ||||
1148 | // This is the case when we finished walking through the history | ||||
1149 | // (i.e. when Ctrl-Tab has been released) | ||||
1150 | terminalDisplay = _terminalDisplayHistory[_terminalDisplayHistoryIndex]; | ||||
1151 | _terminalDisplayHistoryIndex = -1; | ||||
1152 | } else { | ||||
1153 | return; | ||||
1154 | } | ||||
1155 | } | ||||
1156 | | ||||
1157 | if (_terminalDisplayHistoryIndex >= 0 && !remove) { | ||||
1158 | // Do not reorder the tab history while we are walking through it | ||||
1159 | return; | ||||
1160 | } | ||||
1161 | | ||||
1162 | for (int i = 0; i < _terminalDisplayHistory.count(); i++) { | ||||
1163 | if (_terminalDisplayHistory[i] == terminalDisplay) { | ||||
1164 | _terminalDisplayHistory.removeAt(i); | ||||
1165 | if (!remove) { | ||||
1166 | _terminalDisplayHistory.prepend(terminalDisplay); | ||||
1167 | } | ||||
1168 | break; | ||||
1169 | } | ||||
1170 | } | ||||
1171 | } |
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.