GnuCash c935c2f+
Loading...
Searching...
No Matches
io-example-account.cpp
1/********************************************************************\
2 * io-example-account.c -- implementation for example accounts *
3 * *
4 * Copyright (C) 2001 James LewisMoss <dres@debian.org> *
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 <glib.h>
25#include <glib/gi18n.h>
26#include <glib/gstdio.h>
27
28#include <config.h>
29
30#include <platform.h>
31#if PLATFORM(WINDOWS)
32#include <windows.h>
33#endif
34
35#include <sys/types.h>
36#include <ctype.h>
37#ifdef HAVE_DIRENT_H
38# include <dirent.h>
39#endif
40#include <string.h>
41#include <sys/stat.h>
42#ifdef HAVE_UNISTD_H
43# include <unistd.h>
44#endif
45
46#include "gnc-engine.h"
47#include "Scrub.h"
48#include "TransLog.h"
49#include "platform.h"
50#if COMPILER(MSVC)
51# define g_fopen fopen
52#endif
53
54#include "sixtp.h"
55
56#include "gnc-xml.h"
57#include "io-example-account.h"
58#include "io-gncxml-gen.h"
59#include "io-utils.h"
60#include "sixtp-dom-generators.h"
61#include "sixtp-dom-parsers.h"
62#include "sixtp-parsers.h"
63
64
65static QofLogModule log_module = GNC_MOD_IO;
66
67#define GNC_ACCOUNT_STRING "gnc-account-example"
68#define GNC_ACCOUNT_SHORT "gnc-act:short-description"
69#define GNC_ACCOUNT_LONG "gnc-act:long-description"
70#define GNC_ACCOUNT_TITLE "gnc-act:title"
71#define GNC_ACCOUNT_EXCLUDEP "gnc-act:exclude-from-select-all"
72#define GNC_ACCOUNT_SELECTED "gnc-act:start-selected"
73
74void
75gnc_destroy_example_account (GncExampleAccount* gea)
76{
77 if (gea->title != NULL)
78 {
79 g_free (gea->title);
80 gea->title = NULL;
81 }
82 if (gea->filename != NULL)
83 {
84 g_free (gea->filename);
85 gea->filename = NULL;
86 }
87 if (gea->root != NULL)
88 {
89 xaccAccountBeginEdit (gea->root);
90 xaccAccountDestroy (gea->root);
91 gea->root = NULL;
92 }
93 if (gea->short_description != NULL)
94 {
95 g_free (gea->short_description);
96 gea->short_description = NULL;
97 }
98 if (gea->long_description != NULL)
99 {
100 g_free (gea->long_description);
101 gea->long_description = NULL;
102 }
103 if (gea->book != NULL)
104 {
105 qof_book_destroy (gea->book);
106 gea->book = NULL;
107 }
108 g_free (gea);
109}
110
111static void
112clear_up_account_commodity (
113 gnc_commodity_table* tbl, Account* act,
114 gnc_commodity * (*getter) (const Account* account),
115 void (*setter) (Account* account, gnc_commodity* comm))
116{
117 gnc_commodity* gcom;
118 gnc_commodity* com = getter (act);
119
120 if (!com)
121 {
122 return;
123 }
124
125 g_return_if_fail (tbl != NULL);
126
127 gcom = gnc_commodity_table_lookup (tbl,
130
131 if (gcom == com)
132 {
133 return;
134 }
135 else if (!gcom)
136 {
137 PWARN ("unable to find global commodity for %s adding new",
140 }
141 else
142 {
143 setter (act, gcom);
145 }
146}
147
148static void
149add_account_local (GncExampleAccount* gea, Account* act)
150{
151 gnc_commodity_table* table;
152
154
155 clear_up_account_commodity (table, act,
158
160
161 if (xaccAccountGetType (act) == ACCT_TYPE_ROOT)
162 {
163 gea->root = act;
164 }
165 else if (!gnc_account_get_parent (act))
166 {
167 if (!gea->root)
168 {
169 g_warning ("The example account file should declared a ROOT "
170 "account before declaring any other accounts.");
171 gea->root = gnc_book_get_root_account (gea->book);
172 }
173 gnc_account_append_child (gea->root, act);
174 }
175}
176
177static gboolean
178generic_callback (const char* tag, gpointer globaldata, gpointer data)
179{
180 GncExampleAccount* gea = (GncExampleAccount*)globaldata;
181
182 if (g_strcmp0 (tag, "gnc:account") == 0)
183 {
184 add_account_local (gea, (Account*)data);
185 }
186 return TRUE;
187}
188
189static char*
190squash_extra_whitespace (char* text)
191{
192 int spot;
193 int length = strlen (text);
194
195 for (spot = 1; spot < length; spot++)
196 {
197 if (isspace (text[spot]) && isspace (text[spot - 1]))
198 {
199 memmove (text + spot, text + spot + 1, length - spot + 1);
200 length--;
201 }
202 else
203 {
204 spot++;
205 }
206 }
207 return text;
208}
209
210static char*
211grab_clean_string (xmlNodePtr tree)
212{
213 auto txt = dom_tree_to_text (tree);
214 auto str = g_strdup (txt ? txt->c_str() : "");
215 return squash_extra_whitespace (g_strstrip (str));
216}
217
218static gboolean
219gnc_short_descrip_end_handler (gpointer data_for_children,
220 GSList* data_from_children, GSList* sibling_data,
221 gpointer parent_data, gpointer global_data,
222 gpointer* result, const gchar* tag)
223{
224 GncExampleAccount* gea =
225 (GncExampleAccount*) ((gxpf_data*)global_data)->parsedata;
226
227 gea->short_description = grab_clean_string ((xmlNodePtr)data_for_children);
228
229 return TRUE;
230}
231
232static sixtp*
233gnc_short_descrip_sixtp_parser_create (void)
234{
235 return sixtp_dom_parser_new (gnc_short_descrip_end_handler, NULL, NULL);
236}
237
238static gboolean
239gnc_long_descrip_end_handler (gpointer data_for_children,
240 GSList* data_from_children, GSList* sibling_data,
241 gpointer parent_data, gpointer global_data,
242 gpointer* result, const gchar* tag)
243{
244 GncExampleAccount* gea =
245 (GncExampleAccount*) ((gxpf_data*)global_data)->parsedata;
246
247 gea->long_description = grab_clean_string ((xmlNodePtr)data_for_children);
248
249 return TRUE;
250}
251
252static sixtp*
253gnc_long_descrip_sixtp_parser_create (void)
254{
255 return sixtp_dom_parser_new (gnc_long_descrip_end_handler, NULL, NULL);
256}
257
258static gboolean
259gnc_excludep_end_handler (gpointer data_for_children,
260 GSList* data_from_children, GSList* sibling_data,
261 gpointer parent_data, gpointer global_data,
262 gpointer* result, const gchar* tag)
263{
264 GncExampleAccount* gea =
265 (GncExampleAccount*) ((gxpf_data*)global_data)->parsedata;
266 gint64 val = 0;
267
268 dom_tree_to_integer ((xmlNodePtr)data_for_children, &val);
269 gea->exclude_from_select_all = (val ? TRUE : FALSE);
270
271 return TRUE;
272}
273
274static sixtp*
275gnc_excludep_sixtp_parser_create (void)
276{
277 return sixtp_dom_parser_new (gnc_excludep_end_handler, NULL, NULL);
278}
279
280static gboolean
281gnc_selected_end_handler (gpointer data_for_children,
282 GSList* data_from_children, GSList* sibling_data,
283 gpointer parent_data, gpointer global_data,
284 gpointer* result, const gchar* tag)
285{
286 GncExampleAccount* gea =
287 (GncExampleAccount*) ((gxpf_data*)global_data)->parsedata;
288 gint64 val = 0;
289
290 dom_tree_to_integer ((xmlNodePtr)data_for_children, &val);
291 gea->start_selected = (val ? TRUE : FALSE);
292
293 return TRUE;
294}
295
296static sixtp*
297gnc_selected_sixtp_parser_create (void)
298{
299 return sixtp_dom_parser_new (gnc_selected_end_handler, NULL, NULL);
300}
301
302static gboolean
303gnc_title_end_handler (gpointer data_for_children,
304 GSList* data_from_children, GSList* sibling_data,
305 gpointer parent_data, gpointer global_data,
306 gpointer* result, const gchar* tag)
307{
308 GncExampleAccount* gea =
309 (GncExampleAccount*) ((gxpf_data*)global_data)->parsedata;
310
311 gea->title = grab_clean_string ((xmlNodePtr)data_for_children);
312
313 return TRUE;
314}
315
316static sixtp*
317gnc_titse_sixtp_parser_create (void)
318{
319 return sixtp_dom_parser_new (gnc_title_end_handler, NULL, NULL);
320}
321
322
323GncExampleAccount*
324gnc_read_example_account (const gchar* filename)
325{
326 GncExampleAccount* gea;
327 sixtp* top_parser;
328 sixtp* main_parser;
329
330 g_return_val_if_fail (filename != NULL, NULL);
331
332 gea = g_new0 (GncExampleAccount, 1);
333
334 gea->book = qof_book_new ();
335 gea->filename = g_strdup (filename);
336
337 top_parser = sixtp_new ();
338 main_parser = sixtp_new ();
339
340 if (!sixtp_add_some_sub_parsers (
341 top_parser, TRUE,
342 GNC_ACCOUNT_STRING, main_parser,
343 NULL, NULL))
344 {
345 gnc_destroy_example_account (gea);
346 return FALSE;
347 }
348
349 if (!sixtp_add_some_sub_parsers (
350 main_parser, TRUE,
351 GNC_ACCOUNT_TITLE, gnc_titse_sixtp_parser_create (),
352 GNC_ACCOUNT_SHORT, gnc_short_descrip_sixtp_parser_create (),
353 GNC_ACCOUNT_LONG, gnc_long_descrip_sixtp_parser_create (),
354 GNC_ACCOUNT_EXCLUDEP, gnc_excludep_sixtp_parser_create (),
355 GNC_ACCOUNT_SELECTED, gnc_selected_sixtp_parser_create (),
356 "gnc:account", gnc_account_sixtp_parser_create (),
357 NULL, NULL))
358 {
359 gnc_destroy_example_account (gea);
360 return FALSE;
361 }
362
363 if (!gnc_xml_parse_file (top_parser, filename,
364 generic_callback, gea, gea->book))
365 {
366 sixtp_destroy (top_parser);
367 xaccLogEnable ();
368 gnc_destroy_example_account (gea);
369 return FALSE;
370 }
371
372 return gea;
373}
374
375static void
376write_string_part (FILE* out, const char* tag, const char* data)
377{
378 xmlNodePtr node;
379
380 node = text_to_dom_tree (tag, data);
381
382 xmlElemDump (out, NULL, node);
383 fprintf (out, "\n");
384
385 xmlFreeNode (node);
386}
387
388static void
389write_bool_part (FILE* out, const char* tag, gboolean data)
390{
391 xmlNodePtr node;
392
393 node = int_to_dom_tree (tag, data);
394
395 xmlElemDump (out, NULL, node);
396 fprintf (out, "\n");
397
398 xmlFreeNode (node);
399}
400
401gboolean
402gnc_write_example_account (GncExampleAccount* gea, const gchar* filename)
403{
404 FILE* out;
405 sixtp_gdv2 data = { 0 };
406
407 out = g_fopen (filename, "w");
408 if (out == NULL)
409 {
410 return FALSE;
411 }
412
413 fprintf (out, "<?xml version=\"1.0\"?>\n");
414 fprintf (out, "<" GNC_ACCOUNT_STRING ">\n");
415
416 write_string_part (out, GNC_ACCOUNT_TITLE, gea->title);
417
418 write_string_part (out, GNC_ACCOUNT_SHORT, gea->short_description);
419
420 write_string_part (out, GNC_ACCOUNT_LONG, gea->long_description);
421
422 write_bool_part (out, GNC_ACCOUNT_EXCLUDEP, gea->exclude_from_select_all);
423
424 write_account_tree (out, gea->root, &data);
425
426 fprintf (out, "</" GNC_ACCOUNT_STRING ">\n\n");
427
428 fclose (out);
429
430 return TRUE;
431
432}
433
434/***********************************************************************/
435
436static void
437slist_destroy_example_account (gpointer data, gpointer user_data)
438{
439 if (data != NULL)
440 {
441 gnc_destroy_example_account ((GncExampleAccount*)data);
442 }
443 else
444 {
445 PWARN ("GncExampleAccount pointer in slist was NULL");
446 }
447}
448
449void
450gnc_free_example_account_list (GSList* list)
451{
452 g_slist_foreach (list, slist_destroy_example_account, NULL);
453 g_slist_free (list);
454}
455
456GSList*
457gnc_load_example_account_list (const char* dirname)
458{
459 GSList* ret;
460 GDir* dir;
461 const gchar* direntry;
462
463 dir = g_dir_open (dirname, 0, NULL);
464
465 if (dir == NULL)
466 {
467 return NULL;
468 }
469
470 ret = NULL;
471
472 for (direntry = g_dir_read_name (dir); direntry != NULL;
473 direntry = g_dir_read_name (dir))
474 {
475 gchar* filename;
476 GncExampleAccount* gea;
477 if (!g_str_has_suffix (direntry, "xea"))
478 continue;
479
480 filename = g_build_filename (dirname, direntry, (gchar*) NULL);
481
482 if (!g_file_test (filename, G_FILE_TEST_IS_DIR))
483 {
484 gea = gnc_read_example_account (filename);
485
486 if (gea == NULL)
487 {
488 g_free (filename);
489 gnc_free_example_account_list (ret);
490 g_dir_close (dir);
491 return NULL;
492 }
493
494 ret = g_slist_append (ret, gea);
495 }
496
497 g_free (filename);
498 }
499 g_dir_close (dir);
500
501 return ret;
502}
503
504
505
506/***********************************************************************/
507/*
508gboolean
509gnc_is_example_account_xml(const gchar *name)
510{
511 return gnc_is_our_xml_file(name, GNC_ACCOUNT_STRING, NULL);
512} */
convert single-entry accounts to clean double-entry
API for the transaction logger.
All type declarations for the whole Gnucash engine.
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition Account.cpp:1475
void gnc_account_append_child(Account *new_parent, Account *child)
This function will remove from the child account any pre-existing parent relationship,...
Definition Account.cpp:2836
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
Definition Account.cpp:3267
void xaccAccountDestroy(Account *acc)
The xaccAccountDestroy() routine can be used to get rid of an account.
Definition Account.cpp:1590
Account * gnc_account_get_parent(const Account *acc)
This routine returns a pointer to the parent of the specified account.
Definition Account.cpp:2935
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity
Definition Account.cpp:3408
void xaccAccountSetCommodity(Account *acc, gnc_commodity *com)
Set the account's commodity.
Definition Account.cpp:2678
void qof_book_destroy(QofBook *book)
End any editing sessions associated with book, and free all memory associated with it.
Definition qofbook.cpp:331
QofBook * qof_book_new(void)
Allocate, initialise and return a new QofBook.
Definition qofbook.cpp:290
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
Retrieve the namespace for the specified commodity.
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
gnc_commodity * gnc_commodity_table_insert(gnc_commodity_table *table, gnc_commodity *comm)
Add a new commodity to the commodity table.
void gnc_commodity_destroy(gnc_commodity *cm)
Destroy a commodity.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
const char * gnc_commodity_get_unique_name(const gnc_commodity *cm)
Retrieve the 'unique' name for the specified commodity.
#define PWARN(format, args...)
Log a warning.
Definition qoflog.h:250
void xaccAccountScrubCommodity(Account *account)
The xaccAccountScrubCommodity method fixed accounts without a commodity by using the old account curr...
Definition Scrub.cpp:1238
void xaccLogEnable(void)
document me
Definition TransLog.cpp:100
STRUCTS.
Definition sixtp.h:130