Changeset View
Changeset View
Standalone View
Standalone View
src/ViewSplitter.cpp
Show All 21 Lines | |||||
22 | // Own | 22 | // Own | ||
23 | #include "ViewSplitter.h" | 23 | #include "ViewSplitter.h" | ||
24 | 24 | | |||
25 | // Qt | 25 | // Qt | ||
26 | #include <QDebug> | 26 | #include <QDebug> | ||
27 | 27 | | |||
28 | // Konsole | 28 | // Konsole | ||
29 | #include "ViewContainer.h" | 29 | #include "ViewContainer.h" | ||
30 | #include "TerminalDisplay.h" | ||||
30 | 31 | | |||
31 | using Konsole::ViewSplitter; | 32 | using Konsole::ViewSplitter; | ||
32 | using Konsole::TabbedViewContainer; | 33 | using Konsole::TerminalDisplay; | ||
34 | | ||||
35 | //TODO: Connect the TerminalDisplay destroyed signal here. | ||||
33 | 36 | | |||
34 | ViewSplitter::ViewSplitter(QWidget *parent) : | 37 | ViewSplitter::ViewSplitter(QWidget *parent) : | ||
35 | QSplitter(parent), | 38 | QSplitter(parent) | ||
36 | _containers(QList<TabbedViewContainer *>()), | | |||
37 | _recursiveSplitting(true) | | |||
38 | { | 39 | { | ||
39 | } | 40 | } | ||
40 | 41 | | |||
41 | void ViewSplitter::childEmpty(ViewSplitter *splitter) | 42 | void ViewSplitter::adjustTerminalDisplaySize(TerminalDisplay *container, int percentage) | ||
42 | { | | |||
43 | delete splitter; | | |||
44 | | ||||
45 | if (count() == 0) { | | |||
46 | emit empty(this); | | |||
47 | } | | |||
48 | } | | |||
49 | | ||||
50 | void ViewSplitter::adjustContainerSize(TabbedViewContainer *container, int percentage) | | |||
51 | { | 43 | { | ||
52 | int containerIndex = indexOf(container); | 44 | int containerIndex = indexOf(container); | ||
53 | 45 | | |||
54 | Q_ASSERT(containerIndex != -1); | 46 | Q_ASSERT(containerIndex != -1); | ||
55 | 47 | | |||
56 | QList<int> containerSizes = sizes(); | 48 | QList<int> containerSizes = sizes(); | ||
57 | 49 | | |||
58 | const int oldSize = containerSizes[containerIndex]; | 50 | const int oldSize = containerSizes[containerIndex]; | ||
Show All 22 Lines | 72 | while ((splitter == nullptr) && (widget != nullptr)) { | |||
81 | splitter = qobject_cast<ViewSplitter *>(widget); | 73 | splitter = qobject_cast<ViewSplitter *>(widget); | ||
82 | widget = widget->parentWidget(); | 74 | widget = widget->parentWidget(); | ||
83 | } | 75 | } | ||
84 | 76 | | |||
85 | Q_ASSERT(splitter); | 77 | Q_ASSERT(splitter); | ||
86 | return splitter; | 78 | return splitter; | ||
87 | } | 79 | } | ||
88 | 80 | | |||
89 | void ViewSplitter::registerContainer(TabbedViewContainer *container) | | |||
90 | { | | |||
91 | _containers << container; | | |||
92 | connect(container, SIGNAL(empty(TabbedViewContainer*)), this, SLOT(containerEmpty(TabbedViewContainer*))); | | |||
93 | } | | |||
94 | | ||||
95 | void ViewSplitter::unregisterContainer(TabbedViewContainer *container) | | |||
96 | { | | |||
97 | _containers.removeAll(container); | | |||
98 | disconnect(container, nullptr, this, nullptr); | | |||
99 | } | | |||
100 | | ||||
101 | void ViewSplitter::updateSizes() | 81 | void ViewSplitter::updateSizes() | ||
102 | { | 82 | { | ||
103 | int space; | 83 | int space; | ||
104 | 84 | | |||
105 | if (orientation() == Qt::Horizontal) { | 85 | if (orientation() == Qt::Horizontal) { | ||
106 | space = width() / count(); | 86 | space = width() / count(); | ||
107 | } else { | 87 | } else { | ||
108 | space = height() / count(); | 88 | space = height() / count(); | ||
109 | } | 89 | } | ||
110 | 90 | | |||
111 | QList<int> widgetSizes; | 91 | QList<int> widgetSizes; | ||
112 | const int widgetCount = count(); | 92 | const int widgetCount = count(); | ||
113 | widgetSizes.reserve(widgetCount); | 93 | widgetSizes.reserve(widgetCount); | ||
114 | for (int i = 0; i < widgetCount; i++) { | 94 | for (int i = 0; i < widgetCount; i++) { | ||
115 | widgetSizes << space; | 95 | widgetSizes << space; | ||
116 | } | 96 | } | ||
117 | 97 | | |||
118 | setSizes(widgetSizes); | 98 | setSizes(widgetSizes); | ||
119 | } | 99 | } | ||
120 | 100 | | |||
121 | void ViewSplitter::setRecursiveSplitting(bool recursive) | 101 | void ViewSplitter::addTerminalDisplay(TerminalDisplay *terminalDisplay, Qt::Orientation containerOrientation) | ||
122 | { | | |||
123 | _recursiveSplitting = recursive; | | |||
124 | } | | |||
125 | | ||||
126 | bool ViewSplitter::recursiveSplitting() const | | |||
127 | { | | |||
128 | return _recursiveSplitting; | | |||
129 | } | | |||
130 | | ||||
131 | void ViewSplitter::removeContainer(TabbedViewContainer *container) | | |||
132 | { | | |||
133 | Q_ASSERT(containers().contains(container)); | | |||
134 | | ||||
135 | unregisterContainer(container); | | |||
136 | } | | |||
137 | | ||||
138 | void ViewSplitter::addContainer(TabbedViewContainer *container, Qt::Orientation containerOrientation) | | |||
139 | { | 102 | { | ||
140 | ViewSplitter *splitter = activeSplitter(); | 103 | ViewSplitter *splitter = activeSplitter(); | ||
141 | 104 | | |||
142 | if (splitter->count() < 2 | 105 | if (splitter->count() < 2 | ||
143 | || containerOrientation == splitter->orientation() | 106 | || containerOrientation == splitter->orientation()) { | ||
144 | || !_recursiveSplitting) { | 107 | splitter->addWidget(terminalDisplay); | ||
145 | splitter->registerContainer(container); | | |||
146 | splitter->addWidget(container); | | |||
147 | 108 | | |||
148 | if (splitter->orientation() != containerOrientation) { | 109 | if (splitter->orientation() != containerOrientation) { | ||
149 | splitter->setOrientation(containerOrientation); | 110 | splitter->setOrientation(containerOrientation); | ||
150 | } | 111 | } | ||
151 | 112 | connect(terminalDisplay, &QObject::destroyed, this, &ViewSplitter::childDestroyed); | |||
152 | splitter->updateSizes(); | 113 | splitter->updateSizes(); | ||
153 | } else { | 114 | } else { | ||
154 | auto newSplitter = new ViewSplitter(this); | 115 | auto newSplitter = new ViewSplitter(); | ||
155 | connect(newSplitter, &Konsole::ViewSplitter::empty, splitter, | 116 | connect(newSplitter, &QObject::destroyed, this, &ViewSplitter::childDestroyed); | ||
156 | &Konsole::ViewSplitter::childEmpty); | 117 | connect(terminalDisplay, &QObject::destroyed, newSplitter, &ViewSplitter::childDestroyed); | ||
157 | 118 | | |||
158 | TabbedViewContainer *oldContainer = splitter->activeContainer(); | 119 | TerminalDisplay *oldTerminalDisplay = splitter->activeTerminalDisplay(); | ||
159 | const int oldContainerIndex = splitter->indexOf(oldContainer); | 120 | disconnect(oldTerminalDisplay, &QObject::destroyed, nullptr, nullptr); | ||
160 | 121 | connect(oldTerminalDisplay, &QObject::destroyed, newSplitter, &ViewSplitter::childDestroyed); | |||
161 | splitter->unregisterContainer(oldContainer); | 122 | | ||
162 | 123 | const int oldContainerIndex = splitter->indexOf(oldTerminalDisplay); | |||
163 | newSplitter->registerContainer(oldContainer); | 124 | newSplitter->addWidget(oldTerminalDisplay); | ||
164 | newSplitter->registerContainer(container); | 125 | newSplitter->addWidget(terminalDisplay); | ||
165 | | ||||
166 | newSplitter->addWidget(oldContainer); | | |||
167 | newSplitter->addWidget(container); | | |||
168 | newSplitter->setOrientation(containerOrientation); | 126 | newSplitter->setOrientation(containerOrientation); | ||
169 | newSplitter->updateSizes(); | 127 | newSplitter->updateSizes(); | ||
170 | newSplitter->show(); | 128 | newSplitter->show(); | ||
171 | 129 | | |||
172 | splitter->insertWidget(oldContainerIndex, newSplitter); | 130 | splitter->insertWidget(oldContainerIndex, newSplitter); | ||
173 | } | 131 | } | ||
174 | } | 132 | } | ||
175 | 133 | | |||
176 | void ViewSplitter::containerEmpty(TabbedViewContainer * myContainer) | 134 | void ViewSplitter::childDestroyed(QObject *childWidget) | ||
177 | { | 135 | { | ||
178 | _containers.removeAll(myContainer); | 136 | // remove the parent so count() has the correct value. | ||
137 | childWidget->setParent(nullptr); | ||||
179 | if (count() == 0) { | 138 | if (count() == 0) { | ||
180 | emit empty(this); | 139 | deleteLater(); | ||
181 | } | 140 | } | ||
182 | | ||||
183 | int children = 0; | | |||
184 | foreach (auto container, _containers) { | | |||
185 | children += container->count(); | | |||
186 | } | 141 | } | ||
187 | 142 | | |||
188 | if (children == 0) { | | |||
189 | emit allContainersEmpty(); | | |||
190 | } | | |||
191 | 143 | | |||
192 | // This container is no more, try to find another container to focus. | 144 | void ViewSplitter::focusUp() | ||
193 | ViewSplitter *currentSplitter = activeSplitter(); | 145 | { | ||
194 | while(qobject_cast<ViewSplitter*>(currentSplitter->parent())) { | 146 | qDebug() << "Focus up called"; | ||
195 | currentSplitter = qobject_cast<ViewSplitter*>(currentSplitter->parent()); | 147 | auto terminalDisplay = activeTerminalDisplay(); | ||
196 | } | 148 | auto activeViewSplitter = qobject_cast<ViewSplitter*>(terminalDisplay->parentWidget()); | ||
149 | auto idx = activeViewSplitter->indexOf(terminalDisplay); | ||||
197 | 150 | | |||
198 | for(auto tabWidget : currentSplitter->findChildren<TabbedViewContainer*>()) { | 151 | // Easy, we are in a vertical spliter and we want to focus up. | ||
199 | if (tabWidget != myContainer && tabWidget->count()) { | 152 | if (activeViewSplitter->orientation() == Qt::Vertical && idx > 0) { | ||
200 | tabWidget->setCurrentIndex(0); | 153 | activeViewSplitter->widget(idx - 1)->setFocus(Qt::OtherFocusReason); | ||
201 | } | | |||
202 | } | | |||
203 | } | 154 | } | ||
204 | 155 | | |||
205 | void ViewSplitter::activateNextContainer() | 156 | // Hard, we are in a horizontal splitter or we are in the top of the vertical splitter. | ||
206 | { | 157 | else { | ||
207 | TabbedViewContainer *active = activeContainer(); | 158 | ViewSplitter *parentTerminalWidget = nullptr; | ||
159 | ViewSplitter *oldParent = activeViewSplitter; | ||||
160 | do { | ||||
161 | parentTerminalWidget = qobject_cast<ViewSplitter*>( | ||||
162 | parentTerminalWidget ? parentTerminalWidget->parentWidget() | ||||
163 | : activeViewSplitter->parentWidget()); | ||||
208 | 164 | | |||
209 | int index = _containers.indexOf(active); | 165 | if (parentTerminalWidget) { | ||
166 | idx = parentTerminalWidget->indexOf(oldParent); | ||||
167 | } | ||||
168 | oldParent = parentTerminalWidget; | ||||
169 | } while (parentTerminalWidget && parentTerminalWidget->orientation() != Qt::Vertical); | ||||
210 | 170 | | |||
211 | if (index == -1) { | 171 | if (!parentTerminalWidget) { | ||
212 | return; | 172 | return; | ||
213 | } | 173 | } | ||
214 | 174 | | |||
215 | if (index == _containers.count() - 1) { | 175 | if (idx > 0) { | ||
216 | index = 0; | 176 | parentTerminalWidget->widget(idx - 1)->setFocus(Qt::OtherFocusReason); | ||
217 | } else { | 177 | } else { | ||
218 | index++; | 178 | qDebug() << "Could not find idx."; | ||
179 | } | ||||
219 | } | 180 | } | ||
220 | | ||||
221 | setActiveContainer(_containers.at(index)); | | |||
222 | } | 181 | } | ||
223 | 182 | | |||
224 | void ViewSplitter::activatePreviousContainer() | 183 | void ViewSplitter::focusDown() | ||
225 | { | 184 | { | ||
226 | TabbedViewContainer *active = activeContainer(); | | |||
227 | | ||||
228 | int index = _containers.indexOf(active); | | |||
229 | | ||||
230 | if (index == 0) { | | |||
231 | index = _containers.count() - 1; | | |||
232 | } else { | | |||
233 | index--; | | |||
234 | } | 185 | } | ||
235 | 186 | | |||
236 | setActiveContainer(_containers.at(index)); | 187 | void ViewSplitter::focusLeft() | ||
188 | { | ||||
237 | } | 189 | } | ||
238 | 190 | | |||
239 | void ViewSplitter::setActiveContainer(TabbedViewContainer *container) | 191 | void ViewSplitter::focusRight() | ||
240 | { | 192 | { | ||
241 | QWidget *activeView = container->currentWidget(); | | |||
242 | | ||||
243 | if (activeView != nullptr) { | | |||
244 | activeView->setFocus(Qt::OtherFocusReason); | | |||
245 | } | | |||
246 | } | 193 | } | ||
247 | 194 | | |||
248 | TabbedViewContainer *ViewSplitter::activeContainer() const | 195 | | ||
196 | void ViewSplitter::activateNextTerminalDisplay() | ||||
249 | { | 197 | { | ||
250 | if (QWidget *focusW = focusWidget()) { | 198 | TerminalDisplay *active = activeTerminalDisplay(); | ||
251 | TabbedViewContainer *focusContainer = nullptr; | | |||
252 | 199 | | |||
253 | while (focusW != nullptr) { | 200 | int index = indexOf(active); | ||
254 | foreach (TabbedViewContainer *container, _containers) { | 201 | | ||
255 | if (container == focusW) { | 202 | if (index == -1) { | ||
256 | focusContainer = container; | 203 | return; | ||
257 | break; | | |||
258 | } | | |||
259 | } | | |||
260 | focusW = focusW->parentWidget(); | | |||
261 | } | 204 | } | ||
262 | 205 | | |||
263 | if (focusContainer != nullptr) { | 206 | if (index == count() - 1) { | ||
264 | return focusContainer; | 207 | index = 0; | ||
208 | } else { | ||||
209 | index++; | ||||
265 | } | 210 | } | ||
211 | widget(index)->setFocus(Qt::OtherFocusReason); | ||||
266 | } | 212 | } | ||
267 | 213 | | |||
268 | QList<ViewSplitter *> splitters = findChildren<ViewSplitter *>(); | 214 | void ViewSplitter::activatePreviousTerminalDisplay() | ||
215 | { | ||||
216 | TerminalDisplay *active = activeTerminalDisplay(); | ||||
217 | | ||||
218 | int index = indexOf(active); | ||||
269 | 219 | | |||
270 | if (!splitters.isEmpty()) { | 220 | if (index == 0) { | ||
271 | return splitters.last()->activeContainer(); | 221 | index = count() - 1; | ||
272 | } else { | | |||
273 | if (!_containers.isEmpty()) { | | |||
274 | return _containers.last(); | | |||
275 | } else { | 222 | } else { | ||
276 | return nullptr; | 223 | index--; | ||
277 | } | 224 | } | ||
225 | widget(index)->setFocus(Qt::OtherFocusReason); | ||||
278 | } | 226 | } | ||
227 | | ||||
hindenburg: try not to shadow another variable here | |||||
228 | TerminalDisplay *ViewSplitter::activeTerminalDisplay() const | ||||
229 | { | ||||
230 | auto focusedWidget = qobject_cast<TerminalDisplay*>(focusWidget()); | ||||
231 | return focusedWidget ? focusedWidget : findChild<TerminalDisplay*>(); | ||||
279 | } | 232 | } |
try not to shadow another variable here