[gthumb] scripts: save the accelerators as window shortcuts



commit 3450a75e015d5b891d36be30e39efc02b50cf4f1
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sat Nov 16 10:14:54 2019 +0100

    scripts: save the accelerators as window shortcuts
    
    This allows to handle accelerator collisions and change the
    script shortcuts from the preferences dialog as well.

 extensions/list_tools/callbacks.c                |  13 +--
 extensions/list_tools/dlg-personalize-scripts.c  | 125 +++++++++++++++++------
 extensions/list_tools/gth-script-editor-dialog.c |  60 ++++++++---
 extensions/list_tools/gth-script-editor-dialog.h |   1 +
 extensions/list_tools/gth-script.c               |  79 ++++++++------
 extensions/list_tools/gth-script.h               |   7 +-
 extensions/list_tools/shortcuts.h                |   1 +
 gthumb/dlg-preferences-shortcuts.c               |  96 +++++------------
 gthumb/gth-shortcut.c                            |  80 ++++++++++++---
 gthumb/gth-shortcut.h                            |  10 +-
 gthumb/gth-window.c                              | 115 +++++++++++++++++++--
 gthumb/gth-window.h                              |   8 ++
 12 files changed, 413 insertions(+), 182 deletions(-)
---
diff --git a/extensions/list_tools/callbacks.c b/extensions/list_tools/callbacks.c
index 2c23533e..fffa1732 100644
--- a/extensions/list_tools/callbacks.c
+++ b/extensions/list_tools/callbacks.c
@@ -29,10 +29,10 @@
 #include "gth-script-file.h"
 #include "gth-script-task.h"
 #include "list-tools.h"
+#include "shortcuts.h"
 
 
 #define BROWSER_DATA_KEY "list-tools-browser-data"
-#define SCRIPTS_GROUP "scripts"
 
 
 static const GActionEntry actions[] = {
@@ -76,23 +76,18 @@ update_scripts (BrowserData *data)
                GthScript   *script = scan->data;
                GthShortcut *shortcut;
 
-               shortcut = gth_script_get_shortcut (script);
+               shortcut = gth_script_create_shortcut (script);
                gth_window_add_removable_shortcut (GTH_WINDOW (data->browser),
                                                   SCRIPTS_GROUP,
                                                   shortcut);
 
                if (gth_script_is_visible (script)) {
-                       char *detailed_action;
-
-                       detailed_action = g_strdup_printf ("win.exec-script('%s')", gth_script_get_id 
(script));
                        gth_menu_manager_append_entry (menu_manager,
                                                       data->menu_merge_id,
                                                       gth_script_get_display_name (script),
-                                                      detailed_action,
-                                                      shortcut->label,
+                                                      shortcut->detailed_action,
+                                                      "",
                                                       NULL);
-
-                       g_free (detailed_action);
                }
 
                gth_shortcut_free (shortcut);
diff --git a/extensions/list_tools/dlg-personalize-scripts.c b/extensions/list_tools/dlg-personalize-scripts.c
index 0a765a3f..6737adcd 100644
--- a/extensions/list_tools/dlg-personalize-scripts.c
+++ b/extensions/list_tools/dlg-personalize-scripts.c
@@ -27,6 +27,7 @@
 #include "gth-script.h"
 #include "gth-script-editor-dialog.h"
 #include "gth-script-file.h"
+#include "shortcuts.h"
 
 
 #define GET_WIDGET(name) _gtk_builder_get_widget (data->builder, (name))
@@ -131,13 +132,15 @@ row_inserted_cb (GtkTreeModel *tree_model,
 
 
 static char *
-get_script_shortcut (GthScript *script)
+get_shortcut_label (DialogData *data,
+                   GthScript  *script)
 {
-       guint           keyval;
-       GdkModifierType modifiers;
+       GthShortcut *shortcut;
 
-       gth_script_get_accelerator (script, &keyval, &modifiers);
-       return gtk_accelerator_get_label (keyval, modifiers);
+       shortcut = gth_window_get_shortcut (GTH_WINDOW (data->browser),
+                                           gth_script_get_detailed_action (script));
+
+       return (shortcut != NULL) ? shortcut->label : "";
 }
 
 
@@ -151,20 +154,15 @@ set_script_list (DialogData *data,
 
        for (scan = script_list; scan; scan = scan->next) {
                GthScript   *script = scan->data;
-               char        *shortcut;
                GtkTreeIter  iter;
 
-               shortcut = get_script_shortcut (script);
-
                gtk_list_store_append (data->list_store, &iter);
                gtk_list_store_set (data->list_store, &iter,
                                    COLUMN_SCRIPT, script,
                                    COLUMN_NAME, gth_script_get_display_name (script),
-                                   COLUMN_SHORTCUT, shortcut,
+                                   COLUMN_SHORTCUT, get_shortcut_label (data, script),
                                    COLUMN_VISIBLE, gth_script_is_visible (script),
                                   -1);
-
-               g_free (shortcut);
        }
 
        g_signal_handlers_unblock_by_func (data->list_store, row_inserted_cb, data);
@@ -295,7 +293,31 @@ add_columns (GtkTreeView *treeview,
 
 
 static gboolean
-get_script_iter (DialogData  *data,
+get_iter_for_shortcut (DialogData  *data,
+                      GthShortcut *shortcut,
+                      GtkTreeIter *iter)
+{
+       GtkTreeModel *model = GTK_TREE_MODEL (data->list_store);
+       gboolean      found = FALSE;
+       if (! gtk_tree_model_get_iter_first (model, iter))
+               return FALSE;
+
+       do {
+               GthScript *script;
+
+               gtk_tree_model_get (model, iter, COLUMN_SCRIPT, &script, -1);
+               found = g_strcmp0 (shortcut->detailed_action, gth_script_get_detailed_action (script)) == 0;
+
+               g_object_unref (script);
+       }
+       while (! found && gtk_tree_model_iter_next (model, iter));
+
+       return found;
+}
+
+
+static gboolean
+get_iter_script (DialogData  *data,
                 GthScript   *script,
                 GtkTreeIter *iter)
 {
@@ -329,16 +351,12 @@ script_editor_dialog__response_cb (GtkDialog *dialog,
        DialogData    *data = user_data;
        GthScript     *script;
        GError        *error = NULL;
+       GPtrArray     *shortcuts_v;
        GthScriptFile *script_file;
        gboolean       new_script;
+       GthShortcut   *shortcut;
        GtkTreeIter    iter;
-       gboolean       change_list = TRUE;
-
-
-       if (response == GTK_RESPONSE_HELP) {
-               /* FIXME: show help dialog */
-               return;
-       }
+       gboolean       change_list;
 
        if (response != GTK_RESPONSE_OK) {
                gtk_widget_destroy (GTK_WIDGET (dialog));
@@ -352,42 +370,71 @@ script_editor_dialog__response_cb (GtkDialog *dialog,
                return;
        }
 
-       /* update the script file */
+       /* update the shortcuts */
+
+       shortcuts_v = g_ptr_array_copy (gth_window_get_shortcuts (GTH_WINDOW (data->browser)),
+                                       (GCopyFunc) gth_shortcut_dup,
+                                       NULL);
+
+       /* If another shortcut has the same accelerator, reset the accelerator
+        * for that shortcut. */
+
+       shortcut = gth_shortcut_array_find_by_accel (shortcuts_v,
+                                                    GTH_SHORTCUT_CONTEXT_BROWSER_VIEWER,
+                                                    gth_script_get_accelerator (script));
+       if (shortcut != NULL) {
+               if (g_strcmp0 (shortcut->detailed_action, gth_script_get_detailed_action (script)) != 0) {
+                       if (get_iter_for_shortcut (data, shortcut, &iter))
+                               gtk_list_store_set (data->list_store, &iter,
+                                                   COLUMN_SHORTCUT, "",
+                                                   -1);
+                       gth_shortcut_set_key (shortcut, 0, 0);
+               }
+       }
+
+       /* update the script shortcut */
+
+       shortcut = gth_shortcut_array_find_by_action (shortcuts_v, gth_script_get_detailed_action (script));
+       if (shortcut != NULL)
+               g_ptr_array_remove (shortcuts_v, shortcut);
+
+       shortcut = gth_script_create_shortcut (script);
+       g_ptr_array_add (shortcuts_v, shortcut);
+
+       /* save the script */
 
        script_file = gth_script_file_get ();
        new_script = ! gth_script_file_has_script (script_file, script);
 
        g_signal_handlers_block_by_func (script_file, scripts_changed_cb, data);
        gth_script_file_add (script_file, script);
-       gth_script_file_save (script_file, NULL); /* FIXME: handle errors */
+       gth_script_file_save (script_file, NULL);
        g_signal_handlers_unblock_by_func (script_file, scripts_changed_cb, data);
 
+       gth_main_shortcuts_changed (shortcuts_v);
+
        /* update the script list */
 
        if (new_script) {
                g_signal_handlers_block_by_func (data->list_store, row_inserted_cb, data);
                gtk_list_store_append (data->list_store, &iter);
                g_signal_handlers_unblock_by_func (data->list_store, row_inserted_cb, data);
+               change_list = TRUE;
        }
        else
-               change_list = get_script_iter (data, script, &iter);
+               change_list = get_iter_script (data, script, &iter);
 
-       if (change_list) {
-               char *shortcut;
-
-               shortcut = get_script_shortcut (script);
+       if (change_list)
                gtk_list_store_set (data->list_store, &iter,
                                    COLUMN_SCRIPT, script,
                                    COLUMN_NAME, gth_script_get_display_name (script),
-                                   COLUMN_SHORTCUT, shortcut,
+                                   COLUMN_SHORTCUT, shortcut->label,
                                    COLUMN_VISIBLE, gth_script_is_visible (script),
                                    -1);
 
-               g_free (shortcut);
-       }
-
        gtk_widget_destroy (GTK_WIDGET (dialog));
 
+       g_ptr_array_unref (shortcuts_v);
        g_object_unref (script);
 }
 
@@ -398,7 +445,7 @@ new_script_cb (GtkButton  *button,
 {
        GtkWidget *dialog;
 
-       dialog = gth_script_editor_dialog_new (_("New Command"), GTK_WINDOW (data->dialog));
+       dialog = gth_script_editor_dialog_new (_("New Command"), GTH_WINDOW (data->browser), GTK_WINDOW 
(data->dialog));
        g_signal_connect (dialog, "response",
                          G_CALLBACK (script_editor_dialog__response_cb),
                          data);
@@ -425,7 +472,7 @@ edit_script_cb (GtkButton  *button,
        if (script == NULL)
                return;
 
-       dialog = gth_script_editor_dialog_new (_("Edit Command"), GTK_WINDOW (data->dialog));
+       dialog = gth_script_editor_dialog_new (_("Edit Command"), GTH_WINDOW (data->browser), GTK_WINDOW 
(data->dialog));
        gth_script_editor_dialog_set_script (GTH_SCRIPT_EDITOR_DIALOG (dialog), script);
        g_signal_connect (dialog,
                          "response",
@@ -448,6 +495,8 @@ delete_script_cb (GtkButton  *button,
        GtkTreeModel     *model = GTK_TREE_MODEL (data->list_store);
        GtkTreeIter       iter;
        GthScript        *script;
+       GPtrArray        *shortcuts_v;
+       GthShortcut      *shortcut;
        GthScriptFile    *script_file;
 
        d = _gtk_message_dialog_new (GTK_WINDOW (data->dialog),
@@ -471,6 +520,16 @@ delete_script_cb (GtkButton  *button,
        if (script == NULL)
                return;
 
+       /* update the shortcuts */
+
+       shortcuts_v = g_ptr_array_copy (gth_window_get_shortcuts (GTH_WINDOW (data->browser)),
+                                       (GCopyFunc) gth_shortcut_dup,
+                                       NULL);
+
+       shortcut = gth_shortcut_array_find_by_action (shortcuts_v, gth_script_get_detailed_action (script));
+       if (shortcut != NULL)
+               g_ptr_array_remove (shortcuts_v, shortcut);
+
        /* update the script file */
 
        script_file = gth_script_file_get ();
@@ -479,6 +538,8 @@ delete_script_cb (GtkButton  *button,
        gth_script_file_save (script_file, NULL);
        g_signal_handlers_unblock_by_func (script_file, scripts_changed_cb, data);
 
+       gth_main_shortcuts_changed (shortcuts_v);
+
        /* update the script list */
 
        g_signal_handlers_block_by_func (data->list_store, row_deleted_cb, data);
diff --git a/extensions/list_tools/gth-script-editor-dialog.c 
b/extensions/list_tools/gth-script-editor-dialog.c
index 48333c78..659c4a22 100644
--- a/extensions/list_tools/gth-script-editor-dialog.c
+++ b/extensions/list_tools/gth-script-editor-dialog.c
@@ -37,14 +37,16 @@ enum {
 };
 
 struct _GthScriptEditorDialogPrivate {
-       GtkBuilder *builder;
-       GtkWidget  *accel_button;
-       char       *script_id;
-       gboolean    script_visible;
-       gboolean    wait_command;
-       gboolean    shell_script;
-       gboolean    for_each_file;
-       gboolean    help_visible;
+       GthWindow   *shortcut_window;
+       GtkBuilder  *builder;
+       GtkWidget   *accel_button;
+       char        *script_id;
+       gboolean     script_visible;
+       gboolean     wait_command;
+       gboolean     shell_script;
+       gboolean     for_each_file;
+       gboolean     help_visible;
+       GthShortcut *shortcut;
 };
 
 
@@ -90,6 +92,8 @@ gth_script_editor_dialog_init (GthScriptEditorDialog *dialog)
        dialog->priv->shell_script = FALSE;
        dialog->priv->for_each_file = FALSE;
        dialog->priv->help_visible = FALSE;
+       dialog->priv->shortcut = NULL;
+       dialog->priv->shortcut_window = NULL;
 }
 
 
@@ -117,6 +121,26 @@ command_entry_icon_press_cb (GtkEntry             *entry,
 }
 
 
+static gboolean
+accel_button_change_value_cb (GthAccelButton  *button,
+                             guint            keycode,
+                             GdkModifierType  modifiers,
+                             gpointer         user_data)
+{
+       GthScriptEditorDialog *self = user_data;
+       gboolean               change;
+
+       change = gth_window_can_change_shortcut (self->priv->shortcut_window,
+                                                self->priv->shortcut != NULL ? 
self->priv->shortcut->detailed_action : NULL,
+                                                GTH_SHORTCUT_CONTEXT_BROWSER_VIEWER,
+                                                keycode,
+                                                modifiers,
+                                                GTK_WINDOW (self));
+
+       return change ? GDK_EVENT_PROPAGATE : GDK_EVENT_STOP;
+}
+
+
 static void
 gth_script_editor_dialog_construct (GthScriptEditorDialog *self,
                                    const char            *title,
@@ -138,6 +162,11 @@ gth_script_editor_dialog_construct (GthScriptEditorDialog *self,
        gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (self))), 
_gtk_builder_get_widget (self->priv->builder, "script_editor"), TRUE, TRUE, 0);
 
        self->priv->accel_button = gth_accel_button_new ();
+       g_signal_connect (self->priv->accel_button,
+                         "change-value",
+                         G_CALLBACK (accel_button_change_value_cb),
+                         self);
+
        gtk_widget_show (self->priv->accel_button);
        gtk_box_pack_start (GTK_BOX (GET_WIDGET ("accel_box")), self->priv->accel_button, FALSE, FALSE, 0);
 
@@ -154,6 +183,7 @@ gth_script_editor_dialog_construct (GthScriptEditorDialog *self,
 
 GtkWidget *
 gth_script_editor_dialog_new (const char *title,
+                             GthWindow  *shortcut_window,
                              GtkWindow  *parent)
 {
        GthScriptEditorDialog *self;
@@ -161,6 +191,7 @@ gth_script_editor_dialog_new (const char *title,
        self = g_object_new (GTH_TYPE_SCRIPT_EDITOR_DIALOG,
                             "use-header-bar", _gtk_settings_get_dialogs_use_header (),
                             NULL);
+       self->priv->shortcut_window = shortcut_window;
        gth_script_editor_dialog_construct (self, title, parent);
 
        return (GtkWidget *) self;
@@ -186,14 +217,11 @@ gth_script_editor_dialog_set_script (GthScriptEditorDialog *self,
        g_free (self->priv->script_id);
        self->priv->script_id = NULL;
        self->priv->script_visible = TRUE;
+       self->priv->shortcut = NULL;
 
        _gth_script_editor_dialog_set_new_script (self);
 
        if (script != NULL) {
-               guint            keyval;
-               GdkModifierType  modifiers;
-
-
                self->priv->script_id = g_strdup (gth_script_get_id (script));
                self->priv->script_visible = gth_script_is_visible (script);
 
@@ -203,8 +231,12 @@ gth_script_editor_dialog_set_script (GthScriptEditorDialog *self,
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("for_each_file_checkbutton")), 
gth_script_for_each_file (script));
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("wait_command_checkbutton")), 
gth_script_wait_command (script));
 
-               gth_script_get_accelerator (script, &keyval, &modifiers);
-               gth_accel_button_set_accelerator (GTH_ACCEL_BUTTON (self->priv->accel_button), keyval, 
modifiers);
+               self->priv->shortcut = gth_window_get_shortcut (self->priv->shortcut_window, 
gth_script_get_detailed_action (script));
+               if (self->priv->shortcut != NULL) {
+                       gth_accel_button_set_accelerator (GTH_ACCEL_BUTTON (self->priv->accel_button),
+                                                         self->priv->shortcut->keyval,
+                                                         self->priv->shortcut->modifiers);
+               }
        }
 
        update_sensitivity (self);
diff --git a/extensions/list_tools/gth-script-editor-dialog.h 
b/extensions/list_tools/gth-script-editor-dialog.h
index 2a17a69e..bee9cf15 100644
--- a/extensions/list_tools/gth-script-editor-dialog.h
+++ b/extensions/list_tools/gth-script-editor-dialog.h
@@ -49,6 +49,7 @@ struct _GthScriptEditorDialogClass {
 
 GType       gth_script_editor_dialog_get_type   (void);
 GtkWidget * gth_script_editor_dialog_new        (const char             *title,
+                                                GthWindow              *shortcut_window,
                                                 GtkWindow              *parent);
 void        gth_script_editor_dialog_set_script (GthScriptEditorDialog  *self,
                                                 GthScript              *script);
diff --git a/extensions/list_tools/gth-script.c b/extensions/list_tools/gth-script.c
index 891868fe..cca9191e 100644
--- a/extensions/list_tools/gth-script.c
+++ b/extensions/list_tools/gth-script.c
@@ -43,12 +43,6 @@ enum {
 };
 
 
-typedef struct {
-       guint            keyval;
-       GdkModifierType  modifiers;
-       char            *name;
-} _Accel;
-
 struct _GthScriptPrivate {
        char            *id;
        char            *display_name;
@@ -57,7 +51,8 @@ struct _GthScriptPrivate {
        gboolean         shell_script;
        gboolean         for_each_file;
        gboolean         wait_command;
-       _Accel           accelerator;
+       char            *accelerator;
+       char            *detailed_action;
 };
 
 
@@ -89,7 +84,6 @@ gth_script_real_create_element (DomDomizable *base,
                                               "shell-script", (self->priv->shell_script ? "true" : "false"),
                                               "for-each-file", (self->priv->for_each_file ? "true" : 
"false"),
                                               "wait-command", (self->priv->wait_command ? "true" : "false"),
-                                              "accelerator", self->priv->accelerator.name,
                                               NULL);
        if (! self->priv->visible)
                dom_element_set_attribute (element, "display", "none");
@@ -115,7 +109,7 @@ gth_script_real_load_from_element (DomDomizable *base,
                      "shell-script", (g_strcmp0 (dom_element_get_attribute (element, "shell-script"), 
"true") == 0),
                      "for-each-file", (g_strcmp0 (dom_element_get_attribute (element, "for-each-file"), 
"true") == 0),
                      "wait-command", (g_strcmp0 (dom_element_get_attribute (element, "wait-command"), 
"true") == 0),
-                     "accelerator", dom_element_get_attribute (element, "accelerator"),
+                     "accelerator", "",
                      NULL);
 }
 
@@ -135,7 +129,7 @@ gth_script_real_duplicate (GthDuplicable *duplicable)
                      "shell-script", script->priv->shell_script,
                      "for-each-file", script->priv->for_each_file,
                      "wait-command", script->priv->wait_command,
-                     "accelerator", script->priv->accelerator.name,
+                     "accelerator", script->priv->accelerator,
                      NULL);
 
        return (GObject *) new_script;
@@ -151,12 +145,28 @@ gth_script_finalize (GObject *base)
        g_free (self->priv->id);
        g_free (self->priv->display_name);
        g_free (self->priv->command);
-       g_free (self->priv->accelerator.name);
+       g_free (self->priv->accelerator);
+       g_free (self->priv->detailed_action);
 
        G_OBJECT_CLASS (gth_script_parent_class)->finalize (base);
 }
 
 
+static char *
+detailed_action_from_id (char *id)
+{
+       GVariant *param;
+       char     *detailed_action;
+
+       param = g_variant_new_string (id);
+       detailed_action = g_action_print_detailed_name ("exec-script", param);
+
+       g_variant_unref (param);
+
+       return detailed_action;
+}
+
+
 static void
 gth_script_set_property (GObject      *object,
                         guint         property_id,
@@ -173,6 +183,8 @@ gth_script_set_property (GObject      *object,
                self->priv->id = g_value_dup_string (value);
                if (self->priv->id == NULL)
                        self->priv->id = g_strdup ("");
+               g_free (self->priv->detailed_action);
+               self->priv->detailed_action = detailed_action_from_id (self->priv->id);
                break;
        case PROP_DISPLAY_NAME:
                g_free (self->priv->display_name);
@@ -199,10 +211,8 @@ gth_script_set_property (GObject      *object,
                self->priv->wait_command = g_value_get_boolean (value);
                break;
        case PROP_ACCELERATOR:
-               self->priv->accelerator.name = g_value_dup_string (value);
-               gtk_accelerator_parse (self->priv->accelerator.name,
-                                      &self->priv->accelerator.keyval,
-                                      &self->priv->accelerator.modifiers);
+               g_free (self->priv->accelerator);
+               self->priv->accelerator = g_value_dup_string (value);
                break;
        default:
                break;
@@ -243,7 +253,7 @@ gth_script_get_property (GObject    *object,
                g_value_set_boolean (value, self->priv->wait_command);
                break;
        case PROP_ACCELERATOR:
-               g_value_set_string (value, self->priv->accelerator.name);
+               g_value_set_string (value, self->priv->accelerator);
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -345,9 +355,12 @@ gth_script_init (GthScript *self)
        self->priv->id = NULL;
        self->priv->display_name = NULL;
        self->priv->command = NULL;
-       self->priv->accelerator.name = NULL;
-       self->priv->accelerator.keyval = 0;
-       self->priv->accelerator.modifiers = 0;
+       self->priv->visible = FALSE;
+       self->priv->shell_script = FALSE;
+       self->priv->for_each_file = FALSE;
+       self->priv->wait_command = FALSE;
+       self->priv->accelerator = NULL;
+       self->priv->detailed_action = NULL;
 }
 
 
@@ -386,6 +399,13 @@ gth_script_get_command (GthScript *script)
 }
 
 
+const char *
+gth_script_get_detailed_action (GthScript *self)
+{
+       return self->priv->detailed_action;
+}
+
+
 gboolean
 gth_script_is_visible (GthScript *script)
 {
@@ -1026,30 +1046,25 @@ gth_script_get_command_line (GthScript  *script,
 }
 
 
-void
-gth_script_get_accelerator (GthScript       *self,
-                           guint           *keyval,
-                           GdkModifierType *modifiers)
+const char *
+gth_script_get_accelerator (GthScript *self)
 {
-       g_return_if_fail (GTH_IS_SCRIPT (self));
-       if (keyval) *keyval = self->priv->accelerator.keyval;
-       if (modifiers) *modifiers = self->priv->accelerator.modifiers;
+       g_return_val_if_fail (GTH_IS_SCRIPT (self), NULL);
+       return self->priv->accelerator;
 }
 
 
 GthShortcut *
-gth_script_get_shortcut (GthScript *self)
+gth_script_create_shortcut (GthScript *self)
 {
        GthShortcut *shortcut;
 
-       shortcut = gth_shortcut_new ();
-       shortcut->action_name = g_strdup ("exec-script");
-       shortcut->action_parameter = g_variant_ref_sink (g_variant_new_string (gth_script_get_id (self)));
+       shortcut = gth_shortcut_new ("exec-script", g_variant_new_string (gth_script_get_id (self)));
        shortcut->description = g_strdup (self->priv->display_name);
        shortcut->context = GTH_SHORTCUT_CONTEXT_BROWSER_VIEWER;
        shortcut->category = GTH_SHORTCUT_CATEGORY_LIST_TOOLS;
-       gth_shortcut_set_key (shortcut, self->priv->accelerator.keyval, self->priv->accelerator.modifiers);
-       shortcut->default_accelerator = g_strdup (shortcut->accelerator);
+       gth_shortcut_set_accelerator (shortcut, self->priv->accelerator);
+       shortcut->default_accelerator = g_strdup ("");
 
        return shortcut;
 }
diff --git a/extensions/list_tools/gth-script.h b/extensions/list_tools/gth-script.h
index c3146d96..b7f7b2f6 100644
--- a/extensions/list_tools/gth-script.h
+++ b/extensions/list_tools/gth-script.h
@@ -55,6 +55,7 @@ GthScript *       gth_script_new                       (void);
 const char *      gth_script_get_id                    (GthScript       *script);
 const char *      gth_script_get_display_name          (GthScript       *script);
 const char *      gth_script_get_command               (GthScript       *script);
+const char *      gth_script_get_detailed_action       (GthScript       *script);
 gboolean          gth_script_is_visible                (GthScript       *script);
 gboolean          gth_script_is_shell_script           (GthScript       *script);
 gboolean          gth_script_for_each_file             (GthScript       *script);
@@ -65,10 +66,8 @@ char *            gth_script_get_command_line          (GthScript       *script,
                                                        GList           *file_list /* GthFileData */,
                                                        gboolean         can_skip,
                                                        GError         **error);
-void              gth_script_get_accelerator           (GthScript       *script,
-                                                       guint           *keyval,
-                                                       GdkModifierType *modifiers);
-GthShortcut *     gth_script_get_shortcut              (GthScript       *script);
+const char *      gth_script_get_accelerator           (GthScript       *script);
+GthShortcut *     gth_script_create_shortcut           (GthScript       *script);
 
 G_END_DECLS
 
diff --git a/extensions/list_tools/shortcuts.h b/extensions/list_tools/shortcuts.h
index 2239ab61..8a78852b 100644
--- a/extensions/list_tools/shortcuts.h
+++ b/extensions/list_tools/shortcuts.h
@@ -23,5 +23,6 @@
 #define LIST_TOOLS_SHORTCUTS_H
 
 #define GTH_SHORTCUT_CATEGORY_LIST_TOOLS "list-tools"
+#define SCRIPTS_GROUP "scripts"
 
 #endif /* LIST_TOOLS_SHORTCUTS_H */
diff --git a/gthumb/dlg-preferences-shortcuts.c b/gthumb/dlg-preferences-shortcuts.c
index f5d2c33d..07c6f407 100644
--- a/gthumb/dlg-preferences-shortcuts.c
+++ b/gthumb/dlg-preferences-shortcuts.c
@@ -129,7 +129,7 @@ find_row_by_shortcut (BrowserData *browser_data,
 
        for (i = 0; i < browser_data->rows->len; i++) {
                RowData *row_data = g_ptr_array_index (browser_data->rows, i);
-               if (g_strcmp0 (row_data->shortcut->action_name, shortcut->action_name) == 0)
+               if (g_strcmp0 (row_data->shortcut->detailed_action, shortcut->detailed_action) == 0)
                        return row_data;
        }
 
@@ -143,78 +143,36 @@ row_data_update_shortcut (RowData         *row_data,
                          GdkModifierType  modifiers,
                          GtkWindow       *parent)
 {
-       GPtrArray   *shortcuts_v;
-       GthShortcut *shortcut;
-
-       shortcuts_v = gth_window_get_shortcuts (GTH_WINDOW (row_data->browser_data->browser));
-       shortcut = gth_shortcut_array_find (shortcuts_v,
-                                           row_data->shortcut->context,
-                                           keycode,
-                                           modifiers);
-
-       if (shortcut != NULL) {
-               if (g_strcmp0 (shortcut->action_name, row_data->shortcut->action_name) != 0) {
-                       char      *label;
-                       char      *msg;
-                       GtkWidget *dialog;
-                       gboolean   reassign;
-
-                       label = gtk_accelerator_get_label (keycode, modifiers);
-                       msg = g_strdup_printf (_("The key combination «%s» is already assigned to the action 
«%s».  Do you want to reassign it to «%s» instead?"),
-                                              label,
-                                              shortcut->description,
-                                              row_data->shortcut->description);
-
-                       dialog = _gtk_yesno_dialog_new (parent,
-                                                       GTK_DIALOG_MODAL,
-                                                       msg,
-                                                       _GTK_LABEL_CANCEL,
-                                                       _("Reassign"));
-
-                       reassign = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES;
-                       gtk_widget_destroy (GTK_WIDGET (dialog));
-
-                       if (reassign) {
-                               gth_shortcut_set_key (shortcut, 0, 0);
-                               row_data_update_accel_label (find_row_by_shortcut (row_data->browser_data, 
shortcut));
-                       }
-
-                       g_free (msg);
-                       g_free (label);
-
-                       if (! reassign)
-                               return FALSE;
-               }
-               else {
-                       char      *label;
-                       char      *msg;
-                       GtkWidget *dialog;
-
-                       label = gtk_accelerator_get_label (keycode, modifiers);
-                       msg = g_strdup_printf (_("The key combination «%s» is already assigned to this 
action."), label);
-                       dialog = _gtk_message_dialog_new (parent,
-                                                         GTK_DIALOG_MODAL,
-                                                         _GTK_ICON_NAME_DIALOG_INFO,
-                                                         msg,
-                                                         NULL,
-                                                         _GTK_LABEL_CLOSE, GTK_RESPONSE_CANCEL,
-                                                         NULL);
-                       gtk_dialog_run (GTK_DIALOG (dialog));
-                       gtk_widget_destroy (GTK_WIDGET (dialog));
-
-                       g_free (msg);
-                       g_free (label);
-
-                       return FALSE;
+       gboolean change;
+
+       change = gth_window_can_change_shortcut (GTH_WINDOW (row_data->browser_data->browser),
+                                                row_data->shortcut->detailed_action,
+                                                row_data->shortcut->context,
+                                                keycode,
+                                                modifiers,
+                                                parent);
+
+       if (change) {
+               GPtrArray   *shortcuts_v;
+               GthShortcut *shortcut;
+
+               shortcuts_v = gth_window_get_shortcuts (GTH_WINDOW (row_data->browser_data->browser));
+               shortcut = gth_shortcut_array_find (shortcuts_v,
+                                                   row_data->shortcut->context,
+                                                   keycode,
+                                                   modifiers);
+               if (shortcut != NULL) {
+                       gth_shortcut_set_key (shortcut, 0, 0);
+                       row_data_update_accel_label (find_row_by_shortcut (row_data->browser_data, shortcut));
                }
-       }
 
-       gth_shortcut_set_key (row_data->shortcut, keycode, modifiers);
-       row_data_update_accel_label (row_data);
+               gth_shortcut_set_key (row_data->shortcut, keycode, modifiers);
+               row_data_update_accel_label (row_data);
 
-       gth_main_shortcuts_changed (gth_window_get_shortcuts (GTH_WINDOW (row_data->browser_data->browser)));
+               gth_main_shortcuts_changed (gth_window_get_shortcuts (GTH_WINDOW 
(row_data->browser_data->browser)));
+       }
 
-       return TRUE;
+       return change;
 }
 
 
diff --git a/gthumb/gth-shortcut.c b/gthumb/gth-shortcut.c
index 4ae9b371..9dfb2199 100644
--- a/gthumb/gth-shortcut.c
+++ b/gthumb/gth-shortcut.c
@@ -29,13 +29,17 @@
 
 
 GthShortcut *
-gth_shortcut_new (void)
+gth_shortcut_new (const char *action_name,
+                 GVariant   *param)
 {
        GthShortcut *shortcut;
 
+       g_return_val_if_fail (action_name != NULL, NULL);
+
        shortcut = g_new (GthShortcut, 1);
-       shortcut->action_name = NULL;
-       shortcut->action_parameter = NULL;
+       shortcut->action_name = g_strdup (action_name);
+       shortcut->action_parameter = (param != NULL) ? g_variant_ref_sink (param) : NULL;
+       shortcut->detailed_action = g_action_print_detailed_name (shortcut->action_name, 
shortcut->action_parameter);
        shortcut->description = NULL;
        shortcut->context = 0;
        shortcut->category = NULL;
@@ -54,12 +58,7 @@ gth_shortcut_dup (const GthShortcut *shortcut)
 {
        GthShortcut *new_shortcut;
 
-       new_shortcut = gth_shortcut_new ();
-       new_shortcut->action_name = g_strdup (shortcut->action_name);
-       if (shortcut->action_parameter != NULL)
-               new_shortcut->action_parameter = g_variant_ref_sink (shortcut->action_parameter);
-       else
-               new_shortcut->action_parameter = NULL;
+       new_shortcut = gth_shortcut_new (shortcut->action_name, shortcut->action_parameter);
        new_shortcut->description = g_strdup (shortcut->description);
        new_shortcut->context = shortcut->context;
        new_shortcut->category = shortcut->category;
@@ -76,6 +75,7 @@ gth_shortcut_free (GthShortcut *shortcut)
        g_free (shortcut->action_name);
        if (shortcut->action_parameter != NULL)
                g_variant_unref (shortcut->action_parameter);
+       g_free (shortcut->detailed_action);
        g_free (shortcut->description);
        g_free (shortcut->default_accelerator);
        g_free (shortcut->accelerator);
@@ -114,6 +114,14 @@ gth_shortcut_set_key (GthShortcut       *shortcut,
 }
 
 
+gboolean
+gth_shortcut_customizable (GthShortcut *shortcut)
+{
+       return ((shortcut->context & GTH_SHORTCUT_CONTEXT_FIXED) == 0)
+               && ((shortcut->context & GTH_SHORTCUT_CONTEXT_INTERNAL) == 0);
+}
+
+
 GthShortcut *
 gth_shortcut_array_find (GPtrArray       *shortcuts_v,
                         int              context,
@@ -140,6 +148,50 @@ gth_shortcut_array_find (GPtrArray       *shortcuts_v,
 }
 
 
+GthShortcut *
+gth_shortcut_array_find_by_accel (GPtrArray  *shortcuts_v,
+                                 int         context,
+                                 const char *accelerator)
+{
+       int i;
+
+       if (accelerator == NULL)
+               return NULL;
+
+       for (i = 0; i < shortcuts_v->len; i++) {
+               GthShortcut *shortcut = g_ptr_array_index (shortcuts_v, i);
+
+               if (((shortcut->context & context) == context)
+                       && (g_strcmp0 (shortcut->accelerator, accelerator) == 0))
+               {
+                       return shortcut;
+               }
+       }
+
+       return NULL;
+}
+
+
+GthShortcut *
+gth_shortcut_array_find_by_action (GPtrArray  *shortcuts_v,
+                                  const char *detailed_action)
+{
+       int i;
+
+       if (detailed_action == NULL)
+               return NULL;
+
+       for (i = 0; i < shortcuts_v->len; i++) {
+               GthShortcut *shortcut = g_ptr_array_index (shortcuts_v, i);
+
+               if (g_strcmp0 (shortcut->detailed_action, detailed_action) == 0)
+                       return shortcut;
+       }
+
+       return NULL;
+}
+
+
 gboolean
 gth_shortcut_valid (guint           keycode,
                    GdkModifierType modifiers)
@@ -188,7 +240,7 @@ gth_shortcuts_write_to_file (GPtrArray  *shortcuts_v,
 
                dom_element_append_child (shortcuts,
                        dom_document_create_element (doc, "shortcut",
-                                                    "action", shortcut->action_name,
+                                                    "action", shortcut->detailed_action,
                                                     "accelerator", shortcut->accelerator,
                                                     NULL));
        }
@@ -230,17 +282,17 @@ gth_shortcuts_load_from_file (GPtrArray  *shortcuts_v,
 
                                        for (shortcut_node = node->first_child; shortcut_node; shortcut_node 
= shortcut_node->next_sibling) {
                                                if (g_strcmp0 (shortcut_node->tag_name, "shortcut") == 0) {
-                                                       const char  *action_name;
+                                                       const char  *detailed_action;
                                                        const char  *accelerator;
                                                        GthShortcut *shortcut;
 
-                                                       action_name = dom_element_get_attribute 
(shortcut_node, "action");
+                                                       detailed_action = dom_element_get_attribute 
(shortcut_node, "action");
                                                        accelerator = dom_element_get_attribute 
(shortcut_node, "accelerator");
 
-                                                       if (action_name == NULL)
+                                                       if (detailed_action == NULL)
                                                                continue;
 
-                                                       shortcut = g_hash_table_lookup (shortcuts, 
action_name);
+                                                       shortcut = g_hash_table_lookup (shortcuts, 
detailed_action);
                                                        if (shortcut != NULL)
                                                                gth_shortcut_set_accelerator (shortcut, 
accelerator);
                                                }
diff --git a/gthumb/gth-shortcut.h b/gthumb/gth-shortcut.h
index c194b9f8..38f2906b 100644
--- a/gthumb/gth-shortcut.h
+++ b/gthumb/gth-shortcut.h
@@ -53,10 +53,12 @@ typedef struct {
        guint            keyval;
        GdkModifierType  modifiers;
        GVariant        *action_parameter;
+       char            *detailed_action;
 } GthShortcut;
 
 
-GthShortcut * gth_shortcut_new                 (void);
+GthShortcut * gth_shortcut_new                 (const char        *action_name,
+                                                GVariant          *param);
 GthShortcut * gth_shortcut_dup                 (const GthShortcut *shortcut);
 void          gth_shortcut_free                        (GthShortcut       *shortcut);
 void          gth_shortcut_set_key             (GthShortcut       *shortcut,
@@ -64,10 +66,16 @@ void          gth_shortcut_set_key          (GthShortcut       *shortcut,
                                                 GdkModifierType    modifiers);
 void          gth_shortcut_set_accelerator     (GthShortcut       *shortcut,
                                                 const char        *name);
+gboolean      gth_shortcut_customizable         (GthShortcut       *shortcut);
 GthShortcut * gth_shortcut_array_find           (GPtrArray         *shortcuts_v,
                                                 int                context,
                                                 guint              keycode,
                                                 GdkModifierType    modifiers);
+GthShortcut * gth_shortcut_array_find_by_accel  (GPtrArray         *shortcuts_v,
+                                                int                context,
+                                                const char        *accelerator);
+GthShortcut * gth_shortcut_array_find_by_action (GPtrArray         *shortcuts_v,
+                                                const char        *detailed_action);
 gboolean      gth_shortcut_valid                (guint              keycode,
                                                 GdkModifierType    modifiers);
 gboolean      gth_shortcuts_write_to_file       (GPtrArray         *shortcuts_v,
diff --git a/gthumb/gth-window.c b/gthumb/gth-window.c
index 2cad403a..336206ca 100644
--- a/gthumb/gth-window.c
+++ b/gthumb/gth-window.c
@@ -709,10 +709,10 @@ static void
 _gth_window_add_shortcut (GthWindow   *window,
                          GthShortcut *shorcut)
 {
+       g_ptr_array_add (window->priv->shortcuts_v, shorcut);
        g_hash_table_insert (window->priv->shortcuts,
-                            g_strdup (shorcut->action_name),
+                            g_strdup (shorcut->detailed_action),
                             shorcut);
-       g_ptr_array_add (window->priv->shortcuts_v, shorcut);
 }
 
 
@@ -720,7 +720,7 @@ static void
 _gth_window_remove_shortcut (GthWindow   *window,
                             GthShortcut *shorcut)
 {
-       g_hash_table_remove (window->priv->shortcuts, shorcut->action_name);
+       g_hash_table_remove (window->priv->shortcuts, shorcut->detailed_action);
        g_ptr_array_remove (window->priv->shortcuts_v, shorcut);
 }
 
@@ -744,8 +744,7 @@ gth_window_add_accelerators (GthWindow                      *window,
                                                        acc->accelerator,
                                                        NULL);
 
-               shortcut = gth_shortcut_new ();
-               shortcut->action_name = g_strdup (acc->action_name);
+               shortcut = gth_shortcut_new (acc->action_name, NULL);
                shortcut->context = GTH_SHORTCUT_CONTEXT_INTERNAL | GTH_SHORTCUT_CONTEXT_ANY;
                shortcut->category = GTH_SHORTCUT_CATEGORY_HIDDEN;
                gth_shortcut_set_accelerator (shortcut, acc->accelerator);
@@ -836,6 +835,16 @@ gth_window_get_shortcuts (GthWindow *window)
 }
 
 
+GthShortcut *
+gth_window_get_shortcut (GthWindow  *window,
+                        const char *detailed_action)
+{
+       g_return_val_if_fail (GTH_IS_WINDOW (window), NULL);
+
+       return g_hash_table_lookup (window->priv->shortcuts, detailed_action);
+}
+
+
 static int
 sort_shortcuts_by_category (gconstpointer a,
                            gconstpointer b)
@@ -918,10 +927,15 @@ gth_window_add_removable_shortcut (GthWindow   *window,
                                   GthShortcut *shortcut)
 {
        GPtrArray   *shortcuts_v;
+       GthShortcut *old_shortcut;
        GthShortcut *new_shortcut;
 
        g_return_if_fail (GTH_IS_WINDOW (window));
        g_return_if_fail (group_name != NULL);
+       g_return_if_fail (shortcut != NULL);
+       g_return_if_fail (shortcut->detailed_action != NULL);
+
+       /* create the group if it doesn't exist. */
 
        shortcuts_v = g_hash_table_lookup (window->priv->shortcut_groups, group_name);
        if (shortcuts_v == NULL) {
@@ -931,10 +945,18 @@ gth_window_add_removable_shortcut (GthWindow   *window,
                                     shortcuts_v);
        }
 
+       /* remove the old shortcut */
+
+       old_shortcut = g_hash_table_lookup (window->priv->shortcuts, shortcut->detailed_action);
+       if (old_shortcut != NULL) {
+               g_ptr_array_remove (shortcuts_v, old_shortcut);
+               _gth_window_remove_shortcut (window, old_shortcut);
+       }
+
+       /* add the new shortcut */
+
        new_shortcut = gth_shortcut_dup (shortcut);
-       gth_shortcut_set_accelerator (new_shortcut, shortcut->default_accelerator);
        _gth_window_add_shortcut (window, new_shortcut);
-
        g_ptr_array_add (shortcuts_v, new_shortcut);
 }
 
@@ -960,3 +982,82 @@ gth_window_remove_shortcuts (GthWindow  *window,
 
        g_hash_table_remove (window->priv->shortcut_groups, group_name);
 }
+
+
+gboolean
+gth_window_can_change_shortcut (GthWindow         *window,
+                               const char        *detailed_action,
+                               int                context,
+                               guint              keycode,
+                               GdkModifierType    modifiers,
+                               GtkWindow         *parent)
+{
+       GthShortcut *shortcut;
+
+       if (window == NULL)
+               return TRUE;
+
+       shortcut = gth_shortcut_array_find (gth_window_get_shortcuts (window ),
+                                           GTH_SHORTCUT_CONTEXT_BROWSER_VIEWER,
+                                           keycode,
+                                           modifiers);
+
+       if (shortcut == NULL)
+               return TRUE;
+
+       if (g_strcmp0 (shortcut->detailed_action, detailed_action) == 0)
+               return FALSE;
+
+       if (gth_shortcut_customizable (shortcut)) {
+               char      *label;
+               char      *msg;
+               GtkWidget *dialog;
+               gboolean   reassign;
+
+               label = gtk_accelerator_get_label (keycode, modifiers);
+               msg = g_strdup_printf (_("The key combination «%s» is already assigned to the action «%s».  
Do you want to reassign it to this action instead?"),
+                                      label,
+                                      shortcut->description);
+
+               dialog = _gtk_yesno_dialog_new (parent,
+                                               GTK_DIALOG_MODAL,
+                                               msg,
+                                               _GTK_LABEL_CANCEL,
+                                               _("Reassign"));
+
+               reassign = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_YES;
+               gtk_widget_destroy (GTK_WIDGET (dialog));
+
+               g_free (msg);
+               g_free (label);
+
+               if (! reassign)
+                       return FALSE;
+       }
+       else {
+               char      *label;
+               char      *msg;
+               GtkWidget *dialog;
+
+               label = gtk_accelerator_get_label (keycode, modifiers);
+               msg = g_strdup_printf (_("The key combination «%s» is already assigned to the action «%s»."),
+                                      label,
+                                      shortcut->description);
+               dialog = _gtk_message_dialog_new (parent,
+                                                 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                 _GTK_ICON_NAME_DIALOG_ERROR,
+                                                 NULL,
+                                                 msg,
+                                                 _GTK_LABEL_OK, GTK_RESPONSE_OK,
+                                                 NULL);
+               gtk_dialog_run (GTK_DIALOG (dialog));
+               gtk_widget_destroy (GTK_WIDGET (dialog));
+
+               g_free (msg);
+               g_free (label);
+
+               return FALSE;
+       }
+
+       return TRUE;
+}
diff --git a/gthumb/gth-window.h b/gthumb/gth-window.h
index 7eeb89e4..89843e1c 100644
--- a/gthumb/gth-window.h
+++ b/gthumb/gth-window.h
@@ -125,6 +125,8 @@ void                gth_window_add_shortcuts        (GthWindow              *window,
                                                 const GthShortcut      *shortcuts,
                                                 int                     n_shortcuts);
 GPtrArray *    gth_window_get_shortcuts        (GthWindow              *window);
+GthShortcut *   gth_window_get_shortcut                (GthWindow              *window,
+                                                const char             *detailed_action);
 GPtrArray *    gth_window_get_shortcuts_by_category
                                                (GthWindow              *window);
 gboolean       gth_window_activate_shortcut    (GthWindow              *window,
@@ -138,6 +140,12 @@ void               gth_window_add_removable_shortcut
                                                 GthShortcut            *shortcut);
 void           gth_window_remove_shortcuts     (GthWindow              *window,
                                                 const char             *group_name);
+gboolean       gth_window_can_change_shortcut  (GthWindow              *window,
+                                                const char             *detailed_action,
+                                                int                     context,
+                                                guint                   keycode,
+                                                GdkModifierType         modifiers,
+                                                GtkWindow              *parent);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]