# HG changeset patch
# Node ID 29bbc75917a1
# Parent  b45add2a840c
diff --git a/ChangeLog.API b/ChangeLog.API
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -135,6 +135,7 @@
 		* purple_plugin_pref_set_type renamed to
 		  purple_plugin_pref_set_pref_type
 		* purple_prefs_get_type renamed to purple_prefs_get_pref_type
+		* purple_presence_set_idle no longer takes timestamp.
 		* proto_chat_entry has been renamed to PurpleProtocolChatEntry
 		* PurpleProxyType members are now name spaced under PURPLE_PROXY_TYPE_*
 		* purple_proxy_info_get_host renamed to purple_proxy_info_get_hostname
diff --git a/libpurple/plugins/idle/idle.c b/libpurple/plugins/idle/idle.c
--- a/libpurple/plugins/idle/idle.c
+++ b/libpurple/plugins/idle/idle.c
@@ -55,34 +55,36 @@
 }
 
 static void
-set_idle_time(PurpleAccount *acct, int mins_idle)
-{
+set_idle_time(PurpleAccount *acct, int mins_idle) {
 	PurpleConnection *gc = purple_account_get_connection(acct);
 	PurpleContactInfo *info = PURPLE_CONTACT_INFO(acct);
 	PurplePresence *presence = purple_account_get_presence(acct);
 	GDateTime *idle_since = NULL;
-	gboolean idle = FALSE;
 
-	if (!gc)
+	if(!gc) {
 		return;
+	}
 
 	purple_debug_info("idle", "setting idle time for %s to %d\n",
 	                  purple_contact_info_get_username(info), mins_idle);
 
-	idle = mins_idle > 0;
-
-	if(idle) {
+	if(mins_idle > 0) {
 		GDateTime *now = g_date_time_new_now_local();
 		idle_since = g_date_time_add_minutes(now, -1 * mins_idle);
 		g_date_time_unref(now);
 	}
 
-	purple_presence_set_idle(presence, idle, idle_since);
+	purple_presence_set_idle_time(presence, idle_since);
 
 	g_clear_pointer(&idle_since, g_date_time_unref);
 }
 
 static void
+set_idle_time_cb(gpointer data, gpointer user_data) {
+	set_idle_time(data, GPOINTER_TO_INT(user_data));
+}
+
+static void
 idle_action_ok(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
 	PurpleAccount *acct = purple_request_page_get_account(page, "acct");
 	PurpleContactInfo *info = PURPLE_CONTACT_INFO(acct);
@@ -255,7 +257,7 @@
 {
 	/* freeing the list here will cause segfaults if the user idles an account
 	 * after the list is freed */
-	g_list_foreach(idled_accts, (GFunc)set_idle_time, GINT_TO_POINTER(0));
+	g_list_foreach(idled_accts, set_idle_time_cb, GINT_TO_POINTER(0));
 	g_clear_list(&idled_accts, NULL);
 }
 
diff --git a/libpurple/purplepresence.h b/libpurple/purplepresence.h
--- a/libpurple/purplepresence.h
+++ b/libpurple/purplepresence.h
@@ -89,32 +89,11 @@
 
 G_BEGIN_DECLS
 
-/**
- * PurplePresenceClass:
- * @update_idle: Updates the logs and the UI when the idle state or time of the
- *               presence changes.
- *
- * The base class for all #PurplePresence's.
- *
- * Since: 3.0
- */
-struct _PurplePresenceClass {
-	/*< private >*/
-	GObjectClass parent;
-
-	/*< public >*/
-	void (*update_idle)(PurplePresence *presence, gboolean old_idle);
-	GList *(*get_statuses)(PurplePresence *presence);
-
-	/*< private >*/
-	gpointer reserved[4];
-};
-
 #define PURPLE_TYPE_PRESENCE purple_presence_get_type()
 
 PURPLE_AVAILABLE_IN_3_0
-G_DECLARE_DERIVABLE_TYPE(PurplePresence, purple_presence, PURPLE, PRESENCE,
-                         GObject)
+G_DECLARE_FINAL_TYPE(PurplePresence, purple_presence, PURPLE, PRESENCE,
+                     GObject)
 
 /**
  * purple_presence_new:
@@ -141,7 +120,20 @@
  * Since: 2.0
  */
 PURPLE_AVAILABLE_IN_ALL
-void purple_presence_set_idle(PurplePresence *presence, gboolean idle, GDateTime *idle_time);
+void purple_presence_set_idle(PurplePresence *presence, gboolean idle);
+
+/**
+ * purple_presence_set_idle_time:
+ * @presence: The instance.
+ * @idle_time: (transfer none) (nullable): The time when the presence went
+ *             idle, or %NULL to clear the idle state.
+ *
+ * Sets the time that @presence went idle to @idle_time.
+ *
+ * Since: 3.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+void purple_presence_set_idle_time(PurplePresence *presence, GDateTime *idle_time);
 
 /**
  * purple_presence_set_login_time:
diff --git a/libpurple/purplepresence.c b/libpurple/purplepresence.c
--- a/libpurple/purplepresence.c
+++ b/libpurple/purplepresence.c
@@ -22,6 +22,8 @@
 
 #include <glib/gi18n-lib.h>
 
+#include <birb.h>
+
 #include "purplepresence.h"
 
 #include "debug.h"
@@ -29,8 +31,11 @@
 #include "purpleprivate.h"
 #include "util.h"
 
+struct _PurplePresence {
+	GObject parent;
+};
+
 typedef struct {
-	gboolean idle;
 	GDateTime *idle_time;
 	GDateTime *login_time;
 
@@ -55,7 +60,8 @@
 };
 static GParamSpec *properties[N_PROPERTIES] = {NULL, };
 
-G_DEFINE_TYPE_WITH_PRIVATE(PurplePresence, purple_presence, G_TYPE_OBJECT)
+G_DEFINE_FINAL_TYPE_WITH_PRIVATE(PurplePresence, purple_presence,
+                                 G_TYPE_OBJECT)
 
 /******************************************************************************
  * GObject Implementation
@@ -68,11 +74,10 @@
 
 	switch (param_id) {
 		case PROP_IDLE:
-			purple_presence_set_idle(presence, g_value_get_boolean(value),
-			                         NULL);
+			purple_presence_set_idle(presence, g_value_get_boolean(value));
 			break;
 		case PROP_IDLE_TIME:
-			purple_presence_set_idle(presence, TRUE, g_value_get_boxed(value));
+			purple_presence_set_idle_time(presence, g_value_get_boxed(value));
 			break;
 		case PROP_LOGIN_TIME:
 			purple_presence_set_login_time(presence, g_value_get_boxed(value));
@@ -171,9 +176,11 @@
 	 *
 	 * Since: 3.0
 	 */
-	properties[PROP_IDLE] = g_param_spec_boolean("idle", "Idle",
-				"Whether the presence is in idle state.", FALSE,
-				G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+	properties[PROP_IDLE] = g_param_spec_boolean(
+		"idle", "idle",
+		"Whether the presence is in idle state.",
+		FALSE,
+		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
 	/**
 	 * PurplePresence:idle-time:
@@ -183,10 +190,10 @@
 	 * Since: 3.0
 	 */
 	properties[PROP_IDLE_TIME] = g_param_spec_boxed(
-				"idle-time", "Idle time",
-				"The idle time of the presence",
-				G_TYPE_DATE_TIME,
-				G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+		"idle-time", "idle-time",
+		"The idle time of the presence",
+		G_TYPE_DATE_TIME,
+		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
 	/**
 	 * PurplePresence:login-time:
@@ -196,7 +203,7 @@
 	 * Since: 3.0
 	 */
 	properties[PROP_LOGIN_TIME] = g_param_spec_boxed(
-		"login-time", "Login time",
+		"login-time", "login-time",
 		"The login time of the presence.",
 		G_TYPE_DATE_TIME,
 		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
@@ -283,40 +290,34 @@
 }
 
 void
-purple_presence_set_idle(PurplePresence *presence, gboolean idle,
-                         GDateTime *idle_time)
-{
+purple_presence_set_idle_time(PurplePresence *presence, GDateTime *idle_time) {
 	PurplePresencePrivate *priv = NULL;
-	PurplePresenceClass *klass = NULL;
-	gboolean old_idle;
-	GObject *obj = NULL;
 
 	g_return_if_fail(PURPLE_IS_PRESENCE(presence));
 
 	priv = purple_presence_get_instance_private(presence);
-	klass = PURPLE_PRESENCE_GET_CLASS(presence);
+
+	if(birb_date_time_set(&priv->idle_time, idle_time)) {
+		GObject *obj = G_OBJECT(presence);
 
-	if (priv->idle == idle && priv->idle_time == idle_time) {
-		return;
+		g_object_freeze_notify(obj);
+		g_object_notify_by_pspec(obj, properties[PROP_IDLE]);
+		g_object_notify_by_pspec(obj, properties[PROP_IDLE_TIME]);
+		g_object_thaw_notify(obj);
+	}
+}
+
+void
+purple_presence_set_idle(PurplePresence *presence, gboolean idle) {
+	GDateTime *idle_time = NULL;
+
+	g_return_if_fail(PURPLE_IS_PRESENCE(presence));
+
+	if(idle) {
+		idle_time = g_date_time_new_now_local();
 	}
 
-	old_idle = priv->idle;
-	priv->idle = idle;
-
-	g_clear_pointer(&priv->idle_time, g_date_time_unref);
-	if(idle && idle_time != NULL) {
-		priv->idle_time = g_date_time_ref(idle_time);
-	}
-
-	obj = G_OBJECT(presence);
-	g_object_freeze_notify(obj);
-	g_object_notify_by_pspec(obj, properties[PROP_IDLE]);
-	g_object_notify_by_pspec(obj, properties[PROP_IDLE_TIME]);
-	g_object_thaw_notify(obj);
-
-	if(klass->update_idle) {
-		klass->update_idle(presence, old_idle);
-	}
+	purple_presence_set_idle_time(presence, idle_time);
 }
 
 void
@@ -328,23 +329,10 @@
 
 	priv = purple_presence_get_instance_private(presence);
 
-	if(priv->login_time != NULL && login_time != NULL) {
-		if(g_date_time_equal(priv->login_time, login_time)) {
-			return;
-		}
-	}
-
-	if(priv->login_time != NULL) {
-		g_date_time_unref(priv->login_time);
+	if(birb_date_time_set(&priv->login_time, login_time)) {
+		g_object_notify_by_pspec(G_OBJECT(presence),
+		                         properties[PROP_LOGIN_TIME]);
 	}
-
-	if(login_time != NULL) {
-		priv->login_time = g_date_time_ref(login_time);
-	} else {
-		priv->login_time = NULL;
-	}
-
-	g_object_notify_by_pspec(G_OBJECT(presence), properties[PROP_LOGIN_TIME]);
 }
 
 gboolean
@@ -392,7 +380,7 @@
 
 	priv = purple_presence_get_instance_private(presence);
 
-	return priv->idle;
+	return (priv->idle_time != NULL);
 }
 
 GDateTime *
diff --git a/libpurple/tests/test_contact_info.c b/libpurple/tests/test_contact_info.c
--- a/libpurple/tests/test_contact_info.c
+++ b/libpurple/tests/test_contact_info.c
@@ -460,7 +460,7 @@
 	 * detailed callback.
 	 */
 	g_assert_cmpint(counter, ==, 0);
-	purple_presence_set_idle(presence, TRUE, NULL);
+	purple_presence_set_idle(presence, TRUE);
 	g_assert_cmpint(counter, ==, 3);
 
 	/* Cleanup. */
diff --git a/protocols/demo/purpledemocontacts.c b/protocols/demo/purpledemocontacts.c
--- a/protocols/demo/purpledemocontacts.c
+++ b/protocols/demo/purpledemocontacts.c
@@ -137,7 +137,7 @@
 		now = g_date_time_new_now_local();
 		idle_since = g_date_time_add_minutes(now, -1 * ivalue);
 
-		purple_presence_set_idle(presence, TRUE, idle_since);
+		purple_presence_set_idle_time(presence, idle_since);
 
 		g_date_time_unref(idle_since);
 		g_date_time_unref(now);
diff --git a/protocols/demo/purpledemoprotocolactions.c b/protocols/demo/purpledemoprotocolactions.c
--- a/protocols/demo/purpledemoprotocolactions.c
+++ b/protocols/demo/purpledemoprotocolactions.c
@@ -151,7 +151,7 @@
 		format = ngettext(tick_str, tick_plural_str, DEFAULT_REAP_TIME);
 		message = g_strdup_printf(format, DEFAULT_REAP_TIME);
 
-		purple_presence_set_idle(presence, FALSE, NULL);
+		purple_presence_set_idle(presence, FALSE);
 		purple_presence_set_message(presence, message);
 		g_free(message);
 	}
