Re: Patch for Delete key behavior (for dia-0.96.1) - save/load accels



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 20:47:32.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,15 @@
   { "SelectInverse", NULL, N_("Inverse"), NULL, NULL, SELECT_INVERT }
 };
 
+/** Group name in menurc file for the accelerators */
+static gchar user_accel_group[] = "UserAccels";
+/** Struct for the accel saving iterator */
+struct _accel_struct
+{
+  GKeyFile* keyfile;
+  gint bindno;
+};
+
 /* need initialisation? */
 static gboolean initialise = TRUE;
 
@@ -295,16 +307,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)
+{
+  struct _accel_struct* acs = (struct _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;
+  struct _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 +609,6 @@
   DiaCallbackFilter    *cbf;
   GtkActionGroup       *plugin_actions;
   GtkAction            *action;
-  gchar                *accelfilename;
   GList                *cblist;
   guint                 id;
   GError               *error = NULL;
@@ -594,13 +736,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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]