changeset 15518:b15cc37605c4

In Pidgin, display a full date on the timestamp of the first message to cross the boundary into a new day. Sean and various users want this. I think I'm finally going to admit it's a decent idea. I've also refactored plenty of code related to the conversation-timestamp and log-timestamp signals. This breaks API compatibility, but I'm pretty sure the only plugin that uses those signals is the Message Timestamps plugin that we ship. The changes eliminate duplicated code between the core/UI and the plugin.
author Richard Laager <rlaager@wiktel.com>
date Sat, 03 Feb 2007 20:28:41 +0000
parents 75ffc646647f
children 9c32176ac555
files libpurple/log.c libpurple/signals.c libpurple/signals.h pidgin/gtkconv.c pidgin/gtkconv.h pidgin/plugins/timestamp_format.c
diffstat 6 files changed, 92 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/log.c	Sat Feb 03 18:46:49 2007 +0000
+++ b/libpurple/log.c	Sat Feb 03 20:28:41 2007 +0000
@@ -595,9 +595,9 @@
 
 	gaim_signal_register(handle, "log-timestamp",
 #if SIZEOF_TIME_T == 4
-	                     gaim_marshal_POINTER__POINTER_INT,
+	                     gaim_marshal_POINTER__POINTER_INT_BOOLEAN,
 #elif SIZEOF_TIME_T == 8
-			     gaim_marshal_POINTER__POINTER_INT64,
+			     gaim_marshal_POINTER__POINTER_INT64_BOOLEAN,
 #else
 #error Unknown size of time_t
 #endif
@@ -605,12 +605,13 @@
 	                     gaim_value_new(GAIM_TYPE_SUBTYPE,
 	                                    GAIM_SUBTYPE_LOG),
 #if SIZEOF_TIME_T == 4
-	                     gaim_value_new(GAIM_TYPE_INT));
+	                     gaim_value_new(GAIM_TYPE_INT),
 #elif SIZEOF_TIME_T == 8
-	                     gaim_value_new(GAIM_TYPE_INT64));
+	                     gaim_value_new(GAIM_TYPE_INT64),
 #else
 # error Unknown size of time_t
 #endif
+	                     gaim_value_new(GAIM_TYPE_BOOLEAN));
 
 	gaim_prefs_connect_callback(NULL, "/core/logging/format",
 							    logger_pref_cb, NULL);
@@ -633,17 +634,20 @@
 
 static char *log_get_timestamp(GaimLog *log, time_t when)
 {
+	gboolean show_date;
 	char *date;
 	struct tm tm;
 
+	show_date = (log->type == GAIM_LOG_SYSTEM) || (time(NULL) > when + 20*60);
+
 	date = gaim_signal_emit_return_1(gaim_log_get_handle(),
 	                          "log-timestamp",
-	                          log, when);
+	                          log, when, show_date);
 	if (date != NULL)
 		return date;
 
 	tm = *(localtime(&when));
-	if (log->type == GAIM_LOG_SYSTEM || time(NULL) > when + 20*60)
+	if (show_date)
 		return g_strdup(gaim_date_format_long(&tm));
 	else
 		return g_strdup(gaim_time_format(&tm));
--- a/libpurple/signals.c	Sat Feb 03 18:46:49 2007 +0000
+++ b/libpurple/signals.c	Sat Feb 03 20:28:41 2007 +0000
@@ -976,6 +976,38 @@
 }
 
 void
+gaim_marshal_POINTER__POINTER_INT_BOOLEAN(
+                                    GaimCallback cb, va_list args, void *data,
+                                    void **return_val)
+{
+	gpointer ret_val;
+	void *arg1 = va_arg(args, void *);
+	gint arg2 = va_arg(args, gint);
+	gboolean arg3 = va_arg(args, gboolean);
+
+	ret_val = ((gpointer(*)(void *, gint, gboolean, void *))cb)(arg1, arg2, arg3, data);
+
+	if (return_val != NULL)
+		*return_val = ret_val;
+}
+
+void
+gaim_marshal_POINTER__POINTER_INT64_BOOLEAN(
+                                    GaimCallback cb, va_list args, void *data,
+                                    void **return_val)
+{
+	gpointer ret_val;
+	void *arg1 = va_arg(args, void *);
+	gint64 arg2 = va_arg(args, gint64);
+	gboolean arg3 = va_arg(args, gboolean);
+
+	ret_val = ((gpointer(*)(void *, gint64, gboolean, void *))cb)(arg1, arg2, arg3, data);
+
+	if (return_val != NULL)
+		*return_val = ret_val;
+}
+
+void
 gaim_marshal_POINTER__POINTER_POINTER(GaimCallback cb, va_list args, void *data,
                                       void **return_val)
 {
--- a/libpurple/signals.h	Sat Feb 03 18:46:49 2007 +0000
+++ b/libpurple/signals.h	Sat Feb 03 20:28:41 2007 +0000
@@ -331,6 +331,10 @@
 		GaimCallback cb, va_list args, void *data, void **return_val);
 void gaim_marshal_POINTER__POINTER_INT64(
 		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_POINTER__POINTER_INT_BOOLEAN(
+		GaimCallback cb, va_list args, void *data, void **return_val);
+void gaim_marshal_POINTER__POINTER_INT64_BOOLEAN(
+		GaimCallback cb, va_list args, void *data, void **return_val);
 void gaim_marshal_POINTER__POINTER_POINTER(
 		GaimCallback cb, va_list args, void *data, void **return_val);
 /*@}*/
--- a/pidgin/gtkconv.c	Sat Feb 03 18:46:49 2007 +0000
+++ b/pidgin/gtkconv.c	Sat Feb 03 20:28:41 2007 +0000
@@ -4810,6 +4810,16 @@
 	return buddytag;
 }
 
+static void pidgin_conv_calculate_newday(PidginConversation *gtkconv, time_t mtime)
+{
+	struct tm *tm = localtime(&mtime);
+
+	tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
+	tm->tm_mday++;
+
+	gtkconv->newday = mktime(tm);
+}
+
 static void
 pidgin_conv_write_conv(GaimConversation *conv, const char *name, const char *alias,
 						const char *message, GaimMessageFlags flags,
@@ -4825,6 +4835,7 @@
 	int max_scrollback_lines;
 	int line_count;
 	char buf2[BUF_LONG];
+	gboolean show_date;
 	char *mdate;
 	char color[10];
 	char *str;
@@ -4932,18 +4943,30 @@
 	if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml))))
 		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", gtk_font_options_all);
 
+	/* First message in a conversation. */
+	if (gtkconv->newday == 0)
+		pidgin_conv_calculate_newday(gtkconv, mtime);
+
+	/* Show the date on the first message in a new day, or if the message is
+	 * older than 20 minutes. */
+	show_date = (mtime >= gtkconv->newday) || (time(NULL) > mtime + 20*60);
+
 	mdate = gaim_signal_emit_return_1(pidgin_conversations_get_handle(),
 	                                  "conversation-timestamp",
-	                                  conv, mtime);
+	                                  conv, mtime, show_date);
+
 	if (mdate == NULL)
 	{
 		struct tm *tm = localtime(&mtime);
-		if (time(NULL) > mtime + 20*60) /* show date if older than 20 minutes */
+		if (show_date)
 			mdate = g_strdup(gaim_date_format_long(tm));
 		else
 			mdate = g_strdup(gaim_time_format(tm));
 	}
 
+	if (mtime >= gtkconv->newday)
+		pidgin_conv_calculate_newday(gtkconv, mtime);
+
 	sml_attrib = g_strdup_printf("sml=\"%s\"", gaim_account_get_protocol_name(account));
 
 	gtk_font_options |= GTK_IMHTML_NO_COMMENTS;
@@ -6778,22 +6801,23 @@
 
 	gaim_signal_register(handle, "conversation-timestamp",
 #if SIZEOF_TIME_T == 4
-	                     gaim_marshal_POINTER__POINTER_INT,
+	                     gaim_marshal_POINTER__POINTER_INT_BOOLEAN,
 #elif SIZEOF_TIME_T == 8
-			     gaim_marshal_POINTER__POINTER_INT64,
+			     gaim_marshal_POINTER__POINTER_INT64_BOOLEAN,
 #else
 #error Unkown size of time_t
 #endif
-	                     gaim_value_new(GAIM_TYPE_POINTER), 2,
+	                     gaim_value_new(GAIM_TYPE_POINTER), 3,
 	                     gaim_value_new(GAIM_TYPE_SUBTYPE,
 	                                    GAIM_SUBTYPE_CONVERSATION),
 #if SIZEOF_TIME_T == 4
-	                     gaim_value_new(GAIM_TYPE_INT));
+	                     gaim_value_new(GAIM_TYPE_INT),
 #elif SIZEOF_TIME_T == 8
-	                     gaim_value_new(GAIM_TYPE_INT64));
+	                     gaim_value_new(GAIM_TYPE_INT64),
 #else
 # error Unknown size of time_t
 #endif
+	                     gaim_value_new(GAIM_TYPE_BOOLEAN));
 
 	gaim_signal_register(handle, "displaying-im-msg",
 						 gaim_marshal_BOOLEAN__POINTER_POINTER_POINTER_POINTER_POINTER,
--- a/pidgin/gtkconv.h	Sat Feb 03 18:46:49 2007 +0000
+++ b/pidgin/gtkconv.h	Sat Feb 03 20:28:41 2007 +0000
@@ -155,6 +155,8 @@
 		PidginChatPane *chat;
 
 	} u;
+
+	time_t newday;
 };
 
 /*@}*/
--- a/pidgin/plugins/timestamp_format.c	Sat Feb 03 18:46:49 2007 +0000
+++ b/pidgin/plugins/timestamp_format.c	Sat Feb 03 20:28:41 2007 +0000
@@ -53,18 +53,18 @@
 
 static char *timestamp_cb_common(GaimConversation *conv,
                                  time_t t,
+                                 gboolean show_date,
                                  gboolean force,
                                  const char *dates)
 {
-	struct tm *tm = localtime(&t);
 	g_return_val_if_fail(conv != NULL, NULL);
 	g_return_val_if_fail(dates != NULL, NULL);
 
-	if (!strcmp(dates, "always") ||
-	    (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT &&
-	     !strcmp(dates, "chats")) ||
-	    (time(NULL) > (mktime(tm) + 20*60)))
+	if (show_date ||
+	    !strcmp(dates, "always") ||
+	    (gaim_conversation_get_type(conv) == GAIM_CONV_TYPE_CHAT && !strcmp(dates, "chats")))
 	{
+		struct tm *tm = localtime(&t);
 		if (force)
 			return g_strdup(gaim_utf8_strftime("%Y-%m-%d %H:%M:%S", tm));
 		else
@@ -72,13 +72,16 @@
 	}
 
 	if (force)
+	{
+		struct tm *tm = localtime(&t);
 		return g_strdup(gaim_utf8_strftime("%H:%M:%S", tm));
+	}
 
 	return NULL;
 }
 
 static char *conversation_timestamp_cb(GaimConversation *conv,
-                                       time_t t, gpointer data)
+                                       time_t t, gboolean show_date, gpointer data)
 {
 	gboolean force = gaim_prefs_get_bool(
 				"/plugins/gtk/timestamp_format/force_24hr");
@@ -87,10 +90,10 @@
 
 	g_return_val_if_fail(conv != NULL, NULL);
 
-	return timestamp_cb_common(conv, t, force, dates);
+	return timestamp_cb_common(conv, t, show_date, force, dates);
 }
 
-static char *log_timestamp_cb(GaimLog *log, time_t t, gpointer data)
+static char *log_timestamp_cb(GaimLog *log, time_t t, gboolean show_date, gpointer data)
 {
 	gboolean force = gaim_prefs_get_bool(
 				"/plugins/gtk/timestamp_format/force_24hr");
@@ -99,17 +102,7 @@
 
 	g_return_val_if_fail(log != NULL, NULL);
 
-	if (log->type == GAIM_LOG_SYSTEM)
-	{
-		if (force) {
-			struct tm *tm = localtime(&t);
-			return g_strdup(gaim_utf8_strftime("%Y-%m-%d %H:%M:%S", tm));
-		} else {
-			return NULL;
-		}
-	}
-
-	return timestamp_cb_common(log->conv, t, force, dates);
+	return timestamp_cb_common(log->conv, t, show_date, force, dates);
 }
 
 static gboolean
@@ -140,7 +133,7 @@
 	GAIM_MAJOR_VERSION,
 	GAIM_MINOR_VERSION,
 	GAIM_PLUGIN_STANDARD,                             /**< type           */
-	PIDGIN_PLUGIN_TYPE,                             /**< ui_requirement */
+	PIDGIN_PLUGIN_TYPE,                               /**< ui_requirement */
 	0,                                                /**< flags          */
 	NULL,                                             /**< dependencies   */
 	GAIM_PRIORITY_DEFAULT,                            /**< priority       */