Just a minor fix for the patch - consting a static string + one typedef. Ondrej Mikle wrote: > Hans Breuer wrote: >> A patch to fix the broken user editable shortcuts should give you the same >> workaround but not break the use of Delete for diagram editing for other >> users. It would have a much bigger chance for inclusion. >> > > I send a patch that makes the saving and loading of accel keys work. The > accel keys are stored in the old menurc file ($HOME/.dia/menurc), but > the file has different format (the glib key-file - > http://library.gnome.org/devel/glib/2.12/glib-Key-value-file-parser.html), > perhaps you may wish to change the name of the file. > > A sample line: > > binding43=<Actions>/display-actions/EditDelete;Delete; > > So you can keep the default Delete key for EditDelete action or user can > change it to whatever (e.g. <Control>Delete). Having a dialog for > shorcuts would be even nicer, but AFAIK gtk does not have a widget for > grabbing shortcuts (and GtkEntry wouldn't be that nice). > > I tested it on linux, but it should work on other platforms as well, > since I used the platform-independent glib functions (also I tried to > keep the style&indenting same as the rest of the code). > > File is read upon startup and actual bindings are written upon exit (so > if e.g. the mentioned shortcut dialog would change the accels run-time, > they would be saved). > > Cheers, > O. Mikle > > >
diff -aur dia2/dia-0.96.1/app/menus.c dia-0.96.1/app/menus.c --- dia2/dia-0.96.1/app/menus.c 2007-03-04 21:39:24.000000000 +0100 +++ dia-0.96.1/app/menus.c 2007-09-25 21:24:34.000000000 +0200 @@ -24,6 +24,9 @@ #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> #include <string.h> +#include <glib.h> +#include <glib/gprintf.h> +#include <glib/gstdio.h> #include "intl.h" #include "menus.h" @@ -235,6 +238,16 @@ { "SelectInverse", NULL, N_("Inverse"), NULL, NULL, SELECT_INVERT } }; +/** Group name in menurc file for the accelerators */ +static const gchar user_accel_group[] = "UserAccels"; +/** Struct for the accel saving iterator */ +struct _accel_struct +{ + GKeyFile* keyfile; + gint bindno; +}; +typedef struct _accel_struct accel_struct; + /* need initialisation? */ static gboolean initialise = TRUE; @@ -295,16 +308,147 @@ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooldata->widget),TRUE); } -static gint -save_accels(gpointer data) +/** + * GtkAccelMapForeach function to save each accelerator. Used by + * menus_save_user_accels. + * + * @param data non-NULL pointer to accel_struct holding the keyfile and current + * binding number + * + * Rest of the parameters - see GtkAccelMapForeach in gtk manual + */ +static void +menus_save_each_accel (gpointer data, + const gchar *accel_path, + guint accel_key, + GdkModifierType accel_mods, + gboolean changed) +{ + accel_struct* acs = (accel_struct*)data; + + gchar *accel_str = gtk_accelerator_name (accel_key, accel_mods); + const gchar *accel_pair[] = {accel_path, (accel_str) ? accel_str : ""}; + + /* name of the key is not really important, we just need some unique keys */ + gchar *key_str = g_malloc (10+(acs->bindno/10)); + g_sprintf(key_str, "binding%d", acs->bindno); + + g_key_file_set_string_list (acs->keyfile, user_accel_group, key_str, accel_pair, 2); + g_free (accel_str); + g_free (key_str); + acs->bindno++; +} + +/** + * Loads user defined accelerator keys from config file. + * + * @return TRUE iff the loading succeeded - file was readable and in the right format + */ +static gboolean +menus_load_user_accels () { - gchar *accelfilename; + GError *err = NULL; + GKeyFile* keyfile = g_key_file_new (); + gboolean res; + gchar **keys, **acclist; + gsize keycount, listsize, i; + gchar *accelfname = dia_config_filename("menurc"); + GdkModifierType mods; + guint acc; + + res = g_key_file_load_from_file (keyfile, accelfname, G_KEY_FILE_NONE, NULL); + if (!res) return FALSE; /* file may not yet exist etc. */ - accelfilename = dia_config_filename("menurc"); - if (accelfilename) { - gtk_accel_map_save (accelfilename); - g_free (accelfilename); + keys = g_key_file_get_keys(keyfile, user_accel_group, &keycount, &err); + if (err) + { + g_message ("Error loading shortcut keys from %s: %s", accelfname, + err->message); + g_error_free (err); + g_key_file_free (keyfile); + g_free (accelfname); + return FALSE; } + + /* get each key, get the accel path, accel string, parse it, set it */ + for (i=0; i<keycount; i++) + { + acclist = g_key_file_get_string_list (keyfile, user_accel_group, keys[i], + &listsize, NULL); + if (!acclist) continue; + if (listsize < 2) /* list too short, we need accel path and accel string */ + { + g_strfreev (acclist); + continue; + } + + gtk_accelerator_parse(acclist[1], &acc, &mods); + gtk_accel_map_change_entry(acclist[0], acc, mods, TRUE); + g_strfreev (acclist); + } + + g_strfreev (keys); + g_key_file_free (keyfile); + g_free (accelfname); + + return TRUE; +} + +/** + * Saves all current accelerators to given file name. Format is the key=value glib + * format. + * + * @return TRUE iff the saving was successful + */ +static gboolean +menus_save_user_accels () +{ + gchar *filedata; + gsize filelen; + accel_struct acs; + GError *err = NULL; + gchar *accelfname; + + GKeyFile* keyfile = g_key_file_new (); + + if (!keyfile) + { + g_warning("keyfile pointer is NULL"); + + return FALSE; + } + + acs.bindno = 0; + acs.keyfile = keyfile; + + g_key_file_set_list_separator (keyfile, ';'); + gtk_accel_map_foreach ((gpointer)&acs, &menus_save_each_accel); + g_key_file_set_comment (keyfile, NULL, NULL, + "Auto-generated shortcut list. Will be read upon Dia start. Modify the shortcuts if you wish to.", + NULL); + filedata = g_key_file_to_data (keyfile, &filelen, &err); + if (err) + { + g_message("Error converting shortcuts data: %s", err->message); + g_key_file_free (keyfile); + g_error_free (err); + return FALSE; + } + + accelfname = dia_config_filename("menurc"); + g_file_set_contents(accelfname, filedata, filelen, &err); + g_key_file_free (keyfile); + g_free (filedata); + if (err) + { + g_message ("Error writing shortcut keys file %s: %s", accelfname, err->message); + g_error_free (err); + g_free (accelfname); + return FALSE; + } + + g_free (accelfname); + return TRUE; } @@ -466,7 +610,6 @@ DiaCallbackFilter *cbf; GtkActionGroup *plugin_actions; GtkAction *action; - gchar *accelfilename; GList *cblist; guint id; GError *error = NULL; @@ -594,13 +737,8 @@ add_plugin_actions (display_ui_manager); /* load accelerators and prepare to later save them */ - accelfilename = dia_config_filename("menurc"); - - if (accelfilename) { - gtk_accel_map_load(accelfilename); - g_free(accelfilename); - } - gtk_quit_add(1, save_accels, NULL); + menus_load_user_accels (); + gtk_quit_add(1, &menus_save_user_accels, NULL); } void
_______________________________________________ Dia-list mailing list Dia-list@gnome.org http://mail.gnome.org/mailman/listinfo/dia-list FAQ at http://live.gnome.org/Dia/Faq Main page at http://live.gnome.org/Dia