[Gnucash-changes] r12027 - gnucash/trunk - Rewrite the code that assigns accelerator keys to the names of menu

David Hampton hampton at cvs.gnucash.org
Thu Nov 24 01:16:38 EST 2005


Author: hampton
Date: 2005-11-24 01:16:37 -0500 (Thu, 24 Nov 2005)
New Revision: 12027
Trac: http://svn.gnucash.org/trac/changeset/12027

Modified:
   gnucash/trunk/ChangeLog
   gnucash/trunk/src/gnome-utils/gnc-menu-extensions.c
   gnucash/trunk/src/gnome-utils/gnc-menu-extensions.h
   gnucash/trunk/src/gnome-utils/gnc-menu-extensions.scm
   gnucash/trunk/src/gnome-utils/gnc-plugin-menu-additions.c
   gnucash/trunk/src/gnome-utils/gnome-utils.scm
   gnucash/trunk/src/report/report-gnome/report-gnome.scm
Log:
Rewrite the code that assigns accelerator keys to the names of menu
extensions.  The new C language implementation is now called as late
as possible (when menus are populated), and rewritten understands utf8
strings.  The code now also translates the menu extension path
components as it goes so that sub-menus will appear properly in
non-English languages.


Modified: gnucash/trunk/ChangeLog
===================================================================
--- gnucash/trunk/ChangeLog	2005-11-23 23:28:44 UTC (rev 12026)
+++ gnucash/trunk/ChangeLog	2005-11-24 06:16:37 UTC (rev 12027)
@@ -1,5 +1,18 @@
 2005-11-23  David Hampton  <hampton at employees.org>
 
+	* src/report/report-gnome/report-gnome.scm:
+	* src/gnome-utils/gnc-menu-extensions.c:
+	* src/gnome-utils/gnc-menu-extensions.h:
+	* src/gnome-utils/gnc-plugin-menu-additions.c:
+	* src/gnome-utils/gnome-utils.scm:
+	* src/gnome-utils/gnc-menu-extensions.scm: Rewrite the code that
+	assigns accelerator keys to the names of menu extensions.  The new
+	C language implementation is now called as late as possible (when
+	menus are populated), and rewritten understands utf8 strings.  The
+	code now also translates the menu extension path components as it
+	goes so that sub-menus will appear properly in non-English
+	languages.
+
 	* src/gnome-utils/ui/gnc-main-window-ui.xml:
 	* src/gnome-utils/gnc-main-window.c:
 	* src/gnome/top-level.c: Restore long lost functionality to

Modified: gnucash/trunk/src/gnome-utils/gnc-menu-extensions.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-menu-extensions.c	2005-11-23 23:28:44 UTC (rev 12026)
+++ gnucash/trunk/src/gnome-utils/gnc-menu-extensions.c	2005-11-24 06:16:37 UTC (rev 12027)
@@ -149,7 +149,10 @@
 
     if (SCM_STRINGP(item))
     {
-      strings[i] = g_strdup(SCM_STRING_CHARS(item));
+      if (i == 1)
+	strings[i] = g_strdup(SCM_STRING_CHARS(item));
+      else
+	strings[i] = g_strdup(gettext(SCM_STRING_CHARS(item)));
     }
     else
     {
@@ -219,6 +222,7 @@
 {
   ExtensionInfo *ext_info;
   gchar *typeStr, *tmp;
+  const gchar *name;
 
   ext_info = g_new0(ExtensionInfo, 1);
   ext_info->extension = extension;
@@ -230,8 +234,9 @@
   }
 
   /* Get all the pieces */
-  ext_info->ae.label = gnc_extension_name(extension);
-  ext_info->ae.name = gnc_ext_gen_action_name(ext_info->ae.label);
+  name = gnc_extension_name(extension);
+  ext_info->ae.label = g_strdup(gettext(name));
+  ext_info->ae.name = gnc_ext_gen_action_name(name);
   ext_info->ae.tooltip = gnc_extension_documentation(extension);
   ext_info->ae.stock_id = "";
   ext_info->ae.accelerator = NULL;

Modified: gnucash/trunk/src/gnome-utils/gnc-menu-extensions.h
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-menu-extensions.h	2005-11-23 23:28:44 UTC (rev 12026)
+++ gnucash/trunk/src/gnome-utils/gnc-menu-extensions.h	2005-11-24 06:16:37 UTC (rev 12027)
@@ -34,6 +34,7 @@
   gchar *sort_key;
   const gchar *typeStr;
   GtkUIManagerItemType type;
+  gboolean accel_assigned;
 } ExtensionInfo;
 
 

Modified: gnucash/trunk/src/gnome-utils/gnc-menu-extensions.scm
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-menu-extensions.scm	2005-11-23 23:28:44 UTC (rev 12026)
+++ gnucash/trunk/src/gnome-utils/gnc-menu-extensions.scm	2005-11-24 06:16:37 UTC (rev 12027)
@@ -63,42 +63,3 @@
 (if (gnc:debugging?)
     (gnc:hook-add-dangler gnc:*ui-startup-hook*
                           gnc:extensions-menu-setup))
-
-;; Automatically pick accelerators for menu names
-(define (gnc:new-menu-namer)
-
-  (define letter-hash (make-hash-table 23))
-  (define name-hash (make-hash-table 23))
-
-  (define (add-name raw-name)
-    (let* ((name (_ raw-name))
-           (length (string-length name)))
-
-      (define (try-at-k k)
-        (if (>= k length)
-            (begin
-              (hash-set! name-hash raw-name name)
-              name)
-            (let* ((char (char-upcase (string-ref name k)))
-                   (used (hash-ref letter-hash char)))
-              (if (not used)
-                  (let ((new-name (string-append
-                                   (substring name 0 k)
-                                   "_"
-                                   (substring name k length))))
-                    (hash-set! letter-hash char #t)
-                    (hash-set! name-hash raw-name new-name)
-                    new-name)
-                  (try-at-k (+ k 1))))))
-
-      (try-at-k 0)))
-
-  (define (lookup name)
-    (hash-ref name-hash name))
-
-  (define (dispatch key)
-    (case key
-      ((add-name) add-name)
-      ((lookup) lookup)))
-
-  dispatch)

Modified: gnucash/trunk/src/gnome-utils/gnc-plugin-menu-additions.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-plugin-menu-additions.c	2005-11-23 23:28:44 UTC (rev 12026)
+++ gnucash/trunk/src/gnome-utils/gnc-plugin-menu-additions.c	2005-11-24 06:16:37 UTC (rev 12027)
@@ -62,7 +62,6 @@
 /* This static indicates the debugging module that this .o belongs to.  */
 static QofLogModule log_module = GNC_MOD_GUI;
 
-
 #define PLUGIN_ACTIONS_NAME "gnc-plugin-menu-additions-actions"
 
 /** Private data for this plugin.  This data structure is unused. */
@@ -244,6 +243,140 @@
 }
 
 
+/** Initialize the hash table of accelerator key maps.
+ *
+ *  @param unused Unused.
+ *
+ *  @return an empty hash table. */
+static gpointer
+gnc_menu_additions_init_accel_table (gpointer unused)
+{
+  return g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+}
+
+
+/** Examine an extension menu item and see if it already has an
+ *  accelerator key defined (in the source).  If so, add this key to
+ *  the map of already used accelerator keys.  These maps are
+ *  maintained per path, so accelerator keys may be duplicated across
+ *  different menus but are guaranteed to be unique within any given
+ *  menu.
+ *
+ *  @param info A menu extension.
+ *
+ *  @param table A hash table of accelerator maps. */
+static void
+gnc_menu_additions_do_preassigned_accel (ExtensionInfo *info, GHashTable *table)
+{
+  gchar *map, *new_map, *accel_key;
+  const gchar *ptr;
+
+  ENTER("Checking %s/%s [%s]", info->path, info->ae.label, info->ae.name);
+  if (info->accel_assigned) {
+    LEAVE("Already processed");
+    return;
+  }
+
+  if (!g_utf8_validate(info->ae.label, -1, NULL)) {
+    g_warning("Extension menu label '%s' is not valid utf8.", info->ae.label);
+    info->accel_assigned = TRUE;
+    LEAVE("Label is invalid utf8");
+    return;
+  }
+
+  /* Was an accelerator pre-assigned in the source? */
+  ptr = g_utf8_strchr(info->ae.label, -1, '_');
+  if (ptr == NULL) {
+    LEAVE("not preassigned");
+    return;
+  }
+
+  accel_key = g_utf8_strdown(g_utf8_next_char(ptr), 1);
+  DEBUG("Accelerator preassigned: '%s'", accel_key);
+
+  /* Now build a new map. Old one freed automatically. */
+  map = g_hash_table_lookup(table, info->path);
+  if (map == NULL)
+    map = "";
+  new_map = g_strconcat(map, accel_key, (gchar *)NULL);
+  DEBUG("path '%s', map '%s' -> '%s'", info->path, map, new_map);
+  g_hash_table_replace(table, info->path, new_map);
+
+  info->accel_assigned = TRUE;
+  g_free(accel_key);
+  LEAVE("preassigned");
+}
+
+
+/** Examine an extension menu item and see if it needs to have an
+ *  accelerator key assigned to it.  If so, find the first character
+ *  in the menu name that isn't already assigned as an accelerator in
+ *  the same menu, assign it to this item, and add it to the map of
+ *  already used accelerator keys.  These maps are maintained per
+ *  path, so accelerator keys may be duplicated across different menus
+ *  but are guaranteed to be unique within any given menu.
+ *
+ *  @param info A menu extension.
+ *
+ *  @param table A hash table of accelerator maps. */
+static void
+gnc_menu_additions_assign_accel (ExtensionInfo *info, GHashTable *table)
+{
+  gchar *map, *new_map, *new_label, *start, buf[16];
+  const gchar *ptr;
+  gunichar uni;
+  gint len;
+
+  ENTER("Checking %s/%s [%s]", info->path, info->ae.label, info->ae.name);
+  if (info->accel_assigned) {
+    LEAVE("Already processed");
+    return;
+  }
+
+  /* Get map of used keys */
+  map = g_hash_table_lookup(table, info->path);
+  if (map == NULL)
+    map = g_strdup("");
+  DEBUG("map '%s', path %s", map, info->path);
+
+  for (ptr = info->ae.label; *ptr; ptr = g_utf8_next_char(ptr)) {
+    uni = g_utf8_get_char(ptr);
+    if (!g_unichar_isalpha(uni))
+      continue;
+    uni = g_unichar_tolower(uni);
+    len = g_unichar_to_utf8(uni, buf);
+    buf[len] = '\0';
+    DEBUG("Testing character '%s'", buf);
+    if (!g_utf8_strchr(map, -1, uni))
+      break;
+  }
+
+  if (ptr == NULL) {
+    /* Ran out of characters. Nothing to do. */
+    info->accel_assigned = TRUE;
+    LEAVE("All characters already assigned");
+    return;
+  }
+
+  /* Now build a new string in the form "<start>_<end>". */
+  start = g_strndup(info->ae.label, ptr - info->ae.label);
+  DEBUG("start %p, len %ld, text '%s'", start, g_utf8_strlen(start, -1), start);
+  new_label = g_strconcat(start, "_", ptr, (gchar *)NULL);
+  g_free(start);
+  DEBUG("label '%s' -> '%s'", info->ae.label, new_label);
+  g_free((gchar *)info->ae.label);
+  info->ae.label = new_label;
+
+  /* Now build a new map. Old one freed automatically. */
+  new_map = g_strconcat(map, buf, (gchar *)NULL);
+  DEBUG("map '%s' -> '%s'", map, new_map);
+  g_hash_table_replace(table, info->path, new_map);
+
+  info->accel_assigned = TRUE;
+  LEAVE("assigned");
+}
+
+
 /** Add one extension item to the UI manager.  This function creates a
  *  per-callback data structure for easy access to the opaque Scheme
  *  data block in the callback.  It then adds the action to the UI
@@ -296,6 +429,8 @@
 					 GQuark type)
 {
   GncPluginMenuAdditionsPerWindow per_window;
+  static GOnce accel_table_init = G_ONCE_INIT;
+  static GHashTable *table;
   GSList *menu_list;
 
   ENTER(" ");
@@ -309,6 +444,14 @@
 
   menu_list = g_slist_sort(gnc_extensions_get_menu_list(),
 			   (GCompareFunc)gnc_menu_additions_alpha_sort);
+
+  /* Assign accelerators */
+  table = g_once(&accel_table_init, gnc_menu_additions_init_accel_table, NULL);
+  g_slist_foreach(menu_list,
+		  (GFunc)gnc_menu_additions_do_preassigned_accel, table);
+  g_slist_foreach(menu_list, (GFunc)gnc_menu_additions_assign_accel, table);
+
+  /* Add to window. */
   g_slist_foreach(menu_list, (GFunc)gnc_menu_additions_menu_setup_one,
 		  &per_window);
 

Modified: gnucash/trunk/src/gnome-utils/gnome-utils.scm
===================================================================
--- gnucash/trunk/src/gnome-utils/gnome-utils.scm	2005-11-23 23:28:44 UTC (rev 12026)
+++ gnucash/trunk/src/gnome-utils/gnome-utils.scm	2005-11-24 06:16:37 UTC (rev 12027)
@@ -15,7 +15,6 @@
 (export gnc:make-menu-item)
 (export gnc:make-menu)
 (export gnc:make-separator)
-(export gnc:new-menu-namer)
 (re-export gnc:*add-extension-hook*)
 
 (export gnc:kvp-option-dialog)

Modified: gnucash/trunk/src/report/report-gnome/report-gnome.scm
===================================================================
--- gnucash/trunk/src/report/report-gnome/report-gnome.scm	2005-11-23 23:28:44 UTC (rev 12026)
+++ gnucash/trunk/src/report/report-gnome/report-gnome.scm	2005-11-24 06:16:37 UTC (rev 12027)
@@ -46,7 +46,6 @@
               (gnc:warning-dialog #f (_ "This report has no options.")))))))
 
 (define (gnc:add-report-template-menu-items)
-  (define menu-namer (gnc:new-menu-namer))
   (define *template-items* '())
 
   (define (add-template-menu-item name template)
@@ -72,7 +71,7 @@
 
           (set! item
                 (gnc:make-menu-item
-                 ((menu-namer 'add-name) name)
+                 name
                  menu-tip
                  menu-path
                  (lambda (window)
@@ -96,7 +95,6 @@
    (sort *template-items* sort-templates)))
 
 (define (gnc:report-menu-setup)
-  (define menu-namer (gnc:new-menu-namer))
   (define asset-liability-menu
     (gnc:make-menu gnc:menuname-asset-liability (list gnc:menuname-reports)))
   (define income-expense-menu



More information about the gnucash-changes mailing list