[gnome-panel] status-notifier: add SnDBusMenuItem
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-panel] status-notifier: add SnDBusMenuItem
- Date: Fri, 4 Nov 2016 20:13:11 +0000 (UTC)
commit b1df78adba638695b5c688cc4054bfc0008ea370
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Fri Nov 4 15:32:17 2016 +0200
status-notifier: add SnDBusMenuItem
applets/status-notifier/Makefile.am | 2 +
applets/status-notifier/sn-dbus-menu-item.c | 466 +++++++++++++++++++++++++++
applets/status-notifier/sn-dbus-menu-item.h | 62 ++++
3 files changed, 530 insertions(+), 0 deletions(-)
---
diff --git a/applets/status-notifier/Makefile.am b/applets/status-notifier/Makefile.am
index 4ce5ddc..303f921 100644
--- a/applets/status-notifier/Makefile.am
+++ b/applets/status-notifier/Makefile.am
@@ -21,6 +21,8 @@ status_notifier_la_CFLAGS = \
status_notifier_la_SOURCES = \
sn-applet.c \
sn-applet.h \
+ sn-dbus-menu-item.c \
+ sn-dbus-menu-item.h \
sn-host.c \
sn-host.h \
sn-host-v0.c \
diff --git a/applets/status-notifier/sn-dbus-menu-item.c b/applets/status-notifier/sn-dbus-menu-item.c
new file mode 100644
index 0000000..455bb35
--- /dev/null
+++ b/applets/status-notifier/sn-dbus-menu-item.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "sn-dbus-menu-item.h"
+#include "sn-image-menu-item.h"
+
+static GdkPixbuf *
+pxibuf_new (GVariant *variant)
+{
+ gsize length;
+ const guchar *data;
+ GInputStream *stream;
+ GdkPixbuf *pixbuf;
+ GError *error;
+
+ data = g_variant_get_fixed_array (variant, &length, sizeof (guchar));
+
+ if (length == 0)
+ return NULL;
+
+ stream = g_memory_input_stream_new_from_data (data, length, NULL);
+
+ if (stream == NULL)
+ return NULL;
+
+ error = NULL;
+ pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error);
+ g_object_unref (stream);
+
+ if (error != NULL)
+ {
+ g_warning ("Unable to build GdkPixbuf from icon data: %s", error->message);
+ g_error_free (error);
+ }
+
+ return pixbuf;
+}
+
+static SnShortcut *
+sn_shortcut_new (guint key,
+ GdkModifierType mask)
+{
+ SnShortcut *shortcut;
+
+ shortcut = g_new0 (SnShortcut, 1);
+
+ shortcut->key = key;
+ shortcut->mask = mask;
+
+ return shortcut;
+}
+
+static SnShortcut **
+sn_shortcuts_new (GVariant *variant)
+{
+ GPtrArray *array;
+ GVariantIter shortcuts;
+ GVariantIter *shortcut;
+
+ if (variant == NULL || g_variant_iter_init (&shortcuts, variant) == 0)
+ return NULL;
+
+ array = g_ptr_array_new ();
+ while (g_variant_iter_next (&shortcuts, "as", &shortcut))
+ {
+ guint key;
+ GdkModifierType mask;
+ const gchar *string;
+
+ key = 0;
+ mask = 0;
+
+ while (g_variant_iter_next (shortcut, "&s", &string))
+ {
+ if (g_strcmp0 (string, "Control") == 0)
+ mask |= GDK_CONTROL_MASK;
+ else if (g_strcmp0 (string, "Alt") == 0)
+ mask |= GDK_MOD1_MASK;
+ else if (g_strcmp0 (string, "Shift") == 0)
+ mask |= GDK_SHIFT_MASK;
+ else if (g_strcmp0 (string, "Super") == 0)
+ mask |= GDK_SUPER_MASK;
+ else
+ gtk_accelerator_parse (string, &key, NULL);
+ }
+
+ g_ptr_array_add (array,sn_shortcut_new (key, mask));
+ g_variant_iter_free (shortcut);
+ }
+
+ g_ptr_array_add (array, NULL);
+ return (SnShortcut **) g_ptr_array_free (array, FALSE);
+}
+
+static void
+sn_shortcuts_free (SnShortcut **shortcuts)
+{
+ guint i;
+
+ if (shortcuts == NULL)
+ return;
+
+ for (i = 0; shortcuts[i] != NULL; i++)
+ g_free (shortcuts[i]);
+
+ g_free (shortcuts);
+}
+
+SnDBusMenuItem *
+sn_dbus_menu_item_new (GVariant *props)
+{
+ SnDBusMenuItem *item;
+ GVariantIter iter;
+ const gchar *prop;
+ GVariant *value;
+
+ item = g_new0 (SnDBusMenuItem, 1);
+
+ item->enabled = TRUE;
+ item->toggle_state = -1;
+ item->visible = TRUE;
+
+ g_variant_iter_init (&iter, props);
+ while (g_variant_iter_next (&iter, "{&sv}", &prop, &value))
+ {
+ if (g_strcmp0 (prop, "accessible-desc") == 0)
+ item->accessible_desc = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (prop, "children-display") == 0)
+ item->children_display = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (prop, "disposition") == 0)
+ item->disposition = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (prop, "enabled") == 0)
+ item->enabled = g_variant_get_boolean (value);
+ else if (g_strcmp0 (prop, "icon-name") == 0)
+ item->icon_name = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (prop, "icon-data") == 0)
+ item->icon_data = pxibuf_new (value);
+ else if (g_strcmp0 (prop, "label") == 0)
+ item->label = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (prop, "shortcut") == 0)
+ item->shortcuts = sn_shortcuts_new (value);
+ else if (g_strcmp0 (prop, "toggle-type") == 0)
+ item->toggle_type = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (prop, "toggle-state") == 0)
+ item->toggle_state = g_variant_get_int32 (value);
+ else if (g_strcmp0 (prop, "type") == 0)
+ item->type = g_variant_dup_string (value, NULL);
+ else if (g_strcmp0 (prop, "visible") == 0)
+ item->visible = g_variant_get_boolean (value);
+ else
+ g_debug ("unknown property '%s'", prop);
+
+ g_variant_unref (value);
+ }
+
+ if (g_strcmp0 (item->type, "separator") == 0)
+ {
+ item->item = gtk_separator_menu_item_new ();
+ }
+ else
+ {
+ if (g_strcmp0 (item->toggle_type, "checkmark") == 0)
+ {
+ item->item = gtk_check_menu_item_new ();
+ }
+ else if (g_strcmp0 (item->toggle_type, "radio") == 0)
+ {
+ item->item = gtk_radio_menu_item_new (NULL);
+ }
+ else
+ {
+ SnImageMenuItem *image_item;
+
+ item->item = sn_image_menu_item_new ();
+ image_item = SN_IMAGE_MENU_ITEM (item->item);
+
+ if (item->icon_name)
+ {
+ sn_image_menu_item_set_image_from_icon_name (image_item,
+ item->icon_name);
+ }
+ else if (item->icon_data)
+ {
+ sn_image_menu_item_set_image_from_icon_pixbuf (image_item,
+ item->icon_data);
+ }
+ }
+
+ if (g_strcmp0 (item->children_display, "submenu") == 0)
+ {
+ GtkWidget *submenu;
+
+ submenu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item->item), submenu);
+
+ item->submenu = GTK_MENU (submenu);
+ g_object_ref_sink (item->submenu);
+ }
+
+ gtk_menu_item_set_label (GTK_MENU_ITEM (item->item), item->label);
+
+ if (item->shortcuts)
+ {
+ guint i;
+
+ for (i = 0; item->shortcuts[i] != NULL; i++)
+ {
+ }
+ }
+
+ if (item->toggle_state != -1 && GTK_IS_CHECK_MENU_ITEM (item->item))
+ {
+ GtkCheckMenuItem *check;
+
+ check = GTK_CHECK_MENU_ITEM (item->item);
+
+ if (item->toggle_state == 1)
+ gtk_check_menu_item_set_active (check, TRUE);
+ else if (item->toggle_state == 0)
+ gtk_check_menu_item_set_active (check, FALSE);
+ }
+ }
+
+ gtk_widget_set_sensitive (item->item, item->enabled);
+ gtk_widget_set_visible (item->item, item->visible);
+
+ g_object_ref_sink (item->item);
+ return item;
+}
+
+void
+sn_dubs_menu_item_free (gpointer data)
+{
+ SnDBusMenuItem *item;
+
+ item = (SnDBusMenuItem *) data;
+ if (item == NULL)
+ return;
+
+ g_clear_pointer (&item->accessible_desc, g_free);
+ g_clear_pointer (&item->children_display, g_free);
+ g_clear_pointer (&item->disposition, g_free);
+ g_clear_pointer (&item->icon_name, g_free);
+ g_clear_object (&item->icon_data);
+ g_clear_pointer (&item->label, g_free);
+ g_clear_pointer (&item->shortcuts, sn_shortcuts_free);
+ g_clear_pointer (&item->toggle_type, g_free);
+ g_clear_pointer (&item->type, g_free);
+
+ gtk_widget_destroy (item->item);
+ g_clear_object (&item->item);
+ g_clear_object (&item->submenu);
+
+ g_free (item);
+}
+
+void
+sn_dbus_menu_item_update_props (SnDBusMenuItem *item,
+ GVariant *props)
+{
+ GVariantIter iter;
+ const gchar *prop;
+ GVariant *value;
+
+ g_variant_iter_init (&iter, props);
+ while (g_variant_iter_next (&iter, "{&sv}", &prop, &value))
+ {
+ if (g_strcmp0 (prop, "accessible-desc") == 0)
+ {
+ g_free (item->accessible_desc);
+ item->accessible_desc = g_variant_dup_string (value, NULL);
+ }
+ else if (g_strcmp0 (prop, "children-display") == 0)
+ {
+ g_free (item->children_display);
+ item->children_display = g_variant_dup_string (value, NULL);
+ }
+ else if (g_strcmp0 (prop, "disposition") == 0)
+ {
+ g_free (item->disposition);
+ item->disposition = g_variant_dup_string (value, NULL);
+ }
+ else if (g_strcmp0 (prop, "enabled") == 0)
+ {
+ item->enabled = g_variant_get_boolean (value);
+ gtk_widget_set_sensitive (item->item, item->enabled);
+ }
+ else if (g_strcmp0 (prop, "icon-name") == 0)
+ {
+ SnImageMenuItem *image_item;
+
+ g_free (item->icon_name);
+ item->icon_name = g_variant_dup_string (value, NULL);
+
+ image_item = SN_IMAGE_MENU_ITEM (item->item);
+
+ if (item->icon_name)
+ {
+ sn_image_menu_item_set_image_from_icon_name (image_item,
+ item->icon_name);
+ }
+ else
+ {
+ sn_image_menu_item_unset_image (image_item);
+ }
+ }
+ else if (g_strcmp0 (prop, "icon-data") == 0)
+ {
+ SnImageMenuItem *image_item;
+
+ g_clear_object (&item->icon_data);
+ item->icon_data = pxibuf_new (value);
+
+ image_item = SN_IMAGE_MENU_ITEM (item->item);
+
+ if (item->icon_data)
+ {
+ sn_image_menu_item_set_image_from_icon_pixbuf (image_item,
+ item->icon_data);
+ }
+ else
+ {
+ sn_image_menu_item_unset_image (image_item);
+ }
+ }
+ else if (g_strcmp0 (prop, "label") == 0)
+ {
+ g_free (item->label);
+ item->label = g_variant_dup_string (value, NULL);
+
+ if (!GTK_IS_SEPARATOR_MENU_ITEM (item->item))
+ gtk_menu_item_set_label (GTK_MENU_ITEM (item->item), item->label);
+ }
+ else if (g_strcmp0 (prop, "shortcut") == 0)
+ {
+ sn_shortcuts_free (item->shortcuts);
+ item->shortcuts = sn_shortcuts_new (value);
+ }
+ else if (g_strcmp0 (prop, "toggle-type") == 0)
+ {
+ g_free (item->toggle_type);
+ item->toggle_type = g_variant_dup_string (value, NULL);
+ }
+ else if (g_strcmp0 (prop, "toggle-state") == 0)
+ {
+ item->toggle_state = g_variant_get_int32 (value);
+
+ if (item->toggle_state != -1 && GTK_IS_CHECK_MENU_ITEM (item->item))
+ {
+ GtkCheckMenuItem *check;
+
+ check = GTK_CHECK_MENU_ITEM (item->item);
+
+ if (item->toggle_state == 1)
+ gtk_check_menu_item_set_active (check, TRUE);
+ else if (item->toggle_state == 0)
+ gtk_check_menu_item_set_active (check, FALSE);
+ }
+ }
+ else if (g_strcmp0 (prop, "type") == 0)
+ {
+ g_free (item->type);
+ item->type = g_variant_dup_string (value, NULL);
+ }
+ else if (g_strcmp0 (prop, "visible") == 0)
+ {
+ item->visible = g_variant_get_boolean (value);
+ gtk_widget_set_visible (item->item, item->visible);
+ }
+ else
+ {
+ g_debug ("updating unknown property - '%s'", prop);
+ }
+
+ g_variant_unref (value);
+ }
+}
+
+void
+sn_dbus_menu_item_remove_props (SnDBusMenuItem *item,
+ GVariant *props)
+{
+ GVariantIter iter;
+ const gchar *prop;
+
+ g_variant_iter_init (&iter, props);
+ while (g_variant_iter_next (&iter, "&s", &prop))
+ {
+ if (g_strcmp0 (prop, "accessible-desc") == 0)
+ {
+ g_clear_pointer (&item->accessible_desc, g_free);
+ }
+ else if (g_strcmp0 (prop, "children-display") == 0)
+ {
+ g_clear_pointer (&item->children_display, g_free);
+ }
+ else if (g_strcmp0 (prop, "disposition") == 0)
+ {
+ g_clear_pointer (&item->disposition, g_free);
+ }
+ else if (g_strcmp0 (prop, "enabled") == 0)
+ {
+ item->enabled = TRUE;
+ gtk_widget_set_sensitive (item->item, item->enabled);
+ }
+ else if (g_strcmp0 (prop, "icon-name") == 0)
+ {
+ g_clear_pointer (&item->icon_name, g_free);
+ if (SN_IS_IMAGE_MENU_ITEM (item->item))
+ sn_image_menu_item_unset_image (SN_IMAGE_MENU_ITEM (item->item));
+ }
+ else if (g_strcmp0 (prop, "icon-data") == 0)
+ {
+ g_clear_object (&item->icon_data);
+ if (SN_IS_IMAGE_MENU_ITEM (item->item))
+ sn_image_menu_item_unset_image (SN_IMAGE_MENU_ITEM (item->item));
+ }
+ else if (g_strcmp0 (prop, "label") == 0)
+ {
+ g_clear_pointer (&item->label, g_free);
+ if (!GTK_IS_SEPARATOR_MENU_ITEM (item->item))
+ gtk_menu_item_set_label (GTK_MENU_ITEM (item->item), item->label);
+ }
+ else if (g_strcmp0 (prop, "shortcut") == 0)
+ {
+ g_clear_pointer (&item->shortcuts, sn_shortcuts_free);
+ }
+ else if (g_strcmp0 (prop, "toggle-type") == 0)
+ {
+ g_clear_pointer (&item->toggle_type, g_free);
+ }
+ else if (g_strcmp0 (prop, "toggle-state") == 0)
+ {
+ item->toggle_state = -1;
+ }
+ else if (g_strcmp0 (prop, "type") == 0)
+ {
+ g_clear_pointer (&item->type, g_free);
+ }
+ else if (g_strcmp0 (prop, "visible") == 0)
+ {
+ item->visible = TRUE;
+ gtk_widget_set_visible (item->item, item->visible);
+ }
+ else
+ {
+ g_debug ("removing unknown property - '%s'", prop);
+ }
+ }
+}
diff --git a/applets/status-notifier/sn-dbus-menu-item.h b/applets/status-notifier/sn-dbus-menu-item.h
new file mode 100644
index 0000000..a5ff995
--- /dev/null
+++ b/applets/status-notifier/sn-dbus-menu-item.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SN_DBUS_MENU_ITEM_H
+#define SN_DUBS_MENU_ITEM_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ guint key;
+ GdkModifierType mask;
+} SnShortcut;
+
+typedef struct
+{
+ gchar *accessible_desc;
+ gchar *children_display;
+ gchar *disposition;
+ gboolean enabled;
+ gchar *icon_name;
+ GdkPixbuf *icon_data;
+ gchar *label;
+ SnShortcut **shortcuts;
+ gchar *toggle_type;
+ gint32 toggle_state;
+ gchar *type;
+ gboolean visible;
+
+ GtkWidget *item;
+ GtkMenu *submenu;
+} SnDBusMenuItem;
+
+SnDBusMenuItem *sn_dbus_menu_item_new (GVariant *props);
+
+void sn_dubs_menu_item_free (gpointer data);
+
+void sn_dbus_menu_item_update_props (SnDBusMenuItem *item,
+ GVariant *props);
+
+void sn_dbus_menu_item_remove_props (SnDBusMenuItem *item,
+ GVariant *props);
+
+G_END_DECLS
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]