app, pdb: layers-merge-layers* and image-merge-layers multi-layer aware.

Multi selection actually only really matter when "Merge within active
groups only" option is checked, in which case we are able to merge
layers within several layer groups simultaneously, and end up with
multi-selected merged layers.

Also not sure why both layers-merge-layers and image-merge-layers exist,
as they are exactly the same (exact same callback called when
activated).
This commit is contained in:
Jehan 2020-05-07 14:30:21 +02:00
parent 0ae4686172
commit 5964f72cea
9 changed files with 130 additions and 88 deletions

View file

@ -1040,7 +1040,7 @@ layers_actions_update (GimpActionGroup *group,
SET_SENSITIVE ("layers-merge-down-button", layer && !fs && !ac); SET_SENSITIVE ("layers-merge-down-button", layer && !fs && !ac);
SET_VISIBLE ("layers-merge-group", children); SET_VISIBLE ("layers-merge-group", children);
SET_SENSITIVE ("layers-merge-group", layer && !fs && !ac && children); SET_SENSITIVE ("layers-merge-group", layer && !fs && !ac && children);
SET_SENSITIVE ("layers-merge-layers", layer && !fs && !ac); SET_SENSITIVE ("layers-merge-layers", n_layers > 0 && !fs && !ac);
SET_SENSITIVE ("layers-flatten-image", layer && !fs && !ac); SET_SENSITIVE ("layers-flatten-image", layer && !fs && !ac);
SET_VISIBLE ("layers-text-discard", text_layer && !ac); SET_VISIBLE ("layers-text-discard", text_layer && !ac);

View file

@ -388,7 +388,7 @@ gimp_dialog_config_class_init (GimpDialogConfigClass *klass)
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_LAYER_MERGE_ACTIVE_GROUP_ONLY, GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_LAYER_MERGE_ACTIVE_GROUP_ONLY,
"layer-merge-active-group-only", "layer-merge-active-group-only",
"Default layer merge active group only", "Default layer merge active groups only",
LAYER_MERGE_ACTIVE_GROUP_ONLY_BLURB, LAYER_MERGE_ACTIVE_GROUP_ONLY_BLURB,
TRUE, TRUE,
GIMP_PARAM_STATIC_STRINGS); GIMP_PARAM_STATIC_STRINGS);

View file

@ -66,7 +66,7 @@ static GimpLayer * gimp_image_merge_layers (GimpImage *image,
/* public functions */ /* public functions */
GimpLayer * GList *
gimp_image_merge_visible_layers (GimpImage *image, gimp_image_merge_visible_layers (GimpImage *image,
GimpContext *context, GimpContext *context,
GimpMergeType merge_type, GimpMergeType merge_type,
@ -74,10 +74,11 @@ gimp_image_merge_visible_layers (GimpImage *image,
gboolean discard_invisible, gboolean discard_invisible,
GimpProgress *progress) GimpProgress *progress)
{ {
GimpContainer *container; const gchar *undo_desc = C_("undo-type", "Merge Visible Layers");
GList *list; GList *containers = NULL;
GSList *merge_list = NULL; GList *new_layers = NULL;
GSList *invisible_list = NULL; GList *iter;
GList *iter2;
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
@ -85,89 +86,119 @@ gimp_image_merge_visible_layers (GimpImage *image,
if (merge_active_group) if (merge_active_group)
{ {
GimpLayer *active_layer = gimp_image_get_active_layer (image); GList *selected_layers = gimp_image_get_selected_layers (image);
/* if the active layer is the floating selection, get the /* if the active layer is the floating selection, get the
* underlying drawable, but only if it is a layer * underlying drawable, but only if it is a layer
*/ */
if (active_layer && gimp_layer_is_floating_sel (active_layer)) if (g_list_length (selected_layers) == 1 && gimp_layer_is_floating_sel (selected_layers->data))
{ {
GimpDrawable *fs_drawable; GimpDrawable *fs_drawable;
fs_drawable = gimp_layer_get_floating_sel_drawable (active_layer); fs_drawable = gimp_layer_get_floating_sel_drawable (selected_layers->data);
if (GIMP_IS_LAYER (fs_drawable)) if (GIMP_IS_LAYER (fs_drawable))
active_layer = GIMP_LAYER (fs_drawable); containers = g_list_prepend (containers,
gimp_item_get_container (GIMP_ITEM (fs_drawable)));
} }
if (active_layer)
container = gimp_item_get_container (GIMP_ITEM (active_layer));
else else
container = gimp_image_get_layers (image);
}
else
{
container = gimp_image_get_layers (image);
}
for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (container));
list;
list = g_list_next (list))
{
GimpLayer *layer = list->data;
if (gimp_layer_is_floating_sel (layer))
continue;
if (gimp_item_get_visible (GIMP_ITEM (layer)))
{ {
merge_list = g_slist_append (merge_list, layer); for (iter = selected_layers; iter; iter = iter->next)
if (! gimp_item_get_parent (iter->data))
break;
/* No need to list selected groups if any selected layer is
* to-level.
*/
if (iter == NULL)
{
for (iter = selected_layers; iter; iter = iter->next)
{
for (iter2 = selected_layers; iter2; iter2 = iter2->next)
{
/* Only retain a selected layer's container if no
* other selected layers are its parents.
*/
if (iter->data != iter2->data &&
gimp_item_is_ancestor (iter->data, iter2->data))
break;
}
if (iter2 == NULL &&
! g_list_find (containers, gimp_item_get_container (GIMP_ITEM (iter->data))))
containers = g_list_prepend (containers,
gimp_item_get_container (GIMP_ITEM (iter->data)));
}
}
} }
else if (discard_invisible) }
if (! containers)
containers = g_list_prepend (NULL, gimp_image_get_layers (image));
gimp_set_busy (image->gimp);
gimp_image_undo_group_start (image,
GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE,
undo_desc);
for (iter = containers; iter; iter = iter->next)
{
GimpContainer *container = iter->data;
GSList *merge_list = NULL;
GSList *invisible_list = NULL;
for (iter2 = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (container));
iter2;
iter2 = g_list_next (iter2))
{ {
invisible_list = g_slist_append (invisible_list, layer); GimpLayer *layer = iter2->data;
if (gimp_layer_is_floating_sel (layer))
continue;
if (gimp_item_get_visible (GIMP_ITEM (layer)))
{
merge_list = g_slist_append (merge_list, layer);
}
else if (discard_invisible)
{
invisible_list = g_slist_append (invisible_list, layer);
}
}
if (merge_list)
{
GimpLayer *layer;
/* if there's a floating selection, anchor it */
if (gimp_image_get_floating_selection (image))
floating_sel_anchor (gimp_image_get_floating_selection (image));
layer = gimp_image_merge_layers (image,
container,
merge_list, context, merge_type,
undo_desc, progress);
g_slist_free (merge_list);
if (invisible_list)
{
GSList *list;
for (list = invisible_list; list; list = g_slist_next (list))
gimp_image_remove_layer (image, list->data, TRUE, NULL);
g_slist_free (invisible_list);
}
new_layers = g_list_prepend (new_layers, layer);
} }
} }
if (merge_list) gimp_image_set_selected_layers (image, new_layers);
{ gimp_image_undo_group_end (image);
GimpLayer *layer; gimp_unset_busy (image->gimp);
const gchar *undo_desc = C_("undo-type", "Merge Visible Layers");
gimp_set_busy (image->gimp); g_list_free (new_layers);
g_list_free (containers);
gimp_image_undo_group_start (image, return gimp_image_get_selected_layers (image);
GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE,
undo_desc);
/* if there's a floating selection, anchor it */
if (gimp_image_get_floating_selection (image))
floating_sel_anchor (gimp_image_get_floating_selection (image));
layer = gimp_image_merge_layers (image,
container,
merge_list, context, merge_type,
undo_desc, progress);
g_slist_free (merge_list);
if (invisible_list)
{
GSList *list;
for (list = invisible_list; list; list = g_slist_next (list))
gimp_image_remove_layer (image, list->data, TRUE, NULL);
g_slist_free (invisible_list);
}
gimp_image_undo_group_end (image);
gimp_unset_busy (image->gimp);
return layer;
}
return gimp_image_get_active_layer (image);
} }
GimpLayer * GimpLayer *

View file

@ -19,7 +19,7 @@
#define __GIMP_IMAGE_MERGE_H__ #define __GIMP_IMAGE_MERGE_H__
GimpLayer * gimp_image_merge_visible_layers (GimpImage *image, GList * gimp_image_merge_visible_layers (GimpImage *image,
GimpContext *context, GimpContext *context,
GimpMergeType merge_type, GimpMergeType merge_type,
gboolean merge_active_group, gboolean merge_active_group,

View file

@ -135,7 +135,7 @@ image_merge_layers_dialog_new (GimpImage *image,
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame); gtk_widget_show (frame);
button = gtk_check_button_new_with_mnemonic (_("Merge within active _group only")); button = gtk_check_button_new_with_mnemonic (_("Merge within active _groups only"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
private->merge_active_group); private->merge_active_group);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

View file

@ -2353,7 +2353,7 @@ prefs_dialog_new (Gimp *gimp,
GTK_GRID (grid), 0, size_group); GTK_GRID (grid), 0, size_group);
prefs_check_button_add (object, "layer-merge-active-group-only", prefs_check_button_add (object, "layer-merge-active-group-only",
_("Merge within active group only"), _("Merge within active groups only"),
GTK_BOX (vbox2)); GTK_BOX (vbox2));
prefs_check_button_add (object, "layer-merge-discard-invisible", prefs_check_button_add (object, "layer-merge-discard-invisible",
_("Discard invisible layers"), _("Discard invisible layers"),

View file

@ -618,16 +618,13 @@ file_open_layers (Gimp *gimp,
if (merge_visible && n_visible > 1) if (merge_visible && n_visible > 1)
{ {
GimpLayer *layer;
g_list_free (layers); g_list_free (layers);
layer = gimp_image_merge_visible_layers (new_image, context, layers = gimp_image_merge_visible_layers (new_image, context,
GIMP_CLIP_TO_IMAGE, GIMP_CLIP_TO_IMAGE,
FALSE, FALSE, FALSE, FALSE,
NULL); NULL);
layers = g_list_copy (layers);
layers = g_list_prepend (NULL, layer);
} }
if (layers) if (layers)

View file

@ -1393,9 +1393,16 @@ image_merge_visible_layers_invoker (GimpProcedure *procedure,
if (success) if (success)
{ {
layer = gimp_image_merge_visible_layers (image, context, merge_type, GList *layers;
FALSE, FALSE,
progress); layers = gimp_image_merge_visible_layers (image, context, merge_type,
FALSE, FALSE, progress);
if (layers)
/* With merge_selected_groups set to FALSE, we always get only a
* single selected layer.
*/
layer = layers->data;
if (! layer) if (! layer)
success = FALSE; success = FALSE;

View file

@ -737,9 +737,16 @@ HELP
headers => [ qw("core/gimpimage-merge.h") ], headers => [ qw("core/gimpimage-merge.h") ],
code => <<'CODE' code => <<'CODE'
{ {
layer = gimp_image_merge_visible_layers (image, context, merge_type, GList *layers;
FALSE, FALSE,
progress); layers = gimp_image_merge_visible_layers (image, context, merge_type,
FALSE, FALSE, progress);
if (layers)
/* With merge_selected_groups set to FALSE, we always get only a
* single selected layer.
*/
layer = layers->data;
if (! layer) if (! layer)
success = FALSE; success = FALSE;