diff --git a/src/attribute-rel-util.cpp b/src/attribute-rel-util.cpp index 42b6bebf2571dfb755feff0ee04c67be23ae427b..d377e5edb37dfd0e3eea05310dd57e39a93f0540 100644 --- a/src/attribute-rel-util.cpp +++ b/src/attribute-rel-util.cpp @@ -34,11 +34,14 @@ unsigned int sp_attribute_clean_get_prefs() { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); unsigned int flags = 0; if( prefs->getBool("/options/svgoutput/incorrect_attributes_warn") ) flags += SP_ATTR_CLEAN_ATTR_WARN; - if( prefs->getBool("/options/svgoutput/incorrect_attributes_remove") ) flags += SP_ATTR_CLEAN_ATTR_REMOVE; + if( prefs->getBool("/options/svgoutput/incorrect_attributes_remove") && + !prefs->getBool("/options/svgoutput/disable_optimizations" ) ) flags += SP_ATTR_CLEAN_ATTR_REMOVE; if( prefs->getBool("/options/svgoutput/incorrect_style_properties_warn") ) flags += SP_ATTR_CLEAN_STYLE_WARN; - if( prefs->getBool("/options/svgoutput/incorrect_style_properties_remove" ) ) flags += SP_ATTR_CLEAN_STYLE_REMOVE; + if( prefs->getBool("/options/svgoutput/incorrect_style_properties_remove" ) && + !prefs->getBool("/options/svgoutput/disable_optimizations" ) ) flags += SP_ATTR_CLEAN_STYLE_REMOVE; if( prefs->getBool("/options/svgoutput/style_defaults_warn") ) flags += SP_ATTR_CLEAN_DEFAULT_WARN; - if( prefs->getBool("/options/svgoutput/style_defaults_remove") ) flags += SP_ATTR_CLEAN_DEFAULT_REMOVE; + if( prefs->getBool("/options/svgoutput/style_defaults_remove") && + !prefs->getBool("/options/svgoutput/disable_optimizations" ) ) flags += SP_ATTR_CLEAN_DEFAULT_REMOVE; return flags; } diff --git a/src/desktop.cpp b/src/desktop.cpp index 47c82b6d939d37c5bdadbdabc2f16f09ce66d2ea..72739305ae5780a4645a21d41899bac0e4ff908d 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -117,6 +117,7 @@ SPDesktop::SPDesktop() : waiting_cursor( false ), showing_dialogs ( false ), guides_active( false ), + on_live_extension(false), gr_item( NULL ), gr_point_type( POINT_LG_BEGIN ), gr_point_i( 0 ), diff --git a/src/desktop.h b/src/desktop.h index f4eecf8b71f9dcadefe2ee24e2b86c1aa062a696..8b20195db141c2a3831d4746b97fbc84c5ce5b71 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -188,9 +188,9 @@ public: unsigned int interaction_disabled_counter; bool waiting_cursor; bool showing_dialogs; - /// \todo fixme: This has to be implemented in different way */ guint guides_active : 1; + bool on_live_extension; // storage for selected dragger used by GrDrag as it's // created and deleted by tools diff --git a/src/extension/execution-env.cpp b/src/extension/execution-env.cpp index 7e233d2151b95822c821867b3379cace489c152d..bde04d924f9bd9733552fca7f9879bf920d7de24 100644 --- a/src/extension/execution-env.cpp +++ b/src/extension/execution-env.cpp @@ -22,6 +22,8 @@ #include "selection.h" #include "effect.h" #include "document.h" +#include "desktop.h" +#include "inkscape.h" #include "document-undo.h" #include "desktop.h" #include "object/sp-namedview.h" @@ -52,19 +54,6 @@ ExecutionEnv::ExecutionEnv (Effect * effect, Inkscape::UI::View::View * doc, Imp _show_working(show_working), _show_errors(show_errors) { - SPDesktop *desktop = (SPDesktop *)_doc; - sp_namedview_document_from_window(desktop); - - if (desktop != NULL) { - auto selected = desktop->getSelection()->items(); - for(auto x = selected.begin(); x != selected.end(); ++x){ - Glib::ustring selected_id; - selected_id = (*x)->getId(); - _selected.insert(_selected.end(), selected_id); - //std::cout << "Selected: " << selected_id << std::endl; - } - } - genDocCache(); return; @@ -189,24 +178,14 @@ ExecutionEnv::commit (void) { void ExecutionEnv::reselect (void) { - if (_doc == NULL) { return; } - SPDocument * doc = _doc->doc(); - if (doc == NULL) { return; } - - SPDesktop *desktop = (SPDesktop *)_doc; - sp_namedview_document_from_window(desktop); - - if (desktop == NULL) { return; } - - Inkscape::Selection * selection = desktop->getSelection(); - - for (std::list::iterator i = _selected.begin(); i != _selected.end(); ++i) { - SPObject * obj = doc->getObjectById(i->c_str()); - if (obj != NULL) { - selection->add(obj); + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + Inkscape::Selection * selection = NULL; + if(desktop) { + selection = desktop->getSelection(); + if (!desktop->on_live_extension) { + selection->restoreBackup(); } } - return; } diff --git a/src/extension/execution-env.h b/src/extension/execution-env.h index b1a3a8ea22a65ad2c53a19139e30af7c9a636738..8af97cd92345db04415a77f33aec807a8fc97595 100644 --- a/src/extension/execution-env.h +++ b/src/extension/execution-env.h @@ -54,9 +54,6 @@ private: Glib::RefPtr _mainloop; /** \brief The document that we're working on. */ Inkscape::UI::View::View * _doc; - /** \brief A list of the IDs of all the selected objects before - we started to work on this document. */ - std::list _selected; /** \brief A document cache if we were passed one. */ Implementation::ImplementationDocumentCache * _docCache; diff --git a/src/extension/implementation/implementation.cpp b/src/extension/implementation/implementation.cpp index 6e6100d2b66460007042be42a4bfe81da2d7bf86..e05dbf3c43276b5917e53dad1956dceedb1809de 100644 --- a/src/extension/implementation/implementation.cpp +++ b/src/extension/implementation/implementation.cpp @@ -27,6 +27,23 @@ namespace Inkscape { namespace Extension { namespace Implementation { +ImplementationDocumentCache::ImplementationDocumentCache (Inkscape::UI::View::View * view) + : _view(view) +{ + SPDesktop *desktop = (SPDesktop*)view; + Inkscape::Selection * selection = NULL; + if (desktop) { + selection = desktop->getSelection(); + if (selection && !selection->params.empty()) { + selection->restoreBackup(); + if (!desktop->on_live_extension) { + selection->emptyBackup(); + } + } + } + return; +} + Gtk::Widget * Implementation::prefs_input(Inkscape::Extension::Input *module, gchar const */*filename*/) { return module->autogui(NULL, NULL); diff --git a/src/extension/implementation/implementation.h b/src/extension/implementation/implementation.h index 1232ae0c871a6fa22c9280ab3335abb3e8d80130..5bb909ef262cc6a4c84111b00a35318761bae8f6 100644 --- a/src/extension/implementation/implementation.h +++ b/src/extension/implementation/implementation.h @@ -56,11 +56,8 @@ class ImplementationDocumentCache { */ Inkscape::UI::View::View * _view; public: - ImplementationDocumentCache (Inkscape::UI::View::View * view) : - _view(view) - { - return; - }; + ImplementationDocumentCache (Inkscape::UI::View::View * view); + virtual ~ImplementationDocumentCache ( ) { return; }; Inkscape::UI::View::View const * view ( ) { return _view; }; }; diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index f25c8a5d69ff225a26fab0cfc56f2a8d4884abe6..1e8556de7732d466b31eea793cad39fb654d1526 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -418,10 +418,12 @@ ScriptDocCache::ScriptDocCache (Inkscape::UI::View::View * view) : SPDesktop *desktop = (SPDesktop *) view; sp_namedview_document_from_window(desktop); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setBool("/options/svgoutput/disable_optimizations", true); Inkscape::Extension::save( Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE), view->doc(), _filename.c_str(), false, false, false, Inkscape::Extension::FILE_SAVE_METHOD_TEMPORARY); - + prefs->setBool("/options/svgoutput/disable_optimizations", false); return; } @@ -686,57 +688,14 @@ void Script::effect(Inkscape::Extension::Effect *module, return; } - auto selected = - desktop->getSelection()->items(); //desktop should not be NULL since doc was checked and desktop is a casted pointer - for(auto x = selected.begin(); x != selected.end(); ++x){ - Glib::ustring selected_id; - selected_id += "--id="; - selected_id += (*x)->getId(); - params.push_front(selected_id); - } - - {//add selected nodes - Inkscape::UI::Tools::NodeTool *tool = 0; - if (SP_ACTIVE_DESKTOP ) { - Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; - if (INK_IS_NODE_TOOL(ec)) { - tool = static_cast(ec); + if (desktop) { + Inkscape::Selection * selection = desktop->getSelection(); + if (!selection->isEmpty()) { + selection->setBackup(); } + params = selection->params; + module->paramListString(params); } - - if(tool){ - Inkscape::UI::ControlPointSelection *cps = tool->_selected_nodes; - for (Inkscape::UI::ControlPointSelection::iterator i = cps->begin(); i != cps->end(); ++i) { - Inkscape::UI::Node *node = dynamic_cast(*i); - if (node) { - std::string id = node->nodeList().subpathList().pm().item()->getId(); - - int sp = 0; - bool found_sp = false; - for(Inkscape::UI::SubpathList::iterator i = node->nodeList().subpathList().begin(); i != node->nodeList().subpathList().end(); ++i,++sp){ - if(&**i == &(node->nodeList())){ - found_sp = true; - break; - } - } - int nl=0; - bool found_nl = false; - for (Inkscape::UI::NodeList::iterator j = node->nodeList().begin(); j != node->nodeList().end(); ++j, ++nl){ - if(&*j==node){ - found_nl = true; - break; - } - } - std::ostringstream ss; - ss<< "--selected-nodes=" << id << ":" << sp << ":" << nl; - Glib::ustring selected = ss.str(); - - if(found_nl && found_sp)params.push_front(selected); - else g_warning("Something went wrong while trying to pass selected nodes to extension. Please report a bug."); - } - } - } - }//end add selected nodes file_listener fileout; int data_read = execute(command, params, dc->_filename, fileout); @@ -790,6 +749,7 @@ void Script::effect(Inkscape::Extension::Effect *module, layer = document->getObjectById(g_quark_to_string(nv->default_layer_id)); } } + desktop->showGrids(nv->grids_visible); } sp_namedview_update_layers_from_document(desktop); @@ -798,6 +758,14 @@ void Script::effect(Inkscape::Extension::Effect *module, //set the current layer desktop->setCurrentLayer(layer); } + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + Inkscape::Selection * selection = desktop->getSelection(); + if (selection && selection->isEmpty() && !desktop->on_live_extension) { + selection->restoreBackup(); + selection->emptyBackup(); + } + } } mydoc->release(); } @@ -859,80 +827,33 @@ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newr oldroot->setAttribute(name, newroot->attribute(name)); } - // Question: Why is the "sodipodi:namedview" special? Treating it as a normal // elmement results in crashes. // Seems to be a bug: // http://inkscape.13.x6.nabble.com/Effect-that-modifies-the-document-properties-tt2822126.html std::vector delete_list; - Inkscape::XML::Node * oldroot_namedview = NULL; - Inkscape::XML::Node * newroot_namedview = NULL; // Make list for (Inkscape::XML::Node * child = oldroot->firstChild(); child != NULL; child = child->next()) { if (!strcmp("sodipodi:namedview", child->name())) { - oldroot_namedview = child; for (Inkscape::XML::Node * oldroot_namedview_child = child->firstChild(); oldroot_namedview_child != NULL; oldroot_namedview_child = oldroot_namedview_child->next()) { delete_list.push_back(oldroot_namedview_child); } - } else { - delete_list.push_back(child); + break; } } - if(!oldroot_namedview) - { - g_warning("Error on copy_doc: No namedview on destination document."); - return; - } - // Unparent (delete) for (unsigned int i = 0; i < delete_list.size(); i++) { sp_repr_unparent(delete_list[i]); } - - // Copy - for (Inkscape::XML::Node * child = newroot->firstChild(); - child != NULL; - child = child->next()) { - if (!strcmp("sodipodi:namedview", child->name())) { - newroot_namedview = child; - for (Inkscape::XML::Node * newroot_namedview_child = child->firstChild(); - newroot_namedview_child != NULL; - newroot_namedview_child = newroot_namedview_child->next()) { - oldroot_namedview->appendChild(newroot_namedview_child->duplicate(oldroot->document())); - } - } else { - oldroot->appendChild(child->duplicate(oldroot->document())); - } - } - attribs.clear(); - - // Must explicitly copy namedview attributes. - // Make a list of all attributes of the old namedview node. - for (List iter = oldroot_namedview->attributeList(); iter; ++iter) { - attribs.push_back(g_quark_to_string(iter->key)); - } - - // Delete the attributes of the old namedview node. - for (std::vector::const_iterator it = attribs.begin(); it != attribs.end(); ++it) { - oldroot_namedview->setAttribute(*it, NULL); - } - - // Set the new attributes. - for (List iter = newroot_namedview->attributeList(); iter; ++iter) { - gchar const *name = g_quark_to_string(iter->key); - oldroot_namedview->setAttribute(name, newroot_namedview->attribute(name)); - } - - /** \todo Restore correct layer */ - /** \todo Restore correct selection */ + oldroot->mergeFrom(newroot, "id", true, true); } /** \brief This function checks the stderr file, and if it has data, diff --git a/src/extension/prefdialog.cpp b/src/extension/prefdialog.cpp index 0247e18e9001a5932d5bf18810a68492ee34e7c9..0861f1dc33f94fdfbf60d9bfe2b07531ba67ed04 100644 --- a/src/extension/prefdialog.cpp +++ b/src/extension/prefdialog.cpp @@ -18,6 +18,8 @@ // Used to get SP_ACTIVE_DESKTOP #include "inkscape.h" #include "desktop.h" +#include "document.h" +#include "document-undo.h" #include "effect.h" #include "implementation/implementation.h" @@ -61,6 +63,13 @@ PrefDialog::PrefDialog (Glib::ustring name, gchar const * help, Gtk::Widget * co controls = _effect->get_imp()->prefs_effect(_effect, SP_ACTIVE_DESKTOP, &_signal_param_change, NULL); _signal_param_change.connect(sigc::mem_fun(this, &PrefDialog::param_change)); } + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + Inkscape::Selection * selection = desktop->getSelection(); + if (selection) { + selection->emptyBackup(); + } + } hbox->pack_start(*controls, true, true, 0); hbox->show(); @@ -170,12 +179,29 @@ PrefDialog::run (void) { void PrefDialog::preview_toggle (void) { + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SPDocument *document = SP_ACTIVE_DOCUMENT; + Inkscape::Selection * selection = NULL; + bool modified = document->isModifiedSinceSave(); + if(desktop) { + selection = desktop->getSelection(); + if (!selection->isEmpty()) { + selection->setBackup(); + } + } if(_param_preview->get_bool(NULL, NULL)) { - set_modal(true); if (_exEnv == NULL) { + set_modal(true); + if (desktop && selection) { + desktop->on_live_extension = true; + + } _exEnv = new ExecutionEnv(_effect, SP_ACTIVE_DESKTOP, NULL, false, false); _effect->set_execution_env(_exEnv); _exEnv->run(); + if (desktop && selection) { + selection->clear(); + } } } else { set_modal(false); @@ -185,8 +211,13 @@ PrefDialog::preview_toggle (void) { delete _exEnv; _exEnv = NULL; _effect->set_execution_env(_exEnv); + if (desktop && selection) { + selection->restoreBackup(); + desktop->on_live_extension = false; + } } } + document->setModifiedSinceSave(modified); } void diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index ed00092b2cfeb1ee216a24b1f1ead345f796db7a..23040fcfd4cdbb136425682a0bff5feca2fdf77d 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -323,6 +323,7 @@ static char const preferences_skeleton[] = " clips=\"16711935\"" // 00ff00ff " masks=\"65535\"/>\n" // 0x0000ffff " event_context; + if (INK_IS_NODE_TOOL(ec)) { + tool = static_cast(ec); + } + } + _selected_ids.clear(); + _seldata.clear(); + params.clear(); + auto items = const_cast(this)->items(); + for (auto iter = items.begin(); iter != items.end(); ++iter) { + SPItem *item = *iter; + std::string selected_id; + selected_id += "--id="; + selected_id += item->getId(); + params.push_back(selected_id); + _selected_ids.push_back(item->getId()); + } + if(tool){ + Inkscape::UI::ControlPointSelection *cps = tool->_selected_nodes; + std::list points_list = cps->_points_list; + for (std::list::iterator i = points_list.begin(); i != points_list.end(); ++i) { + Inkscape::UI::Node *node = dynamic_cast(*i); + if (node) { + std::string id = node->nodeList().subpathList().pm().item()->getId(); + + int sp = 0; + bool found_sp = false; + for(Inkscape::UI::SubpathList::iterator i = node->nodeList().subpathList().begin(); i != node->nodeList().subpathList().end(); ++i,++sp){ + if(&**i == &(node->nodeList())){ + found_sp = true; + break; + } + } + int nl=0; + bool found_nl = false; + for (Inkscape::UI::NodeList::iterator j = node->nodeList().begin(); j != node->nodeList().end(); ++j, ++nl){ + if(&*j==node){ + found_nl = true; + break; + } + } + std::ostringstream ss; + ss<< "--selected-nodes=" << id << ":" << sp << ":" << nl; + Glib::ustring selected_nodes = ss.str(); + + if(found_nl && found_sp) { + _seldata.push_back(std::make_pair(id,std::make_pair(sp,nl))); + params.push_back(selected_nodes); + } else { + g_warning("Something went wrong while trying to pass selected nodes to extension. Please report a bug."); + } + } + } + }//end add selected nodes +} + +void +Selection::restoreBackup() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SPDocument *document = SP_ACTIVE_DOCUMENT; + Inkscape::UI::Tools::NodeTool *tool = 0; + if (desktop) { + Inkscape::UI::Tools::ToolBase *ec = desktop->event_context; + if (INK_IS_NODE_TOOL(ec)) { + tool = static_cast(ec); + } + } + clear(); + std::vector::iterator it = _selected_ids.begin(); + for (; it!= _selected_ids.end(); ++it){ + SPItem * item = dynamic_cast(document->getObjectById(it->c_str())); + SPDefs * defs = document->getDefs(); + if (item && !defs->isAncestorOf(item)) { + add(item); + } + } + if (tool) { + Inkscape::UI::ControlPointSelection *cps = tool->_selected_nodes; + cps->selectAll(); + std::list points_list = cps->_points_list; + cps->clear(); + Inkscape::UI::Node * node = dynamic_cast(*points_list.begin()); + if (node) { + Inkscape::UI::SubpathList sp = node->nodeList().subpathList(); + for (std::vector > >::iterator l = _seldata.begin(); l != _seldata.end(); ++l) { + SPPath * path = dynamic_cast(document->getObjectById(l->first)); + gint sp_count = 0; + for (Inkscape::UI::SubpathList::iterator j = sp.begin(); j != sp.end(); ++j, ++sp_count) { + if(sp_count == l->second.first) { + gint nt_count = 0; + for (Inkscape::UI::NodeList::iterator k = (*j)->begin(); k != (*j)->end(); ++k, ++nt_count) { + if(nt_count == l->second.second) { + cps->insert(k.ptr()); + break; + } + } + break; + } + } + } + } + points_list.clear(); + } +} + + } /* diff --git a/src/selection.h b/src/selection.h index 2b454e94748619181c7c86ebc5ac593452475042..989adf6b0efd2bbc9e7dd76ac82c9b7461cfb148 100644 --- a/src/selection.h +++ b/src/selection.h @@ -183,6 +183,23 @@ public: return _modified_signal.slots().insert(_modified_signal.slots().begin(), slot); } + /** + * Set a backup of current selection and store it also to be command line readable by extension system + */ + void setBackup(); + /** + * Clear backup of current selection + */ + void emptyBackup(); + /** + * Restore a selection from a existing backup + */ + void restoreBackup(); + /** + * Here store a paramlist when set backup + */ + std::list params; + protected: void _emitSignals(); void _connectSignals(SPObject* object); @@ -212,7 +229,8 @@ private: SPObject* _selection_context; unsigned int _flags; unsigned int _idle; - + std::vector > > _seldata; + std::vector _selected_ids; std::map _modified_connections; sigc::connection _context_release_connection; diff --git a/src/svg/path-string.cpp b/src/svg/path-string.cpp index 7d0092dfaa12caaff62e3868258900019d81c847..2fa2c8f0264c886af3a72038923fce659ad378fd 100644 --- a/src/svg/path-string.cpp +++ b/src/svg/path-string.cpp @@ -28,7 +28,7 @@ int Inkscape::SVG::PathString::minimumexponent; Inkscape::SVG::PATHSTRING_FORMAT Inkscape::SVG::PathString::format; Inkscape::SVG::PathString::PathString() : - force_repeat_commands(Inkscape::Preferences::get()->getBool("/options/svgoutput/forcerepeatcommands")) + force_repeat_commands(!Inkscape::Preferences::get()->getBool("/options/svgoutput/disable_optimizations" ) && Inkscape::Preferences::get()->getBool("/options/svgoutput/forcerepeatcommands")) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); format = (PATHSTRING_FORMAT)prefs->getIntLimited("/options/svgoutput/pathstring_format", 1, 0, PATHSTRING_FORMAT_SIZE - 1 ); diff --git a/src/svg/svg-color.cpp b/src/svg/svg-color.cpp index d1e91ace12bd58e5d1fcdff33a2a7276c09b42ae..1f26d02b120e993d9f044b964a999867036e39d6 100644 --- a/src/svg/svg-color.cpp +++ b/src/svg/svg-color.cpp @@ -491,7 +491,8 @@ void sp_svg_write_color(gchar *buf, unsigned const buflen, guint32 const rgba32) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); unsigned const rgb24 = rgba32 >> 8; - if (prefs->getBool("/options/svgoutput/usenamedcolors")) { + if ( prefs->getBool("/options/svgoutput/usenamedcolors") && + !prefs->getBool("/options/svgoutput/disable_optimizations" )) { rgb24_to_css(buf, rgb24); } else { g_snprintf(buf, buflen, "#%06x", rgb24); diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h index ec845b1b393d35e7f1be0c824d5dab16bf63cf64..d0cfce8d2fc5001f9dd1c39a4df1a3092331629b 100644 --- a/src/ui/tool/control-point-selection.h +++ b/src/ui/tool/control-point-selection.h @@ -117,6 +117,8 @@ public: void getOriginalPoints(std::vector &pts); void getUnselectedPoints(std::vector &pts); void setOriginalPoints(); + //the purpose of this list is to keep track of first and last selected + std::list _points_list; private: // The functions below are invoked from SelectableControlPoint. @@ -140,8 +142,7 @@ private: double _rotationRadius(Geom::Point const &); set_type _points; - //the purpose of this list is to keep track of first and last selected - std::list _points_list; + set_type _all_points; INK_UNORDERED_MAP _original_positions; INK_UNORDERED_MAP _last_trans; diff --git a/src/ui/tool/selectable-control-point.cpp b/src/ui/tool/selectable-control-point.cpp index f3f9c0e1e47349d4520076b3063bfa1c21ea997b..83ed7d38b183d35e71b7d0359cd6d111c0ff6f3d 100644 --- a/src/ui/tool/selectable-control-point.cpp +++ b/src/ui/tool/selectable-control-point.cpp @@ -87,6 +87,15 @@ bool SelectableControlPoint::clicked(GdkEventButton *event) return true; } +void SelectableControlPoint::select(bool toselect) +{ + if (toselect) { + _selection.insert(this); + } else { + _selection.erase(this); + } +} + void SelectableControlPoint::_takeSelection() { _selection.clear(); diff --git a/src/ui/tool/selectable-control-point.h b/src/ui/tool/selectable-control-point.h index 362d4addcaad42e2789b81610c56a96e61820e47..c16f639b1e52425058a1bebd932866f04ecb7a50 100644 --- a/src/ui/tool/selectable-control-point.h +++ b/src/ui/tool/selectable-control-point.h @@ -28,8 +28,10 @@ public: virtual Geom::Rect bounds() const { return Geom::Rect(position(), position()); } + virtual void select(bool toselect); friend class NodeList; + protected: SelectableControlPoint(SPDesktop *d, Geom::Point const &initial_pos, SPAnchorType anchor, diff --git a/src/xml/node.h b/src/xml/node.h index 29cfdab4684893b76331fd9a113dbab6b67c7379..8d9fc19e4a2f2cb7e6871586a51e1630ce19ff08 100644 --- a/src/xml/node.h +++ b/src/xml/node.h @@ -384,6 +384,20 @@ public: */ virtual void changeOrder(Node *child, Node *after)=0; + /** + * @brief Remove all elements that not in src node + * @param src The node to check for elemments into this node + * @param key The attribute to use as the identity attribute + */ + virtual void cleanOriginal(Node *src, gchar const *key)=0; + + + /** + * @brief Compare 2 nodes equality + * @param other The other node to compare + * @param recursive Recursive mode check + */ + virtual bool equal(Node const *other, bool recursive)=0; /** * @brief Merge all children of another node with the current * @@ -397,8 +411,11 @@ public: * * @param src The node to merge into this node * @param key The attribute to use as the identity attribute + * @param noid If true process noid items + * @param key If clean callback to cleanOriginal */ - virtual void mergeFrom(Node const *src, char const *key)=0; + + virtual void mergeFrom(Node const *src, char const *key, bool extension = false, bool clean = false)=0; /*@}*/ diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp index 2ff9d477698a5bde44cb95b498407db8e21a6015..519b30cd44575d1f85484be5b8bfa8a397863778 100644 --- a/src/xml/repr-io.cpp +++ b/src/xml/repr-io.cpp @@ -871,8 +871,8 @@ static void sp_repr_write_stream_root_element(Node *repr, Writer &out, bool clean = prefs->getBool("/options/svgoutput/check_on_writing"); if (clean) sp_attribute_clean_tree( repr ); - // Sort attributes in a canonical order (helps with "diffing" SVG files). - bool sort = prefs->getBool("/options/svgoutput/sort_attributes"); + // Sort attributes in a canonical order (helps with "diffing" SVG files).only if not set disable optimizations + bool sort = !prefs->getBool("/options/svgoutput/disable_optimizations") && prefs->getBool("/options/svgoutput/sort_attributes"); if (sort) sp_attribute_sort_tree( repr ); Glib::QueryQuark xml_prefix=g_quark_from_static_string("xml"); diff --git a/src/xml/simple-node.cpp b/src/xml/simple-node.cpp index 78fc52a27999521fcdabfbb575eb0220edd1b667..a1a7127cca23a532b24e338606eaf701d4f2a594 100644 --- a/src/xml/simple-node.cpp +++ b/src/xml/simple-node.cpp @@ -315,7 +315,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ // Check usefulness of attributes on elements in the svg namespace, optionally don't add them to tree. Glib::ustring element = g_quark_to_string(_name); - // g_message("setAttribute: %s: %s: %s", element.c_str(), name, value); + //g_message("setAttribute: %s: %s: %s", element.c_str(), name, value); gchar* cleaned_value = g_strdup( value ); // Only check elements in SVG name space and don't block setting attribute to NULL. @@ -645,28 +645,112 @@ Node *SimpleNode::root() { } } -void SimpleNode::mergeFrom(Node const *src, gchar const *key) { +void SimpleNode::cleanOriginal(Node *src, gchar const *key){ + std::vector to_delete; + for ( Node *child = this->firstChild() ; child != NULL ; child = child->next() ) + { + gchar const *id = child->attribute(key); + if (id) { + Node *rch = sp_repr_lookup_child(src, key, id); + if (rch) { + child->cleanOriginal(rch, key); + } else { + to_delete.push_back(child); + } + } else { + to_delete.push_back(child); + } + } + for ( std::vector::iterator i = to_delete.begin(); i != to_delete.end(); ++i) { + removeChild(*i); + } +} + +bool SimpleNode::equal(Node const *other, bool recursive) { + if(strcmp(name(),other->name())!= 0){ + return false; + } + if (!(strcmp("sodipodi:namedview", name()))) { + return true; + } + guint orig_length = 0; + guint other_length = 0; + + if(content() && other->content() && strcmp(content(), other->content()) != 0){ + return false; + } + for (List orig_attr = attributeList(); orig_attr; ++orig_attr) { + for (List other_attr = other->attributeList(); other_attr; ++other_attr) { + const gchar * key_orig = g_quark_to_string(orig_attr->key); + const gchar * key_other = g_quark_to_string(other_attr->key); + if (!strcmp(key_orig, key_other) && + !strcmp(orig_attr->value, other_attr->value)) + { + other_length++; + break; + } + } + orig_length++; + } + if (orig_length != other_length) { + return false; + } + if (recursive) { + //NOTE: for faster the childs need to be in the same order + Node const *other_child = other->firstChild(); + for ( Node *child = firstChild(); + child; + child = child->next()) + { + if (!child->equal(other_child, recursive)) { + return false; + } + other_child = other_child->next(); + if(!other_child) { + return false; + } + } + } + return true; +} + +void SimpleNode::mergeFrom(Node const *src, gchar const *key, bool extension, bool clean) { g_return_if_fail(src != NULL); g_return_if_fail(key != NULL); g_assert(src != this); setContent(src->content()); + if(_parent) { + setPosition(src->position()); + } + + if (clean) { + Node * srcp = const_cast(src); + cleanOriginal(srcp, key); + } for ( Node const *child = src->firstChild() ; child != NULL ; child = child->next() ) { gchar const *id = child->attribute(key); if (id) { Node *rch=sp_repr_lookup_child(this, key, id); - if (rch) { - rch->mergeFrom(child, key); + if (rch && (!extension || rch->equal(child, false))) { + rch->mergeFrom(child, key, extension); } else { + if(rch) { + removeChild(rch); + } + guint pos = child->position(); rch = child->duplicate(_document); appendChild(rch); + rch->setPosition(pos); rch->release(); } } else { + guint pos = child->position(); Node *rch=child->duplicate(_document); appendChild(rch); + rch->setPosition(pos); rch->release(); } } diff --git a/src/xml/simple-node.h b/src/xml/simple-node.h index f2cfa953c9d18af5eed7aac76b33d29b066d99c2..fd41e53a88c056c56f9d02d787c07fa8a936b6a9 100644 --- a/src/xml/simple-node.h +++ b/src/xml/simple-node.h @@ -91,7 +91,9 @@ public: char const *content() const; void setContent(char const *value); - void mergeFrom(Node const *src, char const *key); + void cleanOriginal(Node *src, gchar const *key); + bool equal(Node const *other, bool recursive); + void mergeFrom(Node const *src, char const *key, bool extension = false, bool clean = false); Inkscape::Util::List attributeList() const { return _attributes;