diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 75d008ff0e9816638a4a81546b0ce7386fcd1bc1..af17fc3f0ce1a9c52b046dda0452c4ddd817e64c 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -57,7 +57,6 @@ #include "widgets/desktop-widget.h" #include "xml/attribute-record.h" #include "xml/rebase-hrefs.h" -#include "xml/node.h" /* Namespaces */ namespace Inkscape { @@ -639,20 +638,17 @@ void Script::_change_extension(Inkscape::Extension::Extension *module, SPDocumen fileout.toFile(tempfile_out.get_filename()); pump_events(); - Inkscape::XML::Document *myxmldoc = nullptr; + Inkscape::XML::Document *new_xmldoc = nullptr; if (data_read > 10) { - myxmldoc = sp_repr_read_file(tempfile_out.get_filename().c_str(), SP_SVG_NS_URI); + new_xmldoc = sp_repr_read_file(tempfile_out.get_filename().c_str(), SP_SVG_NS_URI); } // data_read pump_events(); - if (myxmldoc) { + if (new_xmldoc) { //uncomment if issues on ref extensions links (with previous function) - //sp_change_hrefs(myxmldoc, tempfile_out.get_filename().c_str(), doc->getDocumentFilename()); - doc->emitReconstructionStart(); - copy_doc(doc->getReprRoot(), myxmldoc->root()); - doc->emitReconstructionFinish(); - myxmldoc->release(); + //sp_change_hrefs(new_xmldoc, tempfile_out.get_filename().c_str(), doc->getDocumentFilename()); + rebase_doc (doc, new_xmldoc); } else { Inkscape::UI::gui_warning(_("The output from the extension could not be parsed."), parent_window); } @@ -660,35 +656,51 @@ void Script::_change_extension(Inkscape::Extension::Extension *module, SPDocumen return; } - - /** - \brief A function to replace all the elements in an old document - by those from a new document. + \brief A function to replace all the elements in a document + by those from a new XML::Document. document and repinserts them into an emptied old document. - \param oldroot The root node of the old (destination) document. - \param newroot The root node of the new (source) document. + \param doc The target document (all content is replaced except root "svg" tag). + \param new_xmldoc The root node to inject into. This function first deletes all the root attributes in the old document followed - by copying all the root attributes from the new document to the old document. - - It then deletes all the elements in the old document by - making two passes, the first to create a list of the old elements and - the second to actually delete them. This two pass approach removes issues - with the list being changed while parsing through it... lots of nasty bugs. + by copying all the root attributes from the new document to the old document. - Then, it copies all the element in the new document into the old document. - - Finally, it copies the attributes in namedview. + Then, it copies all the element in the new XML::Document into the root of document. + keep a diferent approach for namedview to not erase it and merge new values */ -void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newroot) +void Script::rebase_doc (SPDocument *doc, Inkscape::XML::Document * new_xmldoc) { - if ((oldroot == nullptr) || (newroot == nullptr)) + if ((doc == nullptr) || (new_xmldoc == nullptr)) { - g_warning("Error on copy_doc: NULL pointer input."); + g_warning("Error on rebase_doc: NULL pointer input."); return; } - oldroot->mergeFrom(newroot, "id", true, true); + doc->emitReconstructionStart(); + Inkscape::XML::Document * origin_xmldoc = doc->getReprDoc(); + Inkscape::XML::Node *namedview = nullptr; + for ( Inkscape::XML::Node *child = origin_xmldoc->root()->lastChild() ; child != nullptr ;) + { + Inkscape::XML::Node *prevchild = child->prev(); + if (!g_strcmp0(child->name(),"sodipodi:namedview")) { + namedview = child; + } else { + origin_xmldoc->root()->removeChild(child); + } + child = prevchild; + } + for ( Inkscape::XML::Node *child = new_xmldoc->root()->firstChild() ; child != nullptr ; child = child->next() ) + { + if (!g_strcmp0(child->name(),"sodipodi:namedview")) { + namedview->mergeFrom(child, "id", true, true); + } else { + Inkscape::XML::Node *new_child = child->duplicate(origin_xmldoc); + origin_xmldoc->root()->appendChild(new_child); + Inkscape::GC::release(new_child); + } + } + doc->emitReconstructionFinish(); + new_xmldoc->release(); } /** \brief This function checks the stderr file, and if it has data, diff --git a/src/extension/implementation/script.h b/src/extension/implementation/script.h index 530643403225748394aea2a1309d7793ae83387a..b472a252de84c16a68f41ea091bfb7b1420a2cea 100644 --- a/src/extension/implementation/script.h +++ b/src/extension/implementation/script.h @@ -15,6 +15,7 @@ #define INKSCAPE_EXTENSION_IMPEMENTATION_SCRIPT_H_SEEN #include "implementation.h" +#include "xml/node.h" #include #include #include @@ -79,7 +80,7 @@ private: */ Gtk::Window *parent_window; - void copy_doc(Inkscape::XML::Node * olddoc, Inkscape::XML::Node * newdoc); + void rebase_doc(SPDocument *doc, Inkscape::XML::Document * new_xmldoc); void checkStderr (Glib::ustring const& filename, Gtk::MessageType type, Glib::ustring const& message); class file_listener {