40 #include "swig-runtime.h" 41 #include "guile-mappings.h" 47 #include "gnc-menu-extensions.h" 50 static void gnc_plugin_menu_additions_finalize (GObject *
object);
52 static void gnc_plugin_menu_additions_add_to_window (GncPlugin *plugin,
GncMainWindow *window, GQuark type);
53 static void gnc_plugin_menu_additions_remove_from_window (GncPlugin *plugin,
GncMainWindow *window, GQuark type);
54 static void gnc_plugin_menu_additions_action_new_cb (GSimpleAction *simple, GVariant *parameter, gpointer user_data);
59 static QofLogModule log_module = GNC_MOD_GUI;
61 #define PLUGIN_ACTIONS_NAME "gnc-plugin-menu-additions-actions" 67 GHashTable *item_hash;
72 typedef struct _GncPluginMenuAdditionsPerWindow
78 GHashTable *build_menu_hash;
85 static GActionEntry gnc_plugin_actions [] =
87 {
"AdditionsAction", gnc_plugin_menu_additions_action_new_cb,
"s", NULL, NULL },
90 static guint gnc_plugin_n_actions = G_N_ELEMENTS(gnc_plugin_actions);
96 G_DEFINE_TYPE(GncPluginMenuAdditions, gnc_plugin_menu_additions, GNC_TYPE_PLUGIN)
99 gnc_plugin_menu_additions_class_init (GncPluginMenuAdditionsClass *klass)
101 GObjectClass *object_class = G_OBJECT_CLASS (klass);
102 GncPluginClass *plugin_class = GNC_PLUGIN_CLASS (klass);
104 object_class->finalize = gnc_plugin_menu_additions_finalize;
107 plugin_class->plugin_name = GNC_PLUGIN_MENU_ADDITIONS_NAME;
110 plugin_class->add_to_window = gnc_plugin_menu_additions_add_to_window;
111 plugin_class->remove_from_window = gnc_plugin_menu_additions_remove_from_window;
113 plugin_class->actions = gnc_plugin_actions;
114 plugin_class->n_actions = gnc_plugin_n_actions;
118 gnc_plugin_menu_additions_init (GncPluginMenuAdditions *plugin)
120 ENTER(
"plugin %p", plugin);
125 gnc_plugin_menu_additions_finalize (GObject *
object)
127 g_return_if_fail (GNC_IS_PLUGIN_MENU_ADDITIONS(
object));
129 ENTER(
"plugin %p",
object);
131 g_hash_table_destroy (GNC_PLUGIN_MENU_ADDITIONS(
object)->item_hash);
133 G_OBJECT_CLASS (gnc_plugin_menu_additions_parent_class)->finalize (
object);
146 GncPlugin *plugin_page = NULL;
149 plugin_page = GNC_PLUGIN (g_object_new (GNC_TYPE_PLUGIN_MENU_ADDITIONS, NULL));
150 LEAVE(
"plugin %p", plugin_page);
161 static swig_type_info * main_window_type = NULL;
166 if (!main_window_type)
167 main_window_type = SWIG_TypeQuery(
"_p_GncMainWindow");
169 return SWIG_NewPointerObj(window, main_window_type, 0);
173 gnc_plugin_menu_additions_action_new_cb (GSimpleAction *simple,
179 const gchar *action_name;
181 g_return_if_fail (G_IS_SIMPLE_ACTION(simple));
185 action_name = g_variant_get_string (parameter, &length);
187 PINFO(
"action name is '%s'", action_name);
190 GncPluginMenuAdditions *plugin = GNC_PLUGIN_MENU_ADDITIONS(cb_data->data);
191 extension = g_hash_table_lookup (plugin->item_hash, action_name);
195 PINFO(
"Found action in table");
196 gnc_extension_invoke_cb (extension, gnc_main_window_to_scm (cb_data->window));
216 if (a->type == b->type)
217 return strcmp(a->sort_key, b->sort_key);
218 else if (a->type == GNC_SUB_MENU_ITEM)
220 else if (b->type == GNC_SUB_MENU_ITEM)
233 gnc_menu_additions_init_accel_table (gpointer unused)
235 return g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
252 gchar *map, *new_map, *accel_key;
255 ENTER(
"Checking %s/%s [%s]", info->path, info->action_label, info->action_name);
256 if (info->accel_assigned)
258 LEAVE(
"Already processed");
262 if (!g_utf8_validate(info->action_label, -1, NULL))
264 g_warning (
"Extension menu label '%s' is not valid utf8.", info->action_label);
265 info->accel_assigned = TRUE;
266 LEAVE(
"Label is invalid utf8");
271 ptr = g_utf8_strchr (info->action_label, -1,
'_');
274 LEAVE(
"not preassigned");
278 accel_key = g_utf8_strdown(g_utf8_next_char(ptr), 1);
279 DEBUG(
"Accelerator preassigned: '%s'", accel_key);
282 map = g_hash_table_lookup(
table, info->path);
285 new_map = g_strconcat(map, accel_key, (gchar *)NULL);
286 DEBUG(
"path '%s', map '%s' -> '%s'", info->path, map, new_map);
287 g_hash_table_replace(
table, info->path, new_map);
289 info->accel_assigned = TRUE;
291 LEAVE(
"preassigned");
309 gchar *map, *new_map, *new_label, *start, buf[16];
313 gboolean map_allocated = FALSE;
315 ENTER(
"Checking %s/%s [%s]", info->path, info->action_label, info->action_name);
316 if (info->accel_assigned)
318 LEAVE(
"Already processed");
323 map = g_hash_table_lookup(
table, info->path);
327 map_allocated = TRUE;
329 DEBUG(
"map '%s', path %s", map, info->path);
331 for (ptr = info->action_label; *ptr; ptr = g_utf8_next_char(ptr))
333 uni = g_utf8_get_char(ptr);
334 if (!g_unichar_isalpha(uni))
336 uni = g_unichar_tolower(uni);
337 len = g_unichar_to_utf8(uni, buf);
339 DEBUG(
"Testing character '%s'", buf);
340 if (!g_utf8_strchr(map, -1, uni))
347 info->accel_assigned = TRUE;
352 LEAVE(
"All characters already assigned");
357 start = g_strndup (info->action_label, ptr - info->action_label);
358 DEBUG(
"start %p, len %ld, text '%s'", start, g_utf8_strlen(start, -1), start);
359 new_label = g_strconcat(start,
"_", ptr, (gchar *)NULL);
361 DEBUG(
"label '%s' -> '%s'", info->action_label, new_label);
362 g_free((gchar *)info->action_label);
363 info->action_label = new_label;
366 new_map = g_strconcat(map, buf, (gchar *)NULL);
367 DEBUG(
"map '%s' -> '%s'", map, new_map);
368 g_hash_table_replace(
table, info->path, new_map);
370 info->accel_assigned = TRUE;
381 GMenuItem *gmenu_item = NULL;
383 if (g_strcmp0 (ext_info->typeStr,
"menuitem") == 0)
385 gmenu_item = g_menu_item_new (ext_info->action_label, NULL);
386 g_menu_item_set_action_and_target_value (gmenu_item,
"gnc-plugin-menu-additions-actions.AdditionsAction",
387 g_variant_new_string (ext_info->action_name));
389 g_menu_item_set_attribute (gmenu_item, GNC_MENU_ATTRIBUTE_TOOLTIP,
"s", ext_info->action_tooltip);
392 if (g_strcmp0 (ext_info->typeStr,
"menu") == 0)
394 GMenuModel *sub_menu = G_MENU_MODEL(g_menu_new ());
396 gmenu_item = g_menu_item_new_submenu (ext_info->action_label, sub_menu);
397 g_object_set_data (G_OBJECT(gmenu_item),
"sub-menu", sub_menu);
415 GMenuItem *item_path, *item_with_full_path;
416 gchar *full_path = NULL;
417 GMenuItem *gmenu_item = NULL;
419 DEBUG(
"Adding %s/%s [%s] as [%s]", ext_info->path, ext_info->action_label,
420 ext_info->action_name, ext_info->typeStr );
422 g_hash_table_insert (per_window->
item_hash, g_strdup (ext_info->action_name), ext_info->extension);
424 if (g_str_has_suffix (ext_info->path, _(
"_Custom")))
427 full_path = g_strconcat (ext_info->path,
"/", ext_info->action_label, NULL);
429 item_path = g_hash_table_lookup (per_window->build_menu_hash, ext_info->path);
430 item_with_full_path = g_hash_table_lookup (per_window->build_menu_hash, full_path);
432 if (!item_path && !item_with_full_path)
434 gmenu_item = setup_gmenu_item_with_tooltip (ext_info);
436 g_menu_append_item (G_MENU(per_window->report_menu), gmenu_item);
439 if (item_path && !item_with_full_path)
441 GMenuModel *sub_menu = G_MENU_MODEL(g_object_get_data (G_OBJECT(item_path),
"sub-menu"));
443 gmenu_item = setup_gmenu_item_with_tooltip (ext_info);
445 g_menu_append_item (G_MENU(sub_menu), gmenu_item);
447 g_hash_table_insert (per_window->build_menu_hash, g_strdup (full_path), gmenu_item);
466 gnc_plugin_menu_additions_add_to_window (GncPlugin *plugin,
471 static GOnce accel_table_init = G_ONCE_INIT;
472 static GHashTable *
table;
475 GncMenuModelSearch *gsm = g_new0 (GncMenuModelSearch, 1);
479 GncPluginMenuAdditions *menu_plugin = GNC_PLUGIN_MENU_ADDITIONS (plugin);
480 if (!menu_plugin->item_hash)
481 menu_plugin->item_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
483 per_window.
item_hash = menu_plugin->item_hash;
484 per_window.build_menu_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
485 per_window.report_menu = g_menu_new ();
487 menu_list = g_slist_sort (gnc_extensions_get_menu_list(),
488 (GCompareFunc)gnc_menu_additions_sort);
491 table = g_once (&accel_table_init, gnc_menu_additions_init_accel_table, NULL);
492 g_slist_foreach (menu_list,
493 (GFunc)gnc_menu_additions_do_preassigned_accel,
table);
494 g_slist_foreach (menu_list, (GFunc)gnc_menu_additions_assign_accel,
table);
497 g_slist_foreach (menu_list, (GFunc)gnc_menu_additions_menu_setup_one,
501 gsm->search_action_label = NULL;
502 gsm->search_action_name =
"ReportsPlaceholder0";
503 gsm->search_action_target = NULL;
507 g_menu_insert_section (G_MENU(gsm->model), gsm->index, NULL, G_MENU_MODEL(per_window.report_menu));
510 PERR(
"Could not find 'ReportsAction' in menu model");
512 g_hash_table_destroy (per_window.build_menu_hash);
514 g_slist_free (menu_list);
534 gnc_plugin_menu_additions_remove_from_window (GncPlugin *plugin,
538 GSimpleActionGroup *simple_action_group;
546 if (simple_action_group && !window->just_plugin_prefs)
#define PINFO(format, args...)
Print an informational note.
GMenuModel * gnc_main_window_get_menu_model(GncMainWindow *window)
Return the GMenuModel for the main window menu bar.
gboolean gnc_menubar_model_find_item(GMenuModel *menu_model, GncMenuModelSearch *gsm)
Find a GtkMenu item from the action name.
#define DEBUG(format, args...)
Print a debugging message.
Functions that are supported by all types of windows.
#define PERR(format, args...)
Log a serious error.
#define ENTER(format, args...)
Print a function entry debugging message.
All type declarations for the whole Gnucash engine.
#define PLUGIN_ACTIONS_NAME
The label given to the main window for this plugin.
#define LEAVE(format, args...)
Print a function exit debugging message.
GSimpleActionGroup * gnc_main_window_get_action_group(GncMainWindow *window, const gchar *group_name)
Retrieve a specific set of user interface actions from a window.
The instance data structure for a main window object.