diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
index 6adb5be..a8d9d50 100644
--- a/.settings/language.settings.xml
+++ b/.settings/language.settings.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp
index 45ce63e..8697f19 100644
--- a/src/DockContainerWidget.cpp
+++ b/src/DockContainerWidget.cpp
@@ -122,9 +122,28 @@ struct DockContainerWidgetPrivate
void saveChildNodesState(QDataStream& Stream, QWidget* Widget);
/**
- * Restore state of child nodes
+ * Restore state of child nodes.
+ * \param[in] Stream The data stream that contains the serialized state
+ * \param[out] CreatedWidget The widget created from parsed data
+ * \param[in] Testing If Testing is true, only the stream data is
+ * parsed without modifiying anything.
*/
- void restoreChildNodes(QDataStream& Stream, QWidget*& CreatedWidget);
+ bool restoreChildNodes(QDataStream& Stream, QWidget*& CreatedWidget,
+ bool Testing);
+
+ /**
+ * Restores a splitter.
+ * \see restoreChildNodes() for details
+ */
+ bool restoreSplitter(QDataStream& Stream, QWidget*& CreatedWidget,
+ bool Testing);
+
+ /**
+ * Restores a dock area.
+ * \see restoreChildNodes() for details
+ */
+ bool restoreDockArea(QDataStream& Stream, QWidget*& CreatedWidget,
+ bool Testing);
}; // struct DockContainerWidgetPrivate
@@ -290,7 +309,7 @@ void DockContainerWidgetPrivate::saveChildNodesState(QDataStream& stream, QWidge
QSplitter* Splitter = dynamic_cast(Widget);
if (Splitter)
{
- stream << NodeSplitter << Splitter->orientation() << Splitter->count();
+ stream << internal::SplitterMarker << Splitter->orientation() << Splitter->count();
std::cout << "NodeSplitter orient: " << Splitter->orientation()
<< " WidgetCont: " << Splitter->count() << std::endl;
for (int i = 0; i < Splitter->count(); ++i)
@@ -301,7 +320,7 @@ void DockContainerWidgetPrivate::saveChildNodesState(QDataStream& stream, QWidge
}
else
{
- stream << NodeDockArea;
+ stream << internal::DockAreaMarker;
CDockAreaWidget* DockArea = dynamic_cast(Widget);
if (DockArea)
{
@@ -312,35 +331,43 @@ void DockContainerWidgetPrivate::saveChildNodesState(QDataStream& stream, QWidge
//============================================================================
-void DockContainerWidgetPrivate::restoreChildNodes(QDataStream& stream,
- QWidget*& CreatedWidget)
+bool DockContainerWidgetPrivate::restoreSplitter(QDataStream& stream,
+ QWidget*& CreatedWidget, bool Testing)
{
- int NodeType;
- stream >> NodeType;
- if (NodeSplitter == NodeType)
+ int Orientation;
+ int WidgetCount;
+ stream >> Orientation >> WidgetCount;
+ std::cout << "Restore NodeSplitter Orientation: " << Orientation <<
+ " WidgetCount: " << WidgetCount << std::endl;
+ QSplitter* Splitter = nullptr;
+ if (!Testing)
{
- int Orientation;
- int WidgetCount;
- stream >> Orientation >> WidgetCount;
- std::cout << "Restore NodeSplitter Orientation: " << Orientation <<
- " WidgetCount: " << WidgetCount << std::endl;
- QSplitter* Splitter = internal::newSplitter((Qt::Orientation)Orientation);
- bool Visible = false;
- for (int i = 0; i < WidgetCount; ++i)
+ Splitter = internal::newSplitter((Qt::Orientation)Orientation);
+ }
+ bool Visible = false;
+ for (int i = 0; i < WidgetCount; ++i)
+ {
+ QWidget* ChildNode;
+ if (!restoreChildNodes(stream, ChildNode, Testing))
{
- QWidget* ChildNode;
- restoreChildNodes(stream, ChildNode);
- if (ChildNode)
- {
- Splitter->addWidget(ChildNode);
- }
- std::cout << "ChildNode isVisible " << ChildNode->isVisible()
- << " isVisibleTo " << ChildNode->isVisibleTo(Splitter) << std::endl;
- Visible |= ChildNode->isVisibleTo(Splitter);
+ return false;
}
- QList Sizes;
- stream >> Sizes;
+ if (Testing)
+ {
+ continue;
+ }
+
+ std::cout << "ChildNode isVisible " << ChildNode->isVisible()
+ << " isVisibleTo " << ChildNode->isVisibleTo(Splitter) << std::endl;
+ Splitter->addWidget(ChildNode);
+ Visible |= ChildNode->isVisibleTo(Splitter);
+ }
+
+ QList Sizes;
+ stream >> Sizes;
+ if (!Testing)
+ {
if (!Splitter->count())
{
delete Splitter;
@@ -355,43 +382,89 @@ void DockContainerWidgetPrivate::restoreChildNodes(QDataStream& stream,
}
else
{
- int Tabs;
- int CurrentIndex;
- stream >> Tabs >> CurrentIndex;
- std::cout << "Restore NodeDockArea Tabs: " << Tabs << " CurrentIndex: "
- << CurrentIndex << std::endl;
+ CreatedWidget = nullptr;
+ }
+ return true;
+}
- CDockAreaWidget* DockArea = new CDockAreaWidget(DockManager, _this);
- for (int i = 0; i < Tabs; ++i)
+
+//============================================================================
+bool DockContainerWidgetPrivate::restoreDockArea(QDataStream& stream,
+ QWidget*& CreatedWidget, bool Testing)
+{
+ int Tabs;
+ int CurrentIndex;
+ stream >> Tabs >> CurrentIndex;
+ std::cout << "Restore NodeDockArea Tabs: " << Tabs << " CurrentIndex: "
+ << CurrentIndex << std::endl;
+
+ CDockAreaWidget* DockArea = nullptr;
+ if (!Testing)
+ {
+ DockArea = new CDockAreaWidget(DockManager, _this);
+ }
+
+ for (int i = 0; i < Tabs; ++i)
+ {
+ int Marker;
+ stream >> Marker;
+ if (Marker != internal::DockWidgetMarker)
{
- QString ObjectName;
- bool Closed;
- stream >> ObjectName >> Closed;
- std::cout << "Restore DockWidget " << ObjectName.toStdString() << " Closed: "
- << Closed << std::endl;
-
- CDockWidget* DockWidget = DockManager->findChild(ObjectName);
- if (!DockWidget)
- {
- continue;
- }
- else
- {
- std::cout << "Dock Widget found - parent " << DockWidget->parent()
- << std::endl;
- DockArea->addDockWidget(DockWidget);
- }
- DockWidget->toggleView(!Closed);
+ return false;
}
- if (!DockArea->count())
+ QString ObjectName;
+ bool Closed;
+ stream >> ObjectName >> Closed;
+ std::cout << "Restore DockWidget " << ObjectName.toStdString() << " Closed: "
+ << Closed << std::endl;
+
+ CDockWidget* DockWidget = DockManager->findDockWidget(ObjectName);
+ if (!DockWidget || Testing)
{
- delete DockArea;
- DockArea = nullptr;
+ continue;
}
- CreatedWidget = DockArea;
- DockAreas.append(DockArea);
- DockArea->setCurrentIndex(CurrentIndex);
+
+ std::cout << "Dock Widget found - parent " << DockWidget->parent()
+ << std::endl;
+ DockArea->addDockWidget(DockWidget);
+ DockWidget->toggleView(!Closed);
+ }
+
+ if (Testing)
+ {
+ return true;
+ }
+
+ if (!DockArea->count())
+ {
+ delete DockArea;
+ DockArea = nullptr;
+ }
+ CreatedWidget = DockArea;
+ DockAreas.append(DockArea);
+ DockArea->setCurrentIndex(CurrentIndex);
+ return true;
+}
+
+
+//============================================================================
+bool DockContainerWidgetPrivate::restoreChildNodes(QDataStream& stream,
+ QWidget*& CreatedWidget, bool Testing)
+{
+ int Marker;
+ stream >> Marker;
+ if (internal::SplitterMarker == Marker)
+ {
+ return restoreSplitter(stream, CreatedWidget, Testing);
+ }
+ else if (internal::DockAreaMarker == Marker)
+ {
+ return restoreDockArea(stream, CreatedWidget, Testing);
+ }
+ else
+ {
+ return false;
}
}
@@ -700,6 +773,7 @@ void CDockContainerWidget::saveState(QDataStream& stream) const
{
std::cout << "CDockContainerWidget::saveState isFloating "
<< isFloating() << std::endl;
+ stream << internal::ContainerMarker;
stream << isFloating();
if (isFloating())
{
@@ -712,30 +786,52 @@ void CDockContainerWidget::saveState(QDataStream& stream) const
//============================================================================
-bool CDockContainerWidget::restoreState(QDataStream& stream)
+bool CDockContainerWidget::restoreState(QDataStream& stream, bool Testing)
{
bool IsFloating;
+ int Marker;
+ stream >> Marker;
+ if (Marker != internal::ContainerMarker)
+ {
+ return false;
+ }
+
stream >> IsFloating;
std::cout << "Restore CDockContainerWidget Floating" << IsFloating << std::endl;
QWidget* NewRootSplitter;
- d->DockAreas.clear();
- if (isFloating())
+ if (!Testing)
{
- std::cout << "Restore floating widget" << std::endl;
- CFloatingDockContainer* FloatingWidget = internal::findParent(this);
- QByteArray Geometry;
- stream >> Geometry;
- FloatingWidget->restoreGeometry(Geometry);
- FloatingWidget->show();
+ d->DockAreas.clear();
}
- d->restoreChildNodes(stream, NewRootSplitter);
+ if (IsFloating)
+ {
+ std::cout << "Restore floating widget" << std::endl;
+ QByteArray Geometry;
+ stream >> Geometry;
+ if (!Testing)
+ {
+ CFloatingDockContainer* FloatingWidget = internal::findParent(this);
+ FloatingWidget->restoreGeometry(Geometry);
+ FloatingWidget->show();
+ }
+ }
+
+ if (!d->restoreChildNodes(stream, NewRootSplitter, Testing))
+ {
+ return false;
+ }
+
+ if (Testing)
+ {
+ return true;
+ }
d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter);
QSplitter* OldRoot = d->RootSplitter;
d->RootSplitter = dynamic_cast(NewRootSplitter);
- delete OldRoot;
+ OldRoot->deleteLater();
return true;
}
diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h
index 278a504..9d344bd 100644
--- a/src/DockContainerWidget.h
+++ b/src/DockContainerWidget.h
@@ -140,9 +140,12 @@ public:
void saveState(QDataStream& Stream) const;
/**
- * Restores the state from given stream
+ * 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 restoreState(QDataStream& Stream, bool Testing);
signals:
/**
diff --git a/src/DockManager.cpp b/src/DockManager.cpp
index e40766f..f3fdb4d 100644
--- a/src/DockManager.cpp
+++ b/src/DockManager.cpp
@@ -32,21 +32,19 @@
#include
#include
+#include
#include
#include "FloatingDockContainer.h"
#include "DockOverlay.h"
+#include "DockWidget.h"
+#include "ads_globals.h"
+#include "DockStateSerialization.h"
namespace ads
{
-// sentinel values used to validate state data
-enum VersionMarkers
-{
- VersionMarker = 0xff
-};
-
/**
* Private data class of CDockManager class (pimpl)
*/
@@ -57,6 +55,7 @@ struct DockManagerPrivate
QList Containers;
CDockOverlay* ContainerOverlay;
CDockOverlay* DockAreaOverlay;
+ QMap DockWidgetsMap;
/**
* Private data constructor
@@ -67,6 +66,17 @@ struct DockManagerPrivate
* Restores a non existing container from stream
*/
bool restoreContainer(QDataStream& Stream);
+
+ /**
+ * Checks if the given data stream is a valid docking system state
+ * file.
+ */
+ bool checkFormat(const QByteArray &state, int version);
+
+ /**
+ * Restores the state
+ */
+ bool restoreState(const QByteArray &state, int version);
};
// struct DockManagerPrivate
@@ -83,6 +93,97 @@ bool DockManagerPrivate::restoreContainer(QDataStream& Stream)
{
std::cout << "restoreContainer" << std::endl;
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
+ return true;
+}
+
+
+//============================================================================
+bool DockManagerPrivate::checkFormat(const QByteArray &state, int version)
+{
+ if (state.isEmpty())
+ {
+ return false;
+ }
+ QByteArray sd = state;
+ QDataStream stream(&sd, QIODevice::ReadOnly);
+
+ int marker;
+ int v;
+ stream >> marker;
+ stream >> v;
+
+ if (stream.status() != QDataStream::Ok || marker != internal::VersionMarker || v != version)
+ {
+ return false;
+ }
+
+ int Result = true;
+ int ContainerCount;
+ stream >> ContainerCount;
+ std::cout << "ContainerCount " << ContainerCount << std::endl;
+ int i;
+ for (i = 0; i < ContainerCount; ++i)
+ {
+ if (!Containers[0]->restoreState(stream, internal::RestoreTesting))
+ {
+ Result = false;
+ break;
+ }
+ }
+
+ return Result;
+}
+
+
+//============================================================================
+bool DockManagerPrivate::restoreState(const QByteArray &state, int version)
+{
+ if (state.isEmpty())
+ {
+ return false;
+ }
+ QByteArray sd = state;
+ QDataStream stream(&sd, QIODevice::ReadOnly);
+
+ int marker;
+ int v;
+ stream >> marker;
+ stream >> v;
+
+ if (stream.status() != QDataStream::Ok || marker != internal::VersionMarker || v != version)
+ {
+ return false;
+ }
+
+ int Result = true;
+ int ContainerCount;
+ stream >> ContainerCount;
+ std::cout << "ContainerCount " << ContainerCount << std::endl;
+ int i;
+ for (i = 0; i < ContainerCount; ++i)
+ {
+ if (i >= Containers.count())
+ {
+ CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
+ }
+
+ std::cout << "d->Containers[i]->restoreState " << i << std::endl;
+ if (!Containers[i]->restoreState(stream, internal::Restore))
+ {
+ Result = false;
+ break;
+ }
+ }
+
+ // Delete remaining empty floating widgets
+ int FloatingWidgetIndex = i - 1;
+ int DeleteCount = FloatingWidgets.count() - FloatingWidgetIndex;
+ for (int i = 0; i < DeleteCount; ++i)
+ {
+ delete FloatingWidgets[FloatingWidgetIndex];
+ }
+
+ return Result;
}
@@ -187,7 +288,7 @@ QByteArray CDockManager::saveState(int version) const
{
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
- stream << VersionMarker;
+ stream << internal::VersionMarker;
stream << version;
stream << d->Containers.count();
@@ -202,39 +303,36 @@ QByteArray CDockManager::saveState(int version) const
//============================================================================
bool CDockManager::restoreState(const QByteArray &state, int version)
{
- if (state.isEmpty())
+ if (!d->checkFormat(state, version))
{
- return false;
- }
- QByteArray sd = state;
- QDataStream stream(&sd, QIODevice::ReadOnly);
-
- int marker;
- int v;
- stream >> marker;
- stream >> v;
-
- if (stream.status() != QDataStream::Ok || marker != VersionMarker || v != version)
- {
- return false;
+ std::cout << "checkFormat: Error checking format!!!!!!!" << std::endl;
+ return false;
}
- int ContainerCount;
- stream >> ContainerCount;
- std::cout << "ContainerCount " << ContainerCount << std::endl;
- for (int i = 0; i < ContainerCount; ++i)
+ if (!d->restoreState(state, version))
{
- if (i >= d->Containers.count())
- {
- CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(this);
- }
-
- std::cout << "d->Containers[i]->restoreState " << i << std::endl;
- d->Containers[i]->restoreState(stream);
+ std::cout << "restoreState: Error restoring state!!!!!!!" << std::endl;
+ return false;
}
return true;
}
+
+
+//============================================================================
+CDockAreaWidget* CDockManager::addDockWidget(DockWidgetArea area,
+ CDockWidget* Dockwidget, CDockAreaWidget* DockAreaWidget)
+{
+ d->DockWidgetsMap.insert(Dockwidget->objectName(), Dockwidget);
+ return CDockContainerWidget::addDockWidget(area, Dockwidget, DockAreaWidget);
+}
+
+
+//============================================================================
+CDockWidget* CDockManager::findDockWidget(const QString& ObjectName)
+{
+ return d->DockWidgetsMap.value(ObjectName, nullptr);
+}
} // namespace ads
//---------------------------------------------------------------------------
diff --git a/src/DockManager.h b/src/DockManager.h
index 5192646..91db2d9 100644
--- a/src/DockManager.h
+++ b/src/DockManager.h
@@ -98,6 +98,23 @@ public:
*/
CDockOverlay* dockAreaOverlay() const;
+ /**
+ * Adds dockwidget into the given area.
+ * If DockAreaWidget is not null, then the area parameter indicates the area
+ * into the DockAreaWidget. If DockAreaWidget is null, the Dockwidget will
+ * be dropped into the container.
+ * \return Returns the dock area widget that contains the new DockWidget
+ */
+ CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
+ CDockAreaWidget* DockAreaWidget = nullptr);
+
+ /**
+ * Searches for a registered doc widget with the given ObjectName
+ * \return Return the found dock widget or nullptr if a dock widget with the
+ * given name is not registered
+ */
+ CDockWidget* findDockWidget(const QString& ObjectName);
+
/**
* Returns the list of all active and visible dock containers
* Dock containers are the main dock manager and all floating widgets
diff --git a/src/DockStateSerialization.h b/src/DockStateSerialization.h
index 698f6e5..6d0fe6f 100644
--- a/src/DockStateSerialization.h
+++ b/src/DockStateSerialization.h
@@ -34,11 +34,22 @@
namespace ads
{
-enum eDockTreeNodeType
+
+namespace internal
{
- NodeSplitter,
- NodeDockArea
+// sentinel values used to validate state data
+enum VersionMarkers
+{
+ VersionMarker = 0xff,
+ ContainerMarker = 0xfe,
+ SplitterMarker = 0xfd,
+ DockAreaMarker = 0xfc,
+ DockWidgetMarker = 0xfb
};
+
+static const bool RestoreTesting = true;
+static const bool Restore = false;
+} // internal
} // namespace ads
//-----------------------------------------------------------------------------
#endif // DockManagerH
diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp
index c49daad..a43c9c8 100644
--- a/src/DockWidget.cpp
+++ b/src/DockWidget.cpp
@@ -44,7 +44,7 @@
#include "DockAreaWidget.h"
#include "DockManager.h"
#include "FloatingDockContainer.h"
-
+#include "DockStateSerialization.h"
#include "ads_globals.h"
namespace ads
@@ -356,6 +356,7 @@ void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
//============================================================================
void CDockWidget::saveState(QDataStream& stream) const
{
+ stream << internal::DockWidgetMarker;
std::cout << "CDockWidget::saveState " << objectName().toStdString()
<< " closed " << d->Closed << std::endl;
stream << objectName() << d->Closed;
diff --git a/src/ads_globals.h b/src/ads_globals.h
index a1aea46..a79c947 100644
--- a/src/ads_globals.h
+++ b/src/ads_globals.h
@@ -51,8 +51,11 @@ enum DockWidgetArea
};
Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea)
+
namespace internal
{
+
+
/**
* Helper function to create new splitter widgets
*/