From 526a7dda3eed65d4874e84355781b487f406f631 Mon Sep 17 00:00:00 2001 From: ChristiaanSmith <11035832+ChristiaanSmith@users.noreply.github.com> Date: Wed, 5 May 2021 00:53:10 +0100 Subject: [PATCH] Fix #2389 - cannot clone object without id attribute Selected objects without an ID attribute are assigned one so that they can be cloned. Moved enforceObjectIds method from SPDocument to ObjectSet. Removed unnecessary InfoDialog from enforceIds method. Changed the order of #includes in object-set.cpp to comply with the clang-format style checker. --- src/document.cpp | 31 ------------------------------- src/document.h | 1 - src/extension/execution-env.cpp | 17 +++++++++++------ src/object/object-set.cpp | 31 ++++++++++++++++++++++++++----- src/object/object-set.h | 6 ++++++ src/selection-chemistry.cpp | 3 +++ 6 files changed, 46 insertions(+), 43 deletions(-) diff --git a/src/document.cpp b/src/document.cpp index 226a5a3324..712dacc1b7 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1011,37 +1011,6 @@ void SPDocument::bindObjectToId(gchar const *id, SPObject *object) { } } -/** - * Assign IDs to selected objects that don't have an ID attribute - * Checks if the object's id attribute is NULL. If it is, assign it a unique ID - */ -void SPDocument::enforceObjectIds() -{ - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - Inkscape::Selection *selection = desktop->getSelection(); - bool showInfoDialog = false; - Glib::ustring msg = _("Selected objects require IDs.\nThe following IDs have been assigned:\n"); - auto items = selection->items(); - for (auto iter = items.begin(); iter != items.end(); ++iter) { - SPItem *item = *iter; - if(!item->getId()) - { - // Selected object does not have an ID, so assign it a unique ID - gchar *id = sp_object_get_unique_id(item, nullptr); - item->setAttribute("id", id); - item->updateRepr(); - msg += Glib::ustring::compose(_(" %1\n"), id); - g_free(id); - showInfoDialog = true; - } - } - if(showInfoDialog) { - desktop->showInfoDialog(msg); - setModifiedSinceSave(true); - } - return; -} - SPObject *SPDocument::getObjectById(Glib::ustring const &id) const { if (iddef.empty()) { diff --git a/src/document.h b/src/document.h index a04c19d1ec..e81051a577 100644 --- a/src/document.h +++ b/src/document.h @@ -240,7 +240,6 @@ public: // Find items ----------------------------- void bindObjectToId(char const *id, SPObject *object); - void enforceObjectIds(); SPObject *getObjectById(Glib::ustring const &id) const; SPObject *getObjectById(char const *id) const; diff --git a/src/extension/execution-env.cpp b/src/extension/execution-env.cpp index 1d62be9848..8f197438de 100644 --- a/src/extension/execution-env.cpp +++ b/src/extension/execution-env.cpp @@ -50,13 +50,18 @@ ExecutionEnv::ExecutionEnv (Effect * effect, Inkscape::UI::View::View * doc, Imp _effect(effect), _show_working(show_working) { - SPDocument* document = _doc->doc(); - if(document) { - Inkscape::DocumentUndo::setUndoSensitive(document, false); - document->enforceObjectIds(); // Make sure all selected objects have an ID attribute - Inkscape::DocumentUndo::setUndoSensitive(document, true); + SPDesktop *desktop = (SPDesktop *)_doc; + SPDocument *document = _doc->doc(); + if (document && desktop) { + // Temporarily prevent undo in this scope + Inkscape::DocumentUndo::ScopedInsensitive pauseUndo(document); + Inkscape::Selection *selection = desktop->getSelection(); + if (selection) { + // Make sure all selected objects have an ID attribute + selection->enforceIds(); + } } - + genDocCache(); return; diff --git a/src/object/object-set.cpp b/src/object/object-set.cpp index 3a60baae47..43863956c8 100644 --- a/src/object/object-set.cpp +++ b/src/object/object-set.cpp @@ -10,14 +10,16 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ -#include -#include #include "object-set.h" + +#include +#include +#include +#include + #include "box3d.h" #include "persp3d.h" #include "preferences.h" -#include -#include namespace Inkscape { @@ -300,7 +302,26 @@ void ObjectSet::setReprList(std::vector const &list) { _emitChanged(); } - +void ObjectSet::enforceIds() +{ + bool idAssigned = false; + auto items = this->items(); + for (auto *item : items) { + if (!item->getId()) { + // Selected object does not have an ID, so assign it a unique ID + gchar *id = sp_object_get_unique_id(item, nullptr); + item->setAttribute("id", id); + g_free(id); + idAssigned = true; + } + } + if (idAssigned) { + SPDocument *document = _desktop->getDocument(); + if (document) { + document->setModifiedSinceSave(true); + } + } +} Geom::OptRect ObjectSet::bounds(SPItem::BBoxType type) const { diff --git a/src/object/object-set.h b/src/object/object-set.h index 2a9141f6aa..f421e46dfc 100644 --- a/src/object/object-set.h +++ b/src/object/object-set.h @@ -293,6 +293,12 @@ public: */ void setReprList(std::vector const &list); + /** + * Assign IDs to selected objects that don't have an ID attribute + * Checks if the object's id attribute is NULL. If it is, assign it a unique ID + */ + void enforceIds(); + /** * Adds the specified objects to selection, without deselecting first. * diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 432fac4470..5271b2d368 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -2666,6 +2666,9 @@ void ObjectSet::clone() return; } + // Assign IDs to selected objects that don't have an ID attribute + enforceIds(); + std::vector reprs(xmlNodes().begin(), xmlNodes().end()); clear(); -- GitLab