diff --git a/CMakeLists.txt b/CMakeLists.txt index 289e108..8a9f919 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,7 +86,7 @@ install(TARGETS qtadvanceddocking ARCHIVE DESTINATION lib COMPONENT library ) target_include_directories(qtadvanceddocking PUBLIC - $ + "$" $ ) target_link_libraries(qtadvanceddocking PUBLIC ${ads_LIBS}) diff --git a/README.md b/README.md index 3dad5c8..5df35cd 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Qt Advanced Docking System lets you create customizable layouts using a full featured window docking system similar to what is found in many popular integrated development environements (IDEs) such as Visual Studio. Everything is implemented with standard Qt functionality without any -platform specific code. Basic usage of QWidgets an QLayouts and using basic +platform specific code. Basic usage of QWidgets and QLayouts and using basic styles as much as possible. This work is based on and inspired by the diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index 553bd18..817432e 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -24,7 +24,6 @@ set(ads_demo_SRCS main.cpp MainWindow.cpp mainwindow.ui - main.qrc ) add_executable(AdvancedDockingSystemDemo WIN32 ${ads_demo_SRCS}) if(BUILD_STATIC) diff --git a/demo/demo.pro b/demo/demo.pro index 2d787e9..998876d 100644 --- a/demo/demo.pro +++ b/demo/demo.pro @@ -21,7 +21,6 @@ HEADERS += \ FORMS += \ mainwindow.ui -RESOURCES += main.qrc LIBS += -L$${ADS_OUT_ROOT}/lib diff --git a/demo/main.qrc b/demo/main.qrc deleted file mode 100644 index 45fb1b9..0000000 --- a/demo/main.qrc +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/example/example.pro b/example/example.pro index 6b37fd4..33b73f9 100644 --- a/example/example.pro +++ b/example/example.pro @@ -23,7 +23,6 @@ HEADERS += \ FORMS += \ MainWindow.ui -#RESOURCES += main.qrc LIBS += -L$${ADS_OUT_ROOT}/lib diff --git a/src/DockAreaTabBar.h b/src/DockAreaTabBar.h index f065ebd..d769be1 100644 --- a/src/DockAreaTabBar.h +++ b/src/DockAreaTabBar.h @@ -44,6 +44,10 @@ class CFloatingDockContainer; * Custom tabbar implementation for tab area that is shown on top of a * dock area widget. * The tabbar displays the tab widgets of the contained dock widgets. + * We cannot use QTabBar here because it does a lot of fancy animations + * that will crash the application if a tab is removed while the animation + * has not finished. And we need to remove a tab, if the user drags a + * a dock widget out of a group of tabbed widgets */ class CDockAreaTabBar : public QScrollArea { @@ -61,6 +65,7 @@ private slots: protected: virtual void wheelEvent(QWheelEvent* Event) override; + /** * Stores mouse position to detect dragging */ @@ -96,6 +101,7 @@ protected: public: using Super = QScrollArea; + /** * Default Constructor */ diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index 1e3c2d3..b1b0446 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -99,8 +99,9 @@ struct DockAreaTitleBarPrivate } /** - * Helper class to set title bar button icons depending on operating system - * and to avoid duplicated code + * Helper function to set title bar button icons depending on operating + * system and to avoid duplicated code. On windows the standard icons + * are blurry since Qt 5.11 so we need to do some additional steps */ void setTitleBarButtonIcon(tTileBarButton* Button, QStyle::StandardPixmap StandarPixmap) { @@ -136,14 +137,14 @@ void DockAreaTitleBarPrivate::createButtons() TabsMenuButton->setPopupMode(QToolButton::InstantPopup); setTitleBarButtonIcon(TabsMenuButton, QStyle::SP_TitleBarUnshadeButton); QMenu* TabsMenu = new QMenu(TabsMenuButton); - #ifndef QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP TabsMenu->setToolTipsVisible(true); - #endif +#endif _this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow())); TabsMenuButton->setMenu(TabsMenu); - #ifndef QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP TabsMenuButton->setToolTip(QObject::tr("List all tabs")); - #endif +#endif TabsMenuButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); TopLayout->addWidget(TabsMenuButton, 0); _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)), @@ -154,9 +155,9 @@ void DockAreaTitleBarPrivate::createButtons() UndockButton = new tTileBarButton(); UndockButton->setObjectName("undockButton"); UndockButton->setAutoRaise(true); - #ifndef QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP UndockButton->setToolTip(QObject::tr("Detach Group")); - #endif +#endif setTitleBarButtonIcon(UndockButton, QStyle::SP_TitleBarNormalButton); UndockButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); TopLayout->addWidget(UndockButton, 0); @@ -168,7 +169,7 @@ void DockAreaTitleBarPrivate::createButtons() CloseButton->setObjectName("closeButton"); CloseButton->setAutoRaise(true); setTitleBarButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton); - #ifndef QT_NO_TOOLTIP +#ifndef QT_NO_TOOLTIP if (testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab)) { CloseButton->setToolTip(QObject::tr("Close Active Tab")); @@ -177,7 +178,7 @@ void DockAreaTitleBarPrivate::createButtons() { CloseButton->setToolTip(QObject::tr("Close Group")); } - #endif +#endif CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); CloseButton->setIconSize(QSize(16, 16)); TopLayout->addWidget(CloseButton, 0); diff --git a/src/DockAreaTitleBar.h b/src/DockAreaTitleBar.h index 3ea1d3e..8b07d7b 100644 --- a/src/DockAreaTitleBar.h +++ b/src/DockAreaTitleBar.h @@ -43,7 +43,9 @@ class CDockAreaWidget; struct DockAreaTitleBarPrivate; /** - * Title bar of a dock area + * Title bar of a dock area. + * The title bar contains a tabbar with all tabs for a dock widget group and + * with a tabs menu button, a undock button and a close button. */ class CDockAreaTitleBar : public QFrame { @@ -61,6 +63,10 @@ private slots: void showContextMenu(const QPoint& pos); public slots: + /** + * Call this slot to tell the title bar that it should update the tabs menu + * the next time it is shown. + */ void markTabsMenuOutdated(); @@ -87,7 +93,8 @@ public: QAbstractButton* button(TitleBarButton which) const; /** - * This function is here for debug reasons + * Marks the tabs menu outdated before it calls its base class + * implementation */ virtual void setVisible(bool Visible) override; diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 4dcd289..cbf2f36 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -63,8 +63,11 @@ static const char* const INDEX_PROPERTY = "index"; static const char* const ACTION_PROPERTY = "action"; /** - * New dock area layout mimics stack layout but only inserts the current - * widget into the internal QLayout object + * Internal dock area layout mimics stack layout but only inserts the current + * widget into the internal QLayout object. + * \warning Only the current widget has a parent. All other widgets + * do not have a parent. That means, a widget that is in this layout may + * return nullptr for its parent() function if it is not the current widget. */ class CDockAreaLayout { @@ -118,7 +121,7 @@ public: } /** - * Removes the given widget from the lyout + * Removes the given widget from the layout */ void removeWidget(QWidget* Widget) { diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index 02f2339..91e8605 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -185,12 +185,12 @@ public: QList dockWidgets() const; /** - * Returns the number of dock widgets in this area + * Returns the number of open dock widgets in this area */ int openDockWidgetsCount() const; /** - * Returns a list of dock widgets that are not closed + * Returns a list of dock widgets that are not closed. */ QList openedDockWidgets() const; @@ -236,8 +236,10 @@ public: * This functions returns the dock widget features of all dock widget in * this area. * A bitwise and is used to combine the flags of all dock widgets. That - * means, if only dock widget does not support a certain flag, the whole - * dock are does not support the flag. + * means, if only one single dock widget does not support a certain flag, + * the whole dock are does not support the flag. I.e. if one single + * dock widget in this area is not closabe, the whole dock are is not + * closable. */ CDockWidget::DockWidgetFeatures features() const; diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index c923ecc..66e0799 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -50,7 +50,10 @@ struct FloatingDockContainerPrivate; /** * Container that manages a number of dock areas with single dock widgets - * or tabyfied dock widgets in each area + * or tabyfied dock widgets in each area. + * Each window that support docking has a DockContainerWidget. That means + * the main application window and all floating windows are ore contain + * an DockContainerWidget. */ class ADS_EXPORT CDockContainerWidget : public QFrame { diff --git a/src/DockManager.h b/src/DockManager.h index 4a6dfdc..2309484 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -131,7 +131,7 @@ public: * If the given parent is a QMainWindow, the dock manager sets itself as the * central widget. * Before you create any dock widgets, you should properly setup the - * configuration flags via setConfigFlags() + * configuration flags via setConfigFlags(). */ CDockManager(QWidget* parent = 0); diff --git a/src/DockOverlay.h b/src/DockOverlay.h index 0fb27cc..da66334 100644 --- a/src/DockOverlay.h +++ b/src/DockOverlay.h @@ -245,9 +245,6 @@ public: protected: virtual void showEvent(QShowEvent* e) override; void setAreaWidgets(const QHash& widgets); - -private: - }; // CDockOverlayCross } // namespace ads diff --git a/src/DockSplitter.h b/src/DockSplitter.h index 88ac78b..32ee2ab 100644 --- a/src/DockSplitter.h +++ b/src/DockSplitter.h @@ -38,7 +38,8 @@ namespace ads struct DockSplitterPrivate; /** - * Splitter used internally instead of QSplitter + * Splitter used internally instead of QSplitter with some additional + * fuctionality. */ class ADS_EXPORT CDockSplitter : public QSplitter { diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index 92f6277..aaf4530 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -444,7 +444,7 @@ void CDockWidgetTab::setIcon(const QIcon& Icon) d->Icon = Icon; if (d->IconLabel) { - d->IconLabel->setPixmap(Icon.pixmap(this->windowHandle(), QSize(16, 16))); + d->IconLabel->setPixmap(Icon.pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this))); d->IconLabel->setVisible(true); } } diff --git a/src/DockWidgetTab.h b/src/DockWidgetTab.h index 9acbe15..3b8136e 100644 --- a/src/DockWidgetTab.h +++ b/src/DockWidgetTab.h @@ -143,7 +143,6 @@ public: virtual bool event(QEvent *e) override; public slots: - virtual void setVisible(bool visible) override; diff --git a/src/ElidingLabel.cpp b/src/ElidingLabel.cpp index 4849da0..73b46b4 100644 --- a/src/ElidingLabel.cpp +++ b/src/ElidingLabel.cpp @@ -158,9 +158,9 @@ QSize CElidingLabel::minimumSizeHint() const } const QFontMetrics &fm = fontMetrics(); #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) - QSize size(fm.horizontalAdvance(d->Text), QLabel::sizeHint().height()); + QSize size(fm.horizontalAdvance(d->Text.left(2) + "…"), fm.height()); #else - QSize size(fm.width(d->Text), QLabel::sizeHint().height()); + QSize size(fm.width(d->Text.left(2) + "…"), fm.height()); #endif return size; } diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index d6baa30..41af3d3 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -1,21 +1,20 @@ /******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library 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 -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - + ** Qt Advanced Docking System + ** Copyright (C) 2017 Uwe Kindler + ** + ** This library is free software; you can redistribute it and/or + ** modify it under the terms of the GNU Lesser General Public + ** License as published by the Free Software Foundation; either + ** version 2.1 of the License, or (at your option) any later version. + ** + ** This library 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 + ** Lesser General Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public + ** License along with this library; If not, see . + ******************************************************************************/ //============================================================================ /// \file FloatingDockContainer.cpp @@ -24,7 +23,6 @@ /// \brief Implementation of CFloatingDockContainer class //============================================================================ - //============================================================================ // INCLUDES //============================================================================ @@ -50,7 +48,6 @@ #include #endif - namespace ads { static unsigned int zOrderCounter = 0; @@ -59,14 +56,14 @@ static unsigned int zOrderCounter = 0; */ struct FloatingDockContainerPrivate { - CFloatingDockContainer* _this; - CDockContainerWidget* DockContainer; + CFloatingDockContainer *_this; + CDockContainerWidget *DockContainer; unsigned int zOrderIndex = ++zOrderCounter; QPointer DockManager; eDragState DraggingState = DraggingInactive; QPoint DragStartMousePosition; - CDockContainerWidget* DropContainer = nullptr; - CDockAreaWidget* SingleDockArea = nullptr; + CDockContainerWidget *DropContainer = nullptr; + CDockAreaWidget *SingleDockArea = nullptr; #ifdef Q_OS_LINUX QWidget* MouseEventHandler = nullptr; CFloatingWidgetTitleBar* TitleBar = nullptr; @@ -75,10 +72,10 @@ struct FloatingDockContainerPrivate /** * Private data constructor */ - FloatingDockContainerPrivate(CFloatingDockContainer* _public); + FloatingDockContainerPrivate(CFloatingDockContainer *_public); void titleMouseReleaseEvent(); - void updateDropOverlays(const QPoint& GlobalPos); + void updateDropOverlays(const QPoint &GlobalPos); /** * Tests is a certain state is active @@ -93,28 +90,25 @@ struct FloatingDockContainerPrivate DraggingState = StateId; } - void setWindowTitle(const QString& Text) - { + void setWindowTitle(const QString &Text) + { #ifdef Q_OS_LINUX TitleBar->setTitle(Text); #else - _this->setWindowTitle(Text); + _this->setWindowTitle(Text); #endif - } + } }; // struct FloatingDockContainerPrivate - - //============================================================================ -FloatingDockContainerPrivate::FloatingDockContainerPrivate(CFloatingDockContainer* _public) : +FloatingDockContainerPrivate::FloatingDockContainerPrivate( + CFloatingDockContainer *_public) : _this(_public) { } - - //============================================================================ void FloatingDockContainerPrivate::titleMouseReleaseEvent() { @@ -124,25 +118,31 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent() return; } - if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea - || DockManager->containerOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea) + if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() + != InvalidDockWidgetArea + || DockManager->containerOverlay()->dropAreaUnderCursor() + != InvalidDockWidgetArea) { // Resize the floating widget to the size of the highlighted drop area // rectangle - CDockOverlay* Overlay = DockManager->containerOverlay(); + CDockOverlay *Overlay = DockManager->containerOverlay(); if (!Overlay->dropOverlayRect().isValid()) { Overlay = DockManager->dockAreaOverlay(); } QRect Rect = Overlay->dropOverlayRect(); - int FrameWidth = (_this->frameSize().width() - _this->rect().width()) / 2; - int TitleBarHeight = _this->frameSize().height() - _this->rect().height() - FrameWidth; + int FrameWidth = (_this->frameSize().width() - _this->rect().width()) + / 2; + int TitleBarHeight = _this->frameSize().height() + - _this->rect().height() - FrameWidth; if (Rect.isValid()) { QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft()); TopLeft.ry() += TitleBarHeight; - _this->setGeometry(QRect(TopLeft, QSize(Rect.width(), Rect.height() - TitleBarHeight))); + _this->setGeometry( + QRect(TopLeft, + QSize(Rect.width(), Rect.height() - TitleBarHeight))); QApplication::processEvents(); } DropContainer->dropFloatingWidget(_this, QCursor::pos()); @@ -152,94 +152,94 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent() DockManager->dockAreaOverlay()->hideOverlay(); } - - //============================================================================ -void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos) +void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos) { if (!_this->isVisible() || !DockManager) { return; } - auto Containers = DockManager->dockContainers(); - CDockContainerWidget* TopContainer = nullptr; - for (auto ContainerWidget : Containers) - { - if (!ContainerWidget->isVisible()) - { - continue; - } + auto Containers = DockManager->dockContainers(); + CDockContainerWidget *TopContainer = nullptr; + for (auto ContainerWidget : Containers) + { + if (!ContainerWidget->isVisible()) + { + continue; + } - if (DockContainer == ContainerWidget) - { - continue; - } + if (DockContainer == ContainerWidget) + { + continue; + } - QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos); - if (ContainerWidget->rect().contains(MappedPos)) - { - if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer)) - { - TopContainer = ContainerWidget; - } - } - } + QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos); + if (ContainerWidget->rect().contains(MappedPos)) + { + if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer)) + { + TopContainer = ContainerWidget; + } + } + } - DropContainer = TopContainer; - auto ContainerOverlay = DockManager->containerOverlay(); - auto DockAreaOverlay = DockManager->dockAreaOverlay(); + DropContainer = TopContainer; + auto ContainerOverlay = DockManager->containerOverlay(); + auto DockAreaOverlay = DockManager->dockAreaOverlay(); - if (!TopContainer) - { - ContainerOverlay->hideOverlay(); - DockAreaOverlay->hideOverlay(); - return; - } + if (!TopContainer) + { + ContainerOverlay->hideOverlay(); + DockAreaOverlay->hideOverlay(); + return; + } - int VisibleDockAreas = TopContainer->visibleDockAreaCount(); - ContainerOverlay->setAllowedAreas(VisibleDockAreas > 1 ? - OuterDockAreas : AllDockAreas); + int VisibleDockAreas = TopContainer->visibleDockAreaCount(); + ContainerOverlay->setAllowedAreas( + VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas); DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer); ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea); - auto DockArea = TopContainer->dockAreaAt(GlobalPos); - if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0) - { - DockAreaOverlay->enableDropPreview(true); - DockAreaOverlay->setAllowedAreas((VisibleDockAreas == 1) ? - NoDockWidgetArea : AllDockAreas); - DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea); + auto DockArea = TopContainer->dockAreaAt(GlobalPos); + if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0) + { + DockAreaOverlay->enableDropPreview(true); + DockAreaOverlay->setAllowedAreas( + (VisibleDockAreas == 1) ? NoDockWidgetArea : AllDockAreas); + DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea); - // A CenterDockWidgetArea for the dockAreaOverlay() indicates that - // the mouse is in the title bar. If the ContainerArea is valid - // then we ignore the dock area of the dockAreaOverlay() and disable - // the drop preview - if ((Area == CenterDockWidgetArea) && (ContainerArea != InvalidDockWidgetArea)) - { - DockAreaOverlay->enableDropPreview(false); - ContainerOverlay->enableDropPreview(true); - } - else - { - ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area); - } - } - else - { - DockAreaOverlay->hideOverlay(); - } + // A CenterDockWidgetArea for the dockAreaOverlay() indicates that + // the mouse is in the title bar. If the ContainerArea is valid + // then we ignore the dock area of the dockAreaOverlay() and disable + // the drop preview + if ((Area == CenterDockWidgetArea) + && (ContainerArea != InvalidDockWidgetArea)) + { + DockAreaOverlay->enableDropPreview(false); + ContainerOverlay->enableDropPreview(true); + } + else + { + ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area); + } + } + else + { + DockAreaOverlay->hideOverlay(); + } } - //============================================================================ -CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) : - tFloatingWidgetBase(DockManager), +CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) : + tFloatingWidgetBase(DockManager), d(new FloatingDockContainerPrivate(this)) { - d->DockManager = DockManager; - d->DockContainer = new CDockContainerWidget(DockManager, this); - connect(d->DockContainer, SIGNAL(dockAreasAdded()), this, SLOT(onDockAreasAddedOrRemoved())); - connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this, SLOT(onDockAreasAddedOrRemoved())); + d->DockManager = DockManager; + d->DockContainer = new CDockContainerWidget(DockManager, this); + connect(d->DockContainer, SIGNAL(dockAreasAdded()), this, + SLOT(onDockAreasAddedOrRemoved())); + connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this, + SLOT(onDockAreasAddedOrRemoved())); #ifdef Q_OS_LINUX d->TitleBar = new CFloatingWidgetTitleBar(this); @@ -250,26 +250,25 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) : setTitleBarWidget(d->TitleBar); connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close())); #else - setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint); - QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom); - l->setContentsMargins(0, 0, 0, 0); - l->setSpacing(0); - setLayout(l); - l->addWidget(d->DockContainer); + setWindowFlags( + Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint); + QBoxLayout *l = new QBoxLayout(QBoxLayout::TopToBottom); + l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); + setLayout(l); + l->addWidget(d->DockContainer); #endif DockManager->registerFloatingWidget(this); - // We install an event filter to detect mouse release events because we // do not receive mouse release event if the floating widget is behind // the drop overlay cross - qApp->installEventFilter(this); + qApp->installEventFilter(this); } - //============================================================================ -CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget* DockArea) : +CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget *DockArea) : CFloatingDockContainer(DockArea->dockManager()) { d->DockContainer->addDockArea(DockArea); @@ -278,12 +277,11 @@ CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget* DockArea) : #endif } - //============================================================================ -CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) : - CFloatingDockContainer(DockWidget->dockManager()) +CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) : + CFloatingDockContainer(DockWidget->dockManager()) { - d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget); + d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget); #ifdef Q_OS_LINUX d->TitleBar->enableCloseButton(isClosable()); #endif @@ -292,7 +290,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) : //============================================================================ CFloatingDockContainer::~CFloatingDockContainer() { - ADS_PRINT("~CFloatingDockContainer"); + ADS_PRINT("~CFloatingDockContainer"); if (d->DockManager) { d->DockManager->removeFloatingWidget(this); @@ -300,82 +298,77 @@ CFloatingDockContainer::~CFloatingDockContainer() delete d; } - //============================================================================ CDockContainerWidget* CFloatingDockContainer::dockContainer() const { return d->DockContainer; } - //============================================================================ void CFloatingDockContainer::changeEvent(QEvent *event) { QWidget::changeEvent(event); if ((event->type() == QEvent::ActivationChange) && isActiveWindow()) - { - ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange "); + { + ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange "); d->zOrderIndex = ++zOrderCounter; - return; - } + return; + } } - //============================================================================ void CFloatingDockContainer::moveEvent(QMoveEvent *event) { QWidget::moveEvent(event); - switch (d->DraggingState) + switch (d->DraggingState) { case DraggingMousePressed: - d->setState(DraggingFloatingWidget); - d->updateDropOverlays(QCursor::pos()); - break; + d->setState(DraggingFloatingWidget); + d->updateDropOverlays(QCursor::pos()); + break; case DraggingFloatingWidget: - d->updateDropOverlays(QCursor::pos()); - break; + d->updateDropOverlays(QCursor::pos()); + break; default: break; - } + } } - //============================================================================ void CFloatingDockContainer::closeEvent(QCloseEvent *event) { - ADS_PRINT("CFloatingDockContainer closeEvent"); + ADS_PRINT("CFloatingDockContainer closeEvent"); d->setState(DraggingInactive); - if (isClosable()) - { - // In Qt version after 5.9.2 there seems to be a bug that causes the - // QWidget::event() function to not receive any NonClientArea mouse - // events anymore after a close/show cycle. The bug is reported here: - // https://bugreports.qt.io/browse/QTBUG-73295 - // The following code is a workaround for Qt versions > 5.9.2 that seems - // to work - // Starting from Qt version 5.12.2 this seems to work again. But - // now the QEvent::NonClientAreaMouseButtonPress function returns always - // Qt::RightButton even if the left button was pressed + if (isClosable()) + { + // In Qt version after 5.9.2 there seems to be a bug that causes the + // QWidget::event() function to not receive any NonClientArea mouse + // events anymore after a close/show cycle. The bug is reported here: + // https://bugreports.qt.io/browse/QTBUG-73295 + // The following code is a workaround for Qt versions > 5.9.2 that seems + // to work + // Starting from Qt version 5.12.2 this seems to work again. But + // now the QEvent::NonClientAreaMouseButtonPress function returns always + // Qt::RightButton even if the left button was pressed #ifndef Q_OS_LINUX #if (QT_VERSION > QT_VERSION_CHECK(5, 9, 2) && QT_VERSION < QT_VERSION_CHECK(5, 12, 2)) event->ignore(); this->hide(); #else - Super::closeEvent(event); + Super::closeEvent(event); #endif #else // Q_OS_LINUX Super::closeEvent(event); #endif - } - else - { - event->ignore(); - } + } + else + { + event->ignore(); + } } - //============================================================================ void CFloatingDockContainer::hideEvent(QHideEvent *event) { @@ -389,14 +382,12 @@ void CFloatingDockContainer::hideEvent(QHideEvent *event) } } - //============================================================================ void CFloatingDockContainer::showEvent(QShowEvent *event) { Super::showEvent(event); } - //============================================================================ bool CFloatingDockContainer::event(QEvent *e) { @@ -412,9 +403,10 @@ bool CFloatingDockContainer::event(QEvent *e) // It is really great to work around the whole NonClientMouseArea // bugs #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2)) - if (e->type() == QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/) + if (e->type() + == QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/) { - ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type()); + ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type()); d->setState(DraggingMousePressed); } #else @@ -425,43 +417,43 @@ bool CFloatingDockContainer::event(QEvent *e) } #endif } - break; + break; case DraggingMousePressed: switch (e->type()) { case QEvent::NonClientAreaMouseButtonDblClick: - ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick"); - d->setState(DraggingInactive); - break; + ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick"); + d->setState(DraggingInactive); + break; case QEvent::Resize: - // If the first event after the mouse press is a resize event, then - // the user resizes the window instead of dragging it around. - // But there is one exception. If the window is maximized, - // then dragging the window via title bar will cause the widget to - // leave the maximized state. This in turn will trigger a resize event. - // To know, if the resize event was triggered by user via moving a - // corner of the window frame or if it was caused by a windows state - // change, we check, if we are not in maximized state. - if (!isMaximized()) - { - d->setState(DraggingInactive); - } - break; + // If the first event after the mouse press is a resize event, then + // the user resizes the window instead of dragging it around. + // But there is one exception. If the window is maximized, + // then dragging the window via title bar will cause the widget to + // leave the maximized state. This in turn will trigger a resize event. + // To know, if the resize event was triggered by user via moving a + // corner of the window frame or if it was caused by a windows state + // change, we check, if we are not in maximized state. + if (!isMaximized()) + { + d->setState(DraggingInactive); + } + break; default: break; } - break; + break; case DraggingFloatingWidget: if (e->type() == QEvent::NonClientAreaMouseButtonRelease) { - ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease"); + ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease"); d->titleMouseReleaseEvent(); } - break; + break; default: break; @@ -473,25 +465,24 @@ bool CFloatingDockContainer::event(QEvent *e) return QWidget::event(e); } - //============================================================================ bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *event) { - Q_UNUSED(watched); - if (event->type() == QEvent::MouseButtonRelease && d->isState(DraggingFloatingWidget)) + Q_UNUSED(watched); + if (event->type() == QEvent::MouseButtonRelease + && d->isState(DraggingFloatingWidget)) { - ADS_PRINT("FloatingWidget::eventFilter QEvent::MouseButtonRelease"); - finishDragging(); + ADS_PRINT("FloatingWidget::eventFilter QEvent::MouseButtonRelease"); + finishDragging(); d->titleMouseReleaseEvent(); - } + } return false; } - //============================================================================ -void CFloatingDockContainer::startFloating(const QPoint& DragStartMousePos, const QSize& Size, - eDragState DragState, QWidget* MouseEventHandler) +void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos, + const QSize &Size, eDragState DragState, QWidget *MouseEventHandler) { #ifndef Q_OS_LINUX Q_UNUSED(MouseEventHandler) @@ -500,89 +491,94 @@ void CFloatingDockContainer::startFloating(const QPoint& DragStartMousePos, cons d->setState(DragState); d->DragStartMousePosition = DragStartMousePos; #ifdef Q_OS_LINUX - if (DraggingFloatingWidget == DragState) - { - setAttribute(Qt::WA_X11NetWmWindowTypeDock, true); - setWindowOpacity(0.6); - d->MouseEventHandler = MouseEventHandler; - if (d->MouseEventHandler) - { - d->MouseEventHandler->grabMouse(); - } - } + // I have not found a way on Linux to display the floating widget behind the + // dock overlay. That means if the user drags this floating widget around, + // it is always painted in front of the dock overlay and dock overlay cross. + // and the user will not see the dock overlay. To work around this issue, + // the window opacity is set to 0.6 to make the dock overlay visible + // again. If someone has an idea, how to place the dragged floating widget + // behind the dock overlay, then a pull request would be welcome. + if (DraggingFloatingWidget == DragState) + { + setAttribute(Qt::WA_X11NetWmWindowTypeDock, true); + setWindowOpacity(0.6); + d->MouseEventHandler = MouseEventHandler; + if (d->MouseEventHandler) + { + d->MouseEventHandler->grabMouse(); + } + } #endif moveFloating(); - show(); + show(); } - //============================================================================ void CFloatingDockContainer::moveFloating() { int BorderSize = (frameSize().width() - size().width()) / 2; - const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition - QPoint(BorderSize, 0); - move(moveToPos); + const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition + - QPoint(BorderSize, 0); + move(moveToPos); } - //============================================================================ bool CFloatingDockContainer::isClosable() const { - return d->DockContainer->features().testFlag(CDockWidget::DockWidgetClosable); + return d->DockContainer->features().testFlag( + CDockWidget::DockWidgetClosable); } - //============================================================================ void CFloatingDockContainer::onDockAreasAddedOrRemoved() { - ADS_PRINT("CFloatingDockContainer::onDockAreasAddedOrRemoved()"); + ADS_PRINT("CFloatingDockContainer::onDockAreasAddedOrRemoved()"); auto TopLevelDockArea = d->DockContainer->topLevelDockArea(); if (TopLevelDockArea) { d->SingleDockArea = TopLevelDockArea; - d->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle()); + d->setWindowTitle( + d->SingleDockArea->currentDockWidget()->windowTitle()); connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this, - SLOT(onDockAreaCurrentChanged(int))); + SLOT(onDockAreaCurrentChanged(int))); } else { if (d->SingleDockArea) { disconnect(d->SingleDockArea, SIGNAL(currentChanged(int)), this, - SLOT(onDockAreaCurrentChanged(int))); + SLOT(onDockAreaCurrentChanged(int))); d->SingleDockArea = nullptr; } - d->setWindowTitle(qApp->applicationDisplayName()); + d->setWindowTitle(qApp->applicationDisplayName()); } } - //============================================================================ void CFloatingDockContainer::updateWindowTitle() { auto TopLevelDockArea = d->DockContainer->topLevelDockArea(); if (TopLevelDockArea) { - d->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle()); + d->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle()); } else { - d->setWindowTitle(qApp->applicationDisplayName()); + d->setWindowTitle(qApp->applicationDisplayName()); } } - //============================================================================ void CFloatingDockContainer::onDockAreaCurrentChanged(int Index) { Q_UNUSED(Index); - d->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle()); + d->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle()); } - //============================================================================ -bool CFloatingDockContainer::restoreState(QXmlStreamReader& Stream, bool Testing) +bool CFloatingDockContainer::restoreState(QXmlStreamReader &Stream, + bool Testing) { if (!d->DockContainer->restoreState(Stream, Testing)) { @@ -593,33 +589,28 @@ bool CFloatingDockContainer::restoreState(QXmlStreamReader& Stream, bool Testing return true; } - //============================================================================ bool CFloatingDockContainer::hasTopLevelDockWidget() const { return d->DockContainer->hasTopLevelDockWidget(); } - //============================================================================ CDockWidget* CFloatingDockContainer::topLevelDockWidget() const { return d->DockContainer->topLevelDockWidget(); } - //============================================================================ QList CFloatingDockContainer::dockWidgets() const { return d->DockContainer->dockWidgets(); } - - //============================================================================ void CFloatingDockContainer::finishDragging() { - ADS_PRINT("CFloatingDockContainer::finishDragging"); + ADS_PRINT("CFloatingDockContainer::finishDragging"); #ifdef Q_OS_LINUX setAttribute(Qt::WA_X11NetWmWindowTypeDock, false); setWindowOpacity(1); @@ -632,7 +623,6 @@ void CFloatingDockContainer::finishDragging() #endif } - } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/FloatingDockContainer.h b/src/FloatingDockContainer.h index 898f31c..d8e4b3d 100644 --- a/src/FloatingDockContainer.h +++ b/src/FloatingDockContainer.h @@ -60,7 +60,8 @@ class CFloatingWidgetTitleBar; /** * This implements a floating widget that is a dock container that accepts * docking of dock widgets like the main window and that can be docked into - * another dock container + * another dock container. + * Every floating window of the docking system is a FloatingDockContainer. */ class ADS_EXPORT CFloatingDockContainer : public tFloatingWidgetBase { diff --git a/src/ads_globals.h b/src/ads_globals.h index c19f260..72967bc 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -45,12 +45,15 @@ #define ADS_EXPORT #endif +// Define ADS_DEBUG_PRINT to enable a lot of debug output #ifdef ADS_DEBUG_PRINT #define ADS_PRINT(s) qDebug() << s #else #define ADS_PRINT(s) #endif +// Set ADS_DEBUG_LEVEL to enable additional debug output and to enable layout +// dumps to qDebug and std::cout after layout changes #define ADS_DEBUG_LEVEL 0 class QSplitter; diff --git a/src/linux/FloatingWidgetTitleBar.cpp b/src/linux/FloatingWidgetTitleBar.cpp index 43551bd..c4c1c7c 100644 --- a/src/linux/FloatingWidgetTitleBar.cpp +++ b/src/linux/FloatingWidgetTitleBar.cpp @@ -1,21 +1,20 @@ /******************************************************************************* -** Qt Advanced Docking System -** Copyright (C) 2017 Uwe Kindler -** -** This library is free software; you can redistribute it and/or -** modify it under the terms of the GNU Lesser General Public -** License as published by the Free Software Foundation; either -** version 2.1 of the License, or (at your option) any later version. -** -** This library 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 -** Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public -** License along with this library; If not, see . -******************************************************************************/ - + ** Qt Advanced Docking System + ** Copyright (C) 2017 Uwe Kindler + ** + ** This library is free software; you can redistribute it and/or + ** modify it under the terms of the GNU Lesser General Public + ** License as published by the Free Software Foundation; either + ** version 2.1 of the License, or (at your option) any later version. + ** + ** This library 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 + ** Lesser General Public License for more details. + ** + ** You should have received a copy of the GNU Lesser General Public + ** License along with this library; If not, see . + ******************************************************************************/ //============================================================================ /// \file FloatingWidgetTitleBar.cpp @@ -48,140 +47,137 @@ namespace ads using tTabLabel = CElidingLabel; using tCloseButton = QPushButton; - /** * @brief Private data class of public interface CFloatingWidgetTitleBar */ struct FloatingWidgetTitleBarPrivate { - CFloatingWidgetTitleBar* _this; ///< public interface class - QLabel* IconLabel = nullptr; - tTabLabel* TitleLabel; - tCloseButton* CloseButton = nullptr; - CFloatingDockContainer* FloatingWidget = nullptr; - eDragState DragState = DraggingInactive; + CFloatingWidgetTitleBar *_this; ///< public interface class + QLabel *IconLabel = nullptr; + tTabLabel *TitleLabel; + tCloseButton *CloseButton = nullptr; + CFloatingDockContainer *FloatingWidget = nullptr; + eDragState DragState = DraggingInactive; - FloatingWidgetTitleBarPrivate(CFloatingWidgetTitleBar* _public) : _this(_public) {} + FloatingWidgetTitleBarPrivate(CFloatingWidgetTitleBar *_public) : + _this(_public) + { + } - /** - * Creates the complete layout including all controls - */ - void createLayout(); + /** + * Creates the complete layout including all controls + */ + void createLayout(); }; - //============================================================================ void FloatingWidgetTitleBarPrivate::createLayout() { - TitleLabel = new tTabLabel(); - TitleLabel->setElideMode(Qt::ElideRight); - TitleLabel->setText("DockWidget->windowTitle()"); - TitleLabel->setObjectName("floatingTitleLabel"); - TitleLabel->setAlignment(Qt::AlignLeft); + TitleLabel = new tTabLabel(); + TitleLabel->setElideMode(Qt::ElideRight); + TitleLabel->setText("DockWidget->windowTitle()"); + TitleLabel->setObjectName("floatingTitleLabel"); + TitleLabel->setAlignment(Qt::AlignLeft); - CloseButton = new tCloseButton(); - CloseButton->setObjectName("floatingTitleCloseButton"); - CloseButton->setFlat(true); - //CloseButton->setAutoRaise(true); - // The standard icons do does not look good on high DPI screens - QIcon CloseIcon; - QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton); - CloseIcon.addPixmap(normalPixmap, QIcon::Normal); - CloseIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled); - CloseButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarCloseButton)); - CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - CloseButton->setVisible(true); - CloseButton->setFocusPolicy(Qt::NoFocus); - _this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested())); + CloseButton = new tCloseButton(); + CloseButton->setObjectName("floatingTitleCloseButton"); + CloseButton->setFlat(true); - QFontMetrics fm(TitleLabel->font()); - int Spacing = qRound(fm.height() / 4.0); + // The standard icons do does not look good on high DPI screens + QIcon CloseIcon; + QPixmap normalPixmap = _this->style()->standardPixmap( + QStyle::SP_TitleBarCloseButton, 0, CloseButton); + CloseIcon.addPixmap(normalPixmap, QIcon::Normal); + CloseIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), + QIcon::Disabled); + CloseButton->setIcon( + _this->style()->standardIcon(QStyle::SP_TitleBarCloseButton)); + CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + CloseButton->setVisible(true); + CloseButton->setFocusPolicy(Qt::NoFocus); + _this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested())); - // Fill the layout - QBoxLayout* Layout = new QBoxLayout(QBoxLayout::LeftToRight); - Layout->setContentsMargins(6,0,0,0); - Layout->setSpacing(0); - _this->setLayout(Layout); - Layout->addWidget(TitleLabel, 1); - Layout->addSpacing(Spacing); - Layout->addWidget(CloseButton); - Layout->setAlignment(Qt::AlignCenter); + QFontMetrics fm(TitleLabel->font()); + int Spacing = qRound(fm.height() / 4.0); - TitleLabel->setVisible(true); + // Fill the layout + QBoxLayout *Layout = new QBoxLayout(QBoxLayout::LeftToRight); + Layout->setContentsMargins(6, 0, 0, 0); + Layout->setSpacing(0); + _this->setLayout(Layout); + Layout->addWidget(TitleLabel, 1); + Layout->addSpacing(Spacing); + Layout->addWidget(CloseButton); + Layout->setAlignment(Qt::AlignCenter); + + TitleLabel->setVisible(true); } - //============================================================================ -CFloatingWidgetTitleBar::CFloatingWidgetTitleBar(CFloatingDockContainer *parent) - : QWidget(parent), - d(new FloatingWidgetTitleBarPrivate(this)) +CFloatingWidgetTitleBar::CFloatingWidgetTitleBar(CFloatingDockContainer *parent) : + QWidget(parent), + d(new FloatingWidgetTitleBarPrivate(this)) { - d->FloatingWidget = parent; - d->createLayout(); + d->FloatingWidget = parent; + d->createLayout(); } - //============================================================================ CFloatingWidgetTitleBar::~CFloatingWidgetTitleBar() { - delete d; + delete d; } - //============================================================================ -void CFloatingWidgetTitleBar::mousePressEvent(QMouseEvent* ev) +void CFloatingWidgetTitleBar::mousePressEvent(QMouseEvent *ev) { - if (ev->button() == Qt::LeftButton) - { - d->DragState = DraggingFloatingWidget; - d->FloatingWidget->startDragging(ev->pos(), d->FloatingWidget->size(), this); - return; - } - Super::mousePressEvent(ev); + if (ev->button() == Qt::LeftButton) + { + d->DragState = DraggingFloatingWidget; + d->FloatingWidget->startDragging(ev->pos(), d->FloatingWidget->size(), + this); + return; + } + Super::mousePressEvent(ev); } - //============================================================================ -void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent* ev) +void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev) { - d->DragState = DraggingInactive; - Super::mouseReleaseEvent(ev); + d->DragState = DraggingInactive; + Super::mouseReleaseEvent(ev); } - //============================================================================ -void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent* ev) +void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev) { - if (!(ev->buttons() & Qt::LeftButton) || DraggingInactive == d->DragState) - { - d->DragState = DraggingInactive; - Super::mouseMoveEvent(ev); - return; - } + if (!(ev->buttons() & Qt::LeftButton) || DraggingInactive == d->DragState) + { + d->DragState = DraggingInactive; + Super::mouseMoveEvent(ev); + return; + } - // move floating window - if (DraggingFloatingWidget == d->DragState) - { - d->FloatingWidget->moveFloating(); - Super::mouseMoveEvent(ev); - return; - } - Super::mouseMoveEvent(ev); + // move floating window + if (DraggingFloatingWidget == d->DragState) + { + d->FloatingWidget->moveFloating(); + Super::mouseMoveEvent(ev); + return; + } + Super::mouseMoveEvent(ev); } - //============================================================================ void CFloatingWidgetTitleBar::enableCloseButton(bool Enable) { - d->CloseButton->setEnabled(Enable); + d->CloseButton->setEnabled(Enable); } - //============================================================================ -void CFloatingWidgetTitleBar::setTitle(const QString& Text) +void CFloatingWidgetTitleBar::setTitle(const QString &Text) { - d->TitleLabel->setText(Text); + d->TitleLabel->setText(Text); } - } // namespace ads diff --git a/src/linux/FloatingWidgetTitleBar.h b/src/linux/FloatingWidgetTitleBar.h index 6f02612..d09ed38 100644 --- a/src/linux/FloatingWidgetTitleBar.h +++ b/src/linux/FloatingWidgetTitleBar.h @@ -37,32 +37,49 @@ class CFloatingDockContainer; struct FloatingWidgetTitleBarPrivate; + +/** + * Titlebar for floating widgets to capture non client are mouse events. + * Linux does not support NonClieantArea mouse events like + * QEvent::NonClientAreaMouseButtonPress. Because these events are required + * for the docking system to work properly, we use our own titlebar here to + * capture the required mouse events. + */ class CFloatingWidgetTitleBar : public QWidget { - Q_OBJECT + Q_OBJECT private: - FloatingWidgetTitleBarPrivate* d; ///< private data (pimpl) + FloatingWidgetTitleBarPrivate *d; ///< private data (pimpl) protected: - virtual void mousePressEvent(QMouseEvent* ev) override; - virtual void mouseReleaseEvent(QMouseEvent* ev) override; - virtual void mouseMoveEvent(QMouseEvent* ev) override; + virtual void mousePressEvent(QMouseEvent *ev) override; + virtual void mouseReleaseEvent(QMouseEvent *ev) override; + virtual void mouseMoveEvent(QMouseEvent *ev) override; public: - using Super = QWidget; - explicit CFloatingWidgetTitleBar (CFloatingDockContainer *parent = nullptr); + using Super = QWidget; + explicit CFloatingWidgetTitleBar(CFloatingDockContainer *parent = nullptr); - /** - * Virtual Destructor - */ - virtual ~CFloatingWidgetTitleBar(); + /** + * Virtual Destructor + */ + virtual ~CFloatingWidgetTitleBar(); - void enableCloseButton(bool Enable); + /** + * Enables / disables the window close button. + */ + void enableCloseButton(bool Enable); - void setTitle(const QString& Text); + /** + * Sets the window title, that means, the text of the internal tile label. + */ + void setTitle(const QString &Text); signals: - void closeRequested(); + /** + * This signal is emitted, if the close button is clicked. + */ + void closeRequested(); }; } // namespace ads #endif // FLOATINGWIDGETTITLEBAR_H