From 04ecf9ba755e0fd3be7025cf5bbcfb81cbc69d76 Mon Sep 17 00:00:00 2001 From: David Hampton Date: Tue, 22 Aug 2006 00:38:10 +0000 Subject: [PATCH 01/14] Initial removal of the engine Group.h, GroupP.h, and Group.c files. This completely removes the AccountGroup data structure. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/branches/remove-group@14703 57a11ea4-9604-0410-9ed3-97b8803252fd --- gnucash.m4 | 1 - lib/libqof/backend/file/qof-backend-qsf.h | 3 +- lib/libqof/qof/qofinstance-p.h | 3 - lib/libqof/qof/qofinstance.h | 3 + lib/libqof/qof/qofsession.h | 2 +- src/app-utils/gnc-account-merge.c | 31 +- src/app-utils/gnc-account-merge.h | 5 +- src/app-utils/gnc-component-manager.c | 1 - src/app-utils/gnc-ui-util.c | 49 +- src/app-utils/gnc-ui-util.h | 8 +- src/app-utils/guile-util.h | 3 +- src/backend/file/gnc-account-xml-v2.c | 31 +- src/backend/file/gnc-book-xml-v2.c | 29 +- src/backend/file/gnc-commodity-xml-v2.c | 1 - src/backend/file/gnc-schedxaction-xml-v2.c | 19 +- src/backend/file/io-example-account.c | 22 +- src/backend/file/io-example-account.h | 2 +- src/backend/file/io-gncbin-r.c | 1532 ----------------- src/backend/file/io-gncbin.h | 64 - src/backend/file/io-gncxml-v1.c | 110 +- src/backend/file/io-gncxml-v2.c | 84 +- src/backend/file/io-utils.c | 45 +- src/backend/file/io-utils.h | 3 +- src/backend/file/test/test-load-xml2.c | 9 +- src/backend/file/test/test-xml-account.c | 13 +- src/backend/file/test/test-xml-transaction.c | 2 - src/backend/postgres/PostgresBackend.c | 58 +- src/backend/postgres/PostgresBackend.h | 1 - src/backend/postgres/account.c | 100 +- src/backend/postgres/account.h | 6 +- src/backend/postgres/checkpoint.c | 13 +- src/backend/postgres/checkpoint.h | 5 +- src/backend/postgres/events.c | 5 +- src/backend/postgres/table.m4 | 4 +- src/backend/postgres/test/test-db.c | 46 +- src/backend/postgres/test/test-period.c | 11 +- src/backend/postgres/txn.c | 40 +- src/backend/postgres/txn.h | 3 +- src/backend/postgres/txnmass.c | 10 +- src/business/business-core/gncInvoice.c | 2 +- .../business-gnome/business-gnome-utils.c | 3 +- src/business/business-gnome/dialog-payment.c | 2 +- .../business-gnome/gnc-plugin-business.c | 10 +- .../business-gnome/gnc-plugin-page-invoice.c | 2 +- src/business/business-ledger/gncEntryLedger.c | 2 +- .../business-ledger/gncEntryLedgerLoad.c | 14 +- .../business-reports/owner-report.scm | 6 +- src/engine/Account.c | 949 ++++++++-- src/engine/Account.h | 485 +++++- src/engine/AccountP.h | 4 +- src/engine/Group.c | 1322 -------------- src/engine/Group.h | 439 ----- src/engine/GroupP.h | 102 -- src/engine/Makefile.am | 3 - src/engine/Period.c | 120 +- src/engine/SX-book-p.h | 7 +- src/engine/SX-book.c | 75 +- src/engine/SX-book.h | 4 +- src/engine/SchedXaction.c | 8 +- src/engine/Scrub.c | 133 +- src/engine/Scrub.h | 21 +- src/engine/Scrub2.c | 2 - src/engine/Scrub3.c | 15 +- src/engine/Scrub3.h | 5 - src/engine/ScrubP.h | 2 +- src/engine/Split.c | 1 - src/engine/TransLog.c | 1 - src/engine/Transaction.c | 39 +- src/engine/cap-gains.c | 15 +- src/engine/cashobjects.c | 2 - src/engine/engine-helpers.c | 1 - src/engine/engine.scm | 4 +- src/engine/gnc-associate-account.c | 9 +- src/engine/gnc-budget.c | 7 +- src/engine/gnc-engine.c | 1 - src/engine/gnc-engine.h | 5 - src/engine/test-core/test-engine-stuff.c | 111 +- src/engine/test-core/test-engine-stuff.h | 8 +- src/engine/test/test-group-vs-book.c | 70 +- src/engine/test/test-lots.c | 7 +- src/engine/test/test-period.c | 13 +- src/engine/test/test-query.c | 7 +- src/experimental/cgi-bin/gnc-server.c | 11 +- src/experimental/cgi-bin/hello2.c | 11 +- src/experimental/cgi-bin/hello3.c | 11 +- src/gnome-utils/account-quickfill.c | 38 +- src/gnome-utils/account-quickfill.h | 7 +- src/gnome-utils/dialog-account.c | 125 +- src/gnome-utils/dialog-account.h | 23 +- src/gnome-utils/dialog-transfer.c | 2 +- src/gnome-utils/gnc-account-sel.c | 10 +- src/gnome-utils/gnc-file.c | 16 +- src/gnome-utils/gnc-html.c | 1 - src/gnome-utils/gnc-tree-model-account.c | 556 ++---- src/gnome-utils/gnc-tree-model-account.h | 19 +- src/gnome-utils/gnc-tree-model.h | 2 - src/gnome-utils/gnc-tree-view-account.c | 67 +- src/gnome-utils/gnc-tree-view-account.h | 23 +- src/gnome-utils/window-main-summarybar.c | 26 +- src/gnome/dialog-commodities.c | 2 +- src/gnome/dialog-find-transactions.c | 14 +- src/gnome/dialog-sxsincelast.c | 24 +- src/gnome/druid-acct-period.c | 3 +- src/gnome/druid-hierarchy.c | 88 +- src/gnome/druid-merge.c | 10 +- src/gnome/druid-merge.h | 2 +- src/gnome/druid-stock-split.c | 5 +- src/gnome/gnc-plugin-page-account-tree.c | 27 +- src/gnome/gnc-plugin-page-register.c | 12 +- src/gnome/gnc-split-reg.c | 4 +- src/gnome/reconcile-list.c | 7 +- src/gnome/top-level.c | 4 +- src/gnome/window-reconcile.c | 2 +- .../binary-import/druid-commodity.c | 6 +- src/import-export/hbci/druid-hbci-utils.c | 20 +- src/import-export/hbci/gnc-hbci-gettrans.c | 2 +- src/import-export/hbci/gnc-hbci-transfer.c | 4 +- src/import-export/import-account-matcher.c | 6 +- src/import-export/import-backend.c | 2 +- src/import-export/import-match-map.c | 7 +- src/import-export/ofx/gnc-ofx-import.c | 2 +- .../qif-import/druid-qif-import.c | 22 +- .../qif-import/qif-guess-map.scm | 4 +- src/import-export/qif-import/qif-import.scm | 4 +- .../qif-import/qif-merge-groups.scm | 10 +- src/import-export/qif-import/qif-to-gnc.scm | 10 +- .../qif-io-core/qif-acct-table.scm | 4 +- src/import-export/qif-io-core/qif-io-core.scm | 2 +- .../qif-io-core/test/test-import-phase-1.scm | 6 +- src/register/ledger-core/gnc-ledger-display.c | 28 +- .../ledger-core/split-register-control.c | 11 +- .../ledger-core/split-register-load.c | 16 +- .../ledger-core/split-register-model.c | 3 +- src/register/ledger-core/split-register-p.h | 1 - src/register/ledger-core/split-register.c | 2 +- src/register/ledger-core/split-register.h | 1 - .../locale-specific/us/taxtxf-de_DE.scm | 4 +- src/report/locale-specific/us/taxtxf.scm | 4 +- src/report/report-system/html-acct-table.scm | 2 +- src/report/report-system/html-utilities.scm | 6 +- src/report/report-system/report-system.scm | 6 +- src/report/report-system/report-utilities.scm | 72 +- .../standard-reports/account-piecharts.scm | 9 +- .../standard-reports/account-summary.scm | 2 +- .../standard-reports/average-balance.scm | 2 +- src/report/standard-reports/balance-sheet.scm | 4 +- src/report/standard-reports/budget.scm | 2 +- src/report/standard-reports/cash-flow.scm | 4 +- .../standard-reports/category-barchart.scm | 8 +- src/report/standard-reports/daily-reports.scm | 2 +- .../standard-reports/income-statement.scm | 4 +- 151 files changed, 2491 insertions(+), 5380 deletions(-) delete mode 100644 src/backend/file/io-gncbin-r.c delete mode 100644 src/backend/file/io-gncbin.h delete mode 100644 src/engine/Group.c delete mode 100644 src/engine/Group.h delete mode 100644 src/engine/GroupP.h diff --git a/gnucash.m4 b/gnucash.m4 index 18e93bec81..1b667153f7 100644 --- a/gnucash.m4 +++ b/gnucash.m4 @@ -83,7 +83,6 @@ dnl #include #include -#include int main () diff --git a/lib/libqof/backend/file/qof-backend-qsf.h b/lib/libqof/backend/file/qof-backend-qsf.h index 87a1fcdc5f..10a61719d7 100644 --- a/lib/libqof/backend/file/qof-backend-qsf.h +++ b/lib/libqof/backend/file/qof-backend-qsf.h @@ -61,8 +61,7 @@ http://code.neil.williamsleesmill.me.uk/qsf.html QSF itself is now being built into the QOF library for use with pilot-link to allow Palm objects to be described in QOF, written to XML as QSF and imported directly into GnuCash and other QOF-compliant applications. As a generic format, it does not depend -on any pre-defined objects - as the current GnuCash XML format depends on AccountGroup. -Instead, QSF is a simple container for all QOF objects. +on any pre-defined objects. Instead, QSF is a simple container for all QOF objects. QSF grew from the qof_book_merge code base and uses the qof_book_merge code that is now part of QOF. Any QofBook generated by QSF still needs to be merged into the existing diff --git a/lib/libqof/qof/qofinstance-p.h b/lib/libqof/qof/qofinstance-p.h index 338caf3400..66456c93a3 100644 --- a/lib/libqof/qof/qofinstance-p.h +++ b/lib/libqof/qof/qofinstance-p.h @@ -74,9 +74,6 @@ struct QofInstance_s gboolean infant; }; -/* reset the dirty flag */ -void qof_instance_mark_clean (QofInstance *); - void qof_instance_set_slots (QofInstance *, KvpFrame *); /* Set the last_update time. Reserved for use by the SQL backend; diff --git a/lib/libqof/qof/qofinstance.h b/lib/libqof/qof/qofinstance.h index ac28710f4d..4aa4893df0 100644 --- a/lib/libqof/qof/qofinstance.h +++ b/lib/libqof/qof/qofinstance.h @@ -92,6 +92,9 @@ Sets this instance AND the collection as dirty. */ void qof_instance_set_dirty(QofInstance* inst); +/* reset the dirty flag */ +void qof_instance_mark_clean (QofInstance *); + gboolean qof_instance_check_edit(const QofInstance *inst); gboolean qof_instance_do_free(const QofInstance *inst); diff --git a/lib/libqof/qof/qofsession.h b/lib/libqof/qof/qofsession.h index 9afe62e020..92ea05edca 100644 --- a/lib/libqof/qof/qofsession.h +++ b/lib/libqof/qof/qofsession.h @@ -228,7 +228,7 @@ gboolean qof_session_save_may_clobber_data (QofSession *session); /** The qof_session_save() method will commit all changes that have been * made to the session. For the file backend, this is nothing - * more than a write to the file of the current AccountGroup & etc. + * more than a write to the file of the current Accounts & etc. * For the SQL backend, this is typically a no-op (since all data * has already been written out to the database. */ diff --git a/src/app-utils/gnc-account-merge.c b/src/app-utils/gnc-account-merge.c index 4c60d97c10..98006a7b77 100644 --- a/src/app-utils/gnc-account-merge.c +++ b/src/app-utils/gnc-account-merge.c @@ -3,7 +3,6 @@ #include #include "gnc-account-merge.h" #include "Account.h" -#include "Group.h" GncAccountMergeDisposition determine_account_merge_disposition(Account *existing_acct, Account *new_acct) @@ -17,50 +16,48 @@ determine_account_merge_disposition(Account *existing_acct, Account *new_acct) } GncAccountMergeDisposition -determine_merge_disposition(AccountGroup *existing_root, Account *new_acct) +determine_merge_disposition(Account *existing_root, Account *new_acct) { Account *existing_acct; gchar *full_name; full_name = xaccAccountGetFullName(new_acct); - existing_acct = xaccGetAccountFromFullName(existing_root, full_name); + existing_acct = gnc_account_lookup_full_name(existing_root, full_name); g_free(full_name); return determine_account_merge_disposition(existing_acct, new_acct); } void -account_group_merge(AccountGroup *existing_grp, AccountGroup *new_grp) +account_trees_merge(Account *existing_root, Account *new_accts_root) { - GList *accounts_copy; - AccountList *accounts; - g_return_if_fail(new_grp != NULL); - g_return_if_fail(existing_grp != NULL); + GList *accounts, *node; + g_return_if_fail(new_accts_root != NULL); + g_return_if_fail(existing_root != NULL); /* since we're have a chance of mutating the list (via - * xaccGroupInsertAccount) while we're iterating over it, iterate over a - * copy. */ - accounts_copy = g_list_copy(xaccGroupGetAccountList(new_grp)); - for (accounts = accounts_copy; accounts; accounts = accounts->next) + * gnc_account_add_child) while we're iterating over it, iterate + * over a copy. */ + accounts = gnc_account_get_children(new_accts_root); + for (node = accounts; node; node = g_list_next(node)) { Account *existing_named, *new_acct; const char *name; new_acct = (Account*)accounts->data; name = xaccAccountGetName(new_acct); - existing_named = xaccGetAccountFromName(existing_grp, name); + existing_named = gnc_account_lookup_name(existing_root, name); switch (determine_account_merge_disposition(existing_named, new_acct)) { case GNC_ACCOUNT_MERGE_DISPOSITION_USE_EXISTING: /* recurse */ - account_group_merge(xaccAccountGetChildren(existing_named), - xaccAccountGetChildren(new_acct)); + account_trees_merge(existing_named, new_acct); break; case GNC_ACCOUNT_MERGE_DISPOSITION_CREATE_NEW: /* merge this one in. */ - xaccGroupInsertAccount(existing_grp, new_acct); + gnc_account_append_child(existing_root, new_acct); break; } } - g_list_free(accounts_copy); + g_list_free(accounts); } diff --git a/src/app-utils/gnc-account-merge.h b/src/app-utils/gnc-account-merge.h index f91d1f9244..f5ff7afad6 100644 --- a/src/app-utils/gnc-account-merge.h +++ b/src/app-utils/gnc-account-merge.h @@ -4,7 +4,6 @@ #define GNC_ACCOUNT_MERGE_H #include "Account.h" -#include "Group.h" typedef enum { GNC_ACCOUNT_MERGE_DISPOSITION_USE_EXISTING, @@ -18,8 +17,8 @@ typedef struct _merge_error { } GncAccountMergeError; GncAccountMergeDisposition determine_account_merge_disposition(Account *existing_acct, Account *new_acct); -GncAccountMergeDisposition determine_merge_disposition(AccountGroup *existing_root, Account *new_acct); +GncAccountMergeDisposition determine_merge_disposition(Account *existing_root, Account *new_acct); -void account_group_merge(AccountGroup *existing_grp, AccountGroup *new_grp); +void account_trees_merge(Account *existing_root, Account *new_accts_root); #endif /* GNC_ACCOUNT_MERGE_H */ diff --git a/src/app-utils/gnc-component-manager.c b/src/app-utils/gnc-component-manager.c index 6a2438b8f2..d8dc57537e 100644 --- a/src/app-utils/gnc-component-manager.c +++ b/src/app-utils/gnc-component-manager.c @@ -21,7 +21,6 @@ #include -#include "Group.h" #include "gnc-component-manager.h" #include "qof.h" #include "gnc-ui-util.h" diff --git a/src/app-utils/gnc-ui-util.c b/src/app-utils/gnc-ui-util.c index 5ec02cee26..e0aa2a219f 100644 --- a/src/app-utils/gnc-ui-util.c +++ b/src/app-utils/gnc-ui-util.c @@ -45,7 +45,6 @@ #include "gnc-hooks.h" #include "gnc-module.h" #include "gnc-ui-util.h" -#include "Group.h" #include "Transaction.h" #include "guile-mappings.h" #include "gnc-session.h" @@ -206,10 +205,10 @@ gnc_get_current_book (void) return qof_session_get_book (gnc_get_current_session ()); } -AccountGroup * -gnc_get_current_group (void) +Account * +gnc_get_current_root_account (void) { - return gnc_book_get_group (gnc_get_current_book ()); + return gnc_book_get_root_account (gnc_get_current_book ()); } gnc_commodity_table * @@ -374,11 +373,9 @@ gnc_ui_account_get_balance_as_of_date (Account *account, if (include_children) { - AccountGroup *children_group; GList *children, *node; - children_group = xaccAccountGetChildren (account); - children = xaccGroupGetSubAccounts (children_group); + children = gnc_account_get_descendants(account); for (node = children; node; node = node->next) { @@ -393,6 +390,8 @@ gnc_ui_account_get_balance_as_of_date (Account *account, child_balance, child_currency, currency); balance = gnc_numeric_add_fixed (balance, child_balance); } + + g_list_free(children); } /* reverse sign if needed */ @@ -573,11 +572,11 @@ equity_base_name (GNCEquityType equity_type) } Account * -gnc_find_or_create_equity_account (AccountGroup *group, +gnc_find_or_create_equity_account (QofBook *book, GNCEquityType equity_type, - gnc_commodity *currency, - QofBook *book) + gnc_commodity *currency) { + Account *root; Account *parent; Account *account; gboolean name_exists; @@ -588,11 +587,12 @@ gnc_find_or_create_equity_account (AccountGroup *group, g_return_val_if_fail (equity_type >= 0, NULL); g_return_val_if_fail (equity_type < NUM_EQUITY_TYPES, NULL); g_return_val_if_fail (currency != NULL, NULL); - g_return_val_if_fail (group != NULL, NULL); + g_return_val_if_fail (book != NULL, NULL); base_name = equity_base_name (equity_type); - account = xaccGetAccountFromName (group, base_name); + root = gnc_book_get_root_account(book); + account = gnc_account_lookup_name(root, base_name); if (account && xaccAccountGetType (account) != ACCT_TYPE_EQUITY) account = NULL; @@ -600,7 +600,7 @@ gnc_find_or_create_equity_account (AccountGroup *group, { base_name = base_name && *base_name ? _(base_name) : ""; - account = xaccGetAccountFromName (group, base_name); + account = gnc_account_lookup_name(root, base_name); if (account && xaccAccountGetType (account) != ACCT_TYPE_EQUITY) account = NULL; } @@ -613,7 +613,7 @@ gnc_find_or_create_equity_account (AccountGroup *group, name = g_strconcat (base_name, " - ", gnc_commodity_get_mnemonic (currency), NULL); - account = xaccGetAccountFromName (group, name); + account = gnc_account_lookup_name(root, name); if (account && xaccAccountGetType (account) != ACCT_TYPE_EQUITY) account = NULL; @@ -638,9 +638,10 @@ gnc_find_or_create_equity_account (AccountGroup *group, name = g_strdup (base_name); } - parent = xaccGetAccountFromName (group, _("Equity")); + parent = gnc_account_lookup_name(root, _("Equity")); if (parent && xaccAccountGetType (parent) != ACCT_TYPE_EQUITY) - parent = NULL; + parent = root; + g_assert(parent); account = xaccMallocAccount (book); @@ -650,14 +651,9 @@ gnc_find_or_create_equity_account (AccountGroup *group, xaccAccountSetType (account, ACCT_TYPE_EQUITY); xaccAccountSetCommodity (account, currency); - if (parent) - { - xaccAccountBeginEdit (parent); - xaccAccountInsertSubAccount (parent, account); - xaccAccountCommitEdit (parent); - } - else - xaccGroupInsertAccount (group, account); + xaccAccountBeginEdit (parent); + gnc_account_append_child (parent, account); + xaccAccountCommitEdit (parent); xaccAccountCommitEdit (account); @@ -682,10 +678,9 @@ gnc_account_create_opening_balance (Account *account, g_return_val_if_fail (account != NULL, FALSE); equity_account = - gnc_find_or_create_equity_account (xaccAccountGetRoot (account), + gnc_find_or_create_equity_account (book, EQUITY_OPENING_BALANCE, - xaccAccountGetCommodity (account), - book); + xaccAccountGetCommodity (account)); if (!equity_account) return FALSE; diff --git a/src/app-utils/gnc-ui-util.h b/src/app-utils/gnc-ui-util.h index 33c801d0d3..62ab2e1512 100644 --- a/src/app-utils/gnc-ui-util.h +++ b/src/app-utils/gnc-ui-util.h @@ -36,7 +36,6 @@ #include #include "Account.h" -#include "Group.h" #include "qof.h" @@ -77,7 +76,7 @@ void gnc_extract_directory (char **dirname, const char *filename); /* Engine enhancements & i18n ***************************************/ QofBook * gnc_get_current_book (void); -AccountGroup * gnc_get_current_group (void); +Account * gnc_get_current_root_account (void); gnc_commodity_table * gnc_get_current_commodities (void); /* @@ -184,10 +183,9 @@ typedef enum NUM_EQUITY_TYPES } GNCEquityType; -Account * gnc_find_or_create_equity_account (AccountGroup *group, +Account * gnc_find_or_create_equity_account (QofBook *book, GNCEquityType equity_type, - gnc_commodity *currency, - QofBook *book); + gnc_commodity *currency); gboolean gnc_account_create_opening_balance (Account *account, gnc_numeric balance, time_t date, diff --git a/src/app-utils/guile-util.h b/src/app-utils/guile-util.h index 808214c429..e3f8e23ec7 100644 --- a/src/app-utils/guile-util.h +++ b/src/app-utils/guile-util.h @@ -29,8 +29,7 @@ #include "gnc-book.h" #include "qof.h" -#include "Group.h" - +#include "Account.h" /* Helpful functions for calling functions that return * specific kinds of values. These functions do error diff --git a/src/backend/file/gnc-account-xml-v2.c b/src/backend/file/gnc-account-xml-v2.c index 3f0ac38de8..e59edba44f 100644 --- a/src/backend/file/gnc-account-xml-v2.c +++ b/src/backend/file/gnc-account-xml-v2.c @@ -44,7 +44,6 @@ #include "sixtp-dom-parsers.h" #include "AccountP.h" #include "Account.h" -#include "Group.h" static QofLogModule log_module = GNC_MOD_IO; @@ -77,6 +76,7 @@ gnc_account_dom_tree_create(Account *act, gboolean exporting) kvp_frame *kf; xmlNodePtr ret; GList *n; + Account *parent; ENTER ("(account=%p)", act); @@ -123,11 +123,11 @@ gnc_account_dom_tree_create(Account *act, gboolean exporting) } } - if(xaccAccountGetParentAccount(act)) + parent = gnc_account_get_parent(act); + if (parent) { - xmlAddChild(ret, guid_to_dom_tree( - act_parent_string, - xaccAccountGetGUID(xaccAccountGetParentAccount(act)))); + xmlAddChild(ret, guid_to_dom_tree(act_parent_string, + xaccAccountGetGUID(parent))); } n = xaccAccountGetLotList (act); @@ -322,7 +322,7 @@ account_parent_handler (xmlNodePtr node, gpointer act_pdata) g_return_val_if_fail(parent, FALSE); } - xaccAccountInsertSubAccount(parent, pdata->account); + gnc_account_append_child(parent, pdata->account); g_free (gid); @@ -405,10 +405,11 @@ gnc_account_end_handler(gpointer data_for_children, gpointer *result, const gchar *tag) { int successful; - Account *acc; + Account *acc, *parent, *root; xmlNodePtr tree = (xmlNodePtr)data_for_children; gxpf_data *gdata = (gxpf_data*)global_data; QofBook *book = gdata->bookdata; + int type; successful = TRUE; @@ -436,6 +437,22 @@ gnc_account_end_handler(gpointer data_for_children, * rebalances with #accounts rebalances at the end. A BIG win! */ xaccAccountBeginEdit(acc); + + /* Backwards compatability. If there's no parent, see if this + * account is of type ROOT. If not, find or create a ROOT + * account and make that the parent. */ + parent = gnc_account_get_parent(acc); + if (parent == NULL) { + type = xaccAccountGetType(acc); + if (type != ACCT_TYPE_ROOT) { + root = gnc_book_get_root_account(book); + if (root == NULL) { + gnc_commodity *com = xaccAccountGetCommodity(acc); + root = gnc_account_create_root(book, com); + } + gnc_account_append_child(root, acc); + } + } } xmlFreeNode(tree); diff --git a/src/backend/file/gnc-book-xml-v2.c b/src/backend/file/gnc-book-xml-v2.c index 6a94a131ef..7ac2e58f6b 100644 --- a/src/backend/file/gnc-book-xml-v2.c +++ b/src/backend/file/gnc-book-xml-v2.c @@ -45,7 +45,6 @@ #include "sixtp-dom-parsers.h" #include "qof.h" -#include "Group.h" /* non-static because it's used in io-gncxml-v2.c */ const gchar *gnc_v2_book_version_string = "2.0.0"; @@ -62,25 +61,22 @@ static QofLogModule log_module = GNC_MOD_IO; #ifdef IMPLEMENT_BOOK_DOM_TREES_LATER static void -append_group(xmlNodePtr parent, AccountGroup *grp) +append_account_tree (xmlNodePtr parent, Account *account) { - GList *list; - GList *node; + GList *children, *node; - list = xaccGroupGetAccountList(grp); - - for (node = list; node; node = node->next) { + children = gnc_account_get_children(account); + for (node = children; node; node = node->next) + { xmlNodePtr accnode; - AccountGroup *newgrp; + Account *account; - accnode = gnc_account_dom_tree_create((Account*)(node->data), FALSE); + account = node->data; + accnode = gnc_account_dom_tree_create(account, FALSE); xmlAddChild (parent, accnode); - - newgrp = xaccAccountGetChildren((Account*)(node->data)); - - if (newgrp) - append_group(accnode, newgrp); + append_account_tree(accnode, account); } + g_list_free(children); } static int @@ -125,9 +121,10 @@ gnc_book_dom_tree_create(QofBook *book) xmlAddChild(ret, gnc_commodity_dom_tree_create( gnc_book_get_commodity_table(book))); xmlAddChild(ret, gnc_pricedb_dom_tree_create(gnc_book_get_pricedb(book))); - append_group(ret, gnc_book_get_group(book)); + append_account_tree (ret, gnc_book_get_root(book)); - xaccGroupForEachTransaction(gnc_book_get_group(book), traverse_txns, ret); + xaccAccountTreeForEachTransaction (gnc_book_get_root_account(book), + traverse_txns, ret); xmlAddChild(ret, gnc_freqSpec_dom_tree_create (book)); diff --git a/src/backend/file/gnc-commodity-xml-v2.c b/src/backend/file/gnc-commodity-xml-v2.c index 62967d5f03..e5d05b385a 100644 --- a/src/backend/file/gnc-commodity-xml-v2.c +++ b/src/backend/file/gnc-commodity-xml-v2.c @@ -42,7 +42,6 @@ #include "sixtp-dom-parsers.h" #include "AccountP.h" #include "Account.h" -#include "Group.h" static QofLogModule log_module = GNC_MOD_IO; diff --git a/src/backend/file/gnc-schedxaction-xml-v2.c b/src/backend/file/gnc-schedxaction-xml-v2.c index c56ed8f803..a26352d4c5 100644 --- a/src/backend/file/gnc-schedxaction-xml-v2.c +++ b/src/backend/file/gnc-schedxaction-xml-v2.c @@ -26,7 +26,6 @@ #include #include -#include "Group.h" #include "SchedXactionP.h" #include "SX-book.h" @@ -633,7 +632,7 @@ gnc_schedXaction_end_handler(gpointer data_for_children, /* FIXME: this should be removed somewhere near 1.8 release time. */ if ( sx->template_acct == NULL ) { - AccountGroup *ag = NULL; + Account *ra = NULL; const char *id = NULL; Account *acct = NULL; sixtp_gdv2 *sixdata = gdata->parsedata; @@ -644,18 +643,18 @@ gnc_schedXaction_end_handler(gpointer data_for_children, /* We're dealing with a pre-200107 rgmerk change re: storing template accounts. */ /* Fix: get account with name of our GUID from the template - accounts group. Make that our template_acct pointer. */ + accounts. Make that our template_acct pointer. */ /* THREAD-UNSAFE */ id = guid_to_string( xaccSchedXactionGetGUID( sx ) ); - ag = gnc_book_get_template_group(book); - if ( ag == NULL ) + ra = gnc_book_get_template_root(book); + if ( ra == NULL ) { - PERR( "Error getting template account group " + PERR( "Error getting template root account " "from being-parsed Book." ); xmlFreeNode( tree ); return FALSE; } - acct = xaccGetAccountFromName( ag, id ); + acct = gnc_account_lookup_name( ra, id ); if ( acct == NULL ) { PERR( "Error getting template account " @@ -769,9 +768,9 @@ gnc_template_transaction_end_handler(gpointer data_for_children, txd.accts = NULL; txd.transactions = NULL; - /* the DOM tree will have an account tree [the template group - and account] and a list of transactions [which will be - members of the template account]. + /* the DOM tree will have an account tree [the template + accounts] and a list of transactions [which will be members + of the template account]. we want to parse through the dom trees for each, placing the null-parent account in the book's template-group slot, diff --git a/src/backend/file/io-example-account.c b/src/backend/file/io-example-account.c index 1fa5ac31df..c6a5508848 100644 --- a/src/backend/file/io-example-account.c +++ b/src/backend/file/io-example-account.c @@ -43,7 +43,6 @@ #include "sixtp-dom-parsers.h" #include "sixtp-parsers.h" -#include "Group.h" #include "Scrub.h" #include "TransLog.h" @@ -69,11 +68,11 @@ gnc_destroy_example_account(GncExampleAccount *gea) g_free(gea->filename); gea->filename = NULL; } - if(gea->group != NULL) + if(gea->root != NULL) { - xaccAccountGroupBeginEdit (gea->group); - xaccAccountGroupDestroy(gea->group); - gea->group = NULL; + xaccAccountBeginEdit (gea->root); + xaccAccountDestroy(gea->root); + gea->root = NULL; } if(gea->short_description != NULL) { @@ -138,9 +137,9 @@ add_account_local(GncExampleAccount *gea, Account *act) xaccAccountScrubCommodity (act); - if (!xaccAccountGetParent(act)) + if (!gnc_account_get_parent(act)) { - xaccGroupInsertAccount(gea->group, act); + gnc_account_append_child(gea->root, act); } } @@ -301,7 +300,7 @@ gnc_read_example_account(QofBook *book, const gchar *filename) gea->book = book; gea->filename = g_strdup(filename); - gea->group = xaccMallocAccountGroup(book); + gea->root = xaccMallocAccount(book); top_parser = sixtp_new(); main_parser = sixtp_new(); @@ -327,6 +326,8 @@ gnc_read_example_account(QofBook *book, const gchar *filename) return FALSE; } + xaccAccountBeginEdit(gea->root); + if(!gnc_xml_parse_file(top_parser, filename, generic_callback, gea, book)) { @@ -335,8 +336,7 @@ gnc_read_example_account(QofBook *book, const gchar *filename) return FALSE; } - xaccGroupMarkSaved(gea->group); - xaccAccountGroupCommitEdit(gea->group); + xaccAccountCommitEdit(gea->root); return gea; } @@ -389,7 +389,7 @@ gnc_write_example_account(GncExampleAccount *gea, const gchar *filename) write_bool_part(out, GNC_ACCOUNT_EXCLUDEP, gea->exclude_from_select_all); - write_account_group(out, gea->group, NULL); + write_account_tree(out, gea->root, NULL); fprintf(out, "\n\n"); diff --git a/src/backend/file/io-example-account.h b/src/backend/file/io-example-account.h index 54c7bc6ecf..0716b5861f 100644 --- a/src/backend/file/io-example-account.h +++ b/src/backend/file/io-example-account.h @@ -35,7 +35,7 @@ struct GncExampleAccount_struct gchar *title; gchar *filename; QofBook *book; - AccountGroup *group; + Account *root; gchar *short_description; gchar *long_description; gboolean exclude_from_select_all; diff --git a/src/backend/file/io-gncbin-r.c b/src/backend/file/io-gncbin-r.c deleted file mode 100644 index 0992d7e22f..0000000000 --- a/src/backend/file/io-gncbin-r.c +++ /dev/null @@ -1,1532 +0,0 @@ -/********************************************************************\ - * io-gncbin-r.c -- read (old X-Accountant format) binary datafile * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 2 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License* - * along with this program; if not, contact: * - * * - * Free Software Foundation Voice: +1-617-542-5942 * - * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * - * Boston, MA 02110-1301, USA gnu@gnu.org * - * * - ******************************************************************** - * @file io-gncbin-r.c - * @brief read (old X-Accountant format) binary datafile - * @author Copyright (C) 1997 Robin D. Clark - * @author Copyright (C) 1997-2001 Linas Vepstas - * @author Copyright (C) 1999-2000 Rob Browning - * - * NOTE: the readxxxx/writexxxx functions changed the current * - * position in the file, and so the order which these * - * functions are called in important * - * * - * Version 1 is the original file format * - * Version 2 of the file format supports reading and writing of * - * double-entry transactions. * - * Version 3 of the file format supports actions (Buy, Sell, etc.) * - * Version 4 of the file format adds account groups * - * Version 5 of the file format adds splits * - * Version 6 of the file format removes the source split * - * Version 7 of the file format adds currency & security types * - * Version 8 of the file format adds misc fields * - * Version 9 changes the time format to a 64-bit int * - * Version 10 adds auxilliary account info * - * * - * the format of the data in the file: * - * file ::== token Group * - * Group ::== numAccounts (Account)^numAccounts * - * Account ::== accID flags type accountName accountCode * - * description notes currency security * - * AccInfo * - * numTran (Transaction)^numTrans * - * numGroups (Group)^numGroups * - * Transaction ::== num date_entered date_posted description * - * docref numSplits (Split)^numSplits * - * Split ::== memo action reconciled date_recned * - * docref amount share_price account * - * token ::== int [the version of file format == VERSION] * - * numTrans ::== int * - * numAccounts ::== int * - * accID ::== int * - * flags ::== char * - * type ::== char * - * accountName ::== String * - * accountCode ::== String * - * description ::== String * - * notes ::== String * - * currency ::== String * - * security ::== String * - * AccInfo ::== (variable, depends on account type, ... ) * - * * - * num ::== String * - * date_entered::== Date * - * date_posted ::== Date * - * date_recned ::== Date * - * description ::== String * - * memo ::== String * - * action ::== String * - * docref ::== String * - * reconciled ::== char * - * amount ::== double * - * share_price ::== double * - * account ::== int * - * String ::== size (char)^size * - * size ::== int * - * Date ::== seconds nanoseconds * - * seconds ::== signed 64 bit int * - * nanoseconds ::== signed 32 bit int * -\********************************************************************/ - -#include -#include -#include -#include -#include - -#include "config.h" - -#include "Account.h" -#include "AccountP.h" -#include "io-gncbin.h" -#include "Group.h" -#include "GroupP.h" -#include "Transaction.h" -#include "TransactionP.h" -#include "TransLog.h" -#include "gnc-engine.h" -#include "gnc-pricedb.h" -#include "gnc-pricedb-p.h" - -#define PERMS 0666 -#define WFLAGS (O_WRONLY | O_CREAT | O_TRUNC) -#define RFLAGS O_RDONLY - -#undef VERSION -#define VERSION 10 - - -/* The binary file format does not support most of the - * new/improved account & transaction structures - */ - -/* This static indicates the debugging module that this .o belongs to. */ -static QofLogModule log_module = GNC_MOD_IO; - -/** GLOBALS *********************************************************/ - -/* the default currency is used when importin old-style - * file formats, or when importing files with no currency - * specified. This should probably be something that - * is configurable from some user config menu. - */ -#define DEFAULT_CURRENCY "USD" - -static int error_code=0; /* error code, if error occurred */ - -static AccountGroup *holder; /* temporary holder for - * unclassified accounts */ -static AccountGroup *maingrp; /* temporary holder for file - * being read */ - -/* Store mappings from the old/abolished id's to accounts since id's - have been deleted from Account's. - - These shouldn't be global, but since the rest of this file is - completely non-reentrant, and since this file is dead once the xml - format is finished, I'm not going to get too torn up about it... - - FIXME: a bigger issue is whether or not we're being totally kosher - in our handling of keys and values here. We use int32s and - pointers interchangably ATM, and that may be problematic on some - architectures... - - Only used *during* file read process. -*/ - -static GHashTable *ids_to_finished_accounts; -static GHashTable *ids_to_unfinished_accounts; - -/** PriceDB bits ******************************************************/ -/* Commodity prices (stock quotes, etc.) used to be stored as zero - quantity (damount) splits inside the relevant accounts. Now we - used the pricedb. potential_quotes is where we put the info from - all these "quote splits" while reading, until we have a chance to - cram them into the pricedb. We can't do it any sooner because - until we finish reading the file, the Account*'s havent' been - filled out and so their commodities and types may not have been - initilized yet. - - This shouldn't be a static global but see comments above RE ids_to* - hashes. */ - -typedef struct { - Split *split; - gnc_numeric price; -} GNCPotentialQuote; - -static GSList *potential_quotes; - - -#define EPS (1.0e-6) -#define DEQEPS(x,y,eps) (((((x)+(eps))>(y)) ? 1 : 0) && ((((x)-(eps))<(y)) ? 1 : 0)) -#define DEQ(x,y) DEQEPS(x,y,EPS) - -static void -mark_potential_quote(Split *s, double price, double quantity) -{ - if((price != 0) && DEQ(quantity, 0)){ - GNCPotentialQuote *q = g_new0(GNCPotentialQuote, 1); - q->split = s; - q->price = double_to_gnc_numeric(price, - GNC_DENOM_AUTO, - GNC_DENOM_SIGFIGS(9) | GNC_RND_ROUND); - potential_quotes = g_slist_prepend(potential_quotes, q); - } -} - -static gboolean -cvt_potential_prices_to_pricedb_and_cleanup(GNCPriceDB **prices, - QofBook *book) -{ - GSList *item = potential_quotes; - - *prices = gnc_book_get_pricedb(book); - if (!*prices) return FALSE; - - while(item) - { - GNCPotentialQuote *q = (GNCPotentialQuote *) item->data; - Account *split_acct = xaccSplitGetAccount(q->split); - - /* at this point, we already know it's a split with a zero amount */ - if (xaccAccountIsPriced(split_acct)) { - /* this is a quote -- file it in the db and kill the split */ - Transaction *txn = xaccSplitGetParent(q->split); - GNCPrice *price = gnc_price_create(book); - Timespec time = xaccTransRetDatePostedTS(txn); - - gnc_price_begin_edit(price); - gnc_price_set_commodity(price, - DxaccAccountGetSecurity(split_acct)); - gnc_price_set_currency(price, - xaccTransGetCurrency(txn)); - gnc_price_set_time(price, time); - gnc_price_set_source(price, "old-file-import"); - gnc_price_set_type(price, "unknown"); - gnc_price_set_value(price, q->price); - gnc_price_commit_edit(price); - if(!gnc_pricedb_add_price(*prices, price)) { - PERR("problem adding price to pricedb.\n"); - } - gnc_price_unref(price); - - xaccTransBeginEdit(txn); - xaccSplitDestroy(q->split); - xaccTransCommitEdit(txn); - } - g_free(item->data); - item->data = NULL; - item = item->next; - } - g_slist_free(potential_quotes); - potential_quotes = NULL; - - return TRUE; -} - -/** PROTOTYPES ******************************************************/ -static Account *locateAccount (int acc_id, QofBook *book); - -static AccountGroup *readGroup( QofBook *, int fd, Account *, int token ); -static Account *readAccount( QofBook *book, int fd, - AccountGroup *, int token ); -static gboolean readAccInfo( int fd, Account *, int token ); -static Transaction *readTransaction( QofBook *book, - int fd, Account *, int token ); -static Split *readSplit( QofBook *book, int fd, int token ); -static char *readString( int fd, int token ); -static time_t readDMYDate( int fd, int token ); -static int readTSDate( int fd, Timespec *, int token ); - -/*******************************************************/ -/* backwards compatibility definitions for numeric value - * of account type. These numbers are used (are to be - * used) nowhere else but here, precisely because they - * are non-portable. The values of these defines MUST - * NOT BE CHANGED; ANY CHANGES WILL BREAK FILE COMPATIBILITY. - * YOU HAVE BEEN WARNED!!!! - */ - -#define FF_BANK 0 -#define FF_CASH 1 -#define FF_ASSET 2 -#define FF_CREDIT 3 -#define FF_LIABILITY 4 -#define FF_STOCK 5 -#define FF_MUTUAL 6 -#define FF_INCOME 7 -#define FF_EXPENSE 8 -#define FF_EQUITY 9 -#define FF_CHECKING 10 -#define FF_SAVINGS 11 -#define FF_MONEYMRKT 12 -#define FF_CREDITLINE 13 -#define FF_CURRENCY 14 - -/*******************************************************/ - -QofBackendError -gnc_get_binfile_io_error(void) -{ - /* reset the error code */ - int rc = error_code; - error_code = 0; - return rc; -} - -/*******************************************************/ -/* some endian stuff */ - -/* if we are running on a little-endian system, we need to - * do some endian flipping, because the xacc/gnucash native data - * format is big-endian. In particular, Intel x86 is little-endian. */ -#if WORDS_BIGENDIAN - #define XACC_FLIP_DOUBLE(x) - #define XACC_FLIP_LONG_LONG(x) - #define XACC_FLIP_INT(x) - #define XACC_FLIP_SHORT(x) -#else - -/* flip endianness of int, short, etc */ -static int -xaccFlipInt (int val) -{ - guint32 flip; - flip = (val & 0xff000000) >> 24; - flip |= (val & 0xff0000) >> 8; - flip |= (val & 0xff00) << 8; - flip |= (val & 0xff) << 24; - return (int) flip; -} - -static double -xaccFlipDouble (double val) -{ - union { - guint32 i[2]; - double d; - } u; - guint32 w0, w1; - u.d = val; - w0 = xaccFlipInt (u.i[0]); - w1 = xaccFlipInt (u.i[1]); - - u.i[0] = w1; - u.i[1] = w0; - return u.d; -} - -static gint64 -xaccFlipLongLong (gint64 val) -{ - union { - guint32 i[2]; - gint64 d; - } u; - guint32 w0, w1; - u.d = val; - w0 = xaccFlipInt (u.i[0]); - w1 = xaccFlipInt (u.i[1]); - - u.i[0] = w1; - u.i[1] = w0; - return u.d; -} - - #define XACC_FLIP_DOUBLE(x) { (x) = xaccFlipDouble (x); } - #define XACC_FLIP_LONG_LONG(x) { (x) = xaccFlipLongLong (x); } - #define XACC_FLIP_INT(x) { (x) = xaccFlipInt (x); } - #define XACC_FLIP_SHORT(x) { (x) = xaccFlipShort (x); } -#endif /* WORDS_BIGENDIAN */ - - - -/******************************************************************** - * handle legacy currencies : after we load old files, we MUST run the - * gnucash currency conversion functions to get rid of the - * GNC_LEGACY_CURRENCIES namespace. - ********************************************************************/ - -static gnc_commodity * -gnc_commodity_import_legacy(QofBook *book, const char * currency_name) -{ - gnc_commodity_table *table; - gnc_commodity * old = NULL; - - table = gnc_book_get_commodity_table (book); - - g_return_val_if_fail (table != NULL, NULL); - - if(currency_name && (currency_name[0] != 0) ) { - old = gnc_commodity_table_lookup(table, - GNC_COMMODITY_NS_LEGACY, - currency_name); - - if(!old) { - old = gnc_commodity_new(book, currency_name, - GNC_COMMODITY_NS_LEGACY, currency_name, - 0, 100000); - old = gnc_commodity_table_insert(table, old); - } - return old; - } - else { - return NULL; - } -} - - -/********************************************************************\ - ********************** LOAD DATA *********************************** -\********************************************************************/ - -gboolean gnc_is_bin_file (const gchar *name) -{ - int fd, err, token; - - err = 0; - token = 0; - fd = open( name, RFLAGS, 0 ); - - /* check for valid file descriptor */ - if( 0 > fd ) { return FALSE; } - - /* Read in the file format token */ - err = read( fd, &token, sizeof(int) ); - if( sizeof(int) != err ) { return FALSE; } - XACC_FLIP_INT (token); - close(fd); - if(token == VERSION ) { return TRUE; } - return FALSE; -} - -/********************************************************************\ - * reads in the data from file descriptor * - * * - * Args: book -- the book in which to store the data * - * fd -- the file descriptor to read the data from * - * Return: the struct with the program data in it * -\********************************************************************/ -static gboolean -gnc_load_financials_from_fd(QofBook *book, int fd) -{ - int err=0; - int token=0; - int num_unclaimed; - AccountGroup *grp = 0x0; - - maingrp = 0x0; - error_code = ERR_BACKEND_NO_ERR; - - /* check for valid file descriptor */ - if( 0 > fd ) - { - error_code = ERR_FILEIO_FILE_NOT_FOUND; - return FALSE; - } - - /* Read in the file format token */ - err = read( fd, &token, sizeof(int) ); - if( sizeof(int) != err ) - { - error_code = ERR_FILEIO_FILE_EMPTY; - return FALSE; - } - XACC_FLIP_INT (token); - PINFO ("reading file version %d", token); - - /* If this is an old file, ask the user if the file - * should be updated */ - if( VERSION > token ) { - error_code = ERR_FILEIO_FILE_TOO_OLD; - } - - /* If this is a newer file than we know how to deal - * with, warn the user */ - if( VERSION < token ) { - error_code = ERR_BACKEND_TOO_NEW; - return FALSE; - } - - /* FIXME: is this OK (i.e. direct hashes for ints?) */ - ids_to_finished_accounts = g_hash_table_new(g_direct_hash, g_direct_equal); - if(!ids_to_finished_accounts) { - error_code = ERR_BACKEND_ALLOC; - return FALSE; - } - - ids_to_unfinished_accounts = g_hash_table_new(g_direct_hash, g_direct_equal); - if(!ids_to_unfinished_accounts) { - error_code = ERR_BACKEND_ALLOC; - - g_hash_table_destroy(ids_to_finished_accounts); - ids_to_finished_accounts = NULL; - - return FALSE; - } - - potential_quotes = NULL; - - /* disable logging during load; otherwise its just a mess */ - xaccLogDisable(); - holder = xaccMallocAccountGroup(book); - grp = readGroup (book, fd, NULL, token); - - /* the number of unclaimed accounts should be zero if the - * read succeeded. But just in case of a very unlikely - * error, try to continue anyway. */ - num_unclaimed = xaccGroupGetNumSubAccounts (holder); - if (num_unclaimed) { - Account *acc; - error_code = ERR_FILEIO_FILE_BAD_READ; - - /* create a lost account, put the missing accounts there */ - acc = xaccMallocAccount(book); - xaccAccountBeginEdit (acc); - /* Translators: Name of the account where all the missing accounts - are put into. (FIXME: is this correct?) */ - xaccAccountSetName (acc, _("Lost Accounts")); - acc -> children = holder; - xaccAccountCommitEdit (acc); - xaccGroupInsertAccount (grp, acc); - } else { - xaccFreeAccountGroup (holder); - holder = NULL; - } - - maingrp = NULL; - g_hash_table_destroy(ids_to_finished_accounts); - ids_to_finished_accounts = NULL; - g_hash_table_destroy(ids_to_unfinished_accounts); - ids_to_unfinished_accounts = NULL; - - { - GNCPriceDB *tmpdb; - if(!cvt_potential_prices_to_pricedb_and_cleanup(&tmpdb, book)) - { - PWARN("pricedb import failed."); - error_code = ERR_BACKEND_MISC; - gnc_pricedb_destroy(tmpdb); - } - } - - xaccLogEnable(); - - xaccSetAccountGroup(book, grp); - - /* mark the newly read book as saved, since the act of putting it - * together will have caused it to be marked up as not-saved. */ - qof_book_mark_saved(book); - - return (error_code == ERR_BACKEND_NO_ERR); -} - -/********************************************************************\ - * xaccReadAccountGroupFile * - * reads in the data from file datafile * - * * - * Args: datafile - the file to load the data from * - * Return: the struct with the program data in it * -\********************************************************************/ -void -qof_session_load_from_binfile(QofBook *book, const char * datafile) -{ - int fd; - - if(!datafile) { - error_code = ERR_BACKEND_MISC; - return; - } - - maingrp = NULL; - error_code = ERR_BACKEND_NO_ERR; - - fd = open( datafile, RFLAGS, 0 ); - if( 0 > fd ) { - error_code = ERR_FILEIO_FILE_NOT_FOUND; - return; - } - - xaccDisableDataScrubbing(); - gnc_load_financials_from_fd(book, fd); - xaccEnableDataScrubbing(); - - close(fd); -} - -/********************************************************************\ - * readGroup * - * reads in a group of accounts * - * * - * Args: * - * Return: the struct with the program data in it * -\********************************************************************/ -static AccountGroup * -readGroup (QofBook *book, int fd, Account *aparent, int token) - { - int numAcc; - int err=0; - int i; - AccountGroup *grp = xaccMallocAccountGroup(book); - - ENTER (" "); - - if (NULL == aparent) { - maingrp = grp; - } - - /* read numAccs */ - err = read( fd, &numAcc, sizeof(int) ); - if( sizeof(int) != err ) - { - xaccFreeAccountGroup (grp); - return NULL; - } - XACC_FLIP_INT (numAcc); - - DEBUG ("expecting %d accounts", numAcc); - - /* read in the accounts */ - for( i=0; iparent = aparent; - if (aparent) { - aparent->children = grp; - } - return grp; -} - -/********************************************************************\ - * readAccount * - * reads in the data for an account from the datafile * - * * - * Args: book - the top-level account object * - * fd - the filedescriptor of the data file * - * acc - the account structure to be filled in * - * token - the datafile version * - * Return: error value, 0 if OK, else -1 * -\********************************************************************/ -static Account * -readAccount( QofBook *book, int fd, AccountGroup *grp, int token ) -{ - int err=0; - int i; - int numTrans, accID; - Account *acc; - gnc_commodity * currency; - gnc_commodity * security; - char * tmp; - - ENTER (" "); - - /* version 1 does not store the account number */ - if (1 < token) { - err = read( fd, &accID, sizeof(int) ); - if( err != sizeof(int) ) { return NULL; } - XACC_FLIP_INT (accID); - acc = locateAccount (accID, book); - /* locateAccountAlways should always accounts that are open for - editing in this situation */ - } else { - acc = xaccMallocAccount(book); - xaccGroupInsertAccount (holder, acc); - xaccAccountBeginEdit (acc); - } - - { - /* flags are now gone - if you need these, use kv pairs */ - char tmpflags; - err = read( fd, &tmpflags, sizeof(char) ); - if( err != sizeof(char) ) { return NULL; } - } - - /* if (9999>= token) */ { - char ff_acctype; - int acctype; - err = read( fd, &(ff_acctype), sizeof(char) ); - if( err != sizeof(char) ) { return NULL; } - switch (ff_acctype) { - case FF_BANK: { acctype = ACCT_TYPE_BANK; break; } - case FF_CASH: { acctype = ACCT_TYPE_CASH; break; } - case FF_ASSET: { acctype = ACCT_TYPE_ASSET; break; } - case FF_CREDIT: { acctype = ACCT_TYPE_CREDIT; break; } - case FF_LIABILITY: { acctype = ACCT_TYPE_LIABILITY; break; } - case FF_STOCK: { acctype = ACCT_TYPE_STOCK; break; } - case FF_MUTUAL: { acctype = ACCT_TYPE_MUTUAL; break; } - case FF_INCOME: { acctype = ACCT_TYPE_INCOME; break; } - case FF_EXPENSE: { acctype = ACCT_TYPE_EXPENSE; break; } - case FF_EQUITY: { acctype = ACCT_TYPE_EQUITY; break; } - case FF_CHECKING: { acctype = ACCT_TYPE_CHECKING; break; } - case FF_SAVINGS: { acctype = ACCT_TYPE_SAVINGS; break; } - case FF_MONEYMRKT: { acctype = ACCT_TYPE_MONEYMRKT; break; } - case FF_CREDITLINE: { acctype = ACCT_TYPE_CREDITLINE; break; } - case FF_CURRENCY: { acctype = ACCT_TYPE_CURRENCY; break; } - default: return NULL; - } - xaccAccountSetType (acc, acctype); - } - - tmp = readString( fd, token ); - if( NULL == tmp) return NULL; - DEBUG ("reading acct %s", tmp); - xaccAccountSetName (acc, tmp); - g_free (tmp); - - if (8 <= token) { - tmp = readString( fd, token ); - if( NULL == tmp) return NULL; - xaccAccountSetCode (acc, tmp); - g_free (tmp); - } - - tmp = readString( fd, token ); - if( NULL == tmp ) return NULL; - xaccAccountSetDescription (acc, tmp); - g_free (tmp); - - tmp = readString( fd, token ); - if( NULL == tmp ) return NULL; - if(strlen(tmp) > 0) { - xaccAccountSetNotes (acc, tmp); - } - g_free (tmp); - - /* currency and security strings first introduced - * in version 7 of the file format */ - if (7 <= token) { - tmp = readString( fd, token ); - if( NULL == tmp ) return NULL; - - PINFO ("currency is %s", tmp); - currency = gnc_commodity_import_legacy(book, tmp); - DxaccAccountSetCurrency (acc, currency); - - if(tmp) g_free (tmp); - - tmp = readString( fd, token ); - - if (!tmp || *tmp == '\0') - { - if (xaccAccountIsPriced(acc)) { - if (tmp) g_free (tmp); - - tmp = strdup (xaccAccountGetName (acc)); - if (tmp == NULL) return NULL; - } - } - - PINFO ("security is %s", tmp); - security = gnc_commodity_import_legacy(book, tmp); - DxaccAccountSetSecurity (acc, security); - - if(tmp) g_free (tmp); - } - else { - /* set the default currency when importing old files */ - currency = gnc_commodity_import_legacy(book, DEFAULT_CURRENCY); - DxaccAccountSetCurrency (acc, currency); - } - - /* aux account info first appears in version ten files */ - if (10 <= token) { - if(!readAccInfo(fd, acc, token)) { - return(NULL); - } - } - - err = read( fd, &numTrans, sizeof(int) ); - if( err != sizeof(int) ) { return NULL; } - XACC_FLIP_INT (numTrans); - - DEBUG ("expecting %d transactions", numTrans); - /* read the transactions */ - for( i=0; iid); */ - - xaccGroupInsertAccount (grp, acc); - - /* version 4 is the first file version that introduces - * sub-accounts */ - if (4 <= token) { - int numGrps; - err = read( fd, &numGrps, sizeof(int) ); - if( err != sizeof(int) ) { - return NULL; - } - XACC_FLIP_INT (numGrps); - if (numGrps) { - readGroup (book, fd, acc, token); - } - } - - xaccAccountCommitEdit (acc); - - return acc; -} - -/********************************************************************\ - * locateAccount - * - * With the double-entry system, the file may reference accounts that - * have not yet been read or properly parented. Thus, we need a way - * of dealing with this, and this routine performs this - * work. Basically, accounts are requested by their id. If an account - * with the indicated ID does not exist, it is created and placed in a - * temporary hash. Accounts in the temp hash can be located, (so that - * transactions can be added to them) and sprung (so that they can be - * properly parented into a group). - * - * Also, if locate account creates a new account, it'll be open for - * editing. - */ - -static Account * -locateAccount (int acc_id, QofBook *book) -{ - Account * acc; - /* negative account ids denote no account */ - if (0 > acc_id) return NULL; - - /* first, see if we've already created the account */ - acc = (Account *) g_hash_table_lookup(ids_to_finished_accounts, - GINT_TO_POINTER(acc_id)); - if (acc) return acc; - - /* next, see if its an unclaimed account */ - acc = (Account *) g_hash_table_lookup(ids_to_unfinished_accounts, - GINT_TO_POINTER(acc_id)); - if (acc) return acc; - - /* if neither, then it does not yet exist. Create it. - * Put it in the drunk tank. */ - acc = xaccMallocAccount (book); - xaccAccountBeginEdit(acc); - g_hash_table_insert(ids_to_unfinished_accounts, - GINT_TO_POINTER(acc_id), - (gpointer) acc); - return acc; -} - -/********************************************************************\ - * readAccInfo * - * reads in the auxilliary account info * - * * - * Args: fd - the filedescriptor of the data file * - * token - the datafile version * - * Return: the accinfo structure * -\********************************************************************/ - -static gboolean -readAccInfo(int fd, Account *acc, int token) { - - /* The only data that was ever stored in the account info was a - price src if it was an investment account. The AccInfo - abstraction has been abandoned, and all that stuff will soon be - handled by other means, so we're just going to cram pricesrc into - the account kv table for now... */ - - GNCAccountType acc_type; - - if(!acc) return(FALSE); - - acc_type = xaccAccountGetType(acc); - if ((acc_type == ACCT_TYPE_STOCK) || (acc_type == ACCT_TYPE_MUTUAL)) { - const char *tmp = readString( fd, token ); - if(NULL == tmp) return(FALSE); - if(strlen(tmp) > 0) dxaccAccountSetPriceSrc(acc, tmp); - g_free((char *) tmp); - } - return(TRUE); -} - -static void -xaccTransSetMemo (Transaction *trans, const char *memo) -{ - Split *s; - - if (!trans || !memo) return; - - s = xaccTransGetSplit (trans, 0); - xaccSplitSetMemo (s, memo); - - if (xaccTransCountSplits (trans) != 2) - return; - - s = xaccTransGetSplit (trans, 1); - xaccSplitSetMemo (s, memo); -} - -static void -xaccTransSetAction (Transaction *trans, const char *action) -{ - Split *s; - - if (!trans || !action) return; - - s = xaccTransGetSplit (trans, 0); - xaccSplitSetAction (s, action); - - if (xaccTransCountSplits (trans) != 2) - return; - - s = xaccTransGetSplit (trans, 1); - xaccSplitSetAction (s, action); -} - -/********************************************************************\ - * readTransaction * - * reads in the data for a transaction from the datafile * - * * - * Args: fd - the filedescriptor of the data file * - * token - the datafile version * - * Return: the transaction structure * -\********************************************************************/ - -static Transaction * -readTransaction(QofBook *book, int fd, Account *acc, int revision) - { - int err=0; - int acc_id; - int i; - int dummy_category; - int numSplits; - Transaction *trans = 0x0; - char *tmp; - char recn; - double num_shares = 0.0; - double share_price = 0.0; - - ENTER (" "); - - /* create a transaction structure */ - trans = xaccMallocTransaction(book); - xaccTransBeginEdit (trans); - - tmp = readString( fd, revision ); - if (NULL == tmp) - { - PERR ("Premature end of Transaction at num"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - xaccTransSetNum (trans, tmp); - g_free (tmp); - - if (revision <= 7) { - time_t secs; - secs = readDMYDate( fd, revision ); - if( 0 == secs ) - { - PERR ("Premature end of Transaction at date"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - xaccTransSetDateSecs (trans, secs); - xaccTransSetDateEnteredSecs (trans, secs); - } else { - Timespec ts; - int rc; - - /* read posted date first ... */ - rc = readTSDate( fd, &ts, revision ); - if( -1 == rc ) - { - PERR ("Premature end of Transaction at date"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - xaccTransSetDatePostedTS (trans, &ts); - - /* then the entered date ... */ - rc = readTSDate( fd, &ts, revision ); - if( -1 == rc ) - { - PERR ("Premature end of Transaction at date"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - xaccTransSetDateEnteredTS (trans, &ts); - } - - tmp = readString( fd, revision ); - if( NULL == tmp ) - { - PERR ("Premature end of Transaction at description"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - PINFO ("description=%s", tmp); - xaccTransSetDescription (trans, tmp); - g_free (tmp); - - /* docref first makes an appearance in version 8. They're now - deprecated, and we don't think anyone ever used them anyway, but - to be safe, if we find one, we store it in the old-docref slot, a - la old-price-source. */ - if (revision >= 8) { - tmp = readString( fd, revision ); - if( NULL == tmp ) { - PERR ("Premature end of Transaction at docref"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - if(strlen(tmp) > 0) { - kvp_value *new_value = kvp_value_new_string(tmp); - if(!new_value) { - PERR ("Failed to allocate kvp_value for transaction docref."); - g_free(tmp); - return(NULL); - } - kvp_frame_set_slot_nc(xaccTransGetSlots(trans), "old-docref", new_value); - } - g_free (tmp); - } - - /* At version 5, most of the transaction stuff was - * moved to splits. Thus, vast majority of stuff below - * is skipped - */ - if (revision <= 4) { - Split* s; - - tmp = readString( fd, revision ); - if( NULL == tmp ) - { - PERR ("Premature end of Transaction at memo"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - - if(strlen(tmp) > 0) { - xaccTransSetMemo (trans, tmp); - } - g_free (tmp); - - /* action first introduced in version 3 of the file format */ - if (revision >= 3) - { - tmp = readString( fd, revision ); - if( NULL == tmp ) - { - PERR ("Premature end of Transaction at action"); - xaccTransDestroy (trans); - xaccTransCommitEdit (trans); - return NULL; - } - xaccTransSetAction (trans, tmp); - g_free (tmp); - } - - /* category is now obsolete */ - err = read( fd, &(dummy_category), sizeof(int) ); - if( sizeof(int) != err ) - { - PERR ("Premature end of Transaction at category"); - xaccTransDestroy (trans); - xaccTransCommitEdit (trans); - return NULL; - } - - err = read( fd, &recn, sizeof(char) ); - if( sizeof(char) != err ) - { - PERR ("Premature end of Transaction at reconciled"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - - /* The code below really wants to assume that there are a pair - * of splits in every transaction, so make it so. - */ - s = xaccMallocSplit (book); - xaccTransAppendSplit (trans, s); - s = xaccMallocSplit (book); - xaccTransAppendSplit (trans, s); - - s = xaccTransGetSplit (trans, 0); - xaccSplitSetReconcile (s, recn); - s = xaccTransGetSplit (trans, 1); - xaccSplitSetReconcile (s, recn); - - if(revision <= 1) { - /* Note: this is for version 0 of file format only. - * What used to be reconciled, is now cleared... transactions - * aren't reconciled until you get your bank statement, and - * use the reconcile window to mark the transaction reconciled - */ - if( YREC == recn ) { - s = xaccTransGetSplit (trans, 0); - xaccSplitSetReconcile (s, CREC); - s = xaccTransGetSplit (trans, 1); - xaccSplitSetReconcile (s, CREC); - } - } - - /* Version 1 files stored the amount as an integer, - * with the amount recorded as pennies. - * Version 2 and above store the share amounts and - * prices as doubles. */ - if (1 == revision) { - int amount; - - err = read( fd, &amount, sizeof(int) ); - if( sizeof(int) != err ) - { - PERR ("Premature end of Transaction at V1 amount"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - XACC_FLIP_INT (amount); - num_shares = 0.01 * ((double) amount); /* file stores pennies */ - s = xaccTransGetSplit (trans, 0); - DxaccSplitSetShareAmount (s, num_shares); - - /* Version 1 files did not do double-entry */ - s = xaccTransGetSplit (trans, 0); - xaccAccountInsertSplit( acc, s ); - } else { - Account *peer_acc; - double damount; - - /* first, read number of shares ... */ - err = read( fd, &damount, sizeof(double) ); - if( sizeof(double) != err ) - { - PERR ("Premature end of Transaction at amount"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - XACC_FLIP_DOUBLE (damount); - num_shares = damount; - - /* ... next read the share price ... */ - err = read( fd, &damount, sizeof(double) ); - if( err != sizeof(double) ) - { - PERR ("Premature end of Transaction at share_price"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - XACC_FLIP_DOUBLE (damount); - share_price = damount; - s = xaccTransGetSplit (trans, 0); - - DxaccSplitSetSharePriceAndAmount (s, share_price, num_shares); - - /* Read the account numbers for double-entry */ - /* These are first used in Version 2 of the file format */ - - /* first, read the credit account number */ - err = read( fd, &acc_id, sizeof(int) ); - if( err != sizeof(int) ) - { - PERR ("Premature end of Transaction at credit"); - xaccTransDestroy (trans); - xaccTransCommitEdit (trans); - return NULL; - } - XACC_FLIP_INT (acc_id); - DEBUG ("credit %d\n", acc_id); - peer_acc = locateAccount (acc_id, book); - - /* insert the split part of the transaction into - * the credited account */ - s = xaccTransGetSplit (trans, 0); - if (peer_acc) xaccAccountInsertSplit( peer_acc, s); - - mark_potential_quote(s, share_price, num_shares); - - /* next read the debit account number */ - err = read( fd, &acc_id, sizeof(int) ); - if( err != sizeof(int) ) - { - PERR ("Premature end of Transaction at debit"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - XACC_FLIP_INT (acc_id); - DEBUG ("debit %d\n", acc_id); - peer_acc = locateAccount (acc_id, book); - if (peer_acc) { - Split *s0 = xaccTransGetSplit (trans, 0); - Split *s1 = xaccTransGetSplit (trans, 1); - - /* duplicate many of the attributes in the credit split */ - DxaccSplitSetSharePriceAndAmount (s1, share_price, -num_shares); - xaccSplitSetReconcile (s1, xaccSplitGetReconcile (s0)); - xaccSplitSetMemo (s1, xaccSplitGetMemo (s0)); - xaccSplitSetAction (s1, xaccSplitGetAction (s0)); - xaccAccountInsertSplit (peer_acc, s1); - mark_potential_quote(s1, share_price, -num_shares); - } - } - } else { /* else, read version 5 and above files */ - - const char *notes = NULL; - - if (revision == 5) { - /* Version 5 files included a split that immediately - * followed the transaction, before the destination splits. - * Later versions don't have this. */ - Split *split = readSplit (book, fd, revision); - xaccTransAppendSplit(trans, split); - } - - /* read number of splits */ - err = read( fd, &(numSplits), sizeof(int) ); - if( err != sizeof(int) ) { - PERR ("Premature end of Transaction at num-splits"); - xaccTransDestroy(trans); - xaccTransCommitEdit (trans); - return NULL; - } - XACC_FLIP_INT (numSplits); - for (i = 0; i < numSplits; i++) { - Split *split = readSplit(book, fd, revision); - xaccTransAppendSplit(trans, split); - - if(!notes) { - notes = xaccSplitGetMemo (split); - if(notes) xaccTransSetNotes (trans, notes); - } - } - } - - xaccTransCommitEdit (trans); - - return trans; -} - -/********************************************************************\ - * readSplit * - * reads in the data for a split from the datafile * - * * - * Args: fd - the filedescriptor of the data file * - * token - the datafile version * - * Return: the transaction structure * -\********************************************************************/ - -static Split * -readSplit ( QofBook *book, int fd, int token ) -{ - Account *peer_acc; - Split *split; - int err=0; - int acc_id; - char *tmp; - char recn; - double num_shares, share_price; - - ENTER (" "); - - /* create a split structure */ - split = xaccMallocSplit(book); - - tmp = readString( fd, token ); - if( NULL == tmp ) - { - PERR ("Premature end of Split at memo"); - xaccSplitDestroy(split); - return NULL; - } - PINFO ("memo=%s", tmp); - xaccSplitSetMemo (split, tmp); - g_free (tmp); - - tmp = readString( fd, token ); - if( tmp == NULL ) - { - PERR ("Premature end of Split at action"); - xaccSplitDestroy (split); - return NULL; - } - xaccSplitSetAction (split, tmp); - g_free (tmp); - - err = read( fd, &recn, sizeof(char) ); - if( err != sizeof(char) ) - { - PERR ("Premature end of Split at reconciled"); - xaccSplitDestroy (split); - return NULL; - } - - /* make sure the value of split->reconciled is valid... - * Do this mainly in case we change what NREC and - * YREC are defined to be... this way it might loose all - * the reconciled data, but at least the field is valid */ - if( (YREC != recn) && - (FREC != recn) && - (CREC != recn) ) { - recn = NREC; - } - xaccSplitSetReconcile (split, recn); - - /* version 8 and newer files store date-reconciled */ - if (8 <= token) { - Timespec ts; - int rc; - - rc = readTSDate( fd, &ts, token ); - if( -1 == rc ) - { - PERR ("Premature end of Split at date"); - xaccSplitDestroy (split); - return NULL; - } - xaccSplitSetDateReconciledTS (split, &ts); - } else { - time_t now; - now = time (0); - xaccSplitSetDateReconciledSecs (split, now); - } - - /* docref first makes an appearance in version 8. They're now - deprecated, and we don't think anyone ever used them anyway, but - to be safe, if we find one, we store it in the old-docref slot, a - la old-price-source. */ - if (8 <= token) { - tmp = readString( fd, token ); - if( NULL == tmp ) { - PERR ("Premature end of Split at docref"); - xaccSplitDestroy (split); - return NULL; - } - if(strlen(tmp) > 0) { - kvp_value *new_value = kvp_value_new_string(tmp); - if(!new_value) { - PERR ("Failed to allocate kvp_value for split docref."); - g_free(tmp); - return(NULL); - } - kvp_frame_set_slot_nc(xaccSplitGetSlots(split), "old-docref", new_value); - } - g_free (tmp); - } - - /* first, read number of shares ... */ - err = read( fd, &num_shares, sizeof(double) ); - if( sizeof(double) != err ) - { - PERR ("Premature end of Split at amount"); - xaccSplitDestroy (split); - return NULL; - } - XACC_FLIP_DOUBLE (num_shares); - - /* ... next read the share price ... */ - err = read( fd, &share_price, sizeof(double) ); - if( sizeof(double) != err ) - { - PERR ("Premature end of Split at share_price"); - xaccSplitDestroy (split); - return NULL; - } - XACC_FLIP_DOUBLE (share_price); - - DxaccSplitSetSharePriceAndAmount (split, share_price, num_shares); - - DEBUG ("num_shares %f", num_shares); - - /* Read the account number */ - - err = read( fd, &acc_id, sizeof(int) ); - if( sizeof(int) != err ) - { - PERR ("Premature end of Split at account"); - xaccSplitDestroy (split); - return NULL; - } - XACC_FLIP_INT (acc_id); - DEBUG ("account id %d", acc_id); - peer_acc = locateAccount (acc_id, book); - xaccAccountInsertSplit (peer_acc, split); - - mark_potential_quote(split, share_price, num_shares); - return split; -} - -/********************************************************************\ - * readString * - * reads in a string (char *) from the datafile * - * * - * Args: fd - the filedescriptor of the data file * - * token - the datafile version * - * Return: the string * -\********************************************************************/ -static char * -readString( int fd, int token ) - { - int err=0; - int size; - char *str; - - err = read( fd, &size, sizeof(int) ); - if( err != sizeof(int) ) - return NULL; - XACC_FLIP_INT (size); - - str = (char *) g_malloc (size); - if (!str) { - PERR("malloc failed on size %d bytes at position %ld\n", size, - (long int) lseek(fd, 0, SEEK_CUR)); - return NULL; - } - err = read( fd, str, size ); - if( err != size ) - { - PERR("size = %d err = %d str = %s\n", size, err, str ); - g_free(str); - return NULL; - } - - return str; - } - -/********************************************************************\ - * readTSDate * - * reads in a Date struct from the datafile * - * * - * Args: fd - the filedescriptor of the data file * - * token - the datafile version * - * Return: the Date struct * -\********************************************************************/ -static int -readTSDate( int fd, Timespec *ts, int token ) - { - int err=0; - gint64 secs = 0; /* 64-bit int */ - gint32 nsecs = 0; - - /* secs is a 32-bit in in version 8 & earlier files, - * and goes 64-bit in the later files */ - if (8 >= token) - { - gint32 sicks; - err = read( fd, &sicks, sizeof(gint32) ); - if( err != sizeof(gint32) ) - { - return -1; - } - XACC_FLIP_INT (sicks); - secs = sicks; - } - else - { - err = read( fd, &secs, sizeof(gint64) ); - if( err != sizeof(gint64) ) - { - return -1; - } - XACC_FLIP_LONG_LONG (secs); - } - - err = read( fd, &nsecs, sizeof(gint32) ); - if( err != sizeof(gint32) ) - { - return -1; - } - XACC_FLIP_INT (nsecs); - - ts->tv_sec = secs; - ts->tv_nsec = nsecs; - - return 2*err; - } - -/********************************************************************\ - * readDMYDate * - * reads in a Date struct from the datafile * - * * - * Args: fd - the filedescriptor of the data file * - * token - the datafile version * - * Return: the Date struct * -\********************************************************************/ -static time_t -readDMYDate( int fd, int token ) - { - int err=0; - int day, month, year; - time_t secs; - - err = read( fd, &year, sizeof(int) ); - if( err != sizeof(int) ) - { - return 0; - } - XACC_FLIP_INT (year); - - err = read( fd, &month, sizeof(int) ); - if( err != sizeof(int) ) - { - return 0; - } - XACC_FLIP_INT (month); - - err = read( fd, &day, sizeof(int) ); - if( err != sizeof(int) ) - { - return 0; - } - XACC_FLIP_INT (day); - - secs = xaccDMYToSec (day, month, year); - return secs; - } - - -/*********************** END OF FILE *********************************/ diff --git a/src/backend/file/io-gncbin.h b/src/backend/file/io-gncbin.h deleted file mode 100644 index 4ce5f8c823..0000000000 --- a/src/backend/file/io-gncbin.h +++ /dev/null @@ -1,64 +0,0 @@ -/********************************************************************\ - * io-gncbin.h -- read (old X-Accountant format) binary datafile * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 2 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License* - * along with this program; if not, contact: * - * * - * Free Software Foundation Voice: +1-617-542-5942 * - * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * - * Boston, MA 02110-1301, USA gnu@gnu.org * - * * - * Author: Rob Clark * - * Internet: rclark@cs.hmc.edu * - * Address: 609 8th Street * - * Huntington Beach, CA 92648-4632 * -\********************************************************************/ - -#ifndef IO_GNCBIN_H -#define IO_GNCBIN_H - -#include "qof.h" - -/* @file io-gncbin.h - * @brief read (old X-Accountant format) binary datafile - * @author Copyright (C) 1997 Robin D. Clark - * @author Copyright (C) 1998, 1999 Linas Vepstas - - @note These routines should not be used directly for file IO. They - are not inherently safe against file-locking errors. For direct - file IO, the QofBook's higher level functions should be used. -*/ -/** Load the financial data represented by the book's file_path -into the indicated book.*/ -void qof_session_load_from_binfile(QofBook *, const char * filepath); - -/** Error handler. - -\return an error code for any error - detected that occured during reading or writing. - -The error code will be reset after the call. - - The current implementation can be - thought of as a "stack of depth one", and this routine as a "pop". -*/ -QofBackendError gnc_get_binfile_io_error(void); - -/** \brief Attempt to identify the binary format. - -Instead of assuming that anything not v1 or v2 XML is the gnc -binary format, this function tries to load the version token -from the file. -*/ -gboolean gnc_is_bin_file (const gchar *name); - -#endif /* IO_GNCBIN_H */ diff --git a/src/backend/file/io-gncxml-v1.c b/src/backend/file/io-gncxml-v1.c index 5bbdfd5764..3f1dad1635 100644 --- a/src/backend/file/io-gncxml-v1.c +++ b/src/backend/file/io-gncxml-v1.c @@ -35,8 +35,6 @@ #include "gnc-xml-helper.h" #include "Account.h" #include "AccountP.h" -#include "Group.h" -#include "GroupP.h" #include "Query.h" #include "QueryP.h" #include "Scrub.h" @@ -95,8 +93,8 @@ typedef struct { /* The book */ QofBook *book; - /* The account group */ - AccountGroup *account_group; + /* The root account */ + Account *root_account; /* The pricedb */ GNCPriceDB *pricedb; @@ -222,7 +220,7 @@ gnc_version_parser_new(void) ----------- start: NA before-child: make sure we don't get two ledger-data's (not allowed ATM). - after-child: if a ledger-data child, parse_data->account_group = *result. + after-child: if a ledger-data child, parse_data->root_account = *result. characters: allow_and_ignore_only_whitespace Similarly, only one query is allowed ... @@ -252,7 +250,7 @@ gnc_parser_before_child_handler(gpointer data_for_children, g_return_val_if_fail(pstatus, FALSE); if(strcmp(child_tag, "ledger-data") == 0) { - if(pstatus->account_group) { + if(pstatus->root_account) { return(FALSE); } } @@ -283,7 +281,7 @@ gnc_parser_after_child_handler(gpointer data_for_children, { g_return_val_if_fail(child_result, FALSE); g_return_val_if_fail(child_result->data, FALSE); - pstatus->account_group = (AccountGroup *) child_result->data; + pstatus->root_account = (Account *) child_result->data; child_result->should_cleanup = FALSE; } @@ -345,7 +343,7 @@ gncxml_setup_for_read (GNCParseStatus *global_parse_status) global_parse_status->seen_version = FALSE; global_parse_status->gnc_parser = gnc_pr; - global_parse_status->account_group = NULL; + global_parse_status->root_account = NULL; global_parse_status->pricedb = NULL; // global_parse_status->query = NULL; global_parse_status->error = GNC_PARSE_ERR_NONE; @@ -382,15 +380,15 @@ qof_session_load_from_xml_file(QofBook *book, const char *filename) if(parse_ok) { - if(!global_parse_status.account_group) return FALSE; + if(!global_parse_status.root_account) return FALSE; - xaccSetAccountGroup(book, global_parse_status.account_group); + gnc_book_set_root_account(book, global_parse_status.root_account); /* Fix account and transaction commodities */ - xaccGroupScrubCommodities (gnc_book_get_group(book)); + xaccAccountTreeScrubCommodities (gnc_book_get_root_account(book)); /* Fix split amount/value */ - xaccGroupScrubSplits (gnc_book_get_group(book)); + xaccAccountTreeScrubSplits (gnc_book_get_root_account(book)); return(TRUE); } else { @@ -1079,18 +1077,18 @@ kvp_frame_parser_new(void) /****************************************************************************/ /* (parent ) - On failure or on normal cleanup, the account group will be killed, + On failure or on normal cleanup, the root account will be killed, so if you want it, you better set should_cleanup to false input: NA - to-children-via-*result: new AccountGroup* - returns: an AccountGroup* - start: creates the account group and puts it into *result + to-children-via-*result: new root Account* + returns: an Account* + start: creates the root account and puts it into *result characters: NA - end: finishes up the account group and leaves it in result. - cleanup-result: deletes the account group (use should_cleanup to avoid). + end: finishes up the root account and leaves it in result. + cleanup-result: deletes the root account (use should_cleanup to avoid). cleanup-chars: NA - fail: deletes the account group in *result. + fail: deletes the root account in *result. result-fail: same as cleanup-result. chars-fail: NA @@ -1103,16 +1101,16 @@ ledger_data_start_handler(GSList* sibling_data, gpointer parent_data, gpointer *result, const gchar *tag, gchar **attrs) { GNCParseStatus *pstatus = (GNCParseStatus *) global_data; - AccountGroup *ag; + Account *ra; /* disable logging during load; otherwise its just a mess */ xaccLogDisable(); - ag = xaccMallocAccountGroup(pstatus->book); + ra = xaccMallocAccount(pstatus->book); - g_return_val_if_fail(ag, FALSE); + g_return_val_if_fail(ra, FALSE); - *data_for_children = ag; - return(ag != NULL); + *data_for_children = ra; + return(ra != NULL); } static gboolean @@ -1154,23 +1152,21 @@ ledger_data_end_handler(gpointer data_for_children, gpointer *result, const gchar *tag) { - AccountGroup *ag = (AccountGroup *) data_for_children; + Account *ra = (Account *) data_for_children; + GList *descendants; - g_return_val_if_fail(ag, FALSE); + g_return_val_if_fail(ra, FALSE); - /* mark the newly read group as saved, since the act of putting - * it together will have caused it to be marked up as not-saved. - */ - xaccGroupMarkSaved (ag); - - /* commit all groups, this completes the BeginEdit started when the + /* commit all accounts, this completes the BeginEdit started when the * account_end_handler finished reading the account. */ - xaccAccountGroupCommitEdit (ag); + descendants = gnc_account_get_descendants(ra); + g_list_foreach(descendants, (GFunc)xaccAccountCommitEdit, NULL); + g_list_free(descendants); xaccLogEnable(); - *result = ag; + *result = ra; return(TRUE); } @@ -1183,22 +1179,22 @@ ledger_data_fail_handler(gpointer data_for_children, gpointer *result, const gchar *tag) { - AccountGroup *ag = (AccountGroup *) data_for_children; - if(ag) + Account *account = (Account *) data_for_children; + if (account) { - xaccAccountGroupBeginEdit(ag); - xaccAccountGroupDestroy(ag); + xaccAccountBeginEdit(account); + xaccAccountDestroy(account); } } static void ledger_data_result_cleanup(sixtp_child_result *cr) { - AccountGroup *ag = (AccountGroup *) cr->data; - if(ag) + Account *account = (Account *) cr->data; + if (account) { - xaccAccountGroupBeginEdit(ag); - xaccAccountGroupDestroy(ag); + xaccAccountBeginEdit(account); + xaccAccountDestroy(account); } } @@ -1245,9 +1241,9 @@ ledger_data_parser_new(void) to its children. It generates no data of its own, so it doesn't need any cleanup. - input: AccountGroup* + input: Account* - to-children-via-*result: AccountGroup* + to-children-via-*result: Account* returns: NA @@ -1291,7 +1287,7 @@ account_start_handler(GSList* sibling_data, if the resultant account is OK, and if so, we add it to the ledger-data's account group. - input: AccountGroup* + input: Account* to-children-via-*result: new Account* returns: NA start: create new Account*, and leave in for children. @@ -1331,20 +1327,20 @@ account_restore_end_handler(gpointer data_for_children, gpointer parent_data, gpointer global_data, gpointer *result, const gchar *tag) { - AccountGroup *ag = (AccountGroup *) parent_data; + Account *parent = (Account *) parent_data; Account *acc = (Account *) *result; - AccountGroup *parent_ag; + Account *acc_parent; - g_return_val_if_fail((ag && acc), FALSE); + g_return_val_if_fail((parent && acc), FALSE); /* CHECKME: do we need to xaccAccountRecomputeBalance(acc) here? */ xaccAccountCommitEdit(acc); /* If the account doesn't have a parent yet, just cram it into the top level */ - parent_ag = xaccAccountGetParent(acc); - - if(!parent_ag) xaccGroupInsertAccount(ag, acc); + acc_parent = gnc_account_get_parent(acc); + if(!acc_parent) + gnc_account_append_child(parent, acc); *result = NULL; @@ -1713,7 +1709,7 @@ acc_restore_parent_end_handler(gpointer data_for_children, g_return_val_if_fail(parent, FALSE); - xaccAccountInsertSubAccount(parent, acc); + gnc_account_append_child(parent, acc); return(TRUE); } @@ -2682,9 +2678,9 @@ query_server_parser_new (void) to its children. It generates no data of its own, so it doesn't need any cleanup. - input: AccountGroup* + input: Account* - to-children-via-*result: AccountGroup* + to-children-via-*result: Account* returns: NA @@ -2724,7 +2720,7 @@ transaction_start_handler(GSList* sibling_data, gpointer parent_data, see if the resultant account is OK, and if so, we add it to the ledger-data's account group. - from parent: AccountGroup* + from parent: Account* for children: new Transaction* @@ -2772,11 +2768,11 @@ txn_restore_end_handler(gpointer data_for_children, gpointer parent_data, gpointer global_data, gpointer *result, const gchar *tag) { - AccountGroup *ag = (AccountGroup *) parent_data; + Account *parent = (Account *) parent_data; Transaction *trans = (Transaction *) data_for_children; g_return_val_if_fail(trans, FALSE); - if(!ag) { + if (!parent) { xaccTransDestroy(trans); xaccTransCommitEdit(trans); return(FALSE); diff --git a/src/backend/file/io-gncxml-v2.c b/src/backend/file/io-gncxml-v2.c index 646e6af328..6b35ea6daf 100644 --- a/src/backend/file/io-gncxml-v2.c +++ b/src/backend/file/io-gncxml-v2.c @@ -34,8 +34,6 @@ #include "gnc-engine.h" #include "gnc-pricedb-p.h" -#include "Group.h" -#include "GroupP.h" #include "Scrub.h" #include "SX-book.h" #include "SX-book-p.h" @@ -163,6 +161,8 @@ static gboolean add_account_local(sixtp_gdv2 *data, Account *act) { gnc_commodity_table *table; + Account *parent, *root; + int type; table = gnc_book_get_commodity_table (data->book); @@ -180,10 +180,27 @@ add_account_local(sixtp_gdv2 *data, Account *act) xaccAccountScrubCommodity (act); xaccAccountScrubKvp (act); - if(!xaccAccountGetParent(act)) - { - xaccGroupInsertAccount(gnc_book_get_group(data->book), act); + /* Backwards compatability. If there's no parent, see if this + * account is of type ROOT. If not, find or create a ROOT + * account and make that the parent. */ + type = xaccAccountGetType(act); + if (type == ACCT_TYPE_ROOT) { + gnc_book_set_root_account(data->book, act); + } else { + parent = gnc_account_get_parent(act); + if (parent == NULL) { + root = gnc_book_get_root_account(data->book); + if (root == NULL) { + gnc_commodity *com = xaccAccountGetCommodity(act); + root = gnc_account_create_root(data->book, com); + /* Leave the account in the edit state. It will be committed + * at the end of reading all the transactions. */ + xaccAccountBeginEdit(root); + } + gnc_account_append_child(root, act); + } } + data->counter.accounts_loaded++; run_callback(data, "account"); @@ -255,7 +272,7 @@ add_template_transaction_local( sixtp_gdv2 *data, { GList *n; Account *tmpAcct; - AccountGroup *acctGroup = NULL; + Account *acctRoot = NULL; QofBook *book; book = data->book; @@ -264,22 +281,20 @@ add_template_transaction_local( sixtp_gdv2 *data, /* . template accounts. */ /* . transactions in those accounts. */ for ( n = txd->accts; n; n = n->next ) { - if ( xaccAccountGetParent( (Account*)n->data ) == NULL ) { + if ( gnc_account_get_parent( (Account*)n->data ) == NULL ) { /* remove the gnc_book_init-created account of the same name */ - acctGroup = - gnc_book_get_template_group(book); - tmpAcct = - xaccGetAccountFromName( acctGroup, + acctRoot = gnc_book_get_template_root(book); + tmpAcct = gnc_account_lookup_name( acctRoot, xaccAccountGetName( (Account*)n->data ) ); if ( tmpAcct != NULL ) { /* XXX hack alert FIXME .... Should this be 'Remove', or 'Destroy'? * If we just remove, then this seems to be a memory leak to me, since * it is never reparented. Shouldn't it be a Destroy ??? */ - xaccGroupRemoveAccount( acctGroup, tmpAcct ); + gnc_account_remove_child( acctRoot, tmpAcct ); } - xaccGroupInsertAccount( acctGroup, (Account*)n->data ); + gnc_account_append_child( acctRoot, (Account*)n->data ); } } @@ -289,8 +304,6 @@ add_template_transaction_local( sixtp_gdv2 *data, add_transaction_local( data, (Transaction*)n->data ); } - xaccAccountGroupCommitEdit (acctGroup); - return TRUE; } @@ -642,7 +655,7 @@ qof_session_load_from_xml_file_v2_full( FileBackend *fbe, QofBook *book, sixtp_push_handler push_handler, gpointer push_user_data) { - AccountGroup *grp; + Account *root; QofBackend *be = &fbe->be; sixtp_gdv2 *gd; sixtp *top_parser; @@ -749,19 +762,22 @@ qof_session_load_from_xml_file_v2_full( qof_object_foreach_backend (GNC_FILE_BACKEND, scrub_cb, &be_data); /* fix price quote sources */ - grp = gnc_book_get_group(book); - xaccGroupScrubQuoteSources (grp, gnc_book_get_commodity_table(book)); + root = gnc_book_get_root_account(book); + xaccAccountTreeScrubQuoteSources (root, gnc_book_get_commodity_table(book)); /* Fix account and transaction commodities */ - xaccGroupScrubCommodities (grp); + xaccAccountTreeScrubCommodities (root); /* Fix split amount/value */ - xaccGroupScrubSplits (grp); + xaccAccountTreeScrubSplits (root); /* commit all groups, this completes the BeginEdit started when the * account_end_handler finished reading the account. */ - xaccAccountGroupCommitEdit (grp); + gnc_account_foreach_descendant(root, + (AccountCb) xaccAccountCommitEdit, + NULL); + xaccAccountCommitEdit (root); /* start logging again */ xaccLogEnable (); @@ -928,7 +944,7 @@ write_book(FILE *out, QofBook *book, sixtp_gdv2 *gd) gnc_commodity_table_get_size( gnc_book_get_commodity_table(book)), "account", - 1 + xaccGroupGetNumSubAccounts(gnc_book_get_group(book)), + 1 + gnc_account_n_descendants(gnc_book_get_root_account(book)), "transaction", gnc_book_count_transactions(book), "schedxaction", @@ -1040,26 +1056,26 @@ write_transactions(FILE *out, QofBook *book, sixtp_gdv2 *gd) be_data.out = out; be_data.gd = gd; - xaccGroupForEachTransaction(gnc_book_get_group(book), - xml_add_trn_data, - (gpointer) &be_data); + xaccAccountTreeForEachTransaction(gnc_book_get_root_account(book), + xml_add_trn_data, + (gpointer) &be_data); } static void write_template_transaction_data( FILE *out, QofBook *book, sixtp_gdv2 *gd ) { - AccountGroup *ag; + Account *ra; struct file_backend be_data; be_data.out = out; be_data.gd = gd; - ag = gnc_book_get_template_group(book); - if ( xaccGroupGetNumSubAccounts(ag) > 0 ) + ra = gnc_book_get_template_root(book); + if ( gnc_account_n_descendants(ra) > 0 ) { fprintf( out, "<%s>\n", TEMPLATE_TRANSACTION_TAG ); - write_account_group( out, ag, gd ); - xaccGroupForEachTransaction( ag, xml_add_trn_data, (gpointer)&be_data ); + write_account_tree( out, ra, gd ); + xaccAccountTreeForEachTransaction( ra, xml_add_trn_data, (gpointer)&be_data ); fprintf( out, "\n", TEMPLATE_TRANSACTION_TAG ); } } @@ -1172,7 +1188,7 @@ gnc_book_write_to_xml_filehandle_v2(QofBook *book, FILE *out) gd->counter.commodities_total = gnc_commodity_table_get_size(gnc_book_get_commodity_table(book)); gd->counter.accounts_total = 1 + - xaccGroupGetNumSubAccounts(gnc_book_get_group(book)); + gnc_account_n_descendants(gnc_book_get_root_account(book)); gd->counter.transactions_total = gnc_book_count_transactions(book); gd->counter.schedXactions_total = g_list_length( gnc_book_get_schedxactions(book)); @@ -1194,14 +1210,14 @@ gboolean gnc_book_write_accounts_to_xml_filehandle_v2(QofBackend *be, QofBook *book, FILE *out) { gnc_commodity_table *table; - AccountGroup *grp; + Account *root; int ncom, nacc; sixtp_gdv2 *gd; if (!out) return FALSE; - grp = gnc_book_get_group(book); - nacc = 1 + xaccGroupGetNumSubAccounts(grp); + root = gnc_book_get_root_account(book); + nacc = 1 + gnc_account_n_descendants(root); table = gnc_book_get_commodity_table(book); ncom = gnc_commodity_table_get_size(table); diff --git a/src/backend/file/io-utils.c b/src/backend/file/io-utils.c index 21f3138ac1..b24c90500a 100644 --- a/src/backend/file/io-utils.c +++ b/src/backend/file/io-utils.c @@ -28,7 +28,6 @@ #include -#include "Group.h" #include "gnc-xml.h" #include "gnc-xml.h" #include "io-utils.h" @@ -51,40 +50,36 @@ write_emacs_trailer(FILE *out) fprintf(out, emacs_trailer); } -void -write_account_group(FILE *out, AccountGroup *grp, sixtp_gdv2 *gd) +static void +write_one_account(FILE *out, Account *account, sixtp_gdv2 *gd) { - GList *list; - GList *node; + xmlNodePtr accnode; - list = xaccGroupGetAccountList(grp); + accnode = gnc_account_dom_tree_create(account, gd && gd->exporting); - for (node = list; node; node = node->next) - { - xmlNodePtr accnode; - AccountGroup *newgrp; - - accnode = gnc_account_dom_tree_create((Account*)(node->data), - gd && gd->exporting); + xmlElemDump(out, NULL, accnode); + fprintf(out, "\n"); - xmlElemDump(out, NULL, accnode); - fprintf(out, "\n"); + xmlFreeNode(accnode); + gd->counter.accounts_loaded++; + run_callback(gd, "account"); +} - xmlFreeNode(accnode); - gd->counter.accounts_loaded++; - run_callback(gd, "account"); +void +write_account_tree(FILE *out, Account *root, sixtp_gdv2 *gd) +{ + GList *descendants, *node; - newgrp = xaccAccountGetChildren((Account*)(node->data)); + write_one_account(out, root, gd); - if (newgrp) - { - write_account_group(out, newgrp, gd); - } - } + descendants = gnc_account_get_descendants(root); + for (node = descendants; node; node = g_list_next(node)) + write_one_account(out, node->data, gd); + g_list_free(descendants); } void write_accounts(FILE *out, QofBook *book, sixtp_gdv2 *gd) { - write_account_group(out, gnc_book_get_group(book), gd); + write_account_tree(out, gnc_book_get_root_account(book), gd); } diff --git a/src/backend/file/io-utils.h b/src/backend/file/io-utils.h index b8718105eb..4122804fae 100644 --- a/src/backend/file/io-utils.h +++ b/src/backend/file/io-utils.h @@ -27,11 +27,10 @@ #include -#include "Group.h" #include "io-gncxml-v2.h" #include "qof.h" -void write_account_group(FILE *out, AccountGroup *grp, sixtp_gdv2 *gd); +void write_account_tree(FILE *out, Account *root, sixtp_gdv2 *gd); void write_accounts(FILE *out, QofBook *book, sixtp_gdv2 *gd); void write_book_parts(FILE *out, QofBook *book); void write_commodities(FILE *out, QofBook *book, sixtp_gdv2 *gd); diff --git a/src/backend/file/test/test-load-xml2.c b/src/backend/file/test/test-load-xml2.c index 88a7fde849..6820573836 100644 --- a/src/backend/file/test/test-load-xml2.c +++ b/src/backend/file/test/test-load-xml2.c @@ -38,7 +38,6 @@ #include #include "cashobjects.h" -#include "Group.h" #include "TransLog.h" #include "gnc-engine.h" #include "gnc-backend-file.h" @@ -78,7 +77,7 @@ test_load_file(const char *filename) { QofSession *session; QofBook *book; - AccountGroup *grp; + Account *root; gboolean ignore_lock; session = qof_session_new(); @@ -91,9 +90,9 @@ test_load_file(const char *filename) qof_session_load(session, NULL); book = qof_session_get_book (session); - grp = xaccGetAccountGroup(book); - do_test (xaccGroupGetBook (grp) == book, - "book and group don't match"); + root = gnc_book_get_root_account(book); + do_test (gnc_account_get_book (root) == book, + "book and root account don't match"); do_test_args(qof_session_get_error(session) == ERR_BACKEND_NO_ERR, "session load xml2", __FILE__, __LINE__, diff --git a/src/backend/file/test/test-xml-account.c b/src/backend/file/test/test-xml-account.c index e4b3e81c03..619d489773 100644 --- a/src/backend/file/test/test-xml-account.c +++ b/src/backend/file/test/test-xml-account.c @@ -41,7 +41,6 @@ #include "test-file-stuff.h" #include "Account.h" -#include "Group.h" #include "Scrub.h" static QofBook *sixbook; @@ -114,7 +113,8 @@ node_and_account_equal(xmlNodePtr node, Account *act) else if(safe_strcmp((char*)mark->name, "act:commodity") == 0) { if(!equals_node_val_vs_commodity( - mark, xaccAccountGetCommodity(act), xaccAccountGetBook(act))) + mark, xaccAccountGetCommodity(act), + gnc_account_get_book(act))) { return g_strdup("commodities differ"); } @@ -146,8 +146,7 @@ node_and_account_equal(xmlNodePtr node, Account *act) else if(safe_strcmp((char*)mark->name, "act:parent") == 0) { if(!equals_node_val_vs_guid( - mark, xaccAccountGetGUID(xaccGroupGetParentAccount( - xaccAccountGetParent(act))))) + mark, xaccAccountGetGUID(gnc_account_get_parent(act)))) { return g_strdup("parent ids differ"); } @@ -317,7 +316,7 @@ test_generation() /* act1 = get_random_account(); */ /* act2 = get_random_account(); */ -/* xaccAccountInsertSubAccount(act1, act2); */ +/* gnc_account_append_child(act1, act2); */ /* test_account(-1, act2); */ /* test_account(-1, act1); */ @@ -334,9 +333,9 @@ test_real_account(const char *tag, gpointer global_data, gpointer data) char *msg; Account *act = (Account*)data; - if(!xaccAccountGetParent(act)) + if(!gnc_account_get_parent(act)) { - xaccGroupInsertAccount(xaccGetAccountGroup(sixbook), act); + gnc_account_append_child(gnc_book_get_root_account(sixbook), act); } msg = node_and_account_equal((xmlNodePtr)global_data, act); diff --git a/src/backend/file/test/test-xml-transaction.c b/src/backend/file/test/test-xml-transaction.c index f875fd562b..786e4f8d07 100644 --- a/src/backend/file/test/test-xml-transaction.c +++ b/src/backend/file/test/test-xml-transaction.c @@ -365,14 +365,12 @@ test_transaction(void) for(i = 0; i < 50; i++) { Transaction *ran_trn; - AccountGroup *grp; xmlNodePtr test_node; gnc_commodity *com; gchar *compare_msg; gchar *filename1; int fd; - grp = get_random_group(book); ran_trn = get_random_transaction(book); if(!ran_trn) { diff --git a/src/backend/postgres/PostgresBackend.c b/src/backend/postgres/PostgresBackend.c index b2d456c633..84844b26fb 100644 --- a/src/backend/postgres/PostgresBackend.c +++ b/src/backend/postgres/PostgresBackend.c @@ -38,8 +38,6 @@ #include #include "AccountP.h" -#include "Group.h" -#include "GroupP.h" #include "gnc-commodity.h" #include "gnc-engine.h" #include "gnc-pricedb.h" @@ -713,7 +711,7 @@ pgendRunQuery (QofBackend *bend, gpointer q_p) PGBackend *be = (PGBackend *)bend; Query *q = (Query*) q_p; const char * sql_query_string; - AccountGroup *topgroup; + Account *root; sqlQuery *sq; ENTER ("be=%p, qry=%p", be, q); @@ -728,10 +726,10 @@ pgendRunQuery (QofBackend *bend, gpointer q_p) sq = sqlQuery_new(); sql_query_string = sqlQuery_build (sq, q); - topgroup = gnc_book_get_group (pgendGetBook(be)); + root = gnc_book_get_root_account(pgendGetBook(be)); /* stage transactions, save some postgres overhead */ - xaccGroupBeginStagedTransactionTraversals (topgroup); + gnc_account_tree_begin_staged_transaction_traversals (root); /* We will be doing a bulk insertion of transactions below. * We can gain a tremendous performance improvement, @@ -746,17 +744,13 @@ pgendRunQuery (QofBackend *bend, gpointer q_p) * by not very much. */ ncalls = 0; - xaccAccountGroupBeginEdit(topgroup); + xaccAccountBeginEdit(root); pgendFillOutToCheckpoint (be, sql_query_string); - xaccAccountGroupCommitEdit(topgroup); + xaccAccountCommitEdit(root); PINFO ("number of calls to fill out=%d", ncalls); sql_Query_destroy(sq); - /* the fill-out will dirty a lot of data. That's irrelevent, - * mark it all as having been saved. */ - xaccGroupMarkSaved (topgroup); - pgendEnable(be); qof_event_resume(); @@ -793,7 +787,7 @@ get_all_trans_cb (PGBackend *be, PGresult *result, int j, gpointer data) static void -pgendGetAllTransactions (PGBackend *be, AccountGroup *grp) +pgendGetAllTransactions (PGBackend *be, Account *root) { GList *node, *xaction_list = NULL; @@ -804,14 +798,14 @@ pgendGetAllTransactions (PGBackend *be, AccountGroup *grp) xaction_list = pgendGetResults (be, get_all_trans_cb, xaction_list); /* restore the transactions */ - xaccAccountGroupBeginEdit (grp); + xaccAccountBeginEdit (root); for (node=xaction_list; node; node=node->next) { xxxpgendCopyTransactionToEngine (be, (GUID *)node->data); guid_free (node->data); } g_list_free(xaction_list); - xaccAccountGroupCommitEdit (grp); + xaccAccountCommitEdit (root); pgendEnable(be); qof_event_resume(); @@ -871,9 +865,9 @@ static void pgendSync (QofBackend *bend, QofBook *book) { PGBackend *be = (PGBackend *)bend; - AccountGroup *grp = gnc_book_get_group (book); + Account *root = gnc_book_get_root_account(book); - ENTER ("be=%p, grp=%p", be, grp); + ENTER ("be=%p, root=%p", be, root); pgend_set_book (be, book); be->version_check = (guint32) time(0); @@ -894,8 +888,8 @@ pgendSync (QofBackend *bend, QofBook *book) pgendStoreBook (be, book); /* store the account group hierarchy, and then all transactions */ - pgendStoreGroup (be, grp); - pgendStoreAllTransactions (be, grp); + pgendStoreAccountTree (be, root); + pgendStoreAllTransactions (be, root); /* don't send events to GUI, don't accept callbacks to backend */ qof_event_suspend(); @@ -907,7 +901,7 @@ pgendSync (QofBackend *bend, QofBook *book) (MODE_SINGLE_UPDATE != be->session_mode)) { Timespec ts = gnc_iso8601_to_timespec_gmt (CK_BEFORE_LAST_DATE); - pgendGroupGetAllBalances (be, grp, ts); + pgendAccountTreeGetAllBalances (be, root, ts); } else { @@ -958,9 +952,9 @@ pgendSyncSingleFile (QofBackend *bend, QofBook *book) char buff[4000]; char *p; PGBackend *be = (PGBackend *)bend; - AccountGroup *grp = gnc_book_get_group (book); + Account *root = gnc_book_get_root_account(book); - ENTER ("be=%p, grp=%p", be, grp); + ENTER ("be=%p, root=%p", be, root); pgend_set_book (be, book); @@ -1017,14 +1011,14 @@ pgendSyncSingleFile (QofBackend *bend, QofBook *book) pgendStoreBookNoLock (be, book, TRUE); /* Store accounts and commodities */ - xaccClearMarkDownGr (grp, 0); - pgendStoreGroupNoLock (be, grp, TRUE, TRUE); - xaccClearMarkDownGr (grp, 0); + xaccClearMarkDown (root, 0); + pgendStoreAccountTreeNoLock (be, root, TRUE, TRUE); + xaccClearMarkDown (root, 0); /* Recursively walk transactions. Start by reseting the write * flags. We use this to avoid infinite recursion */ - xaccGroupBeginStagedTransactionTraversals(grp); - xaccGroupStagedTransactionTraversal (grp, 1, trans_traverse_cb, be); + gnc_account_tree_begin_staged_transaction_traversals(root); + gnc_account_tree_staged_transaction_traversal (root, 1, trans_traverse_cb, be); /* hack alert -- In some deranged theory, we should be * syncing prices here, as well as syncing any/all other @@ -1424,7 +1418,7 @@ pgend_session_end (QofBackend *bend) * it might be opened in multi-user mode next time. Thus, update * the account balance checkpoints just in case. */ - /* pgendGroupRecomputeAllCheckpoints (be, be->topgroup); */ + /* pgendAccountTreeRecomputeAllCheckpoints (be, be->root); */ break; case MODE_POLL: @@ -1481,7 +1475,7 @@ static void pgend_book_load_poll (QofBackend *bend, QofBook *book) { Timespec ts = gnc_iso8601_to_timespec_gmt (CK_BEFORE_LAST_DATE); - AccountGroup *grp; + Account *root; PGBackend *be = (PGBackend *)bend; if (!be) return; @@ -1508,10 +1502,10 @@ pgend_book_load_poll (QofBackend *bend, QofBook *book) pgendGetAllAccountsInBook (be, book); - grp = gnc_book_get_group (book); - xaccAccountGroupBeginEdit (grp); - pgendGroupGetAllBalances (be, grp, ts); - xaccAccountGroupCommitEdit (grp); + root = gnc_book_get_root_account (book); + xaccAccountBeginEdit (root); + pgendAccountTreeGetAllBalances (be, root, ts); + xaccAccountCommitEdit (root); /* re-enable events */ pgendEnable(be); diff --git a/src/backend/postgres/PostgresBackend.h b/src/backend/postgres/PostgresBackend.h index 0eb409c4c7..71d5f1307b 100644 --- a/src/backend/postgres/PostgresBackend.h +++ b/src/backend/postgres/PostgresBackend.h @@ -37,7 +37,6 @@ #include #include -#include "Group.h" #include "qof.h" #include "Transaction.h" diff --git a/src/backend/postgres/account.c b/src/backend/postgres/account.c index b7d4672c8d..2c0fdc9f3f 100644 --- a/src/backend/postgres/account.c +++ b/src/backend/postgres/account.c @@ -30,8 +30,6 @@ #include "AccountP.h" #include "qof.h" -#include "Group.h" -#include "GroupP.h" #include "gnc-commodity.h" #include "gnc-pricedb.h" @@ -48,7 +46,7 @@ static QofLogModule log_module = GNC_MOD_BACKEND; /* ============================================================= */ /* ============================================================= */ -/* ACCOUNT AND GROUP STUFF */ +/* ACCOUNT STUFF */ /* (UTILITIES FIRST, THEN SETTERS, THEN GETTERS) */ /* ============================================================= */ /* ============================================================= */ @@ -136,8 +134,8 @@ pgendStoreAccountNoLock (PGBackend *be, Account *acct, } /* ============================================================= */ -/* The pgendStoreGroup() routine stores the account hierarchy to - * the sql database. That is, it stores not oonly the top-level +/* The pgendStoreAccountTree() routine stores the account hierarchy + * to the sql database. That is, it stores not oonly the top-level * accounts, but all of thier children too. It also stores the * commodities associated with the accounts. It does *not* store * any of the transactions. @@ -150,38 +148,30 @@ pgendStoreAccountNoLock (PGBackend *be, Account *acct, */ void -pgendStoreGroupNoLock (PGBackend *be, AccountGroup *grp, +pgendStoreAccountTreeNoLock (PGBackend *be, Account *root, gboolean do_mark, gboolean do_check_version) { - GList *start, *node; + GList *descendants, *node; - if (!be || !grp) return; - ENTER("grp=%p mark=%d", grp, do_mark); + if (!be || !root) return; + ENTER("root=%p mark=%d", root, do_mark); /* walk the account tree, and store subaccounts */ - start = xaccGroupGetAccountList (grp); - for (node=start; node; node=node->next) - { - AccountGroup *subgrp; - Account *acc = node->data; - - pgendStoreAccountNoLock (be, acc, do_mark, do_check_version); - - /* recursively walk to child accounts */ - subgrp = xaccAccountGetChildren (acc); - if (subgrp) pgendStoreGroupNoLock(be, subgrp, do_mark, - do_check_version); - } + pgendStoreAccountNoLock (be, root, do_mark, do_check_version); + descendants = gnc_account_get_descendants (root); + for (node=descendants; node; node=node->next) + pgendStoreAccountNoLock (be, node->data, do_mark, do_check_version); + g_list_free(descendants); LEAVE(" "); } void -pgendStoreGroup (PGBackend *be, AccountGroup *grp) +pgendStoreAccountTree (PGBackend *be, Account *root) { char *p; - ENTER ("be=%p, grp=%p", be, grp); - if (!be || !grp) return; + ENTER ("be=%p, root=%p", be, root); + if (!be || !root) return; /* lock it up so that we store atomically */ p = "BEGIN;\n" @@ -192,12 +182,12 @@ pgendStoreGroup (PGBackend *be, AccountGroup *grp) /* Clear the account marks; this is used to avoid visiting * the same account more than once. */ - xaccClearMarkDownGr (grp, 0); + xaccClearMarkDown (root, 0); - pgendStoreGroupNoLock (be, grp, TRUE, TRUE); + pgendStoreAccountTreeNoLock (be, root, TRUE, TRUE); /* reset the write flags again */ - xaccClearMarkDownGr (grp, 0); + xaccClearMarkDown (root, 0); p = "COMMIT;\n" "NOTIFY gncAccount;"; @@ -211,23 +201,23 @@ pgendStoreGroup (PGBackend *be, AccountGroup *grp) /* ============================================================= */ /* ============================================================= */ -/* This routine walks the account group, gets all KVP values */ +/* This routine walks the account tree, gets all KVP values */ -static gpointer +static void restore_cb (Account *acc, void * cb_data) { PGBackend *be = (PGBackend *) cb_data; - if (0 == acc->idata) return NULL; + if (0 == acc->idata) return; acc->inst.kvp_data = pgendKVPFetch (be, acc->idata, acc->inst.kvp_data); - return NULL; } static void -pgendGetAllAccountKVP (PGBackend *be, AccountGroup *grp) +pgendGetAllAccountKVP (PGBackend *be, Account *root) { - if (!grp) return; + if (!root) return; - xaccGroupForEachAccount (grp, restore_cb, be, TRUE); + restore_cb(root, NULL); + gnc_account_foreach_descendant(root, restore_cb, be); } /* ============================================================= */ @@ -319,8 +309,8 @@ get_account_cb (PGBackend *be, PGresult *result, int j, gpointer data) if (guid_equal(guid_null(), &acct_guid)) { /* if the parent guid is null, then this - * account belongs in the top group */ - xaccGroupInsertAccount (gnc_book_get_group(book), acc); + * account belongs in the top level */ + gnc_account_append_child (gnc_book_get_root_account(book), acc); } else { @@ -338,7 +328,7 @@ get_account_cb (PGBackend *be, PGresult *result, int j, gpointer data) else { xaccAccountBeginEdit(parent); - xaccAccountInsertSubAccount(parent, acc); + gnc_account_append_child(parent, acc); xaccAccountCommitEdit(parent); } } @@ -375,7 +365,7 @@ pgendGetAccounts (PGBackend *be, QofBook *book) pgendGetCommodity (be, ri->commodity_string); commodity = gnc_string_to_commodity (ri->commodity_string, - xaccAccountGetBook (ri->account)); + gnc_account_get_book(ri->account)); if (commodity) { @@ -403,7 +393,7 @@ pgendGetAccounts (PGBackend *be, QofBook *book) if (parent) { xaccAccountBeginEdit(parent); - xaccAccountInsertSubAccount(parent, ri->account); + gnc_account_append_child(parent, ri->account); xaccAccountCommitEdit(parent); } else @@ -441,13 +431,8 @@ pgendGetAllAccounts (PGBackend *be) for (node=be->blist; node; node=node->next) { QofBook *book = node->data; - AccountGroup *topgrp = gnc_book_get_group (book); - pgendGetAllAccountKVP (be, topgrp); - - /* Mark the newly read group as saved, since the act of putting - * it together will have caused it to be marked up as not-saved. - */ - xaccGroupMarkSaved (topgrp); + Account *root = gnc_book_get_root_account(book); + pgendGetAllAccountKVP (be, root); } LEAVE (" "); @@ -457,7 +442,7 @@ void pgendGetAllAccountsInBook (PGBackend *be, QofBook *book) { char *p, buff[400]; - AccountGroup *topgrp; + Account *root; ENTER ("be=%p", be); if (!be || !book) return; @@ -474,13 +459,8 @@ pgendGetAllAccountsInBook (PGBackend *be, QofBook *book) SEND_QUERY (be, buff, ); pgendGetAccounts (be, book); - topgrp = gnc_book_get_group (book); - pgendGetAllAccountKVP (be, topgrp); - - /* Mark the newly read group as saved, since the act of putting - * it together will have caused it to be marked up as not-saved. - */ - xaccGroupMarkSaved (topgrp); + root = gnc_book_get_root_account(book); + pgendGetAllAccountKVP (be, root); LEAVE (" "); } @@ -568,7 +548,6 @@ void pgend_account_commit_edit (QofBackend * bend, Account * acct) { - AccountGroup *parent; char *p; QofBackendError err; PGBackend *be = (PGBackend *)bend; @@ -578,8 +557,6 @@ pgend_account_commit_edit (QofBackend * bend, if (FALSE == acct->inst.dirty) { - parent = xaccAccountGetParent(acct); - if (parent) parent->saved = 1; LEAVE ("account not written because not dirty"); return; } @@ -641,13 +618,6 @@ pgend_account_commit_edit (QofBackend * bend, SEND_QUERY (be,p,); FINISH_QUERY(be->connection); - /* Mark this up so that we don't get that annoying gui dialog - * about having to save to file. unfortunately,however, this - * is too liberal, and could screw up synchronization if we've lost - * contact with the back end at some point. So hack alert -- fix - * this. */ - parent = xaccAccountGetParent(acct); - if (parent) parent->saved = 1; LEAVE ("commited"); return; } diff --git a/src/backend/postgres/account.h b/src/backend/postgres/account.h index 20b0ff373c..f60ee52891 100644 --- a/src/backend/postgres/account.h +++ b/src/backend/postgres/account.h @@ -24,7 +24,7 @@ #ifndef POSTGRES_ACCOUNT_H #define POSTGRES_ACCOUNT_H -#include "Group.h" +#include "Account.h" #include "qof.h" #include "PostgresBackend.h" @@ -33,8 +33,8 @@ void pgendGetAllAccountsInBook (PGBackend *be, QofBook *); void pgendGetAllAccounts (PGBackend *be); -void pgendStoreGroup (PGBackend *be, AccountGroup *grp); -void pgendStoreGroupNoLock (PGBackend *be, AccountGroup *grp, +void pgendStoreAccountTree (PGBackend *be, Account *root); +void pgendStoreAccountTreeNoLock (PGBackend *be, Account *root, gboolean do_mark, gboolean do_check_version); Account * pgendCopyAccountToEngine (PGBackend *be, const GUID *acct_guid); diff --git a/src/backend/postgres/checkpoint.c b/src/backend/postgres/checkpoint.c index 8611cd31f4..317d5cab1d 100644 --- a/src/backend/postgres/checkpoint.c +++ b/src/backend/postgres/checkpoint.c @@ -45,7 +45,6 @@ #include "Account.h" #include "AccountP.h" #include "qof.h" -#include "Group.h" #include "gnc-commodity.h" #include "builder.h" @@ -235,11 +234,13 @@ done: /* recompute fresh balance checkpoints for every account */ void -pgendGroupRecomputeAllCheckpoints (PGBackend *be, AccountGroup *grp) +pgendAccountTreeRecomputeAllCheckpoints (PGBackend *be, Account *parent) { GList *acclist, *node; - acclist = xaccGroupGetSubAccounts(grp); + pgendAccountRecomputeAllCheckpoints (be, xaccAccountGetGUID(parent)); + + acclist = gnc_account_get_descendants(parent); for (node = acclist; node; node=node->next) { Account *acc = (Account *) node->data; @@ -510,16 +511,16 @@ pgendAccountGetBalance (PGBackend *be, Account *acc, Timespec as_of_date) /* get checkpoint value for all accounts */ void -pgendGroupGetAllBalances (PGBackend *be, AccountGroup *grp, +pgendAccountTreeGetAllBalances (PGBackend *be, Account *root, Timespec as_of_date) { GList *acclist, *node; - if (!be || !grp) return; + if (!be || !root) return; ENTER("be=%p", be); /* loop over all accounts */ - acclist = xaccGroupGetSubAccounts (grp); + acclist = gnc_account_get_descendants (root); for (node=acclist; node; node=node->next) { Account *acc = (Account *) node->data; diff --git a/src/backend/postgres/checkpoint.h b/src/backend/postgres/checkpoint.h index 44c8094092..09df9bb14d 100644 --- a/src/backend/postgres/checkpoint.h +++ b/src/backend/postgres/checkpoint.h @@ -35,7 +35,6 @@ #define CHECKPOINT_H #include "Account.h" -#include "Group.h" #include "qof.h" #include "Transaction.h" @@ -79,8 +78,8 @@ typedef struct _checkpoint { void pgendTransactionRecomputeCheckpoints (PGBackend *be, Transaction *trans); void pgendAccountRecomputeOneCheckpoint (PGBackend *be, Account *acc, Timespec ts); -void pgendGroupRecomputeAllCheckpoints (PGBackend *, AccountGroup *); -void pgendGroupGetAllBalances (PGBackend *, AccountGroup *, Timespec as_of_date); +void pgendAccountTreeRecomputeAllCheckpoints (PGBackend *, Account *); +void pgendAccountTreeGetAllBalances (PGBackend *, Account *, Timespec as_of_date); /* The pgendAccountGetBalance() routine goes to the sql database and finds the * balance as of the 'as_of_date' argument. It sets the starting balance for diff --git a/src/backend/postgres/events.c b/src/backend/postgres/events.c index fbc235a240..be1fd0b86e 100644 --- a/src/backend/postgres/events.c +++ b/src/backend/postgres/events.c @@ -1,4 +1,4 @@ -/********************************************************************\ +/******************************************************************** \ * events.c -- implements event handling for postgres backend * * Copyright (c) 2001 Linas Vepstas * * * @@ -290,16 +290,13 @@ pgendProcessEvents (QofBackend *bend) /* if the remote user created an account, mirror it here */ acc = pgendCopyAccountToEngine (be, &(ev->guid)); - xaccGroupMarkSaved (xaccAccountGetRoot(acc)); ent = (QofEntity*)acc; break; } case QOF_EVENT_DESTROY: { Account * acc = pgendAccountLookup (be, &(ev->guid)); - AccountGroup *topgrp = xaccAccountGetRoot(acc); xaccAccountBeginEdit (acc); xaccAccountDestroy (acc); - xaccGroupMarkSaved (topgrp); ent = (QofEntity*)acc; break; } diff --git a/src/backend/postgres/table.m4 b/src/backend/postgres/table.m4 index e702e1134c..639ecb7280 100644 --- a/src/backend/postgres/table.m4 +++ b/src/backend/postgres/table.m4 @@ -13,8 +13,8 @@ define(`account', `gncAccount, Account, Account, a, commodity, , char *, gnc_commodity_get_unique_name(xaccAccountGetCommodity(ptr)), version, , int32, xaccAccountGetVersion(ptr), iguid, , int32, ptr->idata, - bookGUID, , GUID *, qof_entity_get_guid((QofEntity*)xaccAccountGetBook(ptr)), - parentGUID, , GUID *, xaccAccountGetGUID(xaccAccountGetParentAccount(ptr)), + bookGUID, , GUID *, qof_entity_get_guid((QofEntity*)gnc_account_get_book(ptr)), + parentGUID, , GUID *, xaccAccountGetGUID(gnc_account_get_parent(ptr)), accountGUID, KEY, GUID *, xaccAccountGetGUID(ptr), ') diff --git a/src/backend/postgres/test/test-db.c b/src/backend/postgres/test/test-db.c index fcc286de4b..829e9dda52 100644 --- a/src/backend/postgres/test/test-db.c +++ b/src/backend/postgres/test/test-db.c @@ -251,14 +251,12 @@ test_access(DbInfo *dbinfo, gboolean multi_user) return TRUE; } -static gpointer +static void mark_account_commodities(Account * a, gpointer data) { GHashTable *hash = data; g_hash_table_insert(hash, xaccAccountGetCommodity(a), hash); - - return NULL; } static int @@ -311,10 +309,10 @@ remove_unneeded_commodities(QofSession * session) book = qof_session_get_book(session); - xaccGroupForEachAccount(gnc_book_get_group(book), - mark_account_commodities, cdi.hash, TRUE); + gnc_account_foreach_descendant(gnc_book_get_root_account(book), + mark_account_commodities, cdi.hash); - xaccGroupForEachTransaction(gnc_book_get_group(book), + xaccAccountTreeForEachTransaction(gnc_book_get_root_account(book), mark_transaction_commodities, cdi.hash); gnc_pricedb_foreach_price(gnc_book_get_pricedb(book), @@ -473,16 +471,16 @@ num_trans_helper(Transaction * trans, gpointer data) static int session_num_trans(QofSession * session) { - AccountGroup *group; + Account *root; QofBook *book; int num = 0; g_return_val_if_fail(session, 0); book = qof_session_get_book(session); - group = gnc_book_get_group(book); + root = gnc_book_get_root_account(book); - xaccGroupForEachTransaction(group, num_trans_helper, &num); + xaccAccountTreeForEachTransaction(root, num_trans_helper, &num); return num; } @@ -626,7 +624,7 @@ compare_balances(QofSession * session_1, QofSession * session_2) ok = TRUE; - list = xaccGroupGetSubAccounts(gnc_book_get_group(book_1)); + list = gnc_account_get_descendants(gnc_book_get_root_account(book_1)); for (node = list; node; node = node->next) { Account *account_1 = node->data; Account *account_2; @@ -677,21 +675,21 @@ static gboolean test_queries(QofSession * session_base, DbInfo *dbinfo) { QueryTestData qtd; - AccountGroup *group; + Account *root; QofBook *book; gboolean ok; g_return_val_if_fail(dbinfo->dbname && dbinfo->mode, FALSE); book = qof_session_get_book(session_base); - group = gnc_book_get_group(book); + root = gnc_book_get_root_account(book); qtd.session_base = session_base; qtd.dbinfo = dbinfo; qtd.loaded = 0; qtd.total = 0; - ok = xaccGroupForEachTransaction(group, test_trans_query, &qtd); + ok = xaccAccountTreeForEachTransaction(root, test_trans_query, &qtd); #if 0 g_warning("average percentage loaded = %3.2f%%", @@ -708,8 +706,8 @@ typedef struct { QofBook *book_1; QofBook *book_2; - AccountGroup *group_1; - AccountGroup *group_2; + Account *root_1; + Account *root_2; GList *accounts_1; GList *accounts_2; @@ -834,8 +832,8 @@ test_updates_2(QofSession * session_base, DbInfo *dbinfo) td.session_1 = session_base; td.book_1 = qof_session_get_book(session_base); - td.group_1 = gnc_book_get_group(td.book_1); - td.accounts_1 = xaccGroupGetSubAccounts(td.group_1); + td.root_1 = gnc_book_get_root_account(td.book_1); + td.accounts_1 = gnc_account_get_descendants(td.root_1); td.session_2 = qof_session_new(); @@ -845,12 +843,12 @@ test_updates_2(QofSession * session_base, DbInfo *dbinfo) multi_user_get_everything(td.session_2, NULL); td.book_2 = qof_session_get_book(td.session_2); - td.group_2 = gnc_book_get_group(td.book_2); - td.accounts_2 = xaccGroupGetSubAccounts(td.group_2); + td.root_2 = gnc_book_get_root_account(td.book_2); + td.accounts_2 = gnc_account_get_descendants(td.root_2); ok = TRUE; transes = NULL; - xaccGroupForEachTransaction(td.group_1, add_trans_helper, &transes); + xaccAccountTreeForEachTransaction(td.root_1, add_trans_helper, &transes); for (node = transes; node; node = node->next) { ok = test_trans_update(node->data, &td); if (!ok) @@ -891,8 +889,8 @@ test_updates_2(QofSession * session_base, DbInfo *dbinfo) xaccAccountBeginEdit(account); xaccAccountBeginEdit(child); - xaccGroupInsertAccount(td.group_1, account); - xaccAccountInsertSubAccount(account, child); + gnc_account_append_child(td.root_1, account); + gnc_account_append_child(account, child); xaccAccountCommitEdit(child); xaccAccountCommitEdit(account); @@ -1128,8 +1126,8 @@ main (int argc, char **argv) set_max_kvp_depth(3); set_max_kvp_frame_elements(3); - set_max_group_depth(3); - set_max_group_accounts(3); + set_max_account_tree_depth(3); + set_max_accounts_per_level(3); random_timespec_zero_nsec(TRUE); diff --git a/src/backend/postgres/test/test-period.c b/src/backend/postgres/test/test-period.c index 4b8ee8920a..22887671af 100644 --- a/src/backend/postgres/test/test-period.c +++ b/src/backend/postgres/test/test-period.c @@ -28,7 +28,6 @@ #include #include "Account.h" -#include "Group.h" #include "Period.h" #include "qof.h" #include "test-stuff.h" @@ -43,9 +42,8 @@ run_test (void) QofBackendError io_err; QofSession *session; QofBook *openbook, *closedbook; - AccountGroup *grp; - AccountList *acclist, *anode; - Account * acc = NULL; + GList *acclist, *anode; + Account *root, *acc = NULL; SplitList *splist; Split *sfirst, *slast; Transaction *tfirst, *tlast; @@ -72,9 +70,9 @@ run_test (void) add_random_transactions_to_book (openbook, 12); - grp = gnc_book_get_group (openbook); + root = gnc_book_get_root_account(openbook); - acclist = xaccGroupGetSubAccounts (grp); + acclist = gnc_account_get_descendants (root); for (anode=acclist; anode; anode=anode->next) { int ns; @@ -83,6 +81,7 @@ run_test (void) if (2 <= ns) break; acc = NULL; } + g_list_free(acclist); if(!acc) { diff --git a/src/backend/postgres/txn.c b/src/backend/postgres/txn.c index 156519f7de..a02f2b1bb7 100644 --- a/src/backend/postgres/txn.c +++ b/src/backend/postgres/txn.c @@ -31,8 +31,6 @@ #include "Account.h" #include "AccountP.h" -#include "Group.h" -#include "GroupP.h" #include "gnc-commodity.h" #include "gnc-engine.h" #include "gnc-pricedb.h" @@ -350,11 +348,11 @@ trans_traverse_cb (Transaction *trans, void *cb_data) void -pgendStoreAllTransactions (PGBackend *be, AccountGroup *grp) +pgendStoreAllTransactions (PGBackend *be, Account *root) { char *p; - ENTER ("be=%p, grp=%p", be, grp); - if (!be || !grp) return; + ENTER ("be=%p, root=%p", be, root); + if (!be || !root) return; /* lock it up so that we store atomically */ p = "BEGIN;\n" @@ -365,8 +363,8 @@ pgendStoreAllTransactions (PGBackend *be, AccountGroup *grp) /* Recursively walk transactions. Start by reseting the write * flags. We use this to avoid infinite recursion */ - xaccGroupBeginStagedTransactionTraversals(grp); - xaccGroupStagedTransactionTraversal (grp, 1, trans_traverse_cb, be); + gnc_account_tree_begin_staged_transaction_traversals(root); + gnc_account_tree_staged_transaction_traversal (root, 1, trans_traverse_cb, be); p = "COMMIT;\n" "NOTIFY gncTransaction;"; @@ -378,7 +376,7 @@ pgendStoreAllTransactions (PGBackend *be, AccountGroup *grp) if ((MODE_POLL == be->session_mode) || (MODE_EVENT == be->session_mode)) { - pgendGroupRecomputeAllCheckpoints(be, grp); + pgendAccountTreeRecomputeAllCheckpoints(be, root); } LEAVE(" "); } @@ -503,8 +501,6 @@ pgendCopySplitsToEngine (PGBackend *be, Transaction *trans) if (acc) { - int save_state; - if (acc != previous_acc) { xaccAccountCommitEdit (previous_acc); @@ -512,15 +508,7 @@ pgendCopySplitsToEngine (PGBackend *be, Transaction *trans) previous_acc = acc; } - if (acc->parent) - save_state = acc->parent->saved; - else - save_state = 1; - xaccAccountInsertSplit(acc, s); - - if (acc->parent) - acc->parent->saved = save_state; } /* It's ok to set value without an account, since @@ -570,21 +558,12 @@ pgendCopySplitsToEngine (PGBackend *be, Transaction *trans) if (account) { gnc_numeric amount; - int save_state; int acct_frac; - if (account->parent) - save_state = account->parent->saved; - else - save_state = 1; - xaccAccountBeginEdit (account); xaccAccountInsertSplit (account, sri->split); xaccAccountCommitEdit (account); - if (account->parent) - account->parent->saved = save_state; - acct_frac = xaccAccountGetCommoditySCU (account); amount = gnc_numeric_create (sri->amount, acct_frac); xaccSplitSetAmount (sri->split, amount); @@ -1059,12 +1038,17 @@ pgend_trans_commit_edit (QofBackend * bend, * what should happen is the user should get a chance to * resynchronize their data with the backend, before quiting out. */ +#if 0 + /* DRH - Is this code required any more? The whole point seems to + * be to clear the dirty flag in any of the AccountGroup data + * structures. Since these structures no longer exist.... */ { Split * s = xaccTransGetSplit (trans, 0); Account *acc = xaccSplitGetAccount (s); - AccountGroup *top = xaccAccountGetRoot (acc); + AccountGroup *top = gnc_account_get_root (acc); xaccGroupMarkSaved (top); } +#endif LEAVE ("commited"); return; diff --git a/src/backend/postgres/txn.h b/src/backend/postgres/txn.h index 8fbcdf8544..92eb055310 100644 --- a/src/backend/postgres/txn.h +++ b/src/backend/postgres/txn.h @@ -36,7 +36,6 @@ #include -#include "Group.h" #include "qof.h" #include "Transaction.h" @@ -45,7 +44,7 @@ int pgendCopyTransactionToEngine (PGBackend *be, const GUID *trans_guid); void pgendCopySplitsToEngine (PGBackend *be, Transaction *trans); -void pgendStoreAllTransactions (PGBackend *be, AccountGroup *grp); +void pgendStoreAllTransactions (PGBackend *be, Account *root); void pgendStoreTransactionNoLock (PGBackend *be, Transaction *trans, gboolean do_check_version); void pgend_trans_commit_edit (QofBackend * bend, Transaction * trans, Transaction * oldtrans); diff --git a/src/backend/postgres/txnmass.c b/src/backend/postgres/txnmass.c index 34ed16dc43..30be9d55b8 100644 --- a/src/backend/postgres/txnmass.c +++ b/src/backend/postgres/txnmass.c @@ -31,8 +31,6 @@ #include "Account.h" #include "AccountP.h" -#include "Group.h" -#include "GroupP.h" #include "gnc-commodity.h" #include "gnc-engine.h" #include "Transaction.h" @@ -215,7 +213,7 @@ pgendGetMassTransactions (PGBackend *be, QofBook *book) { char *p, buff[900]; GList *node, *xaction_list = NULL; - AccountGroup *grp; + Account *root; qof_event_suspend(); pgendDisable(be); @@ -233,8 +231,8 @@ pgendGetMassTransactions (PGBackend *be, QofBook *book) SEND_QUERY (be, buff, ); /* restore the transactions */ - grp = gnc_book_get_group (book); - xaccAccountGroupBeginEdit (grp); + root = gnc_book_get_root_account (book); + xaccAccountBeginEdit (root); be->tmp_return = NULL; pgendGetResults (be, get_mass_trans_cb, book); @@ -280,7 +278,7 @@ pgendGetMassTransactions (PGBackend *be, QofBook *book) } g_list_free(xaction_list); - xaccAccountGroupCommitEdit (grp); + xaccAccountCommitEdit (root); pgendEnable(be); qof_event_resume(); diff --git a/src/business/business-core/gncInvoice.c b/src/business/business-core/gncInvoice.c index ec9698948f..265cb839f4 100644 --- a/src/business/business-core/gncInvoice.c +++ b/src/business/business-core/gncInvoice.c @@ -1262,7 +1262,7 @@ gncOwnerApplyPayment (GncOwner *owner, GncInvoice* invoice, g_return_val_if_fail (owner->owner.undefined != NULL, NULL); /* Compute the ancillary data */ - book = xaccAccountGetBook (posted_acc); + book = gnc_account_get_book (posted_acc); name = gncOwnerGetName (gncOwnerGetEndOwner (owner)); commodity = gncOwnerGetCurrency (owner); reverse = (gncOwnerGetType (owner) == GNC_OWNER_CUSTOMER); diff --git a/src/business/business-gnome/business-gnome-utils.c b/src/business/business-gnome/business-gnome-utils.c index 7e8970378c..89a3c2f5e6 100644 --- a/src/business/business-gnome/business-gnome-utils.c +++ b/src/business/business-gnome/business-gnome-utils.c @@ -28,7 +28,6 @@ #include #include -#include "Group.h" #include "Account.h" #include "gnc-ui-util.h" #include "qof.h" @@ -318,7 +317,7 @@ gnc_fill_account_select_combo (GtkWidget *combo, GNCBook *book, /* Figure out if anything is set in the combo */ text = gtk_combo_box_get_active_text(GTK_COMBO_BOX(combo)); - list = xaccGroupGetSubAccounts (gnc_book_get_group (book)); + list = gnc_account_get_descendants (gnc_book_get_root_account (book)); /* Clear the existing list */ entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(combo))); diff --git a/src/business/business-gnome/dialog-payment.c b/src/business/business-gnome/dialog-payment.c index 9e6ba6302a..c7aad6426d 100644 --- a/src/business/business-gnome/dialog-payment.c +++ b/src/business/business-gnome/dialog-payment.c @@ -255,7 +255,7 @@ gnc_payment_ok_cb (GtkWidget *widget, gpointer data) return; } - post = xaccGetAccountFromFullName (gnc_book_get_group (pw->book), text); + post = gnc_account_lookup_full_name (gnc_book_get_root_account (pw->book), text); if (!post) { char *msg = g_strdup_printf ( diff --git a/src/business/business-gnome/gnc-plugin-business.c b/src/business/business-gnome/gnc-plugin-business.c index 6beb2581cd..965510b8bd 100644 --- a/src/business/business-gnome/gnc-plugin-business.c +++ b/src/business/business-gnome/gnc-plugin-business.c @@ -886,7 +886,7 @@ gnc_plugin_business_cmd_test_init_data (GtkAction *action, GncInvoice *invoice = gncInvoiceCreate(book); GncOwner *owner = gncOwnerCreate(); GncJob *job = gncJobCreate(book); - AccountGroup *group = xaccGetAccountGroup(book); + Account *root = gnc_book_get_root_account(book); Account *inc_acct = xaccMallocAccount(book); Account *bank_acct = xaccMallocAccount(book); Account *tax_acct = xaccMallocAccount(book); @@ -925,25 +925,25 @@ gnc_plugin_business_cmd_test_init_data (GtkAction *action, xaccAccountSetType(ar_acct, ACCT_TYPE_RECEIVABLE); xaccAccountSetName(ar_acct, "A/R"); xaccAccountSetCommodity(ar_acct, gnc_default_currency()); - xaccGroupInsertAccount(group, ar_acct); + gnc_account_append_child(root, ar_acct); // Create the Income account xaccAccountSetType(inc_acct, ACCT_TYPE_INCOME); xaccAccountSetName(inc_acct, "Income"); xaccAccountSetCommodity(inc_acct, gnc_default_currency()); - xaccGroupInsertAccount(group, inc_acct); + gnc_account_append_child(root, inc_acct); // Create the Bank account xaccAccountSetType(bank_acct, ACCT_TYPE_BANK); xaccAccountSetName(bank_acct, "Bank"); xaccAccountSetCommodity(bank_acct, gnc_default_currency()); - xaccGroupInsertAccount(group, bank_acct); + gnc_account_append_child(root, bank_acct); // Create the Tax account xaccAccountSetType(tax_acct, ACCT_TYPE_LIABILITY); xaccAccountSetName(tax_acct, "Tax-Holding"); xaccAccountSetCommodity(tax_acct, gnc_default_currency()); - xaccGroupInsertAccount(group, tax_acct); + gnc_account_append_child(root, tax_acct); // Launch the invoice editor gnc_ui_invoice_edit(invoice); diff --git a/src/business/business-gnome/gnc-plugin-page-invoice.c b/src/business/business-gnome/gnc-plugin-page-invoice.c index cdf86af9b8..b8653269b5 100644 --- a/src/business/business-gnome/gnc-plugin-page-invoice.c +++ b/src/business/business-gnome/gnc-plugin-page-invoice.c @@ -534,7 +534,7 @@ gnc_plugin_page_invoice_cmd_new_account (GtkAction *action, g_return_if_fail(GNC_IS_PLUGIN_PAGE_INVOICE(plugin_page)); ENTER("(action %p, plugin_page %p)", action, plugin_page); - gnc_ui_new_account_window (NULL); + gnc_ui_new_account_window (gnc_get_current_book(), NULL); LEAVE(" "); } diff --git a/src/business/business-ledger/gncEntryLedger.c b/src/business/business-ledger/gncEntryLedger.c index 1c31d621e6..21604d51ce 100644 --- a/src/business/business-ledger/gncEntryLedger.c +++ b/src/business/business-ledger/gncEntryLedger.c @@ -86,7 +86,7 @@ gnc_entry_ledger_get_account_by_name (GncEntryLedger *ledger, BasicCell * bcell, Account *account; /* Find the account */ - account = xaccGetAccountFromFullName (gnc_get_current_group (), name); + account = gnc_account_lookup_full_name (gnc_get_current_root_account (), name); if (!account) { /* Ask if they want to create a new one. */ diff --git a/src/business/business-ledger/gncEntryLedgerLoad.c b/src/business/business-ledger/gncEntryLedgerLoad.c index 3747ce5e14..aec1b9e876 100644 --- a/src/business/business-ledger/gncEntryLedgerLoad.c +++ b/src/business/business-ledger/gncEntryLedgerLoad.c @@ -180,13 +180,13 @@ skip_income_acct_cb (Account *account, gpointer user_data) static void load_xfer_type_cells (GncEntryLedger *ledger) { - AccountGroup *group; + Account *root; ComboCell *cell; QuickFill *qf=NULL; GtkListStore *store = NULL; - group = gnc_book_get_group (ledger->book); - if (group == NULL) return; + root = gnc_book_get_root_account (ledger->book); + if (root == NULL) return; /* Use a common, shared quickfill. For the ORDER or INVOICE, * ledgers, we don't want expense-type accounts in the menu. @@ -198,9 +198,9 @@ load_xfer_type_cells (GncEntryLedger *ledger) case GNCENTRY_ORDER_VIEWER: case GNCENTRY_INVOICE_ENTRY: case GNCENTRY_INVOICE_VIEWER: - qf = gnc_get_shared_account_name_quickfill (group, IKEY, + qf = gnc_get_shared_account_name_quickfill (root, IKEY, skip_expense_acct_cb, NULL); - store = gnc_get_shared_account_name_list_store (group, IKEY, + store = gnc_get_shared_account_name_list_store (root, IKEY, skip_expense_acct_cb, NULL); break; @@ -209,9 +209,9 @@ load_xfer_type_cells (GncEntryLedger *ledger) case GNCENTRY_EXPVOUCHER_ENTRY: case GNCENTRY_EXPVOUCHER_VIEWER: case GNCENTRY_NUM_REGISTER_TYPES: - qf = gnc_get_shared_account_name_quickfill (group, EKEY, + qf = gnc_get_shared_account_name_quickfill (root, EKEY, skip_income_acct_cb, NULL); - store = gnc_get_shared_account_name_list_store (group, EKEY, + store = gnc_get_shared_account_name_list_store (root, EKEY, skip_income_acct_cb, NULL); break; } diff --git a/src/business/business-reports/owner-report.scm b/src/business/business-reports/owner-report.scm index d24f4c4de5..62102f39e0 100644 --- a/src/business/business-reports/owner-report.scm +++ b/src/business/business-reports/owner-report.scm @@ -626,14 +626,14 @@ document)) (define (find-first-account type) - (define (find-first group num index) + (define (find-first account num index) (if (>= index num) '() (let* ((this-account (xaccGroupGetAccount group index)) (account-type (xaccAccountGetType this-account))) (if (eq? account-type type) - this-account - (find-first group num (+ index 1)))))) + this-child + (find-first account num (+ index 1)))))) (let* ((current-group (gnc-get-current-group)) (num-accounts (xaccGroupGetNumAccounts diff --git a/src/engine/Account.c b/src/engine/Account.c index ddc8836a11..614cad1cda 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -30,8 +30,8 @@ #include #include "AccountP.h" -#include "Group.h" -#include "GroupP.h" +#include "Split.h" +#include "Transaction.h" #include "TransactionP.h" #include "gnc-event.h" #include "gnc-glib-utils.h" @@ -40,6 +40,8 @@ #include "gnc-pricedb.h" #include "policy.h" +#define GNC_ID_ROOT_ACCOUNT "RootAccount" + static QofLogModule log_module = GNC_MOD_ACCOUNT; /* The Canonical Account Separator. Pre-Initialized. */ @@ -100,7 +102,6 @@ G_INLINE_FUNC void mark_account (Account *acc); void mark_account (Account *acc) { - if (acc->parent) acc->parent->saved = FALSE; qof_instance_set_dirty(&acc->inst); } @@ -151,6 +152,58 @@ xaccInitAccount (Account * acc, QofBook *book) /********************************************************************\ \********************************************************************/ +Account * +gnc_coll_get_root_account (QofCollection *col) +{ + if (!col) return NULL; + return qof_collection_get_data (col); +} + +void +gnc_coll_set_root_account (QofCollection *col, Account *root) +{ + Account *old_root; + if (!col) return; + + old_root = gnc_coll_get_root_account (col); + if (old_root == root) return; + + qof_collection_set_data (col, root); + + if (old_root) { + xaccAccountBeginEdit (old_root); + xaccAccountDestroy (old_root); + } +} + +Account * +gnc_book_get_root_account (QofBook *book) +{ + QofCollection *col; + if (!book) return NULL; + col = qof_book_get_collection (book, GNC_ID_ROOT_ACCOUNT); + return gnc_coll_get_root_account (col); +} + +void +gnc_book_set_root_account (QofBook *book, Account *root) +{ + QofCollection *col; + if (!book) return; + + if (root && gnc_account_get_book(root) != book) + { + PERR ("cannot mix and match books freely!"); + return; + } + + col = qof_book_get_collection (book, GNC_ID_ROOT_ACCOUNT); + gnc_coll_set_root_account (col, root); +} + +/********************************************************************\ +\********************************************************************/ + Account * xaccMallocAccount (QofBook *book) { @@ -165,6 +218,21 @@ xaccMallocAccount (QofBook *book) return acc; } +Account * +gnc_account_create_root (QofBook *book, gnc_commodity *com) +{ + Account *root; + + root = xaccMallocAccount(book); + xaccAccountBeginEdit(root); + root->type = ACCT_TYPE_ROOT; + root->commodity = com; + root->commodity_scu = gnc_commodity_get_fraction(com); + xaccAccountCommitEdit(root); + gnc_book_set_root_account(book, root); + return root; +} + static Account * xaccCloneAccountCommon(const Account *from, QofBook *book) { @@ -222,6 +290,32 @@ xaccCloneAccountSimple (const Account *from, QofBook *book) /********************************************************************\ \********************************************************************/ +static void +xaccFreeOneChildAccount (Account *acc, gpointer dummy) +{ + /* FIXME: this code is kind of hacky. actually, all this code + * seems to assume that the account edit levels are all 1. */ + if (acc->inst.editlevel == 0) + xaccAccountBeginEdit(acc); + xaccAccountDestroy(acc); +} + +static void +xaccFreeAccountChildren (Account *acc) +{ + GList *children; + + /* Copy the list since it will be modified */ + children = g_list_copy(acc->children); + g_list_foreach(children, (GFunc)xaccFreeOneChildAccount, NULL); + g_list_free(children); + + /* The foreach should have removed all the children already. */ + if (acc->children) + g_list_free(acc->children); + acc->children = NULL; +} + void xaccFreeAccount (Account *acc) { @@ -237,8 +331,7 @@ xaccFreeAccount (Account *acc) " xaccAccountBeginEdit(); xaccAccountDestroy(); \n"); /* First, recursively free children */ - xaccFreeAccountGroup (acc->children); - acc->children = NULL; + xaccFreeAccountChildren(acc); } /* remove lots -- although these should be gone by now. */ @@ -329,7 +422,9 @@ static inline void on_err (QofInstance *inst, QofBackendError errcode) static inline void acc_free (QofInstance *inst) { Account *acc = (Account *) inst; - xaccGroupRemoveAccount(acc->parent, acc); + + if (acc->parent) + gnc_account_remove_child(acc->parent, acc); xaccFreeAccount(acc); } @@ -360,8 +455,7 @@ xaccAccountCommitEdit (Account *acc) acc->inst.editlevel++; /* First, recursively free children */ - xaccFreeAccountGroup (acc->children); - acc->children = NULL; + xaccFreeAccountChildren(acc); PINFO ("freeing splits for account %p (%s)", acc, acc->accountName ? acc->accountName : "(null)"); @@ -432,6 +526,48 @@ xaccAccountGetVersion (const Account *acc) /********************************************************************\ \********************************************************************/ +static gboolean +xaccAcctChildrenEqual(const GList *na, + const GList *nb, + gboolean check_guids) +{ + if ((!na && nb) || (na && !nb)) + { + PWARN ("only one has accounts"); + return(FALSE); + } + + while (na && nb) + { + Account *aa = na->data; + Account *ab = nb->data; + + if (!xaccAccountEqual(aa, ab, check_guids)) + { + char sa[GUID_ENCODING_LENGTH + 1]; + char sb[GUID_ENCODING_LENGTH + 1]; + + guid_to_string_buff (xaccAccountGetGUID (aa), sa); + guid_to_string_buff (xaccAccountGetGUID (ab), sb); + + PWARN ("accounts %s and %s differ", sa, sb); + + return(FALSE); + } + + na = na->next; + nb = nb->next; + } + + if (na || nb) + { + PWARN ("different numbers of accounts"); + return(FALSE); + } + + return(TRUE); +} + gboolean xaccAccountEqual(const Account *aa, const Account *ab, gboolean check_guids) { @@ -633,7 +769,7 @@ xaccAccountEqual(const Account *aa, const Account *ab, gboolean check_guids) } } - if (!xaccGroupEqual(aa->children, ab->children, check_guids)) + if (!xaccAcctChildrenEqual(aa->children, ab->children, check_guids)) { PWARN ("children differ"); return FALSE; @@ -712,69 +848,23 @@ xaccAccountSetMark (Account *acc, short m) void xaccClearMark (Account *acc, short val) { - AccountGroup *topgrp; + Account *root; if (!acc) return; - topgrp = xaccAccountGetRoot (acc); - - if (topgrp) - { - GList *list; - GList *node; - - list = xaccGroupGetAccountList (topgrp); - - for (node = list; node; node = node->next) - { - Account *account = node->data; - - xaccClearMarkDown (account, val); - } - } - else - xaccClearMarkDown (acc, val); + root = gnc_account_get_root (acc); + xaccClearMarkDown (root ? root : acc, val); } void xaccClearMarkDown (Account *acc, short val) { - AccountGroup *children; + GList *node; if (!acc) return; acc->mark = val; - children = acc->children; - if (children) - { - GList *list; - GList *node; - - list = xaccGroupGetAccountList (children); - - for (node = list; node; node = node->next) - { - Account *account = node->data; - - xaccClearMarkDown (account, val); - } - } -} - -void -xaccClearMarkDownGr (AccountGroup *grp, short val) -{ - GList *list; - GList *node; - - if (!grp) return; - - list = xaccGroupGetAccountList (grp); - - for (node = list; node; node = node->next) - { - Account *account = node->data; - - xaccClearMarkDown (account, val); + for (node = acc->children; node; node = node->next) { + xaccClearMarkDown (node->data, val); } } @@ -996,20 +1086,20 @@ static int revorder[NUM_ACCOUNT_TYPES] = { int -xaccAccountOrder (const Account **aa, const Account **ab) +xaccAccountOrder (const Account *aa, const Account *ab) { char *da, *db; char *endptr = NULL; int ta, tb, result; long la, lb; - if ( (*aa) && !(*ab) ) return -1; - if ( !(*aa) && (*ab) ) return +1; - if ( !(*aa) && !(*ab) ) return 0; + if ( aa && !ab ) return -1; + if ( !aa && ab ) return +1; + if ( !aa && !ab ) return 0; /* sort on accountCode strings */ - da = (*aa)->accountCode; - db = (*ab)->accountCode; + da = aa->accountCode; + db = ab->accountCode; /* If accountCodes are both base 36 integers do an integer sort */ la = strtoul (da, &endptr, 36); @@ -1036,22 +1126,28 @@ xaccAccountOrder (const Account **aa, const Account **ab) } /* otherwise, sort on account type */ - ta = (*aa)->type; - tb = (*ab)->type; + ta = aa->type; + tb = ab->type; ta = revorder[ta]; tb = revorder[tb]; if (ta < tb) return -1; if (ta > tb) return +1; /* otherwise, sort on accountName strings */ - da = (*aa)->accountName; - db = (*ab)->accountName; + da = aa->accountName; + db = ab->accountName; result = safe_utf8_collate(da, db); if (result) return result; /* guarantee a stable sort */ - return guid_compare (&((*aa)->inst.entity.guid), &((*ab)->inst.entity.guid)); + return guid_compare (&(aa->inst.entity.guid), &(ab->inst.entity.guid)); +} + +static int +qof_xaccAccountOrder (const Account **aa, const Account **ab) +{ + return xaccAccountOrder(*aa, *ab); } /********************************************************************\ @@ -1115,7 +1211,7 @@ qofAccountSetParent (Account *acc, QofEntity *parent) parent_acc = (Account*)parent; xaccAccountBeginEdit(acc); xaccAccountBeginEdit(parent_acc); - xaccAccountInsertSubAccount(parent_acc, acc); + gnc_account_append_child(parent_acc, acc); mark_account (parent_acc); mark_account (acc); xaccAccountCommitEdit(acc); @@ -1258,30 +1354,376 @@ DxaccAccountSetCurrency (Account * acc, gnc_commodity * currency) /********************************************************************\ \********************************************************************/ -AccountGroup * -xaccAccountGetChildren (const Account *acc) +void +gnc_account_append_child (Account *new_parent, Account *child) +{ + Account *old_parent; + QofCollection *col; + + g_assert(new_parent); + g_assert(child); + + old_parent = child->parent; + if (old_parent == new_parent) + return; + + // xaccAccountBeginEdit(new_parent); + xaccAccountBeginEdit(child); + if (old_parent) { + gnc_account_remove_child(old_parent, child); + + if (old_parent->inst.book != new_parent->inst.book) { + /* hack alert -- this implementation is not exactly correct. + * If the entity tables are not identical, then the 'from' book + * may have a different backend than the 'to' book. This means + * that we should get the 'from' backend to destroy this account, + * and the 'to' backend to save it. Right now, this is broken. + * + * A 'correct' implementation similar to this is in Period.c + * except its for transactions ... + * + * Note also, we need to reparent the children to the new book as well. + */ + PWARN ("reparenting accounts across books is not correctly supported\n"); + + qof_event_gen (&child->inst.entity, QOF_EVENT_DESTROY, NULL); + col = qof_book_get_collection (new_parent->inst.book, GNC_ID_ACCOUNT); + qof_collection_insert_entity (col, &child->inst.entity); + qof_event_gen (&child->inst.entity, QOF_EVENT_CREATE, NULL); + } + } + child->parent = new_parent; + new_parent->children = g_list_append(new_parent->children, child); + qof_instance_set_dirty(&new_parent->inst); + qof_instance_set_dirty(&child->inst); + + /* Send events data. Warning: The call to commit_edit is also gpoing + * to send a MODIFY event. If the gtktreemodelfilter code gets the + * MODIFY before it gets the ADD, it gets very confused and thinks + * that two nodes have been added. */ + qof_event_gen (&child->inst.entity, QOF_EVENT_ADD, NULL); + // qof_event_gen (&new_parent->inst.entity, QOF_EVENT_MODIFY, NULL); + + xaccAccountCommitEdit (child); + // xaccAccountCommitEdit(new_parent); +} + +void +gnc_account_remove_child (Account *parent, Account *child) { - return acc ? acc->children : NULL; + GncEventData ed; + + if (!child) return; + + /* Note this routine might be called on accounts which + * are not yet parented. */ + if (!parent) return; + + if (child->parent != parent) + { + PERR ("account not a child of parent"); + return; + } + + /* Gather event data */ + ed.node = parent; + ed.idx = g_list_index(parent->children, child); + + parent->children = g_list_remove (parent->children, child); + + /* Now send the event. */ + qof_event_gen(&child->inst.entity, QOF_EVENT_REMOVE, &ed); + + /* clear the account's parent pointer after REMOVE event generation. */ + child->parent = NULL; + + qof_event_gen (&parent->inst.entity, QOF_EVENT_MODIFY, NULL); } -AccountGroup * -xaccAccountGetParent (const Account *acc) +Account * +gnc_account_get_parent (const Account *acc) { return acc ? acc->parent : NULL; } Account * -xaccAccountGetParentAccount (const Account * acc) +gnc_account_get_root (Account *acc) +{ + if (!acc) + return NULL; + + while (acc->parent) { + acc = acc->parent; + } + + return acc; +} + +gboolean +gnc_account_is_root (const Account *account) +{ + return (account && account->parent == NULL); +} + +GList * +gnc_account_get_children (const Account *acc) +{ + return acc ? g_list_copy(acc->children) : NULL; +} + +gint +gnc_account_n_children (const Account *account) +{ + return account ? g_list_length(account->children) : 0; +} + +gint +gnc_account_child_index (const Account *parent, const Account *child) +{ + return parent ? g_list_index(parent->children, child) : -1; +} + +Account * +gnc_account_nth_child (const Account *parent, gint num) +{ + return parent ? g_list_nth_data(parent->children, num) : NULL; +} + +GList * +gnc_account_get_descendants (const Account *account) { - return acc ? xaccGroupGetParentAccount(acc->parent) : NULL; + GList *child, *descendants; + + if (!account || !account->children) + return NULL; + + descendants = NULL; + for (child = account->children; child; child = g_list_next(child)) { + descendants = g_list_append(descendants, child->data); + descendants = g_list_concat(descendants, + gnc_account_get_descendants(child->data)); + } + return descendants; } GList * -xaccAccountGetDescendants (const Account *acc) +gnc_account_get_descendants_sorted (const Account *account) +{ + GList *child, *children, *descendants; + + if (!account || !account->children) + return NULL; + + descendants = NULL; + children = g_list_sort(g_list_copy(account->children), (GCompareFunc)xaccAccountOrder); + for (child = children; child; child = g_list_next(child)) { + descendants = g_list_append(descendants, child->data); + descendants = g_list_concat(descendants, + gnc_account_get_descendants(child->data)); + } + g_list_free(children); + return descendants; +} + +gint +gnc_account_n_descendants (const Account *account) { - return acc ? xaccGroupGetSubAccounts(acc->children) : NULL; + GList *node; + gint count = 0; + + if (!account) + return 0; + + for (node = account->children; node; node = g_list_next(node)) { + count += gnc_account_n_descendants(node->data) + 1; + } + return count; } +gint +gnc_account_get_depth (const Account *account) +{ + GList *node; + gint depth = 0, child_depth; + + if (!account) + return 0; + if (!account->children) + return 1; + + for (node = account->children; node; node = g_list_next(node)) { + child_depth = gnc_account_get_depth(node->data); + depth = MAX(depth, child_depth); + } + return depth + 1; +} + +Account * +gnc_account_lookup_name (const Account *parent, const char * name) +{ + Account *child, *result; + GList *node; + + if (!parent) return NULL; + if (!name) return NULL; + + /* first, look for accounts hanging off the current node */ + for (node = parent->children; node; node = node->next) + { + child = node->data; + if (safe_strcmp(child->accountName, name) == 0) + return child; + } + + /* if we are still here, then we haven't found the account yet. + * Recursively search each of the child accounts next */ + for (node = parent->children; node; node = node->next) + { + child = node->data; + result = gnc_account_lookup_name (child, name); + if (result) + return result; + } + + return NULL; +} + +/********************************************************************\ + * Fetch an account, given its full name * +\********************************************************************/ + +static Account * +gnc_account_lookup_full_name_helper (const Account *parent, + gchar **names) +{ + Account *found; + GList *node; + + g_return_val_if_fail(parent, NULL); + g_return_val_if_fail(names, NULL); + + /* Look for the first name in the children. */ + for (node = parent->children; node; node = node->next) { + Account *account = node->data; + + if (safe_strcmp(account->accountName, names[0]) == 0) { + /* We found an account. If the next entry is NULL, there is + * nothing left in the name, so just return the account. */ + if (names[1] == NULL) + return account; + + /* No children? We're done. */ + if (!account->children) + return NULL; + + /* There's stuff left to search for. Search recursively. */ + found = gnc_account_lookup_full_name_helper(account, &names[1]); + if (found != NULL) { + return found; + } + } + } + + return NULL; +} + + +Account * +gnc_account_lookup_full_name (const Account *any_acc, + const gchar *name) +{ + const Account *root; + Account *found; + gchar **names; + + if (!any_acc) return NULL; + if (!name) return NULL; + + root = any_acc; + while (root->parent) + root = root->parent; + names = g_strsplit(name, gnc_get_account_separator_string(), -1); + found = gnc_account_lookup_full_name_helper(root, names); + g_strfreev(names); + return found; +} + +void +gnc_account_foreach_child (const Account *acc, + AccountCb thunk, + gpointer user_data) +{ + GList *node; + + if (!acc || !thunk) return; + + for (node = acc->children; node; node = node->next) { + thunk (node->data, user_data); + } +} + +gpointer +gnc_account_foreach_child_until (const Account *acc, + AccountCb2 thunk, + gpointer user_data) +{ + GList *node; + gpointer result; + + if (!acc || !thunk) return(NULL); + + for (node = acc->children; node; node = node->next) { + result = thunk (node->data, user_data); + if (result) + return(result); + } + + return(NULL); +} + +void +gnc_account_foreach_descendant (const Account *acc, + AccountCb thunk, + gpointer user_data) +{ + GList *node; + Account *child; + + if (!acc || !thunk) return; + + for (node = acc->children; node; node = node->next) { + child = node->data; + thunk(child, user_data); + gnc_account_foreach_descendant(child, thunk, user_data); + } +} + +gpointer +gnc_account_foreach_descendant_until (const Account *acc, + AccountCb2 thunk, + gpointer user_data) +{ + GList *node; + Account *child; + gpointer result; + + if (!acc || !thunk) return(NULL); + + for (node = acc->children; node; node = node->next) { + child = node->data; + result = thunk(child, user_data); + if (result) + return(result); + + result = gnc_account_foreach_descendant_until(child, thunk, user_data); + if (result) + return(result); + } + + return(NULL); +} + + GNCAccountType xaccAccountGetType (const Account *acc) { @@ -1314,23 +1756,25 @@ xaccAccountGetFullName(const Account *account) gchar **names; int level; - if (account == NULL) + if (!account || !account->parent) return g_strdup(""); - /* Figure out how much space is needed */ + /* Figure out how much space is needed by counting the nodes up to + * the root. */ level = 0; - for (a = account; a; a = xaccAccountGetParentAccount(a)) { + for (a = account; a; a = a->parent) { level++; } - /* Get all the pointers in the right order. */ - names = g_malloc((level+1) * sizeof(gchar *)); - names[level] = NULL; - for (a = account; a; a = xaccAccountGetParentAccount(a)) { + /* Get all the pointers in the right order. The root node "entry" + * becomes the terminating NULL pointer for the array of strings. */ + names = g_malloc(level * sizeof(gchar *)); + names[--level] = NULL; + for (a = account; level > 0; a = a->parent) { names[--level] = a->accountName; } - /* Build it */ + /* Build the full name */ fullname = g_strjoinv(account_separator, names); g_free(names); @@ -1551,7 +1995,7 @@ xaccAccountConvertBalanceToCurrency(const Account *acc, /* for book */ gnc_commodity_equiv (balance_currency, new_currency)) return balance; - book = xaccGroupGetBook (xaccAccountGetRoot (acc)); + book = gnc_account_get_book (acc); pdb = gnc_pricedb_get_db (book); balance = gnc_pricedb_convert_balance_latest_price( @@ -1579,7 +2023,7 @@ xaccAccountConvertBalanceToCurrencyAsOfDate(const Account *acc, /* for book */ gnc_commodity_equiv (balance_currency, new_currency)) return balance; - book = xaccGroupGetBook (xaccAccountGetRoot (acc)); + book = gnc_account_get_book (acc); pdb = gnc_book_get_pricedb (book); ts.tv_sec = date; @@ -1639,34 +2083,33 @@ typedef struct * tree. This function is called once per account, and sums up the * values of all these accounts. */ -static gpointer +static void xaccAccountBalanceHelper (Account *acc, gpointer data) { CurrencyBalance *cb = data; gnc_numeric balance; if (!cb->fn || !cb->currency) - return NULL; + return; balance = xaccAccountGetXxxBalanceInCurrency (acc, cb->fn, cb->currency); cb->balance = gnc_numeric_add (cb->balance, balance, gnc_commodity_get_fraction (cb->currency), GNC_HOW_RND_ROUND); - return NULL; } -static gpointer + +static void xaccAccountBalanceAsOfDateHelper (Account *acc, gpointer data) { CurrencyBalance *cb = data; gnc_numeric balance; - g_return_val_if_fail (cb->asOfDateFn && cb->currency, NULL); + g_return_if_fail (cb->asOfDateFn && cb->currency); balance = xaccAccountGetXxxBalanceAsOfDateInCurrency ( acc, cb->date, cb->asOfDateFn, cb->currency); cb->balance = gnc_numeric_add (cb->balance, balance, gnc_commodity_get_fraction (cb->currency), GNC_HOW_RND_ROUND); - return NULL; } @@ -1700,8 +2143,7 @@ xaccAccountGetXxxBalanceInCurrencyRecursive (const Account *acc, if (include_children) { CurrencyBalance cb = { report_commodity, balance, fn, NULL, 0 }; - xaccGroupForEachAccount (acc->children, xaccAccountBalanceHelper, - &cb, TRUE); + gnc_account_foreach_descendant (acc, xaccAccountBalanceHelper, &cb); balance = cb.balance; } @@ -1727,8 +2169,7 @@ xaccAccountGetXxxBalanceAsOfDateInCurrencyRecursive ( if (include_children) { CurrencyBalance cb = { report_commodity, balance, NULL, fn, date }; - xaccGroupForEachAccount (acc->children, - xaccAccountBalanceAsOfDateHelper, &cb, TRUE); + gnc_account_foreach_descendant (acc, xaccAccountBalanceAsOfDateHelper, &cb); balance = cb.balance; } @@ -1974,7 +2415,7 @@ xaccAccountGetDescendantPlaceholder (const Account *acc) if (!acc) return PLACEHOLDER_NONE; if (xaccAccountGetPlaceholder(acc)) return PLACEHOLDER_THIS; - descendants = xaccGroupGetSubAccounts(acc->children); + descendants = gnc_account_get_descendants(acc); for (node = descendants; node; node = node->next) if (xaccAccountGetPlaceholder((Account *) node->data)) { ret = PLACEHOLDER_CHILD; @@ -2018,7 +2459,7 @@ xaccAccountIsHidden (const Account *acc) if (xaccAccountGetHidden(acc)) return TRUE; - while ((acc = xaccAccountGetParentAccount(acc)) != NULL) { + while ((acc = acc->parent) != NULL) { if (xaccAccountGetHidden(acc)) return TRUE; } @@ -2036,7 +2477,7 @@ xaccAccountHasAncestor (const Account *acc, const Account * ancestor) if (!acc || !ancestor) return FALSE; while (parent && parent != ancestor) - parent = xaccAccountGetParentAccount(parent); + parent = parent->parent; return (parent == ancestor); } @@ -2068,6 +2509,7 @@ xaccAccountTypeEnumAsString(GNCAccountType type) GNC_RETURN_ENUM_AS_STRING(EQUITY); GNC_RETURN_ENUM_AS_STRING(RECEIVABLE); GNC_RETURN_ENUM_AS_STRING(PAYABLE); + GNC_RETURN_ENUM_AS_STRING(ROOT); GNC_RETURN_ENUM_AS_STRING(CHECKING); GNC_RETURN_ENUM_AS_STRING(SAVINGS); GNC_RETURN_ENUM_AS_STRING(MONEYMRKT); @@ -2102,6 +2544,7 @@ xaccAccountStringToType(const char* str, GNCAccountType *type) GNC_RETURN_ON_MATCH(EQUITY); GNC_RETURN_ON_MATCH(RECEIVABLE); GNC_RETURN_ON_MATCH(PAYABLE); + GNC_RETURN_ON_MATCH(ROOT); GNC_RETURN_ON_MATCH(CHECKING); GNC_RETURN_ON_MATCH(SAVINGS); GNC_RETURN_ON_MATCH(MONEYMRKT); @@ -2580,18 +3023,6 @@ xaccAccountGetReconcileChildrenStatus(const Account *acc) /********************************************************************\ \********************************************************************/ -gint -xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc, - void *data) -{ - if (!acc || !proc) return 0; - xaccAccountBeginStagedTransactionTraversals (acc); - return xaccAccountStagedTransactionTraversal(acc, 42, proc, data); -} - -/********************************************************************\ -\********************************************************************/ - /* The caller of this function can get back one or both of the * matching split and transaction pointers, depending on whether * a valid pointer to the location to store those pointers is @@ -2651,6 +3082,286 @@ xaccAccountFindTransByDesc(const Account *acc, const char *description) return trans; } +/* ================================================================ */ +/* Concatenation, Mergeing functions */ + +void +gnc_account_join_children (Account *to_parent, Account *from_parent) +{ + GList *children, *node; + + if (!to_parent || !from_parent) return; + if (!from_parent->children) return; + + ENTER (" "); + children = g_list_copy(from_parent->children); + for (node = children; node; node = g_list_next(node)) + gnc_account_append_child(to_parent, node->data); + g_list_free(children); + LEAVE (" "); +} + +void +gnc_account_copy_children (Account *to, Account *from) +{ + GList *node; + QofBook *to_book; + + if (!to || !from) return; + if (!from->children) return; + to_book = gnc_account_get_book(to); + if (!to_book) return; + + ENTER (" "); + xaccAccountBeginEdit(to); + xaccAccountBeginEdit(from); + for (node = from->children; node; node=node->next) + { + Account *to_acc, *from_acc = node->data; + + /* This will copy the basic data and the KVP. It will + * not copy any splits/transactions. It will gemini. */ + to_acc = xaccCloneAccount (from_acc, to_book); + + xaccAccountBeginEdit (to_acc); + to->children = g_list_append (to->children, to_acc); + + to_acc->parent = to; + qof_instance_set_dirty(&to_acc->inst); + + /* Copy child accounts too. */ + if (from_acc->children) + { + gnc_account_copy_children(to_acc, from_acc); + } + xaccAccountCommitEdit (to_acc); + qof_event_gen (&to_acc->inst.entity, QOF_EVENT_CREATE, NULL); + /* DRH - Should this send ADD/REMOVE events */ + } + xaccAccountCommitEdit(from); + xaccAccountCommitEdit(to); + LEAVE (" "); +} + +/********************************************************************\ +\********************************************************************/ + +void +gnc_account_merge_children (Account *parent) +{ + GList *node_a; + GList *node_b; + + if (!parent) return; + + for (node_a = parent->children; node_a; node_a = node_a->next) + { + Account *acc_a = node_a->data; + + for (node_b = node_a->next; node_b; node_b = g_list_next(node_b)) + { + Account *acc_b = node_b->data; + + if (0 != safe_strcmp(acc_a->accountName, acc_b->accountName)) + continue; + if (0 != safe_strcmp(acc_a->accountCode, acc_b->accountCode)) + continue; + if (0 != safe_strcmp(acc_a->description, acc_b->description)) + continue; + if (!gnc_commodity_equiv(acc_a->commodity, acc_b->commodity)) + continue; + if (0 != safe_strcmp(xaccAccountGetNotes(acc_a), + xaccAccountGetNotes(acc_b))) + continue; + if (acc_a->type != acc_b->type) + continue; + + /* consolidate children */ + if (acc_b->children) { + acc_a->children = g_list_concat(acc_a->children, acc_b->children); + acc_b->children = NULL; + qof_event_gen (&acc_a->inst.entity, QOF_EVENT_MODIFY, NULL); + qof_event_gen (&acc_b->inst.entity, QOF_EVENT_MODIFY, NULL); + } + + /* recurse to do the children's children */ + gnc_account_merge_children (acc_a); + + /* consolidate transactions */ + while (acc_b->splits) + xaccSplitSetAccount (acc_b->splits->data, acc_a); + + /* move back one before removal. next iteration around the loop + * will get the node after node_b */ + node_b = g_list_previous(node_b); + + /* The destroy function will remove from list -- node_a is ok, + * it's before node_b */ + xaccAccountBeginEdit (acc_b); + xaccAccountDestroy (acc_b); + } + } +} + +/* ================================================================ */ +/* Transaction Traversal functions */ + + +void +xaccSplitsBeginStagedTransactionTraversals (GList *splits) +{ + GList *lp; + + for (lp = splits; lp; lp = lp->next) + { + Split *s = lp->data; + Transaction *trans = s->parent; + + if (trans) + trans->marker = 0; + } +} + +/* original function */ +void +xaccAccountBeginStagedTransactionTraversals (const Account *account) +{ + if (account) + xaccSplitsBeginStagedTransactionTraversals (account->splits); +} + +gboolean +xaccTransactionTraverse (Transaction *trans, int stage) +{ + if (trans == NULL) return FALSE; + + if (trans->marker < stage) + { + trans->marker = stage; + return TRUE; + } + + return FALSE; +} + +gboolean +xaccSplitTransactionTraverse (Split *split, int stage) +{ + if (split == NULL) return FALSE; + + return xaccTransactionTraverse (split->parent, stage); +} + +static void do_one_split (Split *s, gpointer data) +{ + Transaction *trans = s->parent; + trans->marker = 0; +} + +static void do_one_account (Account *account, gpointer data) +{ + g_list_foreach(account->splits, (GFunc)do_one_split, NULL); +} + +/* Replacement for xaccGroupBeginStagedTransactionTraversals */ +void +gnc_account_tree_begin_staged_transaction_traversals (Account *account) +{ + GList *descendants; + + descendants = gnc_account_get_descendants(account); + g_list_foreach(descendants, (GFunc)do_one_account, NULL); + g_list_free(descendants); +} + +int +xaccAccountStagedTransactionTraversal (const Account *acc, + unsigned int stage, + TransactionCallback thunk, + void *cb_data) +{ + GList *split_p; + Transaction *trans; + Split *s; + int retval; + + if (!acc) return 0; + + for(split_p = acc->splits; split_p; split_p = g_list_next(split_p)) { + s = split_p->data; + trans = s->parent; + if (trans && (trans->marker < stage)) { + trans->marker = stage; + if (thunk) { + retval = thunk(trans, cb_data); + if (retval) return retval; + } + } + } + + return 0; +} + +int +gnc_account_tree_staged_transaction_traversal (const Account *acc, + unsigned int stage, + TransactionCallback thunk, + void *cb_data) +{ + GList *acc_p, *split_p; + Transaction *trans; + Split *s; + int retval; + + if (!acc) return 0; + + /* depth first traversal */ + for (acc_p = acc->children; acc_p; acc_p = g_list_next(acc_p)) { + retval = gnc_account_tree_staged_transaction_traversal(acc_p->data, stage, + thunk, cb_data); + if (retval) return retval; + } + + /* Now this account */ + for(split_p = acc->splits; split_p; split_p = g_list_next(split_p)) { + s = split_p->data; + trans = s->parent; + if (trans && (trans->marker < stage)) { + trans->marker = stage; + if (thunk) { + retval = thunk(trans, cb_data); + if (retval) return retval; + } + } + } + + return 0; +} + +/********************************************************************\ +\********************************************************************/ + +int +xaccAccountTreeForEachTransaction (Account *acc, + int (*proc)(Transaction *t, void *data), + void *data) +{ + if (!acc || !proc) return 0; + + gnc_account_tree_begin_staged_transaction_traversals (acc); + return gnc_account_tree_staged_transaction_traversal (acc, 42, proc, data); +} + + +gint +xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc, + void *data) +{ + if (!acc || !proc) return 0; + xaccAccountBeginStagedTransactionTraversals (acc); + return xaccAccountStagedTransactionTraversal(acc, 42, proc, data); +} + /* ================================================================ */ /* QofObject function implementation and registration */ @@ -2706,7 +3417,7 @@ gboolean xaccAccountRegister (void) (QofAccessFunc) xaccAccountGetNonStdSCU, (QofSetterFunc) xaccAccountSetNonStdSCU }, { ACCOUNT_PARENT, GNC_ID_ACCOUNT, - (QofAccessFunc) xaccAccountGetParentAccount, + (QofAccessFunc) gnc_account_get_parent, (QofSetterFunc) qofAccountSetParent }, { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc) qof_instance_get_book, NULL }, @@ -2717,7 +3428,7 @@ gboolean xaccAccountRegister (void) { NULL }, }; - qof_class_register (GNC_ID_ACCOUNT, (QofSortFunc) xaccAccountOrder, params); + qof_class_register (GNC_ID_ACCOUNT, (QofSortFunc) qof_xaccAccountOrder, params); return qof_object_register (&account_object_def); } diff --git a/src/engine/Account.h b/src/engine/Account.h index b1cb461722..c65c24e288 100644 --- a/src/engine/Account.h +++ b/src/engine/Account.h @@ -32,8 +32,7 @@ (e.g. "IBM", "McDonald's"), a currency (e.g. "USD", "GBP"), or anything added to the commodity table. - Accounts can be arranged in a hierarchical tree. The nodes of the tree - are called "Account Groups" (@pxref{Account Groups}). By accounting + Accounts can be arranged in a hierarchical tree. By accounting convention, the value of an Account is equal to the value of all of its Splits plus the value of all of its sub-Accounts. @{ */ @@ -57,6 +56,9 @@ typedef gnc_numeric (*xaccGetBalanceInCurrencyFn) ( typedef gnc_numeric (*xaccGetBalanceAsOfDateFn) ( Account *account, time_t date); +typedef void (*AccountCb)(Account *a, gpointer data); +typedef gpointer (*AccountCb2)(Account *a, gpointer data); + #define GNC_IS_ACCOUNT(obj) (QOF_CHECK_TYPE((obj), GNC_ID_ACCOUNT)) #define GNC_ACCOUNT(obj) (QOF_CHECK_CAST((obj), GNC_ID_ACCOUNT, Account)) @@ -121,17 +123,19 @@ typedef enum ACCT_TYPE_PAYABLE = 12, /**< A/P account type */ - NUM_ACCOUNT_TYPES = 13, /**< stop here; the following types + ACCT_TYPE_ROOT = 13, /**< The hidden root account of an account tree. */ + + NUM_ACCOUNT_TYPES = 14, /**< stop here; the following types * just aren't ready for prime time */ /* bank account types */ - ACCT_TYPE_CHECKING = 13, /**< bank account type -- don't use this + ACCT_TYPE_CHECKING = 14, /**< bank account type -- don't use this * for now, see NUM_ACCOUNT_TYPES */ - ACCT_TYPE_SAVINGS = 14, /**< bank account type -- don't use this for + ACCT_TYPE_SAVINGS = 15, /**< bank account type -- don't use this for * now, see NUM_ACCOUNT_TYPES */ - ACCT_TYPE_MONEYMRKT = 15, /**< bank account type -- don't use this + ACCT_TYPE_MONEYMRKT = 16, /**< bank account type -- don't use this * for now, see NUM_ACCOUNT_TYPES */ - ACCT_TYPE_CREDITLINE = 16, /**< line of credit -- don't use this for + ACCT_TYPE_CREDITLINE = 17, /**< line of credit -- don't use this for * now, see NUM_ACCOUNT_TYPES */ } GNCAccountType; @@ -143,6 +147,9 @@ typedef enum /** Constructor */ Account * xaccMallocAccount (QofBook *book); +/** Create a new root level account. */ +Account * gnc_account_create_root (QofBook *book, gnc_commodity *com); + /** The xaccCloneAccount() does the same as xaccCloneAccountSimple(), * except that it also also places a pair of GUID-pointers * of each account to the other, in the other's kvp slot. @@ -188,7 +195,7 @@ gboolean xaccAccountEqual(const Account *a, const Account* b, * the account codes are compared, and if these are equal, then * account types, and, if these are equal, the account names. */ -int xaccAccountOrder (const Account **account_1, const Account **account_2); +int xaccAccountOrder (const Account *account_1, const Account *account_2); /** @} */ @@ -205,8 +212,17 @@ const gchar *gnc_get_account_separator_string (void); gunichar gnc_get_account_separator (void); void gnc_set_account_separator (const gchar *separator); +Account *gnc_coll_get_root_account(QofCollection *col); +void gnc_coll_set_root_account(QofCollection *col, Account *root); +Account *gnc_book_get_root_account(QofBook *book); +void gnc_book_set_root_account(QofBook *book, Account *root); + /** @deprecated */ -#define xaccAccountGetBook(X) qof_instance_get_book(QOF_INSTANCE(X)) +static inline QofBook * +gnc_account_get_book (const Account *acc) +{ + return qof_instance_get_book(QOF_INSTANCE(acc)); +} #define xaccAccountGetGUID(X) qof_entity_get_guid(QOF_ENTITY(X)) #define xaccAccountReturnGUID(X) (X ? *(qof_entity_get_guid(QOF_ENTITY(X))) : *(guid_null())) @@ -445,32 +461,269 @@ gnc_numeric xaccAccountGetBalanceChangeForPeriod ( @{ */ -/** This routine returns the group holding the set of subaccounts - * for this account. */ -AccountGroup * xaccAccountGetChildren (const Account *account); - -/** This routine returns the group which contains this account. +/** This function will remove from the child account any pre-existing + * parent relationship, and will then add the account as a child of + * the new parent. The exception to this is when the old and new + * parent accounts are the same, in which case this function does + * nothing. + * + * If the child account belongs to a different book than the + * specified new parent account, the child will be removed from the + * other book (and thus, the other book's entity tables, generating a + * destroy event), and will be added to the new book (generating a + * create event). + * + * @param new_parent The new parent account to which the child should + * be attached. + * + * @param child The account to attach. */ -AccountGroup * xaccAccountGetParent (const Account *account); +void gnc_account_append_child (Account *new_parent, Account *child); -/** This routine returns the parent of the group that is the parent - * of this account. It is equivalent to the nested call - * xaccGroupGetParentAccount (xaccAccountGetParent ()) - * Note that if the account is in the root group node, then its - * parent will be NULL. - */ -Account * xaccAccountGetParentAccount (const Account *account); +/** This function will remove the speified child account from the + * specified parent account. It will NOT free the associated memory + * or otherwise alter the account: the account can now be reparented + * to a new location. Note, however, that it will mark the old + * parents as having been modified. + * + * @param parent The parent account from which the child should be + * removed. + * + * @param child The child account to remove. */ +void gnc_account_remove_child (Account *parent, Account *child); + +/** This routine returns a pointer to the parent of the specified + * account. If the account has no parent, i.e it is either the root + * node or is a disconnected account, then its parent will be NULL. + * + * @param account A pointer to any exiting account. + * + * @return A pointer to the parent account node, or NULL if there is + * no parent account. */ +Account * gnc_account_get_parent (const Account *account); + +/** This routine returns the root account of the account tree that the + * specified account belongs to. It is the equivalent of repeatedly + * calling the gnc_account_get_parent() routine until that routine + * returns NULL. + * + * @param account A pointer to any existing account. + * + * @return The root node of the account tree to which this account + * belongs. NULL if the account is not part of any account tree. */ +Account * gnc_account_get_root (Account *account); + +/** This routine indicates whether the spcified account is the root + * node of an account tree. + * + * @param account A pointer to any account. + * + * @return TRUE if this account is of type ROOT. FALSE otherwise. */ +gboolean gnc_account_is_root (const Account *account); + +/** This routine returns a GList of all children of the specified + * account. This function only returns the immediate children of the + * specified account. For a list of all descendant accounts, use the + * gnc_account_get_descendants() function. + * + * @param account The account whose children should be returned. + * + * @return A GList of account pointers, or NULL if there are no + * children. It is the callers responsibility to free any returned + * list with the g_list_free() function. */ +GList *gnc_account_get_children (const Account *account); + +/** Return the number of children of the specified account. The + * returned number does not include the account itself. + * + * @param account The account to query. + * + * @return The number of children of the specified account. */ +gint gnc_account_n_children (const Account *account); + +/** Return the index of the specified child within the list of the + * parent's children. The first child index is 0. This function + * returns -1 if the parent account is NULL of if the specified child + * does not belong to the parent account. + * + * @param parent The parent account to check. + * + * @param child The child account to find. + * + * @return The index of the child account within the specified + * parent, or -1. */ +gint gnc_account_child_index (const Account *parent, const Account *child); + +/** Return the n'th child account of the specified parent account. If + * the parent account is not specified or the child index number is + * invalid, this function returns NULL. + * + * @param parent The parent account to check. + * + * @param num The index number of the child account that should be + * returned. + * + * @return A pointer to the specified child account, or NULL */ +Account *gnc_account_nth_child (const Account *parent, gint num); + +/** This routine returns a flat list of all of the accounts that are + * descendants of the specified account. This includes not only the + * the children, but the children of the children, etc. For a list of + * only the immediate child accounts, use the + * gnc_account_get_children() function. Within each set of child + * accounts, the accounts returned by this function are unordered. + * For a list of descendants where each set of children is sorted via + * the standard account sort function, use the + * gnc_account_get_descendants_sorted() function. + * + * @param account The account whose descendants should be returned. + * + * @return A GList of account pointers, or NULL if there are no + * descendants. It is the callers responsibility to free any returned + * list with the g_list_free() function. */ +GList * gnc_account_get_descendants (const Account *account); + +/** This function returns a GList containing all the descendants of + * the specified account, sorted at each level. This includes not + * only the the children, but the children of the children, etc. + * Within each set of child accounts, the accounts returned by this + * function are ordered via the standard account sort function. For + * a list of descendants where each set of children is unordered, use + * the gnc_account_get_descendants() function. + * + * Note: Use this function where the results are intended for display + * to the user. If the results are internal to GnuCash or will be + * resorted at som later point in time you should use the + * gnc_account_get_descendants() function. + * + * @param account The account whose descendants should be returned. + * + * @return A GList of account pointers, or NULL if there are no + * descendants. It is the callers responsibility to free any returned + * list with the g_list_free() function. */ +GList *gnc_account_get_descendants_sorted (const Account *account); -/** This routine returns a flat list of all of the accounts - * that are descendents of this account. This includes not - * only the the children, but the children of the children, etc. - * This routine is equivalent to the nested calls - * xaccGroupGetSubAccounts (xaccAccountGetChildren()) +/** Return the number of descendants of the specified account. The + * returned number does not include the account itself. * - * The returned list should be freed with g_list_free() when - * no longer needed. + * @param account The account to query. + * + * @return The number of descendants of the specified account. */ +gint gnc_account_n_descendants (const Account *account); + +/** Return the number of levels of descendants accounts below the + * specified account. The returned number does not include the + * specifed account itself. + * + * @param account The account to query. + * + * @return The number of levels of descendants. */ +gint gnc_account_get_depth (const Account *account); + +/** @name ForEach + @{ +*/ + +/** This method will traverse the immediate children of this accounts, + * calling 'func' on each account. This function traverses all + * children nodes. To traverse only a subset of the child nodes use + * the gnc_account_foreach_child_until() function. + * + * @param account A pointer to the account on whose children the + * function should be called. + * + * @param func A function taking two arguments, an Account and a + * gpointer. + * + * @param user_data This data will be passed to each call of func. */ +void gnc_account_foreach_child (const Account *account, + AccountCb func, gpointer user_data); + +/** This method will traverse the immediate children of this accounts, + * calling 'func' on each account. Traversal will stop when func + * returns a non-null value, and the routine will return with that + * value. Therefore, this function will return null iff func returns + * null for every account. For a simpler function that always + * traverses all children nodes, use the gnc_account_foreach_child() + * function. + * + * @param account A pointer to the account on whose children the + * function should be called. + * + * @param func A function taking two arguments, an Account and a + * gpointer. + * + * @param user_data This data will be passed to each call of func. */ +gpointer gnc_account_foreach_child_until (const Account *account, + AccountCb2 func, gpointer user_data); + + +/** This method will traverse all children of this accounts and their + * descendants, calling 'func' on each account. This function + * traverses all descendant nodes. To traverse only a subset of the + * descendant nodes use the gnc_account_foreach_descendant_until() + * function. + * + * @param account A pointer to the account on whose descendants the + * function should be called. + * + * @param func A function taking two arguments, an Account and a + * gpointer. + * + * @param user_data This data will be passed to each call of func. */ +void gnc_account_foreach_descendant (const Account *account, + AccountCb func, gpointer user_data); + +/** This method will traverse all children of this accounts and their + * descendants, calling 'func' on each account. Traversal will stop + * when func returns a non-null value, and the routine will return + * with that value. Therefore, this function will return null iff + * func returns null for every account. For a simpler function that + * always traverses all children nodes, use the + * gnc_account_foreach_descendant() function. + * + * @param account A pointer to the account on whose descendants the + * function should be called. + * + * @param func A function taking two arguments, an Account and a + * gpointer. + * + * @param user_data This data will be passed to each call of func. */ +gpointer gnc_account_foreach_descendant_until (const Account *account, + AccountCb2 func, gpointer user_data); + + +/** @} */ + +/** @name Concatenation, Merging + @{ +*/ + +/** The gnc_account_join_children() subroutine will move (reparent) + * all child accounts from the from_parent account to the to_parent + * account, preserving the account heirarchy. It will also take care + * that the moved accounts will have the to_parent's book parent + * as well. + */ +void gnc_account_join_children (Account *to_parent, Account *from_parent); + +/** The gnc_account_copy_children() subroutine will copy all child + * accounts from the "src" account to the "dest" account, preserving + * the account heirarchy. It will also take care that the moved + * accounts will have the "dest" account's book parent as well. This + * routine will *NOT* copy any splits/transactions. It will copy the + * KVP trees in each account. + */ +void gnc_account_copy_children (Account *dest, Account *src); + +/** The gnc_account_merge_children() subroutine will go through an + * account, merging all child accounts that have the same name and + * description. This function is useful when importing Quicken(TM) + * files. */ -GList * xaccAccountGetDescendants (const Account *account); +void gnc_account_merge_children (Account *parent); + +/** @} */ /** DOCUMENT ME! */ void xaccAccountSetReconcileChildrenStatus(Account *account, gboolean status); @@ -489,6 +742,28 @@ gboolean xaccAccountHasAncestor(const Account *acc, const Account *ancestor); /** @} */ +/** @name Getting Accounts and Subaccounts by Name + @{ +*/ +/** The gnc_account_lookup_name() subroutine fetches the account by + * name from the descendants of the specified account. The immediate + * children are searched first. If there is no match,, then a + * recursive search of all descendants is performed looking for a + * match. + * + * @return A pointer to the account with the specified name, or NULL + * if the account was not found. + */ +Account *gnc_account_lookup_name (const Account *parent, const char *name); + +/** The gnc_account_lookup_full_name() subroutine works like + * gnc_account_lookup_name, but uses fully-qualified names using the + * given separator. + */ +Account *gnc_account_lookup_full_name (const Account *any_account, + const gchar *name); + +/** @} */ /* ------------------ */ @@ -694,7 +969,7 @@ typedef enum /** Get the "placeholder" flag for an account. If this flag is set * then the account may not be modified by the user. * - * @param acc The account whose flag should be retrieved. + * @param account The account whose flag should be retrieved. * * @return The current state of the account's "placeholder" flag. */ gboolean xaccAccountGetPlaceholder (const Account *account); @@ -702,13 +977,13 @@ gboolean xaccAccountGetPlaceholder (const Account *account); /** Set the "placeholder" flag for an account. If this flag is set * then the account may not be modified by the user. * - * @param acc The account whose flag should be retrieved. + * @param account The account whose flag should be retrieved. * * @param val The new state for the account's "placeholder" flag. */ -void xaccAccountSetPlaceholder (Account *account, gboolean option); +void xaccAccountSetPlaceholder (Account *account, gboolean val); /** Returns PLACEHOLDER_NONE if account is NULL or neither account nor - * any descendent of account is a placeholder. If account is a + * any descendant of account is a placeholder. If account is a * placeholder, returns PLACEHOLDER_THIS. Otherwise, if any * descendant of account is a placeholder, return PLACEHOLDER_CHILD. */ @@ -782,15 +1057,149 @@ void xaccAccountSetMark (Account *account, short mark); /** Get the mark set by xaccAccountSetMark */ short xaccAccountGetMark (const Account *account); -/** The xaccClearMark will find the topmost group, and clear the mark in - * the entire group tree. */ +/** The xaccClearMark will find the root account, and clear the mark in + * the entire account tree. */ void xaccClearMark (Account *account, short val); /** The xaccClearMarkDown will clear the mark only in this and in * sub-accounts.*/ void xaccClearMarkDown (Account *account, short val); -/** Will clear the mark for all the accounts of the AccountGroup .*/ -void xaccClearMarkDownGr (AccountGroup *group, short val); +/** @} */ + +/** @name Staged Traversal + + * The following functions provide support for "staged traversals" + * over all of the transactions in an account or group. The idea + * is to be able to perform a sequence of traversals ("stages"), + * and perform an operation on each transaction exactly once + * for that stage. + * + * Only transactions whose current "stage" is less than the + * stage of the current traversal will be affected, and they will + * be "brought up" to the current stage when they are processed. + * + * For example, you could perform a stage 1 traversal of all the + * transactions in an account, and then perform a stage 1 traversal of + * the transactions in a second account. Presuming the traversal of + * the first account didn't abort prematurely, any transactions shared + * by both accounts would be ignored during the traversal of the + * second account since they had been processed while traversing the + * first account. + * + * However, if you had traversed the second account using a stage + * of 2, then all the transactions in the second account would have + * been processed. + * + * Traversal can be aborted by having the callback function return + * a non-zero value. The traversal is aborted immediately, and the + * non-zero value is returned. Note that an aborted traversal can + * be restarted; no information is lost due to an abort. + * + * The initial impetus for this particular approach came from + * generalizing a mark/sweep practice that was already being + * used in FileIO.c. + * + * Note that currently, there is a hard limit of 256 stages, which + * can be changed by enlarging "marker" in the transaction struct. + * + @{ +*/ +/** gnc_account_tree_begin_staged_transaction_traversals() + * resets the traversal marker inside every transactions of every + * account in the account tree originating with the specified node. + * This is done so that a new sequence of staged traversals can + * begin. + */ +void gnc_account_tree_begin_staged_transaction_traversals(Account *acc); + +/** xaccSplitsBeginStagedTransactionTraversals() resets the traversal + * marker for each transaction which is a parent of one of the + * splits in the list. + */ +void xaccSplitsBeginStagedTransactionTraversals(SplitList *splits); + +/** xaccAccountBeginStagedTransactionTraversals() resets the traversal + * marker for each transaction which is a parent of one of the + * splits in the account. + */ +void xaccAccountBeginStagedTransactionTraversals(const Account *account); + +/** xaccTransactionTraverse() checks the stage of the given transaction. + * If the transaction hasn't reached the given stage, the transaction + * is updated to that stage and the function returns TRUE. Otherwise + * no change is made and the function returns FALSE. + */ +gboolean xaccTransactionTraverse(Transaction *trans, int stage); + +/** xaccSplitTransactionTraverse() behaves as above using the parent of + * the given split. + */ +gboolean xaccSplitTransactionTraverse(Split *split, int stage); + +/** xaccAccountStagedTransactionTraversal() calls thunk on each + * transaction in the account whose current marker is less than the + * given `stage' and updates each transaction's marker to be `stage'. + * The traversal will stop if thunk() returns a non-zero value. + * xaccAccountStagedTransactionTraversal() function will return zero + * or the non-zero value returned by thunk(). + * This API does not handle handle recursive traversals. + * + * Currently the result of adding or removing transactions during + * a traversal is undefined, so don't do that. + */ + +int xaccAccountStagedTransactionTraversal(const Account *a, + unsigned int stage, + TransactionCallback thunk, + void *data); + +/** gnc_account_tree_staged_transaction_traversal() calls thunk on each + * transaction in the group whose current marker is less than the + * given `stage' and updates each transaction's marker to be `stage'. + * The traversal will stop if thunk() returns a non-zero value. + * gnc_account_tree_staged_transaction_traversal() function will return zero + * or the non-zero value returned by thunk(). This + * API does not handle handle recursive traversals. + * + * Currently the result of adding or removing transactions during + * a traversal is undefined, so don't do that. + */ + +int gnc_account_tree_staged_transaction_traversal(const Account *account, + unsigned int stage, + TransactionCallback thunk, + void *data); + +/** Traverse all of the transactions in the given account group. + Continue processing IFF proc returns 0. This function + will descend recursively to traverse transactions in the + children of the accounts in the group. + + Proc will be called exactly once for each transaction that is + pointed to by at least one split in any account in the hierarchy + topped by the root Account acc. + + The result of this function will be 0 IFF every relevant + transaction was traversed exactly once; otherwise, the return + value is the last non-zero value returned by the callback. + + Note that the traversal occurs only over the transactions that + are locally cached in the local gnucash engine. If the gnucash + engine is attached to a remote database, the database may contain + (many) transactions that are not mirrored in the local cache. + This routine will not cause an SQL database query to be performed; + it will not traverse transactions present only in the remote + database. + + Note that this routine is just a trivial wrapper for + + gnc_account_tree_begin_staged_transaction_traversals(g); + gnc_account_tree_staged_transaction_traversal(g, 42, proc, data); + */ + +int xaccAccountTreeForEachTransaction(Account *acc, + TransactionCallback proc, void *data); + /** @} */ diff --git a/src/engine/AccountP.h b/src/engine/AccountP.h index 933628861c..993fc41583 100644 --- a/src/engine/AccountP.h +++ b/src/engine/AccountP.h @@ -98,8 +98,8 @@ struct account_s /* The parent and children pointers are used to implement an account * hierarchy, of accounts that have sub-accounts ("detail accounts"). */ - AccountGroup *parent; /* back-pointer to parent */ - AccountGroup *children; /* pointer to sub-accounts */ + Account *parent; /* back-pointer to parent */ + GList *children; /* list of sub-accounts */ /* protected data, cached parameters */ gnc_numeric starting_balance; diff --git a/src/engine/Group.c b/src/engine/Group.c deleted file mode 100644 index 012afa906e..0000000000 --- a/src/engine/Group.c +++ /dev/null @@ -1,1322 +0,0 @@ -/********************************************************************\ - * Group.c -- chart of accounts (hierarchical tree of accounts) * - * Copyright (C) 1997 Robin D. Clark * - * Copyright (C) 1997-2001,2003 Linas Vepstas * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 2 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License* - * along with this program; if not, contact: * - * * - * Free Software Foundation Voice: +1-617-542-5942 * - * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * - * Boston, MA 02110-1301, USA gnu@gnu.org * - * * -\********************************************************************/ - -#include "config.h" - -#include -#include - -#include "Account.h" -#include "AccountP.h" -#include "Group.h" -#include "GroupP.h" -#include "TransactionP.h" -#include "gnc-event.h" - -static QofLogModule log_module = GNC_MOD_ENGINE; - -/********************************************************************\ - * Because I can't use C++ for this project, doesn't mean that I * - * can't pretend to! These functions perform actions on the * - * AccountGroup data structure, in order to encapsulate the * - * knowledge of the internals of the AccountGroup in one file. * -\********************************************************************/ - -/********************************************************************\ -\********************************************************************/ - -static void -xaccInitializeAccountGroup (AccountGroup *grp, QofBook *book) -{ - grp->saved = 1; - - grp->parent = NULL; - grp->accounts = NULL; - - grp->book = book; - grp->editlevel = 0; -} - -/********************************************************************\ -\********************************************************************/ - -AccountGroup * -xaccMallocAccountGroup (QofBook *book) -{ - AccountGroup *grp; - g_return_val_if_fail (book, NULL); - - grp = g_new (AccountGroup, 1); - xaccInitializeAccountGroup (grp, book); - - return grp; -} - -/********************************************************************\ -\********************************************************************/ - -AccountGroup * -xaccCollGetAccountGroup (const QofCollection *col) -{ - if (!col) return NULL; - return qof_collection_get_data (col); -} - -void -xaccCollSetAccountGroup (QofCollection *col, AccountGroup *grp) -{ - AccountGroup *old_grp; - if (!col) return; - - old_grp = xaccCollGetAccountGroup (col); - if (old_grp == grp) return; - - qof_collection_set_data (col, grp); - - xaccAccountGroupBeginEdit (old_grp); - xaccAccountGroupDestroy (old_grp); -} - -AccountGroup * -xaccGetAccountGroup (QofBook *book) -{ - QofCollection *col; - if (!book) return NULL; - col = qof_book_get_collection (book, GNC_ID_GROUP); - return xaccCollGetAccountGroup (col); -} - -void -xaccSetAccountGroup (QofBook *book, AccountGroup *grp) -{ - QofCollection *col; - if (!book) return; - - if (grp && grp->book != book) - { - PERR ("cannot mix and match books freely!"); - return; - } - - col = qof_book_get_collection (book, GNC_ID_GROUP); - xaccCollSetAccountGroup (col, grp); -} - -/********************************************************************\ -\********************************************************************/ - -gboolean -xaccGroupEqual(const AccountGroup *ga, - const AccountGroup *gb, - gboolean check_guids) -{ - GList *na; - GList *nb; - - if (!ga && !gb) return(TRUE); - - if (!ga || !gb) - { - PWARN ("one is NULL"); - return(FALSE); - } - - na = ga->accounts; - nb = gb->accounts; - - if ((!na && nb) || (na && !nb)) - { - PWARN ("only one has accounts"); - return(FALSE); - } - - while (na && nb) - { - Account *aa = na->data; - Account *ab = nb->data; - - if (!xaccAccountEqual(aa, ab, check_guids)) - { - char sa[GUID_ENCODING_LENGTH + 1]; - char sb[GUID_ENCODING_LENGTH + 1]; - - guid_to_string_buff (xaccAccountGetGUID (aa), sa); - guid_to_string_buff (xaccAccountGetGUID (ab), sb); - - PWARN ("accounts %s and %s differ", sa, sb); - - return(FALSE); - } - - na = na->next; - nb = nb->next; - } - - if (na || nb) - { - PWARN ("different numbers of accounts"); - return(FALSE); - } - - return(TRUE); -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccAccountGroupBeginEdit (AccountGroup *grp) -{ - GList *node; - - if (!grp) return; - grp->editlevel++; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - - xaccAccountBeginEdit (account); - xaccAccountGroupBeginEdit (account->children); - } -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccAccountGroupCommitEdit (AccountGroup *grp) -{ - GList *node; - - if (!grp) return; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - - xaccAccountGroupCommitEdit (account->children); - xaccAccountCommitEdit (account); - } - grp->editlevel--; -} - -/********************************************************************\ -\********************************************************************/ - -static void -xaccGroupMarkDoFree (AccountGroup *grp) -{ - GList *node; - - if (!grp) return; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - account->inst.do_free = TRUE; - xaccGroupMarkDoFree (account->children); - } -} - -void -xaccAccountGroupDestroy (AccountGroup *grp) -{ - xaccGroupMarkDoFree (grp); - xaccFreeAccountGroup (grp); -} - -/********************************************************************\ -\********************************************************************/ - -QofBook * -xaccGroupGetBook (const AccountGroup *group) -{ - if (!group) return NULL; - return group->book; -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccFreeAccountGroup (AccountGroup *grp) -{ - gboolean root_grp; - - if (!grp) return; - - root_grp = grp->parent == NULL; - - if (grp->accounts) - { - Account *account; - /* This is a weird iterator & needs some explanation. - * xaccAccountDestroy() will rip the account out of the list, thus - * iterating while grp->accounts is non-null is enough to iterate - * the loop. But when it deletes the last account, then it will - * also delete the group, unless it's the root group, making the - * grp pointer invalid. So we have to be careful with the last - * deletion: in particular, g_free(grp) would be freeing that - * memory a second time, so don't do it. */ - while (grp->accounts->next) - { - account = grp->accounts->next->data; - - /* FIXME: this and the same code below is kind of hacky. - * actually, all this code seems to assume that - * the account edit levels are all 1. */ - if (account->inst.editlevel == 0) - xaccAccountBeginEdit (account); - - xaccAccountDestroy (account); - } - account = grp->accounts->data; - if (account->inst.editlevel == 0) - xaccAccountBeginEdit (account); - xaccAccountDestroy (account); - - if (!root_grp) return; - } - - if (grp->parent) grp->parent->children = NULL; - - grp->parent = NULL; - - g_free (grp); -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccGroupMarkSaved (AccountGroup *grp) -{ - GList *node; - - if (!grp) return; - - grp->saved = 1; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - - xaccGroupMarkSaved (account->children); - } -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccGroupMarkNotSaved (AccountGroup *grp) -{ - if (!grp) return; - - grp->saved = 0; -} - -/********************************************************************\ -\********************************************************************/ - -gboolean -xaccGroupNotSaved (const AccountGroup *grp) -{ - GList *node; - - if (!grp) return FALSE; - - if (grp->saved == 0) return TRUE; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - - if (xaccGroupNotSaved (account->children)) - return TRUE; - } - - return FALSE; -} - -/********************************************************************\ - * Get the number of accounts, including subaccounts * -\********************************************************************/ - -int -xaccGroupGetNumSubAccounts (const AccountGroup *grp) -{ - GList *node; - int num_acc; - - if (!grp) return 0; - - num_acc = g_list_length (grp->accounts); - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - - num_acc += xaccGroupGetNumSubAccounts (account->children); - } - - return num_acc; -} - -/********************************************************************\ - * Recursively get all of the accounts, including subaccounts * -\********************************************************************/ - -static void -xaccPrependAccounts (const AccountGroup *grp, GList **accounts_p) -{ - GList *node; - - if (!grp || !accounts_p) return; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - - *accounts_p = g_list_prepend (*accounts_p, account); - - xaccPrependAccounts (account->children, accounts_p); - } -} - -AccountList * -xaccGroupGetSubAccounts (const AccountGroup *grp) -{ - GList *accounts = NULL; - - if (!grp) return NULL; - - xaccPrependAccounts (grp, &accounts); - - return g_list_reverse (accounts); -} - -static int -group_sort_helper (gconstpointer a, gconstpointer b) -{ - const Account *aa = (const Account *) a; - const Account *bb = (const Account *) b; - - /* xaccAccountOrder returns > 1 if aa should come after bb. - * This funciton is building a reversed list. */ - return xaccAccountOrder (&aa, &bb); -} - -static void -xaccPrependAccountsSorted (const AccountGroup *grp, GList **accounts_p) -{ - GList *node, *tmp_list; - - if (!grp || !accounts_p) return; - - tmp_list = g_list_copy(grp->accounts); - tmp_list = g_list_sort(tmp_list, group_sort_helper); - - for (node = tmp_list; node; node = node->next) - { - Account *account = node->data; - - *accounts_p = g_list_prepend (*accounts_p, account); - - xaccPrependAccountsSorted (account->children, accounts_p); - } - g_list_free(tmp_list); -} - -AccountList * -xaccGroupGetSubAccountsSorted (const AccountGroup *grp) -{ - GList *accounts = NULL; - - if (!grp) return NULL; - - xaccPrependAccountsSorted (grp, &accounts); - - return g_list_reverse (accounts); -} - -AccountList * -xaccGroupGetAccountList (const AccountGroup *grp) -{ - if (!grp) return NULL; - - return grp->accounts; -} - -AccountList * -xaccGroupGetAccountListSorted (const AccountGroup *grp) -{ - if (!grp) return NULL; - - return g_list_sort(g_list_copy(grp->accounts), group_sort_helper); - -} - -/********************************************************************\ - * Fetch the root of the tree * -\********************************************************************/ - -AccountGroup * -xaccGroupGetRoot (const AccountGroup * grp) -{ - const AccountGroup * root = NULL; - - /* find the root of the account group structure */ - while (grp) - { - Account *parent_acc; - - root = grp; - parent_acc = grp->parent; - - if (parent_acc) - grp = parent_acc->parent; - else - grp = NULL; - } - - return (AccountGroup*)root; -} - -AccountGroup * -xaccAccountGetRoot (const Account * acc) -{ - return acc ? xaccGroupGetRoot (acc->parent) : NULL; -} - -/********************************************************************\ - * Fetch an account, given its name * -\********************************************************************/ - -Account * -xaccGetAccountFromName (const AccountGroup *grp, const char * name) -{ - GList *node; - - if (!grp) return NULL; - if (!name) return NULL; - - /* first, look for accounts hanging off the root */ - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - - if (safe_strcmp(xaccAccountGetName (account), name) == 0) - return account; - } - - /* if we are still here, then we haven't found the account yet. - * Recursively search the subgroups next */ - /* first, look for accounts hanging off the root */ - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - Account *acc; - - acc = xaccGetAccountFromName (account->children, name); - if (acc) - return acc; - } - - return NULL; -} - -/********************************************************************\ - * Fetch an account, given its full name * -\********************************************************************/ - -static Account * -xaccGetAccountFromFullNameHelper (const AccountGroup *grp, - gchar **names) -{ - Account *found = NULL; - GList *node; - gchar *name_str, *temp_str; - const gchar *separator; - gboolean str_alloced = FALSE; - - g_return_val_if_fail(grp, NULL); - g_return_val_if_fail(names, NULL); - - separator = gnc_get_account_separator_string(); - /* start with the first name in the list */ - name_str = names[0]; - - /* Make sure we actually HAVE a string! */ - if (name_str == NULL) - return NULL; - - while (1) - { - /* Look for the first name in the children. */ - for (node = grp->accounts; node; node = node->next) { - Account *account = node->data; - - if (safe_strcmp(xaccAccountGetName (account), name_str) == 0) { - /* We found an account. If the next entry is NULL, there is - * nothing left in the name, so just return the account. */ - if (names[1] == NULL) { - found = account; - goto done; - } - - /* No children? We're done. */ - if (!account->children) { - found = NULL; - goto done; - } - - /* There's stuff left to search for. Search recursively. */ - found = xaccGetAccountFromFullNameHelper(account->children, &names[1]); - if (found != NULL) { - goto done; - } - } - } - - /* If we got here then we didn't find a match based on name_str - * so build a new name_str using the next token and try again. - */ - - /* If there's no more names then we're done. We didn't find anything */ - if (names[1] == NULL) { - found = NULL; - break; - } - - /* If we are here, we didn't find anything and there - * must be more separators. So, continue looking with - * a longer name, in case there is a name with the - * separator character in it. */ - - /* Build the new name string */ - temp_str = g_strconcat(name_str, separator, names[1], NULL); - if (str_alloced) - g_free(name_str); - str_alloced = TRUE; - names++; - name_str = temp_str; - } - -done: - if (str_alloced) - g_free(name_str); - return found; -} - - -Account * -xaccGetAccountFromFullName (const AccountGroup *grp, - const char *name) -{ - Account *found; - gchar **names; - - if (!grp) return NULL; - if (!name) return NULL; - - names = g_strsplit(name, gnc_get_account_separator_string(), -1); - found = xaccGetAccountFromFullNameHelper(grp, names); - g_strfreev(names); - return found; -} - -/********************************************************************\ - * Fetch an account, given its name * -\********************************************************************/ - -Account * -xaccGetPeerAccountFromName (const Account *acc, const char * name) -{ - AccountGroup * root; - Account *peer_acc; - - if (!acc) return NULL; - if (!name) return NULL; - - /* first, find the root of the account group structure */ - root = xaccAccountGetRoot (acc); - - /* now search all accounts hanging off the root */ - peer_acc = xaccGetAccountFromName (root, name); - - return peer_acc; -} - -/********************************************************************\ - * Fetch an account, given its full name * -\********************************************************************/ - -Account * -xaccGetPeerAccountFromFullName (const Account *acc, const char * name) -{ - AccountGroup * root; - Account *peer_acc; - - if (!acc) return NULL; - if (!name) return NULL; - - /* first, find the root of the account group structure */ - root = xaccAccountGetRoot (acc); - - /* now search all acounts hanging off the root */ - peer_acc = xaccGetAccountFromFullName (root, name); - - return peer_acc; -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccAccountRemoveGroup (Account *acc) -{ - AccountGroup *grp; - - /* if this group has no parent, it must be the topgroup */ - if (!acc) return; - - grp = acc->children; - - if (grp) grp->parent = NULL; - acc->children = NULL; - - /* make sure that the parent of the group is marked - * as having been modified. */ - grp = acc->parent; - if (!grp) return; - - grp->saved = 0; - - qof_event_gen (&acc->inst.entity, QOF_EVENT_MODIFY, NULL); -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccGroupRemoveAccount (AccountGroup *grp, Account *acc) -{ - GncEventData ed; - - if (!acc) return; - - /* Note this routine might be called on accounts which - * are not yet parented. */ - if (!grp) return; - - if (acc->parent != grp) - { - PERR ("account not in group"); - return; - } - - /* Gather event data */ - ed.node = grp->parent; - ed.idx = g_list_index(grp->accounts, acc); - - grp->accounts = g_list_remove (grp->accounts, acc); - - /* Now send the event. */ - qof_event_gen(&acc->inst.entity, QOF_EVENT_REMOVE, &ed); - - /* clear the account's group pointer after REMOVE event generation. */ - acc->parent = NULL; - - grp->saved = 0; - - /* if this was the last account in a group, delete - * the group as well (unless its a root group) */ - if ((grp->accounts == NULL) && (grp->parent)) - { - xaccAccountRemoveGroup (grp->parent); - xaccFreeAccountGroup (grp); - } - - qof_event_gen (&acc->inst.entity, QOF_EVENT_MODIFY, NULL); -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccAccountInsertSubAccount (Account *adult, Account *child) -{ - if (!adult) return; - - /* if a container for the children doesn't yet exist, add it */ - if (adult->children == NULL) - adult->children = xaccMallocAccountGroup (adult->inst.book); - - /* set back-pointer to parent */ - adult->children->parent = adult; - - /* allow side-effect of creating a child-less account group */ - if (!child) return; - - xaccGroupInsertAccount (adult->children, child); - - qof_event_gen (&adult->inst.entity, QOF_EVENT_MODIFY, NULL); -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccGroupInsertAccount (AccountGroup *grp, Account *acc) -{ - if (!grp || !grp->book) return; - if (!acc) return; - - ENTER("group %p, account %p named %s", grp, acc, xaccAccountGetName(acc)); - /* If the account is currently in another group, remove it there - * first. Basically, we can't have accounts being in two places at - * once. If old and new parents are the same, reinsertion causes - * the sort order to be checked. */ - if (acc->parent != grp) - { - xaccAccountBeginEdit (acc); - - if (acc->parent) - { - xaccGroupRemoveAccount (acc->parent, acc); - - /* switch over between books, if needed */ - if (grp->book != acc->inst.book) - { - QofCollection *col; -// xxxxxxxxxxxxxxxxxxxxxxx - /* hack alert -- this implementation is not exactly correct. - * If the entity tables are not identical, then the 'from' book - * may have a different backend than the 'to' book. This means - * that we should get the 'from' backend to destroy this account, - * and the 'to' backend to save it. Right now, this is broken. - * - * A 'correct' implementation similar to this is in Period.c - * except its for transactions ... - * - * Note also, we need to reparent the children to the new book as well. - */ - PWARN ("reparenting accounts across books is not correctly supported\n"); - - qof_event_gen (&acc->inst.entity, QOF_EVENT_DESTROY, NULL); - col = qof_book_get_collection (grp->book, GNC_ID_ACCOUNT); - qof_collection_insert_entity (col, &acc->inst.entity); - qof_event_gen (&acc->inst.entity, QOF_EVENT_CREATE, NULL); - } - } - - /* set back-pointer to the account's parent */ - acc->parent = grp; - - grp->accounts = g_list_append (grp->accounts, acc); - - /* Gather event data */ - qof_event_gen (&acc->inst.entity, QOF_EVENT_ADD, NULL); - - qof_instance_set_dirty(&acc->inst); - xaccAccountCommitEdit (acc); - } - - grp->saved = 0; - - qof_event_gen (&acc->inst.entity, QOF_EVENT_MODIFY, NULL); - LEAVE(" "); -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccGroupConcatGroup (AccountGroup *togrp, AccountGroup *fromgrp) -{ - if (!togrp) return; - if (!fromgrp) return; - - /* The act of inserting the account into togrp also causes it to - * automatically be deleted from fromgrp. This causes linked - * lists to be re-written, and so a cursor traversal is not safe. - * Be careful! */ - - while (TRUE) - { - Account *account; - GList *accounts; - GList *next; - - accounts = fromgrp->accounts; - if (!accounts) return; - - next = accounts->next; - - account = accounts->data; - - xaccGroupInsertAccount (togrp, account); - - if (!next) return; - } -} - -void -xaccGroupCopyGroup (AccountGroup *to, AccountGroup *from) -{ - int i; - GList *node; - if (!to || !from) return; - if (!from->accounts || !to->book) return; - - ENTER (" "); - xaccAccountGroupBeginEdit(to); - xaccAccountGroupBeginEdit(from); - for (node = from->accounts; node; node=node->next) - { - Account *to_acc, *from_acc = node->data; - - /* This will copy the basic data and the KVP. It will - * not copy any splits/transactions. It will gemini. */ - to_acc = xaccCloneAccount (from_acc, to->book); - - xaccAccountBeginEdit (to_acc); - to->accounts = g_list_append (to->accounts, to_acc); - - to_acc->parent = to; - qof_instance_set_dirty(&to_acc->inst); - - /* Copy child accounts too. */ - if (from_acc->children) - { - to_acc->children = xaccMallocAccountGroup (to->book); - to_acc->children->parent = to_acc; - xaccGroupCopyGroup (to_acc->children, from_acc->children); - } - xaccAccountCommitEdit (to_acc); - qof_event_gen (&to_acc->inst.entity, QOF_EVENT_CREATE, NULL); - - /* make sure that we have a symmetric, uniform number of - * begin-edits, so that subsequent GroupCommitEdit's - * balance out. */ - for (i=0; ieditlevel; i++) - { - xaccAccountBeginEdit (to_acc); - xaccAccountGroupBeginEdit (to_acc->children); - } - } - xaccAccountGroupCommitEdit(from); - xaccAccountGroupCommitEdit(to); - LEAVE (" "); -} - -/********************************************************************\ -\********************************************************************/ - -void -xaccGroupMergeAccounts (AccountGroup *grp) -{ - GList *node_a; - GList *node_b; - - if (!grp) return; - - for (node_a = grp->accounts; node_a; node_a = node_a->next) - { - Account *acc_a = node_a->data; - - for (node_b = node_a->next; node_b; node_b = node_b->next) - { - Account *acc_b = node_b->data; - - if ((0 == safe_strcmp(xaccAccountGetName(acc_a), - xaccAccountGetName(acc_b))) && - (0 == safe_strcmp(xaccAccountGetCode(acc_a), - xaccAccountGetCode(acc_b))) && - (0 == safe_strcmp(xaccAccountGetDescription(acc_a), - xaccAccountGetDescription(acc_b))) && - (gnc_commodity_equiv(xaccAccountGetCommodity(acc_a), - xaccAccountGetCommodity(acc_b))) && - (0 == safe_strcmp(xaccAccountGetNotes(acc_a), - xaccAccountGetNotes(acc_b))) && - (xaccAccountGetType(acc_a) == xaccAccountGetType(acc_b))) - { - AccountGroup *ga, *gb; - - /* consolidate children */ - ga = (AccountGroup *) acc_a->children; - gb = (AccountGroup *) acc_b->children; - - if (gb) - { - if (!ga) - { - acc_a->children = gb; - gb->parent = acc_a; - acc_b->children = NULL; - - qof_event_gen (&acc_a->inst.entity, QOF_EVENT_MODIFY, NULL); - qof_event_gen (&acc_b->inst.entity, QOF_EVENT_MODIFY, NULL); - } - else - { - xaccGroupConcatGroup (ga, gb); - acc_b->children = NULL; - qof_event_gen (&acc_b->inst.entity, QOF_EVENT_MODIFY, NULL); - } - } - - /* recurse to do the children's children */ - xaccGroupMergeAccounts (ga); - - /* consolidate transactions */ - while (acc_b->splits) - xaccSplitSetAccount (acc_b->splits->data, acc_a); - - /* move back one before removal */ - node_b = node_b->prev; - - /* The destroy function will remove from list -- node_a is ok, - * it's before node_b */ - xaccAccountBeginEdit (acc_b); - xaccAccountDestroy (acc_b); - break; - } - } - } -} - -/********************************************************************\ -\********************************************************************/ - -int -xaccGroupGetNumAccounts (const AccountGroup *grp) -{ - if (!grp) return 0; - - return g_list_length (grp->accounts); -} - -Account * -xaccGroupGetAccount (const AccountGroup *grp, int i) -{ - if (!grp) return NULL; - - return g_list_nth_data (grp->accounts, i); -} - -Account * -xaccGroupGetParentAccount (const AccountGroup * grp) -{ - if (!grp) return NULL; - - return grp->parent; -} - -/********************************************************************\ -\********************************************************************/ - -int -xaccGroupGetDepth (const AccountGroup *grp) -{ - GList *node; - int depth = 0; - int maxdepth = 0; - - if (!grp) return 0; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - - depth = xaccGroupGetDepth (account->children); - - if (depth > maxdepth) - maxdepth = depth; - } - - maxdepth++; - - return maxdepth; -} - -/********************************************************************\ -\********************************************************************/ -void -xaccSplitsBeginStagedTransactionTraversals (GList *splits) -{ - GList *lp; - - for (lp = splits; lp; lp = lp->next) - { - Split *s = lp->data; - Transaction *trans = s->parent; - - if (trans) - trans->marker = 0; - } -} - -void -xaccAccountBeginStagedTransactionTraversals (const Account *account) -{ - if (account) - xaccSplitsBeginStagedTransactionTraversals (account->splits); -} - -gboolean -xaccTransactionTraverse (Transaction *trans, int stage) -{ - if (trans == NULL) return FALSE; - - if (trans->marker < stage) - { - trans->marker = stage; - return TRUE; - } - - return FALSE; -} - -gboolean -xaccSplitTransactionTraverse (Split *split, int stage) -{ - if (split == NULL) return FALSE; - - return xaccTransactionTraverse (split->parent, stage); -} - -void -xaccGroupBeginStagedTransactionTraversals (AccountGroup *grp) -{ - GList *node; - - if (!grp) return; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - GList *lp; - - /* recursively do sub-accounts */ - xaccGroupBeginStagedTransactionTraversals (account->children); - - for (lp = account->splits; lp; lp = lp->next) - { - Split *s = lp->data; - Transaction *trans = s->parent; - trans->marker = 0; - } - } -} - -int -xaccAccountStagedTransactionTraversal (const Account *acc, - unsigned int stage, - int (*callback)(Transaction *t, - void *cb_data), - void *cb_data) -{ - GList *lp; - if (!acc) return 0; - - for(lp = acc->splits; lp; lp = lp->next) - { - Split *s = (Split *) lp->data; - Transaction *trans = s->parent; - if (trans && (trans->marker < stage)) - { - trans->marker = stage; - if (callback) - { - int retval; - retval = callback(trans, cb_data); - if (retval) return retval; - } - } - } - - return 0; -} - -int -xaccGroupStagedTransactionTraversal (AccountGroup *grp, - unsigned int stage, - int (*callback)(Transaction *t, - void *cb_data), - void *cb_data) -{ - GList *node; - - if (!grp) return 0; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - int retval; - - /* recursively do sub-accounts */ - retval = xaccGroupStagedTransactionTraversal (account->children, stage, - callback, cb_data); - if (retval) return retval; - - retval = xaccAccountStagedTransactionTraversal (account, stage, - callback, cb_data); - if (retval) return retval; - } - - return 0; -} - -/********************************************************************\ -\********************************************************************/ - -int -xaccGroupForEachTransaction (AccountGroup *g, - int (*proc)(Transaction *t, void *data), - void *data) -{ - if (!g || !proc) return 0; - - xaccGroupBeginStagedTransactionTraversals (g); - return xaccGroupStagedTransactionTraversal (g, 42, proc, data); -} - -/********************************************************************\ -\********************************************************************/ - -AccountList * -xaccGroupMapAccounts (AccountGroup *grp, - gpointer (*thunk)(Account *a, gpointer data), - gpointer data) -{ - GList *result = NULL; - GList *node; - - if (!grp || !thunk) return NULL; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - gpointer thunk_result = thunk (account, data); - - if (thunk_result) - { - result = g_list_append (result, thunk_result); - } - } - - return (result); -} - -gpointer -xaccGroupForEachAccount (AccountGroup *grp, - gpointer (*thunk)(Account *a, gpointer data), - gpointer data, - gboolean deeply) -{ - GList *node; - - if (!grp || !thunk) return(NULL); - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - gpointer result = thunk (account, data); - - if (result) - return(result); - - if(deeply) - result = xaccGroupForEachAccount (account->children, - thunk, data, TRUE); - - if (result) - return(result); - } - - return(NULL); -} - -/* ============================================================== */ - -QofBackend * -xaccGroupGetBackend (const AccountGroup *grp) -{ - grp = xaccGroupGetRoot (grp); - if (!grp || !grp->book) return NULL; - return qof_book_get_backend(grp->book); -} - -/* ============================================================== */ -/* gncObject function implementation and registration */ - -static void -group_book_begin (QofBook *book) -{ - xaccSetAccountGroup (book, xaccMallocAccountGroup(book)); -} - -static void -group_book_end (QofBook *book) -{ - xaccSetAccountGroup (book, NULL); -} - -static gboolean -group_is_dirty (const QofCollection *col) -{ - return xaccGroupNotSaved(xaccCollGetAccountGroup(col)); -} - -static void -group_mark_clean(QofCollection *col) -{ - xaccGroupMarkSaved(xaccCollGetAccountGroup(col)); -} - -static QofObject group_object_def = -{ - interface_version: QOF_OBJECT_VERSION, - e_type: GNC_ID_GROUP, - type_label: "AccountGroup", - create: (gpointer)xaccMallocAccountGroup, - book_begin: group_book_begin, - book_end: group_book_end, - is_dirty: group_is_dirty, - mark_clean: group_mark_clean, - foreach: NULL, - printable: NULL, - version_cmp: NULL, -}; - -gboolean -xaccGroupRegister (void) -{ - return qof_object_register (&group_object_def); -} - -/* ========================= END OF FILE ======================== */ diff --git a/src/engine/Group.h b/src/engine/Group.h deleted file mode 100644 index aaf45c830b..0000000000 --- a/src/engine/Group.h +++ /dev/null @@ -1,439 +0,0 @@ -/********************************************************************\ - * Group.h -- chart of accounts (hierarchical tree of accounts) * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 2 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License* - * along with this program; if not, contact: * - * * - * Free Software Foundation Voice: +1-617-542-5942 * - * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * - * Boston, MA 02110-1301, USA gnu@gnu.org * - * * -\********************************************************************/ -/** @addtogroup Engine - @{ */ -/** @addtogroup Group Account Heirarchy Tree - Accounts are organized into a heirarchical tree. The account - group is the parent node that holds accounts. - @{ */ -/** @file Group.h - @brief Account handling public routines - @author Copyright (C) 1997 Robin D. Clark - @author Copyright (C) 1997-2000,2003 Linas Vepstas -*/ - - -#ifndef XACC_ACCOUNT_GROUP_H -#define XACC_ACCOUNT_GROUP_H - -#include -#include "qof.h" -#include "Account.h" - -/* PROTOTYPES ******************************************************/ -/** @name Constructors, Destructors - @{ -*/ -/** - * The xaccMallocAccountGroup() routine will create a new account group. - * This is an internal-use function, you almost certainly want to - * be using the xaccGetAccountGroup() routine instead. - */ -AccountGroup *xaccMallocAccountGroup (QofBook *book); - -/** - * The xaccGetAccountGroup() routine will return the top-most - * account group associated with the indicated book. - */ -AccountGroup * xaccGetAccountGroup (QofBook *book); - -/** - * The xaccCollAccountGroup() routine will return the top-most - * account group associated with the indicated collection. - */ -AccountGroup * xaccCollGetAccountGroup (const QofCollection *col); - -/** The xaccAccountDestroy() routine will destroy and free all - * the data associated with this account group. The group - * must have been opened for editing with - * xaccAccountGroupBeginEdit() first, before the Destroy is called. - */ -void xaccAccountGroupDestroy (AccountGroup *grp); - -/* @deprecated XXX backwards-compat define, remove at later convenience */ -#define gnc_book_get_group xaccGetAccountGroup - -/** Return the book to which this account belongs */ -QofBook * xaccGroupGetBook (const AccountGroup *group); - -/** Compare two account groups - -warns if one is NULL, if one has no accounts or if the two -groups have different numbers of accounts. - -@return TRUE if the two account groups are equal, FALSE otherwise. -*/ -gboolean xaccGroupEqual(const AccountGroup *a, const AccountGroup *b, - gboolean check_guids); - -/** @} */ - -/** @name Editing - @{ -*/ -/** Start of begine/commit sequence. All changes to an account - * group should be bracketed by calls to begin-edit/commit-edit - */ -void xaccAccountGroupBeginEdit (AccountGroup *grp); - -/** End of begine/commit sequence. All changes to an account - * group should be bracketed by calls to begin-edit/commit-edit - */ -void xaccAccountGroupCommitEdit (AccountGroup *grp); - -/** The xaccGroupNotSaved() subroutine will return TRUE - * if any account in the group or in any subgroup - * hasn't been saved. - XXX this should be moved to private header file, this is not a public routine! - */ -gboolean xaccGroupNotSaved (const AccountGroup *grp); - -/** The xaccGroupMarkSaved() subroutine will mark - * the entire group as having been saved, including - * all of the child accounts. - - XXX this should be moved to private header file, this is not a public routine! - */ -void xaccGroupMarkSaved (AccountGroup *grp); - -/** The xaccGroupMarkNotSaved() subroutine will mark - * the given group as not having been saved. - XXX this should be moved to private header file, this is not a public routine! - */ -void xaccGroupMarkNotSaved (AccountGroup *grp); -/** @} */ - -/** @name Concatenation, Merging - @{ -*/ -/** - * The xaccGroupConcatGroup() subroutine will move (reparent) - * all accounts from the "src" group to the "dest" group, - * preserving the account heirarchy. It will also take care - * that the moved accounts will have the "dest" group's book - * parent as well. - */ -void xaccGroupConcatGroup (AccountGroup *dest, AccountGroup *src); - -/** The xaccGroupCopyGroup() subroutine will copy all accounts - * from the "src" group to the "dest" group, preserving the - * account heirarchy. It will also take care that the moved - * accounts will have the "dest" group's book parent as well. - * This routine will *NOT* copy any splits/transactions. - * It will copy the KVP trees in each account. - */ -void xaccGroupCopyGroup (AccountGroup *dest, AccountGroup *src); - -/** The xaccGroupMergeAccounts() subroutine will go through a group, - * merging all accounts that have the same name and description. - * This function is useful when importing Quicken(TM) files. - */ -void xaccGroupMergeAccounts (AccountGroup *grp); - -/** The xaccGroupInsertAccount() subroutine will insert the indicated - * account into the indicated group. If it already is the child - * of another group, it will be removed there first. If the - * account belongs to a different book than the the group, it - * will be removed from the other book (and thus, the other book's - * entity tables, generating destroy & create events). If the - * account is removed from and inserted into the same group, the - * overall account sort order will be recomputed. - */ -void xaccGroupInsertAccount (AccountGroup *grp, Account *acc); - -/** The xaccAccountInsertSubAccount() does the same, except that - * the parent is specified as an account. - */ -void xaccAccountInsertSubAccount (Account *parent, Account *child); -/** @} */ - -/** @name Counting the Size and Depth of the Account Tree - @{ -*/ -/** The xaccGroupGetNumSubAccounts() subroutine returns the number - * of accounts, including subaccounts, in the account group - */ -int xaccGroupGetNumSubAccounts (const AccountGroup *grp); - -/** The xaccGroupGetNumAccounts() subroutine returns the number - * of accounts in the indicated group only (children not counted). - */ -int xaccGroupGetNumAccounts (const AccountGroup *grp); - -/** The xaccGroupGetDepth() subroutine returns the length of the - * longest tree branch. Each link between an account and its - * (non-null) children counts as one unit of length. - */ -int xaccGroupGetDepth (const AccountGroup *grp); -/** @} */ - -/** @name Getting Accounts and Subaccounts - @{ -*/ -/** DOCUMENT ME! is this routine deprecated? XXX using index is weird! */ -Account * xaccGroupGetAccount (const AccountGroup *group, int index); - -/** The xaccGroupGetSubAccounts() subroutine returns an list of the accounts, - * including subaccounts, in the account group. The returned list - * should be freed with g_list_free() when no longer needed. - */ -AccountList * xaccGroupGetSubAccounts (const AccountGroup *grp); - -/** The xaccGroupGetSubAccounts() subroutine returns a sorted list of - * the accounts, including subaccounts, in the account group. The - * returned list should be freed with g_list_free() when no longer - * needed. - */ -AccountList * xaccGroupGetSubAccountsSorted (const AccountGroup *grp); - -/** The xaccGroupGetAccountList() subroutines returns only the immediate - * children of the account group. The returned list should *not* - * be freed by the caller. - */ -AccountList * xaccGroupGetAccountList (const AccountGroup *grp); - -/** The xaccGroupGetAccountList() subroutines returns only the - * immediate children of the account group. The returned list - * should be freed with g_list_free() when no longer needed. - */ -AccountList * xaccGroupGetAccountListSorted (const AccountGroup *grp); - -/** The xaccGroupGetRoot() subroutine will find the topmost - * (root) group to which this group belongs. - */ -AccountGroup * xaccGroupGetRoot (const AccountGroup *grp); - -/** The xaccGetAccountRoot() subroutine will find the topmost - * (root) group to which this account belongs. - */ -AccountGroup * xaccAccountGetRoot (const Account *account); - -/** The xaccGroupGetParentAccount() subroutine returns the parent - * account of the group, or NULL. - */ -Account * xaccGroupGetParentAccount (const AccountGroup *group); - -/** @} */ - -/** @name Getting Accounts and Subaccounts by Name - @{ -*/ -/** The xaccGetAccountFromName() subroutine fetches the - * account by name from the collection of accounts - * in the indicated AccountGroup group. It returns NULL if the - * account was not found. - */ -Account *xaccGetAccountFromName (const AccountGroup *group, const char *name); - -/** The xaccGetAccountFromFullName() subroutine works like - * xaccGetAccountFromName, but uses fully-qualified names - * using the given separator. - */ -Account *xaccGetAccountFromFullName (const AccountGroup *group, - const char *name); - -/** The xaccGetPeerAccountFromName() subroutine fetches the - * account by name from the collection of accounts - * in the same AccountGroup anchor group. It returns NULL if the - * account was not found. - */ -Account *xaccGetPeerAccountFromName (const Account *account, const char *name); - -/** The xaccGetPeerAccountFromFullName() subroutine works like - * xaccGetPeerAccountFromName, but uses fully-qualified - * names using the given separator. - */ -Account *xaccGetPeerAccountFromFullName (const Account *acc, - const char * name); - -/** @} */ - -/** @name Traversal, ForEach - @{ -*/ - -typedef gpointer (*AccountCallback) (Account *a, gpointer data); - -/** The xaccGroupMapAccounts() routine will traverse the account - group, returning a list of accounts. If the callback - returns null for a given item, it won't show up in - the result list. You should free the returned list when - you are done with it. -*/ -AccountList *xaccGroupMapAccounts(AccountGroup *grp, - AccountCallback func, - gpointer data); - -/** The xaccGroupForEachAccount() method will traverse the AccountGroup - * tree, calling 'func' on each account. Traversal will stop when - * func returns a non-null value, and the routine will return with that - * value. Therefore, this function will return null iff func returns - * null for every account. - * - * If 'deeply' is FALSE, then only the immediate children of - * the account will be traversed. If TRUE, then the whole tree will - * be traversed. - */ - -gpointer xaccGroupForEachAccount (AccountGroup *grp, - AccountCallback func, - gpointer data, - gboolean deeply); - -/** @} */ - -/** @name Staged Traversal - - * The following functions provide support for "staged traversals" - * over all of the transactions in an account or group. The idea - * is to be able to perform a sequence of traversals ("stages"), - * and perform an operation on each transaction exactly once - * for that stage. - * - * Only transactions whose current "stage" is less than the - * stage of the current traversal will be affected, and they will - * be "brought up" to the current stage when they are processed. - * - * For example, you could perform a stage 1 traversal of all the - * transactions in an account, and then perform a stage 1 traversal of - * the transactions in a second account. Presuming the traversal of - * the first account didn't abort prematurely, any transactions shared - * by both accounts would be ignored during the traversal of the - * second account since they had been processed while traversing the - * first account. - * - * However, if you had traversed the second account using a stage - * of 2, then all the transactions in the second account would have - * been processed. - * - * Traversal can be aborted by having the callback function return - * a non-zero value. The traversal is aborted immediately, and the - * non-zero value is returned. Note that an aborted traversal can - * be restarted; no information is lost due to an abort. - * - * The initial impetus for this particular approach came from - * generalizing a mark/sweep practice that was already being - * used in FileIO.c. - * - * Note that currently, there is a hard limit of 256 stages, which - * can be changed by enlarging "marker" in the transaction struct. - * - @{ -*/ -/** xaccGroupBeginStagedTransactionTraversals() resets the traversal - * marker inside each of all the transactions in the group so that - * a new sequence of staged traversals can begin. - */ -void xaccGroupBeginStagedTransactionTraversals(AccountGroup *grp); - -/** xaccSplitsBeginStagedTransactionTraversals() resets the traversal - * marker for each transaction which is a parent of one of the - * splits in the list. - */ -void xaccSplitsBeginStagedTransactionTraversals(SplitList *splits); - -/** xaccAccountBeginStagedTransactionTraversals() resets the traversal - * marker for each transaction which is a parent of one of the - * splits in the account. - */ -void xaccAccountBeginStagedTransactionTraversals(const Account *account); - -/** xaccTransactionTraverse() checks the stage of the given transaction. - * If the transaction hasn't reached the given stage, the transaction - * is updated to that stage and the function returns TRUE. Otherwise - * no change is made and the function returns FALSE. - */ -gboolean xaccTransactionTraverse(Transaction *trans, int stage); - -/** xaccSplitTransactionTraverse() behaves as above using the parent of - * the given split. - */ -gboolean xaccSplitTransactionTraverse(Split *split, int stage); - -/** xaccGroupStagedTransactionTraversal() calls thunk on each - * transaction in the group whose current marker is less than the - * given `stage' and updates each transaction's marker to be `stage'. - * The traversal will stop if thunk() returns a non-zero value. - * xaccGroupStagedTransactionTraversal() function will return zero - * or the non-zero value returned by thunk(). This - * API does not handle handle recursive traversals. - * - * Currently the result of adding or removing transactions during - * a traversal is undefined, so don't do that. - */ - -int xaccGroupStagedTransactionTraversal(AccountGroup *grp, - unsigned int stage, - TransactionCallback, - void *data); - -/** xaccAccountStagedTransactionTraversal() calls thunk on each - * transaction in the account whose current marker is less than the - * given `stage' and updates each transaction's marker to be `stage'. - * The traversal will stop if thunk() returns a non-zero value. - * xaccAccountStagedTransactionTraversal() function will return zero - * or the non-zero value returned by thunk(). - * This API does not handle handle recursive traversals. - * - * Currently the result of adding or removing transactions during - * a traversal is undefined, so don't do that. - */ - -int xaccAccountStagedTransactionTraversal(const Account *a, - unsigned int stage, - TransactionCallback thunk, - void *data); - -/** Traverse all of the transactions in the given account group. - Continue processing IFF proc returns 0. This function - will descend recursively to traverse transactions in the - children of the accounts in the group. - - Proc will be called exactly once for each transaction that is - pointed to by at least one split in any account in the hierarchy - topped by AccountGroup g. - - The result of this function will be 0 IFF every relevant - transaction was traversed exactly once; otherwise, the return - value is the last non-zero value returned by the callback. - - Note that the traversal occurs only over the transactions that - are locally cached in the local gnucash engine. If the gnucash - engine is attached to a remote database, the database may contain - (many) transactions that are not mirrored in the local cache. - This routine will not cause an SQL database query to be performed; - it will not traverse transactions present only in the remote - database. - - Note that this routine is just a trivial wrapper for - - xaccGroupBeginStagedTransactionTraversals(g); - xaccGroupStagedTransactionTraversal(g, 42, proc, data); - */ - -int xaccGroupForEachTransaction(AccountGroup *g, - TransactionCallback proc, void *data); - -/** @} */ -#endif /* XACC_ACCOUNT_GROUP_H */ -/** @} */ -/** @} */ diff --git a/src/engine/GroupP.h b/src/engine/GroupP.h deleted file mode 100644 index a716b8d528..0000000000 --- a/src/engine/GroupP.h +++ /dev/null @@ -1,102 +0,0 @@ -/********************************************************************\ - * GroupP.h -- private header file for chart of accounts * - * Copyright (C) 1997 Robin D. Clark * - * Copyright (C) 1997, 1998, 1999, 2000 Linas Vepstas * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 2 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License* - * along with this program; if not, contact: * - * * - * Free Software Foundation Voice: +1-617-542-5942 * - * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * - * Boston, MA 02110-1301, USA gnu@gnu.org * - * * -\********************************************************************/ - -/* - * FILE: - * GroupP.h - * - * FUNCTION: - * This is the *private* account group structure. - * This header should *not* be included by any code outside of the - * engine. - * - */ - -#ifndef XACC_GROUP_P_H -#define XACC_GROUP_P_H - -#include "Group.h" -#include "Transaction.h" - -/** STRUCTS *********************************************************/ -struct account_group_s -{ - /* The flags: */ - unsigned int saved : 1; - - Account *parent; /* back-pointer to parent */ - - AccountList *accounts; /* list of account pointers */ - - QofBook *book; /* The book which this group belongs to */ - - /* keep track of nesting level of begin/end edit calls */ - gint32 editlevel; -}; - -/* - * The xaccAccountRemoveGroup() subroutine will remove the indicated - * account group from its parent account. It will NOT free the - * associated memory or otherwise alter the account group: the - * account group can now be reparented to a new location. - * Note, however, that it will mark the old parents as having - * been modified. - * - * The xaccGroupRemoveAccount() subroutine will remove the indicated - * account from its parent account group. It will NOT free the - * associated memory or otherwise alter the account: the account - * can now be reparented to a new location. - * Note, however, that it will mark the old parents as having - * been modified. - * - * Both of the above routines are private routines, since they are slightly - * dangerous: If the removed group/account is not immediately reparented, - * it can be lost, i.e. turn into a memory leak. If the GUI or other engine - * user needs to move an account or group from here to there, it should use - * the 'Insert' routines, such as xaccGroupInsertAccount(), to make the move. - * The 'Insert' routines will automatically remove the account from its - * previous location. - */ - -void xaccAccountRemoveGroup (Account *acc); -void xaccGroupRemoveAccount (AccountGroup *grp, Account *account); - -/* - * The xaccFreeAccountGroup() subroutine will ... - */ -void xaccFreeAccountGroup (AccountGroup *account_group); - -/* Set the top-level group in the book */ -void xaccSetAccountGroup (QofBook *book, AccountGroup *grp); -void xaccCollSetAccountGroup (QofCollection *col, AccountGroup *grp); - -/* - * The xaccGroupGetBackend() subroutine will find the - * persistent-data storage backend associated with this account group. - */ -QofBackend * xaccGroupGetBackend (const AccountGroup *group); - -gboolean xaccGroupRegister (void); - -#endif diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am index 0a6d3b6274..6a4411e4fd 100644 --- a/src/engine/Makefile.am +++ b/src/engine/Makefile.am @@ -16,7 +16,6 @@ libgncmod_engine_la_SOURCES = \ Account.c \ FreqSpec.c \ Recurrence.c \ - Group.c \ Period.c \ Query.c \ SchedXaction.c \ @@ -57,7 +56,6 @@ gncinclude_HEADERS = \ FreqSpec.h \ Recurrence.h \ GNCId.h \ - Group.h \ Period.h \ SchedXaction.h \ SX-book.h \ @@ -96,7 +94,6 @@ gncinclude_HEADERS = \ noinst_HEADERS = \ AccountP.h \ FreqSpecP.h \ - GroupP.h \ QueryP.h \ SchedXactionP.h \ ScrubP.h \ diff --git a/src/engine/Period.c b/src/engine/Period.c index 18d8444865..59c831b335 100644 --- a/src/engine/Period.c +++ b/src/engine/Period.c @@ -40,9 +40,8 @@ #include "gnc-lot-p.h" #include "gnc-pricedb.h" #include "gnc-pricedb-p.h" -#include "Group.h" -#include "GroupP.h" #include "Period.h" +#include "Transaction.h" #include "TransactionP.h" /* This static indicates the debugging module that this .o belongs to. */ @@ -432,29 +431,19 @@ trans_list_preen_open_lots (TransList *trans_list) /* clear the markers for the above routines */ static void -clear_markers (AccountGroup *grp) +clear_markers (Account *account, gpointer dummy) { - GList *node; + GList *lp; - if (!grp) return; - - for (node = grp->accounts; node; node = node->next) - { - Account *account = node->data; - GList *lp; - - /* recursively do sub-accounts */ - clear_markers (account->children); - - for (lp = account->splits; lp; lp = lp->next) - { - Split *s = lp->data; - Transaction *trans = s->parent; - GNCLot *lot = s->lot; - trans->marker = 0; - if (lot) lot->marker = 0; - } - } + if (!account) return; + + for (lp = xaccAccountGetSplitList(account); lp; lp = lp->next) { + Split *s = lp->data; + Transaction *trans = s->parent; + GNCLot *lot = s->lot; + trans->marker = 0; + if (lot) lot->marker = 0; + } } /* ================================================================ */ @@ -526,7 +515,7 @@ void gnc_book_partition_txn (QofBook *dest_book, QofBook *src_book, QofQuery *query) { gnc_commodity_table *src_tbl, *dst_tbl; - AccountGroup *src_grp, *dst_grp; + Account *src_root, *dst_root; time_t now; TransList *trans_list, *tnode; LotList *lot_list, *lnode; @@ -552,18 +541,18 @@ gnc_book_partition_txn (QofBook *dest_book, QofBook *src_book, QofQuery *query) /* hack alert -- FIXME -- this should really be a merge, not a * clobber copy, but I am too lazy to write an account-group merge * routine, and it is not needed for the current usage. */ - src_grp = xaccGetAccountGroup (src_book); - dst_grp = xaccGetAccountGroup (dest_book); - xaccGroupCopyGroup (dst_grp, src_grp); + src_root = gnc_book_get_root_account (src_book); + dst_root = gnc_book_get_root_account (dest_book); + gnc_account_copy_children (dst_root, src_root); /* Next, run the query */ - xaccAccountGroupBeginEdit (dst_grp); - xaccAccountGroupBeginEdit (src_grp); + xaccAccountBeginEdit (dst_root); + xaccAccountBeginEdit (src_root); qof_query_set_book (query, src_book); trans_list = qof_query_run (query); /* Preen: remove open lots/ open trnasactions */ - clear_markers (src_grp); + gnc_account_foreach_descendant(src_root, clear_markers, NULL); trans_list = trans_list_preen_open_lots (trans_list); lot_list = create_lot_list_from_trans_list (trans_list); lot_list = lot_list_preen_open_lots (lot_list); @@ -583,8 +572,8 @@ gnc_book_partition_txn (QofBook *dest_book, QofBook *src_book, QofQuery *query) gnc_book_insert_trans (dest_book, trans); } - xaccAccountGroupCommitEdit (src_grp); - xaccAccountGroupCommitEdit (dst_grp); + xaccAccountCommitEdit (src_root); + xaccAccountCommitEdit (dst_root); /* Make note of the sibling books */ now = time(0); @@ -603,41 +592,37 @@ gnc_book_partition_txn (QofBook *dest_book, QofBook *src_book, QofQuery *query) static Account * find_nearest_equity_acct (Account *acc) { - AccountList *acc_list, *node; - AccountGroup *parent; - Account *next_up, *candidate; + QofBook *book; + GList *acc_list, *node; + Account *parent, *root, *candidate; - /* See if we can find an equity account that is peered to this account */ - parent = xaccAccountGetParent (acc); + parent = gnc_account_get_parent (acc); g_return_val_if_fail (parent, NULL); - acc_list = xaccGroupGetAccountList (parent); - for (node=acc_list; node; node=node->next) - { - candidate = (Account *) node->data; - if ((ACCT_TYPE_EQUITY == xaccAccountGetType (candidate)) && - gnc_commodity_equiv(xaccAccountGetCommodity(acc), - xaccAccountGetCommodity(candidate))) - { + /* See if we can find an equity account that is peered to this + * account. If not, check succssively higher levels. */ + while (parent != NULL) { + acc_list = gnc_account_get_children(parent); + for (node=acc_list; node; node=node->next) { + candidate = (Account *) node->data; + if ((ACCT_TYPE_EQUITY == xaccAccountGetType (candidate)) && + gnc_commodity_equiv(xaccAccountGetCommodity(acc), + xaccAccountGetCommodity(candidate))) { return candidate; - } + } + } + g_list_free(acc_list); + parent = gnc_account_get_parent (parent); } - /* If we got to here, we did not find a peer equity account. - * So go up one layer, and look there */ - next_up = xaccGroupGetParentAccount (parent); - if (next_up) - { - candidate = find_nearest_equity_acct (next_up); - if (candidate) return candidate; - } - - /* If we got to here, then we are at the top group, and there is no + /* If we got to here, then we are at the root account, and there is no * equity account to be found. So we need to create one. */ - - candidate = xaccMallocAccount (xaccGroupGetBook(parent)); + + book = gnc_account_get_book(acc); + root = gnc_book_get_root_account(book); + candidate = xaccMallocAccount (book); xaccAccountBeginEdit (candidate); - xaccGroupInsertAccount (parent, candidate); + gnc_account_append_child (root, candidate); xaccAccountSetType (candidate, ACCT_TYPE_EQUITY); xaccAccountSetName (candidate, xaccAccountGetTypeStr(ACCT_TYPE_EQUITY)); xaccAccountSetCommodity (candidate, xaccAccountGetCommodity(acc)); @@ -650,28 +635,27 @@ find_nearest_equity_acct (Account *acc) /* Traverse all accounts, get account balances */ static void -add_closing_balances (AccountGroup *closed_grp, +add_closing_balances (Account *parent, QofBook *open_book, QofBook *closed_book, Account *equity_account, Timespec *post_date, Timespec *date_entered, const char *desc) { - AccountList *acc_list, *node; + GList *acc_list, *node; - if (!closed_grp) return; + if (!parent) return; ENTER (" enter=%s post=%s desc=%s", gnc_print_date(*date_entered), gnc_print_date (*post_date), desc); xaccAccountBeginEdit (equity_account); /* Walk accounts in closed book */ - acc_list = xaccGroupGetAccountList (closed_grp); + acc_list = gnc_account_get_children(parent); for (node=acc_list; node; node=node->next) { KvpFrame *cwd; Account *twin; - AccountGroup *childs; Account * candidate = (Account *) node->data; GNCAccountType tip = xaccAccountGetType (candidate); @@ -774,16 +758,16 @@ add_closing_balances (AccountGroup *closed_grp, xaccAccountCommitEdit (twin); /* Recurse down to the children */ - childs = xaccAccountGetChildren(candidate); - if (childs) + if (gnc_account_n_children(candidate) > 0) { PINFO ("add closing baln to subaccts of %s", candidate->description); - add_closing_balances (childs, open_book, closed_book, + add_closing_balances (candidate, open_book, closed_book, equity_account, post_date, date_entered, desc); } } + g_list_free(acc_list); xaccAccountCommitEdit (equity_account); LEAVE (" "); } @@ -884,7 +868,7 @@ gnc_book_close_period (QofBook *existing_book, Timespec calve_date, /* add in transactions to equity accounts that will * hold the colsing balances */ - add_closing_balances (xaccGetAccountGroup(closing_book), + add_closing_balances (gnc_book_get_root_account(closing_book), existing_book, closing_book, equity_account, &calve_date, &ts, memo); diff --git a/src/engine/SX-book-p.h b/src/engine/SX-book-p.h index 99c1051b1f..04faefa88d 100644 --- a/src/engine/SX-book-p.h +++ b/src/engine/SX-book-p.h @@ -47,9 +47,10 @@ void gnc_book_set_schedxactions( QofBook *book, GList *newList ); void gnc_collection_set_schedxactions( QofCollection *col, GList *newList ); -/* Associate the given template group with a book */ -void gnc_book_set_template_group (QofBook *book, AccountGroup *templateGroup); -void gnc_collection_set_template_group (QofCollection *col, AccountGroup *templateGroup); +/* Associate the given template root account with a book */ +void gnc_book_set_template_root (QofBook *book, Account *templateRoot); +void gnc_collection_set_template_root (QofCollection *col, Account *templateRoot); + gboolean gnc_sxtt_register (void); diff --git a/src/engine/SX-book.c b/src/engine/SX-book.c index d647c6aa21..3ee1b67776 100644 --- a/src/engine/SX-book.c +++ b/src/engine/SX-book.c @@ -39,8 +39,8 @@ #include #include "gnc-engine.h" -#include "Group.h" -#include "GroupP.h" +#include "Account.h" +#include "Split.h" #include "SchedXaction.h" #include "SX-book.h" #include "SX-book-p.h" @@ -52,52 +52,54 @@ static QofLogModule log_module = GNC_MOD_SX; /* ====================================================================== */ -AccountGroup * -gnc_collection_get_template_group( const QofCollection *col ) +Account * +gnc_collection_get_template_root( const QofCollection *col ) { return qof_collection_get_data (col); } -AccountGroup * -gnc_book_get_template_group( QofBook *book ) +Account * +gnc_book_get_template_root( QofBook *book ) { QofCollection *col; if (!book) return NULL; col = qof_book_get_collection (book, GNC_ID_SXTG); - return gnc_collection_get_template_group (col); + return gnc_collection_get_template_root (col); } void -gnc_collection_set_template_group (QofCollection *col, - AccountGroup *templateGroup) +gnc_collection_set_template_root (QofCollection *col, + Account *templateRoot) { - AccountGroup *old_grp; + Account *old_root; if (!col) return; - old_grp = gnc_collection_get_template_group (col); - if (old_grp == templateGroup) return; + old_root = gnc_collection_get_template_root (col); + if (old_root == templateRoot) return; - qof_collection_set_data (col, templateGroup); + qof_collection_set_data (col, templateRoot); - xaccAccountGroupBeginEdit (old_grp); - xaccAccountGroupDestroy (old_grp); + if (old_root) { + xaccAccountBeginEdit (old_root); + xaccAccountDestroy (old_root); + } } void -gnc_book_set_template_group (QofBook *book, AccountGroup *templateGroup) +gnc_book_set_template_root (QofBook *book, Account *templateRoot) { QofCollection *col; if (!book) return; - if (templateGroup && templateGroup->book != book) + if (templateRoot && gnc_account_get_book(templateRoot) != book) { PERR ("cannot mix and match books freely!"); return; } col = qof_book_get_collection (book, GNC_ID_SXTG); - gnc_collection_set_template_group (col, templateGroup); + gnc_collection_set_template_root (col, templateRoot); } @@ -107,26 +109,55 @@ gnc_book_set_template_group (QofBook *book, AccountGroup *templateGroup) static void sxtg_book_begin (QofBook *book) { - gnc_book_set_template_group (book, xaccMallocAccountGroup(book)); + Account *root; + + root = xaccMallocAccount(book); + xaccAccountBeginEdit(root); + xaccAccountSetType(root, ACCT_TYPE_ROOT); + xaccAccountCommitEdit(root); + gnc_book_set_template_root (book, root); } static void sxtg_book_end (QofBook *book) { - gnc_book_set_template_group (book, NULL); + gnc_book_set_template_root (book, NULL); } static gboolean sxtg_is_dirty(const QofCollection *col) { - return xaccGroupNotSaved(gnc_collection_get_template_group(col)); + Account *root; + GList *accounts, *node; + gboolean dirty = FALSE; + + root = gnc_collection_get_template_root(col); + accounts = gnc_account_get_descendants(root); + for (node = accounts; node; node = g_list_next(node)) { + if (qof_instance_is_dirty(node->data)) { + dirty = TRUE; + break; + } + } + g_list_free(accounts); + + return dirty; } static void sxtg_mark_clean(QofCollection *col) { - xaccGroupMarkSaved(gnc_collection_get_template_group(col)); + Account *root; + GList *accounts, *node; + + root = gnc_collection_get_template_root(col); + qof_collection_mark_clean(col); + + accounts = gnc_account_get_descendants(root); + for (node = accounts; node; node = g_list_next(node)) + qof_instance_mark_clean(node->data); + g_list_free(accounts); } static QofObject sxtg_object_def = diff --git a/src/engine/SX-book.h b/src/engine/SX-book.h index 27d1c9be85..f118aba5e6 100644 --- a/src/engine/SX-book.h +++ b/src/engine/SX-book.h @@ -48,8 +48,8 @@ GList * gnc_collection_get_schedxactions(const QofCollection *col); GList * gnc_book_get_schedxactions(QofBook *book); /** Returns the template group from the book. **/ -AccountGroup * gnc_book_get_template_group(QofBook *book); -AccountGroup * gnc_collection_get_template_group(const QofCollection *col); +Account *gnc_book_get_template_root(QofBook *book); +Account *gnc_collection_get_template_root(const QofCollection *col); /** @return The list of SXes which reference the given Account. Caller should free this list. **/ GList* gnc_sx_get_sxes_referencing_account(QofBook *book, Account *acct); diff --git a/src/engine/SchedXaction.c b/src/engine/SchedXaction.c index 2e7c573f8f..4a800786b1 100644 --- a/src/engine/SchedXaction.c +++ b/src/engine/SchedXaction.c @@ -32,8 +32,6 @@ #include "FreqSpec.h" #include "Account.h" #include "gnc-book.h" -#include "Group.h" -#include "GroupP.h" #include "SX-book.h" #include "SX-ttinfo.h" #include "SchedXaction.h" @@ -50,7 +48,7 @@ void sxprivtransactionListMapDelete( gpointer data, gpointer user_data ); static void xaccSchedXactionInit(SchedXaction *sx, QofBook *book) { - AccountGroup *ag; + Account *ra; qof_instance_init (&sx->inst, GNC_ID_SCHEDXACTION, book); @@ -79,8 +77,8 @@ xaccSchedXactionInit(SchedXaction *sx, QofBook *book) "template", "template", "template", "template", 1 ) ); xaccAccountSetType( sx->template_acct, ACCT_TYPE_BANK ); - ag = gnc_book_get_template_group( book ); - xaccGroupInsertAccount( ag, sx->template_acct ); + ra = gnc_book_get_template_root( book ); + gnc_account_append_child( ra, sx->template_acct ); } SchedXaction* diff --git a/src/engine/Scrub.c b/src/engine/Scrub.c index 0d2d987faa..f4637313b9 100644 --- a/src/engine/Scrub.c +++ b/src/engine/Scrub.c @@ -45,8 +45,6 @@ #include "Account.h" #include "AccountP.h" -#include "Group.h" -#include "GroupP.h" #include "Scrub.h" #include "ScrubP.h" #include "Transaction.h" @@ -57,35 +55,20 @@ static QofLogModule log_module = GNC_MOD_SCRUB; /* ================================================================ */ -void -xaccGroupScrubOrphans (AccountGroup *grp) -{ - GList *list; - GList *node; - - if (!grp) return; - - list = xaccGroupGetAccountList (grp); - - for (node = list; node; node = node->next) - { - Account *account = node->data; - - xaccAccountTreeScrubOrphans (account); - } -} - void xaccAccountTreeScrubOrphans (Account *acc) { + GList *descendants; if (!acc) return; - xaccGroupScrubOrphans (xaccAccountGetChildren(acc)); xaccAccountScrubOrphans (acc); + descendants = gnc_account_get_descendants(acc); + g_list_foreach(descendants, (GFunc)xaccAccountScrubOrphans, NULL); + g_list_free(descendants); } static void -TransScrubOrphansFast (Transaction *trans, AccountGroup *root) +TransScrubOrphansFast (Transaction *trans, Account *root) { GList *node; @@ -125,7 +108,7 @@ xaccAccountScrubOrphans (Account *acc) Split *split = node->data; TransScrubOrphansFast (xaccSplitGetParent (split), - xaccAccountGetRoot (acc)); + gnc_account_get_root (acc)); } } @@ -135,14 +118,14 @@ xaccTransScrubOrphans (Transaction *trans) { SplitList *node; QofBook *book = NULL; - AccountGroup *root = NULL; + Account *root = NULL; for (node = trans->splits; node; node = node->next) { Split *split = node->data; if (split->acc) { - TransScrubOrphansFast (trans, xaccAccountGetRoot(split->acc)); + TransScrubOrphansFast (trans, gnc_account_get_root(split->acc)); return; } } @@ -154,35 +137,21 @@ xaccTransScrubOrphans (Transaction *trans) */ PINFO ("Free Floating Transaction!"); book = xaccTransGetBook (trans); - root = xaccGetAccountGroup (book); + root = gnc_book_get_root_account (book); TransScrubOrphansFast (trans, root); } /* ================================================================ */ -void -xaccGroupScrubSplits (AccountGroup *group) -{ - GList *list; - GList *node; - - if (!group) return; - - list = xaccGroupGetAccountList (group); - - for (node = list; node; node = node->next) - { - Account *account = node->data; - - xaccAccountTreeScrubSplits (account); - } -} - void xaccAccountTreeScrubSplits (Account *account) { - xaccGroupScrubSplits (xaccAccountGetChildren(account)); + GList *descendants; + xaccAccountScrubSplits (account); + descendants = gnc_account_get_descendants(account); + g_list_foreach(descendants, (GFunc)xaccAccountScrubSplits, NULL); + g_list_free(descendants); } void @@ -288,29 +257,15 @@ xaccSplitScrub (Split *split) /* ================================================================ */ -void -xaccGroupScrubImbalance (AccountGroup *grp) -{ - GList *list; - GList *node; - - if (!grp) return; - - list = xaccGroupGetAccountList (grp); - - for (node = list; node; node = node->next) - { - Account *account = node->data; - - xaccAccountTreeScrubImbalance (account); - } -} - void xaccAccountTreeScrubImbalance (Account *acc) { - xaccGroupScrubImbalance (xaccAccountGetChildren(acc)); + GList *descendants; + xaccAccountScrubImbalance (acc); + descendants = gnc_account_get_descendants(acc); + g_list_foreach(descendants, (GFunc)xaccAccountScrubImbalance, NULL); + g_list_free(descendants); } void @@ -332,7 +287,7 @@ xaccAccountScrubImbalance (Account *acc) xaccTransScrubCurrencyFromSplits(trans); - xaccTransScrubImbalance (trans, xaccAccountGetRoot (acc), NULL); + xaccTransScrubImbalance (trans, gnc_account_get_root (acc), NULL); } } @@ -397,7 +352,7 @@ xaccTransScrubCurrencyFromSplits(Transaction *trans) } void -xaccTransScrubImbalance (Transaction *trans, AccountGroup *root, +xaccTransScrubImbalance (Transaction *trans, Account *root, Account *account) { Split *balance_split = NULL; @@ -418,7 +373,7 @@ xaccTransScrubImbalance (Transaction *trans, AccountGroup *root, { if (!root) { - root = xaccGetAccountGroup (xaccTransGetBook (trans)); + root = gnc_book_get_root_account (xaccTransGetBook (trans)); if (NULL == root) { /* This can't occur, things should be in books */ @@ -754,27 +709,22 @@ scrub_trans_currency_helper (Transaction *t, gpointer data) return 0; } -static gpointer +static void scrub_account_commodity_helper (Account *account, gpointer data) { xaccAccountScrubCommodity (account); xaccAccountDeleteOldData (account); - return NULL; } void -xaccGroupScrubCommodities (AccountGroup *group) +xaccAccountTreeScrubCommodities (Account *acc) { - if (!group) return; - - xaccAccountGroupBeginEdit (group); - - xaccGroupForEachTransaction (group, scrub_trans_currency_helper, NULL); + if (!acc) return; - xaccGroupForEachAccount (group, scrub_account_commodity_helper, - NULL, TRUE); + xaccAccountTreeForEachTransaction (acc, scrub_trans_currency_helper, NULL); - xaccAccountGroupCommitEdit (group); + scrub_account_commodity_helper (acc, NULL); + gnc_account_foreach_descendant (acc, scrub_account_commodity_helper, NULL); } /* ================================================================ */ @@ -788,7 +738,7 @@ check_quote_source (gnc_commodity *com, gpointer data) return TRUE; } -static gpointer +static void move_quote_source (Account *account, gpointer data) { gnc_commodity *com; @@ -798,12 +748,12 @@ move_quote_source (Account *account, gpointer data) com = xaccAccountGetCommodity(account); if (!com) - return NULL; + return; if (!new_style) { source = dxaccAccountGetPriceSrc(account); if (!source || !*source) - return NULL; + return; tz = dxaccAccountGetQuoteTZ(account); PINFO("to %8s from %s", gnc_commodity_get_mnemonic(com), @@ -818,27 +768,26 @@ move_quote_source (Account *account, gpointer data) dxaccAccountSetPriceSrc(account, NULL); dxaccAccountSetQuoteTZ(account, NULL); - return NULL; + return; } void -xaccGroupScrubQuoteSources (AccountGroup *group, gnc_commodity_table *table) +xaccAccountTreeScrubQuoteSources (Account *root, gnc_commodity_table *table) { gboolean new_style = FALSE; ENTER(" "); - if (!group || !table) { + if (!root || !table) { LEAVE("Oops"); return; } gnc_commodity_table_foreach_commodity (table, check_quote_source, &new_style); - xaccAccountGroupBeginEdit (group); - xaccGroupForEachAccount (group, move_quote_source, - GINT_TO_POINTER(new_style), TRUE); - xaccAccountGroupCommitEdit (group); + move_quote_source(root, GINT_TO_POINTER(new_style)); + gnc_account_foreach_descendant (root, move_quote_source, + GINT_TO_POINTER(new_style)); LEAVE("Migration done"); } @@ -874,7 +823,7 @@ xaccAccountScrubKvp (Account *account) /* ================================================================ */ Account * -xaccScrubUtilityGetOrMakeAccount (AccountGroup *root, gnc_commodity * currency, +xaccScrubUtilityGetOrMakeAccount (Account *root, gnc_commodity * currency, const char *name_root) { char * accname; @@ -893,19 +842,19 @@ xaccScrubUtilityGetOrMakeAccount (AccountGroup *root, gnc_commodity * currency, gnc_commodity_get_mnemonic (currency), NULL); /* See if we've got one of these going already ... */ - acc = xaccGetAccountFromName (root, accname); + acc = gnc_account_lookup_name(root, accname); if (acc == NULL) { /* Guess not. We'll have to build one. */ - acc = xaccMallocAccount (root->book); + acc = xaccMallocAccount(gnc_account_get_book (root)); xaccAccountBeginEdit (acc); xaccAccountSetName (acc, accname); xaccAccountSetCommodity (acc, currency); xaccAccountSetType (acc, ACCT_TYPE_BANK); /* Hang the account off the root. */ - xaccGroupInsertAccount (root, acc); + gnc_account_append_child (root, acc); xaccAccountCommitEdit (acc); } diff --git a/src/engine/Scrub.h b/src/engine/Scrub.h index d4201bf8ac..ee1cadeab9 100644 --- a/src/engine/Scrub.h +++ b/src/engine/Scrub.h @@ -50,7 +50,6 @@ #ifndef XACC_SCRUB_H #define XACC_SCRUB_H -#include "Group.h" #include "gnc-engine.h" /** @name Double-Entry Scrubbing @@ -85,11 +84,6 @@ void xaccAccountScrubOrphans (Account *acc); */ void xaccAccountTreeScrubOrphans (Account *acc); -/** The xaccGroupScrubOrphans() method performs this scrub for the - * child accounts of this group. - */ -void xaccGroupScrubOrphans (AccountGroup *grp); - /** The xaccSplitScrub method ensures that if this split has the same * commodity and currency, then it will have the same amount and value. * If the commoidty is the currency, the split->amount is set to the @@ -106,18 +100,16 @@ void xaccSplitScrub (Split *split); void xaccTransScrubSplits (Transaction *trans); void xaccAccountScrubSplits (Account *account); void xaccAccountTreeScrubSplits (Account *account); -void xaccGroupScrubSplits (AccountGroup *group); /** The xaccScrubImbalance() method searches for transactions that do * not balance to zero. If any such transactions are found, a split * is created to offset this amount and is added to an "imbalance" * account. */ -void xaccTransScrubImbalance (Transaction *trans, AccountGroup *root, +void xaccTransScrubImbalance (Transaction *trans, Account *root, Account *parent); void xaccAccountScrubImbalance (Account *acc); void xaccAccountTreeScrubImbalance (Account *acc); -void xaccGroupScrubImbalance (AccountGroup *grp); /** The xaccTransScrubCurrency method fixes transactions without a * common_currency by using the old account currency and security @@ -137,9 +129,10 @@ void xaccTransScrubCurrencyFromSplits(Transaction *trans); * a commodity by using the old account currency and security. */ void xaccAccountScrubCommodity (Account *account); -/** The xaccGroupScrubCommodities will scrub the currency/commodity - * of all accounts & transactions in the group. */ -void xaccGroupScrubCommodities (AccountGroup *group); +/** The xaccAccountTreeScrubCommodities will scrub the + * currency/commodity of all accounts & transactions in the specified + * account or any child account. */ +void xaccAccountTreeScrubCommodities (Account *acc); /** This routine will migrate the information about price quote * sources from the account data structures to the commodity data @@ -148,13 +141,13 @@ void xaccGroupScrubCommodities (AccountGroup *group); * out as part of the account. Just in case anyone needs to fall * back from CVS to a production version of code. * - * @param group A pointer to the account group containing all + * @param acc A pointer to the root account containing all * accounts in the current book. * * @param table A pointer to the commodity table for the current * book. */ -void xaccGroupScrubQuoteSources (AccountGroup *group, gnc_commodity_table *table); +void xaccAccountTreeScrubQuoteSources (Account *root, gnc_commodity_table *table); void xaccAccountScrubKvp (Account *account); diff --git a/src/engine/Scrub2.c b/src/engine/Scrub2.c index b04d6fc6fc..e332fe26bb 100644 --- a/src/engine/Scrub2.c +++ b/src/engine/Scrub2.c @@ -36,8 +36,6 @@ #include "Account.h" #include "AccountP.h" -#include "Group.h" -#include "GroupP.h" #include "Transaction.h" #include "TransactionP.h" #include "Scrub2.h" diff --git a/src/engine/Scrub3.c b/src/engine/Scrub3.c index 55f5ea8c27..162327dbae 100644 --- a/src/engine/Scrub3.c +++ b/src/engine/Scrub3.c @@ -40,7 +40,6 @@ #include "policy-p.h" #include "Account.h" #include "AccountP.h" -#include "Group.h" #include "Scrub2.h" #include "Scrub3.h" #include "Transaction.h" @@ -176,19 +175,11 @@ xaccAccountScrubLots (Account *acc) /* ============================================================== */ -static gpointer +static void lot_scrub_cb (Account *acc, gpointer data) { - if (FALSE == xaccAccountHasTrades (acc)) return NULL; + if (FALSE == xaccAccountHasTrades (acc)) return; xaccAccountScrubLots (acc); - return NULL; -} - -void -xaccGroupScrubLots (AccountGroup *grp) -{ - if (!grp) return; - xaccGroupForEachAccount (grp, lot_scrub_cb, NULL, TRUE); } void @@ -196,7 +187,7 @@ xaccAccountTreeScrubLots (Account *acc) { if (!acc) return; - xaccGroupScrubLots (acc->children); + gnc_account_foreach_descendant(acc, lot_scrub_cb, NULL); xaccAccountScrubLots (acc); } diff --git a/src/engine/Scrub3.h b/src/engine/Scrub3.h index 97b920c7d2..f9dd00a0f1 100644 --- a/src/engine/Scrub3.h +++ b/src/engine/Scrub3.h @@ -62,16 +62,11 @@ gboolean xaccScrubLot (GNCLot *lot); * lot structure, and the cap-gains for an account are in good * order. * - * The xaccGroupScrubLots() routine walks the account tree, and invokes - * xaccAccountScrubLots() on all accounts that are trading accounts. - * The xaccAccountTreeScrubLots() does the same. - * * Most GUI routines will want to use one of these xacc[*]ScrubLots() * routines, instead of the various component routines, since it will * usually makes sense to work only with these high-level routines. */ void xaccAccountScrubLots (Account *acc); -void xaccGroupScrubLots (AccountGroup *grp); void xaccAccountTreeScrubLots (Account *acc); /** @} */ diff --git a/src/engine/ScrubP.h b/src/engine/ScrubP.h index 656c5d4940..2d2ca5aa8e 100644 --- a/src/engine/ScrubP.h +++ b/src/engine/ScrubP.h @@ -33,7 +33,7 @@ #include "gnc-engine.h" /* Utility to make account by name. Not for public use. */ -Account * xaccScrubUtilityGetOrMakeAccount (AccountGroup *root, +Account * xaccScrubUtilityGetOrMakeAccount (Account *root, gnc_commodity * currency, const char *name_root); diff --git a/src/engine/Split.c b/src/engine/Split.c index 7e620383e8..73d81e3e94 100644 --- a/src/engine/Split.c +++ b/src/engine/Split.c @@ -36,7 +36,6 @@ #include "Split.h" #include "AccountP.h" -#include "Group.h" #include "Scrub.h" #include "Scrub3.h" #include "TransactionP.h" diff --git a/src/engine/TransLog.c b/src/engine/TransLog.c index c9bb2e02c0..b7876ef087 100644 --- a/src/engine/TransLog.c +++ b/src/engine/TransLog.c @@ -29,7 +29,6 @@ #include #include "Account.h" -#include "AccountP.h" #include "Transaction.h" #include "TransactionP.h" #include "TransLog.h" diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c index 488ef71076..0eb96191b7 100644 --- a/src/engine/Transaction.c +++ b/src/engine/Transaction.c @@ -35,7 +35,6 @@ #include #include "AccountP.h" -#include "Group.h" #include "Scrub.h" #include "Scrub3.h" #include "TransactionP.h" @@ -1665,47 +1664,11 @@ guint gnc_book_count_transactions(QofBook *book) { guint count = 0; - xaccGroupForEachTransaction(xaccGetAccountGroup(book), + xaccAccountTreeForEachTransaction(gnc_book_get_root_account(book), counter_thunk, (void*)&count); return count; } -/********************************************************************\ -\********************************************************************/ -/* walk through the splits, looking for any account */ -static Account * -get_any_account(const Transaction *trans) -{ - GList *node; - if (!trans) return NULL; - for (node = trans->splits; node; node = node->next) - if (((Split *)node->data)->acc) - return ((Split *)node->data)->acc; - return NULL; -} -Account * -xaccGetAccountByName (const Transaction *trans, const char * name) -{ - Account *acc; - if (!trans || !name) return NULL; - - acc = get_any_account(trans); - return acc ? xaccGetPeerAccountFromName (acc, name) : NULL; -} - -/********************************************************************\ -\********************************************************************/ - -Account * -xaccGetAccountByFullName (const Transaction *trans, const char * name) -{ - Account *acc; - if (!trans || !name) return NULL; - - acc = get_any_account(trans); - return acc ? xaccGetPeerAccountFromFullName (acc, name) : NULL; -} - /********************************************************************\ \********************************************************************/ diff --git a/src/engine/cap-gains.c b/src/engine/cap-gains.c index d64a1a0940..63a170dfb6 100644 --- a/src/engine/cap-gains.c +++ b/src/engine/cap-gains.c @@ -58,10 +58,7 @@ ToDo: #include #include -#include "Account.h" #include "AccountP.h" -#include "Group.h" -#include "GroupP.h" #include "Scrub2.h" #include "Scrub3.h" #include "Transaction.h" @@ -221,7 +218,7 @@ xaccAccountFindLatestOpenLot (Account *acc, gnc_numeric sign, /* Similar to GetOrMakeAccount, but different in important ways */ static Account * -GetOrMakeLotOrphanAccount (AccountGroup *root, gnc_commodity * currency) +GetOrMakeLotOrphanAccount (Account *root, gnc_commodity * currency) { char * accname; Account * acc; @@ -239,12 +236,12 @@ GetOrMakeLotOrphanAccount (AccountGroup *root, gnc_commodity * currency) gnc_commodity_get_mnemonic (currency), NULL); /* See if we've got one of these going already ... */ - acc = xaccGetAccountFromName (root, accname); + acc = gnc_account_lookup_name(root, accname); if (acc == NULL) { /* Guess not. We'll have to build one. */ - acc = xaccMallocAccount (root->book); + acc = xaccMallocAccount (gnc_account_get_book(root)); xaccAccountBeginEdit (acc); xaccAccountSetName (acc, accname); xaccAccountSetCommodity (acc, currency); @@ -256,7 +253,7 @@ GetOrMakeLotOrphanAccount (AccountGroup *root, gnc_commodity * currency) "that haven't been recorded elsewhere.")); /* Hang the account off the root. */ - xaccGroupInsertAccount (root, acc); + gnc_account_append_child (root, acc); xaccAccountCommitEdit (acc); } @@ -344,10 +341,10 @@ GetOrMakeGainAcct (Account *acc, gnc_commodity * currency) * for this account, then create such a place */ if (NULL == gain_acct) { - AccountGroup *root; + Account *root; xaccAccountBeginEdit (acc); - root = xaccAccountGetRoot(acc); + root = gnc_account_get_root(acc); gain_acct = GetOrMakeLotOrphanAccount (root, currency); vvv = kvp_value_new_guid (xaccAccountGetGUID (gain_acct)); diff --git a/src/engine/cashobjects.c b/src/engine/cashobjects.c index 52f40243b7..53faf67d21 100644 --- a/src/engine/cashobjects.c +++ b/src/engine/cashobjects.c @@ -27,7 +27,6 @@ #include "cashobjects.h" #include "gnc-engine.h" #include "AccountP.h" -#include "GroupP.h" #include "TransactionP.h" #include "FreqSpec.h" #include "SchedXaction.h" @@ -43,7 +42,6 @@ cashobjects_register(void) g_return_val_if_fail(xaccAccountRegister(), FALSE); g_return_val_if_fail ( xaccTransRegister(), FALSE); g_return_val_if_fail ( xaccSplitRegister(), FALSE); - g_return_val_if_fail ( xaccGroupRegister(), FALSE); g_return_val_if_fail ( FreqSpecRegister(), FALSE); g_return_val_if_fail ( SXRegister (), FALSE); g_return_val_if_fail ( gnc_sxtt_register(), FALSE); diff --git a/src/engine/engine-helpers.c b/src/engine/engine-helpers.c index 33e085919d..2523e493cf 100644 --- a/src/engine/engine-helpers.c +++ b/src/engine/engine-helpers.c @@ -29,7 +29,6 @@ #include #include "Account.h" -#include "Group.h" #include "engine-helpers.h" #include "glib-helpers.h" #include "gnc-date.h" diff --git a/src/engine/engine.scm b/src/engine/engine.scm index 567d885117..2c7e008d68 100644 --- a/src/engine/engine.scm +++ b/src/engine/engine.scm @@ -42,8 +42,8 @@ (export GNC_COMMODITY_NS_MUTUAL) (export gnc:url->loaded-session) -(export gnc:group-map-all-accounts) -(export gnc:group-map-accounts) +(export gnc:account-map-descendants) +(export gnc:account-map-children) (export gnc:split-structure) (export gnc:make-split-scm) diff --git a/src/engine/gnc-associate-account.c b/src/engine/gnc-associate-account.c index 339045750d..2b866d50bf 100644 --- a/src/engine/gnc-associate-account.c +++ b/src/engine/gnc-associate-account.c @@ -28,7 +28,6 @@ #include "config.h" -#include "AccountP.h" #include "gnc-associate-account.h" #include "gnc-engine.h" #include "qof.h" @@ -297,7 +296,8 @@ gnc_tracking_find_expense_accounts(Account *stock_account, kvpd_on_account_list = kvp_frame_get_slot(account_frame, expense_to_key[category]); - return de_kvp_account_list(kvpd_on_account_list, stock_account->inst.book); + return de_kvp_account_list(kvpd_on_account_list, + gnc_account_get_book(stock_account)); } /*********************************************************************\ @@ -329,7 +329,8 @@ gnc_tracking_find_income_accounts(Account *stock_account, kvpd_on_account_list = kvp_frame_get_slot(income_acc_frame, income_to_key[category]); - return de_kvp_account_list(kvpd_on_account_list, stock_account->inst.book); + return de_kvp_account_list(kvpd_on_account_list, + gnc_account_get_book(stock_account)); } /*********************************************************************\ @@ -440,7 +441,7 @@ gnc_tracking_dissociate_account(Account *inc_or_expense_account) inc_or_expense_account_guid = xaccAccountGetGUID(inc_or_expense_account); stock_account = xaccAccountLookup - (stock_account_guid, inc_or_expense_account->inst.book); + (stock_account_guid, gnc_account_get_book(inc_or_expense_account)); stock_account_kvpframe = xaccAccountGetSlots(stock_account); diff --git a/src/engine/gnc-budget.c b/src/engine/gnc-budget.c index 70d09be3e7..b0d40926f9 100644 --- a/src/engine/gnc-budget.c +++ b/src/engine/gnc-budget.c @@ -32,7 +32,6 @@ #include "glib-compat.h" #include "Account.h" -#include "Group.h" #include "gnc-budget.h" #include "gnc-commodity.h" @@ -290,14 +289,12 @@ is_same_commodity(Account *a, gpointer data) static gboolean xaccAccountChildrenHaveSameCommodity(Account *account) { - AccountGroup *grp; gpointer different; gnc_commodity *comm; comm = xaccAccountGetCommodity(account); - grp = xaccAccountGetChildren(account); - different = xaccGroupForEachAccount( - grp, is_same_commodity, comm, TRUE); + different = + gnc_account_foreach_descendant_until(account, is_same_commodity, comm); return (different == NULL); } #endif diff --git a/src/engine/gnc-engine.c b/src/engine/gnc-engine.c index a0ea2899d6..4268002254 100644 --- a/src/engine/gnc-engine.c +++ b/src/engine/gnc-engine.c @@ -28,7 +28,6 @@ #include "qof.h" #include "cashobjects.h" #include "AccountP.h" -#include "GroupP.h" #include "SX-book-p.h" #include "gnc-budget.h" #include "TransactionP.h" diff --git a/src/engine/gnc-engine.h b/src/engine/gnc-engine.h index 3d8b2371cd..4959518690 100644 --- a/src/engine/gnc-engine.h +++ b/src/engine/gnc-engine.h @@ -92,7 +92,6 @@ #define GNC_ID_COMMODITY_NAMESPACE "CommodityNamespace" #define GNC_ID_COMMODITY_TABLE "CommodityTable" #define GNC_ID_FREQSPEC "FreqSpec" -#define GNC_ID_GROUP "AccountGroup" #define GNC_ID_LOT "Lot" #define GNC_ID_PERIOD "Period" #define GNC_ID_PRICE "Price" @@ -130,10 +129,6 @@ * through the functions in Account.h .*/ typedef struct account_s Account; -/** @brief A group of accounts in Gnucash. -*/ -typedef struct account_group_s AccountGroup; - /** @brief Split in Gnucash. * A "split" is more commonly refered to as a "entry" in a * "transaction". Each split belongs to one Account and one diff --git a/src/engine/test-core/test-engine-stuff.c b/src/engine/test-core/test-engine-stuff.c index ec54b3af3a..22bf2f15bb 100644 --- a/src/engine/test-core/test-engine-stuff.c +++ b/src/engine/test-core/test-engine-stuff.c @@ -29,8 +29,6 @@ #include "Account.h" #include "AccountP.h" -#include "Group.h" -#include "GroupP.h" #include "gnc-engine.h" #include "Transaction.h" #include "TransactionP.h" @@ -45,8 +43,8 @@ static GHashTable *exclude_kvp_types = NULL; static gint kvp_max_depth = 5; static gint kvp_frame_max_elements = 10; -static gint max_group_depth = 1; -static gint max_group_accounts = 3; +static gint max_tree_depth = 1; +static gint max_level_accounts = 3; static gint max_total_accounts = 10; static gint max_trans_num = 1000; static gint total_num_accounts = 0; @@ -69,15 +67,15 @@ gboolean gnc_engine_debug_random = FALSE; /* Set control parameters governing the run. */ void -set_max_group_depth (gint max_group_depth_in) +set_max_account_tree_depth (gint max_tree_depth_in) { - max_group_depth = MAX (max_group_depth_in, 1); + max_tree_depth = MAX (max_tree_depth_in, 1); } void -set_max_group_accounts (gint max_group_accounts_in) +set_max_accounts_per_level (gint max_level_accounts_in) { - max_group_accounts = MAX (max_group_accounts_in, 1); + max_level_accounts = MAX (max_level_accounts_in, 1); } void @@ -838,7 +836,7 @@ account_add_subaccounts (QofBook *book, Account *account, int depth) { Account *sub = get_random_account (book); - xaccAccountInsertSubAccount (account, sub); + gnc_account_append_child (account, sub); total_num_accounts ++; if (total_num_accounts > max_total_accounts) return; @@ -848,64 +846,40 @@ account_add_subaccounts (QofBook *book, Account *account, int depth) } static void -make_random_group_depth (QofBook *book, AccountGroup *group, int depth) -{ - int num_accounts; - - g_return_if_fail (book); - g_return_if_fail (group); - - if (depth <= 0) - return; - - num_accounts = get_random_int_in_range (1, max_group_accounts); - - while (num_accounts-- > 0) - { - Account *account = get_random_account (book); - - xaccGroupInsertAccount (group, account); - total_num_accounts++; - - account_add_subaccounts (book, account, depth - 1); - } -} - -static void -make_random_group (QofBook *book, AccountGroup *group) +make_random_account_tree (QofBook *book, Account *root) { int depth; g_return_if_fail (book); - g_return_if_fail (group); + g_return_if_fail (root); total_num_accounts = 0; - depth = get_random_int_in_range (1, max_group_depth); + depth = get_random_int_in_range (1, max_tree_depth); - make_random_group_depth (book, group, depth); + account_add_subaccounts (book, root, depth); /* Make sure we have at least two accounts! */ if (total_num_accounts <= 1) - make_random_group_depth (book, group, 1); + account_add_subaccounts (book, root, 1); } -AccountGroup * -get_random_group (QofBook *book) +Account * +get_random_accounts (QofBook *book) { - AccountGroup * group; + Account * root; g_return_val_if_fail (book, NULL); - group = xaccGetAccountGroup (book); - if (!group) + root = gnc_book_get_root_account (book); + if (!root) { - group = xaccMallocAccountGroup (book); - xaccSetAccountGroup (book, group); + root = xaccMallocAccount (book); + gnc_book_set_root_account (book, root); } - make_random_group (book, group); + make_random_account_tree (book, root); - return group; + return root; } /* ================================================================= */ @@ -1073,7 +1047,7 @@ add_trans_helper (Transaction *trans, gpointer data) } void -make_random_changes_to_group (QofBook *book, AccountGroup *group) +make_random_changes_to_level (QofBook *book, Account *parent) { Account *new_account; Account *account; @@ -1082,24 +1056,24 @@ make_random_changes_to_group (QofBook *book, AccountGroup *group) GList *splits; GList *node; - g_return_if_fail (group && book); + g_return_if_fail (parent && book); - accounts = xaccGroupGetSubAccounts (group); + accounts = gnc_account_get_descendants (parent); /* Add a new account */ new_account = get_random_account (book); if (get_random_boolean () || !accounts) - xaccGroupInsertAccount (group, new_account); + gnc_account_append_child (parent, new_account); else { account = get_random_list_element (accounts); - xaccAccountInsertSubAccount (account, new_account); + gnc_account_append_child (account, new_account); } g_list_free (accounts); - accounts = xaccGroupGetSubAccounts (group); + accounts = gnc_account_get_descendants (parent); /* Add some new transactions */ add_random_transactions_to_book (book, get_random_int_in_range (1, 6)); @@ -1115,7 +1089,7 @@ make_random_changes_to_group (QofBook *book, AccountGroup *group) /* Mess with the transactions & splits */ transes = NULL; - xaccGroupForEachTransaction (group, add_trans_helper, &transes); + xaccAccountTreeForEachTransaction (parent, add_trans_helper, &transes); for (node = transes; node; node = node->next) { @@ -1161,7 +1135,7 @@ make_random_changes_to_group (QofBook *book, AccountGroup *group) g_list_free (splits); g_list_free (accounts); - accounts = xaccGroupGetSubAccounts (group); + accounts = gnc_account_get_descendants (parent); /* move some accounts around */ if (accounts && (g_list_length (accounts) > 1)) @@ -1181,7 +1155,7 @@ make_random_changes_to_group (QofBook *book, AccountGroup *group) if (!a2) { - xaccGroupInsertAccount (group, a1); + gnc_account_append_child (parent, a1); continue; } @@ -1193,7 +1167,7 @@ make_random_changes_to_group (QofBook *book, AccountGroup *group) continue; } - xaccAccountInsertSubAccount (a2, a1); + gnc_account_append_child (a2, a1); } } @@ -1203,8 +1177,7 @@ make_random_changes_to_group (QofBook *book, AccountGroup *group) Account* get_random_account(QofBook *book) { - AccountGroup *grp; - Account *ret; + Account *root, *ret; int tmp_int; ret = xaccMallocAccount(book); @@ -1224,13 +1197,13 @@ get_random_account(QofBook *book) xaccAccountSetSlots_nc(ret, get_random_kvp_frame()); - grp = xaccGetAccountGroup (book); - if (!grp) + root = gnc_book_get_root_account (book); + if (!root) { - grp = xaccMallocAccountGroup (book); - xaccSetAccountGroup (book, grp); + root = xaccMallocAccount (book); + gnc_book_set_root_account (book, root); } - xaccGroupInsertAccount (grp, ret); + gnc_account_append_child (root, ret); xaccAccountCommitEdit(ret); return ret; @@ -1430,7 +1403,7 @@ get_random_transaction_with_currency(QofBook *book, numstr = g_new0(gchar, 10); if (!account_list) { - account_list = xaccGroupGetSubAccounts (xaccGetAccountGroup (book)); + account_list = gnc_account_get_descendants (gnc_book_get_root_account (book)); } /* Gotta have at least two different accounts */ @@ -1878,7 +1851,7 @@ get_random_book (void) book = qof_book_new (); - get_random_group (book); + get_random_accounts (book); get_random_pricedb (book); return book; @@ -1894,7 +1867,7 @@ get_random_session (void) book = qof_session_get_book (session); - get_random_group (book); + get_random_accounts (book); get_random_pricedb (book); return session; @@ -1910,7 +1883,7 @@ add_random_transactions_to_book (QofBook *book, gint num_transactions) g_return_if_fail (book); - accounts = xaccGroupGetSubAccounts (xaccGetAccountGroup (book)); + accounts = gnc_account_get_descendants (gnc_book_get_root_account (book)); g_return_if_fail (accounts); table = gnc_commodity_table_get_table (book); @@ -1931,7 +1904,7 @@ make_random_changes_to_book (QofBook *book) { g_return_if_fail (book); - make_random_changes_to_group (book, xaccGetAccountGroup (book)); + make_random_changes_to_level (book, gnc_book_get_root_account (book)); make_random_changes_to_pricedb (book, gnc_pricedb_get_db (book)); #if 0 diff --git a/src/engine/test-core/test-engine-stuff.h b/src/engine/test-core/test-engine-stuff.h index 1318239d09..ffa4714572 100644 --- a/src/engine/test-core/test-engine-stuff.h +++ b/src/engine/test-core/test-engine-stuff.h @@ -35,13 +35,13 @@ void random_glist_strings_only (gboolean strings_only); void kvp_exclude_type (KvpValueType kvp_type); void set_max_kvp_depth (gint max_kvp_depth); void set_max_kvp_frame_elements (gint max_kvp_frame_elements); -void set_max_group_depth (gint max_group_depth); -void set_max_group_accounts (gint max_group_accounts); +void set_max_account_tree_depth (gint max_tree_depth); +void set_max_accounts_per_level (gint max_accounts); GNCPrice * get_random_price(QofBook *book); gboolean make_random_pricedb (QofBook *book, GNCPriceDB *pdb); GNCPriceDB * get_random_pricedb(QofBook *book); -AccountGroup * get_random_group(QofBook * book); +Account * get_random_accounts(QofBook * book); Account* get_random_account(QofBook * book); Split* get_random_split(QofBook *book, Account *account, Transaction *trn); Transaction* get_random_transaction(QofBook *book); @@ -84,7 +84,7 @@ void make_random_changes_to_transaction_and_splits (QofBook *book, Transaction *trans, GList *accounts); void make_random_changes_to_account (QofBook *book, Account *account); -void make_random_changes_to_group (QofBook *book, AccountGroup *group); +void make_random_changes_to_level (QofBook *book, Account *parent); void make_random_changes_to_book (QofBook *book); void make_random_changes_to_session (QofSession *session); diff --git a/src/engine/test/test-group-vs-book.c b/src/engine/test/test-group-vs-book.c index 7a7a0b5e8b..5c4673da5a 100644 --- a/src/engine/test/test-group-vs-book.c +++ b/src/engine/test/test-group-vs-book.c @@ -25,34 +25,30 @@ #include #include "qof.h" #include "cashobjects.h" -#include "Group.h" -#include "GroupP.h" +#include "Account.h" #include "TransLog.h" #include "gnc-engine.h" #include "test-engine-stuff.h" #include "test-stuff.h" static gboolean -group_has_book (AccountGroup *group, QofBook *book) +account_tree_has_book (Account *parent, QofBook *book) { - GList *node; + GList *children, *node; - if (!group) + if (!parent) return (book == NULL); - if (xaccGroupGetBook (group) != book) + if (gnc_account_get_book(parent) != book) return FALSE; - for (node = xaccGroupGetAccountList (group); node; node = node->next) + children = gnc_account_get_children(parent); + for (node = children; node; node = node->next) { - AccountGroup *children = xaccAccountGetChildren (node->data); - - if (!children) - continue; - - if (!group_has_book (children, book)) + if (!account_tree_has_book (node->data, book)) return FALSE; } + g_list_free(children); return TRUE; } @@ -61,8 +57,8 @@ group_has_book (AccountGroup *group, QofBook *book) static void run_test (void) { - AccountGroup *group1; - AccountGroup *group2; + Account *root1; + Account *root2; Account *account1; Account *account2; QofBook *book; @@ -74,16 +70,16 @@ run_test (void) exit(get_rv()); } - group1 = get_random_group (book); - if(!group1) + root1 = get_random_account (book); + if(!root1) { - failure("group1 not created"); + failure("root1 not created"); exit(get_rv()); } - if (!group_has_book (group1, book)) + if (!account_tree_has_book (root1, book)) { - failure("new group has wrong book"); + failure("new root has wrong book"); exit(get_rv()); } @@ -93,34 +89,34 @@ run_test (void) * interface. the maintenance of the correct * book pointers is important for correct * engine operation. */ - xaccSetAccountGroup (book, group1); - if (!group_has_book (group1, book)) + gnc_book_set_root_account (book, root1); + if (!account_tree_has_book (root1, book)) { - failure("xaccSetAccountGroup didn't take"); + failure("gnc_book_set_root_account didn't take"); exit(get_rv()); } - group2 = get_random_group (book); - if(!group2) + root2 = get_random_account (book); + if(!root2) { - failure("group2 not created"); + failure("root2 not created"); exit(get_rv()); } - xaccSetAccountGroup (book, group2); + gnc_book_set_root_account (book, root2); #if 0 /* a group cannot have a 'null' book; this test is nonsense. */ - if (!group_has_book (group1, NULL)) + if (!account_tree_has_book (root1, NULL)) { - failure("xaccSetAccountGroup didn't clear old"); + failure("gnc_book_set_root_account didn't clear old"); exit(get_rv()); } #endif - if (!group_has_book (group2, book)) + if (!account_tree_has_book (root2, book)) { - failure("xaccSetAccountGroup didn't take"); + failure("gnc_book_set_root_account didn't take"); exit(get_rv()); } @@ -131,8 +127,8 @@ run_test (void) exit(get_rv()); } - xaccGroupInsertAccount (group2, account1); - if (group2 != xaccAccountGetParent (account1)) + gnc_account_append_child (root2, account1); + if (root2 != gnc_account_get_parent (account1)) { failure("group insert account didn't work"); exit(get_rv()); @@ -145,15 +141,15 @@ run_test (void) exit(get_rv()); } - xaccAccountInsertSubAccount (account1, account2); - if (!group_has_book (xaccAccountGetParent (account2), book)) + gnc_account_append_child (account1, account2); + if (!account_tree_has_book (gnc_account_get_parent (account2), book)) { failure("account2 has wrong book"); exit(get_rv()); } - xaccGroupRemoveAccount (group2, account1); - if (xaccAccountGetParent (account1) != NULL) + gnc_account_remove_child (root2, account1); + if (gnc_account_get_parent (account1) != NULL) { failure("remove group didn't take"); exit(get_rv()); diff --git a/src/engine/test/test-lots.c b/src/engine/test/test-lots.c index 1409f32af5..e7eea8ffe1 100644 --- a/src/engine/test/test-lots.c +++ b/src/engine/test/test-lots.c @@ -30,7 +30,6 @@ #include #include "qof.h" #include "Account.h" -#include "Group.h" #include "Scrub3.h" #include "cashobjects.h" #include "test-stuff.h" @@ -45,7 +44,7 @@ run_test (void) { QofSession *sess; QofBook *book; - AccountGroup *grp; + Account *root; /* --------------------------------------------------------- */ /* In the first test, we will merely try to see if we can run @@ -56,8 +55,8 @@ run_test (void) add_random_transactions_to_book (book, transaction_num); - grp = xaccGetAccountGroup (book); - xaccGroupScrubLots (grp); + root = gnc_book_get_root_account (book); + xaccAccountTreeScrubLots (root); /* --------------------------------------------------------- */ /* In the second test, we create an account with unrealized gains, diff --git a/src/engine/test/test-period.c b/src/engine/test/test-period.c index 065723938c..20a4549d68 100644 --- a/src/engine/test/test-period.c +++ b/src/engine/test/test-period.c @@ -32,7 +32,6 @@ #include #include "cashobjects.h" #include "Account.h" -#include "Group.h" #include "Period.h" #include "test-stuff.h" #include "test-engine-stuff.h" @@ -44,9 +43,8 @@ run_test (void) { QofSession *sess1, *sess2; QofBook *openbook, *closedbook; - AccountGroup *grp; - AccountList *acclist, *anode; - Account *acc, *equity; + GList *acclist, *anode; + Account *root, *acc, *equity; SplitList *splist; Split *sfirst, *slast; Transaction *tfirst, *tlast; @@ -66,9 +64,9 @@ run_test (void) add_random_transactions_to_book (openbook, num_trans); - grp = xaccGetAccountGroup (openbook); + root = gnc_book_get_root_account (openbook); - acclist = xaccGroupGetSubAccounts (grp); + acclist = gnc_account_get_descendants (root); for (anode=acclist; anode; anode=anode->next) { int ns; @@ -77,10 +75,11 @@ run_test (void) if (2 <= ns) break; acc = NULL; } + g_list_free(acclist); if(!acc) { - failure("group didn't have accounts with enough splits"); + failure("book didn't have accounts with enough splits"); exit(get_rv()); } diff --git a/src/engine/test/test-query.c b/src/engine/test/test-query.c index 03178be21c..80a40bac29 100644 --- a/src/engine/test/test-query.c +++ b/src/engine/test/test-query.c @@ -25,7 +25,6 @@ #include #include "qof.h" #include "cashobjects.h" -#include "Group.h" #include "Transaction.h" #include "TransLog.h" #include "gnc-engine.h" @@ -70,16 +69,16 @@ static void run_test (void) { QofSession *session; - AccountGroup *group; + Account *root; QofBook *book; session = get_random_session (); book = qof_session_get_book (session); - group = xaccGetAccountGroup (book); + root = gnc_book_get_root_account (book); add_random_transactions_to_book (book, 20); - xaccGroupForEachTransaction (group, test_trans_query, book); + xaccAccountTreeForEachTransaction (root, test_trans_query, book); qof_session_end (session); } diff --git a/src/experimental/cgi-bin/gnc-server.c b/src/experimental/cgi-bin/gnc-server.c index 1ca09fd32a..09b96a1dc6 100644 --- a/src/experimental/cgi-bin/gnc-server.c +++ b/src/experimental/cgi-bin/gnc-server.c @@ -17,7 +17,6 @@ #include "gnc-book.h" #include "gnc-engine.h" -#include "Group.h" #include "io-gncxml.h" #include @@ -213,7 +212,7 @@ main (int argc, char *argv[]) int err, fake_argc =1; char * fake_argv[] = {"hello", 0}; GNCBook *book; - AccountGroup *grp; + Account *root; char *request_bufp, *reply_bufp; int rc, sz; @@ -230,8 +229,8 @@ main (int argc, char *argv[]) rc = gnc_book_load (book); if (!rc) goto bookerrexit; - /* the grp pointer points to our local cache of the data */ - grp = gnc_book_get_group (book); + /* the root pointer points to our local cache of the data */ + root = gnc_book_get_root_account (book); /* --------------------------------------------------- */ /* done with initialization, go into event loop */ @@ -326,7 +325,7 @@ main (int argc, char *argv[]) * in, send them the full set of accounts. * (Do not send them any transactions yet). */ - gncxml_write_group_to_buf(grp, &reply_bufp, &sz); + gncxml_write_group_to_buf(root, &reply_bufp, &sz); /* send the xml to the client */ printf ("%s", reply_bufp); @@ -345,7 +344,7 @@ main (int argc, char *argv[]) /* conver the xml input into a gnucash query structure... */ q = gncxml_read_query (request_bufp, read_len); - xaccQuerySetGroup (q, grp); + xaccQuerySetGroup (q, root); /* hack -- limit to 30 splits ... */ xaccQuerySetMaxSplits (q, 30); diff --git a/src/experimental/cgi-bin/hello2.c b/src/experimental/cgi-bin/hello2.c index 698d32d8f8..81de6853ca 100644 --- a/src/experimental/cgi-bin/hello2.c +++ b/src/experimental/cgi-bin/hello2.c @@ -12,7 +12,6 @@ #include "gnc-book.h" #include "gnc-engine.h" -#include "Group.h" #include "io-gncxml.h" #include "Query.h" @@ -22,7 +21,7 @@ main (int argc, char *argv[]) int fake_argc =1; char * fake_argv[] = {"hello2", 0}; GNCBook *book; - AccountGroup *grp; + Account *root; Query *q, *qq; GList *split_list, *sl2, *node; Split *s; @@ -54,12 +53,12 @@ main (int argc, char *argv[]) goto bookerrexit; } - /* the grp pointer points to our local cache of the data */ - grp = gnc_book_get_group (book); + /* the root pointer points to our local cache of the data */ + root = gnc_book_get_root_account (book); /* build a query */ q = xaccMallocQuery (); - xaccQuerySetGroup (q, grp); + xaccQuerySetGroup (q, root); xaccQuerySetMaxSplits (q, 30); /* Get everything between some random dates */ @@ -81,7 +80,7 @@ main (int argc, char *argv[]) gncxml_write_query_to_buf(q, &bufp, &sz); qq = gncxml_read_query (bufp, sz); xaccQuerySetMaxSplits (qq, 30); - xaccQuerySetGroup (qq, grp); + xaccQuerySetGroup (qq, root); sl2 = xaccQueryGetSplits (qq); /* count number of splits */ diff --git a/src/experimental/cgi-bin/hello3.c b/src/experimental/cgi-bin/hello3.c index 296d7d9886..150c07007b 100644 --- a/src/experimental/cgi-bin/hello3.c +++ b/src/experimental/cgi-bin/hello3.c @@ -16,7 +16,6 @@ #include "gnc-book.h" #include "gnc-engine.h" -#include "Group.h" #include "io-gncxml.h" #include @@ -28,7 +27,7 @@ main (int argc, char *argv[]) int err, fake_argc =1; char * fake_argv[] = {"hello", 0}; GNCBook *book; - AccountGroup *grp; + Account *root; char *bufp; int rc, sz; @@ -44,8 +43,8 @@ main (int argc, char *argv[]) rc = gnc_book_load (book); if (!rc) goto bookerrexit; - /* the grp pointer points to our local cache of the data */ - grp = gnc_book_get_group (book); + /* the root pointer points to our local cache of the data */ + root = gnc_book_get_root_account (book); /* --------------------------------------------------- */ /* done with initialization, go into event loop */ @@ -65,7 +64,7 @@ main (int argc, char *argv[]) * but not the transactions/splits. */ if (!strcmp ("GET", request_method)) { - gncxml_write_group_to_buf(grp, &bufp, &sz); + gncxml_write_group_to_buf(root, &bufp, &sz); /* print the HTTP header */ printf("Content-type: text/gnc-xml\r\n" @@ -92,7 +91,7 @@ main (int argc, char *argv[]) /* conver the xml input into a gnucash query structure... */ q = gncxml_read_query (bufp, read_len); - xaccQuerySetGroup (q, grp); + xaccQuerySetGroup (q, root); /* hack -- limit to 30 splits ... */ xaccQuerySetMaxSplits (q, 30); diff --git a/src/gnome-utils/account-quickfill.c b/src/gnome-utils/account-quickfill.c index d6262e6336..9ee7adc065 100644 --- a/src/gnome-utils/account-quickfill.c +++ b/src/gnome-utils/account-quickfill.c @@ -54,7 +54,7 @@ typedef struct { gboolean load_list_store; GtkListStore *list_store; QofBook *book; - AccountGroup *group; + Account *root; gint listener; AccountBoolCB dont_add_cb; gpointer dont_add_data; @@ -105,7 +105,7 @@ shared_quickfill_find_accounts (GtkTreeModel *model, /* Splat the account name into the shared quickfill object */ -static gpointer +static void load_shared_qf_cb (Account *account, gpointer data) { QFB *qfb = data; @@ -115,11 +115,11 @@ load_shared_qf_cb (Account *account, gpointer data) if (qfb->dont_add_cb) { gboolean skip = (qfb->dont_add_cb) (account, qfb->dont_add_data); - if (skip) return NULL; + if (skip) return; } name = xaccAccountGetFullName (account); - if (NULL == name) return NULL; + if (NULL == name) return; gnc_quickfill_insert (qfb->qf, name, QUICKFILL_ALPHA); if (qfb->load_list_store) { gtk_list_store_append (qfb->list_store, &iter); @@ -129,8 +129,6 @@ load_shared_qf_cb (Account *account, gpointer data) -1); } g_free(name); - - return NULL; } static void @@ -142,7 +140,7 @@ shared_quickfill_gconf_changed (GConfEntry *entry, gpointer user_data) gnc_quickfill_purge(qfb->qf); gtk_list_store_clear(qfb->list_store); qfb->load_list_store = TRUE; - xaccGroupForEachAccount (qfb->group, load_shared_qf_cb, qfb, TRUE); + gnc_account_foreach_descendant(qfb->root, load_shared_qf_cb, qfb); qfb->load_list_store = FALSE; } @@ -151,7 +149,7 @@ shared_quickfill_gconf_changed (GConfEntry *entry, gpointer user_data) * Essentially same loop as in gnc_load_xfer_cell() above. */ static QFB * -build_shared_quickfill (QofBook *book, AccountGroup *group, const char * key, +build_shared_quickfill (QofBook *book, Account *root, const char * key, AccountBoolCB cb, gpointer data) { QFB *qfb; @@ -159,7 +157,7 @@ build_shared_quickfill (QofBook *book, AccountGroup *group, const char * key, qfb = g_new0(QFB, 1); qfb->qf = gnc_quickfill_new (); qfb->book = book; - qfb->group = group; + qfb->root = root; qfb->listener = 0; qfb->dont_add_cb = cb; qfb->dont_add_data = data; @@ -171,7 +169,7 @@ build_shared_quickfill (QofBook *book, AccountGroup *group, const char * key, shared_quickfill_gconf_changed, qfb); - xaccGroupForEachAccount (group, load_shared_qf_cb, qfb, TRUE); + gnc_account_foreach_descendant(root, load_shared_qf_cb, qfb); qfb->load_list_store = FALSE; qfb->listener = @@ -183,36 +181,36 @@ build_shared_quickfill (QofBook *book, AccountGroup *group, const char * key, } QuickFill * -gnc_get_shared_account_name_quickfill (AccountGroup *group, +gnc_get_shared_account_name_quickfill (Account *root, const char * key, AccountBoolCB cb, gpointer cb_data) { QFB *qfb; QofBook *book; - book = xaccGroupGetBook (group); + book = gnc_account_get_book (root); qfb = qof_book_get_data (book, key); if (qfb) return qfb->qf; - qfb = build_shared_quickfill (book, group, key, cb, cb_data); + qfb = build_shared_quickfill (book, root, key, cb, cb_data); return qfb->qf; } GtkListStore * -gnc_get_shared_account_name_list_store (AccountGroup *group, +gnc_get_shared_account_name_list_store (Account *root, const char * key, AccountBoolCB cb, gpointer cb_data) { QFB *qfb; QofBook *book; - book = xaccGroupGetBook (group); + book = gnc_account_get_book (root); qfb = qof_book_get_data (book, key); if (qfb) return qfb->list_store; - qfb = build_shared_quickfill (book, group, key, cb, cb_data); + qfb = build_shared_quickfill (book, root, key, cb, cb_data); return qfb->list_store; } @@ -245,8 +243,8 @@ listen_for_account_events (QofEntity *entity, QofEventId event_type, ENTER("entity %p, event type %x, user data %p, ecent data %p", entity, event_type, user_data, event_data); - if (xaccAccountGetRoot(account) != qfb->group) { - LEAVE("root group mismatch"); + if (gnc_account_get_root(account) != qfb->root) { + LEAVE("root account mismatch"); return; } @@ -262,7 +260,7 @@ listen_for_account_events (QofEntity *entity, QofEventId event_type, /* Find the account (and all its descendants) in the model. The * full name of all these accounts has changed. */ - data.accounts = xaccAccountGetDescendants(account); + data.accounts = gnc_account_get_descendants(account); data.accounts = g_list_prepend(data.accounts, account); gtk_tree_model_foreach(GTK_TREE_MODEL(qfb->list_store), shared_quickfill_find_accounts, &data); @@ -313,7 +311,7 @@ listen_for_account_events (QofEntity *entity, QofEventId event_type, /* Remove from qf */ gnc_quickfill_purge(qfb->qf); - xaccGroupForEachAccount (qfb->group, load_shared_qf_cb, qfb, TRUE); + gnc_account_foreach_descendant(qfb->root, load_shared_qf_cb, qfb); /* Does the account exist in the model? */ data.accounts = g_list_append(NULL, account); diff --git a/src/gnome-utils/account-quickfill.h b/src/gnome-utils/account-quickfill.h index b5c46beffd..2108c6ef1f 100644 --- a/src/gnome-utils/account-quickfill.h +++ b/src/gnome-utils/account-quickfill.h @@ -43,7 +43,6 @@ #include #include "Account.h" -#include "Group.h" #include "QuickFill.h" typedef gboolean (*AccountBoolCB) (Account *, gpointer); @@ -57,7 +56,7 @@ typedef gboolean (*AccountBoolCB) (Account *, gpointer); * the quickfill. The 'cb_data' is passed to the callback. * * The quickfill is created only once; it is then stored with - * the QofBook that is the parent of the AccountGroup. It is + * the QofBook that is the parent of the root account. It is * automatically destroyed when the QofBook is destroyed. * * Multiple, distinct quickfills, for different uses, are allowed. @@ -69,12 +68,12 @@ typedef gboolean (*AccountBoolCB) (Account *, gpointer); * it). This code does not currently listen to account-destroy * events. */ -QuickFill * gnc_get_shared_account_name_quickfill (AccountGroup *group, +QuickFill * gnc_get_shared_account_name_quickfill (Account *root, const char * key, AccountBoolCB skip_cb, gpointer cb_data); GtkListStore * -gnc_get_shared_account_name_list_store (AccountGroup *group, +gnc_get_shared_account_name_list_store (Account *root, const char * key, AccountBoolCB cb, gpointer cb_data); diff --git a/src/gnome-utils/dialog-account.c b/src/gnome-utils/dialog-account.c index 9aba912e0b..14cbc82c5f 100644 --- a/src/gnome-utils/dialog-account.c +++ b/src/gnome-utils/dialog-account.c @@ -70,13 +70,13 @@ typedef enum typedef struct _AccountWindow { + QofBook *book; gboolean modal; GtkWidget *dialog; AccountDialogType dialog_type; GUID account; - Account *top_level_account; /* owned by the model */ Account *created_account; gchar **subaccount_names; @@ -161,7 +161,7 @@ aw_get_account (AccountWindow *aw) if (!aw) return NULL; - return xaccAccountLookup (&aw->account, gnc_get_current_book ()); + return xaccAccountLookup (&aw->account, aw->book); } static void @@ -246,7 +246,8 @@ gnc_account_to_ui(AccountWindow *aw) static gboolean -gnc_account_create_transfer_balance (Account *account, +gnc_account_create_transfer_balance (QofBook *book, + Account *account, Account *transfer, gnc_numeric balance, time_t date) @@ -263,7 +264,7 @@ gnc_account_create_transfer_balance (Account *account, xaccAccountBeginEdit (account); xaccAccountBeginEdit (transfer); - trans = xaccMallocTransaction (gnc_get_current_book ()); + trans = xaccMallocTransaction (book); xaccTransBeginEdit (trans); @@ -271,7 +272,7 @@ gnc_account_create_transfer_balance (Account *account, xaccTransSetDateSecs (trans, date); xaccTransSetDescription (trans, _("Opening Balance")); - split = xaccMallocSplit (gnc_get_current_book ()); + split = xaccMallocSplit (book); xaccTransAppendSplit (trans, split); xaccAccountInsertSplit (account, split); @@ -281,7 +282,7 @@ gnc_account_create_transfer_balance (Account *account, balance = gnc_numeric_neg (balance); - split = xaccMallocSplit (gnc_get_current_book ()); + split = xaccMallocSplit (book); xaccTransAppendSplit (trans, split); xaccAccountInsertSplit (transfer, split); @@ -383,18 +384,11 @@ gnc_ui_to_account(AccountWindow *aw) xaccAccountSetHidden (account, flag); parent_account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree)); - if (parent_account == aw->top_level_account) - parent_account = NULL; - if (parent_account != NULL) - { - xaccAccountBeginEdit (parent_account); - if (parent_account != xaccAccountGetParentAccount (account)) - xaccAccountInsertSubAccount (parent_account, account); - xaccAccountCommitEdit (parent_account); - } - else - xaccGroupInsertAccount (gnc_get_current_group (), account); + if (parent_account == NULL) + parent_account = gnc_get_current_root_account(); + if (parent_account != gnc_account_get_parent (account)) + gnc_account_append_child (parent_account, account); xaccAccountCommitEdit (account); @@ -417,8 +411,7 @@ gnc_ui_to_account(AccountWindow *aw) if (use_equity) { - if (!gnc_account_create_opening_balance (account, balance, date, - gnc_get_current_book ())) + if (!gnc_account_create_opening_balance (account, balance, date, aw->book)) { const char *message = _("Could not create opening balance."); gnc_error_dialog(aw->dialog, message); @@ -434,7 +427,7 @@ gnc_ui_to_account(AccountWindow *aw) return; } - gnc_account_create_transfer_balance (account, transfer, balance, date); + gnc_account_create_transfer_balance (aw->book, account, transfer, balance, date); } LEAVE(" "); } @@ -505,7 +498,7 @@ gnc_finish_ok (AccountWindow *aw) gnc_suspend_gui_refresh (); parent = aw_get_account (aw); - account = xaccMallocAccount (gnc_get_current_book ()); + account = xaccMallocAccount (aw->book); aw->account = *xaccAccountGetGUID (account); aw->type = xaccAccountGetType (parent); @@ -564,6 +557,7 @@ add_children_to_expander (GObject *object, GParamSpec *param_spec, gpointer data gtk_container_add (GTK_CONTAINER (expander), scrolled_window); gtk_widget_show_all (scrolled_window); } + g_list_free(children); } /* Check whether there are children needing a type adjustment because of a @@ -684,7 +678,7 @@ gnc_filter_parent_accounts (Account *account, gpointer data) if (aw_account == NULL) return FALSE; - if (account == aw->top_level_account) + if (gnc_account_is_root(account)) return TRUE; if (account == aw_account) @@ -700,14 +694,13 @@ gnc_filter_parent_accounts (Account *account, gpointer data) static gboolean gnc_common_ok (AccountWindow *aw) { - Account *account, *parent; - AccountGroup *group; + Account *root, *account, *parent; gnc_commodity * commodity; gchar *fullname, *fullname_parent; const gchar *name, *separator; ENTER("aw %p", aw); - group = gnc_get_current_group (); + root = gnc_book_get_root_account (aw->book); separator = gnc_get_account_separator_string(); @@ -724,12 +717,12 @@ gnc_common_ok (AccountWindow *aw) parent = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree)); if (parent == NULL) { - account = xaccGetAccountFromFullName(group, name); + account = gnc_account_lookup_full_name(root, name); } else { fullname_parent = xaccAccountGetFullName(parent); fullname = g_strconcat(fullname_parent, separator, name, NULL); - account = xaccGetAccountFromFullName(group, fullname); + account = gnc_account_lookup_full_name(root, fullname); g_free(fullname_parent); g_free(fullname); @@ -945,8 +938,6 @@ gnc_account_window_destroy_cb (GtkObject *object, gpointer data) gnc_unregister_gui_component (aw->component_id); - aw->top_level_account = NULL; - gnc_resume_gui_refresh (); if (aw->subaccount_names) { @@ -1232,7 +1223,6 @@ gnc_account_window_create(AccountWindow *aw) box = glade_xml_get_widget (xml, "parent_scroll"); - // group = gnc_book_get_group (gnc_get_current_book ()); aw->parent_tree = gnc_tree_view_account_new(TRUE); gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(aw->parent_tree)); gtk_widget_show(GTK_WIDGET(aw->parent_tree)); @@ -1302,13 +1292,9 @@ get_ui_fullname (AccountWindow *aw) if (!name || *name == '\0') name = _(""); - parent_account = NULL; - parent_account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT (aw->parent_tree)); - if (parent_account == aw->top_level_account) - parent_account = NULL; - if (parent_account) + if (!gnc_account_is_root(parent_account)) { char *parent_name; const gchar *separator; @@ -1421,7 +1407,8 @@ refresh_handler (GHashTable *changes, gpointer user_data) static AccountWindow * -gnc_ui_new_account_window_internal (Account *base_account, +gnc_ui_new_account_window_internal (QofBook *book, + Account *base_account, gchar **subaccount_names, GList *valid_types, gnc_commodity * default_commodity, @@ -1432,8 +1419,11 @@ gnc_ui_new_account_window_internal (Account *base_account, Account *account; GList *list; + g_return_val_if_fail(book, NULL); + aw = g_new0 (AccountWindow, 1); + aw->book = book; aw->modal = modal; aw->dialog_type = NEW_ACCOUNT; @@ -1441,7 +1431,7 @@ gnc_ui_new_account_window_internal (Account *base_account, for (list = valid_types; list; list = list->next) aw->valid_types |= (1 << GPOINTER_TO_INT (list->data)); - account = xaccMallocAccount (gnc_get_current_book ()); + account = xaccMallocAccount (book); aw->account = *xaccAccountGetGUID (account); if (base_account) { @@ -1504,21 +1494,20 @@ gnc_ui_new_account_window_internal (Account *base_account, static gchar ** -gnc_split_account_name (const char *in_name, Account **base_account) +gnc_split_account_name (QofBook *book, const char *in_name, Account **base_account) { - AccountGroup *group; - Account *account; + Account *root, *account; gchar **names, **ptr, **out_names; GList *list, *node; - group = gnc_get_current_group (); + root = gnc_book_get_root_account (book); + list = gnc_account_get_children(root); names = g_strsplit(in_name, gnc_get_account_separator_string(), -1); for (ptr = names; *ptr; ptr++) { /* Stop if there are no children at the current level. */ - if (group == NULL) + if (list == NULL) break; - list = xaccGroupGetAccountList (group); /* Look for the first name in the children. */ for (node = list; node; node = g_list_next(node)) { @@ -1535,11 +1524,14 @@ gnc_split_account_name (const char *in_name, Account **base_account) if (node == NULL) break; - group = xaccAccountGetChildren (account); + g_list_free(list); + list = gnc_account_get_children (account); } out_names = g_strdupv(ptr); g_strfreev(names); + if (list) + g_list_free(list); return out_names; } @@ -1567,6 +1559,7 @@ gnc_ui_new_accounts_from_name_with_defaults (const char *name, gnc_commodity * default_commodity, Account * parent) { + QofBook *book; AccountWindow *aw; Account *base_account = NULL; Account *created_account = NULL; @@ -1576,19 +1569,20 @@ gnc_ui_new_accounts_from_name_with_defaults (const char *name, ENTER("name %s, valid %p, commodity %p, account %p", name, valid_types, default_commodity, parent); + book = gnc_get_current_book(); if (!name || *name == '\0') { subaccount_names = NULL; base_account = NULL; } else - subaccount_names = gnc_split_account_name (name, &base_account); + subaccount_names = gnc_split_account_name (book, name, &base_account); if (parent != NULL) { base_account=parent; } - aw = gnc_ui_new_account_window_internal (base_account, subaccount_names, + aw = gnc_ui_new_account_window_internal (book, base_account, subaccount_names, valid_types, default_commodity, TRUE); @@ -1659,6 +1653,7 @@ gnc_ui_edit_account_window(Account *account) aw = g_new0 (AccountWindow, 1); + aw->book = gnc_account_get_book(account); aw->modal = FALSE; aw->dialog_type = EDIT_ACCOUNT; aw->account = *xaccAccountGetGUID (account); @@ -1675,9 +1670,9 @@ gnc_ui_edit_account_window(Account *account) gtk_widget_show_all (aw->dialog); gtk_widget_hide (aw->opening_balance_page); - parent = xaccAccountGetParentAccount (account); + parent = gnc_account_get_parent (account); if (parent == NULL) - parent = aw->top_level_account; + parent = account; /* must be at the root */ gtk_tree_view_collapse_all (aw->parent_tree); gnc_tree_view_account_set_selected_account ( @@ -1703,30 +1698,21 @@ gnc_ui_edit_account_window(Account *account) /* * opens up a window to create a new account * - * Args: group - not used + * Args: book - containing book for the new account + * parent - The initial parent for the new account (optional) */ void -gnc_ui_new_account_window (AccountGroup *this_is_not_used) +gnc_ui_new_account_window(QofBook *book, Account *parent) { - /* FIXME get_current_account went away. */ - gnc_ui_new_account_window_internal (NULL, NULL, NULL, NULL, FALSE); -} + g_return_if_fail(book != NULL); + if (parent && book) + g_return_if_fail(gnc_account_get_book(parent) == book); -/* - * opens up a window to create a new account - * - * Args: group - not used - * parent - The initial parent for the new account - */ -void -gnc_ui_new_account_window_with_default(AccountGroup *this_is_not_used, - Account * parent) -{ - gnc_ui_new_account_window_internal (parent, NULL, NULL, NULL, FALSE); + gnc_ui_new_account_window_internal (book, parent, NULL, NULL, NULL, FALSE); } void -gnc_ui_new_account_with_types( AccountGroup *unused, +gnc_ui_new_account_with_types( QofBook *book, GList *valid_types ) { gnc_ui_new_account_window_internal( NULL, NULL, valid_types, NULL, FALSE ); @@ -1798,7 +1784,6 @@ gnc_account_renumber_response_cb (GtkDialog *dialog, gint response, RenumberDialog *data) { - AccountGroup *group; GList *children, *tmp; gchar *str; gchar *prefix; @@ -1806,8 +1791,7 @@ gnc_account_renumber_response_cb (GtkDialog *dialog, if (response == GTK_RESPONSE_OK) { gtk_widget_hide(data->dialog); - group = xaccAccountGetChildren(data->parent); - children = xaccGroupGetAccountListSorted(group); + children = gnc_account_get_children(data->parent); prefix = gtk_editable_get_chars(GTK_EDITABLE(data->prefix), 0, -1); interval = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(data->interval)); @@ -1820,6 +1804,7 @@ gnc_account_renumber_response_cb (GtkDialog *dialog, g_free(str); } gnc_unset_busy_cursor (NULL); + g_list_free(children); } gtk_widget_destroy(data->dialog); @@ -1831,14 +1816,12 @@ gnc_account_renumber_create_dialog (GtkWidget *window, Account *account) { RenumberDialog *data; GladeXML *xml; - AccountGroup *children; GtkWidget *widget; gchar *string; data = g_new(RenumberDialog, 1); data->parent = account; - children = xaccAccountGetChildren(account); - data->num_children = xaccGroupGetNumAccounts(children); + data->num_children = gnc_account_n_children(account); xml = gnc_glade_xml_new ("account.glade", "Renumber Accounts"); data->dialog = glade_xml_get_widget (xml, "Renumber Accounts"); diff --git a/src/gnome-utils/dialog-account.h b/src/gnome-utils/dialog-account.h index ba77fc7a35..78b3015c76 100644 --- a/src/gnome-utils/dialog-account.h +++ b/src/gnome-utils/dialog-account.h @@ -25,7 +25,6 @@ #define DIALOG_ACCOUNT_H #include "Account.h" -#include "Group.h" /** @addtogroup GUI @{ */ @@ -52,28 +51,24 @@ void gnc_ui_edit_account_window (Account *account); -/** Disply a window for creating a new account - * - * @param group This parameter is not used. - */ -void gnc_ui_new_account_window (AccountGroup *group); - - /** Disply a window for creating a new account. This function will * also initially set the parent account of the new account to what * the caller specified. The user is free, however, to choose any * parent account they wish. * - * @param group This parameter is not used. + * @param book The book in which the new account should be created. + * This is a required argument. * - * @param parent The initially selected parent account. + * @param parent The initially selected parent account. This + * argument is optional, but if supplied must be an account contained + * in the specified book. */ -void gnc_ui_new_account_window_with_default (AccountGroup *group, - Account * parent); +void gnc_ui_new_account_window (QofBook *book, Account *parent); /** Disply a window for creating a new account. This function will - * restrict the available account type values to the list specified by the caller. + * restrict the available account type values to the list specified + * by the caller. * * @param unused This parameter is not used. * @@ -81,7 +76,7 @@ void gnc_ui_new_account_window_with_default (AccountGroup *group, * which are allowed to be created. The calling function is * responsible for freeing this list. */ -void gnc_ui_new_account_with_types (AccountGroup *unused, +void gnc_ui_new_account_with_types (QofBook *book, GList *valid_types); /** @} */ diff --git a/src/gnome-utils/dialog-transfer.c b/src/gnome-utils/dialog-transfer.c index 3dad1c37b2..17f3535172 100644 --- a/src/gnome-utils/dialog-transfer.c +++ b/src/gnome-utils/dialog-transfer.c @@ -1868,7 +1868,7 @@ gnc_xfer_dialog (GtkWidget * parent, Account * initial) xferData->transaction_cb = NULL; if (initial) { - book = xaccAccountGetBook (initial); + book = gnc_account_get_book (initial); } else { book = gnc_get_current_book (); } diff --git a/src/gnome-utils/gnc-account-sel.c b/src/gnome-utils/gnc-account-sel.c index f797fd9c45..72a91321fe 100644 --- a/src/gnome-utils/gnc-account-sel.c +++ b/src/gnome-utils/gnc-account-sel.c @@ -171,7 +171,7 @@ void gas_populate_list( GNCAccountSel *gas ) { account_filter_data atnd; - AccountGroup *ag; + Account *root; Account *acc; GtkTreeIter iter; GtkEntry *entry; @@ -183,8 +183,8 @@ gas_populate_list( GNCAccountSel *gas ) currentSel = gtk_editable_get_chars( GTK_EDITABLE(entry), 0, -1 ); - ag = gnc_book_get_group( gnc_get_current_book() ); - accts = (GList*)xaccGroupGetSubAccountsSorted( ag ); + root = gnc_book_get_root_account( gnc_get_current_book() ); + accts = gnc_account_get_descendants_sorted( root ); filteredAccts = NULL; atnd.gas = gas; @@ -404,7 +404,7 @@ gas_new_account_click( GtkButton *b, gpointer ud ) gnc_ui_new_accounts_from_name_window_with_types ( NULL, gas->acctTypeFilters ); else - gnc_ui_new_account_with_types( NULL, gas->acctTypeFilters ); + gnc_ui_new_account_with_types( gnc_get_current_book(), gas->acctTypeFilters ); } gint @@ -442,7 +442,7 @@ gnc_account_sel_purge_account( GNCAccountSel *gas, while (acc) { if (acc == target) break; - acc = xaccAccountGetParentAccount(acc); + acc = gnc_account_get_parent(acc); } if (acc == target) diff --git a/src/gnome-utils/gnc-file.c b/src/gnome-utils/gnc-file.c index edbca8a875..f4a6edb23d 100644 --- a/src/gnome-utils/gnc-file.c +++ b/src/gnome-utils/gnc-file.c @@ -744,7 +744,7 @@ gnc_post_file_open (const char * filename) if (!uh_oh) { - AccountGroup *new_group; + Account *new_root; char * logpath = xaccResolveFilePath(newfile); PINFO ("logpath=%s", logpath ? logpath : "(null)"); @@ -776,12 +776,12 @@ gnc_post_file_open (const char * filename) uh_oh = show_session_error (io_err, newfile, GNC_FILE_DIALOG_OPEN); - new_group = gnc_book_get_group (qof_session_get_book (new_session)); - if (uh_oh) new_group = NULL; + new_root = gnc_book_get_root_account (qof_session_get_book (new_session)); + if (uh_oh) new_root = NULL; /* Umm, came up empty-handed, but no error: * The backend forgot to set an error. So make one up. */ - if (!uh_oh && !new_group) + if (!uh_oh && !new_root) { uh_oh = show_session_error (ERR_BACKEND_MISC, newfile, GNC_FILE_DIALOG_OPEN); @@ -797,11 +797,11 @@ gnc_post_file_open (const char * filename) qof_session_destroy (new_session); xaccLogEnable(); - /* well, no matter what, I think it's a good idea to have a - * topgroup around. For example, early in the gnucash startup + /* well, no matter what, I think it's a good idea to have a root + * account around. For example, early in the gnucash startup * sequence, the user opens a file; if this open fails for any - * reason, we don't want to leave them high & dry without a - * topgroup, because if the user continues, then bad things will + * reason, we don't want to leave them high & dry without a root + * account, because if the user continues, then bad things will * happen. */ gnc_get_current_session (); diff --git a/src/gnome-utils/gnc-html.c b/src/gnome-utils/gnc-html.c index a5392c89d9..6960cfcaa4 100644 --- a/src/gnome-utils/gnc-html.c +++ b/src/gnome-utils/gnc-html.c @@ -43,7 +43,6 @@ #include #include "Account.h" -#include "Group.h" #include "print-session.h" #include "gnc-engine.h" #include "gnc-gui-query.h" diff --git a/src/gnome-utils/gnc-tree-model-account.c b/src/gnome-utils/gnc-tree-model-account.c index 60c55f609a..e356402647 100644 --- a/src/gnome-utils/gnc-tree-model-account.c +++ b/src/gnome-utils/gnc-tree-model-account.c @@ -32,7 +32,6 @@ #include "gnc-tree-model-account.h" #include "gnc-component-manager.h" #include "Account.h" -#include "Group.h" #include "gnc-accounting-period.h" #include "gnc-commodity.h" #include "gnc-gconf-utils.h" @@ -84,10 +83,6 @@ static gboolean gnc_tree_model_account_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child); -/** Helper Functions ****************************************************/ -static void gnc_tree_model_account_set_toplevel (GncTreeModelAccount *model, - Account *toplevel); - /** Component Manager Callback ******************************************/ static void gnc_tree_model_account_event_handler (QofEntity *entity, QofEventId event_type, @@ -98,8 +93,7 @@ static void gnc_tree_model_account_event_handler (QofEntity *entity, typedef struct GncTreeModelAccountPrivate { QofBook *book; - AccountGroup *root; - Account *toplevel; + Account *root; gint event_handler_id; const gchar *negative_color; } GncTreeModelAccountPrivate; @@ -208,7 +202,6 @@ gnc_tree_model_account_init (GncTreeModelAccount *model) priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); priv->book = NULL; priv->root = NULL; - priv->toplevel = NULL; priv->negative_color = red ? "red" : "black"; gnc_gconf_general_register_cb(KEY_NEGATIVE_IN_RED, @@ -275,18 +268,18 @@ gnc_tree_model_account_dispose (GObject *object) /************************************************************/ GtkTreeModel * -gnc_tree_model_account_new (AccountGroup *group) +gnc_tree_model_account_new (Account *root) { GncTreeModelAccount *model; GncTreeModelAccountPrivate *priv; const GList *item; - ENTER("group %p", group); + ENTER("root %p", root); item = gnc_gobject_tracking_get_list(GNC_TREE_MODEL_ACCOUNT_NAME); for ( ; item; item = g_list_next(item)) { model = (GncTreeModelAccount *)item->data; priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); - if (priv->root == group) { + if (priv->root == root) { g_object_ref(G_OBJECT(model)); LEAVE("returning existing model %p", model); return GTK_TREE_MODEL(model); @@ -298,14 +291,7 @@ gnc_tree_model_account_new (AccountGroup *group) priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); priv->book = gnc_get_current_book(); - priv->root = group; - - { - Account *account; - - account = xaccMallocAccount(priv->book); - gnc_tree_model_account_set_toplevel (model, account); - } + priv->root = root; priv->event_handler_id = qof_event_register_handler ((QofEventHandler)gnc_tree_model_account_event_handler, model); @@ -441,9 +427,8 @@ gnc_tree_model_account_get_iter (GtkTreeModel *tree_model, { GncTreeModelAccountPrivate *priv; GncTreeModelAccount *model; - Account *account = NULL; - AccountGroup *group = NULL, *children; - gint i = 0, *indices; + Account *account, *parent; + gint i, *indices; { gchar *path_string = gtk_tree_path_to_string(path); @@ -454,55 +439,36 @@ gnc_tree_model_account_get_iter (GtkTreeModel *tree_model, model = GNC_TREE_MODEL_ACCOUNT (tree_model); priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); - if (priv->toplevel != NULL) { - if (gtk_tree_path_get_depth (path) > 1) { - i++; - } else { - - iter->user_data = priv->toplevel; - iter->user_data2 = NULL; - iter->user_data3 = GINT_TO_POINTER (0); - iter->stamp = model->stamp; - - LEAVE("iter (1) %s", iter_to_string(iter)); - return TRUE; - } - } - if (priv->root == NULL) { - LEAVE("failed (2)"); + if (gtk_tree_path_get_depth (path) <= 0) { + LEAVE("bad depth"); return FALSE; } - children = priv->root; - indices = gtk_tree_path_get_indices (path); - for (; i < gtk_tree_path_get_depth (path); i++) { - group = children; - if (indices[i] >= xaccGroupGetNumAccounts (group)) { - iter->stamp = 0; + if (indices[0] != 0) { + LEAVE("bad root index"); + return FALSE; + } - LEAVE("failed (3)"); + parent = NULL; + account = priv->root; + for (i = 1; i < gtk_tree_path_get_depth (path); i++) { + parent = account; + account = gnc_account_nth_child(parent, indices[i]); + if (account == NULL) { + iter->stamp = 0; + LEAVE("bad index"); return FALSE; } - - account = xaccGroupGetAccount (group, indices[i]); - children = xaccAccountGetChildren (account); - } - - if (account == NULL || group == NULL) { - iter->stamp = 0; - - LEAVE("failed (4)"); - return FALSE; } iter->stamp = model->stamp; iter->user_data = account; - iter->user_data2 = group; + iter->user_data2 = parent; iter->user_data3 = GINT_TO_POINTER (indices[i - 1]); - LEAVE("iter (5) %s", iter_to_string(iter)); + LEAVE("iter %s", iter_to_string(iter)); return TRUE; } @@ -512,11 +478,9 @@ gnc_tree_model_account_get_path (GtkTreeModel *tree_model, { GncTreeModelAccount *model = GNC_TREE_MODEL_ACCOUNT (tree_model); GncTreeModelAccountPrivate *priv; - Account *account; - AccountGroup *group; + Account *account, *parent; GtkTreePath *path; gint i; - gboolean found, finished = FALSE; ENTER("model %p, iter %s", model, iter_to_string(iter)); g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), NULL); @@ -531,49 +495,23 @@ gnc_tree_model_account_get_path (GtkTreeModel *tree_model, } account = (Account *) iter->user_data; - group = (AccountGroup *) iter->user_data2; + parent = (Account *) iter->user_data2; path = gtk_tree_path_new (); - - if (priv->toplevel != NULL) { - if (account == priv->toplevel) { - gtk_tree_path_append_index (path, 0); - - { - gchar *path_string = gtk_tree_path_to_string(path); - LEAVE("path (2) %s", path_string); - g_free(path_string); - } - return path; - } - } - - do { - found = FALSE; - for (i = 0; i < xaccGroupGetNumAccounts (group); i++) { - if (xaccGroupGetAccount (group, i) == account) { - found = TRUE; - if (group == priv->root) - finished = TRUE; - break; - } - } - - if (!found) { + while (parent) { + i = gnc_account_child_index(parent, account); + if (i == -1) { gtk_tree_path_free (path); LEAVE("failed (3)"); return NULL; } - gtk_tree_path_prepend_index (path, i); + account = parent; + parent = gnc_account_get_parent(account); + }; - account = xaccAccountGetParentAccount (account); - group = xaccAccountGetParent (account); - } while (!finished); - - if (priv->toplevel != NULL) { - gtk_tree_path_prepend_index (path, 0); - } + /* Add the root node. */ + gtk_tree_path_prepend_index (path, 0); { gchar *path_string = gtk_tree_path_to_string(path); @@ -608,7 +546,7 @@ gnc_tree_model_account_compute_period_balance(GncTreeModelAccount *model, gnc_numeric b3; priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); - if (acct == priv->toplevel) + if (acct == priv->root) return g_strdup(""); t1 = gnc_accounting_period_fiscal_start(); @@ -652,7 +590,7 @@ gnc_tree_model_account_get_value (GtkTreeModel *tree_model, switch (column) { case GNC_TREE_MODEL_ACCOUNT_COL_NAME: g_value_init (value, G_TYPE_STRING); - if (account == priv->toplevel) + if (account == priv->root) g_value_set_string (value, _("New top level account")); else g_value_set_string (value, xaccAccountGetName (account)); @@ -850,8 +788,7 @@ gnc_tree_model_account_iter_next (GtkTreeModel *tree_model, { GncTreeModelAccount *model = GNC_TREE_MODEL_ACCOUNT (tree_model); GncTreeModelAccountPrivate *priv; - Account *account; - AccountGroup *group; + Account *account, *parent; gint i; ENTER("model %p, iter %s", tree_model, iter_to_string(iter)); @@ -861,23 +798,17 @@ gnc_tree_model_account_iter_next (GtkTreeModel *tree_model, g_return_val_if_fail (iter->stamp == model->stamp, FALSE); priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); - if (iter->user_data == priv->toplevel) { - iter->stamp = 0; - LEAVE("failed (1)"); - return FALSE; - } - group = (AccountGroup *) iter->user_data2; - i = GPOINTER_TO_INT (iter->user_data3); - - if (i > xaccGroupGetNumAccounts (group) - 2) { - iter->stamp = 0; - LEAVE("failed (2)"); - return FALSE; + parent = (Account *) iter->user_data2; + if (parent == NULL) { + /* This is the root. There is no next. */ + LEAVE("at root"); + return FALSE; } - account = xaccGroupGetAccount (group, i + 1); - + /* Get the *next* sibling account. */ + i = GPOINTER_TO_INT (iter->user_data3); + account = gnc_account_nth_child (parent, i + 1); if (account == NULL) { iter->stamp = 0; LEAVE("failed (3)"); @@ -885,7 +816,7 @@ gnc_tree_model_account_iter_next (GtkTreeModel *tree_model, } iter->user_data = account; - iter->user_data2 = group; + iter->user_data2 = parent; iter->user_data3 = GINT_TO_POINTER (i + 1); LEAVE("iter %s", iter_to_string(iter)); @@ -895,84 +826,51 @@ gnc_tree_model_account_iter_next (GtkTreeModel *tree_model, static gboolean gnc_tree_model_account_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, - GtkTreeIter *parent) + GtkTreeIter *parent_iter) { GncTreeModelAccountPrivate *priv; GncTreeModelAccount *model; - Account *account; - AccountGroup *group; + Account *account, *parent; - if (parent) { - ENTER("model %p, iter %p (to be filed in), parent %s", - tree_model, iter, iter_to_string(parent)); + if (parent_iter) { + ENTER("model %p, iter %p (to be filed in), parent_iter %s", + tree_model, iter, iter_to_string(parent_iter)); } else { - ENTER("model %p, iter %p (to be filed in), parent (null)", tree_model, iter); + ENTER("model %p, iter %p (to be filed in), parent_iter (null)", tree_model, iter); } g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (tree_model), FALSE); model = GNC_TREE_MODEL_ACCOUNT (tree_model); priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); - if (priv->toplevel != NULL) { - if (parent == NULL) { - iter->user_data = priv->toplevel; - iter->user_data2 = NULL; - iter->user_data3 = GINT_TO_POINTER (0); - iter->stamp = model->stamp; - LEAVE("iter (1) %s", iter_to_string(iter)); - return TRUE; - } else if (parent->user_data == priv->toplevel) { - parent = NULL; - } - } - - if (priv->root == NULL || - xaccGroupGetNumAccounts (priv->root) == 0) { + if (priv->root == NULL) { iter->stamp = 0; - LEAVE("failed (either no group or group has no accounts)"); + LEAVE("failed (no root)"); return FALSE; } - if (parent == NULL) { - account = xaccGroupGetAccount (priv->root, 0); - - if (account == NULL) { - iter->stamp = 0; - LEAVE("failed (couldn't get account from group)"); - return FALSE; - } - - iter->user_data = account; - iter->user_data2 = priv->root; - iter->user_data3 = GINT_TO_POINTER (0); - iter->stamp = model->stamp; - LEAVE("iter (2) %s", iter_to_string(iter)); - return TRUE; - } - - g_return_val_if_fail (parent != NULL, FALSE); - g_return_val_if_fail (parent->user_data != NULL, FALSE); - g_return_val_if_fail (parent->stamp == model->stamp, FALSE); - - group = xaccAccountGetChildren ((Account *) parent->user_data); - - if (group == NULL || xaccGroupGetNumAccounts (group) == 0) { - iter->stamp = 0; - LEAVE("failed (children group was %s)", - group ? "empty" : "null"); - return FALSE; + /* Special case when no parent supplied. */ + if (!parent_iter) { + iter->user_data = priv->root; + iter->user_data2 = NULL; + iter->user_data3 = GINT_TO_POINTER (0); + iter->stamp = model->stamp; + LEAVE("iter (3) %s", iter_to_string(iter)); + return TRUE; } - account = xaccGroupGetAccount (group, 0); - + g_return_val_if_fail (parent_iter->user_data != NULL, FALSE); + g_return_val_if_fail (parent_iter->stamp == model->stamp, FALSE); + parent = (Account *)parent_iter->user_data; + account = gnc_account_nth_child (parent, 0); if (account == NULL) { iter->stamp = 0; - LEAVE("failed (group's account is null)"); + LEAVE("failed (child account is null)"); return FALSE; } iter->user_data = account; - iter->user_data2 = group; + iter->user_data2 = parent; iter->user_data3 = GINT_TO_POINTER (0); iter->stamp = model->stamp; LEAVE("iter (3) %s", iter_to_string(iter)); @@ -985,7 +883,7 @@ gnc_tree_model_account_iter_has_child (GtkTreeModel *tree_model, { GncTreeModelAccount *model; GncTreeModelAccountPrivate *priv; - AccountGroup *group; + Account *account; ENTER("model %p, iter %s", tree_model, iter_to_string(iter)); g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (tree_model), FALSE); @@ -997,19 +895,14 @@ gnc_tree_model_account_iter_has_child (GtkTreeModel *tree_model, g_return_val_if_fail (iter->user_data != NULL, FALSE); g_return_val_if_fail (iter->stamp == model->stamp, FALSE); - if (iter->user_data == priv->toplevel) { - group = priv->root; - } else { - group = xaccAccountGetChildren ((Account *) iter->user_data); - } - - if (group == NULL || xaccGroupGetNumAccounts (group) == 0) { - LEAVE("no"); - return FALSE; + account = (Account *) iter->user_data; + if (gnc_account_n_children(account) > 0) { + LEAVE("yes"); + return TRUE; } - LEAVE("yes"); - return TRUE; + LEAVE("no"); + return FALSE; } static int @@ -1018,7 +911,7 @@ gnc_tree_model_account_iter_n_children (GtkTreeModel *tree_model, { GncTreeModelAccount *model; GncTreeModelAccountPrivate *priv; - AccountGroup *group; + gint num; ENTER("model %p, iter %s", tree_model, iter_to_string(iter)); g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (tree_model), FALSE); @@ -1027,50 +920,40 @@ gnc_tree_model_account_iter_n_children (GtkTreeModel *tree_model, priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); if (iter == NULL) { - if (priv->toplevel != NULL) { - LEAVE("count is 1"); - return 1; - } else { - LEAVE("count is %d", xaccGroupGetNumAccounts (priv->root)); - return xaccGroupGetNumAccounts (priv->root); - } + num = gnc_account_n_children(priv->root); + LEAVE("count is %d", num); + return num; } g_return_val_if_fail (iter != NULL, FALSE); g_return_val_if_fail (iter->user_data != NULL, FALSE); g_return_val_if_fail (iter->stamp == model->stamp, FALSE); - if (priv->toplevel == iter->user_data) { - group = priv->root; - } else { - group = xaccAccountGetChildren ((Account *) iter->user_data); - } - - LEAVE("count is %d", xaccGroupGetNumAccounts (group)); - return xaccGroupGetNumAccounts (group); + num = gnc_account_n_children(iter->user_data); + LEAVE("count is %d", num); + return num; } static gboolean gnc_tree_model_account_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter, - GtkTreeIter *parent, + GtkTreeIter *parent_iter, int n) { GncTreeModelAccount *model; GncTreeModelAccountPrivate *priv; - Account *account; - AccountGroup *group; + Account *account, *parent; - if (parent) { + if (parent_iter) { gchar *parent_string; - parent_string = strdup(iter_to_string(parent)); - ENTER("model %p, iter %s, parent %s, n %d", + parent_string = strdup(iter_to_string(parent_iter)); + ENTER("model %p, iter %s, parent_iter %s, n %d", tree_model, iter_to_string(iter), parent_string, n); g_free(parent_string); } else { - ENTER("model %p, iter %s, parent (null), n %d", + ENTER("model %p, iter %s, parent_iter (null), n %d", tree_model, iter_to_string(iter), n); } g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (tree_model), FALSE); @@ -1078,66 +961,37 @@ gnc_tree_model_account_iter_nth_child (GtkTreeModel *tree_model, model = GNC_TREE_MODEL_ACCOUNT (tree_model); priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); - if (parent == NULL) { - if (priv->toplevel != NULL) { - if (n > 0) { - iter->stamp = 0; - LEAVE("failed (1)"); - return FALSE; - } else { - iter->user_data = priv->toplevel; - iter->user_data2 = NULL; - iter->user_data3 = GINT_TO_POINTER (0); - iter->stamp = model->stamp; - LEAVE("iter (1) %s", iter_to_string(iter)); - return TRUE; - } - } - - account = xaccGroupGetAccount (priv->root, n); - - if (account == NULL) { - iter->stamp = 0; - LEAVE("failed (2)"); - return FALSE; - } - - iter->user_data = account; - iter->user_data2 = priv->root; - iter->user_data3 = GINT_TO_POINTER (n); - iter->stamp = model->stamp; - LEAVE("iter (2) %s", iter_to_string(iter)); - return TRUE; + /* Special case when no parent supplied. */ + if (!parent_iter) { + if (n != 0) { + LEAVE("bad root index"); + return FALSE; + } + + iter->user_data = priv->root; + iter->user_data2 = NULL; + iter->user_data3 = GINT_TO_POINTER (0); + iter->stamp = model->stamp; + LEAVE("root %s", iter_to_string(iter)); + return TRUE; } - g_return_val_if_fail (parent->user_data != NULL, FALSE); - g_return_val_if_fail (parent->stamp == model->stamp, FALSE); - - if (priv->toplevel == parent->user_data) { - group = priv->root; - } else { - group = xaccAccountGetChildren ((Account *) parent->user_data); - } + g_return_val_if_fail (parent_iter->user_data != NULL, FALSE); + g_return_val_if_fail (parent_iter->stamp == model->stamp, FALSE); + parent = (Account *)parent_iter->user_data; + account = gnc_account_nth_child(parent, n); - if (group == NULL || xaccGroupGetNumAccounts (group) <= n) { - iter->stamp = 0; - LEAVE("failed (3)"); - return FALSE; - } - - account = xaccGroupGetAccount (group, n); - if (account == NULL) { iter->stamp = 0; - LEAVE("failed (4)"); + LEAVE("failed (2)"); return FALSE; } iter->user_data = account; - iter->user_data2 = group; + iter->user_data2 = parent; iter->user_data3 = GINT_TO_POINTER (n); iter->stamp = model->stamp; - LEAVE("iter (3) %s", iter_to_string(iter)); + LEAVE("iter (2) %s", iter_to_string(iter)); return TRUE; } @@ -1148,8 +1002,7 @@ gnc_tree_model_account_iter_parent (GtkTreeModel *tree_model, { GncTreeModelAccount *model; GncTreeModelAccountPrivate *priv; - Account *account; - AccountGroup *group; + Account *account, *parent; gint i; if (child) { @@ -1174,149 +1027,30 @@ gnc_tree_model_account_iter_parent (GtkTreeModel *tree_model, g_return_val_if_fail (child->stamp == model->stamp, FALSE); account = (Account *) child->user_data; - - if (account == priv->toplevel) { + account = gnc_account_get_parent(account); + if (account == NULL) { + /* Can't go up from the root node */ iter->stamp = 0; LEAVE("failed (1)"); return FALSE; } - account = xaccAccountGetParentAccount (account); - group = xaccAccountGetParent (account); - - if (account == NULL || group == NULL) { - if (priv->toplevel != NULL) { - iter->user_data = priv->toplevel; - iter->user_data2 = NULL; - iter->user_data3 = GINT_TO_POINTER (0); - iter->stamp = model->stamp; - LEAVE("iter (1) %s", iter_to_string(iter)); - return TRUE; - } else { - iter->stamp = 0; - LEAVE("failed (2)"); - return FALSE; - } - } - - for (i = 0; i < xaccGroupGetNumAccounts (group); i++) { - if (xaccGroupGetAccount (group, i) == account) { - iter->user_data = account; - iter->user_data2 = group; - iter->user_data3 = GINT_TO_POINTER (i); - iter->stamp = model->stamp; - LEAVE("iter (2) %s", iter_to_string(iter)); - return TRUE; - } - } - - if (priv->toplevel != NULL) { - iter->user_data = priv->toplevel; - iter->user_data2 = NULL; - iter->user_data3 = GINT_TO_POINTER (0); - iter->stamp = model->stamp; - LEAVE("iter (3) %s", iter_to_string(iter)); - return TRUE; - } - iter->stamp = 0; - LEAVE("failed (3)"); - return FALSE; -} - - -/************************************************************/ -/* Account Tree View Root Functions */ -/************************************************************/ - -static gpointer -account_row_inserted (Account *account, - gpointer data) -{ - GtkTreePath *path; - GtkTreeIter iter; - - ENTER("account %p (%s), model %p", - account, xaccAccountGetName(account), data); - if (!gnc_tree_model_account_get_iter_from_account - (GNC_TREE_MODEL_ACCOUNT (data), account, &iter)) - return NULL; - - path = gtk_tree_model_get_path (GTK_TREE_MODEL (data), &iter); - - gtk_tree_model_row_inserted (GTK_TREE_MODEL (data), path, &iter); - - gtk_tree_path_free (path); - - LEAVE(" "); - return NULL; -} - -/* - * Gets the top node of the model. This node is for a pseudo-account - * that lives above the main level accounts in the engine. - */ -Account * -gnc_tree_model_account_get_toplevel (GncTreeModelAccount *model) -{ - GncTreeModelAccountPrivate *priv; - - g_return_val_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model), NULL); - - priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); - return priv->toplevel; -} - -/* - * Add a new top node to the model. This node is for a pseudo-account - * that lives above the main level accounts in the engine. - */ -static void -gnc_tree_model_account_set_toplevel (GncTreeModelAccount *model, - Account *toplevel) -{ - GncTreeModelAccountPrivate *priv; - GtkTreePath *path; - gint i; - GtkTreeIter iter; - - ENTER("model %p, toplevel %p", model, toplevel); - g_return_if_fail (GNC_IS_TREE_MODEL_ACCOUNT (model)); - - priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); - DEBUG("old toplevel %p", priv->toplevel); - if (priv->toplevel != NULL) { - /* CAS: this can't happen because we only set toplevel on - * new tree models. */ - path = gtk_tree_path_new_first (); - gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path); - gtk_tree_path_free (path); + parent = gnc_account_get_parent(account); + if (parent == NULL) { + /* Now at the root. */ + i = 0; } else { - /* CAS: I think this is bogus for the same reason - we'll - * have no rows, so why are we emitting a bunch of - * "row_deleted" signals when no rows can exist? */ - path = gtk_tree_path_new_first (); - for (i = 0; i < xaccGroupGetNumAccounts (priv->root); i++) { - gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path); - } - gtk_tree_path_free (path); + i = gnc_account_child_index(parent, account); } - - DEBUG("set new toplevel %p", toplevel); - priv->toplevel = toplevel; - - if (priv->toplevel != NULL) { - path = gtk_tree_path_new_first (); - if (gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path)) - gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter); - gtk_tree_path_free (path); - } - - if (priv->root != NULL) { - xaccGroupForEachAccount (priv->root, account_row_inserted, model, TRUE); - } - LEAVE("new toplevel %p", priv->root); + iter->user_data = account; + iter->user_data2 = parent; + iter->user_data3 = GINT_TO_POINTER (i); + iter->stamp = model->stamp; + LEAVE("iter (2) %s", iter_to_string(iter)); + return TRUE; } + /************************************************************/ /* Account Tree View Filter Functions */ /************************************************************/ @@ -1348,8 +1082,7 @@ gnc_tree_model_account_get_iter_from_account (GncTreeModelAccount *model, GtkTreeIter *iter) { GncTreeModelAccountPrivate *priv; - AccountGroup *group; - gboolean found = FALSE; + Account *parent; gint i; ENTER("model %p, account %p, iter %p", model, account, iter); @@ -1361,32 +1094,24 @@ gnc_tree_model_account_get_iter_from_account (GncTreeModelAccount *model, iter->stamp = model->stamp; priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); - if (account == priv->toplevel) { + if (account == priv->root) { iter->user_data2 = NULL; iter->user_data3 = GINT_TO_POINTER (0); - LEAVE("Matched top level"); + LEAVE("Matched root"); return TRUE; } - if (priv->root != xaccAccountGetRoot (account)) { + if (priv->root != gnc_account_get_root (account)) { LEAVE("Root doesn't match"); return FALSE; } - group = xaccAccountGetParent (account); - DEBUG("Looking through %d accounts at this level", - xaccGroupGetNumAccounts (group)); - for (i = 0; i < xaccGroupGetNumAccounts (group); i++) { - if (xaccGroupGetAccount (group, i) == account) { - found = TRUE; - break; - } - } - - iter->user_data2 = group; + parent = gnc_account_get_parent(account); + i = gnc_account_child_index(parent, account); + iter->user_data2 = parent; iter->user_data3 = GINT_TO_POINTER (i); LEAVE("iter %s", iter_to_string(iter)); - return found; + return (i != -1); } /* @@ -1438,9 +1163,16 @@ propagate_change(GtkTreeModel *model, GtkTreePath *path, gint toggle_if_num) { GtkTreeIter iter; - /* Immediate parent */ - if (gtk_tree_path_up(path) && - gtk_tree_model_get_iter(model, &iter, path)) { + /* Already at the invisible root node? */ + if (!gtk_tree_path_up(path)) + return; + + /* Did we just move up to the invisible root node? */ + if (gtk_tree_path_get_depth(path) == 0) + return; + + /* Handle the immediate parent */ + if (gtk_tree_model_get_iter(model, &iter, path)) { gtk_tree_model_row_changed(model, path, &iter); if (gtk_tree_model_iter_n_children(model, &iter) == toggle_if_num) gtk_tree_model_row_has_child_toggled(model, path, &iter); @@ -1502,11 +1234,11 @@ gnc_tree_model_account_event_handler (QofEntity *entity, priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); account = GNC_ACCOUNT(entity); - if (xaccAccountGetBook(account) != priv->book) { + if (gnc_account_get_book(account) != priv->book) { LEAVE("not in this book"); return; } - if (xaccAccountGetRoot(account) != priv->root) { + if (gnc_account_get_root(account) != priv->root) { LEAVE("not in this model"); return; } @@ -1532,7 +1264,7 @@ gnc_tree_model_account_event_handler (QofEntity *entity, case QOF_EVENT_REMOVE: if (!ed) /* Required for a remove. */ break; - parent = ed->node ? GNC_ACCOUNT(ed->node) : priv->toplevel; + parent = ed->node ? GNC_ACCOUNT(ed->node) : priv->root; parent_name = ed->node ? xaccAccountGetName(parent) : "Root"; DEBUG("remove child %d of account %p (%s)", ed->idx, parent, parent_name); path = gnc_tree_model_account_get_path_from_account(model, parent); diff --git a/src/gnome-utils/gnc-tree-model-account.h b/src/gnome-utils/gnc-tree-model-account.h index 3fec08ff3a..5694ff2199 100644 --- a/src/gnome-utils/gnc-tree-model-account.h +++ b/src/gnome-utils/gnc-tree-model-account.h @@ -39,7 +39,7 @@ #include #include "gnc-tree-model.h" -#include "Group.h" +#include "Account.h" G_BEGIN_DECLS @@ -124,28 +124,13 @@ GType gnc_tree_model_account_get_type (void); * * @param group The account group to put at the top level of the tree * hierarchy. */ -GtkTreeModel *gnc_tree_model_account_new (AccountGroup *group); +GtkTreeModel *gnc_tree_model_account_new (Account *root); /** @} */ /** @name Account Tree Model Get/Set Functions @{ */ -/** This function returns the account associated with the top level - * pseudo-account. The gnucash engine does not have a single top - * level account (it has a list of top level accounts), but this code - * provides one so that it can be used with all parts of the gnucash - * gui. - * - * @internal This function should only be called from gnc-tree-view-account.c. - * - * @param account_view A pointer to an account tree view. - * - * @return The top-level pseudo-account. - */ -Account *gnc_tree_model_account_get_toplevel (GncTreeModelAccount *model); - - /** Convert a model/iter pair to a gnucash account. This routine should * only be called from an account tree view filter function. The * model and iter values will be provided as part of the call to the diff --git a/src/gnome-utils/gnc-tree-model.h b/src/gnome-utils/gnc-tree-model.h index b266bddd09..a4a357f91f 100644 --- a/src/gnome-utils/gnc-tree-model.h +++ b/src/gnome-utils/gnc-tree-model.h @@ -37,8 +37,6 @@ #include -#include "Group.h" - G_BEGIN_DECLS /* type macros */ diff --git a/src/gnome-utils/gnc-tree-view-account.c b/src/gnome-utils/gnc-tree-view-account.c index 6437abcea0..cd6f670546 100644 --- a/src/gnome-utils/gnc-tree-view-account.c +++ b/src/gnome-utils/gnc-tree-view-account.c @@ -38,7 +38,6 @@ #include "gnc-tree-view-account.h" #include "Account.h" -#include "Group.h" #include "gnc-accounting-period.h" #include "gnc-commodity.h" #include "gnc-component-manager.h" @@ -71,8 +70,6 @@ static gboolean gnc_tree_view_account_filter_helper (GtkTreeModel *model, GtkTreeIter *iter, gpointer data); -static Account *gtva_get_top_level_from_model (GtkTreeModel *s_model); - static void gtva_setup_column_renderer_edited_cb(GncTreeViewAccount *account_view, GtkTreeViewColumn *column, GtkCellRenderer *renderer, @@ -290,7 +287,7 @@ sort_by_string (GtkTreeModel *f_model, result = safe_utf8_collate(str1, str2); if (result != 0) return result; - return xaccAccountOrder(&account1, &account2); + return xaccAccountOrder(account1, account2); } static gint @@ -304,7 +301,7 @@ sort_by_code (GtkTreeModel *f_model, sort_cb_setup (f_model, f_iter_a, f_iter_b, &account_a, &account_b); /* Default ordering uses this column first. */ - return xaccAccountOrder(&account_a, &account_b); + return xaccAccountOrder(account_a, account_b); } static gint @@ -329,7 +326,7 @@ sort_by_xxx_value (xaccGetBalanceInCurrencyFn fn, result = gnc_numeric_compare(balance_a, balance_b); if (result != 0) return result; - return xaccAccountOrder(&account_a, &account_b); + return xaccAccountOrder(account_a, account_b); } static gint @@ -412,7 +409,7 @@ sort_by_placeholder (GtkTreeModel *f_model, return -1; else if (flag_a < flag_b) return 1; - return xaccAccountOrder(&account_a, &account_b); + return xaccAccountOrder(account_a, account_b); } static gint @@ -438,7 +435,7 @@ sort_by_xxx_period_value (GtkTreeModel *f_model, result = gnc_numeric_compare(b1, b2); if (result != 0) return result; - return xaccAccountOrder((const Account **)&acct1, (const Account **)&acct2); + return xaccAccountOrder(acct1, acct2); } static gint @@ -470,7 +467,7 @@ sort_by_total_period_value (GtkTreeModel *f_model, * model. */ GtkTreeView * -gnc_tree_view_account_new_with_group (AccountGroup *group, gboolean show_root) +gnc_tree_view_account_new_with_root (Account *root, gboolean show_root) { GncTreeView *view; GtkTreeModel *model, *f_model, *s_model; @@ -486,7 +483,7 @@ gnc_tree_view_account_new_with_group (AccountGroup *group, gboolean show_root) priv = GNC_TREE_VIEW_ACCOUNT_GET_PRIVATE(GNC_TREE_VIEW_ACCOUNT (view)); /* Create/get a pointer to the existing model for this set of books. */ - model = gnc_tree_model_account_new (group); + model = gnc_tree_model_account_new (root); /* Set up the view private filter layer on the common model. */ if (!show_root) @@ -683,10 +680,10 @@ gnc_tree_view_account_new_with_group (AccountGroup *group, gboolean show_root) GtkTreeView * gnc_tree_view_account_new (gboolean show_root) { - AccountGroup *group; + Account *root; - group = gnc_book_get_group (gnc_get_current_book ()); - return gnc_tree_view_account_new_with_group (group, show_root); + root = gnc_book_get_root_account (gnc_get_current_book ()); + return gnc_tree_view_account_new_with_root (root, show_root); } /************************************************************/ @@ -951,34 +948,6 @@ gnc_tree_view_account_filter_by_type_selection(Account* acct, gpointer data) /* Account Tree View Get/Set Functions */ /************************************************************/ -static Account * -gtva_get_top_level_from_model (GtkTreeModel *s_model) -{ - GtkTreeModel *model, *f_model; - - g_return_val_if_fail (GTK_TREE_MODEL_SORT (s_model), NULL); - - f_model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (s_model)); - model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (f_model)); - - return gnc_tree_model_account_get_toplevel (GNC_TREE_MODEL_ACCOUNT (model)); -} - -/* - * Return the account associated with the top level pseudo-account for - * the tree. - */ -Account * -gnc_tree_view_account_get_top_level (GncTreeViewAccount *view) -{ - GtkTreeModel *s_model; - - g_return_val_if_fail (GNC_IS_TREE_VIEW_ACCOUNT (view), NULL); - s_model = gtk_tree_view_get_model (GTK_TREE_VIEW (view)); - - return gtva_get_top_level_from_model (s_model); -} - /* * Retrieve the selected account from an account tree view. The * account tree must be in single selection mode. @@ -2015,8 +1984,8 @@ tree_restore_expanded_row (GncTreeViewAccount *view, QofBook *book; book = qof_session_get_book(gnc_get_current_session()); - account = xaccGetAccountFromFullName(xaccGetAccountGroup(book), - account_name); + account = gnc_account_lookup_full_name(gnc_book_get_root_account(book), + account_name); if (account) gnc_tree_view_account_expand_to_account(view, account); } @@ -2037,8 +2006,8 @@ tree_restore_selected_row (GncTreeViewAccount *view, QofBook *book; book = qof_session_get_book(gnc_get_current_session()); - account = xaccGetAccountFromFullName(xaccGetAccountGroup(book), - account_name); + account = gnc_account_lookup_full_name(gnc_book_get_root_account(book), + account_name); if (account) gnc_tree_view_account_set_selected_account(view, account); } @@ -2121,12 +2090,12 @@ gnc_tree_view_account_restore(GncTreeViewAccount *view, void gnc_tree_view_account_name_edited_cb(Account *account, GtkTreeViewColumn *col, const gchar *new_name) { - // check for accounts with the same name in our parent's group. + // check for accounts with the same name among our parent's children. // should probably factor this consistency check out to the account - // itself... or maybe the account group. + // itself.... { - AccountGroup *parent = xaccAccountGetParent(account); - Account *existing = xaccGetAccountFromName(parent, new_name); + Account *parent = gnc_account_get_parent(account); + Account *existing = gnc_account_lookup_name(parent, new_name); if (existing != NULL && existing != account) { PERR("account with the same name [%s] already exists.", new_name); diff --git a/src/gnome-utils/gnc-tree-view-account.h b/src/gnome-utils/gnc-tree-view-account.h index ff78b48f29..05d8aa5669 100644 --- a/src/gnome-utils/gnc-tree-view-account.h +++ b/src/gnome-utils/gnc-tree-view-account.h @@ -38,7 +38,6 @@ #include #include "gnc-tree-view.h" -#include "Group.h" #include "gnc-ui-util.h" #include "gnc-plugin-page.h" @@ -132,8 +131,8 @@ GType gnc_tree_view_account_get_type (void); * * @return A pointer to a new account tree view. */ -GtkTreeView *gnc_tree_view_account_new_with_group (AccountGroup *group, - gboolean show_root); +GtkTreeView *gnc_tree_view_account_new_with_root (Account *root, + gboolean show_root); /** Create a new account tree view. This view may or may not show a * pseudo top-level account. The gnucash engine does not have a @@ -339,24 +338,6 @@ gint gnc_tree_view_account_count_children (GncTreeViewAccount *view, -/** This function returns the account associated with the top level - * pseudo-account. The gnucash engine does not have a single top - * level account (it has a list of top level accounts), but this code - * provides one so that it can be used with all parts of the gnucash - * gui. - * - * @note It only makes sense to call this function when the account - * tree is created such that the "top level account" is visible. At - * the time this was written, only the "New/Edit Account" dialog does - * that. - * - * @param view A pointer to an account tree view. - * - * @return The top-level pseudo-account. - */ -Account * gnc_tree_view_account_get_top_level (GncTreeViewAccount *view); - - /** This function returns the account associated with the specified * path. This function is useful in selection callbacks on an * account tree widget. diff --git a/src/gnome-utils/window-main-summarybar.c b/src/gnome-utils/window-main-summarybar.c index 63865bc0b1..5b0c283264 100644 --- a/src/gnome-utils/window-main-summarybar.c +++ b/src/gnome-utils/window-main-summarybar.c @@ -29,7 +29,6 @@ #include #include "Account.h" -#include "Group.h" #include "gnc-accounting-period.h" #include "gnc-component-manager.h" #include "gnc-euro.h" @@ -120,14 +119,13 @@ gnc_ui_get_currency_accumulator(GList **list, gnc_commodity * currency, gint tot * @fixme Move this non-GUI code into the engine. **/ static void -gnc_ui_accounts_recurse (AccountGroup *group, GList **currency_list, +gnc_ui_accounts_recurse (Account *parent, GList **currency_list, GNCSummarybarOptions options) { gnc_numeric start_amount; gnc_numeric start_amount_default_currency; gnc_numeric end_amount; gnc_numeric end_amount_default_currency; - AccountGroup *children; GNCAccountType account_type; gnc_commodity * account_currency; gnc_commodity * euro_commodity; @@ -135,21 +133,20 @@ gnc_ui_accounts_recurse (AccountGroup *group, GList **currency_list, GNCCurrencyAcc *euro_accum = NULL; GNCCurrencyAcc *grand_total_accum = NULL; GNCCurrencyAcc *non_curr_accum = NULL; - GList *list; - GList *node; + GList *children, *node; gboolean non_currency = FALSE; Timespec end_timespec; Timespec start_timespec; + if (parent == NULL) return; - list = xaccGroupGetAccountList (group); - for (node = list; node; node = node->next) + children = gnc_account_get_children(parent); + for (node = children; node; node = g_list_next(node)) { Account *account = node->data; account_type = xaccAccountGetType(account); account_currency = xaccAccountGetCommodity(account); - children = xaccAccountGetChildren(account); if(options.grand_total) grand_total_accum = gnc_ui_get_currency_accumulator(currency_list, @@ -226,8 +223,7 @@ gnc_ui_accounts_recurse (AccountGroup *group, GList **currency_list, GNC_RND_ROUND); } - if (children != NULL) - gnc_ui_accounts_recurse(children, currency_list, options); + gnc_ui_accounts_recurse(account, currency_list, options); break; case ACCT_TYPE_INCOME: case ACCT_TYPE_EXPENSE: @@ -292,8 +288,7 @@ gnc_ui_accounts_recurse (AccountGroup *group, GList **currency_list, GNC_RND_ROUND); } - if (children != NULL) - gnc_ui_accounts_recurse(children, currency_list, options); + gnc_ui_accounts_recurse(account, currency_list, options); break; case ACCT_TYPE_EQUITY: /* no-op, see comments at top about summing assets */ @@ -303,6 +298,7 @@ gnc_ui_accounts_recurse (AccountGroup *group, GList **currency_list, break; } } + g_list_free(children); } static char* @@ -358,7 +354,7 @@ enum { static void gnc_main_window_summary_refresh (GNCMainSummary * summary) { - AccountGroup *group; + Account *root; char asset_string[256]; char profit_string[256]; GNCCurrencyAcc *currency_accum; @@ -387,8 +383,8 @@ gnc_main_window_summary_refresh (GNCMainSummary * summary) gnc_ui_get_currency_accumulator (¤cy_list, options.default_currency, TOTAL_SINGLE); - group = gnc_get_current_group (); - gnc_ui_accounts_recurse(group, ¤cy_list, options); + root = gnc_get_current_root_account (); + gnc_ui_accounts_recurse(root, ¤cy_list, options); { GtkTreeIter iter; diff --git a/src/gnome/dialog-commodities.c b/src/gnome/dialog-commodities.c index e485b1c93a..dbafe84343 100644 --- a/src/gnome/dialog-commodities.c +++ b/src/gnome/dialog-commodities.c @@ -113,7 +113,7 @@ remove_clicked (CommoditiesDialog *cd) if (commodity == NULL) return; - accounts = xaccGroupGetSubAccounts (xaccGetAccountGroup(cd->book)); + accounts = gnc_account_get_descendants (gnc_book_get_root_account(cd->book)); can_delete = TRUE; do_delete = FALSE; diff --git a/src/gnome/dialog-find-transactions.c b/src/gnome/dialog-find-transactions.c index 272b424202..1dee530ff3 100644 --- a/src/gnome/dialog-find-transactions.c +++ b/src/gnome/dialog-find-transactions.c @@ -141,8 +141,8 @@ gnc_ui_find_transactions_dialog_create(GNCLedgerDisplay * orig_ledg) /* In lieu of not "mis-using" some portion of the infrastructure by writing * a bunch of new code, we just filter out the accounts of the template - * transactions. While these are in a seperate AccountGroup just for this - * reason, the query engine makes no distinction between AccountGroups. + * transactions. While these are in a seperate Account trees just for this + * reason, the query engine makes no distinction between Account trees. * See Gnome Bug 86302. * -- jsled * @@ -152,15 +152,15 @@ gnc_ui_find_transactions_dialog_create(GNCLedgerDisplay * orig_ledg) * key in the KVP frame of the split. */ { - AccountGroup *tAG; - AccountList *al; + Account *tRoot; + GList *al; - tAG = gnc_book_get_template_group( gnc_get_current_book() ); - al = xaccGroupGetSubAccounts( tAG ); + tRoot = gnc_book_get_template_root( gnc_get_current_book() ); + al = gnc_account_get_descendants( tRoot ); xaccQueryAddAccountMatch( start_q, al, GUID_MATCH_NONE, QUERY_AND ); g_list_free (al); al = NULL; - tAG = NULL; + tRoot = NULL; } ftd->q = start_q; /* save this to destroy it later */ diff --git a/src/gnome/dialog-sxsincelast.c b/src/gnome/dialog-sxsincelast.c index 175b38a0b0..869e27628d 100644 --- a/src/gnome/dialog-sxsincelast.c +++ b/src/gnome/dialog-sxsincelast.c @@ -56,7 +56,6 @@ #include #include "Account.h" -#include "Group.h" #include "Query.h" #include "QueryNew.h" #include "SchedXaction.h" @@ -2736,22 +2735,21 @@ create_transactions_on(SchedXaction *sx, GList **creation_errors) { createData createUD; - AccountGroup *ag; - Account *acct; + Account *root, *acct; const char *id; if (tci) { g_assert(g_date_compare(gd, tci->date) == 0); } - ag = gnc_book_get_template_group( gnc_get_current_book () ); + root = gnc_book_get_template_root( gnc_get_current_book () ); id = guid_to_string( xaccSchedXactionGetGUID(sx) ); - if ( !(ag && id) ) { + if ( !(root && id) ) { return; } /* This looks strange but it's right. The account is named after the guid string. */ - acct = xaccGetAccountFromName( ag, id ); + acct = gnc_account_lookup_name( root, id ); if (!acct) { return; } @@ -2864,14 +2862,13 @@ _get_vars_helper(Transaction *txn, void *var_hash_data) void sxsl_get_sx_vars( SchedXaction *sx, GHashTable *var_hash ) { - AccountGroup *ag; - Account *acct; + Account *root, *acct; const char *id; - ag = gnc_book_get_template_group( gnc_get_current_book () ); + root = gnc_book_get_template_root( gnc_get_current_book () ); id = guid_to_string( xaccSchedXactionGetGUID(sx) ); /* Get account named after guid string. */ - acct = xaccGetAccountFromName( ag, id ); + acct = gnc_account_lookup_name( root, id ); xaccAccountForEachTransaction(acct, _get_vars_helper, var_hash); @@ -2972,17 +2969,16 @@ sxsincelast_tc_row_sel( GtkCTree *ct, /* Setup the query for the to-create register to only show the * transaction[s] associated with this lineitem. */ { - AccountGroup *ag; - Account *acct; + Account *root, *acct; Query *q; const gchar *sxGUIDstr; SplitRegister *sr; q = xaccMallocQuery(); xaccQuerySetBook( q, gnc_get_current_book() ); - ag = gnc_book_get_template_group( gnc_get_current_book() ); + root = gnc_book_get_template_root( gnc_get_current_book() ); sxGUIDstr = guid_to_string( xaccSchedXactionGetGUID( tci->parentTCT->sx ) ); - acct = xaccGetAccountFromName( ag, sxGUIDstr ); + acct = gnc_account_lookup_name( root, sxGUIDstr ); g_assert( acct != NULL ); xaccQueryAddSingleAccountMatch( q, acct, QUERY_AND ); diff --git a/src/gnome/druid-acct-period.c b/src/gnome/druid-acct-period.c index bdec3736b7..78eb009a05 100644 --- a/src/gnome/druid-acct-period.c +++ b/src/gnome/druid-acct-period.c @@ -29,7 +29,6 @@ #include "glib-compat.h" #include "FreqSpec.h" -#include "Group.h" #include "Period.h" #include "Query.h" #include "Scrub.h" @@ -280,7 +279,7 @@ show_book_details (AcctPeriodInfo *info) ntrans = get_num_xactions_before_date(currbook, gnc_timet_get_day_end_gdate (&info->closing_date)); - nacc = xaccGroupGetNumSubAccounts (xaccGetAccountGroup (currbook)); + nacc = gnc_account_n_descendants (gnc_book_get_root_account (currbook)); /* Display the book info */ period_text = diff --git a/src/gnome/druid-hierarchy.c b/src/gnome/druid-hierarchy.c index df9017383f..2d8af6c198 100644 --- a/src/gnome/druid-hierarchy.c +++ b/src/gnome/druid-hierarchy.c @@ -29,7 +29,6 @@ #include #include -#include "Group.h" #include "gnc-account-merge.h" #include "dialog-new-user.h" #include "dialog-utils.h" @@ -88,7 +87,7 @@ typedef struct { /** Map **/ GHashTable *balance_hash; - AccountGroup *our_final_group; + Account *our_account_tree; QofBook *temporary; gboolean account_list_added; @@ -487,7 +486,7 @@ categories_tree_selection_changed (GtkTreeSelection *selection, buffer = gtk_text_view_get_buffer(data->category_description); gtk_text_buffer_set_text(buffer, gea->long_description, -1); - tree_view = gnc_tree_view_account_new_with_group (gea->group, FALSE); + tree_view = gnc_tree_view_account_new_with_root (gea->root, FALSE); /* Override the normal fixed (user settable) sizing */ column = gtk_tree_view_get_column(GTK_TREE_VIEW(tree_view), 0); gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); @@ -549,13 +548,13 @@ clear_all_clicked (GtkButton *button, ************************************************************/ static void -delete_our_final_group (hierarchy_data *data) +delete_our_account_tree (hierarchy_data *data) { - if (data->our_final_group != NULL) + if (data->our_account_tree != NULL) { - xaccAccountGroupBeginEdit (data->our_final_group); - xaccAccountGroupDestroy (data->our_final_group); - data->our_final_group = NULL; + xaccAccountBeginEdit (data->our_account_tree); + xaccAccountDestroy (data->our_account_tree); + data->our_account_tree = NULL; } } @@ -573,27 +572,27 @@ clone_account (const Account* from, gnc_commodity *com) struct add_group_data_struct { - AccountGroup *to; + Account *to; Account *parent; gnc_commodity *com; }; -static gpointer +static void add_groups_for_each (Account *toadd, gpointer data) { struct add_group_data_struct *dadata = data; Account *foundact; - foundact = xaccGetAccountFromName (dadata->to, xaccAccountGetName(toadd)); + foundact = gnc_account_lookup_name(dadata->to, xaccAccountGetName(toadd)); if (!foundact) { foundact = clone_account (toadd, dadata->com); if (dadata->to) - xaccGroupInsertAccount (dadata->to, foundact); + gnc_account_append_child (dadata->to, foundact); else if (dadata->parent) - xaccAccountInsertSubAccount (dadata->parent, foundact); + gnc_account_append_child (dadata->parent, foundact); else { g_warning ("add_groups_for_each: no valid parent"); @@ -601,26 +600,21 @@ add_groups_for_each (Account *toadd, gpointer data) } { - AccountGroup *addgrp = xaccAccountGetChildren (toadd); - - if (xaccGroupGetNumAccounts(addgrp) > 0) + if (gnc_account_n_children(toadd) > 0) { struct add_group_data_struct downdata; - downdata.to = xaccAccountGetChildren(foundact); + downdata.to = foundact; downdata.parent = foundact; downdata.com = dadata->com; - xaccGroupForEachAccount (addgrp, add_groups_for_each, - &downdata, FALSE); + gnc_account_foreach_child (toadd, add_groups_for_each, &downdata); } } - - return NULL; } static void -add_groups_to_with_random_guids (AccountGroup *into, AccountGroup *from, +add_new_accts_with_random_guids (Account *into, Account *from, gnc_commodity *com) { struct add_group_data_struct data; @@ -628,20 +622,20 @@ add_groups_to_with_random_guids (AccountGroup *into, AccountGroup *from, data.parent = NULL; data.com = com; - xaccGroupForEachAccount (from, add_groups_for_each, &data, FALSE); + gnc_account_foreach_child (from, add_groups_for_each, &data); } -static AccountGroup * -hierarchy_merge_groups (GSList *dalist, gnc_commodity *com) +static Account * +hierarchy_merge_accounts (GSList *dalist, gnc_commodity *com) { GSList *mark; - AccountGroup *ret = xaccMallocAccountGroup (gnc_get_current_book ()); + Account *ret = xaccMallocAccount (gnc_get_current_book ()); for (mark = dalist; mark; mark = mark->next) { GncExampleAccount *xea = mark->data; - add_groups_to_with_random_guids (ret, xea->group, com); + add_new_accts_with_random_guids (ret, xea->root, com); } return ret; @@ -712,7 +706,7 @@ balance_cell_data_func (GtkTreeViewColumn *tree_column, string=_("zero"); } else { GncAccountMergeDisposition disp; - disp = determine_merge_disposition(gnc_book_get_group(gnc_get_current_book()), account); + disp = determine_merge_disposition(gnc_book_get_root_account(gnc_get_current_book()), account); if (disp == GNC_ACCOUNT_MERGE_DISPOSITION_CREATE_NEW) { allow_value = !xaccAccountGetPlaceholder(account); @@ -765,22 +759,22 @@ placeholder_cell_data_func (GtkTreeViewColumn *tree_column, GtkTreeIter *iter, gpointer user_data) { - Account *account; + Account *account, *root; gboolean willbe_placeholder = FALSE; GncAccountMergeDisposition disp; g_return_if_fail (GTK_TREE_MODEL (model)); account = gnc_tree_view_account_get_account_from_iter (model, iter); - disp = determine_merge_disposition(gnc_book_get_group(gnc_get_current_book()), account); + root = gnc_book_get_root_account(gnc_get_current_book()); + disp = determine_merge_disposition(root, account); switch (disp) { case GNC_ACCOUNT_MERGE_DISPOSITION_USE_EXISTING: { /* find the existing account, do whatever it is. */ gchar *full_name; Account *existing_acct; - AccountGroup *root_group = gnc_book_get_group(gnc_get_current_book()); full_name = xaccAccountGetFullName(account); - existing_acct = xaccGetAccountFromFullName(root_group, full_name); + existing_acct = gnc_account_lookup_full_name(root, full_name); willbe_placeholder = xaccAccountGetPlaceholder(existing_acct); g_free(full_name); } break; @@ -801,7 +795,7 @@ use_existing_account_data_func(GtkTreeViewColumn *tree_column, gpointer user_data) { Account *new_acct; - AccountGroup *real_root; + Account *real_root; GncAccountMergeDisposition disposition; char *to_user = "(error; unknown condition)"; @@ -813,7 +807,7 @@ use_existing_account_data_func(GtkTreeViewColumn *tree_column, return; } - real_root = gnc_book_get_group(gnc_get_current_book()); + real_root = gnc_book_get_root_account(gnc_get_current_book()); disposition = determine_merge_disposition(real_root, new_acct); switch (disposition) { @@ -852,18 +846,18 @@ on_final_account_prepare (GnomeDruidPage *gnomedruidpage, gtk_widget_destroy(GTK_WIDGET(data->final_account_tree)); data->final_account_tree = NULL; } - delete_our_final_group (data); + delete_our_account_tree (data); /* Build a new account list */ actlist = get_selected_account_list (data->categories_tree); com = gnc_currency_edit_get_currency (GNC_CURRENCY_EDIT(data->currency_selector)); - data->our_final_group = hierarchy_merge_groups (actlist, com); + data->our_account_tree = hierarchy_merge_accounts (actlist, com); /* Now build a new account tree */ data->final_account_tree - = GNC_TREE_VIEW_ACCOUNT(gnc_tree_view_account_new_with_group (data->our_final_group, FALSE)); + = GNC_TREE_VIEW_ACCOUNT(gnc_tree_view_account_new_with_root (data->our_account_tree, FALSE)); tree_view = GTK_TREE_VIEW(data->final_account_tree); gnc_tree_view_account_set_name_edited(data->final_account_tree, gnc_tree_view_account_name_edited_cb); @@ -921,7 +915,7 @@ on_final_account_prepare (GnomeDruidPage *gnomedruidpage, } // only in the case where there *are* existing accounts... - if (xaccGroupGetNumSubAccounts(gnc_book_get_group(gnc_get_current_book())) > 0) + if (gnc_account_n_descendants(gnc_book_get_root_account(gnc_get_current_book())) > 0) { GList *renderers; column = gnc_tree_view_add_text_column(GNC_TREE_VIEW(tree_view), @@ -954,13 +948,13 @@ on_cancel (GnomeDruid *gnomedruid, { gnc_suspend_gui_refresh (); delete_hierarchy_dialog (data); - delete_our_final_group (data); + delete_our_account_tree (data); gncp_new_user_finish (); g_free(data); gnc_resume_gui_refresh (); } -static gpointer +static void starting_balance_helper (Account *account, hierarchy_data *data) { gnc_numeric balance; @@ -971,8 +965,6 @@ starting_balance_helper (Account *account, hierarchy_data *data) if (!gnc_numeric_zero_p (balance)) gnc_account_create_opening_balance (account, balance, time (NULL), gnc_get_current_book ()); - - return NULL; } void @@ -983,11 +975,11 @@ on_finish (GnomeDruidPage *gnomedruidpage, GncHierarchyDruidFinishedCallback when_completed; ENTER (" "); - if (data->our_final_group) + if (data->our_account_tree) { - xaccGroupForEachAccount (data->our_final_group, - (AccountCallback)starting_balance_helper, - data, TRUE); + gnc_account_foreach_descendant (data->our_account_tree, + (AccountCb)starting_balance_helper, + data); } // delete before we suspend GUI events, and then muck with the model, @@ -998,9 +990,9 @@ on_finish (GnomeDruidPage *gnomedruidpage, gnc_suspend_gui_refresh (); - account_group_merge(gnc_get_current_group(), data->our_final_group); + account_trees_merge(gnc_get_current_root_account(), data->our_account_tree); - delete_our_final_group (data); + delete_our_account_tree (data); qof_book_destroy(data->temporary); when_completed = data->when_completed; diff --git a/src/gnome/druid-merge.c b/src/gnome/druid-merge.c index a0515a70d7..974acb14e0 100644 --- a/src/gnome/druid-merge.c +++ b/src/gnome/druid-merge.c @@ -38,7 +38,6 @@ #include "druid-hierarchy.h" #include "gnc-ui-util.h" #include "Account.h" -#include "Group.h" GtkWidget *druid_hierarchy_window = NULL; static GtkWidget *qsf_import_merge_window = NULL; @@ -197,12 +196,15 @@ void currency_transfer_cb ( QofEntity* ent, gpointer user_data) } } +/* If the account has no parent, shove it into the top level under the root. */ void reference_parent_cb ( QofEntity* ent, gpointer user_data) { + Account *root; + if(!ent) return; - if(xaccAccountGetParent((Account*)ent) == NULL) { - xaccGroupInsertAccount(xaccGroupGetRoot( - xaccGetAccountGroup(targetBook)), (Account*)ent); + if(gnc_account_get_parent((Account*)ent) == NULL) { + root = gnc_book_get_root_account(targetBook); + gnc_account_append_child(root, (Account*)ent); } } diff --git a/src/gnome/druid-merge.h b/src/gnome/druid-merge.h index dfa1e24ad1..6b4718cbfb 100644 --- a/src/gnome/druid-merge.h +++ b/src/gnome/druid-merge.h @@ -81,7 +81,7 @@ void gnc_ui_qsf_import_merge_druid(QofSession *original, QofSession *import); /** \brief gncCommodity is not QOF enabled, need to set a default commodity before the merge */ void currency_transfer_cb ( QofEntity* ent, gpointer user_data); -/** \brief workaround for AccountGroup not being fully QOF enabled. */ +/** \brief workaround for AccountGroup not being fully QOF enabled. Eh? */ void reference_parent_cb ( QofEntity* ent, gpointer user_data); /** @} */ diff --git a/src/gnome/druid-stock-split.c b/src/gnome/druid-stock-split.c index c34ea0a7ae..4121e575fb 100644 --- a/src/gnome/druid-stock-split.c +++ b/src/gnome/druid-stock-split.c @@ -27,7 +27,6 @@ #include #include -#include "Group.h" #include "Transaction.h" #include "dialog-utils.h" #include "druid-stock-split.h" @@ -132,7 +131,7 @@ fill_account_list (StockSplitInfo *info, Account *selected_account) gtk_list_store_clear (list); - accounts = xaccGroupGetSubAccountsSorted (gnc_get_current_group ()); + accounts = gnc_account_get_descendants_sorted (gnc_get_current_root_account ()); for (node = accounts; node; node = node->next) { Account *account = node->data; @@ -226,7 +225,7 @@ refresh_details_page (StockSplitInfo *info) xaccAccountGetCommoditySCU (account)); commodity = xaccAccountGetCommodity (account); - book = xaccAccountGetBook (account); + book = gnc_account_get_book (account); db = gnc_book_get_pricedb(book); prices = gnc_pricedb_lookup_latest_any_currency(db, commodity); diff --git a/src/gnome/gnc-plugin-page-account-tree.c b/src/gnome/gnc-plugin-page-account-tree.c index f98aab04bd..cad3057eb5 100644 --- a/src/gnome/gnc-plugin-page-account-tree.c +++ b/src/gnome/gnc-plugin-page-account-tree.c @@ -670,7 +670,7 @@ gnc_plugin_page_account_tree_selection_changed_cb (GtkTreeSelection *selection, account = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(view)); sensitive = (account != NULL); - subaccounts = (xaccAccountGetChildren(account) != NULL); + subaccounts = (gnc_account_n_children(account) != 0); /* Check here for placeholder accounts, etc. */ } @@ -694,7 +694,7 @@ gnc_plugin_page_account_tree_cmd_new_account (GtkAction *action, GncPluginPageAc { Account *account = gnc_plugin_page_account_tree_get_current_account (page); - gnc_ui_new_account_window_with_default (NULL, account); + gnc_ui_new_account_window (gnc_get_current_book(), account); } static void @@ -848,7 +848,6 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag Account *account = gnc_plugin_page_account_tree_get_current_account (page); gchar *acct_name; GList *splits; - AccountGroup *children; delete_helper_t delete_res = { FALSE, FALSE }; GtkWidget *widget; GtkWidget *window; @@ -871,13 +870,12 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag } splits = xaccAccountGetSplitList(account); - children = xaccAccountGetChildren(account); /* * If the account has transactions or child accounts then conduct a * dialog to allow the user to specify what should be done with them. */ - if ((NULL != splits) || (NULL != children)) { + if ((NULL != splits) || (gnc_account_n_children(account) > 0)) { GList *filter; GladeXML *xml; GtkWidget *label; @@ -926,12 +924,12 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag /* * Adjust the dialog based on whether the account has children. */ - if (children != NULL) { + if (gnc_account_n_children(account) > 0) { /* * Check for RO txns in descendants */ - xaccGroupForEachAccount(children, delete_account_helper, - &delete_res, TRUE); + gnc_account_foreach_descendant_until(account, delete_account_helper, + &delete_res); if (delete_res.has_ro_splits) { gtk_widget_destroy(glade_xml_get_widget (xml, "sa_trans_rw")); widget = glade_xml_get_widget (xml, "dtdrb"); @@ -999,7 +997,7 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag lines[++i] = g_strdup_printf("%s", format); } } - if (children) { + if (gnc_account_n_children(account) > 0) { if (daa) { name = xaccAccountGetFullName(daa); format = _("All of its sub-accounts will be moved to " @@ -1050,15 +1048,14 @@ gnc_plugin_page_account_tree_cmd_delete_account (GtkAction *action, GncPluginPag xaccAccountBeginEdit (daa); acct_list = g_list_copy(xaccGroupGetAccountList(children)); for (ptr = acct_list; ptr; ptr = g_list_next(ptr)) - xaccAccountInsertSubAccount (daa, ptr->data); + gnc_account_append_child (daa, ptr->data); g_list_free(acct_list); xaccAccountCommitEdit (daa); } else if (NULL != dta) { /* Move the splits of its subaccounts, if any. */ - xaccGroupForEachAccount (children, - (gpointer (*)(Account *, gpointer)) - xaccAccountMoveAllSplits, - dta, TRUE); + gnc_account_foreach_descendant(account, + (AccountCb)xaccAccountMoveAllSplits, + dta); } if (NULL != ta) { /* Move the splits of the account to be deleted. */ @@ -1195,7 +1192,7 @@ gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAcco static void gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAccountTree *page) { - AccountGroup *group = gnc_get_current_group (); + Account *root = gnc_get_current_root_account (); gnc_suspend_gui_refresh (); diff --git a/src/gnome/gnc-plugin-page-register.c b/src/gnome/gnc-plugin-page-register.c index 69810389e3..5b7746be77 100644 --- a/src/gnome/gnc-plugin-page-register.c +++ b/src/gnome/gnc-plugin-page-register.c @@ -997,8 +997,8 @@ gnc_plugin_page_register_recreate_page (GtkWidget *window, acct_name = g_key_file_get_string(key_file, group_name, KEY_ACCOUNT_NAME, &error); book = qof_session_get_book(gnc_get_current_session()); - account = xaccGetAccountFromFullName(xaccGetAccountGroup(book), - acct_name); + account = gnc_account_lookup_full_name(gnc_book_get_root_account(book), + acct_name); g_free(acct_name); if (account == NULL) { LEAVE("Bad account name"); @@ -2577,7 +2577,7 @@ gnc_plugin_page_register_cmd_scrub_current (GtkAction *action, { GncPluginPageRegisterPrivate *priv; Query *query; - AccountGroup *root; + Account *root; Transaction *trans; SplitRegister *reg; @@ -2600,7 +2600,7 @@ gnc_plugin_page_register_cmd_scrub_current (GtkAction *action, } gnc_suspend_gui_refresh(); - root = gnc_get_current_group(); + root = gnc_get_current_root_account(); xaccTransScrubOrphans(trans); xaccTransScrubImbalance(trans, root, NULL); gnc_resume_gui_refresh(); @@ -2613,7 +2613,7 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction *action, { GncPluginPageRegisterPrivate *priv; Query *query; - AccountGroup *root; + Account *root; Transaction *trans; Split *split; GList *node; @@ -2630,7 +2630,7 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction *action, } gnc_suspend_gui_refresh(); - root = gnc_get_current_group(); + root = gnc_get_current_root_account(); for (node = xaccQueryGetSplits(query); node; node = node->next) { diff --git a/src/gnome/gnc-split-reg.c b/src/gnome/gnc-split-reg.c index 5d5cabcb59..050dded3f9 100644 --- a/src/gnome/gnc-split-reg.c +++ b/src/gnome/gnc-split-reg.c @@ -483,7 +483,7 @@ account_latest_price (Account *account) commodity = xaccAccountGetCommodity (account); currency = gnc_default_currency (); - book = xaccAccountGetBook (account); + book = gnc_account_get_book (account); pdb = gnc_book_get_pricedb (book); return gnc_pricedb_lookup_latest (pdb, commodity, currency); @@ -501,7 +501,7 @@ account_latest_price_any_currency (Account *account) if (!account) return NULL; commodity = xaccAccountGetCommodity (account); - book = xaccAccountGetBook (account); + book = gnc_account_get_book (account); pdb = gnc_book_get_pricedb (book); price_list = gnc_pricedb_lookup_latest_any_currency (pdb, commodity); diff --git a/src/gnome/reconcile-list.c b/src/gnome/reconcile-list.c index cf43dbc3e2..8f8e0d97cc 100644 --- a/src/gnome/reconcile-list.c +++ b/src/gnome/reconcile-list.c @@ -144,7 +144,7 @@ gnc_reconcile_list_new(Account *account, GNCReconcileListType type, include_children = xaccAccountGetReconcileChildrenStatus(account); if (include_children) - accounts = xaccAccountGetDescendants(account); + accounts = gnc_account_get_descendants(account); /* match the account */ accounts = g_list_prepend (accounts, account); @@ -290,7 +290,6 @@ gnc_reconcile_list_toggle_split(GNCReconcileList *list, Split *split) static void gnc_reconcile_list_toggle_children(Account *account, GNCReconcileList *list, Split *split) { - AccountGroup *account_group; GList *child_accounts, *node; Transaction *transaction; @@ -301,8 +300,7 @@ gnc_reconcile_list_toggle_children(Account *account, GNCReconcileList *list, Spl * * For each of these splits toggle them all to the same state. */ - account_group = xaccAccountGetChildren(account); - child_accounts = xaccGroupGetSubAccounts(account_group); + child_accounts = gnc_account_get_descendants(account); child_accounts = g_list_prepend(child_accounts, account); transaction = xaccSplitGetParent(split); for(node = xaccTransGetSplitList(transaction); node; node = node->next) @@ -331,6 +329,7 @@ gnc_reconcile_list_toggle_children(Account *account, GNCReconcileList *list, Spl } gnc_reconcile_list_toggle_split(current_list, other_split); } + g_list_free(child_accounts); } static void diff --git a/src/gnome/top-level.c b/src/gnome/top-level.c index 4365706b75..1a3e921076 100644 --- a/src/gnome/top-level.c +++ b/src/gnome/top-level.c @@ -119,8 +119,8 @@ gnc_html_register_url_cb (const char *location, const char *label, /* href="gnc-register:account=My Bank Account" */ if (strncmp("account=", location, 8) == 0) { - account = xaccGetAccountFromFullName (gnc_get_current_group (), - location + 8); + account = gnc_account_lookup_full_name (gnc_get_current_root_account (), + location + 8); } /* href="gnc-register:guid=12345678901234567890123456789012" */ diff --git a/src/gnome/window-reconcile.c b/src/gnome/window-reconcile.c index 5992c705a7..7f1f122493 100644 --- a/src/gnome/window-reconcile.c +++ b/src/gnome/window-reconcile.c @@ -1393,7 +1393,7 @@ recn_set_watches (RecnWindow *recnData) include_children = xaccAccountGetReconcileChildrenStatus(account); if (include_children) - accounts = xaccAccountGetDescendants(account); + accounts = gnc_account_get_descendants(account); /* match the account */ accounts = g_list_prepend (accounts, account); diff --git a/src/import-export/binary-import/druid-commodity.c b/src/import-export/binary-import/druid-commodity.c index 61cb0c4744..4503cbcb00 100644 --- a/src/import-export/binary-import/druid-commodity.c +++ b/src/import-export/binary-import/druid-commodity.c @@ -460,7 +460,7 @@ finish_helper(gpointer key, gpointer value, gpointer data) comm); /* now replace all the accounts using old_comm with new_comm */ - accts = xaccGroupGetSubAccounts(gnc_get_current_group ()); + accts = gnc_account_get_descendants(gnc_get_current_root_account ()); for(node = accts; node; node = node->next) { @@ -493,10 +493,10 @@ gnc_ui_commodity_druid_finish_cb(GnomeDruidPage * page, gpointer druid, g_hash_table_foreach(cd->new_map, &finish_helper, (gpointer)cd); /* Fix account and transaction commodities */ - xaccGroupScrubCommodities (gnc_get_current_group ()); + xaccAccountTreeScrubCommodities (gnc_get_current_root_account ()); /* Fix split amount/value */ - xaccGroupScrubSplits (gnc_get_current_group ()); + xaccAccountTreeScrubSplits (gnc_get_current_root_account ()); /* destroy the dialog */ gnc_ui_commodity_druid_destroy(cd); diff --git a/src/import-export/hbci/druid-hbci-utils.c b/src/import-export/hbci/druid-hbci-utils.c index dbb56341ed..4557f37cac 100644 --- a/src/import-export/hbci/druid-hbci-utils.c +++ b/src/import-export/hbci/druid-hbci-utils.c @@ -66,7 +66,7 @@ accounts_save_kvp_cb (gpointer key, gpointer value, gpointer user_data) (gnc_acc, AB_Account_GetBankCode(hbci_acc)); } -static gpointer accounts_clear_kvp (Account *gnc_acc, gpointer user_data) +static void accounts_clear_kvp (Account *gnc_acc, gpointer user_data) { if (gnc_hbci_get_account_uid(gnc_acc)) gnc_hbci_set_account_uid (gnc_acc, 0); @@ -74,7 +74,6 @@ static gpointer accounts_clear_kvp (Account *gnc_acc, gpointer user_data) gnc_hbci_set_account_accountid (gnc_acc, ""); if (gnc_hbci_get_account_bankcode(gnc_acc)) gnc_hbci_set_account_bankcode (gnc_acc, ""); - return NULL; } /* hash is a DIRECT hash from each HBCI account to each gnucash @@ -82,13 +81,11 @@ static gpointer accounts_clear_kvp (Account *gnc_acc, gpointer user_data) void accounts_save_kvp (GHashTable *hash) { - AccountGroup *grp; + Account *root; g_assert(hash); - grp = gnc_book_get_group (gnc_get_current_book ()); - xaccGroupForEachAccount (grp, - &accounts_clear_kvp, - NULL, TRUE); + root = gnc_book_get_root_account (gnc_get_current_book ()); + gnc_account_foreach_descendant (root, accounts_clear_kvp, NULL); g_hash_table_foreach (hash, &accounts_save_kvp_cb, NULL); } @@ -112,7 +109,7 @@ struct hbci_acc_cb_data GHashTable *hash; }; -static gpointer +static void gnc_hbci_new_hash_from_kvp_cb (Account *gnc_acc, gpointer user_data) { struct hbci_acc_cb_data *data = user_data; @@ -122,7 +119,6 @@ gnc_hbci_new_hash_from_kvp_cb (Account *gnc_acc, gpointer user_data) if (hbci_acc) { g_hash_table_insert (data->hash, hbci_acc, gnc_acc); } - return NULL; } GHashTable * @@ -133,12 +129,10 @@ gnc_hbci_new_hash_from_kvp (AB_BANKING *api) hash = g_hash_table_new (&g_direct_hash, &g_direct_equal); if (api) { struct hbci_acc_cb_data data; - AccountGroup *grp = gnc_book_get_group (gnc_get_current_book ()); + Account *root = gnc_book_get_root_account (gnc_get_current_book ()); data.api = api; data.hash = hash; - xaccGroupForEachAccount (grp, - &gnc_hbci_new_hash_from_kvp_cb, - &data, TRUE); + gnc_account_foreach_descendant(root, gnc_hbci_new_hash_from_kvp_cb, &data); } return hash; } diff --git a/src/import-export/hbci/gnc-hbci-gettrans.c b/src/import-export/hbci/gnc-hbci-gettrans.c index b991da5548..d6873e960e 100644 --- a/src/import-export/hbci/gnc-hbci-gettrans.c +++ b/src/import-export/hbci/gnc-hbci-gettrans.c @@ -256,7 +256,7 @@ AB_TRANSACTION *gnc_hbci_trans_list_cb(AB_TRANSACTION *h_trans, void *user_data) gnc_acc = data->gnc_acc; g_assert(gnc_acc); - book = xaccAccountGetBook(gnc_acc); + book = gnc_account_get_book(gnc_acc); /* Create new gnucash transaction for the given hbci one */ gnc_trans = xaccMallocTransaction(book); diff --git a/src/import-export/hbci/gnc-hbci-transfer.c b/src/import-export/hbci/gnc-hbci-transfer.c index 686ab330f7..a724bfe505 100644 --- a/src/import-export/hbci/gnc-hbci-transfer.c +++ b/src/import-export/hbci/gnc-hbci-transfer.c @@ -78,7 +78,7 @@ gnc_hbci_maketrans (GtkWidget *parent, Account *gnc_acc, GList *template_list = gnc_trans_templ_glist_from_kvp_glist ( gnc_hbci_get_book_template_list - ( xaccAccountGetBook(gnc_acc))); + ( gnc_account_get_book(gnc_acc))); int result; gboolean successful = FALSE; HBCITransDialog *td; @@ -224,7 +224,7 @@ void maketrans_save_templates(GtkWidget *parent, Account *gnc_acc, g_list_length(template_list), kvp_value_glist_to_string(kvp_list));*/ gnc_hbci_set_book_template_list - (xaccAccountGetBook(gnc_acc), kvp_list); + (gnc_account_get_book(gnc_acc), kvp_list); } } diff --git a/src/import-export/import-account-matcher.c b/src/import-export/import-account-matcher.c index 9d1de85e7a..968a37bad5 100644 --- a/src/import-export/import-account-matcher.c +++ b/src/import-export/import-account-matcher.c @@ -158,12 +158,12 @@ Account * gnc_import_select_account(gncUIWidget parent, /*DEBUG("Looking for account with online_id: %s", account_online_id_value);*/ if(account_online_id_value!=NULL) { - retval = xaccGroupForEachAccount(gnc_get_current_group (), + retval = + gnc_account_foreach_descendant_until(gnc_get_current_root_account (), test_acct_online_id_match, /* This argument will only be used as a "const char*" */ - (void*)account_online_id_value, - TRUE); + (void*)account_online_id_value); } if(retval==NULL && auto_create != 0) { diff --git a/src/import-export/import-backend.c b/src/import-export/import-backend.c index c4343dfb2a..db197f81d7 100644 --- a/src/import-export/import-backend.c +++ b/src/import-export/import-backend.c @@ -845,7 +845,7 @@ gnc_import_process_trans_item (GncImportMatchMap *matchmap, /* Create the 'other' split. */ Split *split = xaccMallocSplit - (xaccAccountGetBook + (gnc_account_get_book (gnc_import_TransInfo_get_destacc (trans_info))); xaccTransAppendSplit (gnc_import_TransInfo_get_trans (trans_info), split); diff --git a/src/import-export/import-match-map.c b/src/import-export/import-match-map.c index c1ba98ab1a..408f009348 100644 --- a/src/import-export/import-match-map.c +++ b/src/import-export/import-match-map.c @@ -31,7 +31,6 @@ #include #include #include "import-match-map.h" -#include "Group.h" #include "gnc-ui-util.h" #include "gnc-engine.h" @@ -66,7 +65,7 @@ gnc_imap_create_from_frame (kvp_frame *frame, Account *acc, GNCBook *book) * marking dirtiness */ if (acc) - book = xaccAccountGetBook (acc); + book = gnc_account_get_book (acc); imap->acc = acc; imap->book = book; @@ -442,8 +441,8 @@ Account* gnc_imap_find_account_bayes(GncImportMatchMap *imap, GList *tokens) { PINFO("found match"); LEAVE(" "); - return xaccGetAccountFromFullName(gnc_book_get_group(imap->book), - account_i.account_name); + return gnc_account_lookup_full_name(gnc_book_get_root_account(imap->book), + account_i.account_name); } PINFO("no match"); diff --git a/src/import-export/ofx/gnc-ofx-import.c b/src/import-export/ofx/gnc-ofx-import.c index 9f4ffd0fdd..d002eb8fd9 100644 --- a/src/import-export/ofx/gnc-ofx-import.c +++ b/src/import-export/ofx/gnc-ofx-import.c @@ -132,7 +132,7 @@ int ofx_proc_transaction_cb(struct OfxTransactionData data, void * transaction_u gnc_utf8_strip_invalid(data.memo); /********** Create the transaction and setup transaction data ************/ - book = xaccAccountGetBook(account); + book = gnc_account_get_book(account); transaction = xaccMallocTransaction(book); xaccTransBeginEdit(transaction); diff --git a/src/import-export/qif-import/druid-qif-import.c b/src/import-export/qif-import/druid-qif-import.c index 015635c0eb..3ada8fc730 100644 --- a/src/import-export/qif-import/druid-qif-import.c +++ b/src/import-export/qif-import/druid-qif-import.c @@ -116,7 +116,7 @@ struct _qifimportwindow { SCM new_stocks; SCM ticker_map; - SCM imported_account_group; + SCM imported_account_tree; SCM match_transactions; int selected_transaction; }; @@ -189,7 +189,7 @@ gnc_ui_qif_import_druid_destroy (QIFImportWindow * window) scm_gc_unprotect_object(window->stock_hash); scm_gc_unprotect_object(window->new_stocks); scm_gc_unprotect_object(window->ticker_map); - scm_gc_unprotect_object(window->imported_account_group); + scm_gc_unprotect_object(window->imported_account_tree); scm_gc_unprotect_object(window->match_transactions); g_free(window); @@ -1276,14 +1276,14 @@ gnc_ui_qif_import_convert(QIFImportWindow * wind) _("An error occurred while importing " "QIF transactions into GnuCash. Your " "accounts are unchanged.")); - scm_gc_unprotect_object(wind->imported_account_group); - wind->imported_account_group = SCM_BOOL_F; - scm_gc_protect_object(wind->imported_account_group); + scm_gc_unprotect_object(wind->imported_account_tree); + wind->imported_account_tree = SCM_BOOL_F; + scm_gc_protect_object(wind->imported_account_tree); } else { - scm_gc_unprotect_object(wind->imported_account_group); - wind->imported_account_group = retval; - scm_gc_protect_object(wind->imported_account_group); + scm_gc_unprotect_object(wind->imported_account_tree); + wind->imported_account_tree = retval; + scm_gc_protect_object(wind->imported_account_tree); /* now detect duplicate transactions */ gnc_set_busy_cursor(NULL, TRUE); @@ -1853,7 +1853,7 @@ gnc_ui_qif_import_finish_cb(GnomeDruidPage * gpage, { SCM save_map_prefs = scm_c_eval_string("qif-import:save-map-prefs"); - SCM cat_and_merge = scm_c_eval_string("gnc:group-catenate-and-merge"); + SCM cat_and_merge = scm_c_eval_string("gnc:account-tree-catenate-and-merge"); SCM prune_xtns = scm_c_eval_string("gnc:prune-matching-transactions"); QIFImportWindow * wind = user_data; @@ -2056,7 +2056,7 @@ gnc_ui_qif_import_druid_make(void) retval->stock_hash = SCM_BOOL_F; retval->new_stocks = SCM_BOOL_F; retval->ticker_map = SCM_BOOL_F; - retval->imported_account_group = SCM_BOOL_F; + retval->imported_account_tree = SCM_BOOL_F; retval->match_transactions = SCM_BOOL_F; retval->selected_transaction = 0; @@ -2221,7 +2221,7 @@ gnc_ui_qif_import_druid_make(void) scm_gc_protect_object(retval->stock_hash); scm_gc_protect_object(retval->new_stocks); scm_gc_protect_object(retval->ticker_map); - scm_gc_protect_object(retval->imported_account_group); + scm_gc_protect_object(retval->imported_account_tree); scm_gc_protect_object(retval->match_transactions); /* set a default currency for new accounts */ diff --git a/src/import-export/qif-import/qif-guess-map.scm b/src/import-export/qif-import/qif-guess-map.scm index 95c5607668..2acd07ec7d 100644 --- a/src/import-export/qif-import/qif-guess-map.scm +++ b/src/import-export/qif-import/qif-guess-map.scm @@ -25,8 +25,8 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define (qif-import:load-map-prefs) - (define (extract-all-account-info agroup root-name) - (if (not agroup) + (define (extract-all-account-info an-account root-name) + (if (not an-account) '() (let ((children-list (xaccGroupGetAccountListSorted agroup)) (names '())) diff --git a/src/import-export/qif-import/qif-import.scm b/src/import-export/qif-import/qif-import.scm index 5835384a7a..2f3b5b2ffe 100644 --- a/src/import-export/qif-import/qif-import.scm +++ b/src/import-export/qif-import/qif-import.scm @@ -65,6 +65,6 @@ (export qif-dialog:make-category-display) (export qif-dialog:make-memo-display) -(export gnc:group-find-duplicates) -(export gnc:group-catenate-and-merge) +(export gnc:account-tree-find-duplicates) +(export gnc:account-tree-catenate-and-merge) (export gnc:prune-matching-transactions) diff --git a/src/import-export/qif-import/qif-merge-groups.scm b/src/import-export/qif-import/qif-merge-groups.scm index 8c3bd94458..0444d2892a 100644 --- a/src/import-export/qif-import/qif-merge-groups.scm +++ b/src/import-export/qif-import/qif-merge-groups.scm @@ -25,16 +25,16 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; gnc:group-find-duplicates +;; gnc:account-tree-find-duplicates ;; detect redundant splits/xtns from 'new' and return ;; them in a list. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define (gnc:group-find-duplicates old-group new-group window) +(define (gnc:account-tree-find-duplicates old-root new-root window) ;; get all the transactions in the new group, then iterate over them ;; trying to find matches in the new group. If there are matches, ;; push the matches onto a list. - (let* ((new-xtns (gnc:group-get-transactions new-group)) + (let* ((new-xtns (gnc:account-tree-get-transactions new-root)) (progress-dialog #f) (work-to-do (length new-xtns)) (work-done 0) @@ -47,7 +47,7 @@ (gnc-progress-dialog-set-heading progress-dialog (_ "Finding duplicate transactions...")))) - ;; for each transaction in the new group, build a query that could + ;; for each transaction in the new account tree, build a query that could ;; match possibly similar transactions. (for-each (lambda (xtn) @@ -93,7 +93,7 @@ QOF-QUERY-AND) ;; we want the value for the split to match the value - ;; the old-group split. We should really check for + ;; the old-root split. We should really check for ;; fuzziness. (xaccQueryAddValueMatch sq (xaccSplitGetValue split) diff --git a/src/import-export/qif-import/qif-to-gnc.scm b/src/import-export/qif-import/qif-to-gnc.scm index 33a493764c..5e074a5afa 100644 --- a/src/import-export/qif-import/qif-to-gnc.scm +++ b/src/import-export/qif-import/qif-to-gnc.scm @@ -155,7 +155,7 @@ (set! parent-acct (qif-import:find-or-make-acct pinfo #t default-currency #f default-currency - gnc-acct-hash old-group new-group)))) + gnc-acct-hash old-root new-root)))) (if parent-acct (xaccAccountInsertSubAccount parent-acct new-acct) (xaccGroupInsertAccount new-group new-acct)) @@ -265,16 +265,16 @@ (qif-import:find-or-make-acct acctinfo #f security #t default-currency gnc-acct-hash - old-group new-group)) + old-root new-root)) ((and security (or stock? (gnc-commodity-is-currency security))) (qif-import:find-or-make-acct acctinfo #f security #t default-currency - gnc-acct-hash old-group new-group)) + gnc-acct-hash old-root new-root)) (#t (qif-import:find-or-make-acct acctinfo #f default-currency #t default-currency - gnc-acct-hash old-group new-group))))) + gnc-acct-hash old-root new-root))))) sorted-accounts-list) ;; before trying to mark transactions, prune down the list of @@ -355,7 +355,7 @@ (if progress-dialog (gnc-progress-dialog-destroy progress-dialog)) - new-group)))) + new-root)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; qif-import:qif-xtn-to-gnc-xtn diff --git a/src/import-export/qif-io-core/qif-acct-table.scm b/src/import-export/qif-io-core/qif-acct-table.scm index a2552a3578..e11aa992c7 100644 --- a/src/import-export/qif-io-core/qif-acct-table.scm +++ b/src/import-export/qif-io-core/qif-acct-table.scm @@ -43,7 +43,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; qif-io:acct-table-make-gnc-group +;; qif-io:acct-table-make-gnc-acct-tree ;; fill in information for the gnucash accounts and organize them ;; in a group tree ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -123,4 +123,4 @@ ;; the other brokerage-related accounts - group)) + root)) diff --git a/src/import-export/qif-io-core/qif-io-core.scm b/src/import-export/qif-io-core/qif-io-core.scm index 6114624abc..49365df846 100644 --- a/src/import-export/qif-io-core/qif-io-core.scm +++ b/src/import-export/qif-io-core/qif-io-core.scm @@ -85,7 +85,7 @@ ;; acct-table.scm (export qif-io:acct-table-lookup) (export qif-io:acct-table-insert!) -(export qif-io:acct-table-make-gnc-group) +(export qif-io:acct-table-make-gnc-acct-tree) ;; from main (export simple-format) diff --git a/src/import-export/qif-io-core/test/test-import-phase-1.scm b/src/import-export/qif-io-core/test/test-import-phase-1.scm index 7872d8bad4..d2dd101bb1 100644 --- a/src/import-export/qif-io-core/test/test-import-phase-1.scm +++ b/src/import-export/qif-io-core/test/test-import-phase-1.scm @@ -56,9 +56,9 @@ (qif-io:invst-xtn-import xtn qiffile acct-table commodity)) (qif-io:file-invst-xtns qiffile)) - ;; build a gnucash account group - (let ((group (qif-io:acct-table-make-gnc-group - acct-table qiffile commodity))) + ;; build a gnucash account tree + (let ((root (qif-io:acct-table-make-gnc-acct-tree + acct-table qiffile commodity))) ;; write the file (let* ((name (simple-format #f "file:~A.gnc" filename))) (simple-format #t "using book name='~A'\n" name) diff --git a/src/register/ledger-core/gnc-ledger-display.c b/src/register/ledger-core/gnc-ledger-display.c index 5211c3c6c6..4ea02ec9bf 100644 --- a/src/register/ledger-core/gnc-ledger-display.c +++ b/src/register/ledger-core/gnc-ledger-display.c @@ -26,7 +26,6 @@ #include #include "Account.h" -#include "Group.h" #include "Query.h" #include "QueryCore.h" #include "QueryNew.h" @@ -311,9 +310,7 @@ gnc_get_reg_type (Account *leader, GNCLedgerDisplayType ld_type) gpointer ret; reg_type = GENERAL_LEDGER; - ret = xaccGroupForEachAccount (xaccAccountGetChildren (leader), - look_for_portfolio_cb, - NULL, TRUE); + ret = gnc_account_foreach_descendant_until(leader, look_for_portfolio_cb, NULL); if (ret) reg_type = PORTFOLIO_LEDGER; break; } @@ -404,20 +401,20 @@ gnc_ledger_display_gl (void) /* In lieu of not "mis-using" some portion of the infrastructure by writing * a bunch of new code, we just filter out the accounts of the template - * transactions. While these are in a seperate AccountGroup just for this - * reason, the query engine makes no distinction between AccountGroups. + * transactions. While these are in a seperate Account trees just for this + * reason, the query engine makes no distinction between Account trees. * See Gnome Bug 86302. * -- jsled */ { - AccountGroup *tAG; - AccountList *al; + Account *tRoot; + GList *al; - tAG = gnc_book_get_template_group( gnc_get_current_book() ); - al = xaccGroupGetSubAccounts( tAG ); + tRoot = gnc_book_get_template_root( gnc_get_current_book() ); + al = gnc_account_get_descendants( tRoot ); xaccQueryAddAccountMatch( query, al, GUID_MATCH_NONE, QUERY_AND ); g_list_free (al); al = NULL; - tAG = NULL; + tRoot = NULL; } gnc_tm_get_today_start(&tm); @@ -448,8 +445,7 @@ gnc_ledger_display_template_gl (char *id) Query *q; GNCLedgerDisplay *ld; SplitRegister *sr; - AccountGroup *ag; - Account *acct; + Account *root, *acct; gboolean isTemplateModeTrue; acct = NULL; @@ -461,8 +457,8 @@ gnc_ledger_display_template_gl (char *id) xaccQuerySetBook (q, book); if ( id != NULL ) { - ag = gnc_book_get_template_group (book); - acct = xaccGetAccountFromName (ag, id); + root = gnc_book_get_template_root (book); + acct = gnc_account_lookup_name(root, id); g_assert( acct ); xaccQueryAddSingleAccountMatch (q, acct, QUERY_AND); } @@ -630,7 +626,7 @@ gnc_ledger_display_make_query (GNCLedgerDisplay *ld, leader = gnc_ledger_display_leader (ld); if (ld->ld_type == LD_SUBACCOUNT) - accounts = xaccGroupGetSubAccounts (xaccAccountGetChildren (leader)); + accounts = gnc_account_get_descendants (leader); else accounts = NULL; diff --git a/src/register/ledger-core/split-register-control.c b/src/register/ledger-core/split-register-control.c index 7e93449f87..6f544480c6 100644 --- a/src/register/ledger-core/split-register-control.c +++ b/src/register/ledger-core/split-register-control.c @@ -25,7 +25,6 @@ #include #include -#include "Group.h" #include "Scrub.h" #include "combocell.h" #include "gnc-component-manager.h" @@ -53,6 +52,7 @@ gnc_split_register_balance_trans (SplitRegister *reg, Transaction *trans) int default_value; Account *default_account; Account *other_account; + Account *root; GList *radio_list = NULL; const char *title = _("Rebalance Transaction"); const char *message = _("The current transaction is not balanced."); @@ -133,6 +133,7 @@ gnc_split_register_balance_trans (SplitRegister *reg, Transaction *trans) g_list_free (radio_list); + root = gnc_account_get_root(default_account); switch (choice) { default: @@ -140,17 +141,15 @@ gnc_split_register_balance_trans (SplitRegister *reg, Transaction *trans) break; case 1: - xaccTransScrubImbalance (trans, gnc_get_current_group (), NULL); + xaccTransScrubImbalance (trans, root, NULL); break; case 2: - xaccTransScrubImbalance (trans, gnc_get_current_group (), - default_account); + xaccTransScrubImbalance (trans, root, default_account); break; case 3: - xaccTransScrubImbalance (trans, gnc_get_current_group (), - other_account); + xaccTransScrubImbalance (trans, root, other_account); break; } diff --git a/src/register/ledger-core/split-register-load.c b/src/register/ledger-core/split-register-load.c index 1f449ae7bd..5e8c79d490 100644 --- a/src/register/ledger-core/split-register-load.c +++ b/src/register/ledger-core/split-register-load.c @@ -24,7 +24,6 @@ #include "config.h" -#include "Group.h" #include "account-quickfill.h" #include "combocell.h" #include "gnc-component-manager.h" @@ -579,20 +578,19 @@ skip_cb (Account *account, gpointer x) static void gnc_split_register_load_xfer_cells (SplitRegister *reg, Account *base_account) { - AccountGroup *group; + Account *root; QuickFill *qf; ComboCell *cell; GtkListStore *store; - group = xaccAccountGetRoot(base_account); - if (group == NULL) - group = gnc_get_current_group(); - - if (group == NULL) + root = gnc_account_get_root(base_account); + if (root == NULL) + root = gnc_get_current_root_account(); + if (root == NULL) return; - qf = gnc_get_shared_account_name_quickfill (group, QKEY, skip_cb, NULL); - store = gnc_get_shared_account_name_list_store (group, QKEY, skip_cb, NULL); + qf = gnc_get_shared_account_name_quickfill (root, QKEY, skip_cb, NULL); + store = gnc_get_shared_account_name_list_store (root, QKEY, skip_cb, NULL); cell = (ComboCell *) gnc_table_layout_get_cell (reg->table->layout, XFRM_CELL); diff --git a/src/register/ledger-core/split-register-model.c b/src/register/ledger-core/split-register-model.c index f55d09080c..c42e71407c 100644 --- a/src/register/ledger-core/split-register-model.c +++ b/src/register/ledger-core/split-register-model.c @@ -25,7 +25,6 @@ #include #include -#include "Group.h" #include "datecell.h" #include "dialog-utils.h" #include "gnc-engine.h" @@ -83,7 +82,7 @@ gnc_split_register_use_security_cells (SplitRegister *reg, const char *name; name = gnc_table_layout_get_cell_value (reg->table->layout, XFRM_CELL); - account = xaccGetAccountFromFullName (gnc_get_current_group (), name); + account = gnc_account_lookup_full_name (gnc_get_current_root_account (), name); } if (!account) diff --git a/src/register/ledger-core/split-register-p.h b/src/register/ledger-core/split-register-p.h index 3af5c0f364..77cba87781 100644 --- a/src/register/ledger-core/split-register-p.h +++ b/src/register/ledger-core/split-register-p.h @@ -23,7 +23,6 @@ #ifndef SPLIT_REGISTER_P_H #define SPLIT_REGISTER_P_H -#include "Group.h" #include "split-register.h" diff --git a/src/register/ledger-core/split-register.c b/src/register/ledger-core/split-register.c index 80a70cce40..b86ec8c12f 100644 --- a/src/register/ledger-core/split-register.c +++ b/src/register/ledger-core/split-register.c @@ -1504,7 +1504,7 @@ gnc_split_register_get_account_by_name (SplitRegister *reg, BasicCell * bcell, return NULL; /* Find the account */ - account = xaccGetAccountFromFullName (gnc_get_current_group (), name); + account = gnc_account_lookup_full_name (gnc_get_current_root_account (), name); if (!account) { /* Ask if they want to create a new one. */ diff --git a/src/register/ledger-core/split-register.h b/src/register/ledger-core/split-register.h index 1f926ae9d9..6eb05b64c1 100644 --- a/src/register/ledger-core/split-register.h +++ b/src/register/ledger-core/split-register.h @@ -135,7 +135,6 @@ to store an SRInfo structure containing the blank split. #include -#include "Group.h" #include "Transaction.h" #include "table-allgui.h" diff --git a/src/report/locale-specific/us/taxtxf-de_DE.scm b/src/report/locale-specific/us/taxtxf-de_DE.scm index 3e8a25d7b7..082c7e30c3 100644 --- a/src/report/locale-specific/us/taxtxf-de_DE.scm +++ b/src/report/locale-specific/us/taxtxf-de_DE.scm @@ -460,7 +460,7 @@ (txf-special-split? (gnc:account-get-txf-code account))) (+ gen 1) ; Est Fed Tax has a extra generation gen) ; no kids, return input - (apply max (gnc:group-map-accounts + (apply max (gnc:account-map-children (lambda (x) (num-generations x (+ 1 gen))) children))))) @@ -643,7 +643,7 @@ (for-each (lambda (x) (if (gnc:account-is-inc-exp? x) (set! sum (+ sum (+ 1 (count-accounts (+ 1 level) - (gnc:account-get-immediate-subaccounts x))))) + (gnc:account-get-children x))))) 0)) accounts) sum) diff --git a/src/report/locale-specific/us/taxtxf.scm b/src/report/locale-specific/us/taxtxf.scm index c7d78d90d4..f605e9e036 100644 --- a/src/report/locale-specific/us/taxtxf.scm +++ b/src/report/locale-specific/us/taxtxf.scm @@ -437,7 +437,7 @@ (txf-special-split? (gnc:account-get-txf-code account))) (+ gen 1) ; Est Fed Tax has a extra generation gen) ; no kids, return input - (apply max (gnc:group-map-accounts + (apply max (gnc:account-map-children (lambda (x) (num-generations x (+ 1 gen))) children))))) @@ -620,7 +620,7 @@ (for-each (lambda (x) (if (gnc:account-is-inc-exp? x) (set! sum (+ sum (+ 1 (count-accounts (+ 1 level) - (gnc:account-get-immediate-subaccounts x))))) + (gnc:account-get-children x))))) 0)) accounts) sum) diff --git a/src/report/report-system/html-acct-table.scm b/src/report/report-system/html-acct-table.scm index 2ef38b9b71..0897a005e7 100644 --- a/src/report/report-system/html-acct-table.scm +++ b/src/report/report-system/html-acct-table.scm @@ -709,7 +709,7 @@ (for-each (lambda (acct) - (let* ((subaccts (gnc:account-get-immediate-subaccounts acct)) + (let* ((subaccts (gnc:account-get-children acct)) ;; assign output parameters (account acct) (account-name (xaccAccountGetName acct)) diff --git a/src/report/report-system/html-utilities.scm b/src/report/report-system/html-utilities.scm index 0648de66a5..b586750393 100644 --- a/src/report/report-system/html-utilities.scm +++ b/src/report/report-system/html-utilities.scm @@ -458,7 +458,7 @@ (lambda (x) (if x (gnc-commodity-collector-merge this-collector x ))) - (gnc:group-map-all-accounts + (gnc:account-map-descendants (lambda (a) ;; Important: Calculate the balance if and only if the ;; account a is shown, i.e. (use-acct? a) == #t. @@ -580,7 +580,7 @@ (lambda (acct) (let ((subaccts (filter use-acct? - (gnc:account-get-immediate-subaccounts acct)))) + (gnc:account-get-children acct)))) (set! sum (+ sum 1)) (if (or (= current-depth tree-depth) (null? subaccts)) sum @@ -647,7 +647,7 @@ (lambda (acct) (let ((subaccts (filter use-acct? - (gnc:account-get-immediate-subaccounts acct)))) + (gnc:account-get-children acct)))) (set! work-done (+ 1 work-done)) (if start-percent (gnc:report-percent-done diff --git a/src/report/report-system/report-system.scm b/src/report/report-system/report-system.scm index 51425dc841..55486824ee 100644 --- a/src/report/report-system/report-system.scm +++ b/src/report/report-system/report-system.scm @@ -561,10 +561,8 @@ (export gnc:decompose-accountlist) (export gnc:account-get-type-string-plural) (export gnc:accounts-get-commodities) -(export gnc:get-current-group-depth) +(export gnc:get-current-account-tree-depth) (export gnc:split-get-corr-account-full-name) -(export gnc:account-get-immediate-subaccounts) -(export gnc:account-get-all-subaccounts) (export gnc:acccounts-get-all-subaccounts) (export gnc:make-stats-collector) (export gnc:make-drcr-collector) @@ -579,10 +577,8 @@ (export gnc:accounts-get-comm-total-income) (export gnc:accounts-get-comm-total-expense) (export gnc:accounts-get-comm-total-assets) -(export gnc:group-get-comm-balance-at-date) (export gnc:account-get-balance-interval) (export gnc:account-get-comm-balance-interval) -(export gnc:group-get-comm-balance-interval) (export gnc:accountlist-get-comm-balance-interval) (export gnc:accountlist-get-comm-balance-at-date) (export gnc:query-set-match-non-voids-only!) diff --git a/src/report/report-system/report-utilities.scm b/src/report/report-system/report-utilities.scm index 17b51397df..403688f663 100644 --- a/src/report/report-system/report-utilities.scm +++ b/src/report/report-system/report-utilities.scm @@ -133,6 +133,7 @@ ;; Returns the depth of the current account hierarchy, that is, the +<<<<<<< HEAD ;; maximum level of subaccounts in the current-group. (define (gnc:get-current-group-depth) ;; Given a list of accounts, this function determines the maximum @@ -148,11 +149,18 @@ accounts))) (accounts-get-children-depth (xaccGroupGetAccountListSorted (gnc-get-current-group)))) +======= +;; maximum level of subaccounts in the tree +(define (gnc:get-current-account-tree-depth) + (let ((root (gnc:get-current-root-account))) + (gnc:account-get-depth root))) +>>>>>>> Initial removal of the engine Group.h, GroupP.h, and Group.c files. (define (gnc:split-get-corr-account-full-name split) (xaccSplitGetCorrAccountFullName split)) +<<<<<<< HEAD ;; get children that are the direct descendant of this acct (define (gnc:account-get-immediate-subaccounts acct) (define (acctptr-eq? a1 a2) @@ -178,12 +186,18 @@ (let ((group (xaccAccountGetChildren acct))) (xaccGroupGetSubAccountsSorted group))) +======= +>>>>>>> Initial removal of the engine Group.h, GroupP.h, and Group.c files. ;; Get all children of this list of accounts. (define (gnc:acccounts-get-all-subaccounts accountlist) (append-map (lambda (a) +<<<<<<< HEAD (xaccGroupGetSubAccountsSorted (xaccAccountGetChildren a))) +======= + (gnc:account-get-descendants a)) +>>>>>>> Initial removal of the engine Group.h, GroupP.h, and Group.c files. accountlist)) ;;; Here's a statistics collector... Collects max, min, total, and makes @@ -493,6 +507,7 @@ ;; values rather than double values. (define (gnc:account-get-comm-balance-at-date account date include-children?) +<<<<<<< HEAD (let ((balance-collector (if include-children? (gnc:group-get-comm-balance-at-date @@ -507,6 +522,27 @@ (qof-query-set-sort-order query (list SPLIT-TRANS TRANS-DATE-POSTED) (list QUERY-DEFAULT-SORT) +======= + (let ((balance-collector (gnc:make-commodity-collector)) + (query (gnc:malloc-query)) + (splits #f)) + + (if include-children? + (for-each + (lambda (x) + (gnc:commodity-collector-merge balance-collector x)) + (gnc:account-map-descendants + (lambda (child) + (gnc:account-get-comm-balance-at-date child date #f)) + account))) + + (gnc:query-set-book query (gnc:get-current-book)) + (gnc:query-add-single-account-match query account 'query-and) + (gnc:query-add-date-match-timepair query #f date #t date 'query-and) + (gnc:query-set-sort-order query + (list gnc:split-trans gnc:trans-date-posted) + (list gnc:query-default-sort) +>>>>>>> Initial removal of the engine Group.h, GroupP.h, and Group.c files. '()) (qof-query-set-sort-increasing query #t #t #t) (qof-query-set-max-results query 1) @@ -580,6 +616,7 @@ get-balance-fn (lambda(x) #f))) +<<<<<<< HEAD ;; returns a commodity-collector (define (gnc:group-get-comm-balance-at-date group date) (let ((this-collector (gnc:make-commodity-collector))) @@ -593,6 +630,8 @@ group)) this-collector)) +======= +>>>>>>> Initial removal of the engine Group.h, GroupP.h, and Group.c files. ;; get the change in balance from the 'from' date to the 'to' date. ;; this isn't quite as efficient as it could be, but it's a whole lot ;; simpler :) @@ -618,6 +657,7 @@ include-children?)) this-collector)) +<<<<<<< HEAD ;; the version which returns a commodity-collector (define (gnc:group-get-comm-balance-interval group from to) (let ((this-collector (gnc:make-commodity-collector))) @@ -629,6 +669,8 @@ account from to #t)) group)) this-collector)) +======= +>>>>>>> Initial removal of the engine Group.h, GroupP.h, and Group.c files. ;; This calculates the increase in the balance(s) of all accounts in ;; over the period from to . ;; Returns a commodity collector. @@ -708,11 +750,16 @@ (gnc:accounts-count-splits (cdr accounts))) 0)) -;; Sums up any splits of a certain type affecting a group of accounts. +;; Sums up any splits of a certain type affecting a set of accounts. ;; the type is an alist '((str "match me") (cased #f) (regexp #f)) (define (gnc:account-get-trans-type-balance-interval +<<<<<<< HEAD group type start-date-tp end-date-tp) (let* ((query (qof-query-create-for-splits)) +======= + account-list type start-date-tp end-date-tp) + (let* ((query (gnc:malloc-query)) +>>>>>>> Initial removal of the engine Group.h, GroupP.h, and Group.c files. (splits #f) (get-val (lambda (alist key) (let ((lst (assoc-ref alist key))) @@ -722,10 +769,17 @@ (regexp (if (get-val type 'regexp) #t #f)) (total (gnc:make-commodity-collector)) ) +<<<<<<< HEAD (qof-query-set-book query (gnc-get-current-book)) (gnc:query-set-match-non-voids-only! query (gnc-get-current-book)) (xaccQueryAddAccountMatch query group QOF-GUID-MATCH-ANY QOF-QUERY-AND) (xaccQueryAddDateMatchTS +======= + (gnc:query-set-book query (gnc:get-current-book)) + (gnc:query-set-match-non-voids-only! query (gnc:get-current-book)) + (gnc:query-add-account-match query account-list 'guid-match-any 'query-and) + (gnc:query-add-date-match-timepair +>>>>>>> Initial removal of the engine Group.h, GroupP.h, and Group.c files. query (and start-date-tp #t) start-date-tp (and end-date-tp #t) end-date-tp QOF-QUERY-AND) @@ -751,9 +805,15 @@ ;; similar, but only counts transactions with non-negative shares and ;; *ignores* any closing entries (define (gnc:account-get-pos-trans-total-interval +<<<<<<< HEAD group type start-date-tp end-date-tp) (let* ((str-query (qof-query-create-for-splits)) (sign-query (qof-query-create-for-splits)) +======= + account-list type start-date-tp end-date-tp) + (let* ((str-query (gnc:malloc-query)) + (sign-query (gnc:malloc-query)) +>>>>>>> Initial removal of the engine Group.h, GroupP.h, and Group.c files. (total-query #f) (splits #f) (get-val (lambda (alist key) @@ -765,6 +825,7 @@ (pos? (if (get-val type 'positive) #t #f)) (total (gnc:make-commodity-collector)) ) +<<<<<<< HEAD (qof-query-set-book str-query (gnc-get-current-book)) (qof-query-set-book sign-query (gnc-get-current-book)) (gnc:query-set-match-non-voids-only! str-query (gnc-get-current-book)) @@ -772,6 +833,15 @@ (xaccQueryAddAccountMatch str-query group QOF-GUID-MATCH-ANY QOF-QUERY-AND) (xaccQueryAddAccountMatch sign-query group QOF-GUID-MATCH-ANY QOF-QUERY-AND) (xaccQueryAddDateMatchTS +======= + (gnc:query-set-book str-query (gnc:get-current-book)) + (gnc:query-set-book sign-query (gnc:get-current-book)) + (gnc:query-set-match-non-voids-only! str-query (gnc:get-current-book)) + (gnc:query-set-match-non-voids-only! sign-query (gnc:get-current-book)) + (gnc:query-add-account-match str-query account-list 'guid-match-any 'query-and) + (gnc:query-add-account-match sign-query account-list 'guid-match-any 'query-and) + (gnc:query-add-date-match-timepair +>>>>>>> Initial removal of the engine Group.h, GroupP.h, and Group.c files. str-query (and start-date-tp #t) start-date-tp (and end-date-tp #t) end-date-tp QOF-QUERY-AND) diff --git a/src/report/standard-reports/account-piecharts.scm b/src/report/standard-reports/account-piecharts.scm index 623b4d8202..da6df33085 100644 --- a/src/report/standard-reports/account-piecharts.scm +++ b/src/report/standard-reports/account-piecharts.scm @@ -223,7 +223,7 @@ balance at a given time")) (let* ((exchange-fn (gnc:case-exchange-fn price-source report-currency to-date-tp)) (tree-depth (if (equal? account-levels 'all) - (gnc:get-current-group-depth) + (gnc:get-current-account-tree-depth) account-levels)) (combined '()) (other-anchor "") @@ -251,7 +251,7 @@ balance at a given time")) (for-each (lambda (a) (set! sum (+ sum (+ 1 (count-accounts (+ 1 current-depth) - (gnc:account-get-immediate-subaccounts a)))))) + (gnc:account-get-children a)))))) accts) sum) (length (filter show-acct? accts)))) @@ -281,7 +281,7 @@ balance at a given time")) (set! res (append (traverse-accounts (+ 1 current-depth) - (gnc:account-get-immediate-subaccounts a)) + (gnc:account-get-children a)) res)))) accts) res) @@ -356,8 +356,7 @@ balance at a given time")) (if (string? (cadr pair)) other-anchor (let* ((acct (cadr pair)) - (subaccts - (gnc:account-get-immediate-subaccounts acct))) + (subaccts (gnc:account-get-children acct))) (if (null? subaccts) ;; if leaf-account, make this an anchor ;; to the register. diff --git a/src/report/standard-reports/account-summary.scm b/src/report/standard-reports/account-summary.scm index 00d3479872..572bb186ed 100644 --- a/src/report/standard-reports/account-summary.scm +++ b/src/report/standard-reports/account-summary.scm @@ -315,7 +315,7 @@ (doc (gnc:make-html-document)) ;; just in case we need this information... (tree-depth (if (equal? depth-limit 'all) - (gnc:get-current-group-depth) + (gnc:get-current-account-tree-depth) depth-limit)) ;; exchange rates calculation parameters (exchange-fn diff --git a/src/report/standard-reports/average-balance.scm b/src/report/standard-reports/average-balance.scm index fdb2a45ce0..08aceeabd4 100644 --- a/src/report/standard-reports/average-balance.scm +++ b/src/report/standard-reports/average-balance.scm @@ -353,7 +353,7 @@ (for-each (lambda (acct) (let ((this-acct-subs - (gnc:account-get-all-subaccounts acct))) + (gnc:account-get-descendants acct))) (if (list? this-acct-subs) (set! subaccts (append subaccts this-acct-subs))))) diff --git a/src/report/standard-reports/balance-sheet.scm b/src/report/standard-reports/balance-sheet.scm index 377ed55454..b1b5382cb6 100644 --- a/src/report/standard-reports/balance-sheet.scm +++ b/src/report/standard-reports/balance-sheet.scm @@ -356,7 +356,7 @@ ;; is the only simple way to ensure that all three tables ;; (asset, liability, equity) have the same width. (tree-depth (if (equal? depth-limit 'all) - (gnc:get-current-group-depth) + (gnc:get-current-account-tree-depth) depth-limit)) ;; exchange rates calculation parameters (exchange-fn @@ -423,7 +423,7 @@ (gnc:html-make-no-account-warning reportname (gnc:report-id report-obj))) - ;; Get all the balances for each account group. + ;; Get all the balances for each of the account types. (let* ((asset-balance #f) (neg-liability-balance #f) ;; credit balances are < 0 (liability-balance #f) diff --git a/src/report/standard-reports/budget.scm b/src/report/standard-reports/budget.scm index 3dfb4cb92f..52067e5718 100644 --- a/src/report/standard-reports/budget.scm +++ b/src/report/standard-reports/budget.scm @@ -294,7 +294,7 @@ (apply max (map (lambda (acct) (let ((children - (gnc:account-get-immediate-subaccounts acct))) + (gnc:account-get-children acct))) (if (null? children) 1 (+ 1 (accounts-get-children-depth children))))) diff --git a/src/report/standard-reports/cash-flow.scm b/src/report/standard-reports/cash-flow.scm index c14bf61f54..c0e0c88698 100644 --- a/src/report/standard-reports/cash-flow.scm +++ b/src/report/standard-reports/cash-flow.scm @@ -194,7 +194,7 @@ (apply max (map (lambda (acct) (let ((children - (gnc:account-get-immediate-subaccounts acct))) + (gnc:account-get-children acct))) (if (null? children) 1 (+ 1 (accounts-get-children-depth children))))) @@ -382,7 +382,7 @@ (if (<= (account-get-depth account) tree-depth) (let* ((anchor (gnc:html-markup/format (if (and (= (account-get-depth account) tree-depth) - (not (eq? (gnc:account-get-immediate-subaccounts account) '()))) + (not (eq? (gnc:account-get-children account) '()))) (if show-subaccts? (_ "%s and subaccounts") (_ "%s and selected subaccounts")) diff --git a/src/report/standard-reports/category-barchart.scm b/src/report/standard-reports/category-barchart.scm index 808d8e24f9..8bea1cabed 100644 --- a/src/report/standard-reports/category-barchart.scm +++ b/src/report/standard-reports/category-barchart.scm @@ -227,7 +227,7 @@ developing over time")) (let* ((commodity-list #f) (exchange-fn #f) (tree-depth (if (equal? account-levels 'all) - (gnc:get-current-group-depth) + (gnc:get-current-account-tree-depth) account-levels)) ;; This is the list of date intervals to calculate. (dates-list (if do-intervals? @@ -297,7 +297,7 @@ developing over time")) (for-each (lambda (a) (set! sum (+ sum (+ 1 (count-accounts (+ 1 current-depth) - (gnc:account-get-immediate-subaccounts a)))))) + (gnc:account-get-children a)))))) accts) sum) (length (filter show-acct? accts)))) @@ -331,7 +331,7 @@ developing over time")) (set! res (append (traverse-accounts (+ 1 current-depth) - (gnc:account-get-immediate-subaccounts a)) + (gnc:account-get-children a)) res)))) accts) res) @@ -487,7 +487,7 @@ developing over time")) other-anchor (let* ((acct (car pair)) (subaccts - (gnc:account-get-immediate-subaccounts acct))) + (gnc:account-get-children acct))) (if (null? subaccts) ;; if leaf-account, make this an anchor ;; to the register. diff --git a/src/report/standard-reports/daily-reports.scm b/src/report/standard-reports/daily-reports.scm index 73ed979cd9..b6befcfd21 100644 --- a/src/report/standard-reports/daily-reports.scm +++ b/src/report/standard-reports/daily-reports.scm @@ -391,7 +391,7 @@ (for-each (lambda (acct) (let ((this-acct-subs - (gnc:account-get-all-subaccounts acct))) + (gnc:account-get-descendants acct))) (if (list? this-acct-subs) (set! subaccts (append subaccts this-acct-subs))))) diff --git a/src/report/standard-reports/income-statement.scm b/src/report/standard-reports/income-statement.scm index 7b9f805010..0ee4c78ddb 100644 --- a/src/report/standard-reports/income-statement.scm +++ b/src/report/standard-reports/income-statement.scm @@ -347,7 +347,7 @@ ;; is the only simple way to ensure that both tables ;; (revenue, expense) have the same width. (tree-depth (if (equal? depth-limit 'all) - (gnc:get-current-group-depth) + (gnc:get-current-account-tree-depth) depth-limit)) ;; exchange rates calculation parameters (exchange-fn @@ -411,7 +411,7 @@ (gnc:html-make-no-account-warning reportname (gnc:report-id report-obj))) - ;; Get all the balances for each account group. + ;; Get all the balances for each of the account types. (let* ((revenue-closing #f) (expense-closing #f) (neg-revenue-total #f) From 97f61cbea95bda08868c1c94341afc68fa8e90be Mon Sep 17 00:00:00 2001 From: David Hampton Date: Tue, 22 Aug 2006 02:43:21 +0000 Subject: [PATCH 02/14] Mark a couple of functions as static. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/branches/remove-group@14704 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/engine/Account.c | 4 ++-- src/engine/Account.h | 2 -- src/engine/SX-book-p.h | 1 - src/engine/SX-book.c | 4 ++-- src/engine/SX-book.h | 1 - 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/engine/Account.c b/src/engine/Account.c index 614cad1cda..7389ae56fe 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -152,14 +152,14 @@ xaccInitAccount (Account * acc, QofBook *book) /********************************************************************\ \********************************************************************/ -Account * +static Account * gnc_coll_get_root_account (QofCollection *col) { if (!col) return NULL; return qof_collection_get_data (col); } -void +static void gnc_coll_set_root_account (QofCollection *col, Account *root) { Account *old_root; diff --git a/src/engine/Account.h b/src/engine/Account.h index c65c24e288..fdf02c5826 100644 --- a/src/engine/Account.h +++ b/src/engine/Account.h @@ -212,8 +212,6 @@ const gchar *gnc_get_account_separator_string (void); gunichar gnc_get_account_separator (void); void gnc_set_account_separator (const gchar *separator); -Account *gnc_coll_get_root_account(QofCollection *col); -void gnc_coll_set_root_account(QofCollection *col, Account *root); Account *gnc_book_get_root_account(QofBook *book); void gnc_book_set_root_account(QofBook *book, Account *root); diff --git a/src/engine/SX-book-p.h b/src/engine/SX-book-p.h index 04faefa88d..ccfa5d9758 100644 --- a/src/engine/SX-book-p.h +++ b/src/engine/SX-book-p.h @@ -49,7 +49,6 @@ void gnc_collection_set_schedxactions( QofCollection *col, GList *newList ); /* Associate the given template root account with a book */ void gnc_book_set_template_root (QofBook *book, Account *templateRoot); -void gnc_collection_set_template_root (QofCollection *col, Account *templateRoot); diff --git a/src/engine/SX-book.c b/src/engine/SX-book.c index 3ee1b67776..17bd08c6ee 100644 --- a/src/engine/SX-book.c +++ b/src/engine/SX-book.c @@ -52,7 +52,7 @@ static QofLogModule log_module = GNC_MOD_SX; /* ====================================================================== */ -Account * +static Account * gnc_collection_get_template_root( const QofCollection *col ) { return qof_collection_get_data (col); @@ -67,7 +67,7 @@ gnc_book_get_template_root( QofBook *book ) return gnc_collection_get_template_root (col); } -void +static void gnc_collection_set_template_root (QofCollection *col, Account *templateRoot) { diff --git a/src/engine/SX-book.h b/src/engine/SX-book.h index f118aba5e6..b16cba9d0e 100644 --- a/src/engine/SX-book.h +++ b/src/engine/SX-book.h @@ -49,7 +49,6 @@ GList * gnc_book_get_schedxactions(QofBook *book); /** Returns the template group from the book. **/ Account *gnc_book_get_template_root(QofBook *book); -Account *gnc_collection_get_template_root(const QofCollection *col); /** @return The list of SXes which reference the given Account. Caller should free this list. **/ GList* gnc_sx_get_sxes_referencing_account(QofBook *book, Account *acct); From e28c8cdc22bbb879eb20a35afc6de2b50253b2b5 Mon Sep 17 00:00:00 2001 From: David Hampton Date: Tue, 22 Aug 2006 21:51:36 +0000 Subject: [PATCH 03/14] Don't require the root account to have a commodity. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/branches/remove-group@14713 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/backend/file/gnc-account-xml-v2.c | 3 +-- src/backend/file/io-gncxml-v2.c | 3 +-- src/engine/Account.c | 4 +--- src/engine/Account.h | 2 +- src/engine/Scrub.c | 1 + 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/backend/file/gnc-account-xml-v2.c b/src/backend/file/gnc-account-xml-v2.c index e59edba44f..53cd0987eb 100644 --- a/src/backend/file/gnc-account-xml-v2.c +++ b/src/backend/file/gnc-account-xml-v2.c @@ -447,8 +447,7 @@ gnc_account_end_handler(gpointer data_for_children, if (type != ACCT_TYPE_ROOT) { root = gnc_book_get_root_account(book); if (root == NULL) { - gnc_commodity *com = xaccAccountGetCommodity(acc); - root = gnc_account_create_root(book, com); + root = gnc_account_create_root(book); } gnc_account_append_child(root, acc); } diff --git a/src/backend/file/io-gncxml-v2.c b/src/backend/file/io-gncxml-v2.c index 6b35ea6daf..5603ab6775 100644 --- a/src/backend/file/io-gncxml-v2.c +++ b/src/backend/file/io-gncxml-v2.c @@ -191,8 +191,7 @@ add_account_local(sixtp_gdv2 *data, Account *act) if (parent == NULL) { root = gnc_book_get_root_account(data->book); if (root == NULL) { - gnc_commodity *com = xaccAccountGetCommodity(act); - root = gnc_account_create_root(data->book, com); + root = gnc_account_create_root(data->book); /* Leave the account in the edit state. It will be committed * at the end of reading all the transactions. */ xaccAccountBeginEdit(root); diff --git a/src/engine/Account.c b/src/engine/Account.c index 7389ae56fe..639c0618de 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -219,15 +219,13 @@ xaccMallocAccount (QofBook *book) } Account * -gnc_account_create_root (QofBook *book, gnc_commodity *com) +gnc_account_create_root (QofBook *book) { Account *root; root = xaccMallocAccount(book); xaccAccountBeginEdit(root); root->type = ACCT_TYPE_ROOT; - root->commodity = com; - root->commodity_scu = gnc_commodity_get_fraction(com); xaccAccountCommitEdit(root); gnc_book_set_root_account(book, root); return root; diff --git a/src/engine/Account.h b/src/engine/Account.h index fdf02c5826..9f35efd1bb 100644 --- a/src/engine/Account.h +++ b/src/engine/Account.h @@ -148,7 +148,7 @@ typedef enum Account * xaccMallocAccount (QofBook *book); /** Create a new root level account. */ -Account * gnc_account_create_root (QofBook *book, gnc_commodity *com); +Account * gnc_account_create_root (QofBook *book); /** The xaccCloneAccount() does the same as xaccCloneAccountSimple(), * except that it also also places a pair of GUID-pointers diff --git a/src/engine/Scrub.c b/src/engine/Scrub.c index f4637313b9..9d18612bea 100644 --- a/src/engine/Scrub.c +++ b/src/engine/Scrub.c @@ -666,6 +666,7 @@ xaccAccountScrubCommodity (Account *account) gnc_commodity *commodity; if (!account) return; + if (xaccAccountGetType(account) == ACCT_TYPE_ROOT) return; commodity = xaccAccountGetCommodity (account); if (commodity) return; From 9ee43458cd3566fdadb44151c8a263d5cfc10ba5 Mon Sep 17 00:00:00 2001 From: David Hampton Date: Wed, 23 Aug 2006 03:09:40 +0000 Subject: [PATCH 04/14] Fix a mistake in the updated tree model. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/branches/remove-group@14714 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 3 +++ src/gnome-utils/gnc-tree-model-account.c | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3b049f99f1..69e9080a19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -94,6 +94,9 @@ 2006-08-20 David Hampton + * src/gnome-utils/gnc-tree-model-account.c: Fix a mistake in the + updated tree model. + * src/backend/file/gnc-account-xml-v2.c: * src/backend/file/gnc-commodity-xml-v2.c: * src/gnome/top-level.c: Remove some conditional code that is no diff --git a/src/gnome-utils/gnc-tree-model-account.c b/src/gnome-utils/gnc-tree-model-account.c index e356402647..1cf3287bd7 100644 --- a/src/gnome-utils/gnc-tree-model-account.c +++ b/src/gnome-utils/gnc-tree-model-account.c @@ -920,9 +920,10 @@ gnc_tree_model_account_iter_n_children (GtkTreeModel *tree_model, priv = GNC_TREE_MODEL_ACCOUNT_GET_PRIVATE(model); if (iter == NULL) { - num = gnc_account_n_children(priv->root); - LEAVE("count is %d", num); - return num; + /* How many children does the invisible root node + * have. One! Its the real root account node. */ + LEAVE("count is 1"); + return 1; } g_return_val_if_fail (iter != NULL, FALSE); From 97e65c9d7422ec2854ba4aa12f1194dfd1ea0310 Mon Sep 17 00:00:00 2001 From: David Hampton Date: Wed, 23 Aug 2006 03:17:29 +0000 Subject: [PATCH 05/14] Make sure the root account exists when the code asks for it. This works both for reading a new file and a user performing File->New->New File. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/branches/remove-group@14715 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 5 +++++ src/backend/file/io-gncxml-v2.c | 7 ------- src/engine/Account.c | 7 ++++++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 69e9080a19..ebe303e324 100644 --- a/ChangeLog +++ b/ChangeLog @@ -94,6 +94,11 @@ 2006-08-20 David Hampton + * src/backend/file/io-gncxml-v2.c: + * src/engine/Account.c: Make sure the root account exists when the + code asks for it. This works both for reading a new file and a + user performing File->New->New File. + * src/gnome-utils/gnc-tree-model-account.c: Fix a mistake in the updated tree model. diff --git a/src/backend/file/io-gncxml-v2.c b/src/backend/file/io-gncxml-v2.c index 5603ab6775..0327316cb5 100644 --- a/src/backend/file/io-gncxml-v2.c +++ b/src/backend/file/io-gncxml-v2.c @@ -190,12 +190,6 @@ add_account_local(sixtp_gdv2 *data, Account *act) parent = gnc_account_get_parent(act); if (parent == NULL) { root = gnc_book_get_root_account(data->book); - if (root == NULL) { - root = gnc_account_create_root(data->book); - /* Leave the account in the edit state. It will be committed - * at the end of reading all the transactions. */ - xaccAccountBeginEdit(root); - } gnc_account_append_child(root, act); } } @@ -776,7 +770,6 @@ qof_session_load_from_xml_file_v2_full( gnc_account_foreach_descendant(root, (AccountCb) xaccAccountCommitEdit, NULL); - xaccAccountCommitEdit (root); /* start logging again */ xaccLogEnable (); diff --git a/src/engine/Account.c b/src/engine/Account.c index 639c0618de..7f0cea3edd 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -180,9 +180,14 @@ Account * gnc_book_get_root_account (QofBook *book) { QofCollection *col; + Account *root; + if (!book) return NULL; col = qof_book_get_collection (book, GNC_ID_ROOT_ACCOUNT); - return gnc_coll_get_root_account (col); + root = gnc_coll_get_root_account (col); + if (root == NULL) + root = gnc_account_create_root(book); + return root; } void From 2390690d4d4a9cb3c8f28d5b27b8358a73dfde87 Mon Sep 17 00:00:00 2001 From: David Hampton Date: Wed, 23 Aug 2006 03:20:42 +0000 Subject: [PATCH 06/14] Merge account trees properly. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/branches/remove-group@14716 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 2 ++ src/app-utils/gnc-account-merge.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ebe303e324..fe195933e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -94,6 +94,8 @@ 2006-08-20 David Hampton + * src/app-utils/gnc-account-merge.c: Merge account trees properly. + * src/backend/file/io-gncxml-v2.c: * src/engine/Account.c: Make sure the root account exists when the code asks for it. This works both for reading a new file and a diff --git a/src/app-utils/gnc-account-merge.c b/src/app-utils/gnc-account-merge.c index 98006a7b77..27623a893e 100644 --- a/src/app-utils/gnc-account-merge.c +++ b/src/app-utils/gnc-account-merge.c @@ -44,7 +44,7 @@ account_trees_merge(Account *existing_root, Account *new_accts_root) Account *existing_named, *new_acct; const char *name; - new_acct = (Account*)accounts->data; + new_acct = (Account*)node->data; name = xaccAccountGetName(new_acct); existing_named = gnc_account_lookup_name(existing_root, name); switch (determine_account_merge_disposition(existing_named, new_acct)) From b171307ad9983e35c059146fd1a47c859ce0d7fb Mon Sep 17 00:00:00 2001 From: David Hampton Date: Mon, 25 Dec 2006 18:29:57 +0000 Subject: [PATCH 07/14] Sync changes 15066:15252 into the branch. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/branches/remove-group2@15254 57a11ea4-9604-0410-9ed3-97b8803252fd --- AUTHORS | 38 +- README | 10 +- README.dependencies | 23 +- configure.in | 13 +- doc/README.francais | 704 ++++++------------ lib/libqof/qof/Makefile.am | 4 +- lib/libqof/qof/qofquerycore.c | 8 +- lib/libqof/qof/qofsession-p.h | 1 + lib/libqof/qof/qofsession.c | 26 +- lib/libqof/qof/qofsession.h | 1 + macros/ac_pkg_swig.m4 | 7 +- packaging/win32/custom.sh | 98 +-- packaging/win32/dist.sh | 183 +++++ packaging/win32/functions | 87 +++ packaging/win32/gnucash.iss.in | 98 +-- packaging/win32/goffice-0.3.2-patch.diff | 91 +++ packaging/win32/install.sh | 479 ++++++------ src/app-utils/Makefile.am | 3 +- src/app-utils/gnc-component-manager.c | 8 +- src/app-utils/gnc-ui-util.c | 36 +- src/app-utils/gnc-ui-util.h | 28 +- src/backend/file/gnc-account-xml-v2.c | 2 +- src/backend/file/gnc-backend-file.c | 17 +- src/backend/file/gnc-commodity-xml-v2.c | 16 +- src/backend/file/gnc-transaction-xml-v2.c | 2 +- src/backend/file/io-gncxml-v2.c | 2 +- src/backend/file/test/test-xml-account.c | 2 +- src/backend/file/test/test-xml-commodity.c | 2 +- src/backend/file/test/test-xml-pricedb.c | 2 +- src/backend/file/test/test-xml-transaction.c | 2 +- src/base-typemaps.i | 8 +- src/bin/Makefile.am | 1 + src/bin/gnucash-bin.c | 12 +- src/business/business-core/Makefile.am | 4 +- .../business-core/file/gnc-invoice-xml-v2.c | 2 +- .../business-core/file/gnc-order-xml-v2.c | 2 +- src/business/business-core/gncAddress.c | 6 +- src/business/business-core/gncBillTerm.c | 4 +- src/business/business-core/gncCustomer.c | 6 +- src/business/business-core/gncEmployee.c | 6 +- src/business/business-core/gncEntry.c | 6 +- src/business/business-core/gncInvoice.c | 6 +- src/business/business-core/gncJob.c | 4 +- src/business/business-core/gncOrder.c | 6 +- src/business/business-core/gncTaxTable.c | 6 +- src/business/business-core/gncVendor.c | 6 +- src/business/business-gnome/Makefile.am | 1 + src/business/business-reports/aging.scm | 3 +- src/business/business-reports/invoice.scm | 4 +- src/business/business-utils/Makefile.am | 1 + src/business/dialog-tax-table/Makefile.am | 2 +- src/core-utils/Makefile.am | 2 +- src/core-utils/gnc-gobject-utils.c | 2 +- src/engine/Account.c | 6 +- src/engine/Makefile.am | 10 +- src/engine/SchedXaction.c | 4 +- src/engine/Split.c | 19 +- src/engine/TransLog.c | 2 +- src/engine/binreloc.c | 33 - src/engine/binreloc.h | 2 - src/engine/gnc-budget.c | 4 +- src/engine/gnc-commodity.c | 4 +- src/engine/gnc-lot.c | 4 +- src/engine/gnc-path.c | 25 +- src/engine/gnc-path.h | 5 +- src/engine/gnc-pricedb.c | 4 +- src/engine/gncla-dir.h.in | 7 +- src/engine/kvp-scm.c | 16 +- src/gnc-module/Makefile.am | 2 +- src/gnc-module/gnc-module.c | 32 +- src/gnc-module/gnc-module.h | 4 +- src/gnome-utils/Makefile.am | 6 +- src/gnome-utils/argv-list-converters.c | 126 ---- src/gnome-utils/argv-list-converters.h | 58 -- src/gnome-utils/dialog-transfer.c | 4 + src/gnome-utils/druid-gconf-setup.c | 23 +- src/gnome-utils/gnc-dense-cal.c | 17 +- src/gnome-utils/gnc-file.c | 36 +- src/gnome-utils/gnc-frequency.c | 11 +- src/gnome-utils/gnc-gnome-utils.c | 8 +- src/gnome-utils/gnc-html.c | 19 +- src/gnome-utils/gnc-main-window.c | 80 +- src/gnome-utils/gnc-plugin-file-history.c | 24 +- src/gnome-utils/gnc-tree-view.c | 6 +- src/gnome/Makefile.am | 3 +- src/gnome/dialog-sxsincelast.c | 112 ++- src/gnome/druid-hierarchy.c | 6 + src/gnome/druid-loan.c | 36 +- src/gnome/druid-merge.c | 4 +- src/gnome/glade/account.glade | 2 +- src/gnome/gnc-plugin-basic-commands.c | 39 +- src/gnome/top-level.c | 4 +- src/gnome/ui/gnc-plugin-basic-commands-ui.xml | 8 +- src/import-export/hbci/gnc-file-aqb-import.c | 7 +- src/import-export/hbci/gnc-hbci-getbalance.c | 4 + src/import-export/log-replay/gnc-log-replay.c | 12 +- src/import-export/ofx/gnc-ofx-import.c | 11 +- src/import-export/qif-import/Makefile.am | 1 + .../qif-import/druid-qif-import.c | 18 +- src/import-export/qif-import/qif-file.scm | 5 +- .../qif-import/qif-merge-groups.scm | 2 +- src/import-export/qif-import/qif-parse.scm | 2 +- src/import-export/qif-import/qif-to-gnc.scm | 2 +- src/pixmaps/Makefile.am | 1 + src/pixmaps/gnucash-icon.ico | Bin 0 -> 8522 bytes src/report/report-gnome/Makefile.am | 3 +- .../report-gnome/gnc-plugin-page-report.c | 14 +- src/report/report-system/Makefile.am | 2 +- src/report/report-system/report.scm | 8 +- .../standard-reports/account-piecharts.scm | 3 +- .../standard-reports/category-barchart.scm | 3 +- 111 files changed, 1474 insertions(+), 1532 deletions(-) create mode 100644 packaging/win32/dist.sh create mode 100644 packaging/win32/functions create mode 100644 packaging/win32/goffice-0.3.2-patch.diff delete mode 100644 src/gnome-utils/argv-list-converters.c delete mode 100644 src/gnome-utils/argv-list-converters.h create mode 100644 src/pixmaps/gnucash-icon.ico diff --git a/AUTHORS b/AUTHORS index 54c2ebad05..595fb18c61 100644 --- a/AUTHORS +++ b/AUTHORS @@ -25,16 +25,14 @@ Jeremy Collins publicized the GnoMoney project he put the selection of the name up to popular vote. We all learned that democracy is not a good way to pick names.) Jeremy registered the domain name, and created and maintained the gnucash.org web site - for years, and got the initial GTK/gnome code working. The newest - website design is Jeremy's as well. + for years, and got the initial GTK/gnome code working. Rob Browning abused everyone for not using perl, and then after we added Perl support, dumped Perl in favor of - Guile/Scheme support. Rob maintined the build infrastructure for a - while, added user preferences, and re-wrote the reports in scheme. - One of Rob's recent contributions is the change-over of the - file-format to XML. He is now concentrating on scheme performance. - He is the g-wrap guile wrapper maintainer. + Guile/Scheme support. Rob added user preferences, re-wrote the + reports in scheme, and contributed the change-over of the + file-format to XML. He then concentrated on scheme performance and + has been the g-wrap guile wrapper maintainer. Dave Peticolas worked on most parts of Gnucash, especially the register and GUI. @@ -52,12 +50,13 @@ James LewisMoss design doc patches, XML refactoring, automated test suite, new file hierarchy import. Christian Stimming is a report-generating - monster. He's been one of the largest contributors to the current report - infrastructure, creating many of the important reports. - He has also contributed HBCI support. + monster. He's been one of the largest contributors to the report + infrastructure, creating many of the important reports initially. + He has also contributed HBCI online banking support and manages + internationalization and translation. Joshua Sled works on scheduled transactions - and budgeting. + and budgeting. The current website design is his as well. Derek Atkins wrote the business-accounting package for Gnucash. This includes the Customer/Vendor database, Job tracking, @@ -73,19 +72,23 @@ David Hampton is an all-around hacker. He hack obsessively on GnuCash. (Something in the name?) Chris Lyttle Administers the GnuCash bug list. - Is currently writing new help and integrating and finishing a - concepts and tutorial written by Carol Champagne. Looks after + Improved the help and integrated and finished a concepts and + tutorial written by Carol Champagne. Looks after releasing new GnuCash versions and updating the website. Benoit Grégoire coded a long awaited OFX module for GnuCash and wrote the external libOFX library that it uses. Neil Williams finished conversion from GncBook - to QofBook and the separation of QoF into a standalone library. - Lots of Doxygen fixes and updates. + to QofBook and worked on the separation of QoF into a standalone + library. He also contributed lots of Doxygen fixes and updates. Chris Shoemaker implemented budgeting support - for GnuCash. He is also an all around hacker. + for GnuCash. He replaced g-wrap by SWIG as GnuCash's guile wrapper + generator and is also an all around hacker. + +Andreas Köhler is hunting down lots of bugs, + especially for GUI code and other gtk related issues. Other Contributors: ---------------- @@ -94,6 +97,7 @@ Other Contributors: Mike Alexander Cap gains, lot and MacOS fixes. Andrew Arensburger for FreeBSD & other patches Matt Armstrong for misc fixes +Jon Arney Windows porting patches, misc fixes A. Alper Atici Turkish translation Fred Baube for attempted Java port/MoneyDance Roman Bertle Austrian German account templates @@ -160,7 +164,6 @@ Prakash Kailasa for gnome build fixes Alexey Kakunin quickfill patch for Cyrillic Ben Kelly for Motif menu bug fix, core dump fixes Tom Kludy for SGI Irix port -Andreas Köhler German translation Matt Kraai date accelerator bug fix Sven Kuenzler for SuSE README file Fabrice Kurz French translation @@ -220,6 +223,7 @@ Tomas Pospisek Debian patches Paul Poulain French translations Ron Record for SCO Unixware & OpenServer binaries Keith Refson Solaris fixes +Jerry Quinn Bugfixes Andreas Rottmann fixes for g-wrap 1.9 Betina Schmidt German account template Dirk Schoenberger Qt/KDE work diff --git a/README b/README index f1da190e71..a78b98e0d1 100644 --- a/README +++ b/README @@ -243,7 +243,7 @@ Building & Installing GnuCash uses GNU Automake to handle the build process, so for most of the details, see the generic instructions in INSTALL. (If you are -building directory from CVS, read the README.cvs for more instructions.) +building directory from SVN, read the README.svn for more instructions.) Below we detail the GnuCash specific bits. Prior to building GnuCash, you will have to obtain and install the @@ -261,7 +261,7 @@ following packages: http://www.gnucash.org/pub/g-wrap. You should use g-wrap 1.3.4 or later. - texinfo: If you are building from CVS, you need the GNU texinfo + texinfo: If you are building from SVN, you need the GNU texinfo package, version 4.0 or later. What you'll need to get and install in order to make sure you have all @@ -279,7 +279,7 @@ you'll need for the systems we know about: SuSE: - see README.dependencies and doc/build-suse.txt + see README.dependencies GnuCash understands a few non-standard ./configure options. You should run ./configure --help for the most up to date summary of the @@ -365,7 +365,7 @@ You can download GnuCash Solaris packages from: - http://www.unixrealm.com/downloads/ -You can get GnuCash Mandrake packages on Mandrake Cooker sites. +You can get GnuCash Mandrake packages on Mandriva Cooker sites. Precompiled binaries & pre-requisite packages can be found at the @@ -436,7 +436,7 @@ Before you start developing GnuCash, you should do the following: Submitting a Patch: - This section has been removed to the file README.patches + This section has been moved to the file README.patches Please consult that file for details on using the script provided to make patches suitable for submitting to the GnuCash development team. diff --git a/README.dependencies b/README.dependencies index a4f98388dd..edc26a91c7 100644 --- a/README.dependencies +++ b/README.dependencies @@ -66,6 +66,7 @@ libart2 libglade2 libgnomeprint2.2 libgnomeui2 +[lib]goffice libgsf1 [lib]gtkhtml3 libofx @@ -205,12 +206,32 @@ The major distributions, as defined by http://distrowatch.com/dwres.php?resource - libxml-2.6.17 - pango-1.8.1 - libgtkhtml-3.1.11 -- SUSE +- SUSE / opensuse + - 10.2 = 2006-12-07 + - aqbanking-2.2.3 + - cairo-1.2.4 + - gconf2-2.14.0 + - glib2-2.12.4 + - goffice-0.2.1 + - gtk2-2.10.6 + - gtkhtml2-3.12.2 + - guile-1.8.1 + - g-wrap: not included + - libart_lgpl-2.3.17 + - libglade2-2.6.0 + - libgnomeprint-2.12.1 + - libgnomeui-2.16.1 + - libgsf-1.14.2 + - libofx-0.8.2 + - libxml2-2.6.26 + - pango-1.14.5 + - swig-1.3.29 - 10.1 = 2006-05-11 - aqbanking-1.2.0 (but package is broken; needs to be replaced by >=1.3.0) - cairo-1.0.2 - gconf2-2.12.1 - glib2-2.8.5 + - goffice-0.1.2 - gtk2-2.8.10 - gtkhtml2-3.10.0 - guile-1.6.7 diff --git a/configure.in b/configure.in index 9eca90fc5a..11de7db846 100644 --- a/configure.in +++ b/configure.in @@ -836,12 +836,13 @@ AC_SUBST(HBCI_DIR) ### -------------------------------------------------------------------------- ### i18n -AC_ARG_WITH( locale-dir, - [ --with-locale-dir=PATH specify where to look for locale-specific information], - LOCALE_DIR="$with_locale_dir", - LOCALE_DIR="\${prefix}/share/locale") - -AC_SUBST(LOCALE_DIR) +# This variable is set by GLIB_WITH_NLS, called through +# AM_GLIB_GNU_GETTEXT above. Usually it is "share", but on some +# platforms it is "lib". Make sure it is set. +if test "x$DATADIRNAME" = "x"; then + DATADIRNAME="share" + AC_SUBST(DATADIRNAME) +fi dnl check for nl_langinfo(D_FMT) which is missing on FreeBSD LANGINFO_D_FMT_CHECK diff --git a/doc/README.francais b/doc/README.francais index 81fcf10575..2bc27bfee1 100644 --- a/doc/README.francais +++ b/doc/README.francais @@ -1,213 +1,145 @@ -####################################################################### - Fichier README de Gnucash 1.5.x . - -NOTE: C'EST UNE VERSION DE DEVELOPPEMENT!!! CETTE VERSION N'A PAS -ETE TESTEE CORRECTEMENT ET PEUT FAIRE ABSOLUMENT N'IMPORTE QUOI! - -UTILISEZ LA A VOS PROPRES RISQUES (ET FAITES *BEAUCOUP* DE SAUVEGARDES) - -Si vous voulez quelque chose de plus testé, s'il vous plaît utilisez -les series stables 1.4. ------------------------------------------------------------------------ +########################################### + GnuCash version 2.0.x +------------------------------------------- ######### Sommaire: --------- - Vue d'ensemble - - Mise à jour depuis la version 1.2.x - - Dépendences + - Mise à jour depuis la version 1.8.x + - Dépendances - Mise en route - Internationalisation - Compilation et installation - - OS supportés - - Sites additionnels de téléchargement - - Récupérer les sources avec CVS + - plates-formes supportées + - Sites de téléchargement miroirs + - Récupérer les sources avec SVN - Développement de GnuCash -############### + +############## Vue d'ensemble ---------------- +-------------- -GnuCash est un gestionnaire de finances personnelles.Une interface -graphique d'enregistrement ressemblant au talon de votre chéquier -vous permet d'entrer et de suivre vos comptes bancaires,actions, -revenus et même les marchés des changes. L'interface est conçu pour -être simple et facile à utiliser, mais elle est adossée à -des principes de comptabilité de la partie double pour -s'assurer que les livres sont équilibrés. +GnuCash est un gestionnaire de finances personnelles. Une interface graphique +d'enregistrement ressemblant au talon de votre chéquier vous permet d'entrer et +de suivre vos comptes bancaires, actions, revenus et même vos opérations +boursières. L'interface est conçue pour être simple et facile à utiliser, mais +elle est adossée aux principes de comptabilité de la partie double pour assurer +l'équilibre des comptes. Quelques une de ces caractéristiques sont: - - Une interface facile à utiliser. Si vous savez utiliser - le talon de votre chéquier, vous savez utiliser GnuCash. - Tapez directement dans le registre, - déplacez vous entre les champs, et utilisez quick-fill - (saisie rapide) pour compléter automatiquement la transaction. - L'interface est personalisable depuis l'application elle-même - (pas de fichiers de config à modifier :) ). - - Importation de fichiers Quicken: Importation de fichiers au format - QIF de Quicken. - Les fichiers QIF sont automatiquement fusionnés pour éliminer - les transactions dupliquées - - La fenêtre de rapprochement avec soldes actuels rapprochés et - pointés rend le rapprochement facile. - - Potefeuille d'actions/fonds de placements (SICAV et FCP en France): - Suivi d'actions individuellement (une par compte) ou dans un - portefeuille de comptes (un groupe de comptes qui peuvent - être affiché ensemble). - - Récupère les cours des actions et fonds communs (FCP et SICAV) depuis - différents sites web, met à jour automatiquement le porte-feuille - (plus de fonds étant ajouter régulièrement). - - Rapports: Affichent la feuille bilan , pertes et profits, évaluation du - portefeuille, rapports de transactions, ou suivi du solde du compte, - ou exportation de ceux-ci en HTML. Vous pouvez écrire votre propre - rapport personalisé si vous connaissez un peu Scheme. Les rapports - peuvent maintenant être réalisés sur une période comptable! - - Monnaies/devises multiples et Marché des changes: - De multiple monnaies sont supportées et peuvent être achetées - et vendus(faire du commerce avec elles). Les mouvements monétaires - entre comptes sont totallement équilibrés quand la partie double - est activée. - (Quelques aspects du support de multiples monnaies ne sont pas - totallement implémentés. - - Tableau de comptes: Un compte maitre/principal peut avoir une arborescence - de comptes détaillés en desssous de lui. Celà permet d'avoir des types de - comptes similaires (par exemple Liquidités, Banque, Actions) - groupés dans un compte maitre (par exemple Avoirs). - - Transactions réparties: Une simple transaction peut être répartie - en plusieurs morceaux pour enregistrer les impôts, paiements, et - autres entrées composées. - - Partie double: Quand elle est activé, chaque transaction - doit débiter un compte et créditer un autre d'un montant équivalent. - Celà permet de s'assurer que les "livres sont équilibrés": - c'est à dire que la différence entre les revenus et les sorties est - exactement égale à la somme de tous les avoirs, qu'ils soit bancaire, - liquidités, actions ou autre. - - Types de comptes Revenus/Dépenses (Catégories): - Ils ne servent pas uniquement à catégoriser votre flux - de liquidités/argent, mais quand ils sont utilisés avec la fonction de - la partie double, ceux-ci peuvent fournir un état exact des pertes et - profits et donc du résultat de la période. - - Extrait de compte/grand livre: De multiples comptes peuvent être affichés - dans une fenêtre registre/d'enregistrement au même moment. Celà peut - faciliter l'ennui de la recherche/vérification des erreurs de - frappe/d'entrée. - Il fournit aussi une manière agréable de visualiser un porte-feuille de - beaucoup d'actions, en montrant toutes les transactions dans ce - portefeuille. - - Ecrit en C avec un support étendu de scheme via Guile. - - Le support de Perl est disponible en option pour les scripts fonctionnant - via SWIG. - - L'accès au fichier est verrouillé par un drapeau de sécurité réseau, - prévenant des dommages accidentels si plusieurs utilisateurs essaient - d'accéder au même fichier, même si le fichier est monté par NFS. - - Fournit un format de flux de données(byte-stream format), qui permet aux - comptes et groupes de comptes d'être transmi par d'autres processus - via pipes ou sockets. - - Chargement de la date au format européen, traductions française, - anglaise, allemande et suédoise. +* Une interface facile à utiliser. Si vous savez utiliser le talon de votre +chéquier, vous savez utiliser GnuCash. Tapez directement dans le registre, +déplacez vous entre les champs, et utilisez quick-fill (saisie rapide) pour +compléter automatiquement la transaction. L'interface est personnalisable depuis +l'application elle-même (pas de fichiers de config à modifier :) ). +* Transactions récurrentes : GnuCash a la possibilité de générer automatiquement +des transactions, de rappeler leur échéance, de proposer de la valider ou de la +retarder et également de les supprimer après un certain temps. +* Importation de fichiers OFX : GnuCash est le premier logiciel libre à +supporter le protocole « Open Financial Exchange » qui est de plus en plus +utilisé par les banques. Le développement du support OFX et HBCI a permis une +amélioration du mécanisme permettant de retrouver des transactions homologues +et les doublons. +* Support de l'HBCI : GnuCash est le premier logiciel libre à supporter le +protocole allemand d'opérations bancaires en ligne +* Importation de fichiers Quicken: Importation de fichiers au format QIF de +Quicken. Les fichiers QIF sont automatiquement fusionnés pour éliminer les +transactions dupliquées. +* La fenêtre de rapprochement avec les soldes actuels rapprochés et pointés rend +le rapprochement facile. +* Portefeuille d'actions/fonds de placements (SICAV et FCP en France): suivi +d'actions individuellement (une par compte) ou dans un portefeuille de comptes +(un groupe de comptes qui peuvent être affichés ensemble). +* Récupération des cours des actions et fonds communs (FCP et SICAV) depuis +différents sites Web, mise à jour automatique du portefeuille. +* Rapports : affichent le bilan , les pertes et profits, évaluation du +portefeuille, rapports de transactions, ou suivi du solde du compte, ou +exportation de ceux-ci en HTML. Vous pouvez écrire votre propre rapport +personnalisé si vous connaissez un peu le langage Scheme. Les rapports peuvent +maintenant être réalisés sur une période comptable. +* Monnaies/devises multiples et Marché des changes : de multiple monnaies sont +supportées et peuvent être achetées et vendues (faire du commerce avec elles). +Les mouvements monétaires entre comptes sont totalement équilibrés quand la +partie double est activée. Les transferts en devises multiples sont supportés. +* Tableau de comptes : un compte maître/principal peut avoir une arborescence +de comptes détaillés en dessous de lui. Cela permet d'avoir des types de +comptes similaires (par exemple Liquidités, Banque, Actions) groupés dans un +compte maître (par exemple Avoirs). +* Transactions réparties : une simple transaction peut être répartie en +plusieurs morceaux pour enregistrer les impôts, paiements, et autres entrées +composées. +* Partie double: Quand elle est activée, chaque transaction doit débiter un +compte et créditer un autre d'un montant équivalent. Cela permet de s'assurer +que les "livres sont équilibrés" : c'est à dire que la différence entre les +revenus et les sorties est exactement égale à la somme de tous les avoirs, +qu'ils soient bancaire, liquidités, actions ou autre. +* Types de comptes Revenus/Dépenses (Catégories) : ils ne servent pas uniquement +à catégoriser votre flux de liquidités/argent, mais quand ils sont utilisés avec +la fonction de la partie double, ceux-ci peuvent fournir un état exact des +pertes et profits et donc du résultat de la période. +* Extrait de compte/grand livre : de multiples comptes peuvent être affichés +dans une fenêtre registre/d'enregistrement au même moment. Cela peut faciliter +l'ennui de la recherche/vérification des erreurs de frappe/d'entrée. Il fournit +aussi une manière agréable de visualiser un portefeuille de beaucoup d'actions, +en montrant toutes les transactions dans ce portefeuille. +* Écrit en C avec un support étendu de Scheme via Guile. +* L'accès au fichier est verrouillé par un drapeau de sécurité réseau, prévenant +des dommages accidentels si plusieurs utilisateurs essaient d'accéder au même +fichier, même si le fichier est monté par NFS. +* Fournit un format de flux de données (byte-stream format), qui permet aux +comptes et groupes de comptes d'être transmis par d'autres processus via pipes +ou sockets. +* Chargement de la date au format européen, traductions diverses. +* Nouveau manuel utilisateur : une toute nouvelle aide en ligne a été écrite : +elle se focalise sur comment faire les actions en relation avec un tutoriel et +un guide des concepts. +* De nouveaux menus : les menus de GnuCash ont été revus pour se conformer aux +principes d'interface de Gnome. Home Page: http://gnucash.org/ (site officiel - version anglaise) -http://www.multimania.com/yleny/gnucash (version française) Binaires précompilés / exécutables: http://www.gnucash.org/pub/gnucash/ Versions de développement: -http://www.gnucash.org/source_code.php3 - +http://www.gnucash.org/en/hacking.phtml ################################### -Mise à jour depuis la version 1.2.x +Mise à jour depuis la version 1.8.x ----------------------------------- -Il y a beaucoup, beaucoup de changements depuis la serie 1.2 - -donnez un coup d'oeil au fichier NEWS si vous voulez plus de détails. -Toutefois, le plus important pour l'installation est que GnuCash -maintenant requiert les librairies Gnome à la place de Motif, et guile -est requis. Regardez la section "dépendances" de ce fichier pour plus -de détails. Le format de fichier n'a pas changé -(mais faites une sauvegarde de vos données de toute façon . . . ) - -Nous espérons que vous vous amuserez avec toutes les nouvelles fonctionnalités! - -############ -Dépendences ------------- - -Les packages suivants sont requis et doivent être installé pour faire -fonctionner gnucash: +Il y a beaucoup, beaucoup de changements depuis la série 1.8 - +Jetez un coup d'oeil au fichier NEWS si vous voulez plus de détails. -guile -- Fournit l'infrastructure du langage d'extension principal. - Il est utilisé intensivement par gnucash pour l'initialisation - et le démarrage. - Requiert la version 1.3 ou ultérieure/plus récente. - Le rpm guile-1.3-7 fonctionne. +- GnuCash nécessite g-wrap version 1.3.4 ou supérieur. Consultez la section « +Dépendances » pour plus de détails. -slib -- librairies scheme pour guile. A besoin de slib2c4 ou ultérieure. +- Les données ne sont plus accessibles à partir de la version 1.6 une fois de +nouvelles fonctionnalités utilisées : il n'y a pas de compatibilité +descendante. Sauvegardez vos données!! -libpng -- librairie PNG(portable network graphics). N'importe quelle version. +- La documentation de GnuCash est désormais déplacée dans un package séparé +(gnucash-docs). si vous voyez un message du type « URL non trouvée », en +cliquant un item du menu Aide, vous devrez installer la package gnucash-docs. -libjpeg -- librairie de chargement d'image JPEG. N'importe quelle version. +Nous espérons que vous vous apprécierez toutes les nouvelles fonctionnalités! -libz -- librairie de compression. N'importe quelle version. - -xpm -- extension Pixmap pour X. N'importe quelle version. - -gnome-libs: la version 1.0.40 ou ultérieure/plus récente devrait fonctionner. - Ces librairies requièrent des librairies supportant de nombreuses - autres, tel que gtk et glib. - -gnome-print: N'importe quelle version récente devrait fonctionner. - -gdk-pixbuf: N'importe quelle version devrait fonctionner. - -gtkhtml: La version 0.4 ou ultérieure/plus récente devrait fonctionner. - Vous pouvez obtenir la dernière version de gtkhtml depuis - Helix Code. (voir site ftp Gnome: ftp.gnome.org) - Noter que celà à changé depuis la 1.4, qui utilisait la vieille - librairie gtkxmhtml. - Pour compiler les sources de GtkHTML-0.4, il faut gdk-pixbuf 0.7.0 - (ou ultérieure), Bonobo 0.15 (ou ultérieure) et gnome-print 0.16 - (ou ultérieure). - -Pour avoir la possibilité d'utiliser certaines fonctionnalitées de GnuCash, -tel que les rapports et les téléchargements de cours d'actions par le réseau, -vous devez avoir les packages suivant ci-dessous installés -(en plus de ceux listés ci-dessus). - -Les RPM pour la plupart de ceux-ci peuvent être trouvés à - http://rufus.w3.org/linux/ - -perl -- A peu près n'importe quelle version de perl5 devrait fonctionner. - J'utilise perl-5.004 - -En plus, quelques modules perl ont besoin d'être installés: +############ +Dépendances +------------ -perl-LWP/libwww-perl-5.36 -perl-HTML/HTML-0.6 -perl-HTML/HTML-Parser-2.20 - -- ces modules perl sont utilisés pour récupérer les cours des - actions et fonds de placements à partir d'internet. Vous pouvez - récupérer ces RPMS à: - ftp://ftp.gnucash.org/pub/gnucash/binaries/RPMS - http://rufus.w3.org/linux/RPM/PByName.html - http://linas.org/linux/gnucash (en dernier recours) - ou les sources à - http://www.cpan.org/CPAN.html +Les packages suivants sont requis et doivent être installés pour faire +fonctionner GnuCash: - Si vous souhaitez utiliser le rapport de suivi du solde et avoir de superbes - graphiques, - vous aurez besoin d'installer: +[Consultez le fichier README.dependencies] - gnuplot: Un programme de dessin. - Les RPM et debs sont disponible depuis les distributeurs - Vous pouvez récupérer les sources depuis: - http://www.gnuplot.vt.edu/ ############# Mise en route @@ -215,183 +147,102 @@ Mise en route Pour les détails d'invocation/de lancement de GnuCash, regardez les pages de man dans doc/gnucash.1. -Bientôt, nous aurons aussi la possibilité de lancer gnucash --help, mais ce -n'est pas encore fini ... - -Vous pouvez démarrer GnuCash en ligne de commande, avec "gnucash" ou "gnucash -", où est un fichier de compte de GnuCash. -Des exemples de comptes peuvent être trouvé dans le sous-répertoire "data". -les fichiers *.dat sont les comptes de GnuCash qui peuvent être ouvert avec -l'entrée du menu "Ouvrir fichier". Les fichiers *.qif sont des fichiers -au format d'importation Quicken qui peuvent être ouvert avec l'entrée du menu -"Importer QIF". - -GnuCash répond aux variables d'environnement suivantes: +Vous pouvez également taper gnucash --help sur la ligne de commande. - GNC_RUN_AS_SHELL - si activé, permet à GnuCash de s'ouvrir dans un shell - guile avec toutes les fonctions de gnucash chargées. Depuis là, vous pouvez - récupérer comportement du démarrage normal comme ceci: +Vous pouvez démarrer GnuCash en ligne de commande, avec « gnucash » ou « gnucash + », où est un fichier de données de GnuCash. - GNC_RUN_AS_SHELL=t ./gnucash - guile> (primitive-load (getenv "GNC_BOOTSTRAP_SCM")) - guile> (gnc:load "startup.scm") - guile> (gnc:main) +Des exemples de comptes peuvent être trouvés dans le sous-répertoire "data". +Les fichiers *.xac sont les comptes de GnuCash qui peuvent être ouverts avec +le menu « Fichier/Ouvrir ». +Les fichiers *.qif sont des fichiers au format Quicken qui peuvent être ouverts +par le menu « Fichier/Importer QIF ». - C'est la même chose qui se passe si vous n'utilisez pas cette variable - d'environnement. Celà peut être utile quand vous essayez d'écrire et tester - de nouveaux fichiers .scm. +GnuCash répond aux variables d'environnement suivantes : GNC_BOOTSTRAP_SCM - l'emplacement du code scheme initial de bootstrapping. - GNC_SCM_LOAD_PATH - une contrainte pour le chemin de chargement de scheme - pour GnuCash.Il devrait être une chaine représentant une liste scheme - appropriée. Chaque élément peut soit être une chaine représentant un - répertoire, soit le symbole par défaut qui s'étendra au chemin par défaut, - ou l'actuel qui s'étendra au chemin de chargement par défaut au moment où - il rencontre le symbole. - - GNC_DEBUG - active la sortie de débogage. Celà vous permet d'activer - le débogage précédent dans le processus de démarrage que vous pouvez faire - avec --debug. - -Comme exemple, voici un script d'encapsulation (wrapper script) que nous -utilisons pour vous permettre d'utiliser de lancer gnucash depuis le répertoire -local: + GUILE_LOAD_PATH - Pour surpasser le chemin de GnuCash utilisé pour le + chargement de fichiers Scheme. C'est une variable de la même forme que les + variables d'environnement PATH ou LIBRARY_PATH. - #! /bin/sh + GNC_MODULE_PATH - Pour surpasser le chemin de GnuCash utilisé pour le + chargement de modules GnuCash. C'est une variable de la même forme que les + variables d'environnement PATH ou LIBRARY_PATH. - export G - - NC_BOOTSTRAP_SCM=./share/scm/bootstrap.scm - export GNC_SCM_LOAD_PATH='("./share/scm")' - export GNC_DEBUG=t - - # Run whichever one was built last. - exec ./src/gnucash \ - --debug \ - --share-dir ./share \ - --config-dir ./etc \ - --doc-path '("./doc/html/C")' \ - "$@" + GNC_DEBUG - active la sortie de débogage. Cela vous permet d'activer + le débogage dans le processus de démarrageplus rapidement qu'avec l'option + --debug. ########################### Internationalisation (i18n) --------------------------- -Des catalogues de messages existent pour le français et l'allemand. Ceux-ci -sont activés avec les variables d'environnement. Par example, +Des traductions (fichiers .po) existent pour différentes langues. Ceux-ci +sont activés avec les variables d'environnement. Par exemple, En français, avec bash: export LANG=fr_FR - + En français, avec tcsh: setenv LANG fr_FR - + Pour la version allemande: export LANG=de_DE - - -Les autres locales qui devrait pour la plupart fonctionner, mais sont -toujours en développement: - -en_US -en_GB -fr_CH -de_CH -(Gnucash utilise gettext maintenant, alors il faut utiliser -les fichiers *.po , le traduire et le compiler par msgfmt. -exemple: msgfmt fr.po --output=./gnucash.mo en ligne de commande -dans /gnucash/po pour le fichier pour la france et copier gnucash.mo sur une -redhat 6.1 GPL dans /usr/share/locale/fr/LC_MESSAGES et vous aurez vos menus -et messages en français.) +########################### +Compilation et installation +--------------------------- -############################ -Compilation et installation: ----------------------------- - -Ces étapes ne s'applique pas aux distributions de binaires; uniquement aux -distributions de sources. - -Pour plus de détails sur le système de compilation, regardez -doc/README.build-system.) +[Pour plus de détails sur la compilation, lisez doc/README.build-system] GnuCash utilise GNU Automake pour traiter le processus de compilation, donc pour plus de détails, regardez les instructions générales dans INSTALL. -(Notez que, pour avoir un ./configure fonctionnant, vous devrez lancer -./autogen.sh.) -Ci-dessous nous détaillons les parties spécifiques de Gnucash. - + +Ci-dessous nous détaillons les parties spécifiques de GnuCash. + Avant de compiler GnuCash, vous devrez obtenir et installer les packages suivants: -libtool : Utiliser pour compiler nos versions internes de g-wrap qui charge - nos encapsuleurs C avec guile. - Disponible à ftp://ftp.gnu.org/gnu. - Les RPMs et debs sont largement disponible avec la plupart des +libtool : Disponible à ftp://ftp.gnu.org/gnu. + Les RPMs et debs sont largement disponibles avec la plupart des distributions. -SWIG : Utilisé pour autogénérer les encapsuleurs perl. - Disponible à www.swig.org - nécessite 1.1p5 ou ultérieure ... - système de développement gnome: en-têtes (headers), librairies, etc. -ibxml: disponible sur ftp.gnome.org + +libxml: disponible sur ftp.gnome.org g-wrap : Les RPM's, debs, et sources sont disponibles à - ftp://ftp.gnucash.org/pub/g-wrap. - Si vous utilisez guile version 1.4 ou ultérieure, vous avez besoin de - g-wrap 0.9.5 ou ultérieure. Si vous utilisez une précédente version - de guile, vous devrez utilisez g-wrap 0.9.4. + http://www.gnucash.org/pub/g-wrap. + vous devrez utilisez g-wrap 1.3.4 ou supérieur - texinfo: Si vous compilez le CVS, vous avez besoin du package GNU texinfo, - version 4.0 ou ultérieure. +texinfo: Si vous compilez depuis svn, vous avez besoin du package GNU texinfo, + version 4.0 ou ultérieure. - docbook: Pour compiler le manuel en ligne, vous aurez besoin des outils - docbook, incluant jade et les feuillles de style (stylesheets) de docbook . - -Ce que vous aurez besoin de récupérer et d'installer dans l'ordre pour être -sûr que vous ayez tous ces éléments corectement installés pour votre -système d'exploitation favorit en particulier variera, mais ici se trouve au -moins une liste partielle de ce que vous aurez besoin pour les systèmes -que nous connaissons: +Ce que vous aurez besoin de récupérer et d'installer pour être sûr d'avoir +tous ces éléments correctement installés dépendra de votre système +d'exploitation , mais ici se trouve une liste partielle de ce que vous aurez +besoin pour les systèmes que nous connaissons: - Debian/GNU/Linux: + Debian/GNU/Linux: (cf README.dependencies) actuel: libgnome-dev - libgtkhtml-dev (vous pouvez le récupérer depuis Helixcode, il n'est pas - dans la Debian) - guile1.3 - libguile6-dev - libguile6-slib - - RedHat: - ??? - -GnuCash comprend quelques options de ./configure non-standard. Vous -devriez lancer ./configure --help pour le résumé le plus à jour des options -supportées, mais ici se trouvent quelques descriptions sétaillées de -quelques-unes d'entre elles: - - --enable-opt-style-install - - Gnucash supporte deux types d'installation, la première est le style normal - /usr ou /usr/local/ , où les fichiers sont installés dans - /usr/bin /usr/lib, etc. Celà se fait par défaut. - - Le second style est le FSSTND, l'installation de style opt. Dans ce style, - tous les fichiers sont installés sous un sous-répertoire commun,souvent - dans /usr/local/opt, avec les exécutables allant dans - /usr/local/opt/foo/bin, les librairies allant dans /usr/local/opt/foo/lib, - etc. Pour demander ce style d'installation, utilisez uniquement l'option - --enable-opt-style-install de ./configure. - -Si seulement vous voulez q'une langue en particulier soit installée, vous -pouvez mettre la variable d'environnement LINGUAS avant de lancer configure. + libgtkhtml-dev + guile1.4 + libguile9-dev + libguile9-slib + + +GnuCash comprend quelques options non-standard de ./configure . Vous +devriez lancer « ./configure --help » pour la liste la plus à jour des options +supportées. + +Si vous voulez seulement qu'une langue en particulier soit installée, vous +pouvez définir la variable d'environnement LINGUAS avant de lancer ./configure. Par exemple, pour installer seulement les traductions française, lancez $ export LINGUAS=fr @@ -402,127 +253,94 @@ Si vous voulez $ unset LINGUAS $ ./configure -La dernière version 1.2 stable de GnuCash avait une interface utilisateur basée -sur Motif, et il y avait aussi un expérimental, mais jamais terminé interface -en QT. -L'ensemble de ceux-ci ont été enlevé de l'arborescence des sources durant le -processus de migration vers automake, mais quelqu'un qui est intéressé par la -resurrection de ces parties peut facilement les retrouver dans le CVS. -Notez que tandis que vous avez besoin des librairies Gnome installées, vous -n'avez pas besoin d'avoir le bureau/interface Gnome. - -Les destinations de lancement et d'installations sont séparées. Le --prefix -que vous spécifiez à configure détermine où les exécutables résultant seront -regardé pour des choses au lancement. Normallement celà détermine où un -"make install" mettra tous les fichiers. Toutefois, automake aussi supporte la -variable. DESTDIR est utilisé durant l'étape `make install' pour relocaliser -les objets d'installation dans un endroit prédisposé. Chaque objet et chemin -est préfixé avec la valeur de `DESTDIR' avant d'être copié dans l'endroit -d'installation. -Voici un exemple d'usage typique de DESTDIR: - - make DESTDIR=/tmp/staging install - - Celà place les objets d'installation dans une arborescence de répertoire - construit sous `/tmp/staging'. Si `/gnu/bin/foo' et - `/gnu/share/aclocal/foo.m4' sont à être installés, - la commande ci-dessous devrait installer -`/tmp/staging/gnu/bin/foo' et `/tmp/staging/gnu/share/aclocal/foo.m4'. +Bien que vous ayez besoin des librairies Gnome installées, vous n'avez pas +besoin d'utiliser le bureau/interface Gnome. + +Les chemins de lancement et d'installations sont séparées. Le --prefix que vous +spécifiez à ./configure détermine le chemin où les exécutables chercheront des +fichiers à leur lancement. Normalement, cela détermine où « make install » +installera les fichiers. Cependant, automake supporte également des variables. +DESTDIR est utilisée pendant le processus « make install » pour installer des +objets dans un répertoire tampon. Chaque objet et chemin est préfixé avec la +valeur de 'DESTDIR' avant d'être copié dans les répertoires d'installation. + + make DESTDIR=/tmp/staging install + +Cela place les objets d'installation dans une arborescence de répertoire +construit sous `/tmp/staging'. +Si `/gnu/bin/foo' et /gnu/share/aclocal/foo.m4' doivent être installés, la +commande ci-dessus installera `/tmp/staging/gnu/bin/foo' et +`/tmp/staging/gnu/share/aclocal/foo.m4'. DESTDIR peut être utile quand on essaie de construire des images d'installation et des packages. -############### -Os supportés : ---------------- -La version 1.5.X de GnuCash est connu pour fonctionner sur les systèmes +######################## +Plates-formes supportées +------------------------ + +La version 2.0.x de GnuCash est réputer fonctionner sur les systèmes d'exploitation suivants: -GNU/Linux -- x86, Sparc, Alpha +GNU/Linux -- x86, Sparc, Alpha Solaris -- Sparc -FreeBSD -- x86 -OpenBSD -- x86 +FreeBSD -- x86 +OpenBSD -- x86 +MacOS X -- PPC -Les précédente versions sont connu pour fonctionner sur les -plateformes suivantes, mais leurs états actuels sont inconnus: +Les précédentes versions étaient réputées fonctionner sur les plateformes +suivantes : -SGI IRIX -- MIPS +SGI IRIX -- MIPS IBM AIX 4.1.5 -- RS/6000 http://www-frec.bull.com/ Unixware 7 -- Intel SCO OpenServer 5.0.4 -- Intel -regardez à ftp://ftp.gnucash.org/pub/xacc (grande-bande passante) -ou http://linas.org/linux/gnucash (slow-www ) -pour les binaires précompilés ( mais *très vieilles*) pour ces plateformes. +GnuCash peut probablement fonctionner avec la plupart des plateformes POSIX, si +les librairies et les outils sont disponibles. -Gnucash peut probablement être fait pour fonctionner avec la plupart des -plateformes POSIX, si les les librairies fournies et les outils sont -disponibles. -##################################### -Sites additionnels de téléchargement: -------------------------------------- +############################### +Sites de téléchargement miroirs +------------------------------- -Vous pouvez aussi télécharger gnucash à partir de: +Vous pouvez aussi télécharger GnuCash à partir de: - http://download.sourceforge.net/gnucash - - ftp://ftp.krondo.com + Vous pouvez télécharger les packages Solaris de GnuCash à partir de: - http://www.unixrealm.com/downloads/ -Vous pouvez récupérer les packages Mandrake de GnuCash sur les sites Cooker de -Mandrake. - -Les binaires précompilés et les packages pré-requis peuvent être trouvé sur -les sites suivants.Les versions de Gnucash ici sont toutes *extrêmement* -vieilles, et sont en fait de l'ancêtre de gnucash : "x-accountant ou xacc". - -IBM AIX 4.1.5 - -- SMIT-installable images - -- warning, this is from the 1.0 series of xacc - http://www.bull.de/pub/ - see also http://www-frec.bull.com/ - -SCO OpenServer 5.0.4 - http://www.sco.com/skunkware/osr5/x11/apps/xacc/VOLS.tar - -- warning, this is from the 1.0 series of xacc +Vous pouvez récupérer les packages Mandriva de GnuCash sur les sites Cooker de +Mandriva ou dans les dernières versions de la distribution) -Unixware 7 - -- use pkgadd to install - http://www.sco.com/skunkware/uw7/x11/apps/xacc/xacc.pkg.gz - -SGI Irix - -- in SGI install format - -- warning, this is a very down-level version - http://linas.org/linux/xacc/xacc-1.0b7-sgi-irix.inst.tar +##################################### +Récupérer les sources avec Subversion +------------------------------------- -############################### -Récupérer les sources avec CVS -------------------------------- +Une version en lecture seule de l'arborescence Subversion est disponible à +cette adresse : -Une version en lecture-seule de l'arborescence de cvs tree est disponible -sur le net. -Pour y accéder, premièrement, loggger vous, comme ceci: + http://svn.gnucash.org/repo/gnucash/ - cvs -d :pserver:cvs@cvs.gnucash.org:/home/cvs/cvsroot login +Pour obtenir ce qui fut le CVS HEAD (et ce qui inclus maintenant ce qui était +gnucash-gnome2-dev), vous devrez obtenir le svn TRUNK : -Le mot de passe (password)est "guest" + svn checkout http://svn.gnucash.org/repo/gnucash/trunk gnucash -Pour récupérer une copie des sources dans l'arborescence de développpement -expérimental faites un +L'argument « gnucash » ci dessus peut être n'importe quel nom de répertoire sur +votre disque local, et est optionnel. Si vous l'omettez, vous aurez un +répertoire nommé « trunk » contenant les sources. -cvs -z3 -d :pserver:cvs@cvs.gnucash.org:/home/cvs/cvsroot checkout -r HEAD -gnucash +Si vous voulez obtenir les derniers sources de la version 2.0.x, vous devrez +les récupérer dans le branche 2.0, comme suit : -Pour récupérer une copie des sources de l'arborescence de la version de -production stable gnucash-1.4, faites un + svn checkout http://svn.gnucash.org/repo/gnucash/branches/2.0 gnucash-2.0 -cvs -z3 -d :pserver:cvs@cvs.gnucash.org:/home/cvs/cvsroot checkout -r -gnucash-1-4-branch gnucash ######################## Développement de GnuCash @@ -530,101 +348,27 @@ D Avant de démarrer à développer sur GnuCash, vous devriez faire les choses suivantes: -1. lisez le fichier src/coding-style.txt pour apprendre les styles - de codage utilisés dans le code source de GnuCash. +1. lisez le fichier src/doc/coding-style.txt pour apprendre les styles + de codage utilisés dans le code source de GnuCash. Lisez également + http://wiki.gnucash.org/wiki/Development 2. Plusieurs des répertoires sous src contiennent des fichiers appellés design.txt qui expliquent beaucoup des aspects de la conception de GnuCash. Lisez les. -3. Allez sur le site web de gnucash et survoler les archives de la liste de - courriers de développement de gnucash(development mailing list). +3. Allez sur le site web de GnuCash et survoler les archives de la liste de + diffusion du développement de GnuCash (gnucash-devel). -4. Rejoignez la liste de courriers de développement de gnucash(development - mailing list). - Regardez le site web de gnucash pour des détails sur comment faire celà. + 4. Rejoignez la liste de diffusion de développement de GnuCash + (gnucash-devel). Regardez le site web de GnuCash pour des détails sur la + méthode pour y parvenir. Soumettre un patch -Dès que vous avez fait un certain travail que vous aimeriez soumettre, vous -avez besoin d'envoyer un patch. Il y a un script perl appelé make-gnucash-patch -fourni avec la distribution que vous pouvez utiliser pour créer le patch. -Ici, se trouve comment utiliser ce script perl. - -Premièrement, configurer vos répertoires de développement comme ce qui suit: - -< Répertoire de développement maison (home) de GnuCash > - | - |---- < répertoire contenant les sources originales de GnuCash > - | - |---- < répertoire contenant vos sources modifiées de GnuCash > - -Un exemple concret de ces répertoires devrait être: - -/home/me/gnucash - | - |---- /home/me/gnucash/gnucash.pristine (sources originales) - | - |---- /home/me/gnucash/gnucash.mywork (sources originales + mes modifs) - -Copier le script make-gnucash-patch vers le répertoire de développement maison -(/home/me/gnucash au-dessus). Maintenant metter les trois variables en haut -de ce fichier pour refléter les noms de vos répertoires. Les noms donnés -ci-dessous, vous devriez les utiliser - - export GNC_MAKEPATCH_OLD_DIR=gnucash.pristine - export GNC_MAKEPATCH_NEW_DIR=gnucash.mywork - export GNC_MAKEPATCH_HOME_DIR=/home/me/gnucash - -Bien sûr avant de faire votre, soyez sûr *qu'ensemble* votre répertoire de -travail et votre répertoire pristine sont synchroniser avec le cvs. -Lancez 'cvs -z3 update -dP' dans l'ensemble des répertoires pour vous assurer -que c'est le cas. -La mise à jour depuis le cvs dans votre répertoire de travail -peut causer les conflits dans un fichier. -Vous devez résoudre ces conflits avant de faire un patch. - - -Maintenant lancer le script. Notez que le script requiert les programmes -'makepatch', 'gzip', 'diff', et 'uuencode' (et, bien sûr , 'perl') -pour fonctionner. - -Quand vous lancez le script, trois fichiers seront générés: - - gnc.diff - Ce fichier est un fichier texte ascii contenant les différences - entre les sources originales et vos modifications. En bas de ce - fichier se trouve une liste de fichiers qui sont ajoutés, - changés, ou supprimés. - - S'il vous plait examinez ce fichier (spéciallement la liste en -bas) - pour être sûr que tous vos changements (et pas d'autres -changements) - sont présent dans le fichier. - - Ne pas soumettre ce fichier! - - gnucash.diff.gz - C'est une version gzippé du fichier au-dessus. - - Ne pas soumettre ce fichier! - - gnucash.diff.gz.uue - C'est une version uuencodée (ascii-encodé) - du fichier au-dessus. - - C'est le fichier à soumettre. - -Envoyez gnucash.diff.gz.uue à gnucash-patches@gnucash.org - -Merci par avance pour votre contribution! - +[Cette section a été transférée dans le fichier README.patches] -Traduction faite le 12/11/00 par Yannick LE NY -Cette traduction n'est peut-etre plus à jour, -donc référez vous au fichier README en anglais. -Pour toutes remarques ou suggestions: -y-le-ny@ifrance.com +Lisez SVP ce fichier sur les méthodes utilisées pour transmettre un patch à +l'équipe de développement de GnuCash. -Local Variables: -mode: text -End: +Merci, diff --git a/lib/libqof/qof/Makefile.am b/lib/libqof/qof/Makefile.am index 0af4d21a5b..45bc80740d 100644 --- a/lib/libqof/qof/Makefile.am +++ b/lib/libqof/qof/Makefile.am @@ -82,8 +82,6 @@ noinst_HEADERS = \ qofquerycore-p.h \ qofsession-p.h -QOFLIBdir = $(QOF_LIB_DIR) - EXTRA_DIST = \ qofla-dir.h.in \ qofmath128.c @@ -91,7 +89,7 @@ EXTRA_DIST = \ qofla-dir.h: $(srcdir)/qofla-dir.h.in Makefile rm -f $@.tmp sed < $< > $@.tmp \ - -e 's#@-libdir-@#${QOFLIBdir}#g' + -e 's#@-libdir-@#${QOF_LIB_DIR}#g' mv $@.tmp $@ BUILT_SOURCES = qofla-dir.h diff --git a/lib/libqof/qof/qofquerycore.c b/lib/libqof/qof/qofquerycore.c index bf29a01b23..e51352033c 100644 --- a/lib/libqof/qof/qofquerycore.c +++ b/lib/libqof/qof/qofquerycore.c @@ -269,11 +269,17 @@ qof_query_string_predicate (QofQueryCompare how, pdata->matchstring = g_strdup (str); if (is_regex) { + int rc; int flags = REG_EXTENDED; if (options == QOF_STRING_MATCH_CASEINSENSITIVE) flags |= REG_ICASE; - regcomp(&pdata->compiled, str, flags); + rc = regcomp(&pdata->compiled, str, flags); + if (rc) { + g_free(pdata->matchstring); + g_free(pdata); + return NULL; + } pdata->is_regex = TRUE; } diff --git a/lib/libqof/qof/qofsession-p.h b/lib/libqof/qof/qofsession-p.h index 3ba3cb6080..1b22eebcf4 100644 --- a/lib/libqof/qof/qofsession-p.h +++ b/lib/libqof/qof/qofsession-p.h @@ -63,6 +63,7 @@ struct _QofSession /* Pointer to the backend that is actually used to move data * between the persistant store and the local engine. */ QofBackend *backend; + gint lock; }; diff --git a/lib/libqof/qof/qofsession.c b/lib/libqof/qof/qofsession.c index dbc46691af..ea6f43051a 100644 --- a/lib/libqof/qof/qofsession.c +++ b/lib/libqof/qof/qofsession.c @@ -197,6 +197,7 @@ qof_session_init (QofSession *session) session->books = g_list_append (NULL, qof_book_new ()); session->book_id = NULL; session->backend = NULL; + session->lock = 1; qof_session_clear_error (session); } @@ -1051,7 +1052,7 @@ qof_session_begin (QofSession *session, const char * book_id, g_free(session->book_id); session->book_id = NULL; qof_session_push_error (session, err, msg); - LEAVE(" backend error %d %s", err, msg); + LEAVE(" backend error %d %s", err, msg ? msg : "(null)"); return; } if (msg != NULL) @@ -1193,8 +1194,10 @@ qof_session_save (QofSession *session, int err; gint num; char *msg, *book_id; - + if (!session) return; + if (!g_atomic_int_dec_and_test(&session->lock)) + goto leave; ENTER ("sess=%p book_id=%s", session, session->book_id ? session->book_id : "(null)"); /* Partial book handling. */ @@ -1260,7 +1263,7 @@ qof_session_save (QofSession *session, session->book_id = NULL; qof_session_push_error (session, err, msg); LEAVE("changed backend error %d", err); - return; + goto leave; } if (msg != NULL) { @@ -1280,11 +1283,11 @@ qof_session_save (QofSession *session, p = p->next; } } - if(!session->backend) + if(!session->backend) { msg = g_strdup_printf("failed to load backend"); qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg); - return; + goto leave; } } /* If there is a backend, and the backend is reachable @@ -1308,7 +1311,8 @@ qof_session_save (QofSession *session, if (be->sync) { (be->sync)(be, abook); - if (save_error_handler(be, session)) return; + if (save_error_handler(be, session)) + goto leave; } } /* If we got to here, then the backend saved everything @@ -1316,7 +1320,7 @@ qof_session_save (QofSession *session, /* Return the book_id to previous value. */ qof_session_clear_error (session); LEAVE("Success"); - return; + goto leave; } else { @@ -1324,9 +1328,17 @@ qof_session_save (QofSession *session, qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg); } LEAVE("error -- No backend!"); + leave: + g_atomic_int_inc(&session->lock); + return; } /* ====================================================================== */ +gboolean +qof_session_save_in_progress(QofSession *session) +{ + return (session && g_atomic_int_get(&session->lock) != 1); +} void qof_session_end (QofSession *session) diff --git a/lib/libqof/qof/qofsession.h b/lib/libqof/qof/qofsession.h index 92ea05edca..2e4364e318 100644 --- a/lib/libqof/qof/qofsession.h +++ b/lib/libqof/qof/qofsession.h @@ -222,6 +222,7 @@ const char * qof_session_get_url (QofSession *session); * if any data in the session hasn't been saved to long-term storage. */ gboolean qof_session_not_saved(QofSession *session); +gboolean qof_session_save_in_progress(QofSession *session); /** Allows the backend to warn the user if a dataset already exists. */ gboolean qof_session_save_may_clobber_data (QofSession *session); diff --git a/macros/ac_pkg_swig.m4 b/macros/ac_pkg_swig.m4 index cc5a137d54..406bc4b32b 100644 --- a/macros/ac_pkg_swig.m4 +++ b/macros/ac_pkg_swig.m4 @@ -74,15 +74,16 @@ AC_DEFUN([AC_PROG_SWIG],[ SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false' else AC_MSG_NOTICE([SWIG executable is '$SWIG']) - SWIG_LIB=`$SWIG -swiglib` - AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB']) +dnl We do not make use of SWIG_LIB and `$SWIG -swiglib` made problems on MinGW (output was two lines) +dnl SWIG_LIB=`$SWIG -swiglib` +dnl AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB']) fi else AC_MSG_ERROR([cannot determine SWIG version]) SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false' fi fi - AC_SUBST([SWIG_LIB]) +dnl AC_SUBST([SWIG_LIB]) ]) # SWIG_ENABLE_CXX() diff --git a/packaging/win32/custom.sh b/packaging/win32/custom.sh index 05b8c11139..73b834f864 100644 --- a/packaging/win32/custom.sh +++ b/packaging/win32/custom.sh @@ -6,9 +6,11 @@ GLOBAL_DIR=c:\\soft TMP_DIR=$GLOBAL_DIR\\tmp DOWNLOAD_DIR=$GLOBAL_DIR\\downloads -REPOS_URL="http://svn.gnucash.org/repo/gnucash/trunk" -REPOS_DIR=$GLOBAL_DIR\\repos GNUCASH_DIR=$GLOBAL_DIR\\gnucash +REPOS_URL="http://svn.gnucash.org/repo/gnucash/trunk" +REPOS_DIR=$GNUCASH_DIR\\repos +BUILD_DIR=$GNUCASH_DIR\\build +INSTALL_DIR=$GNUCASH_DIR\\inst #### cross_compile="no" @@ -46,14 +48,15 @@ GNOME_MIRROR="ftp.gnome.org/pub/gnome" DTK_URL="$SF_MIRROR/mingw/msysDTK-1.0.1.exe" -MINGW_URL="$SF_MIRROR/mingw/MinGW-5.0.2.exe" +MINGW_URL="$SF_MIRROR/mingw/MinGW-5.1.0.exe" MINGW_DIR=$GLOBAL_DIR\\mingw UNZIP_URL="$SF_MIRROR/gnuwin32/unzip-5.51-1.exe" UNZIP_DIR=$GLOBAL_DIR\\unzip -REGEX_BIN_URL="$SF_MIRROR/gnuwin32/regex-0.12-bin.zip" -REGEX_LIB_URL="$SF_MIRROR/gnuwin32/regex-0.12-lib.zip" +# do not use regex-gnu or regex-spencer v3.8.g3, see bug #382852 +REGEX_BIN_URL="$SF_MIRROR/gnuwin32/regex-spencer-3.8-bin.zip" +REGEX_LIB_URL="$SF_MIRROR/gnuwin32/regex-spencer-3.8-lib.zip" REGEX_DIR=$GLOBAL_DIR\\regex READLINE_BIN_URL="$SF_MIRROR/gnuwin32/readline-5.0-bin.zip" @@ -66,6 +69,11 @@ INDENT_DIR=$GLOBAL_DIR\\indent ACTIVE_PERL_URL="http://downloads.activestate.com/ActivePerl/Windows/5.6/ActivePerl-5.6.1.638-MSWin32-x86.zip" ACTIVE_PERL_DIR=$GLOBAL_DIR\\active-perl +AUTOCONF_URL="http://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.bz2" +AUTOMAKE_URL="http://ftp.gnu.org/gnu/automake/automake-1.9.6.tar.bz2" +LIBTOOL_URL="http://ftp.gnu.org/gnu/libtool/libtool-1.5.22.tar.gz" +AUTOTOOLS_DIR=$GLOBAL_DIR\\autotools + GUILE_URL="http://ftp.gnu.org/pub/gnu/guile/guile-1.6.8.tar.gz" SLIB_URL="http://swiss.csail.mit.edu/ftpdir/scm/OLD/slib3a3.zip" GUILE_DIR=$GLOBAL_DIR\\guile @@ -76,50 +84,49 @@ OPENSSL_DIR=$GLOBAL_DIR\\openssl PEXPORTS_URL="http://www.emmestech.com/software/cygwin/pexports-0.43/pexports-0.43.zip" PEXPORTS_DIR=$GLOBAL_DIR\\pexports -LIBXML2_URL="http://www.zlatkovic.com/pub/libxml/libxml2-2.6.26.win32.zip" +LIBXML2_URL="http://www.zlatkovic.com/pub/libxml/libxml2-2.6.27.win32.zip" LIBXML2_DIR=$GLOBAL_DIR\\gnome #avoid XML_FLAGS -EXPAT_URL="ftp://ftp.jclark.com/pub/xml/expat.zip" -EXPAT_DIR=$GLOBAL_DIR\\gnome #avoid EXPAT_FLAGS - GNOME_WIN32_URL="$GNOME_MIRROR/binaries/win32" -GETTEXT_URL="$GTK_MIRROR/glib/2.12/win32/dependencies/gettext-0.14.5.zip" -GETTEXT_DEV_URL="$GTK_MIRROR/glib/2.12/win32/dependencies/gettext-dev-0.14.5.zip" -LIBICONV_URL="$GTK_MIRROR/glib/2.12/win32/dependencies/libiconv-1.9.1.bin.woe32.zip" -GLIB_URL="$GNOME_WIN32_URL/glib/2.12/glib-2.12.3.zip" -GLIB_DEV_URL="$GNOME_WIN32_URL/glib/2.12/glib-dev-2.12.3.zip" -LIBJPEG_URL="$GNOME_MIRROR/platform/2.13/2.13.92/win32/dependencies/libjpeg-6b-4.zip" +GNOME_WIN32_DEPS_URL="$GNOME_WIN32_URL/dependencies" +GETTEXT_URL="$GNOME_WIN32_DEPS_URL/gettext-0.14.5.zip" +GETTEXT_DEV_URL="$GNOME_WIN32_DEPS_URL/gettext-dev-0.14.5.zip" +LIBICONV_URL="$GNOME_WIN32_DEPS_URL/libiconv-1.9.1.bin.woe32.zip" +GLIB_URL="$GNOME_WIN32_URL/glib/2.12/glib-2.12.4.zip" +GLIB_DEV_URL="$GNOME_WIN32_URL/glib/2.12/glib-dev-2.12.4.zip" +LIBJPEG_URL="$GNOME_WIN32_DEPS_URL/libjpeg-6b-4.zip" LIBPNG_URL="$GTK_MIRROR/gtk/v2.10/win32/dependencies/libpng-1.2.8-bin.zip" ZLIB_URL="$GTK_MIRROR/gtk/v2.10/win32/dependencies/zlib123-dll.zip" -PKG_CONFIG_URL="$GTK_MIRROR/gtk/v2.10/win32/dependencies/pkg-config-0.20.zip" -CAIRO_URL="$GTK_MIRROR/gtk/v2.8/win32/cairo-1.2.4.zip" -CAIRO_DEV_URL="$GTK_MIRROR/gtk/v2.8/win32/cairo-dev-1.2.4.zip" -FONTCONFIG_URL="$GTK_MIRROR/gtk/v2.8/win32/dependencies/fontconfig-2.2.2-20040412.zip" -FONTCONFIG_DEV_URL="$GTK_MIRROR/gtk/v2.8/win32/dependencies/fontconfig-dev-2.2.2-20040412.zip" -FREETYPE_URL="$GTK_MIRROR/gtk/v2.8/win32/dependencies/freetype-2.1.10.zip" +PKG_CONFIG_URL="$GNOME_WIN32_DEPS_URL/pkg-config-0.20.zip" +CAIRO_URL="$GNOME_WIN32_DEPS_URL/cairo-1.2.6.zip" +CAIRO_DEV_URL="$GNOME_WIN32_DEPS_URL/cairo-dev-1.2.6.zip" +EXPAT_URL="$GNOME_WIN32_DEPS_URL/expat-2.0.0.zip" +FONTCONFIG_URL="$GNOME_WIN32_DEPS_URL/fontconfig-2.3.2-tml-20060825.zip" +FONTCONFIG_DEV_URL="$GNOME_WIN32_DEPS_URL/fontconfig-dev-2.3.2-tml-20060825.zip" +FREETYPE_URL="$GNOME_WIN32_DEPS_URL/freetype-2.1.10.zip" FREETYPE_DEV_URL="$SF_MIRROR/gnuwin32/freetype-2.1.10-lib.zip" -ATK_URL="$GNOME_WIN32_URL/atk/1.12/atk-1.12.2.zip" -ATK_DEV_URL="$GNOME_WIN32_URL/atk/1.12/atk-dev-1.12.2.zip" -PANGO_URL="$GNOME_WIN32_URL/pango/1.14/pango-1.14.3.zip" -PANGO_DEV_URL="$GNOME_WIN32_URL/pango/1.14/pango-dev-1.14.3.zip" +ATK_URL="$GNOME_WIN32_URL/atk/1.12/atk-1.12.3.zip" +ATK_DEV_URL="$GNOME_WIN32_URL/atk/1.12/atk-dev-1.12.3.zip" +PANGO_URL="$GNOME_WIN32_URL/pango/1.14/pango-1.14.5.zip" +PANGO_DEV_URL="$GNOME_WIN32_URL/pango/1.14/pango-dev-1.14.5.zip" LIBART_LGPL_URL="$GNOME_WIN32_URL/libart_lgpl/2.3/libart_lgpl-2.3.17.zip" LIBART_LGPL_DEV_URL="$GNOME_WIN32_URL/libart_lgpl/2.3/libart_lgpl-dev-2.3.17.zip" -GTK_URL="$GNOME_WIN32_URL/gtk+/2.10/gtk+-2.10.3.zip" -GTK_DEV_URL="$GNOME_WIN32_URL/gtk+/2.10/gtk+-dev-2.10.3.zip" +GTK_URL="$GNOME_WIN32_URL/gtk+/2.10/gtk+-2.10.6.zip" +GTK_DEV_URL="$GNOME_WIN32_URL/gtk+/2.10/gtk+-dev-2.10.6.zip" INTLTOOL_URL="$GNOME_WIN32_URL/intltool/0.35/intltool-0.35.0.zip" -ORBIT2_URL="$GNOME_WIN32_URL/ORBit2/2.14/ORBit2-2.14.2.zip" -ORBIT2_DEV_URL="$GNOME_WIN32_URL/ORBit2/2.14/ORBit2-dev-2.14.2.zip" -GAIL_URL="$GNOME_WIN32_URL/gail/1.9/gail-1.9.2.zip" -GAIL_DEV_URL="$GNOME_WIN32_URL/gail/1.9/gail-dev-1.9.2.zip" -POPT_URL="$GNOME_MIRROR/platform/2.13/2.13.92/win32/dependencies/popt-1.10.2-tml-20050828.zip" -POPT_DEV_URL="$GNOME_MIRROR/platform/2.13/2.13.92/win32/dependencies/popt-dev-1.10.2-tml-20050828.zip" +ORBIT2_URL="$GNOME_WIN32_URL/ORBit2/2.13/ORBit2-2.13.3.zip" +ORBIT2_DEV_URL="$GNOME_WIN32_URL/ORBit2/2.13/ORBit2-dev-2.13.3.zip" +GAIL_URL="$GNOME_WIN32_URL/gail/1.9/gail-1.9.3.zip" +GAIL_DEV_URL="$GNOME_WIN32_URL/gail/1.9/gail-dev-1.9.3.zip" +POPT_URL="$GNOME_WIN32_DEPS_URL/popt-1.10.2-tml-20050828.zip" +POPT_DEV_URL="$GNOME_WIN32_DEPS_URL/popt-dev-1.10.2-tml-20050828.zip" GCONF_URL="$GNOME_WIN32_URL/GConf/2.14/GConf-2.14.0.zip" GCONF_DEV_URL="$GNOME_WIN32_URL/GConf/2.14/GConf-dev-2.14.0.zip" LIBBONOBO_URL="$GNOME_WIN32_URL/libbonobo/2.16/libbonobo-2.16.0.zip" LIBBONOBO_DEV_URL="$GNOME_WIN32_URL/libbonobo/2.16/libbonobo-dev-2.16.0.zip" GNOME_VFS_URL="$GNOME_WIN32_URL/gnome-vfs/2.14/gnome-vfs-2.14.2.zip" GNOME_VFS_DEV_URL="$GNOME_WIN32_URL/gnome-vfs/2.14/gnome-vfs-dev-2.14.2.zip" -LIBGNOME_URL="$GNOME_WIN32_URL/libgnome/2.16/libgnome-2.16.0.zip" +LIBGNOME_URL="$GNOME_WIN32_URL/libgnome/2.16/libgnome-2.16.0-1.zip" LIBGNOME_DEV_URL="$GNOME_WIN32_URL/libgnome/2.16/libgnome-dev-2.16.0.zip" LIBGNOMECANVAS_URL="$GNOME_WIN32_URL/libgnomecanvas/2.14/libgnomecanvas-2.14.0.zip" LIBGNOMECANVAS_DEV_URL="$GNOME_WIN32_URL/libgnomecanvas/2.14/libgnomecanvas-dev-2.14.0.zip" @@ -137,25 +144,24 @@ GTKHTML_URL="$GNOME_WIN32_URL/gtkhtml/3.12/gtkhtml-3.12.0.zip" GTKHTML_DEV_URL="$GNOME_WIN32_URL/gtkhtml/3.12/gtkhtml-dev-3.12.0.zip" GNOME_DIR=$GLOBAL_DIR\\gnome -SWIG_URL="$SF_MIRROR/swig/swigwin-1.3.29.zip" +SWIG_URL="$SF_MIRROR/swig/swigwin-1.3.31.zip" SWIG_DIR=$GLOBAL_DIR\\swig -AUTOCONF_URL="http://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.bz2" -AUTOMAKE_URL="http://ftp.gnu.org/gnu/automake/automake-1.9.6.tar.bz2" -LIBTOOL_URL="http://ftp.gnu.org/gnu/libtool/libtool-1.5.22.tar.gz" -AUTOTOOLS_DIR=$GLOBAL_DIR\\autotools - -LIBGSF_URL="$GNOME_MIRROR/sources/libgsf/1.14/libgsf-1.14.1.tar.bz2" +LIBGSF_URL="$GNOME_MIRROR/sources/libgsf/1.14/libgsf-1.14.3.tar.bz2" LIBGSF_DIR=$GLOBAL_DIR\\libgsf +# do not update this if you are unwilling to hack gnc-html-graph-gog.c GOFFICE_URL="$GNOME_MIRROR/sources/goffice/0.3/goffice-0.3.0.tar.bz2" GOFFICE_DIR=$GLOBAL_DIR\\goffice GOFFICE_PATCH=`pwd`/goffice-0.3.0-patch.diff -GLADE_URL="$GNOME_MIRROR/sources/glade3/3.0/glade3-3.0.1.tar.bz2" +GLADE_URL="$GNOME_MIRROR/sources/glade3/3.0/glade3-3.1.2.tar.bz2" GLADE_DIR=$GLOBAL_DIR\\glade -SVN_URL="http://subversion.tigris.org/files/documents/15/32856/svn-1.3.2-setup.exe" +INNO_URL="http://files.jrsoftware.org/ispack/ispack-5.1.9.exe" +INNO_DIR=$GLOBAL_DIR\\inno + +SVN_URL="http://subversion.tigris.org/files/documents/15/35379/svn-1.4.2-setup.exe" SVN_DIR=$GLOBAL_DIR\\svn # There is no reason to ever need to comment these out! @@ -172,19 +178,21 @@ add_step inst_indent if test x$cross_compile != xyes ; then add_step inst_active_perl fi +add_step inst_autotools add_step inst_guile if test x$cross_compile != xyes ; then add_step inst_openssl fi add_step inst_pexports add_step inst_libxml2 -add_step inst_expat add_step inst_gnome add_step inst_swig -add_step inst_autotools add_step inst_libgsf add_step inst_goffice #add_step inst_glade +if test x$cross_compile != xyes ; then + add_step inst_inno +fi add_step inst_svn add_step svn_up add_step inst_gnucash diff --git a/packaging/win32/dist.sh b/packaging/win32/dist.sh new file mode 100644 index 0000000000..91b6fef927 --- /dev/null +++ b/packaging/win32/dist.sh @@ -0,0 +1,183 @@ +#!/bin/sh + +set -e + +function qpushd() { pushd "$@" >/dev/null; } +function qpopd() { popd >/dev/null; } +function unix_path() { echo "$*" | sed 's,^\([A-Za-z]\):,/\1,;s,\\,/,g'; } + +qpushd "$(dirname $(unix_path "$0"))" +. functions +. custom.sh + +register_env_var PATH ":" + +function prepare() { + # this directory is hardcoded in gnucash.iss.in + DIST_DIR=${INSTALL_DIR}\\..\\dist + DIST_UDIR=`unix_path $DIST_DIR` + DIST_WFSDIR=`win_fs_path $DIST_DIR` + TMP_UDIR=`unix_path $TMP_DIR` + if [ -x $DIST_DIR ]; then + die "Please remove ${DIST_DIR} first" + fi + _UNZIP_UDIR=`unix_path $UNZIP_DIR` + _AUTOTOOLS_UDIR=`unix_path $AUTOTOOLS_DIR` + _GUILE_UDIR=`unix_path $GUILE_DIR` + _WIN_UDIR=`unix_path $WINDIR` + _LIBXML2_UDIR=`unix_path $LIBXML2_DIR` + _GNOME_UDIR=`unix_path $GNOME_DIR` + _LIBGSF_UDIR=`unix_path $LIBGSF_DIR` + _GOFFICE_UDIR=`unix_path $GOFFICE_DIR` + _GNUCASH_UDIR=`unix_path $GNUCASH_DIR` + _BUILD_UDIR=`unix_path $BUILD_DIR` + _INSTALL_UDIR=`unix_path $INSTALL_DIR` + _INNO_UDIR=`unix_path $INNO_DIR` + add_to_env $_UNZIP_UDIR/bin PATH # unzip + add_to_env $_GNOME_UDIR/bin PATH # gconftool-2 +} + +function dist_regex() { + setup RegEx + smart_wget $REGEX_BIN_URL $DOWNLOAD_DIR + unzip -q $LAST_FILE bin/regex.dll -d $DIST_DIR +} + +function dist_autotools() { + setup Autotools + mkdir -p $DIST_UDIR/bin + cp -a $_AUTOTOOLS_UDIR/bin/*.dll $DIST_UDIR/bin +} + +function dist_guile() { + setup Guile + mkdir -p $DIST_UDIR/bin + cp -a $_GUILE_UDIR/bin/libguile{.,-ltdl.,-srfi}*dll $DIST_UDIR/bin + cp -a $_GUILE_UDIR/bin/guile.exe $DIST_UDIR/bin + mkdir -p $DIST_UDIR/share + cp -a $_GUILE_UDIR/share/guile $DIST_UDIR/share + [ -f $DIST_UDIR/share/guile/1.6/slibcat ] && rm $DIST_UDIR/share/guile/1.6/slibcat +} + +function dist_openssl() { + setup OpenSSL + mkdir -p $DIST_UDIR/bin + cp -a $_WIN_UDIR/system32/lib{eay,ssl}*.dll $DIST_UDIR/bin +} + +function dist_libxml2() { + setup LibXML2 + mkdir -p $DIST_UDIR/bin + cp -a $_LIBXML2_UDIR/bin/libxml2.dll $DIST_UDIR/bin +} + +function dist_gnome() { + setup Gnome platform + wget_unpacked $GETTEXT_URL $DOWNLOAD_DIR $DIST_DIR + smart_wget $LIBICONV_URL $DOWNLOAD_DIR + unzip -q $LAST_FILE bin/iconv.dll -d $DIST_DIR + wget_unpacked $GLIB_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $LIBJPEG_URL $DOWNLOAD_DIR $DIST_DIR + smart_wget $LIBPNG_URL $DOWNLOAD_DIR + unzip -q $LAST_FILE bin/libpng13.dll -d $DIST_DIR + smart_wget $ZLIB_URL $DOWNLOAD_DIR + unzip -q $LAST_FILE zlib1.dll -d $DIST_DIR\\bin + wget_unpacked $CAIRO_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $EXPAT_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $FONTCONFIG_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $FREETYPE_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $ATK_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $PANGO_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $LIBART_LGPL_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $GTK_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $ORBIT2_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $GAIL_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $POPT_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $GCONF_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $LIBBONOBO_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $GNOME_VFS_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $LIBGNOME_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $LIBGNOMECANVAS_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $LIBBONOBOUI_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $LIBGNOMEUI_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $LIBGLADE_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $LIBGNOMEPRINT_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $LIBGNOMEPRINTUI_URL $DOWNLOAD_DIR $DIST_DIR + wget_unpacked $GTKHTML_URL $DOWNLOAD_DIR $DIST_DIR + rm -rf $DIST_UDIR/etc/gconf/gconf.xml.defaults/{desktop,schemas} +} + +function dist_libgsf() { + setup libGSF + mkdir -p $DIST_UDIR/bin + cp -a $_LIBGSF_UDIR/bin/libgsf*.dll $DIST_UDIR/bin + mkdir -p $DIST_UDIR/etc/gconf/schemas + cp -a $_LIBGSF_UDIR/etc/gconf/schemas/* $DIST_UDIR/etc/gconf/schemas + mkdir -p $DIST_UDIR/lib + cp -a $_LIBGSF_UDIR/lib/locale $DIST_UDIR/lib +} + +function dist_goffice() { + setup GOffice + mkdir -p $DIST_UDIR/bin + cp -a $_GOFFICE_UDIR/bin/libgoffice*.dll $DIST_UDIR/bin + mkdir -p $DIST_UDIR/lib + cp -a $_GOFFICE_UDIR/lib/{goffice,locale} $DIST_UDIR/lib + mkdir -p $DIST_UDIR/share + cp -a $_GOFFICE_UDIR/share/{goffice,pixmaps} $DIST_UDIR/share +} + +function dist_gnucash() { + setup GnuCash + mkdir -p $DIST_UDIR/bin + cp -a $_INSTALL_UDIR/bin/* $DIST_UDIR/bin + mkdir -p $DIST_UDIR/etc/gconf/schemas + cp -a $_INSTALL_UDIR/etc/gconf/schemas/* $DIST_UDIR/etc/gconf/schemas + mkdir -p $DIST_UDIR/lib + cp -a $_INSTALL_UDIR/lib/{bin,locale} $DIST_UDIR/lib + cp -a $_INSTALL_UDIR/lib/lib*.{dll,la} $DIST_UDIR/lib + mkdir -p $DIST_UDIR/lib/gnucash + cp -a $_INSTALL_UDIR/lib/gnucash/lib*.{dll,la} $DIST_UDIR/lib/gnucash + cp -a $_INSTALL_UDIR/libexec $DIST_UDIR + mkdir -p $DIST_UDIR/share + cp -a $_INSTALL_UDIR/share/{gnucash,pixmaps,xml} $DIST_UDIR/share + cp -a $_BUILD_UDIR/packaging/win32/gnucash.iss $_GNUCASH_UDIR +} + +function finish() { + for file in $DIST_UDIR/etc/gconf/schemas/*.schemas; do + echo -n "Installing $file ... " + gconftool-2 \ + --config-source=xml:merged:${DIST_WFSDIR}/etc/gconf/gconf.xml.defaults \ + --install-schema-file $file >/dev/null + echo "done" + done + + # Strip redirections in distributed libtool .la files + for file in `find $DIST_UDIR/lib -name '*.la'`; do + cat $file | sed 's,^libdir=,#libdir=,' > $file.new + mv $file.new $file + done + + echo "You can now run the Inno Setup Compiler for creating the setup.exe:" + echo ${_INNO_UDIR}/iscc ${_GNUCASH_UDIR}/gnucash.iss +} + +prepare +dist_regex +dist_autotools +dist_guile +dist_openssl +dist_libxml2 +dist_gnome +dist_libgsf +dist_goffice +dist_gnucash +finish +qpopd + + +### Local Variables: *** +### sh-basic-offset: 4 *** +### tab-width: 8 *** +### End: *** diff --git a/packaging/win32/functions b/packaging/win32/functions new file mode 100644 index 0000000000..f67a060359 --- /dev/null +++ b/packaging/win32/functions @@ -0,0 +1,87 @@ +function add_step() { steps=("${steps[@]}" "$@"); } +function quiet() { "$@" &>/dev/null; } + +# c:/dir/sub +function win_fs_path() { echo "$*" | sed 's,\\,/,g'; } + +# usage: smart_wget URL DESTDIR +function smart_wget() { + _FILE=`basename $1` + _DLD=`unix_path $2` + + # If the file already exists in the download directory ($2) + # then don't do anything. But if it does NOT exist then + # download the file to the tmpdir and then when that completes + # move it to the dest dir. + if [ ! -f $_DLD/$_FILE ] ; then + wget --passive-ftp -c $1 -P $TMP_DIR + mv $TMP_UDIR/$_FILE $_DLD + fi + LAST_FILE=$_DLD/$_FILE +} + +# usage: wget_unpacked URL DOWNLOAD_DIR UNPACK_DIR +function wget_unpacked() { + smart_wget $1 $2 + _UPD=`unix_path $3` + echo -n "Extracting ${LAST_FILE##*/} ... " + case $LAST_FILE in + *.zip) unzip -q -o $LAST_FILE -d $_UPD;; + *.tar.gz) tar -xzpf $LAST_FILE -C $_UPD;; + *.tar.bz2) tar -xjpf $LAST_FILE -C $_UPD;; + *) die "Cannot unpack file $LAST_FILE!";; + esac + echo "done" +} + +function setup() { + echo + echo "############################################################" + echo "### $*" + echo "############################################################" +} + +function die() { + echo + echo "!!! $* !!!" + echo "!!! ABORTING !!!" + exit -1 +} + +# usage: register_env_var NAME SEPARATOR [DEFAULT] +function register_env_var() { + [ $# -ge 2 -a $# -le 3 ] || die hard + eval "SEPS_$1"'="'"$2"'"' + if [ $# -eq 3 ]; then + eval "$1_BASE=$3" + else + eval "$1_BASE"'=$'"$1" + fi + eval "$1_ADDS=" + eval export "$1" + ENV_VARS="$ENV_VARS $1" +} +ENV_VARS= + +# usage: add_to_env VALUE NAME +function add_to_env() { + _SEP=`eval echo '"$'"SEPS_$2"'"'` + _ENV=`eval echo '"$'"$2"'"'` + _SED=`eval echo '"s#.*'"${_SEP}$1${_SEP}"'.*##"'` + _TEST=`echo "${_SEP}${_ENV}${_SEP}" | sed "${_SED}"` + if [ "$_TEST" ]; then + if [ "$_ENV" ]; then + eval "$2_ADDS"'="'"$1${_SEP}"'$'"$2_ADDS"'"' + else + eval "$2_ADDS"'="'"$1"'"' + fi + eval "$2"'="$'"$2_ADDS"'$'"$2_BASE"'"' + fi +} + + +### Local Variables: *** +### mode: shell-script *** +### sh-basic-offset: 4 *** +### tab-width: 8 *** +### End: *** diff --git a/packaging/win32/gnucash.iss.in b/packaging/win32/gnucash.iss.in index 9804275900..f88d853edf 100644 --- a/packaging/win32/gnucash.iss.in +++ b/packaging/win32/gnucash.iss.in @@ -15,12 +15,12 @@ AppSupportURL=http://www.gnucash.org AppUpdatesURL=http://www.gnucash.org DefaultDirName={pf}\@PACKAGE@ DefaultGroupName=GnuCash -LicenseFile=..\..\COPYING +LicenseFile=@prefix@\..\dist\share\@PACKAGE@\doc\COPYING Compression=lzma OutputDir=. OutputBaseFilename=@PACKAGE@-@VERSION@-setup UninstallFilesDir={app}\uninstall\@PACKAGE@ -InfoAfterFile=README +InfoAfterFile=@prefix@\..\dist\share\@PACKAGE@\doc\README [Types] Name: "full"; Description: "{cm:FullInstall}" @@ -28,20 +28,21 @@ Name: "custom"; Description: "{cm:CustomInstall}"; Flags: iscustom [Components] Name: "main"; Description: "{cm:MainFiles}"; Types: full custom; Flags: fixed -Name: "translations"; Description: "{cm:TranslFiles}"; Types: full -Name: "templates"; Description: "{cm:TemplFiles}"; Types: full +;Name: "translations"; Description: "{cm:TranslFiles}"; Types: full +;Name: "templates"; Description: "{cm:TemplFiles}"; Types: full [Tasks] Name: desktopicon; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" Name: menuicon; Description: "{cm:CreateMenuLink}"; GroupDescription: "{cm:AdditionalIcons}" [Icons] -Name: "{group}\GnuCash"; Filename: "{app}\bin\gnucash.bat"; WorkingDir: "{app}\bin"; Comment: "GnuCash Free Finance Manager"; IconFilename: "{app}\share\pixmaps\gnucash-icon.png"; Tasks: menuicon +Name: "{group}\GnuCash"; Filename: "{app}\bin\gnucash.bat"; WorkingDir: "{app}\bin"; Comment: "GnuCash Free Finance Manager"; IconFilename: "{app}\share\gnucash\pixmaps\gnucash-icon.ico"; Tasks: menuicon Name: "{group}\Uninstall GnuCash"; Filename: "{uninstallexe}"; Tasks: menuicon -Name: "{userdesktop}\GnuCash"; Filename: "{app}\bin\gnucash.bat"; WorkingDir: "{app}\bin"; Comment: "GnuCash Free Finance Manager"; IconFilename: "{app}\share\pixmaps\gnucash-icon.png"; Tasks: desktopicon +Name: "{userdesktop}\GnuCash"; Filename: "{app}\bin\gnucash.bat"; WorkingDir: "{app}\bin"; Comment: "GnuCash Free Finance Manager"; IconFilename: "{app}\share\gnucash\pixmaps\gnucash-icon.ico"; Tasks: desktopicon [Run] Filename: "{app}\bin\gnucash.bat"; Description: "{cm:RunPrg}"; WorkingDir: "{app}\bin"; Flags: postinstall skipifsilent +Filename: "{app}\bin\guile.bat"; Parameters: "-c ""(use-modules (ice-9 slib)) (require 'printf)"""; Flags: runhidden ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Here we configure the included files and the place of their @@ -49,26 +50,26 @@ Filename: "{app}\bin\gnucash.bat"; Description: "{cm:RunPrg}"; WorkingDir: "{app ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; [Files] ; The main executables and DLLs -Source: "@prefix@\bin\*"; DestDir: "{app}\bin"; Flags: recursesubdirs; Components: main -Source: "@prefix@\etc\*"; DestDir: "{app}\etc"; Flags: recursesubdirs; Components: main -Source: "@prefix@\lib\*"; DestDir: "{app}\lib"; Flags: recursesubdirs; Components: main -Source: "@prefix@\libexec\*"; DestDir: "{app}\libexec"; Flags: recursesubdirs; Components: main -Source: "@prefix@\share\*"; DestDir: "{app}\share"; Flags: recursesubdirs; Components: main +Source: "@prefix@\..\dist\bin\*"; DestDir: "{app}\bin"; Flags: recursesubdirs; Components: main; AfterInstall: MyAfterInstallConfig() +; Note: The above AfterInstall function will create the +; gnucash.bat file on-the-fly by the Pascal script below. -; The translations (no idea why mingw installs them in prefix/lib/locale) -Source: "@prefix@\lib\locale\*"; DestDir: "{app}\lib\locale"; Flags: recursesubdirs; Components: translations +Source: "@prefix@\..\dist\etc\*"; DestDir: "{app}\etc"; Flags: recursesubdirs; Components: main +Source: "@prefix@\..\dist\lib\*"; DestDir: "{app}\lib"; Flags: recursesubdirs; Components: main +Source: "@prefix@\..\dist\libexec\*"; DestDir: "{app}\libexec"; Flags: recursesubdirs; Components: main +Source: "@prefix@\..\dist\share\*"; DestDir: "{app}\share"; Flags: recursesubdirs; Components: main -; The account templates -Source: "@prefix@\share\gnucash\accounts\*"; DestDir: "{app}\share\gnucash\accounts"; Flags: recursesubdirs; Components: templates - -; The loading shell script. It is post-processed by the Pascal script below. -Source: "..\..\src\bin\gnucash.in"; DestDir: "{app}\bin"; Components: main; AfterInstall: MyAfterInstallConfig(ExpandConstant('{app}\bin\gnucash')) +;; The translations (no idea why mingw installs them in prefix/lib/locale) +;Source: "@prefix@\..\dist\lib\locale\*"; DestDir: "{app}\lib\locale"; Flags: recursesubdirs; Components: translations +; +;; The account templates +;Source: "@prefix@\..\dist\share\gnucash\accounts\*"; DestDir: "{app}\share\gnucash\accounts"; Flags: recursesubdirs; Components: templates ; And all the documentation -Source: "..\..\README"; DestDir: "{app}\doc\@PACKAGE@"; Components: main -Source: "..\..\COPYING"; DestDir: "{app}\doc\@PACKAGE@"; Flags: ignoreversion; Components: main -Source: "..\..\AUTHORS"; DestDir: "{app}\doc\@PACKAGE@"; Components: main -Source: "..\..\ChangeLog"; DestDir: "{app}\doc\@PACKAGE@"; Components: main +Source: "@prefix@\..\dist\share\@PACKAGE@\doc\README"; DestDir: "{app}\doc\@PACKAGE@"; Components: main +Source: "@prefix@\..\dist\share\@PACKAGE@\doc\COPYING"; DestDir: "{app}\doc\@PACKAGE@"; Flags: ignoreversion; Components: main +Source: "@prefix@\..\dist\share\@PACKAGE@\doc\AUTHORS"; DestDir: "{app}\doc\@PACKAGE@"; Components: main +Source: "@prefix@\..\dist\share\@PACKAGE@\doc\ChangeLog"; DestDir: "{app}\doc\@PACKAGE@"; Components: main ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -85,7 +86,11 @@ Root: HKCU; Subkey: "Software\GnuCash\Paths"; ValueType: string; ValueName: "loc ; Delete the created config script on uninstall ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; [UninstallDelete] -Type: files; Name: "{app}\bin\gnucash" +Type: files; Name: "{app}\bin\gnucash.bat" +Type: files; Name: "{app}\bin\guile.bat" +Type: files; Name: "{app}\share\guile\1.6\slibcat" +Type: filesandordirs; Name: "{app}\etc\gconf" +Type: dirifempty; Name: "{app}\etc" ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This large section is a Pascal scripting program that will modify @@ -106,40 +111,39 @@ begin StringChange(Result, '\', '/'); end; -procedure MyAfterInstallConfig(FileName: String); +procedure MyAfterInstallConfig(); var - FileString, appdir, libdir, pkglibdir, pkgdatadir: String; + FileName, FileString, appdir, libdir, pkglibdir, pkgdatadir: String; Res: Boolean; begin - { Load the unchanged original file } - Res := LoadStringFromFile(Format('%s.in',[FileName]), FileString); - if Res = False then - MsgBox('Error on loading '+FileName+'.in for final adaptation', mbInformation, MB_OK); + { Get the installation-specific paths } + appdir := ExpandConstant('{app}'); + libdir := appdir + '\lib'; + pkglibdir := libdir + '\gnucash'; + pkgdatadir := appdir + '\share\gnucash'; - { Insert the custom file header; #10 is the linefeed character } - Insert('#!/bin/sh '#10'dir="@prefix'+'@"'#10, FileString, 0); + { Create the gnucash.bat file; #10 is the linefeed character and #13 CR } + FileName := appdir + '\bin\gnucash.bat' ; + FileString := 'set PATH=' + appdir + '\bin;' + libdir + '\bin;%PATH%'#13#10 ; - { Get the installation-specific paths } - appdir := MingwBacksl(ExpandConstant('{app}')); - libdir := appdir + '/lib'; - pkglibdir := libdir + '/gnucash'; - pkgdatadir := appdir + '/share/gnucash'; - - { Now make all the replacements } - { Explanation: StringChange(S,FromStr,ToStr): Change all occurances in S of FromStr to ToStr. } - StringChange(FileString, '@'+'-PATH_SEPARATOR-@', ';'); - StringChange(FileString, '@'+'-BIN_DIR-@', appdir + '/bin'); - StringChange(FileString, '@'+'-GNC_PKGLIB_INSTALLDIR-@', pkglibdir); - StringChange(FileString, '@'+'-GNC_MODULE_DIR-@', pkglibdir); - StringChange(FileString, '@'+'-GNC_LIB_INSTALLDIR-@', libdir); - StringChange(FileString, '@'+'-GNC_GUILE_MODULE_DIR-@', pkgdatadir + '/guile-modules'); - StringChange(FileString, '@'+'-GNC_SCM_INSTALL_DIR-@', pkgdatadir + '/scm'); + FileString := FileString + 'set GUILE_WARN_DEPRECATED=no'#13#10 ; + FileString := FileString + 'set GNC_MODULE_PATH=' + pkglibdir + ''#13#10 ; + FileString := FileString + 'set GUILE_LOAD_PATH=' + pkgdatadir + '\guile-modules;' + pkgdatadir + '\scm;' + appdir + '\share\guile\1.6;%GUILE_LOAD_PATH%'#13#10 ; + FileString := FileString + 'set LTDL_LIBRARY_PATH=' + libdir + ''#13#10 ; + FileString := FileString + 'start gnucash-bin'#13#10 ; { Save the final file } Res := SaveStringToFile(FileName, FileString, False); if Res = False then - MsgBox('Error on saving '+FileName+' for final adaptation', mbInformation, MB_OK); + MsgBox('Error on saving '+FileName+' for completing the installation', mbInformation, MB_OK); + + FileName := appdir + '\bin\guile.bat' ; + FileString := 'set GUILE_LOAD_PATH=' + pkgdatadir + '\guile-modules;' + pkgdatadir + '\scm;' + appdir + '\share\guile\1.6;%GUILE_LOAD_PATH%'#13#10 ; + FileString := FileString + 'start guile.exe %*'#13#10 ; + Res := SaveStringToFile(FileName, FileString, False); + if Res = False then + MsgBox('Error on saving '+FileName+' for completing the installation', mbInformation, MB_OK); end; diff --git a/packaging/win32/goffice-0.3.2-patch.diff b/packaging/win32/goffice-0.3.2-patch.diff new file mode 100644 index 0000000000..dc69b980ae --- /dev/null +++ b/packaging/win32/goffice-0.3.2-patch.diff @@ -0,0 +1,91 @@ +diff -Nur goffice-0.3.2-old/goffice/Makefile.am goffice-0.3.2/goffice/Makefile.am +--- goffice-0.3.2-old/goffice/Makefile.am Tue Sep 19 16:06:53 2006 ++++ goffice-0.3.2/goffice/Makefile.am Mon Oct 30 15:47:16 2006 +@@ -31,7 +31,8 @@ + libgoffice_0_la_DEPENDENCIES = goffice.def + libgoffice_0_la_LDFLAGS += -no-undefined -export-symbols goffice.def + if WITH_NATIVE_WIN32 +-libgoffice_0_la_LIBADD += -luuid -lhtmlhelp -lurlmon ++libgoffice_0_la_LDFLAGS += -no-undefined ++libgoffice_0_la_LIBADD += -luuid + endif + endif + +@@ -76,7 +77,7 @@ + data/local.def drawing/local.def graph/local.def \ + gtk/local.def ms-compat/local.def utils/local.def + echo EXPORTS > $@ && \ +- cat $^ | sort >> $@ ++ cat $^ | sort | sed '/^go_doc_mark_not_modified$$/d;/^go_plugin_init$$/d;/^go_plugin_shutdown$$/d' >> $@ + + if HAVE_LIBEXE + goffice_mslibdir = $(DESTDIR)$(libdir) +diff -Nur goffice-0.3.2-old/goffice-win32.mk goffice-0.3.2/goffice-win32.mk +--- goffice-0.3.2-old/goffice-win32.mk Tue Sep 19 16:06:52 2006 ++++ goffice-0.3.2/goffice-win32.mk Mon Oct 30 15:50:27 2006 +@@ -16,7 +16,7 @@ + fi; \ + done; \ + cat $(top_builddir)/goffice/goffice-config.h $$hdrs_list | \ +- sed -e 's/^#[ \t]*include[ \t]\+.*$$//g' | \ ++ sed -e 's/^#[ ]*include[ ]\+.*$$//g' | \ + $(CPP) $(AM_CPPFLAGS) "-DGO_VAR_DECL=__declspec(dllexport)" -P - > xgen-localdef.1 && \ + perl $(top_srcdir)/dumpdef.pl \ + xgen-localdef.1 > xgen-localdef.2 \ +diff -Nur goffice-0.3.2-old/gtk-doc.m4 goffice-0.3.2/gtk-doc.m4 +--- goffice-0.3.2-old/gtk-doc.m4 Thu Jan 1 00:00:00 1970 ++++ goffice-0.3.2/gtk-doc.m4 Mon Oct 30 15:47:16 2006 +@@ -0,0 +1,53 @@ ++dnl -*- mode: autoconf -*- ++ ++# serial 1 ++ ++dnl Usage: ++dnl GTK_DOC_CHECK([minimum-gtk-doc-version]) ++AC_DEFUN([GTK_DOC_CHECK], ++[ ++ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first ++ AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first ++ dnl for overriding the documentation installation directory ++ AC_ARG_WITH(html-dir, ++ AC_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),, ++ [with_html_dir='${datadir}/gtk-doc/html']) ++ HTML_DIR="$with_html_dir" ++ AC_SUBST(HTML_DIR) ++ ++ dnl enable/disable documentation building ++ AC_ARG_ENABLE(gtk-doc, ++ AC_HELP_STRING([--enable-gtk-doc], ++ [use gtk-doc to build documentation [default=no]]),, ++ enable_gtk_doc=no) ++ ++ have_gtk_doc=no ++ if test x$enable_gtk_doc = xyes; then ++ if test -z "$PKG_CONFIG"; then ++ AC_PATH_PROG(PKG_CONFIG, pkg-config, no) ++ fi ++ if test "$PKG_CONFIG" != "no" && $PKG_CONFIG --exists gtk-doc; then ++ have_gtk_doc=yes ++ fi ++ ++ dnl do we want to do a version check? ++ifelse([$1],[],, ++ [gtk_doc_min_version=$1 ++ if test "$have_gtk_doc" = yes; then ++ AC_MSG_CHECKING([gtk-doc version >= $gtk_doc_min_version]) ++ if $PKG_CONFIG --atleast-version $gtk_doc_min_version gtk-doc; then ++ AC_MSG_RESULT(yes) ++ else ++ AC_MSG_RESULT(no) ++ have_gtk_doc=no ++ fi ++ fi ++]) ++ if test "$have_gtk_doc" != yes; then ++ enable_gtk_doc=no ++ fi ++ fi ++ ++ AM_CONDITIONAL(ENABLE_GTK_DOC, test x$enable_gtk_doc = xyes) ++ AM_CONDITIONAL(GTK_DOC_USE_LIBTOOL, test -n "$LIBTOOL") ++]) diff --git a/packaging/win32/install.sh b/packaging/win32/install.sh index e8c42d2518..bc91fcdcba 100644 --- a/packaging/win32/install.sh +++ b/packaging/win32/install.sh @@ -2,126 +2,63 @@ set -e -function add_step() { steps=("${steps[@]}" "$@"); } function qpushd() { pushd "$@" >/dev/null; } function qpopd() { popd >/dev/null; } - -# c:/dir/sub -function win_fs_path() { - echo "$*" | sed 's,\\,/,g' -} - -# /c/dir/sub -function unix_path() { - echo "$*" | sed 's,^\([A-Za-z]\):,/\1,;s,\\,/,g' -} +function unix_path() { echo "$*" | sed 's,^\([A-Za-z]\):,/\1,;s,\\,/,g'; } qpushd "$(dirname $(unix_path "$0"))" +. functions . custom.sh -SEPS_ACLOCAL_FLAGS=" " -SEPS_AUTOTOOLS_CPPFLAGS=" " -SEPS_AUTOTOOLS_LDFLAGS=" " -SEPS_GNOME_CPPFLAGS=" " -SEPS_GNOME_LDFLAGS=" " -SEPS_GUILE_LOAD_PATH=";" -SEPS_GUILE_CPPFLAGS=" " -SEPS_GUILE_LDFLAGS=" " -SEPS_INTLTOOL_PERL=" " -SEPS_PATH=":" -SEPS_PKG_CONFIG_PATH=":" -SEPS_READLINE_CPPFLAGS=" " -SEPS_READLINE_LDFLAGS=" " -SEPS_REGEX_CPPFLAGS=" " -SEPS_REGEX_LDFLAGS=" " -ENV_VARS="\ -ACLOCAL_FLAGS \ -AUTOTOOLS_CPPFLAGS \ -AUTOTOOLS_LDFLAGS \ -GNOME_CPPFLAGS \ -GNOME_LDFLAGS \ -GUILE_LOAD_PATH \ -GUILE_CPPFLAGS \ -GUILE_LDFLAGS \ -INTLTOOL_PERL \ -PATH \ -PKG_CONFIG_PATH \ -READLINE_CPPFLAGS \ -READLINE_LDFLAGS \ -REGEX_CPPFLAGS \ -REGEX_LDFLAGS \ -" - -function setup() { - echo - echo "############################################################" - echo "### $*" - echo "############################################################" -} - -function die() { - echo - echo "!!! $* !!!" - echo "!!! ABORTING !!!" - exit -1 -} - -function quiet() { "$@" &>/dev/null; } -function add_to_env() { - _SEP=`eval echo '"$'"SEPS_$2"'"'` - _ENV=`eval echo '"$'"$2"'"'` - _SED=`eval echo '"s#.*'"${_SEP}$1${_SEP}"'.*##"'` - _TEST=`echo "${_SEP}${_ENV}${_SEP}" | sed "${_SED}"` - if [ "$_TEST" ]; then - if [ "$_ENV" ]; then - eval "$2_ADDS"'="'"$1${_SEP}"'$'"$2_ADDS"'"' - else - eval "$2_ADDS"'="'"$1"'"' - fi - eval "$2"'="$'"$2_ADDS"'$'"$2_BASE"'"' - fi -} +register_env_var ACLOCAL_FLAGS " " +register_env_var AUTOTOOLS_CPPFLAGS " " +register_env_var AUTOTOOLS_LDFLAGS " " +register_env_var GNOME_CPPFLAGS " " +register_env_var GNOME_LDFLAGS " " +register_env_var GUILE_LOAD_PATH ";" +register_env_var GUILE_CPPFLAGS " " +register_env_var GUILE_LDFLAGS " " +register_env_var INTLTOOL_PERL " " +register_env_var PATH ":" +register_env_var PKG_CONFIG ":" "" +register_env_var PKG_CONFIG_PATH ":" +register_env_var READLINE_CPPFLAGS " " +register_env_var READLINE_LDFLAGS " " +register_env_var REGEX_CPPFLAGS " " +register_env_var REGEX_LDFLAGS " " function prepare() { - mkdir -p $TMP_DIR - mkdir -p $DOWNLOAD_DIR - for _ENV in $ENV_VARS; do - eval "${_ENV}_BASE"'=$'"${_ENV}" - eval "${_ENV}_ADDS=" - eval export "${_ENV}" + # Necessary so that intltoolize doesn't come up with some + # foolish AC_CONFIG_AUX_DIR; bug#362006 + # We cannot simply create install-sh in the repository, because + # this will confuse other parts of the tools + _REPOS_UDIR=`unix_path $REPOS_DIR` + level0=. + level1=$(basename ${_REPOS_UDIR}) + level2=$(basename $(dirname ${_REPOS_UDIR}))"/"$level1 + for mydir in $level0 $level1 $level2; do + if [ -f $mydir/gnucash.m4 ]; then + die "Do not save install.sh in the repository or one its parent directories" + fi done - DOWNLOAD_UDIR=`unix_path $DOWNLOAD_DIR` - TMP_UDIR=`unix_path $TMP_DIR` -} - -# usage: smart_wget URL DESTDIR -function smart_wget() { - _FILE=`basename $1` - _DLD=`unix_path $2` - - # If the file already exists in the download directory ($2) - # then don't do anything. But if it does NOT exist then - # download the file to the tmpdir and then when that completes - # move it to the dest dir. - if [ ! -f $_DLD/$_FILE ] ; then - wget --passive-ftp -c $1 -P $TMP_DIR - mv $TMP_UDIR/$_FILE $_DLD + # Remove old empty install-sh files + if [ -f ${_REPOS_UDIR}/install-sh -a "$(cat ${_REPOS_UDIR}/install-sh &>/dev/null | wc -l)" -eq 0 ]; then + rm -f ${_REPOS_UDIR}/install-sh + fi + # Partially remove RegEx-GNU if installed + _REGEX_UDIR=`unix_path $REGEX_DIR` + if [ -f ${_REGEX_UDIR}/contrib/regex-0.12-GnuWin32.README ]; then + qpushd ${_REGEX_UDIR} + rm -f bin/*regex*.dll + rm -f contrib/regex* + rm -f lib/*regex* + qpopd fi - LAST_FILE=$_DLD/$_FILE -} -# usage: wget_unpacked URL DOWNLOAD_DIR UNPACK_DIR -function wget_unpacked() { - smart_wget $1 $2 - _UPD=`unix_path $3` - echo -n "Extracting ${LAST_FILE##*/} ... " - case $LAST_FILE in - *.zip) unzip -q -o $LAST_FILE -d $_UPD;; - *.tar.gz) tar -xzpf $LAST_FILE -C $_UPD;; - *.tar.bz2) tar -xjpf $LAST_FILE -C $_UPD;; - *) die "Cannot unpack file $LAST_FILE!";; - esac - echo "done" + DOWNLOAD_UDIR=`unix_path $DOWNLOAD_DIR` + TMP_UDIR=`unix_path $TMP_DIR` + mkdir -p $TMP_UDIR + mkdir -p $DOWNLOAD_UDIR } function inst_wget() { @@ -131,7 +68,7 @@ function inst_wget() { then echo "already installed. skipping." else - mkdir -p $WGET_DIR + mkdir -p $_WGET_UDIR tar -xjpf $DOWNLOAD_UDIR/wget*.tar.bz2 -C $WGET_DIR cp $_WGET_UDIR/*/*/wget.exe $WGET_DIR fi @@ -141,7 +78,8 @@ function inst_wget() { function inst_dtk() { setup MSYS DTK - if quiet perl --help + _MSYS_UDIR=`unix_path $MSYS_DIR` + if quiet ${_MSYS_UDIR}/bin/perl --help then echo "msys dtk already installed. skipping." else @@ -158,7 +96,7 @@ function inst_dtk() { mv $file $_dst_file done fi - quiet perl --help || die "msys dtk not installed correctly" + quiet ${_MSYS_UDIR}/bin/perl --help || die "msys dtk not installed correctly" } function inst_mingw() { @@ -202,7 +140,7 @@ function inst_regex() { then echo "regex already installed. skipping." else - mkdir -p $REGEX_DIR + mkdir -p $_REGEX_UDIR wget_unpacked $REGEX_BIN_URL $DOWNLOAD_DIR $REGEX_DIR wget_unpacked $REGEX_LIB_URL $DOWNLOAD_DIR $REGEX_DIR fi @@ -219,7 +157,7 @@ function inst_readline() { then echo "readline already installed. skipping." else - mkdir -p $READLINE_DIR + mkdir -p $_READLINE_UDIR wget_unpacked $READLINE_BIN_URL $DOWNLOAD_DIR $READLINE_DIR wget_unpacked $READLINE_LIB_URL $DOWNLOAD_DIR $READLINE_DIR fi @@ -234,7 +172,7 @@ function inst_indent() { then echo "indent already installed. skipping." else - mkdir -p $INDENT_DIR + mkdir -p $_INDENT_UDIR wget_unpacked $INDENT_BIN_URL $DOWNLOAD_DIR $INDENT_DIR fi quiet which indent || die "indent unavailable" @@ -260,6 +198,49 @@ function inst_active_perl() { quiet $INTLTOOL_PERL --help || die "ActivePerl not installed correctly" } +function inst_autotools() { + setup Autotools + _AUTOTOOLS_UDIR=`unix_path $AUTOTOOLS_DIR` + add_to_env $_AUTOTOOLS_UDIR/bin PATH + if quiet autoconf --help && quiet automake --help + then + echo "autoconf/automake already installed. skipping." + else + wget_unpacked $AUTOCONF_URL $DOWNLOAD_DIR $TMP_DIR + wget_unpacked $AUTOMAKE_URL $DOWNLOAD_DIR $TMP_DIR + qpushd $TMP_UDIR/autoconf-* + echo "building autoconf..." + ./configure --prefix=$_AUTOTOOLS_UDIR + make + make install + qpopd + qpushd $TMP_UDIR/automake-* + echo "building automake..." + ./configure --prefix=$_AUTOTOOLS_UDIR + make + make install + qpopd + fi + if quiet ${LIBTOOLIZE} --help + then + echo "libtool/libtoolize already installed. skipping." + else + wget_unpacked $LIBTOOL_URL $DOWNLOAD_DIR $TMP_DIR + qpushd $TMP_UDIR/libtool-* + echo "building libtool..." + ./configure ${HOST_XCOMPILE} --prefix=$_AUTOTOOLS_UDIR + make + make install + qpopd + fi + add_to_env -I$_AUTOTOOLS_UDIR/include AUTOTOOLS_CPPFLAGS + add_to_env -L$_AUTOTOOLS_UDIR/lib AUTOTOOLS_LDFLAGS + add_to_env "-I $_AUTOTOOLS_UDIR/share/aclocal" ACLOCAL_FLAGS + quiet autoconf --help && + quiet automake --help && + quiet ${LIBTOOLIZE} --help || die "autotools not installed correctly" +} + function inst_guile() { setup Guile _GUILE_WFSDIR=`win_fs_path $GUILE_DIR` @@ -273,8 +254,10 @@ function inst_guile() { echo "guile and slib already installed. skipping." else smart_wget $GUILE_URL $DOWNLOAD_DIR + _GUILE_BALL=$LAST_FILE smart_wget $SLIB_URL $DOWNLOAD_DIR - tar -xzpf $DOWNLOAD_UDIR/guile-*.tar.gz -C $TMP_UDIR + _SLIB_BALL=$LAST_FILE + tar -xzpf $_GUILE_BALL -C $TMP_UDIR qpushd $TMP_UDIR/guile-* qpushd ice-9 cp boot-9.scm boot-9.scm.bak @@ -308,18 +291,11 @@ function inst_guile() { cp Makefile Makefile.bak cat Makefile.bak | sed '/-bindir-/s,:,^,g' > Makefile qpopd - make LDFLAGS="-lwsock32 ${READLINE_LDFLAGS} ${REGEX_LDFLAGS} -lregex -no-undefined" + make LDFLAGS="-lwsock32 ${READLINE_LDFLAGS} ${REGEX_LDFLAGS} -lregex -no-undefined -avoid-version" make install qpopd - qpushd $GUILE_DIR/bin - mv libguilereadline-v-12-12.dll libguilereadline-v-12.dll - mv libguile-srfi-srfi-4-v-1-1.dll libguile-srfi-srfi-4-v-1.dll - mv libguile-srfi-srfi-13-14-v-1-1.dll libguile-srfi-srfi-13-14-v-1.dll - qpopd - _GUILE_MAJOR=`echo $_GUILE_UDIR/share/guile/1.* | sed 's,.*/,,'` - _SLIB_DIR=$GUILE_DIR\\share\\guile\\$_GUILE_MAJOR - mkdir -p $_SLIB_DIR - unzip $DOWNLOAD_DIR/slib*.zip -d $_SLIB_DIR + _SLIB_DIR=$_GUILE_UDIR/share/guile/1.* + unzip $_SLIB_BALL -d $_SLIB_DIR qpushd $_SLIB_DIR/slib cp guile.init guile.init.bak sed '/lambda.*'"'"'unix/a\ @@ -327,7 +303,7 @@ function inst_guile() { qpopd fi if test x$cross_compile = xyes ; then - qpushd $GUILE_DIR/bin + qpushd $_GUILE_UDIR/bin # The cross-compiling guile expects these program names # for the build-time guile ln -sf /usr/bin/guile-config mingw32-guile-config @@ -401,7 +377,7 @@ includedir=\${prefix}/include Name: libXML Version: $_LIBXML2_VERSION -Description: libXML library version2. +Description: libXML library version 2. Requires: Libs: -L\${libdir} -lxml2 -lz Cflags: -I\${includedir} @@ -411,23 +387,6 @@ EOF quiet ${LD} -L$_LIBXML2_UDIR/lib -lxml2 -o $TMP_UDIR/ofile || die "libxml2 not installed correctly" } -function inst_expat() { - setup Expat - _EXPAT_UDIR=`unix_path $EXPAT_DIR` - add_to_env $_EXPAT_UDIR/bin PATH - if quiet which xmlwf && test -f $_EXPAT_UDIR/bin/xmlwf.exe - then - echo "expat already installed. skipping." - else - wget_unpacked $EXPAT_URL $DOWNLOAD_DIR $EXPAT_DIR - qpushd $EXPAT_DIR - cp -r expat/* . - rm -rf expat - qpopd - fi - quiet which xmlwf || die "expat not installed correctly" -} - function inst_gnome() { setup Gnome platform _GNOME_UDIR=`unix_path $GNOME_DIR` @@ -435,14 +394,15 @@ function inst_gnome() { add_to_env -L$_GNOME_UDIR/lib GNOME_LDFLAGS add_to_env $_GNOME_UDIR/bin PATH add_to_env $_GNOME_UDIR/lib/pkgconfig PKG_CONFIG_PATH + add_to_env $_GNOME_UDIR/bin/pkg-config-msys.sh PKG_CONFIG add_to_env "-I $_GNOME_UDIR/share/aclocal" ACLOCAL_FLAGS if quiet gconftool-2 --version && - pkg-config --exists gconf-2.0 libgnome-2.0 libgnomeui-2.0 libgnomeprint-2.2 libgnomeprintui-2.2 libgtkhtml-3.8 && + ${PKG_CONFIG} --exists gconf-2.0 libgnome-2.0 libgnomeui-2.0 libgnomeprint-2.2 libgnomeprintui-2.2 libgtkhtml-3.8 && quiet intltoolize --version then echo "gnome packages installed. skipping." else - mkdir -p $GNOME_DIR + mkdir -p $_GNOME_UDIR wget_unpacked $GETTEXT_URL $DOWNLOAD_DIR $GNOME_DIR wget_unpacked $GETTEXT_DEV_URL $DOWNLOAD_DIR $GNOME_DIR wget_unpacked $LIBICONV_URL $DOWNLOAD_DIR $GNOME_DIR @@ -454,6 +414,7 @@ function inst_gnome() { wget_unpacked $PKG_CONFIG_URL $DOWNLOAD_DIR $GNOME_DIR wget_unpacked $CAIRO_URL $DOWNLOAD_DIR $GNOME_DIR wget_unpacked $CAIRO_DEV_URL $DOWNLOAD_DIR $GNOME_DIR + wget_unpacked $EXPAT_URL $DOWNLOAD_DIR $GNOME_DIR wget_unpacked $FONTCONFIG_URL $DOWNLOAD_DIR $GNOME_DIR wget_unpacked $FONTCONFIG_DEV_URL $DOWNLOAD_DIR $GNOME_DIR wget_unpacked $FREETYPE_URL $DOWNLOAD_DIR $GNOME_DIR @@ -503,7 +464,17 @@ function inst_gnome() { mv libz.dll.a ../lib qpopd fi - [ -f bin/libintl-2.dll ] || cp bin/intl.dll bin/libintl-2.dll + # work around a bug in msys bash, adding 0x01 smilies + cat > bin/pkg-config-msys.sh < /dev/null 2>&1 ; then + res=true +else + res=false +fi +\${PKG_CONFIG} "\$@" | tr -d \\\\r && \$res +EOF _FREETYPE_VERSION=`echo $FREETYPE_DEV_URL | sed 's#.*freetype-\(.*\)-lib.zip#\1#'` cat > lib/pkgconfig/freetype2.pc <