diff --git a/src/App/Document.cpp b/src/App/Document.cpp index f1b3272fee..894ddf508e 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -88,6 +88,7 @@ recompute path. Also, it enables more complicated dependencies beyond trees. #include #include #include +#include #include #include #include @@ -1284,7 +1285,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()) { @@ -2084,12 +2084,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 cc21764ada..892462844f 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 9a620004e2..5c392a9b51 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. */ @@ -75,7 +74,6 @@ void Extension::initExtensionType(Base::Type type) { } void Extension::initExtension(ExtensionContainer* obj) { - if (m_extensionType.isBad()) throw Base::RuntimeError("Extension: Extension type not set"); @@ -198,6 +196,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 10e54e4355..f9251e249c 100644 --- a/src/App/Extension.h +++ b/src/App/Extension.h @@ -273,6 +273,7 @@ public: //@{ virtual void extensionSave(Base::Writer&) const {} virtual void extensionRestore(Base::XMLReader&) {} + virtual void extensionRestore(Base::DocumentReader&) {} //@} /** @name TypeHandling */ @@ -289,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 30022e809b..88aaca16f3 100644 --- a/src/App/ExtensionContainer.cpp +++ b/src/App/ExtensionContainer.cpp @@ -30,6 +30,12 @@ #include "Extension.h" #include "ExtensionContainer.h" +#include + +#ifndef _PreComp_ +# include +//# include +#endif using namespace App; @@ -48,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"); @@ -307,6 +312,17 @@ void ExtensionContainer::Restore(Base::XMLReader& reader) { App::PropertyContainer::Restore(reader); } +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,containerEl); + App::PropertyContainer::Restore(reader,containerEl); +} + void ExtensionContainer::saveExtensions(Base::Writer& writer) const { //we don't save anything if there are no dynamic extensions @@ -352,6 +368,80 @@ void ExtensionContainer::saveExtensions(Base::Writer& writer) const { writer.decInd(); } +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(containerEl,"expanded"); + if(!expanded_cstr) + return; + 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 ); + 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 (ext && 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) @@ -431,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 @@ -444,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 68517fda3d..2586de023c 100644 --- a/src/App/ExtensionContainer.h +++ b/src/App/ExtensionContainer.h @@ -25,6 +25,14 @@ #define APP_EXTENSIONCONTAINER_H #include "PropertyContainer.h" +#include + +XERCES_CPP_NAMESPACE_BEGIN + class DOMNode; + class DOMElement; +// class DefaultHandler; +// class SAX2XMLReader; +XERCES_CPP_NAMESPACE_END namespace App { @@ -177,11 +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 *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 *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. @@ -191,6 +201,7 @@ public: * If no extension handles the request, then the containers handleChangedPropertyName() is called. */ 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. * @@ -199,6 +210,9 @@ public: * If no extension handles the request, then the containers handleChangedPropertyType() is called. */ 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 e4f76e92aa..2ccf2c8f1e 100644 --- a/src/App/PropertyContainer.cpp +++ b/src/App/PropertyContainer.cpp @@ -30,6 +30,11 @@ #include "Property.h" #include "PropertyContainer.h" +#include + +#ifndef _PreComp_ +# include +#endif FC_LOG_LEVEL_INIT("App",true,true) @@ -74,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); } @@ -198,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 @@ -217,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::beforeSave() const @@ -338,6 +358,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")) { @@ -420,6 +442,117 @@ void PropertyContainer::Restore(Base::XMLReader &reader) reader.readEndElement("Properties"); } +void PropertyContainer::Restore(Base::DocumentReader &reader, XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *containerEl) +{ + reader.clearPartialRestoreProperty(); + + 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 ;igetContainer() != 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"); + } +#endif +} + void PropertyContainer::onPropertyStatusChanged(const Property &prop, unsigned long oldStatus) { (void)prop; diff --git a/src/App/PropertyContainer.h b/src/App/PropertyContainer.h index 17a2102efc..f31099adb7 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,6 +230,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 *containerEl) override; virtual void beforeSave() const; virtual void editProperty(const char * /*propName*/) {} @@ -248,11 +259,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); public: // forbidden PropertyContainer(const PropertyContainer&) = delete; PropertyContainer& operator = (const PropertyContainer&) = delete; + void readProperty(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *PropertyDOM); protected: DynamicProperty dynamicProps; diff --git a/src/App/PropertyGeo.cpp b/src/App/PropertyGeo.cpp index a72364f265..01cced5580 100644 --- a/src/App/PropertyGeo.cpp +++ b/src/App/PropertyGeo.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ #include "Placement.h" #include "ObjectIdentifier.h" +#include using namespace App; using namespace Base; @@ -152,6 +154,25 @@ void PropertyVector::Restore(Base::XMLReader &reader) hasSetValue(); } +void PropertyVector::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + // read my Element + auto PropertyVectorDOM = reader.FindElement(ContainerDOM,"PropertyVector"); + if(PropertyVectorDOM){ + // get the value of my Attribute + const char* valueX_cstr = reader.GetAttribute(PropertyVectorDOM,"valueX"); + const char* valueY_cstr = reader.GetAttribute(PropertyVectorDOM,"valueY"); + const char* valueZ_cstr = reader.GetAttribute(PropertyVectorDOM,"valueZ"); + if(valueX_cstr || valueY_cstr || valueZ_cstr){ + aboutToSetValue(); + _cVec.x = reader.ContentToFloat(valueX_cstr); + _cVec.y = reader.ContentToFloat(valueY_cstr); + _cVec.z = reader.ContentToFloat(valueZ_cstr); + hasSetValue(); + } + } +} + Property *PropertyVector::Copy() const { diff --git a/src/App/PropertyGeo.h b/src/App/PropertyGeo.h index 829e251f98..c29be90761 100644 --- a/src/App/PropertyGeo.h +++ b/src/App/PropertyGeo.h @@ -89,6 +89,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 *containerEl) override; Property *Copy() const override; void Paste(const Property &from) override; @@ -273,7 +274,7 @@ public: void setPyObject(PyObject *) override; void Save (Base::Writer &writer) const override; - void Restore(Base::XMLReader &reader) override; + void Restore(Base::XMLReader &reader) override; Property *Copy() const override; void Paste(const Property &from) override; diff --git a/src/App/PropertyPythonObject.cpp b/src/App/PropertyPythonObject.cpp index 0efc797efb..e21738f575 100644 --- a/src/App/PropertyPythonObject.cpp +++ b/src/App/PropertyPythonObject.cpp @@ -30,8 +30,13 @@ #include #include #include +#include #include +//#ifndef _PreComp_ +//# include +//#endif + #include "PropertyPythonObject.h" #include "DocumentObject.h" @@ -281,6 +286,37 @@ void PropertyPythonObject::restoreObject(Base::XMLReader &reader) } } +void PropertyPythonObject::restoreObject(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + Base::PyGILStateLocker lock; + try { + PropertyContainer* parent = this->getContainer(); + const char* object_cstr = reader.GetAttribute(ContainerDOM,"object"); + if (object_cstr) { + if (strcmp(object_cstr,"yes") == 0) { + Py::Object obj = Py::asObject(parent->getPyObject()); + this->object.setAttr("__object__", obj); + } + } + const char* vobject_cstr = reader.GetAttribute(ContainerDOM,"vobject"); + if (vobject_cstr) { + if (strcmp(vobject_cstr,"yes") == 0) { + Py::Object obj = Py::asObject(parent->getPyObject()); + this->object.setAttr("__vobject__", obj); + } + } + } + catch (Py::Exception& e) { + e.clear(); + } + catch (const Base::Exception& e) { + Base::Console().Error("%s\n",e.what()); + } + catch (...) { + Base::Console().Error("Critical error in PropertyPythonObject::restoreObject\n"); + } +} + void PropertyPythonObject::Save (Base::Writer &writer) const { //if (writer.isForceXML()) { @@ -398,6 +434,88 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader) } } +void PropertyPythonObject::Restore(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM) +{ + auto PythonDOM = reader.FindElement(ContainerDOM,"Python"); + if(PythonDOM){ + const char* file_cstr = reader.GetAttribute(PythonDOM,"file"); + if (file_cstr){ + reader.addFile(file_cstr,this); + }else{ + bool load_json=false; + bool load_pickle=false; + bool load_failed=false; + const char* value_cstr = reader.GetAttribute(PythonDOM,"value"); + const char* encoded_cstr = reader.GetAttribute(PythonDOM,"encoded"); + std::string buffer = value_cstr; + if (encoded_cstr && strcmp(encoded_cstr,"yes") == 0) { + buffer = Base::base64_decode(buffer); + }else { + buffer = decodeValue(buffer); + } + Base::PyGILStateLocker lock; + try { + boost::regex pickle(R"(^\(i(\w+)\n(\w+)\n)"); + boost::match_results what; + std::string::const_iterator start, end; + start = buffer.begin(); + end = buffer.end(); + + const char* module_cstr = reader.GetAttribute(PythonDOM,"module"); + const char* class_cstr = reader.GetAttribute(PythonDOM,"class"); + const char* json_cstr = reader.GetAttribute(PythonDOM,"json"); + if (module_cstr && class_cstr) { + Py::Module mod(PyImport_ImportModule(module_cstr),true); + if (mod.isNull()) + throw Py::Exception(); + PyObject* cls = mod.getAttr(class_cstr).ptr(); + if (!cls) { + std::stringstream s; + s << "Module " << module_cstr + << " has no class " << class_cstr; + throw Py::AttributeError(s.str()); + } + if (PyType_Check(cls)) { + this->object = PyType_GenericAlloc((PyTypeObject*)cls, 0); + } + else { + throw Py::TypeError("neither class nor type object"); + } + load_json = true; + } + else if (boost::regex_search(start, end, what, pickle)) { + std::string name = std::string(what[1].first, what[1].second); + std::string type = std::string(what[2].first, what[2].second); + Py::Module mod(PyImport_ImportModule(name.c_str()),true); + if (mod.isNull()) + throw Py::Exception(); + this->object = PyObject_CallObject(mod.getAttr(type).ptr(), nullptr); + load_pickle = true; + buffer = std::string(what[2].second, end); + } + else if (json_cstr) { + load_json = true; + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + this->object = Py::None(); + load_failed = true; + } + aboutToSetValue(); + if (load_json) + this->fromString(buffer); + else if (load_pickle) + this->loadPickle(buffer); + else if (!load_failed) + Base::Console().Warning("PropertyPythonObject::Restore: unsupported serialisation: %s\n", buffer.c_str()); + restoreObject(reader,PythonDOM); + hasSetValue(); + } + } +} + void PropertyPythonObject::SaveDocFile (Base::Writer &writer) const { std::string buffer = this->toString(); diff --git a/src/App/PropertyPythonObject.h b/src/App/PropertyPythonObject.h index cf1357a234..febdbb255b 100644 --- a/src/App/PropertyPythonObject.h +++ b/src/App/PropertyPythonObject.h @@ -60,6 +60,7 @@ public: void Save (Base::Writer &writer) const override; /** Use Python's pickle module to restore the object */ 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; @@ -73,6 +74,7 @@ public: private: void saveObject(Base::Writer &writer) const; void restoreObject(Base::XMLReader &reader); + void restoreObject(Base::DocumentReader &reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *ContainerDOM); std::string encodeValue(const std::string& str) const; std::string decodeValue(const std::string& str) const; void loadPickle(const std::string& str); diff --git a/src/App/PropertyStandard.cpp b/src/App/PropertyStandard.cpp index be966ccc6c..3017cc89b8 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()) { @@ -777,6 +856,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(); @@ -897,6 +1005,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(); @@ -988,6 +1125,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(); @@ -1233,6 +1385,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()); @@ -1493,6 +1663,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(); @@ -1625,6 +1820,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(); @@ -1746,6 +1953,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(); @@ -1910,6 +2143,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(); @@ -1995,6 +2254,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 { @@ -2113,6 +2381,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(); @@ -2266,6 +2546,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(); @@ -2345,6 +2636,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()); @@ -2495,6 +2802,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)) @@ -2574,6 +2907,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()); @@ -2670,6 +3019,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 7fb7be85c5..7d39ef055c 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/CMakeLists.txt b/src/Base/CMakeLists.txt index d73271bed1..e095c55c53 100644 --- a/src/Base/CMakeLists.txt +++ b/src/Base/CMakeLists.txt @@ -278,6 +278,7 @@ SET(FreeCADBase_CPP_SRCS Writer.cpp XMLTools.cpp ZipHeader.cpp + DocumentReader.cpp ) SET(SWIG_HEADERS diff --git a/src/Base/DocumentReader.cpp b/src/Base/DocumentReader.cpp new file mode 100644 index 0000000000..b91c0e5b1f --- /dev/null +++ b/src/Base/DocumentReader.cpp @@ -0,0 +1,351 @@ +/*************************************************************************** + * Copyright (c) 2011 Jürgen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ +#include "PreCompiled.h" +#include "DocumentReader.h" +#include "InputSource.h" +#include "XMLTools.h" + +#include +#include +#include "Persistence.h" +#include "Sequencer.h" + + +#ifdef _MSC_VER +#include +#endif +#include + +#ifndef _PreComp_ +//# include +# include +# include +# include +#endif + +#ifdef _MSC_VER +# define strdup _strdup +#endif + +XERCES_CPP_NAMESPACE_USE + +//using namespace std; +using namespace Base; + +// --------------------------------------------------------------------------- +// DocumentReader: Constructors and Destructor +// --------------------------------------------------------------------------- +static XercesDOMParser::ValSchemes gValScheme = XercesDOMParser::Val_Auto; +DocumentReader::DocumentReader() +{ + gDoNamespaces = false; + gDoSchema = false; + gSchemaFullChecking = false; + gDoCreate = true; +} + +int DocumentReader::LoadDocument(Base::Reader& reader) +{ + FileInfo _File( reader.getFileName() ); + StdInputSource inputSource(reader, _File.filePath().c_str()); + + // + // Create our parser, then attach an error handler to the parser. + // The parser will call back to methods of the ErrorHandler if it + // discovers errors during the course of parsing the XML document. + // + XercesDOMParser *parser = new XercesDOMParser; + parser->setValidationScheme(gValScheme); + parser->setDoNamespaces(gDoNamespaces); + parser->setDoSchema(gDoSchema); + parser->setValidationSchemaFullChecking(gSchemaFullChecking); + parser->setCreateEntityReferenceNodes(gDoCreate); + + DOMTreeErrorReporter *errReporter = new DOMTreeErrorReporter(); + parser->setErrorHandler(errReporter); + // + // Parse the XML file, catching any XML exceptions that might propagate + // out of it. + // + bool errorsOccured = false; + try { + parser->parse(inputSource); + } + catch (const XMLException& e) { + std::cerr << "An error occurred during parsing\n Message: " + << StrX(e.getMessage()) << std::endl; + errorsOccured = true; + } + catch (const DOMException& e) { + std::cerr << "A DOM error occurred during parsing\n DOMException code: " + << e.code << std::endl; + errorsOccured = true; + } + catch (...) { + std::cerr << "An error occurred during parsing\n " << std::endl; + errorsOccured = true; + } + + if (errorsOccured) { + delete parser; + delete errReporter; + return 0; + } + + XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* _pDocument = parser->adoptDocument(); + delete parser; + delete errReporter; + + if (!_pDocument) + throw XMLBaseException("Malformed Parameter document: Invalid document"); + + DOMElement* rootElem = _pDocument->getDocumentElement(); + if (!rootElem) + throw XMLBaseException("Malformed Parameter document: Root group not found"); + + _pGroupNode = rootElem; + + if (!_pGroupNode){ + throw XMLBaseException("Malformed document."); + } + + return 1; +} + +XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DocumentReader::GetRootElement() const +{ + //if (!_pGroupNode) + //return nullptr; + return _pGroupNode; +} + +XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DocumentReader::FindElement(const char* Type) const +{ + if(!Type) + return nullptr; + + for (DOMNode *clChild = _pGroupNode->getFirstChild(); clChild != nullptr; clChild = clChild->getNextSibling()) { + if (clChild->getNodeType() == DOMNode::ELEMENT_NODE) { + if (!strcmp(Type,StrX(clChild->getNodeName()).c_str())) { + return static_cast(clChild); + } + } + } + return nullptr; +} + +XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DocumentReader::FindElementByField( + XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start, + const char* TypeEl,const char* field_name,const char* field_value) const +{ + if(!TypeEl || !field_name ||!field_value) + return nullptr; + for (DOMNode *clChild = Start; clChild != nullptr; clChild = clChild->getNextSibling()) { + //auto cast = static_cast(clChild); + const char* attr = GetAttribute( static_cast(clChild), field_name ); + if(attr){ + if( !strcmp( attr, field_value ) ){ + return static_cast(clChild);; + } + } + } + return nullptr; +} + +XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DocumentReader::FindElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start, const char* Type) const +{ + if(!Start || !Type) + return nullptr; + for (DOMNode *clChild = Start->getFirstChild(); clChild != nullptr; clChild = clChild->getNextSibling()) { + if (clChild->getNodeType() == DOMNode::ELEMENT_NODE) { + if (!strcmp(Type,StrX(clChild->getNodeName()).c_str())) { + return static_cast(clChild); + } + } + } + return nullptr; +} + +XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DocumentReader::FindNextElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *Prev, const char* Type) const +{ + if (!Prev || !Type) + return nullptr; + DOMNode *clChild = Prev; + while ((clChild = clChild->getNextSibling()) != nullptr) { + if (clChild->getNodeType() == DOMNode::ELEMENT_NODE) { + // the right node Type + if (!strcmp(Type,StrX(clChild->getNodeName()).c_str())) { + return static_cast(clChild); + } + } + } + return nullptr; +} + +long DocumentReader::ContentToInt( const char* content ) +{ + return atol( content ); +} + +unsigned long DocumentReader::ContentToUnsigned(const char* content) +{ + return strtoul(content,nullptr,10); +} + +double DocumentReader::ContentToFloat(const char* content) +{ + return atof(content); +} + +bool DocumentReader::ContentToBool(const char* content) +{ + if (strcmp(content,"1")) + return false; + else + return true; +} + +//ATTRIBUTE: +const char * DocumentReader::GetAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DOMEl, const char* Attr) const +{ + if(!Attr) + return nullptr; + XStr xstr( Attr ); + bool hasAttr = DOMEl->hasAttribute(xstr.unicodeForm()); + if (!hasAttr){ + return nullptr; + } + const XMLCh * attr = DOMEl->getAttribute( xstr.unicodeForm() ); + return strdup( StrX( attr ).c_str() ); +} + +const char * DocumentReader::GetAttribute(const char* Attr) const +{ + if(!Attr) + return nullptr; + XStr xstr( Attr ); + bool hasAttr = _pGroupNode->hasAttribute(xstr.unicodeForm()); + if (!hasAttr){ + return nullptr; + } + const XMLCh * attr = _pGroupNode->getAttribute( xstr.unicodeForm() ); + return strdup( StrX( attr ).c_str() );//strdup is needed since pointer from strx only exists in context where StrX() is created. +} +//Status +void Base::DocumentReader::setPartialRestore(bool on) +{ + setStatus(PartialRestore, on); + setStatus(PartialRestoreInDocumentObject, on); + setStatus(PartialRestoreInProperty, on); + setStatus(PartialRestoreInObject, on); +} + +void Base::DocumentReader::clearPartialRestoreProperty() +{ + setStatus(PartialRestoreInProperty, false); + setStatus(PartialRestoreInObject, false); +} + +bool Base::DocumentReader::testStatus(ReaderStatus pos) const +{ + return StatusBits.test(static_cast(pos)); +} + +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 new file mode 100644 index 0000000000..cf9bf4e71e --- /dev/null +++ b/src/Base/DocumentReader.h @@ -0,0 +1,121 @@ +/*************************************************************************** + * Copyright (c) 2011 Jürgen Riegel * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef BASE_DOCUMENTREADER_H +#define BASE_DOCUMENTREADER_H + +#include +#include +#include +#include +#include +#include + +#include + +namespace zipios { +class ZipInputStream; +} + +XERCES_CPP_NAMESPACE_BEGIN + class DOMNode; + class DOMElement; +XERCES_CPP_NAMESPACE_END +namespace Base +{ +class Reader; +class Persistence; + +class BaseExport DocumentReader +{ +public: + enum ReaderStatus { + PartialRestore = 0, // This bit indicates that a partial restore took place somewhere in this Document + PartialRestoreInDocumentObject = 1, // This bit is local to the DocumentObject being read indicating a partial restore therein + PartialRestoreInProperty = 2, // Local to the Property + PartialRestoreInObject = 3 // Local to the object partially restored itself + }; + DocumentReader(); + int LoadDocument(Base::Reader& reader); + + XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *GetRootElement() const; + XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *FindElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start, const char* Type) const; + XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *FindElement(const char* Type) const; + + XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *FindElementByField(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start, + const char* TypeEl,const char* field_name, const char* field_value) const; + + XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *FindNextElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *Prev, const char* Type) const; + + static long ContentToASCII(const char* Content); + + 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; + + /// return the status bits + 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; + +}; + +} + +#endif diff --git a/src/Base/Parameter.cpp b/src/Base/Parameter.cpp index 01d3d02db9..b650f63f21 100644 --- a/src/Base/Parameter.cpp +++ b/src/Base/Parameter.cpp @@ -33,7 +33,6 @@ # include # include # include -# include # include # include # include @@ -64,49 +63,49 @@ using namespace Base; //************************************************************************** //************************************************************************** // private classes declaration: -// - DOMTreeErrorReporter // - StrX // - DOMPrintFilter // - DOMPrintErrorHandler // - XStr //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +DOMTreeErrorReporter::DOMTreeErrorReporter(): + fSawErrors(false) { +} - -class DOMTreeErrorReporter : public ErrorHandler +void DOMTreeErrorReporter::warning(const SAXParseException&) { -public: - // ----------------------------------------------------------------------- - // Constructors and Destructor - // ----------------------------------------------------------------------- - DOMTreeErrorReporter() = default; + // + // Ignore all warnings. + // +} - ~DOMTreeErrorReporter() override = default; +void DOMTreeErrorReporter::error(const SAXParseException& toCatch) +{ + fSawErrors = true; + std::cerr << "Error at file \"" << StrX(toCatch.getSystemId()) + << "\", line " << toCatch.getLineNumber() + << ", column " << toCatch.getColumnNumber() + << "\n Message: " << StrX(toCatch.getMessage()) << std::endl; +} +void DOMTreeErrorReporter::fatalError(const SAXParseException& toCatch) +{ + fSawErrors = true; + std::cerr << "Fatal Error at file \"" << StrX(toCatch.getSystemId()) + << "\", line " << toCatch.getLineNumber() + << ", column " << toCatch.getColumnNumber() + << "\n Message: " << StrX(toCatch.getMessage()) << std::endl; +} - // ----------------------------------------------------------------------- - // Implementation of the error handler interface - // ----------------------------------------------------------------------- - void warning(const SAXParseException& toCatch) override; - void error(const SAXParseException& toCatch) override; - void fatalError(const SAXParseException& toCatch) override; - void resetErrors() override; - - // ----------------------------------------------------------------------- - // Getter methods - // ----------------------------------------------------------------------- - bool getSawErrors() const; - - // ----------------------------------------------------------------------- - // Private data members - // - // fSawErrors - // This is set if we get any errors, and is queryable via a getter - // method. Its used by the main code to suppress output if there are - // errors. - // ----------------------------------------------------------------------- - bool fSawErrors{false}; -}; +void DOMTreeErrorReporter::resetErrors() +{ + // No-op in this case +} +inline bool DOMTreeErrorReporter::getSawErrors() const +{ + return fSawErrors; +} class DOMPrintFilter : public DOMLSSerializerFilter { @@ -150,14 +149,6 @@ public: void operator=(const DOMErrorHandler&) = delete; }; - - -inline bool DOMTreeErrorReporter::getSawErrors() const -{ - return fSawErrors; -} - - //************************************************************************** //************************************************************************** // ParameterManager @@ -1833,42 +1824,6 @@ void ParameterManager::CheckDocument() const } -//************************************************************************** -//************************************************************************** -// DOMTreeErrorReporter -//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -void DOMTreeErrorReporter::warning(const SAXParseException&) -{ - // - // Ignore all warnings. - // -} - -void DOMTreeErrorReporter::error(const SAXParseException& toCatch) -{ - fSawErrors = true; - std::cerr << "Error at file \"" << StrX(toCatch.getSystemId()) - << "\", line " << toCatch.getLineNumber() - << ", column " << toCatch.getColumnNumber() - << "\n Message: " << StrX(toCatch.getMessage()) << std::endl; -} - -void DOMTreeErrorReporter::fatalError(const SAXParseException& toCatch) -{ - fSawErrors = true; - std::cerr << "Fatal Error at file \"" << StrX(toCatch.getSystemId()) - << "\", line " << toCatch.getLineNumber() - << ", column " << toCatch.getColumnNumber() - << "\n Message: " << StrX(toCatch.getMessage()) << std::endl; -} - -void DOMTreeErrorReporter::resetErrors() -{ - // No-op in this case -} - - //************************************************************************** //************************************************************************** // DOMPrintFilter diff --git a/src/Base/Parameter.h b/src/Base/Parameter.h index 6ae3bc2c4f..f27c3b02cb 100644 --- a/src/Base/Parameter.h +++ b/src/Base/Parameter.h @@ -53,6 +53,7 @@ using PyObject = struct _object; #include #include #include +#include #include "Handle.h" #include "Observer.h" @@ -65,7 +66,6 @@ using PyObject = struct _object; # pragma warning( disable : 4275 ) #endif - XERCES_CPP_NAMESPACE_BEGIN class DOMNode; class DOMElement; @@ -269,6 +269,7 @@ protected: ~ParameterGrp() override; /// helper function for GetGroup Base::Reference _GetGroup(const char* Name); + bool ShouldRemove() const; void _Reset(); @@ -421,11 +422,43 @@ private: bool gUseFilter ; bool gFormatPrettyPrint ; -private: ParameterManager(); ~ParameterManager() override; }; +XERCES_CPP_NAMESPACE_USE + +class DOMTreeErrorReporter : public ErrorHandler +{ +public: + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + DOMTreeErrorReporter(); + // ----------------------------------------------------------------------- + // Implementation of the error handler interface + // ----------------------------------------------------------------------- + void warning(const SAXParseException& toCatch) override; + void error(const SAXParseException& toCatch) override; + void fatalError(const SAXParseException& toCatch) override; + void resetErrors() override; + // ----------------------------------------------------------------------- + // Getter methods + // ----------------------------------------------------------------------- + bool getSawErrors() const; +private: + // ----------------------------------------------------------------------- + // Private data members + // + // fSawErrors + // This is set if we get any errors, and is queryable via a getter + // method. Its used by the main code to suppress output if there are + // errors. + // ----------------------------------------------------------------------- + bool fSawErrors; +}; + + /** python wrapper function */ BaseExport PyObject* GetPyObject( const Base::Reference &hcParamGrp); diff --git a/src/Base/Persistence.cpp b/src/Base/Persistence.cpp index 5a97ef649a..4e066b5f37 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; @@ -61,6 +65,20 @@ void Persistence::Save (Writer &/*writer*/) const assert(0); } + +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*/) +{ + // you have to implement this method in all descending classes! + assert(0); +} + void Persistence::Restore(XMLReader &/*reader*/) { // you have to implement this method in all descending classes! diff --git a/src/Base/Persistence.h b/src/Base/Persistence.h index 75deac6212..cf4634c66d 100644 --- a/src/Base/Persistence.h +++ b/src/Base/Persistence.h @@ -26,11 +26,21 @@ #include "BaseClass.h" +#include + +XERCES_CPP_NAMESPACE_BEGIN + class DOMNode; + class DOMElement; +// class DefaultHandler; +// class SAX2XMLReader; +XERCES_CPP_NAMESPACE_END + namespace Base { class Reader; class Writer; class XMLReader; +class DocumentReader; /// Persistence class and root of the type system class BaseExport Persistence : public BaseClass @@ -77,6 +87,9 @@ public: * \endcode */ 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 @@ -141,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 189a1c34d3..80c4e8cfd0 100644 --- a/src/Base/Reader.cpp +++ b/src/Base/Reader.cpp @@ -26,11 +26,13 @@ #ifndef _PreComp_ #include # include +# include #endif #include #include "Reader.h" +#include "DocumentReader.h" #include "Base64.h" #include "Console.h" #include "InputSource.h" @@ -45,7 +47,6 @@ #include #include - XERCES_CPP_NAMESPACE_USE using namespace std; @@ -382,12 +383,14 @@ void Base::XMLReader::readFiles(zipios::ZipInputStream &zipstream) const // 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()) + Base::Reader reader(zipstream, jt->FileName, FileVersion); + jt->Object->RestoreDocFile(reader); + if (reader.getLocalReader()) reader.getLocalReader()->readFiles(zipstream); - } - catch(...) { + 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. @@ -628,3 +631,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 64149820a0..5e92c783e7 100644 --- a/src/Base/Reader.h +++ b/src/Base/Reader.h @@ -50,6 +50,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 @@ -321,13 +322,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/Base/XMLTools.cpp b/src/Base/XMLTools.cpp index fb0fda11e7..fb492c062d 100644 --- a/src/Base/XMLTools.cpp +++ b/src/Base/XMLTools.cpp @@ -26,15 +26,15 @@ #include "XMLTools.h" using namespace Base; +XERCES_CPP_NAMESPACE_USE -std::unique_ptr XMLTools::transcoder; +std::unique_ptr XMLTools::transcoder; void XMLTools::initialize() { - XERCES_CPP_NAMESPACE_USE; if (!transcoder.get()) { XMLTransService::Codes res{}; - transcoder.reset(XERCES_CPP_NAMESPACE_QUALIFIER XMLPlatformUtils::fgTransService->makeNewTranscoderFor(XERCES_CPP_NAMESPACE_QUALIFIER XMLRecognizer::UTF_8, res, 4096, XERCES_CPP_NAMESPACE_QUALIFIER XMLPlatformUtils::fgMemoryManager)); + transcoder.reset(XMLPlatformUtils::fgTransService->makeNewTranscoderFor(XMLRecognizer::UTF_8, res, 4096, XMLPlatformUtils::fgMemoryManager)); if (res != XMLTransService::Ok) throw Base::UnicodeError("Can\'t create transcoder"); } @@ -44,7 +44,6 @@ std::string XMLTools::toStdString(const XMLCh* const toTranscode) { std::string str; - XERCES_CPP_NAMESPACE_USE; initialize(); //char outBuff[128]; @@ -74,8 +73,7 @@ std::basic_string XMLTools::toXMLString(const char* const fromTranscode) std::basic_string str; if (!fromTranscode) return str; - - XERCES_CPP_NAMESPACE_USE; + initialize(); static XMLCh outBuff[128]; diff --git a/src/Base/XMLTools.h b/src/Base/XMLTools.h index d0dc66c876..e5f537b2f2 100644 --- a/src/Base/XMLTools.h +++ b/src/Base/XMLTools.h @@ -28,16 +28,10 @@ #include #include #include +#include #include - - -XERCES_CPP_NAMESPACE_BEGIN - class DOMNode; - class DOMElement; - class DOMDocument; -XERCES_CPP_NAMESPACE_END - +XERCES_CPP_NAMESPACE_USE // Helper class class BaseExport XMLTools { @@ -48,7 +42,7 @@ public: static void terminate(); private: - static std::unique_ptr transcoder; + static std::unique_ptr transcoder; }; //************************************************************************** @@ -79,12 +73,12 @@ inline std::ostream& operator<<(std::ostream& target, const StrX& toDump) inline StrX::StrX(const XMLCh* const toTranscode) { // Call the private transcoding method - fLocalForm = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(toTranscode); + fLocalForm = XMLString::transcode(toTranscode); } inline StrX::~StrX() { - XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&fLocalForm); + XMLString::release(&fLocalForm); } @@ -158,12 +152,12 @@ private : inline XStr::XStr(const char* const toTranscode) { - fUnicodeForm = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(toTranscode); + fUnicodeForm = XMLString::transcode(toTranscode); } inline XStr::~XStr() { - XERCES_CPP_NAMESPACE_QUALIFIER XMLString::release(&fUnicodeForm); + XMLString::release(&fUnicodeForm); } diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 9b7fdeeb22..f58c18072e 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -54,6 +54,8 @@ #include #include +#include + #include #include @@ -929,6 +931,19 @@ void Application::slotActiveDocument(const App::Document& Doc) Py::Module("FreeCADGui").setAttr(std::string("ActiveDocument"),Py::None()); } } + + //Set Unit System. + int projectUnitSystemIndex = doc->second->getProjectUnitSystem(); + int ignore = doc->second->getProjectUnitSystemIgnore(); + if( projectUnitSystemIndex >= 0 && !ignore ){//is valid + Base::UnitsApi::setSchema(static_cast(projectUnitSystemIndex)); + }else{// set up Unit system default + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath + ("User parameter:BaseApp/Preferences/Units"); + Base::UnitsApi::setSchema((Base::UnitSystem)hGrp->GetInt("UserSchema",0)); + Base::UnitsApi::setDecimals(hGrp->GetInt("Decimals", Base::UnitsApi::getDecimals())); + } + signalActiveDocument(*doc->second); updateActions(); } diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index 21f2a6a702..584c2d8a32 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -33,6 +33,7 @@ # include # include # include +# include #endif #include @@ -45,6 +46,7 @@ #include #include #include +#include #include #include @@ -66,7 +68,6 @@ #include "ViewProviderDocumentObjectGroup.h" #include "WaitCursor.h" - FC_LOG_LEVEL_INIT("Gui", true, true) using namespace Gui; @@ -105,6 +106,9 @@ struct DocumentP std::map _CoinMap; std::map _ViewProviderMapAnnotation; std::list _redoViewProviders; + + int projectUnitSystem=-1; + bool projectUnitSystemIgnore; using Connection = boost::signals2::connection; Connection connectNewObject; @@ -648,6 +652,30 @@ void Document::setPos(const char* name, const Base::Matrix4D& rclMtrx) } +void Document::setProjectUnitSystem(int pUS) +{ + if(pUS != d->projectUnitSystem && pUS >= 0){ + d->projectUnitSystem = pUS; + setModified(true); + } +} + +int Document::getProjectUnitSystem() const +{ + return d->projectUnitSystem; +} + +void Document::setProjectUnitSystemIgnore(bool ignore) +{ + d->projectUnitSystemIgnore = ignore; + setModified(true); +} + +bool Document::getProjectUnitSystemIgnore() const +{ + return d->projectUnitSystemIgnore; +} + //***************************************************************************************************** // Document //***************************************************************************************************** @@ -655,7 +683,6 @@ void Document::slotNewObject(const App::DocumentObject& Obj) { auto pcProvider = static_cast(getViewProvider(&Obj)); if (!pcProvider) { - //Base::Console().Log("Document::slotNewObject() called\n"); std::string cName = Obj.getViewProviderNameStored(); for(;;) { if (cName.empty()) { @@ -738,7 +765,6 @@ void Document::slotDeletedObject(const App::DocumentObject& Obj) { std::list::iterator vIt; setModified(true); - //Base::Console().Log("Document::slotDeleteObject() called\n"); // cycling to all views of the document ViewProvider* viewProvider = getViewProvider(&Obj); @@ -1377,6 +1403,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; @@ -1391,13 +1418,20 @@ void Document::Restore(Base::XMLReader &reader) */ void Document::RestoreDocFile(Base::Reader &reader) { + + 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->FileVersion = reader.getFileVersion(); localreader->readElement("Document"); long scheme = localreader->getAttributeAsInteger("SchemaVersion"); - localreader->DocumentSchema = scheme; + //localreader->DocumentSchema = scheme; bool hasExpansion = localreader->hasAttribute("HasExpansion"); if(hasExpansion) { @@ -1414,29 +1448,37 @@ void Document::RestoreDocFile(Base::Reader &reader) // // 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 + 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"); @@ -1452,17 +1494,119 @@ void Document::RestoreDocFile(Base::Reader &reader) it->onMsg(cameraSettings.c_str(), pReturnIgnore); } } + catch (const Base::Exception& e) { Base::Console().Error("%s\n", e.what()); } } } - localreader->readEndElement("Document"); - - // reset modified flag reader.initLocalReader(localreader); - setModified(false); +} + +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"); + if(vpd_count_cstr){ + 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"); + 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 && 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; + } + } + + } + + + } + } + // read camera settings + auto CameraDOM = docReader->FindElement("Camera"); + if(CameraDOM){ + 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()); + } + } + } + + 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 ); + } + + } + reader.initLocalDocReader(docReader); } void Document::slotStartRestoreDocument(const App::Document& doc) @@ -1578,6 +1722,15 @@ void Document::SaveDocFile (Base::Writer &writer) const writer.Stream() << writer.ind() << "\n"; writer.decInd(); // indentation for camera settings + + if( d->projectUnitSystem >= 0 ){ + writer.incInd(); // indentation for ProjectUnitSystem + writer.Stream() << writer.ind() << "projectUnitSystem << "\" ignore=\"" + << d->projectUnitSystemIgnore << "\"/>\n"; + writer.decInd(); // indentation for ProjectUnitSystem + } + writer.Stream() << "" << std::endl; } diff --git a/src/Gui/Document.h b/src/Gui/Document.h index 73df51510d..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); @@ -297,6 +299,12 @@ public: const char *getCameraSettings() const; bool saveCameraSettings(const char *) const; + + void setProjectUnitSystem(int); + int getProjectUnitSystem() const; + + void setProjectUnitSystemIgnore(bool); + bool getProjectUnitSystemIgnore() const; protected: // pointer to the python class diff --git a/src/Gui/PreferencePages/DlgSettingsGeneral.cpp b/src/Gui/PreferencePages/DlgSettingsGeneral.cpp index 40448509de..f513244d34 100644 --- a/src/Gui/PreferencePages/DlgSettingsGeneral.cpp +++ b/src/Gui/PreferencePages/DlgSettingsGeneral.cpp @@ -38,6 +38,8 @@ #include #include +#include + #include #include #include @@ -93,6 +95,7 @@ DlgSettingsGeneral::DlgSettingsGeneral( QWidget* parent ) for (int i = 0; i < num; i++) { QString item = Base::UnitsApi::getDescription(static_cast(i)); ui->comboBox_UnitSystem->addItem(item, i); + ui->comboBox_projectUnitSystem->addItem(item, i); } // Enable/disable the fractional inch option depending on system @@ -203,7 +206,21 @@ void DlgSettingsGeneral::saveSettings() // Set and save the Unit System viewSystemIndex = ui->comboBox_UnitSystem->currentIndex(); - UnitsApi::setSchema(static_cast(viewSystemIndex)); + auto activeDoc = Gui::Application::Instance->activeDocument(); + bool projectUnitSystemIgnore = ui->checkBox_projectUnitSystemIgnore->isChecked(); + if(activeDoc){ + activeDoc->setProjectUnitSystemIgnore( projectUnitSystemIgnore ); + if(!projectUnitSystemIgnore){ + int projectUnitSystemIndex = ui->comboBox_projectUnitSystem->currentIndex(); + activeDoc->setProjectUnitSystem( projectUnitSystemIndex ); + UnitsApi::setSchema(static_cast(projectUnitSystemIndex)); + }else{ + UnitsApi::setSchema(static_cast(viewSystemIndex)); + } + }else{ + UnitsApi::setSchema(static_cast(viewSystemIndex)); + } + // ui->SubstituteDecimal->onSave(); ui->UseLocaleFormatting->onSave(); @@ -252,6 +269,24 @@ void DlgSettingsGeneral::loadSettings() // handy little equation. cbIndex = std::log2(FracInch) - 1; ui->comboBox_FracInch->setCurrentIndex(cbIndex); + + + auto activeDoc = Gui::Application::Instance->activeDocument(); + if(activeDoc){ + int us = activeDoc->getProjectUnitSystem(); + if(us >= 0){//Valid unit system: + ui->comboBox_projectUnitSystem->setCurrentIndex( us ); + int pusIgnore = activeDoc->getProjectUnitSystemIgnore(); + ui->checkBox_projectUnitSystemIgnore->setChecked( pusIgnore ); + }else{ + ui->comboBox_projectUnitSystem->setCurrentIndex( 0 ); + ui->checkBox_projectUnitSystemIgnore->setChecked( false ); + } + }else{ + ui->checkBox_projectUnitSystemIgnore->setEnabled(false); + ui->comboBox_projectUnitSystem->setEnabled(false); + } + ui->SubstituteDecimal->onRestore(); @@ -389,9 +424,11 @@ void DlgSettingsGeneral::changeEvent(QEvent *event) if (event->type() == QEvent::LanguageChange) { int index = ui->UseLocaleFormatting->currentIndex(); int index2 = ui->comboBox_UnitSystem->currentIndex(); + int pusIndex = ui->comboBox_projectUnitSystem->currentIndex(); ui->retranslateUi(this); ui->UseLocaleFormatting->setCurrentIndex(index); ui->comboBox_UnitSystem->setCurrentIndex(index2); + ui->comboBox_projectUnitSystem->setCurrentIndex(pusIndex); } else { QWidget::changeEvent(event); @@ -600,6 +637,19 @@ void DlgSettingsGeneral::onUnitSystemIndexChanged(int index) } } +void DlgSettingsGeneral::on_checkBox_projectUnitSystemIgnore_stateChanged(int state) +{ + if (state < 0) + return; // happens when clearing the combo box in retranslateUi() + + // Enable/disable the projectUnitSystem if being ignored: + if(state == 2){//ignore + ui->comboBox_projectUnitSystem->setEnabled(false); + }else if(state == 0){ + ui->comboBox_projectUnitSystem->setEnabled(true); + } +} + void DlgSettingsGeneral::onThemeChanged(int index) { Q_UNUSED(index); themeChanged = true; diff --git a/src/Gui/PreferencePages/DlgSettingsGeneral.h b/src/Gui/PreferencePages/DlgSettingsGeneral.h index 1c3cc6ad0f..6713250165 100644 --- a/src/Gui/PreferencePages/DlgSettingsGeneral.h +++ b/src/Gui/PreferencePages/DlgSettingsGeneral.h @@ -70,6 +70,7 @@ protected Q_SLOTS: public Q_SLOTS: void onUnitSystemIndexChanged(int index); + void on_checkBox_projectUnitSystemIgnore_stateChanged(int state); private: void saveDockWindowVisibility(); diff --git a/src/Gui/PreferencePages/DlgSettingsGeneral.ui b/src/Gui/PreferencePages/DlgSettingsGeneral.ui index 382e9c83cd..e457b417c4 100644 --- a/src/Gui/PreferencePages/DlgSettingsGeneral.ui +++ b/src/Gui/PreferencePages/DlgSettingsGeneral.ui @@ -87,14 +87,42 @@ + + + + Project Unit system: + + + + + + + + Unit system used for display metrics stored in project + + + + + + + + If enabled, Unit System stored in project will be ignored. + + + Ignore + + + + + Minimum fractional inch: - + Minimum fractional inch to be displayed @@ -136,14 +164,14 @@ - + Number format: - + UseLocaleFormatting @@ -168,7 +196,7 @@ - + If enabled, numerical keypad decimal separator diff --git a/src/Gui/PreferencePages/DlgSettingsNavigation.cpp b/src/Gui/PreferencePages/DlgSettingsNavigation.cpp index 55ff7a0a66..f52118d296 100644 --- a/src/Gui/PreferencePages/DlgSettingsNavigation.cpp +++ b/src/Gui/PreferencePages/DlgSettingsNavigation.cpp @@ -28,6 +28,8 @@ # include # include #endif +#include +#include #include #include @@ -35,8 +37,7 @@ #include #include #include -#include -#include + #include "DlgSettingsNavigation.h" #include "ui_DlgSettingsNavigation.h" diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index d1ed313356..95985ccffd 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -35,6 +35,11 @@ # include #endif +// clang-format off +#include +#include +// clang-format on + #include #include #include @@ -44,9 +49,9 @@ #include #include #include +#include #include -#include -#include + #include #include diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 2dfab108ad..7adea03fec 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -66,6 +66,10 @@ #include "Widgets.h" #include "Workbench.h" +#include +#include +#include + FC_LOG_LEVEL_INIT("Tree", false, true, true) @@ -351,6 +355,33 @@ public: } reader.readEndElement("Expand", level - 1); } + + void restore(Base::DocumentReader& reader, XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *expandEl) { + const char* count_cstr = reader.GetAttribute(expandEl,"count"); + if(count_cstr){ + long count = reader.ContentToInt( count_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]; + 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; + } + } + } }; // --------------------------------------------------------------------------- @@ -3951,6 +3982,21 @@ void DocumentItem::Restore(Base::XMLReader& reader) { } } +void DocumentItem::Restore(Base::DocumentReader& reader) { + auto expandEl = reader.FindElement("Expand"); + if( !reader.GetAttribute(expandEl,"count") ) + return; + _ExpandInfo.reset(new ExpandInfo); + _ExpandInfo->restore(reader,expandEl); + for (auto inst : TreeWidget::Instances) { + if (inst != getTree()) { + auto docItem = inst->getDocumentItem(document()); + if (docItem) + docItem->_ExpandInfo = _ExpandInfo; + } + } +} + void DocumentItem::restoreItemExpansion(const ExpandInfoPtr& info, DocumentObjectItem* item) { item->setExpanded(true); if (!info) diff --git a/src/Gui/Tree.h b/src/Gui/Tree.h index f10b618d07..1a830597e4 100644 --- a/src/Gui/Tree.h +++ b/src/Gui/Tree.h @@ -297,6 +297,7 @@ public: unsigned int getMemSize () const override; void Save (Base::Writer &) const override; void Restore(Base::XMLReader &) override; + void Restore(Base::DocumentReader& reader) override; class ExpandInfo; using ExpandInfoPtr = std::shared_ptr; diff --git a/src/Gui/ViewProvider.cpp b/src/Gui/ViewProvider.cpp index 63f813d75a..152da008a8 100644 --- a/src/Gui/ViewProvider.cpp +++ b/src/Gui/ViewProvider.cpp @@ -837,6 +837,18 @@ void ViewProvider::Restore(Base::XMLReader& reader) { // setStatus(Gui::isRestoring, false); } +void ViewProvider::Restore(Base::DocumentReader& reader, XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *viewProviderEl) { + // Because some PropertyLists type properties are stored in a separate file, + // and is thus restored outside this function. So we rely on Gui::Document + // to set the isRestoring flags for us. + // + // setStatus(Gui::isRestoring, true); + + TransactionalObject::Restore(reader,viewProviderEl); + + // setStatus(Gui::isRestoring, false); +} + void ViewProvider::updateData(const App::Property* prop) { auto vector = getExtensionsDerivedFromType(); diff --git a/src/Gui/ViewProvider.h b/src/Gui/ViewProvider.h index a319ec0c8d..65a5df2a3f 100644 --- a/src/Gui/ViewProvider.h +++ b/src/Gui/ViewProvider.h @@ -500,6 +500,7 @@ public: //restoring the object from document: //this may be of interest to extensions, hence call them void Restore(Base::XMLReader& reader) override; + void Restore(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *viewProviderEl); bool isRestoring() {return testStatus(Gui::isRestoring);} diff --git a/src/Main/MainGui.cpp b/src/Main/MainGui.cpp index b405a07832..48ae847ef4 100644 --- a/src/Main/MainGui.cpp +++ b/src/Main/MainGui.cpp @@ -23,6 +23,12 @@ #include +#if defined(_MSC_VER) +#include +#include +#endif + + #ifdef _PreComp_ # undef _PreComp_ #endif @@ -305,8 +311,6 @@ int main( int argc, char ** argv ) } #if defined(_MSC_VER) -#include -#include typedef BOOL (__stdcall *tMDWD)( IN HANDLE hProcess, diff --git a/src/Main/MainPy.cpp b/src/Main/MainPy.cpp index e202653592..83ccf0fe36 100644 --- a/src/Main/MainPy.cpp +++ b/src/Main/MainPy.cpp @@ -27,6 +27,10 @@ # undef _PreComp_ #endif +#if defined(FC_OS_WIN32) +# include +#endif + #if defined(FC_OS_LINUX) || defined(FC_OS_BSD) # include #endif @@ -52,9 +56,7 @@ #include #include - #if defined(FC_OS_WIN32) -# include /** DllMain is called when DLL is loaded */ diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index d759b4cb05..046461816e 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -31,6 +31,8 @@ #include #include #endif +#include +#include #include #include @@ -44,8 +46,7 @@ #include #include #include -#include -#include + #include #include diff --git a/src/Mod/Fem/Gui/TaskCreateNodeSet.cpp b/src/Mod/Fem/Gui/TaskCreateNodeSet.cpp index 1cd9a2af14..e72b3e78b4 100644 --- a/src/Mod/Fem/Gui/TaskCreateNodeSet.cpp +++ b/src/Mod/Fem/Gui/TaskCreateNodeSet.cpp @@ -30,14 +30,14 @@ #include #include #endif +#include +#include #include #include #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/Fem/Gui/TaskFemConstraint.cpp b/src/Mod/Fem/Gui/TaskFemConstraint.cpp index 9b1e3ddac3..93aee4b5a0 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraint.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraint.cpp @@ -32,10 +32,12 @@ #include #endif +#include + #include #include #include -#include + #include #include #include diff --git a/src/Mod/Fem/Gui/TaskPostBoxes.cpp b/src/Mod/Fem/Gui/TaskPostBoxes.cpp index caab82b88c..0ee9fe1a65 100644 --- a/src/Mod/Fem/Gui/TaskPostBoxes.cpp +++ b/src/Mod/Fem/Gui/TaskPostBoxes.cpp @@ -35,6 +35,10 @@ #include #include #endif +// clang-format off +#include +#include +// clang-format on #include #include @@ -46,8 +50,6 @@ #include #include #include -#include -#include #include #include "ui_TaskPostClip.h" diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp index dd69252905..4fe2b2da56 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp @@ -42,6 +42,10 @@ #include #include #endif +// clang-format off +#include +#include +// clang-format on #include #include @@ -49,9 +53,8 @@ #include #include #include + #include -#include -#include #include "FemSettings.h" #include "TaskPostBoxes.h" diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp index 4b7d5d4dd5..92a81f33f5 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp @@ -46,6 +46,9 @@ #include #endif +#include +#include + #include #include #include @@ -56,8 +59,7 @@ #include #include #include -#include -#include + #include #include "TaskPostBoxes.h" diff --git a/src/Mod/Inspection/Gui/Command.cpp b/src/Mod/Inspection/Gui/Command.cpp index 8dfc5f420b..a1d8117cd8 100644 --- a/src/Mod/Inspection/Gui/Command.cpp +++ b/src/Mod/Inspection/Gui/Command.cpp @@ -24,6 +24,8 @@ #ifndef _PreComp_ #include #endif +#include +#include #include #include @@ -31,8 +33,6 @@ #include #include #include -#include -#include #include #include "ViewProviderInspection.h" diff --git a/src/Mod/Inspection/Gui/ViewProviderInspection.cpp b/src/Mod/Inspection/Gui/ViewProviderInspection.cpp index b5d363f6ff..363719eae6 100644 --- a/src/Mod/Inspection/Gui/ViewProviderInspection.cpp +++ b/src/Mod/Inspection/Gui/ViewProviderInspection.cpp @@ -46,13 +46,15 @@ #include #endif +#include + #include #include #include #include #include #include -#include + #include #include #include diff --git a/src/Mod/Mesh/Gui/Command.cpp b/src/Mod/Mesh/Gui/Command.cpp index 87a8d4f19b..8cb74d9422 100644 --- a/src/Mod/Mesh/Gui/Command.cpp +++ b/src/Mod/Mesh/Gui/Command.cpp @@ -38,6 +38,8 @@ #ifndef __InventorAll__ #include #endif +#include +#include #include #include @@ -53,8 +55,6 @@ #include #include #include -#include -#include #include #include diff --git a/src/Mod/Mesh/Gui/MeshEditor.cpp b/src/Mod/Mesh/Gui/MeshEditor.cpp index 4393961d42..e478c3d431 100644 --- a/src/Mod/Mesh/Gui/MeshEditor.cpp +++ b/src/Mod/Mesh/Gui/MeshEditor.cpp @@ -45,11 +45,12 @@ #include #include #endif +#include +#include #include #include -#include -#include + #include #include #include diff --git a/src/Mod/Mesh/Gui/MeshSelection.cpp b/src/Mod/Mesh/Gui/MeshSelection.cpp index ee54fc9eb6..ab50940821 100644 --- a/src/Mod/Mesh/Gui/MeshSelection.cpp +++ b/src/Mod/Mesh/Gui/MeshSelection.cpp @@ -32,7 +32,10 @@ #include #include #endif - +// clang-format off +#include +#include +// clang-format on #include #include #include @@ -42,8 +45,7 @@ #include #include #include -#include -#include + #include #include #include diff --git a/src/Mod/MeshPart/Gui/Command.cpp b/src/Mod/MeshPart/Gui/Command.cpp index 9e3b6cb0c5..59ad55ca5b 100644 --- a/src/Mod/MeshPart/Gui/Command.cpp +++ b/src/Mod/MeshPart/Gui/Command.cpp @@ -26,7 +26,10 @@ #include #include #endif - +// clang-format off +#include +#include +// clang-format on #include #include #include @@ -35,8 +38,6 @@ #include #include #include -#include -#include #include #include "CrossSections.h" diff --git a/src/Mod/MeshPart/Gui/CrossSections.cpp b/src/Mod/MeshPart/Gui/CrossSections.cpp index 9aa92e639d..7f748988d5 100644 --- a/src/Mod/MeshPart/Gui/CrossSections.cpp +++ b/src/Mod/MeshPart/Gui/CrossSections.cpp @@ -42,13 +42,15 @@ #include #endif +// clang-format off +#include +#include +// clang-format on #include #include #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/MeshPart/Gui/CurveOnMesh.cpp b/src/Mod/MeshPart/Gui/CurveOnMesh.cpp index f4b9e194a3..6490fe6b63 100644 --- a/src/Mod/MeshPart/Gui/CurveOnMesh.cpp +++ b/src/Mod/MeshPart/Gui/CurveOnMesh.cpp @@ -51,13 +51,16 @@ #include #endif +// clang-format off +#include +#include +// clang-format on + #include #include #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/Part/Gui/BoxSelection.cpp b/src/Mod/Part/Gui/BoxSelection.cpp index 9a18d68d31..cc9215ed97 100644 --- a/src/Mod/Part/Gui/BoxSelection.cpp +++ b/src/Mod/Part/Gui/BoxSelection.cpp @@ -33,7 +33,8 @@ # include # include #endif - +#include +#include #include #include #include @@ -41,8 +42,6 @@ #include #include #include -#include -#include #include "BoxSelection.h" #include "ViewProviderExt.h" diff --git a/src/Mod/Part/Gui/Command.cpp b/src/Mod/Part/Gui/Command.cpp index 5773bac1b3..4b378d9748 100644 --- a/src/Mod/Part/Gui/Command.cpp +++ b/src/Mod/Part/Gui/Command.cpp @@ -31,7 +31,8 @@ # include # include #endif - +#include +#include #include #include #include @@ -48,8 +49,6 @@ #include #include #include -#include -#include #include #include "BoxSelection.h" diff --git a/src/Mod/Part/Gui/CrossSections.cpp b/src/Mod/Part/Gui/CrossSections.cpp index 76069d3282..f1144e9115 100644 --- a/src/Mod/Part/Gui/CrossSections.cpp +++ b/src/Mod/Part/Gui/CrossSections.cpp @@ -38,7 +38,8 @@ # include # include #endif - +#include +#include #include #include #include @@ -46,8 +47,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/Part/Gui/DlgPrimitives.cpp b/src/Mod/Part/Gui/DlgPrimitives.cpp index 0d6d1c525a..9ac0dc2d86 100644 --- a/src/Mod/Part/Gui/DlgPrimitives.cpp +++ b/src/Mod/Part/Gui/DlgPrimitives.cpp @@ -33,7 +33,8 @@ #include #include #endif - +#include +#include #include #include #include @@ -43,8 +44,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp b/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp index 4d0704f981..48dbec94ce 100644 --- a/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp +++ b/src/Mod/Part/Gui/DlgProjectionOnSurface.cpp @@ -42,12 +42,11 @@ # include # include #endif - +#include +#include #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/Part/Gui/SectionCutting.cpp b/src/Mod/Part/Gui/SectionCutting.cpp index ddf2c15b7d..8fa4a41534 100644 --- a/src/Mod/Part/Gui/SectionCutting.cpp +++ b/src/Mod/Part/Gui/SectionCutting.cpp @@ -38,7 +38,8 @@ # include # include #endif - +#include +#include #include #include #include @@ -50,8 +51,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/Part/Gui/TaskDimension.cpp b/src/Mod/Part/Gui/TaskDimension.cpp index a733465e24..b916f05168 100644 --- a/src/Mod/Part/Gui/TaskDimension.cpp +++ b/src/Mod/Part/Gui/TaskDimension.cpp @@ -62,7 +62,8 @@ # include # include #endif - +#include +#include #include #include #include @@ -72,8 +73,6 @@ #include #include #include -#include -#include #include #include "TaskDimension.h" diff --git a/src/Mod/Part/Gui/TaskFaceColors.cpp b/src/Mod/Part/Gui/TaskFaceColors.cpp index 0b088f898a..84a71e1740 100644 --- a/src/Mod/Part/Gui/TaskFaceColors.cpp +++ b/src/Mod/Part/Gui/TaskFaceColors.cpp @@ -42,7 +42,8 @@ # include # include #endif - +#include +#include #include #include #include @@ -51,8 +52,6 @@ #include #include #include -#include -#include #include "TaskFaceColors.h" #include "ui_TaskFaceColors.h" diff --git a/src/Mod/Part/Gui/ViewProviderGridExtension.cpp b/src/Mod/Part/Gui/ViewProviderGridExtension.cpp index ed298adff3..fed8af47ae 100644 --- a/src/Mod/Part/Gui/ViewProviderGridExtension.cpp +++ b/src/Mod/Part/Gui/ViewProviderGridExtension.cpp @@ -38,6 +38,9 @@ # include #endif +#include +#include + #include #include #include @@ -45,8 +48,7 @@ #include #include #include -#include -#include + #include #include diff --git a/src/Mod/PartDesign/Gui/ViewProviderBody.cpp b/src/Mod/PartDesign/Gui/ViewProviderBody.cpp index 19313c0003..ed06ec5b4d 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderBody.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderBody.cpp @@ -29,7 +29,8 @@ # include # include #endif - +#include +#include #include #include #include @@ -39,8 +40,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp b/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp index 7c84e38206..2d0e2fda58 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderDatum.cpp @@ -40,14 +40,13 @@ # include # include #endif - +#include +#include #include #include #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/Path/Gui/AppPathGui.cpp b/src/Mod/Path/Gui/AppPathGui.cpp index 8b3c0641c2..2f5699c46f 100644 --- a/src/Mod/Path/Gui/AppPathGui.cpp +++ b/src/Mod/Path/Gui/AppPathGui.cpp @@ -25,7 +25,7 @@ #include #include #include -#include + #include #include @@ -34,6 +34,7 @@ #include "ViewProviderPath.h" #include "ViewProviderPathCompound.h" #include "ViewProviderPathShape.h" +#include // use a different name to CreateCommand() diff --git a/src/Mod/Points/Gui/Command.cpp b/src/Mod/Points/Gui/Command.cpp index 07e2a3ba3b..e57985c32c 100644 --- a/src/Mod/Points/Gui/Command.cpp +++ b/src/Mod/Points/Gui/Command.cpp @@ -26,6 +26,8 @@ #include #include #endif +#include +#include #include #include @@ -39,8 +41,7 @@ #include #include #include -#include -#include + #include #include diff --git a/src/Mod/Points/Gui/ViewProvider.cpp b/src/Mod/Points/Gui/ViewProvider.cpp index 4f6fc004e6..c45d252562 100644 --- a/src/Mod/Points/Gui/ViewProvider.cpp +++ b/src/Mod/Points/Gui/ViewProvider.cpp @@ -36,13 +36,14 @@ #include #include #endif +#include #include #include #include #include #include -#include + #include #include diff --git a/src/Mod/Sandbox/Gui/AppSandboxGui.cpp b/src/Mod/Sandbox/Gui/AppSandboxGui.cpp index 14664b6ae9..b2ce5434fa 100644 --- a/src/Mod/Sandbox/Gui/AppSandboxGui.cpp +++ b/src/Mod/Sandbox/Gui/AppSandboxGui.cpp @@ -30,7 +30,8 @@ # include # include #endif - +#include +#include #include #include #include @@ -42,8 +43,6 @@ #include #include #include -#include -#include #include #ifdef HAVE_PART #include diff --git a/src/Mod/Sandbox/Gui/Command.cpp b/src/Mod/Sandbox/Gui/Command.cpp index 5709af9019..6775130893 100644 --- a/src/Mod/Sandbox/Gui/Command.cpp +++ b/src/Mod/Sandbox/Gui/Command.cpp @@ -58,7 +58,9 @@ # include # include #endif - +#include +#include +#include #include #include #include @@ -68,9 +70,6 @@ #include #include #include -#include -#include -#include #include #include diff --git a/src/Mod/Sandbox/Gui/Overlay.cpp b/src/Mod/Sandbox/Gui/Overlay.cpp index 61ca950f4d..eb3c269dc8 100644 --- a/src/Mod/Sandbox/Gui/Overlay.cpp +++ b/src/Mod/Sandbox/Gui/Overlay.cpp @@ -29,6 +29,8 @@ # include # include #endif +#include +#include #include @@ -36,9 +38,7 @@ #include #include #include -#include -#include - +#include #include "Overlay.h" @@ -435,9 +435,6 @@ void paintSelection() } // --------------------------------------- -#include -#include -#include #if 0 void MeshSelection::prepareFreehandSelection(bool add) { diff --git a/src/Mod/Sandbox/Gui/PreCompiled.h b/src/Mod/Sandbox/Gui/PreCompiled.h index f8a4715690..7f913bc123 100644 --- a/src/Mod/Sandbox/Gui/PreCompiled.h +++ b/src/Mod/Sandbox/Gui/PreCompiled.h @@ -26,6 +26,10 @@ #include +#ifdef FC_OS_WIN32 +# include +#endif + // Importing of App classes #ifdef FC_OS_WIN32 # define SandboxAppExport __declspec(dllimport) @@ -62,10 +66,6 @@ // Xerces #include -#ifdef FC_OS_WIN32 -# include -#endif - // Qt Toolkit #include #include diff --git a/src/Mod/Sketcher/Gui/AppSketcherGui.cpp b/src/Mod/Sketcher/Gui/AppSketcherGui.cpp index 2d416d37dc..7c9e8085a5 100644 --- a/src/Mod/Sketcher/Gui/AppSketcherGui.cpp +++ b/src/Mod/Sketcher/Gui/AppSketcherGui.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" +#include "ViewProviderSketch.h" #include #include #include @@ -34,7 +35,7 @@ #include "SketcherSettings.h" #include "SoZoomTranslation.h" #include "ViewProviderPython.h" -#include "ViewProviderSketch.h" + #include "ViewProviderSketchGeometryExtension.h" #include "ViewProviderSketchGeometryExtensionPy.h" #include "Workbench.h" diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index bbb90b79ed..b362b14dab 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -29,6 +29,11 @@ #include #endif +// clang-format off +#include +#include +// clang-format on + #include #include #include @@ -37,8 +42,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp index 402341ba59..12adc95424 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp +++ b/src/Mod/Sketcher/Gui/DrawSketchHandler.cpp @@ -28,14 +28,17 @@ #include #endif // #ifndef _PreComp_ +// clang-format off +#include +#include +// clang-format on + #include #include #include #include #include #include -#include -#include #include #include "CommandConstraints.h" diff --git a/src/Mod/Sketcher/Gui/EditDatumDialog.cpp b/src/Mod/Sketcher/Gui/EditDatumDialog.cpp index 3ae6def1f1..7f7be469ef 100644 --- a/src/Mod/Sketcher/Gui/EditDatumDialog.cpp +++ b/src/Mod/Sketcher/Gui/EditDatumDialog.cpp @@ -30,14 +30,17 @@ #include #endif +// clang-format off +#include +#include +// clang-format on + #include #include #include #include #include #include -#include -#include #include #include diff --git a/src/Mod/Sketcher/Gui/PropertyVisualLayerList.cpp b/src/Mod/Sketcher/Gui/PropertyVisualLayerList.cpp index 2f35d2b9f2..162e5d56e8 100644 --- a/src/Mod/Sketcher/Gui/PropertyVisualLayerList.cpp +++ b/src/Mod/Sketcher/Gui/PropertyVisualLayerList.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #include +#include #include #include #include @@ -91,6 +92,36 @@ void PropertyVisualLayerList::Restore(Base::XMLReader& reader) setValues(std::move(layers)); } +void PropertyVisualLayerList::Restore(Base::DocumentReader& reader, + XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* containerEl) +{ + auto Prop_VisualLayerListDOM = + reader.FindElementByField(containerEl, "Property", "name", "VisualLayerList"); + if (Prop_VisualLayerListDOM) { + auto VisualLayerListDOM = reader.FindElement(Prop_VisualLayerListDOM, "VisualLayerList"); + const char* count_cstr = reader.GetAttribute(VisualLayerListDOM, "count"); + if (count_cstr) { + int count = reader.ContentToInt(count_cstr); + std::vector layers; + layers.reserve(count); + + auto prev_VisualLayerDOM = reader.FindElement(VisualLayerListDOM, "VisualLayer"); + VisualLayer visualLayer; + visualLayer.Restore(reader, prev_VisualLayerDOM); + layers.push_back(std::move(visualLayer)); + for (int i = 1; i < count; i++) { + auto VisualLayerDOM_i = reader.FindNextElement(prev_VisualLayerDOM, "VisualLayer"); + VisualLayer visualLayer; + visualLayer.Restore(reader, VisualLayerDOM_i); + layers.push_back(std::move(visualLayer)); + prev_VisualLayerDOM = VisualLayerDOM_i; + } + + setValues(std::move(layers)); + } + } +} + Property* PropertyVisualLayerList::Copy() const { PropertyVisualLayerList* p = new PropertyVisualLayerList(); diff --git a/src/Mod/Sketcher/Gui/PropertyVisualLayerList.h b/src/Mod/Sketcher/Gui/PropertyVisualLayerList.h index 23a3bd631a..ed4cd1c47d 100644 --- a/src/Mod/Sketcher/Gui/PropertyVisualLayerList.h +++ b/src/Mod/Sketcher/Gui/PropertyVisualLayerList.h @@ -61,6 +61,8 @@ public: void Save(Base::Writer& writer) const override; void Restore(Base::XMLReader& reader) override; + void Restore(Base::DocumentReader& reader, + XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* containerEl) override; Property* Copy() const override; void Paste(const Property& from) override; diff --git a/src/Mod/Sketcher/Gui/TaskDlgEditSketch.cpp b/src/Mod/Sketcher/Gui/TaskDlgEditSketch.cpp index 9a7627b88f..1aab1cb96f 100644 --- a/src/Mod/Sketcher/Gui/TaskDlgEditSketch.cpp +++ b/src/Mod/Sketcher/Gui/TaskDlgEditSketch.cpp @@ -21,13 +21,11 @@ ***************************************************************************/ #include "PreCompiled.h" - -#include - -#include "TaskDlgEditSketch.h" +// clang-format off #include "ViewProviderSketch.h" - - +#include +#include "TaskDlgEditSketch.h" +// clang-format on using namespace SketcherGui; //************************************************************************** diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 0c438d2c18..120e1e5afa 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -39,6 +39,11 @@ #include #endif +// clang-format off +#include +#include +// clang-format on + #include #include #include @@ -52,8 +57,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index 2886064eb2..820078bac0 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -29,10 +29,12 @@ #include #include +#include + #include #include #include -#include + #include #include #include diff --git a/src/Mod/Sketcher/Gui/VisualLayer.cpp b/src/Mod/Sketcher/Gui/VisualLayer.cpp index f44acb4719..f2f3a3cd9b 100644 --- a/src/Mod/Sketcher/Gui/VisualLayer.cpp +++ b/src/Mod/Sketcher/Gui/VisualLayer.cpp @@ -22,6 +22,8 @@ #include "PreCompiled.h" +#include +#include #include #include @@ -86,3 +88,20 @@ void VisualLayer::Restore(Base::XMLReader& reader) linePattern = reader.getAttributeAsUnsigned("linePattern"); lineWidth = reader.getAttributeAsFloat("lineWidth"); } + +void VisualLayer::Restore(Base::DocumentReader& reader, + XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* ContainerDOM) +{ + const char* visible_cstr = reader.GetAttribute(ContainerDOM, "visible"); + if (visible_cstr) { + std::string str = visible_cstr; + visible = (str == "true"); + + const char* linePattern_cstr = reader.GetAttribute(ContainerDOM, "linePattern"); + const char* lineWidth_cstr = reader.GetAttribute(ContainerDOM, "lineWidth"); + if (linePattern_cstr && lineWidth_cstr) { + linePattern = reader.ContentToUnsigned(linePattern_cstr); + lineWidth = reader.ContentToUnsigned(lineWidth_cstr); + } + } +} diff --git a/src/Mod/Sketcher/Gui/VisualLayer.h b/src/Mod/Sketcher/Gui/VisualLayer.h index 2a609bfd9f..dad9b0129f 100644 --- a/src/Mod/Sketcher/Gui/VisualLayer.h +++ b/src/Mod/Sketcher/Gui/VisualLayer.h @@ -52,6 +52,8 @@ public: void Save(Base::Writer& /*writer*/) const; void Restore(Base::XMLReader& /*reader*/); + void Restore(Base::DocumentReader& reader, + XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* containerEl); private: unsigned int linePattern; diff --git a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp index 4d815e7c15..4a85a159b5 100644 --- a/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp +++ b/src/Mod/Spreadsheet/Gui/ViewProviderSpreadsheet.cpp @@ -29,11 +29,12 @@ #include #endif +#include + #include #include #include #include -#include #include #include "SpreadsheetView.h" diff --git a/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp b/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp index 83d6e0c79b..404a42629f 100644 --- a/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp +++ b/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp @@ -35,7 +35,8 @@ # include # include #endif - +#include +#include #include #include #include @@ -50,8 +51,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/src/Mod/TechDraw/Gui/Grabber3d.cpp b/src/Mod/TechDraw/Gui/Grabber3d.cpp index 85c8139352..07a8463e8a 100644 --- a/src/Mod/TechDraw/Gui/Grabber3d.cpp +++ b/src/Mod/TechDraw/Gui/Grabber3d.cpp @@ -21,12 +21,11 @@ ***************************************************************************/ #include "PreCompiled.h" - +#include +#include #include #include #include -#include -#include #include "Grabber3d.h" diff --git a/src/Mod/TechDraw/Gui/QGVPage.cpp b/src/Mod/TechDraw/Gui/QGVPage.cpp index 3869bea238..5c5b05d449 100644 --- a/src/Mod/TechDraw/Gui/QGVPage.cpp +++ b/src/Mod/TechDraw/Gui/QGVPage.cpp @@ -34,7 +34,8 @@ #include #include #endif - +#include +#include #include #include #include @@ -42,8 +43,6 @@ #include #include #include -#include -#include #include #include diff --git a/src/Mod/TechDraw/Gui/TaskActiveView.cpp b/src/Mod/TechDraw/Gui/TaskActiveView.cpp index bcd2c7b657..c97ad31027 100644 --- a/src/Mod/TechDraw/Gui/TaskActiveView.cpp +++ b/src/Mod/TechDraw/Gui/TaskActiveView.cpp @@ -27,6 +27,8 @@ # include # include #endif // #ifndef _PreComp_ +#include +#include #include #include @@ -36,8 +38,7 @@ #include #include #include -#include -#include + #include #include diff --git a/src/Mod/TechDraw/Gui/TaskProjection.cpp b/src/Mod/TechDraw/Gui/TaskProjection.cpp index 9c2e2aa227..87a011d80c 100644 --- a/src/Mod/TechDraw/Gui/TaskProjection.cpp +++ b/src/Mod/TechDraw/Gui/TaskProjection.cpp @@ -26,15 +26,14 @@ #ifndef _PreComp_ # include #endif - +#include +#include #include #include #include #include #include #include -#include -#include #include #include "TaskProjection.h" diff --git a/src/Tools/_TEMPLATE_/Gui/PreCompiled.h b/src/Tools/_TEMPLATE_/Gui/PreCompiled.h index 46cef8ca92..d1550781f4 100644 --- a/src/Tools/_TEMPLATE_/Gui/PreCompiled.h +++ b/src/Tools/_TEMPLATE_/Gui/PreCompiled.h @@ -26,6 +26,10 @@ #include +#ifdef FC_OS_WIN32 +#include +#endif + // Importing of App classes #ifdef FC_OS_WIN32 #define _TEMPLATE_AppExport __declspec(dllimport) @@ -56,9 +60,6 @@ // Xerces #include -#ifdef FC_OS_WIN32 -#include -#endif // Qt Toolkit #ifndef __QtAll__