#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 GType 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);
}