From 44790307d80199d0456add407993e01a623d31f8 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 1 Nov 2022 11:02:01 +0100 Subject: [PATCH] Properly implemented restore functionality for auto hide container --- examples/autohide/mainwindow.cpp | 2 +- src/AutoHideDockContainer.cpp | 64 ++++++-------- src/AutoHideDockContainer.h | 35 ++++---- src/DockAreaWidget.cpp | 9 +- src/DockAreaWidget.h | 4 +- src/DockContainerWidget.cpp | 143 ++++++++----------------------- src/DockManager.cpp | 3 +- src/DockWidget.h | 2 + src/DockWidgetSideTab.cpp | 1 - src/SideTabBar.cpp | 17 ++-- src/SideTabBar.h | 1 + 11 files changed, 95 insertions(+), 186 deletions(-) diff --git a/examples/autohide/mainwindow.cpp b/examples/autohide/mainwindow.cpp index 42dc49c..30061aa 100644 --- a/examples/autohide/mainwindow.cpp +++ b/examples/autohide/mainwindow.cpp @@ -47,7 +47,7 @@ CMainWindow::CMainWindow(QWidget *parent) TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget); TableDockWidget->setMinimumSize(200,150); const auto autoHideContainer = DockManager->addAutoHideDockWidget(SideBarLocation::Left, TableDockWidget, CDockWidget::Last); - autoHideContainer->setSize(480, 100); + autoHideContainer->setSize(480); ui->menuView->addAction(TableDockWidget->toggleViewAction()); table = new QTableWidget(); diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index 267039c..936782c 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -167,7 +167,14 @@ AutoHideDockContainerPrivate::AutoHideDockContainerPrivate( //============================================================================ CDockContainerWidget* CAutoHideDockContainer::parentContainer() const { - return internal::findParent(this); + if (d->DockArea) + { + return d->DockArea->dockContainer(); + } + else + { + return internal::findParent(this); + } } @@ -176,6 +183,7 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockManager* DockManager, SideBa Super(parent), d(new AutoHideDockContainerPrivate(this)) { + hide(); // auto hide dock container is initially always hidden d->SideTabBarArea = area; d->SideTab = componentsFactory()->createDockWidgetSideTab(nullptr); connect(d->SideTab, &CDockWidgetSideTab::pressed, this, &CAutoHideDockContainer::toggleCollapseState); @@ -363,40 +371,11 @@ void CAutoHideDockContainer::cleanupAndDelete() //============================================================================ void CAutoHideDockContainer::saveState(QXmlStreamWriter& s) { + s.writeStartElement("Widget"); + s.writeAttribute("Name", d->DockWidget->objectName()); + s.writeAttribute("Closed", QString::number(d->DockWidget->isClosed() ? 1 : 0)); s.writeAttribute("Size", QString::number(d->isHorizontal() ? d->Size.height() : d->Size.width())); - - qDebug() << ": saveState Size: " << d->Size; - qDebug() << ": saveState Size " << QString::number(d->isHorizontal() ? d->Size.height() : d->Size.width()); -} - - -//============================================================================ -bool CAutoHideDockContainer::restoreState(CDockingStateReader& s, bool Testing) -{ - bool ok; - int Size = s.attributes().value("Size").toInt(&ok); - if (!ok) - { - return false; - } - - if (Testing) - { - return true; - } - - if (d->isHorizontal()) - { - d->Size.setHeight(Size); - } - else - { - d->Size.setWidth(Size); - qDebug() << ": restoreState Width " << Size; - } - - qDebug() << ": restoreState Size: " << d->Size; - return true; + s.writeEndElement(); } @@ -438,6 +417,11 @@ void CAutoHideDockContainer::collapseView(bool Enable) show(); d->DockWidget->dockManager()->setDockWidgetFocused(d->DockWidget); qApp->installEventFilter(this); + + qDebug() << "CAutoHideDockContainer.hidden " << this->isHidden(); + qDebug() << "d->DockArea->isHidden() " << d->DockArea->isHidden(); + qDebug() << "d->DockWidget->isHidden() " << d->DockWidget->isHidden(); + qDebug() << "CAutoHideDockContainer.geometry() " << this->geometry(); } ADS_PRINT("CAutoHideDockContainer::collapseView " << Enable); @@ -453,9 +437,17 @@ void CAutoHideDockContainer::toggleCollapseState() //============================================================================ -void CAutoHideDockContainer::setSize(int width, int height) +void CAutoHideDockContainer::setSize(int Size) { - d->Size = QSize(width, height); + if (d->isHorizontal()) + { + d->Size.setHeight(Size); + } + else + { + d->Size.setWidth(Size); + } + updateSize(); } diff --git a/src/AutoHideDockContainer.h b/src/AutoHideDockContainer.h index 3a6b8c7..eb93cf2 100644 --- a/src/AutoHideDockContainer.h +++ b/src/AutoHideDockContainer.h @@ -46,6 +46,7 @@ class CDockContainerWidget; class CSideTabBar; class CDockAreaWidget; class CDockingStateReader; +struct SideTabBarPrivate; /** * Auto hide container for hosting an auto hide dock widget @@ -57,13 +58,18 @@ class ADS_EXPORT CAutoHideDockContainer : public QFrame private: AutoHideDockContainerPrivate* d; ///< private data (pimpl) friend struct AutoHideDockContainerPrivate; + friend CSideTabBar; + friend SideTabBarPrivate; protected: bool eventFilter(QObject* watched, QEvent* event) override; void resizeEvent(QResizeEvent* event) override; void updateSize(); - CDockContainerWidget* parentContainer() const; + /* + * Saves the state and size + */ + void saveState(QXmlStreamWriter& Stream); public: using Super = QFrame; @@ -114,6 +120,11 @@ public: */ CDockAreaWidget* dockAreaWidget() const; + /** + * Returns the parent container that hosts this auto hide container + */ + CDockContainerWidget* parentContainer() const; + /** * Moves the contents to the parent container widget * Used before removing this Auto Hide dock container @@ -125,16 +136,6 @@ public: */ void cleanupAndDelete(); - /* - * Saves the state and size - */ - void saveState(QXmlStreamWriter& Stream); - - /* - * Restores the size of the splitter - */ - bool restoreState(CDockingStateReader& Stream, bool Testing); - /* * Toggles the auto Hide dock container widget * This will also hide the side tab widget @@ -153,13 +154,13 @@ public: void toggleCollapseState(); /** - * Use this instead of resize. This will ensure the size is consistent internally. - * E.g. If you set a height less than the parent height when it's vertical - * It will simply be rescaled to the parent height while the width will be resized + * Use this instead of resize. + * Depending on the sidebar location this will set the width or heigth + * of this auto hide container. */ - void setSize(int width, int height); + void setSize(int Size); }; -} - +} // namespace ads +//----------------------------------------------------------------------------- #endif diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 4d47cb1..adaad98 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -870,13 +870,6 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : ""; s.writeAttribute("Current", Name); - // To keep the saved XML data small, we only save the allowed areas and the - // dock area flags if the values are different from the default values - if (isAutoHide()) - { - autoHideDockContainer()->saveState(s); - } - if (d->AllowedAreas != DefaultAllowedAreas) { s.writeAttribute("AllowedAreas", QString::number(d->AllowedAreas, 16)); @@ -897,7 +890,7 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const //============================================================================ -bool CDockAreaWidget::restoreDockArea(CDockingStateReader& s, CDockAreaWidget*& CreatedWidget, +bool CDockAreaWidget::restoreState(CDockingStateReader& s, CDockAreaWidget*& CreatedWidget, bool Testing, CDockContainerWidget* Container) { bool Ok; diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index 61862be..edb1b02 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -301,8 +301,8 @@ public: * Restores a dock area. * \see restoreChildNodes() for details */ - static bool restoreDockArea(CDockingStateReader& Stream, CDockAreaWidget*& CreatedWidget, - bool Testing, CDockContainerWidget* Container); + static bool restoreState(CDockingStateReader& Stream, CDockAreaWidget*& CreatedWidget, + bool Testing, CDockContainerWidget* ParentContainer); /** * This functions returns the dock widget features of all dock widget in diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index f6c51b3..2569539 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -250,13 +250,6 @@ public: bool restoreDockArea(CDockingStateReader& Stream, QWidget*& CreatedWidget, bool Testing); - /** - * Restores the auto hide dock area. - * Assumes that there are no auto hidden dock areas, and then restores all the dock areas that - * exist in the XML - */ - bool restoreAutoHideDockArea(CDockingStateReader& s, SideBarLocation area, bool Testing); - /** * Restores a auto hide side bar */ @@ -1030,98 +1023,13 @@ bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s, return true; } -//============================================================================ -bool DockContainerWidgetPrivate::restoreAutoHideDockArea(CDockingStateReader& s, SideBarLocation area, bool Testing) -{ - if (!CDockManager::testConfigFlag(CDockManager::AutoHideFeatureEnabled)) - { - return false; - } - - bool Ok; -#ifdef ADS_DEBUG_PRINT - int Tabs = s.attributes().value("Tabs").toInt(&Ok); - if (!Ok) - { - return false; - } -#endif - - QString CurrentDockWidget = s.attributes().value("Current").toString(); - ADS_PRINT("Restore NodeDockArea Tabs: " << Tabs << " Current: " - << CurrentDockWidget); - - CDockAreaWidget* DockArea = nullptr; - CAutoHideDockContainer* AutoHideContainer = nullptr; - if (!Testing) - { - AutoHideContainer = new CAutoHideDockContainer(DockManager, area, _this); - if (!AutoHideContainer->restoreState(s, Testing)) - { - return false; - } - - AutoHideContainer->hide(); - DockArea = AutoHideContainer->dockAreaWidget(); - DockArea->updateAutoHideButtonCheckState(); - DockArea->updateTitleBarButtonToolTip(); - } - - while (s.readNextStartElement()) - { - if (s.name() != QLatin1String("Widget")) - { - continue; - } - - auto ObjectName = s.attributes().value("Name"); - if (ObjectName.isEmpty()) - { - return false; - } - - bool Closed = s.attributes().value("Closed").toInt(&Ok); - if (!Ok) - { - return false; - } - - s.skipCurrentElement(); - CDockWidget* DockWidget = DockManager->findDockWidget(ObjectName.toString()); - if (!DockWidget || Testing) - { - continue; - } - - ADS_PRINT("Dock Widget found - parent " << DockWidget->parent()); - // 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->setClosedState(Closed); - DockWidget->setProperty(internal::ClosedProperty, Closed); - DockWidget->setProperty(internal::DirtyProperty, false); - _this->sideTabBar(area)->insertSideTab(-1, DockWidget->sideTabWidget()); - DockArea->autoHideDockContainer()->addDockWidget(DockWidget); - DockWidget->sideTabWidget()->updateStyle(); // Needed as the side tab widget get it's left/right property from the overlay dock container which was just added - DockArea->autoHideDockContainer()->toggleView(!Closed); - } - - if (AutoHideContainer && !AutoHideContainer->dockWidget()) - { - AutoHideContainer->cleanupAndDelete(); - } - - return true; -} - //============================================================================ bool DockContainerWidgetPrivate::restoreDockArea(CDockingStateReader& s, QWidget*& CreatedWidget, bool Testing) { CDockAreaWidget* DockArea = nullptr; - auto Result = CDockAreaWidget::restoreDockArea(s, DockArea, Testing, _this); + auto Result = CDockAreaWidget::restoreState(s, DockArea, Testing, _this); if (Result && DockArea) { appendDockAreas({DockArea}); @@ -1136,14 +1044,14 @@ bool DockContainerWidgetPrivate::restoreSideBar(CDockingStateReader& s, QWidget*& CreatedWidget, bool Testing) { Q_UNUSED(CreatedWidget) - // Simply ignore side bar auto hide widgets + // Simply ignore side bar auto hide widgets from saved state if + // auto hide support is disabled if (!CDockManager::testConfigFlag(CDockManager::AutoHideFeatureEnabled)) { return true; } bool Ok; - //int Tabs = s.attributes().value("Tabs").toInt(&Ok); auto Area = (ads::SideBarLocation)s.attributes().value("Area").toInt(&Ok); if (!Ok) { @@ -1152,15 +1060,42 @@ bool DockContainerWidgetPrivate::restoreSideBar(CDockingStateReader& s, while (s.readNextStartElement()) { - if (s.name() != QLatin1String("Area")) + if (s.name() != QLatin1String("Widget")) { continue; } - if (!restoreAutoHideDockArea(s, Area, Testing)) - { - return false; - } + auto Name = s.attributes().value("Name"); + if (Name.isEmpty()) + { + return false; + } + + bool Ok; + bool Closed = s.attributes().value("Closed").toInt(&Ok); + if (!Ok) + { + return false; + } + + int Size = s.attributes().value("Size").toInt(&Ok); + if (!Ok) + { + return false; + } + + s.skipCurrentElement(); + CDockWidget* DockWidget = DockManager->findDockWidget(Name.toString()); + if (!DockWidget || Testing) + { + continue; + } + + auto SideBar = _this->sideTabBar(Area); + auto AutoHideContainer = SideBar->insertDockWidget(-1, DockWidget); + AutoHideContainer->setSize(Size); + DockWidget->setProperty(internal::ClosedProperty, Closed); + DockWidget->setProperty(internal::DirtyProperty, false); } return true; @@ -1453,14 +1388,6 @@ CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer( DockWidget->setDockManager(d->DockManager); // Auto hide Dock Container needs a valid dock manager } - /*sideTabBar(area)->insertSideTab(insertOrder == CDockWidget::First ? 0 : -1, DockWidget->sideTabWidget()); - DockWidget->sideTabWidget()->show(); - - const auto AutoHideContainer = new CAutoHideDockContainer(DockWidget, area, this); - AutoHideContainer->hide(); - d->DockManager->dockFocusController()->clearDockWidgetFocus(DockWidget); - return AutoHideContainer;*/ - return sideTabBar(area)->insertDockWidget(insertOrder == CDockWidget::First ? 0 : -1, DockWidget); } diff --git a/src/DockManager.cpp b/src/DockManager.cpp index cb55869..5899192 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -700,7 +700,8 @@ QByteArray CDockManager::saveState(int version) const QByteArray xmldata; QXmlStreamWriter s(&xmldata); auto ConfigFlags = CDockManager::configFlags(); - s.setAutoFormatting(ConfigFlags.testFlag(XmlAutoFormattingEnabled)); + //s.setAutoFormatting(ConfigFlags.testFlag(XmlAutoFormattingEnabled)); + s.setAutoFormatting(true); s.writeStartDocument(); s.writeStartElement("QtAdvancedDockingSystem"); s.writeAttribute("Version", QString::number(CurrentVersion)); diff --git a/src/DockWidget.h b/src/DockWidget.h index ae8852c..d8048a2 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -48,6 +48,7 @@ class DockContainerWidgetPrivate; class CFloatingDockContainer; class CDockWidgetSideTab; class CAutoHideDockContainer; +class CSideTabBar; /** * The QDockWidget class provides a widget that can be docked inside a @@ -78,6 +79,7 @@ protected: friend struct DockWidgetTabPrivate; friend struct DockAreaTitleBarPrivate; friend class CAutoHideDockContainer; + friend CSideTabBar; /** * Assigns the dock manager that manages this dock widget diff --git a/src/DockWidgetSideTab.cpp b/src/DockWidgetSideTab.cpp index 29e8ccc..c7c1b1a 100644 --- a/src/DockWidgetSideTab.cpp +++ b/src/DockWidgetSideTab.cpp @@ -114,7 +114,6 @@ SideBarLocation CDockWidgetSideTab::sideTabBarArea() const { if (d->SideTabBar) { - qDebug() << "CDockWidgetSideTab::sideTabBarArea() " << d->SideTabBar->sideTabBarArea(); return d->SideTabBar->sideTabBarArea(); } diff --git a/src/SideTabBar.cpp b/src/SideTabBar.cpp index 8c7296d..8ee67a3 100644 --- a/src/SideTabBar.cpp +++ b/src/SideTabBar.cpp @@ -42,6 +42,7 @@ #include "DockFocusController.h" #include "AutoHideDockContainer.h" #include "DockAreaWidget.h" +#include "DockingStateReader.h" namespace ads { @@ -141,15 +142,6 @@ void CSideTabBar::insertSideTab(int Index, CDockWidgetSideTab* SideTab) //============================================================================ CAutoHideDockContainer* CSideTabBar::insertDockWidget(int Index, CDockWidget* DockWidget) { - /* - * sideTabBar(area)->insertSideTab(insertOrder == CDockWidget::First ? 0 : -1, DockWidget->sideTabWidget()); - DockWidget->sideTabWidget()->show(); - - const auto AutoHideContainer = new CAutoHideDockContainer(DockWidget, area, this); - AutoHideContainer->hide(); - d->DockManager->dockFocusController()->clearDockWidgetFocus(DockWidget); - return AutoHideContainer;*/ - auto AutoHideContainer = new CAutoHideDockContainer(DockWidget, d->SideTabArea, d->ContainerWidget); DockWidget->dockManager()->dockFocusController()->clearDockWidgetFocus(DockWidget); auto Tab = AutoHideContainer->sideTab(); @@ -297,10 +289,11 @@ void CSideTabBar::saveState(QXmlStreamWriter& s) const continue; } - auto DockArea = Tab->dockWidget()->dockAreaWidget(); - DockArea->saveState(s); + Tab->dockWidget()->autoHideDockContainer()->saveState(s); } s.writeEndElement(); } -} + + +} // namespace ads diff --git a/src/SideTabBar.h b/src/SideTabBar.h index 585be39..f11e3e3 100644 --- a/src/SideTabBar.h +++ b/src/SideTabBar.h @@ -42,6 +42,7 @@ class DockContainerWidgetPrivate; class CDockContainerWidget; class CDockWidgetSideTab; class CAutoHideDockContainer; +class CDockingStateReader; /** * Side tab bar widget that is shown at the edges of a dock container.