Improved serialization support

This commit is contained in:
Uwe Kindler 2017-03-27 10:41:27 +02:00
parent 2277ba3630
commit 1b1c636107
8 changed files with 338 additions and 109 deletions

View File

@ -5,7 +5,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/> <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/> <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser" keep-relative-paths="false" name="CDT GCC Build Output Parser" parameter="(g?cc)|([gc]\+\+)|(clang)" prefer-non-shared="true"/> <provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser" keep-relative-paths="false" name="CDT GCC Build Output Parser" parameter="(g?cc)|([gc]\+\+)|(clang)" prefer-non-shared="true"/>
<provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorMinGW" console="false" env-hash="1111767096691303650" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorMinGW" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings MinGW" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true"> <provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorMinGW" console="false" env-hash="-797032510223863550" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorMinGW" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings MinGW" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/> <language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/> <language-scope id="org.eclipse.cdt.core.g++"/>
</provider> </provider>

View File

@ -122,9 +122,28 @@ struct DockContainerWidgetPrivate
void saveChildNodesState(QDataStream& Stream, QWidget* Widget); 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 }; // struct DockContainerWidgetPrivate
@ -290,7 +309,7 @@ void DockContainerWidgetPrivate::saveChildNodesState(QDataStream& stream, QWidge
QSplitter* Splitter = dynamic_cast<QSplitter*>(Widget); QSplitter* Splitter = dynamic_cast<QSplitter*>(Widget);
if (Splitter) if (Splitter)
{ {
stream << NodeSplitter << Splitter->orientation() << Splitter->count(); stream << internal::SplitterMarker << Splitter->orientation() << Splitter->count();
std::cout << "NodeSplitter orient: " << Splitter->orientation() std::cout << "NodeSplitter orient: " << Splitter->orientation()
<< " WidgetCont: " << Splitter->count() << std::endl; << " WidgetCont: " << Splitter->count() << std::endl;
for (int i = 0; i < Splitter->count(); ++i) for (int i = 0; i < Splitter->count(); ++i)
@ -301,7 +320,7 @@ void DockContainerWidgetPrivate::saveChildNodesState(QDataStream& stream, QWidge
} }
else else
{ {
stream << NodeDockArea; stream << internal::DockAreaMarker;
CDockAreaWidget* DockArea = dynamic_cast<CDockAreaWidget*>(Widget); CDockAreaWidget* DockArea = dynamic_cast<CDockAreaWidget*>(Widget);
if (DockArea) if (DockArea)
{ {
@ -312,35 +331,43 @@ void DockContainerWidgetPrivate::saveChildNodesState(QDataStream& stream, QWidge
//============================================================================ //============================================================================
void DockContainerWidgetPrivate::restoreChildNodes(QDataStream& stream, bool DockContainerWidgetPrivate::restoreSplitter(QDataStream& stream,
QWidget*& CreatedWidget) QWidget*& CreatedWidget, bool Testing)
{ {
int NodeType; int Orientation;
stream >> NodeType; int WidgetCount;
if (NodeSplitter == NodeType) stream >> Orientation >> WidgetCount;
std::cout << "Restore NodeSplitter Orientation: " << Orientation <<
" WidgetCount: " << WidgetCount << std::endl;
QSplitter* Splitter = nullptr;
if (!Testing)
{ {
int Orientation; Splitter = internal::newSplitter((Qt::Orientation)Orientation);
int WidgetCount; }
stream >> Orientation >> WidgetCount; bool Visible = false;
std::cout << "Restore NodeSplitter Orientation: " << Orientation << for (int i = 0; i < WidgetCount; ++i)
" WidgetCount: " << WidgetCount << std::endl; {
QSplitter* Splitter = internal::newSplitter((Qt::Orientation)Orientation); QWidget* ChildNode;
bool Visible = false; if (!restoreChildNodes(stream, ChildNode, Testing))
for (int i = 0; i < WidgetCount; ++i)
{ {
QWidget* ChildNode; return false;
restoreChildNodes(stream, ChildNode);
if (ChildNode)
{
Splitter->addWidget(ChildNode);
}
std::cout << "ChildNode isVisible " << ChildNode->isVisible()
<< " isVisibleTo " << ChildNode->isVisibleTo(Splitter) << std::endl;
Visible |= ChildNode->isVisibleTo(Splitter);
} }
QList<int> Sizes; if (Testing)
stream >> Sizes; {
continue;
}
std::cout << "ChildNode isVisible " << ChildNode->isVisible()
<< " isVisibleTo " << ChildNode->isVisibleTo(Splitter) << std::endl;
Splitter->addWidget(ChildNode);
Visible |= ChildNode->isVisibleTo(Splitter);
}
QList<int> Sizes;
stream >> Sizes;
if (!Testing)
{
if (!Splitter->count()) if (!Splitter->count())
{ {
delete Splitter; delete Splitter;
@ -355,43 +382,89 @@ void DockContainerWidgetPrivate::restoreChildNodes(QDataStream& stream,
} }
else else
{ {
int Tabs; CreatedWidget = nullptr;
int CurrentIndex; }
stream >> Tabs >> CurrentIndex; return true;
std::cout << "Restore NodeDockArea Tabs: " << Tabs << " CurrentIndex: " }
<< CurrentIndex << std::endl;
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; return false;
bool Closed;
stream >> ObjectName >> Closed;
std::cout << "Restore DockWidget " << ObjectName.toStdString() << " Closed: "
<< Closed << std::endl;
CDockWidget* DockWidget = DockManager->findChild<CDockWidget*>(ObjectName);
if (!DockWidget)
{
continue;
}
else
{
std::cout << "Dock Widget found - parent " << DockWidget->parent()
<< std::endl;
DockArea->addDockWidget(DockWidget);
}
DockWidget->toggleView(!Closed);
} }
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; continue;
DockArea = nullptr;
} }
CreatedWidget = DockArea;
DockAreas.append(DockArea); std::cout << "Dock Widget found - parent " << DockWidget->parent()
DockArea->setCurrentIndex(CurrentIndex); << 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 " std::cout << "CDockContainerWidget::saveState isFloating "
<< isFloating() << std::endl; << isFloating() << std::endl;
stream << internal::ContainerMarker;
stream << isFloating(); stream << isFloating();
if (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; bool IsFloating;
int Marker;
stream >> Marker;
if (Marker != internal::ContainerMarker)
{
return false;
}
stream >> IsFloating; stream >> IsFloating;
std::cout << "Restore CDockContainerWidget Floating" << IsFloating << std::endl; std::cout << "Restore CDockContainerWidget Floating" << IsFloating << std::endl;
QWidget* NewRootSplitter; QWidget* NewRootSplitter;
d->DockAreas.clear(); if (!Testing)
if (isFloating())
{ {
std::cout << "Restore floating widget" << std::endl; d->DockAreas.clear();
CFloatingDockContainer* FloatingWidget = internal::findParent<CFloatingDockContainer*>(this);
QByteArray Geometry;
stream >> Geometry;
FloatingWidget->restoreGeometry(Geometry);
FloatingWidget->show();
} }
d->restoreChildNodes(stream, NewRootSplitter); if (IsFloating)
{
std::cout << "Restore floating widget" << std::endl;
QByteArray Geometry;
stream >> Geometry;
if (!Testing)
{
CFloatingDockContainer* FloatingWidget = internal::findParent<CFloatingDockContainer*>(this);
FloatingWidget->restoreGeometry(Geometry);
FloatingWidget->show();
}
}
if (!d->restoreChildNodes(stream, NewRootSplitter, Testing))
{
return false;
}
if (Testing)
{
return true;
}
d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter); d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter);
QSplitter* OldRoot = d->RootSplitter; QSplitter* OldRoot = d->RootSplitter;
d->RootSplitter = dynamic_cast<QSplitter*>(NewRootSplitter); d->RootSplitter = dynamic_cast<QSplitter*>(NewRootSplitter);
delete OldRoot; OldRoot->deleteLater();
return true; return true;
} }

View File

@ -140,9 +140,12 @@ public:
void saveState(QDataStream& Stream) const; 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: signals:
/** /**

View File

@ -32,21 +32,19 @@
#include <QMainWindow> #include <QMainWindow>
#include <QList> #include <QList>
#include <QMap>
#include <iostream> #include <iostream>
#include "FloatingDockContainer.h" #include "FloatingDockContainer.h"
#include "DockOverlay.h" #include "DockOverlay.h"
#include "DockWidget.h"
#include "ads_globals.h"
#include "DockStateSerialization.h"
namespace ads namespace ads
{ {
// sentinel values used to validate state data
enum VersionMarkers
{
VersionMarker = 0xff
};
/** /**
* Private data class of CDockManager class (pimpl) * Private data class of CDockManager class (pimpl)
*/ */
@ -57,6 +55,7 @@ struct DockManagerPrivate
QList<CDockContainerWidget*> Containers; QList<CDockContainerWidget*> Containers;
CDockOverlay* ContainerOverlay; CDockOverlay* ContainerOverlay;
CDockOverlay* DockAreaOverlay; CDockOverlay* DockAreaOverlay;
QMap<QString, CDockWidget*> DockWidgetsMap;
/** /**
* Private data constructor * Private data constructor
@ -67,6 +66,17 @@ struct DockManagerPrivate
* Restores a non existing container from stream * Restores a non existing container from stream
*/ */
bool restoreContainer(QDataStream& 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 // struct DockManagerPrivate
@ -83,6 +93,97 @@ bool DockManagerPrivate::restoreContainer(QDataStream& Stream)
{ {
std::cout << "restoreContainer" << std::endl; std::cout << "restoreContainer" << std::endl;
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this); 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; QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly); QDataStream stream(&data, QIODevice::WriteOnly);
stream << VersionMarker; stream << internal::VersionMarker;
stream << version; stream << version;
stream << d->Containers.count(); stream << d->Containers.count();
@ -202,39 +303,36 @@ QByteArray CDockManager::saveState(int version) const
//============================================================================ //============================================================================
bool CDockManager::restoreState(const QByteArray &state, int version) bool CDockManager::restoreState(const QByteArray &state, int version)
{ {
if (state.isEmpty()) if (!d->checkFormat(state, version))
{ {
return false; std::cout << "checkFormat: Error checking format!!!!!!!" << std::endl;
} 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;
} }
int ContainerCount; if (!d->restoreState(state, version))
stream >> ContainerCount;
std::cout << "ContainerCount " << ContainerCount << std::endl;
for (int i = 0; i < ContainerCount; ++i)
{ {
if (i >= d->Containers.count()) std::cout << "restoreState: Error restoring state!!!!!!!" << std::endl;
{ return false;
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(this);
}
std::cout << "d->Containers[i]->restoreState " << i << std::endl;
d->Containers[i]->restoreState(stream);
} }
return true; 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 } // namespace ads
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -98,6 +98,23 @@ public:
*/ */
CDockOverlay* dockAreaOverlay() const; 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 * Returns the list of all active and visible dock containers
* Dock containers are the main dock manager and all floating widgets * Dock containers are the main dock manager and all floating widgets

View File

@ -34,11 +34,22 @@
namespace ads namespace ads
{ {
enum eDockTreeNodeType
namespace internal
{ {
NodeSplitter, // sentinel values used to validate state data
NodeDockArea 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 } // namespace ads
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#endif // DockManagerH #endif // DockManagerH

View File

@ -44,7 +44,7 @@
#include "DockAreaWidget.h" #include "DockAreaWidget.h"
#include "DockManager.h" #include "DockManager.h"
#include "FloatingDockContainer.h" #include "FloatingDockContainer.h"
#include "DockStateSerialization.h"
#include "ads_globals.h" #include "ads_globals.h"
namespace ads namespace ads
@ -356,6 +356,7 @@ void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
//============================================================================ //============================================================================
void CDockWidget::saveState(QDataStream& stream) const void CDockWidget::saveState(QDataStream& stream) const
{ {
stream << internal::DockWidgetMarker;
std::cout << "CDockWidget::saveState " << objectName().toStdString() std::cout << "CDockWidget::saveState " << objectName().toStdString()
<< " closed " << d->Closed << std::endl; << " closed " << d->Closed << std::endl;
stream << objectName() << d->Closed; stream << objectName() << d->Closed;

View File

@ -51,8 +51,11 @@ enum DockWidgetArea
}; };
Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea) Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea)
namespace internal namespace internal
{ {
/** /**
* Helper function to create new splitter widgets * Helper function to create new splitter widgets
*/ */