diff options
Diffstat (limited to 'src/libs/advanceddockingsystem/dockfocuscontroller.cpp')
-rw-r--r-- | src/libs/advanceddockingsystem/dockfocuscontroller.cpp | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/src/libs/advanceddockingsystem/dockfocuscontroller.cpp b/src/libs/advanceddockingsystem/dockfocuscontroller.cpp new file mode 100644 index 0000000000..16450c778c --- /dev/null +++ b/src/libs/advanceddockingsystem/dockfocuscontroller.cpp @@ -0,0 +1,273 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Uwe Kindler +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or (at your option) any later version. +** The licenses are as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPLv21 included in the packaging +** of this file. Please review the following information to ensure +** the GNU Lesser General Public License version 2.1 requirements +** will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "dockfocuscontroller.h" + +#include "dockareawidget.h" +#include "dockareatitlebar.h" +#include "dockcontainerwidget.h" +#include "dockmanager.h" +#include "dockwidget.h" +#include "dockwidgettab.h" +#include "floatingdockcontainer.h" + +#ifdef Q_OS_LINUX +#include "linux/floatingwidgettitlebar.h" +#endif + +#include <QApplication> +#include <QPointer> + +#include <algorithm> +#include <iostream> + +namespace ADS +{ + /** + * Private data class of CDockFocusController class (pimpl) + */ + class DockFocusControllerPrivate + { + public: + DockFocusController *q; + QPointer<DockWidget> m_focusedDockWidget = nullptr; + QPointer<DockAreaWidget> m_focusedArea = nullptr; + #ifdef Q_OS_LINUX + QPointer<FloatingDockContainer> m_floatingWidget = nullptr; + #endif + DockManager *m_dockManager = nullptr; + + /** + * Private data constructor + */ + DockFocusControllerPrivate(DockFocusController *parent); + + /** + * This function updates the focus style of the given dock widget and + * the dock area that it belongs to + */ + void updateDockWidgetFocus(DockWidget *dockWidget); + }; // class DockFocusControllerPrivate + + static void updateDockWidgetFocusStyle(DockWidget *dockWidget, bool focused) + { + dockWidget->setProperty("focused", focused); + dockWidget->tabWidget()->setProperty("focused", focused); + dockWidget->tabWidget()->updateStyle(); + internal::repolishStyle(dockWidget); + } + + static void updateDockAreaFocusStyle(DockAreaWidget *dockArea, bool focused) + { + dockArea->setProperty("focused", focused); + internal::repolishStyle(dockArea); + internal::repolishStyle(dockArea->titleBar()); + } + +#ifdef Q_OS_LINUX + static void updateFloatingWidgetFocusStyle(FloatingDockContainer *floatingWidget, bool focused) + { + auto titleBar = qobject_cast<FloatingWidgetTitleBar *>(floatingWidget->titleBarWidget()); + if (!titleBar) + return; + + titleBar->setProperty("focused", focused); + titleBar->updateStyle(); + } +#endif + + DockFocusControllerPrivate::DockFocusControllerPrivate(DockFocusController *parent) + : q(parent) + {} + + void DockFocusControllerPrivate::updateDockWidgetFocus(DockWidget *dockWidget) + { + DockAreaWidget *newFocusedDockArea = nullptr; + if (m_focusedDockWidget) + updateDockWidgetFocusStyle(m_focusedDockWidget, false); + + DockWidget *old = m_focusedDockWidget; + m_focusedDockWidget = dockWidget; + updateDockWidgetFocusStyle(m_focusedDockWidget, true); + newFocusedDockArea = m_focusedDockWidget->dockAreaWidget(); + if (newFocusedDockArea && (m_focusedArea != newFocusedDockArea)) + { + if (m_focusedArea) + { + QObject::disconnect(m_focusedArea, &DockAreaWidget::viewToggled, + q, &DockFocusController::onFocusedDockAreaViewToggled); + updateDockAreaFocusStyle(m_focusedArea, false); + } + + m_focusedArea = newFocusedDockArea; + updateDockAreaFocusStyle(m_focusedArea, true); + QObject::connect(m_focusedArea, &DockAreaWidget::viewToggled, + q, &DockFocusController::onFocusedDockAreaViewToggled); + } + + auto newFloatingWidget = m_focusedDockWidget->dockContainer()->floatingWidget(); + if (newFloatingWidget) + newFloatingWidget->setProperty("FocusedDockWidget", QVariant::fromValue(dockWidget)); + + #ifdef Q_OS_LINUX + // This code is required for styling the floating widget titlebar for linux + // depending on the current focus state + if (m_floatingWidget == newFloatingWidget) + return; + + if (m_floatingWidget) + updateFloatingWidgetFocusStyle(m_floatingWidget, false); + + m_floatingWidget = newFloatingWidget; + + if (m_floatingWidget) + updateFloatingWidgetFocusStyle(m_floatingWidget, true); + #endif + + if (old != dockWidget) + emit m_dockManager->focusedDockWidgetChanged(old, dockWidget); + } + + DockFocusController::DockFocusController(DockManager *dockManager) + : QObject(dockManager) + , d(new DockFocusControllerPrivate(this)) + { + d->m_dockManager = dockManager; + connect(qApp, &QApplication::focusChanged, + this, &DockFocusController::onApplicationFocusChanged); + connect(d->m_dockManager, &DockManager::stateRestored, + this, &DockFocusController::onStateRestored); + } + + DockFocusController::~DockFocusController() + { + delete d; + } + + void DockFocusController::onApplicationFocusChanged(QWidget *focusedOld, QWidget *focusedNow) + { + if (d->m_dockManager->isRestoringState()) + return; + + if (!focusedNow) + return; + + DockWidget *dockWidget = nullptr; + auto dockWidgetTab = qobject_cast<DockWidgetTab *>(focusedNow); + if (dockWidgetTab) + dockWidget = dockWidgetTab->dockWidget(); + + if (!dockWidget) + dockWidget = qobject_cast<DockWidget *>(focusedNow); + + if (!dockWidget) + dockWidget = internal::findParent<DockWidget *>(focusedNow); + + #ifdef Q_OS_LINUX + if (!dockWidget) + return; + #else + if (!dockWidget || dockWidget->tabWidget()->isHidden()) + return; + #endif + + d->updateDockWidgetFocus(dockWidget); + } + + void DockFocusController::setDockWidgetFocused(DockWidget *focusedNow) + { + d->updateDockWidgetFocus(focusedNow); + } + + void DockFocusController::onFocusedDockAreaViewToggled(bool open) + { + if (d->m_dockManager->isRestoringState()) + return; + + DockAreaWidget* dockArea = qobject_cast<DockAreaWidget *>(sender()); + if (!dockArea || open) + return; + + auto container = dockArea->dockContainer(); + auto openedDockAreas = container->openedDockAreas(); + if (openedDockAreas.isEmpty()) + return; + + DockManager::setWidgetFocus(openedDockAreas[0]->currentDockWidget()->tabWidget()); + } + + void DockFocusController::notifyWidgetOrAreaRelocation(QWidget *droppedWidget) + { + if (d->m_dockManager->isRestoringState()) + return; + + DockWidget *dockWidget = qobject_cast<DockWidget *>(droppedWidget); + if (dockWidget) + { + DockManager::setWidgetFocus(dockWidget->tabWidget()); + return; + } + + DockAreaWidget* dockArea = qobject_cast<DockAreaWidget*>(droppedWidget); + if (!dockArea) + return; + + dockWidget = dockArea->currentDockWidget(); + DockManager::setWidgetFocus(dockWidget->tabWidget()); + } + + void DockFocusController::notifyFloatingWidgetDrop(FloatingDockContainer *floatingWidget) + { + if (!floatingWidget || d->m_dockManager->isRestoringState()) + return; + + auto vDockWidget = floatingWidget->property("FocusedDockWidget"); + if (!vDockWidget.isValid()) + return; + + auto dockWidget = vDockWidget.value<DockWidget *>(); + if (dockWidget) { + dockWidget->dockAreaWidget()->setCurrentDockWidget(dockWidget); + DockManager::setWidgetFocus(dockWidget->tabWidget()); + } + } + + void DockFocusController::onStateRestored() + { + if (d->m_focusedDockWidget) + updateDockWidgetFocusStyle(d->m_focusedDockWidget, false); + } + +} // namespace ADS |