From 72ec61a04382631a6d1257a8c2527520dd11eff8 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Sat, 3 Nov 2018 20:51:02 +0100 Subject: [PATCH] Added access functions for the titlebar buttons --- src/DockAreaTabBar.cpp | 14 ++++++++-- src/DockAreaTabBar.h | 9 ++++++ src/DockAreaTitleBar.cpp | 39 ++++++++++++++++++++++++++ src/DockAreaTitleBar.h | 12 ++++++++ src/DockAreaWidget.cpp | 52 ++++++++++++++++++++++++++++------- src/DockAreaWidget.h | 13 +++++++-- src/DockContainerWidget.cpp | 4 --- src/DockManager.cpp | 28 ++++--------------- src/DockWidgetTab.cpp | 5 +--- src/FloatingDockContainer.cpp | 3 ++ src/FloatingDockContainer.h | 1 + src/ads_globals.h | 7 +++++ 12 files changed, 141 insertions(+), 46 deletions(-) diff --git a/src/DockAreaTabBar.cpp b/src/DockAreaTabBar.cpp index ecf4b62..e508779 100644 --- a/src/DockAreaTabBar.cpp +++ b/src/DockAreaTabBar.cpp @@ -214,17 +214,25 @@ void CDockAreaTabBar::mouseDoubleClickEvent(QMouseEvent *event) //============================================================================ -void CDockAreaTabBar::startFloating(const QPoint& Pos) +CFloatingDockContainer* CDockAreaTabBar::makeAreaFloating(const QPoint& Pos) { QSize Size = d->DockArea->size(); CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(d->DockArea); FloatingWidget->startFloating(Pos, Size); - d->FloatingWidget = FloatingWidget; - auto TopLevelDockWidget = d->FloatingWidget->topLevelDockWidget(); + auto TopLevelDockWidget = FloatingWidget->topLevelDockWidget(); if (TopLevelDockWidget) { TopLevelDockWidget->emitTopLevelChanged(true); } + + return FloatingWidget; +} + + +//============================================================================ +void CDockAreaTabBar::startFloating(const QPoint& Pos) +{ + d->FloatingWidget = makeAreaFloating(Pos); } diff --git a/src/DockAreaTabBar.h b/src/DockAreaTabBar.h index 5756643..727ad1d 100644 --- a/src/DockAreaTabBar.h +++ b/src/DockAreaTabBar.h @@ -36,6 +36,8 @@ namespace ads class CDockAreaWidget; class CDockWidgetTab; struct DockAreaTabBarPrivate; +class CDockAreaTitleBar; +class CFloatingDockContainer; /** * Custom tabbar implementation for tab area that is shown on top of a @@ -48,6 +50,7 @@ class CDockAreaTabBar : public QScrollArea private: DockAreaTabBarPrivate* d; ///< private data (pimpl) friend class DockAreaTabBarPrivate; + friend class CDockAreaTitleBar; private slots: void onTabClicked(); @@ -81,6 +84,12 @@ protected: */ void startFloating(const QPoint& Pos); + /** + * Makes the dock area loating + */ + CFloatingDockContainer* makeAreaFloating(const QPoint& Pos); + + public: using Super = QScrollArea; /** diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index e967b78..a7c6be2 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -41,6 +41,7 @@ struct DockAreaTitleBarPrivate { CDockAreaTitleBar* _this; tTileBarButton* TabsMenuButton; + tTileBarButton* UndockButton; tTileBarButton* CloseButton; QBoxLayout* TopLayout; CDockAreaWidget* DockArea; @@ -106,6 +107,15 @@ void DockAreaTitleBarPrivate::createButtons() _this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)), SLOT(onTabsMenuActionTriggered(QAction*))); + // Undock button + UndockButton = new tTileBarButton(); + UndockButton->setObjectName("undockButton"); + UndockButton->setAutoRaise(true); + UndockButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarNormalButton)); + UndockButton->setMaximumWidth(UndockButton->iconSize().width()); + TopLayout->addWidget(UndockButton, 0); + _this->connect(UndockButton, SIGNAL(clicked()), SLOT(onUndockButtonClicked())); + CloseButton = new tTileBarButton(); CloseButton->setObjectName("closeButton"); CloseButton->setAutoRaise(true); @@ -213,6 +223,14 @@ void CDockAreaTitleBar::onCloseButtonClicked() } +//============================================================================ +void CDockAreaTitleBar::onUndockButtonClicked() +{ + std::cout << "CDockAreaTitleBar::onUndockButtonClicked" << std::endl; + d->TabBar->makeAreaFloating(mapFromGlobal(QCursor::pos())); +} + + //============================================================================ void CDockAreaTitleBar::onTabsMenuActionTriggered(QAction* Action) { @@ -230,6 +248,27 @@ void CDockAreaTitleBar::onCurrentTabChanged(int Index) } +//============================================================================ +QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const +{ + switch (which) + { + case TitleBarButtonTabsMenu: return d->TabsMenuButton; + case TitleBarButtonUndock: return d->UndockButton; + case TitleBarButtonClose: return d->CloseButton; + default: + return nullptr; + } +} + + +//============================================================================ +void CDockAreaTitleBar::setVisible(bool Visible) +{ + Super::setVisible(Visible); +} + + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockAreaTitleBar.h b/src/DockAreaTitleBar.h index 8b54931..9a3b87e 100644 --- a/src/DockAreaTitleBar.h +++ b/src/DockAreaTitleBar.h @@ -32,6 +32,10 @@ //============================================================================ #include +#include "ads_globals.h" + +class QAbstractButton; + namespace ads { class CDockAreaTabBar; @@ -52,6 +56,7 @@ private slots: void markTabsMenuOutdated(); void onTabsMenuAboutToShow(); void onCloseButtonClicked(); + void onUndockButtonClicked(); void onTabsMenuActionTriggered(QAction* Action); void onCurrentTabChanged(int Index); @@ -72,6 +77,13 @@ public: */ CDockAreaTabBar* tabBar() const; + /** + * Returns the button corresponding to the given title bar button identifier + */ + QAbstractButton* button(TitleBarButton which) const; + + virtual void setVisible(bool Visible) override; + signals: /** * This signal is emitted if a tab in the tab bar is clicked by the user diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 392f290..fe1b1ec 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -258,7 +258,7 @@ struct DockAreaWidgetPrivate * Updates the tab bar visibility depending on the number of dock widgets * in this area */ - void updateTabBar(); + void updateTitleBarVisibility(); /** * Convenience function for tabbar access @@ -294,7 +294,7 @@ void DockAreaWidgetPrivate::createTitleBar() //============================================================================ -void DockAreaWidgetPrivate::updateTabBar() +void DockAreaWidgetPrivate::updateTitleBarVisibility() { CDockContainerWidget* Container = _this->dockContainer(); if (!Container) @@ -358,7 +358,11 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget, d->ContentsLayout->insertWidget(index, DockWidget); DockWidget->tabWidget()->setDockAreaWidget(this); auto TabWidget = DockWidget->tabWidget(); + // Inserting the tab will change the current index which in turn will + // make the tab widget visible in the slot + d->tabBar()->blockSignals(true); d->tabBar()->insertTab(index, TabWidget); + d->tabBar()->blockSignals(false); TabWidget->setVisible(!DockWidget->isClosed()); DockWidget->setProperty(INDEX_PROPERTY, index); if (Activate) @@ -398,7 +402,7 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) hideAreaWithNoVisibleContent(); } - d->updateTabBar(); + d->updateTitleBarVisibility(); auto TopLevelDockWidget = dockContainer()->topLevelDockWidget(); if (TopLevelDockWidget) { @@ -415,6 +419,7 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) //============================================================================ void CDockAreaWidget::hideAreaWithNoVisibleContent() { + std::cout << "CDockAreaWidget::hideAreaWithNoVisibleContent()" << std::endl; this->toggleView(false); // Hide empty parent splitter @@ -430,9 +435,21 @@ void CDockAreaWidget::hideAreaWithNoVisibleContent() //Hide empty floating widget CDockContainerWidget* Container = this->dockContainer(); - if (Container->isFloating() && Container->openedDockAreas().isEmpty()) + if (!Container->isFloating()) + { + return; + } + + d->updateTitleBarVisibility(); + auto TopLevelWidget = Container->topLevelDockWidget(); + auto FloatingWidget = Container->floatingWidget(); + if (TopLevelWidget) + { + FloatingWidget->updateWindowTitle(); + CDockWidget::emitTopLevelEventForWidget(TopLevelWidget, true); + } + else if (Container->openedDockAreas().isEmpty()) { - CFloatingDockContainer* FloatingWidget = internal::findParent(Container); FloatingWidget->hide(); } } @@ -449,7 +466,13 @@ void CDockAreaWidget::onTabCloseRequested(int Index) //============================================================================ CDockWidget* CDockAreaWidget::currentDockWidget() const { - return dockWidget(currentIndex()); + int CurrentIndex = currentIndex(); + if (CurrentIndex < 0) + { + return nullptr; + } + + return dockWidget(CurrentIndex); } @@ -576,7 +599,7 @@ int CDockAreaWidget::dockWidgetsCount() const //============================================================================ CDockWidget* CDockAreaWidget::dockWidget(int Index) const { - return dynamic_cast(d->ContentsLayout->widget(Index)); + return qobject_cast(d->ContentsLayout->widget(Index)); } @@ -610,7 +633,7 @@ void CDockAreaWidget::toggleDockWidgetView(CDockWidget* DockWidget, bool Open) //============================================================================ void CDockAreaWidget::updateTabBarVisibility() { - d->updateTabBar(); + d->updateTitleBarVisibility(); } @@ -619,9 +642,11 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const { s.writeStartElement("DockAreaWidget"); s.writeAttribute("Tabs", QString::number(d->ContentsLayout->count())); - s.writeAttribute("CurrentDockWidget", currentDockWidget()->objectName()); + auto CurrentDockWidget = currentDockWidget(); + QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : ""; + s.writeAttribute("CurrentDockWidget", Name); qDebug() << "CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count() - << " CurrentDockWidge: " << currentDockWidget()->objectName(); + << " CurrentDockWidge: " << Name; for (int i = 0; i < d->ContentsLayout->count(); ++i) { dockWidget(i)->saveState(s); @@ -675,6 +700,13 @@ void CDockAreaWidget::toggleView(bool Open) setVisible(Open); emit viewToggled(Open); } + + +//============================================================================ +QAbstractButton* CDockAreaWidget::titleBarButton(TitleBarButton which) const +{ + return d->TitleBar->button(which); +} } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index d845618..592b095 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -36,6 +36,7 @@ #include "DockWidget.h" class QXmlStreamWriter; +class QAbstractButton; namespace ads { @@ -190,12 +191,14 @@ public: CDockWidget* dockWidget(int Index) const; /** - * Returns the index of the current active dock widget + * Returns the index of the current active dock widget or -1 if there + * are is no active dock widget (ie.e if all dock widgets are closed) */ int currentIndex() const; /** - * Returns the current active dock widget + * Returns the current active dock widget or a nullptr if there is no + * active dock widget (i.e. if all dock widgets are closed) */ CDockWidget* currentDockWidget() const; @@ -218,6 +221,12 @@ public: */ CDockWidget::DockWidgetFeatures features() const; + /** + * Returns the title bar button corresponding to the given title bar + * button identifier + */ + QAbstractButton* titleBarButton(TitleBarButton which) const; + public slots: /** * This activates the tab for the given tab index. diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index eaf5565..0a19e3f 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -528,10 +528,6 @@ bool DockContainerWidgetPrivate::restoreDockArea(QXmlStreamReader& s, QString CurrentDockWidget = s.attributes().value("CurrentDockWidget").toString(); - if (CurrentDockWidget.isEmpty()) - { - return false; - } qDebug() << "Restore NodeDockArea Tabs: " << Tabs << " CurrentDockWidget: " << CurrentDockWidget; diff --git a/src/DockManager.cpp b/src/DockManager.cpp index 2be9c82..b8c5acd 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -264,6 +264,11 @@ bool DockManagerPrivate::restoreState(const QByteArray &state, int version) { CDockAreaWidget* DockArea = DockContainer->dockArea(i); QString DockWidgetName = DockArea->property("currentDockWidget").toString(); + if (DockWidgetName.isEmpty()) + { + continue; + } + CDockWidget* DockWidget = _this->findDockWidget(DockWidgetName); if (!DockWidget->isClosed()) { @@ -272,29 +277,6 @@ bool DockManagerPrivate::restoreState(const QByteArray &state, int version) } } - - // Finally we need to send the topLevelChanged() signals for all dock - // widgets if top level changed - /*for (auto DockContainer : Containers) - { - CDockWidget* TopLevelDockWidget = DockContainer->topLevelDockWidget(); - if (TopLevelDockWidget) - { - TopLevelDockWidget->emitTopLevelChanged(true); - } - else - { - for (int i = 0; i < DockContainer->dockAreaCount(); ++i) - { - auto DockArea = DockContainer->dockArea(i); - for (auto DockWidget : DockArea->dockWidgets()) - { - DockWidget->emitTopLevelChanged(false); - } - } - } - }*/ - return true; } diff --git a/src/DockWidgetTab.cpp b/src/DockWidgetTab.cpp index 8912ad0..e88ee98 100644 --- a/src/DockWidgetTab.cpp +++ b/src/DockWidgetTab.cpp @@ -400,10 +400,7 @@ void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event) //============================================================================ void CDockWidgetTab::setVisible(bool visible) { - /*if (!visible) - { - qDebug() << "CDockWidgetTab::setVisible " << visible; - }*/ + // Just here for debugging to insert debug output Super::setVisible(visible); } diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 5ebc921..6d97935 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include "DockContainerWidget.h" #include "DockAreaWidget.h" @@ -471,6 +472,7 @@ void CFloatingDockContainer::onDockAreasAddedOrRemoved() 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))); @@ -479,6 +481,7 @@ 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/FloatingDockContainer.h b/src/FloatingDockContainer.h index 9fb423f..f0affc7 100644 --- a/src/FloatingDockContainer.h +++ b/src/FloatingDockContainer.h @@ -69,6 +69,7 @@ private: friend class CDockAreaTitleBar; friend struct DockAreaTitleBarPrivate; friend class CDockWidget; + friend class CDockAreaWidget; private slots: void onDockAreasAddedOrRemoved(); diff --git a/src/ads_globals.h b/src/ads_globals.h index a32fad6..de5932c 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -61,6 +61,13 @@ enum DockWidgetArea Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea) +enum TitleBarButton +{ + TitleBarButtonTabsMenu, + TitleBarButtonUndock, + TitleBarButtonClose +}; + namespace internal {