/soc/2015/igor.gajowiak/chatlog: ad0758165399: Implemented showi...

Igor Gajowiak igor.gajowiak at gmail.com
Fri Jul 31 15:59:53 EDT 2015


Changeset: ad07581653998b3cd64ebd893ce1e63efd5cbca0
Author:	 Igor Gajowiak <igor.gajowiak at gmail.com>
Date:	 2015-07-31 21:59 +0200
Branch:	 default
URL: https://hg.pidgin.im/soc/2015/igor.gajowiak/chatlog/rev/ad0758165399

Description:

Implemented showing messages in log.

diffstat:

 pidgin/gtkgenericlog.c      |  316 ++++++++++++++++++++++++++++++++++++++++---
 pidgin/gtkgenericlog.h      |    3 +
 pidgin/themes/Template.html |    5 +
 3 files changed, 301 insertions(+), 23 deletions(-)

diffs (truncated from 441 to 300 lines):

diff --git a/pidgin/gtkgenericlog.c b/pidgin/gtkgenericlog.c
--- a/pidgin/gtkgenericlog.c
+++ b/pidgin/gtkgenericlog.c
@@ -19,6 +19,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
 
+#include <string.h>
+
 #include <sys/time.h>
 
 #include "buddylist.h"
@@ -243,25 +245,24 @@ on_buddylist_row_changed(GtkTreeSelectio
 	GtkTreeModel *model;
 	GtkTreeIter row;
 
-	/* No buddy selected */
-	if (!gtk_tree_selection_get_selected(sel, &model, &row)) {
-		gtk_tree_store_clear(viewer->calendar_tree_store);
-		return;
+	PurpleBuddy *buddy = NULL;
+
+	if (gtk_tree_selection_get_selected(sel, &model, &row)) {
+		gtk_tree_model_get(model, &row, BLIST_TREE_STORE_COL_BUDDY, &buddy, -1);
+
+		if (buddy) {
+			g_object_ref(G_OBJECT(buddy));
+			viewer->current_buddy = buddy;
+		}
 	}
 
-	gpointer buddy = NULL;
-	gtk_tree_model_get(model, &row, BLIST_TREE_STORE_COL_BUDDY, &buddy, -1);
+	/* Unhook calendar model during updating to get better performance */
+	gtk_tree_view_set_model(viewer->calendar_tree_view, NULL);
 
-	/* Group row activated */
-	if (!buddy) {
-		gtk_tree_store_clear(viewer->calendar_tree_store);
-		return;
-	}
+	populate_calendar_store(buddy, viewer->calendar_tree_store);
 
-	g_object_ref(buddy);
-	viewer->current_buddy = buddy;
-
-	populate_calendar_store((PurpleBuddy*) buddy, viewer->calendar_tree_store);
+	gtk_tree_view_set_model(viewer->calendar_tree_view,
+		viewer->calendar_tree_store);
 }
 
 static void
@@ -365,13 +366,202 @@ static void
 on_calendar_row_activated(GtkTreeView *tv, GtkTreePath *path,
 	GtkTreeViewColumn *col, gpointer data)
 {
-	printf("on_calendar_row_activated\n");
+	toggle_row_expansion(tv, path);
 }
 
+/* TODO: Copied from gtkconv.c, try to refactor */
+static char *
+replace_message_tokens(
+	const char *text,
+	const char *messageId,
+	const char *name, /* author */
+	const char *alias, /* author's alias */
+	const char *message,
+	PurpleMessageFlags flags,
+	time_t mtime)
+{
+	GString *str;
+	const char *cur = text;
+	const char *prev = cur;
+	struct tm *tm = NULL;
+
+	if (text == NULL || *text == '\0')
+		return NULL;
+
+	str = g_string_new(NULL);
+	while ((cur = strchr(cur, '%'))) {
+		const char *replace = NULL;
+		const char *fin = NULL;
+		gpointer freeval = NULL;
+
+		if (g_str_has_prefix(cur, "%message%")) {
+			replace = message;
+
+		} else if (g_str_has_prefix(cur, "%messageClasses%")) {
+			char *user;
+			GString *classes = g_string_new(NULL);
+#define ADD_CLASS(f, class) \
+			if (flags & f) \
+				g_string_append(classes, class);
+			ADD_CLASS(PURPLE_MESSAGE_SEND, "outgoing ");
+			ADD_CLASS(PURPLE_MESSAGE_RECV, "incoming ");
+#undef ADD_CLASS
+			user = g_strconcat("-pidgin-user:", name, NULL);
+			g_string_append(classes, user);
+			g_free(user);
+
+			replace = freeval = g_string_free(classes, FALSE);
+
+		} else if (g_str_has_prefix(cur, "%time")) {
+			const char *tmp = cur + strlen("%time");
+
+			if (*tmp == '{') {
+				char *end;
+				tmp++;
+				end = strstr(tmp, "}%");
+				if (!end) /* Invalid string */
+					continue;
+				if (!tm)
+					tm = localtime(&mtime);
+				replace = freeval = purple_uts35_to_str(tmp, end - tmp, tm);
+				fin = end + 1;
+			} else {
+				if (!tm)
+					tm = localtime(&mtime);
+
+				replace = purple_utf8_strftime("%X", tm);
+			}
+
+		} else if (g_str_has_prefix(cur, "%shortTime%")) {
+			if (!tm)
+				tm = localtime(&mtime);
+
+			replace = purple_utf8_strftime("%H:%M", tm);
+		} else if (g_str_has_prefix(cur, "%senderScreenName%")) {
+			replace = name;
+
+		} else if (g_str_has_prefix(cur, "%sender%")) {
+			replace = alias;
+
+		} else if (g_str_has_prefix(cur, "%senderColor%")) {
+			replace = freeval = flags & PURPLE_MESSAGE_RECV ?
+				g_strdup("#000000") : g_strdup("#ed3240");
+		} else if (g_str_has_prefix(cur, "%messageDirection%")) {
+			replace = purple_markup_is_rtl(message) ? "rtl" : "ltr";
+
+		} else if (g_str_has_prefix(cur, "%status%")) {
+			GString *classes = g_string_new(NULL);
+
+			if (flags & PURPLE_MESSAGE_ERROR)
+				g_string_append(classes, "error ");
+
+			replace = freeval = g_string_free(classes, FALSE);
+		} else if (g_str_has_prefix(cur, "%messageId%")) {
+			replace = messageId;
+		} else {
+			cur++;
+			continue;
+		}
+
+		/* Here we have a replacement to make */
+		g_string_append_len(str, prev, cur - prev);
+		if (replace)
+			g_string_append(str, replace);
+		g_free(freeval);
+		replace = freeval = NULL;
+
+		/* And update the pointers */
+		if (fin) {
+			prev = cur = fin + 1;
+		} else {
+			prev = cur = strchr(cur + 1, '%') + 1;
+		}
+
+	}
+
+	/* And wrap it up */
+	g_string_append(str, prev);
+
+	return g_string_free(str, FALSE);
+}
+
+static gchar *
+prepare_script(PurpleMessage *msg, PidginConvTheme *theme)
+{
+	PurpleMessageFlags flags = purple_message_get_flags(msg);
+
+	const char *message_html = flags & PURPLE_MESSAGE_SEND ?
+		pidgin_conversation_theme_get_template(theme,
+			PIDGIN_CONVERSATION_THEME_TEMPLATE_OUTGOING_CONTENT) :
+		pidgin_conversation_theme_get_template(theme,
+			PIDGIN_CONVERSATION_THEME_TEMPLATE_INCOMING_CONTENT);
+
+	char *message_id = g_strdup_printf("%u", purple_message_get_id(msg));
+	char *msg_tokenized = replace_message_tokens(message_html,
+		message_id,
+		purple_message_get_author(msg),
+		purple_message_get_author_alias(msg),
+		purple_message_get_contents(msg),
+		flags,
+		purple_message_get_time(msg));
+	char *escape = pidgin_webview_quote_js_string(msg_tokenized ?
+		msg_tokenized : "");
+
+	char *script = g_strdup_printf("appendMessage(%s)", escape);
+
+	g_free(message_id);
+	g_free(msg_tokenized);
+	g_free(escape);
+
+	return script;
+}
+
+static void
+clear_webview(PidginWebView *webview);
+
 static void
 on_calendar_row_changed(GtkTreeSelection *sel, gpointer data)
 {
-	printf("on_calendar_row_changed\n");
+	PidginGenericLogViewer *viewer = (PidginGenericLogViewer*) data;
+
+	clear_webview(PIDGIN_WEBVIEW(viewer->webview));
+
+	/* No buddy selected */
+	if (!viewer->current_buddy)
+		return;
+
+	GtkTreeModel *model;
+	GtkTreeIter row;
+
+	/* No row selected */
+	if (!gtk_tree_selection_get_selected(sel, &model, &row))
+		return;
+
+	/* Row with year selected */
+	if (gtk_tree_path_get_depth(gtk_tree_model_get_path(model, &row)) == 1)
+		return;
+
+	guint64 day;
+	gtk_tree_model_get(model, &row, CALENDAR_TREE_STORE_COL_DATE, &day, -1);
+
+	GList *messages = NULL;
+	if (!purple_genericlog_get_all_msgs(viewer->current_buddy,
+		day, &messages, NULL)) {
+		purple_debug_error(GTKGENERICLOG_DEBUG_CATEGORY,
+			"Getting all messages failed");
+		return;
+	}
+
+	/* Fill webview */
+	for (GList *it = messages; it != NULL; it = it->next) {
+		gchar *script = prepare_script(PURPLE_MESSAGE(it->data), viewer->theme);
+
+		pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(viewer->webview),
+			script);
+
+		g_free(script);
+	}
+	g_list_free_full(messages, g_object_unref);
 }
 
 static gboolean
@@ -410,11 +600,13 @@ append_new_calendar_group(GtkTreeStore *
 static void
 populate_calendar_store(PurpleBuddy *buddy, GtkTreeStore *store)
 {
-	g_assert(buddy);
 	g_assert(store);
 
 	gtk_tree_store_clear(store);
 
+	if (!buddy)
+		return;
+
 	GArray *days;
 	if (!purple_genericlog_get_all_days(buddy, &days, NULL)) {
 		purple_debug_error(GTKGENERICLOG_DEBUG_CATEGORY,
@@ -488,12 +680,86 @@ create_calendar_view(GtkTreeStore *store
 /* Webview                                                                    */
 /******************************************************************************/
 
-static GtkWidget *
-create_webview(GtkWidget **webview, PidginGenericLogViewer *viewer)
+/* TODO: Copied from gtkconv.c, try to refactor */
+static char *
+replace_template_tokens(PidginConvTheme *theme, const char *header,
+	const char *footer)
+{
+	GString *str;
+	const char *text;
+	char **ms;
+	char *path;
+
+	text = pidgin_conversation_theme_get_template(theme,
+		PIDGIN_CONVERSATION_THEME_TEMPLATE_MAIN);
+	if (text == NULL)
+		return NULL;
+
+	ms = g_strsplit(text, "%@", 6);
+	if (ms[0] == NULL || ms[1] == NULL || ms[2] == NULL || ms[3] == NULL ||
+		ms[4] == NULL || ms[5] == NULL) {
+		g_strfreev(ms);
+		return NULL;
+	}
+



More information about the Commits mailing list