GnuCash  5.6-150-g038405b370+
SX-book.cpp
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 GNC_ACCOUNT(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(QOF_INSTANCE(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  auto rtn = GNC_SCHEDXACTIONS (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 
264  col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
265  auto sxes = GNC_SCHEDXACTIONS (g_object_new (GNC_TYPE_SCHEDXACTIONS, NULL));
266  g_assert(sxes);
267  qof_instance_init_data(&sxes->inst, GNC_ID_SXES, book);
268  sxes->sx_list = NULL;
269  sxes->sx_notsaved = TRUE;
270  qof_collection_set_data(col, sxes);
271 }
272 
273 static void
274 book_sxes_end(QofBook* book)
275 {
276  QofCollection *col;
277 
278  col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION);
279  auto sxes = GNC_SCHEDXACTIONS (qof_collection_get_data(col));
280  if (sxes != NULL)
281  {
282  g_list_free(sxes->sx_list);
283  g_object_unref(sxes);
284  qof_collection_set_data(col, NULL);
285  }
286 }
287 
288 static void
289 book_sxns_mark_saved(QofCollection *col)
290 {
291  SchedXactions *sxl;
292  sxl = gnc_collection_get_schedxactions(col);
293  if (!sxl)
294  return;
295  sxl->sx_notsaved = FALSE;
296  g_list_foreach(sxl->sx_list,
297  mark_sx_clean,
298  NULL);
299 }
300 
301 static gboolean
302 book_sxlist_notsaved(const QofCollection *col)
303 {
304  GList *sxlist;
305  SchedXactions *sxl;
306 
307  sxl = gnc_collection_get_schedxactions(col);
308  if (!sxl) return FALSE;
309  if (sxl->sx_notsaved) return TRUE;
310 
311  for (sxlist = sxl->sx_list;
312  sxlist != NULL;
313  sxlist = g_list_next(sxlist))
314  {
315  SchedXaction *sx;
316  sx = (SchedXaction *) (sxlist->data);
317  if (xaccSchedXactionIsDirty( sx ))
318  return TRUE;
319  }
320 
321  return FALSE;
322 }
323 
324 static QofObject sxes_object_def =
325 {
326  DI(.interface_version = ) QOF_OBJECT_VERSION,
327  DI(.e_type = ) GNC_ID_SXES,
328  DI(.type_label = ) "Scheduled Transactions List",
329  DI(.create = ) NULL,
330  DI(.book_begin = ) book_sxes_setup,
331  DI(.book_end = ) book_sxes_end,
332  DI(.is_dirty = ) book_sxlist_notsaved,
333  DI(.mark_clean = ) book_sxns_mark_saved,
334  DI(.foreach = ) NULL,
335  DI(.printable = ) NULL,
336  DI(.version_cmp = ) NULL
337 };
338 
339 static QofObject sxtt_object_def =
340 {
341  DI(.interface_version = ) QOF_OBJECT_VERSION,
342  DI(.e_type = ) GNC_ID_SXTT,
343  DI(.type_label = ) "Scheduled Transaction Templates",
344  DI(.create = ) NULL,
345  DI(.book_begin = ) NULL,
346  DI(.book_end = ) NULL,
347  DI(.is_dirty = ) NULL,
348  DI(.mark_clean = ) NULL,
349  DI(.foreach = ) NULL,
350  DI(.printable = ) NULL,
351  DI(.version_cmp = ) NULL,
352 };
353 
354 gboolean
355 gnc_sxtt_register (void)
356 {
357  if (!qof_object_register(&sxes_object_def))
358  return FALSE;
359  if (!qof_object_register(&sxtg_object_def))
360  return FALSE;
361  return qof_object_register(&sxtt_object_def);
362 }
363 
364 GList*
366 {
367  GList *rtn = NULL;
368  const GncGUID *acct_guid = qof_entity_get_guid(QOF_INSTANCE(acct));
369  GList *sx_list;
370  SchedXactions *sxactions = gnc_book_get_schedxactions(book);
371  g_return_val_if_fail( sxactions != NULL, rtn);
372  for (sx_list = sxactions->sx_list; sx_list != NULL; sx_list = sx_list->next)
373  {
374  SchedXaction *sx = (SchedXaction*)sx_list->data;
375  GList *splits = xaccSchedXactionGetSplits(sx);
376  for (GList *node = splits; node; node = node->next)
377  {
378  Split *s = (Split*)node->data;
379  GncGUID *guid = NULL;
380  qof_instance_get (QOF_INSTANCE (s), "sx-account", &guid, NULL);
381  if (guid_equal(acct_guid, guid))
382  rtn = g_list_prepend (rtn, sx);
383 
384  guid_free (guid);
385  }
386  g_list_free (splits);
387  }
388  return g_list_reverse (rtn);
389 }
390 
391 /* ========================== END OF FILE =============================== */
void xaccAccountSetType(Account *acc, GNCAccountType tip)
Set the account&#39;s type.
Definition: Account.cpp:2418
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:166
STRUCTS.
Account * gnc_book_get_template_root(const QofBook *book)
Returns the template group from the book.
Definition: SX-book.cpp: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:63
GList * gnc_sx_get_sxes_referencing_account(QofBook *book, Account *acct)
Definition: SX-book.cpp:365
void xaccAccountDestroy(Account *acc)
The xaccAccountDestroy() routine can be used to get rid of an account.
Definition: Account.cpp:1593
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:317
void qof_collection_mark_clean(QofCollection *)
reset value of dirty flag
Definition: qofid.cpp:261
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:3005
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1479
Account * xaccMallocAccount(QofBook *book)
Constructor.
Definition: Account.cpp:1275
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:521
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
Definition: qofobject.cpp:299
gpointer qof_collection_get_data(const QofCollection *col)
Store and retrieve arbitrary object-defined data.
Definition: qofid.cpp:289
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:1520
void xaccAccountSetName(Account *acc, const char *str)
Set the account&#39;s name.
Definition: Account.cpp:2439
The hidden root account of an account tree.
Definition: Account.h:153