GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 [email protected] *
21 \********************************************************************/
22 
23 #include "config.h"
24 
25 #include <gtk/gtk.h>
26 #include <glib/gi18n.h>
27 #include <ctype.h>
28 
29 #include "guile-util.h"
30 #include "gnc-engine.h"
31 #include "gnc-menu-extensions.h"
32 #include "gnc-ui.h"
33 
34 typedef struct _Getters Getters;
35 struct _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. */
46 static QofLogModule log_module = GNC_MOD_GUI;
47 
48 static GSList *extension_list = NULL;
49 static Getters getters = {0, 0, 0, 0, 0, 0};
50 
51 GSList *
52 gnc_extensions_get_menu_list (void)
53 {
54  return g_slist_copy(extension_list);
55 }
56 
57 static void
58 initialize_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 
76 static gboolean
77 gnc_extension_type (SCM extension, GtkUIManagerItemType *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 = GTK_UI_MANAGER_MENUITEM;
93  }
94  else if (g_strcmp0(string, "menu") == 0)
95  {
96  *type = GTK_UI_MANAGER_MENU;
97  }
98  else if (g_strcmp0(string, "separator") == 0)
99  {
100  *type = GTK_UI_MANAGER_SEPARATOR;
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 */
114 static char *
115 gnc_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 */
124 static char *
125 gnc_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 */
134 static char *
135 gnc_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 */
143 static void
144 gnc_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 
212 static gchar*
213 gnc_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 
237 void
238 gnc_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 
256 static gboolean
257 gnc_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->ae.label = g_strdup(gettext(name));
278  ext_info->ae.name = gnc_ext_gen_action_name(guid);
279  ext_info->ae.tooltip = gnc_extension_documentation(extension);
280  ext_info->ae.stock_id = NULL;
281  ext_info->ae.accelerator = NULL;
282  ext_info->ae.callback = NULL;
283  g_free(name);
284  g_free(guid);
285 
286  tmp = g_strdup_printf("%s/%s", ext_info->path, ext_info->ae.label);
287  ext_info->sort_key = g_utf8_collate_key(tmp, -1);
288  g_free(tmp);
289 
290  switch (ext_info->type)
291  {
292  case GTK_UI_MANAGER_MENU:
293  typeStr = "menu";
294  break;
295  case GTK_UI_MANAGER_MENUITEM:
296  typeStr = "menuitem";
297  break;
298  default:
299  typeStr = "unk";
300  break;
301  }
302  ext_info->typeStr = typeStr;
303 
304  DEBUG( "extension: %s/%s [%s] tip [%s] type %s\n",
305  ext_info->path, ext_info->ae.label, ext_info->ae.name,
306  ext_info->ae.tooltip, ext_info->typeStr );
307 
308  scm_gc_protect_object(extension);
309 
310  /* need to append so we can run them in order */
311  extension_list = g_slist_append(extension_list, ext_info);
312 
313  return TRUE;
314 }
315 
316 static void
317 cleanup_extension_info(gpointer extension_info, gpointer not_used)
318 {
319  ExtensionInfo *ext_info = extension_info;
320 
321  if (ext_info->extension)
322  scm_gc_unprotect_object(ext_info->extension);
323 
324  g_free(ext_info->sort_key);
325  g_free((gchar *)ext_info->ae.name);
326  g_free((gchar *)ext_info->ae.label);
327  g_free((gchar *)ext_info->ae.tooltip);
328  g_free(ext_info->path);
329  g_free(ext_info);
330 }
331 
332 
333 void
334 gnc_add_scm_extension (SCM extension)
335 {
336  if (!gnc_create_extension_info(extension))
337  {
338  PERR("bad extension");
339  return;
340  }
341 }
342 
343 /******************** Shutdown ********************/
344 
345 void
346 gnc_extensions_shutdown (void)
347 {
348  g_slist_foreach(extension_list, cleanup_extension_info, NULL);
349 
350  g_slist_free(extension_list);
351 
352  extension_list = NULL;
353 }
#define DEBUG(format, args...)
Definition: qoflog.h:255
#define PERR(format, args...)
Definition: qoflog.h:237
All type declarations for the whole Gnucash engine.
const gchar * QofLogModule
Definition: qofid.h:89