From ac164c3a97552323f342230e5daab0c45b296874 Mon Sep 17 00:00:00 2001 From: Logan Barnes Date: Sun, 11 Aug 2019 00:40:08 +0100 Subject: [PATCH 1/7] fix: Add quotes to cmake BUILD_INTERFACE generator --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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}) From a2b07fd97f0fac63fd7a0ed7b1eb0692b3efab71 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 13 Aug 2019 20:13:19 +0200 Subject: [PATCH 2/7] Reverted change of last pull request because it broke ElidingLabel on Windows --- src/ElidingLabel.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/ElidingLabel.cpp b/src/ElidingLabel.cpp index 4849da0..8e6ea56 100644 --- a/src/ElidingLabel.cpp +++ b/src/ElidingLabel.cpp @@ -157,11 +157,7 @@ QSize CElidingLabel::minimumSizeHint() const return QLabel::minimumSizeHint(); } const QFontMetrics &fm = fontMetrics(); - #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) - QSize size(fm.horizontalAdvance(d->Text), QLabel::sizeHint().height()); - #else - QSize size(fm.width(d->Text), QLabel::sizeHint().height()); - #endif + QSize size(fm.width(d->Text.left(2) + "…"), fm.height()); return size; } @@ -174,11 +170,7 @@ QSize CElidingLabel::sizeHint() const return QLabel::sizeHint(); } const QFontMetrics& fm = fontMetrics(); - #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) - QSize size(fm.horizontalAdvance(d->Text), QLabel::sizeHint().height()); - #else - QSize size(fm.width(d->Text), QLabel::sizeHint().height()); - #endif + QSize size(fm.width(d->Text), QLabel::sizeHint().height()); return size; } From 12b0182337b29134d8c362e72401115166ea7140 Mon Sep 17 00:00:00 2001 From: Nick D'Ademo Date: Thu, 22 Aug 2019 21:04:02 +0800 Subject: [PATCH 3/7] Use small icon size from QStyle for dock widget tab icon. --- src/DockWidgetTab.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } } From c8d4487a9539c25900b50c6665e00b599a6bf2d2 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 26 Aug 2019 07:58:56 +0200 Subject: [PATCH 4/7] Improved source code documentation, removed empty main.qrc to silence qmake warning --- demo/demo.pro | 1 - demo/main.qrc | 3 - src/DockAreaTabBar.h | 6 + src/DockAreaTitleBar.cpp | 21 +- src/DockAreaTitleBar.h | 11 +- src/DockAreaWidget.cpp | 9 +- src/DockAreaWidget.h | 10 +- src/DockContainerWidget.h | 5 +- src/DockManager.h | 2 +- src/DockOverlay.h | 3 - src/DockSplitter.h | 3 +- src/DockWidgetTab.h | 1 - src/FloatingDockContainer.cpp | 442 +++++++++++++-------------- src/FloatingDockContainer.h | 3 +- src/ads_globals.h | 3 + src/linux/FloatingWidgetTitleBar.cpp | 204 ++++++------- src/linux/FloatingWidgetTitleBar.h | 45 ++- 17 files changed, 397 insertions(+), 375 deletions(-) delete mode 100644 demo/main.qrc 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/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.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/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 From 9bd55cc15a96aafbc11de589be7ba18e885f247c Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Thu, 29 Aug 2019 08:16:19 +0200 Subject: [PATCH 5/7] Fixed broken CMake build --- demo/CMakeLists.txt | 1 - example/example.pro | 1 - 2 files changed, 2 deletions(-) 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/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 From 8e0ea573195b0a899caee87ecac6b12ec342a2be Mon Sep 17 00:00:00 2001 From: githubuser0xFFFF Date: Fri, 30 Aug 2019 21:15:39 +0200 Subject: [PATCH 6/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 53ec8b896a1adfe4fafd2c485bdbec23556a2f5f Mon Sep 17 00:00:00 2001 From: Tibo Clausen Date: Mon, 9 Sep 2019 14:05:37 +0100 Subject: [PATCH 7/7] Replace deprecated function call --- src/ElidingLabel.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ElidingLabel.cpp b/src/ElidingLabel.cpp index 8e6ea56..73b46b4 100644 --- a/src/ElidingLabel.cpp +++ b/src/ElidingLabel.cpp @@ -157,7 +157,11 @@ QSize CElidingLabel::minimumSizeHint() const return QLabel::minimumSizeHint(); } const QFontMetrics &fm = fontMetrics(); - QSize size(fm.width(d->Text.left(2) + "…"), fm.height()); + #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) + QSize size(fm.horizontalAdvance(d->Text.left(2) + "…"), fm.height()); + #else + QSize size(fm.width(d->Text.left(2) + "…"), fm.height()); + #endif return size; } @@ -170,7 +174,11 @@ QSize CElidingLabel::sizeHint() const return QLabel::sizeHint(); } const QFontMetrics& fm = fontMetrics(); - QSize size(fm.width(d->Text), QLabel::sizeHint().height()); + #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) + QSize size(fm.horizontalAdvance(d->Text), QLabel::sizeHint().height()); + #else + QSize size(fm.width(d->Text), QLabel::sizeHint().height()); + #endif return size; }