[gnome-panel] status-notifier: get properties from proxy
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-panel] status-notifier: get properties from proxy
- Date: Thu, 3 Nov 2016 16:44:46 +0000 (UTC)
commit c15053e1dda73dfca6acc7b66c4c16fb8277096e
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Thu Nov 3 18:40:27 2016 +0200
status-notifier: get properties from proxy
applets/status-notifier/sn-applet.c | 45 +++-
applets/status-notifier/sn-host-v0.c | 9 +-
applets/status-notifier/sn-item-v0.c | 664 +++++++++++++++++++++++++++++++++-
applets/status-notifier/sn-item.c | 51 +++
applets/status-notifier/sn-item.h | 21 +-
5 files changed, 783 insertions(+), 7 deletions(-)
---
diff --git a/applets/status-notifier/sn-applet.c b/applets/status-notifier/sn-applet.c
index 65bd141..427ee2e 100644
--- a/applets/status-notifier/sn-applet.c
+++ b/applets/status-notifier/sn-applet.c
@@ -33,6 +33,47 @@ struct _SnApplet
G_DEFINE_TYPE (SnApplet, sn_applet, GP_TYPE_APPLET)
+static gint
+compare_items (gconstpointer a,
+ gconstpointer b)
+{
+ SnItem *item1;
+ SnItem *item2;
+ SnItemCategory c1;
+ SnItemCategory c2;
+ const gchar *id1;
+ const gchar *id2;
+
+ item1 = (SnItem *) a;
+ item2 = (SnItem *) b;
+
+ c1 = sn_item_get_category (item1);
+ c2 = sn_item_get_category (item2);
+
+ if (c1 < c2)
+ return -1;
+ else if (c1 > c2)
+ return 1;
+
+ id1 = sn_item_get_id (item1);
+ id2 = sn_item_get_id (item2);
+
+ return g_strcmp0 (id1, id2);
+}
+
+static void
+reorder_items (GtkWidget *widget,
+ gpointer user_data)
+{
+ SnApplet *sn;
+ gint position;
+
+ sn = SN_APPLET (user_data);
+
+ position = g_slist_index (sn->items, widget);
+ gtk_box_reorder_child (GTK_BOX (sn->box), widget, position);
+}
+
static void
item_added_cb (SnHost *host,
SnItem *item,
@@ -40,7 +81,9 @@ item_added_cb (SnHost *host,
{
sn->items = g_slist_prepend (sn->items, item);
gtk_box_pack_start (GTK_BOX (sn->box), GTK_WIDGET (item), FALSE, FALSE, 0);
- gtk_widget_show (GTK_WIDGET (item));
+
+ sn->items = g_slist_sort (sn->items, compare_items);
+ gtk_container_foreach (GTK_CONTAINER (sn->box), reorder_items, sn);
}
static void
diff --git a/applets/status-notifier/sn-host-v0.c b/applets/status-notifier/sn-host-v0.c
index 3cd6af9..cff364f 100644
--- a/applets/status-notifier/sn-host-v0.c
+++ b/applets/status-notifier/sn-host-v0.c
@@ -88,6 +88,13 @@ get_bus_name_and_object_path (const gchar *service,
}
static void
+ready_cb (SnItem *item,
+ SnHostV0 *v0)
+{
+ sn_host_emit_item_added (SN_HOST (v0), item);
+}
+
+static void
add_registered_item (SnHostV0 *v0,
const gchar *service)
{
@@ -104,7 +111,7 @@ add_registered_item (SnHostV0 *v0,
g_object_ref_sink (item);
v0->items = g_slist_prepend (v0->items, item);
- sn_host_emit_item_added (SN_HOST (v0), item);
+ g_signal_connect (item, "ready", G_CALLBACK (ready_cb), v0);
g_free (bus_name);
g_free (object_path);
diff --git a/applets/status-notifier/sn-item-v0.c b/applets/status-notifier/sn-item-v0.c
index e88df0c..83955df 100644
--- a/applets/status-notifier/sn-item-v0.c
+++ b/applets/status-notifier/sn-item-v0.c
@@ -20,17 +20,608 @@
#include "sn-item-v0.h"
#include "sn-item-v0-gen.h"
+#define SN_ITEM_INTERFACE "org.kde.StatusNotifierItem"
+
+typedef struct
+{
+ gchar *icon_name;
+ GdkPixbuf **icon_pixmap;
+ gchar *title;
+ gchar *text;
+} SnTooltip;
+
struct _SnItemV0
{
- SnItem parent;
+ SnItem parent;
+
+ GCancellable *cancellable;
+ SnItemV0Gen *proxy;
+
+ gchar *id;
+ gchar *category;
+ gchar *status;
- GCancellable *cancellable;
- SnItemV0Gen *proxy;
+ gchar *title;
+ gint32 window_id;
+ gchar *icon_name;
+ GdkPixbuf **icon_pixmap;
+ gchar *overlay_icon_name;
+ GdkPixbuf **overlay_icon_pixmap;
+ gchar *attention_icon_name;
+ GdkPixbuf **attention_icon_pixmap;
+ gchar *attention_movie_name;
+ SnTooltip *tooltip;
+ gchar *icon_theme_path;
+ gchar *menu;
+ gboolean item_is_menu;
+
+ guint update_id;
};
G_DEFINE_TYPE (SnItemV0, sn_item_v0, SN_TYPE_ITEM)
static void
+update (SnItemV0 *v0)
+{
+ gboolean visible;
+
+ visible = g_strcmp0 (v0->status, "Passive") != 0;
+ gtk_widget_set_visible (GTK_WIDGET (v0), visible);
+}
+
+static gboolean
+update_cb (gpointer user_data)
+{
+ SnItemV0 *v0;
+
+ v0 = SN_ITEM_V0 (user_data);
+
+ v0->update_id = 0;
+ update (v0);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+queue_update (SnItemV0 *v0)
+{
+ if (v0->update_id != 0)
+ return;
+
+ v0->update_id = g_timeout_add (10, update_cb, v0);
+ g_source_set_name_by_id (v0->update_id, "[status-notifier] update_cb");
+}
+
+static GdkPixbuf **
+icon_pixmap_new (GVariant *variant)
+{
+ GVariantIter iter;
+ gsize n_pixbufs;
+ GdkPixbuf **pixbufs;
+ guint i;
+ gint width;
+ gint height;
+ GVariant *value;
+
+ if (variant == NULL)
+ return NULL;
+
+ n_pixbufs = g_variant_iter_init (&iter, variant);
+ if (n_pixbufs == 0)
+ return NULL;
+
+ pixbufs = g_new0 (GdkPixbuf *, n_pixbufs + 1);
+ i = 0;
+
+ while (g_variant_iter_next (&iter, "(ii@ay)", &width, &height, &value))
+ {
+ GBytes *bytes;
+ gint rowstride;
+
+ bytes = g_variant_get_data_as_bytes (value);
+ rowstride = g_bytes_get_size (bytes) / height;
+
+ pixbufs[i++] = gdk_pixbuf_new_from_bytes (bytes, GDK_COLORSPACE_RGB,
+ TRUE, 8, width, height,
+ rowstride);
+
+ g_bytes_unref (bytes);
+ g_variant_unref (value);
+ }
+
+ pixbufs[i] = NULL;
+
+ return pixbufs;
+}
+
+static void
+icon_pixmap_free (GdkPixbuf **data)
+{
+ gint i;
+
+ if (data == NULL)
+ return;
+
+ for (i = 0; data[i] != NULL; i++)
+ g_object_unref (data[i]);
+
+ g_free (data);
+}
+
+static SnTooltip *
+sn_tooltip_new (GVariant *variant)
+{
+ const gchar *icon_name;
+ GVariant *icon_pixmap;
+ const gchar *title;
+ const gchar *text;
+ SnTooltip *tooltip;
+
+ if (variant == NULL)
+ return NULL;
+
+ g_variant_get (variant, "(&s@a(iiay)&s&s)",
+ &icon_name, &icon_pixmap,
+ &title, &text);
+
+ tooltip = g_new0 (SnTooltip, 1);
+
+ tooltip->icon_name = g_strdup (icon_name);
+ tooltip->icon_pixmap = icon_pixmap_new (icon_pixmap);
+ tooltip->title = g_strdup (title);
+ tooltip->text = g_strdup (text);
+
+ g_variant_unref (icon_pixmap);
+ return tooltip;
+}
+
+static void
+sn_tooltip_free (SnTooltip *tooltip)
+{
+ if (tooltip == NULL)
+ return;
+
+ g_free (tooltip->icon_name);
+ icon_pixmap_free (tooltip->icon_pixmap);
+ g_free (tooltip->title);
+ g_free (tooltip->text);
+
+ g_free (tooltip);
+}
+
+static GVariant *
+get_property (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data,
+ gboolean *cancelled)
+{
+ GVariant *variant;
+ GError *error;
+ GVariant *property;
+
+ error = NULL;
+ variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res, &error);
+
+ *cancelled = FALSE;
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ *cancelled = TRUE;
+ g_error_free (error);
+ return NULL;
+ }
+
+ if (error)
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ g_variant_get (variant, "(v)", &property);
+ g_variant_unref (variant);
+
+ return property;
+}
+
+static void
+update_property (SnItemV0 *v0,
+ const gchar *property,
+ GAsyncReadyCallback callback)
+{
+ GDBusProxy *proxy;
+ SnItem *item;
+
+ proxy = G_DBUS_PROXY (v0->proxy);
+ item = SN_ITEM (v0);
+
+ g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
+ sn_item_get_bus_name (item),
+ sn_item_get_object_path (item),
+ "org.freedesktop.DBus.Properties", "Get",
+ g_variant_new ("(ss)", SN_ITEM_INTERFACE, property),
+ G_VARIANT_TYPE ("(v)"),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ v0->cancellable, callback, v0);
+}
+
+static void
+update_title (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SnItemV0 *v0;
+ GVariant *variant;
+ gboolean cancelled;
+
+ variant = get_property (source_object, res, user_data, &cancelled);
+ if (cancelled)
+ return;
+
+ v0 = SN_ITEM_V0 (user_data);
+
+ g_clear_pointer (&v0->title, g_free);
+ v0->title = g_variant_dup_string (variant, NULL);
+ g_clear_pointer (&variant, g_variant_unref);
+
+ queue_update (v0);
+}
+
+static void
+new_title_cb (SnItemV0 *v0)
+{
+ update_property (v0, "Title", update_title);
+}
+
+static void
+update_icon_name (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SnItemV0 *v0;
+ GVariant *variant;
+ gboolean cancelled;
+
+ variant = get_property (source_object, res, user_data, &cancelled);
+ if (cancelled)
+ return;
+
+ v0 = SN_ITEM_V0 (user_data);
+
+ g_clear_pointer (&v0->icon_name, g_free);
+ v0->icon_name = g_variant_dup_string (variant, NULL);
+ g_clear_pointer (&variant, g_variant_unref);
+
+ queue_update (v0);
+}
+
+static void
+update_icon_pixmap (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SnItemV0 *v0;
+ GVariant *variant;
+ gboolean cancelled;
+
+ variant = get_property (source_object, res, user_data, &cancelled);
+ if (cancelled)
+ return;
+
+ v0 = SN_ITEM_V0 (user_data);
+
+ g_clear_pointer (&v0->icon_pixmap, icon_pixmap_free);
+ v0->icon_pixmap = icon_pixmap_new (variant);
+ g_clear_pointer (&variant, g_variant_unref);
+
+ queue_update (v0);
+}
+
+static void
+new_icon_cb (SnItemV0 *v0)
+{
+ update_property (v0, "IconName", update_icon_name);
+ update_property (v0, "IconPixmap", update_icon_pixmap);
+}
+
+static void
+update_overlay_icon_name (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SnItemV0 *v0;
+ GVariant *variant;
+ gboolean cancelled;
+
+ variant = get_property (source_object, res, user_data, &cancelled);
+ if (cancelled)
+ return;
+
+ v0 = SN_ITEM_V0 (user_data);
+
+ g_clear_pointer (&v0->overlay_icon_name, g_free);
+ v0->overlay_icon_name = g_variant_dup_string (variant, NULL);
+ g_clear_pointer (&variant, g_variant_unref);
+
+ queue_update (v0);
+}
+
+static void
+update_overlay_icon_pixmap (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SnItemV0 *v0;
+ GVariant *variant;
+ gboolean cancelled;
+
+ variant = get_property (source_object, res, user_data, &cancelled);
+ if (cancelled)
+ return;
+
+ v0 = SN_ITEM_V0 (user_data);
+
+ g_clear_pointer (&v0->overlay_icon_pixmap, icon_pixmap_free);
+ v0->overlay_icon_pixmap = icon_pixmap_new (variant);
+ g_clear_pointer (&variant, g_variant_unref);
+
+ queue_update (v0);
+}
+
+static void
+new_overlay_icon_cb (SnItemV0 *v0)
+{
+ update_property (v0, "OverlayIconName", update_overlay_icon_name);
+ update_property (v0, "OverlayIconPixmap", update_overlay_icon_pixmap);
+}
+
+static void
+update_attention_icon_name (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SnItemV0 *v0;
+ GVariant *variant;
+ gboolean cancelled;
+
+ variant = get_property (source_object, res, user_data, &cancelled);
+ if (cancelled)
+ return;
+
+ v0 = SN_ITEM_V0 (user_data);
+
+ g_clear_pointer (&v0->attention_icon_name, g_free);
+ v0->attention_icon_name = g_variant_dup_string (variant, NULL);
+ g_clear_pointer (&variant, g_variant_unref);
+
+ queue_update (v0);
+}
+
+static void
+update_attention_icon_pixmap (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SnItemV0 *v0;
+ GVariant *variant;
+ gboolean cancelled;
+
+ variant = get_property (source_object, res, user_data, &cancelled);
+ if (cancelled)
+ return;
+
+ v0 = SN_ITEM_V0 (user_data);
+
+ g_clear_pointer (&v0->attention_icon_pixmap, icon_pixmap_free);
+ v0->attention_icon_pixmap = icon_pixmap_new (variant);
+ g_clear_pointer (&variant, g_variant_unref);
+
+ queue_update (v0);
+}
+
+static void
+new_attention_icon_cb (SnItemV0 *v0)
+{
+ update_property (v0, "AttentionIconName", update_attention_icon_name);
+ update_property (v0, "AttentionIconPixmap", update_attention_icon_pixmap);
+}
+
+static void
+update_tooltip (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SnItemV0 *v0;
+ GVariant *variant;
+ gboolean cancelled;
+
+ variant = get_property (source_object, res, user_data, &cancelled);
+ if (cancelled)
+ return;
+
+ v0 = SN_ITEM_V0 (user_data);
+
+ g_clear_pointer (&v0->tooltip, sn_tooltip_free);
+ v0->tooltip = sn_tooltip_new (variant);
+ g_clear_pointer (&variant, g_variant_unref);
+
+ queue_update (v0);
+}
+
+static void
+new_tooltip_cb (SnItemV0 *v0)
+{
+ update_property (v0, "ToolTip", update_tooltip);
+}
+
+static void
+new_status_cb (SnItemV0 *v0,
+ GVariant *parameters)
+{
+ GVariant *variant;
+
+ variant = g_variant_get_child_value (parameters, 0);
+
+ g_free (v0->status);
+ v0->status = g_variant_dup_string (variant, NULL);
+ g_variant_unref (variant);
+
+ queue_update (v0);
+}
+
+static void
+new_icon_theme_path_cb (SnItemV0 *v0,
+ GVariant *parameters)
+{
+ GVariant *variant;
+
+ variant = g_variant_get_child_value (parameters, 0);
+
+ g_free (v0->icon_theme_path);
+ v0->icon_theme_path = g_variant_dup_string (variant, NULL);
+ g_variant_unref (variant);
+
+ queue_update (v0);
+}
+
+static void
+g_properties_changed_cb (GDBusProxy *proxy,
+ GVariant *changed_properties,
+ GStrv invalidated_properties,
+ SnItemV0 *v0)
+{
+ gchar *debug;
+
+ debug = g_variant_print (changed_properties, FALSE);
+ g_debug ("g_properties_changed_cb: %s", debug);
+ g_free (debug);
+}
+
+static void
+g_signal_cb (GDBusProxy *proxy,
+ gchar *sender_name,
+ gchar *signal_name,
+ GVariant *parameters,
+ SnItemV0 *v0)
+{
+ if (g_strcmp0 (signal_name, "NewTitle") == 0)
+ new_title_cb (v0);
+ else if (g_strcmp0 (signal_name, "NewIcon") == 0)
+ new_icon_cb (v0);
+ else if (g_strcmp0 (signal_name, "NewOverlayIcon") == 0)
+ new_overlay_icon_cb (v0);
+ else if (g_strcmp0 (signal_name, "NewAttentionIcon") == 0)
+ new_attention_icon_cb (v0);
+ else if (g_strcmp0 (signal_name, "NewToolTip") == 0)
+ new_tooltip_cb (v0);
+ else if (g_strcmp0 (signal_name, "NewStatus") == 0)
+ new_status_cb (v0, parameters);
+ else if (g_strcmp0 (signal_name, "NewIconThemePath") == 0)
+ new_icon_theme_path_cb (v0, parameters);
+ else
+ g_assert_not_reached ();
+}
+
+static void
+get_all_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SnItemV0 *v0;
+ GVariant *properties;
+ GError *error;
+ GVariantIter *iter;
+ gchar *key;
+ GVariant *value;
+
+ error = NULL;
+ properties = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
+ res, &error);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ {
+ g_error_free (error);
+ return;
+ }
+
+ v0 = SN_ITEM_V0 (user_data);
+
+ if (error)
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ g_variant_get (properties, "(a{sv})", &iter);
+ while (g_variant_iter_next (iter, "{sv}", &key, &value))
+ {
+ if (g_strcmp0 (key, "Category") == 0)
+ v0->category = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "Id") == 0)
+ v0->id = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "Title") == 0)
+ v0->title = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "Status") == 0)
+ v0->status = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "WindowId") == 0)
+ v0->window_id = g_variant_get_int32 (value);
+ else if (g_strcmp0 (key, "IconName") == 0)
+ v0->icon_name = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "IconPixmap") == 0)
+ v0->icon_pixmap = icon_pixmap_new (value);
+ else if (g_strcmp0 (key, "OverlayIconName") == 0)
+ v0->overlay_icon_name = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "OverlayIconPixmap") == 0)
+ v0->overlay_icon_pixmap = icon_pixmap_new (value);
+ else if (g_strcmp0 (key, "AttentionIconName") == 0)
+ v0->attention_icon_name = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "AttentionIconPixmap") == 0)
+ v0->attention_icon_pixmap = icon_pixmap_new (value);
+ else if (g_strcmp0 (key, "AttentionMovieName") == 0)
+ v0->attention_movie_name = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "ToolTip") == 0)
+ v0->tooltip = sn_tooltip_new (value);
+ else if (g_strcmp0 (key, "IconThemePath") == 0)
+ v0->icon_theme_path = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "Menu") == 0)
+ v0->menu = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (key, "ItemIsMenu") == 0)
+ v0->item_is_menu = g_variant_get_boolean (value);
+ else
+ g_assert_not_reached ();
+ }
+
+ g_variant_iter_free (iter);
+ g_variant_unref (properties);
+
+ if (v0->id == NULL || v0->category == NULL || v0->status == NULL)
+ {
+ SnItem *item;
+ const gchar *bus_name;
+ const gchar *object_path;
+
+ item = SN_ITEM (v0);
+ bus_name = sn_item_get_bus_name (item);
+ object_path = sn_item_get_object_path (item);
+
+ g_warning ("Invalid Status Notifier Item (%s, %s)",
+ bus_name, object_path);
+
+ return;
+ }
+
+ g_signal_connect (v0->proxy, "g-properties-changed",
+ G_CALLBACK (g_properties_changed_cb), v0);
+
+ g_signal_connect (v0->proxy, "g-signal",
+ G_CALLBACK (g_signal_cb), v0);
+
+ update (v0);
+ sn_item_emit_ready (SN_ITEM (v0));
+}
+
+static void
proxy_ready_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
@@ -57,6 +648,15 @@ proxy_ready_cb (GObject *source_object,
g_error_free (error);
return;
}
+
+ g_dbus_connection_call (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy)),
+ sn_item_get_bus_name (SN_ITEM (v0)),
+ sn_item_get_object_path (SN_ITEM (v0)),
+ "org.freedesktop.DBus.Properties", "GetAll",
+ g_variant_new ("(s)", SN_ITEM_INTERFACE),
+ G_VARIANT_TYPE ("(a{sv})"),
+ G_DBUS_CALL_FLAGS_NONE, -1,
+ v0->cancellable, get_all_cb, v0);
}
static void
@@ -90,18 +690,76 @@ sn_item_v0_dispose (GObject *object)
g_clear_object (&v0->cancellable);
g_clear_object (&v0->proxy);
+ if (v0->update_id != 0)
+ {
+ g_source_remove (v0->update_id);
+ v0->update_id = 0;
+ }
+
G_OBJECT_CLASS (sn_item_v0_parent_class)->dispose (object);
}
static void
+sn_item_v0_finalize (GObject *object)
+{
+ SnItemV0 *v0;
+
+ v0 = SN_ITEM_V0 (object);
+
+ g_clear_pointer (&v0->id, g_free);
+ g_clear_pointer (&v0->category, g_free);
+ g_clear_pointer (&v0->status, g_free);
+
+ g_clear_pointer (&v0->title, g_free);
+ g_clear_pointer (&v0->icon_name, g_free);
+ g_clear_pointer (&v0->icon_pixmap, icon_pixmap_free);
+ g_clear_pointer (&v0->overlay_icon_name, g_free);
+ g_clear_pointer (&v0->overlay_icon_pixmap, icon_pixmap_free);
+ g_clear_pointer (&v0->attention_icon_name, g_free);
+ g_clear_pointer (&v0->attention_icon_pixmap, icon_pixmap_free);
+ g_clear_pointer (&v0->attention_movie_name, g_free);
+ g_clear_pointer (&v0->tooltip, sn_tooltip_free);
+ g_clear_pointer (&v0->icon_theme_path, g_free);
+ g_clear_pointer (&v0->menu, g_free);
+
+ G_OBJECT_CLASS (sn_item_v0_parent_class)->finalize (object);
+}
+
+static const gchar *
+sn_item_v0_get_id (SnItem *item)
+{
+ SnItemV0 *v0;
+
+ v0 = SN_ITEM_V0 (item);
+
+ return v0->id;
+}
+
+static const gchar *
+sn_item_v0_get_category (SnItem *item)
+{
+ SnItemV0 *v0;
+
+ v0 = SN_ITEM_V0 (item);
+
+ return v0->category;
+}
+
+static void
sn_item_v0_class_init (SnItemV0Class *v0_class)
{
GObjectClass *object_class;
+ SnItemClass *item_class;
object_class = G_OBJECT_CLASS (v0_class);
+ item_class = SN_ITEM_CLASS (v0_class);
object_class->constructed = sn_item_v0_constructed;
object_class->dispose = sn_item_v0_dispose;
+ object_class->finalize = sn_item_v0_finalize;
+
+ item_class->get_id = sn_item_v0_get_id;
+ item_class->get_category = sn_item_v0_get_category;
}
static void
diff --git a/applets/status-notifier/sn-item.c b/applets/status-notifier/sn-item.c
index 0512793..41b0a84 100644
--- a/applets/status-notifier/sn-item.c
+++ b/applets/status-notifier/sn-item.c
@@ -37,6 +37,15 @@ enum
static GParamSpec *properties[LAST_PROP] = { NULL };
+enum
+{
+ SIGNAL_READY,
+
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SnItem, sn_item, GTK_TYPE_BUTTON)
static void
@@ -127,6 +136,15 @@ install_properties (GObjectClass *object_class)
}
static void
+install_signals (SnItemClass *item_class)
+{
+ signals[SIGNAL_READY] =
+ g_signal_new ("ready", G_TYPE_FROM_CLASS (item_class),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+}
+
+static void
sn_item_class_init (SnItemClass *item_class)
{
GObjectClass *object_class;
@@ -138,6 +156,7 @@ sn_item_class_init (SnItemClass *item_class)
object_class->set_property = sn_item_set_property;
install_properties (object_class);
+ install_signals (item_class);
}
static void
@@ -146,6 +165,32 @@ sn_item_init (SnItem *item)
}
const gchar *
+sn_item_get_id (SnItem *item)
+{
+ return SN_ITEM_GET_CLASS (item)->get_id (item);
+}
+
+SnItemCategory
+sn_item_get_category (SnItem *item)
+{
+ const gchar *string;
+ SnItemCategory category;
+
+ string = SN_ITEM_GET_CLASS (item)->get_category (item);
+
+ if (g_strcmp0 (string, "Hardware") == 0)
+ category = SN_ITEM_CATEGORY_HARDWARE;
+ else if (g_strcmp0 (string, "SystemServices") == 0)
+ category = SN_ITEM_CATEGORY_SYSTEM_SERVICES;
+ else if (g_strcmp0 (string, "Communications") == 0)
+ category = SN_ITEM_CATEGORY_COMMUNICATIONS;
+ else
+ category = SN_ITEM_CATEGORY_APPLICATION_STATUS;
+
+ return category;
+}
+
+const gchar *
sn_item_get_bus_name (SnItem *item)
{
SnItemPrivate *priv;
@@ -164,3 +209,9 @@ sn_item_get_object_path (SnItem *item)
return priv->object_path;
}
+
+void
+sn_item_emit_ready (SnItem *item)
+{
+ g_signal_emit (item, signals[SIGNAL_READY], 0);
+}
diff --git a/applets/status-notifier/sn-item.h b/applets/status-notifier/sn-item.h
index 5985bec..b40f8e1 100644
--- a/applets/status-notifier/sn-item.h
+++ b/applets/status-notifier/sn-item.h
@@ -25,13 +25,30 @@ G_BEGIN_DECLS
#define SN_TYPE_ITEM sn_item_get_type ()
G_DECLARE_DERIVABLE_TYPE (SnItem, sn_item, SN, ITEM, GtkButton)
+typedef enum
+{
+ SN_ITEM_CATEGORY_APPLICATION_STATUS,
+ SN_ITEM_CATEGORY_COMMUNICATIONS,
+ SN_ITEM_CATEGORY_SYSTEM_SERVICES,
+ SN_ITEM_CATEGORY_HARDWARE
+} SnItemCategory;
+
struct _SnItemClass
{
GtkButtonClass parent_class;
+
+ const gchar * (* get_id) (SnItem *item);
+ const gchar * (* get_category) (SnItem *item);
};
-const gchar *sn_item_get_bus_name (SnItem *item);
-const gchar *sn_item_get_object_path (SnItem *item);
+const gchar *sn_item_get_id (SnItem *item);
+
+SnItemCategory sn_item_get_category (SnItem *item);
+
+const gchar *sn_item_get_bus_name (SnItem *item);
+const gchar *sn_item_get_object_path (SnItem *item);
+
+void sn_item_emit_ready (SnItem *item);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]