[telepathy-doc/master] Beginnings of a presence control app in GTK+
Danielle Madeley
danielle.madeley at collabora.co.uk
Tue Sep 22 18:33:09 PDT 2009
---
configure.ac | 1 +
docs/examples/Makefile.am | 1 +
docs/examples/gtk_presence_app/Makefile.am | 11 +
docs/examples/gtk_presence_app/example.c | 90 +++++++++
docs/examples/gtk_presence_app/presence-widget.c | 226 ++++++++++++++++++++++
docs/examples/gtk_presence_app/presence-widget.h | 45 +++++
docs/examples/gtk_presence_app/presence-window.c | 63 ++++++
docs/examples/gtk_presence_app/presence-window.h | 42 ++++
8 files changed, 479 insertions(+), 0 deletions(-)
create mode 100644 docs/examples/gtk_presence_app/Makefile.am
create mode 100644 docs/examples/gtk_presence_app/example.c
create mode 100644 docs/examples/gtk_presence_app/presence-widget.c
create mode 100644 docs/examples/gtk_presence_app/presence-widget.h
create mode 100644 docs/examples/gtk_presence_app/presence-window.c
create mode 100644 docs/examples/gtk_presence_app/presence-window.h
diff --git a/configure.ac b/configure.ac
index 1862bcd..0751158 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,6 +37,7 @@ AC_OUTPUT([
docs/examples/glib_stream_tube/Makefile
docs/examples/glib_mc5_connections/Makefile
docs/examples/glib_mc5_observer/Makefile
+ docs/examples/gtk_presence_app/Makefile
docs/examples/pygtk_chat_client/Makefile
docs/examples/python_get_parameters/Makefile
docs/examples/python_iface_messaging/Makefile
diff --git a/docs/examples/Makefile.am b/docs/examples/Makefile.am
index 05511e3..d14e5ac 100644
--- a/docs/examples/Makefile.am
+++ b/docs/examples/Makefile.am
@@ -9,6 +9,7 @@ example_dirs = \
glib_stream_tube \
glib_mc5_connections \
glib_mc5_observer \
+ gtk_presence_app \
pygtk_chat_client \
python_get_parameters \
python_iface_messaging \
diff --git a/docs/examples/gtk_presence_app/Makefile.am b/docs/examples/gtk_presence_app/Makefile.am
new file mode 100644
index 0000000..b5dc428
--- /dev/null
+++ b/docs/examples/gtk_presence_app/Makefile.am
@@ -0,0 +1,11 @@
+INCLUDES = $(TELEPATHY_GLIB_CFLAGS)
+LDADD = $(TELEPATHY_GLIB_LIBS)
+
+noinst_PROGRAMS = example
+
+example_SOURCES = \
+ presence-window.c presence-window.h \
+ presence-widget.c presence-widget.h \
+ example.c
+
+include $(top_srcdir)/docs/rsync-dist.make
diff --git a/docs/examples/gtk_presence_app/example.c b/docs/examples/gtk_presence_app/example.c
new file mode 100644
index 0000000..153bd62
--- /dev/null
+++ b/docs/examples/gtk_presence_app/example.c
@@ -0,0 +1,90 @@
+/*
+ * A user interface for controlling the presence of my various Telepathy
+ * accounts.
+ *
+ * Authors:
+ * Danielle Madeley <danielle.madeley at collabora.co.uk>
+ */
+
+#include <gtk/gtk.h>
+
+#include <telepathy-glib/account-manager.h>
+
+#include "presence-window.h"
+#include "presence-widget.h"
+
+static void
+dump_children (GtkWidget *widget,
+ gpointer callback_data)
+{
+ g_print (" %s %s (%p)\n",
+ (char *) callback_data, G_OBJECT_TYPE_NAME (widget), widget);
+
+ if (GTK_IS_CONTAINER (widget))
+ {
+ char *str = g_strdup_printf ("%s-", (char *) callback_data);
+ gtk_container_foreach (GTK_CONTAINER (widget), dump_children, str);
+ g_free (str);
+ }
+}
+
+static void
+account_manager_ready (TpAccountManager *am,
+ PresenceWindow *window)
+{
+ GList *l, *accounts = tp_account_manager_get_accounts (am);
+ for (l = accounts; l != NULL; l = l->next)
+ {
+ TpAccount *acct = TP_ACCOUNT (l->data);
+
+ GtkWidget *widget = presence_widget_new (acct);
+ presence_window_add_widget (window, PRESENCE_WIDGET (widget));
+
+ }
+
+ g_list_free (accounts);
+
+ // dump_children (GTK_WIDGET (window), "|-");
+}
+
+static void
+am_notify_ready (GObject *am,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ if (tp_account_manager_is_ready (TP_ACCOUNT_MANAGER (am)))
+ {
+ account_manager_ready (TP_ACCOUNT_MANAGER (am),
+ PRESENCE_WINDOW (user_data));
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ gtk_init (&argc, &argv);
+
+ /* let's use Empathy's status icons */
+ GtkIconTheme *icon_theme = gtk_icon_theme_get_default ();
+ gtk_icon_theme_prepend_search_path (icon_theme,
+ "/usr/share/empathy/icons/");
+
+ GtkWidget *window = presence_window_new ();
+
+ TpAccountManager *am = tp_account_manager_dup ();
+
+ if (tp_account_manager_is_ready (TP_ACCOUNT_MANAGER (am)))
+ {
+ account_manager_ready (TP_ACCOUNT_MANAGER (am),
+ PRESENCE_WINDOW (window));
+ }
+ else
+ {
+ g_signal_connect (am, "notify::ready",
+ G_CALLBACK (am_notify_ready), window);
+ }
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+}
diff --git a/docs/examples/gtk_presence_app/presence-widget.c b/docs/examples/gtk_presence_app/presence-widget.c
new file mode 100644
index 0000000..84328fa
--- /dev/null
+++ b/docs/examples/gtk_presence_app/presence-widget.c
@@ -0,0 +1,226 @@
+/*
+ * presence-widget.c
+ *
+ * PresenceWidget
+ *
+ * Authors:
+ * Danielle Madeley <danielle.madeley at collabora.co.uk>
+ */
+
+#include <string.h>
+
+#include "presence-widget.h"
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_PRESENCE_WIDGET, PresenceWidgetPrivate))
+
+G_DEFINE_TYPE (PresenceWidget, presence_widget, GTK_TYPE_TABLE);
+
+typedef struct _PresenceWidgetPrivate PresenceWidgetPrivate;
+struct _PresenceWidgetPrivate
+{
+ TpAccount *account;
+
+ GtkWidget *enabled_check;
+ GtkWidget *status_icon;
+ GtkWidget *status_message;
+};
+
+enum /* properties */
+{
+ PROP_0,
+ PROP_ACCOUNT
+};
+
+/* presence icons */
+static const char *presence_icons[NUM_TP_CONNECTION_PRESENCE_TYPES] = {
+ "empathy-offline",
+ "empathy-offline",
+ "empathy-available",
+ "empathy-away",
+ "empathy-extended-away",
+ "empathy-offline",
+ "empathy-busy",
+ "empathy-offline",
+ "empathy-offline",
+};
+
+static const char *default_messages[NUM_TP_CONNECTION_PRESENCE_TYPES] = {
+ "Unset",
+ "Offline",
+ "Available",
+ "Away",
+ "Extended Away",
+ "Hidden",
+ "Busy",
+ "Unknown",
+ "Error"
+};
+
+static void
+presence_widget_get_property (GObject *self,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PresenceWidgetPrivate *priv = GET_PRIVATE (self);
+
+ switch (prop_id)
+ {
+ case PROP_ACCOUNT:
+ g_value_set_object (value, priv->account);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+presence_widget_set_property (GObject *self,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PresenceWidgetPrivate *priv = GET_PRIVATE (self);
+
+ switch (prop_id)
+ {
+ case PROP_ACCOUNT:
+ priv->account = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_notify_enabled (PresenceWidget *self,
+ GParamSpec *pspec,
+ TpAccount *account)
+{
+ PresenceWidgetPrivate *priv = GET_PRIVATE (self);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->enabled_check),
+ tp_account_is_enabled (account));
+}
+
+static void
+_notify_display_name (PresenceWidget *self,
+ GParamSpec *pspec,
+ TpAccount *account)
+{
+ PresenceWidgetPrivate *priv = GET_PRIVATE (self);
+
+ gtk_button_set_label (GTK_BUTTON (priv->enabled_check),
+ tp_account_get_display_name (account));
+}
+
+static void
+_notify_presence (PresenceWidget *self,
+ GParamSpec *pspec,
+ TpAccount *account)
+{
+ PresenceWidgetPrivate *priv = GET_PRIVATE (self);
+ TpConnectionPresenceType presence = tp_account_get_presence (account);
+
+ const char *icon_name = presence_icons[presence];
+
+ gtk_image_set_from_icon_name (GTK_IMAGE (priv->status_icon),
+ icon_name, GTK_ICON_SIZE_MENU);
+}
+
+static void
+_notify_status_message (PresenceWidget *self,
+ GParamSpec *pspec,
+ TpAccount *account)
+{
+ PresenceWidgetPrivate *priv = GET_PRIVATE (self);
+ const char *msg = tp_account_get_status_message (account);
+
+ if (strlen (msg) == 0)
+ {
+ TpConnectionPresenceType presence = tp_account_get_presence (account);
+ msg = default_messages[presence];
+ }
+
+ gtk_label_set_text (GTK_LABEL (priv->status_message), msg);
+}
+
+static void
+presence_widget_constructed (GObject *self)
+{
+ PresenceWidgetPrivate *priv = GET_PRIVATE (self);
+
+ g_signal_connect_swapped (priv->account, "notify::enabled",
+ G_CALLBACK (_notify_enabled), self);
+ g_signal_connect_swapped (priv->account, "notify::display-name",
+ G_CALLBACK (_notify_display_name), self);
+ g_signal_connect_swapped (priv->account, "notify::presence",
+ G_CALLBACK (_notify_presence), self);
+ g_signal_connect_swapped (priv->account, "notify::status-message",
+ G_CALLBACK (_notify_status_message), self);
+
+ _notify_enabled (PRESENCE_WIDGET (self), NULL, priv->account);
+ _notify_display_name (PRESENCE_WIDGET (self), NULL, priv->account);
+ _notify_presence (PRESENCE_WIDGET (self), NULL, priv->account);
+ _notify_status_message (PRESENCE_WIDGET (self), NULL, priv->account);
+}
+
+static void
+presence_widget_class_init (PresenceWidgetClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+
+ gobject_class->constructed = presence_widget_constructed;
+ gobject_class->get_property = presence_widget_get_property;
+ gobject_class->set_property = presence_widget_set_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_ACCOUNT,
+ g_param_spec_object ("account",
+ "account",
+ "Telepathy Account",
+ TP_TYPE_ACCOUNT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (gobject_class, sizeof (PresenceWidgetPrivate));
+}
+
+static void
+presence_widget_init (PresenceWidget *self)
+{
+ PresenceWidgetPrivate *priv = GET_PRIVATE (self);
+
+ gtk_table_resize (GTK_TABLE (self), 2, 2);
+
+ priv->enabled_check = gtk_check_button_new ();
+ gtk_table_attach (GTK_TABLE (self), priv->enabled_check,
+ 0, 2, 0, 1,
+ GTK_FILL, GTK_FILL, 0, 0);
+
+ priv->status_icon = gtk_image_new ();
+ gtk_table_attach (GTK_TABLE (self), priv->status_icon,
+ 0, 1, 1, 2,
+ GTK_FILL, GTK_FILL, 0, 0);
+
+ priv->status_message = gtk_label_new ("");
+ gtk_table_attach (GTK_TABLE (self), priv->status_message,
+ 1, 2, 1, 2,
+ GTK_FILL, GTK_FILL, 0, 0);
+
+ gtk_widget_show_all (GTK_WIDGET (self));
+ gtk_widget_hide (GTK_WIDGET (self));
+}
+
+GtkWidget *
+presence_widget_new (TpAccount *account)
+{
+ g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
+
+ return g_object_new (TYPE_PRESENCE_WIDGET,
+ "account", account,
+ NULL);
+}
diff --git a/docs/examples/gtk_presence_app/presence-widget.h b/docs/examples/gtk_presence_app/presence-widget.h
new file mode 100644
index 0000000..671b0c6
--- /dev/null
+++ b/docs/examples/gtk_presence_app/presence-widget.h
@@ -0,0 +1,45 @@
+/*
+ * presence-widget.h
+ *
+ * PresenceWidget
+ *
+ * Authors:
+ * Danielle Madeley <danielle.madeley at collabora.co.uk>
+ */
+
+#ifndef __PRESENCE_WIDGET_H__
+#define __PRESENCE_WIDGET_H__
+
+#include <gtk/gtk.h>
+
+#include <telepathy-glib/account.h>
+
+G_BEGIN_DECLS
+
+#define TYPE_PRESENCE_WIDGET (presence_widget_get_type ())
+#define PRESENCE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PRESENCE_WIDGET, PresenceWidget))
+#define PRESENCE_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), TYPE_PRESENCE_WIDGET, PresenceWidgetClass))
+#define IS_PRESENCE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PRESENCE_WIDGET))
+#define IS_PRESENCE_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), TYPE_PRESENCE_WIDGET))
+#define PRESENCE_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PRESENCE_WIDGET, PresenceWidgetClass))
+
+typedef struct _PresenceWidget PresenceWidget;
+typedef struct _PresenceWidgetClass PresenceWidgetClass;
+
+struct _PresenceWidget
+{
+ GtkTable parent;
+};
+
+struct _PresenceWidgetClass
+{
+ GtkTableClass parent_class;
+};
+
+GType presence_widget_get_type (void);
+
+GtkWidget *presence_widget_new (TpAccount *account);
+
+G_END_DECLS
+
+#endif
diff --git a/docs/examples/gtk_presence_app/presence-window.c b/docs/examples/gtk_presence_app/presence-window.c
new file mode 100644
index 0000000..b673679
--- /dev/null
+++ b/docs/examples/gtk_presence_app/presence-window.c
@@ -0,0 +1,63 @@
+/*
+ * presence-window.c
+ *
+ * PresenceWindow
+ *
+ * Authors:
+ * Danielle Madeley <danielle.madeley at collabora.co.uk>
+ */
+
+#include "presence-window.h"
+#include "presence-widget.h"
+
+#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_PRESENCE_WINDOW, PresenceWindowPrivate))
+
+G_DEFINE_TYPE (PresenceWindow, presence_window, GTK_TYPE_WINDOW);
+
+typedef struct _PresenceWindowPrivate PresenceWindowPrivate;
+struct _PresenceWindowPrivate
+{
+ GtkWidget *vbox;
+};
+
+static void
+presence_window_class_init (PresenceWindowClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+
+ g_type_class_add_private (gobject_class, sizeof (PresenceWindowPrivate));
+}
+
+static void
+presence_window_init (PresenceWindow *self)
+{
+ PresenceWindowPrivate *priv = GET_PRIVATE (self);
+
+ gtk_window_set_title (GTK_WINDOW (self), "Telepathy Account Presence");
+
+ priv->vbox = gtk_vbox_new (FALSE, 3);
+ gtk_container_add (GTK_CONTAINER (self), priv->vbox);
+
+ gtk_widget_show (priv->vbox);
+}
+
+void
+presence_window_add_widget (PresenceWindow *self,
+ PresenceWidget *widget)
+{
+ g_return_if_fail (IS_PRESENCE_WINDOW (self));
+ g_return_if_fail (IS_PRESENCE_WIDGET (widget));
+
+ PresenceWindowPrivate *priv = GET_PRIVATE (self);
+
+ gtk_box_pack_start (GTK_BOX (priv->vbox), GTK_WIDGET (widget), FALSE, TRUE, 0);
+ gtk_widget_show (GTK_WIDGET (widget));
+
+ // FIXME: watch for account removal
+}
+
+GtkWidget *
+presence_window_new (void)
+{
+ return g_object_new (TYPE_PRESENCE_WINDOW, NULL);
+}
diff --git a/docs/examples/gtk_presence_app/presence-window.h b/docs/examples/gtk_presence_app/presence-window.h
new file mode 100644
index 0000000..538a79e
--- /dev/null
+++ b/docs/examples/gtk_presence_app/presence-window.h
@@ -0,0 +1,42 @@
+/*
+ * presence-window.h
+ *
+ * PresenceWindow
+ *
+ * Authors:
+ * Danielle Madeley <danielle.madeley at collabora.co.uk>
+ */
+
+#ifndef __PRESENCE_WINDOW_H__
+#define __PRESENCE_WINDOW_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define TYPE_PRESENCE_WINDOW (presence_window_get_type ())
+#define PRESENCE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PRESENCE_WINDOW, PresenceWindow))
+#define PRESENCE_WINDOW_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), TYPE_PRESENCE_WINDOW, PresenceWindowClass))
+#define IS_PRESENCE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PRESENCE_WINDOW))
+#define IS_PRESENCE_WINDOW_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), TYPE_PRESENCE_WINDOW))
+#define PRESENCE_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PRESENCE_WINDOW, PresenceWindowClass))
+
+typedef struct _PresenceWindow PresenceWindow;
+typedef struct _PresenceWindowClass PresenceWindowClass;
+
+struct _PresenceWindow
+{
+ GtkWindow parent;
+};
+
+struct _PresenceWindowClass
+{
+ GtkWindowClass parent_class;
+};
+
+GType presence_window_get_type (void);
+GtkWidget *presence_window_new (void);
+
+G_END_DECLS
+
+#endif
--
1.5.6.5
More information about the telepathy-commits
mailing list