Merge branch 'cheesequake/refactoring-edit-cut' into 'master'

app: refactor code for 'cut' operation, allow cut for layer groups

See merge request GNOME/gimp!2340
This commit is contained in:
Cheesequake 2025-07-01 23:20:31 +05:30
commit 4d985aefc9
2 changed files with 38 additions and 57 deletions

View file

@ -282,7 +282,7 @@ edit_actions_update (GimpActionGroup *group,
gboolean undo_enabled = FALSE;
gboolean have_no_groups = FALSE; /* At least 1 selected layer is not a group. */
gboolean have_writable = FALSE; /* At least 1 selected layer has no contents lock. */
gboolean have_writable = TRUE; /* At least 1 selected layer has no contents lock. */
if (image)
{
@ -292,11 +292,30 @@ edit_actions_update (GimpActionGroup *group,
for (iter = drawables; iter; iter = iter->next)
{
if (! gimp_viewable_get_children (GIMP_VIEWABLE (iter->data)))
have_no_groups = TRUE;
GimpContainer *container = gimp_viewable_get_children (GIMP_VIEWABLE (iter->data));
if (! gimp_item_is_content_locked (GIMP_ITEM (iter->data), NULL))
have_writable = TRUE;
if (gimp_item_is_content_locked (GIMP_ITEM (iter->data), NULL))
have_writable = FALSE;
/* If we have a layer group, check if any of its children have
* content locked.
*/
if (! container)
{
have_no_groups = TRUE;
}
else
{
gint n_children = gimp_container_get_n_children (container);
for (gint i = 0; i < n_children; i++)
{
GimpObject *child = gimp_container_get_child_by_index (container, i);
if (gimp_item_is_content_locked (GIMP_ITEM (child), NULL))
have_writable = FALSE;
}
}
if (have_no_groups && have_writable)
break;
@ -351,7 +370,7 @@ edit_actions_update (GimpActionGroup *group,
g_free (undo_name);
g_free (redo_name);
SET_SENSITIVE ("edit-cut", have_writable && have_no_groups);
SET_SENSITIVE ("edit-cut", have_writable);
SET_SENSITIVE ("edit-copy", drawables);
SET_SENSITIVE ("edit-copy-visible", image);
/* "edit-paste" is always active */

View file

@ -93,66 +93,28 @@ gimp_edit_cut (GimpImage *image,
undo_label);
g_free (undo_label);
if (gimp_channel_is_empty (gimp_image_get_mask (image)))
/* With a layer, a 'cut' is the same as a 'copy' and
* then deleting layers/clearing selections
*/
if (gimp_edit_copy (image, drawables, context, TRUE, error))
{
GList *remove = NULL;
GimpImage *clip_image;
/* Let's work on a copy because we will edit the list to remove
* layers whose ancestor is also cut.
*/
drawables = g_list_copy (drawables);
for (iter = drawables; iter; iter = iter->next)
{
GList *iter2;
for (iter2 = drawables; iter2; iter2 = iter2->next)
if (! gimp_channel_is_empty (gimp_image_get_mask (image)))
{
if (iter2 == iter)
continue;
if (gimp_viewable_is_ancestor (iter2->data, iter->data))
{
/* When cutting a layer group, all its children come
* with anyway.
*/
remove = g_list_prepend (remove, iter);
break;
}
gimp_drawable_edit_clear (GIMP_DRAWABLE (iter->data), context);
}
else
{
if (! gimp_layer_is_floating_sel (iter->data))
gimp_image_remove_layer (image, GIMP_LAYER (iter->data),
TRUE, NULL);
}
}
for (iter = remove; iter; iter = iter->next)
drawables = g_list_delete_link (drawables, iter->data);
g_list_free (remove);
/* Now copy all layers into the clipboard image. */
clip_image = gimp_image_new_from_drawables (image->gimp, drawables, FALSE, TRUE);
gimp_container_remove (image->gimp->images, GIMP_OBJECT (clip_image));
gimp_set_clipboard_image (image->gimp, clip_image);
g_object_unref (clip_image);
/* Remove layers from source image. */
for (iter = drawables; iter; iter = iter->next)
if (! gimp_layer_is_floating_sel (iter->data))
gimp_image_remove_layer (image, GIMP_LAYER (iter->data),
TRUE, NULL);
g_list_free (drawables);
}
else
{
/* With selection, a cut is similar to a copy followed by a clear. */
if (gimp_edit_copy (image, drawables, context, TRUE, error))
{
for (iter = drawables; iter; iter = iter->next)
if (! GIMP_IS_GROUP_LAYER (iter->data))
gimp_drawable_edit_clear (GIMP_DRAWABLE (iter->data), context);
}
else
{
success = FALSE;
}
success = FALSE;
}
gimp_image_undo_group_end (image);