[Xfce4-commits] <xfce4-settings:nick/settings-editor> WIP: Add property editing capabilities.

Nick Schermer noreply at xfce.org
Thu Feb 2 19:36:01 CET 2012


Updating branch refs/heads/nick/settings-editor
         to 1f2b6ac09c598d3e74efe7d61577805a7f3721bb (commit)
       from fce4a6b865bf382ca15351493925bcd82a4d85f7 (commit)

commit 1f2b6ac09c598d3e74efe7d61577805a7f3721bb
Author: Nick Schermer <nick at xfce.org>
Date:   Mon Jan 30 23:03:04 2012 +0100

    WIP: Add property editing capabilities.

 po/POTFILES.in                                     |    2 +
 xfce4-settings-editor/Makefile.am                  |   32 +-
 .../xfce-settings-cell-renderer.c                  |  637 ++++++++++++++++++++
 .../xfce-settings-cell-renderer.h                  |   45 ++
 .../xfce-settings-editor-dialog.c                  |  210 ++++---
 xfce4-settings-editor/xfce-settings-marshal.list   |    1 +
 xfce4-settings-editor/xfce-settings-prop-dialog.c  |  313 ++++++++++
 xfce4-settings-editor/xfce-settings-prop-dialog.h  |   49 ++
 8 files changed, 1211 insertions(+), 78 deletions(-)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 87f9cd2..14bf032 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -30,7 +30,9 @@ dialogs/mouse-settings/mouse-dialog.glade
 dialogs/mouse-settings/xfce-mouse-settings.desktop.in
 
 xfce4-settings-editor/main.c
+xfce4-settings-editor/xfce-settings-cell-renderer.c
 xfce4-settings-editor/xfce-settings-editor-dialog.c
+xfce4-settings-editor/xfce-settings-prop-dialog.c
 xfce4-settings-editor/xfce4-settings-editor.desktop.in
 
 xfsettingsd/accessibility.c
diff --git a/xfce4-settings-editor/Makefile.am b/xfce4-settings-editor/Makefile.am
index 657a1f7..fd272d1 100644
--- a/xfce4-settings-editor/Makefile.am
+++ b/xfce4-settings-editor/Makefile.am
@@ -8,10 +8,19 @@ INCLUDES = \
 bin_PROGRAMS = \
 	xfce4-settings-editor
 
+xfce4_settings_editor_built_sources = \
+	xfce-settings-marshal.c \
+	xfce-settings-marshal.h
+
 xfce4_settings_editor_SOURCES = \
+	$(xfce4_settings_editor_built_sources) \
 	main.c \
+	xfce-settings-cell-renderer.c \
+	xfce-settings-cell-renderer.h \
 	xfce-settings-editor-dialog.c \
-	xfce-settings-editor-dialog.h
+	xfce-settings-editor-dialog.h \
+	xfce-settings-prop-dialog.c \
+	xfce-settings-prop-dialog.h
 
 xfce4_settings_editor_CFLAGS = \
 	$(GTK_CFLAGS) \
@@ -36,7 +45,28 @@ desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 
 @INTLTOOL_DESKTOP_RULE@
 
+#
+# Build sources
+#
+if MAINTAINER_MODE
+
+xfce-settings-marshal.h: xfce-settings-marshal.list Makefile
+	$(AM_V_GEN) glib-genmarshal --prefix=_xfce_settings_marshal --internal --header $< > $@
+
+xfce-settings-marshal.c: xfce-settings-marshal.list Makefile
+	$(AM_V_GEN) echo "#include \"xfce-settings-marshal.h\"" > $@ \
+	&& glib-genmarshal --prefix=_xfce_settings_marshal --body $< >> $@
+
+DISTCLEANFILES = \
+	$(xfce4_settings_editor_built_sources)
+
+BUILT_SOURCES = \
+	$(xfce4_settings_editor_built_sources)
+
+endif
+
 EXTRA_DIST = \
+	xfce-settings-marshal.list \
 	$(desktop_in_files)
 
 DISTCLEANFILES = \
diff --git a/xfce4-settings-editor/xfce-settings-cell-renderer.c b/xfce4-settings-editor/xfce-settings-cell-renderer.c
new file mode 100644
index 0000000..fd684a1
--- /dev/null
+++ b/xfce4-settings-editor/xfce-settings-cell-renderer.c
@@ -0,0 +1,637 @@
+/*
+ *  xfce4-settings-editor
+ *
+ *  Copyright (c) 2012      Nick Schermer <nick at xfce.org>
+ *
+ *  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; version 2 of the License ONLY.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <dbus/dbus-glib.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include "xfce-settings-cell-renderer.h"
+#include "xfce-settings-marshal.h"
+
+
+
+struct _XfceSettingsCellRendererClass
+{
+    GtkCellRendererClass __parent__;
+};
+
+struct _XfceSettingsCellRenderer
+{
+    GtkCellRenderer __parent__;
+
+    GValue           cell_value;
+
+    guint            locked : 1;
+
+    GtkCellRenderer *renderer_text;
+    GtkCellRenderer *renderer_toggle;
+};
+
+enum
+{
+    PROP_0,
+    PROP_VALUE,
+    PROP_LOCKED
+};
+
+enum
+{
+    VALUE_CHANGED,
+    LAST_SIGNAL
+};
+
+static GQuark edit_data_quark = 0;
+
+static guint  renderer_signals[LAST_SIGNAL];
+
+
+
+static void             xfce_settings_cell_renderer_set_property  (GObject              *object,
+                                                                   guint                 prop_id,
+                                                                   const GValue         *value,
+                                                                   GParamSpec           *pspec);
+static void             xfce_settings_cell_renderer_get_property  (GObject              *object,
+                                                                   guint                 prop_id,
+                                                                   GValue               *value,
+                                                                   GParamSpec           *pspec);
+static void             xfce_settings_cell_renderer_finalize      (GObject              *object);
+static void             xfce_settings_cell_renderer_get_size      (GtkCellRenderer      *cell,
+                                                                   GtkWidget            *widget,
+                                                                   GdkRectangle         *cell_area,
+                                                                   gint                 *x_offset,
+                                                                   gint                 *y_offset,
+                                                                   gint                 *width,
+                                                                   gint                 *height);
+static void             xfce_settings_cell_renderer_render        (GtkCellRenderer      *cell,
+                                                                   GdkDrawable          *window,
+                                                                   GtkWidget            *widget,
+                                                                   GdkRectangle         *background_area,
+                                                                   GdkRectangle         *cell_area,
+                                                                   GdkRectangle         *expose_area,
+                                                                   GtkCellRendererState  flags);
+static gint             xfce_settings_cell_renderer_activate      (GtkCellRenderer      *cell,
+                                                                   GdkEvent             *event,
+                                                                   GtkWidget            *widget,
+                                                                   const gchar          *path,
+                                                                   GdkRectangle         *background_area,
+                                                                   GdkRectangle         *cell_area,
+                                                                   GtkCellRendererState  flags);
+static GtkCellEditable *xfce_settings_cell_renderer_start_editing (GtkCellRenderer      *cell,
+                                                                   GdkEvent             *event,
+                                                                   GtkWidget            *widget,
+                                                                   const gchar          *path,
+                                                                   GdkRectangle         *background_area,
+                                                                   GdkRectangle         *cell_area,
+                                                                   GtkCellRendererState  flags);
+
+
+
+G_DEFINE_TYPE (XfceSettingsCellRenderer, xfce_settings_cell_renderer, GTK_TYPE_CELL_RENDERER)
+
+
+
+static void
+xfce_settings_cell_renderer_class_init (XfceSettingsCellRendererClass *klass)
+{
+    GObjectClass         *gobject_class;
+    GtkCellRendererClass *gtkcellrenderer_class;
+
+    gobject_class = G_OBJECT_CLASS (klass);
+    gobject_class->set_property = xfce_settings_cell_renderer_set_property;
+    gobject_class->get_property = xfce_settings_cell_renderer_get_property;
+    gobject_class->finalize = xfce_settings_cell_renderer_finalize;
+
+    gtkcellrenderer_class = GTK_CELL_RENDERER_CLASS (klass);
+    gtkcellrenderer_class->get_size = xfce_settings_cell_renderer_get_size;
+    gtkcellrenderer_class->render = xfce_settings_cell_renderer_render;
+    gtkcellrenderer_class->activate = xfce_settings_cell_renderer_activate;
+    gtkcellrenderer_class->start_editing = xfce_settings_cell_renderer_start_editing;
+
+    g_object_class_install_property (gobject_class,
+                                     PROP_VALUE,
+                                     g_param_spec_boxed ("value",
+                                                         NULL, NULL,
+                                                         G_TYPE_VALUE,
+                                                         G_PARAM_READWRITE
+                                                         | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property (gobject_class,
+                                     PROP_LOCKED,
+                                     g_param_spec_boolean ("locked",
+                                                           NULL, NULL,
+                                                           FALSE,
+                                                           G_PARAM_READWRITE
+                                                           | G_PARAM_STATIC_STRINGS));
+
+    renderer_signals[VALUE_CHANGED] = g_signal_new (g_intern_static_string ("value-changed"),
+                                                    G_TYPE_FROM_CLASS (klass),
+                                                    G_SIGNAL_RUN_LAST,
+                                                    0, NULL, NULL,
+                                                    _xfce_settings_marshal_VOID__STRING_BOXED,
+                                                    G_TYPE_NONE, 2,
+                                                    G_TYPE_STRING,
+                                                    G_TYPE_VALUE);
+
+    edit_data_quark = g_quark_from_static_string ("path");
+}
+
+
+
+static void
+xfce_settings_cell_renderer_init (XfceSettingsCellRenderer *renderer)
+{
+    renderer->renderer_text = gtk_cell_renderer_text_new ();
+    g_object_ref_sink (G_OBJECT (renderer->renderer_text));
+
+    renderer->renderer_toggle = gtk_cell_renderer_toggle_new ();
+    g_object_ref_sink (G_OBJECT (renderer->renderer_toggle));
+}
+
+
+
+static void
+xfce_settings_cell_renderer_set_property (GObject      *object,
+                                          guint         prop_id,
+                                          const GValue *value,
+                                          GParamSpec   *pspec)
+{
+    XfceSettingsCellRenderer *renderer = XFCE_SETTINGS_CELL_RENDERER (object);
+    GValue                   *real_value;
+    GtkCellRendererMode       cell_mode;
+    GType                     cell_type;
+
+    switch (prop_id)
+    {
+        case PROP_VALUE:
+            if (G_IS_VALUE (&renderer->cell_value))
+                g_value_unset (&renderer->cell_value);
+
+            real_value = g_value_get_boxed (value);
+            cell_mode = GTK_CELL_RENDERER_MODE_INERT;
+            if (G_IS_VALUE (real_value))
+            {
+                cell_type = G_VALUE_TYPE (real_value);
+                g_value_init (&renderer->cell_value, cell_type);
+                g_value_copy (real_value, &renderer->cell_value);
+
+                switch (cell_type)
+                {
+                    case G_TYPE_STRING:
+                    case G_TYPE_INT:
+                    case G_TYPE_UINT:
+                    case G_TYPE_INT64:
+                    case G_TYPE_UINT64:
+                    case G_TYPE_DOUBLE:
+                        cell_mode = GTK_CELL_RENDERER_MODE_EDITABLE;
+                        break;
+
+                    case G_TYPE_BOOLEAN:
+                        cell_mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
+                        break;
+                }
+            }
+
+            g_object_set (object, "mode", cell_mode, NULL);
+            break;
+
+        case PROP_LOCKED:
+            renderer->locked = g_value_get_boolean (value);
+            break;
+
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+
+
+static void
+xfce_settings_cell_renderer_get_property (GObject    *object,
+                                          guint       prop_id,
+                                          GValue     *value,
+                                          GParamSpec *pspec)
+{
+    XfceSettingsCellRenderer *renderer = XFCE_SETTINGS_CELL_RENDERER (object);
+
+    switch (prop_id)
+    {
+        case PROP_VALUE:
+            if (G_IS_VALUE (&renderer->cell_value))
+                g_value_set_boxed (value, &renderer->cell_value);
+            else
+                g_value_set_boxed (value, NULL);
+            break;
+
+        case PROP_LOCKED:
+            g_value_set_boolean (value, renderer->locked);
+            break;
+
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+
+
+static void
+xfce_settings_cell_renderer_finalize (GObject *object)
+{
+    XfceSettingsCellRenderer *renderer = XFCE_SETTINGS_CELL_RENDERER (object);
+
+    if (G_IS_VALUE (&renderer->cell_value))
+        g_value_unset (&renderer->cell_value);
+
+    g_object_unref (G_OBJECT (renderer->renderer_text));
+    g_object_unref (G_OBJECT (renderer->renderer_toggle));
+
+    G_OBJECT_CLASS (xfce_settings_cell_renderer_parent_class)->finalize (object);
+}
+
+
+
+static GtkCellRenderer *
+xfce_settings_cell_renderer_prepare (XfceSettingsCellRenderer *renderer)
+{
+    const GValue *value = &renderer->cell_value;
+    GValue        str_value = { 0, };
+
+    if (G_VALUE_TYPE (value) == xfce_settings_array_type ())
+        goto transform_value;
+
+    switch (G_VALUE_TYPE (value))
+    {
+        case G_TYPE_NONE:
+        case G_TYPE_INVALID:
+            g_object_set (G_OBJECT (renderer->renderer_text),
+                          "text", NULL, NULL);
+            break;
+
+        case G_TYPE_STRING:
+            g_object_set (G_OBJECT (renderer->renderer_text),
+                          "text", g_value_get_string (value), NULL);
+            break;
+
+        case G_TYPE_INT:
+        case G_TYPE_UINT:
+        case G_TYPE_INT64:
+        case G_TYPE_UINT64:
+        case G_TYPE_DOUBLE:
+            transform_value:
+
+            g_value_init (&str_value, G_TYPE_STRING);
+            if (g_value_transform (value, &str_value))
+            {
+                g_object_set (G_OBJECT (renderer->renderer_text),
+                              "text", g_value_get_string (&str_value), NULL);
+            }
+            g_value_unset (&str_value);
+            break;
+
+        case G_TYPE_BOOLEAN:
+            g_object_set (G_OBJECT (renderer->renderer_toggle),
+                          "xalign", 0.0,
+                          "active", g_value_get_boolean (value), NULL);
+
+            return renderer->renderer_toggle;
+
+        default:
+            g_object_set (G_OBJECT (renderer->renderer_text),
+                          "text", "<unknown>", NULL);
+            break;
+    }
+
+    return renderer->renderer_text;
+}
+
+
+
+static void
+xfce_settings_cell_renderer_get_size (GtkCellRenderer      *cell,
+                                      GtkWidget            *widget,
+                                      GdkRectangle         *cell_area,
+                                      gint                 *x_offset,
+                                      gint                 *y_offset,
+                                      gint                 *width,
+                                      gint                 *height)
+{
+    XfceSettingsCellRenderer *renderer = XFCE_SETTINGS_CELL_RENDERER (cell);
+    GtkCellRenderer          *cell_renderer;
+
+    cell_renderer = xfce_settings_cell_renderer_prepare (renderer);
+    gtk_cell_renderer_get_size (cell_renderer,
+                                widget, cell_area,
+                                x_offset, y_offset,
+                                width, height);
+}
+
+
+
+static void
+xfce_settings_cell_renderer_render (GtkCellRenderer      *cell,
+                                    GdkDrawable          *window,
+                                    GtkWidget            *widget,
+                                    GdkRectangle         *background_area,
+                                    GdkRectangle         *cell_area,
+                                    GdkRectangle         *expose_area,
+                                    GtkCellRendererState  flags)
+{
+    XfceSettingsCellRenderer *renderer = XFCE_SETTINGS_CELL_RENDERER (cell);
+    GtkCellRenderer          *cell_renderer;
+
+    cell_renderer = xfce_settings_cell_renderer_prepare (renderer);
+    gtk_cell_renderer_render (cell_renderer,
+                              window, widget,
+                              background_area, cell_area,
+                              expose_area, flags);
+}
+
+
+
+static gint
+xfce_settings_cell_renderer_activate (GtkCellRenderer      *cell,
+                                      GdkEvent             *event,
+                                      GtkWidget            *widget,
+                                      const gchar          *path,
+                                      GdkRectangle         *background_area,
+                                      GdkRectangle         *cell_area,
+                                      GtkCellRendererState  flags)
+{
+    XfceSettingsCellRenderer *renderer = XFCE_SETTINGS_CELL_RENDERER (cell);
+    GValue                    new_value = { 0, };
+
+    if (renderer->locked)
+        return FALSE;
+
+    switch (G_VALUE_TYPE (&renderer->cell_value))
+    {
+        case G_TYPE_NONE:
+        case G_TYPE_INVALID:
+            return FALSE;
+
+        case G_TYPE_BOOLEAN:
+            g_value_init (&new_value, G_TYPE_BOOLEAN);
+            g_value_set_boolean (&new_value, !g_value_get_boolean (&renderer->cell_value));
+
+            g_signal_emit (G_OBJECT (renderer),
+                           renderer_signals[VALUE_CHANGED], 0,
+                           path, &new_value);
+
+            g_value_unset (&new_value);
+            return TRUE;
+
+        default:
+            g_assert_not_reached ();
+            break;
+    }
+
+    return FALSE;
+}
+
+
+
+typedef struct
+{
+    gchar *path;
+    GType  dest_type;
+}
+EditData;
+
+
+
+static void
+xfce_settings_cell_renderer_done_editing (GtkCellEditable          *entry,
+                                          XfceSettingsCellRenderer *renderer)
+{
+    EditData    *data;
+    const gchar *text;
+    GValue       value = { 0, };
+    gdouble      dval;
+
+    data = g_object_get_qdata (G_OBJECT (entry), edit_data_quark);
+    g_value_init (&value, data->dest_type);
+
+    text = gtk_entry_get_text (GTK_ENTRY (entry));
+    if (G_UNLIKELY (text == NULL))
+      text = "";
+
+    switch (data->dest_type)
+    {
+        case G_TYPE_INT:
+            dval = g_ascii_strtod (text, NULL);
+            g_value_set_int (&value, CLAMP (dval, G_MININT, G_MAXINT));
+            break;
+
+        case G_TYPE_UINT:
+            dval = g_ascii_strtod (text, NULL);
+            g_value_set_uint (&value, CLAMP (dval, 0, G_MAXUINT));
+            break;
+
+        case G_TYPE_INT64:
+            g_value_set_int64 (&value, g_ascii_strtoll (text, NULL, 0));
+            break;
+
+        case G_TYPE_UINT64:
+            g_value_set_uint64 (&value, g_ascii_strtoull (text, NULL, 0));
+            break;
+
+        case G_TYPE_DOUBLE:
+            g_value_set_double (&value, g_ascii_strtod (text, NULL));
+            break;
+
+        case G_TYPE_STRING:
+            g_value_set_static_string (&value, text);
+            break;
+
+        default:
+            g_assert_not_reached ();
+            break;
+    }
+
+    g_signal_emit (G_OBJECT (renderer),
+                   renderer_signals[VALUE_CHANGED], 0,
+                   data->path, &value);
+
+    g_value_unset (&value);
+}
+
+
+
+static void
+xfce_settings_cell_renderer_edit_free (gpointer user_data)
+{
+    EditData *data = user_data;
+    g_free (data->path);
+    g_slice_free (EditData, data);
+}
+
+
+
+static GtkCellEditable *
+xfce_settings_cell_renderer_start_editing (GtkCellRenderer      *cell,
+                                           GdkEvent             *event,
+                                           GtkWidget            *widget,
+                                           const gchar          *path,
+                                           GdkRectangle         *background_area,
+                                           GdkRectangle         *cell_area,
+                                           GtkCellRendererState  flags)
+{
+    XfceSettingsCellRenderer *renderer = XFCE_SETTINGS_CELL_RENDERER (cell);
+    GtkWidget                *entry;
+    GValue                    str_value = { 0, };
+    const gchar              *text;
+    EditData                 *data;
+
+    if (renderer->locked)
+        return NULL;
+
+    switch (G_VALUE_TYPE (&renderer->cell_value))
+    {
+        case G_TYPE_NONE:
+        case G_TYPE_INVALID:
+            return NULL;
+
+        case G_TYPE_INT:
+        case G_TYPE_UINT:
+        case G_TYPE_INT64:
+        case G_TYPE_UINT64:
+        case G_TYPE_DOUBLE:
+        case G_TYPE_STRING:
+            g_value_init (&str_value, G_TYPE_STRING);
+            if (g_value_transform (&renderer->cell_value, &str_value))
+            {
+                entry = gtk_entry_new ();
+                text = g_value_get_string (&str_value);
+                gtk_entry_set_text (GTK_ENTRY (entry), text == NULL ? "" : text);
+                gtk_entry_set_has_frame (GTK_ENTRY (entry), FALSE);
+                gtk_widget_show (entry);
+
+                data = g_slice_new0 (EditData);
+                data->path = g_strdup (path);
+                data->dest_type = G_VALUE_TYPE (&renderer->cell_value);
+
+                g_object_set_qdata_full (G_OBJECT (entry), edit_data_quark, data,
+                    xfce_settings_cell_renderer_edit_free);
+
+                g_signal_connect (G_OBJECT (entry), "editing-done",
+                    G_CALLBACK (xfce_settings_cell_renderer_done_editing), cell);
+
+                g_value_unset (&str_value);
+
+                return GTK_CELL_EDITABLE (entry);
+            }
+            else
+            {
+                g_warning ("Unable to transform value from %s to %s",
+                           G_VALUE_TYPE_NAME (&renderer->cell_value),
+                           G_VALUE_TYPE_NAME (&str_value));
+            }
+            break;
+
+        default:
+            g_assert_not_reached ();
+            break;
+    }
+
+    return NULL;
+}
+
+
+
+static void
+xfce_settings_array_to_string (const GValue *src_value,
+                               GValue       *dest_value)
+{
+    GString      *str;
+    GPtrArray    *array = g_value_get_boxed (src_value);
+    guint         i;
+    const GValue *val;
+    GValue        str_val = { 0, };
+
+    g_return_if_fail (G_VALUE_HOLDS_STRING (dest_value));
+    g_return_if_fail (array != NULL);
+
+    str = g_string_new ("[ ");
+
+    for (i = 0; i < array->len; i++)
+    {
+        val = g_ptr_array_index (array, i);
+
+        if (val == NULL)
+        {
+            g_string_append (str, "Null");
+        }
+        else if (G_VALUE_HOLDS_STRING (val))
+        {
+            g_string_append_printf (str, "\"%s\"",
+                g_value_get_string (val));
+        }
+        else
+        {
+            g_value_init (&str_val, G_TYPE_STRING);
+            if (g_value_transform (val, &str_val))
+                g_string_append (str, g_value_get_string (&str_val));
+            else
+                g_string_append (str, "?");
+            g_value_unset (&str_val);
+        }
+
+        if (i < array->len - 1)
+            g_string_append (str, ", ");
+    }
+
+    g_string_append (str, " ]");
+
+    g_value_take_string (dest_value, g_string_free (str, FALSE));
+}
+
+
+
+GtkCellRenderer *
+xfce_settings_cell_renderer_new (void)
+{
+    return g_object_new (XFCE_TYPE_SETTINGS_CELL_RENDERER, NULL);
+}
+
+
+
+GType
+xfce_settings_array_type (void)
+{
+    static GType type = 0;
+
+    if (type == 0)
+    {
+        type = dbus_g_type_get_collection ("GPtrArray", G_TYPE_VALUE);
+        g_value_register_transform_func (type, G_TYPE_STRING,
+                                         xfce_settings_array_to_string);
+    }
+
+    return type;
+}
diff --git a/xfce4-settings-editor/xfce-settings-cell-renderer.h b/xfce4-settings-editor/xfce-settings-cell-renderer.h
new file mode 100644
index 0000000..9934089
--- /dev/null
+++ b/xfce4-settings-editor/xfce-settings-cell-renderer.h
@@ -0,0 +1,45 @@
+/*
+ *  xfce4-settings-editor
+ *
+ *  Copyright (c) 2012      Nick Schermer <nick at xfce.org>
+ *
+ *  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; version 2 of the License ONLY.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __XFCE_SETTINGS_CELL_RENDERER_H__
+#define __XFCE_SETTINGS_CELL_RENDERER_H__
+
+#include <gtk/gtk.h>
+
+#define XFCE_TYPE_SETTINGS_CELL_RENDERER            (xfce_settings_cell_renderer_get_type ())
+#define XFCE_SETTINGS_CELL_RENDERER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_SETTINGS_CELL_RENDERER, XfceSettingsCellRenderer))
+#define XFCE_SETTINGS_CELL_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_SETTINGS_CELL_RENDERER, XfceSettingsCellRendererClass))
+#define XFCE_IS_SETTINGS_CELL_RENDERER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_SETTINGS_CELL_RENDERER))
+#define XFCE_IS_SETTINGS_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_SETTINGS_CELL_RENDERER))
+#define XFCE_SETTINGS_CELL_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_SETTINGS_CELL_RENDERER, XfceSettingsCellRendererClass))
+
+G_BEGIN_DECLS
+
+typedef struct _XfceSettingsCellRenderer      XfceSettingsCellRenderer;
+typedef struct _XfceSettingsCellRendererClass XfceSettingsCellRendererClass;
+
+GType            xfce_settings_cell_renderer_get_type (void) G_GNUC_CONST;
+
+GtkCellRenderer *xfce_settings_cell_renderer_new      (void);
+
+GType            xfce_settings_array_type             (void);
+
+G_END_DECLS
+
+#endif  /* __XFCE_SETTINGS_CELL_RENDERER_H__ */
diff --git a/xfce4-settings-editor/xfce-settings-editor-dialog.c b/xfce4-settings-editor/xfce-settings-editor-dialog.c
index 931cfa4..c9934de 100644
--- a/xfce4-settings-editor/xfce-settings-editor-dialog.c
+++ b/xfce4-settings-editor/xfce-settings-editor-dialog.c
@@ -33,14 +33,14 @@
 
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
-#include <dbus/dbus-glib.h>
 
 #include <libxfce4util/libxfce4util.h>
 #include <libxfce4ui/libxfce4ui.h>
 #include <xfconf/xfconf.h>
 
 #include "xfce-settings-editor-dialog.h"
-
+#include "xfce-settings-prop-dialog.h"
+#include "xfce-settings-cell-renderer.h"
 
 
 
@@ -83,14 +83,13 @@ enum
     PROP_COLUMN_NAME,
     PROP_COLUMN_TYPE_NAME,
     PROP_COLUMN_TYPE,
-    PROP_COLUMN_VALUE_TEXT,
     PROP_COLUMN_LOCKED,
+    PROP_COLUMN_VALUE,
     N_PROP_COLUMNS
 };
 
 
 
-static GType   TYPE_PTR_ARRAY = 0;
 static GSList *monitor_dialogs = NULL;
 
 
@@ -105,6 +104,10 @@ static gboolean xfce_settings_editor_dialog_channel_menu         (XfceSettingsEd
 static gboolean xfce_settings_editor_dialog_channel_button_press (GtkWidget                 *treeview,
                                                                   GdkEventButton            *event,
                                                                   XfceSettingsEditorDialog  *dialog);
+static void     xfce_settings_editor_dialog_value_changed        (GtkCellRenderer           *renderer,
+                                                                  const gchar               *path,
+                                                                  const GValue              *new_value,
+                                                                  XfceSettingsEditorDialog  *dialog);
 static void     xfce_settings_editor_dialog_selection_changed    (GtkTreeSelection          *selection,
                                                                   XfceSettingsEditorDialog  *dialog);
 static gboolean xfce_settings_editor_dialog_query_tooltip        (GtkWidget                 *treeview,
@@ -123,8 +126,6 @@ static gboolean xfce_settings_editor_dialog_key_press_event      (GtkTreeView
 static void     xfce_settings_editor_dialog_property_new         (XfceSettingsEditorDialog  *dialog);
 static void     xfce_settings_editor_dialog_property_edit        (XfceSettingsEditorDialog  *dialog);
 static void     xfce_settings_editor_dialog_property_reset       (XfceSettingsEditorDialog  *dialog);
-static void     xfce_settings_editor_dialog_ptr_array_transform  (const GValue              *src_value,
-                                                                  GValue                    *dest_value);
 
 
 
@@ -143,10 +144,6 @@ xfce_settings_editor_dialog_class_init (XfceSettingsEditorDialogClass *klass)
 
     gtkdialog_class = GTK_DIALOG_CLASS (klass);
     gtkdialog_class->response = xfce_settings_editor_dialog_response;
-
-    TYPE_PTR_ARRAY = dbus_g_type_get_collection ("GPtrArray", G_TYPE_VALUE);
-    g_value_register_transform_func (TYPE_PTR_ARRAY, G_TYPE_STRING,
-        xfce_settings_editor_dialog_ptr_array_transform);
 }
 
 
@@ -178,14 +175,15 @@ xfce_settings_editor_dialog_init (XfceSettingsEditorDialog *dialog)
                                               G_TYPE_STRING,
                                               G_TYPE_STRING,
                                               G_TYPE_STRING,
-                                              G_TYPE_STRING,
-                                              G_TYPE_BOOLEAN);
+                                              G_TYPE_BOOLEAN,
+                                              G_TYPE_VALUE);
     gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dialog->props_store),
                                           PROP_COLUMN_NAME, GTK_SORT_ASCENDING);
 
     gtk_window_set_title (GTK_WINDOW (dialog), _("Settings Editor"));
     xfce_titled_dialog_set_subtitle (XFCE_TITLED_DIALOG (dialog), _("Customize settings stored by Xfconf"));
     gtk_window_set_icon_name (GTK_WINDOW (dialog), "preferences-system");
+    gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NORMAL);
     gtk_window_set_default_size (GTK_WINDOW (dialog),
         xfconf_channel_get_int (dialog->channel, "/last/window-width", 640),
         xfconf_channel_get_int (dialog->channel, "/last/window-height", 500));
@@ -282,12 +280,15 @@ xfce_settings_editor_dialog_init (XfceSettingsEditorDialog *dialog)
     gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
     gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
-    render = gtk_cell_renderer_text_new ();
+    render = xfce_settings_cell_renderer_new ();
     column = gtk_tree_view_column_new_with_attributes (_("Value"), render,
-                                                       "text", PROP_COLUMN_VALUE_TEXT,
+                                                       "value", PROP_COLUMN_VALUE,
+                                                       "locked", PROP_COLUMN_LOCKED,
                                                        NULL);
     gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
     gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+    g_signal_connect (G_OBJECT (render), "value-changed",
+        G_CALLBACK (xfce_settings_editor_dialog_value_changed), dialog);
 
     bbox = gtk_hbutton_box_new ();
     gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 0);
@@ -395,11 +396,21 @@ xfce_settings_editor_dialog_response (GtkDialog *widget,
 static void
 xfce_settings_editor_dialog_load_channels (XfceSettingsEditorDialog *dialog)
 {
-    gchar **channel_names;
-    guint   i;
+    gchar       **channel_names;
+    guint         i;
+    gchar        *channel_name = NULL;
+    GtkTreePath  *path;
+    GtkTreeIter   iter;
 
     g_return_if_fail (GTK_IS_LIST_STORE (dialog->channels_store));
 
+    /* try to restore the selected name (for reload) */
+    if (dialog->props_channel != NULL)
+      {
+        g_object_get (G_OBJECT (dialog->props_channel),
+                      "channel-name", &channel_name, NULL);
+      }
+
     gtk_list_store_clear (dialog->channels_store);
 
     channel_names = xfconf_list_channels ();
@@ -407,12 +418,21 @@ xfce_settings_editor_dialog_load_channels (XfceSettingsEditorDialog *dialog)
     {
         for (i = 0; channel_names[i] != NULL; i++)
         {
-            gtk_list_store_insert_with_values (dialog->channels_store, NULL, i,
+            gtk_list_store_insert_with_values (dialog->channels_store, &iter, i,
                                                CHANNEL_COLUMN_NAME, channel_names[i],
                                                -1);
+
+            if (g_strcmp0 (channel_name, channel_names[i]) == 0)
+              {
+                path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->channels_store), &iter);
+                gtk_tree_view_set_cursor (GTK_TREE_VIEW (dialog->channels_treeview), path, NULL, FALSE);
+                gtk_tree_path_free (path);
+              }
         }
         g_strfreev (channel_names);
     }
+
+    g_free (channel_name);
 }
 
 
@@ -423,22 +443,28 @@ xfce_settings_editor_dialog_type_name (const GValue *value)
     if (G_UNLIKELY (value == NULL))
         return _("Empty");
 
-    if (G_UNLIKELY (G_VALUE_TYPE (value) == TYPE_PTR_ARRAY))
+    if (G_UNLIKELY (G_VALUE_TYPE (value) == xfce_settings_array_type ()))
         return _("Array");
 
     switch (G_VALUE_TYPE (value))
     {
         case G_TYPE_STRING:
             return _("String");
+
+        /* show non-technical name here, the tooltip
+         * contains the full type name */
         case G_TYPE_INT:
         case G_TYPE_UINT:
         case G_TYPE_INT64:
         case G_TYPE_UINT64:
             return _("Integer");
+
         case G_TYPE_BOOLEAN:
             return _("Boolean");
+
         case G_TYPE_DOUBLE:
             return _("Double");
+
         default:
             return G_VALUE_TYPE_NAME (value);
     }
@@ -521,8 +547,8 @@ xfce_settings_editor_dialog_property_load (const gchar               *property,
                                     PROP_COLUMN_FULL, property,
                                     PROP_COLUMN_TYPE, G_VALUE_TYPE_NAME (value),
                                     PROP_COLUMN_TYPE_NAME, xfce_settings_editor_dialog_type_name (value),
-                                    PROP_COLUMN_VALUE_TEXT, g_value_get_string (&string_value),
                                     PROP_COLUMN_LOCKED, xfconf_channel_is_property_locked (dialog->props_channel, property),
+                                    PROP_COLUMN_VALUE, value,
                                     -1);
 
                 if (expand_path != NULL)
@@ -760,7 +786,7 @@ xfce_settings_editor_dialog_channel_reset (XfceSettingsEditorDialog *dialog)
         /* reset all channel properties */
         xfconf_channel_reset_property (dialog->props_channel, "/", TRUE);
 
-        /* check if the channel still exists */
+        /* check if the channel still exists (channel reset, not remove) */
         channels = xfconf_list_channels ();
         if (G_LIKELY (channels != NULL))
         {
@@ -775,9 +801,9 @@ xfce_settings_editor_dialog_channel_reset (XfceSettingsEditorDialog *dialog)
             if (gtk_tree_selection_get_selected (selection, NULL, &iter))
             {
                 if (gtk_list_store_remove (dialog->channels_store, &iter))
-                   path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->channels_store), &iter);
+                    path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->channels_store), &iter);
                 else
-                   path = gtk_tree_path_new_first ();
+                    path = gtk_tree_path_new_first ();
 
                 gtk_tree_view_set_cursor (GTK_TREE_VIEW (dialog->channels_treeview), path, NULL, FALSE);
                 gtk_tree_path_free (path);
@@ -845,14 +871,25 @@ xfce_settings_editor_dialog_channel_monitor_response (GtkWidget     *window,
                                                       gint           response_id,
                                                       XfconfChannel *channel)
 {
-    g_signal_handlers_disconnect_by_func (G_OBJECT (channel),
-        G_CALLBACK (xfce_settings_editor_dialog_channel_monitor_changed), window);
+    GtkTextBuffer *buffer;
+
+    if (response_id == GTK_RESPONSE_REJECT)
+    {
+        buffer = g_object_get_data (G_OBJECT (window), "buffer");
+        g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+        gtk_text_buffer_set_text (buffer, "", 0);
+    }
+    else
+    {
+        g_signal_handlers_disconnect_by_func (G_OBJECT (channel),
+            G_CALLBACK (xfce_settings_editor_dialog_channel_monitor_changed), window);
 
-    g_object_unref (G_OBJECT (channel));
+        g_object_unref (G_OBJECT (channel));
 
-    monitor_dialogs = g_slist_remove (monitor_dialogs, window);
+        monitor_dialogs = g_slist_remove (monitor_dialogs, window);
 
-    gtk_widget_destroy (window);
+        gtk_widget_destroy (window);
+    }
 }
 
 
@@ -881,12 +918,16 @@ xfce_settings_editor_dialog_channel_monitor (XfceSettingsEditorDialog *dialog)
     gtk_window_set_title (GTK_WINDOW (window), title);
     gtk_window_set_icon_name (GTK_WINDOW (window), "utilities-system-monitor");
     gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
+    gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
     xfce_titled_dialog_set_subtitle (XFCE_TITLED_DIALOG (window),
-        _("Watch an Xfconf Channel for property changes"));
-    gtk_dialog_add_button (GTK_DIALOG (window), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
+        _("Watch an Xfconf channel for property changes"));
+    gtk_dialog_add_buttons (GTK_DIALOG (window),
+                            GTK_STOCK_CLEAR, GTK_RESPONSE_REJECT,
+                            GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
     g_signal_connect (G_OBJECT (window), "response",
         G_CALLBACK (xfce_settings_editor_dialog_channel_monitor_response),
         g_object_ref (G_OBJECT (dialog->props_channel)));
+    gtk_dialog_set_default_response (GTK_DIALOG (window), GTK_RESPONSE_CLOSE);
     g_free (title);
 
     monitor_dialogs = g_slist_prepend (monitor_dialogs, window);
@@ -1072,6 +1113,40 @@ xfce_settings_editor_dialog_selected (XfceSettingsEditorDialog *dialog,
 
 
 static void
+xfce_settings_editor_dialog_value_changed (GtkCellRenderer          *renderer,
+                                           const gchar              *str_path,
+                                           const GValue             *new_value,
+                                           XfceSettingsEditorDialog *dialog)
+{
+    GtkTreeModel     *model = GTK_TREE_MODEL (dialog->props_store);
+    GtkTreePath      *path;
+    GtkTreeIter       iter;
+    gchar            *property;
+    GtkTreeSelection *selection;
+
+    g_return_if_fail (G_IS_VALUE (new_value));
+    g_return_if_fail (XFCE_IS_SETTINGS_EDITOR_DIALOG (dialog));
+
+    /* only change values on selected paths, this to avoid miss clicking */
+    path = gtk_tree_path_new_from_string (str_path);
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->props_treeview));
+    if (gtk_tree_selection_path_is_selected (selection, path)
+        && gtk_tree_model_get_iter (model, &iter, path))
+    {
+        gtk_tree_model_get (model, &iter, PROP_COLUMN_FULL, &property, -1);
+        if (G_LIKELY (property != NULL))
+        {
+            if (!xfconf_channel_is_property_locked (dialog->props_channel, property))
+                xfconf_channel_set_property (dialog->props_channel, property, new_value);
+            g_free (property);
+        }
+    }
+    gtk_tree_path_free (path);
+}
+
+
+
+static void
 xfce_settings_editor_dialog_selection_changed (GtkTreeSelection         *selection,
                                                XfceSettingsEditorDialog *dialog)
 {
@@ -1202,17 +1277,44 @@ xfce_settings_editor_dialog_key_press_event (GtkTreeView              *treeview,
 
 
 static void
-xfce_settings_editor_dialog_property_new (XfceSettingsEditorDialog *dialog)
+xfce_settings_editor_dialog_property_dialog (XfceSettingsEditorDialog *dialog,
+                                             gboolean                  make_new)
 {
+    GtkWidget *prop_dialog;
+    gchar     *property;
+
+    property = xfce_settings_editor_dialog_selected (dialog, NULL);
 
+    prop_dialog = xfce_settings_prop_dialog_new (GTK_WINDOW (dialog),
+                                                 dialog->props_channel,
+                                                 make_new ? NULL : property);
+    if (make_new)
+    {
+        /* hint for the parent property based on selected property */
+        xfce_settings_prop_dialog_set_parent_property (
+            XFCE_SETTINGS_PROP_DIALOG (prop_dialog), property);
+    }
+
+    gtk_dialog_run (GTK_DIALOG (prop_dialog));
+    gtk_widget_destroy (prop_dialog);
+
+    g_free (property);
 }
 
 
 
 static void
-xfce_settings_editor_dialog_property_edit (XfceSettingsEditorDialog *dialog)
+xfce_settings_editor_dialog_property_new (XfceSettingsEditorDialog *dialog)
 {
+    xfce_settings_editor_dialog_property_dialog (dialog, TRUE);
+}
+
+
 
+static void
+xfce_settings_editor_dialog_property_edit (XfceSettingsEditorDialog *dialog)
+{
+    xfce_settings_editor_dialog_property_dialog (dialog, FALSE);
 }
 
 
@@ -1237,52 +1339,6 @@ xfce_settings_editor_dialog_property_reset (XfceSettingsEditorDialog *dialog)
 
 
 
-static void
-xfce_settings_editor_dialog_ptr_array_transform (const GValue *src_value,
-                                                 GValue       *dest_value)
-{
-    GString      *str;
-    GPtrArray    *array = g_value_get_boxed (src_value);
-    guint         i;
-    const GValue *val;
-    GValue        str_val = { 0, };
-
-    str = g_string_new ("[ ");
-
-    for (i = 0; i < array->len; i++)
-    {
-        val = g_ptr_array_index (array, i);
-
-        if (val == NULL)
-        {
-            g_string_append (str, "Null");
-        }
-        else if (G_VALUE_HOLDS_STRING (val))
-        {
-            g_string_append_printf (str, "\"%s\"",
-                g_value_get_string (val));
-        }
-        else
-        {
-            g_value_init (&str_val, G_TYPE_STRING);
-            if (g_value_transform (val, &str_val))
-                g_string_append (str, g_value_get_string (&str_val));
-            else
-                g_string_append (str, "?");
-            g_value_unset (&str_val);
-        }
-
-        if (i < array->len - 1)
-            g_string_append (str, ", ");
-    }
-
-    g_string_append (str, " ]");
-
-    g_value_take_string (dest_value, g_string_free (str, FALSE));
-}
-
-
-
 GtkWidget *
 xfce_settings_editor_dialog_new (void)
 {
diff --git a/xfce4-settings-editor/xfce-settings-marshal.list b/xfce4-settings-editor/xfce-settings-marshal.list
new file mode 100644
index 0000000..e72aa4b
--- /dev/null
+++ b/xfce4-settings-editor/xfce-settings-marshal.list
@@ -0,0 +1 @@
+VOID:STRING,BOXED
diff --git a/xfce4-settings-editor/xfce-settings-prop-dialog.c b/xfce4-settings-editor/xfce-settings-prop-dialog.c
new file mode 100644
index 0000000..f31b647
--- /dev/null
+++ b/xfce4-settings-editor/xfce-settings-prop-dialog.c
@@ -0,0 +1,313 @@
+/*
+ *  xfce4-settings-editor
+ *
+ *  Copyright (c) 2012      Nick Schermer <nick at xfce.org>
+ *
+ *  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; version 2 of the License ONLY.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <dbus/dbus-glib.h>
+
+#include <libxfce4util/libxfce4util.h>
+#include <libxfce4ui/libxfce4ui.h>
+#include <xfconf/xfconf.h>
+
+#include "xfce-settings-prop-dialog.h"
+#include "xfce-settings-cell-renderer.h"
+
+
+
+struct _XfceSettingsPropDialogClass
+{
+    GtkDialogClass __parent__;
+};
+
+struct _XfceSettingsPropDialog
+{
+    GtkDialog __parent__;
+
+    XfconfChannel *channel;
+    gchar         *property;
+
+    GValue         cancel_value;
+
+    GtkWidget     *prop_name;
+    GtkWidget     *prop_type;
+};
+
+typedef struct
+{
+    const gchar *name;
+    GType        type;
+}
+ValueTypes;
+
+
+
+static void     xfce_settings_prop_dialog_finalize             (GObject                   *object);
+static void     xfce_settings_prop_dialog_response             (GtkDialog                 *widget,
+                                                                gint                       response_id);
+
+
+
+G_DEFINE_TYPE (XfceSettingsPropDialog, xfce_settings_prop_dialog, GTK_TYPE_DIALOG)
+
+
+
+static ValueTypes value_types[] =
+{
+  { N_("Empty"), G_TYPE_NONE },
+  { N_("String"), G_TYPE_STRING },
+  { N_("Boolean"), G_TYPE_BOOLEAN },
+  { N_("Int"), G_TYPE_INT },
+  { N_("Double"), G_TYPE_DOUBLE },
+  { N_("Array"), G_TYPE_BOXED /* foo type */ },
+  { N_("Unsigned Int"), G_TYPE_UINT },
+  { N_("Int64"), G_TYPE_INT64 },
+  { N_("Unsigned Int64"), G_TYPE_UINT64 }
+};
+
+
+
+enum
+{
+  COLUMN_NAME,
+  COLUMN_ID,
+  N_COLUMNS
+};
+
+
+
+static void
+xfce_settings_prop_dialog_class_init (XfceSettingsPropDialogClass *klass)
+{
+    GObjectClass   *gobject_class;
+    GtkDialogClass *gtkdialog_class;
+
+    gobject_class = G_OBJECT_CLASS (klass);
+    gobject_class->finalize = xfce_settings_prop_dialog_finalize;
+
+    gtkdialog_class = GTK_DIALOG_CLASS (klass);
+    gtkdialog_class->response = xfce_settings_prop_dialog_response;
+}
+
+
+
+static void
+xfce_settings_prop_dialog_init (XfceSettingsPropDialog *dialog)
+{
+    GtkWidget       *table;
+    GtkWidget       *content_area;
+    GtkWidget       *label;
+    GtkWidget       *entry;
+    GtkWidget       *combo;
+    GtkListStore    *store;
+    guint            i;
+    GtkCellRenderer *render;
+
+    gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Property"));
+    gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 400);
+    gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                            GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
+    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+    table = gtk_table_new (3, 2, FALSE);
+    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+    gtk_box_pack_start (GTK_BOX (content_area), table, TRUE, TRUE, 0);
+    gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+    gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+    gtk_container_set_border_width (GTK_CONTAINER (table), 6);
+    gtk_widget_show (table);
+
+    label = gtk_label_new_with_mnemonic (_("_Property:"));
+    gtk_misc_set_alignment (GTK_MISC (label), 0.00, 0.50);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
+                      GTK_FILL, GTK_FILL, 0, 0);
+    gtk_widget_show (label);
+
+    dialog->prop_name = entry = gtk_entry_new ();
+    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
+                      GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
+    gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+    gtk_widget_show (entry);
+
+    label = gtk_label_new_with_mnemonic (_("_Type:"));
+    gtk_misc_set_alignment (GTK_MISC (label), 0.00, 0.50);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
+                      GTK_FILL, GTK_FILL, 0, 0);
+    gtk_widget_show (label);
+
+    store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_UINT);
+    for (i = 0; i < G_N_ELEMENTS (value_types); i++)
+    {
+        gtk_list_store_insert_with_values (store, NULL, i,
+                                           COLUMN_NAME, _(value_types[i].name),
+                                           COLUMN_ID, i, -1);
+    }
+
+    dialog->prop_type = combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+    gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 1, 2,
+                      GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
+    gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
+    gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+    gtk_widget_show (combo);
+    g_object_unref (G_OBJECT (store));
+
+    render = gtk_cell_renderer_text_new ();
+    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), render, TRUE);
+    gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), render,
+                                   "text", COLUMN_NAME);
+
+    label = gtk_label_new_with_mnemonic (_("_Value:"));
+    gtk_misc_set_alignment (GTK_MISC (label), 0.00, 0.50);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
+                      GTK_FILL, GTK_FILL, 0, 0);
+    gtk_widget_show (label);
+}
+
+
+
+static void
+xfce_settings_prop_dialog_finalize (GObject *object)
+{
+    XfceSettingsPropDialog *dialog = XFCE_SETTINGS_PROP_DIALOG (object);
+
+    if (dialog->channel != NULL)
+        g_object_unref (G_OBJECT (dialog->channel));
+
+    if (G_IS_VALUE (&dialog->cancel_value))
+        g_value_unset (&dialog->cancel_value);
+
+    g_free (dialog->property);
+
+    G_OBJECT_CLASS (xfce_settings_prop_dialog_parent_class)->finalize (object);
+}
+
+
+
+static void
+xfce_settings_prop_dialog_response (GtkDialog *widget,
+                                    gint       response_id)
+{
+    XfceSettingsPropDialog *dialog = XFCE_SETTINGS_PROP_DIALOG (widget);
+
+    g_return_if_fail (XFCONF_IS_CHANNEL (dialog->channel));
+
+    if (response_id == GTK_RESPONSE_CANCEL
+        && G_IS_VALUE (&dialog->cancel_value)
+        && dialog->property != NULL)
+    {
+        /* restore value */
+        xfconf_channel_set_property (dialog->channel,
+                                     dialog->property,
+                                     &dialog->cancel_value);
+    }
+}
+
+
+
+static void
+xfce_settings_prop_dialog_type_set_active (XfceSettingsPropDialog *dialog,
+                                           GType                   value_type)
+{
+    guint i;
+
+    if (value_type == xfce_settings_array_type ())
+        value_type = G_TYPE_BOXED;
+
+    for (i = 0; i < G_N_ELEMENTS (value_types); i++)
+    {
+        if (value_types[i].type == value_type)
+        {
+            gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->prop_type), i);
+            break;
+        }
+    }
+}
+
+
+
+GtkWidget *
+xfce_settings_prop_dialog_new (GtkWindow     *parent,
+                               XfconfChannel *channel,
+                               const gchar   *property)
+{
+    XfceSettingsPropDialog *dialog;
+
+    g_return_val_if_fail (XFCONF_IS_CHANNEL (channel), NULL);
+    g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
+
+    dialog = g_object_new (XFCE_TYPE_SETTINGS_PROP_DIALOG, NULL);
+
+    dialog->channel = g_object_ref (G_OBJECT (channel));
+    dialog->property = g_strdup (property);
+
+    if (property != NULL)
+    {
+        /* save property for restoring later */
+        xfconf_channel_get_property (channel, property, &dialog->cancel_value);
+
+        gtk_entry_set_text (GTK_ENTRY (dialog->prop_name), property);
+        gtk_editable_set_editable (GTK_EDITABLE (dialog->prop_name), FALSE);
+
+        xfce_settings_prop_dialog_type_set_active (dialog,
+            G_VALUE_TYPE (&dialog->cancel_value));
+    }
+
+    /* set the transient parent (if any) */
+    if (G_LIKELY (parent != NULL))
+    {
+        gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+        gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+        gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+    }
+
+    return GTK_WIDGET (dialog);
+}
+
+
+
+void
+xfce_settings_prop_dialog_set_parent_property (XfceSettingsPropDialog *dialog,
+                                               const gchar            *property)
+{
+    gchar *p;
+    gint   length = -1;
+    gint   pos = 0;
+
+    g_return_if_fail (XFCE_IS_SETTINGS_PROP_DIALOG (dialog));
+
+    if (property != NULL && *property == '/')
+    {
+        p = strrchr (property, '/');
+        if (G_LIKELY (p != NULL))
+          length = (p - property) + 1;
+
+        gtk_editable_insert_text (GTK_EDITABLE (dialog->prop_name),
+                                  property, length, &pos);
+    }
+}
diff --git a/xfce4-settings-editor/xfce-settings-prop-dialog.h b/xfce4-settings-editor/xfce-settings-prop-dialog.h
new file mode 100644
index 0000000..1fc7aec
--- /dev/null
+++ b/xfce4-settings-editor/xfce-settings-prop-dialog.h
@@ -0,0 +1,49 @@
+/*
+ *  xfce4-settings-editor
+ *
+ *  Copyright (c) 2012      Nick Schermer <nick at xfce.org>
+ *
+ *  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; version 2 of the License ONLY.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __XFCE_SETTINGS_PROP_DIALOG_H__
+#define __XFCE_SETTINGS_PROP_DIALOG_H__
+
+#include <gtk/gtk.h>
+#include <xfconf/xfconf.h>
+
+#define XFCE_TYPE_SETTINGS_PROP_DIALOG            (xfce_settings_prop_dialog_get_type ())
+#define XFCE_SETTINGS_PROP_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_SETTINGS_PROP_DIALOG, XfceSettingsPropDialog))
+#define XFCE_SETTINGS_PROP_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_SETTINGS_PROP_DIALOG, XfceSettingsPropDialogClass))
+#define XFCE_IS_SETTINGS_PROP_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_SETTINGS_PROP_DIALOG))
+#define XFCE_IS_SETTINGS_PROP_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_SETTINGS_PROP_DIALOG))
+#define XFCE_SETTINGS_PROP_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_SETTINGS_PROP_DIALOG, XfceSettingsPropDialogClass))
+
+G_BEGIN_DECLS
+
+typedef struct _XfceSettingsPropDialog      XfceSettingsPropDialog;
+typedef struct _XfceSettingsPropDialogClass XfceSettingsPropDialogClass;
+
+GType      xfce_settings_prop_dialog_get_type            (void) G_GNUC_CONST;
+
+GtkWidget *xfce_settings_prop_dialog_new                 (GtkWindow              *parent,
+                                                          XfconfChannel          *channel,
+                                                          const gchar            *property);
+
+void       xfce_settings_prop_dialog_set_parent_property (XfceSettingsPropDialog *dialog,
+                                                          const gchar            *property);
+
+G_END_DECLS
+
+#endif  /* __XFCE_SETTINGS_PROP_DIALOG_H__ */


More information about the Xfce4-commits mailing list