Code

optionally (default off) relink duplicated clones to the duplicated original
authorbuliabyak <buliabyak@users.sourceforge.net>
Tue, 5 Aug 2008 22:59:15 +0000 (22:59 +0000)
committerbuliabyak <buliabyak@users.sourceforge.net>
Tue, 5 Aug 2008 22:59:15 +0000 (22:59 +0000)
src/preferences-skeleton.h
src/selection-chemistry.cpp
src/ui/dialog/inkscape-preferences.cpp
src/ui/dialog/inkscape-preferences.h

index 7b762f8349ffe7446761f24008efb8bfccdae796..2fb29ac60fe8c7197e78c96ff2e2f0d0f76936e6 100644 (file)
@@ -190,6 +190,7 @@ static char const preferences_skeleton[] =
 "  </group>\n"
 "\n"
 "  <group id=\"options\">\n"
+"    <group id=\"relinkclonesonduplicate\" value=\"0\" />"
 "    <group id=\"mapalt\" value=\"1\" />"
 "    <group id=\"switchonextinput\" value=\"0\" />"
 "    <group id=\"useextinput\" value=\"1\" />"
index 114ed9c645a67470811fe9d9502201820303eab0..763cffa110e36ac03cbbdd1cd276d136be3a62b9 100644 (file)
@@ -220,14 +220,28 @@ void sp_selection_delete()
                      _("Delete"));
 }
 
-/* fixme: sequencing */
+void add_ids_recursive (std::vector<const gchar *> &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<const gchar *> old_ids;
+    std::vector<const gchar *> 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"));
index e7e8892caa012fbc7296a7d31161abe44c213522..ecedf6003031e89c59155d87c6f191373a56fe0b 100644 (file)
@@ -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);
 }
index b29004983d1a2516071e43e9ad77eb7ecd71649d..6efebb7427a7373ef7e3cf5a424dbe2d9ef9a4c0 100644 (file)
@@ -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;