summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarc Jeanmougin <marc@jeanmougin.fr>2016-11-06 22:07:52 +0000
committerMarc Jeanmougin <marcjeanmougin@free.fr>2016-11-06 22:07:52 +0000
commit9fa25f65a98bbd4abd3673b968ed5252cf9f14b3 (patch)
tree8d7a8bb5db62bce3ed50563f2c44dd6fcb83e512 /src
parentFix some bugs on pen/cil dropdown shapes (diff)
parentFix selection issue with ObjectSet::unlinkRecursive() and add tests for it. (diff)
downloadinkscape-9fa25f65a98bbd4abd3673b968ed5252cf9f14b3.tar.gz
inkscape-9fa25f65a98bbd4abd3673b968ed5252cf9f14b3.zip
merge recursive unlink clones branch
(bzr r15220)
Diffstat (limited to 'src')
-rw-r--r--src/menus-skeleton.h1
-rw-r--r--src/object-set.h16
-rw-r--r--src/selection-chemistry.cpp128
-rw-r--r--src/verbs.cpp5
-rw-r--r--src/verbs.h1
5 files changed, 112 insertions, 39 deletions
diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h
index 9c7c65140..75302806b 100644
--- a/src/menus-skeleton.h
+++ b/src/menus-skeleton.h
@@ -66,6 +66,7 @@ static char const menus_skeleton[] =
" <verb verb-id=\"EditClone\" />\n"
" <verb verb-id=\"DialogClonetiler\" />\n"
" <verb verb-id=\"EditUnlinkClone\" />\n"
+" <verb verb-id=\"EditUnlinkCloneRecursive\" />\n"
" <verb verb-id=\"EditRelinkClone\" />\n"
" <verb verb-id=\"EditCloneSelectOriginal\" />\n"
" <verb verb-id=\"EditCloneOriginalPathLPE\" />\n"
diff --git a/src/object-set.h b/src/object-set.h
index 47a2efb9d..12f2cb101 100644
--- a/src/object-set.h
+++ b/src/object-set.h
@@ -330,7 +330,19 @@ public:
void deleteItems();
void duplicate(bool suppressDone = false, bool duplicateLayer = false);
void clone();
- void unlink();
+
+ /**
+ * @brief Unlink all directly selected clones.
+ * @param skip_undo If this is set to true the call to DocumentUndo::done is omitted.
+ * @return True if anything was unlinked, otherwise false.
+ */
+ bool unlink(const bool skip_undo = false);
+ /**
+ * @brief Recursively unlink any clones present in the current selection,
+ * including clones which are used to clip other objects, groups of clones etc.
+ * @return true if anything was unlinked, otherwise false.
+ */
+ bool unlinkRecursive(const bool skip_undo = false);
void relink();
void cloneOriginal();
void cloneOriginalPathLPE();
@@ -376,7 +388,7 @@ public:
void createBitmapCopy();
void setMask(bool apply_clip_path, bool apply_to_layer = false, bool skip_undo = false);
void editMask(bool clip);
- void unsetMask(bool apply_clip_path);
+ void unsetMask(const bool apply_clip_path, const bool skip_undo = false);
void setClipGroup();
// moves
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index cd61ffba3..f8ab33ac4 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -2653,12 +2653,12 @@ void ObjectSet::relink()
}
-void ObjectSet::unlink()
+bool ObjectSet::unlink(const bool skip_undo)
{
if (isEmpty()) {
if(desktop())
desktop()->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>clones</b> to unlink."));
- return;
+ return false;
}
// Get a copy of current selection.
@@ -2669,41 +2669,59 @@ void ObjectSet::unlink()
for (auto i=items_.rbegin();i!=items_.rend();++i){
SPItem *item = *i;
- if (dynamic_cast<SPText *>(item)) {
- SPObject *tspan = sp_tref_convert_to_tspan(item);
-
- if (tspan) {
- item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- }
-
- // Set unlink to true, and fall into the next if which
- // will include this text item in the new selection
- unlinked = true;
+ ObjectSet tmp_set(document());
+ tmp_set.set(item);
+ Inkscape::URIReference *clip = item->clip_ref;
+ Inkscape::URIReference *mask = item->mask_ref;
+ if ((NULL != clip) && (NULL != clip->getObject())) {
+ tmp_set.unsetMask(true,true);
+ unlinked = tmp_set.unlink(true) || unlinked;
+ tmp_set.setMask(true,false,true);
+ new_select.push_back(tmp_set.singleItem());
}
-
- if (!(dynamic_cast<SPUse *>(item) || dynamic_cast<SPTRef *>(item))) {
- // keep the non-use item in the new selection
- new_select.push_back(item);
- continue;
+ else if ((NULL != mask) && (NULL != mask->getObject())) {
+ tmp_set.unsetMask(false,true);
+ unlinked = tmp_set.unlink(true) || unlinked;
+ tmp_set.setMask(false,false,true);
+ new_select.push_back(tmp_set.singleItem());
}
+ else {
+ if (dynamic_cast<SPText *>(item)) {
+ SPObject *tspan = sp_tref_convert_to_tspan(item);
+
+ if (tspan) {
+ item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+
+ // Set unlink to true, and fall into the next if which
+ // will include this text item in the new selection
+ unlinked = true;
+ }
- SPItem *unlink = NULL;
- SPUse *use = dynamic_cast<SPUse *>(item);
- if (use) {
- unlink = use->unlink();
- // Unable to unlink use (external or invalid href?)
- if (!unlink) {
+ if (!(dynamic_cast<SPUse *>(item) || dynamic_cast<SPTRef *>(item))) {
+ // keep the non-use item in the new selection
new_select.push_back(item);
continue;
}
- } else /*if (SP_IS_TREF(use))*/ {
- unlink = dynamic_cast<SPItem *>(sp_tref_convert_to_tspan(item));
- g_assert(unlink != NULL);
- }
- unlinked = true;
- // Add ungrouped items to the new selection.
- new_select.push_back(unlink);
+ SPItem *unlink = NULL;
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if (use) {
+ unlink = use->unlink();
+ // Unable to unlink use (external or invalid href?)
+ if (!unlink) {
+ new_select.push_back(item);
+ continue;
+ }
+ } else /*if (SP_IS_TREF(use))*/ {
+ unlink = dynamic_cast<SPItem *>(sp_tref_convert_to_tspan(item));
+ g_assert(unlink != NULL);
+ }
+
+ unlinked = true;
+ // Add ungrouped items to the new selection.
+ new_select.push_back(unlink);
+ }
}
if (!new_select.empty()) { // set new selection
@@ -2715,8 +2733,42 @@ void ObjectSet::unlink()
desktop()->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No clones to unlink</b> in the selection."));
}
- DocumentUndo::done(document(), SP_VERB_EDIT_UNLINK_CLONE,
- _("Unlink clone"));
+ if (!skip_undo) {
+ DocumentUndo::done(document(), SP_VERB_EDIT_UNLINK_CLONE,
+ _("Unlink clone"));
+ }
+ return unlinked;
+}
+
+bool ObjectSet::unlinkRecursive(const bool skip_undo) {
+ if (isEmpty()){
+ if (desktop())
+ desktop()->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>clones</b> to unlink."));
+ return false;
+ }
+ bool unlinked = false;
+ ObjectSet tmp_set(document());
+ std::vector<SPItem*> items_(items().begin(), items().end());
+ for (auto& it:items_) {
+ tmp_set.set(it);
+ unlinked = tmp_set.unlink(true) || unlinked;
+ it = tmp_set.singleItem();
+ if (SP_IS_GROUP(it)) {
+ std::vector<SPObject*> c = it->childList(false);
+ tmp_set.setList(c);
+ unlinked = tmp_set.unlinkRecursive(true) || unlinked;
+ }
+ }
+ if (!unlinked) {
+ if(desktop())
+ desktop()->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No clones to unlink</b> in the selection."));
+ }
+ if (!skip_undo) {
+ DocumentUndo::done(document(), SP_VERB_EDIT_UNLINK_CLONE_RECURSIVE,
+ _("Unlink clone recursively"));
+ }
+ setList(items_);
+ return unlinked;
}
void ObjectSet::cloneOriginal()
@@ -3960,7 +4012,7 @@ void ObjectSet::setClipGroup()
}
}
-void ObjectSet::unsetMask(bool apply_clip_path) {
+void ObjectSet::unsetMask(const bool apply_clip_path, const bool skip_undo) {
SPDocument *doc = document();
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
@@ -4082,10 +4134,12 @@ void ObjectSet::unsetMask(bool apply_clip_path) {
// rebuild selection
addList(items_to_select);
- if (apply_clip_path) {
- DocumentUndo::done(doc, SP_VERB_OBJECT_UNSET_CLIPPATH, _("Release clipping path"));
- } else {
- DocumentUndo::done(doc, SP_VERB_OBJECT_UNSET_MASK, _("Release mask"));
+ if (!skip_undo) {
+ if (apply_clip_path) {
+ DocumentUndo::done(doc, SP_VERB_OBJECT_UNSET_CLIPPATH, _("Release clipping path"));
+ } else {
+ DocumentUndo::done(doc, SP_VERB_OBJECT_UNSET_MASK, _("Release mask"));
+ }
}
}
diff --git a/src/verbs.cpp b/src/verbs.cpp
index c2167f67c..a5426f324 100644
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
@@ -1009,6 +1009,9 @@ void EditVerb::perform(SPAction *action, void *data)
case SP_VERB_EDIT_UNLINK_CLONE:
dt->selection->unlink();
break;
+ case SP_VERB_EDIT_UNLINK_CLONE_RECURSIVE:
+ dt->selection->unlinkRecursive();
+ break;
case SP_VERB_EDIT_RELINK_CLONE:
dt->selection->relink();
break;
@@ -2530,6 +2533,8 @@ Verb *Verb::_base_verbs[] = {
N_("Create a clone (a copy linked to the original) of selected object"), INKSCAPE_ICON("edit-clone")),
new EditVerb(SP_VERB_EDIT_UNLINK_CLONE, "EditUnlinkClone", N_("Unlin_k Clone"),
N_("Cut the selected clones' links to the originals, turning them into standalone objects"), INKSCAPE_ICON("edit-clone-unlink")),
+ new EditVerb(SP_VERB_EDIT_UNLINK_CLONE_RECURSIVE, "EditUnlinkCloneRecursive", N_("Unlink Clones _recursively"),
+ N_("Unlink all clones in the selection, even if they are in groups."), INKSCAPE_ICON("edit-clone-unlink")),
new EditVerb(SP_VERB_EDIT_RELINK_CLONE, "EditRelinkClone", N_("Relink to Copied"),
N_("Relink the selected clones to the object currently on the clipboard"), NULL),
new EditVerb(SP_VERB_EDIT_CLONE_SELECT_ORIGINAL, "EditCloneSelectOriginal", N_("Select _Original"),
diff --git a/src/verbs.h b/src/verbs.h
index 1780e0ebf..d7e966ae4 100644
--- a/src/verbs.h
+++ b/src/verbs.h
@@ -83,6 +83,7 @@ enum {
SP_VERB_EDIT_DUPLICATE,
SP_VERB_EDIT_CLONE,
SP_VERB_EDIT_UNLINK_CLONE,
+ SP_VERB_EDIT_UNLINK_CLONE_RECURSIVE,
SP_VERB_EDIT_RELINK_CLONE,
SP_VERB_EDIT_CLONE_SELECT_ORIGINAL,
SP_VERB_EDIT_CLONE_ORIGINAL_PATH_LPE,