[gnome-builder/wip/chergert/merge-shortcuts] shorcuts: update shortcut engine snapshot



commit b081a5fd5241bb1b41c61cc27b1a591d80dd9517
Author: Christian Hergert <chergert redhat com>
Date:   Fri May 26 14:40:56 2017 -0700

    shorcuts: update shortcut engine snapshot

 libide/shortcuts/ide-shortcut-controller.c |   26 +++++++++
 libide/shortcuts/ide-shortcut-label.c      |   34 +++++++-----
 libide/shortcuts/ide-shortcut-manager.c    |   37 +++++++++++++
 libide/shortcuts/ide-shortcut-manager.h    |   82 ++++++++++++++++------------
 libide/shortcuts/ide-shortcut-private.h    |    2 +
 libide/shortcuts/ide-shortcut-theme-load.c |   10 ++++
 libide/shortcuts/ide-shortcut-theme-save.c |   10 +++-
 libide/shortcuts/ide-shortcut-theme.c      |   74 +++++++++++++++++++++++++
 libide/shortcuts/ide-shortcut-theme.h      |    3 +
 9 files changed, 228 insertions(+), 50 deletions(-)
---
diff --git a/libide/shortcuts/ide-shortcut-controller.c b/libide/shortcuts/ide-shortcut-controller.c
index a3ad070..3c7932e 100644
--- a/libide/shortcuts/ide-shortcut-controller.c
+++ b/libide/shortcuts/ide-shortcut-controller.c
@@ -78,6 +78,7 @@ typedef struct
    */
   gulong hierarchy_changed_handler;
   gulong widget_destroy_handler;
+  gulong manager_changed_handler;
 } IdeShortcutControllerPrivate;
 
 typedef struct
@@ -152,6 +153,19 @@ ide_shortcut_controller_remove (IdeShortcutController *self,
 }
 
 static void
+ide_shortcut_controller_on_manager_changed (IdeShortcutController *self,
+                                            IdeShortcutManager    *manager)
+{
+  IdeShortcutControllerPrivate *priv = ide_shortcut_controller_get_instance_private (self);
+
+  g_assert (IDE_IS_SHORTCUT_CONTROLLER (self));
+  g_assert (IDE_IS_SHORTCUT_MANAGER (manager));
+
+  g_clear_pointer (&priv->current_chord, ide_shortcut_chord_free);
+  g_clear_object (&priv->context);
+}
+
+static void
 ide_shortcut_controller_widget_destroy (IdeShortcutController *self,
                                         GtkWidget             *widget)
 {
@@ -216,6 +230,9 @@ ide_shortcut_controller_disconnect (IdeShortcutController *self)
 
   g_signal_handler_disconnect (priv->widget, priv->hierarchy_changed_handler);
   priv->hierarchy_changed_handler = 0;
+
+  g_signal_handler_disconnect (ide_shortcut_manager_get_default (), priv->manager_changed_handler);
+  priv->manager_changed_handler = 0;
 }
 
 static void
@@ -226,6 +243,9 @@ ide_shortcut_controller_connect (IdeShortcutController *self)
   g_assert (IDE_IS_SHORTCUT_CONTROLLER (self));
   g_assert (GTK_IS_WIDGET (priv->widget));
 
+  g_clear_pointer (&priv->current_chord, ide_shortcut_chord_free);
+  g_clear_object (&priv->context);
+
   priv->widget_destroy_handler =
     g_signal_connect_swapped (priv->widget,
                               "destroy",
@@ -238,6 +258,12 @@ ide_shortcut_controller_connect (IdeShortcutController *self)
                               G_CALLBACK (ide_shortcut_controller_widget_hierarchy_changed),
                               self);
 
+  priv->manager_changed_handler =
+    g_signal_connect_swapped (ide_shortcut_manager_get_default (),
+                              "changed",
+                              G_CALLBACK (ide_shortcut_controller_on_manager_changed),
+                              self);
+
   ide_shortcut_controller_widget_hierarchy_changed (self, NULL, priv->widget);
 }
 
diff --git a/libide/shortcuts/ide-shortcut-label.c b/libide/shortcuts/ide-shortcut-label.c
index f383026..85e7213 100644
--- a/libide/shortcuts/ide-shortcut-label.c
+++ b/libide/shortcuts/ide-shortcut-label.c
@@ -160,32 +160,40 @@ void
 ide_shortcut_label_set_chord (IdeShortcutLabel       *self,
                               const IdeShortcutChord *chord)
 {
+  g_return_if_fail (IDE_IS_SHORTCUT_LABEL (self));
+
   if (!ide_shortcut_chord_equal (chord, self->chord))
     {
-      g_autofree gchar *accel = NULL;
-
       ide_shortcut_chord_free (self->chord);
       self->chord = ide_shortcut_chord_copy (chord);
 
-      if (self->chord != NULL)
-        accel = ide_shortcut_chord_to_string (self->chord);
-
-      gtk_container_foreach (GTK_CONTAINER (self),
-                             (GtkCallback) gtk_widget_destroy,
-                             NULL);
+      gtk_container_foreach (GTK_CONTAINER (self), (GtkCallback) gtk_widget_destroy, NULL);
 
-      if (accel != NULL)
+      if (chord != NULL)
         {
-          g_auto(GStrv) parts = NULL;
+          GdkModifierType first_mod = 0;
+          guint len;
 
-          parts = g_strsplit (accel, "|", 0);
+          len = ide_shortcut_chord_get_length (chord);
 
-          for (guint i = 0; parts[i]; i++)
+          ide_shortcut_chord_get_nth_key (chord, 0, NULL, &first_mod);
+
+          for (guint i = 0; i < len; i++)
             {
+              g_autofree gchar *accel = NULL;
               GtkWidget *label;
+              GdkModifierType mod = 0;
+              guint keyval = 0;
+
+              ide_shortcut_chord_get_nth_key (chord, i, &keyval, &mod);
+
+              if (i > 0 && (mod & first_mod) == first_mod)
+                accel = gtk_accelerator_name (keyval, mod & ~first_mod);
+              else
+                accel = gtk_accelerator_name (keyval, mod);
 
               label = g_object_new (GTK_TYPE_SHORTCUT_LABEL,
-                                    "accelerator", parts[i],
+                                    "accelerator", accel,
                                     "visible", TRUE,
                                     NULL);
               gtk_container_add (GTK_CONTAINER (self), label);
diff --git a/libide/shortcuts/ide-shortcut-manager.c b/libide/shortcuts/ide-shortcut-manager.c
index 670cad8..4f23add 100644
--- a/libide/shortcuts/ide-shortcut-manager.c
+++ b/libide/shortcuts/ide-shortcut-manager.c
@@ -962,3 +962,40 @@ _ide_shortcut_manager_get_root (IdeShortcutManager *self)
 
   return priv->root;
 }
+
+/**
+ * ide_shortcut_manager_add_shortcut_entries:
+ * @self: (nullable): a #IdeShortcutManager or %NULL for the default
+ * @shortcuts: (array length=n_shortcuts): shortcuts to add
+ * @n_shortcuts: the number of entries in @shortcuts
+ * @translation_domain: (nullable): the gettext domain to use for translations
+ *
+ * This method will add @shortcuts to the #IdeShortcutManager.
+ *
+ * This provides a simple way for widgets to add their shortcuts to the manager
+ * so that they may be overriden by themes or the end user.
+ */
+void
+ide_shortcut_manager_add_shortcut_entries (IdeShortcutManager     *self,
+                                           const IdeShortcutEntry *shortcuts,
+                                           guint                   n_shortcuts,
+                                           const gchar            *translation_domain)
+{
+  g_return_if_fail (!self || IDE_IS_SHORTCUT_MANAGER (self));
+  g_return_if_fail (shortcuts != NULL || n_shortcuts == 0);
+
+  if (self == NULL)
+    self = ide_shortcut_manager_get_default ();
+
+  for (guint i = 0; i < n_shortcuts; i++)
+    {
+      const IdeShortcutEntry *entry = &shortcuts[i];
+
+      ide_shortcut_manager_add_command (self,
+                                        g_dgettext (translation_domain, entry->command),
+                                        g_dgettext (translation_domain, entry->section),
+                                        g_dgettext (translation_domain, entry->group),
+                                        g_dgettext (translation_domain, entry->title),
+                                        g_dgettext (translation_domain, entry->subtitle));
+    }
+}
diff --git a/libide/shortcuts/ide-shortcut-manager.h b/libide/shortcuts/ide-shortcut-manager.h
index eeaec24..181e2e4 100644
--- a/libide/shortcuts/ide-shortcut-manager.h
+++ b/libide/shortcuts/ide-shortcut-manager.h
@@ -30,6 +30,16 @@ G_BEGIN_DECLS
 
 G_DECLARE_DERIVABLE_TYPE (IdeShortcutManager, ide_shortcut_manager, IDE, SHORTCUT_MANAGER, GObject)
 
+typedef struct
+{
+  const gchar *command;
+  const gchar *section;
+  const gchar *group;
+  const gchar *title;
+  const gchar *subtitle;
+  /* TODO: Should we add a default accelerator to add to the default theme? */
+} IdeShortcutEntry;
+
 struct _IdeShortcutManagerClass
 {
   GObjectClass parent_instance;
@@ -45,40 +55,44 @@ struct _IdeShortcutManagerClass
 };
 
 IdeShortcutManager *ide_shortcut_manager_get_default             (void);
-void                ide_shortcut_manager_append_search_path      (IdeShortcutManager *self,
-                                                                  const gchar        *directory);
-void                ide_shortcut_manager_prepend_search_path     (IdeShortcutManager *self,
-                                                                  const gchar        *directory);
-IdeShortcutTheme   *ide_shortcut_manager_get_theme               (IdeShortcutManager *self);
-void                ide_shortcut_manager_set_theme               (IdeShortcutManager *self,
-                                                                  IdeShortcutTheme   *theme);
-const gchar        *ide_shortcut_manager_get_theme_name          (IdeShortcutManager *self);
-void                ide_shortcut_manager_set_theme_name          (IdeShortcutManager *self,
-                                                                  const gchar        *theme_name);
-gboolean            ide_shortcut_manager_handle_event            (IdeShortcutManager *self,
-                                                                  const GdkEventKey  *event,
-                                                                  GtkWidget          *toplevel);
-void                ide_shortcut_manager_add_theme               (IdeShortcutManager *self,
-                                                                  IdeShortcutTheme   *theme);
-void                ide_shortcut_manager_remove_theme            (IdeShortcutManager *self,
-                                                                  IdeShortcutTheme   *theme);
-const gchar        *ide_shortcut_manager_get_user_dir            (IdeShortcutManager *self);
-void                ide_shortcut_manager_set_user_dir            (IdeShortcutManager *self,
-                                                                  const gchar        *user_dir);
-void                ide_shortcut_manager_add_action              (IdeShortcutManager *self,
-                                                                  const gchar        *detailed_action_name,
-                                                                  const gchar        *section,
-                                                                  const gchar        *group,
-                                                                  const gchar        *title,
-                                                                  const gchar        *subtitle);
-void                ide_shortcut_manager_add_command             (IdeShortcutManager *self,
-                                                                  const gchar        *command,
-                                                                  const gchar        *section,
-                                                                  const gchar        *group,
-                                                                  const gchar        *title,
-                                                                  const gchar        *subtitle);
-void                ide_shortcut_manager_add_shortcuts_to_window (IdeShortcutManager *self,
-                                                                  IdeShortcutsWindow *window);
+void                ide_shortcut_manager_append_search_path      (IdeShortcutManager     *self,
+                                                                  const gchar            *directory);
+void                ide_shortcut_manager_prepend_search_path     (IdeShortcutManager     *self,
+                                                                  const gchar            *directory);
+IdeShortcutTheme   *ide_shortcut_manager_get_theme               (IdeShortcutManager     *self);
+void                ide_shortcut_manager_set_theme               (IdeShortcutManager     *self,
+                                                                  IdeShortcutTheme       *theme);
+const gchar        *ide_shortcut_manager_get_theme_name          (IdeShortcutManager     *self);
+void                ide_shortcut_manager_set_theme_name          (IdeShortcutManager     *self,
+                                                                  const gchar            *theme_name);
+gboolean            ide_shortcut_manager_handle_event            (IdeShortcutManager     *self,
+                                                                  const GdkEventKey      *event,
+                                                                  GtkWidget              *toplevel);
+void                ide_shortcut_manager_add_theme               (IdeShortcutManager     *self,
+                                                                  IdeShortcutTheme       *theme);
+void                ide_shortcut_manager_remove_theme            (IdeShortcutManager     *self,
+                                                                  IdeShortcutTheme       *theme);
+const gchar        *ide_shortcut_manager_get_user_dir            (IdeShortcutManager     *self);
+void                ide_shortcut_manager_set_user_dir            (IdeShortcutManager     *self,
+                                                                  const gchar            *user_dir);
+void                ide_shortcut_manager_add_action              (IdeShortcutManager     *self,
+                                                                  const gchar            
*detailed_action_name,
+                                                                  const gchar            *section,
+                                                                  const gchar            *group,
+                                                                  const gchar            *title,
+                                                                  const gchar            *subtitle);
+void                ide_shortcut_manager_add_command             (IdeShortcutManager     *self,
+                                                                  const gchar            *command,
+                                                                  const gchar            *section,
+                                                                  const gchar            *group,
+                                                                  const gchar            *title,
+                                                                  const gchar            *subtitle);
+void                ide_shortcut_manager_add_shortcut_entries    (IdeShortcutManager     *self,
+                                                                  const IdeShortcutEntry *shortcuts,
+                                                                  guint                   n_shortcuts,
+                                                                  const gchar            
*translation_domain);
+void                ide_shortcut_manager_add_shortcuts_to_window (IdeShortcutManager     *self,
+                                                                  IdeShortcutsWindow     *window);
 
 G_END_DECLS
 
diff --git a/libide/shortcuts/ide-shortcut-private.h b/libide/shortcuts/ide-shortcut-private.h
index 8a6895e..d07e8df 100644
--- a/libide/shortcuts/ide-shortcut-private.h
+++ b/libide/shortcuts/ide-shortcut-private.h
@@ -85,6 +85,8 @@ typedef enum
 GNode                 *_ide_shortcut_manager_get_root      (IdeShortcutManager         *self);
 GtkTreeModel          *_ide_shortcut_theme_create_model    (IdeShortcutTheme           *self);
 GHashTable            *_ide_shortcut_theme_get_contexts    (IdeShortcutTheme           *self);
+void                   _ide_shortcut_theme_set_name        (IdeShortcutTheme           *self,
+                                                            const gchar                *name);
 IdeShortcutChordTable *_ide_shortcut_context_get_table     (IdeShortcutContext         *self);
 void                   _ide_shortcut_chord_table_iter_init (IdeShortcutChordTableIter  *iter,
                                                             IdeShortcutChordTable      *table);
diff --git a/libide/shortcuts/ide-shortcut-theme-load.c b/libide/shortcuts/ide-shortcut-theme-load.c
index 585355e..b64b7b1 100644
--- a/libide/shortcuts/ide-shortcut-theme-load.c
+++ b/libide/shortcuts/ide-shortcut-theme-load.c
@@ -21,6 +21,7 @@
 #include <string.h>
 
 #include "ide-shortcut-context.h"
+#include "ide-shortcut-private.h"
 #include "ide-shortcut-theme.h"
 
 typedef enum
@@ -324,6 +325,8 @@ theme_start_element (GMarkupParseContext  *context,
 
   if (g_strcmp0 (element_name, "theme") == 0)
     {
+      const gchar *name = NULL;
+      const gchar *parent = NULL;
       const gchar *domain = NULL;
 
       if (state->stack != NULL)
@@ -336,6 +339,8 @@ theme_start_element (GMarkupParseContext  *context,
         }
 
       if (!g_markup_collect_attributes (element_name, attr_names, attr_values, error,
+                                        G_MARKUP_COLLECT_STRING, "name", &name,
+                                        G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "parent", 
&parent,
                                         G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, 
"translation-domain", &domain,
                                         G_MARKUP_COLLECT_INVALID))
         return;
@@ -343,6 +348,11 @@ theme_start_element (GMarkupParseContext  *context,
       if (domain != NULL)
         state->translation_domain = g_intern_string (domain);
 
+      _ide_shortcut_theme_set_name (state->self, name);
+
+      if (parent != NULL)
+        ide_shortcut_theme_set_parent_name (state->self, parent);
+
       load_state_push (state, load_state_frame_new (LOAD_STATE_THEME));
     }
   else if (g_strcmp0 (element_name, "property") == 0)
diff --git a/libide/shortcuts/ide-shortcut-theme-save.c b/libide/shortcuts/ide-shortcut-theme-save.c
index b89be0b..bad4f98 100644
--- a/libide/shortcuts/ide-shortcut-theme-save.c
+++ b/libide/shortcuts/ide-shortcut-theme-save.c
@@ -30,6 +30,7 @@ ide_shortcut_theme_save_to_stream (IdeShortcutTheme  *self,
   GHashTable *contexts;
   GHashTableIter iter;
   const gchar *name;
+  const gchar *parent;
   const gchar *title;
   const gchar *subtitle;
 
@@ -41,13 +42,16 @@ ide_shortcut_theme_save_to_stream (IdeShortcutTheme  *self,
 
   str = g_string_new ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
 
-  g_string_append (str, "<theme>\n");
-
   name = ide_shortcut_theme_get_name (self);
+  parent = ide_shortcut_theme_get_parent_name (self);
   title = ide_shortcut_theme_get_title (self);
   subtitle = ide_shortcut_theme_get_subtitle (self);
 
-  g_string_append_printf (str, "  <property name=\"name\">%s</property>\n", name ? name : "");
+  if (parent != NULL)
+    g_string_append_printf (str, "<theme name=\"%s\" parent=\"%s\">\n", name, parent);
+  else
+    g_string_append_printf (str, "<theme name=\"%s\">\n", name);
+
   g_string_append_printf (str, "  <property name=\"title\" translatable=\"yes\">%s</property>\n", title ? 
title : "");
   g_string_append_printf (str, "  <property name=\"subtitle\" translatable=\"yes\">%s</property>\n", 
subtitle ? subtitle : "");
 
diff --git a/libide/shortcuts/ide-shortcut-theme.c b/libide/shortcuts/ide-shortcut-theme.c
index d26d5a5..e8628c2 100644
--- a/libide/shortcuts/ide-shortcut-theme.c
+++ b/libide/shortcuts/ide-shortcut-theme.c
@@ -24,6 +24,7 @@
 typedef struct
 {
   gchar      *name;
+  gchar      *parent_name;
   gchar      *title;
   gchar      *subtitle;
   GHashTable *contexts;
@@ -34,6 +35,7 @@ typedef struct
 enum {
   PROP_0,
   PROP_NAME,
+  PROP_PARENT_NAME,
   PROP_SUBTITLE,
   PROP_TITLE,
   N_PROPS
@@ -50,6 +52,7 @@ ide_shortcut_theme_finalize (GObject *object)
   IdeShortcutThemePrivate *priv = ide_shortcut_theme_get_instance_private (self);
 
   g_clear_pointer (&priv->name, g_free);
+  g_clear_pointer (&priv->parent_name, g_free);
   g_clear_pointer (&priv->title, g_free);
   g_clear_pointer (&priv->subtitle, g_free);
   g_clear_pointer (&priv->contexts, g_hash_table_unref);
@@ -73,6 +76,10 @@ ide_shortcut_theme_get_property (GObject    *object,
       g_value_set_string (value, ide_shortcut_theme_get_name (self));
       break;
 
+    case PROP_PARENT_NAME:
+      g_value_set_string (value, ide_shortcut_theme_get_parent_name (self));
+      break;
+
     case PROP_TITLE:
       g_value_set_string (value, ide_shortcut_theme_get_title (self));
       break;
@@ -101,11 +108,17 @@ ide_shortcut_theme_set_property (GObject      *object,
       priv->name = g_value_dup_string (value);
       break;
 
+    case PROP_PARENT_NAME:
+      ide_shortcut_theme_set_parent_name (self, g_value_get_string (value));
+      break;
+
     case PROP_TITLE:
+      g_free (priv->title);
       priv->title = g_value_dup_string (value);
       break;
 
     case PROP_SUBTITLE:
+      g_free (priv->subtitle);
       priv->subtitle = g_value_dup_string (value);
       break;
 
@@ -128,6 +141,13 @@ ide_shortcut_theme_class_init (IdeShortcutThemeClass *klass)
                          "Name",
                          "The name of the theme",
                          NULL,
+                         (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_PARENT_NAME] =
+    g_param_spec_string ("parent-name",
+                         "Parent Name",
+                         "The name of the parent shortcut theme",
+                         NULL,
                          (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   properties [PROP_TITLE] =
@@ -385,3 +405,57 @@ ide_shortcut_theme_set_accel_for_command (IdeShortcutTheme *self,
       ide_shortcut_theme_set_chord_for_command (self, detailed_command_name, chord);
     }
 }
+
+void
+_ide_shortcut_theme_set_name (IdeShortcutTheme *self,
+                              const gchar      *name)
+{
+  IdeShortcutThemePrivate *priv = ide_shortcut_theme_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_SHORTCUT_THEME (self));
+
+  if (g_strcmp0 (name, priv->name) != 0)
+    {
+      g_free (priv->name);
+      priv->name = g_strdup (name);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_NAME]);
+    }
+}
+
+/**
+ * ide_shortcut_theme_get_parent_name:
+ * @self: a #IdeShortcutTheme
+ *
+ * Gets the name of the parent shortcut theme.
+ *
+ * This is used to resolve shortcuts from the parent theme without having to
+ * copy them directly into this shortcut theme. It allows for some level of
+ * copy-on-write (CoW).
+ *
+ * Returns: (nullable): The name of the parent theme, or %NULL if none is set.
+ */
+const gchar *
+ide_shortcut_theme_get_parent_name (IdeShortcutTheme *self)
+{
+  IdeShortcutThemePrivate *priv = ide_shortcut_theme_get_instance_private (self);
+
+  g_return_val_if_fail (IDE_IS_SHORTCUT_THEME (self), NULL);
+
+  return priv->parent_name;
+}
+
+void
+ide_shortcut_theme_set_parent_name (IdeShortcutTheme *self,
+                                    const gchar      *parent_name)
+{
+  IdeShortcutThemePrivate *priv = ide_shortcut_theme_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_SHORTCUT_THEME (self));
+
+  if (g_strcmp0 (parent_name, priv->parent_name) != 0)
+    {
+      g_free (priv->parent_name);
+      priv->parent_name = g_strdup (parent_name);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PARENT_NAME]);
+    }
+}
diff --git a/libide/shortcuts/ide-shortcut-theme.h b/libide/shortcuts/ide-shortcut-theme.h
index 5fd8b82..888ff54 100644
--- a/libide/shortcuts/ide-shortcut-theme.h
+++ b/libide/shortcuts/ide-shortcut-theme.h
@@ -48,6 +48,9 @@ IdeShortcutTheme       *ide_shortcut_theme_new                   (const gchar
 const gchar            *ide_shortcut_theme_get_name              (IdeShortcutTheme        *self);
 const gchar            *ide_shortcut_theme_get_title             (IdeShortcutTheme        *self);
 const gchar            *ide_shortcut_theme_get_subtitle          (IdeShortcutTheme        *self);
+const gchar            *ide_shortcut_theme_get_parent_name       (IdeShortcutTheme        *self);
+void                    ide_shortcut_theme_set_parent_name       (IdeShortcutTheme        *self,
+                                                                  const gchar             *parent_name);
 IdeShortcutContext     *ide_shortcut_theme_find_default_context  (IdeShortcutTheme        *self,
                                                                   GtkWidget               *widget);
 IdeShortcutContext     *ide_shortcut_theme_find_context_by_name  (IdeShortcutTheme        *self,


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