gnucash/libgnucash/app-utils/gnc-gsettings.c
Robert Fewell b2ed250db1 Change gsettings upgrade test so old_maj_min is < 207
With the original value of 208, the use-gnucash-color-theme kept on
being reset to what ever the use-theme-colors was, by default false.
2018-02-18 22:41:39 +00:00

853 lines
26 KiB
C

/********************************************************************\
* gnc-gsettings.c -- utility functions for storing/retrieving *
* data in the GSettings database for GnuCash *
* Copyright (C) 2013 Geert Janssens <geert@kobaltwit.be> *
* *
* 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, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
* *
\********************************************************************/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include "gnc-gsettings.h"
#include "gnc-path.h"
#include "guile-mappings.h"
#include <libguile.h>
#include "qof.h"
#include "gnc-prefs-p.h"
#include <libxml/xmlmemory.h>
#include <libxml/debugXML.h>
#include <libxml/HTMLtree.h>
#include <libxml/xmlIO.h>
#include <libxml/xinclude.h>
#include <libxml/catalog.h>
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#define CLIENT_TAG "%s-%s-client"
#define NOTIFY_TAG "%s-%s-notify_id"
#define GNC_PREF_MIGRATE_PREFS_DONE "migrate-prefs-done"
static GHashTable *schema_hash = NULL;
static const gchar *gsettings_prefix;
static xmlExternalEntityLoader defaultEntityLoader = NULL;
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = "gnc.app-utils.gsettings";
/************************************************************/
/* Internal helper functions */
/************************************************************/
static gboolean gnc_gsettings_is_valid_key(GSettings *settings, const gchar *key)
{
gchar **keys = NULL;
gint i = 0;
gboolean found = FALSE;
#ifdef HAVE_GLIB_2_46
GSettingsSchema *schema;
#endif
// Check if the key is valid key within settings
if (!G_IS_SETTINGS(settings))
return FALSE;
#ifdef HAVE_GLIB_2_46
g_object_get (settings, "settings-schema", &schema, NULL);
if (!schema)
return FALSE;
#endif
// Get list of keys
#ifdef HAVE_GLIB_2_46
keys = g_settings_schema_list_keys(schema);
#else
keys = g_settings_list_keys(settings);
#endif
while (keys && keys[i])
{
if (!g_strcmp0(key, keys[i]))
{
found = TRUE;
break;
}
i++;
}
// Free keys
g_strfreev(keys);
return found;
}
static GSettings * gnc_gsettings_get_settings_ptr (const gchar *schema_str)
{
GSettings *gset = NULL;
gchar *full_name = gnc_gsettings_normalize_schema_name (schema_str);
ENTER("");
if (!schema_hash)
schema_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
gset = g_hash_table_lookup (schema_hash, full_name);
DEBUG ("Looking for schema %s returned gsettings %p", full_name, gset);
if (!gset)
{
gset = g_settings_new (full_name);
DEBUG ("Created gsettings object %p for schema %s", gset, full_name);
if (G_IS_SETTINGS(gset))
g_hash_table_insert (schema_hash, full_name, gset);
else
PWARN ("Ignoring attempt to access unknown gsettings schema %s", full_name);
}
else
{
g_free(full_name);
}
LEAVE("");
return gset;
}
/************************************************************/
/* GSettings Utilities */
/************************************************************/
void
gnc_gsettings_set_prefix (const gchar *prefix)
{
gsettings_prefix = prefix;
}
const gchar *
gnc_gsettings_get_prefix (void)
{
if (!gsettings_prefix)
{
const char *prefix = g_getenv("GNC_GSETTINGS_PREFIX");
if (prefix)
gsettings_prefix = prefix;
else
gsettings_prefix = GSET_SCHEMA_PREFIX;
}
return gsettings_prefix;
}
gchar *
gnc_gsettings_normalize_schema_name (const gchar *name)
{
if (name == NULL)
{
/* Need to return a newly allocated string */
return g_strdup(gnc_gsettings_get_prefix());
}
if (g_str_has_prefix (name, gnc_gsettings_get_prefix ()))
{
/* Need to return a newly allocated string */
return g_strdup(name);
}
return g_strjoin(".", gnc_gsettings_get_prefix(), name, NULL);
}
/************************************************************/
/* Change notification */
/************************************************************/
gulong
gnc_gsettings_register_cb (const gchar *schema,
const gchar *key,
gpointer func,
gpointer user_data)
{
gulong retval = 0;
gchar *signal = NULL;
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
ENTER("");
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), retval);
g_return_val_if_fail (func, retval);
if ((!key) || (*key == '\0'))
signal = g_strdup ("changed");
else
{
if (gnc_gsettings_is_valid_key(settings_ptr, key))
signal = g_strconcat ("changed::", key, NULL);
}
retval = g_signal_connect (settings_ptr, signal, G_CALLBACK (func), user_data);
g_free (signal);
LEAVE("");
return retval;
}
void
gnc_gsettings_remove_cb_by_func (const gchar *schema,
const gchar *key,
gpointer func,
gpointer user_data)
{
gint matched = 0;
GQuark quark = 0;
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_if_fail (G_IS_SETTINGS (settings_ptr));
g_return_if_fail (func);
ENTER ();
if ((key) && (gnc_gsettings_is_valid_key(settings_ptr, key)))
quark = g_quark_from_string (key);
matched = g_signal_handlers_disconnect_matched (
settings_ptr,
G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
g_signal_lookup ("changed", G_TYPE_SETTINGS), /* signal_id */
quark, /* signal_detail */
NULL, /* closure */
G_CALLBACK (func), /* callback function */
user_data);
LEAVE ("Schema: %s, key: %s - removed %d handlers for 'changed' signal", schema, key, matched);
}
void
gnc_gsettings_remove_cb_by_id (const gchar *schema,
guint handlerid)
{
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_if_fail (G_IS_SETTINGS (settings_ptr));
g_signal_handler_disconnect (settings_ptr, handlerid);
}
guint
gnc_gsettings_register_any_cb (const gchar *schema,
gpointer func,
gpointer user_data)
{
return gnc_gsettings_register_cb (schema, NULL, func, user_data);
}
void
gnc_gsettings_remove_any_cb_by_func (const gchar *schema,
gpointer func,
gpointer user_data)
{
gnc_gsettings_remove_cb_by_func (schema, NULL, func, user_data);
}
void gnc_gsettings_bind (const gchar *schema,
/*@ null @*/ const gchar *key,
gpointer object,
const gchar *property)
{
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_if_fail (G_IS_SETTINGS (settings_ptr));
if (gnc_gsettings_is_valid_key (settings_ptr, key))
g_settings_bind (settings_ptr, key, object, property, 0);
else
{
PERR ("Invalid key %s for schema %s", key, schema);
}
}
/************************************************************/
/* Getters/Setters */
/************************************************************/
gboolean
gnc_gsettings_get_bool (const gchar *schema,
const gchar *key)
{
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), FALSE);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
return g_settings_get_boolean (settings_ptr, key);
else
{
PERR ("Invalid key %s for schema %s", key, schema);
return FALSE;
}
}
gboolean
gnc_gsettings_set_bool (const gchar *schema,
const gchar *key,
gboolean value)
{
gboolean result = FALSE;
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), FALSE);
ENTER("schema: %s, key: %s", schema, key);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
{
result = g_settings_set_boolean (settings_ptr, key, value);
if (!result)
PERR ("Unable to set value for key %s in schema %s", key, schema);
}
else
PERR ("Invalid key %s for schema %s", key, schema);
LEAVE("result %i", result);
return result;
}
gint
gnc_gsettings_get_int (const gchar *schema,
const gchar *key)
{
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), 0);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
return g_settings_get_int (settings_ptr, key);
else
{
PERR ("Invalid key %s for schema %s", key, schema);
return 0;
}
}
gboolean
gnc_gsettings_set_int (const gchar *schema,
const gchar *key,
gint value)
{
gboolean result = FALSE;
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), FALSE);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
{
result = g_settings_set_int (settings_ptr, key, value);
if (!result)
PERR ("Unable to set value for key %s in schema %s", key, schema);
}
else
PERR ("Invalid key %s for schema %s", key, schema);
return result;
}
gdouble
gnc_gsettings_get_float (const gchar *schema,
const gchar *key)
{
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), 0);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
return g_settings_get_double (settings_ptr, key);
else
{
PERR ("Invalid key %s for schema %s", key, schema);
return 0;
}
}
gboolean
gnc_gsettings_set_float (const gchar *schema,
const gchar *key,
gdouble value)
{
gboolean result = FALSE;
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), FALSE);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
{
result = g_settings_set_double (settings_ptr, key, value);
if (!result)
PERR ("Unable to set value for key %s in schema %s", key, schema);
}
else
PERR ("Invalid key %s for schema %s", key, schema);
return result;
}
gchar *
gnc_gsettings_get_string (const gchar *schema,
const gchar *key)
{
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), NULL);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
return g_settings_get_string (settings_ptr, key);
else
{
PERR ("Invalid key %s for schema %s", key, schema);
return NULL;
}
}
gboolean
gnc_gsettings_set_string (const gchar *schema,
const gchar *key,
const gchar *value)
{
gboolean result = FALSE;
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), FALSE);
ENTER("schema: %s, key: %s", schema, key);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
{
result = g_settings_set_string (settings_ptr, key, value);
if (!result)
PERR ("Unable to set value for key %s in schema %s", key, schema);
}
else
PERR ("Invalid key %s for schema %s", key, schema);
LEAVE("result %i", result);
return result;
}
gint
gnc_gsettings_get_enum (const gchar *schema,
const gchar *key)
{
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), 0);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
return g_settings_get_enum (settings_ptr, key);
else
{
PERR ("Invalid key %s for schema %s", key, schema);
return 0;
}
}
gboolean
gnc_gsettings_set_enum (const gchar *schema,
const gchar *key,
gint value)
{
gboolean result = FALSE;
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), FALSE);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
{
result = g_settings_set_enum (settings_ptr, key, value);
if (!result)
PERR ("Unable to set value for key %s in schema %s", key, schema);
}
else
PERR ("Invalid key %s for schema %s", key, schema);
return result;
}
GVariant *
gnc_gsettings_get_value (const gchar *schema,
const gchar *key)
{
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), NULL);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
return g_settings_get_value (settings_ptr, key);
else
{
PERR ("Invalid key %s for schema %s", key, schema);
return NULL;
}
}
gboolean
gnc_gsettings_set_value (const gchar *schema,
const gchar *key,
GVariant *value)
{
gboolean result = FALSE;
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_val_if_fail (G_IS_SETTINGS (settings_ptr), FALSE);
if (gnc_gsettings_is_valid_key (settings_ptr, key))
{
result = g_settings_set_value (settings_ptr, key, value);
if (!result)
PERR ("Unable to set value for key %s in schema %s", key, schema);
}
else
PERR ("Invalid key %s for schema %s", key, schema);
return result;
}
void
gnc_gsettings_reset (const gchar *schema,
const gchar *key)
{
GSettings *settings_ptr = gnc_gsettings_get_settings_ptr (schema);
g_return_if_fail (G_IS_SETTINGS (settings_ptr));
if (gnc_gsettings_is_valid_key (settings_ptr, key))
g_settings_reset (settings_ptr, key);
else
PERR ("Invalid key %s for schema %s", key, schema);
}
void
gnc_gsettings_reset_schema (const gchar *schema_str)
{
gchar **keys;
gint counter = 0;
#ifdef HAVE_GLIB_2_46
GSettingsSchema *schema;
#endif
GSettings *settings = gnc_gsettings_get_settings_ptr (schema_str);
if (!settings)
return;
#ifdef HAVE_GLIB_2_46
g_object_get (settings, "settings-schema", &schema, NULL);
if (!schema)
return;
keys = g_settings_schema_list_keys (schema);
#else
keys = g_settings_list_keys (settings);
#endif
if (!keys)
return;
while (keys[counter])
{
gnc_gsettings_reset (schema_str, keys[counter]);
counter++;
}
g_strfreev (keys);
}
void gnc_gsettings_load_backend (void)
{
ENTER("");
/* The gsettings backend only works in an installed environment.
* When called from the source environment (for testing purposes)
* simply return.
*/
if (g_strcmp0 (g_getenv ("GNC_UNINSTALLED"), "1") == 0)
return;
if (!prefsbackend)
prefsbackend = g_new0 (PrefsBackend, 1);
prefsbackend->register_cb = gnc_gsettings_register_cb;
prefsbackend->remove_cb_by_func = gnc_gsettings_remove_cb_by_func;
prefsbackend->remove_cb_by_id = gnc_gsettings_remove_cb_by_id;
prefsbackend->register_group_cb = gnc_gsettings_register_any_cb;
prefsbackend->remove_group_cb_by_func = gnc_gsettings_remove_any_cb_by_func;
prefsbackend->bind = gnc_gsettings_bind;
prefsbackend->get_bool = gnc_gsettings_get_bool;
prefsbackend->get_int = gnc_gsettings_get_int;
prefsbackend->get_float = gnc_gsettings_get_float;
prefsbackend->get_string = gnc_gsettings_get_string;
prefsbackend->get_enum = gnc_gsettings_get_enum;
prefsbackend->get_value = gnc_gsettings_get_value;
prefsbackend->set_bool = gnc_gsettings_set_bool;
prefsbackend->set_int = gnc_gsettings_set_int;
prefsbackend->set_float = gnc_gsettings_set_float;
prefsbackend->set_string = gnc_gsettings_set_string;
prefsbackend->set_enum = gnc_gsettings_set_enum;
prefsbackend->set_value = gnc_gsettings_set_value;
prefsbackend->reset = gnc_gsettings_reset;
prefsbackend->reset_group = gnc_gsettings_reset_schema;
LEAVE("Prefsbackend bind = %p", prefsbackend->bind);
}
/* Attempt to migrate preferences from gconf files
to gsettings if not already done so */
/* This snippet is borrowed from the xsltproc source
* and adapted to help the xsl transform find our temporary
* files in $HOME/.gnc-migration-tmp/
*/
static xmlParserInputPtr
xsltprocExternalEntityLoader(const char *URL, const char *ID,
xmlParserCtxtPtr ctxt)
{
xmlParserInputPtr ret;
warningSAXFunc warning = NULL;
xmlChar *newURL;
gchar *tmpdir = g_build_filename (g_get_home_dir (), ".gnc-migration-tmp", NULL);
const char *lastsegment = URL;
const char *iter = URL;
while (*iter != 0)
{
if (*iter == '/')
lastsegment = iter + 1;
iter++;
}
if ((ctxt != NULL) && (ctxt->sax != NULL))
{
warning = ctxt->sax->warning;
ctxt->sax->warning = NULL;
}
if (defaultEntityLoader != NULL)
{
ret = defaultEntityLoader(URL, ID, ctxt);
if (ret != NULL)
{
if (warning != NULL)
ctxt->sax->warning = warning;
return(ret);
}
}
newURL = xmlStrdup((const xmlChar *) tmpdir);
newURL = xmlStrcat(newURL, (const xmlChar *) "/");
newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
g_free (tmpdir);
if (newURL != NULL)
{
ret = defaultEntityLoader((const char *)newURL, ID, ctxt);
if (ret != NULL)
{
if (warning != NULL)
ctxt->sax->warning = warning;
xmlFree(newURL);
return(ret);
}
xmlFree(newURL);
}
if (warning != NULL)
{
ctxt->sax->warning = warning;
if (URL != NULL)
DEBUG ("External entity \"%s\" not loaded", URL);
else if (ID != NULL)
DEBUG ("External entity \"%s\" not loaded", ID);
}
return(NULL);
}
/* Tool to migrate existing user settings from GConf to GSettings
*
* This tool will first run some sanity checks to see if migration
* is necessary/possible. The actual migration works directly from
* the GConf .xml files. Using an xsl transform it will convert them
* in a guile script to set most settings found.
*
* Notes:
* - due to some limitations in the xslt code, all the gconf xml files are
* first copied into a temporary directory. After the migration has finished,
* that temporary directory and its contents are removed.
* - not all settings can be migrated. All the important ones are though.
* The ones that are missing are mostly with respect to window position
* and size.
* - column widths/visibilities, sorting orders,... are no longer stored
* in gsettings, so these will obviously not be migrated either.
* - upon a successful run, a flag will be set to prevent the migration
* from running again. So in normal circumstances the migration will
* be executed only once.
*/
static void gnc_gsettings_migrate_from_gconf (void)
{
gchar *pkgdatadir, *stylesheet, *input, *output, *command;
gchar *gconf_root, *gconf_apps, *gconf_gnucash;
gchar *base_dir, *iter;
SCM migr_script;
xsltStylesheetPtr stylesheetptr = NULL;
xmlDocPtr inputxml, transformedxml;
FILE *outfile;
gboolean migration_ok = FALSE;
ENTER ();
base_dir = g_strdup (g_get_home_dir ());
for (iter = base_dir; *iter != 0; iter++)
{
if ( *iter == '\\')
*iter = '/';
}
/* Only attempt to migrate if there is something to migrate */
gconf_root = g_build_filename(base_dir, ".gconf", NULL);
gconf_apps = g_build_filename(gconf_root, "apps", NULL);
gconf_gnucash = g_build_filename(gconf_apps, "gnucash", NULL);
migration_ok = (g_file_test (gconf_root, G_FILE_TEST_IS_DIR) &&
g_file_test (gconf_apps, G_FILE_TEST_IS_DIR) &&
g_file_test (gconf_gnucash, G_FILE_TEST_IS_DIR));
g_free (gconf_root);
g_free (gconf_apps);
g_free (gconf_gnucash);
if (!migration_ok)
{
g_free (base_dir);
gnc_gsettings_set_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_MIGRATE_PREFS_DONE, TRUE);
PINFO ("No pre-existing GConf gnucash section found.\n"
"Most likely this system never ran GnuCash before.\n"
"Assume migration is not needed.");
LEAVE ();
return;
}
pkgdatadir = gnc_path_get_pkgdatadir();
stylesheet = g_build_filename(pkgdatadir, "make-prefs-migration-script.xsl", NULL);
input = g_build_filename(pkgdatadir, "migratable-prefs.xml", NULL);
g_free (pkgdatadir);
migration_ok = (g_file_test (stylesheet, G_FILE_TEST_IS_REGULAR) &&
g_file_test (input, G_FILE_TEST_IS_REGULAR));
if (!migration_ok)
{
/* Critical files not found, abort migration */
g_free (base_dir);
g_free (stylesheet);
g_free (input);
PWARN ("Migration input file and stylesheet missing. Skip migration.");
return;
}
command = g_strconcat ("(use-modules (migrate-prefs))(migration-prepare \"",
base_dir, "\")", NULL);
DEBUG ("command = %s", command);
migration_ok = scm_is_true (scm_c_eval_string (command));
g_free (command);
if (!migration_ok)
{
/* Preparation step failed */
g_free (base_dir);
g_free (stylesheet);
g_free (input);
PWARN ("Migration preparation step failed. Skip migration.");
LEAVE ();
return;
}
output = g_build_filename(base_dir, ".gnc-migration-tmp", "migrate-prefs-user.scm", NULL);
xmlSubstituteEntitiesDefault(1);
xmlLoadExtDtdDefaultValue = 1;
defaultEntityLoader = xmlGetExternalEntityLoader();
xmlSetExternalEntityLoader(xsltprocExternalEntityLoader);
stylesheetptr = xsltParseStylesheetFile((const xmlChar *)stylesheet);
inputxml = xmlParseFile(input);
transformedxml = xsltApplyStylesheet(stylesheetptr, inputxml, NULL);
outfile = fopen(output, "w");
xsltSaveResultToFile(outfile, transformedxml, stylesheetptr);
fclose(outfile);
xsltFreeStylesheet(stylesheetptr);
xmlFreeDoc(inputxml);
xmlFreeDoc(transformedxml);
xsltCleanupGlobals();
xmlCleanupParser();
g_free (stylesheet);
g_free (input);
migr_script = scm_from_locale_string (output);
scm_primitive_load (migr_script);
g_free (output);
migration_ok = scm_is_true (scm_c_eval_string ("(use-modules (migrate-prefs-user))(run-migration)"));
if (!migration_ok)
{
/* Actual migration step failed */
g_free (base_dir);
PWARN ("Actual migration step failed. Skip migration.");
LEAVE ();
return;
}
/* If we got here, the preferences were migrated successfully
* Mark this success in gsettings, so we won't run the migration again.
*/
gnc_gsettings_set_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_MIGRATE_PREFS_DONE, TRUE);
/* All that is left now is to cleanup... */
command = g_strconcat ("(use-modules (migrate-prefs))(migration-cleanup \"",
base_dir, "\")", NULL);
DEBUG ("command = %s", command);
migration_ok = scm_is_true (scm_c_eval_string (command));
g_free (command);
if (!migration_ok) /* Cleanup step failed, not critical */
PWARN ("Cleanup step failed. You may need to delete %s/.gnc-migration-tmp manually.", base_dir);
else
PINFO ("Preferences migration completed successfully");
LEAVE ("");
g_free (base_dir);
}
void gnc_gsettings_version_upgrade (void)
{
/* Use versioning to ensure this routine will only sync once for each
* superseded setting */
int old_maj_min = gnc_gsettings_get_int (GNC_PREFS_GROUP_GENERAL, GNC_PREF_VERSION);
int cur_maj_min = GNUCASH_MAJOR_VERSION * 100 + GNUCASH_MINOR_VERSION;
/* Migrate preferences from gconf to gsettings */
if (!gnc_gsettings_get_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_MIGRATE_PREFS_DONE))
gnc_gsettings_migrate_from_gconf ();
/* Convert settings to 3.0 compatibility level */
if (old_maj_min < 207)
{
/* 'use-theme-colors' has been replaced with 'use-gnucash-color-theme'
* which inverts the meaning of the setting */
gboolean old_color_theme = gnc_gsettings_get_bool (GNC_PREFS_GROUP_GENERAL_REGISTER, GNC_PREF_USE_THEME_COLORS);
gnc_gsettings_set_bool (GNC_PREFS_GROUP_GENERAL_REGISTER, GNC_PREF_USE_GNUCASH_COLOR_THEME, !old_color_theme);
}
/* Only write current version if it's more recent than what was set */
if (cur_maj_min > old_maj_min)
gnc_gsettings_set_int (GNC_PREFS_GROUP_GENERAL, GNC_PREF_VERSION, cur_maj_min);
}