# HG changeset patch
# Node ID b95c732ba3c2
# Parent  f4faf0d6ab26
diff --git a/ChangeLog.API b/ChangeLog.API
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -426,6 +426,7 @@
 		* purple_conversations_find_chat. Use
 		  purple_conversation_manager_find_chat_by_id instead.
 		* purple_conversation_set_logging
+		* purple_core_get_ui, use purple_core_get_ui_info instead.
 		* purple_core_ensure_single_instance. Check via GApplication
 		  or whatever is appropriate for your UI.
 		* purple_core_migrate
diff --git a/finch/libfinch.c b/finch/libfinch.c
--- a/finch/libfinch.c
+++ b/finch/libfinch.c
@@ -39,12 +39,6 @@
 #include "config.h"
 #include "package_revision.h"
 
-static PurpleUiInfo *
-finch_ui_get_info(void) {
-	return purple_ui_info_new(_("Finch"), VERSION, "https://pidgin.im",
-	                          "https://developer.pidgin.im", "console");
-}
-
 static void
 finch_quit(void)
 {
@@ -56,7 +50,6 @@
 	finch_prefs_init,
 	finch_ui_init,
 	finch_quit,
-	finch_ui_get_info,
 };
 
 static PurpleCoreUiOps *
@@ -97,6 +90,7 @@
 static int
 init_libpurple(int argc, char **argv)
 {
+	PurpleUiInfo *ui_info = NULL;
 	gboolean opt_nologin = FALSE;
 	gboolean opt_version = FALSE;
 	gboolean opt_debug = FALSE;
@@ -189,7 +183,11 @@
 	purple_core_set_ui_ops(gnt_core_get_ui_ops());
 	purple_idle_set_ui(finch_idle_new());
 
-	if (!purple_core_init(FINCH_UI))
+	ui_info = purple_ui_info_new("finch", _("Finch"), VERSION,
+	                             "https://pidgin.im",
+	                             "https://developer.pidgin.im", "console");
+
+	if (!purple_core_init(ui_info))
 	{
 		fprintf(stderr,
 				"Initialization of the Purple core failed. Dumping core.\n"
diff --git a/libpurple/core.h b/libpurple/core.h
--- a/libpurple/core.h
+++ b/libpurple/core.h
@@ -37,8 +37,7 @@
 
 /**
  * purple_core_init:
- * @ui: The ID of the UI using the core. This should be a
- *           unique ID, registered with the purple team.
+ * @ui_info: (transfer full): The [class@UiInfo] of the UI using the core.
  *
  * Initializes the core of purple.
  *
@@ -46,7 +45,7 @@
  *
  * Returns: %TRUE if successful, or %FALSE otherwise.
  */
-gboolean purple_core_init(const char *ui);
+gboolean purple_core_init(PurpleUiInfo *ui_info);
 
 /**
  * purple_core_quit:
@@ -87,16 +86,6 @@
 const char *purple_core_get_version(void);
 
 /**
- * purple_core_get_ui:
- *
- * Returns the ID of the UI that is using the core, as passed to
- * purple_core_init().
- *
- * Returns: The ID of the UI that is currently using the core.
- */
-const char *purple_core_get_ui(void);
-
-/**
  * purple_get_core:
  *
  * This is used to connect to
@@ -128,9 +117,9 @@
  *
  * Returns a #PurpleUiInfo that contains information about the user interface.
  *
- * Returns: (transfer full): A #PurpleUiInfo instance.
+ * Returns: (transfer none): A #PurpleUiInfo instance.
  */
-PurpleUiInfo* purple_core_get_ui_info(void);
+PurpleUiInfo *purple_core_get_ui_info(void);
 
 G_END_DECLS
 
diff --git a/libpurple/core.c b/libpurple/core.c
--- a/libpurple/core.c
+++ b/libpurple/core.c
@@ -49,7 +49,7 @@
 
 struct PurpleCore
 {
-	char *ui;
+	PurpleUiInfo *ui_info;
 
 	void *reserved;
 };
@@ -84,19 +84,14 @@
 		purple_core_get_version());
 
 	g_free(ui_full_name);
-
-	if(PURPLE_IS_UI_INFO(ui_info)) {
-		g_object_unref(G_OBJECT(ui_info));
-	}
 }
 
 gboolean
-purple_core_init(const char *ui)
-{
+purple_core_init(PurpleUiInfo *ui_info) {
 	PurpleCoreUiOps *ops;
 	PurpleCore *core;
 
-	g_return_val_if_fail(ui != NULL, FALSE);
+	g_return_val_if_fail(PURPLE_IS_UI_INFO(ui_info), FALSE);
 	g_return_val_if_fail(purple_get_core() == NULL, FALSE);
 
 	bindtextdomain(PACKAGE, PURPLE_LOCALEDIR);
@@ -106,7 +101,7 @@
 #endif
 
 	_core = core = g_new0(PurpleCore, 1);
-	core->ui = g_strdup(ui);
+	core->ui_info = ui_info;
 	core->reserved = NULL;
 
 	ops = purple_core_get_ui_ops();
@@ -258,7 +253,7 @@
 
 	purple_signals_uninit();
 
-	g_free(core->ui);
+	g_clear_object(&core->ui_info);
 	g_free(core);
 
 #ifdef _WIN32
@@ -282,16 +277,6 @@
 	return VERSION;
 }
 
-const char *
-purple_core_get_ui(void)
-{
-	PurpleCore *core = purple_get_core();
-
-	g_return_val_if_fail(core != NULL, NULL);
-
-	return core->ui;
-}
-
 PurpleCore *
 purple_get_core(void)
 {
@@ -310,11 +295,7 @@
 	return _ops;
 }
 
-PurpleUiInfo* purple_core_get_ui_info() {
-	PurpleCoreUiOps *ops = purple_core_get_ui_ops();
-
-	if(NULL == ops || NULL == ops->get_ui_info)
-		return NULL;
-
-	return ops->get_ui_info();
+PurpleUiInfo *
+purple_core_get_ui_info() {
+	return _core->ui_info;
 }
diff --git a/libpurple/example/nullclient.c b/libpurple/example/nullclient.c
--- a/libpurple/example/nullclient.c
+++ b/libpurple/example/nullclient.c
@@ -84,6 +84,8 @@
 static void
 init_libpurple(void)
 {
+	PurpleUiInfo *ui_info = NULL;
+
 	/* Set a custom user directory (optional) */
 	purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);
 
@@ -98,10 +100,13 @@
 	 */
 	purple_core_set_ui_ops(&null_core_uiops);
 
+	ui_info = purple_ui_info_new(UI_ID, "NullClient", VERSION, PURPLE_WEBSITE,
+	                             PURPLE_WEBSITE, "example");
+
 	/* Now that all the essential stuff has been set, let's try to init the core. It's
 	 * necessary to provide a non-NULL name for the current ui to the core. This name
 	 * is used by stuff that depends on this ui, for example the ui-specific plugins. */
-	if (!purple_core_init(UI_ID)) {
+	if (!purple_core_init(ui_info)) {
 		/* Initializing the core failed. Terminate. */
 		fprintf(stderr,
 				"libpurple initialization failed. Dumping core.\n"
diff --git a/libpurple/plugins/kwallet/purplekwallet.cpp b/libpurple/plugins/kwallet/purplekwallet.cpp
--- a/libpurple/plugins/kwallet/purplekwallet.cpp
+++ b/libpurple/plugins/kwallet/purplekwallet.cpp
@@ -59,7 +59,6 @@
 	ui_info = purple_core_get_ui_info();
 	if(PURPLE_IS_UI_INFO(ui_info)) {
 		ui_name = purple_ui_info_get_name(ui_info);
-		g_object_unref(G_OBJECT(ui_info));
 	}
 
 	if(ui_name.isEmpty()) {
diff --git a/libpurple/protocols/jabber/bosh.c b/libpurple/protocols/jabber/bosh.c
--- a/libpurple/protocols/jabber/bosh.c
+++ b/libpurple/protocols/jabber/bosh.c
@@ -81,10 +81,6 @@
 	} else {
 		jabber_bosh_useragent = g_strdup("libpurple " VERSION);
 	}
-
-	if(ui_info) {
-		g_object_unref(G_OBJECT(ui_info));
-	}
 }
 
 void jabber_bosh_uninit(void)
diff --git a/libpurple/protocols/jabber/iq.c b/libpurple/protocols/jabber/iq.c
--- a/libpurple/protocols/jabber/iq.c
+++ b/libpurple/protocols/jabber/iq.c
@@ -252,10 +252,6 @@
 		}
 
 		jabber_iq_send(iq);
-
-		if(PURPLE_IS_UI_INFO(ui_info)) {
-			g_object_unref(G_OBJECT(ui_info));
-		}
 	}
 }
 
diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
--- a/libpurple/protocols/jabber/jabber.c
+++ b/libpurple/protocols/jabber/jabber.c
@@ -3735,10 +3735,6 @@
 	jabber_si_init();
 
 	jabber_auth_init();
-
-	if(PURPLE_IS_UI_INFO(ui_info)) {
-		g_object_unref(G_OBJECT(ui_info));
-	}
 }
 
 static void
diff --git a/libpurple/protocols/silc/silc.c b/libpurple/protocols/silc/silc.c
--- a/libpurple/protocols/silc/silc.c
+++ b/libpurple/protocols/silc/silc.c
@@ -720,10 +720,6 @@
 
 	quit_msg = g_strdup_printf(_("Download %s: %s"), ui_name, ui_website);
 
-	if (PURPLE_IS_UI_INFO(ui_info)) {
-		g_object_unref(G_OBJECT(ui_info));
-	}
-
 	return quit_msg;
 }
 
diff --git a/libpurple/purplecoreuiops.h b/libpurple/purplecoreuiops.h
--- a/libpurple/purplecoreuiops.h
+++ b/libpurple/purplecoreuiops.h
@@ -42,8 +42,6 @@
  *                 should use this hook to set all other necessary
  *                 <link linkend="chapter-ui-ops"><literal>UiOps structures</literal></link>.
  * @quit:          Called after most of libpurple has been uninitialized.
- * @get_ui_info:   Called by purple_core_get_ui_info(); should return the
- *                 information documented there.
  *
  * Callbacks that fire at different points of the initialization and teardown
  * of libpurple, along with a hook to return descriptive information about the
@@ -55,8 +53,6 @@
 
 	void (*quit)(void);
 
-	PurpleUiInfo *(*get_ui_info)(void);
-
 	/*< private >*/
 	gpointer reserved[4];
 };
diff --git a/libpurple/purpleplugininfo.c b/libpurple/purpleplugininfo.c
--- a/libpurple/purpleplugininfo.c
+++ b/libpurple/purpleplugininfo.c
@@ -154,10 +154,12 @@
 	}
 
 	if(priv->ui_requirement != NULL) {
-		if(!purple_strequal(priv->ui_requirement, purple_core_get_ui())) {
+		PurpleUiInfo *ui_info = purple_core_get_ui_info();
+		const gchar *ui_id = purple_ui_info_get_id(ui_info);
+		if(!purple_strequal(priv->ui_requirement, ui_id)) {
 			priv->error = g_strdup_printf(_("You are using %s, but this plugin "
 			                                "requires %s."),
-			                              purple_core_get_ui(),
+			                              ui_id,
 			                              priv->ui_requirement);
 			purple_debug_error("plugins",
 			                   "%s is not loadable: The UI requirement is not "
diff --git a/libpurple/purpleuiinfo.h b/libpurple/purpleuiinfo.h
--- a/libpurple/purpleuiinfo.h
+++ b/libpurple/purpleuiinfo.h
@@ -48,7 +48,8 @@
 
 /**
  * purple_ui_info_new:
- * @name: The name.
+ * @id: The identifier.
+ * @name: The name, which will be displayed.
  * @version: The version.
  * @website: The website.
  * @support_website: The support website.
@@ -61,13 +62,26 @@
  *
  * Since: 3.0.0
  */
-PurpleUiInfo *purple_ui_info_new(const gchar *name,
+PurpleUiInfo *purple_ui_info_new(const gchar *id,
+                                 const gchar *name,
                                  const gchar *version,
                                  const gchar *website,
                                  const gchar *support_website,
                                  const gchar *client_type);
 
 /**
+ * purple_ui_info_get_id:
+ * @info: The instance.
+ *
+ * Gets the identifier from @info.
+ *
+ * Returns: The identifier from @info.
+ *
+ * Since: 3.0.0
+ */
+const gchar *purple_ui_info_get_id(PurpleUiInfo *info);
+
+/**
  * purple_ui_info_get_name:
  * @info: The #PurpleUiInfo instance.
  *
diff --git a/libpurple/purpleuiinfo.c b/libpurple/purpleuiinfo.c
--- a/libpurple/purpleuiinfo.c
+++ b/libpurple/purpleuiinfo.c
@@ -25,6 +25,7 @@
 struct _PurpleUiInfo {
 	GObject parent;
 
+	gchar *id;
 	gchar *name;
 	gchar *version;
 	gchar *website;
@@ -34,6 +35,7 @@
 
 enum {
 	PROP_0,
+	PROP_ID,
 	PROP_NAME,
 	PROP_VERSION,
 	PROP_WEBSITE,
@@ -47,6 +49,12 @@
  * Helpers
  *****************************************************************************/
 static void
+purple_ui_info_set_id(PurpleUiInfo *info, const gchar *id) {
+	g_free(info->id);
+	info->id = g_strdup(id);
+}
+
+static void
 purple_ui_info_set_name(PurpleUiInfo *info, const gchar *name) {
 	g_free(info->name);
 	info->name = g_strdup(name);
@@ -90,6 +98,9 @@
 	PurpleUiInfo *info = PURPLE_UI_INFO(obj);
 
 	switch(param_id) {
+		case PROP_ID:
+			g_value_set_string(value, purple_ui_info_get_id(info));
+			break;
 		case PROP_NAME:
 			g_value_set_string(value, purple_ui_info_get_name(info));
 			break;
@@ -118,6 +129,9 @@
 	PurpleUiInfo *info = PURPLE_UI_INFO(obj);
 
 	switch(param_id) {
+		case PROP_ID:
+			purple_ui_info_set_id(info, g_value_get_string(value));
+			break;
 		case PROP_NAME:
 			purple_ui_info_set_name(info, g_value_get_string(value));
 			break;
@@ -148,6 +162,7 @@
 purple_ui_info_finalize(GObject *obj) {
 	PurpleUiInfo *info = PURPLE_UI_INFO(obj);
 
+	g_clear_pointer(&info->id, g_free);
 	g_clear_pointer(&info->name, g_free);
 	g_clear_pointer(&info->version, g_free);
 	g_clear_pointer(&info->website, g_free);
@@ -166,9 +181,24 @@
 	obj_class->finalize = purple_ui_info_finalize;
 
 	/**
-	 * PurpleUiInfo::name:
+	 * PurpleUiInfo:id:
+	 *
+	 * The identifier of the user interface.
+	 *
+	 * Since: 3.0.0
+	 */
+	properties[PROP_ID] =
+		g_param_spec_string("id", "id", "The identifier of the user interface",
+		                    NULL,
+		                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+		                    G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * PurpleUiInfo:name:
 	 *
 	 * The name of the user interface.
+	 *
+	 * Since: 3.0.0
 	 */
 	properties[PROP_NAME] =
 		g_param_spec_string("name", "name", "The name of the user interface",
@@ -177,9 +207,11 @@
 		                    G_PARAM_STATIC_STRINGS);
 
 	/**
-	 * PurpleUiInfo::version:
+	 * PurpleUiInfo:version:
 	 *
-	 * The name of the user interface.
+	 * The version of the user interface.
+	 *
+	 * Since: 3.0.0
 	 */
 	properties[PROP_VERSION] =
 		g_param_spec_string("version", "version",
@@ -189,9 +221,11 @@
 		                    G_PARAM_STATIC_STRINGS);
 
 	/**
-	 * PurpleUiInfo::website:
+	 * PurpleUiInfo:website:
 	 *
 	 * The website of the user interface.
+	 *
+	 * Since: 3.0.0
 	 */
 	properties[PROP_WEBSITE] =
 		g_param_spec_string("website", "website",
@@ -201,9 +235,11 @@
 		                    G_PARAM_STATIC_STRINGS);
 
 	/**
-	 * PurpleUiInfo::support-website:
+	 * PurpleUiInfo:support-website:
 	 *
 	 * The support website of the user interface.
+	 *
+	 * Since: 3.0.0
 	 */
 	properties[PROP_SUPPORT_WEBSITE] =
 		g_param_spec_string("support-website", "support-website",
@@ -213,9 +249,11 @@
 		                    G_PARAM_STATIC_STRINGS);
 
 	/**
-	 * PurpleUiInfo::client-type:
+	 * PurpleUiInfo:client-type:
 	 *
 	 * The client type of the user interface.
+	 *
+	 * Since: 3.0.0
 	 */
 	properties[PROP_CLIENT_TYPE] =
 		g_param_spec_string("client-type", "client-type",
@@ -231,11 +269,12 @@
  * Public API
  *****************************************************************************/
 PurpleUiInfo *
-purple_ui_info_new(const gchar *name, const gchar *version,
-                   const gchar *website, const gchar *support_website,
-                   const gchar *client_type)
+purple_ui_info_new(const gchar *id, const gchar *name,
+                   const gchar *version, const gchar *website,
+                   const gchar *support_website, const gchar *client_type)
 {
 	return g_object_new(PURPLE_TYPE_UI_INFO,
+	                    "id", id,
 	                    "name", name,
 	                    "version", version,
 	                    "website", website,
@@ -245,6 +284,13 @@
 }
 
 const gchar *
+purple_ui_info_get_id(PurpleUiInfo *info) {
+	g_return_val_if_fail(PURPLE_IS_UI_INFO(info), NULL);
+
+	return info->id;
+}
+
+const gchar *
 purple_ui_info_get_name(PurpleUiInfo *info) {
 	g_return_val_if_fail(PURPLE_IS_UI_INFO(info), NULL);
 
@@ -278,4 +324,3 @@
 
 	return info->client_type;
 }
-
diff --git a/libpurple/tests/test_ui.c b/libpurple/tests/test_ui.c
--- a/libpurple/tests/test_ui.c
+++ b/libpurple/tests/test_ui.c
@@ -92,6 +92,7 @@
 
 void
 test_ui_purple_init(void) {
+	PurpleUiInfo *ui_info = NULL;
 	GError *error = NULL;
 
 #ifndef _WIN32
@@ -114,10 +115,13 @@
 	 */
 	purple_core_set_ui_ops(&test_core_uiops);
 
+	ui_info = purple_ui_info_new("test", "Test-UI", VERSION, PURPLE_WEBSITE,
+	                             PURPLE_WEBSITE, "test");
+
 	/* Now that all the essential stuff has been set, let's try to init the core. It's
 	 * necessary to provide a non-NULL name for the current ui to the core. This name
 	 * is used by stuff that depends on this ui, for example the ui-specific plugins. */
-	if (!purple_core_init("test-ui")) {
+	if (!purple_core_init(ui_info)) {
 		/* Initializing the core failed. Terminate. */
 		fprintf(stderr,
 				"libpurple initialization failed. Dumping core.\n"
diff --git a/pidgin/libpidgin.c b/pidgin/libpidgin.c
--- a/pidgin/libpidgin.c
+++ b/pidgin/libpidgin.c
@@ -299,18 +299,11 @@
 	g_application_quit(g_application_get_default());
 }
 
-static PurpleUiInfo *
-pidgin_ui_get_info(void) {
-	return purple_ui_info_new(PIDGIN_NAME, VERSION, "https://pidgin.im",
-	                          "https://developer.pidgin.im", "pc");
-}
-
 static PurpleCoreUiOps core_ops =
 {
 	pidgin_prefs_init,
 	pidgin_ui_init,
 	pidgin_quit,
-	pidgin_ui_get_info,
 };
 
 PurpleCoreUiOps *
diff --git a/pidgin/pidginapplication.c b/pidgin/pidginapplication.c
--- a/pidgin/pidginapplication.c
+++ b/pidgin/pidginapplication.c
@@ -646,6 +646,7 @@
 static void
 pidgin_application_startup(GApplication *application) {
 	PurpleAccountManager *manager = NULL;
+	PurpleUiInfo *ui_info = NULL;
 	GtkCssProvider *provider = NULL;
 	GError *error = NULL;
 	GList *active_accounts = NULL;
@@ -701,7 +702,11 @@
 
 	purple_core_set_ui_ops(pidgin_core_get_ui_ops());
 
-	if(!purple_core_init(PIDGIN_UI)) {
+	ui_info = purple_ui_info_new(PIDGIN_UI, PIDGIN_NAME, VERSION,
+	                             "https://pidgin.im",
+	                             "https://developer.pidgin.im", "pc");
+
+	if(!purple_core_init(ui_info)) {
 		fprintf(stderr,
 				_("Initialization of the libpurple core failed. Aborting!\n"
 				  "Please report this!\n"));
