[glib/wip/gmenu: 6/59] Add GDBusActionGroup



commit eb9577db9312eea7c53bc973fbb9bf342cf622fc
Author: Ryan Lortie <desrt desrt ca>
Date:   Fri Jul 1 02:41:30 2011 +0100

    Add GDBusActionGroup
    
    GDBusActionGroup can be used as a client-side wrapper
    for the an action group that has been exported on D-Bus.

 docs/reference/gio/gio-docs.xml     |    1 +
 docs/reference/gio/gio-sections.txt |   20 ++
 docs/reference/gio/gio.types        |    1 +
 gio/Makefile.am                     |    2 +
 gio/gdbusactiongroup.c              |  574 +++++++++++++++++++++++++++++++++++
 gio/gdbusactiongroup.h              |   74 +++++
 gio/gio.h                           |    1 +
 gio/gio.symbols                     |    6 +
 gio/gioenums.h                      |   20 ++
 gio/giotypes.h                      |    1 +
 10 files changed, 700 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml
index a800fed..06f8717 100644
--- a/docs/reference/gio/gio-docs.xml
+++ b/docs/reference/gio/gio-docs.xml
@@ -199,6 +199,7 @@
         <xi:include href="xml/gaction.xml"/>
         <xi:include href="xml/gsimpleaction.xml"/>
         <xi:include href="xml/gactiongroupexporter.xml"/>
+        <xi:include href="xml/gdbusactiongroup.xml"/>
     </chapter>
     <chapter id="extending">
         <title>Extending GIO</title>
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 5d4a568..afe290d 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -2913,6 +2913,26 @@ g_action_group_exporter_query
 </SECTION>
 
 <SECTION>
+<FILE>gdbusactiongroup</FILE>
+GDBusActionGroup
+g_dbus_action_group_new
+g_dbus_action_group_new_finish
+g_dbus_action_group_new_sync
+g_dbus_action_group_inject
+
+<SUBSECTION Standard>
+G_TYPE_DBUS_ACTION_GROUP
+G_DBUS_ACTION_GROUP
+G_DBUS_ACTION_GROUP_CLASS
+G_IS_DBUS_ACTION_GROUP
+G_IS_DBUS_ACTION_GROUP_CLASS
+G_DBUS_ACTION_GROUP_GET_CLASS
+
+<SUBSECTION Private>
+g_dbus_action_group_get_type
+</SECTION>
+
+<SECTION>
 <FILE>gaction</FILE>
 <TITLE>GAction</TITLE>
 GAction
diff --git a/docs/reference/gio/gio.types b/docs/reference/gio/gio.types
index 7ac9ee6..0100102 100644
--- a/docs/reference/gio/gio.types
+++ b/docs/reference/gio/gio.types
@@ -16,6 +16,7 @@ g_converter_input_stream_get_type
 g_converter_output_stream_get_type
 g_data_input_stream_get_type
 g_data_output_stream_get_type
+g_dbus_action_group_get_type
 g_desktop_app_info_get_type
 g_drive_get_type
 g_emblem_get_type
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 2aa5f0c..a3f5e83 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -129,6 +129,7 @@ application_headers = \
 	gsimpleactiongroup.h		\
 	gaction.h			\
 	gsimpleaction.h			\
+	gdbusactiongroup.h		\
 	gactiongroupexporter.h		\
 	gapplicationcommandline.h	\
 	gapplication.h
@@ -138,6 +139,7 @@ application_sources = \
 	gsimpleactiongroup.c			\
 	gaction.c				\
 	gsimpleaction.c				\
+	gdbusactiongroup.c			\
 	gactiongroupexporter.c			\
 	gapplicationcommandline.c		\
 	gapplicationimpl.h			\
diff --git a/gio/gdbusactiongroup.c b/gio/gdbusactiongroup.c
new file mode 100644
index 0000000..bb05ebe
--- /dev/null
+++ b/gio/gdbusactiongroup.c
@@ -0,0 +1,574 @@
+/*
+ * Copyright  2010 Codethink Limited
+ * Copyright  2011 Canonical Limited
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Ryan Lortie <desrt desrt ca>
+ */
+
+#include "config.h"
+
+#include "gsimpleasyncresult.h"
+#include "gdbusactiongroup.h"
+#include "gdbusconnection.h"
+#include "gasyncinitable.h"
+#include "gactiongroup.h"
+
+
+/**
+ * SECTION:gdbusactiongroup
+ * @title: GDBusActionGroup
+ * @short_description: A D-Bus GActionGroup implementation
+ * @see_also: <link linkend="gio-GActionGroup-exporter">GActionGroup exporter</link>
+ *
+ * #GDBusActionGroup is an implementation of the #GActionGroup
+ * interface that can be used as a proxy for an action group
+ * that is exported over D-Bus with g_action_group_exporter_export().
+ */
+
+struct _GDBusActionGroup
+{
+  GObject parent_instance;
+
+  GDBusConnection *connection;
+  gchar           *bus_name;
+  gchar           *object_path;
+  guint            subscription_id;
+  GHashTable      *actions;
+
+  /* The 'strict' flag indicates that the non-existence of at least one
+   * action has potentially been observed through the API.  This means
+   * that we should always emit 'action-added' signals for all new
+   * actions.
+   *
+   * The user can observe the non-existence of an action by listing the
+   * actions or by performing a query (such as parameter type) on a
+   * non-existent action.
+   *
+   * If the user has no way of knowing that a given action didn't
+   * already exist then we can skip emitting 'action-added' signals
+   * since they have no way of knowing that it wasn't there from the
+   * start.
+   */
+  gboolean         strict;
+};
+
+typedef GObjectClass GDBusActionGroupClass;
+
+typedef struct
+{
+  gchar        *name;
+  GVariantType *parameter_type;
+  gboolean      enabled;
+  GVariant     *state;
+} ActionInfo;
+
+static void
+action_info_free (gpointer user_data)
+{
+  ActionInfo *info = user_data;
+
+  g_free (info->name);
+
+  if (info->state)
+    g_variant_unref (info->state);
+
+  if (info->parameter_type)
+    g_variant_type_free (info->parameter_type);
+
+  g_slice_free (ActionInfo, info);
+}
+
+ActionInfo *
+action_info_new_from_iter (GVariantIter *iter)
+{
+  const gchar *param_str;
+  ActionInfo *info;
+  gboolean enabled;
+  GVariant *state;
+  gchar *name;
+
+  if (!g_variant_iter_next (iter, "{s(bg av)}", &name,
+                            &enabled, &param_str, &state))
+    return NULL;
+
+  info = g_slice_new (ActionInfo);
+  info->name = name;
+  info->enabled = enabled;
+
+  if (g_variant_n_children (state))
+    g_variant_get_child (state, 0, "v", &info->state);
+  else
+    info->state = NULL;
+  g_variant_unref (state);
+
+  if (param_str[0])
+    info->parameter_type = g_variant_type_copy ((GVariantType *) param_str);
+  else
+    info->parameter_type = NULL;
+
+  return info;
+}
+
+static void g_dbus_action_group_iface_init (GActionGroupInterface *);
+G_DEFINE_TYPE_WITH_CODE (GDBusActionGroup, g_dbus_action_group, G_TYPE_OBJECT,
+  G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, g_dbus_action_group_iface_init))
+
+static gchar **
+g_dbus_action_group_list_actions (GActionGroup *g_group)
+{
+  GDBusActionGroup *group = G_DBUS_ACTION_GROUP (g_group);
+  GHashTableIter iter;
+  gint n, i = 0;
+  gchar **keys;
+  gpointer key;
+
+  n = g_hash_table_size (group->actions);
+  keys = g_new (gchar *, n + 1);
+
+  g_hash_table_iter_init (&iter, group->actions);
+  while (g_hash_table_iter_next (&iter, &key, NULL))
+    keys[i++] = g_strdup (key);
+  g_assert_cmpint (i, ==, n);
+  keys[n] = NULL;
+
+  group->strict = TRUE;
+
+  return keys;
+}
+
+static gboolean
+g_dbus_action_group_query_action (GActionGroup        *g_group,
+                                  const gchar         *action_name,
+                                  gboolean            *enabled,
+                                  const GVariantType **parameter_type,
+                                  const GVariantType **state_type,
+                                  GVariant           **state_hint,
+                                  GVariant           **state)
+{
+  GDBusActionGroup *group = G_DBUS_ACTION_GROUP (g_group);
+  ActionInfo *info;
+
+  info = g_hash_table_lookup (group->actions, action_name);
+
+  if (info == NULL)
+    {
+      group->strict = TRUE;
+      return FALSE;
+    }
+
+  if (enabled)
+    *enabled = info->enabled;
+
+  if (parameter_type)
+    *parameter_type = info->parameter_type;
+
+  if (state_type)
+    *state_type = info->state ? g_variant_get_type (info->state) : NULL;
+
+  if (state_hint)
+    *state_hint = NULL;
+
+  if (state)
+    *state = g_variant_ref (info->state);
+
+  return TRUE;
+}
+
+static void
+g_dbus_action_group_change_state (GActionGroup *g_group,
+                                  const gchar  *action_name,
+                                  GVariant     *value)
+{
+  GDBusActionGroup *group = G_DBUS_ACTION_GROUP (g_group);
+
+  /* Don't bother with the checks.  The other side will do it again. */
+  g_dbus_connection_call (group->connection, group->bus_name, group->object_path, "org.gtk.Actions", "SetState",
+                          g_variant_new ("(sva{sv})", action_name, value, NULL),
+                          NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+}
+
+static void
+g_dbus_action_group_activate (GActionGroup *g_group,
+                              const gchar  *action_name,
+                              GVariant     *parameter)
+{
+  GDBusActionGroup *group = G_DBUS_ACTION_GROUP (g_group);
+  GVariantBuilder builder;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
+
+  if (parameter)
+    g_variant_builder_add (&builder, "v", parameter);
+
+  g_dbus_connection_call (group->connection, group->bus_name, group->object_path, "org.gtk.Actions", "Activate",
+                          g_variant_new ("(sava{sv})", action_name, &builder, NULL),
+                          NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+}
+
+static void
+g_dbus_action_group_finalize (GObject *object)
+{
+  GDBusActionGroup *group = G_DBUS_ACTION_GROUP (object);
+
+  g_dbus_connection_signal_unsubscribe (group->connection, group->subscription_id);
+  g_hash_table_unref (group->actions);
+  g_object_unref (group->connection);
+  g_free (group->object_path);
+  g_free (group->bus_name);
+
+  G_OBJECT_CLASS (g_dbus_action_group_parent_class)
+    ->finalize (object);
+}
+
+static void
+g_dbus_action_group_init (GDBusActionGroup *group)
+{
+  group->actions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, action_info_free);
+}
+
+static void
+g_dbus_action_group_class_init (GDBusActionGroupClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->finalize = g_dbus_action_group_finalize;
+}
+
+static void
+g_dbus_action_group_iface_init (GActionGroupInterface *iface)
+{
+  iface->list_actions = g_dbus_action_group_list_actions;
+  iface->query_action = g_dbus_action_group_query_action;
+  iface->change_action_state = g_dbus_action_group_change_state;
+  iface->activate_action = g_dbus_action_group_activate;
+}
+
+static void
+g_dbus_action_group_changed (GDBusConnection *connection,
+                             const gchar     *sender,
+                             const gchar     *object_path,
+                             const gchar     *interface_name,
+                             const gchar     *signal_name,
+                             GVariant        *parameters,
+                             gpointer         user_data)
+{
+  GDBusActionGroup *group = user_data;
+  GActionGroup *g_group = user_data;
+
+  if (g_str_equal (signal_name, "Changed") &&
+      g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(asa{sb}a{sv}a{s(bgav)})")))
+    {
+      /* Removes */
+      {
+        GVariantIter *iter;
+        const gchar *name;
+
+        g_variant_get_child (parameters, 0, "as", &iter);
+        while (g_variant_iter_next (iter, "&s", &name))
+          {
+            if (g_hash_table_lookup (group->actions, name))
+              {
+                g_hash_table_remove (group->actions, name);
+                g_action_group_action_removed (g_group, name);
+              }
+          }
+        g_variant_iter_free (iter);
+      }
+
+      /* Enable changes */
+      {
+        GVariantIter *iter;
+        const gchar *name;
+        gboolean enabled;
+
+        g_variant_get_child (parameters, 1, "a{sb}", &iter);
+        while (g_variant_iter_next (iter, "{&sb}", &name, &enabled))
+          {
+            ActionInfo *info;
+
+            info = g_hash_table_lookup (group->actions, name);
+
+            if (info && info->enabled != enabled)
+              {
+                info->enabled = enabled;
+                g_action_group_action_enabled_changed (g_group, name, enabled);
+              }
+          }
+        g_variant_iter_free (iter);
+      }
+
+      /* State changes */
+      {
+        GVariantIter *iter;
+        const gchar *name;
+        GVariant *state;
+
+        g_variant_get_child (parameters, 2, "a{sv}", &iter);
+        while (g_variant_iter_next (iter, "{&sv}", &name, &state))
+          {
+            ActionInfo *info;
+
+            info = g_hash_table_lookup (group->actions, name);
+
+            if (info && info->state && !g_variant_equal (state, info->state) &&
+                g_variant_is_of_type (state, g_variant_get_type (info->state)))
+              {
+                g_variant_unref (info->state);
+                info->state = g_variant_ref (state);
+
+                g_action_group_action_state_changed (g_group, name, state);
+              }
+
+            g_variant_unref (state);
+          }
+        g_variant_iter_free (iter);
+      }
+
+      /* Additions */
+      {
+        GVariantIter *iter;
+        ActionInfo *info;
+
+        g_variant_get_child (parameters, 3, "a{s(bgav)}", &iter);
+        while ((info = action_info_new_from_iter (iter)))
+          {
+            if (!g_hash_table_lookup (group->actions, info->name))
+              {
+                g_hash_table_insert (group->actions, info->name, info);
+
+                if (group->strict)
+                  g_action_group_action_added (g_group, info->name);
+              }
+            else
+              action_info_free (info);
+          }
+      }
+    }
+}
+
+static void
+g_dbus_action_group_describe_all_done (GObject      *source,
+                                       GAsyncResult *result,
+                                       gpointer      user_data)
+{
+  GSimpleAsyncResult *my_result = user_data;
+  GDBusActionGroup *group;
+  GError *error = NULL;
+  GVariant *reply;
+
+  group = g_simple_async_result_get_op_res_gpointer (my_result);
+  g_assert (G_IS_DBUS_ACTION_GROUP (group));
+  g_assert (group->connection == (gpointer) source);
+  reply = g_dbus_connection_call_finish (group->connection, result, &error);
+
+  if (reply != NULL)
+    {
+      GVariantIter *iter;
+      ActionInfo *action;
+
+      g_variant_get (reply, "(a{s(bgav)})", &iter);
+      while ((action = action_info_new_from_iter (iter)))
+        g_hash_table_insert (group->actions, action->name, action);
+      g_variant_iter_free (iter);
+      g_variant_unref (reply);
+    }
+  else
+    {
+      g_simple_async_result_set_from_error (my_result, error);
+      g_error_free (error);
+    }
+
+  g_simple_async_result_complete (my_result);
+  g_object_unref (my_result);
+}
+
+/**
+ * g_dbus_action_group_new:
+ * @connection: A #GDBusConnection
+ * @bus_name: the bus name which exports the action group
+ * @object_path: the object path at which the action group is exported
+ * @flags: Flags used when constructing the object
+ * @cancellable: A #GCancellable or %NULL
+ * @callback: Callback function to invoke when the object is ready
+ * @user_data: User data to pass to @callback
+ *
+ * Creates a new, empty, #GDBusActionGroup.
+ *
+ * This is a failable asynchronous constructor - when the object
+ * is ready, @callback will be invoked and you can use
+ * g_dbus_action_group_new_finish() to get the result.
+ *
+ * See g_dbus_action_group_new_sync() and for a synchronous version
+ * of this constructor.
+ */
+void
+g_dbus_action_group_new (GDBusConnection       *connection,
+                         const gchar           *bus_name,
+                         const gchar           *object_path,
+                         GDBusActionGroupFlags  flags,
+                         GCancellable          *cancellable,
+                         GAsyncReadyCallback    callback,
+                         gpointer               user_data)
+{
+  GSimpleAsyncResult *result;
+  GDBusActionGroup *group;
+
+  group = g_object_new (G_TYPE_DBUS_ACTION_GROUP, NULL);
+  group->connection = g_object_ref (connection);
+  group->bus_name = g_strdup (bus_name);
+  group->object_path = g_strdup (object_path);
+
+  /* It's probably excessive to worry about watching the name ownership.
+   * The person using this class will know for themselves when the name
+   * disappears.
+   */
+
+  result = g_simple_async_result_new (G_OBJECT (group), callback, user_data, g_dbus_action_group_new);
+  g_simple_async_result_set_op_res_gpointer (result, group, g_object_unref);
+
+  if (~flags & G_DBUS_ACTION_GROUP_FLAGS_DO_NOT_WATCH)
+    group->subscription_id =
+      g_dbus_connection_signal_subscribe (connection, bus_name, "org.gtk.Actions", "Changed", object_path, NULL,
+                                          G_DBUS_SIGNAL_FLAGS_NONE, g_dbus_action_group_changed, group, NULL);
+
+  if (~flags & G_DBUS_ACTION_GROUP_FLAGS_DO_NOT_POPULATE)
+    g_dbus_connection_call (connection, bus_name, object_path, "org.gtk.Actions", "DescribeAll", NULL,
+                            G_VARIANT_TYPE ("(a{s(bgav)})"), G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
+                            g_dbus_action_group_describe_all_done, result);
+
+  else
+    g_simple_async_result_complete_in_idle (result);
+}
+
+/**
+ * g_dbus_action_group_new_finish:
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback
+ *     function passed to g_dbus_action_group_new()
+ * @error: Return location for error or %NULL
+ *
+ * Finishes creating a #GDBusActionGroup.
+ *
+ * Returns: A #GDBusProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+GDBusActionGroup *
+g_dbus_action_group_new_finish (GAsyncResult  *result,
+                                GError       **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+  g_return_val_if_fail (g_simple_async_result_is_valid (result,
+                                                        g_simple_async_result_get_op_res_gpointer (simple),
+                                                        g_dbus_action_group_new), NULL);
+
+  if (g_simple_async_result_propagate_error (simple, error))
+    return NULL;
+
+  return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
+}
+
+/**
+ * g_dbus_action_group_new_sync:
+ * @connection: A #GDBusConnection
+ * @bus_name: the bus name which exports the action group
+ * @object_path: the object path at which the action group is exported
+ * @flags: Flags used when constructing the object
+ * @cancellable: A #GCancellable or %NULL
+ * @error: Return location for error or %NULL
+ *
+ * This is a synchronous failable constructor. See g_dbus_action_group_new()
+ * and g_dbus_action_group_new_finish() for the asynchronous version.
+ *
+ * Returns: A #GDBusProxy or %NULL if @error is set. Free with g_object_unref().
+ */
+GDBusActionGroup *
+g_dbus_action_group_new_sync (GDBusConnection        *connection,
+                              const gchar            *bus_name,
+                              const gchar            *object_path,
+                              GDBusActionGroupFlags   flags,
+                              GCancellable           *cancellable,
+                              GError                **error)
+{
+  GDBusActionGroup *group;
+
+  group = g_object_new (G_TYPE_DBUS_ACTION_GROUP, NULL);
+  group->connection = g_object_ref (connection);
+  group->bus_name = g_strdup (bus_name);
+  group->object_path = g_strdup (object_path);
+
+  if (~flags & G_DBUS_ACTION_GROUP_FLAGS_DO_NOT_WATCH)
+    group->subscription_id =
+      g_dbus_connection_signal_subscribe (connection, bus_name, "org.gtk.Actions", "Changed", object_path, NULL,
+                                          G_DBUS_SIGNAL_FLAGS_NONE, g_dbus_action_group_changed, group, NULL);
+
+  if (~flags & G_DBUS_ACTION_GROUP_FLAGS_DO_NOT_POPULATE)
+    {
+      GVariant *reply;
+
+      reply = g_dbus_connection_call_sync (connection, bus_name, object_path, "org.gtk.Actions",
+                                           "DescribeAll", NULL, G_VARIANT_TYPE ("(a{s(bgav)})"),
+                                           G_DBUS_CALL_FLAGS_NONE, -1, cancellable, error);
+
+      if (reply != NULL)
+        {
+          GVariantIter *iter;
+          ActionInfo *action;
+
+          g_variant_get (reply, "(a{s(bgav)})", &iter);
+          while ((action = action_info_new_from_iter (iter)))
+            g_hash_table_insert (group->actions, action->name, action);
+          g_variant_iter_free (iter);
+          g_variant_unref (reply);
+        }
+      else
+        {
+          g_object_unref (group);
+          return NULL;
+        }
+    }
+
+  return group;
+}
+
+gboolean
+g_dbus_action_group_inject (GDBusActionGroup   *group,
+                            const gchar        *action_name,
+                            const GVariantType *parameter_type,
+                            gboolean            enabled,
+                            GVariant           *state)
+{
+  ActionInfo *action;
+
+  g_return_val_if_fail (G_IS_DBUS_ACTION_GROUP (group), FALSE);
+  g_return_val_if_fail (action_name != NULL, FALSE);
+
+  if (g_hash_table_lookup (group->actions, action_name))
+    return FALSE;
+
+  action = g_slice_new (ActionInfo);
+  action->name = g_strdup (action_name);
+  action->parameter_type = parameter_type ? g_variant_type_copy (parameter_type) : NULL;
+  action->enabled = !!enabled;
+  action->state = state ? g_variant_ref_sink (state) : NULL;
+
+  g_hash_table_insert (group->actions, action->name, action);
+
+  if (group->strict)
+    g_action_group_action_added (G_ACTION_GROUP (group), action_name);
+
+  return TRUE;
+}
diff --git a/gio/gdbusactiongroup.h b/gio/gdbusactiongroup.h
new file mode 100644
index 0000000..a418e8d
--- /dev/null
+++ b/gio/gdbusactiongroup.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright  2010 Codethink Limited
+ * Copyright  2011 Canonical Limited
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Ryan Lortie <desrt desrt ca>
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#ifndef __G_DBUS_ACTION_GROUP_H__
+#define __G_DBUS_ACTION_GROUP_H__
+
+#include "giotypes.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DBUS_ACTION_GROUP                            (g_dbus_action_group_get_type ())
+#define G_DBUS_ACTION_GROUP(inst)                           (G_TYPE_CHECK_INSTANCE_CAST ((inst),                     \
+                                                             G_TYPE_DBUS_ACTION_GROUP, GDBusActionGroup))
+#define G_DBUS_ACTION_GROUP_CLASS(class)                    (G_TYPE_CHECK_CLASS_CAST ((class),                       \
+                                                             G_TYPE_DBUS_ACTION_GROUP, GDBusActionGroupClass))
+#define G_IS_DBUS_ACTION_GROUP(inst)                        (G_TYPE_CHECK_INSTANCE_TYPE ((inst),                     \
+                                                             G_TYPE_DBUS_ACTION_GROUP))
+#define G_IS_DBUS_ACTION_GROUP_CLASS(class)                 (G_TYPE_CHECK_CLASS_TYPE ((class),                       \
+                                                             G_TYPE_DBUS_ACTION_GROUP))
+#define G_DBUS_ACTION_GROUP_GET_CLASS(inst)                 (G_TYPE_INSTANCE_GET_CLASS ((inst),                      \
+                                                             G_TYPE_DBUS_ACTION_GROUP, GDBusActionGroupClass))
+
+GType                   g_dbus_action_group_get_type                  (void) G_GNUC_CONST;
+
+void                    g_dbus_action_group_new                       (GDBusConnection        *connection,
+                                                                       const gchar            *bus_name,
+                                                                       const gchar            *object_path,
+                                                                       GDBusActionGroupFlags   flags,
+                                                                       GCancellable           *cancellable,
+                                                                       GAsyncReadyCallback     callback,
+                                                                       gpointer                user_data);
+
+GDBusActionGroup *      g_dbus_action_group_new_finish                (GAsyncResult           *result,
+                                                                       GError                **error);
+
+GDBusActionGroup *      g_dbus_action_group_new_sync                  (GDBusConnection        *connection,
+                                                                       const gchar            *bus_name,
+                                                                       const gchar            *object_path,
+                                                                       GDBusActionGroupFlags   flags,
+                                                                       GCancellable           *cancellable,
+                                                                       GError                **error);
+
+gboolean                g_dbus_action_group_inject                    (GDBusActionGroup       *group,
+                                                                       const gchar            *action_name,
+                                                                       const GVariantType     *parameter_type,
+                                                                       gboolean                enabled,
+                                                                       GVariant               *state);
+
+G_END_DECLS
+
+#endif /* __G_DBUS_ACTION_GROUP_H__ */
diff --git a/gio/gio.h b/gio/gio.h
index 2a550ae..9db5288 100644
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -145,6 +145,7 @@
 #include <gio/gdbusobjectmanager.h>
 #include <gio/gdbusobjectmanagerclient.h>
 #include <gio/gdbusobjectmanagerserver.h>
+#include <gio/gdbusactiongroup.h>
 
 #undef __GIO_GIO_H_INSIDE__
 
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 461b874..7a8742d 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -1434,6 +1434,12 @@ g_simple_action_new
 g_simple_action_new_stateful
 g_simple_action_set_enabled
 g_simple_action_set_state
+g_dbus_action_group_flags_get_type
+g_dbus_action_group_get_type
+g_dbus_action_group_inject
+g_dbus_action_group_new
+g_dbus_action_group_new_finish
+g_dbus_action_group_new_sync
 g_pollable_input_stream_get_type
 g_pollable_input_stream_can_poll
 g_pollable_input_stream_create_source
diff --git a/gio/gioenums.h b/gio/gioenums.h
index 2d4af44..5c28784 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -1473,6 +1473,7 @@ typedef enum
 } GDBusObjectManagerClientFlags;
 
 /**
+<<<<<<< HEAD
  * GTlsDatabaseVerifyFlags:
  * @G_TLS_DATABASE_VERIFY_NONE: No verification flags
  *
@@ -1516,6 +1517,25 @@ typedef enum {
   G_IO_MODULE_SCOPE_BLOCK_DUPLICATES
 } GIOModuleScopeFlags;
 
+/* GDBusActionGroupFlags:
+ * @G_DBUS_ACTION_GROUP_FLAGS_NONE: No flags set.
+ * @G_DBUS_ACTION_GROUP_FLAGS_DO_NOT_POPULATE: Do not make the initial
+ *   D-Bus call to populate the set of actions in the group.  Instead,
+ *   actions can be added using g_dbus_action_group_inject().  Changes
+ *   are still monitored.
+ * @G_DBUS_ACTION_GROUP_FLAGS_DO_NOT_WATCH: Don't watch for changes.
+ *
+ * Flags used when constructing a #GDBusActionGroup.
+ *
+ * Since: 2.30
+ **/
+typedef enum
+{
+  G_DBUS_ACTION_GROUP_FLAGS_NONE            = 0,
+  G_DBUS_ACTION_GROUP_FLAGS_DO_NOT_POPULATE = (1<<0),
+  G_DBUS_ACTION_GROUP_FLAGS_DO_NOT_WATCH    = (1<<1)
+} GDBusActionGroupFlags;
+
 G_END_DECLS
 
 #endif /* __GIO_ENUMS_H__ */
diff --git a/gio/giotypes.h b/gio/giotypes.h
index 4077dbb..8db258c 100644
--- a/gio/giotypes.h
+++ b/gio/giotypes.h
@@ -48,6 +48,7 @@ typedef struct _GZlibCompressor               GZlibCompressor;
 typedef struct _GZlibDecompressor             GZlibDecompressor;
 
 typedef struct _GSimpleActionGroup            GSimpleActionGroup;
+typedef struct _GDBusActionGroup              GDBusActionGroup;
 typedef struct _GActionGroup                  GActionGroup;
 typedef struct _GSimpleAction                 GSimpleAction;
 typedef struct _GAction                       GAction;



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