From 7ef35e764d2bf79b9f4d77abec7fe2442559c877 Mon Sep 17 00:00:00 2001 From: buliabyak Date: Tue, 5 Aug 2008 22:59:15 +0000 Subject: [PATCH] optionally (default off) relink duplicated clones to the duplicated original --- src/preferences-skeleton.h | 1 + src/selection-chemistry.cpp | 62 +++++++++++++++++++++++--- src/ui/dialog/inkscape-preferences.cpp | 6 +++ src/ui/dialog/inkscape-preferences.h | 1 + 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index 7b762f834..2fb29ac60 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -190,6 +190,7 @@ static char const preferences_skeleton[] = " \n" "\n" " \n" +" " " " " " " " diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 114ed9c64..763cffa11 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -220,14 +220,28 @@ void sp_selection_delete() _("Delete")); } -/* fixme: sequencing */ +void add_ids_recursive (std::vector &ids, SPObject *obj) +{ + if (!obj) + return; + + ids.push_back(SP_OBJECT_ID(obj)); + + if (SP_IS_GROUP(obj)) { + for (SPObject *child = sp_object_first_child(obj) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { + add_ids_recursive (ids, child); + } + } +} + void sp_selection_duplicate(bool suppressDone) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (desktop == NULL) return; - Inkscape::XML::Document* xml_doc = sp_document_repr_doc(desktop->doc()); + SPDocument *doc = desktop->doc(); + Inkscape::XML::Document* xml_doc = sp_document_repr_doc(doc); Inkscape::Selection *selection = sp_desktop_selection(desktop); // check if something is selected @@ -240,22 +254,60 @@ void sp_selection_duplicate(bool suppressDone) selection->clear(); - // sorting items from different parents sorts each parent's subset without possibly mixing them, just what we need + // sorting items from different parents sorts each parent's subset without possibly mixing + // them, just what we need reprs = g_slist_sort(reprs, (GCompareFunc) sp_repr_compare_position); GSList *newsel = NULL; + std::vector old_ids; + std::vector new_ids; + bool relink_clones = prefs_get_int_attribute ("options.relinkclonesonduplicate", "value", 0); + while (reprs) { - Inkscape::XML::Node *parent = ((Inkscape::XML::Node *) reprs->data)->parent(); - Inkscape::XML::Node *copy = ((Inkscape::XML::Node *) reprs->data)->duplicate(xml_doc); + Inkscape::XML::Node *old_repr = (Inkscape::XML::Node *) reprs->data; + Inkscape::XML::Node *parent = old_repr->parent(); + Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); parent->appendChild(copy); + if (relink_clones) { + SPObject *old_obj = doc->getObjectByRepr(old_repr); + SPObject *new_obj = doc->getObjectByRepr(copy); + add_ids_recursive (old_ids, old_obj); + add_ids_recursive (new_ids, new_obj); + } + newsel = g_slist_prepend(newsel, copy); reprs = g_slist_remove(reprs, reprs->data); Inkscape::GC::release(copy); } + if (relink_clones) { + + g_assert (old_ids.size() == new_ids.size()); + + for(int i = 0; i < old_ids.size(); i++) { + const gchar *id = old_ids[i]; + SPObject *old_clone = doc->getObjectById(id); + if (SP_IS_USE(old_clone)) { + SPItem *orig = sp_use_get_original(SP_USE(old_clone)); + for(int j = 0; j < old_ids.size(); j++) { + if (!strcmp(SP_OBJECT_ID(orig), old_ids[j])) { + // we have both orig and clone in selection, relink + // std::cout << id << " old, its ori: " << SP_OBJECT_ID(orig) << "; will relink:" << new_ids[i] << " to " << new_ids[j] << "\n"; + gchar *newref = g_strdup_printf ("#%s", new_ids[j]); + SPObject *new_clone = doc->getObjectById(new_ids[i]); + SP_OBJECT_REPR(new_clone)->setAttribute("xlink:href", newref); + new_clone->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + g_free (newref); + } + } + } + } + } + + if ( !suppressDone ) { sp_document_done(sp_desktop_document(desktop), SP_VERB_EDIT_DUPLICATE, _("Duplicate")); diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index e7e8892ca..ecedf6003 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -571,6 +571,12 @@ void InkscapePreferences::initPageClones() _page_clones.add_line( true, "", _clone_option_delete, "", _("Orphaned clones are deleted along with their original.")); + _page_clones.add_group_header( _("When duplicating original+clones:")); + + _clone_relink_on_duplicate.init ( _("Relink duplicated clones"), "options.relinkclonesonduplicate", "value", false); + _page_clones.add_line(true, "", _clone_relink_on_duplicate, "", + _("When duplicating a selection containing both a clone and its original (possibly in groups), relink the duplicated clone to the duplicated original instead of the old original")); + //TRANSLATORS: Heading for the Inkscape Preferences "Clones" Page this->AddPage(_page_clones, _("Clones"), PREFS_PAGE_CLONES); } diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index b29004983..6efebb742 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -147,6 +147,7 @@ protected: PrefRadioButton _clone_option_parallel, _clone_option_stay, _clone_option_transform, _clone_option_unlink, _clone_option_delete; + PrefCheckButton _clone_relink_on_duplicate; PrefCheckButton _mask_mask_on_top; PrefCheckButton _mask_mask_remove; -- 2.30.2