Implementing agnostic version of ParameterGrp for reading XML, replacing XMLReader from src/Base/reader.cpp with new class DocumentReader
This commit is contained in:
@@ -273,6 +273,7 @@ public:
|
||||
//@{
|
||||
virtual void extensionSave(Base::Writer&) const {}
|
||||
virtual void extensionRestore(Base::XMLReader&) {}
|
||||
virtual void extensionRestore(Base::DocumentReader&) {}
|
||||
//@}
|
||||
|
||||
/** @name TypeHandling */
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "Extension.h"
|
||||
#include "ExtensionContainer.h"
|
||||
#include <Base/DocumentReader.h>
|
||||
|
||||
|
||||
using namespace App;
|
||||
@@ -307,6 +308,18 @@ void ExtensionContainer::Restore(Base::XMLReader& reader) {
|
||||
App::PropertyContainer::Restore(reader);
|
||||
}
|
||||
|
||||
void ExtensionContainer::Restore(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *viewProviderEl) {
|
||||
//restore dynamic extensions.
|
||||
//Note 1: The extension element must be read first, before all other object elements. That is
|
||||
// needed as the element works together with an object element attribute, which would be
|
||||
// cleared if another attribute is read first
|
||||
//Note 2: This must happen before the py object of this container is used, as only in the
|
||||
// pyobject constructor the extension methods are added to the container.
|
||||
restoreExtensions(reader,viewProviderEl);
|
||||
//TODO NOW:
|
||||
//App::PropertyContainer::Restore(reader);
|
||||
}
|
||||
|
||||
void ExtensionContainer::saveExtensions(Base::Writer& writer) const {
|
||||
|
||||
//we don't save anything if there are no dynamic extensions
|
||||
@@ -352,6 +365,70 @@ void ExtensionContainer::saveExtensions(Base::Writer& writer) const {
|
||||
writer.decInd();
|
||||
}
|
||||
|
||||
void ExtensionContainer::restoreExtensions(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *viewProviderEl) {
|
||||
//Dynamic extensions are optional (also because they are introduced late into the document format)
|
||||
//and hence it is possible that the element does not exist. As we cannot check for the existence of
|
||||
//an element a object attribute is set if extensions are available. Here we check that
|
||||
//attribute, and only if it exists the extensions element will be available.
|
||||
const char* expanded_cstr = reader.GetAttribute(viewProviderEl,"expanded");
|
||||
if(!expanded_cstr)
|
||||
return;
|
||||
auto ExtensionsDOM = reader.FindElement(viewProviderEl,"Extensions");
|
||||
if(ExtensionsDOM){
|
||||
const char* cnt_cstr = reader.GetAttribute(ExtensionsDOM,"Count");
|
||||
if(cnt_cstr){
|
||||
long Cnt = reader.ContentToInt( cnt_cstr );
|
||||
for (int i=0 ;i<Cnt ;i++) {
|
||||
auto ExtensionDOM_i = reader.FindElement(ExtensionsDOM,"Extension");
|
||||
const char* type_cstr = reader.GetAttribute(ExtensionDOM_i,"type");
|
||||
const char* name_cstr = reader.GetAttribute(ExtensionDOM_i,"name");
|
||||
try {
|
||||
App::Extension* ext = getExtension(name_cstr);
|
||||
if(!ext) {
|
||||
//get the extension type asked for
|
||||
Base::Type extension = Base::Type::fromName(type_cstr);
|
||||
if (extension.isBad() || !extension.isDerivedFrom(App::Extension::getExtensionClassTypeId())) {
|
||||
std::stringstream str;
|
||||
str << "No extension found of type '" << type_cstr << "'" << std::ends;
|
||||
throw Base::TypeError(str.str());
|
||||
}
|
||||
|
||||
//register the extension
|
||||
ext = static_cast<App::Extension*>(extension.createInstance());
|
||||
//check if this really is a python extension!
|
||||
if (!ext->isPythonExtension()) {
|
||||
delete ext;
|
||||
std::stringstream str;
|
||||
str << "Extension is not a python addable version: '" << type_cstr << "'" << std::ends;
|
||||
throw Base::TypeError(str.str());
|
||||
}
|
||||
ext->initExtension(this);
|
||||
if( strcmp(ext->getExtensionTypeId().getName(), type_cstr) == 0 )
|
||||
ext->extensionRestore(reader);
|
||||
}
|
||||
}
|
||||
catch (const Base::XMLParseException&) {
|
||||
throw; // re-throw
|
||||
}
|
||||
catch (const Base::Exception &e) {
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
}
|
||||
catch (const char* e) {
|
||||
Base::Console().Error("%s\n", e);
|
||||
}
|
||||
#ifndef FC_DEBUG
|
||||
catch (...) {
|
||||
Base::Console().Error("ExtensionContainer::Restore: Unknown C++ exception thrown\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionContainer::restoreExtensions(Base::XMLReader& reader) {
|
||||
|
||||
//Dynamic extensions are optional (also because they are introduced late into the document format)
|
||||
|
||||
@@ -25,6 +25,14 @@
|
||||
#define APP_EXTENSIONCONTAINER_H
|
||||
|
||||
#include "PropertyContainer.h"
|
||||
#include <xercesc/util/XercesDefs.hpp>
|
||||
|
||||
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 *viewProviderEl);
|
||||
|
||||
//those methods save/restore the dynamic extensions without handling properties, which is something
|
||||
//done by the default Save/Restore methods.
|
||||
void saveExtensions(Base::Writer& writer) const;
|
||||
void restoreExtensions(Base::XMLReader& reader);
|
||||
void restoreExtensions(Base::DocumentReader& reader,XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *viewProviderEl);
|
||||
|
||||
/** 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.
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "Property.h"
|
||||
#include "PropertyContainer.h"
|
||||
#include <Base/DocumentReader.h>
|
||||
|
||||
|
||||
FC_LOG_LEVEL_INIT("App",true,true)
|
||||
@@ -402,6 +403,103 @@ void PropertyContainer::Restore(Base::XMLReader &reader)
|
||||
reader.readEndElement("Properties");
|
||||
}
|
||||
|
||||
void PropertyContainer::Restore(Base::DocumentReader &reader)
|
||||
{
|
||||
//TODO NOW
|
||||
Base::Console().Error("PropertyContainer::Restore: DocumentReader\n");
|
||||
reader.clearPartialRestoreProperty();
|
||||
/*
|
||||
reader.clearPartialRestoreProperty();
|
||||
reader.readElement("Properties");
|
||||
int Cnt = reader.getAttributeAsInteger("Count");
|
||||
|
||||
int transientCount = 0;
|
||||
if(reader.hasAttribute("TransientCount"))
|
||||
transientCount = reader.getAttributeAsUnsigned("TransientCount");
|
||||
|
||||
for (int i=0;i<transientCount; ++i) {
|
||||
reader.readElement("_Property");
|
||||
Property* prop = getPropertyByName(reader.getAttribute("name"));
|
||||
if(prop)
|
||||
FC_TRACE("restore transient '" << prop->getName() << "'");
|
||||
if(prop && reader.hasAttribute("status"))
|
||||
prop->setStatusValue(reader.getAttributeAsUnsigned("status"));
|
||||
}
|
||||
|
||||
for (int i=0 ;i<Cnt ;i++) {
|
||||
reader.readElement("Property");
|
||||
std::string PropName = reader.getAttribute("name");
|
||||
std::string TypeName = reader.getAttribute("type");
|
||||
// NOTE: We must also check the type of the current property because a
|
||||
// subclass of PropertyContainer might change the type of a property but
|
||||
// not its name. In this case we would force to read-in a wrong property
|
||||
// type and the behaviour would be undefined.
|
||||
try {
|
||||
auto prop = getPropertyByName(PropName.c_str());
|
||||
if(!prop || prop->getContainer() != this)
|
||||
prop = dynamicProps.restore(*this,PropName.c_str(),TypeName.c_str(),reader);
|
||||
|
||||
decltype(Property::StatusBits) status;
|
||||
if(reader.hasAttribute("status")) {
|
||||
status = decltype(status)(reader.getAttributeAsUnsigned("status"));
|
||||
if(prop)
|
||||
prop->setStatusValue(status.to_ulong());
|
||||
}
|
||||
// name and type match
|
||||
if (prop && strcmp(prop->getTypeId().getName(), TypeName.c_str()) == 0) {
|
||||
if (!prop->testStatus(Property::Transient)
|
||||
&& !status.test(Property::Transient)
|
||||
&& !status.test(Property::PropTransient)
|
||||
&& !prop->testStatus(Property::PropTransient))
|
||||
{
|
||||
FC_TRACE("restore property '" << prop->getName() << "'");
|
||||
prop->Restore(reader);
|
||||
}else
|
||||
FC_TRACE("skip transient '" << prop->getName() << "'");
|
||||
}
|
||||
// name matches but not the type
|
||||
else if (prop) {
|
||||
handleChangedPropertyType(reader, TypeName.c_str(), prop);
|
||||
}
|
||||
// name doesn't match, the sub-class then has to know
|
||||
// if the property has been renamed or removed
|
||||
else {
|
||||
handleChangedPropertyName(reader, TypeName.c_str(), PropName.c_str());
|
||||
}
|
||||
|
||||
if (reader.testStatus(Base::XMLReader::ReaderStatus::PartialRestoreInProperty)) {
|
||||
Base::Console().Error("Property %s of type %s was subject to a partial restore.\n",PropName.c_str(),TypeName.c_str());
|
||||
reader.clearPartialRestoreProperty();
|
||||
}
|
||||
}
|
||||
catch (const Base::XMLParseException&) {
|
||||
throw; // re-throw
|
||||
}
|
||||
catch (const Base::RestoreError &) {
|
||||
reader.setPartialRestore(true);
|
||||
reader.clearPartialRestoreProperty();
|
||||
Base::Console().Error("Property %s of type %s was subject to a partial restore.\n",PropName.c_str(),TypeName.c_str());
|
||||
}
|
||||
catch (const Base::Exception &e) {
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
}
|
||||
catch (const char* e) {
|
||||
Base::Console().Error("%s\n", e);
|
||||
}
|
||||
#ifndef FC_DEBUG
|
||||
catch (...) {
|
||||
Base::Console().Error("PropertyContainer::Restore: Unknown C++ exception thrown\n");
|
||||
}
|
||||
#endif
|
||||
reader.readEndElement("Property");
|
||||
}
|
||||
reader.readEndElement("Properties");
|
||||
*/
|
||||
}
|
||||
|
||||
void PropertyContainer::onPropertyStatusChanged(const Property &prop, unsigned long oldStatus)
|
||||
{
|
||||
(void)prop;
|
||||
|
||||
@@ -220,6 +220,7 @@ public:
|
||||
|
||||
void Save (Base::Writer &writer) const override;
|
||||
void Restore(Base::XMLReader &reader) override;
|
||||
void Restore(Base::DocumentReader &reader) override;
|
||||
|
||||
virtual void editProperty(const char * /*propName*/) {}
|
||||
|
||||
|
||||
@@ -267,6 +267,7 @@ SET(FreeCADBase_CPP_SRCS
|
||||
Writer.cpp
|
||||
XMLTools.cpp
|
||||
ZipHeader.cpp
|
||||
DocumentReader.cpp
|
||||
)
|
||||
|
||||
SET(SWIG_HEADERS
|
||||
|
||||
314
src/Base/DocumentReader.cpp
Normal file
314
src/Base/DocumentReader.cpp
Normal file
@@ -0,0 +1,314 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* *
|
||||
* 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 <locale>
|
||||
|
||||
#include "DocumentReader.h"
|
||||
|
||||
//#include "Reader.h"
|
||||
//#include "Base64.h"
|
||||
//#include "Console.h"
|
||||
#include "InputSource.h"
|
||||
//#include "Persistence.h"
|
||||
//#include "Sequencer.h"
|
||||
//#include "Stream.h"
|
||||
#include "XMLTools.h"
|
||||
//#ifdef _MSC_VER
|
||||
//#include <zipios++/zipios-config.h>
|
||||
//#endif
|
||||
//#include <zipios++/zipinputstream.h>
|
||||
|
||||
#include <Base/Reader.h>
|
||||
#include <Base/Parameter.h>
|
||||
#ifndef _PreComp_
|
||||
//# include <cassert>
|
||||
//# include <memory>
|
||||
# include <xercesc/dom/DOM.hpp>
|
||||
//# include <xercesc/framework/LocalFileFormatTarget.hpp>
|
||||
//# include <xercesc/framework/LocalFileInputSource.hpp>
|
||||
//# include <xercesc/framework/MemBufFormatTarget.hpp>
|
||||
//# include <xercesc/framework/MemBufInputSource.hpp>
|
||||
# include <xercesc/parsers/XercesDOMParser.hpp>
|
||||
//# include <xercesc/sax/ErrorHandler.hpp>
|
||||
//# include <xercesc/sax/SAXParseException.hpp>
|
||||
//# include <sstream>
|
||||
//# include <string>
|
||||
//# include <utility>
|
||||
#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;
|
||||
|
||||
/*
|
||||
gOutputEncoding = nullptr;
|
||||
gMyEOLSequence = nullptr;
|
||||
|
||||
gSplitCdataSections = true;
|
||||
gDiscardDefaultContent = true;
|
||||
gUseFilter = true;
|
||||
gFormatPrettyPrint = true;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
//DocumentReader::~DocumentReader()
|
||||
//{
|
||||
//delete parser;
|
||||
//}
|
||||
//int DocumentReader::LoadDocument(const XERCES_CPP_NAMESPACE_QUALIFIER InputSource& inputSource)
|
||||
//int DocumentReader::LoadDocument(std::istream& Stream,std::string filename)
|
||||
int DocumentReader::LoadDocument(Base::Reader& reader)
|
||||
{
|
||||
FileInfo _File( reader.getFileName() );
|
||||
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())) {
|
||||
if (clChild->getAttributes()->getLength() > 0) {
|
||||
return static_cast<DOMElement*>(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<DOMElement*>(clChild);
|
||||
//if (clChild->getAttributes()->getLength() > 0) {
|
||||
//return static_cast<DOMElement*>(clChild);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DocumentReader::FindNextElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *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<DOMElement*>(clChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
//CONTENT:
|
||||
const char * DocumentReader::GetContent(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DOMEl) const
|
||||
{
|
||||
if (!DOMEl)
|
||||
return nullptr;
|
||||
return StrX(DOMEl->getAttribute(XStr("Value").unicodeForm())).c_str();
|
||||
}
|
||||
|
||||
std::string DocumentReader::GetContentASCII(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *DOMEl) const
|
||||
{
|
||||
//return std::string(StrXUTF8(pcElem->getNodeValue()).c_str() );
|
||||
//maybe its better to use getNodeValue()
|
||||
if (!DOMEl)
|
||||
return nullptr;
|
||||
return std::string( StrXUTF8(DOMEl->getAttribute(XStr("Value").unicodeForm())).c_str() );
|
||||
}
|
||||
*/
|
||||
|
||||
long DocumentReader::ContentToInt( const char* content ) const
|
||||
{
|
||||
return atol( content );
|
||||
}
|
||||
|
||||
unsigned long DocumentReader::ContentToUnsigned(const char* content) const
|
||||
{
|
||||
return strtoul(content,nullptr,10);
|
||||
}
|
||||
|
||||
double DocumentReader::ContentToFloat(const char* content) const
|
||||
{
|
||||
return atof(content);
|
||||
}
|
||||
|
||||
bool DocumentReader::ContentToBool(const char* content) const
|
||||
{
|
||||
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() );
|
||||
//stringLen
|
||||
return strdup( StrX( attr ).c_str() );//strdup is needed since pointer from strx only exists in context where StrX() is created.
|
||||
}
|
||||
|
||||
/*
|
||||
unsigned int Base::XMLReader::getAttributeCount() const
|
||||
{
|
||||
return static_cast<unsigned int>(AttrMap.size());
|
||||
}
|
||||
*/
|
||||
|
||||
//Status
|
||||
|
||||
void Base::DocumentReader::clearPartialRestoreProperty()
|
||||
{
|
||||
setStatus(PartialRestoreInProperty, false);
|
||||
setStatus(PartialRestoreInObject, false);
|
||||
}
|
||||
|
||||
bool Base::DocumentReader::testStatus(ReaderStatus pos) const
|
||||
{
|
||||
return StatusBits.test(static_cast<size_t>(pos));
|
||||
}
|
||||
|
||||
void Base::DocumentReader::setStatus(ReaderStatus pos, bool on)
|
||||
{
|
||||
StatusBits.set(static_cast<size_t>(pos), on);
|
||||
}
|
||||
|
||||
|
||||
98
src/Base/DocumentReader.h
Normal file
98
src/Base/DocumentReader.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
|
||||
* *
|
||||
* 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 <bitset>
|
||||
#include <map>
|
||||
//#include <memory>
|
||||
//#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//#include <xercesc/framework/XMLPScanToken.hpp>
|
||||
//#include <xercesc/sax2/Attributes.hpp>
|
||||
//#include <xercesc/sax2/DefaultHandler.hpp>
|
||||
#include <xercesc/util/XercesDefs.hpp>
|
||||
//#include "FileInfo.h"//reemplazado por:
|
||||
#include <FCGlobal.h>
|
||||
//#include <Base/Parameter.h>
|
||||
|
||||
XERCES_CPP_NAMESPACE_BEGIN
|
||||
class DOMNode;
|
||||
class DOMElement;
|
||||
// class DefaultHandler;
|
||||
// class SAX2XMLReader;
|
||||
XERCES_CPP_NAMESPACE_END
|
||||
namespace Base
|
||||
{
|
||||
class Reader;
|
||||
class Persistence;
|
||||
|
||||
class BaseExport DocumentReader //: public ParameterManager
|
||||
{
|
||||
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 *FindNextElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *Prev, const char* Type) const;
|
||||
|
||||
long ContentToASCII(const char* Content) const;
|
||||
|
||||
long ContentToInt(const char* Content) const;
|
||||
unsigned long ContentToUnsigned(const char* Content) const;
|
||||
double ContentToFloat(const char* Content) const;
|
||||
bool ContentToBool(const char* Content) const;
|
||||
|
||||
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);
|
||||
|
||||
void clearPartialRestoreProperty();
|
||||
|
||||
protected:
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *_pGroupNode;
|
||||
bool gDoNamespaces ;
|
||||
bool gDoSchema ;
|
||||
bool gSchemaFullChecking ;
|
||||
bool gDoCreate ;
|
||||
std::bitset<32> StatusBits;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -75,43 +75,44 @@ using namespace Base;
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
|
||||
class DOMTreeErrorReporter : public ErrorHandler
|
||||
DOMTreeErrorReporter::DOMTreeErrorReporter():
|
||||
fSawErrors(false) {
|
||||
}
|
||||
|
||||
void DOMTreeErrorReporter::warning(const SAXParseException&)
|
||||
{
|
||||
public:
|
||||
// -----------------------------------------------------------------------
|
||||
// Constructors and Destructor
|
||||
// -----------------------------------------------------------------------
|
||||
DOMTreeErrorReporter() :
|
||||
fSawErrors(false) {
|
||||
}
|
||||
//
|
||||
// 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;
|
||||
};
|
||||
void DOMTreeErrorReporter::resetErrors()
|
||||
{
|
||||
// No-op in this case
|
||||
}
|
||||
|
||||
inline bool DOMTreeErrorReporter::getSawErrors() const
|
||||
{
|
||||
return fSawErrors;
|
||||
}
|
||||
|
||||
class DOMPrintFilter : public DOMLSSerializerFilter
|
||||
{
|
||||
@@ -157,14 +158,6 @@ private :
|
||||
void operator=(const DOMErrorHandler&);
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline bool DOMTreeErrorReporter::getSawErrors() const
|
||||
{
|
||||
return fSawErrors;
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
//**************************************************************************
|
||||
// ParameterManager
|
||||
@@ -1865,42 +1858,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
|
||||
|
||||
@@ -65,6 +65,10 @@ using PyObject = struct _object;
|
||||
# pragma warning( disable : 4275 )
|
||||
#endif
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <xercesc/sax/ErrorHandler.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
XERCES_CPP_NAMESPACE_BEGIN
|
||||
class DOMNode;
|
||||
@@ -279,6 +283,7 @@ protected:
|
||||
~ParameterGrp() override;
|
||||
/// helper function for GetGroup
|
||||
Base::Reference<ParameterGrp> _GetGroup(const char* Name);
|
||||
|
||||
bool ShouldRemove() const;
|
||||
|
||||
void _Reset();
|
||||
@@ -411,16 +416,17 @@ public:
|
||||
/// Saves an XML document by calling the serializer's save method.
|
||||
void SaveDocument() const;
|
||||
//@}
|
||||
|
||||
private:
|
||||
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *_pDocument;
|
||||
ParameterSerializer * paramSerializer;
|
||||
|
||||
bool gDoNamespaces ;
|
||||
|
||||
protected:
|
||||
bool gDoNamespaces ;
|
||||
bool gDoSchema ;
|
||||
bool gSchemaFullChecking ;
|
||||
bool gDoCreate ;
|
||||
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *_pDocument;
|
||||
private:
|
||||
ParameterManager();
|
||||
~ParameterManager() override;
|
||||
ParameterSerializer * paramSerializer;
|
||||
|
||||
|
||||
const XMLCh* gOutputEncoding ;
|
||||
@@ -431,11 +437,42 @@ private:
|
||||
bool gUseFilter ;
|
||||
bool gFormatPrettyPrint ;
|
||||
|
||||
private:
|
||||
ParameterManager();
|
||||
~ParameterManager() override;
|
||||
};
|
||||
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
|
||||
class DOMTreeErrorReporter : public ErrorHandler
|
||||
{
|
||||
public:
|
||||
// -----------------------------------------------------------------------
|
||||
// Constructors and Destructor
|
||||
// -----------------------------------------------------------------------
|
||||
DOMTreeErrorReporter();
|
||||
~DOMTreeErrorReporter() override = default;
|
||||
// -----------------------------------------------------------------------
|
||||
// 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<ParameterGrp> &hcParamGrp);
|
||||
|
||||
@@ -61,6 +61,12 @@ 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(XMLReader &/*reader*/)
|
||||
{
|
||||
// you have to implement this method in all descending classes!
|
||||
|
||||
@@ -31,6 +31,7 @@ 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 +78,7 @@ public:
|
||||
* \endcode
|
||||
*/
|
||||
virtual void Restore(XMLReader &/*reader*/) = 0;
|
||||
virtual void Restore(DocumentReader &/*reader*/);
|
||||
/** 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
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <xercesc/sax2/XMLReaderFactory.hpp>
|
||||
# include <xercesc/dom/DOM.hpp>
|
||||
#endif
|
||||
|
||||
#include <locale>
|
||||
@@ -42,7 +43,7 @@
|
||||
#include <zipios++/zipios-config.h>
|
||||
#endif
|
||||
#include <zipios++/zipinputstream.h>
|
||||
|
||||
#include <Gui/Document.h>
|
||||
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
|
||||
@@ -330,24 +331,11 @@ 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);
|
||||
|
||||
try{
|
||||
jt->Object->RestoreDocFile(reader);
|
||||
}catch (const Base::XMLParseException& e) {
|
||||
//For some reason catching this error in RestoreDocFile(reader) its working but
|
||||
//still need to catch it here again. Im not sure how its that possible since its from a constructor.
|
||||
|
||||
//It comes from trying to read "ProjectUnitSystem" from GuiDocument.xml and reaching EndDocument
|
||||
//because was not found.
|
||||
//I dont think EndDocument should throw error anyway.
|
||||
if(e.getMessage() != "End of document reached"){
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.getLocalReader())
|
||||
reader.getLocalReader()->readFiles(zipstream);
|
||||
Base::Reader reader(zipstream, jt->FileName, FileVersion);
|
||||
jt->Object->RestoreDocFile(reader);
|
||||
|
||||
if (reader.getLocalReader())
|
||||
reader.getLocalReader()->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
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
# include <QStatusBar>
|
||||
# include <Inventor/actions/SoSearchAction.h>
|
||||
# include <Inventor/nodes/SoSeparator.h>
|
||||
# include <xercesc/dom/DOM.hpp>
|
||||
#endif
|
||||
|
||||
#include <App/AutoTransaction.h>
|
||||
@@ -45,6 +46,7 @@
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Matrix.h>
|
||||
#include <Base/Reader.h>
|
||||
#include <Base/DocumentReader.h>
|
||||
#include <Base/Writer.h>
|
||||
#include <Base/Tools.h>
|
||||
|
||||
@@ -66,7 +68,6 @@
|
||||
#include "ViewProviderDocumentObjectGroup.h"
|
||||
#include "WaitCursor.h"
|
||||
|
||||
|
||||
FC_LOG_LEVEL_INIT("Gui", true, true)
|
||||
|
||||
using namespace Gui;
|
||||
@@ -680,7 +681,6 @@ void Document::slotNewObject(const App::DocumentObject& Obj)
|
||||
{
|
||||
auto pcProvider = static_cast<ViewProviderDocumentObject*>(getViewProvider(&Obj));
|
||||
if (!pcProvider) {
|
||||
//Base::Console().Log("Document::slotNewObject() called\n");
|
||||
std::string cName = Obj.getViewProviderNameStored();
|
||||
for(;;) {
|
||||
if (cName.empty()) {
|
||||
@@ -762,7 +762,6 @@ void Document::slotDeletedObject(const App::DocumentObject& Obj)
|
||||
{
|
||||
std::list<Gui::BaseView*>::iterator vIt;
|
||||
setModified(true);
|
||||
//Base::Console().Log("Document::slotDeleteObject() called\n");
|
||||
|
||||
// cycling to all views of the document
|
||||
ViewProvider* viewProvider = getViewProvider(&Obj);
|
||||
@@ -1415,88 +1414,134 @@ void Document::Restore(Base::XMLReader &reader)
|
||||
*/
|
||||
void Document::RestoreDocFile(Base::Reader &reader)
|
||||
{
|
||||
// We must create an XML parser to read from the input stream
|
||||
std::shared_ptr<Base::XMLReader> localreader = std::make_shared<Base::XMLReader>("GuiDocument.xml", reader);
|
||||
localreader->FileVersion = reader.getFileVersion();
|
||||
|
||||
localreader->readElement("Document");
|
||||
long scheme = localreader->getAttributeAsInteger("SchemaVersion");
|
||||
localreader->DocumentSchema = scheme;
|
||||
|
||||
bool hasExpansion = localreader->hasAttribute("HasExpansion");
|
||||
if(hasExpansion) {
|
||||
auto tree = TreeWidget::instance();
|
||||
Base::DocumentReader docReader;
|
||||
docReader.LoadDocument(reader);
|
||||
//docReader.GetRootElement()//can be used to get Document XMLElement, but not needed.
|
||||
const char* SchemaVersion_cstr = docReader.GetAttribute("SchemaVersion");
|
||||
long SchemaVersion = docReader.ContentToInt( SchemaVersion_cstr );
|
||||
|
||||
const char* HasExpansion_cstr = docReader.GetAttribute("HasExpansion");
|
||||
if(HasExpansion_cstr){
|
||||
auto tree = TreeWidget::instance();
|
||||
if(tree) {
|
||||
auto docItem = tree->getDocumentItem(this);
|
||||
if(docItem)
|
||||
docItem->Restore(*localreader);
|
||||
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.
|
||||
//
|
||||
// SchemeVersion "1"
|
||||
if (scheme == 1) {
|
||||
// read the viewproviders itself
|
||||
localreader->readElement("ViewProviderData");
|
||||
int Cnt = localreader->getAttributeAsInteger("Count");
|
||||
for (int i=0; i<Cnt; i++) {
|
||||
localreader->readElement("ViewProvider");
|
||||
std::string name = localreader->getAttribute("name");
|
||||
bool expanded = false;
|
||||
if (!hasExpansion && localreader->hasAttribute("expanded")) {
|
||||
const char* attr = localreader->getAttribute("expanded");
|
||||
if (strcmp(attr,"1") == 0) {
|
||||
expanded = true;
|
||||
}
|
||||
}
|
||||
ViewProvider* pObj = getViewProviderByName(name.c_str());
|
||||
if (pObj) // check if this feature has been registered
|
||||
pObj->Restore(*localreader);
|
||||
if (pObj && expanded) {
|
||||
auto vp = static_cast<Gui::ViewProviderDocumentObject*>(pObj);
|
||||
this->signalExpandObject(*vp, TreeItemMode::ExpandItem,0,0);
|
||||
}
|
||||
localreader->readEndElement("ViewProvider");
|
||||
}
|
||||
localreader->readEndElement("ViewProviderData");
|
||||
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<Gui::ViewProviderDocumentObject*>(pObj);
|
||||
this->signalExpandObject(*vp, TreeItemMode::ExpandItem,0,0);
|
||||
}
|
||||
}
|
||||
for (int i=1; i<Cnt; i++) {
|
||||
auto ViewProviderDOM_i = docReader.FindNextElement(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");
|
||||
|
||||
// read camera settings
|
||||
localreader->readElement("Camera");
|
||||
const char* ppReturn = localreader->getAttribute("settings");
|
||||
cameraSettings.clear();
|
||||
if(ppReturn && ppReturn[0]) {
|
||||
saveCameraSettings(ppReturn);
|
||||
try {
|
||||
const char** pReturnIgnore=nullptr;
|
||||
std::list<MDIView*> 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());
|
||||
}
|
||||
}
|
||||
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);//Im still implementing this, which calls ExtensionContainer::Restore.
|
||||
|
||||
if (pObj && expanded) {
|
||||
auto vp = static_cast<Gui::ViewProviderDocumentObject*>(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<MDIView*> 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try{
|
||||
localreader->readElement("ProjectUnitSystem");
|
||||
int US = localreader->getAttributeAsInteger("US");
|
||||
int ignore = localreader->getAttributeAsInteger("ignore");
|
||||
/*
|
||||
try{//if this fails then all other reading attemps will fail, since XERCES doesnt allow to get back to previous point, reading the file should restarted each time an element its not present, since it looks for it untill the end of the document.
|
||||
//Since ProjectUnitSystem its the only optional field, and its being read at the end of this function, it does not cause any issue, but if other optional its added the way of reading XML used in Reader.cpp will be obsolete
|
||||
|
||||
localreader->readElement("ProjectUnitSystem");
|
||||
Base::Console().Error("readElement(ProjectUnitSystem)\n");
|
||||
int US = localreader->getAttributeAsInteger("US");
|
||||
int ignore = localreader->getAttributeAsInteger("ignore");
|
||||
d->projectUnitSystem = US;
|
||||
d->projectUnitSystemIgnore = ignore;
|
||||
|
||||
}catch (const Base::XMLParseException& e) {
|
||||
Base::Console().Warning("ProjectUnitSystem not found: %s\n", e.getMessage().c_str());
|
||||
}
|
||||
}catch(const Base::XMLBaseException& e){
|
||||
Base::Console().Warning("ProjectUnitSystem XMLBaseException: %s\n", e.getMessage().c_str());
|
||||
}catch(...) {
|
||||
Base::Console().Error("ProjectUnitSystem catch(...)\n");
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
localreader->readEndElement("Document");
|
||||
|
||||
// reset modified flag
|
||||
reader.initLocalReader(localreader);
|
||||
setModified(false);
|
||||
/*
|
||||
|
||||
try{
|
||||
localreader->readEndElement("Document");
|
||||
}catch(const Base::XMLParseException& e){
|
||||
Base::Console().Warning("readEndElement(Document) XMLParseException: %s\n", e.getMessage().c_str());
|
||||
}catch(const Base::XMLBaseException& e){
|
||||
Base::Console().Warning("readEndElement(Document) XMLBaseException: %s\n", e.getMessage().c_str());
|
||||
}catch(...) {
|
||||
Base::Console().Error("readEndElement(Document) unkown error.\n");
|
||||
}
|
||||
*/
|
||||
|
||||
// reset modified flag
|
||||
//dont see what this does:
|
||||
//reader.initLocalReader(localreader);
|
||||
setModified(false);
|
||||
}
|
||||
|
||||
void Document::slotStartRestoreDocument(const App::Document& doc)
|
||||
|
||||
@@ -66,6 +66,10 @@
|
||||
#include "Widgets.h"
|
||||
#include "Workbench.h"
|
||||
|
||||
#include <Base/DocumentReader.h>
|
||||
#include <xercesc/util/XercesDefs.hpp>
|
||||
#include <xercesc/dom/DOM.hpp>
|
||||
|
||||
|
||||
FC_LOG_LEVEL_INIT("Tree", false, true, true)
|
||||
|
||||
@@ -348,6 +352,21 @@ public:
|
||||
}
|
||||
reader.readEndElement("Expand", level - 1);
|
||||
}
|
||||
|
||||
void restore(Base::DocumentReader& reader, XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *expandEl) {
|
||||
Base::Console().Error("ExpandInfo restore\n");
|
||||
const char* count_cstr = reader.GetAttribute(expandEl,"count");
|
||||
if(count_cstr){
|
||||
long count = reader.ContentToInt( count_cstr );
|
||||
Base::Console().Error("ExpandInfo count: %d\n",count);
|
||||
auto _expandEl = reader.FindElement(expandEl,"Expand");
|
||||
const char* name_cstr = reader.GetAttribute(_expandEl,"name");
|
||||
Base::Console().Error("ExpandInfo name_cstr: %s\n",name_cstr);
|
||||
auto& entry = (*this)[name_cstr];
|
||||
entry.reset(new ExpandInfo);
|
||||
entry->restore(reader,_expandEl);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -3927,6 +3946,24 @@ void DocumentItem::Restore(Base::XMLReader& reader) {
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentItem::Restore(Base::DocumentReader& reader) {
|
||||
Base::Console().Error("DocumentItem::Restore() DocumentReader\n");
|
||||
auto expandEl = reader.FindElement("Expand");
|
||||
if( !reader.GetAttribute(expandEl,"count") )
|
||||
return;
|
||||
_ExpandInfo.reset(new ExpandInfo);
|
||||
_ExpandInfo->restore(reader,expandEl);
|
||||
//TODO NOW
|
||||
for (auto inst : TreeWidget::Instances) {
|
||||
if (inst != getTree()) {
|
||||
auto docItem = inst->getDocumentItem(document());
|
||||
if (docItem)
|
||||
docItem->_ExpandInfo = _ExpandInfo;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentItem::restoreItemExpansion(const ExpandInfoPtr& info, DocumentObjectItem* item) {
|
||||
item->setExpanded(true);
|
||||
if (!info)
|
||||
|
||||
@@ -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<ExpandInfo>;
|
||||
|
||||
@@ -839,6 +839,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<Gui::ViewProviderExtension>();
|
||||
|
||||
@@ -498,6 +498,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);}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user