[gthumb] added ability to define custom shortcuts for a window



commit a20f5d2254b9852ee9c87ed1aa733f503e48ff3e
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sat Nov 9 17:59:53 2019 +0100

    added ability to define custom shortcuts for a window

 gthumb/gth-browser.c  |  93 ++++++-------------------------
 gthumb/gth-shortcut.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gthumb/gth-shortcut.h |  63 +++++++++++++++++++++
 gthumb/gth-window.c   |  85 +++++++++++++++++++++++++++++
 gthumb/gth-window.h   |   9 +++
 gthumb/meson.build    |   2 +
 gthumb/typedefs.h     |  21 +++++++
 7 files changed, 346 insertions(+), 75 deletions(-)
---
diff --git a/gthumb/gth-browser.c b/gthumb/gth-browser.c
index 879f88ba..d21c0bad 100644
--- a/gthumb/gth-browser.c
+++ b/gthumb/gth-browser.c
@@ -3716,41 +3716,19 @@ static gboolean
 gth_browser_file_list_key_press_cb (GthBrowser  *browser,
                                    GdkEventKey *event)
 {
-       gboolean    result = FALSE;
-       guint       modifiers;
+       guint    modifiers;
+       gboolean activated;
 
        modifiers = gtk_accelerator_get_default_mod_mask ();
+       activated = gth_window_activate_shortcut (GTH_WINDOW (browser),
+                                                 GTH_SHORTCUT_CONTEXT_BROWSER,
+                                                 event->keyval,
+                                                 (event->state & modifiers));
 
-       if ((event->state & modifiers) == 0) {
-               switch (event->keyval) {
-               case GDK_KEY_f:
-                       gth_browser_fullscreen (browser);
-                       result = TRUE;
-                       break;
-
-               case GDK_KEY_e:
-                       if (browser->priv->viewer_page != NULL)
-                               gth_browser_show_viewer_tools (GTH_BROWSER (browser));
-                       result = TRUE;
-                       break;
+       if (! activated)
+               activated = gth_hook_invoke_get ("gth-browser-file-list-key-press", browser, event) != NULL;
 
-               case GDK_KEY_i:
-                       if (gth_window_get_action_state (GTH_WINDOW (browser), "browser-properties"))
-                               gth_browser_hide_sidebar (browser);
-                       else
-                               gth_browser_show_file_properties (browser);
-                       result = TRUE;
-                       break;
-
-               default:
-                       break;
-               }
-        }
-
-       if (! result)
-               result = gth_hook_invoke_get ("gth-browser-file-list-key-press", browser, event) != NULL;
-
-       return result;
+       return activated;
 }
 
 
@@ -5657,56 +5635,21 @@ gboolean
 gth_browser_viewer_key_press_cb (GthBrowser  *browser,
                                 GdkEventKey *event)
 {
-       guint modifiers;
+       guint    modifiers;
+       gboolean activated;
 
        g_return_val_if_fail (event != NULL, FALSE);
 
        modifiers = gtk_accelerator_get_default_mod_mask ();
-       if ((event->state & modifiers) == 0) {
-               switch (event->keyval) {
-               case GDK_KEY_Page_Up:
-               case GDK_KEY_KP_Page_Up:
-               case GDK_KEY_BackSpace:
-                       gth_browser_show_prev_image (browser, FALSE, FALSE);
-                       return TRUE;
-
-               case GDK_KEY_Page_Down:
-               case GDK_KEY_KP_Page_Down:
-               case GDK_KEY_space:
-                       gth_browser_show_next_image (browser, FALSE, FALSE);
-                       return TRUE;
+       activated = gth_window_activate_shortcut (GTH_WINDOW (browser),
+                                                 GTH_SHORTCUT_CONTEXT_VIEWER,
+                                                 event->keyval,
+                                                 (event->state & modifiers));
 
-               case GDK_KEY_Home:
-               case GDK_KEY_KP_Home:
-                       gth_browser_show_first_image (browser, FALSE, FALSE);
-                       return TRUE;
-
-               case GDK_KEY_End:
-               case GDK_KEY_KP_End:
-                       gth_browser_show_last_image (browser, FALSE, FALSE);
-                       return TRUE;
-
-               case GDK_KEY_e:
-                       if (browser->priv->viewer_sidebar != GTH_SIDEBAR_STATE_TOOLS)
-                               gth_browser_show_viewer_tools (browser);
-                       else
-                               gth_browser_hide_sidebar (browser);
-                       return TRUE;
-
-               case GDK_KEY_i:
-                       gth_browser_toggle_properties_on_screen (browser);
-                       return TRUE;
+       if (! activated && gtk_widget_get_realized (browser->priv->file_list))
+               activated = gth_hook_invoke_get ("gth-browser-file-list-key-press", browser, event) != NULL;
 
-               case GDK_KEY_f:
-                       gth_browser_fullscreen (browser);
-                       return TRUE;
-               }
-       }
-
-       if (gtk_widget_get_realized (browser->priv->file_list))
-               return gth_hook_invoke_get ("gth-browser-file-list-key-press", browser, event) != NULL;
-       else
-               return FALSE;
+       return activated;
 }
 
 
diff --git a/gthumb/gth-shortcut.c b/gthumb/gth-shortcut.c
new file mode 100644
index 00000000..aafa7c10
--- /dev/null
+++ b/gthumb/gth-shortcut.c
@@ -0,0 +1,148 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2019 The Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include "gth-shortcut.h"
+
+
+GthShortcut *
+gth_shortcut_new (void)
+{
+       GthShortcut *shortcut;
+
+       shortcut = g_new (GthShortcut, 1);
+       shortcut->action_name = NULL;
+       shortcut->description = NULL;
+       shortcut->context = 0;
+       shortcut->category = 0;
+       shortcut->default_accelerator = NULL;
+       shortcut->accelerator = NULL;
+       shortcut->label = NULL;
+       shortcut->keyval = 0;
+       shortcut->modifiers = 0;
+
+       return shortcut;
+}
+
+
+GthShortcut *
+gth_shortcut_dup (const GthShortcut *shortcut)
+{
+       GthShortcut *new_shortcut;
+
+       new_shortcut = gth_shortcut_new ();
+       new_shortcut->action_name = g_strdup (shortcut->action_name);
+       new_shortcut->description = g_strdup (shortcut->description);
+       new_shortcut->context = shortcut->context;
+       new_shortcut->category = shortcut->category;
+       new_shortcut->default_accelerator = g_strdup (shortcut->default_accelerator);
+       gth_shortcut_set_name (new_shortcut, shortcut->accelerator);
+
+       return new_shortcut;
+}
+
+
+void
+gth_shortcut_free (GthShortcut *shortcut)
+{
+       g_free (shortcut->action_name);
+       g_free (shortcut->description);
+       g_free (shortcut->default_accelerator);
+       g_free (shortcut->accelerator);
+       g_free (shortcut->label);
+       g_free (shortcut);
+}
+
+
+void
+gth_shortcut_set_name (GthShortcut *shortcut,
+                      const char  *accelerator)
+{
+       guint           keyval;
+       GdkModifierType modifiers;
+
+       keyval = 0;
+       modifiers = 0;
+       if (accelerator != NULL)
+               gtk_accelerator_parse (accelerator, &keyval, &modifiers);
+       gth_shortcut_set_key (shortcut, keyval, modifiers);
+}
+
+
+void
+gth_shortcut_set_key (GthShortcut       *shortcut,
+                     guint              keyval,
+                     GdkModifierType    modifiers)
+{
+       g_free (shortcut->accelerator);
+       g_free (shortcut->label);
+
+       shortcut->keyval = keyval;
+       shortcut->modifiers = modifiers;
+       shortcut->accelerator = gtk_accelerator_name (shortcut->keyval, shortcut->modifiers);
+       shortcut->label = gtk_accelerator_get_label (shortcut->keyval, shortcut->modifiers);
+}
+
+
+GthShortcut *
+gth_shortcut_array_find (GPtrArray       *shortcuts_v,
+                        int              context,
+                        guint            keycode,
+                        GdkModifierType  modifiers)
+{
+       int i;
+
+       for (i = 0; i < shortcuts_v->len; i++) {
+               GthShortcut *shortcut = g_ptr_array_index (shortcuts_v, i);
+
+               if (((shortcut->context & context) == context)
+                       && (shortcut->keyval == keycode)
+                       && (shortcut->modifiers == modifiers))
+               {
+                       return shortcut;
+               }
+       }
+
+       return NULL;
+}
+
+
+gboolean
+gth_shortcut_valid (guint           keycode,
+                   GdkModifierType modifiers)
+{
+       switch (keycode) {
+       case GDK_KEY_Escape:
+       case GDK_KEY_Tab:
+               return FALSE;
+
+       case GDK_KEY_Left:
+       case GDK_KEY_Right:
+       case GDK_KEY_Up:
+       case GDK_KEY_Down:
+               return TRUE;
+
+       default:
+               return gtk_accelerator_valid (keycode, modifiers);
+       }
+
+       return FALSE;
+}
diff --git a/gthumb/gth-shortcut.h b/gthumb/gth-shortcut.h
new file mode 100644
index 00000000..2be111d0
--- /dev/null
+++ b/gthumb/gth-shortcut.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2019 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_SHORTCUT_H
+#define GTH_SHORTCUT_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTH_SHORTCUT_CONTEXT_INTERNAL -1
+#define GTH_SHORTCUT_CATEGORY_HIDDEN -1
+
+
+typedef struct {
+       char            *action_name;
+       char            *description;
+       int              context;
+       int              category;
+       char            *default_accelerator;
+       char            *accelerator;
+       char            *label;
+       guint            keyval;
+       GdkModifierType  modifiers;
+} GthShortcut;
+
+
+GthShortcut * gth_shortcut_new                 (void);
+GthShortcut * gth_shortcut_dup                 (const GthShortcut *shortcut);
+void          gth_shortcut_free                        (GthShortcut       *shortcut);
+void          gth_shortcut_set_key             (GthShortcut       *shortcut,
+                                                guint              keyval,
+                                                GdkModifierType    modifiers);
+void          gth_shortcut_set_name            (GthShortcut       *shortcut,
+                                                const char        *name);
+GthShortcut * gth_shortcut_array_find           (GPtrArray         *shortcuts_v,
+                                                int                context,
+                                                guint              keycode,
+                                                GdkModifierType    modifiers);
+gboolean      gth_shortcut_valid                (guint              keycode,
+                                                GdkModifierType    modifiers);
+
+G_END_DECLS
+
+#endif /* GTH_SHORTCUT_H */
diff --git a/gthumb/gth-window.c b/gthumb/gth-window.c
index 5cba0c47..c3b60077 100644
--- a/gthumb/gth-window.c
+++ b/gthumb/gth-window.c
@@ -21,6 +21,7 @@
 
 #include <config.h>
 #include <gtk/gtk.h>
+#include "glib-utils.h"
 #include "gth-window.h"
 #include "gth-window-title.h"
 #include "gtk-utils.h"
@@ -54,6 +55,8 @@ struct _GthWindowPrivate {
        GthWindowSize   *window_size;
        GtkWindowGroup  *window_group;
        GtkAccelGroup   *accel_group;
+       GHashTable      *shortcuts;
+       GPtrArray       *shortcuts_v;
 };
 
 
@@ -249,6 +252,8 @@ gth_window_finalize (GObject *object)
        g_free (window->priv->window_size);
        g_object_unref (window->priv->window_group);
        g_object_unref (window->priv->accel_group);
+       g_hash_table_unref (window->priv->shortcuts);
+       g_ptr_array_free (window->priv->shortcuts_v, TRUE);
 
        G_OBJECT_CLASS (gth_window_parent_class)->finalize (object);
 }
@@ -399,6 +404,9 @@ gth_window_init (GthWindow *window)
        window->priv->accel_group = gtk_accel_group_new ();
        gtk_window_add_accel_group (GTK_WINDOW (window), window->priv->accel_group);
 
+       window->priv->shortcuts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+       window->priv->shortcuts_v = g_ptr_array_new_with_free_func ((GDestroyNotify) gth_shortcut_free);
+
        gtk_window_set_application (GTK_WINDOW (window), Main_Application);
 }
 
@@ -692,6 +700,17 @@ gth_window_get_accel_group (GthWindow *window)
 }
 
 
+static void
+_gth_window_add_shortcut (GthWindow   *window,
+                         GthShortcut *shorcut)
+{
+       g_hash_table_insert (window->priv->shortcuts,
+                            g_strdup (shorcut->action_name),
+                            GINT_TO_POINTER (1));
+       g_ptr_array_add (window->priv->shortcuts_v, shorcut);
+}
+
+
 void
 gth_window_add_accelerators (GthWindow                 *window,
                             const GthAccelerator       *accelerators,
@@ -703,12 +722,20 @@ gth_window_add_accelerators (GthWindow                    *window,
        accel_group = gth_window_get_accel_group (window);
        for (i = 0; i < n_accelerators; i++) {
                const GthAccelerator *acc = accelerators + i;
+               GthShortcut          *shortcut;
 
                _gtk_window_add_accelerator_for_action (GTK_WINDOW (window),
                                                        accel_group,
                                                        acc->action_name,
                                                        acc->accelerator,
                                                        NULL);
+
+               shortcut = gth_shortcut_new ();
+               shortcut->action_name = g_strdup (acc->action_name);
+               shortcut->context = GTH_SHORTCUT_CONTEXT_INTERNAL;
+               shortcut->category = GTH_SHORTCUT_CATEGORY_HIDDEN;
+               gth_shortcut_set_name (shortcut, acc->accelerator);
+               _gth_window_add_shortcut (window, shortcut);
        }
 }
 
@@ -765,3 +792,61 @@ gth_window_change_action_state (GthWindow  *window,
                g_variant_unref (old_state);
        g_variant_unref (new_state);
 }
+
+
+void
+gth_window_add_shortcuts (GthWindow         *window,
+                         const GthShortcut *shortcuts,
+                         int                n_shortcuts)
+{
+       int i;
+
+       for (i = 0; i < n_shortcuts; i++) {
+               const GthShortcut *shortcut = shortcuts + i;
+               GthShortcut       *new_shortcut;
+
+               new_shortcut = gth_shortcut_dup (shortcut);
+               gth_shortcut_set_name (new_shortcut, shortcut->default_accelerator);
+
+               _gth_window_add_shortcut (window, new_shortcut);
+       }
+}
+
+
+GPtrArray *
+gth_window_get_shortcuts (GthWindow *window)
+{
+       g_return_val_if_fail (GTH_IS_WINDOW (window), NULL);
+
+       return window->priv->shortcuts_v;
+}
+
+
+gboolean
+gth_window_activate_shortcut (GthWindow       *window,
+                             int              context,
+                             guint            keycode,
+                             GdkModifierType  modifiers)
+{
+       gboolean     activated = FALSE;
+       GthShortcut *shortcut;
+
+       shortcut = gth_shortcut_array_find (window->priv->shortcuts_v, context, keycode, modifiers);
+       if (shortcut != NULL) {
+               GAction *action;
+
+               action = g_action_map_lookup_action (G_ACTION_MAP (window), shortcut->action_name);
+               if (action != NULL) {
+                       GVariant *variant;
+
+                       variant = g_action_get_state (action);
+                       g_action_activate (action, variant);
+                       activated = TRUE;
+
+                       if (variant != NULL)
+                               g_variant_unref (variant);
+               }
+       }
+
+       return activated;
+}
diff --git a/gthumb/gth-window.h b/gthumb/gth-window.h
index 366c07fc..e6bf2e89 100644
--- a/gthumb/gth-window.h
+++ b/gthumb/gth-window.h
@@ -24,6 +24,7 @@
 
 #include <gtk/gtk.h>
 #include "gtk-utils.h"
+#include "gth-shortcut.h"
 
 G_BEGIN_DECLS
 
@@ -120,6 +121,14 @@ gboolean   gth_window_get_action_state     (GthWindow              *window,
 void           gth_window_change_action_state  (GthWindow              *window,
                                                 const char             *action_name,
                                                 gboolean                value);
+void           gth_window_add_shortcuts        (GthWindow              *window,
+                                                const GthShortcut      *shortcuts,
+                                                int                     n_shortcuts);
+GPtrArray *    gth_window_get_shortcuts        (GthWindow              *window);
+gboolean       gth_window_activate_shortcut    (GthWindow              *window,
+                                                int                     context,
+                                                guint                   keycode,
+                                                GdkModifierType         modifiers);
 
 G_END_DECLS
 
diff --git a/gthumb/meson.build b/gthumb/meson.build
index 514d87f1..2f9065dd 100644
--- a/gthumb/meson.build
+++ b/gthumb/meson.build
@@ -80,6 +80,7 @@ public_header_files = [
   'gth-save-file-data-task.h',
   'gth-save-image-task.h',
   'gth-screensaver.h',
+  'gth-shortcut.h',
   'gth-sidebar.h',
   'gth-sidebar-section.h',
   'gth-statusbar.h',
@@ -244,6 +245,7 @@ source_files = files(
   'gth-save-file-data-task.c',
   'gth-save-image-task.c',
   'gth-screensaver.c',
+  'gth-shortcut.c',
   'gth-sidebar.c',
   'gth-sidebar-section.c',
   'gth-statusbar.c',
diff --git a/gthumb/typedefs.h b/gthumb/typedefs.h
index 5d2f738d..0bb6b9ec 100644
--- a/gthumb/typedefs.h
+++ b/gthumb/typedefs.h
@@ -130,6 +130,27 @@ typedef enum /*< skip >*/ {
 } GthColorSpace;
 
 
+typedef enum {
+       GTH_SHORTCUT_CONTEXT_BROWSER = 1 << 1,
+       GTH_SHORTCUT_CONTEXT_VIEWER = 1 << 2,
+       GTH_SHORTCUT_CONTEXT_SLIDESHOW = 1 << 3,
+
+       /* aggregated values */
+
+       GTH_SHORTCUT_CONTEXT_BROWSER_VIEWER = (GTH_SHORTCUT_CONTEXT_BROWSER | GTH_SHORTCUT_CONTEXT_VIEWER),
+       GTH_SHORTCUT_CONTEXT_ANY = (GTH_SHORTCUT_CONTEXT_BROWSER | GTH_SHORTCUT_CONTEXT_VIEWER | 
GTH_SHORTCUT_CONTEXT_SLIDESHOW),
+} GthShortcutContext;
+
+typedef enum {
+       GTH_SHORTCUT_CATEGORY_UI,
+       GTH_SHORTCUT_CATEGORY_FILE_NAVIGATION,
+       GTH_SHORTCUT_CATEGORY_FILE_EDIT,
+       GTH_SHORTCUT_CATEGORY_IMAGE_VIEW,
+       GTH_SHORTCUT_CATEGORY_IMAGE_EDIT,
+       GTH_SHORTCUT_CATEGORY_SLIDESHOW
+} GthShortcutCategory;
+
+
 typedef void (*DataFunc)         (gpointer    user_data);
 typedef void (*ReadyFunc)        (GError     *error,
                                  gpointer    user_data);


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