[empathy] Add initial adium theme support: Load the template and append messages.



commit bd603ce6e5945ed1d06e550c928fc2ed21da3d88
Author: Xavier Claessens <xclaesse gmail com>
Date:   Wed Jul 16 16:45:29 2008 +0200

    Add initial adium theme support: Load the template and append messages.

 libempathy-gtk/empathy-theme-adium.c |  288 ++++++++++++++++++++++++++++++++--
 libempathy/empathy-contact.c         |   12 ++
 libempathy/empathy-contact.h         |    1 +
 3 files changed, 285 insertions(+), 16 deletions(-)
---
diff --git a/libempathy-gtk/empathy-theme-adium.c b/libempathy-gtk/empathy-theme-adium.c
index 221cf21..9c5efc9 100644
--- a/libempathy-gtk/empathy-theme-adium.c
+++ b/libempathy-gtk/empathy-theme-adium.c
@@ -20,6 +20,10 @@
  */
 
 #include "config.h"
+#include <string.h>
+
+#include <libempathy/empathy-time.h>
+#include <libempathy/empathy-utils.h>
 
 #include "empathy-theme-adium.h"
 
@@ -29,7 +33,17 @@
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyThemeAdium)
 
 typedef struct {
-	guint unused;
+	gchar          *in_content_html;
+	gsize           in_content_len;
+	gchar          *in_nextcontent_html;
+	gsize           in_nextcontent_len;
+	gchar          *out_content_html;
+	gsize           out_content_len;
+	gchar          *out_nextcontent_html;
+	gsize           out_nextcontent_len;
+	EmpathyContact *last_contact;
+	gboolean        ready;
+	GList          *message_queue;
 } EmpathyThemeAdiumPriv;
 
 static void theme_adium_iface_init (EmpathyChatViewIface *iface);
@@ -40,62 +54,235 @@ G_DEFINE_TYPE_WITH_CODE (EmpathyThemeAdium, empathy_theme_adium,
 						theme_adium_iface_init));
 
 static void
-theme_adium_finalize (GObject *object)
+theme_adium_load (EmpathyThemeAdium *theme)
 {
-	G_OBJECT_CLASS (empathy_theme_adium_parent_class)->finalize (object);
-}
+	EmpathyThemeAdiumPriv *priv = GET_PRIV (theme);
+	gchar                 *basedir;
+	gchar                 *file;
+	gchar                 *template_html;
+	gsize                  template_len;
+	GString               *string;
+	gchar                **strv;
+	gchar                 *content;
+	gchar                 *css_path;
 
-static void
-empathy_theme_adium_class_init (EmpathyThemeAdiumClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	
-	object_class->finalize = theme_adium_finalize;
+	/* FIXME: Find a better way to get the theme dir */
+	basedir = g_build_filename (g_get_home_dir (), "Contents", "Resources", NULL);
 
-	g_type_class_add_private (object_class, sizeof (EmpathyThemeAdiumPriv));
+	/* Load html files */
+	file = g_build_filename (basedir, "Template.html", NULL);
+	g_file_get_contents (file, &template_html, &template_len, NULL);
+	g_free (file);
+
+	file = g_build_filename (basedir, "Incoming", "Content.html", NULL);
+	g_file_get_contents (file, &priv->in_content_html, &priv->in_content_len, NULL);
+	g_free (file);
+
+	file = g_build_filename (basedir, "Incoming", "NextContent.html", NULL);
+	g_file_get_contents (file, &priv->in_nextcontent_html, &priv->in_nextcontent_len, NULL);
+	g_free (file);
+
+	file = g_build_filename (basedir, "Outgoing", "Content.html", NULL);
+	g_file_get_contents (file, &priv->out_content_html, &priv->out_content_len, NULL);
+	g_free (file);
+
+	file = g_build_filename (basedir, "Outgoing", "NextContent.html", NULL);
+	g_file_get_contents (file, &priv->out_nextcontent_html, &priv->out_nextcontent_len, NULL);
+	g_free (file);
+
+	css_path = g_build_filename (basedir, "main.css", NULL);
+
+	/* Replace %@ with the needed information in the template html */
+	strv = g_strsplit (template_html, "%@", 5);
+	string = g_string_sized_new (template_len);
+	g_string_append (string, strv[0]);
+	g_string_append (string, basedir);
+	g_string_append (string, strv[1]);
+	g_string_append (string, css_path);
+	g_string_append (string, strv[2]);
+	g_string_append (string, ""); /* We don't want header */
+	g_string_append (string, strv[3]);
+	g_string_append (string, ""); /* We have no footer */
+	g_string_append (string, strv[4]);
+	content = g_string_free (string, FALSE);
+
+	/* Load the template */
+	webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (theme),
+					  content, basedir);
+
+	g_free (basedir);
+	g_free (content);
+	g_free (template_html);
+	g_free (css_path);
+	g_strfreev (strv);
 }
 
-static void
-empathy_theme_adium_init (EmpathyThemeAdium *theme)
+static gchar *
+theme_adium_escape (EmpathyThemeAdium *theme,
+		    const gchar       *text)
 {
-	EmpathyThemeAdiumPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (theme,
-		EMPATHY_TYPE_THEME_ADIUM, EmpathyThemeAdiumPriv);
+	const gchar *cur = text;
+	GString     *string;
 
-	theme->priv = priv;	
+	string = g_string_sized_new (strlen (text));
+	while (!G_STR_EMPTY (cur)) {
+		switch (*cur) {
+		case '\\':
+			g_string_append (string, "\\\\");	
+			break;
+		case '\"':
+			g_string_append (string, "\\\"");
+			break;
+		case '\r':
+			g_string_append (string, "<br/>");
+			break;
+		case '\n':
+			break;
+		default:
+			g_string_append_c (string, *cur);
+		}
+		cur++;
+	}
+
+	return g_string_free (string, FALSE);
 }
 
 static void
 theme_adium_scroll_down (EmpathyChatView *view)
 {
+	/* Not implemented */
 }
 
 static void
 theme_adium_append_message (EmpathyChatView *view,
 			    EmpathyMessage  *msg)
 {
+	EmpathyThemeAdiumPriv *priv = GET_PRIV (view);
+	EmpathyContact        *sender;
+	const gchar           *body;
+	const gchar           *name;
+	gchar                 *avatar;
+	gchar                 *time;
+	gsize                  len;
+	GString               *string;
+	gchar                 *cur;
+	gchar                 *prev;
+	gchar                 *script;
+	gchar                 *escape;
+	const gchar           *func;
+
+	if (!priv->ready) {
+		priv->message_queue = g_list_prepend (priv->message_queue,
+						      g_object_ref (msg));
+		return;
+	}
+
+	/* Get information */
+	sender = empathy_message_get_sender (msg);
+	body = empathy_message_get_body (msg);
+	name = empathy_contact_get_name (sender);
+	avatar = empathy_contact_get_avatar_filename (sender);
+	time = empathy_time_to_string_local (empathy_message_get_timestamp (msg),
+					     EMPATHY_TIME_FORMAT_DISPLAY_SHORT);
+
+	if (!avatar) {
+		/* FIXME: We should give a default icon of a buddy */
+		avatar = g_strdup ("FIXME");
+	}
+
+	/* Get the right html/func to add the message */
+	if (priv->last_contact &&
+	    empathy_contact_equal (priv->last_contact, sender)) {
+		func = "appendNextMessage";
+		if (empathy_contact_is_user (sender)) {
+			cur = priv->out_nextcontent_html;
+			len = priv->out_nextcontent_len;
+		} else {
+			cur = priv->in_nextcontent_html;
+			len = priv->in_nextcontent_len;
+		}
+	} else {
+		func = "appendMessage";
+		if (empathy_contact_is_user (sender)) {
+			cur = priv->out_content_html;
+			len = priv->out_content_len;
+		} else {
+			cur = priv->in_content_html;
+			len = priv->in_content_len;
+		}
+	}
+
+	/* Make some search-and-replece in the html code */
+	prev = cur;
+	string = g_string_sized_new (len + strlen (body));
+	while ((cur = strchr (cur, '%'))) {
+		const gchar *replace = NULL;
+			
+		if (!strncmp (cur, "%message%", strlen ("%message%"))) {
+			replace = body;
+		} else if (!strncmp (cur, "%time", strlen("%time"))) {
+			replace = time;
+		} else if (!strncmp (cur, "%userIconPath%", strlen("%userIconPath%"))) {
+			replace = avatar;
+		} else if (!strncmp(cur, "%sender%", strlen("%sender%"))) {
+			replace = name;
+		} else {
+			cur++;
+			continue;
+		}
+
+		/* Here we have a replacement to make */
+		g_string_append_len (string, prev, cur - prev);
+		g_string_append (string, replace);
+
+		/* And update the pointers */
+		prev = cur = strchr (cur + 1, '%') + 1;
+	}
+	g_string_append (string, prev);
+
+	/* Execute a js to add the message */
+	cur = g_string_free (string, FALSE);
+	escape = theme_adium_escape (EMPATHY_THEME_ADIUM (view), cur);
+	script = g_strdup_printf("%s(\"%s\")", func, escape);
+	webkit_web_view_execute_script (WEBKIT_WEB_VIEW (view), script);
+
+	/* Keep the sender of the last displayed message */
+	if (priv->last_contact) {
+		g_object_unref (priv->last_contact);
+	}
+	priv->last_contact = g_object_ref (sender);
+
+	g_free (time);
+	g_free (avatar);
+	g_free (cur);
+	g_free (script);
 }
 
 static void
 theme_adium_append_event (EmpathyChatView *view,
 			  const gchar     *str)
 {
+	/* Not implemented */
 }
 
 static void
 theme_adium_scroll (EmpathyChatView *view,
 		    gboolean         allow_scrolling)
 {
+	/* Not implemented */
 }
 
 static gboolean
 theme_adium_get_has_selection (EmpathyChatView *view)
 {
+	/* Not implemented */
 	return FALSE;
 }
 
 static void
 theme_adium_clear (EmpathyChatView *view)
 {
+	/* Not implemented */
 }
 
 static gboolean
@@ -103,6 +290,7 @@ theme_adium_find_previous (EmpathyChatView *view,
 			   const gchar     *search_criteria,
 			   gboolean         new_search)
 {
+	/* Not implemented */
 	return FALSE;
 }
 
@@ -111,6 +299,7 @@ theme_adium_find_next (EmpathyChatView *view,
 		       const gchar     *search_criteria,
 		       gboolean         new_search)
 {
+	/* Not implemented */
 	return FALSE;
 }
 
@@ -120,17 +309,20 @@ theme_adium_find_abilities (EmpathyChatView *view,
 			    gboolean       *can_do_previous,
 			    gboolean       *can_do_next)
 {
+	/* Not implemented */
 }
 
 static void
 theme_adium_highlight (EmpathyChatView *view,
 		       const gchar     *text)
 {
+	/* Not implemented */
 }
 
 static void
 theme_adium_copy_clipboard (EmpathyChatView *view)
 {
+	/* Not implemented */
 }
 
 static void
@@ -149,6 +341,70 @@ theme_adium_iface_init (EmpathyChatViewIface *iface)
 	iface->copy_clipboard = theme_adium_copy_clipboard;
 }
 
+static void
+theme_adium_load_finished_cb (WebKitWebView  *view,
+			      WebKitWebFrame *frame,
+			      gpointer        user_data)
+{
+	EmpathyThemeAdiumPriv *priv = GET_PRIV (view);
+	EmpathyChatView       *chat_view = EMPATHY_CHAT_VIEW (view);
+
+	DEBUG ("Page loaded");
+	priv->ready = TRUE;
+
+	/* Display queued messages */
+	priv->message_queue = g_list_reverse (priv->message_queue);
+	while (priv->message_queue) {
+		EmpathyMessage *message = priv->message_queue->data;
+
+		theme_adium_append_message (chat_view, message);
+		priv->message_queue = g_list_remove (priv->message_queue, message);
+		g_object_unref (message);
+	}
+}
+
+static void
+theme_adium_finalize (GObject *object)
+{
+	EmpathyThemeAdiumPriv *priv = GET_PRIV (object);
+
+	g_free (priv->in_content_html);
+	g_free (priv->in_nextcontent_html);
+	g_free (priv->out_content_html);
+	g_free (priv->out_nextcontent_html);
+
+	if (priv->last_contact) {
+		g_object_unref (priv->last_contact);
+	}
+
+	G_OBJECT_CLASS (empathy_theme_adium_parent_class)->finalize (object);
+}
+
+static void
+empathy_theme_adium_class_init (EmpathyThemeAdiumClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	
+	object_class->finalize = theme_adium_finalize;
+
+	g_type_class_add_private (object_class, sizeof (EmpathyThemeAdiumPriv));
+}
+
+static void
+empathy_theme_adium_init (EmpathyThemeAdium *theme)
+{
+	EmpathyThemeAdiumPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (theme,
+		EMPATHY_TYPE_THEME_ADIUM, EmpathyThemeAdiumPriv);
+
+	theme->priv = priv;	
+
+	theme_adium_load (theme);
+
+	g_signal_connect (theme, "load-finished",
+			  G_CALLBACK (theme_adium_load_finished_cb),
+			  NULL);
+}
+
 EmpathyThemeAdium *
 empathy_theme_adium_new (void)
 {
diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c
index 01087c1..6800c8e 100644
--- a/libempathy/empathy-contact.c
+++ b/libempathy/empathy-contact.c
@@ -938,6 +938,18 @@ empathy_contact_load_avatar_cache (EmpathyContact *contact,
   return data != NULL;
 }
 
+gchar *
+empathy_contact_get_avatar_filename (EmpathyContact *contact)
+{
+  EmpathyContactPriv *priv = GET_PRIV (contact);
+
+  if (priv->avatar)
+      return contact_get_avatar_filename (contact, priv->avatar->token);
+
+  return NULL;
+}
+
+
 GType
 empathy_avatar_get_type (void)
 {
diff --git a/libempathy/empathy-contact.h b/libempathy/empathy-contact.h
index ff8d426..0d02dab 100644
--- a/libempathy/empathy-contact.h
+++ b/libempathy/empathy-contact.h
@@ -107,6 +107,7 @@ void empathy_contact_load_avatar_data (EmpathyContact *contact,
     const gchar *token);
 gboolean empathy_contact_load_avatar_cache (EmpathyContact *contact,
     const gchar *token);
+gchar * empathy_contact_get_avatar_filename (EmpathyContact *contact);
 
 
 #define EMPATHY_TYPE_AVATAR (empathy_avatar_get_type ())



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]