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

Reply via email to