From 2fc8bbe9c94d02e3e82c43bd4daa9f2a9cc8f2c9 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Fri, 5 Jun 2020 21:03:47 +0200 Subject: [PATCH] Added mising DockFocusController files --- src/DockFocusController.cpp | 320 ++++++++++++++++++++++++++++++++++++ src/DockFocusController.h | 83 ++++++++++ 2 files changed, 403 insertions(+) create mode 100644 src/DockFocusController.cpp create mode 100644 src/DockFocusController.h diff --git a/src/DockFocusController.cpp b/src/DockFocusController.cpp new file mode 100644 index 0000000..ea81d1b --- /dev/null +++ b/src/DockFocusController.cpp @@ -0,0 +1,320 @@ +//============================================================================ +/// \file DockFocusController.cpp +/// \author Uwe Kindler +/// \date 05.06.2020 +/// \brief Implementation of CDockFocusController class +//============================================================================ + +//============================================================================ +// INCLUDES +//============================================================================ +#include "DockFocusController.h" + +#include +#include + +#include +#include + +#include "DockWidget.h" +#include "DockAreaWidget.h" +#include "DockWidgetTab.h" +#include "DockContainerWidget.h" +#include "FloatingDockContainer.h" +#include "DockManager.h" +#include "DockAreaTitleBar.h" + +namespace ads +{ +/** + * Private data class of CDockFocusController class (pimpl) + */ +struct DockFocusControllerPrivate +{ + CDockFocusController *_this; + QPointer FocusedDockWidget = nullptr; + QPointer FocusedArea = nullptr; + CDockManager* DockManager; + + /** + * Private data constructor + */ + DockFocusControllerPrivate(CDockFocusController *_public); + + /** + * This function updates the focus style of the given dock widget and + * the dock area that it belongs to + */ + void updateDockWidgetFocus(CDockWidget* DockWidget); +}; +// struct DockFocusControllerPrivate + + +//=========================================================================== +static void updateDockWidgetFocusStyle(CDockWidget* DockWidget, bool Focused) +{ + DockWidget->setProperty("focused", Focused); + DockWidget->tabWidget()->setProperty("focused", Focused); + DockWidget->tabWidget()->updateStyle(); + internal::repolishStyle(DockWidget); +} + + +//=========================================================================== +static void updateDockAreaFocusStyle(CDockAreaWidget* DockArea, bool Focused) +{ + DockArea->setProperty("focused", Focused); + internal::repolishStyle(DockArea); + internal::repolishStyle(DockArea->titleBar()); +} + + +//=========================================================================== +#ifdef Q_OS_LINUX +static void updateFloatingWidgetFocusStyle(CFloatingDockContainer* FloatingWidget, bool Focused) +{ + auto TitleBar = qobject_cast(FloatingWidget->titleBarWidget()); + if (!TitleBar) + { + return; + } + TitleBar->setProperty("focused", Focused); + TitleBar->updateStyle(); +} +#endif + + +//============================================================================ +DockFocusControllerPrivate::DockFocusControllerPrivate( + CDockFocusController *_public) : + _this(_public) +{ + +} + + +//============================================================================ +void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget) +{ + CDockAreaWidget* NewFocusedDockArea = nullptr; + if (FocusedDockWidget) + { + updateDockWidgetFocusStyle(FocusedDockWidget, false); + } + + CDockWidget* old = FocusedDockWidget; + if (DockWidget != FocusedDockWidget) + { + std::cout << "!!!!!!!!!!!! focusedDockWidgetChanged " << (FocusedDockWidget ? FocusedDockWidget->objectName().toStdString() : "-") + << " -> " << (DockWidget ? DockWidget->objectName().toStdString() : "-") << std::endl; + } + FocusedDockWidget = DockWidget; + updateDockWidgetFocusStyle(FocusedDockWidget, true); + NewFocusedDockArea = FocusedDockWidget->dockAreaWidget(); + if (NewFocusedDockArea && (FocusedArea != NewFocusedDockArea)) + { + if (FocusedArea) + { + std::cout << "FocusedArea" << std::endl; + QObject::disconnect(FocusedArea, SIGNAL(viewToggled(bool)), _this, SLOT(onFocusedDockAreaViewToggled(bool))); + updateDockAreaFocusStyle(FocusedArea, false); + } + + FocusedArea = NewFocusedDockArea; + updateDockAreaFocusStyle(FocusedArea, true); + QObject::connect(FocusedArea, SIGNAL(viewToggled(bool)), _this, SLOT(onFocusedDockAreaViewToggled(bool))); + } + + + auto NewFloatingWidget = FocusedDockWidget->dockContainer()->floatingWidget(); + if (NewFloatingWidget) + { + std::cout << "NewFloatingWidget->setProperty(FocusedDockWidget)" << std::endl; + 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 (FloatingWidget == NewFloatingWidget) + { + return; + } + + if (FloatingWidget) + { + updateFloatingWidgetFocusStyle(FloatingWidget, false); + } + FloatingWidget = NewFloatingWidget; + + if (FloatingWidget) + { + updateFloatingWidgetFocusStyle(FloatingWidget, true); + } +#endif + + if (old != DockWidget) + { + emit DockManager->focusedDockWidgetChanged(old, DockWidget); + } +} + + + +//============================================================================ +CDockFocusController::CDockFocusController(CDockManager* DockManager) : + Super(DockManager), + d(new DockFocusControllerPrivate(this)) +{ + d->DockManager = DockManager; + connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*, QWidget*)), + this, SLOT(onApplicationFocusChanged(QWidget*, QWidget*))); + connect(d->DockManager, SIGNAL(stateRestored()), SLOT(onStateRestored())); +} + +//============================================================================ +CDockFocusController::~CDockFocusController() +{ + delete d; +} + + +//=========================================================================== +void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidget* focusedNow) +{ + if (d->DockManager->isRestoringState()) + { + return; + } + std::cout << "CDockManager::onFocusChanged" << std::endl; + std::cout << "focusedNow " << focusedNow << std::endl; + Q_UNUSED(focusedOld) + if (!focusedNow) + { + return; + } + + CDockWidget* DockWidget = nullptr; + auto DockWidgetTab = qobject_cast(focusedNow); + std::cout << "FocuseNow " << focusedNow->metaObject()->className() << std::endl; + if (DockWidgetTab) + { + DockWidget = DockWidgetTab->dockWidget(); + } + else + { + DockWidget = internal::findParent(focusedNow); + } + +#ifdef Q_OS_LINUX + if (!DockWidget) + { + return; + } +#else + if (!DockWidget || DockWidget->tabWidget()->isHidden()) + { + std::cout << "!DockWidget || !DockWidget->tabWidget()->isVisible() " << (DockWidget ? DockWidget->objectName().toStdString() : "0") << std::endl; + std::cout << "DockWidget->tabWidget()->isHidden() " << (DockWidget ? DockWidget->tabWidget()->isHidden() : false) << std::endl; + return; + } +#endif + + std::cout << "CDockManager::onFocusChanged " << DockWidget->tabWidget()->text().toStdString() << std::endl; + d->updateDockWidgetFocus(DockWidget); +} + + +//=========================================================================== +void CDockFocusController::onFocusedDockAreaViewToggled(bool Open) +{ + if (d->DockManager->isRestoringState()) + { + return; + } + + CDockAreaWidget* DockArea = qobject_cast(sender()); + if (!DockArea || Open) + { + return; + } + auto Container = DockArea->dockContainer(); + auto OpenedDockAreas = Container->openedDockAreas(); + if (OpenedDockAreas.isEmpty()) + { + return; + } + + CDockManager::setWidgetFocus(OpenedDockAreas[0]->currentDockWidget()->tabWidget()); +} + + +//=========================================================================== +void CDockFocusController::notifyWidgetOrAreaRelocation(QWidget* DroppedWidget) +{ + if (d->DockManager->isRestoringState()) + { + return; + } + std::cout << "\n\nCDockManager::notifyWidgetDrop" << std::endl; + CDockWidget* DockWidget = qobject_cast(DroppedWidget); + if (DockWidget) + { + std::cout << "CDockManager::setWidgetFocus " << DockWidget->objectName().toStdString() << std::endl; + CDockManager::setWidgetFocus(DockWidget->tabWidget()); + return; + } + + CDockAreaWidget* DockArea = qobject_cast(DroppedWidget); + if (!DockArea) + { + return; + } + + DockWidget = DockArea->currentDockWidget(); + CDockManager::setWidgetFocus(DockWidget->tabWidget()); + std::cout << "\n\n" << std::endl; +} + + +//=========================================================================== +void CDockFocusController::notifyFloatingWidgetDrop(CFloatingDockContainer* FloatingWidget) +{ + std::cout << "\n\nCDockManager::notifyFloatingWidgetDrop" << std::endl; + if (!FloatingWidget || d->DockManager->isRestoringState()) + { + return; + } + + auto vDockWidget = FloatingWidget->property("FocusedDockWidget"); + if (!vDockWidget.isValid()) + { + return; + } + std::cout << "vDockWidget.isValid()" << std::endl; + auto DockWidget = vDockWidget.value(); + if (DockWidget) + { + std::cout << "Dropped focus dock widget " << DockWidget->objectName().toStdString() << std::endl; + DockWidget->dockAreaWidget()->setCurrentDockWidget(DockWidget); + CDockManager::setWidgetFocus(DockWidget->tabWidget()); + } + std::cout << "\n\n" << std::endl; +} + + +//========================================================================== +void CDockFocusController::onStateRestored() +{ + std::cout << "CDockFocusController::onStateRestored()" << std::endl; + if (d->FocusedDockWidget) + { + updateDockWidgetFocusStyle(d->FocusedDockWidget, false); + } +} + +} // namespace ads + +//--------------------------------------------------------------------------- +// EOF DockFocusController.cpp diff --git a/src/DockFocusController.h b/src/DockFocusController.h new file mode 100644 index 0000000..cff65bf --- /dev/null +++ b/src/DockFocusController.h @@ -0,0 +1,83 @@ +#ifndef DockFocusControllerH +#define DockFocusControllerH +//============================================================================ +/// \file DockFocusController.h +/// \author Uwe Kindler +/// \date 05.06.2020 +/// \brief Declaration of CDockFocusController class +//============================================================================ + +//============================================================================ +// INCLUDES +//============================================================================ +#include +#include "ads_globals.h" +#include "DockManager.h" + +namespace ads +{ +struct DockFocusControllerPrivate; +class CDockManager; +class CFloatingDockContainer; + +/** + * Manages focus styling of dock widgets and handling of focus changes + */ +class ADS_EXPORT CDockFocusController : public QObject +{ + Q_OBJECT +private: + DockFocusControllerPrivate* d; ///< private data (pimpl) + friend class DockFocusControllerPrivate; + +private slots: + void onApplicationFocusChanged(QWidget *old, QWidget *now); + void onFocusedDockAreaViewToggled(bool Open); + void onStateRestored(); + +public: + using Super = QObject; + /** + * Default Constructor + */ + CDockFocusController(CDockManager* DockManager); + + /** + * Virtual Destructor + */ + virtual ~CDockFocusController(); + + /** + * Helper function to set focus depending on the configuration of the + * FocusStyling flag + */ + template + static void setWidgetFocus(QWidgetPtr widget) + { + if (!CDockManager::configFlags().testFlag(CDockManager::FocusStyling)) + { + return; + } + + widget->setFocus(Qt::OtherFocusReason); + } + + /** + * A container needs to call this function if a widget has been dropped + * into it + */ + void notifyWidgetOrAreaRelocation(QWidget* RelocatedWidget); + + /** + * This function is called, if a floating widget has been dropped into + * an new position. + * When this function is called, all dock widgets of the FloatingWidget + * are already inserted into its new position + */ + void notifyFloatingWidgetDrop(CFloatingDockContainer* FloatingWidget); +}; // class DockFocusController +} + // namespace ads +//----------------------------------------------------------------------------- +#endif // DockFocusControllerH +