[gnome-builder/wip/commands2] commands: refactor to use GbCommand again.



commit 892a6606c9e0095d855174908b51755797c74cc4
Author: Christian Hergert <christian hergert me>
Date:   Thu Oct 9 20:41:33 2014 -0700

    commands: refactor to use GbCommand again.
    
    We wrap GAction in the command. Vim gets a native command.

 src/commands/gb-command-gaction-provider.c |   53 +++++-
 src/commands/gb-command-manager.c          |   24 +--
 src/commands/gb-command-manager.h          |   12 +-
 src/commands/gb-command-provider.c         |   28 +--
 src/commands/gb-command-provider.h         |   29 ++--
 src/commands/gb-command-result.c           |  267 ++++++++++++++++++++++++++++
 src/commands/gb-command-result.h           |   68 +++++++
 src/commands/gb-command-vim-provider.c     |   16 +-
 src/commands/gb-command-vim.c              |  196 ++++++++++++++++++---
 src/commands/gb-command-vim.h              |   31 +++-
 src/commands/gb-command.c                  |   71 ++++++++
 src/commands/gb-command.h                  |   61 +++++++
 src/gnome-builder.mk                       |    4 +
 13 files changed, 756 insertions(+), 104 deletions(-)
---
diff --git a/src/commands/gb-command-gaction-provider.c b/src/commands/gb-command-gaction-provider.c
index dd8c86f..29510fd 100644
--- a/src/commands/gb-command-gaction-provider.c
+++ b/src/commands/gb-command-gaction-provider.c
@@ -32,13 +32,34 @@ gb_command_gaction_provider_new (GbWorkbench *workbench)
                        "workbench", workbench,
                        NULL);
 }
-static GAction *
-gb_command_gaction_provider_lookup (GbCommandProvider  *provider,
-                                    const gchar        *command_text,
-                                    GVariant          **parameters)
+
+static GbCommandResult *
+execute_action (GbCommand *command,
+                gpointer   user_data)
+{
+  GAction *action;
+  GVariant *params;
+
+  g_return_if_fail (GB_IS_COMMAND (command));
+
+  action = g_object_get_data (G_OBJECT (command), "action");
+  g_return_if_fail (G_IS_ACTION (action));
+
+  params = g_object_get_data (G_OBJECT (command), "parameters");
+
+  g_action_activate (action, params);
+
+  return NULL;
+}
+
+static GbCommand *
+gb_command_gaction_provider_lookup (GbCommandProvider *provider,
+                                    const gchar       *command_text)
 {
   GbCommandGactionProvider *self = (GbCommandGactionProvider *)provider;
   GtkWidget *widget;
+  GbCommand *command = NULL;
+  GVariant *parameters = NULL;
   GAction *action = NULL;
   gchar **parts;
   gchar *tmp;
@@ -67,8 +88,8 @@ gb_command_gaction_provider_lookup (GbCommandProvider  *provider,
 
   if (*command_text)
     {
-      *parameters = g_variant_parse (NULL, command_text, NULL, NULL, NULL);
-      if (!*parameters)
+      parameters = g_variant_parse (NULL, command_text, NULL, NULL, NULL);
+      if (!parameters)
         goto cleanup;
     }
 
@@ -105,16 +126,28 @@ gb_command_gaction_provider_lookup (GbCommandProvider  *provider,
       action = g_action_map_lookup_action (G_ACTION_MAP (app), name);
     }
 
-  if (!action && *parameters)
+  if (!action && parameters)
+    {
+      g_variant_unref (parameters);
+      parameters = NULL;
+    }
+
+  if (action)
     {
-      g_variant_unref (*parameters);
-      *parameters = NULL;
+      command = gb_command_new ();
+      if (parameters)
+        g_object_set_data_full (G_OBJECT (command), "parameters",
+                                parameters, (GDestroyNotify)g_variant_unref);
+      g_object_set_data_full (G_OBJECT (command), "action",
+                              g_object_ref (action), g_object_unref);
+      g_signal_connect (command, "execute", G_CALLBACK (execute_action), NULL);
     }
 
+
 cleanup:
   g_free (name);
 
-  return action ? g_object_ref (action) : NULL;
+  return command;
 }
 
 static void
diff --git a/src/commands/gb-command-manager.c b/src/commands/gb-command-manager.c
index 5844263..df083c7 100644
--- a/src/commands/gb-command-manager.c
+++ b/src/commands/gb-command-manager.c
@@ -83,32 +83,28 @@ gb_command_manager_add_provider (GbCommandManager  *manager,
   g_ptr_array_sort (manager->priv->providers, provider_compare_func);
 }
 
-GAction *
-gb_command_manager_lookup (GbCommandManager  *manager,
-                           const gchar       *command_text,
-                           GVariant         **parameters)
+GbCommand *
+gb_command_manager_lookup (GbCommandManager *manager,
+                           const gchar      *command_text)
 {
-  GVariant *dummy = NULL;
-  GAction *ret = NULL;
+  GbCommand *ret = NULL;
   guint i;
 
   g_return_val_if_fail (GB_IS_COMMAND_MANAGER (manager), NULL);
   g_return_val_if_fail (command_text, NULL);
 
-  if (!parameters)
-    parameters = &dummy;
-
-  for (i = 0; !ret && (i < manager->priv->providers->len); i++)
+  for (i = 0; i < manager->priv->providers->len; i++)
     {
       GbCommandProvider *provider;
 
       provider = g_ptr_array_index (manager->priv->providers, i);
-      ret = gb_command_provider_lookup (provider, command_text, parameters);
-    }
+      ret = gb_command_provider_lookup (provider, command_text);
 
-  g_clear_pointer (&dummy, g_variant_unref);
+      if (ret)
+        return ret;
+    }
 
-  return ret;
+  return NULL;
 }
 
 static void
diff --git a/src/commands/gb-command-manager.h b/src/commands/gb-command-manager.h
index 6add7cd..cacc65e 100644
--- a/src/commands/gb-command-manager.h
+++ b/src/commands/gb-command-manager.h
@@ -21,6 +21,7 @@
 
 #include <gio/gio.h>
 
+#include "gb-command.h"
 #include "gb-command-provider.h"
 
 G_BEGIN_DECLS
@@ -50,12 +51,11 @@ struct _GbCommandManagerClass
   GObjectClass parent;
 };
 
-GType     gb_command_manager_get_type     (void) G_GNUC_CONST;
-GAction  *gb_command_manager_lookup       (GbCommandManager   *manager,
-                                           const gchar        *command_text,
-                                           GVariant          **parameters);
-void      gb_command_manager_add_provider (GbCommandManager   *manager,
-                                           GbCommandProvider  *provider);
+GType      gb_command_manager_get_type     (void) G_GNUC_CONST;
+GbCommand *gb_command_manager_lookup       (GbCommandManager  *manager,
+                                            const gchar       *command_text);
+void       gb_command_manager_add_provider (GbCommandManager  *manager,
+                                            GbCommandProvider *provider);
 
 G_END_DECLS
 
diff --git a/src/commands/gb-command-provider.c b/src/commands/gb-command-provider.c
index 575d85f..81e68d2 100644
--- a/src/commands/gb-command-provider.c
+++ b/src/commands/gb-command-provider.c
@@ -212,29 +212,20 @@ gb_command_provider_set_priority (GbCommandProvider *provider,
  * gb_command_provider_lookup:
  * @provider: (in): The #GbCommandProvider
  * @command_text: (in): Command text to be parsed
- * @parameter: (allow-none) (out): location for a resulting #GVariant parameter
  *
- * This function causes the provider to attept to parse @command_text and
- * generate a GAction to execute the command. If the @command_text could not
- * be parsed, then %NULL is returned.
  *
- * Returns: (transfer full): A #GAction that should be freed with
- *   g_object_unref().
+ * Returns: (transfer full): A #GbCommand if successful; otherwise %NULL.
  */
-GAction *
-gb_command_provider_lookup (GbCommandProvider  *provider,
-                            const gchar        *command_text,
-                            GVariant          **parameter)
+GbCommand *
+gb_command_provider_lookup (GbCommandProvider *provider,
+                            const gchar       *command_text)
 {
-  GAction *ret = NULL;
+  GbCommand *ret = NULL;
 
   g_return_val_if_fail (GB_IS_COMMAND_PROVIDER (provider), NULL);
   g_return_val_if_fail (command_text, NULL);
 
-  if (parameter)
-    *parameter = NULL;
-
-  g_signal_emit (provider, gSignals [LOOKUP], 0, command_text, provider, &ret);
+  g_signal_emit (provider, gSignals [LOOKUP], 0, command_text, &ret);
 
   return ret;
 }
@@ -368,10 +359,9 @@ gb_command_provider_class_init (GbCommandProviderClass *klass)
                   g_signal_accumulator_first_wins,
                   NULL,
                   NULL,
-                  G_TYPE_ACTION,
-                  2,
-                  G_TYPE_STRING,
-                  G_TYPE_POINTER);
+                  GB_TYPE_COMMAND,
+                  1,
+                  G_TYPE_STRING);
 }
 
 static void
diff --git a/src/commands/gb-command-provider.h b/src/commands/gb-command-provider.h
index 2398515..e801b90 100644
--- a/src/commands/gb-command-provider.h
+++ b/src/commands/gb-command-provider.h
@@ -21,6 +21,7 @@
 
 #include <gio/gio.h>
 
+#include "gb-command.h"
 #include "gb-tab.h"
 #include "gb-workbench.h"
 
@@ -50,27 +51,19 @@ struct _GbCommandProviderClass
 {
   GObjectClass parent;
 
-  GAction *(*lookup) (GbCommandProvider  *provider,
-                      const gchar        *command_text,
-                      GVariant          **parameters);
-
-  gpointer _padding1;
-  gpointer _padding2;
-  gpointer _padding3;
-  gpointer _padding4;
-  gpointer _padding5;
+  GbCommand *(*lookup) (GbCommandProvider *provider,
+                        const gchar       *command_text);
 };
 
 GType              gb_command_provider_get_type       (void) G_GNUC_CONST;
-GbCommandProvider *gb_command_provider_new            (GbWorkbench        *workbench);
-GbWorkbench       *gb_command_provider_get_workbench  (GbCommandProvider  *provider);
-GbTab             *gb_command_provider_get_active_tab (GbCommandProvider  *provider);
-gint               gb_command_provider_get_priority   (GbCommandProvider  *provider);
-void               gb_command_provider_set_priority   (GbCommandProvider  *provider,
-                                                       gint                priority);
-GAction           *gb_command_provider_lookup         (GbCommandProvider  *provider,
-                                                       const gchar        *command_text,
-                                                       GVariant          **parameters);
+GbCommandProvider *gb_command_provider_new            (GbWorkbench       *workbench);
+GbWorkbench       *gb_command_provider_get_workbench  (GbCommandProvider *provider);
+GbTab             *gb_command_provider_get_active_tab (GbCommandProvider *provider);
+gint               gb_command_provider_get_priority   (GbCommandProvider *provider);
+void               gb_command_provider_set_priority   (GbCommandProvider *provider,
+                                                       gint               priority);
+GbCommand         *gb_command_provider_lookup         (GbCommandProvider *provider,
+                                                       const gchar       *command_text);
 
 G_END_DECLS
 
diff --git a/src/commands/gb-command-result.c b/src/commands/gb-command-result.c
new file mode 100644
index 0000000..d0863ef
--- /dev/null
+++ b/src/commands/gb-command-result.c
@@ -0,0 +1,267 @@
+/* gb-command-result.c
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * 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 3 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 <glib/gi18n.h>
+
+#include "gb-command-result.h"
+
+struct _GbCommandResultPrivate
+{
+  gchar *command_text;
+  gchar *result_text;
+  guint is_error : 1;
+  guint is_running : 1;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GbCommandResult, gb_command_result, G_TYPE_OBJECT)
+
+enum {
+  PROP_0,
+  PROP_COMMAND_TEXT,
+  PROP_IS_ERROR,
+  PROP_IS_RUNNING,
+  PROP_RESULT_TEXT,
+  LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+GbCommandResult *
+gb_command_result_new (void)
+{
+  return g_object_new (GB_TYPE_COMMAND_RESULT, NULL);
+}
+
+const gchar *
+gb_command_result_get_command_text (GbCommandResult *result)
+{
+  g_return_val_if_fail (GB_IS_COMMAND_RESULT (result), NULL);
+
+  return result->priv->command_text;
+}
+
+void
+gb_command_result_set_command_text (GbCommandResult *result,
+                                    const gchar     *command_text)
+{
+  g_return_if_fail (GB_IS_COMMAND_RESULT (result));
+
+  if (result->priv->command_text != command_text)
+    {
+      g_free (result->priv->command_text);
+      result->priv->command_text = g_strdup (command_text);
+      g_object_notify_by_pspec (G_OBJECT (result),
+                                gParamSpecs [PROP_COMMAND_TEXT]);
+    }
+}
+
+const gchar *
+gb_command_result_get_result_text (GbCommandResult *result)
+{
+  g_return_val_if_fail (GB_IS_COMMAND_RESULT (result), NULL);
+
+  return result->priv->result_text;
+}
+
+void
+gb_command_result_set_result_text (GbCommandResult *result,
+                                   const gchar     *result_text)
+{
+  g_return_if_fail (GB_IS_COMMAND_RESULT (result));
+
+  if (result->priv->result_text != result_text)
+    {
+      g_free (result->priv->result_text);
+      result->priv->result_text = g_strdup (result_text);
+      g_object_notify_by_pspec (G_OBJECT (result),
+                                gParamSpecs [PROP_RESULT_TEXT]);
+    }
+}
+
+gboolean
+gb_command_result_get_is_running (GbCommandResult *result)
+{
+  g_return_val_if_fail (GB_IS_COMMAND_RESULT (result), FALSE);
+
+  return result->priv->is_running;
+}
+
+void
+gb_command_result_set_is_running (GbCommandResult *result,
+                                  gboolean         is_running)
+{
+  g_return_if_fail (GB_IS_COMMAND_RESULT (result));
+
+  if (result->priv->is_running != is_running)
+    {
+      result->priv->is_running = is_running;
+      g_object_notify_by_pspec (G_OBJECT (result),
+                                gParamSpecs [PROP_IS_RUNNING]);
+    }
+}
+
+gboolean
+gb_command_result_get_is_error (GbCommandResult *result)
+{
+  g_return_val_if_fail (GB_IS_COMMAND_RESULT (result), FALSE);
+
+  return result->priv->is_error;
+}
+
+void
+gb_command_result_set_is_error (GbCommandResult *result,
+                                gboolean         is_error)
+{
+  g_return_if_fail (GB_IS_COMMAND_RESULT (result));
+
+  if (result->priv->is_error != is_error)
+    {
+      result->priv->is_error = is_error;
+      g_object_notify_by_pspec (G_OBJECT (result),
+                                gParamSpecs [PROP_IS_ERROR]);
+    }
+}
+
+static void
+gb_command_result_finalize (GObject *object)
+{
+  GbCommandResultPrivate *priv = GB_COMMAND_RESULT (object)->priv;
+
+  g_clear_pointer (&priv->command_text, g_free);
+  g_clear_pointer (&priv->result_text, g_free);
+
+  G_OBJECT_CLASS (gb_command_result_parent_class)->finalize (object);
+}
+
+static void
+gb_command_result_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  GbCommandResult *self = GB_COMMAND_RESULT (object);
+
+  switch (prop_id)
+    {
+    case PROP_COMMAND_TEXT:
+      g_value_set_string (value, gb_command_result_get_command_text (self));
+      break;
+
+    case PROP_IS_ERROR:
+      g_value_set_boolean (value, gb_command_result_get_is_error (self));
+      break;
+
+    case PROP_IS_RUNNING:
+      g_value_set_boolean (value, gb_command_result_get_is_running (self));
+      break;
+
+    case PROP_RESULT_TEXT:
+      g_value_set_string (value, gb_command_result_get_result_text (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gb_command_result_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  GbCommandResult *self = GB_COMMAND_RESULT (object);
+
+  switch (prop_id)
+    {
+    case PROP_COMMAND_TEXT:
+      gb_command_result_set_command_text (self, g_value_get_string (value));
+      break;
+
+    case PROP_IS_ERROR:
+      gb_command_result_set_is_error (self, g_value_get_boolean (value));
+      break;
+
+    case PROP_IS_RUNNING:
+      gb_command_result_set_is_running (self, g_value_get_boolean (value));
+      break;
+
+    case PROP_RESULT_TEXT:
+      gb_command_result_set_result_text (self, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gb_command_result_class_init (GbCommandResultClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gb_command_result_finalize;
+  object_class->get_property = gb_command_result_get_property;
+  object_class->set_property = gb_command_result_set_property;
+
+  gParamSpecs [PROP_COMMAND_TEXT] =
+    g_param_spec_string ("command-text",
+                         _("Command Text"),
+                         _("The command text if any."),
+                         NULL,
+                         (G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_COMMAND_TEXT,
+                                   gParamSpecs [PROP_COMMAND_TEXT]);
+
+  gParamSpecs [PROP_IS_ERROR] =
+    g_param_spec_boolean ("is-error",
+                          _("Is Error"),
+                          _("If the result is an error."),
+                          FALSE,
+                          (G_PARAM_READWRITE |
+                           G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_IS_ERROR,
+                                   gParamSpecs [PROP_IS_ERROR]);
+
+  gParamSpecs [PROP_IS_RUNNING] =
+    g_param_spec_boolean ("is-running",
+                          _("Is Running"),
+                          _("If the command is still running."),
+                          FALSE,
+                          (G_PARAM_READWRITE |
+                           G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_IS_RUNNING,
+                                   gParamSpecs [PROP_IS_RUNNING]);
+
+  gParamSpecs [PROP_RESULT_TEXT] =
+    g_param_spec_string ("result-text",
+                         _("Result Text"),
+                         _("The result text if any."),
+                         NULL,
+                         (G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_RESULT_TEXT,
+                                   gParamSpecs [PROP_RESULT_TEXT]);
+}
+
+static void
+gb_command_result_init (GbCommandResult *self)
+{
+  self->priv = gb_command_result_get_instance_private (self);
+}
diff --git a/src/commands/gb-command-result.h b/src/commands/gb-command-result.h
new file mode 100644
index 0000000..5efa9ed
--- /dev/null
+++ b/src/commands/gb-command-result.h
@@ -0,0 +1,68 @@
+/* gb-command-result.h
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * 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 3 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 GB_COMMAND_RESULT_H
+#define GB_COMMAND_RESULT_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GB_TYPE_COMMAND_RESULT            (gb_command_result_get_type())
+#define GB_COMMAND_RESULT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GB_TYPE_COMMAND_RESULT, 
GbCommandResult))
+#define GB_COMMAND_RESULT_CONST(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), GB_TYPE_COMMAND_RESULT, 
GbCommandResult const))
+#define GB_COMMAND_RESULT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GB_TYPE_COMMAND_RESULT, 
GbCommandResultClass))
+#define GB_IS_COMMAND_RESULT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GB_TYPE_COMMAND_RESULT))
+#define GB_IS_COMMAND_RESULT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GB_TYPE_COMMAND_RESULT))
+#define GB_COMMAND_RESULT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  GB_TYPE_COMMAND_RESULT, 
GbCommandResultClass))
+
+typedef struct _GbCommandResult        GbCommandResult;
+typedef struct _GbCommandResultClass   GbCommandResultClass;
+typedef struct _GbCommandResultPrivate GbCommandResultPrivate;
+
+struct _GbCommandResult
+{
+  GObject parent;
+
+  /*< private >*/
+  GbCommandResultPrivate *priv;
+};
+
+struct _GbCommandResultClass
+{
+  GObjectClass parent;
+};
+
+GType            gb_command_result_get_type         (void) G_GNUC_CONST;
+GbCommandResult *gb_command_result_new              (void);
+gboolean         gb_command_result_get_is_running   (GbCommandResult *result);
+void             gb_command_result_set_is_running   (GbCommandResult *result,
+                                                     gboolean         is_running);
+gboolean         gb_command_result_get_is_error     (GbCommandResult *result);
+void             gb_command_result_set_is_error     (GbCommandResult *result,
+                                                     gboolean         is_error);
+const gchar     *gb_command_result_get_command_text (GbCommandResult *result);
+void             gb_command_result_set_command_text (GbCommandResult *result,
+                                                     const gchar     *command_text);
+const gchar     *gb_command_result_get_result_text  (GbCommandResult *result);
+void             gb_command_result_set_result_text  (GbCommandResult *result,
+                                                     const gchar     *result_text);
+
+G_END_DECLS
+
+#endif /* GB_COMMAND_RESULT_H */
diff --git a/src/commands/gb-command-vim-provider.c b/src/commands/gb-command-vim-provider.c
index 8c73739..67e2b2d 100644
--- a/src/commands/gb-command-vim-provider.c
+++ b/src/commands/gb-command-vim-provider.c
@@ -34,10 +34,9 @@ gb_command_vim_provider_new (GbWorkbench *workbench)
                        NULL);
 }
 
-static GAction *
-gb_command_vim_provider_lookup (GbCommandProvider  *provider,
-                                const gchar        *command_text,
-                                GVariant          **parameters)
+static GbCommand *
+gb_command_vim_provider_lookup (GbCommandProvider *provider,
+                                const gchar       *command_text)
 {
   GbWorkbench *workbench;
   GSettings *settings;
@@ -45,7 +44,6 @@ gb_command_vim_provider_lookup (GbCommandProvider  *provider,
 
   g_return_val_if_fail (GB_IS_COMMAND_VIM_PROVIDER (provider), NULL);
   g_return_val_if_fail (command_text, NULL);
-  g_return_val_if_fail (parameters, NULL);
 
   /* Fetch our editor gsettings */
   settings = g_object_get_data (G_OBJECT (provider), "editor-settings");
@@ -68,10 +66,10 @@ gb_command_vim_provider_lookup (GbCommandProvider  *provider,
 
   /* See if GbEditorVim recognizes this command */
   if (gb_editor_vim_is_command (command_text))
-    {
-      *parameters = g_variant_new_string (command_text);
-      return gb_command_vim_new (GB_EDITOR_TAB (active_tab));
-    }
+    return g_object_new (GB_TYPE_COMMAND_VIM,
+                         "command-text", command_text,
+                         "tab", active_tab,
+                         NULL);
 
   return NULL;
 }
diff --git a/src/commands/gb-command-vim.c b/src/commands/gb-command-vim.c
index ec559b8..e9b890c 100644
--- a/src/commands/gb-command-vim.c
+++ b/src/commands/gb-command-vim.c
@@ -16,48 +16,196 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <glib/gi18n.h>
+
 #include "gb-command-vim.h"
+#include "gb-editor-tab.h"
 #include "gb-editor-tab-private.h"
 
-static void
-gb_command_vim_activate (GSimpleAction *action,
-                         GVariant      *parameter,
-                         gpointer       user_data)
+struct _GbCommandVimPrivate
 {
   GbEditorTab *tab;
+  gchar       *command_text;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GbCommandVim, gb_command_vim, GB_TYPE_COMMAND)
+
+enum {
+  PROP_0,
+  PROP_COMMAND_TEXT,
+  PROP_TAB,
+  LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+GbEditorTab *
+gb_command_vim_get_tab (GbCommandVim *vim)
+{
+  g_return_val_if_fail (GB_IS_COMMAND_VIM (vim), NULL);
+
+  return vim->priv->tab;
+}
+
+static void
+gb_command_vim_set_tab (GbCommandVim *vim,
+                        GbEditorTab  *tab)
+{
+  g_return_if_fail (GB_IS_COMMAND_VIM (vim));
+  g_return_if_fail (!tab || GB_IS_EDITOR_TAB (tab));
+
+  if (tab != vim->priv->tab)
+    {
+      if (vim->priv->tab)
+        {
+          g_object_remove_weak_pointer (G_OBJECT (vim->priv->tab),
+                                        (gpointer *)&vim->priv->tab);
+          vim->priv->tab = NULL;
+        }
+
+      if (tab)
+        {
+          vim->priv->tab = tab;
+          g_object_add_weak_pointer (G_OBJECT (vim->priv->tab),
+                                     (gpointer *)&vim->priv->tab);
+        }
+
+      g_object_notify_by_pspec (G_OBJECT (vim), gParamSpecs [PROP_TAB]);
+    }
+}
+
+const gchar *
+gb_command_vim_get_command_text (GbCommandVim *vim)
+{
+  g_return_val_if_fail (GB_IS_COMMAND_VIM (vim), NULL);
+
+  return vim->priv->command_text;
+}
+
+void
+gb_command_vim_set_command_text (GbCommandVim *vim,
+                                 const gchar  *command_text)
+{
+  g_return_if_fail (GB_IS_COMMAND_VIM (vim));
+  g_return_if_fail (command_text);
+
+  if (command_text != vim->priv->command_text)
+    {
+      g_free (vim->priv->command_text);
+      vim->priv->command_text = g_strdup (command_text);
+      g_object_notify_by_pspec (G_OBJECT (vim),
+                                gParamSpecs [PROP_COMMAND_TEXT]);
+    }
+}
 
-  g_return_if_fail (G_IS_SIMPLE_ACTION (action));
-  g_return_if_fail (parameter);
+static GbCommandResult *
+gb_command_vim_execute (GbCommand *command)
+{
+  GbCommandVim *vim = (GbCommandVim *)command;
+
+  g_return_val_if_fail (GB_IS_COMMAND_VIM (vim), NULL);
+
+  if (vim->priv->tab && vim->priv->command_text)
+    {
+      gb_editor_vim_execute_command (vim->priv->tab->priv->vim,
+                                     vim->priv->command_text);
+    }
+
+  return NULL;
+}
 
-  tab = g_object_get_data (G_OBJECT (action), "GB_EDITOR_TAB");
+static void
+gb_command_vim_finalize (GObject *object)
+{
+  GbCommandVimPrivate *priv = GB_COMMAND_VIM (object)->priv;
+
+  gb_command_vim_set_tab (GB_COMMAND_VIM (object), NULL);
+  g_clear_pointer (&priv->command_text, g_free);
+
+  G_OBJECT_CLASS (gb_command_vim_parent_class)->finalize (object);
+}
+
+static void
+gb_command_vim_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  GbCommandVim *self = GB_COMMAND_VIM (object);
 
-  if (!GB_IS_EDITOR_TAB (tab))
+  switch (prop_id)
     {
-      g_warning ("Failed to retrieve editor tab!");
-      return;
+    case PROP_COMMAND_TEXT:
+      g_value_set_string (value, gb_command_vim_get_command_text (self));
+      break;
+
+    case PROP_TAB:
+      g_value_set_object (value, gb_command_vim_get_tab (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
+}
+
+static void
+gb_command_vim_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  GbCommandVim *self = GB_COMMAND_VIM (object);
 
-  if (g_variant_is_of_type (parameter, G_VARIANT_TYPE_STRING))
+  switch (prop_id)
     {
-      const gchar *command_text;
+    case PROP_COMMAND_TEXT:
+      gb_command_vim_set_command_text (self, g_value_get_string (value));
+      break;
 
-      command_text = g_variant_get_string (parameter, NULL);
-      gb_editor_vim_execute_command (tab->priv->vim, command_text);
+    case PROP_TAB:
+      gb_command_vim_set_tab (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
 }
 
-GAction *
-gb_command_vim_new (GbEditorTab *tab)
+static void
+gb_command_vim_class_init (GbCommandVimClass *klass)
 {
-  GSimpleAction *action;
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GbCommandClass *command_class = GB_COMMAND_CLASS (klass);
 
-  g_return_val_if_fail (GB_IS_EDITOR_TAB (tab), NULL);
+  object_class->finalize = gb_command_vim_finalize;
+  object_class->get_property = gb_command_vim_get_property;
+  object_class->set_property = gb_command_vim_set_property;
 
-  action = g_simple_action_new ("vim-command", G_VARIANT_TYPE_STRING);
-  g_object_set_data_full (G_OBJECT (action), "GB_EDITOR_TAB",
-                          g_object_ref (tab), g_object_unref);
-  g_signal_connect (action, "activate", G_CALLBACK (gb_command_vim_activate),
-                    NULL);
+  command_class->execute = gb_command_vim_execute;
 
-  return G_ACTION (action);
+  gParamSpecs [PROP_COMMAND_TEXT] =
+    g_param_spec_string ("command-text",
+                         _("Command Text"),
+                         _("The command text to execute"),
+                         NULL,
+                         (G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_COMMAND_TEXT,
+                                   gParamSpecs [PROP_COMMAND_TEXT]);
+
+  gParamSpecs [PROP_TAB] =
+    g_param_spec_object ("tab",
+                         _("Tab"),
+                         _("The editor tab to modify."),
+                         GB_TYPE_EDITOR_TAB,
+                         (G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_TAB,
+                                   gParamSpecs [PROP_TAB]);
+}
+
+static void
+gb_command_vim_init (GbCommandVim *self)
+{
+  self->priv = gb_command_vim_get_instance_private (self);
 }
diff --git a/src/commands/gb-command-vim.h b/src/commands/gb-command-vim.h
index c2c7ac6..fef73bb 100644
--- a/src/commands/gb-command-vim.h
+++ b/src/commands/gb-command-vim.h
@@ -19,13 +19,36 @@
 #ifndef GB_COMMAND_VIM_H
 #define GB_COMMAND_VIM_H
 
-#include <gio/gio.h>
-
-#include "gb-editor-tab.h"
+#include "gb-command.h"
 
 G_BEGIN_DECLS
 
-GAction *gb_command_vim_new (GbEditorTab *tab);
+#define GB_TYPE_COMMAND_VIM            (gb_command_vim_get_type())
+#define GB_COMMAND_VIM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GB_TYPE_COMMAND_VIM, 
GbCommandVim))
+#define GB_COMMAND_VIM_CONST(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), GB_TYPE_COMMAND_VIM, GbCommandVim 
const))
+#define GB_COMMAND_VIM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GB_TYPE_COMMAND_VIM, 
GbCommandVimClass))
+#define GB_IS_COMMAND_VIM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GB_TYPE_COMMAND_VIM))
+#define GB_IS_COMMAND_VIM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GB_TYPE_COMMAND_VIM))
+#define GB_COMMAND_VIM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  GB_TYPE_COMMAND_VIM, 
GbCommandVimClass))
+
+typedef struct _GbCommandVim        GbCommandVim;
+typedef struct _GbCommandVimClass   GbCommandVimClass;
+typedef struct _GbCommandVimPrivate GbCommandVimPrivate;
+
+struct _GbCommandVim
+{
+  GbCommand parent;
+
+  /*< private >*/
+  GbCommandVimPrivate *priv;
+};
+
+struct _GbCommandVimClass
+{
+  GbCommandClass parent;
+};
+
+GType gb_command_vim_get_type (void) G_GNUC_CONST;
 
 G_END_DECLS
 
diff --git a/src/commands/gb-command.c b/src/commands/gb-command.c
new file mode 100644
index 0000000..aaa8b45
--- /dev/null
+++ b/src/commands/gb-command.c
@@ -0,0 +1,71 @@
+/* gb-command.c
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * 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 3 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 "gb-command.h"
+
+G_DEFINE_TYPE (GbCommand, gb_command, G_TYPE_OBJECT)
+
+enum {
+  EXECUTE,
+  LAST_SIGNAL
+};
+
+static guint gSignals [LAST_SIGNAL];
+
+GbCommand *
+gb_command_new (void)
+{
+  return g_object_new (GB_TYPE_COMMAND, NULL);
+}
+
+static GbCommandResult *
+gb_command_real_execute (GbCommand *command)
+{
+  return NULL;
+}
+
+GbCommandResult *
+gb_command_execute (GbCommand *command)
+{
+  GbCommandResult *ret = NULL;
+  g_return_val_if_fail (GB_IS_COMMAND (command), NULL);
+  g_signal_emit (command, gSignals [EXECUTE], 0, &ret);
+  return ret;
+}
+
+static void
+gb_command_class_init (GbCommandClass *klass)
+{
+  klass->execute = gb_command_real_execute;
+
+  gSignals [EXECUTE] =
+    g_signal_new ("execute",
+                  GB_TYPE_COMMAND,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GbCommandClass, execute),
+                  g_signal_accumulator_first_wins,
+                  NULL,
+                  NULL,
+                  GB_TYPE_COMMAND_RESULT,
+                  0);
+}
+
+static void
+gb_command_init (GbCommand *self)
+{
+}
diff --git a/src/commands/gb-command.h b/src/commands/gb-command.h
new file mode 100644
index 0000000..d2afdbb
--- /dev/null
+++ b/src/commands/gb-command.h
@@ -0,0 +1,61 @@
+/* gb-command.h
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * 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 3 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 GB_COMMAND_H
+#define GB_COMMAND_H
+
+#include <glib-object.h>
+
+#include "gb-command-result.h"
+
+G_BEGIN_DECLS
+
+#define GB_TYPE_COMMAND            (gb_command_get_type())
+#define GB_COMMAND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GB_TYPE_COMMAND, GbCommand))
+#define GB_COMMAND_CONST(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), GB_TYPE_COMMAND, GbCommand const))
+#define GB_COMMAND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GB_TYPE_COMMAND, GbCommandClass))
+#define GB_IS_COMMAND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GB_TYPE_COMMAND))
+#define GB_IS_COMMAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GB_TYPE_COMMAND))
+#define GB_COMMAND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  GB_TYPE_COMMAND, GbCommandClass))
+
+typedef struct _GbCommand        GbCommand;
+typedef struct _GbCommandClass   GbCommandClass;
+typedef struct _GbCommandPrivate GbCommandPrivate;
+
+struct _GbCommand
+{
+  GObject parent;
+
+  /*< private >*/
+  GbCommandPrivate *priv;
+};
+
+struct _GbCommandClass
+{
+  GObjectClass parent;
+
+  GbCommandResult *(*execute) (GbCommand *command);
+};
+
+GType            gb_command_get_type (void) G_GNUC_CONST;
+GbCommand       *gb_command_new      (void);
+GbCommandResult *gb_command_execute  (GbCommand *command);
+
+G_END_DECLS
+
+#endif /* GB_COMMAND_H */
diff --git a/src/gnome-builder.mk b/src/gnome-builder.mk
index 1cffb66..c28496a 100644
--- a/src/gnome-builder.mk
+++ b/src/gnome-builder.mk
@@ -9,12 +9,16 @@ libgnome_builder_la_SOURCES = \
        src/animation/gb-frame-source.h \
        src/app/gb-application.c \
        src/app/gb-application.h \
+       src/commands/gb-command.c \
+       src/commands/gb-command.h \
        src/commands/gb-command-gaction-provider.c \
        src/commands/gb-command-gaction-provider.h \
        src/commands/gb-command-manager.c \
        src/commands/gb-command-manager.h \
        src/commands/gb-command-provider.c \
        src/commands/gb-command-provider.h \
+       src/commands/gb-command-result.c \
+       src/commands/gb-command-result.h \
        src/commands/gb-command-vim-provider.c \
        src/commands/gb-command-vim-provider.h \
        src/commands/gb-command-vim.c \


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