[Xfce4-commits] <xfce4-settings:nick/settings-editor> WIP: Make the properties dialog work.

Nick Schermer noreply at xfce.org
Sun Feb 5 14:14:01 CET 2012


Updating branch refs/heads/nick/settings-editor
         to 46204e9a5abf36dd12a55de22a0cb5e831f377d6 (commit)
       from 06c13c07a9823f3a501f013e0498a7cf7f21adc5 (commit)

commit 46204e9a5abf36dd12a55de22a0cb5e831f377d6
Author: Nick Schermer <nick at xfce.org>
Date:   Sun Feb 5 00:07:59 2012 +0100

    WIP: Make the properties dialog work.

 .../xfce-settings-editor-dialog.c                  |   77 +++--
 xfce4-settings-editor/xfce-settings-prop-dialog.c  |  310 ++++++++++++++++----
 2 files changed, 308 insertions(+), 79 deletions(-)

diff --git a/xfce4-settings-editor/xfce-settings-editor-dialog.c b/xfce4-settings-editor/xfce-settings-editor-dialog.c
index 75a3126..318c36c 100644
--- a/xfce4-settings-editor/xfce-settings-editor-dialog.c
+++ b/xfce4-settings-editor/xfce-settings-editor-dialog.c
@@ -610,14 +610,15 @@ xfce_settings_editor_dialog_property_changed (XfconfChannel            *channel,
                                               const GValue             *value,
                                               XfceSettingsEditorDialog *dialog)
 {
-    GtkTreePath   *path = NULL;
-    DeleteContext *context;
-    GtkTreeIter    child_iter;
-    GtkTreeModel  *model;
-    GValue         parent_val = { 0, };
-    GtkTreeIter    parent_iter;
-    gboolean       empty_prop;
-    gboolean       has_parent;
+    GtkTreePath      *path = NULL;
+    DeleteContext    *context;
+    GtkTreeIter       child_iter;
+    GtkTreeModel     *model;
+    GValue            parent_val = { 0, };
+    GtkTreeIter       parent_iter;
+    gboolean          empty_prop;
+    gboolean          has_parent;
+    GtkTreeSelection *selection;
 
     g_return_if_fail (GTK_IS_TREE_STORE (dialog->props_store));
     g_return_if_fail (XFCONF_IS_CHANNEL (channel));
@@ -648,30 +649,44 @@ xfce_settings_editor_dialog_property_changed (XfconfChannel            *channel,
         {
             if (gtk_tree_model_get_iter (model, &child_iter, context->path))
             {
-                /* delete the value */
-                has_parent = gtk_tree_model_iter_parent (model, &parent_iter, &child_iter);
-                gtk_tree_store_remove (GTK_TREE_STORE (model), &child_iter);
-
-                /* remove the parent nodes if they are empty */
-                while (has_parent)
+                if (gtk_tree_model_iter_has_child (model, &child_iter))
                 {
-                    /* if the parent still has children, stop cleaning */
-                    if (gtk_tree_model_iter_has_child (model, &parent_iter))
-                        break;
-
-                    /* maybe the parent has a value */
-                    gtk_tree_model_get_value (model, &parent_iter, PROP_COLUMN_FULL, &parent_val);
-                    empty_prop = g_value_get_string (&parent_val) == NULL;
-                    g_value_unset (&parent_val);
-
-                    /* nope it points to a real xfconf property */
-                    if (!empty_prop)
-                        break;
-
-                    /* get the parent and remove the empty row */
-                    child_iter = parent_iter;
+                    /* the node has children, so only unset it */
+                    gtk_tree_store_set (GTK_TREE_STORE (model), &child_iter,
+                                        PROP_COLUMN_FULL, NULL,
+                                        PROP_COLUMN_TYPE, NULL,
+                                        PROP_COLUMN_TYPE_NAME, _("Empty"),
+                                        PROP_COLUMN_LOCKED, FALSE,
+                                        PROP_COLUMN_VALUE, NULL,
+                                        -1);
+                }
+                else
+                {
+                    /* delete the node */
                     has_parent = gtk_tree_model_iter_parent (model, &parent_iter, &child_iter);
                     gtk_tree_store_remove (GTK_TREE_STORE (model), &child_iter);
+
+                    /* remove the parent nodes if they are empty */
+                    while (has_parent)
+                    {
+                        /* if the parent still has children, stop cleaning */
+                        if (gtk_tree_model_iter_has_child (model, &parent_iter))
+                            break;
+
+                        /* maybe the parent has a value */
+                        gtk_tree_model_get_value (model, &parent_iter, PROP_COLUMN_FULL, &parent_val);
+                        empty_prop = g_value_get_string (&parent_val) == NULL;
+                        g_value_unset (&parent_val);
+
+                        /* nope it points to a real xfconf property */
+                        if (!empty_prop)
+                            break;
+
+                        /* get the parent and remove the empty row */
+                        child_iter = parent_iter;
+                        has_parent = gtk_tree_model_iter_parent (model, &parent_iter, &child_iter);
+                        gtk_tree_store_remove (GTK_TREE_STORE (model), &child_iter);
+                    }
                 }
             }
 
@@ -680,6 +695,10 @@ xfce_settings_editor_dialog_property_changed (XfconfChannel            *channel,
 
         g_slice_free (DeleteContext, context);
     }
+
+    /* update button sensitivity */
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->props_treeview));
+    xfce_settings_editor_dialog_selection_changed (selection, dialog);
 }
 
 
diff --git a/xfce4-settings-editor/xfce-settings-prop-dialog.c b/xfce4-settings-editor/xfce-settings-prop-dialog.c
index 5ae5f57..e2bcc35 100644
--- a/xfce4-settings-editor/xfce-settings-prop-dialog.c
+++ b/xfce4-settings-editor/xfce-settings-prop-dialog.c
@@ -50,11 +50,8 @@ struct _XfceSettingsPropDialog
     GtkDialog __parent__;
 
     XfconfChannel *channel;
-    gchar         *property;
 
-    GValue         cancel_value;
-
-    gulong         prop_binding;
+    GValue         prop_value;
 
     GtkWidget     *prop_name;
     GtkWidget     *prop_type;
@@ -77,6 +74,8 @@ static void     xfce_settings_prop_dialog_response             (GtkDialog
                                                                 gint                       response_id);
 static void     xfce_settings_prop_dialog_visible_bind         (GtkWidget                 *widget,
                                                                 GtkWidget                 *label);
+static void     xfce_settings_prop_dialog_entry_validate       (GtkWidget                 *entry,
+                                                                XfceSettingsPropDialog    *dialog);
 static void     xfce_settings_prop_dialog_button_toggled       (GtkWidget                 *button);
 static void     xfce_settings_prop_dialog_type_changed         (GtkWidget                 *combo,
                                                                 XfceSettingsPropDialog    *dialog);
@@ -140,7 +139,7 @@ xfce_settings_prop_dialog_init (XfceSettingsPropDialog *dialog)
     guint            i;
     GtkCellRenderer *render;
 
-    gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Property"));
+    gtk_window_set_title (GTK_WINDOW (dialog), _("New Property"));
     gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 200);
     gtk_dialog_add_buttons (GTK_DIALOG (dialog),
                             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
@@ -165,6 +164,8 @@ xfce_settings_prop_dialog_init (XfceSettingsPropDialog *dialog)
     gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
                       GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
     xfce_settings_prop_dialog_visible_bind (entry, label);
+    g_signal_connect (G_OBJECT (entry), "changed",
+        G_CALLBACK (xfce_settings_prop_dialog_entry_validate), dialog);
     gtk_widget_show (entry);
 
     label = gtk_label_new_with_mnemonic (_("_Type:"));
@@ -244,10 +245,8 @@ xfce_settings_prop_dialog_finalize (GObject *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);
+    if (G_IS_VALUE (&dialog->prop_value))
+        g_value_unset (&dialog->prop_value);
 
     G_OBJECT_CLASS (xfce_settings_prop_dialog_parent_class)->finalize (object);
 }
@@ -259,17 +258,73 @@ xfce_settings_prop_dialog_response (GtkDialog *widget,
                                     gint       response_id)
 {
     XfceSettingsPropDialog *dialog = XFCE_SETTINGS_PROP_DIALOG (widget);
+    const gchar            *property;
+    ValueTypes             *value_type;
+    GValue                  value = { 0, };
+    gdouble                 spin_value;
+    gint                    active;
 
     g_return_if_fail (XFCONF_IS_CHANNEL (dialog->channel));
 
-    if (response_id == GTK_RESPONSE_CANCEL
-        && G_IS_VALUE (&dialog->cancel_value)
-        && dialog->property != NULL)
+    if (response_id == GTK_RESPONSE_OK)
     {
-        /* restore value */
-        xfconf_channel_set_property (dialog->channel,
-                                     dialog->property,
-                                     &dialog->cancel_value);
+        property = gtk_entry_get_text (GTK_ENTRY (dialog->prop_name));
+
+        active = gtk_combo_box_get_active (GTK_COMBO_BOX (dialog->prop_type));
+        g_assert (active >= 0 && active < (gint) G_N_ELEMENTS (value_types));
+        value_type = &value_types[active];
+
+        spin_value = gtk_spin_button_get_value (GTK_SPIN_BUTTON (dialog->prop_integer));
+
+        switch (value_type->type)
+        {
+            case G_TYPE_BOXED:
+            case G_TYPE_NONE:
+                return;
+
+            case G_TYPE_STRING:
+                g_value_init (&value, G_TYPE_STRING);
+                g_value_set_static_string (&value,
+                    gtk_entry_get_text (GTK_ENTRY (dialog->prop_string)));
+                break;
+
+            case G_TYPE_BOOLEAN:
+                g_value_init (&value, G_TYPE_BOOLEAN);
+                g_value_set_boolean (&value,
+                    gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->prop_bool)));
+                break;
+
+            case G_TYPE_INT:
+                g_value_init (&value, G_TYPE_INT);
+                g_value_set_int (&value, spin_value);
+                break;
+
+            case G_TYPE_DOUBLE:
+                g_value_init (&value, G_TYPE_DOUBLE);
+                g_value_set_double (&value, spin_value);
+                break;
+
+            case G_TYPE_UINT:
+                g_value_init (&value, G_TYPE_UINT);
+                g_value_set_uint (&value, spin_value);
+                break;
+
+            case G_TYPE_INT64:
+                g_value_init (&value, G_TYPE_INT64);
+                g_value_set_int64 (&value, spin_value);
+                break;
+
+            case G_TYPE_UINT64:
+                g_value_init (&value, G_TYPE_UINT64);
+                g_value_set_uint64 (&value, spin_value);
+                break;
+        }
+
+        if (G_IS_VALUE (&value))
+        {
+            xfconf_channel_set_property (dialog->channel, property, &value);
+            g_value_unset (&value);
+        }
     }
 }
 
@@ -314,6 +369,117 @@ xfce_settings_prop_dialog_visible_bind (GtkWidget *widget,
 
 
 
+/* Copied from xfconfd/xfconf-backend.c */
+static gboolean
+xfconf_property_is_valid (const gchar  *property,
+                          GError      **error)
+{
+    const gchar *p = property;
+
+    if (!p || *p != '/')
+    {
+        if (error != NULL)
+        {
+            g_set_error (error, XFCONF_ERROR, XFCONF_ERROR_INVALID_PROPERTY,
+                         _("Property names must start with a '/' character"));
+        }
+        return FALSE;
+    }
+
+    p++;
+    if (!*p)
+    {
+        if (error != NULL)
+        {
+            g_set_error (error, XFCONF_ERROR, XFCONF_ERROR_INVALID_PROPERTY,
+                         _("The root element ('/') is not a valid property name"));
+        }
+        return FALSE;
+    }
+
+    while (*p)
+    {
+        if (!(*p >= 'A' && *p <= 'Z') && !(*p >= 'a' && *p <= 'z')
+            && !(*p >= '0' && *p <= '9')
+            && *p != '_' && *p != '-' && *p != '/'
+            && !(*p == '<' || *p == '>'))
+        {
+            if (error != NULL)
+            {
+                g_set_error (error, XFCONF_ERROR,
+                             XFCONF_ERROR_INVALID_PROPERTY,
+                             _("Property names can only include the ASCII "
+                               "characters A-Z, a-z, 0-9, '_', '-', '<' "
+                               "and '>', as well as '/' as a separator"));
+            }
+            return FALSE;
+        }
+
+        if ('/' == *p && '/' == *(p - 1))
+        {
+            if (error != NULL)
+            {
+                g_set_error (error, XFCONF_ERROR,
+                             XFCONF_ERROR_INVALID_PROPERTY,
+                             _("Property names cannot have two or more "
+                               "consecutive '/' characters"));
+            }
+            return FALSE;
+        }
+
+        p++;
+    }
+
+    if (*(p - 1) == '/')
+    {
+        if (error != NULL)
+        {
+            g_set_error (error, XFCONF_ERROR, XFCONF_ERROR_INVALID_PROPERTY,
+                         _("Property names cannot end with a '/' character"));
+        }
+
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+
+static void
+xfce_settings_prop_dialog_entry_validate (GtkWidget              *entry,
+                                          XfceSettingsPropDialog *dialog)
+{
+    GtkWidget   *save_button;
+    const gchar *text;
+    gboolean     is_valid = FALSE;
+    GError      *error = NULL;
+
+    text = gtk_entry_get_text (GTK_ENTRY (entry));
+
+    if (text != NULL && *text != '\0')
+    {
+        is_valid = xfconf_property_is_valid (text, &error);
+
+        gtk_entry_set_icon_from_stock (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY,
+                                       is_valid ? NULL : GTK_STOCK_DIALOG_ERROR);
+        gtk_entry_set_icon_tooltip_text (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY,
+                                         is_valid ? NULL : error->message);
+
+        if (error != NULL)
+            g_error_free (error);
+    }
+    else
+    {
+        gtk_entry_set_icon_from_stock (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, NULL);
+    }
+
+    save_button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+    gtk_widget_set_sensitive (save_button, is_valid);
+}
+
+
+
 static void
 xfce_settings_prop_dialog_button_toggled (GtkWidget *button)
 {
@@ -329,18 +495,18 @@ static void
 xfce_settings_prop_dialog_type_changed (GtkWidget              *combo,
                                         XfceSettingsPropDialog *dialog)
 {
-    gint        active;
-    ValueTypes *value_type;
+    gint          active;
+    ValueTypes   *value_type;
+    const GValue *value = &dialog->prop_value;
 
     gtk_widget_hide (dialog->prop_string);
     gtk_widget_hide (dialog->prop_integer);
     gtk_widget_hide (dialog->prop_bool);
 
-    if (dialog->prop_binding != 0)
-    {
-        xfconf_g_property_unbind (dialog->prop_binding);
-        dialog->prop_binding = 0;
-    }
+    gtk_spin_button_set_digits (GTK_SPIN_BUTTON (dialog->prop_integer), 0);
+    gtk_entry_set_text (GTK_ENTRY (dialog->prop_string), "");
+    gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->prop_integer), 0);
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->prop_bool), FALSE);
 
     active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
     if (active < 0 || active >= (gint) G_N_ELEMENTS (value_types))
@@ -351,51 +517,95 @@ xfce_settings_prop_dialog_type_changed (GtkWidget              *combo,
     switch (value_type->type)
     {
         case G_TYPE_NONE:
+        case G_TYPE_BOXED:
+            gtk_widget_grab_focus (dialog->prop_type);
             return;
 
         case G_TYPE_STRING:
             gtk_widget_show (dialog->prop_string);
+            gtk_widget_grab_focus (dialog->prop_string);
 
-            if (dialog->property != NULL)
+            if (G_VALUE_HOLDS_STRING (value))
             {
-                dialog->prop_binding = xfconf_g_property_bind (dialog->channel,
-                                                               dialog->property,
-                                                               G_TYPE_STRING,
-                                                               dialog->prop_string,
-                                                               "text");
+                gtk_entry_set_text (GTK_ENTRY (dialog->prop_string),
+                                    g_value_get_string (value));
             }
             break;
 
         case G_TYPE_BOOLEAN:
             gtk_widget_show (dialog->prop_bool);
+            gtk_widget_grab_focus (dialog->prop_bool);
 
-            if (dialog->property != NULL)
+            if (G_VALUE_HOLDS_BOOLEAN (value))
             {
-                dialog->prop_binding = xfconf_g_property_bind (dialog->channel,
-                                                               dialog->property,
-                                                               G_TYPE_BOOLEAN,
-                                                               dialog->prop_bool,
-                                                               "active");
+                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->prop_bool),
+                                              g_value_get_boolean (value));
             }
             break;
 
-        case G_TYPE_BOXED:
+        case G_TYPE_INT:
+            gtk_widget_show (dialog->prop_integer);
+            gtk_widget_grab_focus (dialog->prop_integer);
+            gtk_spin_button_set_range (GTK_SPIN_BUTTON (dialog->prop_integer),
+                                       G_MININT, G_MAXINT);
+
+            if (G_VALUE_HOLDS_INT (value))
+            {
+                gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->prop_integer),
+                                           g_value_get_int (value));
+            }
             break;
 
-        case G_TYPE_INT:
         case G_TYPE_DOUBLE:
+            gtk_widget_show (dialog->prop_integer);
+            gtk_widget_grab_focus (dialog->prop_integer);
+            gtk_spin_button_set_digits (GTK_SPIN_BUTTON (dialog->prop_integer), 4);
+            gtk_spin_button_set_range (GTK_SPIN_BUTTON (dialog->prop_integer),
+                                       G_MINDOUBLE, G_MAXDOUBLE);
+
+            if (G_VALUE_HOLDS_DOUBLE (value))
+            {
+                gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->prop_integer),
+                                           g_value_get_double (value));
+            }
+            break;
+
         case G_TYPE_UINT:
+            gtk_widget_show (dialog->prop_integer);
+            gtk_widget_grab_focus (dialog->prop_integer);
+            gtk_spin_button_set_range (GTK_SPIN_BUTTON (dialog->prop_integer),
+                                       0, G_MAXUINT);
+
+            if (G_VALUE_HOLDS_UINT (value))
+            {
+                gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->prop_integer),
+                                           g_value_get_uint (value));
+            }
+            break;
+
         case G_TYPE_INT64:
+            gtk_widget_show (dialog->prop_integer);
+            gtk_widget_grab_focus (dialog->prop_integer);
+            gtk_spin_button_set_range (GTK_SPIN_BUTTON (dialog->prop_integer),
+                                       G_MININT64, G_MAXINT64);
+
+            if (G_VALUE_HOLDS_INT64 (value))
+            {
+                gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->prop_integer),
+                                           g_value_get_int64 (value));
+            }
+            break;
+
         case G_TYPE_UINT64:
             gtk_widget_show (dialog->prop_integer);
+            gtk_widget_grab_focus (dialog->prop_integer);
+            gtk_spin_button_set_range (GTK_SPIN_BUTTON (dialog->prop_integer),
+                                       0, G_MAXUINT64);
 
-            if (dialog->property != NULL)
+            if (G_VALUE_HOLDS_UINT64 (value))
             {
-                dialog->prop_binding = xfconf_g_property_bind (dialog->channel,
-                                                               dialog->property,
-                                                               value_type->type,
-                                                               dialog->prop_integer,
-                                                               "value");
+                gtk_spin_button_set_value (GTK_SPIN_BUTTON (dialog->prop_integer),
+                                           g_value_get_uint64 (value));
             }
             break;
     }
@@ -437,19 +647,19 @@ xfce_settings_prop_dialog_new (GtkWindow     *parent,
     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);
+        gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Property"));
 
-        xfce_settings_prop_dialog_type_set_active (dialog,
-            G_VALUE_TYPE (&dialog->cancel_value));
-        gtk_widget_set_sensitive (dialog->prop_type, FALSE);
+        if (xfconf_channel_get_property (channel, property, &dialog->prop_value))
+        {
+            xfce_settings_prop_dialog_type_set_active (dialog,
+                G_VALUE_TYPE (&dialog->prop_value));
+            gtk_widget_set_sensitive (dialog->prop_type, FALSE);
+        }
     }
 
     /* set the transient parent (if any) */


More information about the Xfce4-commits mailing list