Skip to content

Commit

Permalink
Merge branch 'gsettings-cpp' into stable #1682
Browse files Browse the repository at this point in the history
plugs a runaway leak
  • Loading branch information
christopherlam committed Jul 4, 2023
2 parents b011c81 + d287c30 commit 59be6f4
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 58 deletions.
98 changes: 58 additions & 40 deletions libgnucash/app-utils/gnc-gsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,26 @@
#include <boost/property_tree/xml_parser.hpp>
#include <fstream>
#include <iostream>
#include <unordered_map>

namespace bpt = boost::property_tree;

#define GSET_SCHEMA_PREFIX "org.gnucash.GnuCash"
#define GSET_SCHEMA_OLD_PREFIX "org.gnucash"

static GHashTable *schema_hash = nullptr;
struct GSettingsDeleter
{
void operator()(GSettings* gsp)
{
g_object_unref(gsp);
}
};

static GSettingsDeleter g_settings_deleter;

using GSettingsPtr = std::unique_ptr<GSettings, GSettingsDeleter>;

static std::unordered_map<std::string,GSettingsPtr> schema_hash;

/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = "gnc.app-utils.gsettings";
Expand All @@ -72,11 +85,25 @@ static bool gnc_gsettings_is_valid_key(GSettings *settings, const gchar *key)
return found;
}

static std::string
normalize_schema_name (const gchar *name)
{
if (!name)
return GSET_SCHEMA_PREFIX;

if (g_str_has_prefix (name, GSET_SCHEMA_PREFIX) ||
(g_str_has_prefix (name, GSET_SCHEMA_OLD_PREFIX)))
return name;

return std::string{GSET_SCHEMA_PREFIX} + '.' + name;
}

static GSettings * gnc_gsettings_get_settings_obj (const gchar *schema_str)
{
ENTER("");

auto full_name = gnc_gsettings_normalize_schema_name (schema_str);
auto full_name_str = normalize_schema_name (schema_str);
auto full_name = full_name_str.c_str();
auto schema_source {g_settings_schema_source_get_default()};
auto schema {g_settings_schema_source_lookup(schema_source, full_name, true)};
auto gset = g_settings_new_full (schema, nullptr, nullptr);
Expand All @@ -85,13 +112,33 @@ static GSettings * gnc_gsettings_get_settings_obj (const gchar *schema_str)
if (!G_IS_SETTINGS(gset))
PWARN ("Ignoring attempt to access unknown gsettings schema %s", full_name);

g_free(full_name);

LEAVE("");
g_settings_schema_unref (schema);
return gset;
}

static GSettings*
schema_to_gsettings (const char *schema, bool can_retrieve)
{
auto full_name = normalize_schema_name (schema);
auto iter = schema_hash.find (full_name);
if (iter != schema_hash.end())
return iter->second.get();

if (!can_retrieve)
return nullptr;

auto gs_obj = gnc_gsettings_get_settings_obj (schema);
if (!G_IS_SETTINGS (gs_obj))
{
PWARN ("Ignoring attempt to access unknown gsettings schema %s", full_name.c_str());
return nullptr;
}

schema_hash[full_name] = GSettingsPtr (gs_obj, g_settings_deleter);
return gs_obj;
}

/************************************************************/
/* GSettings Utilities */
/************************************************************/
Expand All @@ -102,20 +149,6 @@ gnc_gsettings_get_prefix (void)
return GSET_SCHEMA_PREFIX;
}

gchar *
gnc_gsettings_normalize_schema_name (const gchar *name)
{
if (!name)
return g_strdup(GSET_SCHEMA_PREFIX);

if (g_str_has_prefix (name, GSET_SCHEMA_PREFIX) ||
(g_str_has_prefix (name, GSET_SCHEMA_OLD_PREFIX)))
return g_strdup(name);

return g_strjoin(".", GSET_SCHEMA_PREFIX, name, nullptr);
}


/************************************************************/
/* Change notification */
/************************************************************/
Expand All @@ -128,20 +161,7 @@ gnc_gsettings_register_cb (const gchar *schema, const gchar *key,
ENTER("");
g_return_val_if_fail (func, 0);

if (!schema_hash)
schema_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);

auto full_name = gnc_gsettings_normalize_schema_name (schema);
auto gs_obj = static_cast<GSettings*> (g_hash_table_lookup (schema_hash, full_name));
if (!gs_obj)
{
gs_obj = gnc_gsettings_get_settings_obj (schema);
if (G_IS_SETTINGS (gs_obj))
g_hash_table_insert (schema_hash, g_strdup (full_name), gs_obj);
else
PWARN ("Ignoring attempt to access unknown gsettings schema %s", full_name);
}
g_free (full_name);
auto gs_obj = schema_to_gsettings (schema, true);
g_return_val_if_fail (G_IS_SETTINGS (gs_obj), 0);

auto signal = static_cast<char *> (nullptr);
Expand Down Expand Up @@ -186,9 +206,7 @@ gnc_gsettings_remove_cb_by_func (const gchar *schema, const gchar *key,
ENTER ();
g_return_if_fail (func);

auto full_name = gnc_gsettings_normalize_schema_name (schema);
auto gs_obj = static_cast<GSettings*> (g_hash_table_lookup (schema_hash, full_name));
g_free (full_name);
auto gs_obj = schema_to_gsettings (schema, false);

if (!G_IS_SETTINGS (gs_obj))
{
Expand Down Expand Up @@ -228,9 +246,7 @@ gnc_gsettings_remove_cb_by_id (const gchar *schema, guint handlerid)
{
ENTER ();

auto full_name = gnc_gsettings_normalize_schema_name (schema);
auto gs_obj = static_cast<GSettings*> (g_hash_table_lookup (schema_hash, full_name));
g_free (full_name);
auto gs_obj = schema_to_gsettings (schema, false);

if (!G_IS_SETTINGS (gs_obj))
{
Expand Down Expand Up @@ -297,15 +313,17 @@ gs_obj_unblock_handlers ([[maybe_unused]] gpointer key, gpointer gs_obj,
void gnc_gsettings_block_all (void)
{
ENTER ();
g_hash_table_foreach (schema_hash, gs_obj_block_handlers, nullptr);
for (const auto& it : schema_hash)
gs_obj_block_handlers (nullptr, it.second.get(), nullptr);
LEAVE();
}


void gnc_gsettings_unblock_all (void)
{
ENTER ();
g_hash_table_foreach (schema_hash, gs_obj_unblock_handlers, nullptr);
for (const auto& it : schema_hash)
gs_obj_unblock_handlers (nullptr, it.second.get(), nullptr);
LEAVE();
}

Expand Down
18 changes: 0 additions & 18 deletions libgnucash/app-utils/gnc-gsettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,6 @@
extern "C" {
#endif

/** Convert a partial schema name into a complete gsettings schema name.
*
* This function takes a partial gsettings schema name and converts
* it into a fully qualified gsettings schema name. It does this
* by prepending the standard prefix for all gnucash schemas.
* If the schema is already fully qualified (i.e. begins with the
* default schema prefix, this routine will not change it.
*
* @param name A partial schema name. The default prefix is
* prepended to this name to produce a fully qualified schema
* name.
*
* @return This function returns a string pointer to the fully
* qualified schema name. It is the caller's responsibility to
* free this string.
*/
gchar *gnc_gsettings_normalize_schema_name (const gchar *name);

/** Get the default gsettings schema prefix.
* If none was set explicitly, this defaults to
* "org.gnucash.GnuCash"
Expand Down

0 comments on commit 59be6f4

Please sign in to comment.