31 #include "guile-mappings.h"
33 #include "libqof/qof/qof.h"
34 #include "gnc-prefs-p.h"
36 #include <libxml/xmlmemory.h>
37 #include <libxml/debugXML.h>
38 #include <libxml/HTMLtree.h>
39 #include <libxml/xmlIO.h>
40 #include <libxml/xinclude.h>
41 #include <libxml/catalog.h>
42 #include <libxslt/xslt.h>
43 #include <libxslt/xsltInternals.h>
44 #include <libxslt/transform.h>
45 #include <libxslt/xsltutils.h>
47 #define CLIENT_TAG "%s-%s-client"
48 #define NOTIFY_TAG "%s-%s-notify_id"
50 #define GNC_PREF_MIGRATE_PREFS_DONE "migrate-prefs-done"
52 static GHashTable *schema_hash = NULL;
53 static const gchar *gsettings_prefix;
54 static xmlExternalEntityLoader defaultEntityLoader = NULL;
57 static QofLogModule log_module =
"gnc.app-utils.gsettings";
62 static gboolean gnc_gsettings_is_valid_key(GSettings *settings,
const gchar *key)
66 gboolean found = FALSE;
69 if (!G_IS_SETTINGS(settings))
73 keys = g_settings_list_keys(settings);
75 while (keys && keys[i])
77 if (!g_strcmp0(key, keys[i]))
91 static GSettings * gnc_gsettings_get_schema_ptr (
const gchar *schema_str)
93 GSettings *gset = NULL;
98 schema_hash = g_hash_table_new (g_str_hash, g_str_equal);
100 gset = g_hash_table_lookup (schema_hash, full_name);
101 DEBUG (
"Looking for schema %s returned gsettings %p", full_name, gset);
104 gset = g_settings_new (full_name);
105 DEBUG (
"Created gsettings object %p for schema %s", gset, full_name);
106 if (G_IS_SETTINGS(gset))
107 g_hash_table_insert (schema_hash, full_name, gset);
109 PWARN (
"Ignoring attempt to access unknown gsettings schema %s", full_name);
124 gsettings_prefix = prefix;
130 if (!gsettings_prefix)
132 const char *prefix = g_getenv(
"GNC_GSETTINGS_PREFIX");
134 gsettings_prefix = prefix;
136 gsettings_prefix = GSET_SCHEMA_PREFIX;
138 return gsettings_prefix;
152 return g_strdup(name);
170 gchar *signal = NULL;
172 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
175 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), retval);
176 g_return_val_if_fail (func, retval);
178 if ((!key) || (*key ==
'\0'))
179 signal = g_strdup (
"changed");
182 if (gnc_gsettings_is_valid_key(schema_ptr, key))
183 signal = g_strconcat (
"changed::", key, NULL);
186 retval = g_signal_connect (schema_ptr, signal, G_CALLBACK (func), user_data);
204 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
205 g_return_if_fail (G_IS_SETTINGS (schema_ptr));
206 g_return_if_fail (func);
210 if ((key) && (gnc_gsettings_is_valid_key(schema_ptr, key)))
211 quark = g_quark_from_string (key);
213 matched = g_signal_handlers_disconnect_matched (
215 G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
216 g_signal_lookup (
"changed", G_TYPE_SETTINGS),
221 LEAVE (
"Schema: %s, key: %s - removed %d handlers for 'changed' signal", schema, key, matched);
229 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
230 g_return_if_fail (G_IS_SETTINGS (schema_ptr));
232 g_signal_handler_disconnect (schema_ptr, handlerid);
257 const gchar *property)
259 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
260 g_return_if_fail (G_IS_SETTINGS (schema_ptr));
262 if (gnc_gsettings_is_valid_key (schema_ptr, key))
263 g_settings_bind (schema_ptr, key,
object, property, 0);
266 PERR (
"Invalid key %s for schema %s", key, schema);
278 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
279 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), FALSE);
281 if (gnc_gsettings_is_valid_key (schema_ptr, key))
282 return g_settings_get_boolean (schema_ptr, key);
285 PERR (
"Invalid key %s for schema %s", key, schema);
295 gboolean result = FALSE;
296 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
297 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), FALSE);
299 ENTER(
"schema: %s, key: %s", schema, key);
300 if (gnc_gsettings_is_valid_key (schema_ptr, key))
302 result = g_settings_set_boolean (schema_ptr, key, value);
304 PERR (
"Unable to set value for key %s in schema %s", key, schema);
307 PERR (
"Invalid key %s for schema %s", key, schema);
309 LEAVE(
"result %i", result);
317 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
318 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), 0);
320 if (gnc_gsettings_is_valid_key (schema_ptr, key))
321 return g_settings_get_int (schema_ptr, key);
324 PERR (
"Invalid key %s for schema %s", key, schema);
334 gboolean result = FALSE;
335 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
336 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), FALSE);
338 if (gnc_gsettings_is_valid_key (schema_ptr, key))
340 result = g_settings_set_int (schema_ptr, key, value);
342 PERR (
"Unable to set value for key %s in schema %s", key, schema);
345 PERR (
"Invalid key %s for schema %s", key, schema);
354 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
355 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), 0);
357 if (gnc_gsettings_is_valid_key (schema_ptr, key))
358 return g_settings_get_double (schema_ptr, key);
361 PERR (
"Invalid key %s for schema %s", key, schema);
371 gboolean result = FALSE;
372 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
373 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), FALSE);
375 if (gnc_gsettings_is_valid_key (schema_ptr, key))
377 result = g_settings_set_double (schema_ptr, key, value);
379 PERR (
"Unable to set value for key %s in schema %s", key, schema);
382 PERR (
"Invalid key %s for schema %s", key, schema);
391 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
392 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), NULL);
394 if (gnc_gsettings_is_valid_key (schema_ptr, key))
395 return g_settings_get_string (schema_ptr, key);
398 PERR (
"Invalid key %s for schema %s", key, schema);
408 gboolean result = FALSE;
409 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
410 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), FALSE);
412 ENTER(
"schema: %s, key: %s", schema, key);
413 if (gnc_gsettings_is_valid_key (schema_ptr, key))
415 result = g_settings_set_string (schema_ptr, key, value);
417 PERR (
"Unable to set value for key %s in schema %s", key, schema);
420 PERR (
"Invalid key %s for schema %s", key, schema);
422 LEAVE(
"result %i", result);
430 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
431 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), 0);
433 if (gnc_gsettings_is_valid_key (schema_ptr, key))
434 return g_settings_get_enum (schema_ptr, key);
437 PERR (
"Invalid key %s for schema %s", key, schema);
447 gboolean result = FALSE;
448 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
449 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), FALSE);
451 if (gnc_gsettings_is_valid_key (schema_ptr, key))
453 result = g_settings_set_enum (schema_ptr, key, value);
455 PERR (
"Unable to set value for key %s in schema %s", key, schema);
458 PERR (
"Invalid key %s for schema %s", key, schema);
467 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
468 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), NULL);
470 if (gnc_gsettings_is_valid_key (schema_ptr, key))
471 return g_settings_get_value (schema_ptr, key);
474 PERR (
"Invalid key %s for schema %s", key, schema);
484 gboolean result = FALSE;
485 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
486 g_return_val_if_fail (G_IS_SETTINGS (schema_ptr), FALSE);
488 if (gnc_gsettings_is_valid_key (schema_ptr, key))
490 result = g_settings_set_value (schema_ptr, key, value);
492 PERR (
"Unable to set value for key %s in schema %s", key, schema);
495 PERR (
"Invalid key %s for schema %s", key, schema);
504 GSettings *schema_ptr = gnc_gsettings_get_schema_ptr (schema);
505 g_return_if_fail (G_IS_SETTINGS (schema_ptr));
507 if (gnc_gsettings_is_valid_key (schema_ptr, key))
508 g_settings_reset (schema_ptr, key);
510 PERR (
"Invalid key %s for schema %s", key, schema);
519 keys = g_settings_list_keys (gnc_gsettings_get_schema_ptr (schema));
524 while (keys[counter])
541 if (g_strcmp0 (g_getenv (
"GNC_UNINSTALLED"),
"1") == 0)
568 LEAVE(
"Prefsbackend bind = %p", prefsbackend->bind);
578 static xmlParserInputPtr
579 xsltprocExternalEntityLoader(
const char *URL,
const char *ID,
580 xmlParserCtxtPtr ctxt)
582 xmlParserInputPtr ret;
583 warningSAXFunc warning = NULL;
585 gchar *tmpdir = g_build_filename (g_get_home_dir (),
".gnc-migration-tmp", NULL);
588 const char *lastsegment = URL;
589 const char *iter = URL;
594 lastsegment = iter + 1;
598 if ((ctxt != NULL) && (ctxt->sax != NULL))
600 warning = ctxt->sax->warning;
601 ctxt->sax->warning = NULL;
604 if (defaultEntityLoader != NULL)
606 ret = defaultEntityLoader(URL, ID, ctxt);
610 ctxt->sax->warning = warning;
615 newURL = xmlStrdup((
const xmlChar *) tmpdir);
616 newURL = xmlStrcat(newURL, (
const xmlChar *)
"/");
617 newURL = xmlStrcat(newURL, (
const xmlChar *) lastsegment);
621 ret = defaultEntityLoader((
const char *)newURL, ID, ctxt);
625 ctxt->sax->warning = warning;
633 ctxt->sax->warning = warning;
635 DEBUG (
"External entity \"%s\" not loaded", URL);
637 DEBUG (
"External entity \"%s\" not loaded", ID);
662 void gnc_gsettings_migrate_from_gconf (
void)
664 gchar *pkgdatadir, *stylesheet, *input, *output, *command;
665 gchar *gconf_root, *gconf_apps, *gconf_gnucash;
666 gchar *base_dir, *iter;
667 SCM migr_script, result;
668 xsltStylesheetPtr stylesheetptr = NULL;
669 xmlDocPtr inputxml, transformedxml;
671 gboolean migration_ok = FALSE;
678 LEAVE (
"Preferences migration ran successfully before. Skipping.");
682 base_dir = g_strdup (g_get_home_dir ());
683 for (iter = base_dir; *iter != 0; iter++)
690 gconf_root = g_build_filename(base_dir,
".gconf", NULL);
691 gconf_apps = g_build_filename(gconf_root,
"apps", NULL);
692 gconf_gnucash = g_build_filename(gconf_apps,
"gnucash", NULL);
693 migration_ok = (g_file_test (gconf_root, G_FILE_TEST_IS_DIR) &&
694 g_file_test (gconf_apps, G_FILE_TEST_IS_DIR) &&
695 g_file_test (gconf_gnucash, G_FILE_TEST_IS_DIR));
698 g_free (gconf_gnucash);
703 PINFO (
"No pre-existing GConf gnucash section found.\n"
704 "Most likely this system never ran GnuCash before.\n"
705 "Assume migration is not needed.");
710 pkgdatadir = gnc_path_get_pkgdatadir();
711 stylesheet = g_build_filename(pkgdatadir,
"make-prefs-migration-script.xsl", NULL);
712 input = g_build_filename(pkgdatadir,
"migratable-prefs.xml", NULL);
715 migration_ok = (g_file_test (stylesheet, G_FILE_TEST_IS_REGULAR) &&
716 g_file_test (input, G_FILE_TEST_IS_REGULAR));
723 PWARN (
"Migration input file and stylesheet missing. Skip migration.");
727 command = g_strconcat (
"(use-modules (migrate-prefs))(migration-prepare \"",
728 base_dir,
"\")", NULL);
729 DEBUG (
"command = %s", command);
730 migration_ok = scm_is_true (scm_c_eval_string (command));
738 PWARN (
"Migration preparation step failed. Skip migration.");
743 output = g_build_filename(base_dir,
".gnc-migration-tmp",
"migrate-prefs-user.scm", NULL);
744 xmlSubstituteEntitiesDefault(1);
745 xmlLoadExtDtdDefaultValue = 1;
746 defaultEntityLoader = xmlGetExternalEntityLoader();
747 xmlSetExternalEntityLoader(xsltprocExternalEntityLoader);
748 stylesheetptr = xsltParseStylesheetFile((
const xmlChar *)stylesheet);
749 inputxml = xmlParseFile(input);
750 transformedxml = xsltApplyStylesheet(stylesheetptr, inputxml, NULL);
752 outfile = fopen(output,
"w");
753 xsltSaveResultToFile(outfile, transformedxml, stylesheetptr);
756 xsltFreeStylesheet(stylesheetptr);
757 xmlFreeDoc(inputxml);
758 xmlFreeDoc(transformedxml);
760 xsltCleanupGlobals();
765 migr_script = scm_from_locale_string (output);
766 scm_primitive_load (migr_script);
769 migration_ok = scm_is_true (scm_c_eval_string (
"(use-modules (migrate-prefs-user))(run-migration)"));
774 PWARN (
"Actual migration step failed. Skip migration.");
785 command = g_strconcat (
"(use-modules (migrate-prefs))(migration-cleanup \"",
786 base_dir,
"\")", NULL);
787 DEBUG (
"command = %s", command);
788 migration_ok = scm_is_true (scm_c_eval_string (command));
791 PWARN (
"Cleanup step failed. You may need to delete %s/.gnc-migration-tmp manually.", base_dir);
793 PINFO (
"Preferences migration completed successfully");
gchar * gnc_gsettings_normalize_schema_name(const gchar *name)
gboolean gnc_gsettings_set_int(const gchar *schema, const gchar *key, gint value)
void gnc_gsettings_set_prefix(const gchar *prefix)
gboolean gnc_gsettings_set_float(const gchar *schema, const gchar *key, gdouble value)
#define PINFO(format, args...)
gint gnc_gsettings_get_int(const gchar *schema, const gchar *key)
#define DEBUG(format, args...)
void gnc_gsettings_bind(const gchar *schema, const gchar *key, gpointer object, const gchar *property)
#define PERR(format, args...)
#define ENTER(format, args...)
void gnc_gsettings_remove_any_cb_by_func(const gchar *schema, gpointer func, gpointer user_data)
gboolean gnc_gsettings_set_enum(const gchar *schema, const gchar *key, gint value)
#define PWARN(format, args...)
GVariant * gnc_gsettings_get_value(const gchar *schema, const gchar *key)
guint gnc_gsettings_register_any_cb(const gchar *schema, gpointer func, gpointer user_data)
void gnc_gsettings_reset_schema(const gchar *schema)
gdouble gnc_gsettings_get_float(const gchar *schema, const gchar *key)
void gnc_gsettings_reset(const gchar *schema, const gchar *key)
gchar * gnc_gsettings_get_string(const gchar *schema, const gchar *key)
gint gnc_gsettings_get_enum(const gchar *schema, const gchar *key)
gboolean gnc_gsettings_set_bool(const gchar *schema, const gchar *key, gboolean value)
void gnc_gsettings_load_backend(void)
#define LEAVE(format, args...)
gboolean gnc_gsettings_get_bool(const gchar *schema, const gchar *key)
const gchar * gnc_gsettings_get_prefix(void)
void gnc_gsettings_remove_cb_by_id(const gchar *schema, guint handlerid)
gboolean gnc_gsettings_set_value(const gchar *schema, const gchar *key, GVariant *value)
gulong gnc_gsettings_register_cb(const char *schema, const gchar *key, gpointer func, gpointer user_data)
GSettings helper routines.
gboolean gnc_gsettings_set_string(const gchar *schema, const gchar *key, const gchar *value)
void gnc_gsettings_remove_cb_by_func(const gchar *schema, const gchar *key, gpointer func, gpointer user_data)
const gchar * QofLogModule