From 9cf1cdadbc07b9499b15a1c005f53ad988d69f49 Mon Sep 17 00:00:00 2001 From: AgCaliva Date: Fri, 30 Jun 2023 20:50:36 -0300 Subject: [PATCH] Implemented DocumentReader for GuiDocument.xml reading. Final --- src/App/Document.cpp | 6 +- src/App/DynamicProperty.cpp | 30 +++ src/App/DynamicProperty.h | 11 + src/App/Extension.cpp | 20 +- src/App/Extension.h | 4 + src/App/ExtensionContainer.cpp | 149 +++++++++----- src/App/ExtensionContainer.h | 8 +- src/App/PropertyContainer.cpp | 219 +++++++++++--------- src/App/PropertyContainer.h | 15 +- src/App/PropertyStandard.cpp | 357 +++++++++++++++++++++++++++++++++ src/App/PropertyStandard.h | 24 +++ src/Base/DocumentReader.cpp | 178 ++++++++-------- src/Base/DocumentReader.h | 49 +++-- src/Base/Persistence.cpp | 10 +- src/Base/Persistence.h | 13 ++ src/Base/Reader.cpp | 19 +- src/Base/Reader.h | 4 + src/Gui/Document.cpp | 248 ++++++++++++++--------- src/Gui/Document.h | 2 + src/Gui/Tree.cpp | 29 ++- 20 files changed, 1036 insertions(+), 359 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index a72cc89188..30a65d4579 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -87,6 +87,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #include #include #include +#include #include #include #include @@ -1227,7 +1228,6 @@ Document::readObjects(Base::XMLReader& reader) // read the object types reader.readElement("Objects"); int Cnt = reader.getAttributeAsInteger("Count"); - if(!reader.hasAttribute(FC_ATTR_DEPENDENCIES)) d->partialLoadObjects.clear(); else if(!d->partialLoadObjects.empty()) { @@ -2023,12 +2023,12 @@ void Document::restore (const char *filename, // without GUI. But if available then follow after all data files of the App document. signalRestoreDocument(reader); reader.readFiles(zipstream); - + if (reader.testStatus(Base::XMLReader::ReaderStatus::PartialRestore)) { setStatus(Document::PartialRestore, true); Base::Console().Error("There were errors while loading the file. Some data might have been modified or not recovered at all. Look above for more specific information about the objects involved.\n"); } - + if(!delaySignal) afterRestore(true); } diff --git a/src/App/DynamicProperty.cpp b/src/App/DynamicProperty.cpp index 7ad6419b33..c105483f42 100644 --- a/src/App/DynamicProperty.cpp +++ b/src/App/DynamicProperty.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "DynamicProperty.h" #include "Application.h" @@ -322,6 +323,35 @@ Property *DynamicProperty::restore(PropertyContainer &pc, return addDynamicProperty(pc,TypeName, PropName, group, doc, attribute, readonly, hidden); } +Property *DynamicProperty::restore(PropertyContainer &pc, + const char *PropName, const char *TypeName, Base::DocumentReader &reader, XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *PropertyDOM) +{ + const char* group_cstr = reader.GetAttribute(PropertyDOM,"group"); + if(!group_cstr) + return nullptr; + + short attribute = 0; + bool readonly = false, hidden = false; + + const char* doc_cstr = reader.GetAttribute(PropertyDOM,"doc"); + const char* attr_cstr = reader.GetAttribute(PropertyDOM,"attr"); + + if(attr_cstr){ + std::istringstream str(attr_cstr); + str >> attribute; + } + + const char* ro_cstr = reader.GetAttribute(PropertyDOM,"ro"); + if(ro_cstr) + readonly = (ro_cstr[0]-48) != 0; + + const char* hide_cstr = reader.GetAttribute(PropertyDOM,"hide"); + if(hide_cstr) + hidden = (hide_cstr[0]-48) != 0; + + return addDynamicProperty(pc,TypeName, PropName, group_cstr, doc_cstr, attribute, readonly, hidden); +} + DynamicProperty::PropData DynamicProperty::getDynamicPropertyData(const Property *prop) const { auto &index = props.get<1>(); diff --git a/src/App/DynamicProperty.h b/src/App/DynamicProperty.h index a292f74c8e..e02a2e9659 100644 --- a/src/App/DynamicProperty.h +++ b/src/App/DynamicProperty.h @@ -33,6 +33,15 @@ #include #include #include +#include + + +XERCES_CPP_NAMESPACE_BEGIN + class DOMNode; + class DOMElement; +// class DefaultHandler; +// class SAX2XMLReader; +XERCES_CPP_NAMESPACE_END namespace Base { @@ -145,6 +154,8 @@ public: Property *restore(PropertyContainer &pc, const char *PropName, const char *TypeName, Base::XMLReader &reader); + Property *restore(PropertyContainer &pc, + const char *PropName, const char *TypeName, Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *PropertyDOM); struct PropData { Property* property; diff --git a/src/App/Extension.cpp b/src/App/Extension.cpp index c3dea0f5e7..ce0991f042 100644 --- a/src/App/Extension.cpp +++ b/src/App/Extension.cpp @@ -34,7 +34,6 @@ #include "ExtensionPython.h" #include - /* We do not use a standard property macro for type initiation. The reason is that we have the first * PropertyData in the extension chain, there is no parent property data. */ @@ -79,7 +78,6 @@ void Extension::initExtensionType(Base::Type type) { } void Extension::initExtension(ExtensionContainer* obj) { - if (m_extensionType.isBad()) throw Base::RuntimeError("Extension: Extension type not set"); @@ -205,6 +203,24 @@ bool Extension::extensionHandleChangedPropertyType(Base::XMLReader &reader, cons return false; }; +bool Extension::extensionHandleChangedPropertyName(Base::DocumentReader &reader, const char * TypeName, const char *PropName) +{ + (void) reader; + (void) TypeName; + (void) PropName; + + return false; +}; + +bool Extension::extensionHandleChangedPropertyType(Base::DocumentReader &reader, const char * TypeName, Property * prop) +{ + (void) reader; + (void) TypeName; + (void) prop; + + return false; +}; + namespace App { EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::ExtensionPython, App::ExtensionPython::Inherited) diff --git a/src/App/Extension.h b/src/App/Extension.h index 84bb442a10..d667d35900 100644 --- a/src/App/Extension.h +++ b/src/App/Extension.h @@ -290,6 +290,10 @@ protected: virtual bool extensionHandleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName); /// returns true if the property type change was handled by the extension. virtual bool extensionHandleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop); + /// returns true if the property name change was handled by the extension. + virtual bool extensionHandleChangedPropertyName(Base::DocumentReader &reader, const char * TypeName, const char *PropName); + /// returns true if the property type change was handled by the extension. + virtual bool extensionHandleChangedPropertyType(Base::DocumentReader &reader, const char * TypeName, Property * prop); friend class App::ExtensionContainer; diff --git a/src/App/ExtensionContainer.cpp b/src/App/ExtensionContainer.cpp index 372967dbae..fdcd5a14b8 100644 --- a/src/App/ExtensionContainer.cpp +++ b/src/App/ExtensionContainer.cpp @@ -32,6 +32,11 @@ #include "ExtensionContainer.h" #include +#ifndef _PreComp_ +# include +//# include +#endif + using namespace App; @@ -49,7 +54,6 @@ ExtensionContainer::~ExtensionContainer() { } void ExtensionContainer::registerExtension(Base::Type extension, Extension* ext) { - if(ext->getExtendedContainer() != this) throw Base::ValueError("ExtensionContainer::registerExtension: Extension has not this as base object"); @@ -308,16 +312,15 @@ void ExtensionContainer::Restore(Base::XMLReader& reader) { App::PropertyContainer::Restore(reader); } -void ExtensionContainer::Restore(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *viewProviderEl) { +void ExtensionContainer::Restore(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *containerEl) { //restore dynamic extensions. //Note 1: The extension element must be read first, before all other object elements. That is // needed as the element works together with an object element attribute, which would be // cleared if another attribute is read first //Note 2: This must happen before the py object of this container is used, as only in the // pyobject constructor the extension methods are added to the container. - restoreExtensions(reader,viewProviderEl); - //TODO NOW: - //App::PropertyContainer::Restore(reader); + restoreExtensions(reader,containerEl); + App::PropertyContainer::Restore(reader,containerEl); } void ExtensionContainer::saveExtensions(Base::Writer& writer) const { @@ -365,70 +368,80 @@ void ExtensionContainer::saveExtensions(Base::Writer& writer) const { writer.decInd(); } -void ExtensionContainer::restoreExtensions(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *viewProviderEl) { +void ExtensionContainer::restoreExtensions(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *containerEl) { //Dynamic extensions are optional (also because they are introduced late into the document format) //and hence it is possible that the element does not exist. As we cannot check for the existence of //an element a object attribute is set if extensions are available. Here we check that //attribute, and only if it exists the extensions element will be available. - const char* expanded_cstr = reader.GetAttribute(viewProviderEl,"expanded"); + const char* expanded_cstr = reader.GetAttribute(containerEl,"expanded"); if(!expanded_cstr) return; - auto ExtensionsDOM = reader.FindElement(viewProviderEl,"Extensions"); + auto ExtensionsDOM = reader.FindElement(containerEl,"Extensions"); if(ExtensionsDOM){ const char* cnt_cstr = reader.GetAttribute(ExtensionsDOM,"Count"); if(cnt_cstr){ long Cnt = reader.ContentToInt( cnt_cstr ); - for (int i=0 ;i(extension.createInstance()); - //check if this really is a python extension! - if (!ext->isPythonExtension()) { - delete ext; - std::stringstream str; - str << "Extension is not a python addable version: '" << type_cstr << "'" << std::ends; - throw Base::TypeError(str.str()); - } - ext->initExtension(this); - if( strcmp(ext->getExtensionTypeId().getName(), type_cstr) == 0 ) - ext->extensionRestore(reader); - } - } - catch (const Base::XMLParseException&) { - throw; // re-throw - } - catch (const Base::Exception &e) { - Base::Console().Error("%s\n", e.what()); - } - catch (const std::exception &e) { - Base::Console().Error("%s\n", e.what()); - } - catch (const char* e) { - Base::Console().Error("%s\n", e); - } - #ifndef FC_DEBUG - catch (...) { - Base::Console().Error("ExtensionContainer::Restore: Unknown C++ exception thrown\n"); - } - #endif + auto prev_ExtensionDOM = reader.FindElement(ExtensionsDOM,"Extension"); + readExtension(reader,prev_ExtensionDOM); + for (int i=1 ;i(extension.createInstance()); + //check if this really is a python extension! + if (!ext->isPythonExtension()) { + delete ext; + std::stringstream str; + str << "Extension is not a python addable version: '" << type_cstr << "'" << std::ends; + throw Base::TypeError(str.str()); + } + ext->initExtension(this); + if( strcmp(ext->getExtensionTypeId().getName(), type_cstr) == 0 ) + ext->extensionRestore(reader); + } + } + catch (const Base::XMLParseException&) { + throw; // re-throw + } + catch (const Base::Exception &e) { + Base::Console().Error("%s\n", e.what()); + } + catch (const std::exception &e) { + Base::Console().Error("%s\n", e.what()); + } + catch (const char* e) { + Base::Console().Error("%s\n", e); + } +#ifndef FC_DEBUG + catch (...) { + Base::Console().Error("ExtensionContainer::Restore: Unknown C++ exception thrown\n"); + } +#endif + +} + void ExtensionContainer::restoreExtensions(Base::XMLReader& reader) { //Dynamic extensions are optional (also because they are introduced late into the document format) @@ -508,6 +521,20 @@ void ExtensionContainer::handleChangedPropertyName(Base::XMLReader &reader, cons PropertyContainer::handleChangedPropertyName(reader, TypeName, PropName); } +void ExtensionContainer::handleChangedPropertyName(Base::DocumentReader &reader, const char * TypeName, const char *PropName) +{ + //inform all extensions about changed property name. This includes all properties from the + //extended object (this) as well as all extension properties + for(const auto& entry : _extensions) { + bool handled = entry.second->extensionHandleChangedPropertyName(reader, TypeName, PropName); + + if(handled) + return; // one property change needs only be handled once + } + + PropertyContainer::handleChangedPropertyName(reader, TypeName, PropName); +} + void ExtensionContainer::handleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop) { //inform all extensions about changed property type. This includes all properties from the @@ -521,3 +548,17 @@ void ExtensionContainer::handleChangedPropertyType(Base::XMLReader &reader, cons PropertyContainer::handleChangedPropertyType(reader, TypeName, prop); } + +void ExtensionContainer::handleChangedPropertyType(Base::DocumentReader &reader, const char * TypeName, Property * prop) +{ + //inform all extensions about changed property type. This includes all properties from the + //extended object (this) as well as all extension properties + for(const auto& entry : _extensions) { + bool handled = entry.second->extensionHandleChangedPropertyType(reader, TypeName, prop); + + if(handled) + return; // one property change needs only be handled once + } + + PropertyContainer::handleChangedPropertyType(reader, TypeName, prop); +} diff --git a/src/App/ExtensionContainer.h b/src/App/ExtensionContainer.h index 9c90b95fbf..d71908ba7a 100644 --- a/src/App/ExtensionContainer.h +++ b/src/App/ExtensionContainer.h @@ -185,13 +185,13 @@ public: void Save(Base::Writer& writer) const override; void Restore(Base::XMLReader& reader) override; - void Restore(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *viewProviderEl); + void Restore(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *containerEl); //those methods save/restore the dynamic extensions without handling properties, which is something //done by the default Save/Restore methods. void saveExtensions(Base::Writer& writer) const; void restoreExtensions(Base::XMLReader& reader); - void restoreExtensions(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *viewProviderEl); + void restoreExtensions(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *containerEl); /** Extends the rules for handling property name changed, so that extensions are given an opportunity to handle it. * If an extension handles a change, neither the rest of the extensions, nor the container itself get to handle it. @@ -201,6 +201,7 @@ public: * If no extension handles the request, then the containers handleChangedPropertyName() is called. */ virtual void handleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName) override; + virtual void handleChangedPropertyName(Base::DocumentReader &reader, const char * TypeName, const char *PropName) override; /** Extends the rules for handling property type changed, so that extensions are given an opportunity to handle it. * If an extension handles a change, neither the rest of the extensions, nor the container itself get to handle it. * @@ -209,6 +210,9 @@ public: * If no extension handles the request, then the containers handleChangedPropertyType() is called. */ virtual void handleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop) override; + virtual void handleChangedPropertyType(Base::DocumentReader &reader, const char * TypeName, Property * prop) override; + + void readExtension(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ExtensionDOM); private: //stored extensions diff --git a/src/App/PropertyContainer.cpp b/src/App/PropertyContainer.cpp index 837162fc4b..5d5ee8dd2e 100644 --- a/src/App/PropertyContainer.cpp +++ b/src/App/PropertyContainer.cpp @@ -32,6 +32,10 @@ #include "PropertyContainer.h" #include +#ifndef _PreComp_ +# include +#endif + FC_LOG_LEVEL_INIT("App",true,true) @@ -75,8 +79,9 @@ App::Property* PropertyContainer::addDynamicProperty( Property *PropertyContainer::getPropertyByName(const char* name) const { auto prop = dynamicProps.getDynamicPropertyByName(name); - if(prop) + if(prop){ return prop; + } return getPropertyData().getPropertyByName(this,name); } @@ -199,6 +204,13 @@ void PropertyContainer::handleChangedPropertyName(Base::XMLReader &reader, const (void)PropName; } +void PropertyContainer::handleChangedPropertyName(Base::DocumentReader &reader, const char * TypeName, const char *PropName) +{ + (void)reader; + (void)TypeName; + (void)PropName; +} + /** * @brief PropertyContainer::handleChangedPropertyType is called during restore to possibly * fix reading of older versions of the property container. This method is typically called @@ -218,6 +230,13 @@ void PropertyContainer::handleChangedPropertyType(XMLReader &reader, const char (void)prop; } +void PropertyContainer::handleChangedPropertyType(DocumentReader &reader, const char *TypeName, Property *prop) +{ + (void)reader; + (void)TypeName; + (void)prop; +} + PropertyData PropertyContainer::propertyData; void PropertyContainer::Save (Base::Writer &writer) const @@ -321,6 +340,7 @@ void PropertyContainer::Restore(Base::XMLReader &reader) if(reader.hasAttribute("TransientCount")) transientCount = reader.getAttributeAsUnsigned("TransientCount"); + for (int i=0;igetContainer() != this) + if(!prop || prop->getContainer() != this){ prop = dynamicProps.restore(*this,PropName.c_str(),TypeName.c_str(),reader); + } decltype(Property::StatusBits) status; if(reader.hasAttribute("status")) { @@ -403,101 +424,115 @@ void PropertyContainer::Restore(Base::XMLReader &reader) reader.readEndElement("Properties"); } -void PropertyContainer::Restore(Base::DocumentReader &reader) +void PropertyContainer::Restore(Base::DocumentReader &reader, XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *containerEl) { - //TODO NOW - Base::Console().Error("PropertyContainer::Restore: DocumentReader\n"); reader.clearPartialRestoreProperty(); - /* - reader.clearPartialRestoreProperty(); - reader.readElement("Properties"); - int Cnt = reader.getAttributeAsInteger("Count"); + + auto PropertiesDOM = reader.FindElement(containerEl,"Properties"); + const char* count_cstr = reader.GetAttribute(PropertiesDOM,"Count"); + if(count_cstr){ + long Cnt = reader.ContentToInt( count_cstr ); + const char* TransientCount_cstr = reader.GetAttribute(PropertiesDOM,"TransientCount"); + int transientCount = 0; + if(TransientCount_cstr) + transientCount = reader.ContentToUnsigned( TransientCount_cstr ); + + for (int i=0;igetName() << "'"); + if(prop && status_cstr){ + int u_status = reader.ContentToUnsigned( status_cstr ); + prop->setStatusValue(u_status); + } + } + if(Cnt){ + auto prev_PropertyDOM = reader.FindElement(PropertiesDOM,"Property"); + readProperty(reader,prev_PropertyDOM); + for (int i=1 ;igetName() << "'"); - if(prop && reader.hasAttribute("status")) - prop->setStatusValue(reader.getAttributeAsUnsigned("status")); - } - - for (int i=0 ;igetContainer() != this) - prop = dynamicProps.restore(*this,PropName.c_str(),TypeName.c_str(),reader); - - decltype(Property::StatusBits) status; - if(reader.hasAttribute("status")) { - status = decltype(status)(reader.getAttributeAsUnsigned("status")); - if(prop) - prop->setStatusValue(status.to_ulong()); - } - // name and type match - if (prop && strcmp(prop->getTypeId().getName(), TypeName.c_str()) == 0) { - if (!prop->testStatus(Property::Transient) - && !status.test(Property::Transient) - && !status.test(Property::PropTransient) - && !prop->testStatus(Property::PropTransient)) - { - FC_TRACE("restore property '" << prop->getName() << "'"); - prop->Restore(reader); - }else - FC_TRACE("skip transient '" << prop->getName() << "'"); - } - // name matches but not the type - else if (prop) { - handleChangedPropertyType(reader, TypeName.c_str(), prop); - } - // name doesn't match, the sub-class then has to know - // if the property has been renamed or removed - else { - handleChangedPropertyName(reader, TypeName.c_str(), PropName.c_str()); - } - - if (reader.testStatus(Base::XMLReader::ReaderStatus::PartialRestoreInProperty)) { - Base::Console().Error("Property %s of type %s was subject to a partial restore.\n",PropName.c_str(),TypeName.c_str()); - reader.clearPartialRestoreProperty(); - } - } - catch (const Base::XMLParseException&) { - throw; // re-throw - } - catch (const Base::RestoreError &) { - reader.setPartialRestore(true); - reader.clearPartialRestoreProperty(); - Base::Console().Error("Property %s of type %s was subject to a partial restore.\n",PropName.c_str(),TypeName.c_str()); - } - catch (const Base::Exception &e) { - Base::Console().Error("%s\n", e.what()); - } - catch (const std::exception &e) { - Base::Console().Error("%s\n", e.what()); - } - catch (const char* e) { - Base::Console().Error("%s\n", e); - } +// NOTE: We must also check the type of the current property because a +// subclass of PropertyContainer might change the type of a property but +// not its name. In this case we would force to read-in a wrong property +// type and the behaviour would be undefined. +void PropertyContainer::readProperty(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *PropertyDOM){ + const char* name_cstr = reader.GetAttribute(PropertyDOM,"name"); + const char* type_cstr = reader.GetAttribute(PropertyDOM,"type"); + try { + + auto prop = getPropertyByName(name_cstr); + if(!prop || prop->getContainer() != this){ + prop = dynamicProps.restore(*this,name_cstr,type_cstr,reader,PropertyDOM); + } + + decltype(Property::StatusBits) status; + const char* status_cstr = reader.GetAttribute(PropertyDOM,"status"); + if(status_cstr){ + int u_status = reader.ContentToUnsigned( status_cstr ); + status = decltype(status)(u_status); + if(prop) + prop->setStatusValue(status.to_ulong()); + } + // name and type match + if (prop && strcmp(prop->getTypeId().getName(), type_cstr) == 0) { + if (!prop->testStatus(Property::Transient) + && !status.test(Property::Transient) + && !status.test(Property::PropTransient) + && !prop->testStatus(Property::PropTransient)) + { + FC_TRACE("restore property '" << prop->getName() << "'"); + prop->Restore(reader,PropertyDOM); + }else + FC_TRACE("skip transient '" << prop->getName() << "'"); + } + // name matches but not the type + else if (prop) { + handleChangedPropertyType(reader, type_cstr, prop); + } + // name doesn't match, the sub-class then has to know + // if the property has been renamed or removed + else { + handleChangedPropertyName(reader, type_cstr, name_cstr); + } + + if (reader.testStatus(Base::DocumentReader::ReaderStatus::PartialRestoreInProperty)) { + Base::Console().Error("Property %s of type %s was subject to a partial restore.\n",name_cstr,type_cstr); + reader.clearPartialRestoreProperty(); + } + } + catch (const Base::XMLParseException&) { + throw; // re-throw + } + catch (const Base::RestoreError &) { + reader.setPartialRestore(true); + reader.clearPartialRestoreProperty(); + Base::Console().Error("Property %s of type %s was subject to a partial restore.\n",name_cstr,type_cstr); + } + catch (const Base::Exception &e) { + Base::Console().Error("%s\n", e.what()); + } + catch (const std::exception &e) { + Base::Console().Error("%s\n", e.what()); + } + catch (const char* e) { + Base::Console().Error("%s\n", e); + } #ifndef FC_DEBUG - catch (...) { - Base::Console().Error("PropertyContainer::Restore: Unknown C++ exception thrown\n"); - } + catch (...) { + Base::Console().Error("PropertyContainer::Restore: Unknown C++ exception thrown\n"); + } #endif - reader.readEndElement("Property"); - } - reader.readEndElement("Properties"); - */ } void PropertyContainer::onPropertyStatusChanged(const Property &prop, unsigned long oldStatus) diff --git a/src/App/PropertyContainer.h b/src/App/PropertyContainer.h index 4a165d51ee..d49b8a8e76 100644 --- a/src/App/PropertyContainer.h +++ b/src/App/PropertyContainer.h @@ -30,6 +30,16 @@ #include "DynamicProperty.h" +#include + +XERCES_CPP_NAMESPACE_BEGIN + class DOMNode; + class DOMElement; +// class DefaultHandler; +// class SAX2XMLReader; +XERCES_CPP_NAMESPACE_END + + namespace Base { class Writer; } @@ -220,7 +230,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; - void Restore(Base::DocumentReader &reader) override; + void Restore(Base::DocumentReader &reader, XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *containerEl) override; virtual void editProperty(const char * /*propName*/) {} @@ -248,11 +258,14 @@ protected: virtual void handleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName); virtual void handleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop); + virtual void handleChangedPropertyName(Base::DocumentReader &reader, const char * TypeName, const char *PropName); + virtual void handleChangedPropertyType(Base::DocumentReader &reader, const char * TypeName, Property * prop); private: // forbidden PropertyContainer(const PropertyContainer&); PropertyContainer& operator = (const PropertyContainer&); + void readProperty(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *PropertyDOM); protected: DynamicProperty dynamicProps; diff --git a/src/App/PropertyStandard.cpp b/src/App/PropertyStandard.cpp index 96b69440b0..030d2b3463 100644 --- a/src/App/PropertyStandard.cpp +++ b/src/App/PropertyStandard.cpp @@ -23,6 +23,10 @@ #include "PreCompiled.h" +#ifndef _PreComp_ +# include +#endif + #include #include @@ -30,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -117,6 +122,20 @@ void PropertyInteger::Restore(Base::XMLReader &reader) setValue(reader.getAttributeAsInteger("value")); } +void PropertyInteger::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + // read my Element + auto IntegerDOM = reader.FindElement(ContainerDOM,"Integer"); + if(IntegerDOM){ + // get the value of my Attribute + const char* value_cstr = reader.GetAttribute(IntegerDOM,"value"); + if(value_cstr){ + long value = reader.ContentToInt( value_cstr ); + setValue(value); + } + } +} + Property *PropertyInteger::Copy() const { PropertyInteger *p= new PropertyInteger(); @@ -242,6 +261,18 @@ void PropertyPath::Restore(Base::XMLReader &reader) setValue(reader.getAttribute("value")); } +void PropertyPath::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto PathDOM = reader.FindElement(ContainerDOM,"Path"); + if(PathDOM){ + // get the value of my Attribute + const char* value_cstr = reader.GetAttribute(PathDOM,"value"); + if(value_cstr){ + setValue(value_cstr); + } + } +} + Property *PropertyPath::Copy() const { PropertyPath *p= new PropertyPath(); @@ -432,6 +463,54 @@ void PropertyEnumeration::Restore(Base::XMLReader &reader) hasSetValue(); } +void PropertyEnumeration::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto IntegerDOM = reader.FindElement(ContainerDOM,"Integer"); + if(IntegerDOM){ + // get the value of my Attribute + const char* value_cstr = reader.GetAttribute(IntegerDOM,"value"); + if(value_cstr){ + long val = reader.ContentToInt( value_cstr ); + aboutToSetValue(); + + const char* CustomEnum_cstr = reader.GetAttribute(IntegerDOM,"CustomEnum"); + if(CustomEnum_cstr){ + auto CustomEnumListDOM = reader.FindElement(IntegerDOM,"CustomEnumList"); + if(CustomEnumListDOM){ + const char* count_cstr = reader.GetAttribute(IntegerDOM,"count"); + if(count_cstr){ + long count = reader.ContentToInt( count_cstr ); + std::vector values(count); + + if(count >= 1){ + auto prev_EnumDOM = reader.FindElement(CustomEnumListDOM,"Enum"); + const char* enum_value_cstr = reader.GetAttribute(prev_EnumDOM,"value"); + values[0] = enum_value_cstr; + for(int i = 1; i < count; i++) { + auto EnumDOM_i = reader.FindNextElement(prev_EnumDOM,"Enum"); + const char* _enum_value_cstr = reader.GetAttribute(EnumDOM_i,"value"); + values[i] = _enum_value_cstr; + + prev_EnumDOM = EnumDOM_i; + } + } + _enum.setEnums(values); + } + } + } + if (val < 0) { + // If the enum is empty at this stage do not print a warning + if (_enum.hasEnums()) + Base::Console().Warning("Enumeration index %d is out of range, ignore it\n", val); + val = getValue(); + } + + _enum.setValue(val); + hasSetValue(); + } + } +} + PyObject * PropertyEnumeration::getPyObject() { if (!_enum.isValid()) { @@ -782,6 +861,35 @@ void PropertyIntegerList::Restore(Base::XMLReader &reader) setValues(values); } +void PropertyIntegerList::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto IntegerListDOM = reader.FindElement(ContainerDOM,"IntegerList"); + if(IntegerListDOM){ + // get the value of my Attribute + const char* count_cstr = reader.GetAttribute(IntegerListDOM,"count"); + long count = reader.ContentToInt( count_cstr ); + std::vector values(count); + if(count >= 1){ + auto prev_I_DOM = reader.FindElement(IntegerListDOM,"I"); + const char* v_cstr = reader.GetAttribute(prev_I_DOM,"v"); + long v = reader.ContentToInt( v_cstr ); + values[0] = v; + + for(int i = 1; i < count; i++) { + auto I_DOM_i = reader.FindNextElement(prev_I_DOM,"I"); + const char* _v_cstr = reader.GetAttribute(I_DOM_i,"v"); + long v = reader.ContentToInt( _v_cstr ); + values[i] = v; + + prev_I_DOM = I_DOM_i; + } + } + //assignment + setValues(values); + } +} + + Property *PropertyIntegerList::Copy() const { PropertyIntegerList *p= new PropertyIntegerList(); @@ -902,6 +1010,35 @@ void PropertyIntegerSet::Restore(Base::XMLReader &reader) setValues(values); } +void PropertyIntegerSet::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto IntegerSetDOM = reader.FindElement(ContainerDOM,"IntegerSet"); + if(IntegerSetDOM){ + // get the value of my Attribute + const char* count_cstr = reader.GetAttribute(IntegerSetDOM,"count"); + long count = reader.ContentToInt( count_cstr ); + std::set values; + + if(count >= 1){ + auto prev_I_DOM = reader.FindElement(IntegerSetDOM,"I"); + const char* v_cstr = reader.GetAttribute(prev_I_DOM,"v"); + long v = reader.ContentToInt( v_cstr ); + values.insert( v ); + + for(int i = 1; i < count; i++) { + auto I_DOM_i = reader.FindNextElement(prev_I_DOM,"I"); + const char* _v_cstr = reader.GetAttribute(I_DOM_i,"v"); + long v = reader.ContentToInt( _v_cstr ); + values.insert( v ); + + prev_I_DOM = I_DOM_i; + } + } + //assignment + setValues(values); + } +} + Property *PropertyIntegerSet::Copy() const { PropertyIntegerSet *p= new PropertyIntegerSet(); @@ -993,6 +1130,21 @@ void PropertyFloat::Restore(Base::XMLReader &reader) setValue(reader.getAttributeAsFloat("value")); } +void PropertyFloat::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto FloatDOM = reader.FindElement(ContainerDOM,"Float"); + if(FloatDOM){ + // get the value of my Attribute + const char* value_cstr = reader.GetAttribute(FloatDOM,"value"); + if(value_cstr){ + double value = reader.ContentToFloat( value_cstr ); + setValue(value); + } + } +} + + + Property *PropertyFloat::Copy() const { PropertyFloat *p= new PropertyFloat(); @@ -1242,6 +1394,24 @@ void PropertyFloatList::Restore(Base::XMLReader &reader) } } +void PropertyFloatList::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + //TODO for this its needed to implement addFile() into Reader.cpp, and ReadFiles() since its not possible to have an XMLReader object at this point, because it gives error to use both methods(XMLReader progressive reading and DocumentReader reading) probably because there is something wrong with the zipios implementation, it looks like its locking file or in some way makes the file structure invalid to be readed by xerces by both methods. + //worked around reimplementing ReadFiles in DocumentReader.cpp: + auto FloatListDOM = reader.FindElement(ContainerDOM,"FloatList"); + if(FloatListDOM){ + // get the value of my Attribute + const char* file_cstr = reader.GetAttribute(FloatListDOM,"file"); + if(file_cstr){ + string file ( file_cstr ); + if (!file.empty()) { + // initiate a file read + reader.addFile(file.c_str(),this); + } + } + } +} + void PropertyFloatList::SaveDocFile (Base::Writer &writer) const { Base::OutputStream str(writer.Stream()); @@ -1502,6 +1672,31 @@ void PropertyString::Restore(Base::XMLReader &reader) setValue(reader.getAttribute("value")); } +void PropertyString::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto StringDOM = reader.FindElement(ContainerDOM,"String"); + const char* value_cstr = reader.GetAttribute(StringDOM,"value"); + + auto obj = dynamic_cast(getContainer()); + if(obj && &obj->Label==this) { + const char* restore_cstr = reader.GetAttribute(StringDOM,"restore"); + + if(restore_cstr) { + int restore = reader.ContentToInt( restore_cstr ); + if(restore == 1) { + aboutToSetValue(); + _cValue = value_cstr; + hasSetValue(); + return; + } + return; + } + } + setValue(value_cstr); + + +} + Property *PropertyString::Copy() const { PropertyString *p= new PropertyString(); @@ -1634,6 +1829,18 @@ void PropertyUUID::Restore(Base::XMLReader &reader) setValue(reader.getAttribute("value")); } +void PropertyUUID::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto UuidDOM = reader.FindElement(ContainerDOM,"Uuid"); + if(UuidDOM){ + // get the value of my Attribute + const char* value_cstr = reader.GetAttribute(UuidDOM,"value"); + if(value_cstr){ + setValue(value_cstr); + } + } +} + Property *PropertyUUID::Copy() const { PropertyUUID *p= new PropertyUUID(); @@ -1755,6 +1962,32 @@ void PropertyStringList::Restore(Base::XMLReader &reader) setValues(values); } +void PropertyStringList::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto StringListDOM = reader.FindElement(ContainerDOM,"StringList"); + if(StringListDOM){ + // get the value of my Attribute + const char* count_cstr = reader.GetAttribute(StringListDOM,"count"); + long count = reader.ContentToInt( count_cstr ); + std::vector values(count); + if(count >= 1){ + auto prev_StringDOM = reader.FindElement(StringListDOM,"String"); + const char* value_cstr = reader.GetAttribute(prev_StringDOM,"value"); + values[0] = value_cstr; + for(int i = 1; i < count; i++) { + auto StringDOM_i = reader.FindNextElement(prev_StringDOM,"String"); + const char* _value_cstr = reader.GetAttribute(StringDOM_i,"value"); + values[i] = _value_cstr; + + prev_StringDOM = StringDOM_i; + } + + } + // assignment + setValues(values); + } +} + Property *PropertyStringList::Copy() const { PropertyStringList *p= new PropertyStringList(); @@ -1919,6 +2152,32 @@ void PropertyMap::Restore(Base::XMLReader &reader) setValues(values); } +void PropertyMap::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto MapDOM = reader.FindElement(ContainerDOM,"Map"); + if(MapDOM){ + // get the value of my Attribute + const char* count_cstr = reader.GetAttribute(MapDOM,"count"); + int count = reader.ContentToInt( count_cstr ); + std::map values; + auto prev_ItemDOM = reader.FindElement(MapDOM,"Item"); + const char* key_cstr = reader.GetAttribute(prev_ItemDOM,"key"); + const char* value_cstr = reader.GetAttribute(prev_ItemDOM,"value"); + values[key_cstr] = value_cstr; + + for(int i = 1; i < count; i++) { + auto ItemDOM_i = reader.FindNextElement(prev_ItemDOM,"Item"); + const char* key_cstr = reader.GetAttribute(ItemDOM_i,"key"); + const char* value_cstr = reader.GetAttribute(ItemDOM_i,"value"); + values[key_cstr] = value_cstr; + + prev_ItemDOM = ItemDOM_i; + } + // assignment + setValues(values); + } +} + Property *PropertyMap::Copy() const { PropertyMap *p= new PropertyMap(); @@ -2004,6 +2263,15 @@ void PropertyBool::Restore(Base::XMLReader &reader) (b == "true") ? setValue(true) : setValue(false); } +void PropertyBool::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto BoolDOM = reader.FindElement(ContainerDOM,"Bool"); + if(BoolDOM){ + // get the value of my Attribute + string b = reader.GetAttribute(BoolDOM,"value"); + (b == "true") ? setValue(true) : setValue(false); + } +} Property *PropertyBool::Copy() const { @@ -2122,6 +2390,18 @@ void PropertyBoolList::Restore(Base::XMLReader &reader) setValues(bitset); } +void PropertyBoolList::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + // read my Element + auto BoolListDOM = reader.FindElement(ContainerDOM,"BoolList"); + if(BoolListDOM){ + // get the value of my Attribute + string str = reader.GetAttribute(BoolListDOM,"value"); + boost::dynamic_bitset<> bitset(str); + setValues(bitset); + } +} + Property *PropertyBoolList::Copy() const { PropertyBoolList *p= new PropertyBoolList(); @@ -2275,6 +2555,17 @@ void PropertyColor::Restore(Base::XMLReader &reader) setValue(rgba); } +void PropertyColor::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + // read my Element + auto PropertyColorDOM = reader.FindElement(ContainerDOM,"PropertyColor"); + if(PropertyColorDOM){ + const char* val_cstr = reader.GetAttribute(PropertyColorDOM,"value"); + unsigned long rgba = reader.ContentToUnsigned(val_cstr); + setValue(rgba); + } +} + Property *PropertyColor::Copy() const { PropertyColor *p= new PropertyColor(); @@ -2354,6 +2645,22 @@ void PropertyColorList::Restore(Base::XMLReader &reader) } } +void PropertyColorList::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto ColorListDOM = reader.FindElement(ContainerDOM,"ColorList"); + if(ColorListDOM){ + // get the value of my Attribute + const char* file_cstr = reader.GetAttribute(ColorListDOM,"file"); + if(file_cstr){ + std::string file (file_cstr); + if (!file.empty()) { + // initiate a file read + reader.addFile(file.c_str(),this); + } + } + } +} + void PropertyColorList::SaveDocFile (Base::Writer &writer) const { Base::OutputStream str(writer.Stream()); @@ -2504,6 +2811,32 @@ void PropertyMaterial::Restore(Base::XMLReader &reader) hasSetValue(); } +void PropertyMaterial::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + // read my Element + auto PropertyMaterialDOM = reader.FindElement(ContainerDOM,"PropertyMaterial"); + if(PropertyMaterialDOM){ + // get the value of my Attribute + aboutToSetValue(); + + const char* ambientColor_cstr = reader.GetAttribute(PropertyMaterialDOM,"ambientColor"); + const char* diffuseColor_cstr = reader.GetAttribute(PropertyMaterialDOM,"diffuseColor"); + const char* specularColor_cstr = reader.GetAttribute(PropertyMaterialDOM,"specularColor"); + const char* emissiveColor_cstr = reader.GetAttribute(PropertyMaterialDOM,"emissiveColor"); + const char* shininess_cstr = reader.GetAttribute(PropertyMaterialDOM,"shininess"); + const char* transparency_cstr = reader.GetAttribute(PropertyMaterialDOM,"transparency"); + + _cMat.ambientColor.setPackedValue(reader.ContentToUnsigned(ambientColor_cstr)); + _cMat.diffuseColor.setPackedValue(reader.ContentToUnsigned(diffuseColor_cstr)); + _cMat.specularColor.setPackedValue(reader.ContentToUnsigned(specularColor_cstr)); + _cMat.emissiveColor.setPackedValue(reader.ContentToUnsigned(emissiveColor_cstr)); + _cMat.shininess = (float)reader.ContentToFloat(shininess_cstr); + _cMat.transparency = (float)reader.ContentToFloat(transparency_cstr); + hasSetValue(); + } +} + + const char* PropertyMaterial::getEditorName() const { if(testStatus(MaterialEdit)) @@ -2583,6 +2916,22 @@ void PropertyMaterialList::Restore(Base::XMLReader &reader) } } +void PropertyMaterialList::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto MaterialListDOM = reader.FindElement(ContainerDOM,"MaterialList"); + if(MaterialListDOM){ + // get the value of my Attribute + const char* file_cstr = reader.GetAttribute(MaterialListDOM,"file"); + if(file_cstr){ + std::string file (file_cstr); + if (!file.empty()) { + // initiate a file read + reader.addFile(file.c_str(),this); + } + } + } +} + void PropertyMaterialList::SaveDocFile(Base::Writer &writer) const { Base::OutputStream str(writer.Stream()); @@ -2679,6 +3028,14 @@ void PropertyPersistentObject::Restore(Base::XMLReader &reader){ reader.readEndElement(ELEMENT_PERSISTENT_OBJ); } +void PropertyPersistentObject::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + inherited::Restore(reader,ContainerDOM); + auto element_persistent_obj_DOM = reader.FindElement(ELEMENT_PERSISTENT_OBJ); + if(_pObject) + _pObject->Restore(reader,element_persistent_obj_DOM); +} + Property *PropertyPersistentObject::Copy() const{ auto *p= new PropertyPersistentObject(); p->_cValue = _cValue; diff --git a/src/App/PropertyStandard.h b/src/App/PropertyStandard.h index cd5d8755f3..e1d1cd0d43 100644 --- a/src/App/PropertyStandard.h +++ b/src/App/PropertyStandard.h @@ -36,6 +36,12 @@ #include "Enumeration.h" #include "Material.h" +#include + +XERCES_CPP_NAMESPACE_BEGIN + class DOMElement; +XERCES_CPP_NAMESPACE_END + namespace Base { class Writer; @@ -70,6 +76,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -121,6 +128,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -220,6 +228,7 @@ public: void Save(Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property * Copy() const override; void Paste(const Property &from) override; @@ -358,6 +367,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -403,6 +413,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -462,6 +473,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -515,6 +527,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -658,6 +671,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; void SaveDocFile (Base::Writer &writer) const override; void RestoreDocFile(Base::Reader &reader) override; @@ -705,6 +719,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -758,6 +773,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -824,6 +840,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -865,6 +882,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -902,6 +920,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -949,6 +968,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -988,6 +1008,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; void SaveDocFile (Base::Writer &writer) const override; void RestoreDocFile(Base::Reader &reader) override; @@ -1040,6 +1061,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; const char* getEditorName() const override; @@ -1083,6 +1105,7 @@ public: void Save(Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; void SaveDocFile(Base::Writer &writer) const override; void RestoreDocFile(Base::Reader &reader) override; @@ -1112,6 +1135,7 @@ public: void Save (Base::Writer &writer) const override; void Restore(Base::XMLReader &reader) override; + void Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) override; Property *Copy() const override; void Paste(const Property &from) override; diff --git a/src/Base/DocumentReader.cpp b/src/Base/DocumentReader.cpp index 01b97285f0..4160b2e6a0 100644 --- a/src/Base/DocumentReader.cpp +++ b/src/Base/DocumentReader.cpp @@ -19,41 +19,24 @@ * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ -//#include "PreCompiled.h" - -//#include - #include "DocumentReader.h" - -//#include "Reader.h" -//#include "Base64.h" -//#include "Console.h" #include "InputSource.h" -//#include "Persistence.h" -//#include "Sequencer.h" -//#include "Stream.h" #include "XMLTools.h" -//#ifdef _MSC_VER -//#include -//#endif -//#include #include #include +#include "Persistence.h" +#include "Sequencer.h" + + +#ifdef _MSC_VER +#include +#endif +#include + #ifndef _PreComp_ -//# include -//# include # include -//# include -//# include -//# include -//# include # include -//# include -//# include -//# include -//# include -//# include #endif XERCES_CPP_NAMESPACE_USE @@ -67,30 +50,12 @@ using namespace Base; static XercesDOMParser::ValSchemes gValScheme = XercesDOMParser::Val_Auto; DocumentReader::DocumentReader() { - gDoNamespaces = false; gDoSchema = false; gSchemaFullChecking = false; gDoCreate = true; - - /* - gOutputEncoding = nullptr; - gMyEOLSequence = nullptr; - - gSplitCdataSections = true; - gDiscardDefaultContent = true; - gUseFilter = true; - gFormatPrettyPrint = true; - */ - } -//DocumentReader::~DocumentReader() -//{ - //delete parser; -//} -//int DocumentReader::LoadDocument(const XERCES_CPP_NAMESPACE_QUALIFIER InputSource& inputSource) -//int DocumentReader::LoadDocument(std::istream& Stream,std::string filename) int DocumentReader::LoadDocument(Base::Reader& reader) { FileInfo _File( reader.getFileName() ); @@ -139,7 +104,7 @@ int DocumentReader::LoadDocument(Base::Reader& reader) return 0; } - XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* _pDocument = parser->adoptDocument(); + XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* _pDocument = parser->adoptDocument(); delete parser; delete errReporter; @@ -174,9 +139,7 @@ XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DocumentReader::FindElement(const cha for (DOMNode *clChild = _pGroupNode->getFirstChild(); clChild != nullptr; clChild = clChild->getNextSibling()) { if (clChild->getNodeType() == DOMNode::ELEMENT_NODE) { if (!strcmp(Type,StrX(clChild->getNodeName()).c_str())) { - if (clChild->getAttributes()->getLength() > 0) { - return static_cast(clChild); - } + return static_cast(clChild); } } } @@ -191,9 +154,6 @@ XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DocumentReader::FindElement(XERCES_CP if (clChild->getNodeType() == DOMNode::ELEMENT_NODE) { if (!strcmp(Type,StrX(clChild->getNodeName()).c_str())) { return static_cast(clChild); - //if (clChild->getAttributes()->getLength() > 0) { - //return static_cast(clChild); - //} } } } @@ -216,41 +176,22 @@ XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DocumentReader::FindNextElement(XERCE return nullptr; } -/* -//CONTENT: -const char * DocumentReader::GetContent(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DOMEl) const -{ - if (!DOMEl) - return nullptr; - return StrX(DOMEl->getAttribute(XStr("Value").unicodeForm())).c_str(); -} - -std::string DocumentReader::GetContentASCII(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DOMEl) const -{ - //return std::string(StrXUTF8(pcElem->getNodeValue()).c_str() ); - //maybe its better to use getNodeValue() - if (!DOMEl) - return nullptr; - return std::string( StrXUTF8(DOMEl->getAttribute(XStr("Value").unicodeForm())).c_str() ); -} -*/ - -long DocumentReader::ContentToInt( const char* content ) const +long DocumentReader::ContentToInt( const char* content ) { return atol( content ); } -unsigned long DocumentReader::ContentToUnsigned(const char* content) const +unsigned long DocumentReader::ContentToUnsigned(const char* content) { return strtoul(content,nullptr,10); } -double DocumentReader::ContentToFloat(const char* content) const +double DocumentReader::ContentToFloat(const char* content) { return atof(content); } -bool DocumentReader::ContentToBool(const char* content) const +bool DocumentReader::ContentToBool(const char* content) { if (strcmp(content,"1")) return false; @@ -282,18 +223,16 @@ const char * DocumentReader::GetAttribute(const char* Attr) const return nullptr; } const XMLCh * attr = _pGroupNode->getAttribute( xstr.unicodeForm() ); - //stringLen return strdup( StrX( attr ).c_str() );//strdup is needed since pointer from strx only exists in context where StrX() is created. } - -/* -unsigned int Base::XMLReader::getAttributeCount() const -{ - return static_cast(AttrMap.size()); -} -*/ - //Status +void Base::DocumentReader::setPartialRestore(bool on) +{ + setStatus(PartialRestore, on); + setStatus(PartialRestoreInDocumentObject, on); + setStatus(PartialRestoreInProperty, on); + setStatus(PartialRestoreInObject, on); +} void Base::DocumentReader::clearPartialRestoreProperty() { @@ -311,4 +250,77 @@ void Base::DocumentReader::setStatus(ReaderStatus pos, bool on) StatusBits.set(static_cast(pos), on); } +const char *Base::DocumentReader::addFile(const char* Name, Base::Persistence *Object) +{ + FileEntry temp; + temp.FileName = Name; + temp.Object = Object; + FileList.push_back(temp); + FileNames.push_back( temp.FileName ); + + return Name; +} + +void Base::DocumentReader::readFiles(zipios::ZipInputStream &zipstream) const +{ + // It's possible that not all objects inside the document could be created, e.g. if a module + // is missing that would know these object types. So, there may be data files inside the zip + // file that cannot be read. We simply ignore these files. + // On the other hand, however, it could happen that a file should be read that is not part of + // the zip file. This happens e.g. if a document is written without GUI up but is read with GUI + // up. In this case the associated GUI document asks for its file which is not part of the ZIP + // file, then. + // In either case it's guaranteed that the order of the files is kept. + zipios::ConstEntryPointer entry; + try { + entry = zipstream.getNextEntry(); + } + catch (const std::exception&) { + // There is no further file at all. This can happen if the + // project file was created without GUI + return; + } + std::vector::const_iterator it = FileList.begin(); + Base::SequencerLauncher seq("Importing project files...", FileList.size()); + while (entry->isValid() && it != FileList.end()) { + std::vector::const_iterator jt = it; + // Check if the current entry is registered, otherwise check the next registered files as soon as + // both file names match + while (jt != FileList.end() && entry->getName() != jt->FileName) + ++jt; + // If this condition is true both file names match and we can read-in the data, otherwise + // no file name for the current entry in the zip was registered. + if (jt != FileList.end()) { + try { + Base::Reader reader(zipstream, jt->FileName, FileVersion); + jt->Object->RestoreDocFile(reader); + if (reader.getLocalReader()) + reader.getLocalReader()->readFiles(zipstream); + if (reader.getLocalDocReader()) + reader.getLocalDocReader()->readFiles(zipstream); + + }catch(...) { + // For any exception we just continue with the next file. + // It doesn't matter if the last reader has read more or + // less data than the file size would allow. + // All what we need to do is to notify the user about the + // failure. + Base::Console().Error("Reading failed from embedded file(DocumentReader): %s\n", entry->toString().c_str()); + } + // Go to the next registered file name + it = jt + 1; + } + + seq.next(); + + // In either case we must go to the next entry + try { + entry = zipstream.getNextEntry(); + } + catch (const std::exception&) { + // there is no further entry + break; + } + } +} diff --git a/src/Base/DocumentReader.h b/src/Base/DocumentReader.h index e414046f37..863fa521de 100644 --- a/src/Base/DocumentReader.h +++ b/src/Base/DocumentReader.h @@ -25,18 +25,16 @@ #include #include -//#include -//#include +#include #include #include - -//#include -//#include -//#include #include -//#include "FileInfo.h"//reemplazado por: +//#include "FileInfo.h"//remplaced: #include -//#include + +namespace zipios { +class ZipInputStream; +} XERCES_CPP_NAMESPACE_BEGIN class DOMNode; @@ -49,7 +47,7 @@ namespace Base class Reader; class Persistence; -class BaseExport DocumentReader //: public ParameterManager +class BaseExport DocumentReader { public: enum ReaderStatus { @@ -66,12 +64,12 @@ public: XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *FindElement(const char* Type) const; XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *FindNextElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *Prev, const char* Type) const; - long ContentToASCII(const char* Content) const; + static long ContentToASCII(const char* Content); - long ContentToInt(const char* Content) const; - unsigned long ContentToUnsigned(const char* Content) const; - double ContentToFloat(const char* Content) const; - bool ContentToBool(const char* Content) const; + static long ContentToInt(const char* Content); + static unsigned long ContentToUnsigned(const char* Content); + static double ContentToFloat(const char* Content); + static bool ContentToBool(const char* Content); const char* GetAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* DOMEl, const char* Attr) const; const char* GetAttribute(const char* Attr) const; @@ -80,15 +78,38 @@ public: bool testStatus(ReaderStatus pos) const; /// set the status bits void setStatus(ReaderStatus pos, bool on); + /// sets simultaneously the global and local PartialRestore bits + void setPartialRestore(bool on); void clearPartialRestoreProperty(); + /// add a read request of a persistent object + const char *addFile(const char* Name, Base::Persistence *Object); + + void readFiles(zipios::ZipInputStream &zipstream) const; + + std::shared_ptr getLocalReader() const; + + struct FileEntry { + std::string FileName; + Base::Persistence *Object; + }; + std::vector FileList; + + /// Version of the file format + int FileVersion; + + + protected: XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *_pGroupNode; bool gDoNamespaces ; bool gDoSchema ; bool gSchemaFullChecking ; bool gDoCreate ; + + std::vector FileNames; + std::bitset<32> StatusBits; }; diff --git a/src/Base/Persistence.cpp b/src/Base/Persistence.cpp index 742a06cf35..73e6c2a9f2 100644 --- a/src/Base/Persistence.cpp +++ b/src/Base/Persistence.cpp @@ -34,6 +34,10 @@ /// Here the FreeCAD includes sorted by Base,App,Gui...... #include "Persistence.h" +#ifndef _PreComp_ +# include +#endif + using namespace Base; @@ -63,8 +67,10 @@ void Persistence::Save (Writer &/*writer*/) const void Persistence::Restore(DocumentReader &/*reader*/) { - // you have to implement this method in all descending classes! - assert(0); +} + +void Persistence::Restore(DocumentReader &/*reader*/,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement */*containerEl*/) +{ } void Persistence::Restore(XMLReader &/*reader*/) diff --git a/src/Base/Persistence.h b/src/Base/Persistence.h index 7941f7c748..cf4634c66d 100644 --- a/src/Base/Persistence.h +++ b/src/Base/Persistence.h @@ -26,6 +26,15 @@ #include "BaseClass.h" +#include + +XERCES_CPP_NAMESPACE_BEGIN + class DOMNode; + class DOMElement; +// class DefaultHandler; +// class SAX2XMLReader; +XERCES_CPP_NAMESPACE_END + namespace Base { class Reader; @@ -79,6 +88,8 @@ public: */ virtual void Restore(XMLReader &/*reader*/) = 0; virtual void Restore(DocumentReader &/*reader*/); + virtual void Restore(DocumentReader &/*reader*/,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement */*containerEl*/); + /** This method is used to save large amounts of data to a binary file. * Sometimes it makes no sense to write property data as XML. In case the * amount of data is too big or the data type has a more effective way to @@ -143,6 +154,8 @@ public: * @see Base::Reader,Base::XMLReader */ virtual void RestoreDocFile(Reader &/*reader*/); + + /// Encodes an attribute upon saving. static std::string encodeAttribute(const std::string&); diff --git a/src/Base/Reader.cpp b/src/Base/Reader.cpp index 92e207953b..8ff610621d 100644 --- a/src/Base/Reader.cpp +++ b/src/Base/Reader.cpp @@ -31,6 +31,7 @@ #include #include "Reader.h" +#include "DocumentReader.h" #include "Base64.h" #include "Console.h" #include "InputSource.h" @@ -333,9 +334,11 @@ void Base::XMLReader::readFiles(zipios::ZipInputStream &zipstream) const try { Base::Reader reader(zipstream, jt->FileName, FileVersion); jt->Object->RestoreDocFile(reader); - - if (reader.getLocalReader()) - reader.getLocalReader()->readFiles(zipstream); + if (reader.getLocalReader()) + reader.getLocalReader()->readFiles(zipstream); + if (reader.getLocalDocReader()) + reader.getLocalDocReader()->readFiles(zipstream); + }catch(...) { // For any exception we just continue with the next file. // It doesn't matter if the last reader has read more or @@ -577,3 +580,13 @@ std::shared_ptr Base::Reader::getLocalReader() const { return(this->localreader); } + +void Base::Reader::initLocalDocReader(std::shared_ptr reader) +{ + this->localdocreader = reader; +} + +std::shared_ptr Base::Reader::getLocalDocReader() const +{ + return(this->localdocreader); +} diff --git a/src/Base/Reader.h b/src/Base/Reader.h index d06617a95f..6673a3a43b 100644 --- a/src/Base/Reader.h +++ b/src/Base/Reader.h @@ -48,6 +48,7 @@ XERCES_CPP_NAMESPACE_END namespace Base { class Persistence; +class DocumentReader; /** The XML reader class * This is an important helper class for the store and retrieval system @@ -295,13 +296,16 @@ public: std::string getFileName() const; int getFileVersion() const; void initLocalReader(std::shared_ptr); + void initLocalDocReader(std::shared_ptr); std::shared_ptr getLocalReader() const; + std::shared_ptr getLocalDocReader() const; private: std::istream& _str; std::string _name; int fileVersion; std::shared_ptr localreader; + std::shared_ptr localdocreader; }; } diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index f4c31f7b8a..ef64d500cc 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -1400,6 +1400,7 @@ void Document::Save (Base::Writer &writer) const void Document::Restore(Base::XMLReader &reader) { reader.addFile("GuiDocument.xml",this); + // hide all elements to avoid to update the 3d view when loading data files // RestoreDocFile then restores the visibility status again std::map::iterator it; @@ -1414,134 +1415,195 @@ void Document::Restore(Base::XMLReader &reader) */ void Document::RestoreDocFile(Base::Reader &reader) { - Base::DocumentReader docReader; - docReader.LoadDocument(reader); - //docReader.GetRootElement()//can be used to get Document XMLElement, but not needed. - const char* SchemaVersion_cstr = docReader.GetAttribute("SchemaVersion"); - long SchemaVersion = docReader.ContentToInt( SchemaVersion_cstr ); - const char* HasExpansion_cstr = docReader.GetAttribute("HasExpansion"); - if(HasExpansion_cstr){ - auto tree = TreeWidget::instance(); + readUsing_DocumentReader(reader); + //readUsing_XMLReader(reader); + setModified(false); +} + +void Document::readUsing_XMLReader(Base::Reader &reader){ + // We must create an XML parser to read from the input stream + std::shared_ptr localreader = std::make_shared("GuiDocument.xml", reader); + //localreader->FileVersion = reader.getFileVersion(); + + localreader->readElement("Document"); + long scheme = localreader->getAttributeAsInteger("SchemaVersion"); + //localreader->DocumentSchema = scheme; + + bool hasExpansion = localreader->hasAttribute("HasExpansion"); + if(hasExpansion) { + auto tree = TreeWidget::instance(); if(tree) { auto docItem = tree->getDocumentItem(this); if(docItem) - docItem->Restore(docReader); + docItem->Restore(*localreader); } } - + // At this stage all the document objects and their associated view providers exist. // Now we must restore the properties of the view providers only. - if (SchemaVersion == 1) { - auto VProviderDataDOM = docReader.FindElement("ViewProviderData"); + // + // SchemeVersion "1" + if (scheme == 1) { + + // read the viewproviders itself + + localreader->readElement("ViewProviderData"); + int Cnt = localreader->getAttributeAsInteger("Count"); + + for (int i=0; ireadElement("ViewProvider"); + std::string name = localreader->getAttribute("name"); + bool expanded = false; + if (!hasExpansion && localreader->hasAttribute("expanded")) { + + const char* attr = localreader->getAttribute("expanded"); + if (strcmp(attr,"1") == 0) { + expanded = true; + } + } + ViewProvider* pObj = getViewProviderByName(name.c_str()); + if (pObj){// check if this feature has been registered + pObj->Restore(*localreader); + } + + if (pObj && expanded) { + auto vp = static_cast(pObj); + this->signalExpandObject(*vp, TreeItemMode::ExpandItem,0,0); + } + localreader->readEndElement("ViewProvider"); + } + + localreader->readEndElement("ViewProviderData"); + + + // read camera settings + localreader->readElement("Camera"); + const char* ppReturn = localreader->getAttribute("settings"); + cameraSettings.clear(); + if(ppReturn && ppReturn[0]) { + saveCameraSettings(ppReturn); + try { + const char** pReturnIgnore=nullptr; + std::list mdi = getMDIViews(); + for (const auto & it : mdi) { + if (it->onHasMsg("SetCamera")) + it->onMsg(cameraSettings.c_str(), pReturnIgnore); + } + } + + catch (const Base::Exception& e) { + Base::Console().Error("%s\n", e.what()); + } + } + } + localreader->readEndElement("Document"); + reader.initLocalReader(localreader); +} + +void Document::readUsing_DocumentReader(Base::Reader &reader){ + std::shared_ptr docReader = std::make_shared(); + docReader->LoadDocument(reader); + //docReader->GetRootElement()//can be used to get Document XMLElement, but not needed. + const char* SchemaVersion_cstr = docReader->GetAttribute("SchemaVersion"); + long SchemaVersion = docReader->ContentToInt( SchemaVersion_cstr ); + const char* HasExpansion_cstr = docReader->GetAttribute("HasExpansion"); + if(HasExpansion_cstr){ + auto tree = TreeWidget::instance(); + if(tree) { + auto docItem = tree->getDocumentItem(this); + if(docItem) + docItem->Restore(*docReader); + } + } + + // At this stage all the document objects and their associated view providers exist. + // Now we must restore the properties of the view providers only. + if (SchemaVersion == 1) { + auto VProviderDataDOM = docReader->FindElement("ViewProviderData"); if(VProviderDataDOM){ - const char* vpd_count_cstr = docReader.GetAttribute(VProviderDataDOM,"Count"); + const char* vpd_count_cstr = docReader->GetAttribute(VProviderDataDOM,"Count"); if(vpd_count_cstr){ - long Cnt = docReader.ContentToInt( vpd_count_cstr ); - auto prev_ViewProviderDOM = docReader.FindElement(VProviderDataDOM,"ViewProvider"); + long Cnt = docReader->ContentToInt( vpd_count_cstr ); + auto prev_ViewProviderDOM = docReader->FindElement(VProviderDataDOM,"ViewProvider"); if(prev_ViewProviderDOM){ - const char* name_cstr = docReader.GetAttribute(prev_ViewProviderDOM,"name"); - const char* expanded_cstr = docReader.GetAttribute(prev_ViewProviderDOM,"expanded"); + const char* name_cstr = docReader->GetAttribute(prev_ViewProviderDOM,"name"); + const char* expanded_cstr = docReader->GetAttribute(prev_ViewProviderDOM,"expanded"); bool expanded = false; if (!HasExpansion_cstr && expanded_cstr) { if (strcmp(expanded_cstr,"1") == 0) { expanded = true; } } - ViewProvider* pObj = getViewProviderByName(name_cstr); - if (pObj) - pObj->Restore(docReader,prev_ViewProviderDOM); - + if (pObj){ + pObj->Restore(*docReader,prev_ViewProviderDOM); + } if (pObj && expanded) { auto vp = static_cast(pObj); this->signalExpandObject(*vp, TreeItemMode::ExpandItem,0,0); } - } - for (int i=1; iFindNextElement(prev_ViewProviderDOM,"ViewProvider"); + if(ViewProviderDOM_i){ + const char* name_cstr_i = docReader->GetAttribute(ViewProviderDOM_i,"name"); + const char* expanded_cstr_i = docReader->GetAttribute(ViewProviderDOM_i,"expanded"); + bool expanded = false; + if (!HasExpansion_cstr && expanded_cstr_i) { + if (strcmp(expanded_cstr_i,"1") == 0) { + expanded = true; + } } + ViewProvider* pObj = getViewProviderByName(name_cstr_i); + if (pObj){ + pObj->Restore(*docReader,ViewProviderDOM_i); + } + + if (pObj && expanded) { + auto vp = static_cast(pObj); + this->signalExpandObject(*vp, TreeItemMode::ExpandItem,0,0); + } + prev_ViewProviderDOM = ViewProviderDOM_i; } - ViewProvider* pObj = getViewProviderByName(name_cstr_i); - if (pObj) - pObj->Restore(docReader,ViewProviderDOM_i);//Im still implementing this, which calls ExtensionContainer::Restore. - - if (pObj && expanded) { - auto vp = static_cast(pObj); - this->signalExpandObject(*vp, TreeItemMode::ExpandItem,0,0); - } - prev_ViewProviderDOM = ViewProviderDOM_i; } + } + + } } // read camera settings - auto CameraDOM = docReader.FindElement("Camera"); + auto CameraDOM = docReader->FindElement("Camera"); if(CameraDOM){ - const char* ppReturn = docReader.GetAttribute(CameraDOM,"settings"); + const char* ppReturn = docReader->GetAttribute(CameraDOM,"settings"); cameraSettings.clear(); if(ppReturn && ppReturn[0]) { - saveCameraSettings(ppReturn); - try { - const char** pReturnIgnore=nullptr; - std::list mdi = getMDIViews(); - for (const auto & it : mdi) { - if (it->onHasMsg("SetCamera")) - it->onMsg(cameraSettings.c_str(), pReturnIgnore); - } - } - catch (const Base::Exception& e) { - Base::Console().Error("%s\n", e.what()); - } - } + saveCameraSettings(ppReturn); + try { + const char** pReturnIgnore=nullptr; + std::list mdi = getMDIViews(); + for (const auto & it : mdi) { + if (it->onHasMsg("SetCamera")) + it->onMsg(cameraSettings.c_str(), pReturnIgnore); + } + } + catch (const Base::Exception& e) { + Base::Console().Error("%s\n", e.what()); + } + } + } + + auto ProjectUnitSysDOM = docReader->FindElement("ProjectUnitSystem"); + if(ProjectUnitSysDOM){ + const char* US_cstr = docReader->GetAttribute(ProjectUnitSysDOM,"US"); + const char* ignore_cstr = docReader->GetAttribute(ProjectUnitSysDOM,"ignore"); + + d->projectUnitSystem = docReader->ContentToInt( US_cstr ); + d->projectUnitSystemIgnore = docReader->ContentToInt( ignore_cstr ); } - - /* - try{//if this fails then all other reading attemps will fail, since XERCES doesnt allow to get back to previous point, reading the file should restarted each time an element its not present, since it looks for it untill the end of the document. - //Since ProjectUnitSystem its the only optional field, and its being read at the end of this function, it does not cause any issue, but if other optional its added the way of reading XML used in Reader.cpp will be obsolete - - localreader->readElement("ProjectUnitSystem"); - Base::Console().Error("readElement(ProjectUnitSystem)\n"); - int US = localreader->getAttributeAsInteger("US"); - int ignore = localreader->getAttributeAsInteger("ignore"); - d->projectUnitSystem = US; - d->projectUnitSystemIgnore = ignore; - - }catch (const Base::XMLParseException& e) { - Base::Console().Warning("ProjectUnitSystem not found: %s\n", e.getMessage().c_str()); - }catch(const Base::XMLBaseException& e){ - Base::Console().Warning("ProjectUnitSystem XMLBaseException: %s\n", e.getMessage().c_str()); - }catch(...) { - Base::Console().Error("ProjectUnitSystem catch(...)\n"); - } - */ - } - /* - - try{ - localreader->readEndElement("Document"); - }catch(const Base::XMLParseException& e){ - Base::Console().Warning("readEndElement(Document) XMLParseException: %s\n", e.getMessage().c_str()); - }catch(const Base::XMLBaseException& e){ - Base::Console().Warning("readEndElement(Document) XMLBaseException: %s\n", e.getMessage().c_str()); - }catch(...) { - Base::Console().Error("readEndElement(Document) unkown error.\n"); } - */ - - // reset modified flag - //dont see what this does: - //reader.initLocalReader(localreader); - setModified(false); + reader.initLocalDocReader(docReader); } void Document::slotStartRestoreDocument(const App::Document& doc) diff --git a/src/Gui/Document.h b/src/Gui/Document.h index f7fdad5ebd..5eff465959 100644 --- a/src/Gui/Document.h +++ b/src/Gui/Document.h @@ -158,6 +158,8 @@ public: void SaveDocFile (Base::Writer &writer) const override; /// This method is used to restore large amounts of data from a binary file. void RestoreDocFile(Base::Reader &reader) override; + void readUsing_XMLReader(Base::Reader &reader); + void readUsing_DocumentReader(Base::Reader &reader); void exportObjects(const std::vector&, Base::Writer&); void importObjects(const std::vector&, Base::Reader&, const std::map& nameMapping); diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 54b7d5b2f6..0e255c1a19 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -354,17 +354,29 @@ public: } void restore(Base::DocumentReader& reader, XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *expandEl) { - Base::Console().Error("ExpandInfo restore\n"); const char* count_cstr = reader.GetAttribute(expandEl,"count"); if(count_cstr){ long count = reader.ContentToInt( count_cstr ); - Base::Console().Error("ExpandInfo count: %d\n",count); - auto _expandEl = reader.FindElement(expandEl,"Expand"); - const char* name_cstr = reader.GetAttribute(_expandEl,"name"); - Base::Console().Error("ExpandInfo name_cstr: %s\n",name_cstr); + auto prev_ExpandDOM = reader.FindElement(expandEl,"Expand"); + const char* name_cstr = reader.GetAttribute(prev_ExpandDOM,"name"); + const char* _count_cstr = reader.GetAttribute(prev_ExpandDOM,"count"); auto& entry = (*this)[name_cstr]; - entry.reset(new ExpandInfo); - entry->restore(reader,_expandEl); + if(_count_cstr){ + entry.reset(new ExpandInfo); + entry->restore(reader,prev_ExpandDOM); + } + + for (int i = 1; i < count; ++i) { + auto ExpandDOM_i = reader.FindNextElement(prev_ExpandDOM,"Expand"); + const char* name_cstr = reader.GetAttribute(ExpandDOM_i,"name"); + const char* _count_cstr = reader.GetAttribute(ExpandDOM_i,"count"); + auto& entry = (*this)[name_cstr]; + if(_count_cstr){ + entry.reset(new ExpandInfo); + entry->restore(reader,ExpandDOM_i); + } + prev_ExpandDOM = ExpandDOM_i; + } } } }; @@ -3947,19 +3959,16 @@ void DocumentItem::Restore(Base::XMLReader& reader) { } void DocumentItem::Restore(Base::DocumentReader& reader) { - Base::Console().Error("DocumentItem::Restore() DocumentReader\n"); auto expandEl = reader.FindElement("Expand"); if( !reader.GetAttribute(expandEl,"count") ) return; _ExpandInfo.reset(new ExpandInfo); _ExpandInfo->restore(reader,expandEl); - //TODO NOW for (auto inst : TreeWidget::Instances) { if (inst != getTree()) { auto docItem = inst->getDocumentItem(document()); if (docItem) docItem->_ExpandInfo = _ExpandInfo; - } } }