pidgin/pidgin

Redesign the presence manager a bit

3 months ago, Gary Kramlich
722be3b1a8aa
Parents a980db2607fd
Children f053e7fdd25d
Redesign the presence manager a bit

The presence manager now stores everything in a directory rather than a single
ini file. This avoids relocating schemas which seems to have a number of
issues.

Also bind the "active" setting to the "active-presence" property so that you
can change the active presence via the `manager.ini` gsettings keyfile.

So other various tweaks as well.

Testing Done:
Opened `manager.ini` and toggled the active status between a few I created.

Consulted with the turtles and ran the `presence_manager` and `saved_presence` unit tests under valgrind.

Reviewed at https://reviews.imfreedom.org/r/2912/
--- a/libpurple/data/im.pidgin.Purple.PresenceManager.gschema.xml Tue Jan 23 00:03:38 2024 -0600
+++ b/libpurple/data/im.pidgin.Purple.PresenceManager.gschema.xml Tue Jan 23 00:04:57 2024 -0600
@@ -10,7 +10,7 @@
<value nick="streaming" value="6"/>
</enum>
- <schema id="im.pidgin.Purple.SavedPresence">
+ <schema path="/purple/saved-presence/" id="im.pidgin.Purple.SavedPresence">
<key name="last-used" type="s">
<default>""</default>
<summary>The last time this presence was used</summary>
@@ -62,23 +62,11 @@
<schema path="/purple/presence-manager/" id="im.pidgin.Purple.PresenceManager">
<key name="active" type="s">
- <default>""</default>
+ <default>"ffffffff-ffff-ffff-ffff-ffffffffffff"</default>
<summary>The id of the active presence</summary>
<description>
- The name of the active presence that the libpurple user is currently
+ The id of the active presence that the libpurple user is currently
using.
-
- The presence itself should be have a path of `/presences/%name%` inside
- the im.pidgin.Purple.PresenceManager settings.
- </description>
- </key>
-
- <key name="presences" type="as">
- <default>[]</default>
- <summary>A list of the ids of all saved presences</summary>
- <description>
- The list is used to find all of the saved presences as they are
- relocatable settings.
</description>
</key>
</schema>
--- a/libpurple/meson.build Tue Jan 23 00:03:38 2024 -0600
+++ b/libpurple/meson.build Tue Jan 23 00:04:57 2024 -0600
@@ -248,7 +248,6 @@
'purplefiletransfermanagerprivate.h',
'purplepresencemanagerprivate.h',
'purpleprivate.h',
- 'purplesavedpresenceprivate.h',
]
purple_request_headers = [
--- a/libpurple/purplepresencemanager.c Tue Jan 23 00:03:38 2024 -0600
+++ b/libpurple/purplepresencemanager.c Tue Jan 23 00:04:57 2024 -0600
@@ -21,6 +21,7 @@
*/
#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
#define G_SETTINGS_ENABLE_BACKEND
#include <gio/gsettingsbackend.h>
@@ -29,17 +30,15 @@
#include "purplepresencemanagerprivate.h"
#include "core.h"
-#include "purplesavedpresenceprivate.h"
#include "purpleui.h"
#include "util.h"
#define MANAGER_SCHEMA_ID "im.pidgin.Purple.PresenceManager"
-#define PRESENCE_SCHEMA_ID "im.pidgin.Purple.SavedPresence"
-#define MANAGER_PATH "/purple/presence-manager"
+#define SAVED_PRESENCE_SCHEMA_ID "im.pidgin.Purple.SavedPresence"
enum {
PROP_0,
- PROP_FILENAME,
+ PROP_PATH,
PROP_ACTIVE,
N_PROPERTIES,
};
@@ -55,7 +54,7 @@
struct _PurplePresenceManager {
GObject parent;
- char *filename;
+ char *path;
GSettingsBackend *backend;
GSettings *settings;
@@ -69,8 +68,17 @@
* Helpers
*****************************************************************************/
static inline char *
-purple_presence_manager_path_for_presence(const char *id) {
- return g_strdup_printf("%s/presences/%s/", MANAGER_PATH, id);
+purple_presence_manager_get_path_for_id(PurplePresenceManager *manager,
+ const char *id)
+{
+ char *filename = NULL;
+ char *basename = NULL;
+
+ basename = g_strdup_printf("%s.ini", id);
+ filename = g_build_filename(manager->path, basename, NULL);
+ g_clear_pointer(&basename, g_free);
+
+ return filename;
}
static gboolean
@@ -116,116 +124,171 @@
return ret;
}
-static void
-purple_presence_manager_update_presences_setting(PurplePresenceManager *manager)
-{
- GStrvBuilder *builder = NULL;
- GStrv presences = NULL;
+static PurpleSavedPresence *
+purple_presence_manager_add(PurplePresenceManager *manager, const char *id) {
+ PurpleSavedPresence *presence = NULL;
+ GSettingsBackend *backend = NULL;
+ GSettings *settings = NULL;
+
+ g_return_val_if_fail(PURPLE_IS_PRESENCE_MANAGER(manager), NULL);
+ g_return_val_if_fail(!purple_strempty(id), NULL);
- builder = g_strv_builder_new();
- for(guint i = 0; i < manager->presences->len; i++) {
- PurpleSavedPresence *presence = NULL;
- const char *id = NULL;
+ /* Figure out which settings backend to use. */
+ if(!purple_strempty(manager->path)) {
+ char *filename = NULL;
- presence = g_ptr_array_index(manager->presences, i);
- id = purple_saved_presence_get_id(presence);
- g_strv_builder_add(builder, id);
+ filename = purple_presence_manager_get_path_for_id(manager, id);
+ backend = g_keyfile_settings_backend_new(filename, "/", NULL);
+ g_clear_pointer(&filename, g_free);
+ } else {
+ backend = g_memory_settings_backend_new();
}
- presences = g_strv_builder_end(builder);
- g_settings_set_strv(manager->settings, "presences",
- (const char * const *)presences);
- g_strfreev(presences);
- g_strv_builder_unref(builder);
-}
+ /* Create the settings object with the determined backend. */
+ settings = g_settings_new_with_backend(SAVED_PRESENCE_SCHEMA_ID, backend);
+ g_clear_object(&backend);
-static inline void
-purple_presence_manager_add(PurplePresenceManager *manager,
- PurpleSavedPresence *presence)
-{
- g_return_if_fail(PURPLE_IS_PRESENCE_MANAGER(manager));
- g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence));
+ /* Create the presence. */
+ presence = g_object_new(
+ PURPLE_TYPE_SAVED_PRESENCE,
+ "id", id,
+ "settings", settings,
+ NULL);
g_ptr_array_add(manager->presences, g_object_ref(presence));
- purple_presence_manager_update_presences_setting(manager);
g_signal_emit(manager, signals[SIG_ADDED], 0, presence);
g_list_model_items_changed(G_LIST_MODEL(manager),
manager->presences->len - 1, 0, 1);
+
+ return presence;
}
static void
-purple_presence_manager_set_filename(PurplePresenceManager *manager,
- const char *filename)
+purple_presence_manager_set_path(PurplePresenceManager *manager,
+ const char *path)
{
g_return_if_fail(PURPLE_IS_PRESENCE_MANAGER(manager));
- if(!purple_strequal(filename, manager->filename)) {
- g_free(manager->filename);
- manager->filename = g_strdup(filename);
+ if(!purple_strequal(path, manager->path)) {
+ g_free(manager->path);
+ manager->path = g_strdup(path);
- g_object_notify_by_pspec(G_OBJECT(manager), properties[PROP_FILENAME]);
+ g_object_notify_by_pspec(G_OBJECT(manager), properties[PROP_PATH]);
}
}
static void
purple_presence_manager_load_saved_presences(PurplePresenceManager *manager) {
- GStrv ids = NULL;
+ PurpleSavedPresence *presence = NULL;
+ const char *id = NULL;
+
+ /* Load the presences from disk. */
+ if(manager->path != NULL) {
+ GDir *dir = NULL;
+ GError *error = NULL;
+ const char *basename = NULL;
- ids = g_settings_get_strv(manager->settings, "presences");
+ dir = g_dir_open(manager->path, 0, &error);
+ if(error != NULL) {
+ g_warning("failed to open directory '%s': %s", manager->path,
+ error->message);
+ } else {
+ GPatternSpec *pattern = NULL;
+
+ /* We use ?* to make sure we have at least one character before the
+ * .ini.
+ */
+ pattern = g_pattern_spec_new("?*.ini");
- /* If we don't have any existing presences, create an available one. */
- if(ids[0] == NULL) {
- PurpleSavedPresence *presence = NULL;
- const char *id = NULL;
+ while((basename = g_dir_read_name(dir)) != NULL) {
+ if(purple_strequal(basename, "manager.ini")) {
+ continue;
+ }
+
+ if(g_pattern_spec_match_string(pattern, basename)) {
+ PurpleSavedPresence *presence = NULL;
+ char *id = NULL;
- /* We aren't going to use the ids anymore so free them right away. */
- g_strfreev(ids);
+ id = g_strndup(basename, strlen(basename) - 4);
+ presence = purple_presence_manager_add(manager, id);
+ g_clear_pointer(&id, g_free);
+ g_clear_object(&presence);
+ }
+ }
+ g_dir_close(dir);
- /* Create the default available presence and set it as active. */
- presence = purple_presence_manager_create(manager);
+ g_clear_pointer(&pattern, g_pattern_spec_free);
+ }
+ }
+
+ /* Make sure we have our default available presence. */
+ id = "ffffffff-ffff-ffff-ffff-ffffffffffff";
+ presence = purple_presence_manager_find_with_id(manager, id, NULL);
+ if(!PURPLE_IS_SAVED_PRESENCE(presence)) {
+ presence = purple_presence_manager_add(manager, id);
purple_saved_presence_set_name(presence, _("Available"));
purple_saved_presence_set_primitive(presence,
PURPLE_PRESENCE_PRIMITIVE_AVAILABLE);
-
- id = purple_saved_presence_get_id(presence);
- purple_presence_manager_set_active(manager, id);
+ g_clear_object(&presence);
+ }
- g_clear_object(&presence);
-
- /* Create the default offline presence as well. */
- presence = purple_presence_manager_create(manager);
+ /* Make sure we have our default offline presence as well. */
+ id = "00000000-0000-0000-0000-000000000000";
+ presence = purple_presence_manager_find_with_id(manager, id, NULL);
+ if(!PURPLE_IS_SAVED_PRESENCE(presence)) {
+ presence = purple_presence_manager_add(manager, id);
purple_saved_presence_set_name(presence, _("Offline"));
purple_saved_presence_set_primitive(presence,
PURPLE_PRESENCE_PRIMITIVE_OFFLINE);
g_clear_object(&presence);
+ }
+}
- return;
+/******************************************************************************
+ * GSettings Mappings
+ *****************************************************************************/
+static gboolean
+purple_presence_manager_get_active_mapping(GValue *value, GVariant *variant,
+ gpointer data)
+{
+ PurplePresenceManager *manager = data;
+ PurpleSavedPresence *presence = NULL;
+ const char *id = NULL;
+
+ /* Get the id of the saved presence from gsettings. */
+ id = g_variant_get_string(variant, NULL);
+
+ presence = purple_presence_manager_find_with_id(manager, id, NULL);
+ if(PURPLE_IS_SAVED_PRESENCE(presence)) {
+ g_value_set_object(value, G_OBJECT(presence));
+
+ return TRUE;
}
- for(int i = 0; ids[i] != NULL; i++) {
- PurpleSavedPresence *presence = NULL;
- GSettings *settings = NULL;
- char *path = NULL;
+ return FALSE;
+}
- path = purple_presence_manager_path_for_presence(ids[i]);
- settings = g_settings_new_with_backend_and_path(PRESENCE_SCHEMA_ID,
- manager->backend,
- path);
- g_clear_pointer(&path, g_free);
+static GVariant *
+purple_presence_manager_set_active_mapping(const GValue *value,
+ const GVariantType *expected_type,
+ G_GNUC_UNUSED gpointer data)
+{
+ PurpleSavedPresence *presence = NULL;
+ const char *id = NULL;
- presence = g_object_new(
- PURPLE_TYPE_SAVED_PRESENCE,
- "id", ids[i],
- "settings", settings,
- NULL);
-
- purple_presence_manager_add(manager, presence);
-
- g_clear_object(&presence);
+ if(!g_variant_type_equal(expected_type, G_VARIANT_TYPE_STRING)) {
+ return NULL;
}
- g_strfreev(ids);
+ presence = g_value_get_object(value);
+ if(!PURPLE_IS_SAVED_PRESENCE(presence)) {
+ return NULL;
+ }
+
+ id = purple_saved_presence_get_id(presence);
+
+ return g_variant_new_string(id);
}
/******************************************************************************
@@ -274,15 +337,17 @@
static void
purple_presence_manager_constructed(GObject *obj) {
PurplePresenceManager *manager = PURPLE_PRESENCE_MANAGER(obj);
- char *active_id = NULL;
G_OBJECT_CLASS(purple_presence_manager_parent_class)->constructed(obj);
- if(manager->filename == NULL) {
+ if(manager->path == NULL) {
manager->backend = g_memory_settings_backend_new();
} else {
- manager->backend = g_keyfile_settings_backend_new(manager->filename,
- "/", NULL);
+ char *filename = NULL;
+
+ filename = g_build_filename(manager->path, "manager.ini", NULL);
+ manager->backend = g_keyfile_settings_backend_new(filename, "/", NULL);
+ g_clear_pointer(&filename, g_free);
}
manager->settings = g_settings_new_with_backend(MANAGER_SCHEMA_ID,
@@ -290,21 +355,18 @@
purple_presence_manager_load_saved_presences(manager);
- active_id = g_settings_get_string(manager->settings, "active");
- if(!purple_strempty(active_id)) {
- if(!purple_presence_manager_set_active(manager, active_id)) {
- g_warning("failed to set the active saved presence to %s",
- active_id);
- }
- }
- g_clear_pointer(&active_id, g_free);
+ g_settings_bind_with_mapping(manager->settings, "active", manager,
+ "active-presence", G_SETTINGS_BIND_DEFAULT,
+ purple_presence_manager_get_active_mapping,
+ purple_presence_manager_set_active_mapping,
+ manager, NULL);
}
static void
purple_presence_manager_finalize(GObject *obj) {
PurplePresenceManager *manager = PURPLE_PRESENCE_MANAGER(obj);
- g_clear_pointer(&manager->filename, g_free);
+ g_clear_pointer(&manager->path, g_free);
g_clear_object(&manager->active);
if(manager->presences != NULL) {
@@ -325,9 +387,9 @@
PurplePresenceManager *manager = PURPLE_PRESENCE_MANAGER(obj);
switch(param_id) {
- case PROP_FILENAME:
+ case PROP_PATH:
g_value_set_string(value,
- purple_presence_manager_get_filename(manager));
+ purple_presence_manager_get_path(manager));
break;
case PROP_ACTIVE:
g_value_set_object(value,
@@ -346,9 +408,13 @@
PurplePresenceManager *manager = PURPLE_PRESENCE_MANAGER(obj);
switch(param_id) {
- case PROP_FILENAME:
- purple_presence_manager_set_filename(manager,
- g_value_get_string(value));
+ case PROP_PATH:
+ purple_presence_manager_set_path(manager,
+ g_value_get_string(value));
+ break;
+ case PROP_ACTIVE:
+ purple_presence_manager_set_active(manager,
+ g_value_get_object(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
@@ -372,16 +438,16 @@
obj_class->set_property = purple_presence_manager_set_property;
/**
- * PurplePresenceManager:filename:
+ * PurplePresenceManager:path:
*
- * The filename where settings should be stored. If this is %NULL settings
- * will not be saved to disk.
+ * The directory path where settings should be stored. If this is %NULL
+ * settings will not be saved to disk.
*
* Since: 3.0.0
*/
- properties[PROP_FILENAME] = g_param_spec_string(
- "filename", "filename",
- "The name of the file where settings should be stored.",
+ properties[PROP_PATH] = g_param_spec_string(
+ "path", "path",
+ "The directory path where settings should be stored.",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
@@ -396,7 +462,7 @@
"active-presence", "active-presence",
"The active presence.",
PURPLE_TYPE_SAVED_PRESENCE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
@@ -484,17 +550,17 @@
}
PurplePresenceManager *
-purple_presence_manager_new(const char *filename) {
+purple_presence_manager_new(const char *path) {
return g_object_new(PURPLE_TYPE_PRESENCE_MANAGER,
- "filename", filename,
+ "path", path,
NULL);
}
const char *
-purple_presence_manager_get_filename(PurplePresenceManager *manager) {
+purple_presence_manager_get_path(PurplePresenceManager *manager) {
g_return_val_if_fail(PURPLE_IS_PRESENCE_MANAGER(manager), NULL);
- return manager->filename;
+ return manager->path;
}
PurpleSavedPresence *
@@ -506,27 +572,21 @@
gboolean
purple_presence_manager_set_active(PurplePresenceManager *manager,
- const char *id)
+ PurpleSavedPresence *presence)
{
- PurpleSavedPresence *presence = NULL;
+ PurpleSavedPresence *found = NULL;
+ const char *id = NULL;
g_return_val_if_fail(PURPLE_IS_PRESENCE_MANAGER(manager), FALSE);
+ g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(presence), FALSE);
- if(id != NULL) {
- presence = purple_presence_manager_find_with_id(manager, id, NULL);
- if(!PURPLE_IS_SAVED_PRESENCE(presence)) {
- return FALSE;
- }
- }
+ /* We need to make sure the manager knows about the passed in presence. */
+ id = purple_saved_presence_get_id(presence);
+ found = purple_presence_manager_find_with_id(manager, id, NULL);
+ g_return_val_if_fail(PURPLE_IS_SAVED_PRESENCE(found), FALSE);
if(g_set_object(&manager->active, presence)) {
g_object_notify_by_pspec(G_OBJECT(manager), properties[PROP_ACTIVE]);
-
- /* g_settings_set_string can't handle nulls, so use an empty string if
- * it is null.
- */
- g_settings_set_string(manager->settings, "active",
- id == NULL ? "" : id);
}
return TRUE;
@@ -535,28 +595,13 @@
PurpleSavedPresence *
purple_presence_manager_create(PurplePresenceManager *manager) {
PurpleSavedPresence *presence = NULL;
- GSettings *settings = NULL;
char *id = NULL;
- char *path = NULL;
g_return_val_if_fail(PURPLE_IS_PRESENCE_MANAGER(manager), FALSE);
id = g_uuid_string_random();
- path = purple_presence_manager_path_for_presence(id);
- settings = g_settings_new_with_backend_and_path(PRESENCE_SCHEMA_ID,
- manager->backend, path);
- g_free(path);
-
- presence = g_object_new(
- PURPLE_TYPE_SAVED_PRESENCE,
- "id", id,
- "settings", settings,
- NULL);
-
- g_clear_pointer(&id, g_free);
- g_clear_object(&settings);
-
- purple_presence_manager_add(manager, presence);
+ presence = purple_presence_manager_add(manager, id);
+ g_free(id);
return presence;
}
@@ -565,6 +610,7 @@
purple_presence_manager_remove(PurplePresenceManager *manager, const char *id)
{
PurpleSavedPresence *presence = NULL;
+ char *filename = NULL;
guint index;
g_return_val_if_fail(PURPLE_IS_PRESENCE_MANAGER(manager), FALSE);
@@ -581,8 +627,10 @@
g_object_ref(presence);
g_ptr_array_remove_index(manager->presences, index);
- purple_presence_manager_update_presences_setting(manager);
- purple_saved_presence_reset(presence);
+
+ filename = purple_presence_manager_get_path_for_id(manager, id);
+ g_remove(filename);
+ g_clear_pointer(&filename, g_free);
g_signal_emit(manager, signals[SIG_REMOVED], 0, presence);
g_list_model_items_changed(G_LIST_MODEL(manager), index, 1, 0);
--- a/libpurple/purplepresencemanager.h Tue Jan 23 00:03:38 2024 -0600
+++ b/libpurple/purplepresencemanager.h Tue Jan 23 00:04:57 2024 -0600
@@ -48,7 +48,7 @@
*
* A manager for [class@SavedPresence]'s.
*
- * Since: 3.0.0
+ * Since: 3.0
*/
/**
@@ -63,7 +63,7 @@
*
* Returns: (transfer none) (nullable): The default presence manager.
*
- * Since: 3.0.0
+ * Since: 3.0
*/
PURPLE_AVAILABLE_IN_3_0
PurplePresenceManager *purple_presence_manager_get_default(void);
@@ -84,39 +84,39 @@
* Returns: (transfer none) (nullable): The default presence manager type cast
* to a list model.
*
- * Since: 3.0.0
+ * Since: 3.0
*/
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.
+ * @path: (nullable): An optional directory path where settings will be stored.
*
* Creates a new presence manager instance.
*
- * If @filename is %NULL, settings will not be stored to disk.
+ * If @path is %NULL, settings will not be stored to disk.
*
* Returns: (transfer full): The new instance.
*
- * Since: 3.0.0
+ * Since: 3.0
*/
PURPLE_AVAILABLE_IN_3_0
-PurplePresenceManager *purple_presence_manager_new(const char *filename);
+PurplePresenceManager *purple_presence_manager_new(const char *path);
/**
- * purple_presence_manager_get_filename:
+ * purple_presence_manager_get_path:
* @manager: The instance.
*
- * Gets the file name that @manager is using for storage.
+ * Gets the directory path that @manager is using for storage.
*
- * Returns: (nullable): The filename where settings are being saved to disk or
- * %NULL.
+ * Returns: (nullable): The directory path where settings are being saved to
+ * disk or %NULL.
*
- * Since: 3.0.0
+ * Since: 3.0
*/
PURPLE_AVAILABLE_IN_3_0
-const char *purple_presence_manager_get_filename(PurplePresenceManager *manager);
+const char *purple_presence_manager_get_path(PurplePresenceManager *manager);
/**
* purple_presence_manager_get_active:
@@ -127,7 +127,7 @@
* Returns: (transfer none) (nullable): The active presence if there is one,
* otherwise %NULL.
*
- * Since: 3.0.0
+ * Since: 3.0
*/
PURPLE_AVAILABLE_IN_3_0
PurpleSavedPresence *purple_presence_manager_get_active(PurplePresenceManager *manager);
@@ -135,21 +135,19 @@
/**
* purple_presence_manager_set_active:
* @manager: The instance.
- * @id: The id of the presence to make active.
+ * @presence: The presence to set as active.
*
- * Sets the active presence to the [class@SavedPresence] with a
- * [property@SavedPresence:id] of @id.
+ * Sets the active presence to @presence.
*
- * If @manager doesn't know of a presence with an id of @id, %FALSE will be
- * returned to indicate failure.
+ * If @manager doesn't know about @presence, %FALSE will be returned to
+ * indicate a failure.
*
- * Returns: %TRUE if a presence was found with an id of @id and made active,
- * otherwise %FALSE.
+ * Returns: %TRUE if a presence was found and made active, otherwise %FALSE.
*
- * Since: 3.0.0
+ * Since: 3.0
*/
PURPLE_AVAILABLE_IN_3_0
-gboolean purple_presence_manager_set_active(PurplePresenceManager *manager, const char *id);
+gboolean purple_presence_manager_set_active(PurplePresenceManager *manager, PurpleSavedPresence *presence);
/**
* purple_presence_manager_create:
@@ -163,7 +161,7 @@
*
* Returns: (transfer full): The new [class@SavedPresence].
*
- * Since: 3.0.0
+ * Since: 3.0
*/
PURPLE_AVAILABLE_IN_3_0
PurpleSavedPresence *purple_presence_manager_create(PurplePresenceManager *manager);
@@ -179,7 +177,7 @@
* Returns: %TRUE if a [class@SavedPresence] was found with @id and removed,
* otherwise %FALSE.
*
- * Since: 3.0.0
+ * Since: 3.0
*/
PURPLE_AVAILABLE_IN_3_0
gboolean purple_presence_manager_remove(PurplePresenceManager *manager, const char *id);
--- a/libpurple/purplesavedpresence.c Tue Jan 23 00:03:38 2024 -0600
+++ b/libpurple/purplesavedpresence.c Tue Jan 23 00:04:57 2024 -0600
@@ -24,7 +24,6 @@
#include "purpleenums.h"
#include "purplesavedpresence.h"
-#include "purplesavedpresenceprivate.h"
#include "util.h"
struct _PurpleSavedPresence {
@@ -437,27 +436,6 @@
}
/******************************************************************************
- * Private API
- *****************************************************************************/
-void
-purple_saved_presence_reset(PurpleSavedPresence *presence) {
- GSettingsSchema *schema = NULL;
- GStrv keys = NULL;
-
- g_return_if_fail(PURPLE_IS_SAVED_PRESENCE(presence));
-
- g_object_get(presence->settings, "settings-schema", &schema, NULL);
-
- keys = g_settings_schema_list_keys(schema);
- for(int i = 0; keys[i] != NULL; i++) {
- g_settings_reset(presence->settings, keys[i]);
- }
- g_strfreev(keys);
-
- g_clear_pointer(&schema, g_settings_schema_unref);
-}
-
-/******************************************************************************
* Public API
*****************************************************************************/
GDateTime *
--- a/libpurple/purplesavedpresenceprivate.h Tue Jan 23 00:03:38 2024 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * 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 "purplesavedpresenceprivate.h may only be include by libpurple"
-#endif
-
-#ifndef PURPLE_SAVED_PRESENCE_PRIVATE_H
-#define PURPLE_SAVED_PRESENCE_PRIVATE_H
-
-#include <glib.h>
-
-#include "purplesavedpresence.h"
-
-G_BEGIN_DECLS
-
-/**
- * purple_saved_presence_reset: (skip)
- * @presence: The instance.
- *
- * Resets all of the settings of @presence to their default values.
- *
- * As of at least glib 2.78.0, the GSettings API doesn't have a way to remove a
- * relocatable settings object. We use relocatable settings to store each saved
- * presence which means we can't delete the section from the GKeyFile.
- *
- * To minimize the amount of disk space wasted by this issue, this function
- * will default all of the keys in the settings object for @presence so that
- * the values will be removed from the GKeyFile.
- *
- * Since: 3.0.0
- */
-G_GNUC_INTERNAL void purple_saved_presence_reset(PurpleSavedPresence *presence);
-
-G_END_DECLS
-
-#endif /* PURPLE_SAVED_PRESENCE_PRIVATE_H */
--- a/libpurple/tests/test_presence_manager.c Tue Jan 23 00:03:38 2024 -0600
+++ b/libpurple/tests/test_presence_manager.c Tue Jan 23 00:04:57 2024 -0600
@@ -71,7 +71,6 @@
test_purple_presence_manager_add_remove(void) {
PurplePresenceManager *manager = NULL;
PurpleSavedPresence *presence = NULL;
- GListModel *model = NULL;
gboolean success = FALSE;
guint len = 0;
guint added = 0;
@@ -81,26 +80,6 @@
manager = purple_presence_manager_new(NULL);
- /* When a presence manager is created, if there are no saved statuses it
- * adds some default ones and sets the active presence. We need to clear
- * all of that to get to a known state.
- *
- * The default statuses are checked in test_purple_presence_manager_new.
- */
- model = G_LIST_MODEL(manager);
- purple_presence_manager_set_active(manager, NULL);
- while(g_list_model_get_n_items(model) > 0) {
- PurpleSavedPresence *presence = NULL;
-
- /* Since we're removing items, the positions change, so we just always
- * want to remove the item at position 0.
- */
- presence = g_list_model_get_item(model, 0);
- purple_presence_manager_remove(manager,
- purple_saved_presence_get_id(presence));
- g_assert_finalize_object(presence);
- }
-
/* Connect all of our signals to make sure they're being emitted. */
g_signal_connect(manager, "added",
G_CALLBACK(test_purple_presence_manager_add_remove_counter),
@@ -113,7 +92,8 @@
&changed);
len = g_list_model_get_n_items(G_LIST_MODEL(manager));
- g_assert_cmpuint(len, ==, 0);
+ /* The manager makes sure we always have online and offline presences. */
+ g_assert_cmpuint(len, ==, 2);
presence = purple_presence_manager_create(manager);
g_assert_true(PURPLE_IS_SAVED_PRESENCE(presence));
@@ -126,7 +106,7 @@
g_assert_nonnull(id);
len = g_list_model_get_n_items(G_LIST_MODEL(manager));
- g_assert_cmpuint(len, ==, 1);
+ g_assert_cmpuint(len, ==, 3);
success = purple_presence_manager_remove(manager, id);
g_assert_true(success);
@@ -135,7 +115,7 @@
g_assert_cmpuint(changed, ==, 2);
len = g_list_model_get_n_items(G_LIST_MODEL(manager));
- g_assert_cmpuint(len, ==, 0);
+ g_assert_cmpuint(len, ==, 2);
g_clear_object(&presence);
g_clear_object(&manager);
@@ -145,32 +125,34 @@
test_purple_presence_manager_persistence(void) {
PurplePresenceManager *manager = NULL;
PurpleSavedPresence *presence = NULL;
+ char *path = NULL;
char *filename = NULL;
char *old_id = NULL;
const char *id = NULL;
const char *id1 = NULL;
gboolean ret = FALSE;
- filename = g_build_filename(TEST_CACHE_DIR,
- "presence_manager_persistence.ini",
- NULL);
+ path = g_build_filename(TEST_CACHE_DIR, "presence_manager_persistence",
+ NULL);
/* Remove the file if it exists so we can start from a known state. */
+ filename = g_build_filename(path, "manager.ini", NULL);
g_remove(filename);
+ g_clear_pointer(&filename, g_free);
/* Create the manager, add a presence, and make it active. */
- manager = purple_presence_manager_new(filename);
+ manager = purple_presence_manager_new(path);
g_assert_true(PURPLE_IS_PRESENCE_MANAGER(manager));
presence = purple_presence_manager_create(manager);
- g_assert_true(PURPLE_IS_SAVED_PRESENCE(presence));
+ purple_saved_presence_set_name(presence, "test-presence");
/* Save the id of the presence as we need to use it later. */
id = purple_saved_presence_get_id(presence);
old_id = g_strdup(id);
/* Make the presence active. */
- ret = purple_presence_manager_set_active(manager, id);
+ ret = purple_presence_manager_set_active(manager, presence);
g_assert_true(ret);
g_clear_object(&presence);
@@ -187,7 +169,7 @@
g_clear_object(&manager);
/* Now create the manager again and verify that everything was restored. */
- manager = purple_presence_manager_new(filename);
+ manager = purple_presence_manager_new(path);
g_assert_true(PURPLE_IS_PRESENCE_MANAGER(manager));
presence = purple_presence_manager_get_active(manager);
@@ -199,7 +181,7 @@
/* Cleanup. */
g_clear_object(&manager);
- g_clear_pointer(&filename, g_free);
+ g_clear_pointer(&path, g_free);
}
/******************************************************************************
--- a/libpurple/tests/test_saved_presence.c Tue Jan 23 00:03:38 2024 -0600
+++ b/libpurple/tests/test_saved_presence.c Tue Jan 23 00:04:57 2024 -0600
@@ -124,7 +124,7 @@
char *timestamp = NULL;
backend = g_memory_settings_backend_new();
- settings = g_settings_new_with_backend_and_path(SCHEMA_ID, backend, "/");
+ settings = g_settings_new_with_backend(SCHEMA_ID, backend);
presence = g_object_new(
PURPLE_TYPE_SAVED_PRESENCE,
@@ -178,7 +178,7 @@
char *timestamp = NULL;
backend = g_memory_settings_backend_new();
- settings = g_settings_new_with_backend_and_path(SCHEMA_ID, backend, "/");
+ settings = g_settings_new_with_backend(SCHEMA_ID, backend);
presence = g_object_new(
PURPLE_TYPE_SAVED_PRESENCE,
--- a/pidgin/pidginui.c Tue Jan 23 00:03:38 2024 -0600
+++ b/pidgin/pidginui.c Tue Jan 23 00:04:57 2024 -0600
@@ -185,13 +185,13 @@
static PurplePresenceManager *
pidgin_ui_get_presence_manager(G_GNUC_UNUSED PurpleUi *ui) {
PurplePresenceManager *manager = NULL;
- char *filename = NULL;
+ char *path = 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);
+ path = g_build_filename(purple_config_dir(), "presences", NULL);
+ manager = purple_presence_manager_new(path);
+ g_free(path);
return manager;
}