diff --git a/src/App/CMakeLists.txt b/src/App/CMakeLists.txt
index 238c89b2d..f95b73139 100644
--- a/src/App/CMakeLists.txt
+++ b/src/App/CMakeLists.txt
@@ -77,7 +77,8 @@ SET(Document_CPP_SRCS
Plane.cpp
Transactions.cpp
VRMLObject.cpp
- MaterialObject.cpp
+ MaterialObject.cpp
+ MergeDocuments.cpp
)
SET(Document_HPP_SRCS
@@ -99,7 +100,8 @@ SET(Document_HPP_SRCS
Plane.h
Transactions.h
VRMLObject.h
- MaterialObject.h
+ MaterialObject.h
+ MergeDocuments.h
)
SET(Document_SRCS
${Document_CPP_SRCS}
diff --git a/src/App/DocumentPy.xml b/src/App/DocumentPy.xml
index 3a11e634d..4eb38bfc5 100644
--- a/src/App/DocumentPy.xml
+++ b/src/App/DocumentPy.xml
@@ -33,6 +33,11 @@
Restore the document from disk
+
+
+ Merges this document with another project file
+
+
Export the dependencies of the objects as graph
diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp
index 8167c5493..e377eaf70 100644
--- a/src/App/DocumentPyImp.cpp
+++ b/src/App/DocumentPyImp.cpp
@@ -31,6 +31,7 @@
#include
#include "DocumentObject.h"
#include "DocumentObjectPy.h"
+#include "MergeDocuments.h"
// inclusion of the generated files (generated By DocumentPy.xml)
#include "DocumentPy.h"
@@ -135,6 +136,22 @@ PyObject* DocumentPy::restore(PyObject * args)
Py_Return;
}
+PyObject* DocumentPy::mergeProject(PyObject * args)
+{
+ char* filename;
+ if (!PyArg_ParseTuple(args, "s", &filename)) // convert args: Python->C
+ return NULL; // NULL triggers exception
+
+ PY_TRY {
+ Base::FileInfo fi(filename);
+ Base::ifstream str(fi, std::ios::in | std::ios::binary);
+ App::Document* doc = getDocumentPtr();
+ MergeDocuments md(doc);
+ md.importObjects(str);
+ Py_Return;
+ } PY_CATCH;
+}
+
PyObject* DocumentPy::exportGraphviz(PyObject * args)
{
char* fn=0;
diff --git a/src/App/MergeDocuments.cpp b/src/App/MergeDocuments.cpp
new file mode 100644
index 000000000..3f5198b29
--- /dev/null
+++ b/src/App/MergeDocuments.cpp
@@ -0,0 +1,161 @@
+/***************************************************************************
+ * Copyright (c) 2010 Werner Mayer *
+ * *
+ * 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"
+#ifndef _PreComp_
+# include
+# include
+#endif
+#include "MergeDocuments.h"
+#include
+#include
+#include
+#include
+#include
+
+using namespace App;
+
+namespace App {
+
+class XMLMergeReader : public Base::XMLReader
+{
+public:
+ XMLMergeReader(std::map& name, const char* FileName, std::istream& str)
+ : Base::XMLReader(FileName, str), nameMap(name)
+ {}
+
+ void addName(const char* s1, const char* s2)
+ {
+ nameMap[s1] = s2;
+ }
+ const char* getName(const char* name) const
+ {
+ std::map::const_iterator it = nameMap.find(name);
+ if (it != nameMap.end())
+ return it->second.c_str();
+ else
+ return name;
+ }
+ bool doNameMapping() const
+ {
+ return true;
+ }
+protected:
+ void startElement(const XMLCh* const uri, const XMLCh* const localname,
+ const XMLCh* const qname,
+ const XERCES_CPP_NAMESPACE_QUALIFIER Attributes& attrs)
+ {
+ Base::XMLReader::startElement(uri, localname, qname, attrs);
+ if (LocalName == "Property")
+ propertyStack.push(std::make_pair(AttrMap["name"],AttrMap["type"]));
+
+ if (!propertyStack.empty()) {
+ // replace the stored object name with the real one
+ if (LocalName == "Link" || LocalName == "LinkSub" || (LocalName == "String" && propertyStack.top().first == "Label")) {
+ for (std::map::iterator it = AttrMap.begin(); it != AttrMap.end(); ++it) {
+ std::map::const_iterator jt = nameMap.find(it->second);
+ if (jt != nameMap.end())
+ it->second = jt->second;
+ }
+ }
+ }
+ }
+
+ void endElement(const XMLCh* const uri, const XMLCh *const localname, const XMLCh *const qname)
+ {
+ Base::XMLReader::endElement(uri, localname, qname);
+ if (LocalName == "Property")
+ propertyStack.pop();
+ }
+
+private:
+ std::map& nameMap;
+ typedef std::pair PropertyTag;
+ std::stack propertyStack;
+};
+}
+
+MergeDocuments::MergeDocuments(App::Document* doc) : appdoc(doc)
+{
+ connectExport = doc->signalExportObjects.connect
+ (boost::bind(&MergeDocuments::exportObject, this, _1, _2));
+ connectImport = doc->signalImportObjects.connect
+ (boost::bind(&MergeDocuments::importObject, this, _1, _2));
+}
+
+MergeDocuments::~MergeDocuments()
+{
+ connectExport.disconnect();
+ connectImport.disconnect();
+}
+
+unsigned int MergeDocuments::getMemSize (void) const
+{
+ return 0;
+}
+
+std::vector
+MergeDocuments::importObjects(std::istream& input)
+{
+ this->nameMap.clear();
+ this->stream = new zipios::ZipInputStream(input);
+ XMLMergeReader reader(this->nameMap,"", *stream);
+ std::vector objs = appdoc->importObjects(reader);
+
+ delete this->stream;
+ this->stream = 0;
+
+ return objs;
+}
+
+void MergeDocuments::importObject(const std::vector& o, Base::XMLReader & r)
+{
+ objects = o;
+ Restore(r);
+ r.readFiles(*this->stream);
+}
+
+void MergeDocuments::exportObject(const std::vector& o, Base::Writer & w)
+{
+ objects = o;
+ Save(w);
+}
+
+void MergeDocuments::Save (Base::Writer & w) const
+{
+ // Save view provider stuff
+}
+
+void MergeDocuments::Restore(Base::XMLReader &r)
+{
+ // Restore view provider stuff
+}
+
+void MergeDocuments::SaveDocFile (Base::Writer & w) const
+{
+ // Save view provider stuff
+}
+
+void MergeDocuments::RestoreDocFile(Base::Reader & r)
+{
+ // Restore view provider stuff
+}
diff --git a/src/App/MergeDocuments.h b/src/App/MergeDocuments.h
new file mode 100644
index 000000000..f11236b9d
--- /dev/null
+++ b/src/App/MergeDocuments.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * Copyright (c) 2010 Werner Mayer *
+ * *
+ * 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 APP_MERGEDOCUMENTS_H
+#define APP_MERGEDOCUMENTS_H
+
+#include
+#include
+
+namespace zipios {
+class ZipInputStream;
+}
+
+namespace App {
+class Document;
+class DocumentObject;
+class AppExport MergeDocuments : public Base::Persistence
+{
+public:
+ MergeDocuments(App::Document* doc);
+ ~MergeDocuments();
+ unsigned int getMemSize (void) const;
+ std::vector importObjects(std::istream&);
+ void importObject(const std::vector& o, Base::XMLReader & r);
+ void exportObject(const std::vector& o, Base::Writer & w);
+ void Save (Base::Writer & w) const;
+ void Restore(Base::XMLReader &r);
+ void SaveDocFile (Base::Writer & w) const;
+ void RestoreDocFile(Base::Reader & r);
+
+private:
+ zipios::ZipInputStream* stream;
+ App::Document* appdoc;
+ std::vector objects;
+ std::map nameMap;
+ typedef boost::signals::connection Connection;
+ Connection connectExport;
+ Connection connectImport;
+};
+
+} // namespace App
+
+#endif // APP_MERGEDOCUMENTS_H
diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp
index 015c79239..d448f3600 100644
--- a/src/Gui/Document.cpp
+++ b/src/Gui/Document.cpp
@@ -853,7 +853,8 @@ void Document::exportObjects(const std::vector& obj, Base:
writer.Stream() << "" << std::endl;
}
-void Document::importObjects(const std::vector& obj, Base::Reader& reader)
+void Document::importObjects(const std::vector& obj, Base::Reader& reader,
+ const std::map& nameMapping)
{
// We must create an XML parser to read from the input stream
Base::XMLReader xmlReader("GuiDocument.xml", reader);
@@ -874,15 +875,12 @@ void Document::importObjects(const std::vector& obj, Base:
// thus we try to match by type. This should work because the order of
// objects should not have changed
xmlReader.readElement("ViewProvider");
- std::string type = xmlReader.getAttribute("type");
- ViewProvider* pObj = getViewProvider(*it);
- while (pObj && type != pObj->getTypeId().getName()) {
- if (it != obj.end()) {
- ++it;
- pObj = getViewProvider(*it);
- }
- }
- if (pObj && type == pObj->getTypeId().getName())
+ std::string name = xmlReader.getAttribute("name");
+ std::map::const_iterator jt = nameMapping.find(name);
+ if (jt != nameMapping.end())
+ name = jt->second;
+ Gui::ViewProvider* pObj = this->getViewProviderByName(name.c_str());
+ if (pObj)
pObj->Restore(xmlReader);
xmlReader.readEndElement("ViewProvider");
if (it == obj.end())
@@ -892,6 +890,10 @@ void Document::importObjects(const std::vector& obj, Base:
}
xmlReader.readEndElement("Document");
+
+ // In the file GuiDocument.xml new data files might be added
+ if (!xmlReader.getFilenames().empty())
+ xmlReader.readFiles(static_cast(reader.getStream()));
}
void Document::addRootObjectsToGroup(const std::vector& obj, App::DocumentObjectGroup* grp)
diff --git a/src/Gui/Document.h b/src/Gui/Document.h
index 38fbc772e..9005e9056 100644
--- a/src/Gui/Document.h
+++ b/src/Gui/Document.h
@@ -124,7 +124,8 @@ public:
/// This method is used to restore large amounts of data from a binary file.
virtual void RestoreDocFile(Base::Reader &reader);
void exportObjects(const std::vector&, Base::Writer&);
- void importObjects(const std::vector&, Base::Reader&);
+ void importObjects(const std::vector&, Base::Reader&,
+ const std::map& nameMapping);
/// Add all root objects of the given array to a group
void addRootObjectsToGroup(const std::vector&, App::DocumentObjectGroup*);
//@}
diff --git a/src/Gui/MergeDocuments.cpp b/src/Gui/MergeDocuments.cpp
index 430843129..878113e4c 100644
--- a/src/Gui/MergeDocuments.cpp
+++ b/src/Gui/MergeDocuments.cpp
@@ -164,44 +164,7 @@ void MergeDocuments::SaveDocFile (Base::Writer & w) const
document->exportObjects(objects, w);
}
-void MergeDocuments::RestoreDocFile(Base::Reader & reader)
+void MergeDocuments::RestoreDocFile(Base::Reader & r)
{
- std::vector obj = objects;
- // We must create an XML parser to read from the input stream
- Base::XMLReader xmlReader("GuiDocument.xml", reader);
- xmlReader.readElement("Document");
- long scheme = xmlReader.getAttributeAsInteger("SchemaVersion");
-
- // 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
- xmlReader.readElement("ViewProviderData");
- int Cnt = xmlReader.getAttributeAsInteger("Count");
- std::vector::const_iterator it = obj.begin();
- for (int i=0;igetViewProviderByName(name.c_str());
- //Gui::ViewProvider* pObj = document->getViewProvider(*it);
- if (pObj)
- pObj->Restore(xmlReader);
- xmlReader.readEndElement("ViewProvider");
- if (it == obj.end())
- break;
- }
- xmlReader.readEndElement("ViewProviderData");
- }
-
- xmlReader.readEndElement("Document");
-
- // In the file GuiDocument.xml new data files might be added
- if (!xmlReader.getFilenames().empty())
- xmlReader.readFiles(static_cast(reader.getStream()));
+ document->importObjects(objects, r, nameMap);
}