aboutsummaryrefslogtreecommitdiffstats
path: root/lib/egg/egg-accel-dialog.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/egg/egg-accel-dialog.c')
-rw-r--r--lib/egg/egg-accel-dialog.c332
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);
+}