[gtk+/wip/csoriano/cloud-providers: 232/233] cloud providers
- From: Carlos Soriano Sánchez <csoriano src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/csoriano/cloud-providers: 232/233] cloud providers
- Date: Mon, 6 Jul 2015 22:20:36 +0000 (UTC)
commit 6a6697c898efb343c335fae231b2d69ed7522006
Author: Carlos Soriano <csoriano gnome org>
Date: Wed Jun 17 20:30:46 2015 +0200
cloud providers
docs/reference/gtk/gtk3-sections.txt | 8 +
gtk/Makefile.am | 4 +
gtk/gtk.h | 2 +
gtk/gtkcloudprovider.c | 432 +++++++++++++++++++
gtk/gtkcloudprovider.h | 84 ++++
gtk/gtkcloudprovidermanager.c | 310 ++++++++++++++
gtk/gtkcloudprovidermanager.h | 61 +++
gtk/gtkfilechooser.c | 3 +-
tests/Makefile.am | 20 +
tests/org.gtk.CloudProviderServerExample.ini | 4 +
tests/org.gtk.CloudProviderServerExample.service | 3 +
.../org.gtk.CloudProviderServerExample.service.in | 3 +
tests/testcloudproviderclient.c | 131 ++++++
tests/testcloudproviderserver.c | 437 ++++++++++++++++++++
tests/testpopover.c | 1 +
15 files changed, 1502 insertions(+), 1 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index 7b29c13..ec27cc5 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -2631,6 +2631,14 @@ gtk_paned_get_type
</SECTION>
<SECTION>
+<FILE>gtkcloudprovidermanager</FILE>
+<TITLE>GtkCloudProviderManager</TITLE>
+GtkCloudProviderManager
+gtk_cloud_provider_manager_dup_singleton
+gtk_cloud_provider_manager_get_providers
+</SECTION>
+
+<SECTION>
<FILE>gtkplacessidebar</FILE>
<TITLE>GtkPlacesSidebar</TITLE>
GtkPlacesSidebar
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 4795f84..b91020e 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -164,6 +164,8 @@ gtk_public_h_sources = \
gtkcontainer.h \
gtkcssprovider.h \
gtkcsssection.h \
+ gtkcloudprovider.h \
+ gtkcloudprovidermanager.h \
gtkdebug.h \
gtkdialog.h \
gtkdnd.h \
@@ -666,6 +668,8 @@ gtk_base_c_sources = \
gtkcsstypes.c \
gtkcssvalue.c \
gtkcsswidgetnode.c \
+ gtkcloudprovider.c \
+ gtkcloudprovidermanager.c \
gtkdialog.c \
gtkdrawingarea.c \
gtkeditable.c \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 3cbd13f..0ec9af3 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -71,6 +71,8 @@
#include <gtk/gtkcheckbutton.h>
#include <gtk/gtkcheckmenuitem.h>
#include <gtk/gtkclipboard.h>
+#include <gtk/gtkcloudprovider.h>
+#include <gtk/gtkcloudprovidermanager.h>
#include <gtk/gtkcolorbutton.h>
#include <gtk/gtkcolorchooser.h>
#include <gtk/gtkcolorchooserdialog.h>
diff --git a/gtk/gtkcloudprovider.c b/gtk/gtkcloudprovider.c
new file mode 100644
index 0000000..efab1c5
--- /dev/null
+++ b/gtk/gtkcloudprovider.c
@@ -0,0 +1,432 @@
+/* gtkcloudprovider.c
+ *
+ * Copyright (C) 2015 Carlos Soriano <csoriano gnome org>
+ *
+ * This file 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 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "gtkcloudprovider.h"
+#include "gtkmenu.h"
+#include <gio/gio.h>
+
+static const gchar provider_xml[] =
+ "<node>"
+ " <interface name='org.gtk.CloudProvider'>"
+ " <method name='GetName'>"
+ " <arg type='s' name='name' direction='out'/>"
+ " </method>"
+ " <method name='GetStatus'>"
+ " <arg type='i' name='name' direction='out'/>"
+ " </method>"
+ " <method name='GetIcon'>"
+ " <arg type='v' name='icon' direction='out'/>"
+ " </method>"
+ " <method name='GetPath'>"
+ " <arg type='s' name='path' direction='out'/>"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+
+typedef struct
+{
+ gchar *name;
+ gchar *path;
+ GtkCloudProviderStatus status;
+ GIcon *icon;
+ GtkWidget *menu;
+ GMenuModel *menu_model;
+ GActionGroup *action_group;
+
+ GDBusConnection *bus;
+ GDBusProxy *proxy;
+ gchar *bus_name;
+ gchar *object_path;
+ GCancellable *cancellable;
+} GtkCloudProviderPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkCloudProvider, gtk_cloud_provider, G_TYPE_OBJECT)
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint gSignals [LAST_SIGNAL];
+
+static void
+on_get_icon (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkCloudProvider *self = GTK_CLOUD_PROVIDER (user_data);
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+ GError *error = NULL;
+ GVariant *variant_tuple;
+ GVariant *variant_dict;
+ GVariant *variant;
+
+ g_clear_object (&priv->icon);
+
+ variant_tuple = g_dbus_proxy_call_finish (priv->proxy, res, &error);
+ g_print ("variant tuple %s\n", g_variant_print (variant_tuple, TRUE));
+ if (error != NULL)
+ {
+ g_warning ("Error getting the provider icon %s", error->message);
+ goto out;
+ }
+
+ variant_dict = g_variant_get_child_value (variant_tuple, 0);
+ variant = g_variant_get_child_value (variant_dict, 0);
+ priv->icon = g_icon_deserialize (variant);
+ g_variant_unref (variant);
+ g_variant_unref (variant_dict);
+
+out:
+ g_variant_unref (variant_tuple);
+ g_signal_emit_by_name (self, "changed");
+}
+
+static void
+on_get_name (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkCloudProvider *self = GTK_CLOUD_PROVIDER (user_data);
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+ GError *error = NULL;
+ GVariant *variant_tuple;
+ GVariant *variant;
+
+ if (priv->name != NULL)
+ g_free (priv->name);
+
+ variant_tuple = g_dbus_proxy_call_finish (priv->proxy, res, &error);
+ if (error != NULL)
+ {
+ g_warning ("Error getting the provider name %s", error->message);
+ goto out;
+ }
+
+ variant = g_variant_get_child_value (variant_tuple, 0);
+ priv->name = g_variant_dup_string (variant, NULL);
+ g_variant_unref (variant);
+
+out:
+ g_variant_unref (variant_tuple);
+ g_signal_emit_by_name (self, "changed");
+}
+
+static void
+on_get_path (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkCloudProvider *self = GTK_CLOUD_PROVIDER (user_data);
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+ GError *error = NULL;
+ GVariant *variant_tuple;
+ GVariant *variant;
+
+ if (priv->path != NULL)
+ g_free (priv->path);
+
+ variant_tuple = g_dbus_proxy_call_finish (priv->proxy, res, &error);
+ if (error != NULL)
+ {
+ g_warning ("Error getting the provider path %s", error->message);
+ goto out;
+ }
+
+ variant = g_variant_get_child_value (variant_tuple, 0);
+ priv->path = g_variant_dup_string (variant, NULL);
+ g_variant_unref (variant);
+
+out:
+ g_variant_unref (variant_tuple);
+ g_signal_emit_by_name (self, "changed");
+}
+
+static void
+on_get_status (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkCloudProvider *self = GTK_CLOUD_PROVIDER (user_data);
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+ GError *error = NULL;
+ GVariant *variant_tuple;
+ GVariant *variant;
+
+ variant_tuple = g_dbus_proxy_call_finish (priv->proxy, res, &error);
+ if (error != NULL)
+ {
+ g_warning ("Error getting the provider status %s", error->message);
+ goto out;
+ }
+
+ variant = g_variant_get_child_value (variant_tuple, 0);
+ priv->status = g_variant_get_int32 (variant);
+ g_variant_unref (variant);
+
+out:
+ g_variant_unref (variant_tuple);
+ g_signal_emit_by_name (self, "changed");
+}
+
+void
+gtk_cloud_provider_update (GtkCloudProvider *self)
+{
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+
+ if (priv->proxy != NULL)
+ {
+ g_dbus_proxy_call (priv->proxy,
+ "GetName",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ (GAsyncReadyCallback) on_get_name,
+ self);
+
+ g_dbus_proxy_call (priv->proxy,
+ "GetStatus",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ (GAsyncReadyCallback) on_get_status,
+ self);
+
+ g_dbus_proxy_call (priv->proxy,
+ "GetIcon",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ (GAsyncReadyCallback) on_get_icon,
+ self);
+
+ g_dbus_proxy_call (priv->proxy,
+ "GetPath",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ (GAsyncReadyCallback) on_get_path,
+ self);
+
+ priv->menu_model = (GMenuModel*) g_dbus_menu_model_get (priv->bus,
+ priv->bus_name,
+ priv->object_path);
+ priv->action_group = (GActionGroup*) g_dbus_action_group_get (priv->bus,
+ priv->bus_name,
+ priv->object_path);
+ /* The GMenuModel returned is lazily loaded, so it can't be used as a populated
+ * GMenuModel. To avoid confusion to GtkCloudProvider clients, use a GtkMenu,
+ * which will take care of loading the items */
+ priv->menu = gtk_menu_new_from_model (priv->menu_model);
+ }
+}
+
+static void
+on_proxy_created (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ GtkCloudProvider *self;
+ GtkCloudProviderPrivate *priv;
+ GDBusProxy *proxy;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (error != NULL)
+ {
+ if (error->code != G_IO_ERROR_CANCELLED)
+ g_warning ("Error creating proxy for cloud provider %s", error->message);
+ return;
+ }
+ self = GTK_CLOUD_PROVIDER (user_data);
+ priv = gtk_cloud_provider_get_instance_private (self);
+
+ priv->proxy = proxy;
+
+ gtk_cloud_provider_update (self);
+}
+
+static void
+on_bus_acquired (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ GtkCloudProvider *self;
+ GDBusConnection *bus;
+ GtkCloudProviderPrivate *priv;
+ GDBusInterfaceInfo *interface_info;
+ GDBusNodeInfo *proxy_info;
+
+ bus = g_bus_get_finish (res, &error);
+ if (error != NULL)
+ {
+ if (error->code != G_IO_ERROR_CANCELLED)
+ g_warning ("Error acdquiring bus for cloud provider %s", error->message);
+ return;
+ }
+
+ self = GTK_CLOUD_PROVIDER (user_data);
+ priv = gtk_cloud_provider_get_instance_private (user_data);
+ priv->bus = bus;
+ proxy_info = g_dbus_node_info_new_for_xml (provider_xml, &error);
+ interface_info = g_dbus_node_info_lookup_interface (proxy_info, "org.gtk.CloudProvider");
+ g_clear_object (&priv->cancellable);
+ priv->cancellable = g_cancellable_new ();
+ g_dbus_proxy_new (priv->bus,
+ G_DBUS_PROXY_FLAGS_NONE,
+ interface_info,
+ priv->bus_name,
+ priv->object_path,
+ "org.gtk.CloudProvider",
+ priv->cancellable,
+ on_proxy_created,
+ self);
+}
+
+GtkCloudProvider*
+gtk_cloud_provider_new (const gchar *bus_name,
+ const gchar *object_path)
+{
+ GtkCloudProvider *self;
+ GtkCloudProviderPrivate *priv;
+
+ self = g_object_new (GTK_TYPE_CLOUD_PROVIDER, NULL);
+ priv = gtk_cloud_provider_get_instance_private (self);
+
+ priv->bus_name = g_strdup (bus_name);
+ priv->object_path = g_strdup (object_path);
+ priv->cancellable = g_cancellable_new ();
+ priv->status = GTK_CLOUD_PROVIDER_STATUS_INVALID;
+ g_bus_get (G_BUS_TYPE_SESSION,
+ priv->cancellable,
+ on_bus_acquired,
+ self);
+
+ return self;
+}
+
+static void
+gtk_cloud_provider_finalize (GObject *object)
+{
+ GtkCloudProvider *self = (GtkCloudProvider *)object;
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+
+ g_cancellable_cancel (priv->cancellable);
+ g_clear_object (&priv->cancellable);
+ g_free (priv->name);
+ g_free (priv->path);
+ g_clear_object (&priv->icon);
+ g_clear_object (&priv->menu);
+ g_clear_object (&priv->action_group);
+ g_clear_object (&priv->bus);
+ g_clear_object (&priv->proxy);
+ g_free (priv->bus_name);
+ g_free (priv->object_path);
+
+ G_OBJECT_CLASS (gtk_cloud_provider_parent_class)->finalize (object);
+}
+
+static void
+gtk_cloud_provider_class_init (GtkCloudProviderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_cloud_provider_finalize;
+
+ gSignals [CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 0);
+}
+
+static void
+gtk_cloud_provider_init (GtkCloudProvider *self)
+{
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+
+ priv->status = GTK_CLOUD_PROVIDER_STATUS_INVALID;
+}
+
+gchar*
+gtk_cloud_provider_get_name (GtkCloudProvider *self)
+{
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+
+ return priv->name;
+}
+
+GtkCloudProviderStatus
+gtk_cloud_provider_get_status (GtkCloudProvider *self)
+{
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+
+ return priv->status;
+}
+
+GIcon*
+gtk_cloud_provider_get_icon (GtkCloudProvider *self)
+{
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+
+ return priv->icon;
+}
+
+GtkWidget*
+gtk_cloud_provider_get_menu (GtkCloudProvider *self)
+{
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+
+ return priv->menu;
+}
+
+GMenuModel*
+gtk_cloud_provider_get_menu_model (GtkCloudProvider *self)
+{
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+
+ return priv->menu_model;
+}
+
+GActionGroup*
+gtk_cloud_provider_get_action_group (GtkCloudProvider *self)
+{
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+
+ return priv->action_group;
+}
+
+gchar *
+gtk_cloud_provider_get_path (GtkCloudProvider *self)
+{
+ GtkCloudProviderPrivate *priv = gtk_cloud_provider_get_instance_private (self);
+
+ return priv->path;
+}
diff --git a/gtk/gtkcloudprovider.h b/gtk/gtkcloudprovider.h
new file mode 100644
index 0000000..0036af6
--- /dev/null
+++ b/gtk/gtkcloudprovider.h
@@ -0,0 +1,84 @@
+/* gtkcloudprovider.h
+ *
+ * Copyright (C) 2015 Carlos Soriano <csoriano gnome org>
+ *
+ * This file 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 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTK_CLOUD_PROVIDER_H
+#define GTK_CLOUD_PROVIDER_H
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gio/gio.h>
+#include <gdk/gdk.h>
+#include "gtkwidget.h"
+
+G_BEGIN_DECLS
+
+typedef enum {
+ GTK_CLOUD_PROVIDER_STATUS_INVALID,
+ GTK_CLOUD_PROVIDER_STATUS_IDLE,
+ GTK_CLOUD_PROVIDER_STATUS_SYNCING,
+ GTK_CLOUD_PROVIDER_STATUS_ERROR
+} GtkCloudProviderStatus;
+
+#define GTK_TYPE_CLOUD_PROVIDER (gtk_cloud_provider_get_type())
+#define GTK_CLOUD_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CLOUD_PROVIDER,
GtkCloudProvider))
+#define GTK_CLOUD_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CLOUD_PROVIDER,
GtkCloudProviderClass))
+#define GTK_IS_CLOUD_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CLOUD_PROVIDER))
+#define GTK_IS_CLOUD_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CLOUD_PROVIDER))
+#define GTK_CLOUD_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CLOUD_PROVIDER,
GtkCloudProviderClass))
+
+typedef struct _GtkCloudProvider GtkCloudProvider;
+typedef struct _GtkCloudProviderClass GtkCloudProviderClass;
+
+
+struct _GtkCloudProviderClass
+{
+ GObjectClass parent_class;
+};
+
+struct _GtkCloudProvider
+{
+ GObject parent_instance;
+};
+
+GDK_AVAILABLE_IN_3_18
+GType gtk_cloud_provider_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_3_18
+GtkCloudProvider *gtk_cloud_provider_new (const gchar *bus_name,
+ const gchar *object_path);
+GDK_AVAILABLE_IN_3_18
+gchar* gtk_cloud_provider_get_name (GtkCloudProvider *self);
+GDK_AVAILABLE_IN_3_18
+GtkCloudProviderStatus gtk_cloud_provider_get_status (GtkCloudProvider *self);
+GDK_AVAILABLE_IN_3_18
+GIcon *gtk_cloud_provider_get_icon (GtkCloudProvider *self);
+GDK_AVAILABLE_IN_3_18
+GtkWidget *gtk_cloud_provider_get_menu (GtkCloudProvider *self);
+GDK_AVAILABLE_IN_3_18
+GMenuModel *gtk_cloud_provider_get_menu_model (GtkCloudProvider *self);
+GDK_AVAILABLE_IN_3_18
+GActionGroup* gtk_cloud_provider_get_action_group (GtkCloudProvider *self);
+GDK_AVAILABLE_IN_3_18
+gchar *gtk_cloud_provider_get_path (GtkCloudProvider *self);
+
+
+
+G_END_DECLS
+
+#endif /* GTK_CLOUD_PROVIDER_H */
diff --git a/gtk/gtkcloudprovidermanager.c b/gtk/gtkcloudprovidermanager.c
new file mode 100644
index 0000000..9a161b6
--- /dev/null
+++ b/gtk/gtkcloudprovidermanager.c
@@ -0,0 +1,310 @@
+/* gtkcloudprovidermanager.c
+ *
+ * Copyright (C) 2015 Carlos Soriano <csoriano gnome org>
+ *
+ * This file 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 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkcloudprovidermanager.h"
+#include "gtkcloudprovider.h"
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#define KEY_FILE_GROUP "Gtk Cloud Provider"
+
+typedef struct
+{
+ GList *providers;
+ guint dbus_owner_id;
+ GDBusNodeInfo *dbus_node_info;
+} GtkCloudProviderManagerPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkCloudProviderManager, gtk_cloud_provider_manager, G_TYPE_OBJECT)
+
+enum
+{
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint gSignals [LAST_SIGNAL];
+
+static const gchar manager_xml[] =
+ "<node>"
+ " <interface name='org.gtk.CloudProviderManager'>"
+ " <method name='CloudProviderChanged'>"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ if (g_strcmp0 (method_name, "CloudProviderChanged") == 0)
+ {
+ gtk_cloud_provider_manager_update (GTK_CLOUD_PROVIDER_MANAGER (user_data));
+ }
+}
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+ handle_method_call,
+};
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GtkCloudProviderManager *self = user_data;
+ GtkCloudProviderManagerPrivate *priv = gtk_cloud_provider_manager_get_instance_private (self);
+ guint registration_id;
+
+ g_debug ("Registering cloud provider server 'MyCloud'\n");
+ registration_id = g_dbus_connection_register_object (connection,
+ "/org/gtk/CloudProviderManager",
+ priv->dbus_node_info->interfaces[0],
+ &interface_vtable,
+ self,
+ NULL, /* user_data_free_func */
+ NULL); /* GError** */
+ g_assert (registration_id > 0);
+
+ /* In case some provider updated before adquiring the bus */
+ gtk_cloud_provider_manager_update (GTK_CLOUD_PROVIDER_MANAGER (user_data));
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+}
+
+/**
+ * gtk_cloud_provider_manager_dup_singleton
+ * Returns: (transfer none): A manager singleton
+ */
+GtkCloudProviderManager *
+gtk_cloud_provider_manager_dup_singleton (void)
+{
+ static GObject *self = NULL;
+
+ if (self == NULL)
+ {
+ GtkCloudProviderManagerPrivate *priv;
+
+ self = g_object_new (GTK_TYPE_CLOUD_PROVIDER_MANAGER, NULL);
+ priv = gtk_cloud_provider_manager_get_instance_private (GTK_CLOUD_PROVIDER_MANAGER (self));
+
+ /* Export the interface we listen to, so clients can request properties of
+ * the cloud provider such as name, status or icon */
+ priv->dbus_node_info = g_dbus_node_info_new_for_xml (manager_xml, NULL);
+ g_assert (priv->dbus_node_info != NULL);
+
+ priv->dbus_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ "org.gtk.CloudProviderManager",
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_bus_acquired,
+ on_name_acquired,
+ on_name_lost,
+ self,
+ NULL);
+ return GTK_CLOUD_PROVIDER_MANAGER (self);
+ }
+ else
+ {
+ return g_object_ref (self);
+ }
+}
+
+static void
+gtk_cloud_provider_manager_finalize (GObject *object)
+{
+ GtkCloudProviderManager *self = (GtkCloudProviderManager *)object;
+ GtkCloudProviderManagerPrivate *priv = gtk_cloud_provider_manager_get_instance_private (self);
+
+ g_list_free_full (priv->providers, g_object_unref);
+ g_bus_unown_name (priv->dbus_owner_id);
+ g_dbus_node_info_unref (priv->dbus_node_info);
+
+ G_OBJECT_CLASS (gtk_cloud_provider_manager_parent_class)->finalize (object);
+}
+
+static void
+gtk_cloud_provider_manager_class_init (GtkCloudProviderManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_cloud_provider_manager_finalize;
+
+ gSignals [CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 0);
+}
+
+static void
+gtk_cloud_provider_manager_init (GtkCloudProviderManager *self)
+{
+}
+
+/**
+ * gtk_cloud_provider_manager_get_providers
+ * @manager: A GtkCloudProviderManager
+ * Returns: (transfer none): The list of providers.
+ */
+GList*
+gtk_cloud_provider_manager_get_providers (GtkCloudProviderManager *manager)
+{
+ GtkCloudProviderManagerPrivate *priv = gtk_cloud_provider_manager_get_instance_private (manager);
+
+ return priv->providers;
+}
+
+static void
+on_cloud_provider_changed (GtkCloudProvider *cloud_provider,
+ GtkCloudProviderManager *self)
+{
+ GIcon *icon;
+ gchar *name;
+ guint status;
+
+ name = gtk_cloud_provider_get_name (cloud_provider);
+ icon = gtk_cloud_provider_get_icon (cloud_provider);
+ status = gtk_cloud_provider_get_status (cloud_provider);
+ if (name == NULL || icon == NULL || status == GTK_CLOUD_PROVIDER_STATUS_INVALID)
+ return;
+
+ g_signal_emit_by_name (self, "changed", NULL);
+}
+
+static void
+load_cloud_provider (GtkCloudProviderManager *self,
+ GFile *file)
+{
+ GtkCloudProviderManagerPrivate *priv = gtk_cloud_provider_manager_get_instance_private (self);
+ GKeyFile *key_file;
+ gchar *path;
+ GError *error = NULL;
+ gchar *bus_name;
+ gchar *object_path;
+ gboolean success = FALSE;
+ GtkCloudProvider *cloud_provider;
+
+ key_file = g_key_file_new ();
+ path = g_file_get_path (file);
+ g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error);
+ if (error != NULL)
+ goto out;
+
+ if (!g_key_file_has_group (key_file, KEY_FILE_GROUP))
+ goto out;
+
+ bus_name = g_key_file_get_string (key_file, KEY_FILE_GROUP, "BusName", &error);
+ if (error != NULL)
+ goto out;
+ object_path = g_key_file_get_string (key_file, KEY_FILE_GROUP, "ObjectPath", &error);
+ if (error != NULL)
+ goto out;
+
+ g_print ("cloud provider found %s %s\n", bus_name, object_path);
+ cloud_provider = gtk_cloud_provider_new (bus_name, object_path);
+ g_signal_connect (cloud_provider, "changed",
+ G_CALLBACK (on_cloud_provider_changed), self);
+ priv->providers = g_list_append (priv->providers, cloud_provider);
+
+ success = TRUE;
+out:
+ if (!success)
+ g_warning ("Error while loading cloud provider key file at %s", path);
+ g_key_file_free (key_file);
+}
+
+/**
+ * gtk_cloud_provider_manager_update
+ * @manager: A GtkCloudProviderManager
+ */
+void
+gtk_cloud_provider_manager_update (GtkCloudProviderManager *manager)
+{
+ GtkCloudProviderManagerPrivate *priv = gtk_cloud_provider_manager_get_instance_private (manager);
+ const gchar* const *data_dirs;
+ gint i;
+ gint len;
+ gchar *key_files_directory_path;
+ GFile *key_files_directory_file;
+ GError *error = NULL;
+ GFileEnumerator *file_enumerator;
+
+
+ g_list_free_full (priv->providers, g_object_unref);
+ priv->providers = NULL;
+
+ data_dirs = g_get_system_data_dirs ();
+ len = g_strv_length ((gchar **)data_dirs);
+
+ for (i = 0; i < len; i++)
+ {
+ GFileInfo *info;
+
+ key_files_directory_path = g_build_filename (data_dirs[i], "gtk+", "cloud-providers", NULL);
+ key_files_directory_file = g_file_new_for_path (key_files_directory_path);
+ file_enumerator = g_file_enumerate_children (key_files_directory_file,
+ "standard::name,standard::type",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+ if (error)
+ {
+ error = NULL;
+ continue;
+ }
+
+ info = g_file_enumerator_next_file (file_enumerator, NULL, &error);
+ if (error)
+ {
+ g_warning ("Error while enumerating file %s error: %s\n", key_files_directory_path,
error->message);
+ error = NULL;
+ continue;
+ }
+ while (info != NULL && error == NULL)
+ {
+ load_cloud_provider (manager, g_file_enumerator_get_child (file_enumerator, info));
+ info = g_file_enumerator_next_file (file_enumerator, NULL, &error);
+ }
+ }
+}
diff --git a/gtk/gtkcloudprovidermanager.h b/gtk/gtkcloudprovidermanager.h
new file mode 100644
index 0000000..560d5ff
--- /dev/null
+++ b/gtk/gtkcloudprovidermanager.h
@@ -0,0 +1,61 @@
+/* gtkcloudprovidermanager.h
+ *
+ * Copyright (C) 2015 Carlos Soriano <csoriano gnome org>
+ *
+ * This file 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 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file 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 General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GTK_CLOUD_PROVIDER_MANAGER_H
+#define GTK_CLOUD_PROVIDER_MANAGER_H
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gio/gio.h>
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CLOUD_PROVIDER_MANAGER (gtk_cloud_provider_manager_get_type())
+#define GTK_CLOUD_PROVIDER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GTK_TYPE_CLOUD_PROVIDER_MANAGER, GtkCloudProviderManager))
+#define GTK_CLOUD_PROVIDER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
GTK_TYPE_CLOUD_PROVIDER_MANAGER, GtkCloudProviderManagerClass))
+#define GTK_IS_CLOUD_PROVIDER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GTK_TYPE_CLOUD_PROVIDER_MANAGER))
+#define GTK_IS_CLOUD_PROVIDER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GTK_TYPE_CLOUD_PROVIDER_MANAGER))
+#define GTK_CLOUD_PROVIDER_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GTK_TYPE_CLOUD_PROVIDER_MANAGER, GtkCloudProviderManagerClass))
+
+typedef struct _GtkCloudProviderManager GtkCloudProviderManager;
+typedef struct _GtkCloudProviderManagerClass GtkCloudProviderManagerClass;
+
+struct _GtkCloudProviderManagerClass
+{
+ GObjectClass parent_class;
+};
+
+struct _GtkCloudProviderManager
+{
+ GObject parent_instance;
+};
+
+GDK_AVAILABLE_IN_3_18
+GType gtk_cloud_provider_manager_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_3_18
+GtkCloudProviderManager *gtk_cloud_provider_manager_dup_singleton (void);
+GDK_AVAILABLE_IN_3_18
+void gtk_cloud_provider_manager_update (GtkCloudProviderManager *self);
+GDK_AVAILABLE_IN_3_18
+GList *gtk_cloud_provider_manager_get_providers (GtkCloudProviderManager *self);
+
+G_END_DECLS
+
+#endif /* GTK_CLOUD_PROVIDER_MANAGER_H */
diff --git a/gtk/gtkfilechooser.c b/gtk/gtkfilechooser.c
index 969eae2..853330a 100644
--- a/gtk/gtkfilechooser.c
+++ b/gtk/gtkfilechooser.c
@@ -23,6 +23,7 @@
#include "gtktypebuiltins.h"
#include "gtkprivate.h"
#include "gtkmarshalers.h"
+#include "gtkcloudprovidermanager.h"
/**
@@ -181,7 +182,7 @@ static void
gtk_file_chooser_default_init (GtkFileChooserInterface *iface)
{
GType iface_type = G_TYPE_FROM_INTERFACE (iface);
-
+ gtk_cloud_provider_manager_dup_singleton ();
/**
* GtkFileChooser::current-folder-changed:
* @chooser: the object which received the signal.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 233daa4..fd87f68 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -30,6 +30,18 @@ if OS_LINUX
fontconfig_programs = testfontchooserdialog
endif
+cloudproviderdir = $(datadir)/gtk+/cloud-providers
+dist_cloudprovider_DATA = org.gtk.CloudProviderServerExample.ini
+
+servicedir = $(datadir)/dbus-1/services
+service_in_files = org.gtk.CloudProviderServerExample.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+org.gtk.CloudProviderServerExample.service: org.gtk.CloudProviderServerExample.service.in
+ $(AM_V_GEN) \
+ [ -d $(@D) ] || $(mkdir_p) $(@D) ; \
+ sed -e "s|\ bindir\@|$(bindir)|" $< > $ tmp && mv $ tmp $@
+
noinst_PROGRAMS = $(TEST_PROGS) \
overlayscroll \
syncscroll \
@@ -166,6 +178,8 @@ noinst_PROGRAMS = $(TEST_PROGS) \
testactionbar \
testwindowsize \
testpopover \
+ testcloudproviderserver \
+ testcloudproviderclient \
gdkgears \
$(NULL)
@@ -306,6 +320,8 @@ teststack_DEPENDENCIES = $(TEST_DEPS)
testrevealer_DEPENDENCIES = $(TEST_DEPS)
testtitlebar_DEPENDENCIES = $(TEST_DEPS)
testwindowsize_DEPENDENCIES = $(TEST_DEPS)
+testcloudproviderserver_DEPENDENCIES = $(TEST_DEPS)
+testcloudproviderclient_DEPENDENCIES = $(TEST_DEPS)
animated_resizing_SOURCES = \
animated-resizing.c \
@@ -528,6 +544,10 @@ testtitlebar_SOURCES = testtitlebar.c
testwindowsize_SOURCES = testwindowsize.c
+testcloudproviderserver_SOURCES = testcloudproviderserver.c
+
+testcloudproviderclient_SOURCES = testcloudproviderclient.c
+
gdkgears_SOURCES = \
gdkgears.c \
gtkgears.c \
diff --git a/tests/org.gtk.CloudProviderServerExample.ini b/tests/org.gtk.CloudProviderServerExample.ini
new file mode 100644
index 0000000..424b2eb
--- /dev/null
+++ b/tests/org.gtk.CloudProviderServerExample.ini
@@ -0,0 +1,4 @@
+[Gtk Cloud Provider]
+BusName=org.gtk.CloudProviderServerExample
+ObjectPath=/org/gtk/CloudProviderServerExample
+Version=1
diff --git a/tests/org.gtk.CloudProviderServerExample.service
b/tests/org.gtk.CloudProviderServerExample.service
new file mode 100644
index 0000000..52e93bf
--- /dev/null
+++ b/tests/org.gtk.CloudProviderServerExample.service
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gtk.CloudProviderServerExample
+Exec=/home/csoriano/jhbuild/install/bin/testcloudprovider
diff --git a/tests/org.gtk.CloudProviderServerExample.service.in
b/tests/org.gtk.CloudProviderServerExample.service.in
new file mode 100644
index 0000000..2a8b5e6
--- /dev/null
+++ b/tests/org.gtk.CloudProviderServerExample.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gtk.CloudProviderServerExample
+Exec= bindir@/testcloudprovider
diff --git a/tests/testcloudproviderclient.c b/tests/testcloudproviderclient.c
new file mode 100644
index 0000000..7880527
--- /dev/null
+++ b/tests/testcloudproviderclient.c
@@ -0,0 +1,131 @@
+#include "config.h"
+#include <glib.h>
+#include <gtk/gtk.h>
+
+static void
+print_menu (GtkWidget *menu)
+{
+ GList *children;
+ GList *l;
+ GtkWidget *submenu;
+
+ children = gtk_container_get_children (GTK_CONTAINER (menu));
+ for (l = children; l != NULL; l = l->next)
+ {
+ g_print ("Menu item - %s \n", gtk_menu_item_get_label (l->data));
+ submenu = gtk_menu_item_get_submenu (l->data);
+ if (submenu != NULL)
+ {
+ g_print ("---------\n");
+ print_menu (submenu);
+ g_print ("---------\n");
+ }
+ }
+}
+
+static void
+print_gmenu_model (GMenuModel *model)
+{
+ gint i, n_items;
+ GMenuModel *submodel = NULL;
+ gchar *label;
+
+ n_items = g_menu_model_get_n_items (model);
+
+ for (i = 0; i < n_items; i++)
+ {
+ label = NULL;
+ if (g_menu_model_get_item_attribute (model, i, G_MENU_ATTRIBUTE_LABEL, "s", &label))
+ {
+ g_print ("Menu item - %s\n", label);
+ if (label != NULL)
+ g_free (label);
+ }
+
+ submodel = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION);
+ if (!submodel)
+ submodel = g_menu_model_get_item_link (model, i, G_MENU_LINK_SUBMENU);
+
+ if (!submodel)
+ continue;
+ g_print ("---------\n");
+ print_gmenu_model (submodel);
+ g_print ("---------\n");
+ g_clear_object (&submodel);
+ }
+}
+
+static void
+on_manager_changed (GtkCloudProviderManager *manager)
+{
+ GList *providers;
+ GList *l;
+ gint provider_status;
+ gchar *status_string;
+ GIcon *icon;
+ gchar *icon_representation;
+ GtkWidget *menu;
+ gchar *path;
+
+ providers = gtk_cloud_provider_manager_get_providers (manager);
+ g_print ("Providers data\n");
+ g_print ("##############\n");
+ for (l = providers; l != NULL; l = l->next)
+ {
+ provider_status = gtk_cloud_provider_get_status (GTK_CLOUD_PROVIDER (l->data));
+ switch (provider_status)
+ {
+ case GTK_CLOUD_PROVIDER_STATUS_INVALID:
+ status_string = "invalid";
+ break;
+
+ case GTK_CLOUD_PROVIDER_STATUS_IDLE:
+ status_string = "idle";
+ break;
+
+ case GTK_CLOUD_PROVIDER_STATUS_SYNCING:
+ status_string = "syncing";
+ break;
+
+ case GTK_CLOUD_PROVIDER_STATUS_ERROR:
+ status_string = "error";
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ icon = gtk_cloud_provider_get_icon (l->data);
+ icon_representation = g_icon_to_string (icon);
+
+ g_print ("Name - %s, Status - %s, Path - %s, Icon - %s\n",
+ gtk_cloud_provider_get_name (GTK_CLOUD_PROVIDER (l->data)),
+ status_string,
+ gtk_cloud_provider_get_path (GTK_CLOUD_PROVIDER (l->data)),
+ icon_representation);
+
+ g_free (icon_representation);
+
+ menu = gtk_cloud_provider_get_menu (l->data);
+ g_print ("\nMenu\n");
+ print_menu (menu);
+ }
+ g_print ("\n");
+}
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ GtkCloudProviderManager *manager;
+
+ gtk_init (&argc, &argv);
+
+ manager = gtk_cloud_provider_manager_dup_singleton ();
+ g_signal_connect (manager, "changed", G_CALLBACK (on_manager_changed), NULL);
+ //gtk_cloud_provider_manager_update (manager);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/tests/testcloudproviderserver.c b/tests/testcloudproviderserver.c
new file mode 100644
index 0000000..8f88e23
--- /dev/null
+++ b/tests/testcloudproviderserver.c
@@ -0,0 +1,437 @@
+#include <gio/gio.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+
+#define TIMEOUT 2000
+
+typedef struct _CloudProviderClass CloudProviderClass;
+typedef struct _CloudProvider CloudProvider;
+
+struct _CloudProviderClass
+{
+ GObjectClass parent_class;
+};
+
+struct _CloudProvider
+{
+ GObject parent_instance;
+
+ gchar *name;
+ gint status;
+ GIcon *icon;
+ gchar *path;
+ GDBusProxy *manager_proxy;
+ guint timeout_handler;
+};
+
+
+static GType cloud_provider_get_type (void);
+G_DEFINE_TYPE (CloudProvider, cloud_provider, G_TYPE_OBJECT);
+
+static void
+cloud_provider_finalize (GObject *object)
+{
+ CloudProvider *self = (CloudProvider*)object;
+
+ g_free (self->name);
+ g_free (self->path);
+ g_clear_object (&self->icon);
+ g_clear_object (&self->manager_proxy);
+
+ G_OBJECT_CLASS (cloud_provider_parent_class)->finalize (object);
+}
+
+static void
+cloud_provider_init (CloudProvider *self)
+{
+ GFile *icon_file;
+ gchar *current_dir;
+ gchar *uri;
+
+ current_dir = g_get_current_dir ();
+
+ self->name = "MyCloud";
+ self->path = g_strdup (current_dir);
+ self->status = GTK_CLOUD_PROVIDER_STATUS_INVALID;
+ uri = g_build_filename (current_dir, "apple-red.png", NULL);
+ icon_file = g_file_new_for_uri (uri);
+ self->icon = g_file_icon_new (icon_file);
+
+ g_object_unref (icon_file);
+ g_free (uri);
+ g_free (current_dir);
+}
+
+static void
+cloud_provider_class_init (CloudProviderClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+
+ gobject_class->finalize = cloud_provider_finalize;
+}
+
+static void
+cloud_provider_set_status (CloudProvider *self,
+ gint status)
+{
+ /* Inform the manager that the provider changed */
+ self->status = status;
+ g_dbus_proxy_call (self->manager_proxy,
+ "CloudProviderChanged",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ NULL);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GDBusNodeInfo *introspection_data = NULL;
+
+/* Introspection data for the service we are exporting */
+static const gchar provider_xml[] =
+ "<node>"
+ " <interface name='org.gtk.CloudProvider'>"
+ " <method name='GetName'>"
+ " <arg type='s' name='name' direction='out'/>"
+ " </method>"
+ " <method name='GetStatus'>"
+ " <arg type='i' name='status' direction='out'/>"
+ " </method>"
+ " <method name='GetIcon'>"
+ " <arg type='v' name='icon' direction='out'/>"
+ " </method>"
+ " <method name='GetPath'>"
+ " <arg type='s' name='path' direction='out'/>"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+static const gchar manager_xml[] =
+ "<node>"
+ " <interface name='org.gtk.CloudProviderManager'>"
+ " <method name='CloudProviderChanged'>"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+static const gchar menu_markup[] =
+ "<interface>\n"
+ "<menu id='menu'>\n"
+ " <section>\n"
+ " <item>\n"
+ " <attribute name='label' translatable='yes'>MyCloud website</attribute>\n"
+ " <attribute name='action'>actions.website</attribute>\n"
+ " </item>\n"
+ " <item>\n"
+ " <attribute name='label' translatable='yes'>MyCloud Photos</attribute>\n"
+ " <attribute name='action'>actions.photos</attribute>\n"
+ " </item>\n"
+ " <item>\n"
+ " <attribute name='label' translatable='yes'>MyCloud Notes</attribute>\n"
+ " <attribute name='action'>actions.notes</attribute>\n"
+ " </item>\n"
+ " </section>\n"
+ " <section>\n"
+ " <item>\n"
+ " <attribute name='label' translatable='yes'>Allow Synchronization</attribute>\n"
+ " <attribute name='action'>actions.allow-sync</attribute>\n"
+ " </item>\n"
+ " <submenu>\n"
+ " <attribute name='label' translatable='yes'>Buy Storage</attribute>\n"
+ " <item>\n"
+ " <attribute name='label' translatable='yes'>5GB for 200CZK</attribute>\n"
+ " <attribute name='action'>actions.buy</attribute>\n"
+ " <attribute name='target'>5</attribute>\n"
+ " </item>\n"
+ " <item>\n"
+ " <attribute name='label' translatable='yes'>10GB for 500CZK</attribute>\n"
+ " <attribute name='action'>actions.buy</attribute>\n"
+ " <attribute name='target'>10</attribute>\n"
+ " </item>\n"
+ " <item>\n"
+ " <attribute name='label' translatable='yes'>30GB for 600CZK</attribute>\n"
+ " <attribute name='action'>actions.buy</attribute>\n"
+ " <attribute name='target'>30</attribute>\n"
+ " </item>\n"
+ " </submenu>\n"
+ " </section>\n"
+ "</menu>\n"
+ "</interface>\n";
+
+static void
+activate_action (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ g_print ("Action %s activated\n", g_action_get_name (G_ACTION (action)));
+}
+
+static void
+activate_toggle (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GVariant *old_state, *new_state;
+
+ old_state = g_action_get_state (G_ACTION (action));
+ new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state));
+
+ g_print ("Toggle action %s activated, state changes from %d to %d\n",
+ g_action_get_name (G_ACTION (action)),
+ g_variant_get_boolean (old_state),
+ g_variant_get_boolean (new_state));
+
+ g_simple_action_set_state (action, new_state);
+ g_variant_unref (old_state);
+}
+
+static void
+activate_radio (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GVariant *old_state, *new_state;
+
+ old_state = g_action_get_state (G_ACTION (action));
+ new_state = g_variant_new_string (g_variant_get_string (parameter, NULL));
+
+ g_print ("Radio action %s activated, state changes from %s to %s\n",
+ g_action_get_name (G_ACTION (action)),
+ g_variant_get_string (old_state, NULL),
+ g_variant_get_string (new_state, NULL));
+
+ g_simple_action_set_state (action, new_state);
+ g_variant_unref (old_state);
+}
+
+static GActionEntry actions[] = {
+ { "website", activate_action, NULL, NULL, NULL },
+ { "photos", activate_action, NULL, NULL, NULL },
+ { "notes", activate_action, NULL, NULL, NULL },
+ { "allow-sync", activate_toggle, NULL, "true", NULL },
+ { "buy", activate_radio, "s", NULL, NULL },
+};
+
+static GMenuModel *
+get_model (void)
+{
+ GError *error = NULL;
+ GtkBuilder *builder;
+ GMenuModel *menu;
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_string (builder, menu_markup, -1, &error);
+ g_assert_no_error (error);
+
+ menu = g_object_ref (gtk_builder_get_object (builder, "menu"));
+ g_object_unref (builder);
+
+ return menu;
+}
+
+static GActionGroup *
+get_action_group (void)
+{
+ GSimpleActionGroup *group;
+
+ group = g_simple_action_group_new ();
+
+ g_action_map_add_action_entries (G_ACTION_MAP (group),
+ actions,
+ G_N_ELEMENTS (actions), NULL);
+
+ return G_ACTION_GROUP (group);
+}
+
+static void
+export_menu (GDBusConnection *bus,
+ gchar *object_path)
+{
+ GMenuModel *model;
+ GActionGroup *action_group;
+ GError *error;
+
+ model = get_model ();
+ action_group = get_action_group ();
+
+ g_print ("Exporting menus on the bus...\n");
+ if (!g_dbus_connection_export_menu_model (bus, object_path, model, &error))
+ {
+ g_warning ("Menu export failed: %s", error->message);
+ exit (1);
+ }
+ g_print ("Exporting actions on the bus...\n");
+ if (!g_dbus_connection_export_action_group (bus, object_path, action_group, &error))
+ {
+ g_warning ("Action export failed: %s", error->message);
+ exit (1);
+ }
+}
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ CloudProvider *cloud_provider = user_data;
+
+ g_debug ("Handling dbus call in server\n");
+ if (g_strcmp0 (method_name, "GetName") == 0)
+ {
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(s)", cloud_provider->name));
+ }
+ else if (g_strcmp0 (method_name, "GetStatus") == 0)
+ {
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(i)", cloud_provider->status));
+ }
+ else if (g_strcmp0 (method_name, "GetIcon") == 0)
+ {
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(v)", g_icon_serialize (cloud_provider->icon)));
+ }
+ else if (g_strcmp0 (method_name, "GetPath") == 0)
+ {
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(s)", cloud_provider->path));
+ }
+}
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+ handle_method_call,
+};
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ CloudProvider *cloud_provider = user_data;
+ guint registration_id;
+
+ g_debug ("Registering cloud provider server 'MyCloud'\n");
+ registration_id = g_dbus_connection_register_object (connection,
+ "/org/gtk/CloudProviderServerExample",
+ introspection_data->interfaces[0],
+ &interface_vtable,
+ cloud_provider,
+ NULL, /* user_data_free_func */
+ NULL); /* GError** */
+ g_assert (registration_id > 0);
+ /* Export a menu for our own application */
+ export_menu (connection, "/org/gtk/CloudProviderServerExample");
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ exit (1);
+}
+
+static gboolean
+change_provider (gpointer user_data)
+{
+ CloudProvider *cloud_provider = (CloudProvider *)user_data;
+ GRand *rand;
+ gint new_status;
+
+ rand = g_rand_new ();
+ new_status = g_rand_int_range (rand,
+ GTK_CLOUD_PROVIDER_STATUS_IDLE,
+ GTK_CLOUD_PROVIDER_STATUS_ERROR + 1);
+
+ cloud_provider_set_status (cloud_provider, new_status);
+
+ return TRUE;
+}
+
+static void
+on_manager_proxy_created (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CloudProvider *cloud_provider = user_data;
+ GError *error = NULL;
+
+ cloud_provider->manager_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (error != NULL)
+ g_warning ("Error creating proxy for cloud provider manager %s", error->message);
+ else
+ g_debug ("Manager proxy created for 'MyCloud'\n");
+
+ cloud_provider->timeout_handler = g_timeout_add (TIMEOUT,
+ (GSourceFunc) change_provider,
+ cloud_provider);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GMainLoop *loop;
+ CloudProvider *cloud_provider;
+ guint owner_id;
+ GDBusNodeInfo *proxy_info;
+ GDBusInterfaceInfo *interface_info;
+ GError *error = NULL;
+
+ /* Export the interface we listen to, so clients can request properties of
+ * the cloud provider such as name, status or icon */
+ introspection_data = g_dbus_node_info_new_for_xml (provider_xml, NULL);
+ g_assert (introspection_data != NULL);
+
+ cloud_provider = g_object_new (cloud_provider_get_type (), NULL);
+
+ owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ "org.gtk.CloudProviderServerExample",
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_bus_acquired,
+ on_name_acquired,
+ on_name_lost,
+ cloud_provider,
+ NULL);
+
+ /* Create CloudProviderManager proxy for exporting cloud provider changes */
+ proxy_info = g_dbus_node_info_new_for_xml (manager_xml, &error);
+ interface_info = g_dbus_node_info_lookup_interface (proxy_info, "org.gtk.CloudProviderManager");
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ interface_info,
+ "org.gtk.CloudProviderManager",
+ "/org/gtk/CloudProviderManager",
+ "org.gtk.CloudProviderManager",
+ NULL,
+ on_manager_proxy_created,
+ cloud_provider);
+
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+
+ g_bus_unown_name (owner_id);
+
+ g_dbus_node_info_unref (introspection_data);
+
+ g_object_unref (cloud_provider);
+
+ return 0;
+}
+
diff --git a/tests/testpopover.c b/tests/testpopover.c
index 306e7c9..e132521 100644
--- a/tests/testpopover.c
+++ b/tests/testpopover.c
@@ -145,6 +145,7 @@ main (int argc, char *argv[])
gtk_grid_attach (GTK_GRID (grid), label , 1, 5, 1, 1);
gtk_grid_attach (GTK_GRID (grid), combo, 2, 5, 1, 1);
+ gtk_cloud_provider_manager_dup_singleton ();
gtk_widget_show_all (win);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]