Branch data Line data Source code
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 : 429 : gnc_hook_create (const gchar *name, gint num_args, const gchar *desc)
46 : : {
47 : : GncHook *hook_list;
48 : :
49 : 429 : g_return_val_if_fail(name != NULL, NULL);
50 : 429 : g_return_val_if_fail(num_args <= 1, NULL);
51 : 429 : g_return_val_if_fail(desc != NULL, NULL);
52 : :
53 : 429 : ENTER("name %s", name);
54 : 429 : if (gnc_hooks_list == NULL)
55 : : {
56 : 33 : gnc_hooks_list = g_hash_table_new(g_str_hash, g_str_equal);
57 : :
58 : : /* If we're not initialized then initialize now */
59 : 33 : if (!gnc_hooks_initialized)
60 : 0 : gnc_hooks_init();
61 : : }
62 : :
63 : 429 : hook_list = g_hash_table_lookup(gnc_hooks_list, name);
64 : 429 : if (hook_list)
65 : : {
66 : 0 : LEAVE("List %s(%p) already exists", name, hook_list);
67 : 0 : return((gchar*)name);
68 : : }
69 : :
70 : 429 : hook_list = g_new0(GncHook, 1);
71 : 429 : hook_list->desc = g_strdup(desc);
72 : 429 : hook_list->danglers = g_malloc(sizeof(GHookList));
73 : 429 : g_hook_list_init(hook_list->danglers, sizeof(GHook));
74 : 429 : hook_list->num_args = num_args;
75 : 429 : g_hash_table_insert(gnc_hooks_list, (gchar *)name, hook_list);
76 : :
77 : 429 : LEAVE("created list %s(%p)", name, hook_list);
78 : 429 : return (gchar *)name;
79 : : }
80 : :
81 : : static GncHook *
82 : 36 : gnc_hook_lookup (const gchar *name)
83 : : {
84 : : GncHook *hook;
85 : :
86 : 36 : ENTER("name %s", name);
87 : 36 : if (gnc_hooks_list == NULL)
88 : : {
89 : 3 : PINFO("no hook lists");
90 : 3 : gnc_hooks_init();
91 : : }
92 : :
93 : 36 : hook = g_hash_table_lookup(gnc_hooks_list, name);
94 : 36 : LEAVE("hook list %p", hook);
95 : 36 : return(hook);
96 : : }
97 : :
98 : : int
99 : 30 : gnc_hook_num_args (const gchar *name)
100 : : {
101 : : GncHook *hook;
102 : 30 : int num_args = -1;
103 : :
104 : 30 : ENTER("name %s", name);
105 : 30 : if (gnc_hooks_list == NULL)
106 : : {
107 : 30 : PINFO("no hook lists");
108 : 30 : gnc_hooks_init();
109 : : }
110 : :
111 : 30 : hook = g_hash_table_lookup(gnc_hooks_list, name);
112 : 30 : if (hook)
113 : 30 : num_args = hook->num_args;
114 : 30 : LEAVE("hook list %p, num_args %i", hook, num_args);
115 : 30 : return(num_args);
116 : : }
117 : :
118 : : void
119 : 33 : 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 : 33 : ENTER("list %s, function %p, cbarg %p", name, callback, cb_arg);
126 : 33 : gnc_hook = gnc_hook_lookup(name);
127 : 33 : g_return_if_fail(gnc_hook != NULL);
128 : 33 : hook = g_hook_alloc(gnc_hook->danglers);
129 : 33 : hook->func = callback;
130 : 33 : hook->data = cb_arg;
131 : 33 : hook->destroy = destroy;
132 : 33 : g_hook_append(gnc_hook->danglers, hook);
133 : 33 : LEAVE("");
134 : : }
135 : :
136 : : void
137 : 0 : gnc_hook_remove_dangler (const gchar *name, GFunc callback)
138 : : {
139 : : GncHook *gnc_hook;
140 : : GHook *hook;
141 : :
142 : 0 : ENTER("name %s, function %p", name, callback);
143 : 0 : gnc_hook = gnc_hook_lookup(name);
144 : 0 : if (gnc_hook == NULL)
145 : : {
146 : 0 : LEAVE("Unknown hook list %s", name);
147 : 0 : return;
148 : : }
149 : :
150 : 0 : hook = g_hook_find_func(gnc_hook->danglers, TRUE, callback);
151 : 0 : if (hook == NULL)
152 : : {
153 : 0 : LEAVE("Hook %p not found in %s", callback, name);
154 : 0 : return;
155 : : }
156 : :
157 : 0 : g_hook_destroy_link(gnc_hook->danglers, hook);
158 : 0 : LEAVE("Removed %p from %s", hook, name);
159 : : }
160 : :
161 : : static void
162 : 0 : call_hook (GHook *hook, gpointer data)
163 : : {
164 : 0 : ENTER("hook %p (func %p), data %p, cbarg %p", hook, hook->func, data,
165 : : hook->data);
166 : 0 : ((GFunc)hook->func)(data, hook->data);
167 : 0 : LEAVE("");
168 : 0 : }
169 : :
170 : : void
171 : 3 : gnc_hook_run (const gchar *name, gpointer data)
172 : : {
173 : : GncHook *hook;
174 : :
175 : 3 : ENTER("list %s, data %p", (name == NULL ? "(null)" : name), data);
176 : 3 : hook = gnc_hook_lookup(name);
177 : 3 : if (!hook)
178 : : {
179 : 0 : LEAVE("No such hook list");
180 : 0 : return;
181 : : }
182 : 3 : g_hook_list_marshal(hook->danglers, TRUE, call_hook, data);
183 : 3 : LEAVE("");
184 : : }
185 : :
186 : : void
187 : 33 : gnc_hooks_init(void)
188 : : {
189 : 33 : ENTER("");
190 : :
191 : 33 : if (gnc_hooks_initialized)
192 : : {
193 : 0 : LEAVE("Hooks already initialized");
194 : 0 : return;
195 : : }
196 : :
197 : 33 : gnc_hooks_initialized = TRUE;
198 : :
199 : 33 : gnc_hook_create(HOOK_STARTUP, 0,
200 : : "Functions to run at startup. Hook args: ()");
201 : 33 : gnc_hook_create(HOOK_SHUTDOWN, 0,
202 : : "Functions to run at guile shutdown. Hook args: ()");
203 : 33 : gnc_hook_create(HOOK_UI_STARTUP, 0,
204 : : "Functions to run when the ui comes up. Hook args: ()");
205 : 33 : gnc_hook_create(HOOK_UI_POST_STARTUP, 0,
206 : : "Functions to run after the ui comes up. Hook args: ()");
207 : 33 : gnc_hook_create(HOOK_UI_SHUTDOWN, 0,
208 : : "Functions to run at ui shutdown. Hook args: ()");
209 : 33 : 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 : 33 : gnc_hook_create(HOOK_REPORT, 0,
213 : : "Run just before the reports are pushed into the menus."
214 : : " Hook args: ()");
215 : 33 : gnc_hook_create(HOOK_CURRENCY_CHANGED, 0,
216 : : "Functions to run when the user changes currency settings. Hook args: ()");
217 : 33 : gnc_hook_create(HOOK_SAVE_OPTIONS, 0,
218 : : "Functions to run when saving options. Hook args: ()");
219 : 33 : gnc_hook_create(HOOK_ADD_EXTENSION, 0,
220 : : "Functions to run when the extensions menu is created."
221 : : " Hook args: ()");
222 : :
223 : 33 : gnc_hook_create(HOOK_BOOK_OPENED, 1,
224 : : "Run after book open. Hook args: <gnc:Session*>.");
225 : 33 : gnc_hook_create(HOOK_BOOK_CLOSED, 1,
226 : : "Run before file close. Hook args: <gnc:Session*>");
227 : 33 : gnc_hook_create(HOOK_BOOK_SAVED, 1,
228 : : "Run after file saved. Hook args: <gnc:Session*>");
229 : :
230 : 33 : LEAVE("");
231 : : }
|