# HG changeset patch
# Node ID 7f2c65583c00
# Parent  a9285192c3d3
diff --git a/libpurple/core.c b/libpurple/core.c
--- a/libpurple/core.c
+++ b/libpurple/core.c
@@ -44,6 +44,7 @@
 #include "purpleidlemanagerprivate.h"
 #include "purplemessage.h"
 #include "purplepath.h"
+#include "purplepresencemanagerprivate.h"
 #include "purpleprivate.h"
 #include "savedstatuses.h"
 #include "signals.h"
@@ -164,6 +165,7 @@
 	purple_accounts_init();
 	purple_contact_manager_startup();
 	purple_savedstatuses_init();
+	purple_presence_manager_startup();
 	purple_notify_init();
 	purple_conversations_init();
 	purple_conversation_manager_startup();
@@ -246,6 +248,7 @@
 	purple_notify_uninit();
 	purple_connections_uninit();
 	purple_buddy_icons_uninit();
+	purple_presence_manager_shutdown();
 	purple_savedstatuses_uninit();
 	purple_statuses_uninit();
 	purple_accounts_uninit();
diff --git a/libpurple/meson.build b/libpurple/meson.build
--- a/libpurple/meson.build
+++ b/libpurple/meson.build
@@ -245,6 +245,7 @@
 ]
 
 purple_private_headers = [
+	'purplepresencemanagerprivate.h',
 	'purpleprivate.h',
 	'purplesavedpresenceprivate.h',
 ]
diff --git a/libpurple/purplepresencemanager.h b/libpurple/purplepresencemanager.h
--- a/libpurple/purplepresencemanager.h
+++ b/libpurple/purplepresencemanager.h
@@ -30,6 +30,8 @@
 #include <glib.h>
 #include <glib-object.h>
 
+#include <gio/gio.h>
+
 #include "purplesavedpresence.h"
 #include "purpleversion.h"
 
@@ -50,6 +52,44 @@
  */
 
 /**
+ * purple_presence_manager_get_default:
+ *
+ * Gets the default [class@PresenceManager] that should be used.
+ *
+ * This may be %NULL if libpurple hasn't been initialized or if someone
+ * incorrectly unref'd it.
+ *
+ * Returns: (transfer none) (nullable): The default presence manager.
+ *
+ * Since: 3.0.0
+ *
+ * See Also: [func@PresenceManager.get_default_as_model]
+ */
+PURPLE_AVAILABLE_IN_3_0
+PurplePresenceManager *purple_presence_manager_get_default(void);
+
+/**
+ * purple_presence_manager_get_default_as_model:
+ *
+ * Gets the default [class@PresenceManager] as a [iface@Gio.ListModel].
+ *
+ * This is the equivalent to calling [func@PresenceManager.get_default] and
+ * type casting it to [iface@gio.ListModel].
+ *
+ * This may be %NULL if libpurple hasn't been initialized or if someone
+ * incorrectly unref'd it.
+ *
+ * Returns: (transfer none) (nullable): The default presence manager type cast
+ *          to a list model.
+ *
+ * Since: 3.0.0
+ *
+ * See Also: [func@PresenceManager.get_default]
+ */
+PURPLE_AVAILABLE_IN_3_0
+GListModel *purple_presence_manager_get_default_as_model(void);
+
+/**
  * purple_presence_manager_new:
  * @filename: (nullable): An optional filename where settings will be stored.
  *
diff --git a/libpurple/purplepresencemanager.c b/libpurple/purplepresencemanager.c
--- a/libpurple/purplepresencemanager.c
+++ b/libpurple/purplepresencemanager.c
@@ -23,7 +23,11 @@
 #include <gio/gsettingsbackend.h>
 
 #include "purplepresencemanager.h"
+#include "purplepresencemanagerprivate.h"
+
+#include "core.h"
 #include "purplesavedpresenceprivate.h"
+#include "purpleui.h"
 #include "util.h"
 
 #define MANAGER_SCHEMA_ID "im.pidgin.Purple.PresenceManager"
@@ -56,6 +60,8 @@
 	GPtrArray *presences;
 };
 
+static PurplePresenceManager *default_manager = NULL;
+
 /******************************************************************************
  * Helpers
  *****************************************************************************/
@@ -407,9 +413,44 @@
 }
 
 /******************************************************************************
+ * Private API
+ *****************************************************************************/
+void
+purple_presence_manager_startup(void) {
+	if(default_manager == NULL) {
+		PurpleUi *ui = purple_core_get_ui();
+
+		default_manager = purple_ui_get_presence_manager(ui);
+		if(PURPLE_IS_PRESENCE_MANAGER(default_manager)) {
+			g_object_add_weak_pointer(G_OBJECT(default_manager),
+			                          (gpointer *)&default_manager);
+		}
+	}
+}
+
+void
+purple_presence_manager_shutdown(void) {
+	g_clear_object(&default_manager);
+}
+
+/******************************************************************************
  * Public API
  *****************************************************************************/
 PurplePresenceManager *
+purple_presence_manager_get_default(void) {
+	return default_manager;
+}
+
+GListModel *
+purple_presence_manager_get_default_as_model(void) {
+	if(PURPLE_IS_PRESENCE_MANAGER(default_manager)) {
+		return G_LIST_MODEL(default_manager);
+	}
+
+	return NULL;
+}
+
+PurplePresenceManager *
 purple_presence_manager_new(const char *filename) {
 	return g_object_new(PURPLE_TYPE_PRESENCE_MANAGER,
 	                    "filename", filename,
diff --git a/libpurple/purplepresencemanagerprivate.h b/libpurple/purplepresencemanagerprivate.h
new file mode 100644
--- /dev/null
+++ b/libpurple/purplepresencemanagerprivate.h
@@ -0,0 +1,55 @@
+/*
+ * Purple - Internet Messaging Library
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef PURPLE_COMPILATION
+# error "purplepresencemanagerprivate.h may only be include by libpurple"
+#endif
+
+#ifndef PURPLE_PRESENCE_MANAGER_PRIVATE_H
+#define PURPLE_PRESENCE_MANAGER_PRIVATE_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * purple_presence_manager_startup: (skip)
+ *
+ * This will ask the UI what [class@PresenceManager] should be used and caches
+ * it for use with [func@PresenceManager.get_default].
+ *
+ * Since: 3.0.0
+ */
+G_GNUC_INTERNAL void purple_presence_manager_startup(void);
+
+/**
+ * purple_presence_manager_shutdown: (skip)
+ *
+ * Clears the references to the default manager if one exists.
+ *
+ * Since: 3.0.0
+ */
+G_GNUC_INTERNAL void purple_presence_manager_shutdown(void);
+
+G_END_DECLS
+
+#endif /* PURPLE_PRESENCE_MANAGER_PRIVATE_H */
diff --git a/libpurple/purpleui.h b/libpurple/purpleui.h
--- a/libpurple/purpleui.h
+++ b/libpurple/purpleui.h
@@ -27,6 +27,7 @@
 #include <glib-object.h>
 
 #include "purplehistoryadapter.h"
+#include "purplepresencemanager.h"
 #include "purpleversion.h"
 
 G_BEGIN_DECLS
@@ -73,6 +74,7 @@
 
 	gpointer (*get_settings_backend)(PurpleUi *ui);
 	PurpleHistoryAdapter *(*get_history_adapter)(PurpleUi *ui);
+	PurplePresenceManager *(*get_presence_manager)(PurpleUi *ui);
 
 	/*< private >*/
 	gpointer reserved[4];
@@ -234,6 +236,22 @@
 PURPLE_AVAILABLE_IN_3_0
 PurpleHistoryAdapter *purple_ui_get_history_adapter(PurpleUi *ui);
 
+/**
+ * purple_ui_get_presence_manager:
+ * @ui: The instance:
+ *
+ * Gets the [class@PresenceManager] that the user interface wants to use.
+ *
+ * > Note: This should typically only be called by libpurple. If this returns
+ * %NULL, then libpurple will not be able to manage saved presences.
+ *
+ * Returns: (transfer full) (nullable): The new presence manager or %NULL.
+ *
+ * Since: 3.0.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+PurplePresenceManager *purple_ui_get_presence_manager(PurpleUi *ui);
+
 G_END_DECLS
 
 #endif /* PURPLE_UI_H */
diff --git a/libpurple/purpleui.c b/libpurple/purpleui.c
--- a/libpurple/purpleui.c
+++ b/libpurple/purpleui.c
@@ -439,3 +439,17 @@
 
 	return NULL;
 }
+
+PurplePresenceManager *
+purple_ui_get_presence_manager(PurpleUi *ui) {
+	PurpleUiClass *klass = NULL;
+
+	g_return_val_if_fail(PURPLE_IS_UI(ui), NULL);
+
+	klass = PURPLE_UI_GET_CLASS(ui);
+	if(klass != NULL && klass->get_presence_manager != NULL) {
+		return klass->get_presence_manager(ui);
+	}
+
+	return NULL;
+}
diff --git a/pidgin/pidginui.c b/pidgin/pidginui.c
--- a/pidgin/pidginui.c
+++ b/pidgin/pidginui.c
@@ -191,6 +191,20 @@
 	return adapter;
 }
 
+static PurplePresenceManager *
+pidgin_ui_get_presence_manager(G_GNUC_UNUSED PurpleUi *ui) {
+	PurplePresenceManager *manager = NULL;
+	char *filename = NULL;
+
+	g_mkdir_with_parents(purple_config_dir(), 0700);
+
+	filename = g_build_filename(purple_config_dir(), "presences.ini", NULL);
+	manager = purple_presence_manager_new(filename);
+	g_free(filename);
+
+	return manager;
+}
+
 /******************************************************************************
  * GObject Implementation
  *****************************************************************************/
@@ -207,6 +221,7 @@
 	ui_class->stop = pidgin_ui_stop;
 	ui_class->get_settings_backend = pidgin_ui_get_settings_backend;
 	ui_class->get_history_adapter = pidgin_ui_get_history_adapter;
+	ui_class->get_presence_manager = pidgin_ui_get_presence_manager;
 }
 
 /******************************************************************************
