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 1076 : gnc_get_num_action (const Transaction *trans, const Split *split)
57 : {
58 1076 : if (trans && !split)
59 0 : return xaccTransGetNum(trans);
60 1076 : if (split && !trans)
61 4 : return xaccSplitGetAction(split);
62 1072 : if (trans && split)
63 : {
64 1072 : QofBook* book = qof_session_get_book(gnc_get_current_session ());
65 1072 : if (!book)
66 : {
67 0 : PERR("Session has no book but has a transaction or split!");
68 0 : return NULL;
69 : }
70 1072 : if (qof_book_use_split_action_for_num_field (book))
71 0 : return xaccSplitGetAction(split);
72 : else
73 1072 : 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 295 : gnc_get_action_num (const Transaction *trans, const Split *split)
86 : {
87 295 : gboolean num_action = qof_book_use_split_action_for_num_field
88 295 : (qof_session_get_book(gnc_get_current_session ()));
89 :
90 295 : if (trans && !split)
91 0 : return xaccTransGetNum(trans);
92 295 : if (split && !trans)
93 267 : 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 348 : gnc_set_num_action (Transaction *trans, Split *split,
117 : const char *num, const char *action)
118 : {
119 348 : gboolean num_action = qof_book_use_split_action_for_num_field
120 348 : (qof_session_get_book(gnc_get_current_session ()));
121 :
122 348 : if (trans && num && !split && !action)
123 : {
124 0 : xaccTransSetNum (trans, num);
125 0 : return;
126 : }
127 :
128 348 : if (!trans && !num && split && action)
129 : {
130 97 : xaccSplitSetAction (split, action);
131 97 : return;
132 : }
133 :
134 251 : if (trans)
135 : {
136 78 : if (!num_action && num)
137 74 : xaccTransSetNum (trans, num);
138 78 : if (num_action && action)
139 0 : xaccTransSetNum (trans, action);
140 : }
141 :
142 251 : if (split)
143 : {
144 173 : if (!num_action && action)
145 165 : xaccSplitSetAction (split, action);
146 173 : 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 :
|