Changeset View
Changeset View
Standalone View
Standalone View
src/ViewContainer.cpp
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Line(s) | |||||
42 | #include "IncrementalSearchBar.h" | 42 | #include "IncrementalSearchBar.h" | ||
43 | #include "ViewProperties.h" | 43 | #include "ViewProperties.h" | ||
44 | #include "ProfileList.h" | 44 | #include "ProfileList.h" | ||
45 | #include "ViewManager.h" | 45 | #include "ViewManager.h" | ||
46 | #include "KonsoleSettings.h" | 46 | #include "KonsoleSettings.h" | ||
47 | #include "SessionController.h" | 47 | #include "SessionController.h" | ||
48 | #include "DetachableTabBar.h" | 48 | #include "DetachableTabBar.h" | ||
49 | #include "TerminalDisplay.h" | 49 | #include "TerminalDisplay.h" | ||
50 | #include "ViewSplitter.h" | ||||
51 | #include "MainWindow.h" | ||||
52 | #include "Session.h" | ||||
50 | 53 | | |||
51 | // TODO Perhaps move everything which is Konsole-specific into different files | 54 | // TODO Perhaps move everything which is Konsole-specific into different files | ||
52 | 55 | | |||
53 | using namespace Konsole; | 56 | using namespace Konsole; | ||
54 | 57 | | |||
55 | 58 | | |||
56 | TabbedViewContainer::TabbedViewContainer(ViewManager *connectedViewManager, QWidget *parent) : | 59 | TabbedViewContainer::TabbedViewContainer(ViewManager *connectedViewManager, QWidget *parent) : | ||
57 | QTabWidget(parent), | 60 | QTabWidget(parent), | ||
58 | _connectedViewManager(connectedViewManager), | 61 | _connectedViewManager(connectedViewManager), | ||
59 | _newTabButton(new QToolButton()), | 62 | _newTabButton(new QToolButton()), | ||
60 | _closeTabButton(new QToolButton()), | 63 | _closeTabButton(new QToolButton()), | ||
61 | _contextMenuTabIndex(-1), | 64 | _contextMenuTabIndex(-1), | ||
62 | _navigationVisibility(ViewManager::NavigationVisibility::NavigationNotSet), | 65 | _navigationVisibility(ViewManager::NavigationVisibility::NavigationNotSet) | ||
63 | _tabHistoryIndex(-1) | | |||
64 | { | 66 | { | ||
65 | setAcceptDrops(true); | 67 | setAcceptDrops(true); | ||
66 | 68 | | |||
67 | auto tabBarWidget = new DetachableTabBar(); | 69 | auto tabBarWidget = new DetachableTabBar(); | ||
68 | setTabBar(tabBarWidget); | 70 | setTabBar(tabBarWidget); | ||
69 | setDocumentMode(true); | 71 | setDocumentMode(true); | ||
70 | setMovable(true); | 72 | setMovable(true); | ||
71 | connect(tabBarWidget, &DetachableTabBar::moveTabToWindow, this, &TabbedViewContainer::moveTabToWindow); | 73 | connect(tabBarWidget, &DetachableTabBar::moveTabToWindow, this, &TabbedViewContainer::moveTabToWindow); | ||
72 | tabBar()->setContextMenuPolicy(Qt::CustomContextMenu); | 74 | tabBar()->setContextMenuPolicy(Qt::CustomContextMenu); | ||
73 | _newTabButton->setIcon(QIcon::fromTheme(QStringLiteral("tab-new"))); | 75 | _newTabButton->setIcon(QIcon::fromTheme(QStringLiteral("tab-new"))); | ||
74 | _newTabButton->setAutoRaise(true); | 76 | _newTabButton->setAutoRaise(true); | ||
75 | connect(_newTabButton, &QToolButton::clicked, this, [this]{ | 77 | connect(_newTabButton, &QToolButton::clicked, this, &TabbedViewContainer::newViewRequest); | ||
76 | emit newViewRequest(this); | | |||
77 | }); | | |||
78 | 78 | | |||
79 | _closeTabButton->setIcon(QIcon::fromTheme(QStringLiteral("tab-close"))); | 79 | _closeTabButton->setIcon(QIcon::fromTheme(QStringLiteral("tab-close"))); | ||
80 | _closeTabButton->setAutoRaise(true); | 80 | _closeTabButton->setAutoRaise(true); | ||
81 | connect(_closeTabButton, &QToolButton::clicked, this, [this]{ | 81 | connect(_closeTabButton, &QToolButton::clicked, this, [this]{ | ||
82 | closeCurrentTab(); | 82 | closeCurrentTab(); | ||
83 | }); | 83 | }); | ||
84 | 84 | | |||
85 | connect(tabBar(), &QTabBar::tabBarDoubleClicked, this, | 85 | connect(tabBar(), &QTabBar::tabBarDoubleClicked, this, | ||
86 | &Konsole::TabbedViewContainer::tabDoubleClicked); | 86 | &Konsole::TabbedViewContainer::tabDoubleClicked); | ||
87 | connect(tabBar(), &QTabBar::customContextMenuRequested, this, | 87 | connect(tabBar(), &QTabBar::customContextMenuRequested, this, | ||
88 | &Konsole::TabbedViewContainer::openTabContextMenu); | 88 | &Konsole::TabbedViewContainer::openTabContextMenu); | ||
89 | | ||||
90 | #if defined(ENABLE_DETACHING) | ||||
89 | connect(tabBarWidget, &DetachableTabBar::detachTab, this, [this](int idx) { | 91 | connect(tabBarWidget, &DetachableTabBar::detachTab, this, [this](int idx) { | ||
90 | emit detachTab(this, terminalAt(idx)); | 92 | emit detachTab(idx); | ||
91 | }); | 93 | }); | ||
94 | #endif | ||||
95 | | ||||
anthonyfieroniUnsubmitted Done anthonyfieroni: ```
connect(tabBarWidget, &DetachableTabBar::detachTab, this, &TabbedViewContainer::detachTab)… | |||||
92 | connect(this, &TabbedViewContainer::currentChanged, this, &TabbedViewContainer::currentTabChanged); | 96 | connect(this, &TabbedViewContainer::currentChanged, this, &TabbedViewContainer::currentTabChanged); | ||
anthonyfieroni: Connecting signal to signal should work, same as above. | |||||
93 | 97 | | |||
94 | // The context menu of tab bar | 98 | // The context menu of tab bar | ||
95 | _contextPopupMenu = new QMenu(tabBar()); | 99 | _contextPopupMenu = new QMenu(tabBar()); | ||
96 | connect(_contextPopupMenu, &QMenu::aboutToHide, this, [this]() { | 100 | connect(_contextPopupMenu, &QMenu::aboutToHide, this, [this]() { | ||
97 | // Remove the read-only action when the popup closes | 101 | // Remove the read-only action when the popup closes | ||
98 | for (auto &action : _contextPopupMenu->actions()) { | 102 | for (auto &action : _contextPopupMenu->actions()) { | ||
99 | if (action->objectName() == QStringLiteral("view-readonly")) { | 103 | if (action->objectName() == QStringLiteral("view-readonly")) { | ||
100 | _contextPopupMenu->removeAction(action); | 104 | _contextPopupMenu->removeAction(action); | ||
101 | break; | 105 | break; | ||
102 | } | 106 | } | ||
103 | } | 107 | } | ||
104 | }); | 108 | }); | ||
105 | 109 | | |||
106 | connect(tabBar(), &QTabBar::tabCloseRequested, this, &TabbedViewContainer::closeTerminalTab); | 110 | connect(tabBar(), &QTabBar::tabCloseRequested, this, &TabbedViewContainer::closeTerminalTab); | ||
107 | 111 | | |||
108 | #if defined(ENABLE_DETACHING) | 112 | #if defined(ENABLE_DETACHING) | ||
109 | auto detachAction = _contextPopupMenu->addAction( | 113 | auto detachAction = _contextPopupMenu->addAction( | ||
110 | QIcon::fromTheme(QStringLiteral("tab-detach")), | 114 | QIcon::fromTheme(QStringLiteral("tab-detach")), | ||
111 | i18nc("@action:inmenu", "&Detach Tab"), this, | 115 | i18nc("@action:inmenu", "&Detach Tab"), this, | ||
112 | [this] { emit detachTab(this, terminalAt(_contextMenuTabIndex)); } | 116 | [this] { emit detachTab(_contextMenuTabIndex); } | ||
113 | ); | 117 | ); | ||
114 | detachAction->setObjectName(QStringLiteral("tab-detach")); | 118 | detachAction->setObjectName(QStringLiteral("tab-detach")); | ||
115 | #endif | 119 | #endif | ||
116 | 120 | | |||
117 | auto editAction = _contextPopupMenu->addAction( | 121 | auto editAction = _contextPopupMenu->addAction( | ||
118 | QIcon::fromTheme(QStringLiteral("edit-rename")), | 122 | QIcon::fromTheme(QStringLiteral("edit-rename")), | ||
119 | i18nc("@action:inmenu", "&Rename Tab..."), this, | 123 | i18nc("@action:inmenu", "&Rename Tab..."), this, | ||
120 | [this]{ renameTab(_contextMenuTabIndex); } | 124 | [this]{ renameTab(_contextMenuTabIndex); } | ||
121 | ); | 125 | ); | ||
122 | editAction->setObjectName(QStringLiteral("edit-rename")); | 126 | editAction->setObjectName(QStringLiteral("edit-rename")); | ||
123 | 127 | | |||
124 | auto closeAction = _contextPopupMenu->addAction( | 128 | auto closeAction = _contextPopupMenu->addAction( | ||
125 | QIcon::fromTheme(QStringLiteral("tab-close")), | 129 | QIcon::fromTheme(QStringLiteral("tab-close")), | ||
126 | i18nc("@action:inmenu", "Close Tab"), this, | 130 | i18nc("@action:inmenu", "Close Tab"), this, | ||
127 | [this] { closeTerminalTab(_contextMenuTabIndex); } | 131 | [this] { closeTerminalTab(_contextMenuTabIndex); } | ||
128 | ); | 132 | ); | ||
129 | closeAction->setObjectName(QStringLiteral("tab-close")); | 133 | closeAction->setObjectName(QStringLiteral("tab-close")); | ||
130 | 134 | | |||
131 | auto profileMenu = new QMenu(); | 135 | auto profileMenu = new QMenu(); | ||
132 | auto profileList = new ProfileList(false, profileMenu); | 136 | auto profileList = new ProfileList(false, profileMenu); | ||
133 | profileList->syncWidgetActions(profileMenu, true); | 137 | profileList->syncWidgetActions(profileMenu, true); | ||
134 | connect(profileList, &Konsole::ProfileList::profileSelected, this, | 138 | connect(profileList, &Konsole::ProfileList::profileSelected, this, &TabbedViewContainer::newViewWithProfileRequest); | ||
135 | [this](const Profile::Ptr &profile) { emit newViewWithProfileRequest(this, profile); }); | | |||
136 | _newTabButton->setMenu(profileMenu); | 139 | _newTabButton->setMenu(profileMenu); | ||
137 | 140 | | |||
138 | konsoleConfigChanged(); | 141 | konsoleConfigChanged(); | ||
139 | connect(KonsoleSettings::self(), &KonsoleSettings::configChanged, this, &TabbedViewContainer::konsoleConfigChanged); | 142 | connect(KonsoleSettings::self(), &KonsoleSettings::configChanged, this, &TabbedViewContainer::konsoleConfigChanged); | ||
140 | } | 143 | } | ||
141 | 144 | | |||
142 | TabbedViewContainer::~TabbedViewContainer() | 145 | TabbedViewContainer::~TabbedViewContainer() | ||
143 | { | 146 | { | ||
144 | for(int i = 0, end = count(); i < end; i++) { | 147 | for(int i = 0, end = count(); i < end; i++) { | ||
145 | auto view = widget(i); | 148 | auto view = widget(i); | ||
146 | disconnect(view, &QWidget::destroyed, this, &Konsole::TabbedViewContainer::viewDestroyed); | 149 | disconnect(view, &QWidget::destroyed, this, &Konsole::TabbedViewContainer::viewDestroyed); | ||
147 | } | 150 | } | ||
148 | } | 151 | } | ||
149 | 152 | | |||
150 | TerminalDisplay *TabbedViewContainer::terminalAt(int index) | 153 | ViewSplitter *TabbedViewContainer::activeViewSplitter() | ||
151 | { | 154 | { | ||
152 | return qobject_cast<TerminalDisplay*>(widget(index)); | 155 | return viewSplitterAt(currentIndex()); | ||
153 | } | 156 | } | ||
154 | 157 | | |||
155 | void TabbedViewContainer::moveTabToWindow(int index, QWidget *window) | 158 | ViewSplitter *TabbedViewContainer::viewSplitterAt(int index) | ||
156 | { | 159 | { | ||
157 | const int id = terminalAt(index)->sessionController()->identifier(); | 160 | return qobject_cast<ViewSplitter*>(widget(index)); | ||
158 | // This one line here will be removed as soon as I finish my new split handling. | | |||
159 | // it's hacky but it works. | | |||
160 | const auto widgets = window->findChildren<TabbedViewContainer*>(); | | |||
161 | const auto currentPos = QCursor::pos(); | | |||
162 | for(const auto dropWidget : widgets) { | | |||
163 | if (dropWidget->rect().contains(dropWidget->mapFromGlobal(currentPos))) { | | |||
164 | emit dropWidget->moveViewRequest(-1, id); | | |||
165 | removeView(terminalAt(index)); | | |||
166 | } | 161 | } | ||
162 | | ||||
163 | void TabbedViewContainer::moveTabToWindow(int index, QWidget *window) | ||||
164 | { | ||||
165 | auto splitter = viewSplitterAt(index); | ||||
166 | auto manager = window->findChild<ViewManager*>(); | ||||
167 | | ||||
168 | QHash<TerminalDisplay*, Session*> sessionsMap = _connectedViewManager->forgetAll(splitter); | ||||
169 | | ||||
170 | foreach(TerminalDisplay* terminal, splitter->getTerminalDisplays()) { | ||||
171 | manager->attachView(terminal, sessionsMap[terminal]); | ||||
167 | } | 172 | } | ||
173 | auto container = manager->activeContainer(); | ||||
174 | container->addSplitter(splitter); | ||||
175 | | ||||
176 | auto controller = splitter->activeTerminalDisplay()->sessionController(); | ||||
177 | container->currentSessionControllerChanged(controller); | ||||
178 | | ||||
179 | forgetView(splitter); | ||||
168 | } | 180 | } | ||
169 | 181 | | |||
170 | void TabbedViewContainer::konsoleConfigChanged() | 182 | void TabbedViewContainer::konsoleConfigChanged() | ||
171 | { | 183 | { | ||
172 | // don't show tabs if we are in KParts mode. | 184 | // don't show tabs if we are in KParts mode. | ||
173 | // This is a hack, and this needs to be rewritten. | 185 | // This is a hack, and this needs to be rewritten. | ||
174 | // The container should not be part of the KParts, perhaps just the | 186 | // The container should not be part of the KParts, perhaps just the | ||
175 | // TerminalDisplay should. | 187 | // TerminalDisplay should. | ||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Line(s) | |||||
233 | void TabbedViewContainer::moveActiveView(MoveDirection direction) | 245 | void TabbedViewContainer::moveActiveView(MoveDirection direction) | ||
234 | { | 246 | { | ||
235 | if (count() < 2) { // return if only one view | 247 | if (count() < 2) { // return if only one view | ||
236 | return; | 248 | return; | ||
237 | } | 249 | } | ||
238 | const int currentIndex = indexOf(currentWidget()); | 250 | const int currentIndex = indexOf(currentWidget()); | ||
239 | int newIndex = direction == MoveViewLeft ? qMax(currentIndex - 1, 0) : qMin(currentIndex + 1, count() - 1); | 251 | int newIndex = direction == MoveViewLeft ? qMax(currentIndex - 1, 0) : qMin(currentIndex + 1, count() - 1); | ||
240 | 252 | | |||
241 | auto swappedWidget = terminalAt(newIndex); | 253 | auto swappedWidget = viewSplitterAt(newIndex); | ||
242 | auto currentWidget = terminalAt(currentIndex); | 254 | auto swappedTitle = tabBar()->tabText(newIndex); | ||
243 | auto swappedContext = swappedWidget->sessionController(); | 255 | auto swappedIcon = tabBar()->tabIcon(newIndex); | ||
244 | auto currentContext = currentWidget->sessionController(); | 256 | | ||
257 | auto currentWidget = viewSplitterAt(currentIndex); | ||||
258 | auto currentTitle = tabBar()->tabText(currentIndex); | ||||
259 | auto currentIcon = tabBar()->tabIcon(currentIndex); | ||||
245 | 260 | | |||
246 | if (newIndex < currentIndex) { | 261 | if (newIndex < currentIndex) { | ||
247 | insertTab(newIndex, currentWidget, currentContext->icon(), currentContext->title()); | 262 | insertTab(newIndex, currentWidget, currentIcon, currentTitle); | ||
248 | insertTab(currentIndex, swappedWidget, swappedContext->icon(), swappedContext->title()); | 263 | insertTab(currentIndex, swappedWidget, swappedIcon, swappedTitle); | ||
249 | } else { | 264 | } else { | ||
250 | insertTab(currentIndex, swappedWidget, swappedContext->icon(), swappedContext->title()); | 265 | insertTab(currentIndex, swappedWidget, swappedIcon, swappedTitle); | ||
251 | insertTab(newIndex, currentWidget, currentContext->icon(), currentContext->title()); | 266 | insertTab(newIndex, currentWidget, currentIcon, currentTitle); | ||
252 | } | 267 | } | ||
253 | setCurrentIndex(newIndex); | 268 | setCurrentIndex(newIndex); | ||
254 | } | 269 | } | ||
255 | 270 | | |||
271 | void TabbedViewContainer::addSplitter(ViewSplitter *viewSplitter, int index) { | ||||
272 | if (index == -1) { | ||||
273 | index = addTab(viewSplitter, QString()); | ||||
274 | } else { | ||||
275 | insertTab(index, viewSplitter, QString()); | ||||
276 | } | ||||
277 | connect(viewSplitter, &ViewSplitter::destroyed, this, &TabbedViewContainer::viewDestroyed); | ||||
278 | foreach(TerminalDisplay* terminal, viewSplitter->getTerminalDisplays()) { | ||||
279 | connectTerminalDisplay(terminal); | ||||
280 | } | ||||
281 | setCurrentIndex(index); | ||||
282 | } | ||||
283 | | ||||
256 | void TabbedViewContainer::addView(TerminalDisplay *view, int index) | 284 | void TabbedViewContainer::addView(TerminalDisplay *view, int index) | ||
257 | { | 285 | { | ||
286 | auto viewSplitter = new ViewSplitter(); | ||||
287 | viewSplitter->addTerminalDisplay(view, Qt::Horizontal); | ||||
258 | auto item = view->sessionController(); | 288 | auto item = view->sessionController(); | ||
259 | if (index == -1) { | 289 | if (index == -1) { | ||
260 | addTab(view, item->icon(), item->title()); | 290 | index = addTab(viewSplitter, item->icon(), item->title()); | ||
261 | } else { | 291 | } else { | ||
262 | insertTab(index, view, item->icon(), item->title()); | 292 | insertTab(index, viewSplitter, item->icon(), item->title()); | ||
263 | } | 293 | } | ||
264 | 294 | | |||
265 | _tabHistory.append(view); | 295 | connectTerminalDisplay(view); | ||
296 | connect(viewSplitter, &ViewSplitter::destroyed, this, &TabbedViewContainer::viewDestroyed); | ||||
297 | setCurrentIndex(index); | ||||
298 | emit viewAdded(view); | ||||
299 | } | ||||
300 | | ||||
301 | void TabbedViewContainer::splitView(TerminalDisplay *view, Qt::Orientation orientation) | ||||
302 | { | ||||
303 | auto viewSplitter = qobject_cast<ViewSplitter*>(currentWidget()); | ||||
304 | viewSplitter->addTerminalDisplay(view, orientation); | ||||
305 | connectTerminalDisplay(view); | ||||
306 | } | ||||
307 | | ||||
308 | void TabbedViewContainer::connectTerminalDisplay(TerminalDisplay *display) | ||||
309 | { | ||||
310 | auto item = display->sessionController(); | ||||
311 | connect(item, &Konsole::SessionController::focused, this, | ||||
312 | &Konsole::TabbedViewContainer::currentSessionControllerChanged); | ||||
313 | | ||||
266 | connect(item, &Konsole::ViewProperties::titleChanged, this, | 314 | connect(item, &Konsole::ViewProperties::titleChanged, this, | ||
267 | &Konsole::TabbedViewContainer::updateTitle); | 315 | &Konsole::TabbedViewContainer::updateTitle); | ||
316 | | ||||
268 | connect(item, &Konsole::ViewProperties::iconChanged, this, | 317 | connect(item, &Konsole::ViewProperties::iconChanged, this, | ||
269 | &Konsole::TabbedViewContainer::updateIcon); | 318 | &Konsole::TabbedViewContainer::updateIcon); | ||
319 | | ||||
270 | connect(item, &Konsole::ViewProperties::activity, this, | 320 | connect(item, &Konsole::ViewProperties::activity, this, | ||
271 | &Konsole::TabbedViewContainer::updateActivity); | 321 | &Konsole::TabbedViewContainer::updateActivity); | ||
272 | connect(view, &QWidget::destroyed, this, | 322 | } | ||
273 | &Konsole::TabbedViewContainer::viewDestroyed); | 323 | | ||
274 | emit viewAdded(view); | 324 | void TabbedViewContainer::disconnectTerminalDisplay(TerminalDisplay *display) | ||
325 | { | ||||
326 | auto item = display->sessionController(); | ||||
327 | disconnect(item, &Konsole::SessionController::focused, this, | ||||
328 | &Konsole::TabbedViewContainer::currentSessionControllerChanged); | ||||
329 | | ||||
330 | disconnect(item, &Konsole::ViewProperties::titleChanged, this, | ||||
331 | &Konsole::TabbedViewContainer::updateTitle); | ||||
332 | | ||||
333 | disconnect(item, &Konsole::ViewProperties::iconChanged, this, | ||||
334 | &Konsole::TabbedViewContainer::updateIcon); | ||||
335 | | ||||
336 | disconnect(item, &Konsole::ViewProperties::activity, this, | ||||
337 | &Konsole::TabbedViewContainer::updateActivity); | ||||
275 | } | 338 | } | ||
276 | 339 | | |||
277 | void TabbedViewContainer::viewDestroyed(QObject *view) | 340 | void TabbedViewContainer::viewDestroyed(QObject *view) | ||
278 | { | 341 | { | ||
279 | auto widget = static_cast<TerminalDisplay*>(view); | 342 | auto widget = static_cast<ViewSplitter*>(view); | ||
280 | const auto idx = indexOf(widget); | 343 | const auto idx = indexOf(widget); | ||
281 | 344 | | |||
282 | removeTab(idx); | 345 | removeTab(idx); | ||
283 | forgetView(widget); | 346 | forgetView(widget); | ||
284 | } | 347 | } | ||
285 | 348 | | |||
286 | void TabbedViewContainer::forgetView(TerminalDisplay *view) | 349 | void TabbedViewContainer::forgetView(ViewSplitter *view) | ||
287 | { | 350 | { | ||
288 | updateTabHistory(view, true); | 351 | Q_UNUSED(view); | ||
289 | emit viewRemoved(view); | | |||
290 | if (count() == 0) { | 352 | if (count() == 0) { | ||
291 | emit empty(this); | 353 | emit empty(this); | ||
292 | } | 354 | } | ||
293 | } | 355 | } | ||
294 | 356 | | |||
295 | void TabbedViewContainer::removeView(TerminalDisplay *view) | 357 | void TabbedViewContainer::removeView(TerminalDisplay *view) | ||
296 | { | 358 | { | ||
297 | const int idx = indexOf(view); | 359 | /* TODO: This is absolutely the wrong place. | ||
298 | disconnect(view, &QWidget::destroyed, this, &Konsole::TabbedViewContainer::viewDestroyed); | 360 | * We are removing a terminal display from a ViewSplitter, | ||
299 | removeTab(idx); | 361 | * this should be inside of the view splitter or something. | ||
300 | forgetView(view); | 362 | */ | ||
363 | view->setParent(nullptr); | ||||
301 | } | 364 | } | ||
302 | 365 | | |||
303 | void TabbedViewContainer::activateNextView() | 366 | void TabbedViewContainer::activateNextView() | ||
304 | { | 367 | { | ||
305 | QWidget *active = currentWidget(); | 368 | QWidget *active = currentWidget(); | ||
306 | int index = indexOf(active); | 369 | int index = indexOf(active); | ||
307 | setCurrentIndex(index == count() - 1 ? 0 : index + 1); | 370 | setCurrentIndex(index == count() - 1 ? 0 : index + 1); | ||
308 | } | 371 | } | ||
309 | 372 | | |||
310 | void TabbedViewContainer::activateLastView() | 373 | void TabbedViewContainer::activateLastView() | ||
311 | { | 374 | { | ||
312 | setCurrentIndex(count() - 1); | 375 | setCurrentIndex(count() - 1); | ||
313 | } | 376 | } | ||
314 | 377 | | |||
315 | void TabbedViewContainer::activatePreviousView() | 378 | void TabbedViewContainer::activatePreviousView() | ||
316 | { | 379 | { | ||
317 | QWidget *active = currentWidget(); | 380 | QWidget *active = currentWidget(); | ||
318 | int index = indexOf(active); | 381 | int index = indexOf(active); | ||
319 | setCurrentIndex(index == 0 ? count() - 1 : index - 1); | 382 | setCurrentIndex(index == 0 ? count() - 1 : index - 1); | ||
320 | } | 383 | } | ||
321 | 384 | | |||
322 | void TabbedViewContainer::activateLastUsedView(bool reverse) | | |||
323 | { | | |||
324 | if (_tabHistory.count() <= 1) { | | |||
325 | return; | | |||
326 | } | | |||
327 | | ||||
328 | if (_tabHistoryIndex == -1) { | | |||
329 | _tabHistoryIndex = reverse ? _tabHistory.count() - 1 : 1; | | |||
330 | } else if (reverse) { | | |||
331 | if (_tabHistoryIndex == 0) { | | |||
332 | _tabHistoryIndex = _tabHistory.count() - 1; | | |||
333 | } else { | | |||
334 | _tabHistoryIndex--; | | |||
335 | } | | |||
336 | } else { | | |||
337 | if (_tabHistoryIndex >= _tabHistory.count() - 1) { | | |||
338 | _tabHistoryIndex = 0; | | |||
339 | } else { | | |||
340 | _tabHistoryIndex++; | | |||
341 | } | | |||
342 | } | | |||
343 | | ||||
344 | int index = indexOf(_tabHistory[_tabHistoryIndex]); | | |||
345 | setCurrentIndex(index); | | |||
346 | } | | |||
347 | | ||||
348 | // Jump to last view - this allows toggling between two views | | |||
349 | // Using "Last Used Tabs" shortcut will cause "Toggle between two tabs" | | |||
350 | // shortcut to be incorrect the first time. | | |||
351 | void TabbedViewContainer::toggleLastUsedView() | | |||
352 | { | | |||
353 | if (_tabHistory.count() <= 1) { | | |||
354 | return; | | |||
355 | } | | |||
356 | | ||||
357 | setCurrentIndex(indexOf(_tabHistory.at(1))); | | |||
358 | } | | |||
359 | | ||||
360 | void TabbedViewContainer::keyReleaseEvent(QKeyEvent* event) | 385 | void TabbedViewContainer::keyReleaseEvent(QKeyEvent* event) | ||
361 | { | 386 | { | ||
362 | if (_tabHistoryIndex != -1 && event->modifiers() == Qt::NoModifier) { | 387 | if (event->modifiers() == Qt::NoModifier) { | ||
363 | _tabHistoryIndex = -1; | 388 | _connectedViewManager->updateTerminalDisplayHistory(); | ||
364 | auto *active = qobject_cast<TerminalDisplay*>(currentWidget()); | | |||
365 | if (active != _tabHistory[0]) { | | |||
366 | // Update the tab history now that we have ended the walk-through | | |||
367 | updateTabHistory(active); | | |||
368 | } | | |||
369 | } | | |||
370 | } | | |||
371 | | ||||
372 | void TabbedViewContainer::updateTabHistory(TerminalDisplay* view, bool remove) | | |||
373 | { | | |||
374 | if (_tabHistoryIndex != -1 && !remove) { | | |||
375 | // Do not reorder the tab history while we are walking through it | | |||
376 | return; | | |||
377 | } | | |||
378 | | ||||
379 | for (int i = 0; i < _tabHistory.count(); ++i ) { | | |||
380 | if (_tabHistory[i] == view) { | | |||
381 | _tabHistory.removeAt(i); | | |||
382 | if (!remove) { | | |||
383 | _tabHistory.prepend(view); | | |||
384 | } | | |||
385 | break; | | |||
386 | } | | |||
387 | } | 389 | } | ||
388 | } | 390 | } | ||
389 | 391 | | |||
390 | void TabbedViewContainer::closeCurrentTab() | 392 | void TabbedViewContainer::closeCurrentTab() | ||
391 | { | 393 | { | ||
392 | if (currentIndex() != -1) { | 394 | if (currentIndex() != -1) { | ||
393 | closeTerminalTab(currentIndex()); | 395 | closeTerminalTab(currentIndex()); | ||
394 | } | 396 | } | ||
395 | } | 397 | } | ||
396 | 398 | | |||
397 | void TabbedViewContainer::tabDoubleClicked(int index) | 399 | void TabbedViewContainer::tabDoubleClicked(int index) | ||
398 | { | 400 | { | ||
399 | if (index >= 0) { | 401 | if (index >= 0) { | ||
400 | renameTab(index); | 402 | renameTab(index); | ||
401 | } else { | 403 | } else { | ||
402 | emit newViewRequest(this); | 404 | emit newViewRequest(); | ||
403 | } | 405 | } | ||
404 | } | 406 | } | ||
405 | 407 | | |||
406 | void TabbedViewContainer::renameTab(int index) | 408 | void TabbedViewContainer::renameTab(int index) | ||
407 | { | 409 | { | ||
408 | if (index != -1) { | 410 | if (index != -1) { | ||
409 | terminalAt(index)->sessionController()->rename(); | 411 | setCurrentIndex(index); | ||
412 | viewSplitterAt(index) | ||||
413 | -> activeTerminalDisplay() | ||||
414 | -> sessionController() | ||||
415 | -> rename(); | ||||
410 | } | 416 | } | ||
411 | } | 417 | } | ||
412 | 418 | | |||
413 | void TabbedViewContainer::openTabContextMenu(const QPoint &point) | 419 | void TabbedViewContainer::openTabContextMenu(const QPoint &point) | ||
414 | { | 420 | { | ||
415 | if (point.isNull()) { | 421 | if (point.isNull()) { | ||
416 | return; | 422 | return; | ||
417 | } | 423 | } | ||
418 | 424 | | |||
419 | _contextMenuTabIndex = tabBar()->tabAt(point); | 425 | _contextMenuTabIndex = tabBar()->tabAt(point); | ||
420 | if (_contextMenuTabIndex < 0) { | 426 | if (_contextMenuTabIndex < 0) { | ||
421 | return; | 427 | return; | ||
422 | } | 428 | } | ||
423 | 429 | | |||
424 | //TODO: add a countChanged signal so we can remove this for. | 430 | //TODO: add a countChanged signal so we can remove this for. | ||
425 | // Detaching in mac causes crashes. | 431 | // Detaching in mac causes crashes. | ||
426 | #if defined(ENABLE_DETACHING) | 432 | #if defined(ENABLE_DETACHING) | ||
427 | for(auto action : _contextPopupMenu->actions()) { | 433 | for(auto action : _contextPopupMenu->actions()) { | ||
428 | if (action->objectName() == QStringLiteral("tab-detach")) { | 434 | if (action->objectName() == QStringLiteral("tab-detach")) { | ||
429 | action->setEnabled(count() > 1); | 435 | action->setEnabled(count() > 1); | ||
430 | } | 436 | } | ||
431 | } | 437 | } | ||
432 | #endif | 438 | #endif | ||
433 | 439 | | |||
440 | /* This needs to nove away fro the tab or to lock every thing inside of it. | ||||
441 | * for now, disable. | ||||
442 | * */ | ||||
443 | // | ||||
So the tab right click menu no longer has 'Read Only' - do you plan on fixing this before this is committed? hindenburg: So the tab right click menu no longer has 'Read Only' - do you plan on fixing this before this… | |||||
Yes and no: the read only should apply to a TerminalDisplay, if it's in the Tab does it make sense to apply to all of the TerminalDisplays or just to the currently focused one? I'll add it to the context menu for the TerminalDisplay. tcanabrava: Yes and no: the read only should apply to a TerminalDisplay, if it's in the Tab does it make… | |||||
434 | // Add the read-only action | 444 | // Add the read-only action | ||
435 | auto controller = terminalAt(_contextMenuTabIndex)->sessionController(); | 445 | #if 0 | ||
436 | auto sessionController = qobject_cast<SessionController*>(controller); | 446 | auto sessionController = terminalAt(_contextMenuTabIndex)->sessionController(); | ||
437 | 447 | | |||
438 | if (sessionController != nullptr) { | 448 | if (sessionController != nullptr) { | ||
439 | auto collection = sessionController->actionCollection(); | 449 | auto collection = sessionController->actionCollection(); | ||
440 | auto readonlyAction = collection->action(QStringLiteral("view-readonly")); | 450 | auto readonlyAction = collection->action(QStringLiteral("view-readonly")); | ||
441 | if (readonlyAction != nullptr) { | 451 | if (readonlyAction != nullptr) { | ||
442 | const auto readonlyActions = _contextPopupMenu->actions(); | 452 | const auto readonlyActions = _contextPopupMenu->actions(); | ||
443 | _contextPopupMenu->insertAction(readonlyActions.last(), readonlyAction); | 453 | _contextPopupMenu->insertAction(readonlyActions.last(), readonlyAction); | ||
444 | } | 454 | } | ||
445 | 455 | | |||
446 | // Disable tab rename | 456 | // Disable tab rename | ||
447 | for (auto &action : _contextPopupMenu->actions()) { | 457 | for (auto &action : _contextPopupMenu->actions()) { | ||
448 | if (action->objectName() == QStringLiteral("edit-rename")) { | 458 | if (action->objectName() == QStringLiteral("edit-rename")) { | ||
449 | action->setEnabled(!sessionController->isReadOnly()); | 459 | action->setEnabled(!sessionController->isReadOnly()); | ||
450 | break; | 460 | break; | ||
451 | } | 461 | } | ||
452 | } | 462 | } | ||
453 | } | 463 | } | ||
454 | 464 | #endif | |||
455 | _contextPopupMenu->exec(tabBar()->mapToGlobal(point)); | 465 | _contextPopupMenu->exec(tabBar()->mapToGlobal(point)); | ||
456 | } | 466 | } | ||
457 | 467 | | |||
458 | void TabbedViewContainer::currentTabChanged(int index) | 468 | void TabbedViewContainer::currentTabChanged(int index) | ||
459 | { | 469 | { | ||
460 | if (index != -1) { | 470 | if (index != -1) { | ||
461 | auto *view = terminalAt(index); | 471 | auto splitview = qobject_cast<ViewSplitter*>(widget(index)); | ||
462 | view->setFocus(); | 472 | auto view = splitview->activeTerminalDisplay(); | ||
463 | updateTabHistory(view); | | |||
464 | emit activeViewChanged(view); | 473 | emit activeViewChanged(view); | ||
465 | setTabActivity(index, false); | 474 | setTabActivity(index, false); | ||
466 | } else { | 475 | } else { | ||
467 | deleteLater(); | 476 | deleteLater(); | ||
468 | } | 477 | } | ||
469 | } | 478 | } | ||
470 | 479 | | |||
471 | void TabbedViewContainer::wheelScrolled(int delta) | 480 | void TabbedViewContainer::wheelScrolled(int delta) | ||
Show All 25 Lines | |||||
497 | { | 506 | { | ||
498 | auto controller = qobject_cast<SessionController*>(item); | 507 | auto controller = qobject_cast<SessionController*>(item); | ||
499 | auto index = indexOf(controller->view()); | 508 | auto index = indexOf(controller->view()); | ||
500 | if (index != currentIndex()) { | 509 | if (index != currentIndex()) { | ||
501 | setTabActivity(index, true); | 510 | setTabActivity(index, true); | ||
502 | } | 511 | } | ||
503 | } | 512 | } | ||
504 | 513 | | |||
514 | void TabbedViewContainer::currentSessionControllerChanged(SessionController *controller) | ||||
515 | { | ||||
516 | updateTitle(qobject_cast<ViewProperties*>(controller)); | ||||
517 | } | ||||
518 | | ||||
505 | void TabbedViewContainer::updateTitle(ViewProperties *item) | 519 | void TabbedViewContainer::updateTitle(ViewProperties *item) | ||
506 | { | 520 | { | ||
507 | auto controller = qobject_cast<SessionController*>(item); | 521 | auto controller = qobject_cast<SessionController*>(item); | ||
522 | auto topLevelSplitter = qobject_cast<ViewSplitter*>(controller->view()->parentWidget())->getToplevelSplitter(); | ||||
508 | 523 | | |||
509 | const int index = indexOf(controller->view()); | 524 | const int index = indexOf(topLevelSplitter); | ||
510 | QString tabText = item->title(); | 525 | QString tabText = item->title(); | ||
511 | 526 | | |||
512 | setTabToolTip(index, tabText); | 527 | setTabToolTip(index, tabText); | ||
513 | 528 | | |||
514 | // To avoid having & replaced with _ (shortcut indicator) | 529 | // To avoid having & replaced with _ (shortcut indicator) | ||
515 | tabText.replace(QLatin1Char('&'), QLatin1String("&&")); | 530 | tabText.replace(QLatin1Char('&'), QLatin1String("&&")); | ||
516 | setTabText(index, tabText); | 531 | setTabText(index, tabText); | ||
517 | } | 532 | } | ||
518 | 533 | | |||
519 | void TabbedViewContainer::updateIcon(ViewProperties *item) | 534 | void TabbedViewContainer::updateIcon(ViewProperties *item) | ||
520 | { | 535 | { | ||
521 | auto controller = qobject_cast<SessionController*>(item); | 536 | auto controller = qobject_cast<SessionController*>(item); | ||
522 | const int index = indexOf(controller->view()); | 537 | const int index = indexOf(controller->view()); | ||
523 | setTabIcon(index, item->icon()); | 538 | setTabIcon(index, item->icon()); | ||
524 | } | 539 | } | ||
525 | 540 | | |||
526 | void TabbedViewContainer::closeTerminalTab(int idx) { | 541 | void TabbedViewContainer::closeTerminalTab(int idx) { | ||
527 | terminalAt(idx)->sessionController()->closeSession(); | 542 | //TODO: This for should probably go to the ViewSplitter | ||
543 | for (auto terminal : viewSplitterAt(idx)->findChildren<TerminalDisplay*>()) { | ||||
544 | terminal->sessionController()->closeSession(); | ||||
545 | } | ||||
528 | } | 546 | } | ||
529 | 547 | | |||
530 | ViewManager *TabbedViewContainer::connectedViewManager() | 548 | ViewManager *TabbedViewContainer::connectedViewManager() | ||
531 | { | 549 | { | ||
532 | return _connectedViewManager; | 550 | return _connectedViewManager; | ||
533 | } | 551 | } | ||
534 | 552 | | |||
535 | void TabbedViewContainer::setNavigationVisibility(ViewManager::NavigationVisibility navigationVisibility) { | 553 | void TabbedViewContainer::setNavigationVisibility(ViewManager::NavigationVisibility navigationVisibility) { | ||
536 | if (navigationVisibility == ViewManager::NavigationNotSet) { | 554 | if (navigationVisibility == ViewManager::NavigationNotSet) { | ||
537 | return; | 555 | return; | ||
538 | } | 556 | } | ||
539 | 557 | | |||
540 | setTabBarAutoHide(navigationVisibility == ViewManager::ShowNavigationAsNeeded); | 558 | setTabBarAutoHide(navigationVisibility == ViewManager::ShowNavigationAsNeeded); | ||
541 | if (navigationVisibility == ViewManager::AlwaysShowNavigation) { | 559 | if (navigationVisibility == ViewManager::AlwaysShowNavigation) { | ||
542 | tabBar()->setVisible(true); | 560 | tabBar()->setVisible(true); | ||
543 | } else if (navigationVisibility == ViewManager::AlwaysHideNavigation) { | 561 | } else if (navigationVisibility == ViewManager::AlwaysHideNavigation) { | ||
544 | tabBar()->setVisible(false); | 562 | tabBar()->setVisible(false); | ||
545 | } | 563 | } | ||
546 | } | 564 | } | ||
565 | | ||||
566 | void TabbedViewContainer::maximizeCurrentTerminal() | ||||
567 | { | ||||
568 | activeViewSplitter()->maximizeCurrentTerminal(); | ||||
569 | } | ||||
570 | | ||||
571 | void TabbedViewContainer::restoreOtherTerminals() | ||||
572 | { | ||||
573 | activeViewSplitter()->restoreOtherTerminals(); | ||||
574 | } |