GnuCash  4.13-177-g21dd8aa057+
SX-book.c
1 /********************************************************************\
2  * SX-book.c -- scheduled transaction dataset access *
3  * *
4  * This program is free software; you can redistribute it and/or *
5  * modify it under the terms of the GNU General Public License as *
6  * published by the Free Software Foundation; either version 2 of *
7  * the License, or (at your option) any later version. *
8  * *
9  * This program is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12  * GNU General Public License for more details. *
13  * *
14  * You should have received a copy of the GNU General Public License*
15  * along with this program; if not, contact: *
16  * *
17  * Free Software Foundation Voice: +1-617-542-5942 *
18  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19  * Boston, MA 02110-1301, USA gnu@gnu.org *
20 \********************************************************************/
21 
22 /*
23  * FILE:
24  * SX-book.c
25  *
26  * FUNCTION:
27  * Anchor Scheduled Transaction Info into the book.
28  * See src/doc/books.txt for design overview.
29  *
30  * HISTORY:
31  * Copyright (c) 2003 Linas Vepstas <linas@linas.org>
32  */
33 
34 #include <config.h>
35 
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include <glib.h>
40 
41 #include "gnc-engine.h"
42 #include "Account.h"
43 #include "Split.h"
44 #include "SchedXaction.h"
45 #include "SX-book.h"
46 #include "SX-book-p.h"
47 #include "gnc-event.h"
48 #include <qofinstance-p.h>
49 
50 #undef G_LOG_DOMAIN
51 #define G_LOG_DOMAIN "gnc.engine.sx"
52 
53 /* XXX this whole file is crufty, it doesn't really use entities
54  * in the most efficient/best way */
55 
56 /* ====================================================================== */
57 
58 static Account *
59 gnc_collection_get_template_root( const QofCollection *col )
60 {
61  return qof_collection_get_data (col);
62 }
63 
64 Account *
65 gnc_book_get_template_root( const QofBook *book )
66 {
67  QofCollection *col;
68  if (!book) return NULL;
69  col = qof_book_get_collection (book, GNC_ID_SXTG);
70  return gnc_collection_get_template_root (col);
71 }
72 
73 static void
74 gnc_collection_set_template_root (QofCollection *col,
75  Account *templateRoot)
76 {
77  Account *old_root;
78  if (!col) return;
79 
80  old_root = gnc_collection_get_template_root (col);
81  if (old_root == templateRoot) return;
82 
83  qof_collection_set_data (col, templateRoot);
84 
85  if (old_root)
86  {
87  xaccAccountBeginEdit (old_root);
88  xaccAccountDestroy (old_root);
89  }
90 }
91 
92 
93 void
94 gnc_book_set_template_root (QofBook *book, Account *templateRoot)
95 {
96  QofCollection *col;
97  if (!book) return;
98 
99  if (templateRoot && gnc_account_get_book(templateRoot) != book)
100  {
101  g_critical("cannot mix and match books freely!");
102  return;
103  }
104 
105  col = qof_book_get_collection (book, GNC_ID_SXTG);
106  gnc_collection_set_template_root (col, templateRoot);
107 }
108 
109 
110 /* ====================================================================== */
111 /* gncObject function implementation and registration */
112 
113 static void
114 sxtg_book_begin (QofBook *book)
115 {
116  Account *root;
117 
118  root = xaccMallocAccount(book);
119  xaccAccountBeginEdit(root);
121  xaccAccountSetName(root, "Template Root");
122  qof_instance_set_dirty (QOF_INSTANCE (root));
123  xaccAccountCommitEdit(root);
124  gnc_book_set_template_root (book, root);
125 }
126 
127 static void
128 sxtg_book_end (QofBook *book)
129 {
130  gnc_book_set_template_root (book, NULL);
131 }
132 
133 static gboolean
134 sxtg_is_dirty(const QofCollection *col)
135 {
136  Account *root;
137  GList *descendants, *node;
138  gboolean dirty = FALSE;
139 
140  root = gnc_collection_get_template_root(col);
141  descendants = gnc_account_get_descendants(root);
142  for (node = descendants; node; node = g_list_next(node))
143  {
144  if (qof_instance_is_dirty(node->data))
145  {
146  dirty = TRUE;
147  break;
148  }
149  }
150  g_list_free(descendants);
151 
152  return dirty;
153 }
154 
155 /* EFFECTIVE FRIEND FUNCTION declared in qofinstance-p.h */
156 extern void qof_instance_mark_clean (QofInstance *);
157 
158 static void
159 sxtg_mark_clean(QofCollection *col)
160 {
161  Account *root;
162  GList *descendants;
163 
164  root = gnc_collection_get_template_root(col);
166 
167  descendants = gnc_account_get_descendants(root);
168  g_list_foreach(descendants, (GFunc)qof_instance_mark_clean, NULL);
169  g_list_free(descendants);
170 }
171 
172 #ifdef _MSC_VER
173 /* MSVC compiler doesn't have C99 "designated initializers"
174  * so we wrap them in a macro that is empty on MSVC. */
175 # define DI(x) /* */
176 #else
177 # define DI(x) x
178 #endif
179 static QofObject sxtg_object_def =
180 {
181  DI(.interface_version = ) QOF_OBJECT_VERSION,
182  DI(.e_type = ) GNC_ID_SXTG,
183  DI(.type_label = ) "Scheduled Transaction Group",
184  DI(.create = ) NULL,
185  DI(.book_begin = ) sxtg_book_begin,
186  DI(.book_end = ) sxtg_book_end,
187  DI(.is_dirty = ) sxtg_is_dirty,
188  DI(.mark_clean = ) sxtg_mark_clean,
189  DI(.foreach = ) NULL,
190  DI(.printable = ) NULL,
191 };
192 
193 /* ====================================================================== */
194 
195 SchedXactions*
196 gnc_collection_get_schedxactions(const QofCollection *col)
197 {
198  SchedXactions *rtn = qof_collection_get_data(col);
199  // @@assert(rtn != null);
200  return rtn;
201 }
202 
203 SchedXactions*
204 gnc_book_get_schedxactions(QofBook *book)
205 {
206  QofCollection *col;
207  col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
208  return gnc_collection_get_schedxactions(col);
209 }
210 
211 void
212 gnc_sxes_add_sx(SchedXactions *sxes, SchedXaction *sx)
213 {
214  if (g_list_find(sxes->sx_list, sx) != NULL)
215  return;
216  sxes->sx_list = g_list_append(sxes->sx_list, sx);
217  qof_event_gen(&sxes->inst, GNC_EVENT_ITEM_ADDED, (gpointer)sx);
218 }
219 
220 void
221 gnc_sxes_del_sx(SchedXactions *sxes, SchedXaction *sx)
222 {
223  GList *to_remove;
224  to_remove = g_list_find(sxes->sx_list, sx);
225  if (to_remove == NULL)
226  return;
227  sxes->sx_list = g_list_delete_link(sxes->sx_list, to_remove);
228  qof_event_gen(&sxes->inst, GNC_EVENT_ITEM_REMOVED, (gpointer)sx);
229 }
230 
231 /* ====================================================================== */
232 /* SX-trans stuff */
233 
234 /* GObject initialization */
235 QOF_GOBJECT_IMPL(gnc_schedxactions, SchedXactions, QOF_TYPE_INSTANCE);
236 
237 static void
238 gnc_schedxactions_init(SchedXactions* sxs)
239 {
240 }
241 
242 static void
243 gnc_schedxactions_dispose_real (GObject *sxsp)
244 {
245 }
246 
247 static void
248 gnc_schedxactions_finalize_real(GObject* sxsp)
249 {
250 }
251 
252 static void
253 mark_sx_clean(gpointer data, gpointer user_data)
254 {
255  SchedXaction *sx = (SchedXaction *) data;
256  qof_instance_mark_clean (QOF_INSTANCE(sx));
257 }
258 
259 static void
260 book_sxes_setup(QofBook *book)
261 {
262  QofCollection *col;
263  SchedXactions *sxes;
264 
265  col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
266  sxes = g_object_new (GNC_TYPE_SCHEDXACTIONS, NULL);
267  g_assert(sxes);
268  qof_instance_init_data(&sxes->inst, GNC_ID_SXES, book);
269  sxes->sx_list = NULL;
270  sxes->sx_notsaved = TRUE;
271  qof_collection_set_data(col, sxes);
272 }
273 
274 static void
275 book_sxes_end(QofBook* book)
276 {
277  QofCollection *col;
278  SchedXactions *sxes;
279 
280  col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
281  sxes = qof_collection_get_data(col);
282  if (sxes != NULL)
283  {
284  g_list_free(sxes->sx_list);
285  g_object_unref(sxes);
286  qof_collection_set_data(col, NULL);
287  }
288 }
289 
290 static void
291 book_sxns_mark_saved(QofCollection *col)
292 {
293  SchedXactions *sxl;
294  sxl = gnc_collection_get_schedxactions(col);
295  if (!sxl)
296  return;
297  sxl->sx_notsaved = FALSE;
298  g_list_foreach(sxl->sx_list,
299  mark_sx_clean,
300  NULL);
301 }
302 
303 static gboolean
304 book_sxlist_notsaved(const QofCollection *col)
305 {
306  GList *sxlist;
307  SchedXactions *sxl;
308 
309  sxl = gnc_collection_get_schedxactions(col);
310  if (!sxl) return FALSE;
311  if (sxl->sx_notsaved) return TRUE;
312 
313  for (sxlist = sxl->sx_list;
314  sxlist != NULL;
315  sxlist = g_list_next(sxlist))
316  {
317  SchedXaction *sx;
318  sx = (SchedXaction *) (sxlist->data);
319  if (xaccSchedXactionIsDirty( sx ))
320  return TRUE;
321  }
322 
323  return FALSE;
324 }
325 
326 static QofObject sxes_object_def =
327 {
328  DI(.interface_version = ) QOF_OBJECT_VERSION,
329  DI(.e_type = ) GNC_ID_SXES,
330  DI(.type_label = ) "Scheduled Transactions List",
331  DI(.create = ) NULL,
332  DI(.book_begin = ) book_sxes_setup,
333  DI(.book_end = ) book_sxes_end,
334  DI(.is_dirty = ) book_sxlist_notsaved,
335  DI(.mark_clean = ) book_sxns_mark_saved,
336  DI(.foreach = ) NULL,
337  DI(.printable = ) NULL,
338  DI(.version_cmp = ) NULL
339 };
340 
341 static QofObject sxtt_object_def =
342 {
343  DI(.interface_version = ) QOF_OBJECT_VERSION,
344  DI(.e_type = ) GNC_ID_SXTT,
345  DI(.type_label = ) "Scheduled Transaction Templates",
346  DI(.create = ) NULL,
347  DI(.book_begin = ) NULL,
348  DI(.book_end = ) NULL,
349  DI(.is_dirty = ) NULL,
350  DI(.mark_clean = ) NULL,
351  DI(.foreach = ) NULL,
352  DI(.printable = ) NULL,
353  DI(.version_cmp = ) NULL,
354 };
355 
356 gboolean
357 gnc_sxtt_register (void)
358 {
359  if (!qof_object_register(&sxes_object_def))
360  return FALSE;
361  if (!qof_object_register(&sxtg_object_def))
362  return FALSE;
363  return qof_object_register(&sxtt_object_def);
364 }
365 
366 GList*
368 {
369  GList *rtn = NULL;
370  const GncGUID *acct_guid = qof_entity_get_guid(QOF_INSTANCE(acct));
371  GList *sx_list;
372  SchedXactions *sxactions = gnc_book_get_schedxactions(book);
373  g_return_val_if_fail( sxactions != NULL, rtn);
374  for (sx_list = sxactions->sx_list; sx_list != NULL; sx_list = sx_list->next)
375  {
376  SchedXaction *sx = (SchedXaction*)sx_list->data;
377  GList *splits = xaccSchedXactionGetSplits(sx);
378  for (; splits != NULL; splits = splits->next)
379  {
380  Split *s = (Split*)splits->data;
381  GncGUID *guid = NULL;
382  qof_instance_get (QOF_INSTANCE (s), "sx-account", &guid, NULL);
383  if (guid_equal(acct_guid, guid))
384  rtn = g_list_prepend (rtn, sx);
385 
386  guid_free (guid);
387  }
388  }
389  return g_list_reverse (rtn);
390 }
391 
392 /* ========================== END OF FILE =============================== */
void xaccAccountSetType(Account *acc, GNCAccountType tip)
Set the account&#39;s type.
Definition: Account.cpp:2432
void qof_instance_get(const QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_get.
#define qof_instance_is_dirty
Return value of is_dirty flag.
Definition: qofinstance.h:162
Account * gnc_book_get_template_root(const QofBook *book)
Returns the template group from the book.
Definition: SX-book.c:65
API for Transactions and Splits (journal entries)
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
Definition: qofobject.h:64
GList * gnc_sx_get_sxes_referencing_account(QofBook *book, Account *acct)
Definition: SX-book.c:367
void xaccAccountDestroy(Account *acc)
The xaccAccountDestroy() routine can be used to get rid of an account.
Definition: Account.cpp:1575
void qof_instance_init_data(QofInstance *inst, QofIdType type, QofBook *book)
Initialise the settings associated with an instance.
Account handling public routines.
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
Given two GUIDs, return TRUE if they are non-NULL and equal.
Definition: guid.cpp:204
Anchor Scheduled Transaction info in a book.
#define xaccSchedXactionIsDirty(X)
Definition: SchedXaction.h:321
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
Definition: qofid.cpp:263
Additional event handling code.
All type declarations for the whole Gnucash engine.
const GncGUID * qof_entity_get_guid(gconstpointer ent)
GList * gnc_account_get_descendants(const Account *account)
This routine returns a flat list of all of the accounts that are descendants of the specified account...
Definition: Account.cpp:3042
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1455
Account * xaccMallocAccount(QofBook *book)
Constructor.
Definition: Account.cpp:1228
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:606
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
Definition: qofobject.cpp:317
gpointer qof_collection_get_data(const QofCollection *col)
Store and retrieve arbitrary object-defined data.
Definition: qofid.cpp:291
void qof_event_gen(QofInstance *entity, QofEventId event_id, gpointer event_data)
Invoke all registered event handlers using the given arguments.
Definition: qofevent.cpp:231
Scheduled Transactions public handling routines.
#define GNC_EVENT_ITEM_ADDED
These events are used when a split is added to an account.
Definition: gnc-event.h:45
The type used to store guids in C.
Definition: guid.h:75
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1496
void xaccAccountSetName(Account *acc, const char *str)
Set the account&#39;s name.
Definition: Account.cpp:2453
The hidden root account of an account tree.
Definition: Account.h:156