From c973482b2bdce93704c03a6245ce00500a24259b Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 5 Nov 2018 09:07:18 +0100 Subject: [PATCH] Properly implemented showing and hiding of TitleBarUndockButton --- src/DockAreaWidget.cpp | 73 ++++++++++------ src/DockAreaWidget.h | 2 +- src/DockContainerWidget.cpp | 93 +++++++++++++++++--- src/DockContainerWidget.h | 6 ++ src/DockWidget.cpp | 2 +- src/FloatingDockContainer.cpp | 7 +- src/images/close-button-disabled.svg | 122 +++++++++++++++++++++++++++ src/images/close-button.svg | 119 ++++++++++++++++++++++++++ 8 files changed, 377 insertions(+), 47 deletions(-) create mode 100644 src/images/close-button-disabled.svg create mode 100644 src/images/close-button.svg diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index fe1b1ec..ead90dc 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -66,8 +66,8 @@ static const int APPEND = -1; /** - * New dock area layout mimics stack layout but ony inserts the current - * widget + * New dock area layout mimics stack layout but only inserts the current + * widget into the internal QLayout object */ class CDockAreaLayout { @@ -78,17 +78,27 @@ private: QWidget* m_CurrentWidget = nullptr; public: + /** + * Creates an instance with the given parent layout + */ CDockAreaLayout(QBoxLayout* ParentLayout) : m_ParentLayout(ParentLayout) { } + /** + * Returns the number of widgets in this layout + */ int count() const { return m_Widgets.count(); } + /** + * Inserts the widget at the given index position into the internal widget + * list + */ void insertWidget(int index, QWidget* Widget) { Widget->setParent(0); @@ -110,6 +120,9 @@ public: } } + /** + * Removes the given widget from the lyout + */ void removeWidget(QWidget* Widget) { if (currentWidget() == Widget) @@ -125,11 +138,17 @@ public: m_Widgets.removeOne(Widget); } + /** + * Returns the current selected widget + */ QWidget* currentWidget() const { return m_CurrentWidget; } + /** + * Activates the widget with the give index. + */ void setCurrentIndex(int index) { QWidget *prev = currentWidget(); @@ -169,26 +188,41 @@ public: } } + /** + * Returns the index of the current active widget + */ int currentIndex() const { return m_CurrentIndex; } + /** + * Returns true if there are no widgets in the layout + */ bool isEmpty() const { return m_Widgets.empty(); } + /** + * Returns the index of the given widget + */ int indexOf(QWidget* w) const { return m_Widgets.indexOf(w); } + /** + * Returns the widget for the given index + */ QWidget* widget(int index) const { return (index < m_Widgets.size()) ? m_Widgets.at(index) : nullptr; } + /** + * Returns the geometry of the current active widget + */ QRect geometry() const { return m_Widgets.empty() ? QRect() : currentWidget()->geometry(); @@ -254,12 +288,6 @@ struct DockAreaWidgetPrivate return DockWidget->property(INDEX_PROPERTY).toInt(); } - /** - * Updates the tab bar visibility depending on the number of dock widgets - * in this area - */ - void updateTitleBarVisibility(); - /** * Convenience function for tabbar access */ @@ -293,19 +321,6 @@ void DockAreaWidgetPrivate::createTitleBar() } -//============================================================================ -void DockAreaWidgetPrivate::updateTitleBarVisibility() -{ - CDockContainerWidget* Container = _this->dockContainer(); - if (!Container) - { - return; - } - - TitleBar->setVisible(!Container->isFloating() || !Container->hasTopLevelDockWidget()); -} - - //============================================================================ CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent) : QFrame(parent), @@ -402,7 +417,7 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) hideAreaWithNoVisibleContent(); } - d->updateTitleBarVisibility(); + updateTitleBarVisibility(); auto TopLevelDockWidget = dockContainer()->topLevelDockWidget(); if (TopLevelDockWidget) { @@ -440,7 +455,7 @@ void CDockAreaWidget::hideAreaWithNoVisibleContent() return; } - d->updateTitleBarVisibility(); + updateTitleBarVisibility(); auto TopLevelWidget = Container->topLevelDockWidget(); auto FloatingWidget = Container->floatingWidget(); if (TopLevelWidget) @@ -626,14 +641,20 @@ void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open) { Q_UNUSED(DockWidget); Q_UNUSED(Open); - updateTabBarVisibility(); + updateTitleBarVisibility(); } //============================================================================ -void CDockAreaWidget::updateTabBarVisibility() +void CDockAreaWidget::updateTitleBarVisibility() { - d->updateTitleBarVisibility(); + CDockContainerWidget* Container = dockContainer(); + if (!Container) + { + return; + } + + d->TitleBar->setVisible(!Container->isFloating() || !Container->hasTopLevelDockWidget()); } diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index 592b095..f66e1fd 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -121,7 +121,7 @@ protected: /** * Updates the dock area layout and components visibility */ - void updateTabBarVisibility(); + void updateTitleBarVisibility(); /** * This is the internal private function for setting the current widget. diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 0a19e3f..4dd1dfa 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include "DockManager.h" #include "DockAreaWidget.h" @@ -105,6 +106,7 @@ public: bool isFloating = false; CDockAreaWidget* LastAddedAreaCache[5]{0, 0, 0, 0, 0}; int VisibleDockAreaCount = -1; + CDockAreaWidget* TopLevelDockArea = nullptr; /** * Private data constructor @@ -144,6 +146,12 @@ public: */ void addDockAreasToList(const QList NewDockAreas); + /** + * Wrapper function for DockAreas append, that ensures that dock area signals + * are properly connected to dock container slots + */ + void appendDockAreas(const QList NewDockAreas); + /** * Save state of child nodes */ @@ -208,11 +216,31 @@ public: return VisibleDockAreaCount; } + /** + * The visible dock area count changes, if dock areas are remove, added or + * when its view is toggled + */ + void onVisibleDockAreaCountChanged(); + + void emitDockAreasRemoved() + { + onVisibleDockAreaCountChanged(); + emit _this->dockAreasRemoved(); + } + + void emitDockAreasAdded() + { + onVisibleDockAreaCountChanged(); + emit _this->dockAreasAdded(); + } + // private slots: ------------------------------------------------------------ void onDockAreaViewToggled(bool Visible) { - std::cout << "onDockAreaViewToggled " << Visible << std::endl; + CDockAreaWidget* DockArea = qobject_cast(_this->sender()); VisibleDockAreaCount += Visible ? 1 : -1; + onVisibleDockAreaCountChanged(); + emit _this->dockAreaViewToggled(DockArea, Visible); } }; // struct DockContainerWidgetPrivate @@ -225,6 +253,24 @@ DockContainerWidgetPrivate::DockContainerWidgetPrivate(CDockContainerWidget* _pu } +//============================================================================ +void DockContainerWidgetPrivate::onVisibleDockAreaCountChanged() +{ + auto TopLevelDockArea = _this->topLevelDockArea(); + + if (TopLevelDockArea) + { + this->TopLevelDockArea = TopLevelDockArea; + TopLevelDockArea->titleBarButton(TitleBarButtonUndock)->setVisible(false || !_this->isFloating()); + } + else if (this->TopLevelDockArea) + { + this->TopLevelDockArea->titleBarButton(TitleBarButtonUndock)->setVisible(true); + this->TopLevelDockArea = nullptr; + } +} + + //============================================================================ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* FloatingWidget, DockWidgetArea area) @@ -299,7 +345,7 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin } TargetArea->setCurrentIndex(0); // make the topmost widget active FloatingWidget->deleteLater(); - TargetArea->updateTabBarVisibility(); + TargetArea->updateTitleBarVisibility(); return; } @@ -364,21 +410,39 @@ void DockContainerWidgetPrivate::addDockAreasToList(const QListtitleBarButton(TitleBarButtonUndock)->setVisible(true); + } // 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)->updateTabBarVisibility(); + DockAreas.at(0)->updateTitleBarVisibility(); } if (1 == NewAreaCount) { - DockAreas.last()->updateTabBarVisibility(); + DockAreas.last()->updateTitleBarVisibility(); } - emit _this->dockAreasAdded(); + emitDockAreasAdded(); +} + + +//============================================================================ +void DockContainerWidgetPrivate::appendDockAreas(const QList NewDockAreas) +{ + DockAreas.append(NewDockAreas); + for (auto DockArea : NewDockAreas) + { + _this->connect(DockArea, SIGNAL(viewToggled(bool)), SLOT(onDockAreaViewToggled(bool))); + } } @@ -588,7 +652,7 @@ bool DockContainerWidgetPrivate::restoreDockArea(QXmlStreamReader& s, else { DockArea->setProperty("currentDockWidget", CurrentDockWidget); - DockAreas.append(DockArea); + appendDockAreas({DockArea}); } CreatedWidget = DockArea; @@ -631,7 +695,7 @@ CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoContainer(DockWidgetA CDockAreaWidget* NewDockArea = new CDockAreaWidget(DockManager, _this); NewDockArea->addDockWidget(Dockwidget); addDockArea(NewDockArea, area); - NewDockArea->updateTabBarVisibility(); + NewDockArea->updateTitleBarVisibility(); LastAddedAreaCache[areaIdToIndex(area)] = NewDockArea; return NewDockArea; } @@ -673,9 +737,9 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW RootSplitter = NewSplitter; } - DockAreas.append(NewDockArea); - NewDockArea->updateTabBarVisibility(); - emit _this->dockAreasAdded(); + appendDockAreas({NewDockArea}); + NewDockArea->updateTitleBarVisibility(); + emitDockAreasAdded(); } @@ -744,8 +808,8 @@ CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoDockArea(DockWidgetAr TargetAreaSplitter->insertWidget(index, NewSplitter); } - DockAreas.append(NewDockArea); - emit _this->dockAreasAdded(); + appendDockAreas({NewDockArea}); + emitDockAreasAdded(); return NewDockArea; } @@ -853,6 +917,7 @@ void CDockContainerWidget::addDockArea(CDockAreaWidget* DockAreaWidget, void CDockContainerWidget::removeDockArea(CDockAreaWidget* area) { qDebug() << "CDockContainerWidget::removeDockArea"; + area->disconnect(this); d->DockAreas.removeAll(area); CDockSplitter* Splitter = internal::findParent(area); @@ -913,7 +978,7 @@ emitAndExit: // one single visible dock widget CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true); dumpLayout(); - emit dockAreasRemoved(); + d->emitDockAreasRemoved(); } diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 7d90a3b..3dbf63c 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -240,6 +240,12 @@ signals: * This signal is emitted if one or multiple dock areas has been removed */ void dockAreasRemoved(); + + /** + * This signal is emitted if a dock area is opened or closed via + * toggleView() function + */ + void dockAreaViewToggled(CDockAreaWidget* DockArea, bool Open); }; // class DockContainerWidget } // namespace ads //----------------------------------------------------------------------------- diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index ed8016d..b1cb442 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -643,7 +643,7 @@ void CDockWidget::emitTopLevelEventForWidget(CDockWidget* TopLevelDockWidget, bo { if (TopLevelDockWidget) { - TopLevelDockWidget->dockAreaWidget()->updateTabBarVisibility(); + TopLevelDockWidget->dockAreaWidget()->updateTitleBarVisibility(); TopLevelDockWidget->emitTopLevelChanged(Floating); } } diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 6d97935..63de9e2 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -351,13 +351,13 @@ void CFloatingDockContainer::showEvent(QShowEvent *event) { std::cout << "CFloatingDockContainer showEvent" << std::endl; QWidget::showEvent(event); - for (auto DockArea : d->DockContainer->openedDockAreas()) + /*for (auto DockArea : d->DockContainer->openedDockAreas()) { for (auto DockWidget : DockArea->openedDockWidgets()) { DockWidget->setToggleViewActionChecked(true); } - } + }*/ } @@ -467,12 +467,10 @@ bool CFloatingDockContainer::isClosable() const void CFloatingDockContainer::onDockAreasAddedOrRemoved() { qDebug() << "CFloatingDockContainer::onDockAreasAddedOrRemoved()"; - std::cout << "CFloatingDockContainer::onDockAreasAddedOrRemoved()" << std::endl; auto TopLevelDockArea = d->DockContainer->topLevelDockArea(); if (TopLevelDockArea) { d->SingleDockArea = TopLevelDockArea; - d->SingleDockArea->titleBarButton(TitleBarButtonUndock)->setVisible(false); this->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle()); connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this, SLOT(onDockAreaCurrentChanged(int))); @@ -481,7 +479,6 @@ void CFloatingDockContainer::onDockAreasAddedOrRemoved() { if (d->SingleDockArea) { - d->SingleDockArea->titleBarButton(TitleBarButtonUndock)->setVisible(true); disconnect(d->SingleDockArea, SIGNAL(currentChanged(int)), this, SLOT(onDockAreaCurrentChanged(int))); d->SingleDockArea = nullptr; diff --git a/src/images/close-button-disabled.svg b/src/images/close-button-disabled.svg new file mode 100644 index 0000000..7bce2a8 --- /dev/null +++ b/src/images/close-button-disabled.svg @@ -0,0 +1,122 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/images/close-button.svg b/src/images/close-button.svg new file mode 100644 index 0000000..e6254df --- /dev/null +++ b/src/images/close-button.svg @@ -0,0 +1,119 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file