Merge pull request #1 from XenotriX1337/deprecated_function

Replace deprecated function
This commit is contained in:
Joel Bodenmann 2019-09-09 14:31:19 +02:00 committed by GitHub
commit cdca8c2ac0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 402 additions and 382 deletions

View File

@ -86,7 +86,7 @@ install(TARGETS qtadvanceddocking
ARCHIVE DESTINATION lib COMPONENT library ARCHIVE DESTINATION lib COMPONENT library
) )
target_include_directories(qtadvanceddocking PUBLIC target_include_directories(qtadvanceddocking PUBLIC
$<BUILD_INTERFACE:${ads_INCLUDE}> "$<BUILD_INTERFACE:${ads_INCLUDE}>"
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include>
) )
target_link_libraries(qtadvanceddocking PUBLIC ${ads_LIBS}) target_link_libraries(qtadvanceddocking PUBLIC ${ads_LIBS})

View File

@ -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 featured window docking system similar to what is found in many popular
integrated development environements (IDEs) such as Visual Studio. integrated development environements (IDEs) such as Visual Studio.
Everything is implemented with standard Qt functionality without any 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. styles as much as possible.
This work is based on and inspired by the This work is based on and inspired by the

View File

@ -24,7 +24,6 @@ set(ads_demo_SRCS
main.cpp main.cpp
MainWindow.cpp MainWindow.cpp
mainwindow.ui mainwindow.ui
main.qrc
) )
add_executable(AdvancedDockingSystemDemo WIN32 ${ads_demo_SRCS}) add_executable(AdvancedDockingSystemDemo WIN32 ${ads_demo_SRCS})
if(BUILD_STATIC) if(BUILD_STATIC)

View File

@ -21,7 +21,6 @@ HEADERS += \
FORMS += \ FORMS += \
mainwindow.ui mainwindow.ui
RESOURCES += main.qrc
LIBS += -L$${ADS_OUT_ROOT}/lib LIBS += -L$${ADS_OUT_ROOT}/lib

View File

@ -1,3 +0,0 @@
<RCC>
<qresource prefix="/main"/>
</RCC>

View File

@ -23,7 +23,6 @@ HEADERS += \
FORMS += \ FORMS += \
MainWindow.ui MainWindow.ui
#RESOURCES += main.qrc
LIBS += -L$${ADS_OUT_ROOT}/lib LIBS += -L$${ADS_OUT_ROOT}/lib

View File

@ -44,6 +44,10 @@ class CFloatingDockContainer;
* Custom tabbar implementation for tab area that is shown on top of a * Custom tabbar implementation for tab area that is shown on top of a
* dock area widget. * dock area widget.
* The tabbar displays the tab widgets of the contained dock widgets. * 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 class CDockAreaTabBar : public QScrollArea
{ {
@ -61,6 +65,7 @@ private slots:
protected: protected:
virtual void wheelEvent(QWheelEvent* Event) override; virtual void wheelEvent(QWheelEvent* Event) override;
/** /**
* Stores mouse position to detect dragging * Stores mouse position to detect dragging
*/ */
@ -96,6 +101,7 @@ protected:
public: public:
using Super = QScrollArea; using Super = QScrollArea;
/** /**
* Default Constructor * Default Constructor
*/ */

View File

@ -99,8 +99,9 @@ struct DockAreaTitleBarPrivate
} }
/** /**
* Helper class to set title bar button icons depending on operating system * Helper function to set title bar button icons depending on operating
* and to avoid duplicated code * 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) void setTitleBarButtonIcon(tTileBarButton* Button, QStyle::StandardPixmap StandarPixmap)
{ {
@ -136,14 +137,14 @@ void DockAreaTitleBarPrivate::createButtons()
TabsMenuButton->setPopupMode(QToolButton::InstantPopup); TabsMenuButton->setPopupMode(QToolButton::InstantPopup);
setTitleBarButtonIcon(TabsMenuButton, QStyle::SP_TitleBarUnshadeButton); setTitleBarButtonIcon(TabsMenuButton, QStyle::SP_TitleBarUnshadeButton);
QMenu* TabsMenu = new QMenu(TabsMenuButton); QMenu* TabsMenu = new QMenu(TabsMenuButton);
#ifndef QT_NO_TOOLTIP #ifndef QT_NO_TOOLTIP
TabsMenu->setToolTipsVisible(true); TabsMenu->setToolTipsVisible(true);
#endif #endif
_this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow())); _this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow()));
TabsMenuButton->setMenu(TabsMenu); TabsMenuButton->setMenu(TabsMenu);
#ifndef QT_NO_TOOLTIP #ifndef QT_NO_TOOLTIP
TabsMenuButton->setToolTip(QObject::tr("List all tabs")); TabsMenuButton->setToolTip(QObject::tr("List all tabs"));
#endif #endif
TabsMenuButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); TabsMenuButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
TopLayout->addWidget(TabsMenuButton, 0); TopLayout->addWidget(TabsMenuButton, 0);
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)), _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
@ -154,9 +155,9 @@ void DockAreaTitleBarPrivate::createButtons()
UndockButton = new tTileBarButton(); UndockButton = new tTileBarButton();
UndockButton->setObjectName("undockButton"); UndockButton->setObjectName("undockButton");
UndockButton->setAutoRaise(true); UndockButton->setAutoRaise(true);
#ifndef QT_NO_TOOLTIP #ifndef QT_NO_TOOLTIP
UndockButton->setToolTip(QObject::tr("Detach Group")); UndockButton->setToolTip(QObject::tr("Detach Group"));
#endif #endif
setTitleBarButtonIcon(UndockButton, QStyle::SP_TitleBarNormalButton); setTitleBarButtonIcon(UndockButton, QStyle::SP_TitleBarNormalButton);
UndockButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); UndockButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
TopLayout->addWidget(UndockButton, 0); TopLayout->addWidget(UndockButton, 0);
@ -168,7 +169,7 @@ void DockAreaTitleBarPrivate::createButtons()
CloseButton->setObjectName("closeButton"); CloseButton->setObjectName("closeButton");
CloseButton->setAutoRaise(true); CloseButton->setAutoRaise(true);
setTitleBarButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton); setTitleBarButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton);
#ifndef QT_NO_TOOLTIP #ifndef QT_NO_TOOLTIP
if (testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab)) if (testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
{ {
CloseButton->setToolTip(QObject::tr("Close Active Tab")); CloseButton->setToolTip(QObject::tr("Close Active Tab"));
@ -177,7 +178,7 @@ void DockAreaTitleBarPrivate::createButtons()
{ {
CloseButton->setToolTip(QObject::tr("Close Group")); CloseButton->setToolTip(QObject::tr("Close Group"));
} }
#endif #endif
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
CloseButton->setIconSize(QSize(16, 16)); CloseButton->setIconSize(QSize(16, 16));
TopLayout->addWidget(CloseButton, 0); TopLayout->addWidget(CloseButton, 0);

View File

@ -43,7 +43,9 @@ class CDockAreaWidget;
struct DockAreaTitleBarPrivate; 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 class CDockAreaTitleBar : public QFrame
{ {
@ -61,6 +63,10 @@ private slots:
void showContextMenu(const QPoint& pos); void showContextMenu(const QPoint& pos);
public slots: 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(); void markTabsMenuOutdated();
@ -87,7 +93,8 @@ public:
QAbstractButton* button(TitleBarButton which) const; 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; virtual void setVisible(bool Visible) override;

View File

@ -63,8 +63,11 @@ static const char* const INDEX_PROPERTY = "index";
static const char* const ACTION_PROPERTY = "action"; static const char* const ACTION_PROPERTY = "action";
/** /**
* New dock area layout mimics stack layout but only inserts the current * Internal dock area layout mimics stack layout but only inserts the current
* widget into the internal QLayout object * 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 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) void removeWidget(QWidget* Widget)
{ {

View File

@ -185,12 +185,12 @@ public:
QList<CDockWidget*> dockWidgets() const; QList<CDockWidget*> dockWidgets() const;
/** /**
* Returns the number of dock widgets in this area * Returns the number of open dock widgets in this area
*/ */
int openDockWidgetsCount() const; int openDockWidgetsCount() const;
/** /**
* Returns a list of dock widgets that are not closed * Returns a list of dock widgets that are not closed.
*/ */
QList<CDockWidget*> openedDockWidgets() const; QList<CDockWidget*> openedDockWidgets() const;
@ -236,8 +236,10 @@ public:
* This functions returns the dock widget features of all dock widget in * This functions returns the dock widget features of all dock widget in
* this area. * this area.
* A bitwise and is used to combine the flags of all dock widgets. That * 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 * means, if only one single dock widget does not support a certain flag,
* dock are does not support the 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; CDockWidget::DockWidgetFeatures features() const;

View File

@ -50,7 +50,10 @@ struct FloatingDockContainerPrivate;
/** /**
* Container that manages a number of dock areas with single dock widgets * 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 class ADS_EXPORT CDockContainerWidget : public QFrame
{ {

View File

@ -131,7 +131,7 @@ public:
* If the given parent is a QMainWindow, the dock manager sets itself as the * If the given parent is a QMainWindow, the dock manager sets itself as the
* central widget. * central widget.
* Before you create any dock widgets, you should properly setup the * Before you create any dock widgets, you should properly setup the
* configuration flags via setConfigFlags() * configuration flags via setConfigFlags().
*/ */
CDockManager(QWidget* parent = 0); CDockManager(QWidget* parent = 0);

View File

@ -245,9 +245,6 @@ public:
protected: protected:
virtual void showEvent(QShowEvent* e) override; virtual void showEvent(QShowEvent* e) override;
void setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets); void setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets);
private:
}; // CDockOverlayCross }; // CDockOverlayCross
} // namespace ads } // namespace ads

View File

@ -38,7 +38,8 @@ namespace ads
struct DockSplitterPrivate; struct DockSplitterPrivate;
/** /**
* Splitter used internally instead of QSplitter * Splitter used internally instead of QSplitter with some additional
* fuctionality.
*/ */
class ADS_EXPORT CDockSplitter : public QSplitter class ADS_EXPORT CDockSplitter : public QSplitter
{ {

View File

@ -444,7 +444,7 @@ void CDockWidgetTab::setIcon(const QIcon& Icon)
d->Icon = Icon; d->Icon = Icon;
if (d->IconLabel) 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); d->IconLabel->setVisible(true);
} }
} }

View File

@ -143,7 +143,6 @@ public:
virtual bool event(QEvent *e) override; virtual bool event(QEvent *e) override;
public slots: public slots:
virtual void setVisible(bool visible) override; virtual void setVisible(bool visible) override;

View File

@ -158,9 +158,9 @@ QSize CElidingLabel::minimumSizeHint() const
} }
const QFontMetrics &fm = fontMetrics(); const QFontMetrics &fm = fontMetrics();
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) #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 #else
QSize size(fm.width(d->Text), QLabel::sizeHint().height()); QSize size(fm.width(d->Text.left(2) + ""), fm.height());
#endif #endif
return size; return size;
} }

View File

@ -1,21 +1,20 @@
/******************************************************************************* /*******************************************************************************
** Qt Advanced Docking System ** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler ** Copyright (C) 2017 Uwe Kindler
** **
** This library is free software; you can redistribute it and/or ** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public ** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either ** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version. ** 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, ** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details. ** Lesser General Public License for more details.
** **
** You should have received a copy of the GNU Lesser General Public ** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>. ** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/ ******************************************************************************/
//============================================================================ //============================================================================
/// \file FloatingDockContainer.cpp /// \file FloatingDockContainer.cpp
@ -24,7 +23,6 @@
/// \brief Implementation of CFloatingDockContainer class /// \brief Implementation of CFloatingDockContainer class
//============================================================================ //============================================================================
//============================================================================ //============================================================================
// INCLUDES // INCLUDES
//============================================================================ //============================================================================
@ -50,7 +48,6 @@
#include <xcb/xcb.h> #include <xcb/xcb.h>
#endif #endif
namespace ads namespace ads
{ {
static unsigned int zOrderCounter = 0; static unsigned int zOrderCounter = 0;
@ -59,14 +56,14 @@ static unsigned int zOrderCounter = 0;
*/ */
struct FloatingDockContainerPrivate struct FloatingDockContainerPrivate
{ {
CFloatingDockContainer* _this; CFloatingDockContainer *_this;
CDockContainerWidget* DockContainer; CDockContainerWidget *DockContainer;
unsigned int zOrderIndex = ++zOrderCounter; unsigned int zOrderIndex = ++zOrderCounter;
QPointer<CDockManager> DockManager; QPointer<CDockManager> DockManager;
eDragState DraggingState = DraggingInactive; eDragState DraggingState = DraggingInactive;
QPoint DragStartMousePosition; QPoint DragStartMousePosition;
CDockContainerWidget* DropContainer = nullptr; CDockContainerWidget *DropContainer = nullptr;
CDockAreaWidget* SingleDockArea = nullptr; CDockAreaWidget *SingleDockArea = nullptr;
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
QWidget* MouseEventHandler = nullptr; QWidget* MouseEventHandler = nullptr;
CFloatingWidgetTitleBar* TitleBar = nullptr; CFloatingWidgetTitleBar* TitleBar = nullptr;
@ -75,10 +72,10 @@ struct FloatingDockContainerPrivate
/** /**
* Private data constructor * Private data constructor
*/ */
FloatingDockContainerPrivate(CFloatingDockContainer* _public); FloatingDockContainerPrivate(CFloatingDockContainer *_public);
void titleMouseReleaseEvent(); void titleMouseReleaseEvent();
void updateDropOverlays(const QPoint& GlobalPos); void updateDropOverlays(const QPoint &GlobalPos);
/** /**
* Tests is a certain state is active * Tests is a certain state is active
@ -93,28 +90,25 @@ struct FloatingDockContainerPrivate
DraggingState = StateId; DraggingState = StateId;
} }
void setWindowTitle(const QString& Text) void setWindowTitle(const QString &Text)
{ {
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
TitleBar->setTitle(Text); TitleBar->setTitle(Text);
#else #else
_this->setWindowTitle(Text); _this->setWindowTitle(Text);
#endif #endif
} }
}; };
// struct FloatingDockContainerPrivate // struct FloatingDockContainerPrivate
//============================================================================ //============================================================================
FloatingDockContainerPrivate::FloatingDockContainerPrivate(CFloatingDockContainer* _public) : FloatingDockContainerPrivate::FloatingDockContainerPrivate(
CFloatingDockContainer *_public) :
_this(_public) _this(_public)
{ {
} }
//============================================================================ //============================================================================
void FloatingDockContainerPrivate::titleMouseReleaseEvent() void FloatingDockContainerPrivate::titleMouseReleaseEvent()
{ {
@ -124,25 +118,31 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
return; return;
} }
if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea if (DockManager->dockAreaOverlay()->dropAreaUnderCursor()
|| DockManager->containerOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea) != InvalidDockWidgetArea
|| DockManager->containerOverlay()->dropAreaUnderCursor()
!= InvalidDockWidgetArea)
{ {
// Resize the floating widget to the size of the highlighted drop area // Resize the floating widget to the size of the highlighted drop area
// rectangle // rectangle
CDockOverlay* Overlay = DockManager->containerOverlay(); CDockOverlay *Overlay = DockManager->containerOverlay();
if (!Overlay->dropOverlayRect().isValid()) if (!Overlay->dropOverlayRect().isValid())
{ {
Overlay = DockManager->dockAreaOverlay(); Overlay = DockManager->dockAreaOverlay();
} }
QRect Rect = Overlay->dropOverlayRect(); QRect Rect = Overlay->dropOverlayRect();
int FrameWidth = (_this->frameSize().width() - _this->rect().width()) / 2; int FrameWidth = (_this->frameSize().width() - _this->rect().width())
int TitleBarHeight = _this->frameSize().height() - _this->rect().height() - FrameWidth; / 2;
int TitleBarHeight = _this->frameSize().height()
- _this->rect().height() - FrameWidth;
if (Rect.isValid()) if (Rect.isValid())
{ {
QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft()); QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft());
TopLeft.ry() += TitleBarHeight; 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(); QApplication::processEvents();
} }
DropContainer->dropFloatingWidget(_this, QCursor::pos()); DropContainer->dropFloatingWidget(_this, QCursor::pos());
@ -152,94 +152,94 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
DockManager->dockAreaOverlay()->hideOverlay(); DockManager->dockAreaOverlay()->hideOverlay();
} }
//============================================================================ //============================================================================
void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos) void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
{ {
if (!_this->isVisible() || !DockManager) if (!_this->isVisible() || !DockManager)
{ {
return; return;
} }
auto Containers = DockManager->dockContainers(); auto Containers = DockManager->dockContainers();
CDockContainerWidget* TopContainer = nullptr; CDockContainerWidget *TopContainer = nullptr;
for (auto ContainerWidget : Containers) for (auto ContainerWidget : Containers)
{ {
if (!ContainerWidget->isVisible()) if (!ContainerWidget->isVisible())
{ {
continue; continue;
} }
if (DockContainer == ContainerWidget) if (DockContainer == ContainerWidget)
{ {
continue; continue;
} }
QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos); QPoint MappedPos = ContainerWidget->mapFromGlobal(GlobalPos);
if (ContainerWidget->rect().contains(MappedPos)) if (ContainerWidget->rect().contains(MappedPos))
{ {
if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer)) if (!TopContainer || ContainerWidget->isInFrontOf(TopContainer))
{ {
TopContainer = ContainerWidget; TopContainer = ContainerWidget;
} }
} }
} }
DropContainer = TopContainer; DropContainer = TopContainer;
auto ContainerOverlay = DockManager->containerOverlay(); auto ContainerOverlay = DockManager->containerOverlay();
auto DockAreaOverlay = DockManager->dockAreaOverlay(); auto DockAreaOverlay = DockManager->dockAreaOverlay();
if (!TopContainer) if (!TopContainer)
{ {
ContainerOverlay->hideOverlay(); ContainerOverlay->hideOverlay();
DockAreaOverlay->hideOverlay(); DockAreaOverlay->hideOverlay();
return; return;
} }
int VisibleDockAreas = TopContainer->visibleDockAreaCount(); int VisibleDockAreas = TopContainer->visibleDockAreaCount();
ContainerOverlay->setAllowedAreas(VisibleDockAreas > 1 ? ContainerOverlay->setAllowedAreas(
OuterDockAreas : AllDockAreas); VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas);
DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer); DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer);
ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea); ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea);
auto DockArea = TopContainer->dockAreaAt(GlobalPos); auto DockArea = TopContainer->dockAreaAt(GlobalPos);
if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0) if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0)
{ {
DockAreaOverlay->enableDropPreview(true); DockAreaOverlay->enableDropPreview(true);
DockAreaOverlay->setAllowedAreas((VisibleDockAreas == 1) ? DockAreaOverlay->setAllowedAreas(
NoDockWidgetArea : AllDockAreas); (VisibleDockAreas == 1) ? NoDockWidgetArea : AllDockAreas);
DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea); DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea);
// A CenterDockWidgetArea for the dockAreaOverlay() indicates that // A CenterDockWidgetArea for the dockAreaOverlay() indicates that
// the mouse is in the title bar. If the ContainerArea is valid // the mouse is in the title bar. If the ContainerArea is valid
// then we ignore the dock area of the dockAreaOverlay() and disable // then we ignore the dock area of the dockAreaOverlay() and disable
// the drop preview // the drop preview
if ((Area == CenterDockWidgetArea) && (ContainerArea != InvalidDockWidgetArea)) if ((Area == CenterDockWidgetArea)
{ && (ContainerArea != InvalidDockWidgetArea))
DockAreaOverlay->enableDropPreview(false); {
ContainerOverlay->enableDropPreview(true); DockAreaOverlay->enableDropPreview(false);
} ContainerOverlay->enableDropPreview(true);
else }
{ else
ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area); {
} ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area);
} }
else }
{ else
DockAreaOverlay->hideOverlay(); {
} DockAreaOverlay->hideOverlay();
}
} }
//============================================================================ //============================================================================
CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) : CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
tFloatingWidgetBase(DockManager), tFloatingWidgetBase(DockManager),
d(new FloatingDockContainerPrivate(this)) d(new FloatingDockContainerPrivate(this))
{ {
d->DockManager = DockManager; d->DockManager = DockManager;
d->DockContainer = new CDockContainerWidget(DockManager, this); d->DockContainer = new CDockContainerWidget(DockManager, this);
connect(d->DockContainer, SIGNAL(dockAreasAdded()), this, SLOT(onDockAreasAddedOrRemoved())); connect(d->DockContainer, SIGNAL(dockAreasAdded()), this,
connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this, SLOT(onDockAreasAddedOrRemoved())); SLOT(onDockAreasAddedOrRemoved()));
connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this,
SLOT(onDockAreasAddedOrRemoved()));
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
d->TitleBar = new CFloatingWidgetTitleBar(this); d->TitleBar = new CFloatingWidgetTitleBar(this);
@ -250,26 +250,25 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) :
setTitleBarWidget(d->TitleBar); setTitleBarWidget(d->TitleBar);
connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close())); connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close()));
#else #else
setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint); setWindowFlags(
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom); Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
l->setContentsMargins(0, 0, 0, 0); QBoxLayout *l = new QBoxLayout(QBoxLayout::TopToBottom);
l->setSpacing(0); l->setContentsMargins(0, 0, 0, 0);
setLayout(l); l->setSpacing(0);
l->addWidget(d->DockContainer); setLayout(l);
l->addWidget(d->DockContainer);
#endif #endif
DockManager->registerFloatingWidget(this); DockManager->registerFloatingWidget(this);
// We install an event filter to detect mouse release events because we // We install an event filter to detect mouse release events because we
// do not receive mouse release event if the floating widget is behind // do not receive mouse release event if the floating widget is behind
// the drop overlay cross // the drop overlay cross
qApp->installEventFilter(this); qApp->installEventFilter(this);
} }
//============================================================================ //============================================================================
CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget* DockArea) : CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget *DockArea) :
CFloatingDockContainer(DockArea->dockManager()) CFloatingDockContainer(DockArea->dockManager())
{ {
d->DockContainer->addDockArea(DockArea); d->DockContainer->addDockArea(DockArea);
@ -278,12 +277,11 @@ CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget* DockArea) :
#endif #endif
} }
//============================================================================ //============================================================================
CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) : CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) :
CFloatingDockContainer(DockWidget->dockManager()) CFloatingDockContainer(DockWidget->dockManager())
{ {
d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget); d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
d->TitleBar->enableCloseButton(isClosable()); d->TitleBar->enableCloseButton(isClosable());
#endif #endif
@ -292,7 +290,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) :
//============================================================================ //============================================================================
CFloatingDockContainer::~CFloatingDockContainer() CFloatingDockContainer::~CFloatingDockContainer()
{ {
ADS_PRINT("~CFloatingDockContainer"); ADS_PRINT("~CFloatingDockContainer");
if (d->DockManager) if (d->DockManager)
{ {
d->DockManager->removeFloatingWidget(this); d->DockManager->removeFloatingWidget(this);
@ -300,82 +298,77 @@ CFloatingDockContainer::~CFloatingDockContainer()
delete d; delete d;
} }
//============================================================================ //============================================================================
CDockContainerWidget* CFloatingDockContainer::dockContainer() const CDockContainerWidget* CFloatingDockContainer::dockContainer() const
{ {
return d->DockContainer; return d->DockContainer;
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::changeEvent(QEvent *event) void CFloatingDockContainer::changeEvent(QEvent *event)
{ {
QWidget::changeEvent(event); QWidget::changeEvent(event);
if ((event->type() == QEvent::ActivationChange) && isActiveWindow()) if ((event->type() == QEvent::ActivationChange) && isActiveWindow())
{ {
ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange "); ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange ");
d->zOrderIndex = ++zOrderCounter; d->zOrderIndex = ++zOrderCounter;
return; return;
} }
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::moveEvent(QMoveEvent *event) void CFloatingDockContainer::moveEvent(QMoveEvent *event)
{ {
QWidget::moveEvent(event); QWidget::moveEvent(event);
switch (d->DraggingState) switch (d->DraggingState)
{ {
case DraggingMousePressed: case DraggingMousePressed:
d->setState(DraggingFloatingWidget); d->setState(DraggingFloatingWidget);
d->updateDropOverlays(QCursor::pos()); d->updateDropOverlays(QCursor::pos());
break; break;
case DraggingFloatingWidget: case DraggingFloatingWidget:
d->updateDropOverlays(QCursor::pos()); d->updateDropOverlays(QCursor::pos());
break; break;
default: default:
break; break;
} }
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::closeEvent(QCloseEvent *event) void CFloatingDockContainer::closeEvent(QCloseEvent *event)
{ {
ADS_PRINT("CFloatingDockContainer closeEvent"); ADS_PRINT("CFloatingDockContainer closeEvent");
d->setState(DraggingInactive); d->setState(DraggingInactive);
if (isClosable()) if (isClosable())
{ {
// In Qt version after 5.9.2 there seems to be a bug that causes the // 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 // QWidget::event() function to not receive any NonClientArea mouse
// events anymore after a close/show cycle. The bug is reported here: // events anymore after a close/show cycle. The bug is reported here:
// https://bugreports.qt.io/browse/QTBUG-73295 // https://bugreports.qt.io/browse/QTBUG-73295
// The following code is a workaround for Qt versions > 5.9.2 that seems // The following code is a workaround for Qt versions > 5.9.2 that seems
// to work // to work
// Starting from Qt version 5.12.2 this seems to work again. But // Starting from Qt version 5.12.2 this seems to work again. But
// now the QEvent::NonClientAreaMouseButtonPress function returns always // now the QEvent::NonClientAreaMouseButtonPress function returns always
// Qt::RightButton even if the left button was pressed // Qt::RightButton even if the left button was pressed
#ifndef Q_OS_LINUX #ifndef Q_OS_LINUX
#if (QT_VERSION > QT_VERSION_CHECK(5, 9, 2) && QT_VERSION < QT_VERSION_CHECK(5, 12, 2)) #if (QT_VERSION > QT_VERSION_CHECK(5, 9, 2) && QT_VERSION < QT_VERSION_CHECK(5, 12, 2))
event->ignore(); event->ignore();
this->hide(); this->hide();
#else #else
Super::closeEvent(event); Super::closeEvent(event);
#endif #endif
#else // Q_OS_LINUX #else // Q_OS_LINUX
Super::closeEvent(event); Super::closeEvent(event);
#endif #endif
} }
else else
{ {
event->ignore(); event->ignore();
} }
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::hideEvent(QHideEvent *event) void CFloatingDockContainer::hideEvent(QHideEvent *event)
{ {
@ -389,14 +382,12 @@ void CFloatingDockContainer::hideEvent(QHideEvent *event)
} }
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::showEvent(QShowEvent *event) void CFloatingDockContainer::showEvent(QShowEvent *event)
{ {
Super::showEvent(event); Super::showEvent(event);
} }
//============================================================================ //============================================================================
bool CFloatingDockContainer::event(QEvent *e) bool CFloatingDockContainer::event(QEvent *e)
{ {
@ -412,9 +403,10 @@ bool CFloatingDockContainer::event(QEvent *e)
// It is really great to work around the whole NonClientMouseArea // It is really great to work around the whole NonClientMouseArea
// bugs // bugs
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2)) #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); d->setState(DraggingMousePressed);
} }
#else #else
@ -425,43 +417,43 @@ bool CFloatingDockContainer::event(QEvent *e)
} }
#endif #endif
} }
break; break;
case DraggingMousePressed: case DraggingMousePressed:
switch (e->type()) switch (e->type())
{ {
case QEvent::NonClientAreaMouseButtonDblClick: case QEvent::NonClientAreaMouseButtonDblClick:
ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick"); ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick");
d->setState(DraggingInactive); d->setState(DraggingInactive);
break; break;
case QEvent::Resize: case QEvent::Resize:
// If the first event after the mouse press is a resize event, then // If the first event after the mouse press is a resize event, then
// the user resizes the window instead of dragging it around. // the user resizes the window instead of dragging it around.
// But there is one exception. If the window is maximized, // But there is one exception. If the window is maximized,
// then dragging the window via title bar will cause the widget to // then dragging the window via title bar will cause the widget to
// leave the maximized state. This in turn will trigger a resize event. // 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 // 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 // corner of the window frame or if it was caused by a windows state
// change, we check, if we are not in maximized state. // change, we check, if we are not in maximized state.
if (!isMaximized()) if (!isMaximized())
{ {
d->setState(DraggingInactive); d->setState(DraggingInactive);
} }
break; break;
default: default:
break; break;
} }
break; break;
case DraggingFloatingWidget: case DraggingFloatingWidget:
if (e->type() == QEvent::NonClientAreaMouseButtonRelease) if (e->type() == QEvent::NonClientAreaMouseButtonRelease)
{ {
ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease"); ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease");
d->titleMouseReleaseEvent(); d->titleMouseReleaseEvent();
} }
break; break;
default: default:
break; break;
@ -473,25 +465,24 @@ bool CFloatingDockContainer::event(QEvent *e)
return QWidget::event(e); return QWidget::event(e);
} }
//============================================================================ //============================================================================
bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *event) bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *event)
{ {
Q_UNUSED(watched); Q_UNUSED(watched);
if (event->type() == QEvent::MouseButtonRelease && d->isState(DraggingFloatingWidget)) if (event->type() == QEvent::MouseButtonRelease
&& d->isState(DraggingFloatingWidget))
{ {
ADS_PRINT("FloatingWidget::eventFilter QEvent::MouseButtonRelease"); ADS_PRINT("FloatingWidget::eventFilter QEvent::MouseButtonRelease");
finishDragging(); finishDragging();
d->titleMouseReleaseEvent(); d->titleMouseReleaseEvent();
} }
return false; return false;
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::startFloating(const QPoint& DragStartMousePos, const QSize& Size, void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
eDragState DragState, QWidget* MouseEventHandler) const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
{ {
#ifndef Q_OS_LINUX #ifndef Q_OS_LINUX
Q_UNUSED(MouseEventHandler) Q_UNUSED(MouseEventHandler)
@ -500,89 +491,94 @@ void CFloatingDockContainer::startFloating(const QPoint& DragStartMousePos, cons
d->setState(DragState); d->setState(DragState);
d->DragStartMousePosition = DragStartMousePos; d->DragStartMousePosition = DragStartMousePos;
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
if (DraggingFloatingWidget == DragState) // 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,
setAttribute(Qt::WA_X11NetWmWindowTypeDock, true); // it is always painted in front of the dock overlay and dock overlay cross.
setWindowOpacity(0.6); // and the user will not see the dock overlay. To work around this issue,
d->MouseEventHandler = MouseEventHandler; // the window opacity is set to 0.6 to make the dock overlay visible
if (d->MouseEventHandler) // again. If someone has an idea, how to place the dragged floating widget
{ // behind the dock overlay, then a pull request would be welcome.
d->MouseEventHandler->grabMouse(); if (DraggingFloatingWidget == DragState)
} {
} setAttribute(Qt::WA_X11NetWmWindowTypeDock, true);
setWindowOpacity(0.6);
d->MouseEventHandler = MouseEventHandler;
if (d->MouseEventHandler)
{
d->MouseEventHandler->grabMouse();
}
}
#endif #endif
moveFloating(); moveFloating();
show(); show();
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::moveFloating() void CFloatingDockContainer::moveFloating()
{ {
int BorderSize = (frameSize().width() - size().width()) / 2; int BorderSize = (frameSize().width() - size().width()) / 2;
const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition - QPoint(BorderSize, 0); const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition
move(moveToPos); - QPoint(BorderSize, 0);
move(moveToPos);
} }
//============================================================================ //============================================================================
bool CFloatingDockContainer::isClosable() const bool CFloatingDockContainer::isClosable() const
{ {
return d->DockContainer->features().testFlag(CDockWidget::DockWidgetClosable); return d->DockContainer->features().testFlag(
CDockWidget::DockWidgetClosable);
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::onDockAreasAddedOrRemoved() void CFloatingDockContainer::onDockAreasAddedOrRemoved()
{ {
ADS_PRINT("CFloatingDockContainer::onDockAreasAddedOrRemoved()"); ADS_PRINT("CFloatingDockContainer::onDockAreasAddedOrRemoved()");
auto TopLevelDockArea = d->DockContainer->topLevelDockArea(); auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
if (TopLevelDockArea) if (TopLevelDockArea)
{ {
d->SingleDockArea = TopLevelDockArea; d->SingleDockArea = TopLevelDockArea;
d->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle()); d->setWindowTitle(
d->SingleDockArea->currentDockWidget()->windowTitle());
connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this, connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
SLOT(onDockAreaCurrentChanged(int))); SLOT(onDockAreaCurrentChanged(int)));
} }
else else
{ {
if (d->SingleDockArea) if (d->SingleDockArea)
{ {
disconnect(d->SingleDockArea, SIGNAL(currentChanged(int)), this, disconnect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
SLOT(onDockAreaCurrentChanged(int))); SLOT(onDockAreaCurrentChanged(int)));
d->SingleDockArea = nullptr; d->SingleDockArea = nullptr;
} }
d->setWindowTitle(qApp->applicationDisplayName()); d->setWindowTitle(qApp->applicationDisplayName());
} }
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::updateWindowTitle() void CFloatingDockContainer::updateWindowTitle()
{ {
auto TopLevelDockArea = d->DockContainer->topLevelDockArea(); auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
if (TopLevelDockArea) if (TopLevelDockArea)
{ {
d->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle()); d->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle());
} }
else else
{ {
d->setWindowTitle(qApp->applicationDisplayName()); d->setWindowTitle(qApp->applicationDisplayName());
} }
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::onDockAreaCurrentChanged(int Index) void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
{ {
Q_UNUSED(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)) if (!d->DockContainer->restoreState(Stream, Testing))
{ {
@ -593,33 +589,28 @@ bool CFloatingDockContainer::restoreState(QXmlStreamReader& Stream, bool Testing
return true; return true;
} }
//============================================================================ //============================================================================
bool CFloatingDockContainer::hasTopLevelDockWidget() const bool CFloatingDockContainer::hasTopLevelDockWidget() const
{ {
return d->DockContainer->hasTopLevelDockWidget(); return d->DockContainer->hasTopLevelDockWidget();
} }
//============================================================================ //============================================================================
CDockWidget* CFloatingDockContainer::topLevelDockWidget() const CDockWidget* CFloatingDockContainer::topLevelDockWidget() const
{ {
return d->DockContainer->topLevelDockWidget(); return d->DockContainer->topLevelDockWidget();
} }
//============================================================================ //============================================================================
QList<CDockWidget*> CFloatingDockContainer::dockWidgets() const QList<CDockWidget*> CFloatingDockContainer::dockWidgets() const
{ {
return d->DockContainer->dockWidgets(); return d->DockContainer->dockWidgets();
} }
//============================================================================ //============================================================================
void CFloatingDockContainer::finishDragging() void CFloatingDockContainer::finishDragging()
{ {
ADS_PRINT("CFloatingDockContainer::finishDragging"); ADS_PRINT("CFloatingDockContainer::finishDragging");
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
setAttribute(Qt::WA_X11NetWmWindowTypeDock, false); setAttribute(Qt::WA_X11NetWmWindowTypeDock, false);
setWindowOpacity(1); setWindowOpacity(1);
@ -632,7 +623,6 @@ void CFloatingDockContainer::finishDragging()
#endif #endif
} }
} // namespace ads } // namespace ads
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -60,7 +60,8 @@ class CFloatingWidgetTitleBar;
/** /**
* This implements a floating widget that is a dock container that accepts * 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 * 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 class ADS_EXPORT CFloatingDockContainer : public tFloatingWidgetBase
{ {

View File

@ -45,12 +45,15 @@
#define ADS_EXPORT #define ADS_EXPORT
#endif #endif
// Define ADS_DEBUG_PRINT to enable a lot of debug output
#ifdef ADS_DEBUG_PRINT #ifdef ADS_DEBUG_PRINT
#define ADS_PRINT(s) qDebug() << s #define ADS_PRINT(s) qDebug() << s
#else #else
#define ADS_PRINT(s) #define ADS_PRINT(s)
#endif #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 #define ADS_DEBUG_LEVEL 0
class QSplitter; class QSplitter;

View File

@ -1,21 +1,20 @@
/******************************************************************************* /*******************************************************************************
** Qt Advanced Docking System ** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler ** Copyright (C) 2017 Uwe Kindler
** **
** This library is free software; you can redistribute it and/or ** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public ** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either ** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version. ** 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, ** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details. ** Lesser General Public License for more details.
** **
** You should have received a copy of the GNU Lesser General Public ** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>. ** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/ ******************************************************************************/
//============================================================================ //============================================================================
/// \file FloatingWidgetTitleBar.cpp /// \file FloatingWidgetTitleBar.cpp
@ -48,140 +47,137 @@ namespace ads
using tTabLabel = CElidingLabel; using tTabLabel = CElidingLabel;
using tCloseButton = QPushButton; using tCloseButton = QPushButton;
/** /**
* @brief Private data class of public interface CFloatingWidgetTitleBar * @brief Private data class of public interface CFloatingWidgetTitleBar
*/ */
struct FloatingWidgetTitleBarPrivate struct FloatingWidgetTitleBarPrivate
{ {
CFloatingWidgetTitleBar* _this; ///< public interface class CFloatingWidgetTitleBar *_this; ///< public interface class
QLabel* IconLabel = nullptr; QLabel *IconLabel = nullptr;
tTabLabel* TitleLabel; tTabLabel *TitleLabel;
tCloseButton* CloseButton = nullptr; tCloseButton *CloseButton = nullptr;
CFloatingDockContainer* FloatingWidget = nullptr; CFloatingDockContainer *FloatingWidget = nullptr;
eDragState DragState = DraggingInactive; eDragState DragState = DraggingInactive;
FloatingWidgetTitleBarPrivate(CFloatingWidgetTitleBar* _public) : _this(_public) {} FloatingWidgetTitleBarPrivate(CFloatingWidgetTitleBar *_public) :
_this(_public)
{
}
/** /**
* Creates the complete layout including all controls * Creates the complete layout including all controls
*/ */
void createLayout(); void createLayout();
}; };
//============================================================================ //============================================================================
void FloatingWidgetTitleBarPrivate::createLayout() void FloatingWidgetTitleBarPrivate::createLayout()
{ {
TitleLabel = new tTabLabel(); TitleLabel = new tTabLabel();
TitleLabel->setElideMode(Qt::ElideRight); TitleLabel->setElideMode(Qt::ElideRight);
TitleLabel->setText("DockWidget->windowTitle()"); TitleLabel->setText("DockWidget->windowTitle()");
TitleLabel->setObjectName("floatingTitleLabel"); TitleLabel->setObjectName("floatingTitleLabel");
TitleLabel->setAlignment(Qt::AlignLeft); TitleLabel->setAlignment(Qt::AlignLeft);
CloseButton = new tCloseButton(); CloseButton = new tCloseButton();
CloseButton->setObjectName("floatingTitleCloseButton"); CloseButton->setObjectName("floatingTitleCloseButton");
CloseButton->setFlat(true); 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()));
QFontMetrics fm(TitleLabel->font()); // The standard icons do does not look good on high DPI screens
int Spacing = qRound(fm.height() / 4.0); 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 QFontMetrics fm(TitleLabel->font());
QBoxLayout* Layout = new QBoxLayout(QBoxLayout::LeftToRight); int Spacing = qRound(fm.height() / 4.0);
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); // 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) CFloatingWidgetTitleBar::CFloatingWidgetTitleBar(CFloatingDockContainer *parent) :
: QWidget(parent), QWidget(parent),
d(new FloatingWidgetTitleBarPrivate(this)) d(new FloatingWidgetTitleBarPrivate(this))
{ {
d->FloatingWidget = parent; d->FloatingWidget = parent;
d->createLayout(); d->createLayout();
} }
//============================================================================ //============================================================================
CFloatingWidgetTitleBar::~CFloatingWidgetTitleBar() CFloatingWidgetTitleBar::~CFloatingWidgetTitleBar()
{ {
delete d; delete d;
} }
//============================================================================ //============================================================================
void CFloatingWidgetTitleBar::mousePressEvent(QMouseEvent* ev) void CFloatingWidgetTitleBar::mousePressEvent(QMouseEvent *ev)
{ {
if (ev->button() == Qt::LeftButton) if (ev->button() == Qt::LeftButton)
{ {
d->DragState = DraggingFloatingWidget; d->DragState = DraggingFloatingWidget;
d->FloatingWidget->startDragging(ev->pos(), d->FloatingWidget->size(), this); d->FloatingWidget->startDragging(ev->pos(), d->FloatingWidget->size(),
return; this);
} return;
Super::mousePressEvent(ev); }
Super::mousePressEvent(ev);
} }
//============================================================================ //============================================================================
void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent* ev) void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev)
{ {
d->DragState = DraggingInactive; d->DragState = DraggingInactive;
Super::mouseReleaseEvent(ev); Super::mouseReleaseEvent(ev);
} }
//============================================================================ //============================================================================
void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent* ev) void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev)
{ {
if (!(ev->buttons() & Qt::LeftButton) || DraggingInactive == d->DragState) if (!(ev->buttons() & Qt::LeftButton) || DraggingInactive == d->DragState)
{ {
d->DragState = DraggingInactive; d->DragState = DraggingInactive;
Super::mouseMoveEvent(ev); Super::mouseMoveEvent(ev);
return; return;
} }
// move floating window // move floating window
if (DraggingFloatingWidget == d->DragState) if (DraggingFloatingWidget == d->DragState)
{ {
d->FloatingWidget->moveFloating(); d->FloatingWidget->moveFloating();
Super::mouseMoveEvent(ev); Super::mouseMoveEvent(ev);
return; return;
} }
Super::mouseMoveEvent(ev); Super::mouseMoveEvent(ev);
} }
//============================================================================ //============================================================================
void CFloatingWidgetTitleBar::enableCloseButton(bool Enable) 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 } // namespace ads

View File

@ -37,32 +37,49 @@ class CFloatingDockContainer;
struct FloatingWidgetTitleBarPrivate; 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 class CFloatingWidgetTitleBar : public QWidget
{ {
Q_OBJECT Q_OBJECT
private: private:
FloatingWidgetTitleBarPrivate* d; ///< private data (pimpl) FloatingWidgetTitleBarPrivate *d; ///< private data (pimpl)
protected: protected:
virtual void mousePressEvent(QMouseEvent* ev) override; virtual void mousePressEvent(QMouseEvent *ev) override;
virtual void mouseReleaseEvent(QMouseEvent* ev) override; virtual void mouseReleaseEvent(QMouseEvent *ev) override;
virtual void mouseMoveEvent(QMouseEvent* ev) override; virtual void mouseMoveEvent(QMouseEvent *ev) override;
public: public:
using Super = QWidget; using Super = QWidget;
explicit CFloatingWidgetTitleBar (CFloatingDockContainer *parent = nullptr); explicit CFloatingWidgetTitleBar(CFloatingDockContainer *parent = nullptr);
/** /**
* Virtual Destructor * Virtual Destructor
*/ */
virtual ~CFloatingWidgetTitleBar(); 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: signals:
void closeRequested(); /**
* This signal is emitted, if the close button is clicked.
*/
void closeRequested();
}; };
} // namespace ads } // namespace ads
#endif // FLOATINGWIDGETTITLEBAR_H #endif // FLOATINGWIDGETTITLEBAR_H