From c57d14d0d7ef890aa01f830696cc059c0b4b0a84 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Sat, 11 Mar 2017 21:38:31 +0100 Subject: [PATCH] Implemented restoring of hidden floating widgets --- .../res/stylesheets/default-windows2.css | 2 +- .../src/v2/DockAreaWidget.cpp | 23 ++- AdvancedDockingSystem/src/v2/DockAreaWidget.h | 6 + .../src/v2/DockContainerWidget.cpp | 9 +- .../src/v2/DockContainerWidget.h | 6 + AdvancedDockingSystem/src/v2/DockWidget.cpp | 154 ++++++++++++++++++ AdvancedDockingSystem/src/v2/DockWidget.h | 45 +++++ .../src/v2/DockWidgetTitleBar.cpp | 1 + .../src/v2/FloatingDockContainer.cpp | 23 ++- .../src/mainwindow.cpp | 30 ++-- .../src/mainwindow.ui | 23 --- 11 files changed, 279 insertions(+), 43 deletions(-) diff --git a/AdvancedDockingSystem/res/stylesheets/default-windows2.css b/AdvancedDockingSystem/res/stylesheets/default-windows2.css index 2510dd6..ba8b91a 100644 --- a/AdvancedDockingSystem/res/stylesheets/default-windows2.css +++ b/AdvancedDockingSystem/res/stylesheets/default-windows2.css @@ -60,7 +60,7 @@ ads--CDockWidget QPushButton#closeButton, QPushButton#tabsMenuButton { - padding: 1px; + padding: 2px; } diff --git a/AdvancedDockingSystem/src/v2/DockAreaWidget.cpp b/AdvancedDockingSystem/src/v2/DockAreaWidget.cpp index 1484fef..e588efe 100644 --- a/AdvancedDockingSystem/src/v2/DockAreaWidget.cpp +++ b/AdvancedDockingSystem/src/v2/DockAreaWidget.cpp @@ -314,7 +314,7 @@ void DockAreaWidgetPrivate::createTabBar() CloseButton->setToolTip(_this->tr("Close")); CloseButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); TopLayout->addWidget(CloseButton, 0); - //connect(_closeButton, SIGNAL(clicked(bool)), this, SLOT(onCloseButtonClicked())); + _this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked())); TabsLayoutInitCount = TabsLayout->count(); } @@ -429,7 +429,6 @@ CDockContainerWidget* CDockAreaWidget::dockContainer() const void CDockAreaWidget::addDockWidget(CDockWidget* DockWidget) { insertDockWidget(d->ContentsLayout->count(), DockWidget); - } @@ -441,6 +440,7 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* 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) @@ -448,6 +448,7 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget, setCurrentIndex(index); } d->addTabsMenuEntry(DockWidget, index); + DockWidget->setDockArea(this); } @@ -457,6 +458,7 @@ 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()); @@ -470,6 +472,7 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget) } d->updateTabBar(); + DockWidget->setDockArea(nullptr); } @@ -487,6 +490,20 @@ void CDockAreaWidget::onDockWidgetTitleClicked() } +//============================================================================ +void CDockAreaWidget::onCloseButtonClicked() +{ + currentDockWidget()->toggleView(false); +} + + +//============================================================================ +CDockWidget* CDockAreaWidget::currentDockWidget() const +{ + return dockWidget(currentIndex()); +} + + //============================================================================ void CDockAreaWidget::setCurrentIndex(int index) { @@ -630,8 +647,6 @@ void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex) liFrom = d->ContentsLayout->takeAt(fromIndex); d->ContentsLayout->insertWidget(toIndex, liFrom->widget()); delete liFrom; - - //Menu->removeAction() } diff --git a/AdvancedDockingSystem/src/v2/DockAreaWidget.h b/AdvancedDockingSystem/src/v2/DockAreaWidget.h index b5d86e9..e1212bc 100644 --- a/AdvancedDockingSystem/src/v2/DockAreaWidget.h +++ b/AdvancedDockingSystem/src/v2/DockAreaWidget.h @@ -54,6 +54,7 @@ private: private slots: void onDockWidgetTitleClicked(); void onTabsMenuActionTriggered(QAction* Action); + void onCloseButtonClicked(); public: /** @@ -143,6 +144,11 @@ public: */ int currentIndex() const; + /** + * Returns the current active dock widget + */ + CDockWidget* currentDockWidget() const; + public slots: /** * This sets the index position of the current tab page. diff --git a/AdvancedDockingSystem/src/v2/DockContainerWidget.cpp b/AdvancedDockingSystem/src/v2/DockContainerWidget.cpp index 29e62b4..cad855a 100644 --- a/AdvancedDockingSystem/src/v2/DockContainerWidget.cpp +++ b/AdvancedDockingSystem/src/v2/DockContainerWidget.cpp @@ -411,7 +411,7 @@ CDockContainerWidget::CDockContainerWidget(CDockManager* DockManager, QWidget *p } d->Layout = new QGridLayout(); - d->Layout->setContentsMargins(0, 1, 0, 0); + d->Layout->setContentsMargins(0, 1, 0, 1); d->Layout->setSpacing(0); setLayout(d->Layout); } @@ -539,6 +539,13 @@ CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const } +//============================================================================ +CDockAreaWidget* CDockContainerWidget::dockArea(int Index) const +{ + return (Index < dockAreaCount()) ? d->DockAreas[Index] : 0; +} + + //============================================================================ bool CDockContainerWidget::isFloating() const { diff --git a/AdvancedDockingSystem/src/v2/DockContainerWidget.h b/AdvancedDockingSystem/src/v2/DockContainerWidget.h index 88723de..6b6a410 100644 --- a/AdvancedDockingSystem/src/v2/DockContainerWidget.h +++ b/AdvancedDockingSystem/src/v2/DockContainerWidget.h @@ -111,6 +111,12 @@ public: */ 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 */ diff --git a/AdvancedDockingSystem/src/v2/DockWidget.cpp b/AdvancedDockingSystem/src/v2/DockWidget.cpp index c562233..acc9afc 100644 --- a/AdvancedDockingSystem/src/v2/DockWidget.cpp +++ b/AdvancedDockingSystem/src/v2/DockWidget.cpp @@ -31,10 +31,19 @@ #include "DockWidget.h" #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 @@ -50,11 +59,24 @@ struct DockWidgetPrivate CDockWidgetTitleBar* TitleWidget; CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures; CDockManager* DockManager = nullptr; + CDockAreaWidget* DockArea = nullptr; + QAction* ToggleViewAction; + QString CapturedState; /** * Private data constructor */ DockWidgetPrivate(CDockWidget* _public); + + /** + * Saves the current state into CapturedState variable + */ + void capturedState(); + + /** + * Show dock widget + */ + void showDockWidget(); }; // struct DockWidgetPrivate @@ -65,6 +87,75 @@ DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) : } + +//============================================================================ +void DockWidgetPrivate::capturedState() +{ + QString CapturedState; + QTextStream stream(&CapturedState); + stream << (_this->isFloating() ? "F " : "D "); + if (_this->isFloating()) + { + CFloatingDockContainer* FloatingWidget = internal::findParent(_this); + QRect Rect = FloatingWidget->geometry(); + stream << Rect.left() << " " << Rect.top() << " " << Rect.width() + << " " << Rect.height(); + } + else + { + 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 = CapturedState; + std::cout << "SerializedPosition: " << CapturedState.toStdString() << std::endl; +} + + +//============================================================================ +void DockWidgetPrivate::showDockWidget() +{ + QTextStream stream(&CapturedState); + QString DockedState; + stream >> DockedState; + if (DockedState == "F") + { + std::cout << "Restoring Floating Dock Widget" << std::endl; + QVector v; + while (!stream.atEnd()) + { + int Value; + stream >> Value; + v.append(Value); + } + + if (v.count() == 4) + { + std::cout << "Rectangle Loaded" << std::endl; + QRect Rect(v[0], v[1], v[2], v[3]); + auto FloatingWidget = new CFloatingDockContainer(_this); + FloatingWidget->setGeometry(Rect); + FloatingWidget->show(); + } + } +} + + //============================================================================ CDockWidget::CDockWidget(const QString &title, QWidget *parent) : QFrame(parent), @@ -77,11 +168,16 @@ CDockWidget::CDockWidget(const QString &title, QWidget *parent) : 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; } @@ -157,6 +253,64 @@ CDockAreaWidget* CDockWidget::dockAreaWidget() const return internal::findParent(this); } + +//============================================================================ +bool CDockWidget::isFloating() const +{ + return dockContainer() ? dockContainer()->isFloating() : false; +} + + +//============================================================================ +QAction* CDockWidget::toggleViewAction() const +{ + return d->ToggleViewAction; +} + + +//============================================================================ +void CDockWidget::toggleView(bool Open) +{ + if ((d->DockArea != nullptr) == Open) + { + return; + } + + if (!Open && d->DockArea) + { + hideDockWidget(true); + } + else if (Open && !d->DockArea) + { + d->showDockWidget(); + } +} + + +//============================================================================ +void CDockWidget::setDockArea(CDockAreaWidget* DockArea) +{ + d->DockArea = DockArea; + d->ToggleViewAction->setChecked(DockArea != nullptr); +} + + + +//============================================================================ +void CDockWidget::hideDockWidget(bool RemoveFromDockArea) +{ + d->capturedState(); + if (d->DockArea && RemoveFromDockArea) + { + d->DockArea->removeDockWidget(this); + } + this->setParent(d->DockManager); + this->setDockArea(nullptr); + // Remove title from dock area widget to prevent its deletion if dock + // area is deleted + d->TitleWidget->setParent(this); +} + } // namespace ads //--------------------------------------------------------------------------- diff --git a/AdvancedDockingSystem/src/v2/DockWidget.h b/AdvancedDockingSystem/src/v2/DockWidget.h index 6974149..2b5d32f 100644 --- a/AdvancedDockingSystem/src/v2/DockWidget.h +++ b/AdvancedDockingSystem/src/v2/DockWidget.h @@ -53,11 +53,29 @@ private: 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. + * If RemoveFromDockArea is true, the dock widget will be properly removed + * from dock area. + */ + void hideDockWidget(bool RemoveFromDockArea = true); + public: enum DockWidgetFeature { @@ -69,6 +87,14 @@ public: }; Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature) + + enum eState + { + StateHidden, + StateDocked, + StateFloating + }; + /** * Default Constructor */ @@ -125,6 +151,25 @@ public: * 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 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 diff --git a/AdvancedDockingSystem/src/v2/DockWidgetTitleBar.cpp b/AdvancedDockingSystem/src/v2/DockWidgetTitleBar.cpp index 7151e0d..e4559a6 100644 --- a/AdvancedDockingSystem/src/v2/DockWidgetTitleBar.cpp +++ b/AdvancedDockingSystem/src/v2/DockWidgetTitleBar.cpp @@ -212,6 +212,7 @@ CDockWidgetTitleBar::CDockWidgetTitleBar(CDockWidget* DockWidget, QWidget *paren //============================================================================ CDockWidgetTitleBar::~CDockWidgetTitleBar() { + std::cout << "~CDockWidgetTitleBar()" << std::endl; delete d; } diff --git a/AdvancedDockingSystem/src/v2/FloatingDockContainer.cpp b/AdvancedDockingSystem/src/v2/FloatingDockContainer.cpp index c7916e8..0810465 100644 --- a/AdvancedDockingSystem/src/v2/FloatingDockContainer.cpp +++ b/AdvancedDockingSystem/src/v2/FloatingDockContainer.cpp @@ -43,6 +43,7 @@ #include "DockWidget.h" #include "DockOverlay.h" + namespace ads { static unsigned int zOrderCounter = 0; @@ -170,6 +171,7 @@ 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); @@ -252,11 +254,30 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event) } } + //============================================================================ void CFloatingDockContainer::closeEvent(QCloseEvent *event) { d->setDraggingActive(false); - QWidget::closeEvent(event); + 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(false); + } + } + QWidget::closeEvent(event); + } + else + { + std::cout << "Closing single tab" << std::endl; + event->ignore(); + auto DockArea = dockContainer()->dockArea(0); + DockArea->currentDockWidget()->hideDockWidget(true); + } } diff --git a/AdvancedDockingSystemDemo_v2/src/mainwindow.cpp b/AdvancedDockingSystemDemo_v2/src/mainwindow.cpp index a79ad0b..bc5d670 100644 --- a/AdvancedDockingSystemDemo_v2/src/mainwindow.cpp +++ b/AdvancedDockingSystemDemo_v2/src/mainwindow.cpp @@ -19,7 +19,7 @@ static int CONTENT_COUNT = 0; -static ads::CDockWidget* createLongTextLabelDockWidget(ads::CDockManager* DockManager) +static ads::CDockWidget* createLongTextLabelDockWidget(QMenu* ViewMenu) { static int LabelCount = 0; QLabel* l = new QLabel(); @@ -37,19 +37,21 @@ static ads::CDockWidget* createLongTextLabelDockWidget(ads::CDockManager* DockMa ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Label %1").arg(LabelCount++)); DockWidget->setWidget(l); + ViewMenu->addAction(DockWidget->toggleViewAction()); return DockWidget; } -static ads::CDockWidget* createCalendarDockWidget(ads::CDockManager* DockManager) +static ads::CDockWidget* createCalendarDockWidget(QMenu* ViewMenu) { static int CalendarCount = 0; QCalendarWidget* w = new QCalendarWidget(); ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Calendar %1").arg(CalendarCount++)); DockWidget->setWidget(w); + ViewMenu->addAction(DockWidget->toggleViewAction()); return DockWidget; } -static ads::CDockWidget* createFileSystemTreeDockWidget(ads::CDockManager* DockManager) +static ads::CDockWidget* createFileSystemTreeDockWidget(QMenu* ViewMenu) { static int FileSystemCount = 0; QTreeView* w = new QTreeView(); @@ -59,6 +61,7 @@ static ads::CDockWidget* createFileSystemTreeDockWidget(ads::CDockManager* DockM w->setModel(m); ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1").arg(FileSystemCount++)); DockWidget->setWidget(w); + ViewMenu->addAction(DockWidget->toggleViewAction()); return DockWidget; } @@ -87,22 +90,23 @@ MainWindow::~MainWindow() void MainWindow::createContent() { // Test container docking - auto DockWidget = createCalendarDockWidget(m_DockManager); + QMenu* ViewMenu = this->ui->menuView; + auto DockWidget = createCalendarDockWidget(ViewMenu); DockWidget->setFeatures(DockWidget->features().setFlag(ads::CDockWidget::DockWidgetClosable, false)); m_DockManager->addDockWidget(ads::LeftDockWidgetArea, DockWidget); - m_DockManager->addDockWidget(ads::LeftDockWidgetArea, createLongTextLabelDockWidget(m_DockManager)); - m_DockManager->addDockWidget(ads::BottomDockWidgetArea, createFileSystemTreeDockWidget(m_DockManager)); - auto TopDockArea = m_DockManager->addDockWidget(ads::TopDockWidgetArea, createFileSystemTreeDockWidget(m_DockManager)); - DockWidget = createCalendarDockWidget(m_DockManager); + m_DockManager->addDockWidget(ads::LeftDockWidgetArea, createLongTextLabelDockWidget(ViewMenu)); + m_DockManager->addDockWidget(ads::BottomDockWidgetArea, createFileSystemTreeDockWidget(ViewMenu)); + auto TopDockArea = m_DockManager->addDockWidget(ads::TopDockWidgetArea, createFileSystemTreeDockWidget(ViewMenu)); + DockWidget = createCalendarDockWidget(ViewMenu); DockWidget->setFeatures(DockWidget->features().setFlag(ads::CDockWidget::DockWidgetClosable, false)); m_DockManager->addDockWidget(ads::CenterDockWidgetArea, DockWidget, TopDockArea); // Test dock area docking - auto RighDockArea = m_DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(m_DockManager), TopDockArea); - m_DockManager->addDockWidget(ads::TopDockWidgetArea, createLongTextLabelDockWidget(m_DockManager), RighDockArea); - auto BottomDockArea = m_DockManager->addDockWidget(ads::BottomDockWidgetArea, createLongTextLabelDockWidget(m_DockManager), RighDockArea); - m_DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(m_DockManager), RighDockArea); - m_DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(m_DockManager), BottomDockArea); + auto RighDockArea = m_DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), TopDockArea); + m_DockManager->addDockWidget(ads::TopDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), RighDockArea); + auto BottomDockArea = m_DockManager->addDockWidget(ads::BottomDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), RighDockArea); + m_DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), RighDockArea); + m_DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(ViewMenu), BottomDockArea); } diff --git a/AdvancedDockingSystemDemo_v2/src/mainwindow.ui b/AdvancedDockingSystemDemo_v2/src/mainwindow.ui index 9268de9..8a80726 100644 --- a/AdvancedDockingSystemDemo_v2/src/mainwindow.ui +++ b/AdvancedDockingSystemDemo_v2/src/mainwindow.ui @@ -34,9 +34,6 @@ View - - - @@ -47,26 +44,6 @@ - - - Add SectionContent - - - - - Contents... - - - - - Demo 2 - - - - - Demo 3 - - Exit