/dev/tomkiewicz/new-smileys: d91c44b4a8e6: Remote smileys: corre...

Tomasz Wasilczyk twasilczyk at pidgin.im
Fri Apr 4 15:09:25 EDT 2014


Changeset: d91c44b4a8e6402fade3eb2ec8f61d6d7b6cc65e
Author:	 Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date:	 2014-04-04 21:09 +0200
Branch:	 default
URL: https://hg.pidgin.im/dev/tomkiewicz/new-smileys/rev/d91c44b4a8e6

Description:

Remote smileys: correctly handle failed smileys

diffstat:

 libpurple/conversation.c  |   5 +++-
 libpurple/smiley-list.c   |  49 ++++++++++++++++++++++++++++++++++++++++++----
 libpurple/smiley-parser.h |   3 ++
 libpurple/smiley-remote.c |  35 ++++++++++-----------------------
 libpurple/smiley.c        |   2 +-
 5 files changed, 63 insertions(+), 31 deletions(-)

diffs (250 lines):

diff --git a/libpurple/conversation.c b/libpurple/conversation.c
--- a/libpurple/conversation.c
+++ b/libpurple/conversation.c
@@ -954,8 +954,11 @@ purple_conversation_add_remote_smiley(Pu
 	g_return_val_if_fail(shortcut != NULL, NULL);
 	g_return_val_if_fail(shortcut[0] != '\0', NULL);
 
-	if (priv->remote_smileys == NULL)
+	if (priv->remote_smileys == NULL) {
 		priv->remote_smileys = purple_smiley_list_new();
+		g_object_set(priv->remote_smileys,
+			"drop-failed-remotes", TRUE, NULL);
+	}
 
 	smiley = purple_smiley_list_get_by_shortcut(
 		priv->remote_smileys, shortcut);
diff --git a/libpurple/smiley-list.c b/libpurple/smiley-list.c
--- a/libpurple/smiley-list.c
+++ b/libpurple/smiley-list.c
@@ -36,14 +36,19 @@ typedef struct {
 	PurpleTrie *trie;
 	GHashTable *path_map;
 	GHashTable *shortcut_map;
+
+	gboolean drop_failed_remotes;
 } PurpleSmileyListPrivate;
 
 enum
 {
 	PROP_0,
+	PROP_DROP_FAILED_REMOTES,
 	PROP_LAST
 };
 
+static GParamSpec *properties[PROP_LAST];
+
 static void
 _list_append2(GList **head_p, GList **tail_p, gpointer data)
 {
@@ -90,6 +95,18 @@ purple_smiley_list_new(void)
 	return g_object_new(PURPLE_TYPE_SMILEY_LIST, NULL);
 }
 
+static void
+remote_smiley_failed(PurpleSmiley *smiley, gpointer _list)
+{
+	PurpleSmileyList *list = _list;
+
+	purple_debug_info("smiley-list", "remote smiley '%s' has failed, "
+		"removing it from the list...",
+		purple_smiley_get_shortcut(smiley));
+
+	purple_smiley_list_remove(list, smiley);
+}
+
 gboolean
 purple_smiley_list_add(PurpleSmileyList *list, PurpleSmiley *smiley)
 {
@@ -129,9 +146,18 @@ purple_smiley_list_add(PurpleSmileyList 
 
 	g_hash_table_insert(priv->shortcut_map, g_strdup(shortcut), smiley);
 
+	/* We don't expect non-remote non-ready smileys, but let's check it just
+	 * to be safe. */
+	if (priv->drop_failed_remotes && !purple_smiley_is_ready(smiley) &&
+		PURPLE_IS_REMOTE_SMILEY(smiley))
+	{
+		g_signal_connect_object(smiley, "failed",
+			G_CALLBACK(remote_smiley_failed), list, 0);
+	}
+
 	smiley_path = purple_smiley_get_path(smiley);
 
-	/* TODO: add to the table, when smiley sets the path */
+	/* TODO: add to the table, when the smiley sets the path */
 	if (!smiley_path)
 		return TRUE;
 
@@ -293,9 +319,10 @@ purple_smiley_list_get_property(GObject 
 	PurpleSmileyList *sl = PURPLE_SMILEY_LIST(object);
 	PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(sl);
 
-	(void)priv;
-
 	switch (par_id) {
+		case PROP_DROP_FAILED_REMOTES:
+			g_value_set_boolean(value, priv->drop_failed_remotes);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
 			break;
@@ -309,9 +336,13 @@ purple_smiley_list_set_property(GObject 
 	PurpleSmileyList *sl = PURPLE_SMILEY_LIST(object);
 	PurpleSmileyListPrivate *priv = PURPLE_SMILEY_LIST_GET_PRIVATE(sl);
 
-	(void)priv;
-
 	switch (par_id) {
+		case PROP_DROP_FAILED_REMOTES:
+			priv->drop_failed_remotes = g_value_get_boolean(value);
+			/* XXX: we could scan for remote smiley's on our list
+			 * and change the setting, but we don't care that much.
+			 */
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
 			break;
@@ -328,6 +359,14 @@ purple_smiley_list_class_init(PurpleSmil
 	gobj_class->get_property = purple_smiley_list_get_property;
 	gobj_class->set_property = purple_smiley_list_set_property;
 	gobj_class->finalize = purple_smiley_list_finalize;
+
+	properties[PROP_DROP_FAILED_REMOTES] = g_param_spec_boolean(
+		"drop-failed-remotes", "Drop failed PurpleRemoteSmileys",
+		"Watch added remote smileys and remove them from the list, "
+		"if they change their state to failed", FALSE,
+		G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties(gobj_class, PROP_LAST, properties);
 }
 
 GType
diff --git a/libpurple/smiley-parser.h b/libpurple/smiley-parser.h
--- a/libpurple/smiley-parser.h
+++ b/libpurple/smiley-parser.h
@@ -35,6 +35,9 @@ purple_smiley_parse_escape(void);
  * For outgoing, we could pass conv in ui_data (or something).
  *
  * @ui_data is passed to @cb and #purple_smiley_theme_get_smileys.
+ *
+ * XXX: we might not want to display remote smileys for
+ * outgoing messages. To be considered.
  */
 gchar *
 purple_smiley_parse(PurpleConversation *conv, const gchar *message,
diff --git a/libpurple/smiley-remote.c b/libpurple/smiley-remote.c
--- a/libpurple/smiley-remote.c
+++ b/libpurple/smiley-remote.c
@@ -36,13 +36,12 @@ typedef struct {
 	gboolean failed;
 } PurpleRemoteSmileyPrivate;
 
-#if 0
 enum
 {
 	PROP_0,
+	PROP_FAILED,
 	PROP_LAST
 };
-#endif
 
 enum
 {
@@ -53,9 +52,7 @@ enum
 static GObjectClass *parent_class;
 
 static guint signals[SIG_LAST];
-#if 0
 static GParamSpec *properties[PROP_LAST];
-#endif
 
 /******************************************************************************
  * API implementation
@@ -119,7 +116,8 @@ purple_remote_smiley_failed(PurpleRemote
 	if (priv->failed)
 		return;
 
-	g_object_set(smiley, "failed", TRUE, NULL);
+	priv->failed = TRUE;
+	g_object_notify_by_pspec(G_OBJECT(smiley), properties[PROP_FAILED]);
 	g_signal_emit(smiley, signals[SIG_FAILED], 0);
 }
 
@@ -155,6 +153,7 @@ purple_remote_smiley_init(GTypeInstance 
 		PURPLE_REMOTE_SMILEY_GET_PRIVATE(smiley);
 
 	priv->contents = g_string_new(NULL);
+	priv->failed = FALSE;
 }
 
 static void
@@ -172,7 +171,6 @@ purple_remote_smiley_finalize(GObject *o
 	G_OBJECT_CLASS(parent_class)->finalize(obj);
 }
 
-#if 0
 static void
 purple_remote_smiley_get_property(GObject *object, guint par_id, GValue *value,
 	GParamSpec *pspec)
@@ -181,6 +179,9 @@ purple_remote_smiley_get_property(GObjec
 	PurpleRemoteSmileyPrivate *priv = PURPLE_REMOTE_SMILEY_GET_PRIVATE(remote_smiley);
 
 	switch (par_id) {
+		case PROP_FAILED:
+			g_value_set_boolean(value, priv->failed);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
 			break;
@@ -188,21 +189,6 @@ purple_remote_smiley_get_property(GObjec
 }
 
 static void
-purple_remote_smiley_set_property(GObject *object, guint par_id, const GValue *value,
-	GParamSpec *pspec)
-{
-	PurpleRemoteSmiley *remote_smiley = PURPLE_REMOTE_SMILEY(object);
-	PurpleRemoteSmileyPrivate *priv = PURPLE_REMOTE_SMILEY_GET_PRIVATE(remote_smiley);
-
-	switch (par_id) {
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
-			break;
-	}
-}
-#endif
-
-static void
 purple_remote_smiley_class_init(PurpleRemoteSmileyClass *klass)
 {
 	GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
@@ -216,12 +202,13 @@ purple_remote_smiley_class_init(PurpleRe
 
 	ps_class->get_image = purple_remote_smiley_get_image_impl;
 
-#if 0
 	gobj_class->get_property = purple_remote_smiley_get_property;
-	gobj_class->set_property = purple_remote_smiley_set_property;
+
+	properties[PROP_FAILED] = g_param_spec_boolean("failed", "Failed",
+		"The remote host has failed to send the smiley", FALSE,
+		G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
 	g_object_class_install_properties(gobj_class, PROP_LAST, properties);
-#endif
 
 	signals[SIG_FAILED] = g_signal_new("failed", G_OBJECT_CLASS_TYPE(klass),
 		0, 0, NULL, NULL,
diff --git a/libpurple/smiley.c b/libpurple/smiley.c
--- a/libpurple/smiley.c
+++ b/libpurple/smiley.c
@@ -240,7 +240,7 @@ purple_smiley_class_init(PurpleSmileyCla
 		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
 	properties[PROP_IS_READY] = g_param_spec_boolean("is-ready", "Is ready",
-		"The full path to the smiley image file", TRUE,
+		"The smiley is ready to be displayed", TRUE,
 		G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
 
 	properties[PROP_PATH] = g_param_spec_string("path", "Path",



More information about the Commits mailing list