From aa8a52b845eb97965c3438cabf0ae1bfca36a68d Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 28 Mar 2017 10:57:03 +0200 Subject: [PATCH] Fixed bug with FloatingWidget deletion, fixed handling of unassigned DockWidgets after restoreState() call --- src/DockContainerWidget.cpp | 4 +++ src/DockManager.cpp | 52 +++++++++++++++++++++++++++------ src/DockWidget.cpp | 55 +++++++++++++++++++++++++++-------- src/DockWidget.h | 23 +++++++++++++++ src/FloatingDockContainer.cpp | 13 +++++++++ src/FloatingDockContainer.h | 8 +++++ 6 files changed, 134 insertions(+), 21 deletions(-) diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 1ad78d5..f1724c2 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include "DockManager.h" #include "DockAreaWidget.h" @@ -432,6 +433,7 @@ bool DockContainerWidgetPrivate::restoreDockArea(QDataStream& stream, << std::endl; DockArea->addDockWidget(DockWidget); DockWidget->toggleView(!Closed); + DockWidget->setProperty("dirty", false); } if (Testing) @@ -528,6 +530,7 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW //============================================================================ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget) { +#if defined(QT_DEBUG) QSplitter* Splitter = dynamic_cast(widget); QByteArray buf; buf.fill(' ', level * 4); @@ -549,6 +552,7 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget) } std::cout << buf.toStdString() << "DockArea" << std::endl; } +#endif } diff --git a/src/DockManager.cpp b/src/DockManager.cpp index f3fdb4d..fc77f64 100644 --- a/src/DockManager.cpp +++ b/src/DockManager.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -41,6 +42,7 @@ #include "DockWidget.h" #include "ads_globals.h" #include "DockStateSerialization.h" +#include "DockWidgetTitleBar.h" namespace ads { @@ -77,6 +79,11 @@ struct DockManagerPrivate * Restores the state */ bool restoreState(const QByteArray &state, int version); + + /** + * Restores the container with the given index + */ + bool restoreContainer(int Index, QDataStream& stream, bool Testing); }; // struct DockManagerPrivate @@ -135,6 +142,22 @@ bool DockManagerPrivate::checkFormat(const QByteArray &state, int version) } +//============================================================================ +bool DockManagerPrivate::restoreContainer(int Index, QDataStream& stream, bool Testing) +{ + if (Index >= Containers.count()) + { + CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this); + return FloatingWidget->restoreState(stream, internal::Restore); + } + else + { + std::cout << "d->Containers[i]->restoreState " << Index << std::endl; + return Containers[Index]->restoreState(stream, internal::Restore); + } +} + + //============================================================================ bool DockManagerPrivate::restoreState(const QByteArray &state, int version) { @@ -162,15 +185,9 @@ bool DockManagerPrivate::restoreState(const QByteArray &state, int version) int i; for (i = 0; i < ContainerCount; ++i) { - if (i >= Containers.count()) + Result = restoreContainer(i, stream, internal::Restore); + if (!Result) { - CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this); - } - - std::cout << "d->Containers[i]->restoreState " << i << std::endl; - if (!Containers[i]->restoreState(stream, internal::Restore)) - { - Result = false; break; } } @@ -180,7 +197,7 @@ bool DockManagerPrivate::restoreState(const QByteArray &state, int version) int DeleteCount = FloatingWidgets.count() - FloatingWidgetIndex; for (int i = 0; i < DeleteCount; ++i) { - delete FloatingWidgets[FloatingWidgetIndex]; + FloatingWidgets[FloatingWidgetIndex]->deleteLater(); } return Result; @@ -309,12 +326,29 @@ bool CDockManager::restoreState(const QByteArray &state, int version) return false; } + for (auto DockWidget : d->DockWidgetsMap) + { + DockWidget->setProperty("dirty", true); + } + if (!d->restoreState(state, version)) { std::cout << "restoreState: Error restoring state!!!!!!!" << std::endl; return false; } + // All dock widgets, that have not been processed in the restore state + // function are invisible to the user now and have no assigned dock area + // The do not belong to any dock container, until the user toggles the + // toggle view action the next time + for (auto DockWidget : d->DockWidgetsMap) + { + if (DockWidget->property("dirty").toBool()) + { + DockWidget->flagAsUnassigned(); + } + } + return true; } diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index a43c9c8..a4b3d9d 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -108,21 +109,30 @@ DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) : //============================================================================ void DockWidgetPrivate::showDockWidget() { - DockArea->show(); - DockArea->setCurrentIndex(DockArea->tabIndex(_this)); - QSplitter* Splitter = internal::findParent(_this); - if (Splitter) + if (!DockArea) { - Splitter->show(); - } - - CDockContainerWidget* Container = DockArea->dockContainer(); - if (Container->isFloating()) - { - CFloatingDockContainer* FloatingWidget = internal::findParent< - CFloatingDockContainer*>(Container); + CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this); + FloatingWidget->resize(_this->size()); FloatingWidget->show(); } + else + { + DockArea->show(); + DockArea->setCurrentIndex(DockArea->tabIndex(_this)); + QSplitter* Splitter = internal::findParent(_this); + if (Splitter) + { + Splitter->show(); + } + + CDockContainerWidget* Container = DockArea->dockContainer(); + if (Container->isFloating()) + { + CFloatingDockContainer* FloatingWidget = internal::findParent< + CFloatingDockContainer*>(Container); + FloatingWidget->show(); + } + } } @@ -363,6 +373,27 @@ void CDockWidget::saveState(QDataStream& stream) const } +//============================================================================ +void CDockWidget::flagAsUnassigned() +{ + setParent(d->DockManager); + setDockArea(nullptr); + titleBar()->setParent(this); +} + + +//============================================================================ +bool CDockWidget::event(QEvent *e) +{ + if (e->type() == QEvent::WindowTitleChange) + { + emit titleChanged(windowTitle()); + } + return QFrame::event(e); +} + + + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/DockWidget.h b/src/DockWidget.h index 424eadf..532e7f6 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -55,6 +55,7 @@ protected: friend class CDockContainerWidget; friend class CDockAreaWidget; friend class CFloatingDockContainer; + friend class CDockManager; /** * Assigns the dock manager that manages this dock widget @@ -80,6 +81,17 @@ protected: */ void saveState(QDataStream& Stream) const; + /** + * This is a helper function for the dock manager to flag this widget + * as unassigned. + * When calling the restore function, it may happen, that the saved state + * contains less dock widgets then currently available. All widgets whose + * data is not contained in the saved state, are flagged as unassigned + * after the restore process. If the user shows an unassigned dock widget, + * a floating widget will be created to take up the dock widget. + */ + void flagAsUnassigned(); + public: enum DockWidgetFeature { @@ -172,6 +184,11 @@ public: */ QAction* toggleViewAction() const; + /** + * Emits titleChanged signal if title change event occures + */ + virtual bool event(QEvent *e) override; + public slots: /** * This property controls whether the dock widget is open or closed. @@ -189,6 +206,12 @@ signals: * This signal is emitted if the dock widget is closed */ void closed(); + + /** + * This signal is emitted if the window title of this dock widget + * changed + */ + void titleChanged(const QString& Title); }; // class DockWidget } // namespace ads diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 2b2dae2..52f6216 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -367,6 +367,7 @@ void CFloatingDockContainer::moveFloating() //============================================================================ void CFloatingDockContainer::onDockAreasAddedOrRemoved() { + std::cout << "CFloatingDockContainer::onDockAreasAddedOrRemoved()" << std::endl; if (d->DockContainer->dockAreaCount() == 1) { d->SingleDockArea = d->DockContainer->dockArea(0); @@ -394,6 +395,18 @@ void CFloatingDockContainer::onDockAreaCurrentChanged(int Index) } +//============================================================================ +bool CFloatingDockContainer::restoreState(QDataStream& Stream, bool Testing) +{ + if (!d->DockContainer->restoreState(Stream, Testing)) + { + return false; + } + onDockAreasAddedOrRemoved(); + return true; +} + + } // namespace ads //--------------------------------------------------------------------------- diff --git a/src/FloatingDockContainer.h b/src/FloatingDockContainer.h index 38caf37..bd18e13 100644 --- a/src/FloatingDockContainer.h +++ b/src/FloatingDockContainer.h @@ -103,6 +103,14 @@ public: * startFloating() was called */ void moveFloating(); + + /** + * Restores the state from given stream. + * If Testing is true, the function only parses the data from the given + * stream but does not restore anything. You can use this check for + * faulty files before you start restoring the state + */ + bool restoreState(QDataStream& Stream, bool Testing); }; // class FloatingDockContainer } // namespace ads