Updating branch refs/heads/nick/settings-editor to 46204e9a5abf36dd12a55de22a0cb5e831f377d6 (commit) from 06c13c07a9823f3a501f013e0498a7cf7f21adc5 (commit)
commit 46204e9a5abf36dd12a55de22a0cb5e831f377d6 Author: Nick Schermer <n...@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) */ _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org https://mail.xfce.org/mailman/listinfo/xfce4-commits