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
[email protected]
http://mail.gnome.org/mailman/listinfo/dia-list
FAQ at http://live.gnome.org/Dia/Faq
Main page at http://live.gnome.org/Dia