From 67199a81f4ac461ee3807c27ffb0ab352199217f Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Fri, 7 Sep 2018 11:10:14 +0200 Subject: [PATCH] Fixed docking into empty main dock container, fixed tab handling to properly show the right dock widget tab when removing a dock widget, fixed tab menu to only show visible tabs, tab menu is now dynamically created just befor menu is shown --- src/DockAreaTabBar.cpp | 5 ++ src/DockAreaWidget.cpp | 107 +++++++++++++++++++++++++++++----- src/DockAreaWidget.h | 19 +++++- src/DockContainerWidget.cpp | 49 ++++++++++++++-- src/DockContainerWidget.h | 7 +++ src/DockManager.cpp | 27 ++++++++- src/DockManager.h | 16 +++++ src/DockWidget.cpp | 79 ++++++++++++++++--------- src/DockWidget.h | 21 ++++++- src/DockWidgetTab.cpp | 1 + src/FloatingDockContainer.cpp | 19 ++++++ src/FloatingDockContainer.h | 15 +++++ 12 files changed, 316 insertions(+), 49 deletions(-) diff --git a/src/DockAreaTabBar.cpp b/src/DockAreaTabBar.cpp index 8dbaec2..85ccb10 100644 --- a/src/DockAreaTabBar.cpp +++ b/src/DockAreaTabBar.cpp @@ -18,6 +18,7 @@ #include "DockAreaWidget.h" #include "DockOverlay.h" #include "DockManager.h" +#include "DockWidget.h" namespace ads { @@ -166,6 +167,10 @@ void CDockAreaTabBar::startFloating(const QPoint& Pos) CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(d->DockArea); FloatingWidget->startFloating(Pos, Size); d->FloatingWidget = FloatingWidget; + if (d->FloatingWidget->hasSingleDockWidget()) + { + emit d->FloatingWidget->firstDockWidget()->topLevelChanged(true); + } } } // namespace ads diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index b4e9fe0..512921f 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include "DockContainerWidget.h" @@ -50,11 +51,14 @@ #include "DockOverlay.h" #include "DockAreaTabBar.h" +#include + namespace ads { static const char* const INDEX_PROPERTY = "index"; static const char* const ACTION_PROPERTY = "action"; +static const char* const DOCKWIDGET_PROPERTY = "dockwidget"; static const int APPEND = -1; @@ -75,6 +79,8 @@ struct DockAreaWidgetPrivate QPushButton* CloseButton; int TabsLayoutInitCount; CDockManager* DockManager = nullptr; + QVector OpenDockWidgets; + bool MenuOutdated = true; /** * Private data constructor @@ -99,7 +105,7 @@ struct DockAreaWidgetPrivate */ CDockWidgetTab* titleWidgetAt(int index) { - return dockWidgetAt(index)->titleBar(); + return dockWidgetAt(index)->tabWidget(); } /** @@ -130,6 +136,11 @@ struct DockAreaWidgetPrivate * Update the tabs menu if dock widget order changed or if dock widget has * been removed */ + void markTabsMenuOutdated(); + + /** + * Updates the tabs menu if it is outdated + */ void updateTabsMenu(); /** @@ -178,7 +189,9 @@ void DockAreaWidgetPrivate::createTabBar() TabsMenuButton->setFlat(true); TabsMenuButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton)); TabsMenuButton->setMaximumWidth(TabsMenuButton->iconSize().width()); - TabsMenuButton->setMenu(new QMenu(TabsMenuButton)); + QMenu* TabsMenu = new QMenu(TabsMenuButton); + _this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow())); + TabsMenuButton->setMenu(TabsMenu); TopLayout->addWidget(TabsMenuButton, 0); TabsMenuButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)), @@ -232,20 +245,39 @@ void DockAreaWidgetPrivate::addTabsMenuEntry(CDockWidget* DockWidget, { Action = menu->addAction(DockWidget->icon(), DockWidget->windowTitle()); } + Action->setProperty(DOCKWIDGET_PROPERTY, QVariant::fromValue(DockWidget)); QVariant vAction = QVariant::fromValue(Action); DockWidget->setProperty(ACTION_PROPERTY, vAction); } +//============================================================================ +void DockAreaWidgetPrivate::markTabsMenuOutdated() +{ + MenuOutdated = true; +} + + //============================================================================ void DockAreaWidgetPrivate::updateTabsMenu() { + if (!MenuOutdated) + { + return; + } + QMenu* menu = TabsMenuButton->menu(); menu->clear(); for (int i = 0; i < ContentsLayout->count(); ++i) { + if (dockWidgetAt(i)->isClosed()) + { + continue; + } addTabsMenuEntry(dockWidgetAt(i), APPEND, menu); } + + MenuOutdated = false; } @@ -313,17 +345,16 @@ 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->tabWidget()->setDockAreaWidget(this); + auto TabWidget = DockWidget->tabWidget(); + d->TabsLayout->insertWidget(index, TabWidget); + TabWidget->show(); + connect(TabWidget, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked())); DockWidget->setProperty(INDEX_PROPERTY, index); if (Activate) { setCurrentIndex(index); } - d->addTabsMenuEntry(DockWidget, index); DockWidget->setDockArea(this); } @@ -332,13 +363,18 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget, void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) { qDebug() << "CDockAreaWidget::removeDockWidget"; + auto NextDockWidget = nextOpenDockWidget(DockWidget); + d->ContentsLayout->removeWidget(DockWidget); - auto TitleBar = DockWidget->titleBar(); + auto TitleBar = DockWidget->tabWidget(); TitleBar->hide(); d->TabsLayout->removeWidget(TitleBar); disconnect(TitleBar, SIGNAL(clicked()), this, SLOT(onDockWidgetTitleClicked())); - setCurrentIndex(d->ContentsLayout->currentIndex()); - d->updateTabsMenu(); + if (NextDockWidget) + { + setCurrentDockWidget(NextDockWidget); + d->markTabsMenuOutdated(); + } CDockContainerWidget* DockContainer = dockContainer(); if (d->ContentsLayout->isEmpty()) @@ -550,7 +586,6 @@ void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex) Menu->insertAction(Menu->actions().at(toIndex), TabsAction); } - // now reorder contents and title bars QLayoutItem* liFrom = nullptr; liFrom = d->TabsLayout->takeAt(fromIndex); @@ -561,11 +596,21 @@ void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex) } +//============================================================================ +void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open) +{ + Q_UNUSED(DockWidget); + Q_UNUSED(Open); + d->markTabsMenuOutdated(); +} + + //============================================================================ void CDockAreaWidget::onTabsMenuActionTriggered(QAction* Action) { - int Index = d->TabsMenuButton->menu()->actions().indexOf(Action); - setCurrentIndex(Index); + QVariant vDockWidget = Action->property(DOCKWIDGET_PROPERTY); + CDockWidget* DockWidget = vDockWidget.value(); + setCurrentDockWidget(DockWidget); } @@ -591,6 +636,40 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const s.writeEndElement(); } + +//============================================================================ +CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const +{ + auto OpenDockWidgets = openedDockWidgets(); + if (OpenDockWidgets.count() > 1) + { + CDockWidget* NextDockWidget; + if (OpenDockWidgets.last() == DockWidget) + { + NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2]; + } + else + { + int NextIndex = OpenDockWidgets.indexOf(DockWidget) + 1; + NextDockWidget = OpenDockWidgets[NextIndex]; + } + + return NextDockWidget; + } + else + { + return nullptr; + } +} + + +//============================================================================ +void CDockAreaWidget::onTabsMenuAboutToShow() +{ + std::cout << "CDockAreaWidget::onTabsMenuAboutToShow()" << std::endl; + d->updateTabsMenu(); +} + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index 7643d91..c2e9a30 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -59,11 +59,14 @@ private: friend class CDockContainerWidget; friend class DockContainerWidgetPrivate; friend class CDockWidgetTab; + friend struct DockWidgetPrivate; + friend class CDockWidget; private slots: void onDockWidgetTitleClicked(); void onTabsMenuActionTriggered(QAction* Action); void onCloseButtonClicked(); + void onTabsMenuAboutToShow(); protected: /** @@ -97,6 +100,18 @@ protected: */ void reorderDockWidget(int fromIndex, int toIndex); + /** + * Called from dock widget if it is opened or closed + */ + void toggleDockWidgetView(CDockWidget* DockWidget, bool Open); + + /** + * This is a helper function to get the next open dock widget to activate + * if the given DockWidget will be closed or removed. + * The function returns the next widget that should be activated or + * nullptr in case there are no more open widgets in this area. + */ + CDockWidget* nextOpenDockWidget(CDockWidget* DockWidget) const; public: /** @@ -178,7 +193,9 @@ public: public slots: /** - * This sets the index position of the current tab page. + * This activates the tab for the given tab index. + * If the dock widget for the given tab is not visible, the this function + * call will make it visible. */ void setCurrentIndex(int index); diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 1d8eaad..9994354 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -54,6 +54,26 @@ namespace ads { static unsigned int zOrderCounter = 0; + +/** + * Converts dock area ID to an index for array access + */ +static int areaIdToIndex(DockWidgetArea area) +{ + switch (area) + { + case LeftDockWidgetArea: return 0; + case RightDockWidgetArea: return 1; + case TopDockWidgetArea: return 2; + case BottomDockWidgetArea: return 3; + case CenterDockWidgetArea: return 4; + default: + return 4; + } + + return 4; +} + /** * Helper function to ease insertion of dock area into splitter */ @@ -81,6 +101,7 @@ struct DockContainerWidgetPrivate QGridLayout* Layout = nullptr; QSplitter* RootSplitter; bool isFloating = false; + CDockAreaWidget* LastAddedAreaCache[5]{0, 0, 0, 0, 0}; /** * Private data constructor @@ -172,7 +193,6 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float auto InsertParam = internal::dockAreaInsertParameters(area); auto NewDockAreas = FloatingWidget->dockContainer()->findChildren( QString(), Qt::FindChildrenRecursively); - CDockWidget* DockWidget = FloatingWidget->dockContainer()->findChild(); QSplitter* Splitter = RootSplitter; if (DockAreas.count() <= 1) @@ -209,9 +229,12 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float RootSplitter = Splitter; addDockAreasToList(NewDockAreas); FloatingWidget->deleteLater(); - if (DockWidget) + // If we dropped the floating widget into the main dock container that does + // not contain any dock widgets, then splitter is invisible and we need to + // show it to display the docked widgets + if (!Splitter->isVisible()) { - DockWidget->toggleView(true); + Splitter->show(); } _this->dumpLayout(); } @@ -503,6 +526,8 @@ bool DockContainerWidgetPrivate::restoreDockArea(QXmlStreamReader& s, qDebug() << "Dock Widget found - parent " << DockWidget->parent(); DockArea->addDockWidget(DockWidget); + // We hide the DockArea here to prevent the short display (the flashing) + // of the dock areas during application startup DockArea->hide(); DockWidget->setToggleViewActionChecked(!Closed); DockWidget->setProperty("closed", Closed); @@ -565,6 +590,7 @@ CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoContainer(DockWidgetA CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this); NewDockArea->addDockWidget(Dockwidget); addDockArea(NewDockArea, area); + LastAddedAreaCache[areaIdToIndex(area)] = NewDockArea; return NewDockArea; } @@ -689,7 +715,6 @@ CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *p { d->isFloating = dynamic_cast(parent) != 0; - //setStyleSheet("background: green;"); d->DockManager = DockManager; if (DockManager != this) { @@ -905,6 +930,8 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi CDockAreaWidget* DockArea = dockAreaAt(TargetPos); auto dropArea = InvalidDockWidgetArea; auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); + CDockWidget* TopLevelDockWidget = FloatingWidget->hasSingleDockWidget() ? + FloatingWidget->firstDockWidget() : nullptr; if (DockArea) { auto dropOverlay = d->DockManager->dockAreaOverlay(); @@ -933,6 +960,13 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi d->dropIntoContainer(FloatingWidget, dropArea); } } + + // If we drop a floating widget with only one single dock widget, then we + // drop a top level widget that changes from floating to docked now + if (TopLevelDockWidget) + { + emit TopLevelDockWidget->topLevelChanged(false); + } } @@ -1047,6 +1081,13 @@ void CDockContainerWidget::dumpLayout() } +//============================================================================ +CDockAreaWidget* CDockContainerWidget::lastAddedDockAreaWidget(DockWidgetArea area) const +{ + return d->LastAddedAreaCache[areaIdToIndex(area)]; +} + + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index bf6b92d..40ff2c1 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -103,6 +103,13 @@ protected: */ bool restoreState(QXmlStreamReader& Stream, bool Testing); + /** + * This function returns the last added dock area widget for the given + * area identifier or 0 if no dock area widget has been added for the given + * area + */ + CDockAreaWidget* lastAddedDockAreaWidget(DockWidgetArea area) const; + public: /** * Default Constructor diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 27d436c..be6d770 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -361,7 +361,8 @@ bool CDockManager::restoreState(const QByteArray &state, int version) { CDockAreaWidget* DockArea = DockContainer->dockArea(i); int CurrentIndex = DockArea->property("currentIndex").toInt(); - if (CurrentIndex < DockArea->count() && DockArea->count() > 1 && CurrentIndex > -1) + int OpenDockWidgetCount = DockArea->openedDockWidgets().count(); + if (CurrentIndex < OpenDockWidgetCount && OpenDockWidgetCount > 1 && CurrentIndex > -1) { DockArea->setCurrentIndex(CurrentIndex); } @@ -382,6 +383,30 @@ CDockAreaWidget* CDockManager::addDockWidget(DockWidgetArea area, } +//============================================================================ +CDockAreaWidget* CDockManager::addDockWidgetTab(DockWidgetArea area, + CDockWidget* Dockwidget) +{ + CDockAreaWidget* AreaWidget = lastAddedDockAreaWidget(area); + if (AreaWidget) + { + return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, AreaWidget); + } + else + { + return addDockWidget(area, Dockwidget, AreaWidget); + } +} + + +//============================================================================ +CDockAreaWidget* CDockManager::addDockWidgetTabToArea(CDockWidget* Dockwidget, + CDockAreaWidget* DockAreaWidget) +{ + return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, DockAreaWidget); +} + + //============================================================================ CDockWidget* CDockManager::findDockWidget(const QString& ObjectName) { diff --git a/src/DockManager.h b/src/DockManager.h index c3c577c..3b14214 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -128,6 +128,22 @@ public: CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget, CDockAreaWidget* DockAreaWidget = nullptr); + /** + * This function will add the given Dockwidget to the given dock area as + * a new tab. + * If no dock area widget exists for the given area identifier, a new + * dock area widget is created. + */ + CDockAreaWidget* addDockWidgetTab(DockWidgetArea area, + CDockWidget* Dockwidget); + + /** + * This function will add the given Dockwidget to the given DockAreaWidget + * as a new tab. + */ + CDockAreaWidget* addDockWidgetTabToArea(CDockWidget* Dockwidget, + CDockAreaWidget* DockAreaWidget); + /** * Searches for a registered doc widget with the given ObjectName * \return Return the found dock widget or nullptr if a dock widget with the diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index dee18ff..e56dcbc 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -59,7 +59,7 @@ struct DockWidgetPrivate CDockWidget* _this; QBoxLayout* Layout; QWidget* Widget = nullptr; - CDockWidgetTab* TitleWidget; + CDockWidgetTab* TabWidget; CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures; CDockManager* DockManager = nullptr; CDockAreaWidget* DockArea = nullptr; @@ -87,9 +87,11 @@ struct DockWidgetPrivate void hideEmptyParentSplitters(); /** - * Hides a dock area if all dock widgets in the area are closed + * Hides a dock area if all dock widgets in the area are closed. + * This function updates the current selected tab and hides the parent + * dock area if it is empty */ - void hideEmptyParentDockArea(); + void updateParentDockArea(); /** * Hides a floating widget if all dock areas are empty - that means, @@ -141,8 +143,8 @@ void DockWidgetPrivate::showDockWidget() //============================================================================ void DockWidgetPrivate::hideDockWidget() { - TitleWidget->hide(); - hideEmptyParentDockArea(); + TabWidget->hide(); + updateParentDockArea(); hideEmptyParentSplitters(); hideEmptyFloatingWidget(); } @@ -164,22 +166,11 @@ void DockWidgetPrivate::hideEmptyParentSplitters() //============================================================================ -void DockWidgetPrivate::hideEmptyParentDockArea() +void DockWidgetPrivate::updateParentDockArea() { - auto OpenDockWidgets = DockArea->openedDockWidgets(); - if (OpenDockWidgets.count() > 1) + auto NextDockWidget = DockArea->nextOpenDockWidget(_this); + if (NextDockWidget) { - 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 @@ -213,7 +204,7 @@ CDockWidget::CDockWidget(const QString &title, QWidget *parent) : setWindowTitle(title); setObjectName(title); - d->TitleWidget = new CDockWidgetTab(this); + d->TabWidget = new CDockWidgetTab(this); d->ToggleViewAction = new QAction(title); d->ToggleViewAction->setCheckable(true); connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this, @@ -262,9 +253,9 @@ QWidget* CDockWidget::widget() const //============================================================================ -CDockWidgetTab* CDockWidget::titleBar() const +CDockWidgetTab* CDockWidget::tabWidget() const { - return d->TitleWidget; + return d->TabWidget; } @@ -320,7 +311,39 @@ CDockAreaWidget* CDockWidget::dockAreaWidget() const //============================================================================ bool CDockWidget::isFloating() const { - return dockContainer() ? dockContainer()->isFloating() : false; + if (!isInFloatingContainer()) + { + return false; + } + + if (dockContainer()->dockAreaCount() != 1) + { + return false; + } + + if (dockContainer()->dockArea(0)->count() != 1) + { + return false; + } + + return true; +} + + +//============================================================================ +bool CDockWidget::isInFloatingContainer() const +{ + if (!dockContainer()) + { + return false; + } + + if (!dockContainer()->isFloating()) + { + return false; + } + + return true; } @@ -349,7 +372,7 @@ void CDockWidget::setToggleViewActionMode(eToggleViewActionMode Mode) else { d->ToggleViewAction->setCheckable(false); - d->ToggleViewAction->setIcon(d->TitleWidget->icon()); + d->ToggleViewAction->setIcon(d->TabWidget->icon()); } } @@ -375,6 +398,8 @@ void CDockWidget::toggleView(bool Open) d->ToggleViewAction->blockSignals(true); d->ToggleViewAction->setChecked(Open); d->ToggleViewAction->blockSignals(false); + d->DockArea->toggleDockWidgetView(this, Open); + if (!Open) { emit closed(); @@ -406,7 +431,7 @@ void CDockWidget::flagAsUnassigned() { setParent(d->DockManager); setDockArea(nullptr); - titleBar()->setParent(this); + tabWidget()->setParent(this); } @@ -424,7 +449,7 @@ bool CDockWidget::event(QEvent *e) //============================================================================ void CDockWidget::setIcon(const QIcon& Icon) { - d->TitleWidget->setIcon(Icon); + d->TabWidget->setIcon(Icon); if (!d->ToggleViewAction->isCheckable()) { d->ToggleViewAction->setIcon(Icon); @@ -435,7 +460,7 @@ void CDockWidget::setIcon(const QIcon& Icon) //============================================================================ QIcon CDockWidget::icon() const { - return d->TitleWidget->icon(); + return d->TabWidget->icon(); } diff --git a/src/DockWidget.h b/src/DockWidget.h index 5569f65..5aa9bf5 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -164,7 +164,7 @@ public: /** * Returns the title bar widget of this dock widget */ - CDockWidgetTab* titleBar() const; + CDockWidgetTab* tabWidget() const; /** * Sets, whether the dock widget is movable, closable, and floatable. @@ -193,7 +193,7 @@ public: /** * Returns the dock container widget this dock area widget belongs to or 0 - * if this dock widget has nt been docked yet + * if this dock widget has not been docked yet */ CDockContainerWidget* dockContainer() const; @@ -205,9 +205,19 @@ public: /** * This property holds whether the dock widget is floating. + * A dock widget is only floating, if it is the one and only widget inside + * of a floating container. If there are more than one dock widget in a + * floating container, the all dock widgets are docked and not floating. */ bool isFloating() const; + /** + * This function returns true, if this dock widget is in a floating. + * The function returns true, if the dock widget is floating and it also + * returns true if it is docked inside of a floating container. + */ + bool isInFloatingContainer() const; + /** * Returns true, if this dock widget is closed. */ @@ -266,6 +276,13 @@ signals: * changed */ void titleChanged(const QString& Title); + + /** + * This signal is emitted when the floating property changes. + * The topLevel parameter is true if the dock widget is now floating; + * otherwise it is false. + */ + void topLevelChanged(bool topLevel); }; // class DockWidget } // namespace ads diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index 2b43e88..5572551 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -196,6 +196,7 @@ bool DockWidgetTabPrivate::startFloating() auto Overlay = DockWidget->dockManager()->containerOverlay(); Overlay->setAllowedAreas(OuterDockAreas); this->FloatingWidget = FloatingWidget; + emit DockWidget->topLevelChanged(true); return true; } diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 51eed38..9155190 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -481,6 +481,25 @@ bool CFloatingDockContainer::restoreState(QXmlStreamReader& Stream, bool Testing } +//============================================================================ +bool CFloatingDockContainer::hasSingleDockWidget() const +{ + if (d->DockContainer->dockAreaCount() != 1) + { + return false; + } + + return d->DockContainer->dockArea(0)->count() == 1; +} + + +//============================================================================ +CDockWidget* CFloatingDockContainer::firstDockWidget() const +{ + return d->DockContainer->dockArea(0)->dockWidget(0); +} + + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/FloatingDockContainer.h b/src/FloatingDockContainer.h index 5f9d6cf..dfe0100 100644 --- a/src/FloatingDockContainer.h +++ b/src/FloatingDockContainer.h @@ -132,6 +132,21 @@ public: * It can be closed, if all dock widgets in all dock areas can be closed */ bool isClosable() const; + + /** + * This function returns true, if this floating widget has only one single + * dock widget in a single dock area. + * The single dock widget is a real top level floating widget because no + * other widgets are docked. + */ + bool hasSingleDockWidget() const; + + /** + * This function returns the first dock widget in the first dock area. + * If the function hasSingleDockWidget() returns true, then this function + * returns this single dock widget. + */ + CDockWidget* firstDockWidget() const; }; // class FloatingDockContainer } // namespace ads