1
1
mirror of https://gitlab.gnome.org/GNOME/gimp.git synced 2025-10-06 05:22:40 +02:00

app, menus, pdb: new file-open-as-link-layers action.

Revert the logic of opening all files as link layers back into loading
their current content as normal layers.
Instead just add a new action dedicated to open images as link layers
and add it to the File menu.

Per UX discussions with Aryeom.
This commit is contained in:
Jehan
2025-08-26 16:44:38 +02:00
parent 8280058c5a
commit 66cdecb0fa
14 changed files with 209 additions and 119 deletions

View File

@@ -82,6 +82,12 @@ static const GimpActionEntry file_actions[] =
file_open_as_layers_cmd_callback,
GIMP_HELP_FILE_OPEN_AS_LAYER },
{ "file-open-as-link-layers", GIMP_ICON_LAYER,
NC_("file-action", "Op_en as Link Layer..."), NULL, { "<primary><alt><shift>O", NULL },
NC_("file-action", "Open an image file as Link layer"),
file_open_as_link_layer_cmd_callback,
GIMP_HELP_FILE_OPEN_AS_LAYER },
{ "file-open-location", GIMP_ICON_WEB,
NC_("file-action", "Open _Location..."), NULL, { NULL },
NC_("file-action", "Open an image file from a specified location"),

View File

@@ -73,7 +73,8 @@ static void file_open_dialog_show (Gimp *gimp,
const gchar *title,
GimpImage *image,
GFile *file,
gboolean open_as_layers);
gboolean open_as_layers,
gboolean open_as_link);
static GtkWidget * file_save_dialog_show (Gimp *gimp,
GimpImage *image,
GtkWidget *parent,
@@ -118,7 +119,7 @@ file_open_cmd_callback (GimpAction *action,
file_open_dialog_show (gimp, widget,
_("Open Image"),
image, NULL, FALSE);
image, NULL, FALSE, FALSE);
}
void
@@ -140,7 +141,29 @@ file_open_as_layers_cmd_callback (GimpAction *action,
file_open_dialog_show (gimp, widget,
_("Open Image as Layers"),
image, NULL, TRUE);
image, NULL, TRUE, FALSE);
}
void
file_open_as_link_layer_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data)
{
Gimp *gimp;
GtkWidget *widget;
GimpDisplay *display;
GimpImage *image = NULL;
return_if_no_gimp (gimp, data);
return_if_no_widget (widget, data);
display = action_data_get_display (data);
if (display)
image = gimp_display_get_image (display);
file_open_dialog_show (gimp, widget,
_("Open Image as Link Layer"),
image, NULL, TRUE, TRUE);
}
void
@@ -577,7 +600,7 @@ file_file_open_dialog (Gimp *gimp,
{
file_open_dialog_show (gimp, parent,
_("Open Image"),
NULL, file, FALSE);
NULL, file, FALSE, FALSE);
}
@@ -589,7 +612,8 @@ file_open_dialog_show (Gimp *gimp,
const gchar *title,
GimpImage *image,
GFile *file,
gboolean open_as_layers)
gboolean open_as_layers,
gboolean open_as_link)
{
GtkWidget *dialog;
@@ -621,7 +645,7 @@ file_open_dialog_show (Gimp *gimp,
gtk_window_set_title (GTK_WINDOW (dialog), title);
gimp_open_dialog_set_image (GIMP_OPEN_DIALOG (dialog),
image, open_as_layers);
image, open_as_layers, open_as_link);
gtk_window_set_transient_for (GTK_WINDOW (dialog),
GTK_WINDOW (gtk_widget_get_toplevel (parent)));

View File

@@ -24,6 +24,9 @@ void file_open_cmd_callback (GimpAction *action,
void file_open_as_layers_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
void file_open_as_link_layer_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);
void file_open_location_cmd_callback (GimpAction *action,
GVariant *value,
gpointer data);

View File

@@ -55,11 +55,13 @@ static void file_open_dialog_response (GtkWidget *dialog,
static GimpImage *file_open_dialog_open_image (GtkWidget *dialog,
Gimp *gimp,
GFile *file,
GimpPlugInProcedure *load_proc);
GimpPlugInProcedure *load_proc,
gboolean as_link);
static gboolean file_open_dialog_open_layers (GtkWidget *dialog,
GimpImage *image,
GFile *file,
GimpPlugInProcedure *load_proc);
GimpPlugInProcedure *load_proc,
gboolean as_link);
/* public functions */
@@ -147,13 +149,14 @@ file_open_dialog_response (GtkWidget *dialog,
{
if (! file_dialog->image)
{
gimp_open_dialog_set_image (
open_dialog,
gimp_open_dialog_set_image (open_dialog,
file_open_dialog_open_image (dialog,
gimp,
file,
file_dialog->file_proc),
TRUE);
file_dialog->file_proc,
open_dialog->open_as_link),
TRUE,
open_dialog->open_as_link);
if (file_dialog->image)
{
@@ -170,7 +173,8 @@ file_open_dialog_response (GtkWidget *dialog,
else if (file_open_dialog_open_layers (dialog,
file_dialog->image,
file,
file_dialog->file_proc))
file_dialog->file_proc,
open_dialog->open_as_link))
{
success = TRUE;
}
@@ -180,7 +184,8 @@ file_open_dialog_response (GtkWidget *dialog,
if (file_open_dialog_open_image (dialog,
gimp,
file,
file_dialog->file_proc))
file_dialog->file_proc,
open_dialog->open_as_link))
{
success = TRUE;
@@ -227,7 +232,8 @@ static GimpImage *
file_open_dialog_open_image (GtkWidget *dialog,
Gimp *gimp,
GFile *file,
GimpPlugInProcedure *load_proc)
GimpPlugInProcedure *load_proc,
gboolean as_link)
{
GimpImage *image;
GimpPDBStatusType status;
@@ -236,7 +242,7 @@ file_open_dialog_open_image (GtkWidget *dialog,
image = file_open_with_proc_and_display (gimp,
gimp_get_user_context (gimp),
GIMP_PROGRESS (dialog),
file, FALSE,
file, FALSE, as_link,
load_proc,
G_OBJECT (gimp_widget_get_monitor (dialog)),
&status, &error);
@@ -256,7 +262,8 @@ static gboolean
file_open_dialog_open_layers (GtkWidget *dialog,
GimpImage *image,
GFile *file,
GimpPlugInProcedure *load_proc)
GimpPlugInProcedure *load_proc,
gboolean as_link)
{
GList *new_layers;
GimpPDBStatusType status;
@@ -265,7 +272,7 @@ file_open_dialog_open_layers (GtkWidget *dialog,
new_layers = file_open_layers (image->gimp,
gimp_get_user_context (image->gimp),
GIMP_PROGRESS (dialog),
image, FALSE,
image, FALSE, as_link,
file, GIMP_RUN_INTERACTIVE, load_proc,
&status, &error);

View File

@@ -204,7 +204,7 @@ file_open_location_response (GtkDialog *dialog,
image = file_open_with_proc_and_display (gimp,
gimp_get_user_context (gimp),
GIMP_PROGRESS (box),
file, FALSE, NULL,
file, FALSE, FALSE, NULL,
G_OBJECT (gimp_widget_get_monitor (entry)),
&status, &error);

View File

@@ -571,7 +571,7 @@ gimp_display_shell_drop_uri_list (GtkWidget *widget,
new_layers = file_open_layers (shell->display->gimp, context,
GIMP_PROGRESS (shell->display),
image, FALSE,
image, FALSE, FALSE,
file, GIMP_RUN_INTERACTIVE, NULL,
&status, &error);

View File

@@ -55,7 +55,7 @@
#include "gimp-intl.h"
static GimpImage * file_open_or_link_image (Gimp *gimp,
static GimpImage * file_open_link_image (Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
GFile *file,
@@ -78,6 +78,8 @@ static GList * file_open_get_layers (GimpImage *image,
gboolean merge_visible,
gint *n_visible);
static gboolean file_open_file_proc_is_import (GimpPlugInProcedure *file_proc);
static gboolean file_open_valid_permissions (GFile *file,
GError **error);
/* public functions */
@@ -135,46 +137,8 @@ file_open_image (Gimp *gimp,
}
}
/* FIXME enable these tests for remote files again, needs testing */
if (g_file_is_native (file))
{
GFileInfo *info;
info = g_file_query_info (file,
G_FILE_ATTRIBUTE_STANDARD_TYPE ","
G_FILE_ATTRIBUTE_ACCESS_CAN_READ,
G_FILE_QUERY_INFO_NONE,
NULL, error);
if (info != NULL)
{
if (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) != G_FILE_TYPE_REGULAR)
{
g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("Not a regular file"));
g_object_unref (info);
if (! file_open_valid_permissions (file, error))
return NULL;
}
if (! g_file_info_get_attribute_boolean (info,
G_FILE_ATTRIBUTE_ACCESS_CAN_READ))
{
g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("Permission denied"));
g_object_unref (info);
return NULL;
}
g_object_unref (info);
}
else
{
/* File likely does not exists. error will already have a more
* accurate reason.
*/
return NULL;
}
}
if (! file_proc)
file_proc = gimp_plug_in_manager_file_procedure_find (gimp->plug_in_manager,
@@ -519,9 +483,8 @@ file_open_with_display (Gimp *gimp,
GError **error)
{
return file_open_with_proc_and_display (gimp, context, progress,
file, as_new, NULL,
monitor,
status, error);
file, as_new, FALSE, NULL,
monitor, status, error);
}
GimpImage *
@@ -530,6 +493,7 @@ file_open_with_proc_and_display (Gimp *gimp,
GimpProgress *progress,
GFile *file,
gboolean as_new,
gboolean as_link,
GimpPlugInProcedure *file_proc,
GObject *monitor,
GimpPDBStatusType *status,
@@ -549,7 +513,18 @@ file_open_with_proc_and_display (Gimp *gimp,
if (gimp->no_interface)
run_mode = GIMP_RUN_NONINTERACTIVE;
image = file_open_or_link_image (gimp, context, progress,
if (as_link)
image = file_open_link_image (gimp, context, progress,
file, 0, 0,
as_new,
file_proc,
run_mode,
NULL,
status,
&mime_type,
error);
else
image = file_open_image (gimp, context, progress,
file, 0, 0,
as_new,
file_proc,
@@ -636,6 +611,7 @@ file_open_layers (Gimp *gimp,
GimpProgress *progress,
GimpImage *dest_image,
gboolean merge_visible,
gboolean as_link,
GFile *file,
GimpRunMode run_mode,
GimpPlugInProcedure *file_proc,
@@ -654,7 +630,17 @@ file_open_layers (Gimp *gimp,
g_return_val_if_fail (status != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
new_image = file_open_or_link_image (gimp, context, progress,
if (as_link)
new_image = file_open_link_image (gimp, context, progress,
file,
gimp_image_get_width (dest_image),
gimp_image_get_height (dest_image),
FALSE,
file_proc,
run_mode,
NULL, status, &mime_type, error);
else
new_image = file_open_image (gimp, context, progress,
file,
gimp_image_get_width (dest_image),
gimp_image_get_height (dest_image),
@@ -769,7 +755,7 @@ file_open_from_command_line (Gimp *gimp,
/* private functions */
static GimpImage *
file_open_or_link_image (Gimp *gimp,
file_open_link_image (Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
GFile *file,
@@ -785,14 +771,22 @@ file_open_or_link_image (Gimp *gimp,
{
GimpImage *image = NULL;
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
g_return_val_if_fail (G_IS_FILE (file), NULL);
g_return_val_if_fail (status != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (! file_proc)
file_proc = gimp_plug_in_manager_file_procedure_find (gimp->plug_in_manager,
GIMP_FILE_PROCEDURE_GROUP_OPEN,
file, error);
if (g_file_is_native (file) &&
file_proc != NULL &&
file_open_file_proc_is_import (file_proc))
if (! file_open_valid_permissions (file, error))
return NULL;
if (g_file_is_native (file) && file_proc != NULL)
{
GimpLink *link = gimp_link_new (gimp, file, progress, error);
@@ -825,18 +819,16 @@ file_open_or_link_image (Gimp *gimp,
g_clear_object (&link);
}
else
else if (! g_file_is_native (file))
{
image = file_open_image (gimp, context, progress,
file,
vector_width, vector_height,
as_new,
file_proc,
run_mode,
file_proc_handles_vector,
status,
mime_type,
error);
gchar *uri = g_file_get_uri (file);
if (error && ! *error)
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("Only platform-native file paths are supported: '%s' cannot be opened as link."),
uri);
g_free (uri);
}
return image;
@@ -954,3 +946,53 @@ file_open_file_proc_is_import (GimpPlugInProcedure *file_proc)
g_strcmp0 (proc_name, "file-bz2-load") != 0 &&
g_strcmp0 (proc_name, "file-xz-load") != 0);
}
static gboolean
file_open_valid_permissions (GFile *file,
GError **error)
{
/* FIXME enable these tests for remote files again, needs testing */
if (g_file_is_native (file))
{
GFileInfo *info;
info = g_file_query_info (file,
G_FILE_ATTRIBUTE_STANDARD_TYPE ","
G_FILE_ATTRIBUTE_ACCESS_CAN_READ,
G_FILE_QUERY_INFO_NONE,
NULL, error);
if (info != NULL)
{
if (g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) != G_FILE_TYPE_REGULAR)
{
g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("Not a regular file"));
g_object_unref (info);
return FALSE;
}
if (! g_file_info_get_attribute_boolean (info,
G_FILE_ATTRIBUTE_ACCESS_CAN_READ))
{
g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("Permission denied"));
g_object_unref (info);
return FALSE;
}
g_object_unref (info);
}
else
{
/* File likely does not exists. error will already have a more
* accurate reason.
*/
return FALSE;
}
return TRUE;
}
return FALSE;
}

View File

@@ -59,6 +59,7 @@ GimpImage * file_open_with_proc_and_display (Gimp *gimp,
GimpProgress *progress,
GFile *file,
gboolean as_new,
gboolean as_link,
GimpPlugInProcedure *file_proc,
GObject *monitor,
GimpPDBStatusType *status,
@@ -69,6 +70,7 @@ GList * file_open_layers (Gimp *gimp,
GimpProgress *progress,
GimpImage *dest_image,
gboolean merge_visible,
gboolean as_link,
GFile *file,
GimpRunMode run_mode,
GimpPlugInProcedure *file_proc,

View File

@@ -135,7 +135,7 @@ file_load_layer_invoker (GimpProcedure *procedure,
GimpPDBStatusType status;
layers = file_open_layers (gimp, context, progress,
image, FALSE,
image, FALSE, FALSE,
file, run_mode, NULL, &status, error);
if (layers)
@@ -181,7 +181,7 @@ file_load_layers_invoker (GimpProcedure *procedure,
GimpPDBStatusType status;
layer_list = file_open_layers (gimp, context, progress,
image, FALSE,
image, FALSE, FALSE,
file, run_mode, NULL, &status, error);
if (layer_list)

View File

@@ -774,7 +774,7 @@ gimp_layer_tree_view_drop_uri_list (GimpContainerTreeView *view,
new_layers = file_open_layers (image->gimp,
gimp_container_view_get_context (cont_view),
NULL,
image, FALSE,
image, FALSE, FALSE,
file, GIMP_RUN_INTERACTIVE, NULL,
&status, &error);

View File

@@ -66,7 +66,7 @@ gimp_open_dialog_init (GimpOpenDialog *dialog)
static void
gimp_open_dialog_dispose (GObject *object)
{
gimp_open_dialog_set_image (GIMP_OPEN_DIALOG (object), NULL, FALSE);
gimp_open_dialog_set_image (GIMP_OPEN_DIALOG (object), NULL, FALSE, FALSE);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -99,16 +99,19 @@ gimp_open_dialog_new (Gimp *gimp)
void
gimp_open_dialog_set_image (GimpOpenDialog *dialog,
GimpImage *image,
gboolean open_as_layers)
gboolean open_as_layers,
gboolean open_as_link)
{
GimpFileDialog *file_dialog;
g_return_if_fail (GIMP_IS_OPEN_DIALOG (dialog));
g_return_if_fail (image == NULL || GIMP_IS_IMAGE (image));
g_return_if_fail (! open_as_link || open_as_layers);
file_dialog = GIMP_FILE_DIALOG (dialog);
g_set_weak_pointer (&file_dialog->image, image);
dialog->open_as_layers = open_as_layers;
dialog->open_as_link = open_as_link;
}

View File

@@ -38,6 +38,7 @@ struct _GimpOpenDialog
GimpFileDialog parent_instance;
gboolean open_as_layers;
gboolean open_as_link;
};
struct _GimpOpenDialogClass
@@ -52,4 +53,5 @@ GtkWidget * gimp_open_dialog_new (Gimp *gimp);
void gimp_open_dialog_set_image (GimpOpenDialog *dialog,
GimpImage *image,
gboolean open_as_layers);
gboolean open_as_layers,
gboolean open_as_link);

View File

@@ -14,6 +14,7 @@
</submenu>
<item><attribute name="action">app.file-open</attribute></item>
<item><attribute name="action">app.file-open-as-layers</attribute></item>
<item><attribute name="action">app.file-open-as-link-layers</attribute></item>
<item><attribute name="action">app.file-open-location</attribute></item>
<submenu>
<attribute name="label" translatable="yes" context="file-action">Open _Recent</attribute>

View File

@@ -138,7 +138,7 @@ HELP
GimpPDBStatusType status;
layers = file_open_layers (gimp, context, progress,
image, FALSE,
image, FALSE, FALSE,
file, run_mode, NULL, &status, error);
if (layers)
@@ -186,7 +186,7 @@ HELP
GimpPDBStatusType status;
layer_list = file_open_layers (gimp, context, progress,
image, FALSE,
image, FALSE, FALSE,
file, run_mode, NULL, &status, error);
if (layer_list)