Branch data Line data Source code
1 : : /********************************************************************\
2 : : * engine-helpers.c -- gnucash engine helper functions *
3 : : * Copyright (C) 2000 Linas Vepstas <linas@linas.org> *
4 : : * Copyright (C) 2001 Linux Developers Group, Inc. *
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 : :
25 : : #include <config.h>
26 : :
27 : : #include <string.h>
28 : :
29 : : #include "Account.h"
30 : : #include "engine-helpers.h"
31 : : #include "gnc-date.h"
32 : : #include "gnc-engine.h"
33 : : #include "gnc-session.h"
34 : : #include <qof.h>
35 : : #include <qofbookslots.h>
36 : :
37 : : /** \todo Code dependent on the private query headers
38 : : qofquery-p.h and qofquerycore-p.h may need to be modified.
39 : : These files are temporarily exported for QOF 0.6.0 but
40 : : cannot be considered "standard" or public parts of QOF. */
41 : : #include "qofquery-p.h"
42 : : #include "qofquerycore-p.h"
43 : :
44 : : #define FUNC_NAME G_STRFUNC
45 : :
46 : : static QofLogModule log_module = GNC_MOD_ENGINE;
47 : :
48 : : /** Gets the transaction Number or split Action based on book option:
49 : : * if the book option is TRUE (split action is used for NUM) and a
50 : : * split is provided, split-action is returned; if book option is FALSE
51 : : * (tran-num is used for NUM) and a trans is provided, transaction-num
52 : : * is returned; if split is provided and tran is NULL, split-action is
53 : : * returned; if tran is provided and split is NULL, transaction-num is
54 : : * returned. Otherwise NULL is returned.*/
55 : : const char *
56 : 1141 : gnc_get_num_action (const Transaction *trans, const Split *split)
57 : : {
58 : 1141 : if (trans && !split)
59 : 0 : return xaccTransGetNum(trans);
60 : 1141 : if (split && !trans)
61 : 4 : return xaccSplitGetAction(split);
62 : 1137 : if (trans && split)
63 : : {
64 : 1137 : QofBook* book = qof_session_get_book(gnc_get_current_session ());
65 : 1137 : if (!book)
66 : : {
67 : 0 : PERR("Session has no book but has a transaction or split!");
68 : 0 : return NULL;
69 : : }
70 : 1137 : if (qof_book_use_split_action_for_num_field (book))
71 : 0 : return xaccSplitGetAction(split);
72 : : else
73 : 1137 : return xaccTransGetNum(trans);
74 : : }
75 : 0 : else return NULL;
76 : : }
77 : :
78 : : /** Opposite of 'gnc_get_num_action'; if the book option is TRUE (split action
79 : : * is used for NUM) and a trans is provided, transaction-num is returned; if
80 : : * book option is FALSE (tran-num is used for NUM) and a split is provided,
81 : : * split-action is returned; if split is provided and tran is NULL,
82 : : * split-action is returned; if tran is provided and split is NULL,
83 : : * transaction-num is returned. Otherwise NULL is returned.*/
84 : : const char *
85 : 441 : gnc_get_action_num (const Transaction *trans, const Split *split)
86 : : {
87 : 441 : gboolean num_action = qof_book_use_split_action_for_num_field
88 : 441 : (qof_session_get_book(gnc_get_current_session ()));
89 : :
90 : 441 : if (trans && !split)
91 : 0 : return xaccTransGetNum(trans);
92 : 441 : if (split && !trans)
93 : 413 : return xaccSplitGetAction(split);
94 : 28 : if (trans && split)
95 : : {
96 : 28 : if (num_action)
97 : 0 : return xaccTransGetNum(trans);
98 : : else
99 : 28 : return xaccSplitGetAction(split);
100 : : }
101 : 0 : else return NULL;
102 : : }
103 : :
104 : : /** Sets the transaction Number and/or split Action based on book option:
105 : : * if the book option is TRUE (split action is to be used for NUM) then 'num'
106 : : * sets split-action and, if 'tran' and 'action' are provided, 'action'
107 : : * sets transaction-num; if book option is FALSE (tran-num is to be used for NUM)
108 : : * then 'num' sets transaction-num and, if 'split' and 'action' are
109 : : * provided, 'action' sets 'split-action'. If any arguments are NULL,
110 : : * no change is made to the field that would otherwise be
111 : : * affected. If 'tran' and 'num' are passed with 'split and 'action' set to
112 : : * NULL, it is xaccTransSetNum (trans, num). Likewise, if 'split and 'action'
113 : : * are passed with 'tran' and 'num' set to NULL, it is xaccSplitSetAction (split,
114 : : * action). */
115 : : void
116 : 315 : gnc_set_num_action (Transaction *trans, Split *split,
117 : : const char *num, const char *action)
118 : : {
119 : 315 : gboolean num_action = qof_book_use_split_action_for_num_field
120 : 315 : (qof_session_get_book(gnc_get_current_session ()));
121 : :
122 : 315 : if (trans && num && !split && !action)
123 : : {
124 : 0 : xaccTransSetNum (trans, num);
125 : 0 : return;
126 : : }
127 : :
128 : 315 : if (!trans && !num && split && action)
129 : : {
130 : 97 : xaccSplitSetAction (split, action);
131 : 97 : return;
132 : : }
133 : :
134 : 218 : if (trans)
135 : : {
136 : 68 : if (!num_action && num)
137 : 64 : xaccTransSetNum (trans, num);
138 : 68 : if (num_action && action)
139 : 0 : xaccTransSetNum (trans, action);
140 : : }
141 : :
142 : 218 : if (split)
143 : : {
144 : 150 : if (!num_action && action)
145 : 142 : xaccSplitSetAction (split, action);
146 : 150 : if (num_action && num)
147 : 0 : xaccSplitSetAction (split, num);
148 : : }
149 : : }
150 : :
151 : : /************************************************************/
152 : : /* Notification of Book Option Changes */
153 : : /************************************************************/
154 : :
155 : : static GOnce bo_init_once = G_ONCE_INIT;
156 : : static GHashTable *bo_callback_hash = NULL;
157 : : static GHookList *bo_final_hook_list = NULL;
158 : :
159 : : static gpointer
160 : 0 : bo_init (gpointer unused)
161 : : {
162 : 0 : bo_callback_hash = g_hash_table_new(g_str_hash, g_str_equal);
163 : :
164 : 0 : bo_final_hook_list = g_malloc(sizeof(GHookList));
165 : 0 : g_hook_list_init(bo_final_hook_list, sizeof(GHook));
166 : 0 : return NULL;
167 : : }
168 : :
169 : : static void
170 : 0 : bo_call_hook (GHook *hook, gpointer data)
171 : : {
172 : 0 : ((GFunc)hook->func)(data, hook->data);
173 : 0 : }
174 : :
175 : : /** Calls registered callbacks when num_field_source book option changes so that
176 : : * registers/reports can update themselves */
177 : : void
178 : 0 : gnc_book_option_num_field_source_change (gboolean num_action)
179 : : {
180 : : GHookList *hook_list;
181 : 0 : const gchar *key = OPTION_NAME_NUM_FIELD_SOURCE;
182 : :
183 : 0 : g_once(&bo_init_once, bo_init, NULL);
184 : :
185 : 0 : hook_list = g_hash_table_lookup(bo_callback_hash, key);
186 : 0 : if (hook_list != NULL)
187 : 0 : g_hook_list_marshal(hook_list, TRUE, bo_call_hook, &num_action);
188 : 0 : g_hook_list_invoke(bo_final_hook_list, TRUE);
189 : 0 : }
190 : :
191 : : void
192 : 0 : gnc_book_option_register_cb (const gchar *key, GncBOCb func, gpointer user_data)
193 : : {
194 : : GHookList *hook_list;
195 : : GHook *hook;
196 : :
197 : 0 : g_once(&bo_init_once, bo_init, NULL);
198 : 0 : hook_list = g_hash_table_lookup(bo_callback_hash, key);
199 : 0 : if (hook_list == NULL)
200 : : {
201 : 0 : hook_list = g_malloc(sizeof(GHookList));
202 : 0 : g_hook_list_init(hook_list, sizeof(GHook));
203 : 0 : g_hash_table_insert(bo_callback_hash, (gpointer)key, hook_list);
204 : : }
205 : :
206 : 0 : hook = g_hook_find_func_data(hook_list, TRUE, func, user_data);
207 : 0 : if (hook != NULL)
208 : : {
209 : 0 : return;
210 : : }
211 : :
212 : 0 : hook = g_hook_alloc(hook_list);
213 : 0 : hook->func = func;
214 : 0 : hook->data = user_data;
215 : 0 : g_hook_append(hook_list, hook);
216 : : }
217 : :
218 : : void
219 : 0 : gnc_book_option_remove_cb (const gchar *key, GncBOCb func, gpointer user_data)
220 : : {
221 : : GHookList *hook_list;
222 : : GHook *hook;
223 : :
224 : 0 : g_once(&bo_init_once, bo_init, NULL);
225 : 0 : hook_list = g_hash_table_lookup(bo_callback_hash, key);
226 : 0 : if (hook_list == NULL)
227 : 0 : return;
228 : 0 : hook = g_hook_find_func_data(hook_list, TRUE, func, user_data);
229 : 0 : if (hook == NULL)
230 : 0 : return;
231 : :
232 : 0 : g_hook_destroy_link(hook_list, hook);
233 : 0 : if (hook_list->hooks == NULL)
234 : : {
235 : 0 : g_hash_table_remove(bo_callback_hash, key);
236 : 0 : g_free(hook_list);
237 : : }
238 : : }
239 : :
240 : :
|