33 #include "gnc-component-manager.h" 45 #define REGISTER_SINGLE_CM_CLASS "register-single" 46 #define REGISTER_SUBACCOUNT_CM_CLASS "register-subaccount" 47 #define REGISTER_GL_CM_CLASS "register-gl" 48 #define REGISTER_TEMPLATE_CM_CLASS "register-template" 50 #define GNC_PREF_DOUBLE_LINE_MODE "double-line-mode" 51 #define GNC_PREF_MAX_TRANS "max-transactions" 52 #define GNC_PREF_DEFAULT_STYLE_LEDGER "default-style-ledger" 53 #define GNC_PREF_DEFAULT_STYLE_AUTOLEDGER "default-style-autoledger" 54 #define GNC_PREF_DEFAULT_STYLE_JOURNAL "default-style-journal" 62 Query* pre_filter_query;
64 GNCLedgerDisplayType ld_type;
69 gboolean use_double_line_default;
71 gboolean needs_refresh;
73 GNCLedgerDisplayDestroy destroy;
74 GNCLedgerDisplayGetParent get_parent;
76 GHashTable *excluded_template_acc_hash;
80 gint number_of_subaccounts;
87 static QofLogModule log_module = GNC_MOD_LEDGER;
91 static GNCLedgerDisplay*
92 gnc_ledger_display_internal (
Account* lead_account,
Query* q,
93 GNCLedgerDisplayType ld_type,
96 gboolean use_double_line,
98 gboolean mismatched_commodities);
101 gnc_ledger_display_refresh_internal (GNCLedgerDisplay* ld);
103 static void gnc_ledger_display_make_query (GNCLedgerDisplay* ld,
119 gnc_ledger_display_type (GNCLedgerDisplay* ld)
133 ld->user_data = user_data;
137 gnc_ledger_display_get_user_data (GNCLedgerDisplay* ld)
142 return ld->user_data;
147 GNCLedgerDisplayDestroy destroy,
148 GNCLedgerDisplayGetParent get_parent)
153 ld->destroy = destroy;
154 ld->get_parent = get_parent;
176 exclude_template_accounts (
Query* q, GHashTable *excluded_template_acc_hash)
188 for (node = al; node; node = next)
191 next = g_list_next (node);
193 if (g_hash_table_lookup (excluded_template_acc_hash, acc) != NULL)
194 al = g_list_delete_link (al, node);
196 g_hash_table_insert (excluded_template_acc_hash, acc, acc);
200 xaccQueryAddAccountMatch (q, al, QOF_GUID_MATCH_NONE, QOF_QUERY_AND);
208 find_by_leader (gpointer
find_data, gpointer user_data)
211 GNCLedgerDisplay* ld = user_data;
220 find_by_query (gpointer
find_data, gpointer user_data)
223 GNCLedgerDisplay* ld = user_data;
225 if (ld->reg->type != SEARCH_LEDGER)
231 return ld->query == q;
235 find_by_reg (gpointer
find_data, gpointer user_data)
238 GNCLedgerDisplay* ld = user_data;
243 return ld->reg == reg;
252 GNC_PREF_DEFAULT_STYLE_JOURNAL))
253 new_style = REG_STYLE_JOURNAL;
255 GNC_PREF_DEFAULT_STYLE_AUTOLEDGER))
256 new_style = REG_STYLE_AUTO_LEDGER;
262 look_for_portfolio_cb (
Account* account, gpointer data)
268 gnc_get_reg_type (
Account* leader, GNCLedgerDisplayType ld_type)
273 if (ld_type == LD_GL)
274 return GENERAL_JOURNAL;
278 if (ld_type == LD_SINGLE)
280 switch (account_type)
283 return BANK_REGISTER;
286 return CASH_REGISTER;
289 return ASSET_REGISTER;
292 return CREDIT_REGISTER;
295 return LIABILITY_REGISTER;
298 return PAYABLE_REGISTER;
301 return RECEIVABLE_REGISTER;
305 return STOCK_REGISTER;
308 return INCOME_REGISTER;
311 return EXPENSE_REGISTER;
314 return EQUITY_REGISTER;
317 return CURRENCY_REGISTER;
320 return TRADING_REGISTER;
323 PERR (
"unknown account type %d\n", account_type);
324 return BANK_REGISTER;
328 if (ld_type != LD_SUBACCOUNT)
330 PERR (
"unknown ledger type %d\n", ld_type);
331 return BANK_REGISTER;
334 switch (account_type)
348 reg_type = GENERAL_JOURNAL;
352 if (ret) reg_type = PORTFOLIO_LEDGER;
359 reg_type = PORTFOLIO_LEDGER;
364 reg_type = INCOME_LEDGER;
369 reg_type = GENERAL_JOURNAL;
373 PERR (
"unknown account type:%d", account_type);
374 reg_type = GENERAL_JOURNAL;
386 return (gld->use_double_line_default ||
388 GNC_PREF_DOUBLE_LINE_MODE));
397 gboolean use_double_line;
398 GNCLedgerDisplay* ld;
400 ENTER (
"account=%p", account);
406 use_double_line = TRUE;
409 use_double_line = FALSE;
413 reg_type = gnc_get_reg_type (account, LD_SINGLE);
415 ld = gnc_ledger_display_internal (account, NULL, LD_SINGLE, reg_type,
416 gnc_get_default_register_style (acc_type),
417 use_double_line, FALSE, FALSE);
426 gboolean mismatched_commodities)
429 GNCLedgerDisplay* ld;
431 ENTER (
"account=%p", account);
433 reg_type = gnc_get_reg_type (account, LD_SUBACCOUNT);
435 ld = gnc_ledger_display_internal (account, NULL, LD_SUBACCOUNT,
436 reg_type, REG_STYLE_JOURNAL, FALSE,
437 FALSE, mismatched_commodities);
448 GNCLedgerDisplay* ld;
449 GHashTable *exclude_template_accounts_hash;
453 query = qof_query_create_for (GNC_ID_SPLIT);
457 exclude_template_accounts_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
466 exclude_template_accounts (query, exclude_template_accounts_hash);
469 static const time64 secs_per_thirty_days = 2592000;
472 xaccQueryAddDateMatchTT (query,
477 ld = gnc_ledger_display_internal (NULL, query, LD_GL, GENERAL_JOURNAL,
478 REG_STYLE_JOURNAL, FALSE, FALSE, FALSE);
480 ld->excluded_template_acc_hash = exclude_template_accounts_hash;
500 GNCLedgerDisplay* ld;
503 gboolean isTemplateModeTrue;
505 ENTER (
"id=%s",
id ?
id :
"(null)");
508 isTemplateModeTrue = TRUE;
510 q = qof_query_create_for (GNC_ID_SPLIT);
512 book = gnc_get_current_book();
520 xaccQueryAddSingleAccountMatch (q, acct, QOF_QUERY_AND);
523 ld = gnc_ledger_display_internal (NULL, q, LD_GL,
548 if (ld->get_parent == NULL)
551 return ld->get_parent (ld);
555 gnc_ledger_display_parent (
void* user_data)
557 GNCLedgerDisplay* ld = user_data;
562 gnc_ledger_display_set_watches (GNCLedgerDisplay* ld, GList* splits)
566 gnc_gui_component_clear_watches (ld->component_id);
568 gnc_gui_component_watch_entity_type (ld->component_id,
570 QOF_EVENT_MODIFY | QOF_EVENT_DESTROY
571 | GNC_EVENT_ITEM_CHANGED);
573 for (node = splits; node; node = node->next)
575 Split* split = node->data;
578 gnc_gui_component_watch_entity (ld->component_id,
585 refresh_handler (GHashTable* changes, gpointer user_data)
587 GNCLedgerDisplay* ld = user_data;
591 ENTER (
"changes=%p, user_data=%p", changes, user_data);
595 LEAVE (
"already loading");
599 has_leader = (ld->ld_type == LD_SINGLE || ld->ld_type == LD_SUBACCOUNT);
606 gnc_close_gui_component (ld->component_id);
612 if (changes && has_leader)
614 info = gnc_gui_get_entity_events (changes, &ld->leader);
615 if (info && (info->event_mask & QOF_EVENT_DESTROY))
617 gnc_close_gui_component (ld->component_id);
625 DEBUG (
"immediate refresh because ledger is visible");
630 ld->needs_refresh = TRUE;
636 close_handler (gpointer user_data)
638 GNCLedgerDisplay* ld = user_data;
643 gnc_unregister_gui_component (ld->component_id);
644 ld->component_id = NO_COMPONENT;
653 if (ld->excluded_template_acc_hash)
654 g_hash_table_destroy (ld->excluded_template_acc_hash);
660 ld->pre_filter_query = NULL;
666 gnc_ledger_display_make_query (GNCLedgerDisplay* ld,
686 PERR (
"unknown ledger type: %d", ld->ld_type);
691 ld->query = qof_query_create_for (GNC_ID_SPLIT);
697 if ((limit != 0) && (type != SEARCH_LEDGER))
707 if (ld->ld_type == LD_SUBACCOUNT)
710 ld->number_of_subaccounts = g_list_length (accounts);
715 accounts = g_list_prepend (accounts, leader);
717 xaccQueryAddAccountMatch (ld->query, accounts,
720 g_list_free (accounts);
728 GNCLedgerDisplay* ld;
730 ENTER (
"query=%p", query);
732 ld = gnc_ledger_display_internal (NULL, query, LD_GL, type, style,
733 FALSE, FALSE, FALSE);
735 ld->excluded_template_acc_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
740 static GNCLedgerDisplay*
741 gnc_ledger_display_internal (
Account* lead_account,
Query* q,
742 GNCLedgerDisplayType ld_type,
745 gboolean use_double_line,
746 gboolean is_template,
747 gboolean mismatched_commodities)
749 GNCLedgerDisplay* ld;
756 klass = REGISTER_SINGLE_CM_CLASS;
758 if (reg_type >= NUM_SINGLE_REGISTER_TYPES)
760 PERR (
"single-account register with wrong split register type");
766 PERR (
"single-account register with no account specified");
772 PWARN (
"single-account register with external query");
776 ld = gnc_find_first_gui_component (klass, find_by_leader, lead_account);
783 klass = REGISTER_SUBACCOUNT_CM_CLASS;
787 PERR (
"sub-account register with no lead account");
793 PWARN (
"account register with external query");
797 ld = gnc_find_first_gui_component (klass, find_by_leader, lead_account);
804 klass = REGISTER_GL_CM_CLASS;
808 PWARN (
"general journal with no query");
814 PERR (
"bad ledger type: %d", ld_type);
819 ld = g_new (GNCLedgerDisplay, 1);
823 ld->ld_type = ld_type;
826 ld->needs_refresh = TRUE;
828 ld->get_parent = NULL;
829 ld->user_data = NULL;
830 ld->excluded_template_acc_hash = NULL;
839 gnc_ledger_display_make_query (ld, limit, reg_type);
843 ld->component_id = gnc_register_gui_component (klass,
851 ld->use_double_line_default = use_double_line;
854 is_template, mismatched_commodities);
871 if (!ledger_display || !q)
874 g_return_if_fail (ledger_display->ld_type == LD_GL);
886 return gnc_find_first_gui_component (REGISTER_GL_CM_CLASS, find_by_query, q);
894 gnc_ledger_display_refresh_internal (GNCLedgerDisplay* ld)
897 GList* pre_filter_splits = NULL;
912 gnc_ledger_display_set_watches (ld, splits);
922 ld->needs_refresh = FALSE;
933 LEAVE (
"no display");
939 LEAVE (
"already loading");
945 if (ld->ld_type == LD_SUBACCOUNT)
950 if (g_list_length (accounts) != ld->number_of_subaccounts)
952 time64 start_time, end_time;
953 xaccQueryGetDateMatchTT (ld->query, &start_time, &end_time);
955 cleared_match_t cleared_match = xaccQueryGetClearedMatch (ld->query);
957 gnc_ledger_display_make_query (ld,
959 gnc_get_reg_type (leader, ld->ld_type));
964 if (cleared_match != CLEARED_ALL)
965 xaccQueryAddClearedMatch (ld->query, cleared_match, QOF_QUERY_AND);
967 if (start_time || end_time)
969 xaccQueryAddDateMatchTT (ld->query,
970 start_time != 0, start_time,
971 end_time != 0, end_time,
975 g_list_free (accounts);
985 if (!ld->reg->is_template && (ld->reg->type == SEARCH_LEDGER || ld->ld_type == LD_GL))
987 exclude_template_accounts (ld->query, ld->excluded_template_acc_hash);
992 gnc_ledger_display_refresh_internal (ld);
1001 ld->visible = focus;
1003 if (ld->visible && ld->needs_refresh)
1005 DEBUG (
"deferred refresh because ledger is now visible");
1011 gnc_ledger_display_refresh_by_split_register (SplitRegister* reg)
1013 GNCLedgerDisplay* ld;
1018 ld = gnc_find_first_gui_component (REGISTER_SINGLE_CM_CLASS,
1026 ld = gnc_find_first_gui_component (REGISTER_SUBACCOUNT_CM_CLASS,
1034 ld = gnc_find_first_gui_component (REGISTER_GL_CM_CLASS,
1042 ld = gnc_find_first_gui_component (REGISTER_TEMPLATE_CM_CLASS,
1056 gnc_close_gui_component (ld->component_id);
void gnc_ledger_display_close(GNCLedgerDisplay *ld)
close the window
Public declarations for GncLedgerDisplay class.
void gnc_ledger_display_set_focus(GNCLedgerDisplay *ld, gboolean focus)
Mark the ledger as being in focus (refresh immediately) or not.
void gnc_ledger_display_refresh(GNCLedgerDisplay *ld)
redisplay/redraw only the indicated window.
gboolean gnc_ledger_display_default_double_line(GNCLedgerDisplay *gld)
Returns a boolean of whether this display should be single or double lined mode by default...
Date and Time handling routines.
void gnc_split_register_destroy(SplitRegister *reg)
Destroys a split register.
gboolean xaccAccountIsPriced(const Account *acc)
Returns true if the account is a stock, mutual fund or currency, otherwise false. ...
utility functions for the GnuCash UI
Expense accounts are used to denote expenses.
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
#define DEBUG(format, args...)
Print a debugging message.
Mutual Fund accounts will typically be shown in registers which show three columns: price...
gpointer gnc_account_foreach_descendant_until(const Account *acc, AccountCb2 thunk, gpointer user_data)
This method will traverse all children of this accounts and their descendants, calling 'func' on each...
TableControl specialized for the SplitRegister.
gboolean gnc_split_register_full_refresh_ok(SplitRegister *reg)
Private function – outsiders must not use this.
QofQuery * qof_query_copy(QofQuery *q)
Make a copy of the indicated query.
gboolean qof_query_equal(const QofQuery *q1, const QofQuery *q2)
Compare two queries for equality.
Account * gnc_ledger_display_leader(GNCLedgerDisplay *ld)
Implementations.
void gnc_split_register_set_template_account(SplitRegister *reg, Account *template_account)
Set the template account for use in a template register.
Account * gnc_book_get_template_root(const QofBook *book)
Returns the template group from the book.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
TableModels specialized for SplitRegister and template SplitRegister.
void gnc_ledger_display_set_query(GNCLedgerDisplay *ledger_display, Query *q)
Set the query used for a register.
void gnc_split_register_set_data(SplitRegister *reg, gpointer user_data, SRGetParentCallback get_parent)
Sets the user data and callback hooks for the register.
void gnc_split_register_load(SplitRegister *reg, GList *slist, GList *pre_filter_slist, Account *default_account)
Populates the rows of a register.
These expect a single object and expect the QofAccessFunc returns GncGUID*.
#define PERR(format, args...)
Log a serious error.
#define ENTER(format, args...)
Print a function entry debugging message.
The cash account type is used to denote a shoe-box or pillowcase stuffed with * cash.
Query * gnc_ledger_display_get_query(GNCLedgerDisplay *ld)
return the query associated with a ledger
Account used to record multiple commodity transactions.
void qof_query_set_max_results(QofQuery *q, int n)
Set the maximum number of results that should be returned.
Account * gnc_account_lookup_by_name(const Account *parent, const char *name)
The gnc_account_lookup_by_name() subroutine fetches the account by name from the descendants of the s...
#define PWARN(format, args...)
Log a warning.
Stock accounts will typically be shown in registers which show three columns: price, number of shares, and value.
GNCLedgerDisplay * gnc_ledger_display_subaccounts(Account *account, gboolean mismatched_commodities)
opens up a register window to display the parent account and all of its children. ...
#define xaccAccountGetGUID(X)
Account handling public routines.
void qof_query_destroy(QofQuery *query)
Frees the resources associate with a Query object.
void gnc_ledger_display_set_handlers(GNCLedgerDisplay *ld, GNCLedgerDisplayDestroy destroy, GNCLedgerDisplayGetParent get_parent)
set the handlers used by the ledger display
Income accounts are used to denote income.
The GNCLedgerDisplay struct describes a single register/ledger instance.
void qof_query_set_book(QofQuery *query, QofBook *book)
Set the book to be searched.
Anchor Scheduled Transaction info in a book.
The bank account type denotes a savings or checking account held at a bank.
time64 gnc_time64_get_today_start(void)
The gnc_time64_get_today_start() routine returns a time64 value corresponding to the first second of ...
Additional event handling code.
GtkWidget * gnc_ledger_display_get_parent(GNCLedgerDisplay *ld)
Returns the parent of a given ledger display.
asset (and liability) accounts indicate generic, generalized accounts that are none of the above...
All type declarations for the whole Gnucash engine.
The currency account type indicates that the account is a currency trading account.
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
#define xaccTransGetGUID(X)
Generic api to store and retrieve preferences.
GList * gnc_account_get_descendants(const Account *account)
This routine returns a flat list of all of the accounts that are descendants of the specified account...
GNCLedgerDisplay * gnc_ledger_display_template_gl(char *id)
Displays a template ledger.
GList * qof_query_run(QofQuery *query)
Perform the query, return the results.
liability (and asset) accounts indicate generic, generalized accounts that are none of the above...
GNCLedgerDisplay * gnc_ledger_display_simple(Account *account)
opens up a register window to display a single account
GNCLedgerDisplay * gnc_ledger_display_find_by_query(Query *q)
If the given ledger display still exists, return it.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
#define LEAVE(format, args...)
Print a function exit debugging message.
GNCLedgerDisplay * gnc_ledger_display_query(Query *query, SplitRegisterType type, SplitRegisterStyle style)
display a general ledger for an arbitrary query
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
GNCLedgerDisplay * gnc_ledger_display_gl(void)
opens up a general ledger window
SplitRegister * gnc_ledger_display_get_split_register(GNCLedgerDisplay *ld)
return the split register associated with a ledger display
Equity account is used to balance the balance sheet.
SplitRegisterType
Register types.
gint gnc_list_length_cmp(const GList *list, size_t len)
Scans the GList elements the minimum number of iterations required to test it against a specified siz...
API for Transactions and Splits (journal entries)
The type used to store guids in C.
void gnc_ledger_display_set_user_data(GNCLedgerDisplay *ld, gpointer user_data)
get and set the user data associated with the ledger
SplitRegister * gnc_split_register_new(SplitRegisterType type, SplitRegisterStyle style, gboolean use_double_line, gboolean is_template, gboolean mismatched_commodities)
Creates a new split register.
SplitRegisterStyle
Register styles.
The Credit card account is used to denote credit (e.g.
gdouble gnc_prefs_get_float(const gchar *group, const gchar *pref_name)
Get an float value from the preferences backend.
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
The xaccAccountLookup() subroutine will return the account associated with the given id...