From 317d4a21dd28081a93e955a2e4a94f192231f7c8 Mon Sep 17 00:00:00 2001
From: Vincent Untz <vuntz@gnome.org>
Date: Tue, 11 Oct 2011 16:35:11 +0200
Subject: [PATCH 1/5] panel: Add helper API to write directly to dconf

This will be used for initial setup of panel, for GSettings keys
applying to a specific path, while we don't really have the schema yet.
---
 gnome-panel/libpanel-util/panel-dconf.c |   16 ++++++++++++++++
 gnome-panel/libpanel-util/panel-dconf.h |    4 ++++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/gnome-panel/libpanel-util/panel-dconf.c b/gnome-panel/libpanel-util/panel-dconf.c
index 63a1c48..6d09dd6 100644
--- a/gnome-panel/libpanel-util/panel-dconf.c
+++ b/gnome-panel/libpanel-util/panel-dconf.c
@@ -36,6 +36,22 @@ panel_dconf_client_get (void)
 }
 
 gboolean
+panel_dconf_write_sync (const gchar  *key,
+                        GVariant     *value,
+                        GError      **error)
+{
+        gboolean     ret;
+        DConfClient *client = panel_dconf_client_get ();
+
+        ret = dconf_client_write (client, key, value,
+                                  NULL, NULL, error);
+
+        g_object_unref (client);
+
+        return ret;
+}
+
+gboolean
 panel_dconf_recursive_reset (const gchar  *dir,
                              GError      **error)
 {
diff --git a/gnome-panel/libpanel-util/panel-dconf.h b/gnome-panel/libpanel-util/panel-dconf.h
index 0cf8b35..e4ef1e4 100644
--- a/gnome-panel/libpanel-util/panel-dconf.h
+++ b/gnome-panel/libpanel-util/panel-dconf.h
@@ -29,6 +29,10 @@
 
 G_BEGIN_DECLS
 
+gboolean panel_dconf_write_sync (const gchar  *key,
+                                 GVariant     *value,
+                                 GError      **error);
+
 gboolean panel_dconf_recursive_reset (const gchar  *dir,
                                       GError     **error);
 
-- 
1.7.7


From 8fecde1a4067f9177aea611c9b73f543096d7b6e Mon Sep 17 00:00:00 2001
From: Vincent Untz <vuntz@gnome.org>
Date: Tue, 11 Oct 2011 16:36:15 +0200
Subject: [PATCH 2/5] panel: Support instance configuration of objects in
 default layout

It's now possible to change some settings of the objects in the default
layout. For instance, for a launcher, we would add this to the group of
the launcher in the default layout file to set the .desktop file being
used:

@instance-config/location="foo.desktop"

Syntax is:
 - @instance-config/ prefix
 - value of the key is a GVariant-parsable string
---
 gnome-panel/panel-layout.c |   98 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 98 insertions(+), 0 deletions(-)

diff --git a/gnome-panel/panel-layout.c b/gnome-panel/panel-layout.c
index d52a6a0..4045c4c 100644
--- a/gnome-panel/panel-layout.c
+++ b/gnome-panel/panel-layout.c
@@ -48,6 +48,7 @@ static GSettings *layout_settings = NULL;
 
 #define PANEL_LAYOUT_ERROR panel_layout_error_quark ()
 #define PANEL_LAYOUT_OBJECT_GCONF_PATH_TEMPLATE "/apps/panel3-applets/%s"
+#define PANEL_LAYOUT_INSTANCE_CONFIG_SUBPATH "@instance-config/"
 
 static void panel_layout_load_toplevel    (const char *toplevel_id);
 static void panel_layout_load_object      (const char *object_id);
@@ -277,6 +278,81 @@ panel_layout_find_free_id (const char *id_list_key,
 }
 
 static gboolean
+panel_layout_maybe_append_object_instance_config (GKeyFile    *keyfile,
+                                                  const char  *group,
+                                                  const char  *key,
+                                                  const char  *path_prefix,
+                                                  const char  *unique_id,
+                                                  gboolean     dry_run,
+                                                  gboolean    *key_handled,
+                                                  GError     **error)
+{
+        char       *value_str;
+        const char *keyname;
+        GVariant   *variant;
+
+        *key_handled = FALSE;
+
+        if (!g_str_has_prefix(key, PANEL_LAYOUT_INSTANCE_CONFIG_SUBPATH))
+                return TRUE;
+
+        *key_handled = TRUE;
+
+        value_str = g_key_file_get_string (
+                                keyfile,
+                                group, key,
+                                error);
+        if (!value_str)
+                return FALSE;
+
+        variant = g_variant_parse (NULL, value_str,
+                                   NULL, NULL, error);
+
+        if (!variant) {
+                g_free (value_str);
+                return FALSE;
+        }
+
+        keyname = key + strlen (PANEL_LAYOUT_INSTANCE_CONFIG_SUBPATH);
+
+        if (dry_run) {
+                /* the key can actually be in a subdirectory
+                 * like instance-config/foo/key, so we split
+                 * the tokens to validate all of them */
+                char **tokens;
+                char **token;
+
+                tokens = g_strsplit (keyname, "/", -1);
+
+                for (token = tokens; *token; token++) {
+                        if (!panel_gsettings_is_valid_keyname (*token,
+                                                               error)) {
+                                g_strfreev (tokens);
+                                g_variant_unref (variant);
+                                g_free (value_str);
+                                return FALSE;
+                        }
+                }
+
+                g_strfreev (tokens);
+        } else {
+                char *key;
+
+                key = g_strdup_printf ("%s%s/%s%s",
+                                       path_prefix, unique_id,
+                                       PANEL_LAYOUT_OBJECT_CONFIG_SUFFIX,
+                                       keyname);
+                panel_dconf_write_sync (key, variant, NULL);
+                g_free (key);
+        }
+
+        g_variant_unref (variant);
+        g_free (value_str);
+
+        return TRUE;
+}
+
+static gboolean
 panel_layout_append_group_helper (GKeyFile                  *keyfile,
                                   const char                *group,
                                   int                        set_screen_to,
@@ -292,6 +368,7 @@ panel_layout_append_group_helper (GKeyFile                  *keyfile,
                                   const char                *type_for_error_message)
 {
         gboolean    retval = FALSE;
+        gboolean    appending_object;
         const char *id;
         char       *unique_id = NULL;
         char       *path = NULL;
@@ -304,6 +381,8 @@ panel_layout_append_group_helper (GKeyFile                  *keyfile,
 
         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
+        appending_object = (g_strcmp0 (schema, PANEL_OBJECT_SCHEMA) == 0);
+
         /* Try to extract an id from the group, by stripping the prefix,
          * and create a unique id out of that */
         id = group + strlen (group_prefix);
@@ -339,6 +418,25 @@ panel_layout_append_group_helper (GKeyFile                  *keyfile,
         for (i = 0; keyfile_keys[i] != NULL; i++) {
                 gboolean found = FALSE;
 
+                /* special case keys of the instance config of an object */
+                if (appending_object) {
+                        gboolean handled;
+
+                        if (!panel_layout_maybe_append_object_instance_config (
+                                                        keyfile,
+                                                        group,
+                                                        keyfile_keys[i],
+                                                        path_prefix,
+                                                        unique_id,
+                                                        dry_run,
+                                                        &handled,
+                                                        error))
+                                goto out;
+
+                        if (handled)
+                                continue;
+                }
+
                 for (j = 0; j < key_definitions_len; j++) {
                         if (g_strcmp0 (keyfile_keys[i],
                                        key_definitions[j].name) == 0) {
-- 
1.7.7


From 464c8666f20e885b22f255884580746aa8339b18 Mon Sep 17 00:00:00 2001
From: Vincent Untz <vuntz@gnome.org>
Date: Tue, 11 Oct 2011 17:24:00 +0200
Subject: [PATCH 4/5] panel: Add helper API to get file in the user config
 directory for panel

This just returns ~/.config/gnome-panel/$foo (with $foo optional, and
respecting $XDG_CONFIG_HOME).
---
 gnome-panel/panel-util.c |   10 ++++++++--
 gnome-panel/panel-util.h |    2 ++
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/gnome-panel/panel-util.c b/gnome-panel/panel-util.c
index d8b08ad..1172af4 100644
--- a/gnome-panel/panel-util.c
+++ b/gnome-panel/panel-util.c
@@ -333,11 +333,17 @@ panel_load_icon (GtkIconTheme  *icon_theme,
 	return retval;
 }
 
+char *
+panel_util_get_from_personal_path (const char *file)
+{
+	return g_build_filename (g_get_user_config_dir (),
+				 "gnome-panel", file, NULL);
+}
+
 static char *
 panel_launcher_get_personal_path (void)
 {
-	return g_build_filename (g_get_user_config_dir (),
-				 "gnome-panel", "launchers", NULL);
+	return panel_util_get_from_personal_path ("launchers");
 }
 
 gboolean
diff --git a/gnome-panel/panel-util.h b/gnome-panel/panel-util.h
index fc8e9de..6856a6c 100644
--- a/gnome-panel/panel-util.h
+++ b/gnome-panel/panel-util.h
@@ -30,6 +30,8 @@ GdkPixbuf *     panel_load_icon         (GtkIconTheme  *icon_theme,
 					 int            desired_height,
 					 char         **error_msg);
 
+char       *panel_util_get_from_personal_path  (const char *file);
+
 GFile      *panel_launcher_get_gfile           (const char *location);
 char       *panel_launcher_get_uri             (const char *location);
 char       *panel_launcher_get_filename        (const char *location);
-- 
1.7.7


From bc6beed1c7562f92a3993a720061a6e2f584646e Mon Sep 17 00:00:00 2001
From: Vincent Untz <vuntz@gnome.org>
Date: Tue, 11 Oct 2011 17:25:26 +0200
Subject: [PATCH 5/5] panel: Make it possible to load a default layout from
 the user config

If ~/.config/gnome-panel/panel-default-layout.layout exists, use it in
favor of /usr/share/gnome-panel/panel-default-layout.layout.
---
 gnome-panel/panel-layout.c |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/gnome-panel/panel-layout.c b/gnome-panel/panel-layout.c
index 596d97f..cd4ca37 100644
--- a/gnome-panel/panel-layout.c
+++ b/gnome-panel/panel-layout.c
@@ -41,12 +41,15 @@
 #include "panel-object-loader.h"
 #include "panel-schemas.h"
 #include "panel-toplevel.h"
+#include "panel-util.h"
 
 #include "panel-layout.h"
 
 static GSettings *layout_settings = NULL;
 
 #define PANEL_LAYOUT_ERROR panel_layout_error_quark ()
+
+#define PANEL_LAYOUT_DEFAULT_LAYOUT_FILE "panel-default-layout.layout"
 #define PANEL_LAYOUT_OBJECT_GCONF_PATH_TEMPLATE "/apps/panel3-applets/%s"
 #define PANEL_LAYOUT_INSTANCE_CONFIG_SUBPATH "@instance-config/"
 
@@ -1114,8 +1117,17 @@ panel_layout_load_object (const char *object_id)
 static char *
 panel_layout_get_default_layout_file (void)
 {
+        char *user_file;
+
+        user_file = panel_util_get_from_personal_path (PANEL_LAYOUT_DEFAULT_LAYOUT_FILE);
+
+        if (g_file_test (user_file, G_FILE_TEST_IS_REGULAR))
+                return user_file;
+
+        g_free (user_file);
+
         return g_build_filename (PANELDATADIR,
-                                 "panel-default-layout.layout",
+                                 PANEL_LAYOUT_DEFAULT_LAYOUT_FILE,
                                  NULL);
 }
 
-- 
1.7.7

