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);
159 gnc_main_window_to_scm (GncMainWindow *window)
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);
364 if (info->type == GNC_SUB_MENU_ITEM)
365 info->action_label_original = g_strdup (info->action_label);
367 g_free((gchar *)info->action_label);
368 info->action_label = new_label;
371 new_map = g_strconcat(map, buf, (gchar *)NULL);
372 DEBUG(
"map '%s' -> '%s'", map, new_map);
373 g_hash_table_replace(
table, info->path, new_map);
375 info->accel_assigned = TRUE;
386 GMenuItem *gmenu_item = NULL;
388 if (g_strcmp0 (ext_info->typeStr,
"menuitem") == 0)
390 gmenu_item = g_menu_item_new (ext_info->action_label, NULL);
391 g_menu_item_set_action_and_target_value (gmenu_item,
"gnc-plugin-menu-additions-actions.AdditionsAction",
392 g_variant_new_string (ext_info->action_name));
394 g_menu_item_set_attribute (gmenu_item, GNC_MENU_ATTRIBUTE_TOOLTIP,
"s", ext_info->action_tooltip);
397 if (g_strcmp0 (ext_info->typeStr,
"menu") == 0)
399 GMenuModel *sub_menu = G_MENU_MODEL(g_menu_new ());
401 gmenu_item = g_menu_item_new_submenu (ext_info->action_label, sub_menu);
402 g_object_set_data (G_OBJECT(gmenu_item),
"sub-menu", sub_menu);
420 GMenuItem *item_path, *item_with_full_path;
421 gchar *full_path = NULL;
422 GMenuItem *gmenu_item = NULL;
424 DEBUG(
"Adding %s/%s [%s] as [%s]", ext_info->path, ext_info->action_label,
425 ext_info->action_name, ext_info->typeStr );
427 g_hash_table_insert (per_window->
item_hash, g_strdup (ext_info->action_name), ext_info->extension);
429 if (g_str_has_suffix (ext_info->path, _(
"_Custom")))
432 full_path = g_strconcat (ext_info->path,
"/", ext_info->action_label, NULL);
434 item_path = g_hash_table_lookup (per_window->build_menu_hash, ext_info->path);
435 item_with_full_path = g_hash_table_lookup (per_window->build_menu_hash, full_path);
437 if (!item_path && !item_with_full_path)
439 gmenu_item = setup_gmenu_item_with_tooltip (ext_info);
441 g_menu_append_item (G_MENU(per_window->report_menu), gmenu_item);
444 if (item_path && !item_with_full_path)
446 GMenuModel *sub_menu = G_MENU_MODEL(g_object_get_data (G_OBJECT(item_path),
"sub-menu"));
448 gmenu_item = setup_gmenu_item_with_tooltip (ext_info);
450 g_menu_append_item (G_MENU(sub_menu), gmenu_item);
452 g_hash_table_insert (per_window->build_menu_hash, g_strdup (full_path), gmenu_item);
456 if (ext_info->action_label_original)
458 gchar *full_path_original = g_strconcat (ext_info->path,
"/", ext_info->action_label_original, NULL);
459 g_hash_table_insert (per_window->build_menu_hash, g_strdup (full_path_original), gmenu_item);
460 g_object_ref (gmenu_item);
461 g_free (full_path_original);
480 gnc_plugin_menu_additions_add_to_window (GncPlugin *plugin,
481 GncMainWindow *window,
485 static GOnce accel_table_init = G_ONCE_INIT;
486 static GHashTable *
table;
489 GncMenuModelSearch *gsm = g_new0 (GncMenuModelSearch, 1);
493 GncPluginMenuAdditions *menu_plugin = GNC_PLUGIN_MENU_ADDITIONS (plugin);
494 if (!menu_plugin->item_hash)
495 menu_plugin->item_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
497 per_window.
item_hash = menu_plugin->item_hash;
498 per_window.build_menu_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
499 per_window.report_menu = g_menu_new ();
501 menu_list = g_slist_sort (gnc_extensions_get_menu_list(),
502 (GCompareFunc)gnc_menu_additions_sort);
505 table = g_once (&accel_table_init, gnc_menu_additions_init_accel_table, NULL);
506 g_slist_foreach (menu_list,
507 (GFunc)gnc_menu_additions_do_preassigned_accel,
table);
508 g_slist_foreach (menu_list, (GFunc)gnc_menu_additions_assign_accel,
table);
511 g_slist_foreach (menu_list, (GFunc)gnc_menu_additions_menu_setup_one,
515 gsm->search_action_label = NULL;
516 gsm->search_action_name =
"ReportsPlaceholder0";
517 gsm->search_action_target = NULL;
521 g_menu_insert_section (G_MENU(gsm->model), gsm->index, NULL, G_MENU_MODEL(per_window.report_menu));
524 PERR(
"Could not find 'ReportsAction' in menu model");
526 g_hash_table_destroy (per_window.build_menu_hash);
528 g_slist_free (menu_list);
548 gnc_plugin_menu_additions_remove_from_window (GncPlugin *plugin,
549 GncMainWindow *window,
552 GSimpleActionGroup *simple_action_group;
560 if (simple_action_group && !gnc_main_window_just_plugin_prefs (window))
#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.