From ae46e7dc17aa620b25cae52a8c576022ecc1c66b Mon Sep 17 00:00:00 2001 From: Stefano Karapetsas Date: Sat, 27 Oct 2012 16:41:01 +0200 Subject: migrate keybindings applet to gsettings --- capplets/keybindings/mate-keybinding-properties.c | 1497 +++++++++++---------- 1 file changed, 764 insertions(+), 733 deletions(-) (limited to 'capplets/keybindings/mate-keybinding-properties.c') diff --git a/capplets/keybindings/mate-keybinding-properties.c b/capplets/keybindings/mate-keybinding-properties.c index b0ac2f7f..2e016a94 100644 --- a/capplets/keybindings/mate-keybinding-properties.c +++ b/capplets/keybindings/mate-keybinding-properties.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -17,19 +17,25 @@ #include "capplet-util.h" #include "eggcellrendererkeys.h" #include "activate-settings-daemon.h" +#include "dconf-util.h" + +#define GSETTINGS_KEYBINDINGS_DIR "/org/mate/desktop/keybindings/" +#define CUSTOM_KEYBINDING_SCHEMA "org.mate.control-center.keybinding" -#define MATECONF_BINDING_DIR "/desktop/mate/keybindings" #define MAX_ELEMENTS_BEFORE_SCROLLING 10 #define MAX_CUSTOM_SHORTCUTS 1000 #define RESPONSE_ADD 0 #define RESPONSE_REMOVE 1 typedef struct { + /* The untranslated name, combine with ->package to translate */ char *name; /* The gettext package to use to translate the section title */ char *package; /* Name of the window manager the keys would apply to */ char *wm_name; + /* The GSettings schema for the whole file */ + char *schema; /* an array of KeyListEntry */ GArray *entries; } KeyList; @@ -43,11 +49,15 @@ typedef enum { typedef struct { + char *gsettings_path; + char *schema; char *name; int value; - char *key; - char *description_name; - char *cmd_name; + char *value_schema; /* gsettings schema for key/value */ + char *value_key; + char *description; + char *description_key; + char *cmd_key; Comparison comparison; } KeyListEntry; @@ -60,21 +70,23 @@ enum typedef struct { - char *mateconf_key; + GSettings *settings; + char *gsettings_path; + char *gsettings_key; guint keyval; guint keycode; EggVirtualModifierType mask; gboolean editable; GtkTreeModel *model; char *description; - char *desc_mateconf_key; + char *desc_gsettings_key; gboolean desc_editable; char *command; - char *cmd_mateconf_key; + char *cmd_gsettings_key; gboolean cmd_editable; - guint mateconf_cnxn; - guint mateconf_cnxn_desc; - guint mateconf_cnxn_cmd; + gulong gsettings_cnxn; + gulong gsettings_cnxn_desc; + gulong gsettings_cnxn_cmd; } KeyEntry; static gboolean block_accels = FALSE; @@ -84,7 +96,7 @@ static GtkWidget *custom_shortcut_command_entry = NULL; static GtkWidget* _gtk_builder_get_widget(GtkBuilder* builder, const gchar* name) { - return GTK_WIDGET (gtk_builder_get_object (builder, name)); + return GTK_WIDGET (gtk_builder_get_object (builder, name)); } static GtkBuilder * @@ -106,27 +118,27 @@ create_builder (void) static char* binding_name(guint keyval, guint keycode, EggVirtualModifierType mask, gboolean translate) { - if (keyval != 0 || keycode != 0) - { - if (translate) - { - return egg_virtual_accelerator_label (keyval, keycode, mask); - } - else - { - return egg_virtual_accelerator_name (keyval, keycode, mask); - } - } - else - { - return g_strdup (translate ? _("Disabled") : ""); - } + if (keyval != 0 || keycode != 0) + { + if (translate) + { + return egg_virtual_accelerator_label (keyval, keycode, mask); + } + else + { + return egg_virtual_accelerator_name (keyval, keycode, mask); + } + } + else + { + return g_strdup (translate ? _("Disabled") : ""); + } } static gboolean binding_from_string (const char *str, guint *accelerator_key, - guint *keycode, + guint *keycode, EggVirtualModifierType *accelerator_mods) { g_return_val_if_fail (accelerator_key != NULL, FALSE); @@ -162,26 +174,26 @@ accel_set_func (GtkTreeViewColumn *tree_column, if (key_entry == NULL) g_object_set (cell, - "visible", FALSE, - NULL); + "visible", FALSE, + NULL); else if (! key_entry->editable) g_object_set (cell, - "visible", TRUE, - "editable", FALSE, - "accel_key", key_entry->keyval, - "accel_mask", key_entry->mask, - "keycode", key_entry->keycode, - "style", PANGO_STYLE_ITALIC, - NULL); + "visible", TRUE, + "editable", FALSE, + "accel_key", key_entry->keyval, + "accel_mask", key_entry->mask, + "keycode", key_entry->keycode, + "style", PANGO_STYLE_ITALIC, + NULL); else g_object_set (cell, - "visible", TRUE, - "editable", TRUE, - "accel_key", key_entry->keyval, - "accel_mask", key_entry->mask, - "keycode", key_entry->keycode, - "style", PANGO_STYLE_NORMAL, - NULL); + "visible", TRUE, + "editable", TRUE, + "accel_key", key_entry->keyval, + "accel_mask", key_entry->mask, + "keycode", key_entry->keycode, + "style", PANGO_STYLE_NORMAL, + NULL); } static void @@ -199,28 +211,28 @@ description_set_func (GtkTreeViewColumn *tree_column, if (key_entry != NULL) g_object_set (cell, - "editable", FALSE, - "text", key_entry->description != NULL ? - key_entry->description : _(""), - NULL); + "editable", FALSE, + "text", key_entry->description != NULL ? + key_entry->description : _(""), + NULL); else g_object_set (cell, - "editable", FALSE, NULL); + "editable", FALSE, NULL); } static gboolean keybinding_key_changed_foreach (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data) + GtkTreePath *path, + GtkTreeIter *iter, + gpointer user_data) { KeyEntry *key_entry; KeyEntry *tmp_key_entry; key_entry = (KeyEntry *)user_data; gtk_tree_model_get (key_entry->model, iter, - KEYENTRY_COLUMN, &tmp_key_entry, - -1); + KEYENTRY_COLUMN, &tmp_key_entry, + -1); if (key_entry == tmp_key_entry) { @@ -231,59 +243,53 @@ keybinding_key_changed_foreach (GtkTreeModel *model, } static void -keybinding_key_changed (MateConfClient *client, - guint cnxn_id, - MateConfEntry *entry, - gpointer user_data) +keybinding_key_changed (GSettings *settings, + gchar *key, + KeyEntry *key_entry) { - KeyEntry *key_entry; - const gchar *key_value; + gchar *key_value; - key_entry = (KeyEntry *) user_data; - key_value = entry->value ? mateconf_value_get_string (entry->value) : NULL; + key_value = g_settings_get_string (settings, key); binding_from_string (key_value, &key_entry->keyval, &key_entry->keycode, &key_entry->mask); - key_entry->editable = mateconf_entry_get_is_writable (entry); + key_entry->editable = g_settings_is_writable (settings, key); /* update the model */ gtk_tree_model_foreach (key_entry->model, keybinding_key_changed_foreach, key_entry); } static void -keybinding_description_changed (MateConfClient *client, - guint cnxn_id, - MateConfEntry *entry, - gpointer user_data) +keybinding_description_changed (GSettings *settings, + gchar *key, + KeyEntry *key_entry) { - KeyEntry *key_entry; - const gchar *key_value; + gchar *key_value; - key_entry = (KeyEntry *) user_data; - key_value = entry->value ? mateconf_value_get_string (entry->value) : NULL; + key_value = g_settings_get_string (settings, key); g_free (key_entry->description); key_entry->description = key_value ? g_strdup (key_value) : NULL; - key_entry->desc_editable = mateconf_entry_get_is_writable (entry); + g_free (key_value); + + key_entry->desc_editable = g_settings_is_writable (settings, key); /* update the model */ gtk_tree_model_foreach (key_entry->model, keybinding_key_changed_foreach, key_entry); } static void -keybinding_command_changed (MateConfClient *client, - guint cnxn_id, - MateConfEntry *entry, - gpointer user_data) +keybinding_command_changed (GSettings *settings, + gchar *key, + KeyEntry *key_entry) { - KeyEntry *key_entry; - const gchar *key_value; + gchar *key_value; - key_entry = (KeyEntry *) user_data; - key_value = entry->value ? mateconf_value_get_string (entry->value) : NULL; + key_value = g_settings_get_string (settings, key); g_free (key_entry->command); key_entry->command = key_value ? g_strdup (key_value) : NULL; - key_entry->cmd_editable = mateconf_entry_get_is_writable (entry); + key_entry->cmd_editable = g_settings_is_writable (settings, key); + g_free (key_value); /* update the model */ gtk_tree_model_foreach (key_entry->model, keybinding_key_changed_foreach, key_entry); @@ -375,16 +381,10 @@ clear_old_model (GtkBuilder *builder) else { /* clear the existing model */ - MateConfClient *client; gboolean valid; GtkTreeIter iter; KeyEntry *key_entry; - client = mateconf_client_get_default (); - /* we need the schema name below; - * cached values do not have that set, though */ - mateconf_client_clear_cache (client); - for (valid = gtk_tree_model_get_iter_first (model, &iter); valid; valid = gtk_tree_model_iter_next (model, &iter)) @@ -395,108 +395,134 @@ clear_old_model (GtkBuilder *builder) if (key_entry != NULL) { - mateconf_client_remove_dir (client, key_entry->mateconf_key, NULL); - mateconf_client_notify_remove (client, key_entry->mateconf_cnxn); - if (key_entry->mateconf_cnxn_desc != 0) - mateconf_client_notify_remove (client, key_entry->mateconf_cnxn_desc); - if (key_entry->mateconf_cnxn_cmd != 0) - mateconf_client_notify_remove (client, key_entry->mateconf_cnxn_cmd); - g_free (key_entry->mateconf_key); + g_signal_handler_disconnect (key_entry->settings, key_entry->gsettings_cnxn); + if (key_entry->gsettings_cnxn_desc != 0) + g_signal_handler_disconnect (key_entry->settings, key_entry->gsettings_cnxn_desc); + if (key_entry->gsettings_cnxn_cmd != 0) + g_signal_handler_disconnect (key_entry->settings, key_entry->gsettings_cnxn_cmd); + + g_object_unref (key_entry->settings); + if (key_entry->gsettings_path) + g_free (key_entry->gsettings_path); + g_free (key_entry->gsettings_key); g_free (key_entry->description); - g_free (key_entry->desc_mateconf_key); + g_free (key_entry->desc_gsettings_key); g_free (key_entry->command); - g_free (key_entry->cmd_mateconf_key); + g_free (key_entry->cmd_gsettings_key); g_free (key_entry); } } gtk_tree_store_clear (GTK_TREE_STORE (model)); - g_object_unref (client); } actions_swindow = _gtk_builder_get_widget (builder, "actions_swindow"); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (actions_swindow), - GTK_POLICY_NEVER, GTK_POLICY_NEVER); + GTK_POLICY_NEVER, GTK_POLICY_NEVER); gtk_widget_set_size_request (actions_swindow, -1, -1); } typedef struct { const char *key; + const char *path; + const char *schema; gboolean found; } KeyMatchData; static gboolean key_match(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, gpointer data) { - KeyMatchData* match_data = data; - KeyEntry* element; + KeyMatchData* match_data = data; + KeyEntry* element; + + gtk_tree_model_get(model, iter, + KEYENTRY_COLUMN, &element, + -1); - gtk_tree_model_get(model, iter, - KEYENTRY_COLUMN, &element, - -1); + gchar *element_schema; + gchar *element_path; - if (element && g_strcmp0(element->mateconf_key, match_data->key) == 0) - { - match_data->found = TRUE; - return TRUE; - } + if (element && element->settings && G_IS_SETTINGS(element->settings)) + { + #if GLIB_CHECK_VERSION (2, 32, 0) + g_object_get (element->settings, "schema-id", &element_schema, NULL); + #else + g_object_get (element->settings, "schema", &element_schema, NULL); + #endif + g_object_get (element->settings, "path", &element_path, NULL); + } + else { + element_schema = NULL; + element_path = NULL; + } - return FALSE; + if (element && g_strcmp0(element->gsettings_key, match_data->key) == 0 + && g_strcmp0(element_schema, match_data->schema) == 0 + && g_strcmp0(element_path, match_data->path) == 0) + { + match_data->found = TRUE; + return TRUE; + } + + return FALSE; } static gboolean key_is_already_shown(GtkTreeModel* model, const KeyListEntry* entry) { - KeyMatchData data; + KeyMatchData data; - data.key = entry->name; - data.found = FALSE; - gtk_tree_model_foreach(model, key_match, &data); + data.key = entry->name; + data.schema = entry->schema; + data.path = entry->gsettings_path; + data.found = FALSE; + gtk_tree_model_foreach(model, key_match, &data); - return data.found; + return data.found; } static gboolean should_show_key(const KeyListEntry* entry) { - int value; - MateConfClient *client; - - if (entry->comparison == COMPARISON_NONE) - { - return TRUE; - } - - g_return_val_if_fail(entry->key != NULL, FALSE); - - client = mateconf_client_get_default(); - value = mateconf_client_get_int (client, entry->key, NULL); - g_object_unref (client); - - switch (entry->comparison) - { - case COMPARISON_NONE: - /* For compiler warnings */ - g_assert_not_reached (); - return FALSE; - case COMPARISON_GT: - if (value > entry->value) - { - return TRUE; - } - break; - case COMPARISON_LT: - if (value < entry->value) - { - return TRUE; - } - break; - case COMPARISON_EQ: - if (value == entry->value) - { - return TRUE; - } - break; - } - - return FALSE; + GSettings *settings; + int value; + + if (entry->comparison == COMPARISON_NONE) + { + return TRUE; + } + + g_return_val_if_fail(entry->value_key != NULL, FALSE); + g_return_val_if_fail(entry->value_schema != NULL, FALSE); + + settings = g_settings_new (entry->value_schema); + value = g_settings_get_int (settings, entry->value_key); + g_object_unref (settings); + + switch (entry->comparison) + { + case COMPARISON_NONE: + /* For compiler warnings */ + g_assert_not_reached (); + return FALSE; + case COMPARISON_GT: + if (value > entry->value) + { + return TRUE; + } + break; + case COMPARISON_LT: + if (value < entry->value) + { + return TRUE; + } + break; + case COMPARISON_EQ: + if (value == entry->value) + { + return TRUE; + } + break; + } + + return FALSE; } static gboolean @@ -523,14 +549,14 @@ ensure_scrollbar (GtkBuilder *builder, int i) gtk_widget_size_request (treeview, &rectangle); gtk_widget_set_size_request (treeview, -1, rectangle.height); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (actions_swindow), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); } } static void find_section (GtkTreeModel *model, GtkTreeIter *iter, - const char *title) + const char *title) { gboolean success; @@ -540,8 +566,8 @@ find_section (GtkTreeModel *model, char *description = NULL; gtk_tree_model_get (model, iter, - DESCRIPTION_COLUMN, &description, - -1); + DESCRIPTION_COLUMN, &description, + -1); if (g_strcmp0 (description, title) == 0) return; @@ -556,15 +582,15 @@ find_section (GtkTreeModel *model, static void append_keys_to_tree (GtkBuilder *builder, - const gchar *title, - const KeyListEntry *keys_list) + const gchar *title, + const gchar *schema, + const gchar *package, + const KeyListEntry *keys_list) { - MateConfClient *client; GtkTreeIter parent_iter, iter; GtkTreeModel *model; gint i, j; - client = mateconf_client_get_default (); model = gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_builder_get_object (builder, "shortcut_treeview"))); /* Try to find a section parent iter, if it already exists */ @@ -580,7 +606,8 @@ append_keys_to_tree (GtkBuilder *builder, for (j = 0; keys_list[j].name != NULL; j++) { - MateConfEntry *entry; + GSettings *settings = NULL; + gchar *settings_path; KeyEntry *key_entry; const gchar *key_string; gchar *key_value; @@ -588,57 +615,56 @@ append_keys_to_tree (GtkBuilder *builder, gchar *command; if (!should_show_key (&keys_list[j])) - continue; + continue; if (key_is_already_shown (model, &keys_list[j])) - continue; + continue; key_string = keys_list[j].name; - entry = mateconf_client_get_entry (client, - key_string, - NULL, - TRUE, - NULL); - if (entry == NULL) - { - /* We don't actually want to popup a dialog - just skip this one */ - continue; - } - - if (keys_list[j].description_name != NULL) + if (keys_list[j].gsettings_path != NULL) { - description = mateconf_client_get_string (client, keys_list[j].description_name, NULL); + settings = g_settings_new_with_path (schema, keys_list[j].gsettings_path); + settings_path = g_strdup(keys_list[j].gsettings_path); } else { - description = NULL; + settings = g_settings_new (schema); + settings_path = NULL; + } - if (mateconf_entry_get_schema_name (entry)) + if (keys_list[j].description_key != NULL) + { + /* it's a custom shortcut, so description is in gsettings */ + description = g_settings_get_string (settings, keys_list[j].description_key); + } + else + { + /* it's from keyfile, so description need to be translated */ + description = keys_list[j].description; + if (package) { - MateConfSchema *schema; - - schema = mateconf_client_get_schema (client, - mateconf_entry_get_schema_name (entry), - NULL); - if (schema != NULL) - { - description = g_strdup (mateconf_schema_get_short_desc (schema)); - mateconf_schema_free (schema); - } + bind_textdomain_codeset (package, "UTF-8"); + description = dgettext (package, description); + } + else + { + description = _(description); } } if (description == NULL) { - /* Only print a warning for keys that should have a schema */ - if (keys_list[j].description_name == NULL) - g_warning ("No description for key '%s'", key_string); - } + /* Only print a warning for keys that should have a schema */ + if (keys_list[j].description_key == NULL) + g_warning ("No description for key '%s'", key_string); + } - if (keys_list[j].cmd_name != NULL) + + + if (keys_list[j].cmd_key != NULL) { - command = mateconf_client_get_string (client, keys_list[j].cmd_name, NULL); + command = g_settings_get_string (settings, keys_list[j].cmd_key); } else { @@ -646,54 +672,58 @@ append_keys_to_tree (GtkBuilder *builder, } key_entry = g_new0 (KeyEntry, 1); - key_entry->mateconf_key = g_strdup (key_string); - key_entry->editable = mateconf_entry_get_is_writable (entry); + key_entry->settings = settings; + key_entry->gsettings_path = settings_path; + key_entry->gsettings_key = g_strdup (key_string); + key_entry->editable = g_settings_is_writable (settings, key_string); key_entry->model = model; key_entry->description = description; key_entry->command = command; - if (keys_list[j].description_name != NULL) + if (keys_list[j].description_key != NULL) { - key_entry->desc_mateconf_key = g_strdup (keys_list[j].description_name); - key_entry->desc_editable = mateconf_client_key_is_writable (client, key_entry->desc_mateconf_key, NULL); - key_entry->mateconf_cnxn_desc = mateconf_client_notify_add (client, - key_entry->desc_mateconf_key, - (MateConfClientNotifyFunc) &keybinding_description_changed, - key_entry, NULL, NULL); + key_entry->desc_gsettings_key = g_strdup (keys_list[j].description_key); + key_entry->desc_editable = g_settings_is_writable (settings, key_entry->desc_gsettings_key); + gchar *gsettings_signal = g_strconcat ("changed::", key_entry->desc_gsettings_key, NULL); + key_entry->gsettings_cnxn_desc = g_signal_connect (settings, + gsettings_signal, + G_CALLBACK (keybinding_description_changed), + key_entry); + g_free (gsettings_signal); } - if (keys_list[j].cmd_name != NULL) + if (keys_list[j].cmd_key != NULL) { - key_entry->cmd_mateconf_key = g_strdup (keys_list[j].cmd_name); - key_entry->cmd_editable = mateconf_client_key_is_writable (client, key_entry->cmd_mateconf_key, NULL); - key_entry->mateconf_cnxn_cmd = mateconf_client_notify_add (client, - key_entry->cmd_mateconf_key, - (MateConfClientNotifyFunc) &keybinding_command_changed, - key_entry, NULL, NULL); + key_entry->cmd_gsettings_key = g_strdup (keys_list[j].cmd_key); + key_entry->cmd_editable = g_settings_is_writable (settings, key_entry->cmd_gsettings_key); + gchar *gsettings_signal = g_strconcat ("changed::", key_entry->cmd_gsettings_key, NULL); + key_entry->gsettings_cnxn_cmd = g_signal_connect (settings, + gsettings_signal, + G_CALLBACK (keybinding_command_changed), + key_entry); + g_free (gsettings_signal); } - mateconf_client_add_dir (client, key_string, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL); - key_entry->mateconf_cnxn = mateconf_client_notify_add (client, - key_string, - (MateConfClientNotifyFunc) &keybinding_key_changed, - key_entry, NULL, NULL); + gchar *gsettings_signal = g_strconcat ("changed::", key_string, NULL); + key_entry->gsettings_cnxn = g_signal_connect (settings, + gsettings_signal, + G_CALLBACK (keybinding_key_changed), + key_entry); + g_free (gsettings_signal); - key_value = mateconf_client_get_string (client, key_string, NULL); + key_value = g_settings_get_string (settings, key_string); binding_from_string (key_value, &key_entry->keyval, &key_entry->keycode, &key_entry->mask); g_free (key_value); - mateconf_entry_free (entry); ensure_scrollbar (builder, i); ++i; gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent_iter); /* we use the DESCRIPTION_COLUMN only for the section headers */ gtk_tree_store_set (GTK_TREE_STORE (model), &iter, - KEYENTRY_COLUMN, key_entry, - -1); + KEYENTRY_COLUMN, key_entry, + -1); gtk_tree_view_expand_all (GTK_TREE_VIEW (gtk_builder_get_object (builder, "shortcut_treeview"))); } - g_object_unref (client); - /* Don't show an empty section */ if (gtk_tree_model_iter_n_children (model, &parent_iter) == 0) gtk_tree_store_remove (GTK_TREE_STORE (model), &parent_iter); @@ -706,17 +736,18 @@ append_keys_to_tree (GtkBuilder *builder, static void parse_start_tag (GMarkupParseContext *ctx, - const gchar *element_name, - const gchar **attr_names, - const gchar **attr_values, - gpointer user_data, - GError **error) + const gchar *element_name, + const gchar **attr_names, + const gchar **attr_values, + gpointer user_data, + GError **error) { KeyList *keylist = (KeyList *) user_data; KeyListEntry key; - const char *name, *mateconf_key; + const char *name, *value_key, *description, *value_schema; int value; Comparison comparison; + const char *schema = NULL; name = NULL; @@ -728,42 +759,58 @@ parse_start_tag (GMarkupParseContext *ctx, while (*attr_names && *attr_values) { - if (g_str_equal (*attr_names, "name")) - { - if (**attr_values) - name = *attr_values; - } else if (g_str_equal (*attr_names, "wm_name")) { - if (**attr_values) - wm_name = *attr_values; - } else if (g_str_equal (*attr_names, "package")) { - if (**attr_values) - package = *attr_values; - } - ++attr_names; - ++attr_values; - } + if (g_str_equal (*attr_names, "name")) + { + if (**attr_values) + name = *attr_values; + } + else if (g_str_equal (*attr_names, "wm_name")) + { + if (**attr_values) + wm_name = *attr_values; + } + else if (g_str_equal (*attr_names, "package")) + { + if (**attr_values) + package = *attr_values; + } + else if (g_str_equal (*attr_names, "schema")) + { + if (**attr_values) + schema = *attr_values; + } + ++attr_names; + ++attr_values; + } if (name) { - if (keylist->name) - g_warning ("Duplicate section name"); - g_free (keylist->name); - keylist->name = g_strdup (name); - } + if (keylist->name) + g_warning ("Duplicate section name"); + g_free (keylist->name); + keylist->name = g_strdup (name); + } if (wm_name) { - if (keylist->wm_name) - g_warning ("Duplicate window manager name"); - g_free (keylist->wm_name); - keylist->wm_name = g_strdup (wm_name); - } + if (keylist->wm_name) + g_warning ("Duplicate window manager name"); + g_free (keylist->wm_name); + keylist->wm_name = g_strdup (wm_name); + } if (package) { - if (keylist->package) - g_warning ("Duplicate gettext package name"); - g_free (keylist->package); - keylist->package = g_strdup (package); - } + if (keylist->package) + g_warning ("Duplicate gettext package name"); + g_free (keylist->package); + keylist->package = g_strdup (package); + } + if (schema) + { + if (keylist->schema) + g_warning ("Duplicate schema name"); + g_free (keylist->schema); + keylist->schema = g_strdup (schema); + } return; } @@ -774,34 +821,44 @@ parse_start_tag (GMarkupParseContext *ctx, value = 0; comparison = COMPARISON_NONE; - mateconf_key = NULL; + value_key = NULL; + value_schema = NULL; + description = NULL; while (*attr_names && *attr_values) { if (g_str_equal (*attr_names, "name")) { - /* skip if empty */ - if (**attr_values) - name = *attr_values; - } else if (g_str_equal (*attr_names, "value")) { - if (**attr_values) { - value = (int) g_ascii_strtoull (*attr_values, NULL, 0); - } - } else if (g_str_equal (*attr_names, "key")) { - if (**attr_values) { - mateconf_key = *attr_values; - } - } else if (g_str_equal (*attr_names, "comparison")) { - if (**attr_values) { - if (g_str_equal (*attr_values, "gt")) { - comparison = COMPARISON_GT; - } else if (g_str_equal (*attr_values, "lt")) { - comparison = COMPARISON_LT; - } else if (g_str_equal (*attr_values, "eq")) { - comparison = COMPARISON_EQ; - } - } - } + /* skip if empty */ + if (**attr_values) + name = *attr_values; + } else if (g_str_equal (*attr_names, "value")) { + if (**attr_values) { + value = (int) g_ascii_strtoull (*attr_values, NULL, 0); + } + } else if (g_str_equal (*attr_names, "key")) { + if (**attr_values) { + value_key = *attr_values; + } + } else if (g_str_equal (*attr_names, "comparison")) { + if (**attr_values) { + if (g_str_equal (*attr_values, "gt")) { + comparison = COMPARISON_GT; + } else if (g_str_equal (*attr_values, "lt")) { + comparison = COMPARISON_LT; + } else if (g_str_equal (*attr_values, "eq")) { + comparison = COMPARISON_EQ; + } + } + } else if (g_str_equal (*attr_names, "description")) { + if (**attr_values) { + description = *attr_values; + } + } else if (g_str_equal (*attr_names, "schema")) { + if (**attr_values) { + value_schema = *attr_values; + } + } ++attr_names; ++attr_values; @@ -811,20 +868,27 @@ parse_start_tag (GMarkupParseContext *ctx, return; key.name = g_strdup (name); - key.description_name = NULL; + key.gsettings_path = NULL; + key.description_key = NULL; + key.description = g_strdup(description); + key.schema = g_strdup(schema); key.value = value; - if (mateconf_key) - key.key = g_strdup (mateconf_key); - else - key.key = NULL; + if (value_key) { + key.value_key = g_strdup (value_key); + key.value_schema = g_strdup (value_schema); + } + else { + key.value_key = NULL; + key.value_schema = NULL; + } key.comparison = comparison; - key.cmd_name = NULL; + key.cmd_key = NULL; g_array_append_val (keylist->entries, key); } static gboolean strv_contains (char **strv, - char *str) + char *str) { char **p = strv; for (p = strv; *p; p++) @@ -836,8 +900,8 @@ strv_contains (char **strv, static void append_keys_to_tree_from_file (GtkBuilder *builder, - const char *filename, - char **wm_keybindings) + const char *filename, + char **wm_keybindings) { GMarkupParseContext *ctx; GMarkupParser parser = { parse_start_tag, NULL, NULL, NULL, NULL }; @@ -863,8 +927,9 @@ append_keys_to_tree_from_file (GtkBuilder *builder, g_free (keylist->name); g_free (keylist->package); g_free (keylist->wm_name); + g_free (keylist->schema); for (i = 0; i < keylist->entries->len; i++) - g_free (((KeyListEntry *) &(keylist->entries->data[i]))->name); + g_free (((KeyListEntry *) &(keylist->entries->data[i]))->name); g_array_free (keylist->entries, TRUE); g_free (keylist); keylist = NULL; @@ -884,6 +949,7 @@ append_keys_to_tree_from_file (GtkBuilder *builder, g_free (keylist->name); g_free (keylist->package); g_free (keylist->wm_name); + g_free (keylist->schema); g_array_free (keylist->entries, TRUE); g_free (keylist); return; @@ -891,8 +957,8 @@ append_keys_to_tree_from_file (GtkBuilder *builder, /* Empty KeyListEntry to end the array */ key.name = NULL; - key.description_name = NULL; - key.key = NULL; + key.description_key = NULL; + key.value_key = NULL; key.value = 0; key.comparison = COMPARISON_NONE; g_array_append_val (keylist->entries, key); @@ -906,7 +972,7 @@ append_keys_to_tree_from_file (GtkBuilder *builder, title = _(keylist->name); } - append_keys_to_tree (builder, title, keys); + append_keys_to_tree (builder, title, keylist->schema, keylist->package, keys); g_free (keylist->name); g_free (keylist->package); @@ -916,35 +982,35 @@ append_keys_to_tree_from_file (GtkBuilder *builder, } static void -append_keys_to_tree_from_mateconf (GtkBuilder *builder, const gchar *mateconf_path) +append_keys_to_tree_from_gsettings (GtkBuilder *builder, const gchar *gsettings_path) { - MateConfClient *client; - GSList *custom_list, *l; + gchar **custom_list; GArray *entries; KeyListEntry key; + gint i; - /* load custom shortcuts from MateConf */ + /* load custom shortcuts from GSettings */ entries = g_array_new (FALSE, TRUE, sizeof (KeyListEntry)); - key.key = NULL; + key.value_key = NULL; key.value = 0; key.comparison = COMPARISON_NONE; - client = mateconf_client_get_default (); - custom_list = mateconf_client_all_dirs (client, mateconf_path, NULL); + custom_list = dconf_util_list_subdirs (gsettings_path, FALSE); - for (l = custom_list; l != NULL; l = l->next) + if (custom_list != NULL) { - key.name = g_strconcat (l->data, "/binding", NULL); - key.cmd_name = g_strconcat (l->data, "/action", NULL); - key.description_name = g_strconcat (l->data, "/name", NULL); - g_array_append_val (entries, key); - - g_free (l->data); + for (i = 0; custom_list[i] != NULL; i++) + { + key.gsettings_path = g_strdup_printf("%s%s", gsettings_path, custom_list[i]); + key.name = g_strdup("binding"); + key.cmd_key = g_strdup("action"); + key.description_key = g_strdup("name"); + g_array_append_val (entries, key); + } } - g_slist_free (custom_list); - g_object_unref (client); + g_strfreev (custom_list); if (entries->len > 0) { @@ -952,16 +1018,20 @@ append_keys_to_tree_from_mateconf (GtkBuilder *builder, const gchar *mateconf_pa int i; /* Empty KeyListEntry to end the array */ + key.gsettings_path = NULL; key.name = NULL; - key.description_name = NULL; + key.description_key = NULL; + key.cmd_key = NULL; g_array_append_val (entries, key); keys = (KeyListEntry *) entries->data; - append_keys_to_tree (builder, _("Custom Shortcuts"), keys); + append_keys_to_tree (builder, _("Custom Shortcuts"), CUSTOM_KEYBINDING_SCHEMA, NULL, keys); for (i = 0; i < entries->len; ++i) { g_free (keys[i].name); - g_free (keys[i].description_name); + g_free (keys[i].description_key); + g_free (keys[i].cmd_key); + g_free (keys[i].gsettings_path); } } @@ -989,9 +1059,9 @@ reload_key_entries (GtkBuilder *builder) { if (g_str_has_suffix (name, ".xml")) { - list = g_list_insert_sorted (list, g_strdup (name), - (GCompareFunc) g_ascii_strcasecmp); - } + list = g_list_insert_sorted (list, g_strdup (name), + (GCompareFunc) g_ascii_strcasecmp); + } } g_dir_close (dir); @@ -999,10 +1069,10 @@ reload_key_entries (GtkBuilder *builder) { gchar *path; - path = g_build_filename (MATECC_KEYBINDINGS_DIR, l->data, NULL); + path = g_build_filename (MATECC_KEYBINDINGS_DIR, l->data, NULL); append_keys_to_tree_from_file (builder, path, wm_keybindings); - g_free (l->data); - g_free (path); + g_free (l->data); + g_free (path); } g_list_free (list); @@ -1011,89 +1081,119 @@ reload_key_entries (GtkBuilder *builder) * in a file. Loading the custom shortcuts last makes * such keys not show up in the custom section. */ - append_keys_to_tree_from_mateconf (builder, MATECONF_BINDING_DIR); + append_keys_to_tree_from_gsettings (builder, GSETTINGS_KEYBINDINGS_DIR); g_strfreev (wm_keybindings); } static void -key_entry_controlling_key_changed (MateConfClient *client, - guint cnxn_id, - MateConfEntry *entry, - gpointer user_data) +key_entry_controlling_key_changed (GSettings *settings, gchar *key, gpointer user_data) { reload_key_entries (user_data); } static gboolean cb_check_for_uniqueness(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, KeyEntry* new_key) { - KeyEntry* element; - - gtk_tree_model_get (new_key->model, iter, - KEYENTRY_COLUMN, &element, - -1); - - /* no conflict for : blanks, different modifiers, or ourselves */ - if (element == NULL || new_key->mask != element->mask || - !strcmp (new_key->mateconf_key, element->mateconf_key)) - { - return FALSE; - } - - if (new_key->keyval != 0) - { - if (new_key->keyval != element->keyval) - { - return FALSE; - } - } - else if (element->keyval != 0 || new_key->keycode != element->keycode) - { - return FALSE; - } - - new_key->editable = FALSE; - new_key->mateconf_key = element->mateconf_key; - new_key->description = element->description; - new_key->desc_mateconf_key = element->desc_mateconf_key; - new_key->desc_editable = element->desc_editable; - - return TRUE; + KeyEntry* element; + + gtk_tree_model_get (new_key->model, iter, + KEYENTRY_COLUMN, &element, + -1); + + /* no conflict for : blanks, different modifiers, or ourselves */ + if (element == NULL || new_key->mask != element->mask) + { + return FALSE; + } + + gchar *new_key_schema = NULL; + gchar *element_schema = NULL; + gchar *new_key_path = NULL; + gchar *element_path = NULL; + + /* FIXME GLIB_CHECK_VERSION for < 2.32 */ + if (new_key && new_key->settings) + { + #if GLIB_CHECK_VERSION (2, 32, 0) + g_object_get (new_key->settings, "schema-id", &new_key_schema, NULL); + #else + g_object_get (new_key->settings, "schema", &new_key_schema, NULL); + #endif + g_object_get (new_key->settings, "path", &new_key_path, NULL); + } + + if (element->settings) + { + #if GLIB_CHECK_VERSION (2, 32, 0) + g_object_get (element->settings, "schema-id", &element_schema, NULL); + #else + g_object_get (element->settings, "schema", &element_schema, NULL); + #endif + g_object_get (element->settings, "path", &element_path, NULL); + } + + if (!g_strcmp0 (new_key->gsettings_key, element->gsettings_key) && + !g_strcmp0 (new_key_schema, element_schema) && + !g_strcmp0 (new_key_path, element_path)) + { + return FALSE; + } + + if (new_key->keyval != 0) + { + if (new_key->keyval != element->keyval) + { + return FALSE; + } + } + else if (element->keyval != 0 || new_key->keycode != element->keycode) + { + return FALSE; + } + + new_key->editable = FALSE; + new_key->settings = element->settings; + new_key->gsettings_key = element->gsettings_key; + new_key->description = element->description; + new_key->desc_gsettings_key = element->desc_gsettings_key; + new_key->desc_editable = element->desc_editable; + + return TRUE; } static const guint forbidden_keyvals[] = { - /* Navigation keys */ - GDK_Home, - GDK_Left, - GDK_Up, - GDK_Right, - GDK_Down, - GDK_Page_Up, - GDK_Page_Down, - GDK_End, - GDK_Tab, - - /* Return */ - GDK_KP_Enter, - GDK_Return, - - GDK_space, - GDK_Mode_switch + /* Navigation keys */ + GDK_Home, + GDK_Left, + GDK_Up, + GDK_Right, + GDK_Down, + GDK_Page_Up, + GDK_Page_Down, + GDK_End, + GDK_Tab, + + /* Return */ + GDK_KP_Enter, + GDK_Return, + + GDK_space, + GDK_Mode_switch }; static gboolean keyval_is_forbidden(guint keyval) { - guint i; + guint i; - for (i = 0; i < G_N_ELEMENTS(forbidden_keyvals); i++) - { - if (keyval == forbidden_keyvals[i]) - { - return TRUE; - } - } + for (i = 0; i < G_N_ELEMENTS(forbidden_keyvals); i++) + { + if (keyval == forbidden_keyvals[i]) + { + return TRUE; + } + } - return FALSE; + return FALSE; } static void show_error(GtkWindow* parent, GError* err) @@ -1101,10 +1201,10 @@ static void show_error(GtkWindow* parent, GError* err) GtkWidget *dialog; dialog = gtk_message_dialog_new (parent, - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK, - _("Error saving the new shortcut")); + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + _("Error saving the new shortcut")); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", err->message); @@ -1114,203 +1214,165 @@ static void show_error(GtkWindow* parent, GError* err) static void accel_edited_callback(GtkCellRendererText* cell, const char* path_string, guint keyval, EggVirtualModifierType mask, guint keycode, gpointer data) { - MateConfClient* client; - GtkTreeView* view = (GtkTreeView*) data; - GtkTreeModel* model; - GtkTreePath* path = gtk_tree_path_new_from_string (path_string); - GtkTreeIter iter; - KeyEntry* key_entry, tmp_key; - GError* err = NULL; - char* str; + GtkTreeView* view = (GtkTreeView*) data; + GtkTreeModel* model; + GtkTreePath* path = gtk_tree_path_new_from_string (path_string); + GtkTreeIter iter; + KeyEntry* key_entry, tmp_key; + char* str; + + block_accels = FALSE; + + model = gtk_tree_view_get_model (view); + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_path_free (path); + gtk_tree_model_get (model, &iter, + KEYENTRY_COLUMN, &key_entry, + -1); - block_accels = FALSE; + /* sanity check */ + if (key_entry == NULL) + { + return; + } - model = gtk_tree_view_get_model (view); - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_path_free (path); - gtk_tree_model_get (model, &iter, - KEYENTRY_COLUMN, &key_entry, - -1); - - /* sanity check */ - if (key_entry == NULL) - { - return; - } - - /* CapsLock isn't supported as a keybinding modifier, so keep it from confusing us */ - mask &= ~EGG_VIRTUAL_LOCK_MASK; - - tmp_key.model = model; - tmp_key.keyval = keyval; - tmp_key.keycode = keycode; - tmp_key.mask = mask; - tmp_key.mateconf_key = key_entry->mateconf_key; - tmp_key.description = NULL; - tmp_key.editable = TRUE; /* kludge to stuff in a return flag */ - - if (keyval != 0 || keycode != 0) /* any number of keys can be disabled */ - { - gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc) cb_check_for_uniqueness, &tmp_key); - } - - /* Check for unmodified keys */ - if (tmp_key.mask == 0 && tmp_key.keycode != 0) + /* CapsLock isn't supported as a keybinding modifier, so keep it from confusing us */ + mask &= ~EGG_VIRTUAL_LOCK_MASK; + + tmp_key.model = model; + tmp_key.keyval = keyval; + tmp_key.keycode = keycode; + tmp_key.mask = mask; + tmp_key.settings = key_entry->settings; + tmp_key.gsettings_key = key_entry->gsettings_key; + tmp_key.description = NULL; + tmp_key.editable = TRUE; /* kludge to stuff in a return flag */ + + if (keyval != 0 || keycode != 0) /* any number of keys can be disabled */ + { + gtk_tree_model_foreach(model, (GtkTreeModelForeachFunc) cb_check_for_uniqueness, &tmp_key); + } + + /* Check for unmodified keys */ + if (tmp_key.mask == 0 && tmp_key.keycode != 0) + { + if ((tmp_key.keyval >= GDK_a && tmp_key.keyval <= GDK_z) + || (tmp_key.keyval >= GDK_A && tmp_key.keyval <= GDK_Z) + || (tmp_key.keyval >= GDK_0 && tmp_key.keyval <= GDK_9) + || (tmp_key.keyval >= GDK_kana_fullstop && tmp_key.keyval <= GDK_semivoicedsound) + || (tmp_key.keyval >= GDK_Arabic_comma && tmp_key.keyval <= GDK_Arabic_sukun) + || (tmp_key.keyval >= GDK_Serbian_dje && tmp_key.keyval <= GDK_Cyrillic_HARDSIGN) + || (tmp_key.keyval >= GDK_Greek_ALPHAaccent && tmp_key.keyval <= GDK_Greek_omega) + || (tmp_key.keyval >= GDK_hebrew_doublelowline && tmp_key.keyval <= GDK_hebrew_taf) + || (tmp_key.keyval >= GDK_Thai_kokai && tmp_key.keyval <= GDK_Thai_lekkao) + || (tmp_key.keyval >= GDK_Hangul && tmp_key.keyval <= GDK_Hangul_Special) + || (tmp_key.keyval >= GDK_Hangul_Kiyeog && tmp_key.keyval <= GDK_Hangul_J_YeorinHieuh) + || keyval_is_forbidden (tmp_key.keyval)) + { + + GtkWidget *dialog; + char *name; + + name = binding_name (keyval, keycode, mask, TRUE); + + dialog = gtk_message_dialog_new ( + GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_CANCEL, + _("The shortcut \"%s\" cannot be used because it will become impossible to type using this key.\n" + "Please try with a key such as Control, Alt or Shift at the same time."), + name); + + g_free (name); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + /* set it back to its previous value. */ + egg_cell_renderer_keys_set_accelerator( + EGG_CELL_RENDERER_KEYS(cell), + key_entry->keyval, + key_entry->keycode, + key_entry->mask); + return; + } + } + + /* flag to see if the new accelerator was in use by something */ + if (!tmp_key.editable) { - if ((tmp_key.keyval >= GDK_a && tmp_key.keyval <= GDK_z) - || (tmp_key.keyval >= GDK_A && tmp_key.keyval <= GDK_Z) - || (tmp_key.keyval >= GDK_0 && tmp_key.keyval <= GDK_9) - || (tmp_key.keyval >= GDK_kana_fullstop && tmp_key.keyval <= GDK_semivoicedsound) - || (tmp_key.keyval >= GDK_Arabic_comma && tmp_key.keyval <= GDK_Arabic_sukun) - || (tmp_key.keyval >= GDK_Serbian_dje && tmp_key.keyval <= GDK_Cyrillic_HARDSIGN) - || (tmp_key.keyval >= GDK_Greek_ALPHAaccent && tmp_key.keyval <= GDK_Greek_omega) - || (tmp_key.keyval >= GDK_hebrew_doublelowline && tmp_key.keyval <= GDK_hebrew_taf) - || (tmp_key.keyval >= GDK_Thai_kokai && tmp_key.keyval <= GDK_Thai_lekkao) - || (tmp_key.keyval >= GDK_Hangul && tmp_key.keyval <= GDK_Hangul_Special) - || (tmp_key.keyval >= GDK_Hangul_Kiyeog && tmp_key.keyval <= GDK_Hangul_J_YeorinHieuh) - || keyval_is_forbidden (tmp_key.keyval)) - { - - GtkWidget *dialog; - char *name; - - name = binding_name (keyval, keycode, mask, TRUE); - - dialog = gtk_message_dialog_new ( - GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_CANCEL, - _("The shortcut \"%s\" cannot be used because it will become impossible to type using this key.\n" - "Please try with a key such as Control, Alt or Shift at the same time."), - name); - - g_free (name); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - - /* set it back to its previous value. */ - egg_cell_renderer_keys_set_accelerator( - EGG_CELL_RENDERER_KEYS(cell), - key_entry->keyval, - key_entry->keycode, - key_entry->mask); - return; - } - } - - /* flag to see if the new accelerator was in use by something */ - if (!tmp_key.editable) - { - GtkWidget* dialog; - char* name; - int response; - - name = binding_name(keyval, keycode, mask, TRUE); - - dialog = gtk_message_dialog_new( - GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))), - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_CANCEL, - _("The shortcut \"%s\" is already used for\n\"%s\""), - name, - tmp_key.description ? tmp_key.description : tmp_key.mateconf_key); - g_free (name); - - gtk_message_dialog_format_secondary_text ( - GTK_MESSAGE_DIALOG (dialog), - _("If you reassign the shortcut to \"%s\", the \"%s\" shortcut " - "will be disabled."), - key_entry->description ? key_entry->description : key_entry->mateconf_key, - tmp_key.description ? tmp_key.description : tmp_key.mateconf_key); - - gtk_dialog_add_button(GTK_DIALOG (dialog), _("_Reassign"), GTK_RESPONSE_ACCEPT); - - gtk_dialog_set_default_response(GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); - - response = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - - if (response == GTK_RESPONSE_ACCEPT) - { - MateConfClient* client; - - client = mateconf_client_get_default (); - - mateconf_client_set_string( - client, - tmp_key.mateconf_key, - "", - &err); - - if (err != NULL) - { - show_error(GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), err); - g_error_free (err); - g_object_unref (client); - return; - } - - str = binding_name (keyval, keycode, mask, FALSE); - mateconf_client_set_string (client, key_entry->mateconf_key, str, &err); - - if (err != NULL) - { - show_error (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), err); - g_error_free (err); - - /* reset the previous shortcut */ - mateconf_client_set_string (client, tmp_key.mateconf_key, str, NULL); - } - - g_free (str); - g_object_unref (client); - } - else - { - /* set it back to its previous value. */ - egg_cell_renderer_keys_set_accelerator( - EGG_CELL_RENDERER_KEYS(cell), - key_entry->keyval, - key_entry->keycode, - key_entry->mask); - } - - return; - } - - str = binding_name (keyval, keycode, mask, FALSE); - - client = mateconf_client_get_default (); - mateconf_client_set_string( - client, - key_entry->mateconf_key, - str, - &err); - - g_free (str); - g_object_unref (client); - - if (err != NULL) - { - show_error (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), err); - g_error_free (err); - key_entry->editable = FALSE; - } + GtkWidget* dialog; + char* name; + int response; + + name = binding_name(keyval, keycode, mask, TRUE); + + dialog = gtk_message_dialog_new( + GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_CANCEL, + _("The shortcut \"%s\" is already used for\n\"%s\""), + name, + tmp_key.description ? tmp_key.description : tmp_key.gsettings_key); + g_free (name); + + gtk_message_dialog_format_secondary_text ( + GTK_MESSAGE_DIALOG (dialog), + _("If you reassign the shortcut to \"%s\", the \"%s\" shortcut " + "will be disabled."), + key_entry->description ? key_entry->description : key_entry->gsettings_key, + tmp_key.description ? tmp_key.description : tmp_key.gsettings_key); + + gtk_dialog_add_button(GTK_DIALOG (dialog), _("_Reassign"), GTK_RESPONSE_ACCEPT); + + gtk_dialog_set_default_response(GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); + + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + if (response == GTK_RESPONSE_ACCEPT) + { + g_settings_set_string (tmp_key.settings, tmp_key.gsettings_key, ""); + + str = binding_name (keyval, keycode, mask, FALSE); + g_settings_set_string (key_entry->settings, key_entry->gsettings_key, str); + + g_free (str); + } + else + { + /* set it back to its previous value. */ + egg_cell_renderer_keys_set_accelerator( + EGG_CELL_RENDERER_KEYS(cell), + key_entry->keyval, + key_entry->keycode, + key_entry->mask); + } + + return; + } + + str = binding_name (keyval, keycode, mask, FALSE); + + g_settings_set_string( + key_entry->settings, + key_entry->gsettings_key, + str); + + g_free (str); + } static void accel_cleared_callback (GtkCellRendererText *cell, - const char *path_string, - gpointer data) + const char *path_string, + gpointer data) { - MateConfClient *client; GtkTreeView *view = (GtkTreeView *) data; GtkTreePath *path = gtk_tree_path_new_from_string (path_string); KeyEntry *key_entry; GtkTreeIter iter; - GError *err = NULL; GtkTreeModel *model; block_accels = FALSE; @@ -1319,37 +1381,17 @@ accel_cleared_callback (GtkCellRendererText *cell, gtk_tree_model_get_iter (model, &iter, path); gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, - KEYENTRY_COLUMN, &key_entry, - -1); + KEYENTRY_COLUMN, &key_entry, + -1); /* sanity check */ if (key_entry == NULL) return; /* Unset the key */ - client = mateconf_client_get_default(); - mateconf_client_set_string (client, - key_entry->mateconf_key, - "", - &err); - g_object_unref (client); - - if (err != NULL) - { - GtkWidget *dialog; - - dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))), - GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK, - _("Error unsetting accelerator in configuration database: %s"), - err->message); - gtk_dialog_run (GTK_DIALOG (dialog)); - - gtk_widget_destroy (dialog); - g_error_free (err); - key_entry->editable = FALSE; - } + g_settings_set_string (key_entry->settings, + key_entry->gsettings_key, + ""); } static void @@ -1358,7 +1400,6 @@ description_edited_callback (GtkCellRendererText *renderer, gchar *new_text, gpointer user_data) { - MateConfClient *client; GtkTreeView *view = GTK_TREE_VIEW (user_data); GtkTreeModel *model; GtkTreePath *path = gtk_tree_path_new_from_string (path_string); @@ -1370,18 +1411,15 @@ description_edited_callback (GtkCellRendererText *renderer, gtk_tree_path_free (path); gtk_tree_model_get (model, &iter, - KEYENTRY_COLUMN, &key_entry, - -1); + KEYENTRY_COLUMN, &key_entry, + -1); /* sanity check */ - if (key_entry == NULL || key_entry->desc_mateconf_key == NULL) + if (key_entry == NULL || key_entry->desc_gsettings_key == NULL) return; - client = mateconf_client_get_default (); - if (!mateconf_client_set_string (client, key_entry->desc_mateconf_key, new_text, NULL)) + if (!g_settings_set_string (key_entry->settings, key_entry->desc_gsettings_key, new_text)) key_entry->desc_editable = FALSE; - - g_object_unref (client); } @@ -1397,9 +1435,9 @@ real_start_editing_cb (IdleData *idle_data) { gtk_widget_grab_focus (GTK_WIDGET (idle_data->tree_view)); gtk_tree_view_set_cursor (idle_data->tree_view, - idle_data->path, - idle_data->column, - TRUE); + idle_data->path, + idle_data->column, + TRUE); gtk_tree_path_free (idle_data->path); g_free (idle_data); return FALSE; @@ -1445,8 +1483,6 @@ static gboolean remove_custom_shortcut (GtkTreeModel *model, GtkTreeIter *iter) { GtkTreeIter parent; - MateConfClient *client; - gchar *base; KeyEntry *key; gtk_tree_model_get (model, iter, @@ -1457,28 +1493,21 @@ remove_custom_shortcut (GtkTreeModel *model, GtkTreeIter *iter) if (key->command == NULL) return FALSE; - client = mateconf_client_get_default (); - - mateconf_client_notify_remove (client, key->mateconf_cnxn); - if (key->mateconf_cnxn_desc != 0) - mateconf_client_notify_remove (client, key->mateconf_cnxn_desc); - if (key->mateconf_cnxn_cmd != 0) - mateconf_client_notify_remove (client, key->mateconf_cnxn_cmd); + g_signal_handler_disconnect (key->settings, key->gsettings_cnxn); + if (key->gsettings_cnxn_desc != 0) + g_signal_handler_disconnect (key->settings, key->gsettings_cnxn_desc); + if (key->gsettings_cnxn_cmd != 0) + g_signal_handler_disconnect (key->settings, key->gsettings_cnxn_cmd); - base = g_path_get_dirname (key->mateconf_key); - mateconf_client_recursive_unset (client, base, 0, NULL); - g_free (base); - /* suggest sync now so the unset directory actually gets dropped; - * if we don't do this we may end up with 'zombie' shortcuts when - * restarting the app */ - mateconf_client_suggest_sync (client, NULL); - g_object_unref (client); + dconf_util_recursive_reset (key->gsettings_path, NULL); + g_object_unref (key->settings); - g_free (key->mateconf_key); + g_free (key->gsettings_path); + g_free (key->gsettings_key); g_free (key->description); - g_free (key->desc_mateconf_key); + g_free (key->desc_gsettings_key); g_free (key->command); - g_free (key->cmd_mateconf_key); + g_free (key->cmd_gsettings_key); g_free (key); gtk_tree_model_iter_parent (model, &parent, iter); @@ -1505,40 +1534,47 @@ update_custom_shortcut (GtkTreeModel *model, GtkTreeIter *iter) } else { - MateConfClient *client; - gtk_tree_store_set (GTK_TREE_STORE (model), iter, - KEYENTRY_COLUMN, key, -1); - client = mateconf_client_get_default (); + KEYENTRY_COLUMN, key, -1); if (key->description != NULL) - mateconf_client_set_string (client, key->desc_mateconf_key, key->description, NULL); + g_settings_set_string (key->settings, key->desc_gsettings_key, key->description); else - mateconf_client_unset (client, key->desc_mateconf_key, NULL); - mateconf_client_set_string (client, key->cmd_mateconf_key, key->command, NULL); - g_object_unref (client); + g_settings_reset (key->settings, key->desc_gsettings_key); + g_settings_set_string (key->settings, key->cmd_gsettings_key, key->command); } } static gchar * -find_free_mateconf_key (GError **error) +find_free_gsettings_path (GError **error) { - MateConfClient *client; - - gchar *dir; + gchar **existing_dirs; + gchar *dir = NULL; + gchar *fulldir = NULL; int i; + int j; + gboolean found; - client = mateconf_client_get_default (); + existing_dirs = dconf_util_list_subdirs (GSETTINGS_KEYBINDINGS_DIR, FALSE); for (i = 0; i < MAX_CUSTOM_SHORTCUTS; i++) { - dir = g_strdup_printf ("%s/custom%d", MATECONF_BINDING_DIR, i); - if (!mateconf_client_dir_exists (client, dir, NULL)) - break; - g_free (dir); + found = TRUE; + dir = g_strdup_printf ("custom%d/", i); + for (j = 0; existing_dirs[j] != NULL; j++) + if (!g_strcmp0(dir, existing_dirs[j])) + { + found = FALSE; + g_free (dir); + break; + } + if (found) + break; } + g_strfreev (existing_dirs); if (i == MAX_CUSTOM_SHORTCUTS) { + g_free (dir); dir = NULL; g_set_error_literal (error, g_quark_from_string ("Keyboard Shortcuts"), @@ -1546,9 +1582,9 @@ find_free_mateconf_key (GError **error) _("Too many custom shortcuts")); } - g_object_unref (client); - - return dir; + fulldir = g_strdup_printf ("%s%s", GSETTINGS_KEYBINDINGS_DIR, dir); + g_free (dir); + return fulldir; } static void @@ -1560,11 +1596,10 @@ add_custom_shortcut (GtkTreeView *tree_view, GtkTreeIter parent_iter; GtkTreePath *path; gchar *dir; - MateConfClient *client; GError *error; error = NULL; - dir = find_free_mateconf_key (&error); + dir = find_free_gsettings_path (&error); if (dir == NULL) { show_error (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tree_view))), error); @@ -1574,13 +1609,14 @@ add_custom_shortcut (GtkTreeView *tree_view, } key_entry = g_new0 (KeyEntry, 1); - key_entry->mateconf_key = g_strconcat (dir, "/binding", NULL); + key_entry->gsettings_path = g_strdup(dir); + key_entry->gsettings_key = g_strdup("binding"); key_entry->editable = TRUE; key_entry->model = model; - key_entry->desc_mateconf_key = g_strconcat (dir, "/name", NULL); + key_entry->desc_gsettings_key = g_strdup("name"); key_entry->description = g_strdup (""); key_entry->desc_editable = TRUE; - key_entry->cmd_mateconf_key = g_strconcat (dir, "/action", NULL); + key_entry->cmd_gsettings_key = g_strdup("action"); key_entry->command = g_strdup (""); key_entry->cmd_editable = TRUE; g_free (dir); @@ -1593,28 +1629,25 @@ add_custom_shortcut (GtkTreeView *tree_view, gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent_iter); gtk_tree_store_set (GTK_TREE_STORE (model), &iter, KEYENTRY_COLUMN, key_entry, -1); - /* store in mateconf */ - client = mateconf_client_get_default (); - mateconf_client_set_string (client, key_entry->mateconf_key, "", NULL); - mateconf_client_set_string (client, key_entry->desc_mateconf_key, key_entry->description, NULL); - mateconf_client_set_string (client, key_entry->cmd_mateconf_key, key_entry->command, NULL); - - /* add mateconf watches */ - key_entry->mateconf_cnxn_desc = mateconf_client_notify_add (client, - key_entry->desc_mateconf_key, - (MateConfClientNotifyFunc) &keybinding_description_changed, - key_entry, NULL, NULL); - key_entry->mateconf_cnxn_cmd = mateconf_client_notify_add (client, - key_entry->cmd_mateconf_key, - (MateConfClientNotifyFunc) &keybinding_command_changed, - key_entry, NULL, NULL); - key_entry->mateconf_cnxn = mateconf_client_notify_add (client, - key_entry->mateconf_key, - (MateConfClientNotifyFunc) &keybinding_key_changed, - key_entry, NULL, NULL); - - - g_object_unref (client); + /* store in gsettings */ + key_entry->settings = g_settings_new_with_path (CUSTOM_KEYBINDING_SCHEMA, key_entry->gsettings_path); + g_settings_set_string (key_entry->settings, key_entry->gsettings_key, ""); + g_settings_set_string (key_entry->settings, key_entry->desc_gsettings_key, key_entry->description); + g_settings_set_string (key_entry->settings, key_entry->cmd_gsettings_key, key_entry->command); + + /* add gsettings watches */ + key_entry->gsettings_cnxn_desc = g_signal_connect (key_entry->settings, + "changed::name", + G_CALLBACK (keybinding_description_changed), + key_entry); + key_entry->gsettings_cnxn_cmd = g_signal_connect (key_entry->settings, + "changed::action", + G_CALLBACK (keybinding_command_changed), + key_entry); + key_entry->gsettings_cnxn = g_signal_connect (key_entry->settings, + "changed::binding", + G_CALLBACK (keybinding_key_changed), + key_entry); /* make the new shortcut visible */ path = gtk_tree_model_get_path (model, &iter); @@ -1624,20 +1657,21 @@ add_custom_shortcut (GtkTreeView *tree_view, } else { - g_free (key_entry->mateconf_key); + g_free (key_entry->gsettings_path); + g_free (key_entry->gsettings_key); g_free (key_entry->description); - g_free (key_entry->desc_mateconf_key); + g_free (key_entry->desc_gsettings_key); g_free (key_entry->command); - g_free (key_entry->cmd_mateconf_key); + g_free (key_entry->cmd_gsettings_key); g_free (key_entry); } } static void start_editing_kb_cb (GtkTreeView *treeview, - GtkTreePath *path, - GtkTreeViewColumn *column, - gpointer user_data) + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; @@ -1651,13 +1685,13 @@ start_editing_kb_cb (GtkTreeView *treeview, if (key == NULL) { - /* This is a section heading - expand or collapse */ - if (gtk_tree_view_row_expanded (treeview, path)) - gtk_tree_view_collapse_row (treeview, path); - else - gtk_tree_view_expand_row (treeview, path, FALSE); + /* This is a section heading - expand or collapse */ + if (gtk_tree_view_row_expanded (treeview, path)) + gtk_tree_view_collapse_row (treeview, path); + else + gtk_tree_view_expand_row (treeview, path, FALSE); return; - } + } /* if only the accel can be edited on the selected row * always select the accel column */ @@ -1682,8 +1716,8 @@ start_editing_kb_cb (GtkTreeView *treeview, static gboolean start_editing_cb (GtkTreeView *tree_view, - GdkEventButton *event, - gpointer user_data) + GdkEventButton *event, + gpointer user_data) { GtkTreePath *path; GtkTreeViewColumn *column; @@ -1692,10 +1726,10 @@ start_editing_cb (GtkTreeView *tree_view, return FALSE; if (gtk_tree_view_get_path_at_pos (tree_view, - (gint) event->x, - (gint) event->y, - &path, &column, - NULL, NULL)) + (gint) event->x, + (gint) event->y, + &path, &column, + NULL, NULL)) { IdleData *idle_data; GtkTreeModel *model; @@ -1703,10 +1737,10 @@ start_editing_cb (GtkTreeView *tree_view, KeyEntry *key; if (gtk_tree_path_get_depth (path) == 1) - { - gtk_tree_path_free (path); - return FALSE; - } + { + gtk_tree_path_free (path); + return FALSE; + } model = gtk_tree_view_get_model (tree_view); gtk_tree_model_get_iter (model, &iter, path); @@ -1745,12 +1779,12 @@ start_editing_cb (GtkTreeView *tree_view, * of the widgets */ static gboolean maybe_block_accels(GtkWidget* widget, GdkEventKey* event, gpointer user_data) { - if (block_accels) - { - return gtk_window_propagate_key_event(GTK_WINDOW(widget), event); - } + if (block_accels) + { + return gtk_window_propagate_key_event(GTK_WINDOW(widget), event); + } - return FALSE; + return FALSE; } static void @@ -1804,32 +1838,30 @@ selection_changed (GtkTreeSelection *selection, gpointer data) { gtk_tree_model_get (model, &iter, KEYENTRY_COLUMN, &key, -1); if (key && key->command != NULL && key->editable) - can_remove = TRUE; + can_remove = TRUE; } gtk_widget_set_sensitive (button, can_remove); } static void -setup_dialog (GtkBuilder *builder) +setup_dialog (GtkBuilder *builder, GSettings *marco_settings) { - MateConfClient *client; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkWidget *widget; GtkTreeView *treeview; GtkTreeSelection *selection; - GSList *allowed_keys; + GSettings *keybindings_settings; + gchar **allowed_keys; treeview = GTK_TREE_VIEW (gtk_builder_get_object (builder, "shortcut_treeview")); - client = mateconf_client_get_default (); - g_signal_connect (treeview, "button_press_event", - G_CALLBACK (start_editing_cb), builder); + G_CALLBACK (start_editing_cb), builder); g_signal_connect (treeview, "row-activated", - G_CALLBACK (start_editing_kb_cb), NULL); + G_CALLBACK (start_editing_kb_cb), NULL); renderer = gtk_cell_renderer_text_new (); @@ -1838,9 +1870,9 @@ setup_dialog (GtkBuilder *builder) treeview); column = gtk_tree_view_column_new_with_attributes (_("Action"), - renderer, - "text", DESCRIPTION_COLUMN, - NULL); + renderer, + "text", DESCRIPTION_COLUMN, + NULL); gtk_tree_view_column_set_cell_data_func (column, renderer, description_set_func, NULL, NULL); gtk_tree_view_column_set_resizable (column, FALSE); @@ -1848,8 +1880,8 @@ setup_dialog (GtkBuilder *builder) gtk_tree_view_column_set_sort_column_id (column, DESCRIPTION_COLUMN); renderer = (GtkCellRenderer *) g_object_new (EGG_TYPE_CELL_RENDERER_KEYS, - "accel_mode", EGG_CELL_RENDERER_KEYS_MODE_X, - NULL); + "accel_mode", EGG_CELL_RENDERER_KEYS_MODE_X, + NULL); g_signal_connect (renderer, "accel_edited", G_CALLBACK (accel_edited_callback), @@ -1866,12 +1898,10 @@ setup_dialog (GtkBuilder *builder) gtk_tree_view_append_column (treeview, column); gtk_tree_view_column_set_sort_column_id (column, KEYENTRY_COLUMN); - mateconf_client_add_dir (client, MATECONF_BINDING_DIR, MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL); - mateconf_client_add_dir (client, "/apps/marco/general", MATECONF_CLIENT_PRELOAD_ONELEVEL, NULL); - mateconf_client_notify_add (client, - "/apps/marco/general/num_workspaces", - (MateConfClientNotifyFunc) key_entry_controlling_key_changed, - builder, NULL, NULL); + g_signal_connect (marco_settings, + "changed::num-workspaces", + G_CALLBACK (key_entry_controlling_key_changed), + builder); /* set up the dialog */ reload_key_entries (builder); @@ -1886,21 +1916,17 @@ setup_dialog (GtkBuilder *builder) selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); g_signal_connect (selection, "changed", G_CALLBACK (selection_changed), - _gtk_builder_get_widget (builder, "remove-button")); + _gtk_builder_get_widget (builder, "remove-button")); - allowed_keys = mateconf_client_get_list (client, - MATECONF_BINDING_DIR "/allowed_keys", - MATECONF_VALUE_STRING, - NULL); - if (allowed_keys != NULL) + keybindings_settings = g_settings_new ("org.mate.keybindings"); + allowed_keys = g_settings_get_strv (keybindings_settings, "allowed-keys"); + if (allowed_keys != NULL && allowed_keys[0] != NULL) { - g_slist_foreach (allowed_keys, (GFunc)g_free, NULL); - g_slist_free (allowed_keys); + g_strfreev (allowed_keys); gtk_widget_set_sensitive (_gtk_builder_get_widget (builder, "add-button"), FALSE); } - - g_object_unref (client); + g_object_unref (keybindings_settings); /* setup the custom shortcut dialog */ custom_shortcut_dialog = _gtk_builder_get_widget (builder, @@ -1910,7 +1936,7 @@ setup_dialog (GtkBuilder *builder) custom_shortcut_command_entry = _gtk_builder_get_widget (builder, "custom-shortcut-command-entry"); gtk_dialog_set_default_response (GTK_DIALOG (custom_shortcut_dialog), - GTK_RESPONSE_OK); + GTK_RESPONSE_OK); gtk_window_set_transient_for (GTK_WINDOW (custom_shortcut_dialog), GTK_WINDOW (widget)); } @@ -1925,6 +1951,7 @@ int main (int argc, char *argv[]) { GtkBuilder *builder; + GSettings *marco_settings; g_thread_init (NULL); gtk_init (&argc, &argv); @@ -1943,10 +1970,14 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); wm_common_register_window_manager_change ((GFunc) on_window_manager_change, builder); - setup_dialog (builder); + + marco_settings = g_settings_new ("org.mate.Marco.general"); + + setup_dialog (builder, marco_settings); gtk_main (); + g_object_unref (marco_settings); g_object_unref (builder); return 0; } -- cgit v1.2.1