GnuCash  5.6-150-g038405b370+
gnc-hooks.c
1 /*
2  * gnc-hooks.c -- helpers for using Glib hook functions
3  * Copyright (C) 2005 David Hampton <hampton@employees.org>
4  * Derek Atkins <derek@ihtfp.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, contact:
18  *
19  * Free Software Foundation Voice: +1-617-542-5942
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
21  * Boston, MA 02110-1301, USA gnu@gnu.org
22  */
23 
24 #include <config.h>
25 
26 #include <glib.h>
27 #include <stdio.h>
28 #include "gnc-hooks.h"
29 #include "gnc-engine.h"
30 
31 static QofLogModule log_module = GNC_MOD_ENGINE;
32 
33 static GHashTable* gnc_hooks_list = NULL;
34 static gboolean gnc_hooks_initialized = FALSE;
35 
36 typedef struct
37 {
38  gchar *desc;
39  GHookList *danglers;
40  gint num_args;
41 } GncHook;
42 
43 
44 gchar *
45 gnc_hook_create (const gchar *name, gint num_args, const gchar *desc)
46 {
47  GncHook *hook_list;
48 
49  g_return_val_if_fail(name != NULL, NULL);
50  g_return_val_if_fail(num_args <= 1, NULL);
51  g_return_val_if_fail(desc != NULL, NULL);
52 
53  ENTER("name %s", name);
54  if (gnc_hooks_list == NULL)
55  {
56  gnc_hooks_list = g_hash_table_new(g_str_hash, g_str_equal);
57 
58  /* If we're not initialized then initialize now */
59  if (!gnc_hooks_initialized)
60  gnc_hooks_init();
61  }
62 
63  hook_list = g_hash_table_lookup(gnc_hooks_list, name);
64  if (hook_list)
65  {
66  LEAVE("List %s(%p) already exists", name, hook_list);
67  return((gchar*)name);
68  }
69 
70  hook_list = g_new0(GncHook, 1);
71  hook_list->desc = g_strdup(desc);
72  hook_list->danglers = g_malloc(sizeof(GHookList));
73  g_hook_list_init(hook_list->danglers, sizeof(GHook));
74  hook_list->num_args = num_args;
75  g_hash_table_insert(gnc_hooks_list, (gchar *)name, hook_list);
76 
77  LEAVE("created list %s(%p)", name, hook_list);
78  return (gchar *)name;
79 }
80 
81 static GncHook *
82 gnc_hook_lookup (const gchar *name)
83 {
84  GncHook *hook;
85 
86  ENTER("name %s", name);
87  if (gnc_hooks_list == NULL)
88  {
89  PINFO("no hook lists");
90  gnc_hooks_init();
91  }
92 
93  hook = g_hash_table_lookup(gnc_hooks_list, name);
94  LEAVE("hook list %p", hook);
95  return(hook);
96 }
97 
98 int
99 gnc_hook_num_args (const gchar *name)
100 {
101  GncHook *hook;
102  int num_args = -1;
103 
104  ENTER("name %s", name);
105  if (gnc_hooks_list == NULL)
106  {
107  PINFO("no hook lists");
108  gnc_hooks_init();
109  }
110 
111  hook = g_hash_table_lookup(gnc_hooks_list, name);
112  if (hook)
113  num_args = hook->num_args;
114  LEAVE("hook list %p, num_args %i", hook, num_args);
115  return(num_args);
116 }
117 
118 void
119 gnc_hook_add_dangler (const gchar *name, GFunc callback,
120  GDestroyNotify destroy, gpointer cb_arg)
121 {
122  GncHook *gnc_hook;
123  GHook *hook;
124 
125  ENTER("list %s, function %p, cbarg %p", name, callback, cb_arg);
126  gnc_hook = gnc_hook_lookup(name);
127  g_return_if_fail(gnc_hook != NULL);
128  hook = g_hook_alloc(gnc_hook->danglers);
129  hook->func = callback;
130  hook->data = cb_arg;
131  hook->destroy = destroy;
132  g_hook_append(gnc_hook->danglers, hook);
133  LEAVE("");
134 }
135 
136 void
137 gnc_hook_remove_dangler (const gchar *name, GFunc callback)
138 {
139  GncHook *gnc_hook;
140  GHook *hook;
141 
142  ENTER("name %s, function %p", name, callback);
143  gnc_hook = gnc_hook_lookup(name);
144  if (gnc_hook == NULL)
145  {
146  LEAVE("Unknown hook list %s", name);
147  return;
148  }
149 
150  hook = g_hook_find_func(gnc_hook->danglers, TRUE, callback);
151  if (hook == NULL)
152  {
153  LEAVE("Hook %p not found in %s", callback, name);
154  return;
155  }
156 
157  g_hook_destroy_link(gnc_hook->danglers, hook);
158  LEAVE("Removed %p from %s", hook, name);
159 }
160 
161 static void
162 call_hook (GHook *hook, gpointer data)
163 {
164  ENTER("hook %p (func %p), data %p, cbarg %p", hook, hook->func, data,
165  hook->data);
166  ((GFunc)hook->func)(data, hook->data);
167  LEAVE("");
168 }
169 
170 void
171 gnc_hook_run (const gchar *name, gpointer data)
172 {
173  GncHook *hook;
174 
175  ENTER("list %s, data %p", (name == NULL ? "(null)" : name), data);
176  hook = gnc_hook_lookup(name);
177  if (!hook)
178  {
179  LEAVE("No such hook list");
180  return;
181  }
182  g_hook_list_marshal(hook->danglers, TRUE, call_hook, data);
183  LEAVE("");
184 }
185 
186 void
187 gnc_hooks_init(void)
188 {
189  ENTER("");
190 
191  if (gnc_hooks_initialized)
192  {
193  LEAVE("Hooks already initialized");
194  return;
195  }
196 
197  gnc_hooks_initialized = TRUE;
198 
199  gnc_hook_create(HOOK_STARTUP, 0,
200  "Functions to run at startup. Hook args: ()");
201  gnc_hook_create(HOOK_SHUTDOWN, 0,
202  "Functions to run at guile shutdown. Hook args: ()");
203  gnc_hook_create(HOOK_UI_STARTUP, 0,
204  "Functions to run when the ui comes up. Hook args: ()");
205  gnc_hook_create(HOOK_UI_POST_STARTUP, 0,
206  "Functions to run after the ui comes up. Hook args: ()");
207  gnc_hook_create(HOOK_UI_SHUTDOWN, 0,
208  "Functions to run at ui shutdown. Hook args: ()");
209  gnc_hook_create(HOOK_NEW_BOOK, 0,
210  "Run after a new (empty) book is opened, before the"
211  " book-opened-hook. Hook args: ()");
212  gnc_hook_create(HOOK_REPORT, 0,
213  "Run just before the reports are pushed into the menus."
214  " Hook args: ()");
215  gnc_hook_create(HOOK_CURRENCY_CHANGED, 0,
216  "Functions to run when the user changes currency settings. Hook args: ()");
217  gnc_hook_create(HOOK_SAVE_OPTIONS, 0,
218  "Functions to run when saving options. Hook args: ()");
219  gnc_hook_create(HOOK_ADD_EXTENSION, 0,
220  "Functions to run when the extensions menu is created."
221  " Hook args: ()");
222 
223  gnc_hook_create(HOOK_BOOK_OPENED, 1,
224  "Run after book open. Hook args: <gnc:Session*>.");
225  gnc_hook_create(HOOK_BOOK_CLOSED, 1,
226  "Run before file close. Hook args: <gnc:Session*>");
227  gnc_hook_create(HOOK_BOOK_SAVED, 1,
228  "Run after file saved. Hook args: <gnc:Session*>");
229 
230  LEAVE("");
231 }
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
All type declarations for the whole Gnucash engine.
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282