diff --git a/src/ViewSplitter.cpp b/src/ViewSplitter.cpp index 6af79d5c..bf9a8cca 100644 --- a/src/ViewSplitter.cpp +++ b/src/ViewSplitter.cpp @@ -1,219 +1,223 @@ /* This file is part of the Konsole Terminal. Copyright 2006-2008 Robert Knight This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // Own #include "ViewSplitter.h" // Qt #include #include #include // Konsole #include "ViewContainer.h" #include "TerminalDisplay.h" using Konsole::ViewSplitter; using Konsole::TerminalDisplay; //TODO: Connect the TerminalDisplay destroyed signal here. ViewSplitter::ViewSplitter(QWidget *parent) : QSplitter(parent) { } void ViewSplitter::adjustActiveTerminalDisplaySize(int percentage) { const int containerIndex = indexOf(activeTerminalDisplay()); Q_ASSERT(containerIndex != -1); QList containerSizes = sizes(); const int oldSize = containerSizes[containerIndex]; const int newSize = static_cast(oldSize * (1.0 + percentage / 100.0)); const int perContainerDelta = (count() == 1) ? 0 : ((newSize - oldSize) / (count() - 1)) * (-1); for (int& size : containerSizes) { size += perContainerDelta; } containerSizes[containerIndex] = newSize; setSizes(containerSizes); } // Get the first splitter that's a parent of the current focused widget. ViewSplitter *ViewSplitter::activeSplitter() { QWidget *widget = focusWidget() != nullptr ? focusWidget() : this; ViewSplitter *splitter = nullptr; while ((splitter == nullptr) && (widget != nullptr)) { splitter = qobject_cast(widget); widget = widget->parentWidget(); } Q_ASSERT(splitter); return splitter; } void ViewSplitter::updateSizes() { const int space = (orientation() == Qt::Horizontal ? width() : height()) / count(); setSizes(QVector(count(), space).toList()); } void ViewSplitter::addTerminalDisplay(TerminalDisplay *terminalDisplay, Qt::Orientation containerOrientation) { ViewSplitter *splitter = activeSplitter(); if (splitter->count() < 2) { splitter->addWidget(terminalDisplay); splitter->setOrientation(containerOrientation); } else if (containerOrientation == splitter->orientation()) { auto activeDisplay = splitter->activeTerminalDisplay(); if (!activeDisplay) { splitter->addWidget(terminalDisplay); } else { const int currentIndex = splitter->indexOf(activeDisplay); splitter->insertWidget(currentIndex, terminalDisplay); } } else { auto newSplitter = new ViewSplitter(); TerminalDisplay *oldTerminalDisplay = splitter->activeTerminalDisplay(); const int oldContainerIndex = splitter->indexOf(oldTerminalDisplay); newSplitter->addWidget(oldTerminalDisplay); newSplitter->addWidget(terminalDisplay); newSplitter->setOrientation(containerOrientation); newSplitter->updateSizes(); newSplitter->show(); splitter->insertWidget(oldContainerIndex, newSplitter); } splitter->updateSizes(); } void ViewSplitter::childEvent(QChildEvent *event) { QSplitter::childEvent(event); if (event->removed()) { if (count() == 0) { deleteLater(); } if (!findChild()) { deleteLater(); } } } void ViewSplitter::handleFocusDirection(Qt::Orientation orientation, int direction) { auto terminalDisplay = activeTerminalDisplay(); auto parentSplitter = qobject_cast(terminalDisplay->parentWidget()); auto topSplitter = parentSplitter->getToplevelSplitter(); const auto handleWidth = parentSplitter->handleWidth() <= 1 ? 4 : parentSplitter->handleWidth(); const auto start = QPoint(terminalDisplay->x(), terminalDisplay->y()); const auto startMapped = parentSplitter->mapTo(topSplitter, start); const int newX = orientation != Qt::Horizontal ? startMapped.x() + handleWidth : direction == 1 ? startMapped.x() + terminalDisplay->width() + handleWidth : startMapped.x() - handleWidth; const int newY = orientation != Qt::Vertical ? startMapped.y() + handleWidth : direction == 1 ? startMapped.y() + terminalDisplay->height() + handleWidth : startMapped.y() - handleWidth; const auto newPoint = QPoint(newX, newY); auto child = topSplitter->childAt(newPoint); if (TerminalDisplay* terminal = qobject_cast(child)) { terminal->setFocus(Qt::OtherFocusReason); - } else if (qobject_cast(child)) { - auto scrollbarTerminal = qobject_cast(child->parent()); - scrollbarTerminal->setFocus(Qt::OtherFocusReason); } else if (qobject_cast(child)) { auto targetSplitter = qobject_cast(child->parent()); auto splitterTerminal = qobject_cast(targetSplitter->widget(0)); splitterTerminal->setFocus(Qt::OtherFocusReason); + } else if (qobject_cast(child)) { + TerminalDisplay *terminalParent = nullptr; + while(!terminalParent) { + terminalParent = qobject_cast(child->parentWidget()); + child = child->parentWidget(); + } + terminalParent->setFocus(Qt::OtherFocusReason); } } void ViewSplitter::focusUp() { handleFocusDirection(Qt::Vertical, -1); } void ViewSplitter::focusDown() { handleFocusDirection(Qt::Vertical, +1); } void ViewSplitter::focusLeft() { handleFocusDirection(Qt::Horizontal, -1); } void ViewSplitter::focusRight() { handleFocusDirection(Qt::Horizontal, +1); } TerminalDisplay *ViewSplitter::activeTerminalDisplay() const { auto focusedWidget = qobject_cast(focusWidget()); return focusedWidget ? focusedWidget : findChild(); } void ViewSplitter::maximizeCurrentTerminal() { handleMinimizeMaximize(true); } void ViewSplitter::restoreOtherTerminals() { handleMinimizeMaximize(false); } void ViewSplitter::handleMinimizeMaximize(bool maximize) { auto viewSplitter = getToplevelSplitter(); auto terminalDisplays = viewSplitter->findChildren(); auto currentActiveTerminal = viewSplitter->activeTerminalDisplay(); auto method = maximize ? &QWidget::hide : &QWidget::show; for(auto terminal : terminalDisplays) { if (Q_LIKELY(currentActiveTerminal != terminal)) { (terminal->*method)(); } } } ViewSplitter *ViewSplitter::getToplevelSplitter() { ViewSplitter *current = this; while(qobject_cast(current->parentWidget())) { current = qobject_cast(current->parentWidget()); } return current; }