[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