diff --git a/.cproject b/.cproject
new file mode 100644
index 0000000..bad5a71
--- /dev/null
+++ b/.cproject
@@ -0,0 +1,313 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mingw32-make
+ -j
+ all
+ false
+ false
+ false
+
+
+ make
+ clean
+ false
+ true
+ false
+
+
+ mingw32-make
+ -j6
+ debug
+ false
+ false
+ false
+
+
+ qmake
+ -recursive ../ads.pro
+
+ true
+ false
+ false
+
+
+ mingw32-make
+ -j4
+ release
+ false
+ false
+ false
+
+
+ mingw32-make
+ -j
+ all
+ false
+ false
+ false
+
+
+ make
+
+ clean
+ false
+ true
+ false
+
+
+ mingw32-make
+ -j6
+ debug
+ false
+ false
+ false
+
+
+ qmake
+ -recursive ../../src/src.pro
+
+ true
+ false
+ false
+
+
+ mingw32-make
+ -j4
+ release
+ false
+ false
+ false
+
+
+ mingw32-make
+ -j
+ all
+ false
+ false
+ false
+
+
+ make
+
+ clean
+ false
+ true
+ false
+
+
+ mingw32-make
+ -j6
+ debug
+ false
+ false
+ false
+
+
+ qmake
+ -recursive ../../demo/demo.pro
+
+ true
+ false
+ false
+
+
+ mingw32-make
+ -j4
+ release
+ false
+ false
+ false
+
+
+ mingw32-make
+ -j
+ all
+ false
+ false
+ false
+
+
+ make
+ clean
+ false
+ true
+ false
+
+
+ mingw32-make
+ -j6
+ debug
+ false
+ false
+ false
+
+
+ qmake
+ -recursive ../../AdvancedDockingSystemDemo/AdvancedDockingSystemDemo.pro
+ true
+ false
+ false
+
+
+ mingw32-make
+ -j4
+ release
+ false
+ false
+ false
+
+
+ mingw32-make
+ -j
+ all
+ false
+ false
+ false
+
+
+ make
+ clean
+ false
+ true
+ false
+
+
+ mingw32-make
+ -j6
+ debug
+ false
+ false
+ false
+
+
+ qmake
+ -recursive ../../AdvancedDockingSystemDemo_v2/AdvancedDockingSystemDemo_v2.pro
+ true
+ false
+ false
+
+
+ mingw32-make
+ -j4
+ release
+ false
+ false
+ false
+
+
+ mingw32-make
+ -j
+ all
+ false
+ false
+ false
+
+
+ make
+ clean
+ false
+ true
+ false
+
+
+ mingw32-make
+ -j6
+ debug
+ false
+ false
+ false
+
+
+ qmake
+ -recursive ../../AdvancedDockingSystem/src.pro
+
+ true
+ false
+ false
+
+
+ mingw32-make
+ -j4
+ release
+ false
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.project b/.project
new file mode 100644
index 0000000..9c7157b
--- /dev/null
+++ b/.project
@@ -0,0 +1,27 @@
+
+
+ QtAdvancedDockingSystem
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
new file mode 100644
index 0000000..a8d9d50
--- /dev/null
+++ b/.settings/language.settings.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ContainerWidget.dat b/ContainerWidget.dat
new file mode 100644
index 0000000..a3c10ea
Binary files /dev/null and b/ContainerWidget.dat differ
diff --git a/MainWindow.dat b/MainWindow.dat
new file mode 100644
index 0000000..1470ba3
Binary files /dev/null and b/MainWindow.dat differ
diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp
index 728d83c..0f57778 100644
--- a/src/DockAreaWidget.cpp
+++ b/src/DockAreaWidget.cpp
@@ -1,717 +1,712 @@
-/*******************************************************************************
-** QtAdcancedDockingSystem
-** Copyright (C) 2017 Uwe Kindler
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program 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 General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockAreaWidget.cpp
-/// \author Uwe Kindler
-/// \date 24.02.2017
-/// \brief Implementation of CDockAreaWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include "DockAreaWidget.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "DockContainerWidget.h"
-#include "DockWidget.h"
-#include "DockWidgetTitleBar.h"
-#include "FloatingDockContainer.h"
-#include "DockManager.h"
-#include "DockOverlay.h"
-
-#include
-
-namespace ads
-{
-static const char* const INDEX_PROPERTY = "index";
-static const char* const ACTION_PROPERTY = "action";
-static const int APPEND = -1;
-
-/**
- * Custom scroll bar implementation for dock area tab bar
- * This scroll area enables floating of a whole dock area including all
- * dock widgets
- */
-class CTabsScrollArea : public QScrollArea
-{
-private:
- QPoint m_DragStartMousePos;
- CDockAreaWidget* m_DockArea;
- CFloatingDockContainer* m_FloatingWidget = nullptr;
-
-public:
- CTabsScrollArea(CDockAreaWidget* parent)
- : QScrollArea(parent),
- m_DockArea(parent)
- {
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
- setFrameStyle(QFrame::NoFrame);
- setWidgetResizable(true);
- setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- }
-
-protected:
- virtual void wheelEvent(QWheelEvent* Event) override
- {
- std::cout << "CTabsScrollArea::wheelEvent" << std::endl;
- Event->accept();
- const int direction = Event->angleDelta().y();
- if (direction < 0)
- {
- horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20);
- }
- else
- {
- horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
- }
- }
-
- /**
- * Stores mouse position to detect dragging
- */
- virtual void mousePressEvent(QMouseEvent* ev) override
- {
- if (ev->button() == Qt::LeftButton)
- {
- ev->accept();
- m_DragStartMousePos = ev->pos();
- return;
- }
- QScrollArea::mousePressEvent(ev);
- }
-
- /**
- * Stores mouse position to detect dragging
- */
- virtual void mouseReleaseEvent(QMouseEvent* ev) override
- {
- if (ev->button() == Qt::LeftButton)
- {
- std::cout << "CTabsScrollArea::mouseReleaseEvent" << std::endl;
- ev->accept();
- m_FloatingWidget = nullptr;
- m_DragStartMousePos = QPoint();
- return;
- }
- QScrollArea::mouseReleaseEvent(ev);
- }
-
- /**
- * Starts floating the complete docking area including all dock widgets,
- * if it is not the last dock area in a floating widget
- */
- virtual void mouseMoveEvent(QMouseEvent* ev) override
- {
- QScrollArea::mouseMoveEvent(ev);
- if (ev->buttons() != Qt::LeftButton)
- {
- return;
- }
-
- if (m_FloatingWidget)
- {
- m_FloatingWidget->moveFloating();
- return;
- }
-
- // If this is the last dock area in a dock container it does not make
- // sense to move it to a new floating widget and leave this one
- // empty
- if (m_DockArea->dockContainer()->isFloating() && m_DockArea->dockContainer()->dockAreaCount() == 1)
- {
- return;
- }
-
- if (!this->geometry().contains(ev->pos()))
- {
- std::cout << "CTabsScrollArea::startFloating" << std::endl;
- startFloating(m_DragStartMousePos);
- auto Overlay = m_DockArea->dockManager()->containerOverlay();
- Overlay->setAllowedAreas(OuterDockAreas);
- }
-
- return;
- }
-
- /**
- * Double clicking the title bar also starts floating of the complete area
- */
- virtual void mouseDoubleClickEvent(QMouseEvent *event) override
- {
- startFloating(event->pos());
- }
-
- /**
- * Starts floating
- */
- void startFloating(const QPoint& Pos)
- {
- QSize Size = m_DockArea->size();
- CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(m_DockArea);
- FloatingWidget->startFloating(Pos, Size);
- m_FloatingWidget = FloatingWidget;
- }
-}; // class CTabsScrollArea
-
-
-/**
- * Private data class of CDockAreaWidget class (pimpl)
- */
-struct DockAreaWidgetPrivate
-{
- CDockAreaWidget* _this;
- QBoxLayout* Layout;
- QFrame* TitleBar;
- QBoxLayout* TopLayout;
- QStackedLayout* ContentsLayout;
- QScrollArea* TabsScrollArea;
- QWidget* TabsContainerWidget;
- QBoxLayout* TabsLayout;
- QPushButton* TabsMenuButton;
- QPushButton* CloseButton;
- int TabsLayoutInitCount;
- CDockManager* DockManager = nullptr;
-
- /**
- * Private data constructor
- */
- DockAreaWidgetPrivate(CDockAreaWidget* _public);
-
- /**
- * Creates the layout for top area with tabs and close button
- */
- void createTabBar();
-
- /**
- * Returns the dock widget with the given index
- */
- CDockWidget* dockWidgetAt(int index)
- {
- return dynamic_cast(ContentsLayout->widget(index));
- }
-
- /**
- * Convenience function to ease title widget access by index
- */
- CDockWidgetTitleBar* titleWidgetAt(int index)
- {
- return dockWidgetAt(index)->titleBar();
- }
-
- /**
- * Adds a tabs menu entry for the given dock widget
- * If menu is 0, a menu entry is added to the menu of the TabsMenuButton
- * member. If menu is a valid menu pointer, the entry will be added to
- * the given menu
- */
- void addTabsMenuEntry(CDockWidget* DockWidget, int Index = -1, QMenu* menu = 0);
-
- /**
- * Returns the tab action of the given dock widget
- */
- QAction* dockWidgetTabAction(CDockWidget* DockWidget) const
- {
- return qvariant_cast(DockWidget->property(ACTION_PROPERTY));
- }
-
- /**
- * Returns the index of the given dock widget
- */
- int dockWidgetIndex(CDockWidget* DockWidget) const
- {
- return DockWidget->property(INDEX_PROPERTY).toInt();
- }
-
- /**
- * Update the tabs menu if dock widget order changed or if dock widget has
- * been removed
- */
- void updateTabsMenu();
-
- /**
- * Updates the tab bar visibility depending on the number of dock widgets
- * in this area
- */
- void updateTabBar();
-};
-// struct DockAreaWidgetPrivate
-
-
-//============================================================================
-DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) :
- _this(_public)
-{
-
-}
-
-
-//============================================================================
-void DockAreaWidgetPrivate::createTabBar()
-{
- TitleBar = new QFrame(_this);
- TitleBar->setObjectName("dockAreaTitleBar");
- TopLayout = new QBoxLayout(QBoxLayout::LeftToRight);
- TopLayout->setContentsMargins(0, 0, 0, 0);
- TopLayout->setSpacing(0);
- TitleBar->setLayout(TopLayout);
- Layout->addWidget(TitleBar);
-
- TabsScrollArea = new CTabsScrollArea(_this);
- TopLayout->addWidget(TabsScrollArea, 1);
-
- TabsContainerWidget = new QWidget();
- TabsContainerWidget->setObjectName("tabsContainerWidget");
- TabsScrollArea->setWidget(TabsContainerWidget);
-
- TabsLayout = new QBoxLayout(QBoxLayout::LeftToRight);
- TabsLayout->setContentsMargins(0, 0, 0, 0);
- TabsLayout->setSpacing(0);
- TabsLayout->addStretch(1);
- TabsContainerWidget->setLayout(TabsLayout);
-
- TabsMenuButton = new QPushButton();
- TabsMenuButton->setObjectName("tabsMenuButton");
- TabsMenuButton->setFlat(true);
- TabsMenuButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton));
- TabsMenuButton->setMaximumWidth(TabsMenuButton->iconSize().width());
- TabsMenuButton->setMenu(new QMenu(TabsMenuButton));
- TopLayout->addWidget(TabsMenuButton, 0);
- _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
- SLOT(onTabsMenuActionTriggered(QAction*)));
-
- CloseButton = new QPushButton();
- CloseButton->setObjectName("closeButton");
- CloseButton->setFlat(true);
- CloseButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
- CloseButton->setToolTip(_this->tr("Close"));
- CloseButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- TopLayout->addWidget(CloseButton, 0);
- _this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked()));
-
- TabsLayoutInitCount = TabsLayout->count();
-}
-
-
-//============================================================================
-void DockAreaWidgetPrivate::updateTabBar()
-{
- CDockContainerWidget* Container = _this->dockContainer();
- if (!Container)
- {
- return;
- }
-
- if (Container->isFloating() && (Container->dockAreaCount() == 1) && (_this->count() == 1))
- {
- TitleBar->setVisible(false);
- }
- else
- {
- TitleBar->setVisible(true);
- }
-}
-
-
-//============================================================================
-void DockAreaWidgetPrivate::addTabsMenuEntry(CDockWidget* DockWidget,
- int Index, QMenu* menu)
-{
- menu = menu ? menu : TabsMenuButton->menu();
- QAction* Action;
- if (Index >= 0 && Index < menu->actions().count())
- {
- Action = new QAction(DockWidget->windowTitle());
- menu->insertAction(menu->actions().at(Index), Action);
- }
- else
- {
- Action = menu->addAction(DockWidget->windowTitle());
- }
- QVariant vAction = QVariant::fromValue(Action);
- DockWidget->setProperty(ACTION_PROPERTY, vAction);
-}
-
-
-//============================================================================
-void DockAreaWidgetPrivate::updateTabsMenu()
-{
- QMenu* menu = TabsMenuButton->menu();
- menu->clear();
- for (int i = 0; i < ContentsLayout->count(); ++i)
- {
- CDockWidget* DockWidget = dockWidgetAt(i);
- addTabsMenuEntry(dockWidgetAt(i), APPEND, menu);
- }
-}
-
-
-//============================================================================
-CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) :
- QFrame(parent),
- d(new DockAreaWidgetPrivate(this))
-{
- d->DockManager = DockManager;
- d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
- d->Layout->setContentsMargins(0, 0, 0, 0);
- d->Layout->setSpacing(0);
- setLayout(d->Layout);
-
- d->createTabBar();
-
- d->ContentsLayout = new QStackedLayout();
- d->ContentsLayout->setContentsMargins(0, 0, 0, 0);
- d->ContentsLayout->setSpacing(0);
- d->Layout->addLayout(d->ContentsLayout, 1);
-}
-
-//============================================================================
-CDockAreaWidget::~CDockAreaWidget()
-{
- std::cout << "~CDockAreaWidget()" << std::endl;
- delete d;
-}
-
-
-//============================================================================
-CDockManager* CDockAreaWidget::dockManager() const
-{
- return d->DockManager;
-}
-
-
-//============================================================================
-CDockContainerWidget* CDockAreaWidget::dockContainer() const
-{
- QWidget* Parent = parentWidget();
- while (Parent)
- {
- CDockContainerWidget* Container = dynamic_cast(Parent);
- if (Container)
- {
- return Container;
- }
- Parent = Parent->parentWidget();
- }
-
- return 0;
-}
-
-
-//============================================================================
-void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
-{
- insertDockWidget(d->ContentsLayout->count(), DockWidget);
-}
-
-
-//============================================================================
-void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
- bool Activate)
-{
- d->ContentsLayout->insertWidget(index, DockWidget);
- DockWidget->titleBar()->setDockAreaWidget(this);
- auto TitleBar = DockWidget->titleBar();
- d->TabsLayout->insertWidget(index, TitleBar);
- TitleBar->show();
- connect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
- DockWidget->setProperty(INDEX_PROPERTY, index);
- if (Activate)
- {
- setCurrentIndex(index);
- }
- d->addTabsMenuEntry(DockWidget, index);
- DockWidget->setDockArea(this);
-}
-
-
-//============================================================================
-void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
-{
- std::cout << "CDockAreaWidget::removeDockWidget" << std::endl;
- d->ContentsLayout->removeWidget(DockWidget);
- auto TitleBar = DockWidget->titleBar();
- TitleBar->hide();
- d->TabsLayout->removeWidget(TitleBar);
- disconnect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
- setCurrentIndex(d->ContentsLayout->currentIndex());
- d->updateTabsMenu();
-
- if (d->ContentsLayout->isEmpty())
- {
- std::cout << "Dock Area empty" << std::endl;
- dockContainer()->removeDockArea(this);
- this->deleteLater();
- }
-
- d->updateTabBar();
- DockWidget->setDockArea(nullptr);
-}
-
-
-//============================================================================
-void CDockAreaWidget::onDockWidgetTitleClicked()
-{
- CDockWidgetTitleBar* TitleWidget = qobject_cast(sender());
- if (!TitleWidget)
- {
- return;
- }
-
- int index = d->TabsLayout->indexOf(TitleWidget);
- setCurrentIndex(index);
-}
-
-
-//============================================================================
-void CDockAreaWidget::onCloseButtonClicked()
-{
- currentDockWidget()->toggleView(false);
-}
-
-
-//============================================================================
-CDockWidget* CDockAreaWidget::currentDockWidget() const
-{
- return dockWidget(currentIndex());
-}
-
-
-//============================================================================
-void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget)
-{
- int Index = tabIndex(DockWidget);
- if (Index < 0)
- {
- return;
- }
- setCurrentIndex(Index);
-}
-
-
-//============================================================================
-void CDockAreaWidget::setCurrentIndex(int index)
-{
- if (index < 0 || index > (d->TabsLayout->count() - 1))
- {
- qWarning() << Q_FUNC_INFO << "Invalid index" << index;
- return;
- }
-
- // Set active TAB and update all other tabs to be inactive
- for (int i = 0; i < d->TabsLayout->count(); ++i)
- {
- QLayoutItem* item = d->TabsLayout->itemAt(i);
- if (!item->widget())
- {
- continue;
- }
-
- auto TitleWidget = dynamic_cast(item->widget());
- if (!TitleWidget)
- {
- continue;
- }
-
- if (i == index)
- {
- TitleWidget->show();
- TitleWidget->setActiveTab(true);
- d->TabsScrollArea->ensureWidgetVisible(TitleWidget);
- auto Features = TitleWidget->dockWidget()->features();
- d->CloseButton->setVisible(Features.testFlag(CDockWidget::DockWidgetClosable));
- }
- else
- {
- TitleWidget->setActiveTab(false);
- }
- }
-
- d->ContentsLayout->setCurrentIndex(index);
- d->ContentsLayout->currentWidget()->show();
- emit currentChanged(index);
-}
-
-
-//============================================================================
-int CDockAreaWidget::currentIndex() const
-{
- return d->ContentsLayout->currentIndex();
-}
-
-
-//============================================================================
-QRect CDockAreaWidget::titleAreaGeometry() const
-{
- return d->TopLayout->geometry();
-}
-
-//============================================================================
-QRect CDockAreaWidget::contentAreaGeometry() const
-{
- return d->ContentsLayout->geometry();
-}
-
-
-//============================================================================
-int CDockAreaWidget::tabIndex(CDockWidget* DockWidget)
-{
- return d->ContentsLayout->indexOf(DockWidget);
-}
-
-
-//============================================================================
-QList CDockAreaWidget::dockWidgets() const
-{
- QList DockWidgetList;
- for (int i = 0; i < d->ContentsLayout->count(); ++i)
- {
- DockWidgetList.append(dockWidget(i));
- }
- return DockWidgetList;
-}
-
-
-//============================================================================
-QList CDockAreaWidget::openDockWidgets() const
-{
- QList DockWidgetList;
- for (int i = 0; i < d->ContentsLayout->count(); ++i)
- {
- CDockWidget* DockWidget = dockWidget(i);
- if (!DockWidget->isClosed())
- {
- DockWidgetList.append(dockWidget(i));
- }
- }
- return DockWidgetList;
-}
-
-
-//============================================================================
-int CDockAreaWidget::indexOfContentByTitlePos(const QPoint& p, QWidget* exclude) const
-{
- for (int i = 0; i < d->ContentsLayout->count(); ++i)
- {
- auto TitleWidget = d->titleWidgetAt(i);
- if (TitleWidget->geometry().contains(p) && (!exclude || TitleWidget != exclude))
- {
- return i;
- }
- }
- return -1;
-}
-
-
-//============================================================================
-int CDockAreaWidget::count() const
-{
- return d->ContentsLayout->count();
-}
-
-
-//============================================================================
-CDockWidget* CDockAreaWidget::dockWidget(int Index) const
-{
- return dynamic_cast(d->ContentsLayout->widget(Index));
-}
-
-
-//============================================================================
-void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
-{
- if (fromIndex >= d->ContentsLayout->count() || fromIndex < 0
- || toIndex >= d->ContentsLayout->count() || toIndex < 0 || fromIndex == toIndex)
- {
- qDebug() << "Invalid index for tab movement" << fromIndex << toIndex;
- d->TabsLayout->update();
- return;
- }
-
- CDockWidget* DockWidget = dockWidget(fromIndex);
-
- // reorder tabs menu action to match new order of contents
- auto Menu = d->TabsMenuButton->menu();
- auto TabsAction = d->dockWidgetTabAction(DockWidget);
- Menu->removeAction(TabsAction);
- if (toIndex >= Menu->actions().count())
- {
- Menu->addAction(TabsAction);
- }
- else
- {
- Menu->insertAction(Menu->actions().at(toIndex), TabsAction);
- }
-
-
- // now reorder contents and title bars
- QLayoutItem* liFrom = nullptr;
- liFrom = d->TabsLayout->takeAt(fromIndex);
- d->TabsLayout->insertItem(toIndex, liFrom);
- liFrom = d->ContentsLayout->takeAt(fromIndex);
- d->ContentsLayout->insertWidget(toIndex, liFrom->widget());
- delete liFrom;
-}
-
-
-//============================================================================
-void CDockAreaWidget::onTabsMenuActionTriggered(QAction* Action)
-{
- int Index = d->TabsMenuButton->menu()->actions().indexOf(Action);
- setCurrentIndex(Index);
-}
-
-
-//============================================================================
-void CDockAreaWidget::updateDockArea()
-{
- d->updateTabBar();
-}
-
-
-//============================================================================
-void CDockAreaWidget::hideEvent(QHideEvent* event)
-{
- QFrame::hideEvent(event);
- emit visibilityChanged(isVisible());
-}
-
-
-//============================================================================
-void CDockAreaWidget::showEvent(QShowEvent* event)
-{
- QFrame::showEvent(event);
- emit visibilityChanged(isVisible());
-}
-
-} // namespace ads
-
-//---------------------------------------------------------------------------
-// EOF DockAreaWidget.cpp
+/*******************************************************************************
+** QtAdcancedDockingSystem
+** Copyright (C) 2017 Uwe Kindler
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockAreaWidget.cpp
+/// \author Uwe Kindler
+/// \date 24.02.2017
+/// \brief Implementation of CDockAreaWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include "DockAreaWidget.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#include "DockContainerWidget.h"
+#include "DockWidget.h"
+#include "DockWidgetTitleBar.h"
+#include "FloatingDockContainer.h"
+#include "DockManager.h"
+#include "DockOverlay.h"
+
+#include
+
+namespace ads
+{
+static const char* const INDEX_PROPERTY = "index";
+static const char* const ACTION_PROPERTY = "action";
+static const int APPEND = -1;
+
+/**
+ * Custom scroll bar implementation for dock area tab bar
+ * This scroll area enables floating of a whole dock area including all
+ * dock widgets
+ */
+class CTabsScrollArea : public QScrollArea
+{
+private:
+ QPoint m_DragStartMousePos;
+ CDockAreaWidget* m_DockArea;
+ CFloatingDockContainer* m_FloatingWidget = nullptr;
+
+public:
+ CTabsScrollArea(CDockAreaWidget* parent)
+ : QScrollArea(parent),
+ m_DockArea(parent)
+ {
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
+ setFrameStyle(QFrame::NoFrame);
+ setWidgetResizable(true);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ }
+
+protected:
+ virtual void wheelEvent(QWheelEvent* Event) override
+ {
+ std::cout << "CTabsScrollArea::wheelEvent" << std::endl;
+ Event->accept();
+ const int direction = Event->angleDelta().y();
+ if (direction < 0)
+ {
+ horizontalScrollBar()->setValue(horizontalScrollBar()->value() + 20);
+ }
+ else
+ {
+ horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
+ }
+ }
+
+ /**
+ * Stores mouse position to detect dragging
+ */
+ virtual void mousePressEvent(QMouseEvent* ev) override
+ {
+ if (ev->button() == Qt::LeftButton)
+ {
+ ev->accept();
+ m_DragStartMousePos = ev->pos();
+ return;
+ }
+ QScrollArea::mousePressEvent(ev);
+ }
+
+ /**
+ * Stores mouse position to detect dragging
+ */
+ virtual void mouseReleaseEvent(QMouseEvent* ev) override
+ {
+ if (ev->button() == Qt::LeftButton)
+ {
+ std::cout << "CTabsScrollArea::mouseReleaseEvent" << std::endl;
+ ev->accept();
+ m_FloatingWidget = nullptr;
+ m_DragStartMousePos = QPoint();
+ return;
+ }
+ QScrollArea::mouseReleaseEvent(ev);
+ }
+
+ /**
+ * Starts floating the complete docking area including all dock widgets,
+ * if it is not the last dock area in a floating widget
+ */
+ virtual void mouseMoveEvent(QMouseEvent* ev) override
+ {
+ QScrollArea::mouseMoveEvent(ev);
+ if (ev->buttons() != Qt::LeftButton)
+ {
+ return;
+ }
+
+ if (m_FloatingWidget)
+ {
+ m_FloatingWidget->moveFloating();
+ return;
+ }
+
+ // If this is the last dock area in a dock container it does not make
+ // sense to move it to a new floating widget and leave this one
+ // empty
+ if (m_DockArea->dockContainer()->isFloating() && m_DockArea->dockContainer()->dockAreaCount() == 1)
+ {
+ return;
+ }
+
+ if (!this->geometry().contains(ev->pos()))
+ {
+ std::cout << "CTabsScrollArea::startFloating" << std::endl;
+ startFloating(m_DragStartMousePos);
+ auto Overlay = m_DockArea->dockManager()->containerOverlay();
+ Overlay->setAllowedAreas(OuterDockAreas);
+ }
+
+ return;
+ }
+
+ /**
+ * Double clicking the title bar also starts floating of the complete area
+ */
+ virtual void mouseDoubleClickEvent(QMouseEvent *event) override
+ {
+ startFloating(event->pos());
+ }
+
+ /**
+ * Starts floating
+ */
+ void startFloating(const QPoint& Pos)
+ {
+ QSize Size = m_DockArea->size();
+ CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(m_DockArea);
+ FloatingWidget->startFloating(Pos, Size);
+ m_FloatingWidget = FloatingWidget;
+ }
+}; // class CTabsScrollArea
+
+
+/**
+ * Private data class of CDockAreaWidget class (pimpl)
+ */
+struct DockAreaWidgetPrivate
+{
+ CDockAreaWidget* _this;
+ QBoxLayout* Layout;
+ QFrame* TitleBar;
+ QBoxLayout* TopLayout;
+ QStackedLayout* ContentsLayout;
+ QScrollArea* TabsScrollArea;
+ QWidget* TabsContainerWidget;
+ QBoxLayout* TabsLayout;
+ QPushButton* TabsMenuButton;
+ QPushButton* CloseButton;
+ int TabsLayoutInitCount;
+ CDockManager* DockManager = nullptr;
+
+ /**
+ * Private data constructor
+ */
+ DockAreaWidgetPrivate(CDockAreaWidget* _public);
+
+ /**
+ * Creates the layout for top area with tabs and close button
+ */
+ void createTabBar();
+
+ /**
+ * Returns the dock widget with the given index
+ */
+ CDockWidget* dockWidgetAt(int index)
+ {
+ return dynamic_cast(ContentsLayout->widget(index));
+ }
+
+ /**
+ * Convenience function to ease title widget access by index
+ */
+ CDockWidgetTitleBar* titleWidgetAt(int index)
+ {
+ return dockWidgetAt(index)->titleBar();
+ }
+
+ /**
+ * Adds a tabs menu entry for the given dock widget
+ * If menu is 0, a menu entry is added to the menu of the TabsMenuButton
+ * member. If menu is a valid menu pointer, the entry will be added to
+ * the given menu
+ */
+ void addTabsMenuEntry(CDockWidget* DockWidget, int Index = -1, QMenu* menu = 0);
+
+ /**
+ * Returns the tab action of the given dock widget
+ */
+ QAction* dockWidgetTabAction(CDockWidget* DockWidget) const
+ {
+ return qvariant_cast(DockWidget->property(ACTION_PROPERTY));
+ }
+
+ /**
+ * Returns the index of the given dock widget
+ */
+ int dockWidgetIndex(CDockWidget* DockWidget) const
+ {
+ return DockWidget->property(INDEX_PROPERTY).toInt();
+ }
+
+ /**
+ * Update the tabs menu if dock widget order changed or if dock widget has
+ * been removed
+ */
+ void updateTabsMenu();
+
+ /**
+ * Updates the tab bar visibility depending on the number of dock widgets
+ * in this area
+ */
+ void updateTabBar();
+};
+// struct DockAreaWidgetPrivate
+
+
+//============================================================================
+DockAreaWidgetPrivate::DockAreaWidgetPrivate(CDockAreaWidget* _public) :
+ _this(_public)
+{
+
+}
+
+
+//============================================================================
+void DockAreaWidgetPrivate::createTabBar()
+{
+ TitleBar = new QFrame(_this);
+ TitleBar->setObjectName("dockAreaTitleBar");
+ TopLayout = new QBoxLayout(QBoxLayout::LeftToRight);
+ TopLayout->setContentsMargins(0, 0, 0, 0);
+ TopLayout->setSpacing(0);
+ TitleBar->setLayout(TopLayout);
+ Layout->addWidget(TitleBar);
+
+ TabsScrollArea = new CTabsScrollArea(_this);
+ TopLayout->addWidget(TabsScrollArea, 1);
+
+ TabsContainerWidget = new QWidget();
+ TabsContainerWidget->setObjectName("tabsContainerWidget");
+ TabsScrollArea->setWidget(TabsContainerWidget);
+
+ TabsLayout = new QBoxLayout(QBoxLayout::LeftToRight);
+ TabsLayout->setContentsMargins(0, 0, 0, 0);
+ TabsLayout->setSpacing(0);
+ TabsLayout->addStretch(1);
+ TabsContainerWidget->setLayout(TabsLayout);
+
+ TabsMenuButton = new QPushButton();
+ TabsMenuButton->setObjectName("tabsMenuButton");
+ TabsMenuButton->setFlat(true);
+ TabsMenuButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton));
+ TabsMenuButton->setMaximumWidth(TabsMenuButton->iconSize().width());
+ TabsMenuButton->setMenu(new QMenu(TabsMenuButton));
+ TopLayout->addWidget(TabsMenuButton, 0);
+ _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
+ SLOT(onTabsMenuActionTriggered(QAction*)));
+
+ CloseButton = new QPushButton();
+ CloseButton->setObjectName("closeButton");
+ CloseButton->setFlat(true);
+ CloseButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
+ CloseButton->setToolTip(_this->tr("Close"));
+ CloseButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ TopLayout->addWidget(CloseButton, 0);
+ _this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked()));
+
+ TabsLayoutInitCount = TabsLayout->count();
+}
+
+
+//============================================================================
+void DockAreaWidgetPrivate::updateTabBar()
+{
+ CDockContainerWidget* Container = _this->dockContainer();
+ if (!Container)
+ {
+ return;
+ }
+
+ if (Container->isFloating() && (Container->dockAreaCount() == 1) && (_this->count() == 1))
+ {
+ TitleBar->setVisible(false);
+ }
+ else
+ {
+ TitleBar->setVisible(true);
+ }
+}
+
+
+//============================================================================
+void DockAreaWidgetPrivate::addTabsMenuEntry(CDockWidget* DockWidget,
+ int Index, QMenu* menu)
+{
+ menu = menu ? menu : TabsMenuButton->menu();
+ QAction* Action;
+ if (Index >= 0 && Index < menu->actions().count())
+ {
+ Action = new QAction(DockWidget->windowTitle());
+ menu->insertAction(menu->actions().at(Index), Action);
+ }
+ else
+ {
+ Action = menu->addAction(DockWidget->windowTitle());
+ }
+ QVariant vAction = QVariant::fromValue(Action);
+ DockWidget->setProperty(ACTION_PROPERTY, vAction);
+}
+
+
+//============================================================================
+void DockAreaWidgetPrivate::updateTabsMenu()
+{
+ QMenu* menu = TabsMenuButton->menu();
+ menu->clear();
+ for (int i = 0; i < ContentsLayout->count(); ++i)
+ {
+ CDockWidget* DockWidget = dockWidgetAt(i);
+ addTabsMenuEntry(dockWidgetAt(i), APPEND, menu);
+ }
+}
+
+
+//============================================================================
+CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) :
+ QFrame(parent),
+ d(new DockAreaWidgetPrivate(this))
+{
+ d->DockManager = DockManager;
+ d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
+ d->Layout->setContentsMargins(0, 0, 0, 0);
+ d->Layout->setSpacing(0);
+ setLayout(d->Layout);
+
+ d->createTabBar();
+
+ d->ContentsLayout = new QStackedLayout();
+ d->ContentsLayout->setContentsMargins(0, 0, 0, 0);
+ d->ContentsLayout->setSpacing(0);
+ d->Layout->addLayout(d->ContentsLayout, 1);
+}
+
+//============================================================================
+CDockAreaWidget::~CDockAreaWidget()
+{
+ std::cout << "~CDockAreaWidget()" << std::endl;
+ delete d;
+}
+
+
+//============================================================================
+CDockManager* CDockAreaWidget::dockManager() const
+{
+ return d->DockManager;
+}
+
+
+//============================================================================
+CDockContainerWidget* CDockAreaWidget::dockContainer() const
+{
+ QWidget* Parent = parentWidget();
+ while (Parent)
+ {
+ CDockContainerWidget* Container = dynamic_cast(Parent);
+ if (Container)
+ {
+ return Container;
+ }
+ Parent = Parent->parentWidget();
+ }
+
+ return 0;
+}
+
+
+//============================================================================
+void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget)
+{
+ insertDockWidget(d->ContentsLayout->count(), DockWidget);
+}
+
+
+//============================================================================
+void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
+ bool Activate)
+{
+ d->ContentsLayout->insertWidget(index, DockWidget);
+ DockWidget->titleBar()->setDockAreaWidget(this);
+ auto TitleBar = DockWidget->titleBar();
+ d->TabsLayout->insertWidget(index, TitleBar);
+ TitleBar->show();
+ connect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
+ connect(DockWidget, SIGNAL(viewToggled(bool)), this, SLOT(onDockWidgetViewToggled(bool)));
+ DockWidget->setProperty(INDEX_PROPERTY, index);
+ if (Activate)
+ {
+ setCurrentIndex(index);
+ }
+ d->addTabsMenuEntry(DockWidget, index);
+ DockWidget->setDockArea(this);
+}
+
+
+//============================================================================
+void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
+{
+ std::cout << "CDockAreaWidget::removeDockWidget" << std::endl;
+ d->ContentsLayout->removeWidget(DockWidget);
+ auto TitleBar = DockWidget->titleBar();
+ TitleBar->hide();
+ d->TabsLayout->removeWidget(TitleBar);
+ disconnect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked()));
+ disconnect(DockWidget, SIGNAL(viewToggled(bool)), this, SLOT(onDockWidgetViewToggled(bool)));
+ setCurrentIndex(d->ContentsLayout->currentIndex());
+ d->updateTabsMenu();
+
+ if (d->ContentsLayout->isEmpty())
+ {
+ std::cout << "Dock Area empty" << std::endl;
+ dockContainer()->removeDockArea(this);
+ this->deleteLater();
+ }
+
+ d->updateTabBar();
+ DockWidget->setDockArea(nullptr);
+}
+
+
+//============================================================================
+void CDockAreaWidget::onDockWidgetTitleClicked()
+{
+ CDockWidgetTitleBar* TitleWidget = qobject_cast(sender());
+ if (!TitleWidget)
+ {
+ return;
+ }
+
+ int index = d->TabsLayout->indexOf(TitleWidget);
+ setCurrentIndex(index);
+}
+
+
+//============================================================================
+void CDockAreaWidget::onCloseButtonClicked()
+{
+ currentDockWidget()->toggleView(false);
+}
+
+
+//============================================================================
+CDockWidget* CDockAreaWidget::currentDockWidget() const
+{
+ return dockWidget(currentIndex());
+}
+
+
+//============================================================================
+void CDockAreaWidget::setCurrentDockWidget(CDockWidget* DockWidget)
+{
+ int Index = tabIndex(DockWidget);
+ if (Index < 0)
+ {
+ return;
+ }
+ setCurrentIndex(Index);
+}
+
+
+//============================================================================
+void CDockAreaWidget::setCurrentIndex(int index)
+{
+ if (index < 0 || index > (d->TabsLayout->count() - 1))
+ {
+ qWarning() << Q_FUNC_INFO << "Invalid index" << index;
+ return;
+ }
+
+ // Set active TAB and update all other tabs to be inactive
+ for (int i = 0; i < d->TabsLayout->count(); ++i)
+ {
+ QLayoutItem* item = d->TabsLayout->itemAt(i);
+ if (!item->widget())
+ {
+ continue;
+ }
+
+ auto TitleWidget = dynamic_cast(item->widget());
+ if (!TitleWidget)
+ {
+ continue;
+ }
+
+ if (i == index)
+ {
+ TitleWidget->show();
+ TitleWidget->setActiveTab(true);
+ d->TabsScrollArea->ensureWidgetVisible(TitleWidget);
+ auto Features = TitleWidget->dockWidget()->features();
+ d->CloseButton->setVisible(Features.testFlag(CDockWidget::DockWidgetClosable));
+ }
+ else
+ {
+ TitleWidget->setActiveTab(false);
+ }
+ }
+
+ d->ContentsLayout->setCurrentIndex(index);
+ d->ContentsLayout->currentWidget()->show();
+ emit currentChanged(index);
+}
+
+
+//============================================================================
+int CDockAreaWidget::currentIndex() const
+{
+ return d->ContentsLayout->currentIndex();
+}
+
+
+//============================================================================
+QRect CDockAreaWidget::titleAreaGeometry() const
+{
+ return d->TopLayout->geometry();
+}
+
+//============================================================================
+QRect CDockAreaWidget::contentAreaGeometry() const
+{
+ return d->ContentsLayout->geometry();
+}
+
+
+//============================================================================
+int CDockAreaWidget::tabIndex(CDockWidget* DockWidget)
+{
+ return d->ContentsLayout->indexOf(DockWidget);
+}
+
+
+//============================================================================
+QList CDockAreaWidget::dockWidgets() const
+{
+ QList DockWidgetList;
+ for (int i = 0; i < d->ContentsLayout->count(); ++i)
+ {
+ DockWidgetList.append(dockWidget(i));
+ }
+ return DockWidgetList;
+}
+
+
+//============================================================================
+QList CDockAreaWidget::openedDockWidgets() const
+{
+ QList DockWidgetList;
+ for (int i = 0; i < d->ContentsLayout->count(); ++i)
+ {
+ CDockWidget* DockWidget = dockWidget(i);
+ if (!DockWidget->isClosed())
+ {
+ DockWidgetList.append(dockWidget(i));
+ }
+ }
+ return DockWidgetList;
+}
+
+
+//============================================================================
+int CDockAreaWidget::indexOfContentByTitlePos(const QPoint& p, QWidget* exclude) const
+{
+ for (int i = 0; i < d->ContentsLayout->count(); ++i)
+ {
+ auto TitleWidget = d->titleWidgetAt(i);
+ if (TitleWidget->geometry().contains(p) && (!exclude || TitleWidget != exclude))
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+//============================================================================
+int CDockAreaWidget::count() const
+{
+ return d->ContentsLayout->count();
+}
+
+
+//============================================================================
+CDockWidget* CDockAreaWidget::dockWidget(int Index) const
+{
+ return dynamic_cast(d->ContentsLayout->widget(Index));
+}
+
+
+//============================================================================
+void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
+{
+ if (fromIndex >= d->ContentsLayout->count() || fromIndex < 0
+ || toIndex >= d->ContentsLayout->count() || toIndex < 0 || fromIndex == toIndex)
+ {
+ qDebug() << "Invalid index for tab movement" << fromIndex << toIndex;
+ d->TabsLayout->update();
+ return;
+ }
+
+ CDockWidget* DockWidget = dockWidget(fromIndex);
+
+ // reorder tabs menu action to match new order of contents
+ auto Menu = d->TabsMenuButton->menu();
+ auto TabsAction = d->dockWidgetTabAction(DockWidget);
+ Menu->removeAction(TabsAction);
+ if (toIndex >= Menu->actions().count())
+ {
+ Menu->addAction(TabsAction);
+ }
+ else
+ {
+ Menu->insertAction(Menu->actions().at(toIndex), TabsAction);
+ }
+
+
+ // now reorder contents and title bars
+ QLayoutItem* liFrom = nullptr;
+ liFrom = d->TabsLayout->takeAt(fromIndex);
+ d->TabsLayout->insertItem(toIndex, liFrom);
+ liFrom = d->ContentsLayout->takeAt(fromIndex);
+ d->ContentsLayout->insertWidget(toIndex, liFrom->widget());
+ delete liFrom;
+}
+
+
+//============================================================================
+void CDockAreaWidget::onTabsMenuActionTriggered(QAction* Action)
+{
+ int Index = d->TabsMenuButton->menu()->actions().indexOf(Action);
+ setCurrentIndex(Index);
+}
+
+
+//============================================================================
+void CDockAreaWidget::updateDockArea()
+{
+ d->updateTabBar();
+}
+
+
+//============================================================================
+void CDockAreaWidget::onDockWidgetViewToggled(bool Open)
+{
+ auto DockWidget = dynamic_cast(sender());
+}
+
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF DockAreaWidget.cpp
diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h
index 332dc5e..d95bc44 100644
--- a/src/DockAreaWidget.h
+++ b/src/DockAreaWidget.h
@@ -1,202 +1,198 @@
-#ifndef DockAreaWidgetH
-#define DockAreaWidgetH
-/*******************************************************************************
-** QtAdcancedDockingSystem
-** Copyright (C) 2017 Uwe Kindler
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program 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 General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockAreaWidget.h
-/// \author Uwe Kindler
-/// \date 24.02.2017
-/// \brief Declaration of CDockAreaWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include
-
-namespace ads
-{
-struct DockAreaWidgetPrivate;
-class CDockManager;
-class CDockContainerWidget;
-class CDockWidget;
-
-/**
- * DockAreaWidget manages multiple instances of DckWidgets.
- * It displays a title tab, which is clickable and will switch to
- * the contents associated to the title when clicked.
- */
-class CDockAreaWidget : public QFrame
-{
- Q_OBJECT
-private:
- DockAreaWidgetPrivate* d; ///< private data (pimpl)
- friend class DockAreaWidgetPrivate;
-
-private slots:
- void onDockWidgetTitleClicked();
- void onTabsMenuActionTriggered(QAction* Action);
- void onCloseButtonClicked();
-
-protected:
- virtual void hideEvent(QHideEvent *) override;
- virtual void showEvent(QShowEvent *) override;
-
-public:
- /**
- * Default Constructor
- */
- CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent);
-
- /**
- * Virtual Destructor
- */
- virtual ~CDockAreaWidget();
-
- /**
- * Returns the dock manager object this dock area belongs to
- */
- CDockManager* dockManager() const;
-
- /**
- * Returns the dock container widget this dock area widget belongs to or 0
- * if there is no
- */
- CDockContainerWidget* dockContainer() const;
-
- /**
- * Inserts a dock widget into dock area.
- * All dockwidgets in the dock area tabified in a stacked layout with tabs.
- * The index indicates the index of the new dockwidget in the tabbar and
- * in the stacked layout. If the Activate parameter is true, the new
- * DockWidget will be the active one in the stacked layout
- */
- void insertDockWidget(int index, CDockWidget* DockWidget, bool Activate = true);
-
- /**
- * Add a new dock widget to dock area.
- * All dockwidgets in the dock area tabified in a stacked layout with tabs
- */
- void addDockWidget(CDockWidget* DockWidget);
-
- /**
- * Removes the given dock widget from the dock area
- */
- void removeDockWidget(CDockWidget* DockWidget);
-
- /**
- * Returns the rectangle of the title area
- */
- QRect titleAreaGeometry() const;
-
- /**
- * Returns the rectangle of the content
- */
- QRect contentAreaGeometry() const;
-
- /**
- * Returns the tab index of the given DockWidget
- */
- int tabIndex(CDockWidget* DockWidget);
-
- /**
- * Returns the index of contents of the title widget that is located at
- * mouse position pos
- */
- int indexOfContentByTitlePos(const QPoint& pos, QWidget* exclude = nullptr) const;
-
- /**
- * Returns a list of all dock widgets in this dock area.
- * This list contains open and closed dock widgets.
- */
- QList dockWidgets() const;
-
- /**
- * Returns a list of dock widgets that are not closed
- */
- QList openDockWidgets() const;
-
- /**
- * Returns the number of dock widgets in this area
- */
- int count() const;
-
- /**
- * Returns a dock widget by its index
- */
- CDockWidget* dockWidget(int Index) const;
-
- /**
- * Reorder the index position of DockWidget at fromIndx to toIndex.
- */
- void reorderDockWidget(int fromIndex, int toIndex);
-
- /**
- * Returns the index of the current active dock widget
- */
- int currentIndex() const;
-
- /**
- * Returns the current active dock widget
- */
- CDockWidget* currentDockWidget() const;
-
- /**
- * Shows the tab with tghe given dock widget
- */
- void setCurrentDockWidget(CDockWidget* DockWidget);
-
-public slots:
- /**
- * This sets the index position of the current tab page.
- */
- void setCurrentIndex(int index);
-
- /**
- * Updates the dock area layout and components visibility
- */
- void updateDockArea();
-
-signals:
- /**
- * This signal is emitted when user clicks on a tab at an index.
- */
- void tabBarClicked(int index);
-
- /**
- * This signal is emitted when the tab bar's current tab changes. The new
- * current has the given index, or -1 if there isn't a new one
- * @param index
- */
- void currentChanged(int index);
-
- /**
- * This signal is emitted if a dock areas visibility changed.
- * The visibility changes, if the last dock widget in a dock area is closed
- * or if one dock widget in a dock area with only closed dock widgets
- * becomes visible
- */
- void visibilityChanged(bool Visible);
-}; // class DockAreaWidget
-}
- // namespace ads
-//-----------------------------------------------------------------------------
-#endif // DockAreaWidgetH
+#ifndef DockAreaWidgetH
+#define DockAreaWidgetH
+/*******************************************************************************
+** QtAdcancedDockingSystem
+** Copyright (C) 2017 Uwe Kindler
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockAreaWidget.h
+/// \author Uwe Kindler
+/// \date 24.02.2017
+/// \brief Declaration of CDockAreaWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include
+
+namespace ads
+{
+struct DockAreaWidgetPrivate;
+class CDockManager;
+class CDockContainerWidget;
+class CDockWidget;
+
+/**
+ * DockAreaWidget manages multiple instances of DckWidgets.
+ * It displays a title tab, which is clickable and will switch to
+ * the contents associated to the title when clicked.
+ */
+class CDockAreaWidget : public QFrame
+{
+ Q_OBJECT
+private:
+ DockAreaWidgetPrivate* d; ///< private data (pimpl)
+ friend class DockAreaWidgetPrivate;
+
+private slots:
+ void onDockWidgetTitleClicked();
+ void onTabsMenuActionTriggered(QAction* Action);
+ void onCloseButtonClicked();
+ void onDockWidgetViewToggled(bool Open);
+
+public:
+ /**
+ * Default Constructor
+ */
+ CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent);
+
+ /**
+ * Virtual Destructor
+ */
+ virtual ~CDockAreaWidget();
+
+ /**
+ * Returns the dock manager object this dock area belongs to
+ */
+ CDockManager* dockManager() const;
+
+ /**
+ * Returns the dock container widget this dock area widget belongs to or 0
+ * if there is no
+ */
+ CDockContainerWidget* dockContainer() const;
+
+ /**
+ * Inserts a dock widget into dock area.
+ * All dockwidgets in the dock area tabified in a stacked layout with tabs.
+ * The index indicates the index of the new dockwidget in the tabbar and
+ * in the stacked layout. If the Activate parameter is true, the new
+ * DockWidget will be the active one in the stacked layout
+ */
+ void insertDockWidget(int index, CDockWidget* DockWidget, bool Activate = true);
+
+ /**
+ * Add a new dock widget to dock area.
+ * All dockwidgets in the dock area tabified in a stacked layout with tabs
+ */
+ void addDockWidget(CDockWidget* DockWidget);
+
+ /**
+ * Removes the given dock widget from the dock area
+ */
+ void removeDockWidget(CDockWidget* DockWidget);
+
+ /**
+ * Returns the rectangle of the title area
+ */
+ QRect titleAreaGeometry() const;
+
+ /**
+ * Returns the rectangle of the content
+ */
+ QRect contentAreaGeometry() const;
+
+ /**
+ * Returns the tab index of the given DockWidget
+ */
+ int tabIndex(CDockWidget* DockWidget);
+
+ /**
+ * Returns the index of contents of the title widget that is located at
+ * mouse position pos
+ */
+ int indexOfContentByTitlePos(const QPoint& pos, QWidget* exclude = nullptr) const;
+
+ /**
+ * Returns a list of all dock widgets in this dock area.
+ * This list contains open and closed dock widgets.
+ */
+ QList dockWidgets() const;
+
+ /**
+ * Returns a list of dock widgets that are not closed
+ */
+ QList openedDockWidgets() const;
+
+ /**
+ * Returns the number of dock widgets in this area
+ */
+ int count() const;
+
+ /**
+ * Returns a dock widget by its index
+ */
+ CDockWidget* dockWidget(int Index) const;
+
+ /**
+ * Reorder the index position of DockWidget at fromIndx to toIndex.
+ */
+ void reorderDockWidget(int fromIndex, int toIndex);
+
+ /**
+ * Returns the index of the current active dock widget
+ */
+ int currentIndex() const;
+
+ /**
+ * Returns the current active dock widget
+ */
+ CDockWidget* currentDockWidget() const;
+
+ /**
+ * Shows the tab with tghe given dock widget
+ */
+ void setCurrentDockWidget(CDockWidget* DockWidget);
+
+public slots:
+ /**
+ * This sets the index position of the current tab page.
+ */
+ void setCurrentIndex(int index);
+
+ /**
+ * Updates the dock area layout and components visibility
+ */
+ void updateDockArea();
+
+signals:
+ /**
+ * This signal is emitted when user clicks on a tab at an index.
+ */
+ void tabBarClicked(int index);
+
+ /**
+ * This signal is emitted when the tab bar's current tab changes. The new
+ * current has the given index, or -1 if there isn't a new one
+ * @param index
+ */
+ void currentChanged(int index);
+
+ /**
+ * This signal is emitted if the dock area is closed or opened.
+ * The dock area will be closed, if all dock widgets in the dock area are
+ * closed and will be opened, when the first dock widget is opened
+ */
+ void viewToggled(bool Open);
+}; // class DockAreaWidget
+}
+ // namespace ads
+//-----------------------------------------------------------------------------
+#endif // DockAreaWidgetH
diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp
index 8df425d..21743d2 100644
--- a/src/DockContainerWidget.cpp
+++ b/src/DockContainerWidget.cpp
@@ -1,594 +1,610 @@
-/*******************************************************************************
-** QtAdcancedDockingSystem
-** Copyright (C) 2017 Uwe Kindler
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program 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 General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockContainerWidget.cpp
-/// \author Uwe Kindler
-/// \date 24.02.2017
-/// \brief Implementation of CDockContainerWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include "DockContainerWidget.h"
-
-#include
-#include
-#include
-#include
-#include
-
-#include "DockManager.h"
-#include "DockAreaWidget.h"
-#include "DockWidget.h"
-#include "FloatingDockContainer.h"
-#include "DockOverlay.h"
-#include "ads_globals.h"
-
-#include
-
-namespace ads
-{
-static unsigned int zOrderCounter = 0;
-
-/**
- * Helper function to ease insertion of dock area into splitter
- */
-static void insertWidgetIntoSplitter(QSplitter* Splitter, QWidget* widget, bool Append)
-{
- if (Append)
- {
- Splitter->addWidget(widget);
- }
- else
- {
- Splitter->insertWidget(0, widget);
- }
-}
-
-/**
- * Private data class of CDockContainerWidget class (pimpl)
- */
-struct DockContainerWidgetPrivate
-{
- CDockContainerWidget* _this;
- QPointer DockManager;
- unsigned int zOrderIndex = 0;
- QList DockAreas;
- QGridLayout* Layout = nullptr;
- bool isFloating = false;
-
- /**
- * Private data constructor
- */
- DockContainerWidgetPrivate(CDockContainerWidget* _public);
-
- /**
- * Adds dock widget to container and returns the dock area that contains
- * the inserted dock widget
- */
- CDockAreaWidget* dockWidgetIntoContainer(DockWidgetArea area, CDockWidget* Dockwidget);
-
- /**
- * Adds dock widget to a existing DockWidgetArea
- */
- CDockAreaWidget* dockWidgetIntoDockArea(DockWidgetArea area, CDockWidget* Dockwidget,
- CDockAreaWidget* TargetDockArea);
-
- /**
- * Add dock area to this container
- */
- void addDockArea(CDockAreaWidget* NewDockWidget, DockWidgetArea area = CenterDockWidgetArea);
-
- /**
- * Drop floating widget into container
- */
- void dropIntoContainer(CFloatingDockContainer* FloatingWidget, DockWidgetArea area);
-
- /**
- * Drop floating widget into dock area
- */
- void dropIntoSection(CFloatingDockContainer* FloatingWidget,
- CDockAreaWidget* TargetArea, DockWidgetArea area);
-
- /**
- * Adds new dock areas to the internal dock area list
- */
- void addDockAreasToList(const QList NewDockAreas);
-}; // struct DockContainerWidgetPrivate
-
-
-//============================================================================
-DockContainerWidgetPrivate::DockContainerWidgetPrivate(CDockContainerWidget* _public) :
- _this(_public)
-{
-
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* FloatingWidget,
- DockWidgetArea area)
-{
- auto InsertParam = internal::dockAreaInsertParameters(area);
- auto NewDockAreas = FloatingWidget->dockContainer()->findChildren(
- QString(), Qt::FindChildrenRecursively);
- QSplitter* OldSplitter = nullptr;
-
- // If the container already contains dock areas, then we need to ensure that
- // we have a splitter with an orientation that matches the orientation of
- // the current drop action
- if (!DockAreas.isEmpty())
- {
- OldSplitter = _this->findChild(QString(), Qt::FindDirectChildrenOnly);
- // First replace the dock widget with a splitter
- if (DockAreas.count() == 1)
- {
- auto DockArea = dynamic_cast(Layout->itemAtPosition(0, 0)->widget());
- QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
- Layout->replaceWidget(DockArea, NewSplitter);
- NewSplitter->addWidget(DockArea);
- OldSplitter = NewSplitter;
- }
- else if (OldSplitter->orientation() != InsertParam.orientation())
- {
- QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
- QLayoutItem* li = Layout->replaceWidget(OldSplitter, NewSplitter);
- NewSplitter->addWidget(OldSplitter);
- OldSplitter = NewSplitter;
- }
- }
-
- // Now we can insert the floating widget content into this container
- auto Widget = FloatingWidget->dockContainer()->findChild(QString(), Qt::FindDirectChildrenOnly);
- auto FloatingSplitter = dynamic_cast(Widget);
- if (DockAreas.isEmpty())
- {
- auto Widget = FloatingWidget->dockContainer()->findChild(QString(), Qt::FindDirectChildrenOnly);
- Layout->addWidget(Widget, 0, 0);
- }
- else if (!FloatingSplitter)
- {
- insertWidgetIntoSplitter(OldSplitter, Widget, InsertParam.append());
- }
- else if (FloatingSplitter->orientation() == InsertParam.orientation())
- {
- while (FloatingSplitter->count())
- {
- insertWidgetIntoSplitter(OldSplitter, FloatingSplitter->widget(0), InsertParam.append());
- }
- }
- else
- {
- insertWidgetIntoSplitter(OldSplitter, FloatingSplitter, InsertParam.append());
- }
-
- addDockAreasToList(NewDockAreas);
- FloatingWidget->deleteLater();
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* FloatingWidget,
- CDockAreaWidget* TargetArea, DockWidgetArea area)
-{
- CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
- if (area == CenterDockWidgetArea)
- {
- auto NewDockWidgets = FloatingContainer->findChildren(
- QString(), Qt::FindChildrenRecursively);
- for (auto DockWidget : NewDockWidgets)
- {
- TargetArea->insertDockWidget(0, DockWidget, false);
- }
- TargetArea->setCurrentIndex(0); // make the topmost widget active
- FloatingWidget->deleteLater();
- TargetArea->updateDockArea();
- return;
- }
-
- auto InsertParam = internal::dockAreaInsertParameters(area);
- auto NewDockAreas = FloatingWidget->dockContainer()->findChildren(
- QString(), Qt::FindChildrenRecursively);
- QSplitter* TargetAreaSplitter = internal::findParent(TargetArea);
-
- if (!TargetAreaSplitter)
- {
- QSplitter* Splitter = internal::newSplitter(InsertParam.orientation());
- Layout->replaceWidget(TargetArea, Splitter);
- Splitter->addWidget(TargetArea);
- TargetAreaSplitter = Splitter;
- }
-
- int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
- auto Widget = FloatingWidget->dockContainer()->findChild(QString(), Qt::FindDirectChildrenOnly);
- auto FloatingSplitter = dynamic_cast(Widget);
-
- if (TargetAreaSplitter->orientation() == InsertParam.orientation())
- {
- if (!FloatingSplitter || FloatingSplitter->orientation() != InsertParam.orientation())
- {
- TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), Widget);
- }
- else
- {
- int InsertIndex = AreaIndex + InsertParam.insertOffset();
- while (FloatingSplitter->count())
- {
- TargetAreaSplitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0));
- }
- }
- }
- else
- {
- QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
- if (!FloatingSplitter || FloatingSplitter->orientation() != InsertParam.orientation())
- {
- NewSplitter->addWidget(Widget);
- }
- else
- {
- while (FloatingSplitter->count())
- {
- NewSplitter->addWidget(FloatingSplitter->widget(0));
- }
- }
-
- insertWidgetIntoSplitter(NewSplitter, TargetArea, !InsertParam.append());
- TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter);
- }
-
- FloatingWidget->deleteLater();
- addDockAreasToList(NewDockAreas);
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::addDockAreasToList(const QList NewDockAreas)
-{
- int CountBefore = DockAreas.count();
- int NewAreaCount = NewDockAreas.count();
- DockAreas.append(NewDockAreas);
-
- // We need to ensure, that the dock area title bar is visible. The title bar
- // is invisible, if the dock are is a single dock area in a floating widget.
- if (1 == CountBefore)
- {
- DockAreas.at(0)->updateDockArea();
- }
-
- if (1 == NewAreaCount)
- {
- DockAreas.last()->updateDockArea();
- }
-
- emit _this->dockAreasAdded();
-}
-
-
-//============================================================================
-CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoContainer(DockWidgetArea area,
- CDockWidget* Dockwidget)
-{
- CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
- NewDockArea->addDockWidget(Dockwidget);
- addDockArea(NewDockArea, area);
- return NewDockArea;
-}
-
-
-//============================================================================
-void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockWidgetArea area)
-{
- auto InsertParam = internal::dockAreaInsertParameters(area);
- if (DockAreas.isEmpty())
- {
- Layout->addWidget(NewDockArea, 0, 0);
- }
- else if (DockAreas.count() == 1)
- {
- QSplitter* Splitter = internal::newSplitter(InsertParam.orientation());
- auto DockArea = dynamic_cast(Layout->itemAtPosition(0, 0)->widget());
- Layout->replaceWidget(DockArea, Splitter);
- Splitter->addWidget(DockArea);
- insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append());
- }
- else
- {
- QSplitter* Splitter = _this->findChild(QString(), Qt::FindDirectChildrenOnly);
- if (Splitter->orientation() == InsertParam.orientation())
- {
- insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append());
- }
- else
- {
- QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
- if (InsertParam.append())
- {
- QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
- NewSplitter->addWidget(Splitter);
- NewSplitter->addWidget(NewDockArea);
- delete li;
- }
- else
- {
- NewSplitter->addWidget(NewDockArea);
- QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
- NewSplitter->addWidget(Splitter);
- delete li;
- }
- }
- }
-
- DockAreas.append(NewDockArea);
- NewDockArea->updateDockArea();
- emit _this->dockAreasAdded();
-}
-
-
-//============================================================================
-CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoDockArea(DockWidgetArea area,
- CDockWidget* Dockwidget, CDockAreaWidget* TargetDockArea)
-{
- if (CenterDockWidgetArea == area)
- {
- TargetDockArea->addDockWidget(Dockwidget);
- return TargetDockArea;
- }
-
- CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
- NewDockArea->addDockWidget(Dockwidget);
- auto InsertParam = internal::dockAreaInsertParameters(area);
- if (DockAreas.count() == 1)
- {
- QSplitter* Splitter = internal::newSplitter(InsertParam.orientation());
- auto DockArea = dynamic_cast(Layout->itemAtPosition(0, 0)->widget());
- Layout->replaceWidget(DockArea, Splitter);
- Splitter->addWidget(DockArea);
- insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append());
- }
- else
- {
- QSplitter* TargetAreaSplitter = internal::findParent(TargetDockArea);
- int index = TargetAreaSplitter ->indexOf(TargetDockArea);
- if (TargetAreaSplitter->orientation() == InsertParam.orientation())
- {
- std::cout << "TargetAreaSplitter->orientation() == InsertParam.orientation()" << std::endl;
- TargetAreaSplitter->insertWidget(index + InsertParam.insertOffset(), NewDockArea);
- }
- else
- {
- std::cout << "TargetAreaSplitter->orientation() != InsertParam.orientation()" << std::endl;
- QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
- NewSplitter->addWidget(TargetDockArea);
- insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
- TargetAreaSplitter->insertWidget(index, NewSplitter);
- }
- }
-
- DockAreas.append(NewDockArea);
- emit _this->dockAreasAdded();
- return NewDockArea;
-}
-
-
-//============================================================================
-CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *parent) :
- QFrame(parent),
- d(new DockContainerWidgetPrivate(this))
-{
- d->isFloating = dynamic_cast(parent) != 0;
-
- //setStyleSheet("background: green;");
- d->DockManager = DockManager;
- if (DockManager != this)
- {
- d->DockManager->registerDockContainer(this);
- }
-
- d->Layout = new QGridLayout();
- d->Layout->setContentsMargins(0, 1, 0, 1);
- d->Layout->setSpacing(0);
- setLayout(d->Layout);
-}
-
-//============================================================================
-CDockContainerWidget::~CDockContainerWidget()
-{
- if (d->DockManager)
- {
- d->DockManager->removeDockContainer(this);
- }
- delete d;
-}
-
-
-//============================================================================
-CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
- CDockAreaWidget* DockAreaWidget)
-{
- CDockAreaWidget* OldDockArea = Dockwidget->dockAreaWidget();
- if (OldDockArea)
- {
- OldDockArea->removeDockWidget(Dockwidget);
- }
-
- Dockwidget->setDockManager(d->DockManager);
- if (DockAreaWidget)
- {
- return d->dockWidgetIntoDockArea(area, Dockwidget, DockAreaWidget);
- }
- else
- {
- return d->dockWidgetIntoContainer(area, Dockwidget);
- }
-}
-
-
-//============================================================================
-unsigned int CDockContainerWidget::zOrderIndex() const
-{
- return d->zOrderIndex;
-}
-
-
-//============================================================================
-bool CDockContainerWidget::isInFrontOf(CDockContainerWidget* Other) const
-{
- return this->zOrderIndex() > Other->zOrderIndex();
-}
-
-
-//============================================================================
-bool CDockContainerWidget::event(QEvent *e)
-{
- bool Result = QWidget::event(e);
- if (e->type() == QEvent::WindowActivate)
- {
- d->zOrderIndex = ++zOrderCounter;
- }
- else if (e->type() == QEvent::Show && !d->zOrderIndex)
- {
- d->zOrderIndex = ++zOrderCounter;
- }
-
- return Result;
-}
-
-
-//============================================================================
-void CDockContainerWidget::addDockArea(CDockAreaWidget* DockAreaWidget,
- DockWidgetArea area)
-{
- CDockContainerWidget* Container = DockAreaWidget->dockContainer();
- if (Container && Container != this)
- {
- Container->removeDockArea(DockAreaWidget);
- }
-
- d->addDockArea(DockAreaWidget);
-}
-
-
-//============================================================================
-void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
-{
- std::cout << "CDockContainerWidget::removeDockArea" << std::endl;
- d->DockAreas.removeAll(area);
- QSplitter* Splitter = internal::findParent(area);
- area->setParent(0);
- if (!(Splitter && Splitter->count() == 1))
- {
- emit dockAreasRemoved();
- return;
- }
-
- // It the splitter contains only one single widget, then we do not need
- // it anymore and can replace it with its content
- std::cout << "Replacing splitter with content" << std::endl;
- QWidget* widget = Splitter->widget(0);
- widget->setParent(this);
- QSplitter* ParentSplitter = internal::findParent(Splitter);
- if (ParentSplitter)
- {
- internal::replaceSplitterWidget(ParentSplitter, Splitter, widget);
- }
- else
- {
- d->Layout->replaceWidget(Splitter, widget);
- }
- delete Splitter;
- emit dockAreasRemoved();
-}
-
-
-//============================================================================
-CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const
-{
- for (const auto& DockArea : d->DockAreas)
- {
- if (DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos)))
- {
- return DockArea;
- }
- }
-
- return 0;
-}
-
-
-//============================================================================
-CDockAreaWidget* CDockContainerWidget::dockArea(int Index) const
-{
- return (Index < dockAreaCount()) ? d->DockAreas[Index] : 0;
-}
-
-
-//============================================================================
-bool CDockContainerWidget::isFloating() const
-{
- return d->isFloating;
-}
-
-
-//============================================================================
-int CDockContainerWidget::dockAreaCount() const
-{
- return d->DockAreas.count();
-}
-
-
-//============================================================================
-void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget,
- const QPoint& TargetPos)
-{
- std::cout << "CDockContainerWidget::dropFloatingWidget" << std::endl;
- CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
- auto dropArea = InvalidDockWidgetArea;
- if (DockArea)
- {
- auto dropOverlay = d->DockManager->dockAreaOverlay();
- dropOverlay->setAllowedAreas(AllDockAreas);
- dropArea = dropOverlay->showOverlay(DockArea);
- if (dropArea != InvalidDockWidgetArea)
- {
- std::cout << "Dock Area Drop Content: " << dropArea << std::endl;
- d->dropIntoSection(FloatingWidget, DockArea, dropArea);
- }
- }
-
- // mouse is over container
- if (InvalidDockWidgetArea == dropArea)
- {
- dropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
- std::cout << "Container Drop Content: " << dropArea << std::endl;
- if (dropArea != InvalidDockWidgetArea)
- {
- d->dropIntoContainer(FloatingWidget, dropArea);
- }
- }
-}
-
-
-} // namespace ads
-
-//---------------------------------------------------------------------------
-// EOF DockContainerWidget.cpp
+/*******************************************************************************
+** QtAdcancedDockingSystem
+** Copyright (C) 2017 Uwe Kindler
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockContainerWidget.cpp
+/// \author Uwe Kindler
+/// \date 24.02.2017
+/// \brief Implementation of CDockContainerWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include "DockContainerWidget.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "DockManager.h"
+#include "DockAreaWidget.h"
+#include "DockWidget.h"
+#include "FloatingDockContainer.h"
+#include "DockOverlay.h"
+#include "ads_globals.h"
+
+#include
+
+namespace ads
+{
+static unsigned int zOrderCounter = 0;
+
+/**
+ * Helper function to ease insertion of dock area into splitter
+ */
+static void insertWidgetIntoSplitter(QSplitter* Splitter, QWidget* widget, bool Append)
+{
+ if (Append)
+ {
+ Splitter->addWidget(widget);
+ }
+ else
+ {
+ Splitter->insertWidget(0, widget);
+ }
+}
+
+/**
+ * Private data class of CDockContainerWidget class (pimpl)
+ */
+struct DockContainerWidgetPrivate
+{
+ CDockContainerWidget* _this;
+ QPointer DockManager;
+ unsigned int zOrderIndex = 0;
+ QList DockAreas;
+ QGridLayout* Layout = nullptr;
+ bool isFloating = false;
+
+ /**
+ * Private data constructor
+ */
+ DockContainerWidgetPrivate(CDockContainerWidget* _public);
+
+ /**
+ * Adds dock widget to container and returns the dock area that contains
+ * the inserted dock widget
+ */
+ CDockAreaWidget* dockWidgetIntoContainer(DockWidgetArea area, CDockWidget* Dockwidget);
+
+ /**
+ * Adds dock widget to a existing DockWidgetArea
+ */
+ CDockAreaWidget* dockWidgetIntoDockArea(DockWidgetArea area, CDockWidget* Dockwidget,
+ CDockAreaWidget* TargetDockArea);
+
+ /**
+ * Add dock area to this container
+ */
+ void addDockArea(CDockAreaWidget* NewDockWidget, DockWidgetArea area = CenterDockWidgetArea);
+
+ /**
+ * Drop floating widget into container
+ */
+ void dropIntoContainer(CFloatingDockContainer* FloatingWidget, DockWidgetArea area);
+
+ /**
+ * Drop floating widget into dock area
+ */
+ void dropIntoSection(CFloatingDockContainer* FloatingWidget,
+ CDockAreaWidget* TargetArea, DockWidgetArea area);
+
+ /**
+ * Adds new dock areas to the internal dock area list
+ */
+ void addDockAreasToList(const QList NewDockAreas);
+}; // struct DockContainerWidgetPrivate
+
+
+//============================================================================
+DockContainerWidgetPrivate::DockContainerWidgetPrivate(CDockContainerWidget* _public) :
+ _this(_public)
+{
+
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* FloatingWidget,
+ DockWidgetArea area)
+{
+ auto InsertParam = internal::dockAreaInsertParameters(area);
+ auto NewDockAreas = FloatingWidget->dockContainer()->findChildren(
+ QString(), Qt::FindChildrenRecursively);
+ QSplitter* OldSplitter = nullptr;
+
+ // If the container already contains dock areas, then we need to ensure that
+ // we have a splitter with an orientation that matches the orientation of
+ // the current drop action
+ if (!DockAreas.isEmpty())
+ {
+ OldSplitter = _this->findChild(QString(), Qt::FindDirectChildrenOnly);
+ // First replace the dock widget with a splitter
+ if (DockAreas.count() == 1)
+ {
+ auto DockArea = dynamic_cast(Layout->itemAtPosition(0, 0)->widget());
+ QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
+ Layout->replaceWidget(DockArea, NewSplitter);
+ NewSplitter->addWidget(DockArea);
+ OldSplitter = NewSplitter;
+ }
+ else if (OldSplitter->orientation() != InsertParam.orientation())
+ {
+ QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
+ QLayoutItem* li = Layout->replaceWidget(OldSplitter, NewSplitter);
+ NewSplitter->addWidget(OldSplitter);
+ OldSplitter = NewSplitter;
+ }
+ }
+
+ // Now we can insert the floating widget content into this container
+ auto Widget = FloatingWidget->dockContainer()->findChild(QString(), Qt::FindDirectChildrenOnly);
+ auto FloatingSplitter = dynamic_cast(Widget);
+ if (DockAreas.isEmpty())
+ {
+ auto Widget = FloatingWidget->dockContainer()->findChild(QString(), Qt::FindDirectChildrenOnly);
+ Layout->addWidget(Widget, 0, 0);
+ }
+ else if (!FloatingSplitter)
+ {
+ insertWidgetIntoSplitter(OldSplitter, Widget, InsertParam.append());
+ }
+ else if (FloatingSplitter->orientation() == InsertParam.orientation())
+ {
+ while (FloatingSplitter->count())
+ {
+ insertWidgetIntoSplitter(OldSplitter, FloatingSplitter->widget(0), InsertParam.append());
+ }
+ }
+ else
+ {
+ insertWidgetIntoSplitter(OldSplitter, FloatingSplitter, InsertParam.append());
+ }
+
+ addDockAreasToList(NewDockAreas);
+ FloatingWidget->deleteLater();
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* FloatingWidget,
+ CDockAreaWidget* TargetArea, DockWidgetArea area)
+{
+ CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
+ if (area == CenterDockWidgetArea)
+ {
+ auto NewDockWidgets = FloatingContainer->findChildren(
+ QString(), Qt::FindChildrenRecursively);
+ for (auto DockWidget : NewDockWidgets)
+ {
+ TargetArea->insertDockWidget(0, DockWidget, false);
+ }
+ TargetArea->setCurrentIndex(0); // make the topmost widget active
+ FloatingWidget->deleteLater();
+ TargetArea->updateDockArea();
+ return;
+ }
+
+ auto InsertParam = internal::dockAreaInsertParameters(area);
+ auto NewDockAreas = FloatingWidget->dockContainer()->findChildren(
+ QString(), Qt::FindChildrenRecursively);
+ QSplitter* TargetAreaSplitter = internal::findParent(TargetArea);
+
+ if (!TargetAreaSplitter)
+ {
+ QSplitter* Splitter = internal::newSplitter(InsertParam.orientation());
+ Layout->replaceWidget(TargetArea, Splitter);
+ Splitter->addWidget(TargetArea);
+ TargetAreaSplitter = Splitter;
+ }
+
+ int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
+ auto Widget = FloatingWidget->dockContainer()->findChild(QString(), Qt::FindDirectChildrenOnly);
+ auto FloatingSplitter = dynamic_cast(Widget);
+
+ if (TargetAreaSplitter->orientation() == InsertParam.orientation())
+ {
+ if (!FloatingSplitter || FloatingSplitter->orientation() != InsertParam.orientation())
+ {
+ TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), Widget);
+ }
+ else
+ {
+ int InsertIndex = AreaIndex + InsertParam.insertOffset();
+ while (FloatingSplitter->count())
+ {
+ TargetAreaSplitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0));
+ }
+ }
+ }
+ else
+ {
+ QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
+ if (!FloatingSplitter || FloatingSplitter->orientation() != InsertParam.orientation())
+ {
+ NewSplitter->addWidget(Widget);
+ }
+ else
+ {
+ while (FloatingSplitter->count())
+ {
+ NewSplitter->addWidget(FloatingSplitter->widget(0));
+ }
+ }
+
+ insertWidgetIntoSplitter(NewSplitter, TargetArea, !InsertParam.append());
+ TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter);
+ }
+
+ FloatingWidget->deleteLater();
+ addDockAreasToList(NewDockAreas);
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::addDockAreasToList(const QList NewDockAreas)
+{
+ int CountBefore = DockAreas.count();
+ int NewAreaCount = NewDockAreas.count();
+ DockAreas.append(NewDockAreas);
+
+ // We need to ensure, that the dock area title bar is visible. The title bar
+ // is invisible, if the dock are is a single dock area in a floating widget.
+ if (1 == CountBefore)
+ {
+ DockAreas.at(0)->updateDockArea();
+ }
+
+ if (1 == NewAreaCount)
+ {
+ DockAreas.last()->updateDockArea();
+ }
+
+ emit _this->dockAreasAdded();
+}
+
+
+//============================================================================
+CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoContainer(DockWidgetArea area,
+ CDockWidget* Dockwidget)
+{
+ CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
+ NewDockArea->addDockWidget(Dockwidget);
+ addDockArea(NewDockArea, area);
+ return NewDockArea;
+}
+
+
+//============================================================================
+void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockWidgetArea area)
+{
+ auto InsertParam = internal::dockAreaInsertParameters(area);
+ if (DockAreas.isEmpty())
+ {
+ Layout->addWidget(NewDockArea, 0, 0);
+ }
+ else if (DockAreas.count() == 1)
+ {
+ QSplitter* Splitter = internal::newSplitter(InsertParam.orientation());
+ auto DockArea = dynamic_cast(Layout->itemAtPosition(0, 0)->widget());
+ Layout->replaceWidget(DockArea, Splitter);
+ Splitter->addWidget(DockArea);
+ insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append());
+ }
+ else
+ {
+ QSplitter* Splitter = _this->findChild(QString(), Qt::FindDirectChildrenOnly);
+ if (Splitter->orientation() == InsertParam.orientation())
+ {
+ insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append());
+ }
+ else
+ {
+ QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
+ if (InsertParam.append())
+ {
+ QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
+ NewSplitter->addWidget(Splitter);
+ NewSplitter->addWidget(NewDockArea);
+ delete li;
+ }
+ else
+ {
+ NewSplitter->addWidget(NewDockArea);
+ QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
+ NewSplitter->addWidget(Splitter);
+ delete li;
+ }
+ }
+ }
+
+ DockAreas.append(NewDockArea);
+ NewDockArea->updateDockArea();
+ emit _this->dockAreasAdded();
+}
+
+
+//============================================================================
+CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoDockArea(DockWidgetArea area,
+ CDockWidget* Dockwidget, CDockAreaWidget* TargetDockArea)
+{
+ if (CenterDockWidgetArea == area)
+ {
+ TargetDockArea->addDockWidget(Dockwidget);
+ return TargetDockArea;
+ }
+
+ CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this);
+ NewDockArea->addDockWidget(Dockwidget);
+ auto InsertParam = internal::dockAreaInsertParameters(area);
+ if (DockAreas.count() == 1)
+ {
+ QSplitter* Splitter = internal::newSplitter(InsertParam.orientation());
+ auto DockArea = dynamic_cast(Layout->itemAtPosition(0, 0)->widget());
+ Layout->replaceWidget(DockArea, Splitter);
+ Splitter->addWidget(DockArea);
+ insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append());
+ }
+ else
+ {
+ QSplitter* TargetAreaSplitter = internal::findParent(TargetDockArea);
+ int index = TargetAreaSplitter ->indexOf(TargetDockArea);
+ if (TargetAreaSplitter->orientation() == InsertParam.orientation())
+ {
+ std::cout << "TargetAreaSplitter->orientation() == InsertParam.orientation()" << std::endl;
+ TargetAreaSplitter->insertWidget(index + InsertParam.insertOffset(), NewDockArea);
+ }
+ else
+ {
+ std::cout << "TargetAreaSplitter->orientation() != InsertParam.orientation()" << std::endl;
+ QSplitter* NewSplitter = internal::newSplitter(InsertParam.orientation());
+ NewSplitter->addWidget(TargetDockArea);
+ insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
+ TargetAreaSplitter->insertWidget(index, NewSplitter);
+ }
+ }
+
+ DockAreas.append(NewDockArea);
+ emit _this->dockAreasAdded();
+ return NewDockArea;
+}
+
+
+//============================================================================
+CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *parent) :
+ QFrame(parent),
+ d(new DockContainerWidgetPrivate(this))
+{
+ d->isFloating = dynamic_cast(parent) != 0;
+
+ //setStyleSheet("background: green;");
+ d->DockManager = DockManager;
+ if (DockManager != this)
+ {
+ d->DockManager->registerDockContainer(this);
+ }
+
+ d->Layout = new QGridLayout();
+ d->Layout->setContentsMargins(0, 1, 0, 1);
+ d->Layout->setSpacing(0);
+ setLayout(d->Layout);
+}
+
+//============================================================================
+CDockContainerWidget::~CDockContainerWidget()
+{
+ if (d->DockManager)
+ {
+ d->DockManager->removeDockContainer(this);
+ }
+ delete d;
+}
+
+
+//============================================================================
+CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
+ CDockAreaWidget* DockAreaWidget)
+{
+ CDockAreaWidget* OldDockArea = Dockwidget->dockAreaWidget();
+ if (OldDockArea)
+ {
+ OldDockArea->removeDockWidget(Dockwidget);
+ }
+
+ Dockwidget->setDockManager(d->DockManager);
+ if (DockAreaWidget)
+ {
+ return d->dockWidgetIntoDockArea(area, Dockwidget, DockAreaWidget);
+ }
+ else
+ {
+ return d->dockWidgetIntoContainer(area, Dockwidget);
+ }
+}
+
+
+//============================================================================
+unsigned int CDockContainerWidget::zOrderIndex() const
+{
+ return d->zOrderIndex;
+}
+
+
+//============================================================================
+bool CDockContainerWidget::isInFrontOf(CDockContainerWidget* Other) const
+{
+ return this->zOrderIndex() > Other->zOrderIndex();
+}
+
+
+//============================================================================
+bool CDockContainerWidget::event(QEvent *e)
+{
+ bool Result = QWidget::event(e);
+ if (e->type() == QEvent::WindowActivate)
+ {
+ d->zOrderIndex = ++zOrderCounter;
+ }
+ else if (e->type() == QEvent::Show && !d->zOrderIndex)
+ {
+ d->zOrderIndex = ++zOrderCounter;
+ }
+
+ return Result;
+}
+
+
+//============================================================================
+void CDockContainerWidget::addDockArea(CDockAreaWidget* DockAreaWidget,
+ DockWidgetArea area)
+{
+ CDockContainerWidget* Container = DockAreaWidget->dockContainer();
+ if (Container && Container != this)
+ {
+ Container->removeDockArea(DockAreaWidget);
+ }
+
+ d->addDockArea(DockAreaWidget);
+}
+
+
+//============================================================================
+void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
+{
+ std::cout << "CDockContainerWidget::removeDockArea" << std::endl;
+ d->DockAreas.removeAll(area);
+ QSplitter* Splitter = internal::findParent(area);
+ area->setParent(0);
+ if (!(Splitter && Splitter->count() == 1))
+ {
+ emit dockAreasRemoved();
+ return;
+ }
+
+ // It the splitter contains only one single widget, then we do not need
+ // it anymore and can replace it with its content
+ std::cout << "Replacing splitter with content" << std::endl;
+ QWidget* widget = Splitter->widget(0);
+ widget->setParent(this);
+ QSplitter* ParentSplitter = internal::findParent(Splitter);
+ if (ParentSplitter)
+ {
+ internal::replaceSplitterWidget(ParentSplitter, Splitter, widget);
+ }
+ else
+ {
+ d->Layout->replaceWidget(Splitter, widget);
+ }
+ delete Splitter;
+ emit dockAreasRemoved();
+}
+
+
+//============================================================================
+CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const
+{
+ for (const auto& DockArea : d->DockAreas)
+ {
+ if (DockArea->rect().contains(DockArea->mapFromGlobal(GlobalPos)))
+ {
+ return DockArea;
+ }
+ }
+
+ return 0;
+}
+
+
+//============================================================================
+CDockAreaWidget* CDockContainerWidget::dockArea(int Index) const
+{
+ return (Index < dockAreaCount()) ? d->DockAreas[Index] : 0;
+}
+
+
+//============================================================================
+bool CDockContainerWidget::isFloating() const
+{
+ return d->isFloating;
+}
+
+
+//============================================================================
+int CDockContainerWidget::dockAreaCount() const
+{
+ return d->DockAreas.count();
+}
+
+
+//============================================================================
+void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget,
+ const QPoint& TargetPos)
+{
+ std::cout << "CDockContainerWidget::dropFloatingWidget" << std::endl;
+ CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
+ auto dropArea = InvalidDockWidgetArea;
+ if (DockArea)
+ {
+ auto dropOverlay = d->DockManager->dockAreaOverlay();
+ dropOverlay->setAllowedAreas(AllDockAreas);
+ dropArea = dropOverlay->showOverlay(DockArea);
+ if (dropArea != InvalidDockWidgetArea)
+ {
+ std::cout << "Dock Area Drop Content: " << dropArea << std::endl;
+ d->dropIntoSection(FloatingWidget, DockArea, dropArea);
+ }
+ }
+
+ // mouse is over container
+ if (InvalidDockWidgetArea == dropArea)
+ {
+ dropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
+ std::cout << "Container Drop Content: " << dropArea << std::endl;
+ if (dropArea != InvalidDockWidgetArea)
+ {
+ d->dropIntoContainer(FloatingWidget, dropArea);
+ }
+ }
+}
+
+
+//============================================================================
+QList CDockContainerWidget::openedDockAreas() const
+{
+ QList Result;
+ for (auto DockArea : d->DockAreas)
+ {
+ if (DockArea->isVisible())
+ {
+ Result.append(DockArea);
+ }
+ }
+
+ return Result;
+}
+
+
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF DockContainerWidget.cpp
diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h
index 1f93dfe..7688111 100644
--- a/src/DockContainerWidget.h
+++ b/src/DockContainerWidget.h
@@ -1,146 +1,152 @@
-#ifndef DockContainerWidgetH
-#define DockContainerWidgetH
-/*******************************************************************************
-** QtAdcancedDockingSystem
-** Copyright (C) 2017 Uwe Kindler
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program 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 General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockContainerWidget.h
-/// \author Uwe Kindler
-/// \date 24.02.2017
-/// \brief Declaration of CDockContainerWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include
-
-#include "ads_globals.h"
-
-namespace ads
-{
-struct DockContainerWidgetPrivate;
-class CDockAreaWidget;
-class CDockWidget;
-class CDockManager;
-class CFloatingDockContainer;
-
-/**
- * Container that manages a number of dock areas with single dock widgets
- * or tabyfied dock widgets in each area
- */
-class CDockContainerWidget : public QFrame
-{
- Q_OBJECT
-private:
- DockContainerWidgetPrivate* d; ///< private data (pimpl)
- friend class DockContainerWidgetPrivate;
-
-protected:
- /**
- * Handles activation events to update zOrderIndex
- */
- virtual bool event(QEvent *e) override;
-
-public:
- /**
- * Default Constructor
- */
- CDockContainerWidget(CDockManager* DockManager, QWidget* parent = 0);
-
- /**
- * Virtual Destructor
- */
- virtual ~CDockContainerWidget();
-
- /**
- * Drop floating widget into the container
- */
- void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
-
- /**
- * Adds dockwidget into the given area.
- * If DockAreaWidget is not null, then the area parameter indicates the area
- * into the DockAreaWidget. If DockAreaWidget is null, the Dockwidget will
- * be dropped into the container.
- * \return Returns the dock area widget that contains the new DockWidget
- */
- CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
- CDockAreaWidget* DockAreaWidget = nullptr);
-
- /**
- * Adds the given dock area to this container widget
- */
- void addDockArea(CDockAreaWidget* DockAreaWidget, DockWidgetArea area = CenterDockWidgetArea);
-
- /**
- * Removes the given dock area from this container
- */
- void removeDockArea(CDockAreaWidget* area);
-
- /**
- * Returns the current zOrderIndex
- */
- virtual unsigned int zOrderIndex() const;
-
- /**
- * This function returns true if this container widgets z order index is
- * higher than the index of the container widget given in Other parameter
- */
- bool isInFrontOf(CDockContainerWidget* Other) const;
-
- /**
- * Returns the dock area at teh given global position or 0 if there is no
- * dock area at this position
- */
- CDockAreaWidget* dockAreaAt(const QPoint& GlobalPos) const;
-
- /**
- * Returns the dock area at the given Index or 0 if the index is out of
- * range
- */
- CDockAreaWidget* dockArea(int Index) const;
-
- /**
- * Returns the number of dock areas in this container
- */
- int dockAreaCount() const;
-
- /**
- * This function returns true, if this container is in a floating widget
- */
- bool isFloating() const;
-
-signals:
- /**
- * This signal is emitted if one or multiple dock areas has been added to
- * the internal list of dock areas.
- * If multiple dock areas are inserted, this signal is emitted only once
- */
- void dockAreasAdded();
-
- /**
- * This signal is emitted if one or multiple dock areas has been removed
- */
- void dockAreasRemoved();
-}; // class DockContainerWidget
-} // namespace ads
-//-----------------------------------------------------------------------------
-#endif // DockContainerWidgetH
+#ifndef DockContainerWidgetH
+#define DockContainerWidgetH
+/*******************************************************************************
+** QtAdcancedDockingSystem
+** Copyright (C) 2017 Uwe Kindler
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockContainerWidget.h
+/// \author Uwe Kindler
+/// \date 24.02.2017
+/// \brief Declaration of CDockContainerWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include
+
+#include "ads_globals.h"
+
+namespace ads
+{
+struct DockContainerWidgetPrivate;
+class CDockAreaWidget;
+class CDockWidget;
+class CDockManager;
+class CFloatingDockContainer;
+
+/**
+ * Container that manages a number of dock areas with single dock widgets
+ * or tabyfied dock widgets in each area
+ */
+class CDockContainerWidget : public QFrame
+{
+ Q_OBJECT
+private:
+ DockContainerWidgetPrivate* d; ///< private data (pimpl)
+ friend class DockContainerWidgetPrivate;
+
+protected:
+ /**
+ * Handles activation events to update zOrderIndex
+ */
+ virtual bool event(QEvent *e) override;
+
+public:
+ /**
+ * Default Constructor
+ */
+ CDockContainerWidget(CDockManager* DockManager, QWidget* parent = 0);
+
+ /**
+ * Virtual Destructor
+ */
+ virtual ~CDockContainerWidget();
+
+ /**
+ * Drop floating widget into the container
+ */
+ void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
+
+ /**
+ * Adds dockwidget into the given area.
+ * If DockAreaWidget is not null, then the area parameter indicates the area
+ * into the DockAreaWidget. If DockAreaWidget is null, the Dockwidget will
+ * be dropped into the container.
+ * \return Returns the dock area widget that contains the new DockWidget
+ */
+ CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
+ CDockAreaWidget* DockAreaWidget = nullptr);
+
+ /**
+ * Adds the given dock area to this container widget
+ */
+ void addDockArea(CDockAreaWidget* DockAreaWidget, DockWidgetArea area = CenterDockWidgetArea);
+
+ /**
+ * Removes the given dock area from this container
+ */
+ void removeDockArea(CDockAreaWidget* area);
+
+ /**
+ * Returns the current zOrderIndex
+ */
+ virtual unsigned int zOrderIndex() const;
+
+ /**
+ * This function returns true if this container widgets z order index is
+ * higher than the index of the container widget given in Other parameter
+ */
+ bool isInFrontOf(CDockContainerWidget* Other) const;
+
+ /**
+ * Returns the dock area at teh given global position or 0 if there is no
+ * dock area at this position
+ */
+ CDockAreaWidget* dockAreaAt(const QPoint& GlobalPos) const;
+
+ /**
+ * Returns the dock area at the given Index or 0 if the index is out of
+ * range
+ */
+ CDockAreaWidget* dockArea(int Index) const;
+
+ /**
+ * Returns the list of dock areas that are not closed
+ * If all dock widgets in a dock area are closed, the dock area will be closed
+ */
+ QList openedDockAreas() const;
+
+ /**
+ * Returns the number of dock areas in this container
+ */
+ int dockAreaCount() const;
+
+ /**
+ * This function returns true, if this container is in a floating widget
+ */
+ bool isFloating() const;
+
+signals:
+ /**
+ * This signal is emitted if one or multiple dock areas has been added to
+ * the internal list of dock areas.
+ * If multiple dock areas are inserted, this signal is emitted only once
+ */
+ void dockAreasAdded();
+
+ /**
+ * This signal is emitted if one or multiple dock areas has been removed
+ */
+ void dockAreasRemoved();
+}; // class DockContainerWidget
+} // namespace ads
+//-----------------------------------------------------------------------------
+#endif // DockContainerWidgetH
diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp
index d15e5d5..4dcb2e3 100644
--- a/src/DockWidget.cpp
+++ b/src/DockWidget.cpp
@@ -1,358 +1,404 @@
-/*******************************************************************************
-** QtAdcancedDockingSystem
-** Copyright (C) 2017 Uwe Kindler
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program 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 General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockWidget.cpp
-/// \author Uwe Kindler
-/// \date 26.02.2017
-/// \brief Implementation of CDockWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include "DockWidget.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include "DockWidgetTitleBar.h"
-#include "DockContainerWidget.h"
-#include "DockAreaWidget.h"
-#include "DockManager.h"
-#include "FloatingDockContainer.h"
-
-#include "ads_globals.h"
-
-namespace ads
-{
-/**
- * Private data class of CDockWidget class (pimpl)
- */
-struct DockWidgetPrivate
-{
- CDockWidget* _this;
- QBoxLayout* Layout;
- QWidget* Widget = nullptr;
- CDockWidgetTitleBar* TitleWidget;
- CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures;
- CDockManager* DockManager = nullptr;
- CDockAreaWidget* DockArea = nullptr;
- QAction* ToggleViewAction;
- bool Closed = false;
- struct CapturedState
- {
- QString DockTreePosition;
- QRect GlobalGeometry;
- QPointer DockContainer;
- } CapturedState;
-
- /**
- * Private data constructor
- */
- DockWidgetPrivate(CDockWidget* _public);
-
- /**
- * Saves the current state into CapturedState variable
- */
- void capturedState();
-
- /**
- * Show dock widget
- */
- void showDockWidget();
-
- /**
- * Hides a parent splitter if all dock widgets in the splitter are closed
- */
- void hideEmptyParentSplitter();
-
- /**
- * Hides a dock area if all dock widgets in the area are closed
- */
- void hideEmptyParentDockArea();
-};
-// struct DockWidgetPrivate
-
-//============================================================================
-DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) :
- _this(_public)
-{
-
-}
-
-
-//============================================================================
-void DockWidgetPrivate::capturedState()
-{
- QString DockTreePosition;
- QTextStream stream(&DockTreePosition);
-
- QPoint GlobalTopLeft = _this->mapToGlobal(_this->geometry().topLeft());
- QRect Rect(GlobalTopLeft, _this->geometry().size());
- CapturedState.GlobalGeometry = Rect;
- CapturedState.DockContainer = _this->dockContainer();
-
- QWidget* Widget = DockArea;
- QSplitter* splitter = internal::findParent(Widget);
- QStack SplitterData;
- while (splitter)
- {
- SplitterData.push(QString("%1%2")
- .arg((splitter->orientation() == Qt::Horizontal) ? "H" : "V")
- .arg(splitter->indexOf(Widget)));
- Widget = splitter;
- splitter = internal::findParent(Widget);
- }
-
- QString Separator;
- while (!SplitterData.isEmpty())
- {
- stream << Separator << SplitterData.pop();
- Separator = " ";
- }
- this->CapturedState.DockTreePosition = DockTreePosition;
- std::cout << "SerializedPosition: " << DockTreePosition.toStdString() << std::endl;
-}
-
-
-//============================================================================
-void DockWidgetPrivate::showDockWidget()
-{
- DockArea->show();
- DockArea->setCurrentIndex(DockArea->tabIndex(_this));
- QSplitter* Splitter = internal::findParent(_this);
- if (Splitter)
- {
- Splitter->show();
- }
-}
-
-
-//============================================================================
-void DockWidgetPrivate::hideEmptyParentSplitter()
-{
- QSplitter* Splitter = internal::findParent(_this);
- if (!Splitter)
- {
- return;
- }
-
- for (int i = 0; i < Splitter->count(); ++i)
- {
- if (Splitter->widget(i)->isVisible())
- {
- return;
- }
- }
-
- Splitter->hide();
-}
-
-
-//============================================================================
-void DockWidgetPrivate::hideEmptyParentDockArea()
-{
- auto OpenDockWidgets = DockArea->openDockWidgets();
- if (OpenDockWidgets.count() > 1)
- {
- CDockWidget* NextDockWidget;
- if (OpenDockWidgets.last() == _this)
- {
- NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2];
- }
- else
- {
- int NextIndex = OpenDockWidgets.indexOf(_this) + 1;
- NextDockWidget = OpenDockWidgets[NextIndex];
- }
-
- DockArea->setCurrentDockWidget(NextDockWidget);
- }
- else
- {
- DockArea->hide();
- }
-}
-
-
-//============================================================================
-CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
- QFrame(parent),
- d(new DockWidgetPrivate(this))
-{
- d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
- d->Layout->setContentsMargins(0, 0, 0, 0);
- d->Layout->setSpacing(0);
- setLayout(d->Layout);
- setWindowTitle(title);
-
- d->TitleWidget = new CDockWidgetTitleBar(this);
- d->ToggleViewAction = new QAction(title);
- d->ToggleViewAction->setCheckable(true);
- connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
- SLOT(toggleView(bool)));
-}
-
-//============================================================================
-CDockWidget::~CDockWidget()
-{
- std::cout << "~CDockWidget()" << std::endl;
- delete d;
-}
-
-
-//============================================================================
-void CDockWidget::setWidget(QWidget* widget)
-{
- if (d->Widget)
- {
- d->Layout->replaceWidget(d->Widget, widget);
- }
- else
- {
- d->Layout->addWidget(widget);
- }
-
- d->Widget = widget;
-}
-
-
-//============================================================================
-QWidget* CDockWidget::widget() const
-{
- return d->Widget;
-}
-
-
-//============================================================================
-CDockWidgetTitleBar* CDockWidget::titleBar() const
-{
- return d->TitleWidget;
-}
-
-
-//============================================================================
-void CDockWidget::setFeatures(DockWidgetFeatures features)
-{
- d->Features = features;
-}
-
-
-//============================================================================
-CDockWidget::DockWidgetFeatures CDockWidget::features() const
-{
- return d->Features;
-}
-
-
-//============================================================================
-CDockManager* CDockWidget::dockManager() const
-{
- return d->DockManager;
-}
-
-
-//============================================================================
-void CDockWidget::setDockManager(CDockManager* DockManager)
-{
- d->DockManager = DockManager;
-}
-
-
-//============================================================================
-CDockContainerWidget* CDockWidget::dockContainer() const
-{
- return internal::findParent(this);
-}
-
-
-//============================================================================
-CDockAreaWidget* CDockWidget::dockAreaWidget() const
-{
- return internal::findParent(this);
-}
-
-
-//============================================================================
-bool CDockWidget::isFloating() const
-{
- return dockContainer() ? dockContainer()->isFloating() : false;
-}
-
-
-//============================================================================
-bool CDockWidget::isClosed() const
-{
- return d->Closed;
-}
-
-
-//============================================================================
-QAction* CDockWidget::toggleViewAction() const
-{
- return d->ToggleViewAction;
-}
-
-
-//============================================================================
-void CDockWidget::toggleView(bool Open)
-{
- if (Open)
- {
- d->showDockWidget();
- }
- else
- {
- hideDockWidget();
- }
- d->Closed = !Open;
-}
-
-
-//============================================================================
-void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
-{
- d->DockArea = DockArea;
- d->ToggleViewAction->setChecked(DockArea != nullptr);
-}
-
-
-
-//============================================================================
-void CDockWidget::hideDockWidget()
-{
- CDockAreaWidget* DockArea = d->DockArea;
- d->ToggleViewAction->setChecked(false);
- d->TitleWidget->hide();
- d->hideEmptyParentDockArea();
- d->hideEmptyParentSplitter();
-}
-
-} // namespace ads
-
-//---------------------------------------------------------------------------
-// EOF DockWidget.cpp
+/*******************************************************************************
+** QtAdcancedDockingSystem
+** Copyright (C) 2017 Uwe Kindler
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockWidget.cpp
+/// \author Uwe Kindler
+/// \date 26.02.2017
+/// \brief Implementation of CDockWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include "DockWidget.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "DockWidgetTitleBar.h"
+#include "DockContainerWidget.h"
+#include "DockAreaWidget.h"
+#include "DockManager.h"
+#include "FloatingDockContainer.h"
+
+#include "ads_globals.h"
+
+namespace ads
+{
+/**
+ * Private data class of CDockWidget class (pimpl)
+ */
+struct DockWidgetPrivate
+{
+ CDockWidget* _this;
+ QBoxLayout* Layout;
+ QWidget* Widget = nullptr;
+ CDockWidgetTitleBar* TitleWidget;
+ CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures;
+ CDockManager* DockManager = nullptr;
+ CDockAreaWidget* DockArea = nullptr;
+ QAction* ToggleViewAction;
+ bool Closed = false;
+ struct CapturedState
+ {
+ QString DockTreePosition;
+ QRect GlobalGeometry;
+ QPointer DockContainer;
+ } CapturedState;
+
+ /**
+ * Private data constructor
+ */
+ DockWidgetPrivate(CDockWidget* _public);
+
+ /**
+ * Saves the current state into CapturedState variable
+ */
+ void capturedState();
+
+ /**
+ * Show dock widget
+ */
+ void showDockWidget();
+
+ /**
+ * Hide dock widget.
+ */
+ void hideDockWidget();
+
+ /**
+ * Hides a parent splitter if all dock widgets in the splitter are closed
+ */
+ void hideEmptyParentSplitter();
+
+ /**
+ * Hides a dock area if all dock widgets in the area are closed
+ */
+ void hideEmptyParentDockArea();
+
+ /**
+ * Hides a floating widget if all dock areas are empty - that means,
+ * if all dock widgets in all dock areas are closed
+ */
+ void hideEmptyFloatingWidget();
+};
+// struct DockWidgetPrivate
+
+//============================================================================
+DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) :
+ _this(_public)
+{
+
+}
+
+
+//============================================================================
+void DockWidgetPrivate::capturedState()
+{
+ QString DockTreePosition;
+ QTextStream stream(&DockTreePosition);
+
+ QPoint GlobalTopLeft = _this->mapToGlobal(_this->geometry().topLeft());
+ QRect Rect(GlobalTopLeft, _this->geometry().size());
+ CapturedState.GlobalGeometry = Rect;
+ CapturedState.DockContainer = _this->dockContainer();
+
+ QWidget* Widget = DockArea;
+ QSplitter* splitter = internal::findParent(Widget);
+ QStack SplitterData;
+ while (splitter)
+ {
+ SplitterData.push(QString("%1%2")
+ .arg((splitter->orientation() == Qt::Horizontal) ? "H" : "V")
+ .arg(splitter->indexOf(Widget)));
+ Widget = splitter;
+ splitter = internal::findParent(Widget);
+ }
+
+ QString Separator;
+ while (!SplitterData.isEmpty())
+ {
+ stream << Separator << SplitterData.pop();
+ Separator = " ";
+ }
+ this->CapturedState.DockTreePosition = DockTreePosition;
+ std::cout << "SerializedPosition: " << DockTreePosition.toStdString() << std::endl;
+}
+
+
+//============================================================================
+void DockWidgetPrivate::showDockWidget()
+{
+ DockArea->show();
+ DockArea->setCurrentIndex(DockArea->tabIndex(_this));
+ QSplitter* Splitter = internal::findParent(_this);
+ if (Splitter)
+ {
+ Splitter->show();
+ }
+
+ CDockContainerWidget* Container = DockArea->dockContainer();
+ if (Container->isFloating())
+ {
+ CFloatingDockContainer* FloatingWidget = internal::findParent<
+ CFloatingDockContainer*>(Container);
+ FloatingWidget->show();
+ }
+}
+
+
+//============================================================================
+void DockWidgetPrivate::hideDockWidget()
+{
+ ToggleViewAction->setChecked(false);
+ TitleWidget->hide();
+ hideEmptyParentDockArea();
+ hideEmptyParentSplitter();
+ hideEmptyFloatingWidget();
+}
+
+
+//============================================================================
+void DockWidgetPrivate::hideEmptyParentSplitter()
+{
+ QSplitter* Splitter = internal::findParent(_this);
+ if (!Splitter)
+ {
+ return;
+ }
+
+ for (int i = 0; i < Splitter->count(); ++i)
+ {
+ if (Splitter->widget(i)->isVisible())
+ {
+ return;
+ }
+ }
+
+ Splitter->hide();
+}
+
+
+//============================================================================
+void DockWidgetPrivate::hideEmptyParentDockArea()
+{
+ auto OpenDockWidgets = DockArea->openedDockWidgets();
+ if (OpenDockWidgets.count() > 1)
+ {
+ CDockWidget* NextDockWidget;
+ if (OpenDockWidgets.last() == _this)
+ {
+ NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2];
+ }
+ else
+ {
+ int NextIndex = OpenDockWidgets.indexOf(_this) + 1;
+ NextDockWidget = OpenDockWidgets[NextIndex];
+ }
+
+ DockArea->setCurrentDockWidget(NextDockWidget);
+ }
+ else
+ {
+ DockArea->hide();
+ }
+}
+
+
+//============================================================================
+void DockWidgetPrivate::hideEmptyFloatingWidget()
+{
+ CDockContainerWidget* Container = _this->dockContainer();
+ if (Container->isFloating() && Container->openedDockAreas().isEmpty())
+ {
+ CFloatingDockContainer* FloatingWidget = internal::findParent(Container);
+ FloatingWidget->hide();
+ }
+}
+
+
+//============================================================================
+CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
+ QFrame(parent),
+ d(new DockWidgetPrivate(this))
+{
+ d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
+ d->Layout->setContentsMargins(0, 0, 0, 0);
+ d->Layout->setSpacing(0);
+ setLayout(d->Layout);
+ setWindowTitle(title);
+
+ d->TitleWidget = new CDockWidgetTitleBar(this);
+ d->ToggleViewAction = new QAction(title);
+ d->ToggleViewAction->setCheckable(true);
+ connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
+ SLOT(toggleView(bool)));
+}
+
+//============================================================================
+CDockWidget::~CDockWidget()
+{
+ std::cout << "~CDockWidget()" << std::endl;
+ delete d;
+}
+
+
+//============================================================================
+void CDockWidget::setToggleViewActionChecked(bool Checked)
+{
+ QAction* Action = d->ToggleViewAction;
+ Action->blockSignals(true);
+ Action->setChecked(Checked);
+ Action->blockSignals(false);
+}
+
+
+//============================================================================
+void CDockWidget::setWidget(QWidget* widget)
+{
+ if (d->Widget)
+ {
+ d->Layout->replaceWidget(d->Widget, widget);
+ }
+ else
+ {
+ d->Layout->addWidget(widget);
+ }
+
+ d->Widget = widget;
+}
+
+
+//============================================================================
+QWidget* CDockWidget::widget() const
+{
+ return d->Widget;
+}
+
+
+//============================================================================
+CDockWidgetTitleBar* CDockWidget::titleBar() const
+{
+ return d->TitleWidget;
+}
+
+
+//============================================================================
+void CDockWidget::setFeatures(DockWidgetFeatures features)
+{
+ d->Features = features;
+}
+
+
+//============================================================================
+CDockWidget::DockWidgetFeatures CDockWidget::features() const
+{
+ return d->Features;
+}
+
+
+//============================================================================
+CDockManager* CDockWidget::dockManager() const
+{
+ return d->DockManager;
+}
+
+
+//============================================================================
+void CDockWidget::setDockManager(CDockManager* DockManager)
+{
+ d->DockManager = DockManager;
+}
+
+
+//============================================================================
+CDockContainerWidget* CDockWidget::dockContainer() const
+{
+ return internal::findParent(this);
+}
+
+
+//============================================================================
+CDockAreaWidget* CDockWidget::dockAreaWidget() const
+{
+ return internal::findParent(this);
+}
+
+
+//============================================================================
+bool CDockWidget::isFloating() const
+{
+ return dockContainer() ? dockContainer()->isFloating() : false;
+}
+
+
+//============================================================================
+bool CDockWidget::isClosed() const
+{
+ return d->Closed;
+}
+
+
+//============================================================================
+QAction* CDockWidget::toggleViewAction() const
+{
+ return d->ToggleViewAction;
+}
+
+
+//============================================================================
+void CDockWidget::toggleView(bool Open)
+{
+ if (Open)
+ {
+ d->showDockWidget();
+ }
+ else
+ {
+ d->hideDockWidget();
+ }
+ d->Closed = !Open;
+ if (!Open)
+ {
+ emit closed();
+ }
+ emit viewToggled(Open);
+}
+
+
+//============================================================================
+void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
+{
+ d->DockArea = DockArea;
+ d->ToggleViewAction->setChecked(DockArea != nullptr);
+}
+
+
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF DockWidget.cpp
diff --git a/src/DockWidget.h b/src/DockWidget.h
index 257b456..5911b94 100644
--- a/src/DockWidget.h
+++ b/src/DockWidget.h
@@ -1,180 +1,192 @@
-#ifndef DockWidgetH
-#define DockWidgetH
-/*******************************************************************************
-** QtAdcancedDockingSystem
-** Copyright (C) 2017 Uwe Kindler
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program 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 General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-******************************************************************************/
-
-
-//============================================================================
-/// \file DockWidget.h
-/// \author Uwe Kindler
-/// \date 26.02.2017
-/// \brief Declaration of CDockWidget class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include
-
-namespace ads
-{
-struct DockWidgetPrivate;
-class CDockWidgetTitleBar;
-class CDockManager;
-class CDockContainerWidget;
-class CDockAreaWidget;
-
-/**
- * The QDockWidget class provides a widget that can be docked inside a
- * CDockManager or floated as a top-level window on the desktop.
- */
-class CDockWidget : public QFrame
-{
- Q_OBJECT
-private:
- DockWidgetPrivate* d; ///< private data (pimpl)
- friend class DockWidgetPrivate;
-
-protected:
- friend class CDockContainerWidget;
- friend class CDockAreaWidget;
- friend class CFloatingDockContainer;
-
- /**
- * Assigns the dock manager that manages this dock widget
- */
- void setDockManager(CDockManager* DockManager);
-
- /**
- * If this dock widget is inserted into a dock area, the dock area will
- * be registered on this widget via this function. If a dock widget is
- * removed from a dock area, this function will be called with nullptr
- * value.
- */
- void setDockArea(CDockAreaWidget* DockArea);
-
- /**
- * Hide dock widget.
- */
- void hideDockWidget();
-
-public:
- enum DockWidgetFeature
- {
- DockWidgetClosable = 0x01,
- DockWidgetMovable = 0x02,
- DockWidgetFloatable = 0x04,
- AllDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable,
- NoDockWidgetFeatures = 0x00
- };
- Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
-
-
- enum eState
- {
- StateHidden,
- StateDocked,
- StateFloating
- };
-
- /**
- * Default Constructor
- */
- CDockWidget(const QString &title, QWidget* parent = 0);
-
- /**
- * Virtual Destructor
- */
- virtual ~CDockWidget();
-
- /**
- * Sets the widget for the dock widget to widget.
- */
- void setWidget(QWidget* widget);
-
- /**
- * Returns the widget for the dock widget. This function returns zero if
- * the widget has not been set.
- */
- QWidget* widget() const;
-
- /**
- * Returns the title bar widget of this dock widget
- */
- CDockWidgetTitleBar* titleBar() const;
-
- /**
- * Sets, whether the dock widget is movable, closable, and floatable.
- */
- void setFeatures(DockWidgetFeatures features);
-
- /**
- * This property holds whether the dock widget is movable, closable, and
- * floatable.
- * By default, this property is set to a combination of DockWidgetClosable,
- * DockWidgetMovable and DockWidgetFloatable.
- */
- DockWidgetFeatures features() const;
-
- /**
- * Returns the dock manager that manages the dock widget or 0 if the widget
- * has not been assigned to any dock manager yet
- */
- CDockManager* dockManager() const;
-
- /**
- * Returns the dock container widget this dock area widget belongs to or 0
- * if this dock widget has nt been docked yet
- */
- CDockContainerWidget* dockContainer() const;
-
- /**
- * Returns the dock area widget this dock widget belongs to or 0
- * if this dock widget has not been docked yet
- */
- CDockAreaWidget* dockAreaWidget() const;
-
- /**
- * This property holds whether the dock widget is floating.
- */
- bool isFloating() const;
-
- /**
- * Returns true, if this dock widget is closed.
- */
- bool isClosed() const;
-
- /**
- * Returns a checkable action that can be used to show or close this dock widget.
- * The action's text is set to the dock widget's window title.
- */
- QAction* toggleViewAction() const;
-
-
-public slots:
- /**
- * This property controls whether the dock widget is open or closed.
- * The toogleViewAction triggers this slot
- */
- void toggleView(bool Open);
-}; // class DockWidget
-}
- // namespace ads
-//-----------------------------------------------------------------------------
-#endif // DockWidgetH
+#ifndef DockWidgetH
+#define DockWidgetH
+/*******************************************************************************
+** QtAdcancedDockingSystem
+** Copyright (C) 2017 Uwe Kindler
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+******************************************************************************/
+
+
+//============================================================================
+/// \file DockWidget.h
+/// \author Uwe Kindler
+/// \date 26.02.2017
+/// \brief Declaration of CDockWidget class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include
+
+namespace ads
+{
+struct DockWidgetPrivate;
+class CDockWidgetTitleBar;
+class CDockManager;
+class CDockContainerWidget;
+class CDockAreaWidget;
+
+/**
+ * The QDockWidget class provides a widget that can be docked inside a
+ * CDockManager or floated as a top-level window on the desktop.
+ */
+class CDockWidget : public QFrame
+{
+ Q_OBJECT
+private:
+ DockWidgetPrivate* d; ///< private data (pimpl)
+ friend class DockWidgetPrivate;
+
+protected:
+ friend class CDockContainerWidget;
+ friend class CDockAreaWidget;
+ friend class CFloatingDockContainer;
+
+ /**
+ * Assigns the dock manager that manages this dock widget
+ */
+ void setDockManager(CDockManager* DockManager);
+
+ /**
+ * If this dock widget is inserted into a dock area, the dock area will
+ * be registered on this widget via this function. If a dock widget is
+ * removed from a dock area, this function will be called with nullptr
+ * value.
+ */
+ void setDockArea(CDockAreaWidget* DockArea);
+
+ /**
+ * This function changes the toggle view action without emitting any
+ * signal
+ */
+ void setToggleViewActionChecked(bool Checked);
+
+public:
+ enum DockWidgetFeature
+ {
+ DockWidgetClosable = 0x01,
+ DockWidgetMovable = 0x02,
+ DockWidgetFloatable = 0x04,
+ AllDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable,
+ NoDockWidgetFeatures = 0x00
+ };
+ Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
+
+
+ enum eState
+ {
+ StateHidden,
+ StateDocked,
+ StateFloating
+ };
+
+ /**
+ * Default Constructor
+ */
+ CDockWidget(const QString &title, QWidget* parent = 0);
+
+ /**
+ * Virtual Destructor
+ */
+ virtual ~CDockWidget();
+
+ /**
+ * Sets the widget for the dock widget to widget.
+ */
+ void setWidget(QWidget* widget);
+
+ /**
+ * Returns the widget for the dock widget. This function returns zero if
+ * the widget has not been set.
+ */
+ QWidget* widget() const;
+
+ /**
+ * Returns the title bar widget of this dock widget
+ */
+ CDockWidgetTitleBar* titleBar() const;
+
+ /**
+ * Sets, whether the dock widget is movable, closable, and floatable.
+ */
+ void setFeatures(DockWidgetFeatures features);
+
+ /**
+ * This property holds whether the dock widget is movable, closable, and
+ * floatable.
+ * By default, this property is set to a combination of DockWidgetClosable,
+ * DockWidgetMovable and DockWidgetFloatable.
+ */
+ DockWidgetFeatures features() const;
+
+ /**
+ * Returns the dock manager that manages the dock widget or 0 if the widget
+ * has not been assigned to any dock manager yet
+ */
+ CDockManager* dockManager() const;
+
+ /**
+ * Returns the dock container widget this dock area widget belongs to or 0
+ * if this dock widget has nt been docked yet
+ */
+ CDockContainerWidget* dockContainer() const;
+
+ /**
+ * Returns the dock area widget this dock widget belongs to or 0
+ * if this dock widget has not been docked yet
+ */
+ CDockAreaWidget* dockAreaWidget() const;
+
+ /**
+ * This property holds whether the dock widget is floating.
+ */
+ bool isFloating() const;
+
+ /**
+ * Returns true, if this dock widget is closed.
+ */
+ bool isClosed() const;
+
+ /**
+ * Returns a checkable action that can be used to show or close this dock widget.
+ * The action's text is set to the dock widget's window title.
+ */
+ QAction* toggleViewAction() const;
+
+
+public slots:
+ /**
+ * This property controls whether the dock widget is open or closed.
+ * The toogleViewAction triggers this slot
+ */
+ void toggleView(bool Open);
+
+signals:
+ /**
+ * This signal is emitted if the dock widget is opened or closed
+ */
+ void viewToggled(bool Open);
+
+ /**
+ * This signal is emitted if the dock widget is closed
+ */
+ void closed();
+}; // class DockWidget
+}
+ // namespace ads
+//-----------------------------------------------------------------------------
+#endif // DockWidgetH
diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp
index b16b12d..f863252 100644
--- a/src/FloatingDockContainer.cpp
+++ b/src/FloatingDockContainer.cpp
@@ -1,385 +1,397 @@
-/*******************************************************************************
-** QtAdcancedDockingSystem
-** Copyright (C) 2017 Uwe Kindler
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program 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 General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-******************************************************************************/
-
-
-//============================================================================
-/// \file FloatingDockContainer.cpp
-/// \author Uwe Kindler
-/// \date 01.03.2017
-/// \brief Implementation of CFloatingDockContainer class
-//============================================================================
-
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include "FloatingDockContainer.h"
-
-#include
-#include
-#include
-#include
-
-#include
-
-#include "DockContainerWidget.h"
-#include "DockAreaWidget.h"
-#include "DockManager.h"
-#include "DockWidget.h"
-#include "DockOverlay.h"
-
-
-namespace ads
-{
-static unsigned int zOrderCounter = 0;
-
-/**
- * Private data class of CFloatingDockContainer class (pimpl)
- */
-struct FloatingDockContainerPrivate
-{
- CFloatingDockContainer* _this;
- CDockContainerWidget* DockContainer;
- unsigned int zOrderIndex = ++zOrderCounter;
- QPointer DockManager;
- bool DraggingActive = false;
- QPoint DragStartMousePosition;
- CDockContainerWidget* DropContainer = nullptr;
- CDockAreaWidget* SingleDockArea = nullptr;
-
- /**
- * Private data constructor
- */
- FloatingDockContainerPrivate(CFloatingDockContainer* _public);
-
- void titleMouseReleaseEvent();
- void updateDropOverlays(const QPoint& GlobalPos);
- void setDraggingActive(bool Active);
-};
-// struct FloatingDockContainerPrivate
-
-//============================================================================
-FloatingDockContainerPrivate::FloatingDockContainerPrivate(CFloatingDockContainer* _public) :
- _this(_public)
-{
-
-}
-
-
-
-//============================================================================
-void FloatingDockContainerPrivate::titleMouseReleaseEvent()
-{
- setDraggingActive(false);
- if (!DropContainer)
- {
- return;
- }
-
- std::cout << "Dropped" << std::endl;
- DropContainer->dropFloatingWidget(_this, QCursor::pos());
- DockManager->containerOverlay()->hideOverlay();
- DockManager->dockAreaOverlay()->hideOverlay();
-}
-
-
-
-//============================================================================
-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;
- }
-
- if (DockContainer == ContainerWidget)
- {
- continue;
- }
-
- 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();
-
- if (!TopContainer)
- {
- ContainerOverlay->hideOverlay();
- DockAreaOverlay->hideOverlay();
- return;
- }
-
- ContainerOverlay->setAllowedAreas(TopContainer->dockAreaCount() > 1 ?
- OuterDockAreas : AllDockAreas);
- ContainerOverlay->showOverlay(TopContainer);
- ContainerOverlay->raise();
-
- auto DockArea = TopContainer->dockAreaAt(GlobalPos);
- if (DockArea && TopContainer->dockAreaCount() > 1)
- {
- DockAreaOverlay->setAllowedAreas(AllDockAreas);
- DockAreaOverlay->showOverlay(DockArea);
- }
- else
- {
- DockAreaOverlay->hideOverlay();
- }
-}
-
-
-//============================================================================
-void FloatingDockContainerPrivate::setDraggingActive(bool Active)
-{
- DraggingActive = Active;
-}
-
-
-//============================================================================
-CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) :
- QWidget(DockManager, Qt::Window),
- d(new FloatingDockContainerPrivate(this))
-{
- //setAttribute(Qt::WA_DeleteOnClose);
- d->DockManager = DockManager;
- QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
- l->setContentsMargins(0, 0, 0, 0);
- l->setSpacing(0);
- setLayout(l);
-
- d->DockContainer = new CDockContainerWidget(DockManager, this);
- connect(d->DockContainer, SIGNAL(dockAreasAdded()), this, SLOT(onDockAreasAddedOrRemoved()));
- connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this, SLOT(onDockAreasAddedOrRemoved()));
- l->addWidget(d->DockContainer);
- 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);
-}
-
-
-//============================================================================
-CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget* DockArea) :
- CFloatingDockContainer(DockArea->dockManager())
-{
- d->DockContainer->addDockArea(DockArea);
-}
-
-
-//============================================================================
-CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) :
- CFloatingDockContainer(DockWidget->dockManager())
-{
- d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
-}
-
-//============================================================================
-CFloatingDockContainer::~CFloatingDockContainer()
-{
- std::cout << "~CFloatingDockContainer" << std::endl;
- if (d->DockManager)
- {
- d->DockManager->removeFloatingWidget(this);
- }
- delete d;
-}
-
-
-//============================================================================
-CDockContainerWidget* CFloatingDockContainer::dockContainer() const
-{
- return d->DockContainer;
-}
-
-
-//============================================================================
-void CFloatingDockContainer::changeEvent(QEvent *event)
-{
- QWidget::changeEvent(event);
- if ((event->type() == QEvent::ActivationChange) && isActiveWindow())
- {
- std::cout << "FloatingWidget::changeEvent QEvent::ActivationChange " << std::endl;
- d->zOrderIndex = ++zOrderCounter;
- return;
- }
-}
-
-
-//============================================================================
-void CFloatingDockContainer::moveEvent(QMoveEvent *event)
-{
- QWidget::moveEvent(event);
- if (!qApp->mouseButtons().testFlag(Qt::LeftButton))
- {
- if (d->DraggingActive)
- {
- d->setDraggingActive(false);
- }
- return;
- }
-
- if (d->DraggingActive)
- {
- d->updateDropOverlays(QCursor::pos());
- }
-}
-
-
-//============================================================================
-void CFloatingDockContainer::closeEvent(QCloseEvent *event)
-{
- d->setDraggingActive(false);
- if (dockContainer()->dockAreaCount() > 1 || dockContainer()->dockArea(0)->count() == 1)
- {
- for (int i = 0; i < dockContainer()->dockAreaCount(); ++i)
- {
- auto DockWidgets = dockContainer()->dockArea(i)->dockWidgets();
- for (auto DockWidget : DockWidgets)
- {
- DockWidget->hideDockWidget();
- }
- }
- QWidget::closeEvent(event);
- }
- else
- {
- auto DockArea = dockContainer()->dockArea(0);
- DockArea->currentDockWidget()->hideDockWidget();
- // As long as there are open dock widgets, we do not close the floating
- // window
- if (DockArea->openDockWidgets().count())
- {
- event->ignore();
- }
- }
-}
-
-
-//============================================================================
-bool CFloatingDockContainer::event(QEvent *e)
-{
- if ((e->type() == QEvent::NonClientAreaMouseButtonPress))
- {
- if (QGuiApplication::mouseButtons() == Qt::LeftButton)
- {
- std::cout << "FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type() << std::endl;
- d->setDraggingActive(true);
- }
- }
- else if (e->type() == QEvent::NonClientAreaMouseButtonDblClick)
- {
- std::cout << "FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick" << std::endl;
- d->setDraggingActive(false);
- }
- else if ((e->type() == QEvent::NonClientAreaMouseButtonRelease) && d->DraggingActive)
- {
- std::cout << "FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease" << std::endl;
- d->titleMouseReleaseEvent();
- }
-
- return QWidget::event(e);
-}
-
-
-//============================================================================
-bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *event)
-{
- if (event->type() == QEvent::MouseButtonRelease && d->DraggingActive)
- {
- std::cout << "FloatingWidget::eventFilter QEvent::MouseButtonRelease" << std::endl;
- d->titleMouseReleaseEvent();
- }
-
- return false;
-}
-
-
-//============================================================================
-void CFloatingDockContainer::startFloating(const QPoint& Pos, const QSize& Size)
-{
- resize(Size);
- d->setDraggingActive(true);
- QPoint TargetPos = QCursor::pos() - Pos;
- move(TargetPos);
- show();
- d->DragStartMousePosition = Pos;
-}
-
-
-//============================================================================
-void CFloatingDockContainer::moveFloating()
-{
- int BorderSize = (frameSize().width() - size().width()) / 2;
- const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition - QPoint(BorderSize, 0);
- move(moveToPos);
-}
-
-
-//============================================================================
-void CFloatingDockContainer::onDockAreasAddedOrRemoved()
-{
- if (d->DockContainer->dockAreaCount() == 1)
- {
- d->SingleDockArea = d->DockContainer->dockArea(0);
- this->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
- connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
- SLOT(onDockAreaCurrentChanged(int)));
- }
- else
- {
- if (d->SingleDockArea)
- {
- disconnect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
- SLOT(onDockAreaCurrentChanged(int)));
- d->SingleDockArea = nullptr;
- }
- this->setWindowTitle(qApp->applicationDisplayName());
- }
-}
-
-
-//============================================================================
-void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
-{
- this->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
-}
-
-
-} // namespace ads
-
-//---------------------------------------------------------------------------
-// EOF FloatingDockContainer.cpp
+/*******************************************************************************
+** QtAdcancedDockingSystem
+** Copyright (C) 2017 Uwe Kindler
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+******************************************************************************/
+
+
+//============================================================================
+/// \file FloatingDockContainer.cpp
+/// \author Uwe Kindler
+/// \date 01.03.2017
+/// \brief Implementation of CFloatingDockContainer class
+//============================================================================
+
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include "FloatingDockContainer.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "DockContainerWidget.h"
+#include "DockAreaWidget.h"
+#include "DockManager.h"
+#include "DockWidget.h"
+#include "DockOverlay.h"
+
+
+namespace ads
+{
+static unsigned int zOrderCounter = 0;
+
+/**
+ * Private data class of CFloatingDockContainer class (pimpl)
+ */
+struct FloatingDockContainerPrivate
+{
+ CFloatingDockContainer* _this;
+ CDockContainerWidget* DockContainer;
+ unsigned int zOrderIndex = ++zOrderCounter;
+ QPointer DockManager;
+ bool DraggingActive = false;
+ QPoint DragStartMousePosition;
+ CDockContainerWidget* DropContainer = nullptr;
+ CDockAreaWidget* SingleDockArea = nullptr;
+
+ /**
+ * Private data constructor
+ */
+ FloatingDockContainerPrivate(CFloatingDockContainer* _public);
+
+ void titleMouseReleaseEvent();
+ void updateDropOverlays(const QPoint& GlobalPos);
+ void setDraggingActive(bool Active);
+};
+// struct FloatingDockContainerPrivate
+
+//============================================================================
+FloatingDockContainerPrivate::FloatingDockContainerPrivate(CFloatingDockContainer* _public) :
+ _this(_public)
+{
+
+}
+
+
+
+//============================================================================
+void FloatingDockContainerPrivate::titleMouseReleaseEvent()
+{
+ setDraggingActive(false);
+ if (!DropContainer)
+ {
+ return;
+ }
+
+ std::cout << "Dropped" << std::endl;
+ DropContainer->dropFloatingWidget(_this, QCursor::pos());
+ DockManager->containerOverlay()->hideOverlay();
+ DockManager->dockAreaOverlay()->hideOverlay();
+}
+
+
+
+//============================================================================
+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;
+ }
+
+ if (DockContainer == ContainerWidget)
+ {
+ continue;
+ }
+
+ 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();
+
+ if (!TopContainer)
+ {
+ ContainerOverlay->hideOverlay();
+ DockAreaOverlay->hideOverlay();
+ return;
+ }
+
+ ContainerOverlay->setAllowedAreas(TopContainer->dockAreaCount() > 1 ?
+ OuterDockAreas : AllDockAreas);
+ ContainerOverlay->showOverlay(TopContainer);
+ ContainerOverlay->raise();
+
+ auto DockArea = TopContainer->dockAreaAt(GlobalPos);
+ if (DockArea && TopContainer->dockAreaCount() > 1)
+ {
+ DockAreaOverlay->setAllowedAreas(AllDockAreas);
+ DockAreaOverlay->showOverlay(DockArea);
+ }
+ else
+ {
+ DockAreaOverlay->hideOverlay();
+ }
+}
+
+
+//============================================================================
+void FloatingDockContainerPrivate::setDraggingActive(bool Active)
+{
+ DraggingActive = Active;
+}
+
+
+//============================================================================
+CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) :
+ QWidget(DockManager, Qt::Window),
+ d(new FloatingDockContainerPrivate(this))
+{
+ //setAttribute(Qt::WA_DeleteOnClose);
+ d->DockManager = DockManager;
+ QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+ setLayout(l);
+
+ d->DockContainer = new CDockContainerWidget(DockManager, this);
+ connect(d->DockContainer, SIGNAL(dockAreasAdded()), this, SLOT(onDockAreasAddedOrRemoved()));
+ connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this, SLOT(onDockAreasAddedOrRemoved()));
+ l->addWidget(d->DockContainer);
+ 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);
+}
+
+
+//============================================================================
+CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget* DockArea) :
+ CFloatingDockContainer(DockArea->dockManager())
+{
+ d->DockContainer->addDockArea(DockArea);
+}
+
+
+//============================================================================
+CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) :
+ CFloatingDockContainer(DockWidget->dockManager())
+{
+ d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
+}
+
+//============================================================================
+CFloatingDockContainer::~CFloatingDockContainer()
+{
+ std::cout << "~CFloatingDockContainer" << std::endl;
+ if (d->DockManager)
+ {
+ d->DockManager->removeFloatingWidget(this);
+ }
+ delete d;
+}
+
+
+//============================================================================
+CDockContainerWidget* CFloatingDockContainer::dockContainer() const
+{
+ return d->DockContainer;
+}
+
+
+//============================================================================
+void CFloatingDockContainer::changeEvent(QEvent *event)
+{
+ QWidget::changeEvent(event);
+ if ((event->type() == QEvent::ActivationChange) && isActiveWindow())
+ {
+ std::cout << "FloatingWidget::changeEvent QEvent::ActivationChange " << std::endl;
+ d->zOrderIndex = ++zOrderCounter;
+ return;
+ }
+}
+
+
+//============================================================================
+void CFloatingDockContainer::moveEvent(QMoveEvent *event)
+{
+ QWidget::moveEvent(event);
+ if (!qApp->mouseButtons().testFlag(Qt::LeftButton))
+ {
+ if (d->DraggingActive)
+ {
+ d->setDraggingActive(false);
+ }
+ return;
+ }
+
+ if (d->DraggingActive)
+ {
+ d->updateDropOverlays(QCursor::pos());
+ }
+}
+
+
+//============================================================================
+void CFloatingDockContainer::closeEvent(QCloseEvent *event)
+{
+ d->setDraggingActive(false);
+ QWidget::closeEvent(event);
+
+}
+
+
+//============================================================================
+void CFloatingDockContainer::hideEvent(QHideEvent *event)
+{
+ QWidget::hideEvent(event);
+ auto OpenDockAreas = d->DockContainer->openedDockAreas();
+ for (auto DockArea : OpenDockAreas)
+ {
+ auto OpenDockWidgets = DockArea->openedDockWidgets();
+ for (auto DockWidget : OpenDockWidgets)
+ {
+ DockWidget->setToggleViewActionChecked(false);
+ }
+ }
+}
+
+
+//============================================================================
+void CFloatingDockContainer::showEvent(QShowEvent *event)
+{
+ QWidget::showEvent(event);
+ CDockContainerWidget* DockContainer = dockContainer();
+ for (int i = 0; i < DockContainer->dockAreaCount(); ++i)
+ {
+ auto DockArea = DockContainer->dockArea(i);
+ for (auto DockWidget : DockArea->openedDockWidgets())
+ {
+ DockWidget->setToggleViewActionChecked(true);
+ }
+ }
+}
+
+
+//============================================================================
+bool CFloatingDockContainer::event(QEvent *e)
+{
+ if ((e->type() == QEvent::NonClientAreaMouseButtonPress))
+ {
+ if (QGuiApplication::mouseButtons() == Qt::LeftButton)
+ {
+ std::cout << "FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type() << std::endl;
+ d->setDraggingActive(true);
+ }
+ }
+ else if (e->type() == QEvent::NonClientAreaMouseButtonDblClick)
+ {
+ std::cout << "FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick" << std::endl;
+ d->setDraggingActive(false);
+ }
+ else if ((e->type() == QEvent::NonClientAreaMouseButtonRelease) && d->DraggingActive)
+ {
+ std::cout << "FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease" << std::endl;
+ d->titleMouseReleaseEvent();
+ }
+
+ return QWidget::event(e);
+}
+
+
+//============================================================================
+bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *event)
+{
+ if (event->type() == QEvent::MouseButtonRelease && d->DraggingActive)
+ {
+ std::cout << "FloatingWidget::eventFilter QEvent::MouseButtonRelease" << std::endl;
+ d->titleMouseReleaseEvent();
+ }
+
+ return false;
+}
+
+
+//============================================================================
+void CFloatingDockContainer::startFloating(const QPoint& Pos, const QSize& Size)
+{
+ resize(Size);
+ d->setDraggingActive(true);
+ QPoint TargetPos = QCursor::pos() - Pos;
+ move(TargetPos);
+ show();
+ d->DragStartMousePosition = Pos;
+}
+
+
+//============================================================================
+void CFloatingDockContainer::moveFloating()
+{
+ int BorderSize = (frameSize().width() - size().width()) / 2;
+ const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition - QPoint(BorderSize, 0);
+ move(moveToPos);
+}
+
+
+//============================================================================
+void CFloatingDockContainer::onDockAreasAddedOrRemoved()
+{
+ if (d->DockContainer->dockAreaCount() == 1)
+ {
+ d->SingleDockArea = d->DockContainer->dockArea(0);
+ this->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
+ connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
+ SLOT(onDockAreaCurrentChanged(int)));
+ }
+ else
+ {
+ if (d->SingleDockArea)
+ {
+ disconnect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
+ SLOT(onDockAreaCurrentChanged(int)));
+ d->SingleDockArea = nullptr;
+ }
+ this->setWindowTitle(qApp->applicationDisplayName());
+ }
+}
+
+
+//============================================================================
+void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
+{
+ this->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
+}
+
+
+} // namespace ads
+
+//---------------------------------------------------------------------------
+// EOF FloatingDockContainer.cpp
diff --git a/src/FloatingDockContainer.h b/src/FloatingDockContainer.h
index 503aa08..0841a56 100644
--- a/src/FloatingDockContainer.h
+++ b/src/FloatingDockContainer.h
@@ -1,108 +1,110 @@
-#ifndef FloatingDockContainerH
-#define FloatingDockContainerH
-/*******************************************************************************
-** QtAdcancedDockingSystem
-** Copyright (C) 2017 Uwe Kindler
-**
-** This program is free software: you can redistribute it and/or modify
-** it under the terms of the GNU General Public License as published by
-** the Free Software Foundation, either version 3 of the License, or
-** (at your option) any later version.
-**
-** This program 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 General Public License for more details.
-**
-** You should have received a copy of the GNU General Public License
-** along with this program. If not, see .
-******************************************************************************/
-
-
-//============================================================================
-/// \file FloatingDockContainer.h
-/// \author Uwe Kindler
-/// \date 01.03.2017
-/// \brief Declaration of CFloatingDockContainer class
-//============================================================================
-
-//============================================================================
-// INCLUDES
-//============================================================================
-#include
-
-namespace ads
-{
-struct FloatingDockContainerPrivate;
-class CDockAreaWidget;
-class CDockContainerWidget;
-class CDockWidget;
-class CDockManager;
-
-/**
- * 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
- */
-class CFloatingDockContainer : public QWidget
-{
- Q_OBJECT
-private:
- FloatingDockContainerPrivate* d; ///< private data (pimpl)
- friend class FloatingDockContainerPrivate;
-
-private slots:
- void onDockAreasAddedOrRemoved();
- void onDockAreaCurrentChanged(int Index);
-
-protected:
- /**
- * Private constructor that is called from public constructors
- */
- CFloatingDockContainer(CDockManager* DockManager);
-
-protected: // reimplements QWidget
- virtual void changeEvent(QEvent *event) override;
- virtual void moveEvent(QMoveEvent *event) override;
- virtual bool event(QEvent *e) override;
- virtual void closeEvent(QCloseEvent *event) override;
- virtual bool eventFilter(QObject *watched, QEvent *event) override;
-
-public:
- /**
- * Create floating widget with the given dock area
- */
- CFloatingDockContainer(CDockAreaWidget* DockArea);
-
- /**
- * Create floating widget with the given dock widget
- */
- CFloatingDockContainer(CDockWidget* DockWidget);
-
- /**
- * Virtual Destructor
- */
- virtual ~CFloatingDockContainer();
-
- /**
- * Access function for the internal dock container
- */
- CDockContainerWidget* dockContainer() const;
-
- /**
- * Starts floating at the given global position.
- * Use moveToGlobalPos() to move the widget to a new position
- * depending on the start position given in Pos parameter
- */
- void startFloating(const QPoint& Pos, const QSize& Size = QSize());
-
- /**
- * Moves the widget to a new position relative to the position given when
- * startFloating() was called
- */
- void moveFloating();
-}; // class FloatingDockContainer
-}
- // namespace ads
-//-----------------------------------------------------------------------------
-#endif // FloatingDockContainerH
+#ifndef FloatingDockContainerH
+#define FloatingDockContainerH
+/*******************************************************************************
+** QtAdcancedDockingSystem
+** Copyright (C) 2017 Uwe Kindler
+**
+** This program is free software: you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program 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 General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see .
+******************************************************************************/
+
+
+//============================================================================
+/// \file FloatingDockContainer.h
+/// \author Uwe Kindler
+/// \date 01.03.2017
+/// \brief Declaration of CFloatingDockContainer class
+//============================================================================
+
+//============================================================================
+// INCLUDES
+//============================================================================
+#include
+
+namespace ads
+{
+struct FloatingDockContainerPrivate;
+class CDockAreaWidget;
+class CDockContainerWidget;
+class CDockWidget;
+class CDockManager;
+
+/**
+ * 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
+ */
+class CFloatingDockContainer : public QWidget
+{
+ Q_OBJECT
+private:
+ FloatingDockContainerPrivate* d; ///< private data (pimpl)
+ friend class FloatingDockContainerPrivate;
+
+private slots:
+ void onDockAreasAddedOrRemoved();
+ void onDockAreaCurrentChanged(int Index);
+
+protected:
+ /**
+ * Private constructor that is called from public constructors
+ */
+ CFloatingDockContainer(CDockManager* DockManager);
+
+protected: // reimplements QWidget
+ virtual void changeEvent(QEvent *event) override;
+ virtual void moveEvent(QMoveEvent *event) override;
+ virtual bool event(QEvent *e) override;
+ virtual void closeEvent(QCloseEvent *event) override;
+ virtual void hideEvent(QHideEvent *event) override;
+ virtual void showEvent(QShowEvent *event) override;
+ virtual bool eventFilter(QObject *watched, QEvent *event) override;
+
+public:
+ /**
+ * Create floating widget with the given dock area
+ */
+ CFloatingDockContainer(CDockAreaWidget* DockArea);
+
+ /**
+ * Create floating widget with the given dock widget
+ */
+ CFloatingDockContainer(CDockWidget* DockWidget);
+
+ /**
+ * Virtual Destructor
+ */
+ virtual ~CFloatingDockContainer();
+
+ /**
+ * Access function for the internal dock container
+ */
+ CDockContainerWidget* dockContainer() const;
+
+ /**
+ * Starts floating at the given global position.
+ * Use moveToGlobalPos() to move the widget to a new position
+ * depending on the start position given in Pos parameter
+ */
+ void startFloating(const QPoint& Pos, const QSize& Size = QSize());
+
+ /**
+ * Moves the widget to a new position relative to the position given when
+ * startFloating() was called
+ */
+ void moveFloating();
+}; // class FloatingDockContainer
+}
+ // namespace ads
+//-----------------------------------------------------------------------------
+#endif // FloatingDockContainerH