diff options
| -rw-r--r-- | src/desktop.cpp | 1 | ||||
| -rw-r--r-- | src/desktop.h | 2 | ||||
| -rw-r--r-- | src/extension/execution-env.cpp | 37 | ||||
| -rw-r--r-- | src/extension/execution-env.h | 3 | ||||
| -rw-r--r-- | src/extension/implementation/script.cpp | 137 | ||||
| -rw-r--r-- | src/extension/internal/bitmap/imagemagick.cpp | 10 | ||||
| -rw-r--r-- | src/extension/internal/bluredge.cpp | 13 | ||||
| -rw-r--r-- | src/extension/internal/filter/filter.cpp | 13 | ||||
| -rw-r--r-- | src/extension/internal/grid.cpp | 12 | ||||
| -rw-r--r-- | src/extension/prefdialog.cpp | 28 | ||||
| -rw-r--r-- | src/selection.cpp | 122 | ||||
| -rw-r--r-- | src/selection.h | 20 | ||||
| -rw-r--r-- | src/ui/tool/control-point-selection.h | 5 | ||||
| -rw-r--r-- | src/ui/tool/selectable-control-point.cpp | 9 | ||||
| -rw-r--r-- | src/ui/tool/selectable-control-point.h | 2 | ||||
| -rw-r--r-- | src/xml/node.h | 19 | ||||
| -rw-r--r-- | src/xml/simple-node.cpp | 92 | ||||
| -rw-r--r-- | src/xml/simple-node.h | 4 |
18 files changed, 379 insertions, 150 deletions
diff --git a/src/desktop.cpp b/src/desktop.cpp index 47c82b6d9..72739305a 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 f4eecf8b7..8b20195db 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 7e233d215..bde04d924 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<Glib::ustring>::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 b1a3a8ea2..8af97cd92 100644 --- a/src/extension/execution-env.h +++ b/src/extension/execution-env.h @@ -54,9 +54,6 @@ private: Glib::RefPtr<Glib::MainLoop> _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<Glib::ustring> _selected; /** \brief A document cache if we were passed one. */ Implementation::ImplementationDocumentCache * _docCache; diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index f25c8a5d6..42867b823 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -417,11 +417,29 @@ ScriptDocCache::ScriptDocCache (Inkscape::UI::View::View * view) : SPDesktop *desktop = (SPDesktop *) view; sp_namedview_document_from_window(desktop); - + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool sort_attributes = prefs->getBool("/options/svgoutput/sort_attributes", false); + bool incorrect_style_properties_remove = prefs->getBool("/options/svgoutput/incorrect_style_properties_remove", false); + bool incorrect_attributes_remove = prefs->getBool("/options/svgoutput/incorrect_attributes_remove", false); + bool usenamedcolors = prefs->getBool("/options/svgoutput/usenamedcolors", false); + bool forcerepeatcommands = prefs->getBool("/options/svgoutput/forcerepeatcommands", false); + bool style_defaults_remove = prefs->getBool("/options/svgoutput/style_defaults_remove", false); + prefs->setBool("/options/svgoutput/sort_attributes", false); + prefs->setBool("/options/svgoutput/incorrect_style_properties_remove", false); + prefs->setBool("/options/svgoutput/incorrect_attributes_remove", false); + prefs->setBool("/options/svgoutput/usenamedcolors", false); + prefs->setBool("/options/svgoutput/forcerepeatcommands", false); + prefs->setBool("/options/svgoutput/style_defaults_remove", false); 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/sort_attributes", sort_attributes); + prefs->setBool("/options/svgoutput/incorrect_style_properties_remove", incorrect_style_properties_remove); + prefs->setBool("/options/svgoutput/incorrect_attributes_remove", incorrect_attributes_remove); + prefs->setBool("/options/svgoutput/usenamedcolors", usenamedcolors); + prefs->setBool("/options/svgoutput/forcerepeatcommands", forcerepeatcommands); + prefs->setBool("/options/svgoutput/style_defaults_remove", style_defaults_remove); return; } @@ -686,57 +704,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<Inkscape::UI::Tools::NodeTool*>(ec); - } - } - - 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<Inkscape::UI::Node*>(*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."); - } + if (desktop) { + Inkscape::Selection * selection = desktop->getSelection(); + if (!selection->isEmpty()) { + selection->setBackup(); } + params = selection->params; + module->paramListString(params); } - }//end add selected nodes file_listener fileout; int data_read = execute(command, params, dc->_filename, fileout); @@ -790,6 +765,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 +774,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(); } @@ -833,12 +817,10 @@ void Script::copy_doc (Inkscape::XML::Node * oldroot, Inkscape::XML::Node * newr g_warning("Error on copy_doc: NULL pointer input."); return; } - // For copying attributes in root and in namedview using Inkscape::Util::List; using Inkscape::XML::AttributeRecord; std::vector<gchar const *> attribs; - // Must explicitly copy root attributes. This must be done first since // copying grid lines calls "SPGuide::set()" which needs to know the // width, height, and viewBox of the root element. @@ -859,80 +841,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<Inkscape::XML::Node *> 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<AttributeRecord const> 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<gchar const *>::const_iterator it = attribs.begin(); it != attribs.end(); ++it) { - oldroot_namedview->setAttribute(*it, NULL); - } - - // Set the new attributes. - for (List<AttributeRecord const> 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/internal/bitmap/imagemagick.cpp b/src/extension/internal/bitmap/imagemagick.cpp index 636b9d6a4..32d6f59e3 100644 --- a/src/extension/internal/bitmap/imagemagick.cpp +++ b/src/extension/internal/bitmap/imagemagick.cpp @@ -64,6 +64,16 @@ ImageMagickDocCache::ImageMagickDocCache(Inkscape::UI::View::View * view) : _imageItems(NULL) { 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(); + } + } + } auto selectedItemList = desktop->selection->items(); int selectCount = (int) boost::distance(selectedItemList); diff --git a/src/extension/internal/bluredge.cpp b/src/extension/internal/bluredge.cpp index f04007d00..c086405e5 100644 --- a/src/extension/internal/bluredge.cpp +++ b/src/extension/internal/bluredge.cpp @@ -53,7 +53,7 @@ BlurEdge::load (Inkscape::Extension::Extension */*module*/) void BlurEdge::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *desktop, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) { - Inkscape::Selection * selection = static_cast<SPDesktop *>(desktop)->selection; + float width = module->get_param_float("blur-width"); int steps = module->get_param_int("num-steps"); @@ -61,6 +61,17 @@ BlurEdge::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View Inkscape::Preferences *prefs = Inkscape::Preferences::get(); double old_offset = prefs->getDouble("/options/defaultoffsetwidth/value", 1.0, "px"); + SPDesktop *deskt = static_cast<SPDesktop *>(desktop); + Inkscape::Selection * selection = NULL; + if (deskt) { + selection = deskt->selection; + if (selection && !selection->params.empty()) { + selection->restoreBackup(); + if (!deskt->on_live_extension) { + selection->emptyBackup(); + } + } + } // TODO need to properly refcount the items, at least std::vector<SPItem*> items(selection->items().begin(), selection->items().end()); selection->clear(); diff --git a/src/extension/internal/filter/filter.cpp b/src/extension/internal/filter/filter.cpp index 166e5406f..af4997eba 100644 --- a/src/extension/internal/filter/filter.cpp +++ b/src/extension/internal/filter/filter.cpp @@ -122,8 +122,17 @@ void Filter::effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::Vie } //printf("Calling filter effect\n"); - Inkscape::Selection * selection = ((SPDesktop *)document)->selection; - + SPDesktop *desktop = (SPDesktop *)document; + Inkscape::Selection * selection = NULL; + if (desktop) { + selection = desktop->selection; + if (selection && !selection->params.empty()) { + selection->restoreBackup(); + if (!desktop->on_live_extension) { + selection->emptyBackup(); + } + } + } // TODO need to properly refcount the items, at least std::vector<SPItem*> items(selection->items().begin(), selection->items().end()); diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index c7ebf2494..6b3f2efe3 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -86,7 +86,17 @@ Glib::ustring build_lines(Geom::Rect bounding_area, void Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) { - Inkscape::Selection * selection = ((SPDesktop *)document)->selection; + SPDesktop *desktop = ((SPDesktop *)document); + Inkscape::Selection * selection = NULL; + if (desktop) { + selection = desktop->getSelection(); + if (selection && !selection->params.empty()) { + selection->restoreBackup(); + if (!desktop->on_live_extension) { + selection->emptyBackup(); + } + } + } Geom::Rect bounding_area = Geom::Rect(Geom::Point(0,0), Geom::Point(100,100)); if (selection->isEmpty()) { diff --git a/src/extension/prefdialog.cpp b/src/extension/prefdialog.cpp index 0247e18e9..4c799eb68 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); diff --git a/src/selection.cpp b/src/selection.cpp index b8dffb4ae..6c791f10f 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -28,8 +28,7 @@ #include "object/sp-shape.h" #include "object/sp-path.h" - -#include "xml/repr.h" +#include "object/sp-defs.h" #define SP_SELECTION_UPDATE_PRIORITY (G_PRIORITY_HIGH_IDLE + 1) @@ -179,6 +178,125 @@ void Selection::_releaseSignals(SPObject *object) { _modified_connections.erase(object); } +void +Selection::emptyBackup(){ + _selected_ids.clear(); + _seldata.clear(); + params.clear(); +} + +void +Selection::setBackup () +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + std::vector<SPItem*> selected_items = itemList(); + _selected_ids.clear(); + _seldata.clear(); + params.clear(); + for(std::vector<SPItem*>::const_iterator x = selected_items.begin(); x != selected_items.end(); ++x){ + std::string selected_id; + selected_id += "--id="; + selected_id += (*x)->getId(); + params.push_front(selected_id); + _selected_ids.push_back((*x)->getId()); + } + Inkscape::UI::Tools::NodeTool *tool = 0; + + Inkscape::UI::Tools::ToolBase *ec = desktop->event_context; + if (INK_IS_NODE_TOOL(ec)) { + tool = static_cast<Inkscape::UI::Tools::NodeTool*>(ec); + } + if(tool){ + Inkscape::UI::ControlPointSelection *cps = tool->_selected_nodes; + std::list<Inkscape::UI::SelectableControlPoint *> points_list = cps->_points_list; + for (std::list<Inkscape::UI::SelectableControlPoint *>::iterator i = points_list.begin(); i != points_list.end(); ++i) { + Inkscape::UI::Node *node = dynamic_cast<Inkscape::UI::Node*>(*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; + if (desktop) { + Inkscape::UI::Tools::NodeTool *tool = 0; + Inkscape::UI::Tools::ToolBase *ec = desktop->event_context; + if (INK_IS_NODE_TOOL(ec)) { + tool = static_cast<Inkscape::UI::Tools::NodeTool*>(ec); + } + clear(); + std::vector<std::string>::reverse_iterator rit = _selected_ids.rbegin(); + for (; rit!= _selected_ids.rend(); ++rit){ + SPObject * obj = desktop->doc()->getObjectById(rit->c_str()); + SPDefs * defs = desktop->getDocument()->getDefs(); + if (obj && !defs->isAncestorOf(obj)) { + add(obj); + } + } + if (tool) { + Inkscape::UI::ControlPointSelection *cps = tool->_selected_nodes; + cps->selectAll(); + std::list<Inkscape::UI::SelectableControlPoint *> points_list = cps->_points_list; + cps->clear(); + Inkscape::UI::Node * node = dynamic_cast<Inkscape::UI::Node*>(*points_list.begin()); + if (node) { + Inkscape::UI::SubpathList sp = node->nodeList().subpathList(); + for (std::vector<std::pair<std::string, std::pair<int, int> > >::iterator l = _seldata.begin(); l != _seldata.end(); ++l) { + SPPath * path = dynamic_cast<SPPath *>(desktop->doc()->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) { + k->select(true); + break; + } + } + break; + } + } + } + } + points_list.clear(); + } + } +} + + } /* diff --git a/src/selection.h b/src/selection.h index 2b454e947..989adf6b0 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<std::string> params; + protected: void _emitSignals(); void _connectSignals(SPObject* object); @@ -212,7 +229,8 @@ private: SPObject* _selection_context; unsigned int _flags; unsigned int _idle; - + std::vector<std::pair<std::string, std::pair<int, int> > > _seldata; + std::vector<std::string> _selected_ids; std::map<SPObject *, sigc::connection> _modified_connections; sigc::connection _context_release_connection; diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h index ec845b1b3..d0cfce8d2 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<Inkscape::SnapCandidatePoint> &pts); void getUnselectedPoints(std::vector<Inkscape::SnapCandidatePoint> &pts); void setOriginalPoints(); + //the purpose of this list is to keep track of first and last selected + std::list<SelectableControlPoint *> _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<SelectableControlPoint *> _points_list; + set_type _all_points; INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Point> _original_positions; INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Affine> _last_trans; diff --git a/src/ui/tool/selectable-control-point.cpp b/src/ui/tool/selectable-control-point.cpp index f3f9c0e1e..83ed7d38b 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 362d4addc..c16f639b1 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 29cfdab46..8d9fc19e4 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/simple-node.cpp b/src/xml/simple-node.cpp index 78fc52a27..a1a7127cc 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<Node *> 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<Node *>::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<AttributeRecord const> orig_attr = attributeList(); orig_attr; ++orig_attr) { + for (List<AttributeRecord const> 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<Node *>(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 f2cfa953c..fd41e53a8 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<AttributeRecord const> attributeList() const { return _attributes; |
