GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-menu-extensions.c
1/********************************************************************\
2 * gnc-menu-extensions.c -- functions to build dynamic menus *
3 * Copyright (C) 1999 Rob Browning *
4 * *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License as *
7 * published by the Free Software Foundation; either version 2 of *
8 * the License, or (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License*
16 * along with this program; if not, contact: *
17 * *
18 * Free Software Foundation Voice: +1-617-542-5942 *
19 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
20 * Boston, MA 02110-1301, USA gnu@gnu.org *
21\********************************************************************/
22
23#include <config.h>
24
25#include <gtk/gtk.h>
26#include <glib/gi18n.h>
27#include <ctype.h>
28
29#include "gnc-guile-utils.h"
30#include "gnc-engine.h"
31#include "gnc-menu-extensions.h"
32#include "gnc-ui.h"
33
34typedef struct _Getters Getters;
36{
37 SCM type;
38 SCM name;
39 SCM guid;
40 SCM documentation;
41 SCM path;
42 SCM script;
43};
44
45/* This static indicates the debugging module that this .o belongs to. */
46static QofLogModule log_module = GNC_MOD_GUI;
47
48static GSList *extension_list = NULL;
49static Getters getters = {0, 0, 0, 0, 0, 0};
50
51GSList *
52gnc_extensions_get_menu_list (void)
53{
54 return g_slist_copy(extension_list);
55}
56
57static void
58initialize_getters()
59{
60 static gboolean getters_initialized = FALSE;
61
62 if (getters_initialized)
63 return;
64
65 getters.type = scm_c_eval_string("gnc:extension-type");
66 getters.name = scm_c_eval_string("gnc:extension-name");
67 getters.guid = scm_c_eval_string("gnc:extension-guid");
68 getters.documentation = scm_c_eval_string("gnc:extension-documentation");
69 getters.path = scm_c_eval_string("gnc:extension-path");
70 getters.script = scm_c_eval_string("gnc:extension-script");
71
72 getters_initialized = TRUE;
73}
74
75
76static gboolean
77gnc_extension_type (SCM extension, GNCMenuItemTypes *type)
78{
79 char *string;
80
81 initialize_getters();
82
83 string = gnc_scm_call_1_symbol_to_string(getters.type, extension);
84 if (string == NULL)
85 {
86 PERR("bad type");
87 return FALSE;
88 }
89
90 if (g_strcmp0(string, "menu-item") == 0)
91 {
92 *type = GNC_MENU_ITEM;
93 }
94 else if (g_strcmp0(string, "menu") == 0)
95 {
96 *type = GNC_SUB_MENU_ITEM;
97 }
98 else if (g_strcmp0(string, "separator") == 0)
99 {
100 *type = GNC_SEPARATOR_ITEM;
101 }
102 else
103 {
104 PERR("bad type");
105 return FALSE;
106 }
107
108 free(string);
109
110 return TRUE;
111}
112
113/* returns malloc'd name */
114static char *
115gnc_extension_name (SCM extension)
116{
117 initialize_getters();
118
119 return gnc_scm_call_1_to_string(getters.name, extension);
120}
121
122
123/* returns malloc'd guid */
124static char *
125gnc_extension_guid (SCM extension)
126{
127 initialize_getters();
128
129 return gnc_scm_call_1_to_string(getters.guid, extension);
130}
131
132
133/* returns malloc'd docs */
134static char *
135gnc_extension_documentation (SCM extension)
136{
137 initialize_getters();
138
139 return gnc_scm_call_1_to_string(getters.documentation, extension);
140}
141
142/* returns g_malloc'd path */
143static void
144gnc_extension_path (SCM extension, char **fullpath)
145{
146 SCM path;
147 gchar **strings;
148 gint i;
149 gint num_strings;
150
151 initialize_getters();
152
153 path = gnc_scm_call_1_to_list(getters.path, extension);
154 if ((path == SCM_UNDEFINED) || scm_is_null(path))
155 {
156 *fullpath = g_strdup("");
157 return;
158 }
159
160 num_strings = scm_ilength(path) + 2;
161 strings = g_new0(gchar *, num_strings);
162 strings[0] = "/menubar";
163
164 i = 1;
165 while (!scm_is_null(path))
166 {
167 SCM item;
168
169 item = SCM_CAR(path);
170 path = SCM_CDR(path);
171
172 if (scm_is_string(item))
173 {
174 gchar* s;
175 s = gnc_scm_to_utf8_string(item);
176
177 if (i == 1)
178 strings[i] = g_strdup(s);
179 else
180 strings[i] = g_strdup(gettext(s));
181
182 g_free (s);
183 }
184 else
185 {
186 g_free(strings);
187
188 PERR("not a string");
189
190 *fullpath = g_strdup("");
191 return;
192 }
193
194 i++;
195 }
196
197 *fullpath = g_strjoinv("/", strings);
198
199 for (i = 1; i < num_strings; i++)
200 {
201 if (strings[i] != NULL)
202 {
203 g_free(strings[i]);
204 }
205 }
206
207 g_free(strings);
208}
209
210/******************** New Menu Item ********************/
211
212static gchar*
213gnc_ext_gen_action_name (const gchar *name)
214{
215
216 const gchar *extChar;
217 GString *actionName;
218
219 actionName = g_string_sized_new( strlen( name ) + 7 );
220
221 // 'Mum & ble12' => 'Mumble___ble12'
222 for ( extChar = name; *extChar != '\0'; extChar++ )
223 {
224 if ( ! isalnum( *extChar ) )
225 g_string_append_c( actionName, '_' );
226 g_string_append_c( actionName, *extChar );
227 }
228
229 // 'Mumble + 'Action' => 'MumbleAction'
230 g_string_append_printf( actionName, "Action" );
231
232 return g_string_free(actionName, FALSE);
233}
234
235/******************** Callback ********************/
236
237void
238gnc_extension_invoke_cb (SCM extension, SCM window)
239{
240 SCM script;
241
242 initialize_getters();
243
244 script = gnc_scm_call_1_to_procedure(getters.script, extension);
245 if (script == SCM_UNDEFINED)
246 {
247 PERR("not a procedure.");
248 return;
249 }
250
251 scm_call_1(script, window);
252}
253
254/******************** New Menu Item ********************/
255
256static gboolean
257gnc_create_extension_info (SCM extension)
258{
259 ExtensionInfo *ext_info;
260 gchar *typeStr, *tmp;
261 gchar* name;
262 gchar* guid;
263
264 ext_info = g_new0 (ExtensionInfo, 1);
265 ext_info->extension = extension;
266 gnc_extension_path (extension, &ext_info->path);
267 if (!gnc_extension_type (extension, &ext_info->type))
268 {
269 /* Can't parse the type passed to us. Bail now. */
270 g_free(ext_info);
271 return FALSE;
272 }
273
274 /* Get all the pieces */
275 name = gnc_extension_name (extension);
276 guid = gnc_extension_guid (extension);
277 ext_info->action_label = g_strdup (gettext (name));
278 ext_info->action_label_original = NULL;
279 ext_info->action_name = gnc_ext_gen_action_name (guid);
280 ext_info->action_tooltip = gnc_extension_documentation (extension);
281 g_free (name);
282 g_free (guid);
283
284 tmp = g_strdup_printf ("%s/%s", ext_info->path, ext_info->action_label);
285 ext_info->sort_key = g_utf8_collate_key (tmp, -1);
286 g_free(tmp);
287
288 switch (ext_info->type)
289 {
290 case GNC_SUB_MENU_ITEM:
291 typeStr = "menu";
292 break;
293 case GNC_MENU_ITEM:
294 typeStr = "menuitem";
295 break;
296 case GNC_SEPARATOR_ITEM:
297 typeStr = "sepitem";
298 break;
299 default:
300 typeStr = "unk";
301 break;
302 }
303 ext_info->typeStr = typeStr;
304
305 DEBUG( "extension: %s/%s [%s] tip [%s] type %s\n",
306 ext_info->path, ext_info->action_label, ext_info->action_name,
307 ext_info->action_tooltip, ext_info->typeStr );
308
309 scm_gc_protect_object (extension);
310
311 /* need to append so we can run them in order */
312 extension_list = g_slist_append (extension_list, ext_info);
313
314 return TRUE;
315}
316
317static void
318cleanup_extension_info (gpointer extension_info, gpointer not_used)
319{
320 ExtensionInfo *ext_info = extension_info;
321
322 if (ext_info->extension)
323 scm_gc_unprotect_object (ext_info->extension);
324
325 g_free (ext_info->sort_key);
326 g_free ((gchar *)ext_info->action_name);
327 g_free ((gchar *)ext_info->action_label);
328 g_free ((gchar *)ext_info->action_label_original);
329 g_free ((gchar *)ext_info->action_tooltip);
330 g_free (ext_info->path);
331 g_free (ext_info);
332}
333
334
335void
336gnc_add_scm_extension (SCM extension)
337{
338 if (!gnc_create_extension_info(extension))
339 {
340 PERR("bad extension");
341 return;
342 }
343}
344
345/******************** Shutdown ********************/
346
347void
348gnc_extensions_shutdown (void)
349{
350 g_slist_foreach(extension_list, cleanup_extension_info, NULL);
351
352 g_slist_free(extension_list);
353
354 extension_list = NULL;
355}
All type declarations for the whole Gnucash engine.
#define DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264
#define PERR(format, args...)
Log a serious error.
Definition qoflog.h:244