[gnome-panel/wip/status-notifier: 7/14] snh: add items to applet
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-panel/wip/status-notifier: 7/14] snh: add items to applet
- Date: Wed, 22 Jul 2015 20:26:39 +0000 (UTC)
commit 76552ebe915cd35e4fb32f0f7af7d559472afe04
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Sat Jul 4 17:54:26 2015 +0300
snh: add items to applet
applets/snh/Makefile.am | 2 +
applets/snh/snh-applet.c | 79 ++++++--
applets/snh/snh-item.c | 476 ++++++++++++++++++++++++++++++++++++++++++++++
applets/snh/snh-item.h | 33 ++++
4 files changed, 573 insertions(+), 17 deletions(-)
---
diff --git a/applets/snh/Makefile.am b/applets/snh/Makefile.am
index c949cc8..af4e8d9 100644
--- a/applets/snh/Makefile.am
+++ b/applets/snh/Makefile.am
@@ -16,6 +16,8 @@ AM_CFLAGS = \
SNH_SOURCES = \
snh-applet.c \
snh-applet.h \
+ snh-item.c \
+ snh-item.h \
$(NULL)
SNH_LDADD = \
diff --git a/applets/snh/snh-applet.c b/applets/snh/snh-applet.c
index a795fd5..1870cbf 100644
--- a/applets/snh/snh-applet.c
+++ b/applets/snh/snh-applet.c
@@ -17,9 +17,8 @@
#include "config.h"
-#include <libstatus-notifier/sn.h>
-
#include "snh-applet.h"
+#include "snh-item.h"
struct _SnhApplet
{
@@ -27,38 +26,54 @@ struct _SnhApplet
SnHost *host;
- GtkWidget *label;
+ GtkWidget *box;
};
G_DEFINE_TYPE (SnhApplet, snh_applet, PANEL_TYPE_APPLET)
static void
+item_remove (GtkWidget *widget,
+ gpointer data)
+{
+ gtk_widget_destroy (widget);
+}
+
+static void
items_changed_cb (SnHost *host,
gpointer user_data)
{
SnhApplet *applet;
GList *list;
- gchar *text;
+ GList *l;
applet = SNH_APPLET (user_data);
list = sn_host_get_items (host);
- text = g_strdup_printf ("Items: %d", g_list_length (list));
- g_list_free (list);
+ gtk_container_foreach (GTK_CONTAINER (applet->box),
+ (GtkCallback) item_remove, NULL);
+
+ for (l = list; l; l = l->next)
+ {
+ SnItemClient *item_client;
+ GtkWidget *item;
+
+ item_client = SN_ITEM_CLIENT (l->data);
+ item = snh_item_new (item_client);
- gtk_label_set_text (GTK_LABEL (applet->label), text);
- g_free (text);
+ g_object_bind_property (applet->box, "orientation", item, "orientation",
+ G_BINDING_DEFAULT);
+
+ gtk_box_pack_start (GTK_BOX (applet->box), item, FALSE, FALSE, 0);
+ gtk_widget_show (item);
+ }
+
+ g_list_free (list);
}
static gboolean
snh_applet_fill (SnhApplet *applet)
{
- applet->label = gtk_label_new ("Items: 0");
-
- gtk_container_add (GTK_CONTAINER (applet), applet->label);
- gtk_widget_show (applet->label);
-
gtk_widget_show (GTK_WIDGET (applet));
return TRUE;
@@ -76,7 +91,7 @@ snh_applet_factory (PanelApplet *applet,
}
static void
-snh_applet_finalize (GObject *object)
+snh_applet_dispose (GObject *object)
{
SnhApplet *applet;
@@ -84,33 +99,63 @@ snh_applet_finalize (GObject *object)
g_clear_object (&applet->host);
+ G_OBJECT_CLASS (snh_applet_parent_class)->dispose (object);
+}
+
+static void
+snh_applet_finalize (GObject *object)
+{
G_OBJECT_CLASS (snh_applet_parent_class)->finalize (object);
}
static void
+snh_applet_change_orient (PanelApplet *applet,
+ PanelAppletOrient orient)
+{
+ SnhApplet *snh_applet;
+ GtkOrientation orientation;
+
+ snh_applet = SNH_APPLET (applet);
+ orientation = panel_applet_get_gtk_orientation (applet);
+
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (snh_applet->box),
+ orientation);
+}
+
+static void
snh_applet_class_init (SnhAppletClass *applet_class)
{
GObjectClass *object_class;
+ PanelAppletClass *panel_applet_class;
object_class = G_OBJECT_CLASS (applet_class);
+ panel_applet_class = PANEL_APPLET_CLASS (applet_class);
+ object_class->dispose = snh_applet_dispose;
object_class->finalize = snh_applet_finalize;
+
+ panel_applet_class->change_orient = snh_applet_change_orient;
}
static void
snh_applet_init (SnhApplet *applet)
{
PanelApplet *panel_applet;
+ GtkOrientation orientation;
panel_applet = PANEL_APPLET (applet);
+ orientation = panel_applet_get_gtk_orientation (panel_applet);
- applet->host = sn_host_new ();
+ panel_applet_set_flags (panel_applet, PANEL_APPLET_HAS_HANDLE |
+ PANEL_APPLET_EXPAND_MINOR);
+ applet->host = sn_host_new ();
g_signal_connect (applet->host, "items-changed",
G_CALLBACK (items_changed_cb), applet);
- panel_applet_set_flags (panel_applet, PANEL_APPLET_HAS_HANDLE |
- PANEL_APPLET_EXPAND_MINOR);
+ applet->box = gtk_box_new (orientation, 0);
+ gtk_container_add (GTK_CONTAINER (applet), applet->box);
+ gtk_widget_show (applet->box);
}
PANEL_APPLET_IN_PROCESS_FACTORY ("SnhAppletFactory", SNH_TYPE_APPLET,
diff --git a/applets/snh/snh-item.c b/applets/snh/snh-item.c
new file mode 100644
index 0000000..645d32e
--- /dev/null
+++ b/applets/snh/snh-item.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2015 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "snh-item.h"
+
+#define UPDATE_TIMEOUT 100
+#define UPDATE_ICONS_TIMEOUT 100
+
+struct _SnhItem
+{
+ GtkEventBox parent;
+
+ SnItemClient *item;
+
+ GtkOrientation orientation;
+ gint size;
+
+ guint update_id;
+ guint update_icons_id;
+
+ gchar *title;
+ gchar *tooltip_title;
+ gchar *tooltip_text;
+ gchar *icon_theme_path;
+
+ GdkPixbuf *icon;
+ GdkPixbuf *overlay_icon;
+ GdkPixbuf *attention_icon;
+ GdkPixbuf *tooltip_icon;
+
+ SnItemStatus status;
+
+ GtkWidget *box;
+ GtkWidget *image;
+ GtkWidget *label;
+};
+
+enum
+{
+ PROP_0,
+
+ PROP_ITEM,
+ PROP_ORIENTATION,
+
+ LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP] = { NULL };
+
+G_DEFINE_TYPE (SnhItem, snh_item, GTK_TYPE_EVENT_BOX)
+
+static gboolean
+update_cb (gpointer user_data)
+{
+ SnhItem *item;
+ GtkWidget *widget;
+ GdkPixbuf *icon;
+
+ item = SNH_ITEM (user_data);
+ widget = GTK_WIDGET (item);
+
+ if (item->status == SN_ITEM_STATUS_PASSIVE)
+ {
+ gtk_widget_hide (widget);
+
+ item->update_id = 0;
+ return G_SOURCE_REMOVE;
+ }
+
+ if (gtk_widget_is_visible (widget) == FALSE)
+ gtk_widget_show (widget);
+
+ icon = item->icon;
+
+ if (item->status == SN_ITEM_STATUS_NEEDS_ATTENTION && item->attention_icon)
+ icon = item->attention_icon;
+
+ if (icon)
+ {
+ gtk_widget_hide (item->label);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (item->image), icon);
+ gtk_widget_show (item->image);
+ }
+ else
+ {
+ gtk_widget_hide (item->image);
+
+ gtk_label_set_text (GTK_LABEL (item->label), item->title);
+ gtk_widget_show (item->label);
+ }
+
+ item->update_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
+static void
+snh_item_update (SnhItem *item)
+{
+ if (item->update_id > 0)
+ g_source_remove (item->update_id);
+
+ item->update_id = g_timeout_add (UPDATE_TIMEOUT,
+ (GSourceFunc) update_cb,
+ item);
+ g_source_set_name_by_id (item->update_id, "[gnome-panel] update_cb");
+}
+
+static void
+snh_item_update_title (SnhItem *item)
+{
+ const gchar *title;
+
+ title = sn_item_client_get_title (item->item);
+
+ if (g_strcmp0 (item->title, title) == 0)
+ return;
+
+ g_free (item->title);
+ item->title = g_strdup (title);
+
+ snh_item_update (item);
+}
+
+static void
+snh_item_update_tooltip (SnhItem *item)
+{
+}
+
+static void
+snh_item_update_status (SnhItem *item,
+ SnItemStatus status)
+{
+ if (item->status == status)
+ return;
+
+ item->status = status;
+
+ snh_item_update (item);
+}
+
+static void
+update_icon (SnhItem *item)
+{
+ const gchar *icon_name;
+ GdkPixbuf *icon;
+
+ icon = NULL;
+ icon_name = sn_item_client_get_icon_name (item->item);
+
+ if (icon_name)
+ {
+ icon = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+ icon_name, item->size,
+ GTK_ICON_LOOKUP_FORCE_SIZE, NULL);
+ }
+
+ if (icon == NULL)
+ {
+ }
+
+ g_clear_object (&item->icon);
+ item->icon = icon;
+}
+
+static void
+update_overlay_icon (SnhItem *item)
+{
+}
+
+static void
+update_attention_icon (SnhItem *item)
+{
+}
+
+static void
+update_tooltip_icon (SnhItem *item)
+{
+}
+
+static gboolean
+update_icons_cb (gpointer user_data)
+{
+ SnhItem *item;
+ GtkIconTheme *icon_theme;
+ const gchar *icon_theme_path;
+
+ item = SNH_ITEM (user_data);
+ icon_theme = gtk_icon_theme_get_default ();
+ icon_theme_path = sn_item_client_get_icon_theme_path (item->item);
+
+ if (g_strcmp0 (item->icon_theme_path, icon_theme_path) != 0)
+ {
+ gtk_icon_theme_append_search_path (icon_theme, icon_theme_path);
+
+ g_free (item->icon_theme_path);
+ item->icon_theme_path = g_strdup (icon_theme_path);
+ }
+
+ update_icon (item);
+ update_overlay_icon (item);
+ update_attention_icon (item);
+ update_tooltip_icon (item);
+
+ snh_item_update (item);
+
+ item->update_icons_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
+static void
+snh_item_update_icons (SnhItem *item)
+{
+ if (item->update_icons_id > 0)
+ g_source_remove (item->update_icons_id);
+
+ item->update_icons_id = g_timeout_add (UPDATE_ICONS_TIMEOUT,
+ (GSourceFunc) update_icons_cb,
+ item);
+ g_source_set_name_by_id (item->update_icons_id,
+ "[gnome-panel] update_icons_cb");
+}
+
+static void
+new_title_cb (SnItemClient *item_client,
+ gpointer user_data)
+{
+ SnhItem *item;
+
+ item = SNH_ITEM (user_data);
+
+ snh_item_update_title (item);
+}
+
+static void
+new_icon_cb (SnItemClient *item_client,
+ gpointer user_data)
+{
+ SnhItem *item;
+
+ item = SNH_ITEM (user_data);
+
+ snh_item_update_icons (item);
+}
+
+static void
+new_tooltip_cb (SnItemClient *item_client,
+ gpointer user_data)
+{
+ SnhItem *item;
+
+ item = SNH_ITEM (user_data);
+
+ snh_item_update_tooltip (item);
+ snh_item_update_icons (item);
+}
+
+static void
+new_status_cb (SnItemClient *item_client,
+ SnItemStatus status,
+ gpointer user_data)
+{
+ SnhItem *item;
+
+ item = SNH_ITEM (user_data);
+
+ snh_item_update_status (item, status);
+}
+
+static void
+new_icon_theme_path_cb (SnItemClient *item_client,
+ const gchar *path,
+ gpointer user_data)
+{
+ SnhItem *item;
+
+ item = SNH_ITEM (user_data);
+
+ snh_item_update_icons (item);
+}
+
+static void
+snh_item_constructed (GObject *object)
+{
+ SnhItem *item;
+ SnItemStatus status;
+
+ item = SNH_ITEM (object);
+
+ G_OBJECT_CLASS (snh_item_parent_class)->constructed (object);
+
+ g_signal_connect (item->item, "new-title",
+ G_CALLBACK (new_title_cb), item);
+ g_signal_connect (item->item, "new-icon",
+ G_CALLBACK (new_icon_cb), item);
+ g_signal_connect (item->item, "new-overlay-icon",
+ G_CALLBACK (new_icon_cb), item);
+ g_signal_connect (item->item, "new-attention-icon",
+ G_CALLBACK (new_icon_cb), item);
+ g_signal_connect (item->item, "new-tooltip",
+ G_CALLBACK (new_tooltip_cb), item);
+ g_signal_connect (item->item, "new-status",
+ G_CALLBACK (new_status_cb), item);
+ g_signal_connect (item->item, "new-icon-theme-path",
+ G_CALLBACK (new_icon_theme_path_cb), item);
+
+ snh_item_update_title (item);
+ snh_item_update_tooltip (item);
+
+ status = sn_item_client_get_status (item->item);
+ snh_item_update_status (item, status);
+}
+
+static void
+snh_item_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SnhItem *item;
+ GtkOrientation orientation;
+
+ item = SNH_ITEM (object);
+
+ switch (property_id)
+ {
+ case PROP_ITEM:
+ item->item = g_value_get_object (value);
+ break;
+
+ case PROP_ORIENTATION:
+ orientation = g_value_get_enum (value);
+
+ if (item->orientation != orientation)
+ {
+ item->orientation = orientation;
+
+ snh_item_update_icons (item);
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+snh_item_dispose (GObject *object)
+{
+ SnhItem *item;
+
+ item = SNH_ITEM (object);
+
+ if (item->update_icons_id > 0)
+ {
+ g_source_remove (item->update_icons_id);
+ item->update_icons_id = 0;
+ }
+
+ if (item->update_id > 0)
+ {
+ g_source_remove (item->update_id);
+ item->update_id = 0;
+ }
+
+ g_clear_object (&item->icon);
+ g_clear_object (&item->overlay_icon);
+ g_clear_object (&item->attention_icon);
+ g_clear_object (&item->tooltip_icon);
+
+ G_OBJECT_CLASS (snh_item_parent_class)->dispose (object);
+}
+
+static void
+snh_item_finalize (GObject *object)
+{
+ SnhItem *item;
+
+ item = SNH_ITEM (object);
+
+ g_free (item->title);
+ g_free (item->tooltip_title);
+ g_free (item->tooltip_text);
+ g_free (item->icon_theme_path);
+
+ G_OBJECT_CLASS (snh_item_parent_class)->finalize (object);
+}
+
+static void
+snh_item_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ SnhItem *item;
+ gint size;
+
+ item = SNH_ITEM (widget);
+
+ GTK_WIDGET_CLASS (snh_item_parent_class)->size_allocate (widget, allocation);
+
+ if (item->orientation == GTK_ORIENTATION_HORIZONTAL)
+ size = allocation->height;
+ else
+ size = allocation->width;
+
+ if (item->size == size)
+ return;
+
+ item->size = size;
+
+ snh_item_update_icons (item);
+}
+
+static void
+snh_item_class_init (SnhItemClass *item_class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = G_OBJECT_CLASS (item_class);
+ widget_class = GTK_WIDGET_CLASS (item_class);
+
+ object_class->constructed = snh_item_constructed;
+ object_class->set_property = snh_item_set_property;
+ object_class->dispose = snh_item_dispose;
+ object_class->finalize = snh_item_finalize;
+
+ widget_class->size_allocate = snh_item_size_allocate;
+
+ properties[PROP_ITEM] =
+ g_param_spec_object ("item", "item", "item", SN_TYPE_ITEM_CLIENT,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
+
+ properties[PROP_ORIENTATION] =
+ g_param_spec_enum ("orientation", "orientation", "orientation",
+ GTK_TYPE_ORIENTATION, GTK_ORIENTATION_HORIZONTAL,
+ G_PARAM_WRITABLE);
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+static void
+snh_item_init (SnhItem *item)
+{
+ item->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_container_add (GTK_CONTAINER (item), item->box);
+ gtk_widget_show (item->box);
+
+ item->image = gtk_image_new ();
+ gtk_box_pack_start (GTK_BOX (item->box), item->image, FALSE, FALSE, 0);
+
+ item->label = gtk_label_new (NULL);
+ gtk_box_pack_start (GTK_BOX (item->box), item->label, FALSE, FALSE, 0);
+}
+
+GtkWidget *
+snh_item_new (SnItemClient *item)
+{
+ return g_object_new (SNH_TYPE_ITEM, "item", item, NULL);
+}
diff --git a/applets/snh/snh-item.h b/applets/snh/snh-item.h
new file mode 100644
index 0000000..5a7ce44
--- /dev/null
+++ b/applets/snh/snh-item.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 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 SNH_ITEM_H
+#define SNH_ITEM_H
+
+#include <gtk/gtk.h>
+#include <libstatus-notifier/sn.h>
+
+G_BEGIN_DECLS
+
+#define SNH_TYPE_ITEM snh_item_get_type ()
+G_DECLARE_FINAL_TYPE (SnhItem, snh_item, SNH, ITEM, GtkEventBox)
+
+GtkWidget *snh_item_new (SnItemClient *item);
+
+G_END_DECLS
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]