diff options
Diffstat (limited to 'lib/egg/egg-accel-dialog.c')
-rw-r--r-- | lib/egg/egg-accel-dialog.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/lib/egg/egg-accel-dialog.c b/lib/egg/egg-accel-dialog.c new file mode 100644 index 000000000..4173cbf02 --- /dev/null +++ b/lib/egg/egg-accel-dialog.c @@ -0,0 +1,332 @@ +#include "egg-accel-dialog.h" + +static void egg_accel_dialog_init (EggAccelDialog *self); +static void egg_accel_dialog_class_init (EggAccelDialogClass *class); + +GType +egg_accel_dialog_get_type (void) +{ + static GtkType type = 0; + + if (!type) + { + static const GTypeInfo type_info = + { + sizeof (EggAccelDialogClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) egg_accel_dialog_class_init, + (GClassFinalizeFunc) NULL, + NULL, + + sizeof (EggAccelDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) egg_accel_dialog_init, + }; + + type = g_type_register_static (GTK_TYPE_DIALOG, + "EggAccelDialog", + &type_info, 0); + } + return type; +} + +static void +egg_accel_dialog_class_init (EggAccelDialogClass *class) +{ +} + +static void accel_path_selection_changed (GtkTreeSelection *selection, + EggAccelDialog *self); +static void accel_path_set (GtkWidget *button, EggAccelDialog *self); +static void accel_path_reset (GtkWidget *button, EggAccelDialog *self); + +static void +egg_accel_dialog_init (EggAccelDialog *self) +{ + GtkCellRenderer *renderer; + GtkWidget *swin; + GtkWidget *table; + + /* set up the list store for all the accelerators */ + self->accel_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->accel_store), + 0, GTK_SORT_ASCENDING); + egg_accel_dialog_rescan_accels (self); + + + swin = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (self)->vbox), swin, + TRUE, TRUE, 0); + gtk_widget_show (swin); + + /* set up a two column view of the model in browse selection mode */ + self->accel_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(self->accel_store)); + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (self->accel_view), TRUE); + gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (self->accel_view)), + GTK_SELECTION_BROWSE); + g_signal_connect_object (gtk_tree_view_get_selection (GTK_TREE_VIEW (self->accel_view)), + "changed", G_CALLBACK (accel_path_selection_changed), + G_OBJECT (self), 0); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (G_OBJECT (renderer), "xalign", 0.0, NULL); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->accel_view), + -1, "Path", renderer, + "text", 0, + NULL); + gtk_tree_view_column_set_sort_column_id (gtk_tree_view_get_column (GTK_TREE_VIEW (self->accel_view), 0), 0); + + renderer = gtk_cell_renderer_text_new (); + g_object_set (G_OBJECT (renderer), "xalign", 0.0, NULL); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (self->accel_view), + -1, "Accel", renderer, + "text", 1, + NULL); + gtk_tree_view_column_set_sort_column_id (gtk_tree_view_get_column (GTK_TREE_VIEW (self->accel_view), 1), 1); + + gtk_container_add (GTK_CONTAINER (swin), self->accel_view); + gtk_widget_show (self->accel_view); + + table = gtk_table_new (2, 4, FALSE); + gtk_container_set_border_width (GTK_CONTAINER (table), 2); + gtk_table_set_row_spacings (GTK_TABLE (table), 2); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (self)->vbox), table, FALSE,TRUE, 0); + gtk_widget_show (table); + + /* widgets for editing accels */ + self->shift_toggle = gtk_check_button_new_with_mnemonic ("S_hift"); + gtk_table_attach (GTK_TABLE (table), self->shift_toggle, + 0, 1, 0, 1, + GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (self->shift_toggle); + self->ctrl_toggle = gtk_check_button_new_with_mnemonic ("_Ctrl"); + gtk_table_attach (GTK_TABLE (table), self->ctrl_toggle, + 1, 2, 0, 1, + GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (self->ctrl_toggle); + self->alt_toggle = gtk_check_button_new_with_mnemonic ("_Alt"); + gtk_table_attach (GTK_TABLE (table), self->alt_toggle, + 2, 3, 0, 1, + GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (self->alt_toggle); + self->key_entry = gtk_entry_new (); + gtk_table_attach (GTK_TABLE (table), self->key_entry, + 0, 3, 1, 2, + GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0); + gtk_widget_show (self->key_entry); + + /* buttons for changing path */ + self->set_button = gtk_button_new_with_mnemonic ("_Set"); + gtk_table_attach (GTK_TABLE (table), self->set_button, + 3, 4, 0, 1, + GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (self->set_button); + self->reset_button = gtk_button_new_with_mnemonic ("_Reset"); + gtk_table_attach (GTK_TABLE (table), self->reset_button, + 3, 4, 1, 2, + GTK_FILL, GTK_FILL, 0, 0); + /*gtk_widget_show (self->reset_button);*/ + + g_signal_connect_object (self->set_button, "clicked", + G_CALLBACK (accel_path_set), G_OBJECT (self), 0); + g_signal_connect_object (self->reset_button, "clicked", + G_CALLBACK (accel_path_reset), G_OBJECT (self), 0); + + + self->ok_button = gtk_dialog_add_button (GTK_DIALOG (self), + GTK_STOCK_OK, + GTK_RESPONSE_OK); + gtk_widget_grab_default (self->ok_button); +} + +static void +accel_map_foreach (gpointer data, + const gchar *accel_path, + guint accel_key, + guint accel_mods, + gboolean changed) +{ + EggAccelDialog *self = data; + GtkTreeIter iter; + gchar *accel_name; + + gtk_list_store_append (self->accel_store, &iter); + if (accel_key != 0) + accel_name = gtk_accelerator_name (accel_key, accel_mods); + else + accel_name = ""; + + gtk_list_store_set (self->accel_store, &iter, + 0, accel_path, + 1, accel_name, + -1); + if (accel_key != 0) + g_free(accel_name); +} + +void +egg_accel_dialog_rescan_accels (EggAccelDialog *self) +{ + g_return_if_fail (EGG_IS_ACCEL_DIALOG (self)); + + gtk_list_store_clear (self->accel_store); + gtk_accel_map_foreach (self, accel_map_foreach); +} + +/* make sure the currently selected accel is up to date */ +static void +refresh_selected_row (EggAccelDialog *self) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + + g_return_if_fail (EGG_IS_ACCEL_DIALOG (self)); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->accel_view)); + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { + char *accel_path; + + /* get the accel path for the selected row */ + gtk_tree_model_get (GTK_TREE_MODEL (self->accel_store), &iter, + 0, &accel_path, -1); + if (accel_path) { + GtkAccelKey key; + + if (gtk_accel_map_lookup_entry (accel_path, &key)) { + char *accel_name; + + accel_name = gtk_accelerator_name (key.accel_key, key.accel_mods); + gtk_list_store_set (self->accel_store, &iter, 1, accel_name, -1); + g_free (accel_name); + } + g_free (accel_path); + } + } +} + +static void +accel_path_selection_changed (GtkTreeSelection *selection, + EggAccelDialog *self) +{ + GtkTreeIter iter; + + /* just make sure the selected row is up to date */ + refresh_selected_row (self); + + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { + char *accel_path; + + /* get the accel path for the selected row */ + gtk_tree_model_get (GTK_TREE_MODEL (self->accel_store), &iter, + 0, &accel_path, -1); + if (accel_path) { + GtkAccelKey key; + + if (gtk_accel_map_lookup_entry (accel_path, &key)) { + gchar *keyname; + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->shift_toggle), + (key.accel_mods & GDK_SHIFT_MASK)!=0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->ctrl_toggle), + (key.accel_mods & GDK_CONTROL_MASK)!=0); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->alt_toggle), + (key.accel_mods & GDK_MOD1_MASK)!=0); + keyname = gdk_keyval_name (key.accel_key); + if (keyname) + gtk_entry_set_text (GTK_ENTRY (self->key_entry), keyname); + else + gtk_entry_set_text (GTK_ENTRY (self->key_entry), ""); + } + } + g_free (accel_path); + } +} + +static void +accel_path_set (GtkWidget *button, EggAccelDialog *self) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + gboolean changed = FALSE; + + g_return_if_fail (EGG_IS_ACCEL_DIALOG (self)); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->accel_view)); + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { + char *accel_path; + + /* get the accel path for the selected row */ + gtk_tree_model_get (GTK_TREE_MODEL (self->accel_store), &iter, + 0, &accel_path, -1); + if (accel_path) { + GdkModifierType accel_mods = 0; + const gchar *key_name; + guint accel_key = 0; + + /* get modifiers */ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(self->shift_toggle))) + accel_mods |= GDK_SHIFT_MASK; + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(self->ctrl_toggle))) + accel_mods |= GDK_CONTROL_MASK; + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(self->alt_toggle))) + accel_mods |= GDK_MOD1_MASK; + + key_name = gtk_entry_get_text (GTK_ENTRY (self->key_entry)); + /* check to see if entyr is empty -- if so, unset accel */ + if (key_name[0] != '\0') { + accel_key = gdk_keyval_from_name (key_name); + + if (accel_key) { + changed = gtk_accel_map_change_entry (accel_path, + accel_key, accel_mods, + TRUE); + } + } else + changed = gtk_accel_map_change_entry (accel_path, 0, 0, TRUE); + + g_free (accel_path); + } + } + if (!changed) + gdk_beep (); + accel_path_selection_changed (selection, self); +} + +static void +accel_path_reset (GtkWidget *button, EggAccelDialog *self) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + gboolean changed = FALSE; + + g_return_if_fail (EGG_IS_ACCEL_DIALOG (self)); + + g_message ("don't know how to reset to defaults :("); + return; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->accel_view)); + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { + char *accel_path; + + /* get the accel path for the selected row */ + gtk_tree_model_get (GTK_TREE_MODEL (self->accel_store), &iter, + 0, &accel_path, -1); + if (accel_path) { + changed = gtk_accel_map_change_entry (accel_path, 0, 0, TRUE); + g_free (accel_path); + } + } + if (!changed) + gdk_beep (); + accel_path_selection_changed (selection, self); +} + +GtkWidget * +egg_accel_dialog_new (void) +{ + return g_object_new(EGG_TYPE_ACCEL_DIALOG, NULL); +} |