[dconf] keyfile: many improvements



commit 1f97cd016106267c722be637310b3a9c774996ba
Author: Ryan Lortie <desrt desrt ca>
Date:   Fri Jan 11 18:16:52 2013 -0500

    keyfile: many improvements
    
    Store the keyfile in ~/.config/dconf/$(name).txt instead of
    ~/.config/dconf-keyfile/name.  Adjust the base writer not to pick up
    filenames with dots in them (so we will skip the .txt files the keyfile
    writer puts into the same directory).
    
    Add file change monitoring and reload the file if anyone changes it.
    
    Fix a crasher on the first write of a file if it does not yet exist.
    
    Add proper finalize handling.

 service/dconf-keyfile-writer.c |   94 ++++++++++++++++++++++++++++++++++-----
 service/dconf-writer.c         |    5 ++-
 2 files changed, 86 insertions(+), 13 deletions(-)
---
diff --git a/service/dconf-keyfile-writer.c b/service/dconf-keyfile-writer.c
index d65d25d..2845c65 100644
--- a/service/dconf-keyfile-writer.c
+++ b/service/dconf-keyfile-writer.c
@@ -28,10 +28,12 @@ typedef DConfWriterClass DConfKeyfileWriterClass;
 
 typedef struct
 {
-  DConfWriter  parent_instance;
-  gchar       *filename;
-  gchar       *contents;
-  GKeyFile    *keyfile;
+  DConfWriter   parent_instance;
+  gchar        *filename;
+  GFileMonitor *monitor;
+  guint         scheduled_update;
+  gchar        *contents;
+  GKeyFile     *keyfile;
 } DConfKeyfileWriter;
 
 G_DEFINE_TYPE (DConfKeyfileWriter, dconf_keyfile_writer, DCONF_TYPE_WRITER)
@@ -122,6 +124,25 @@ dconf_keyfile_writer_list (GHashTable *set)
 {
 }
 
+static gboolean dconf_keyfile_update (gpointer user_data);
+
+static void
+dconf_keyfile_changed (GFileMonitor      *monitor,
+                       GFile             *file,
+                       GFile             *other_file,
+                       GFileMonitorEvent  event_type,
+                       gpointer           user_data)
+{
+  DConfKeyfileWriter *kfw = user_data;
+
+  if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT ||
+      event_type == G_FILE_MONITOR_EVENT_CREATED)
+    {
+      if (!kfw->scheduled_update)
+        kfw->scheduled_update = g_idle_add (dconf_keyfile_update, kfw);
+    }
+}
+
 static gboolean
 dconf_keyfile_writer_begin (DConfWriter  *writer,
                             GError      **error)
@@ -132,8 +153,20 @@ dconf_keyfile_writer_begin (DConfWriter  *writer,
   DConfChangeset *changes;
 
   if (kfw->filename == NULL)
-    kfw->filename = g_build_filename (g_get_user_config_dir (), "dconf-keyfile",
-                                      dconf_writer_get_name (writer), NULL);
+    {
+      gchar *filename_base;
+      GFile *file;
+
+      filename_base = g_build_filename (g_get_user_config_dir (), "dconf", dconf_writer_get_name (writer), NULL);
+      kfw->filename = g_strconcat (filename_base, ".txt", NULL);
+      g_free (filename_base);
+
+      file = g_file_new_for_path (kfw->filename);
+      kfw->monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
+      g_object_unref (file);
+
+      g_signal_connect (kfw->monitor, "changed", G_CALLBACK (dconf_keyfile_changed), kfw);
+    }
 
   g_clear_pointer (&kfw->contents, g_free);
 
@@ -150,12 +183,15 @@ dconf_keyfile_writer_begin (DConfWriter  *writer,
 
   kfw->keyfile = g_key_file_new ();
 
-  if (!g_key_file_load_from_data (kfw->keyfile, kfw->contents, -1, G_KEY_FILE_KEEP_COMMENTS, &local_error))
+  if (kfw->contents)
     {
-      g_clear_pointer (&kfw->keyfile, g_key_file_free);
-      g_clear_pointer (&kfw->contents, g_free);
-      g_propagate_error (error, local_error);
-      return FALSE;
+      if (!g_key_file_load_from_data (kfw->keyfile, kfw->contents, -1, G_KEY_FILE_KEEP_COMMENTS, &local_error))
+        {
+          g_clear_pointer (&kfw->keyfile, g_key_file_free);
+          g_clear_pointer (&kfw->contents, g_free);
+          g_propagate_error (error, local_error);
+          return FALSE;
+        }
     }
 
   if (!DCONF_WRITER_CLASS (dconf_keyfile_writer_parent_class)->begin (writer, error))
@@ -307,7 +343,7 @@ dconf_keyfile_writer_commit (DConfWriter  *writer,
     data = g_key_file_to_data (kfw->keyfile, &size, NULL);
 
     /* don't write it again if nothing changed */
-    if (!g_str_equal (kfw->contents, data))
+    if (!kfw->contents || !g_str_equal (kfw->contents, data))
       {
         if (!g_file_set_contents (kfw->filename, data, size, error))
           {
@@ -360,6 +396,36 @@ dconf_keyfile_writer_end (DConfWriter *writer)
   g_clear_pointer (&kfw->contents, g_free);
 }
 
+static gboolean
+dconf_keyfile_update (gpointer user_data)
+{
+  DConfKeyfileWriter *kfw = user_data;
+
+  if (dconf_keyfile_writer_begin (DCONF_WRITER (kfw), NULL))
+    {
+      dconf_keyfile_writer_commit (DCONF_WRITER (kfw), NULL);
+      dconf_keyfile_writer_end (DCONF_WRITER (kfw));
+    }
+
+  kfw->scheduled_update = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+dconf_keyfile_writer_finalize (GObject *object)
+{
+  DConfKeyfileWriter *kfw = (DConfKeyfileWriter *) object;
+
+  if (kfw->scheduled_update)
+    g_source_remove (kfw->scheduled_update);
+
+  g_clear_object (&kfw->monitor);
+  g_free (kfw->filename);
+
+  G_OBJECT_CLASS (dconf_keyfile_writer_parent_class)->finalize (object);
+}
+
 static void
 dconf_keyfile_writer_init (DConfKeyfileWriter *writer)
 {
@@ -369,6 +435,10 @@ dconf_keyfile_writer_init (DConfKeyfileWriter *writer)
 static void
 dconf_keyfile_writer_class_init (DConfWriterClass *class)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->finalize = dconf_keyfile_writer_finalize;
+
   class->list = dconf_keyfile_writer_list;
   class->begin = dconf_keyfile_writer_begin;
   class->change = dconf_keyfile_writer_change;
diff --git a/service/dconf-writer.c b/service/dconf-writer.c
index 7f9f2a5..15801b5 100644
--- a/service/dconf-writer.c
+++ b/service/dconf-writer.c
@@ -75,7 +75,10 @@ dconf_writer_real_list (GHashTable *set)
     return;
 
   while ((name = g_dir_read_name (dir)))
-    g_hash_table_add (set, g_strdup (name));
+    {
+      if (!strchr (name, '.'))
+        g_hash_table_add (set, g_strdup (name));
+    }
 
   g_dir_close (dir);
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]