summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2004-08-09 17:32:20 -0400
committerJohn Wiegley <johnw@newartisans.com>2004-08-09 17:32:20 -0400
commit05b2cc46fdf6accd2ecbdc3c1ce86829bc7bfa68 (patch)
treeab61a5efdcdfe7bb73f346da5e45ac228d6458c0
parent2dc822291f3ecef34eb0ef2920c395b0e056fbda (diff)
downloadfork-ledger-05b2cc46fdf6accd2ecbdc3c1ce86829bc7bfa68.tar.gz
fork-ledger-05b2cc46fdf6accd2ecbdc3c1ce86829bc7bfa68.tar.bz2
fork-ledger-05b2cc46fdf6accd2ecbdc3c1ce86829bc7bfa68.zip
fixed account display bug
-rw-r--r--format.cc81
-rw-r--r--format.h24
-rw-r--r--ledger.h20
-rw-r--r--main.cc33
-rw-r--r--valexpr.cc34
-rw-r--r--valexpr.h2
-rw-r--r--walk.h36
7 files changed, 142 insertions, 88 deletions
diff --git a/format.cc b/format.cc
index aa1a8e1c..a48fa45f 100644
--- a/format.cc
+++ b/format.cc
@@ -397,44 +397,59 @@ void format_transaction::operator()(transaction_t * xact) const
last_xact = xact;
}
-
-void format_account::operator()(account_t * account,
- const unsigned int max_depth,
- const bool report_top) const
+bool format_account::disp_subaccounts_p(const account_t * account,
+ const item_predicate<account_t>&
+ disp_pred_functor,
+ const account_t *& to_show)
{
- // Don't output the account if only one child will be displayed
- // which shows the exact same amount. jww (2004-08-03): How do
- // compute the right figure? It should a value expression specified
- // by the user, to say, "If this expression is equivalent between a
- // parent account and a lone displayed child, then don't display the
- // parent."
-
- if (bool output = ((report_top || account->parent != NULL) &&
- disp_pred_functor(account))) {
- int counted = 0;
- bool display = false;
-
- for (accounts_map::const_iterator i = account->accounts.begin();
- i != account->accounts.end();
- i++) {
- if (! (*i).second->total)
- continue;
-
- if ((*i).second->total != account->total || counted > 0) {
- display = true;
- break;
- }
- counted++;
- }
+ bool display = false;
+ unsigned int counted = 0;
+
+ to_show = NULL;
+
+ for (accounts_map::const_iterator i = account->accounts.begin();
+ i != account->accounts.end();
+ i++) {
+ // jww (2004-08-03): How do compute the right figure? It should a
+ // value expression specified by the user, to say, "If this
+ // expression is equivalent between a parent account and a lone
+ // displayed child, then don't display the parent."
- if (counted == 1 && ! display)
- output = false;
+ if (! (*i).second->total || ! disp_pred_functor((*i).second))
+ continue;
- if (output && (max_depth == 0 || account->depth <= max_depth)) {
- format.format_elements(output_stream, details_t(account));
- account->dflags |= ACCOUNT_DISPLAYED;
+ if ((*i).second->total != account->total || counted > 0) {
+ display = true;
+ break;
}
+ to_show = (*i).second;
+ counted++;
}
+
+ return display;
+}
+
+bool format_account::display_account(const account_t * account,
+ const item_predicate<account_t>&
+ disp_pred_functor)
+{
+ // Never display the master account, or an account that has already
+ // been displayed.
+ if (! account->parent || account->dflags & ACCOUNT_DISPLAYED)
+ return false;
+
+ // At this point, one of two possibilities exists: the account is a
+ // leaf which matches the predicate restrictions; or it is a parent
+ // and two or more children must be subtotaled; or it is a parent
+ // and its child has been hidden by the predicate. So first,
+ // determine if it is a parent that must be displayed regardless of
+ // the predicate.
+
+ const account_t * account_to_show = NULL;
+ if (disp_subaccounts_p(account, disp_pred_functor, account_to_show))
+ return true;
+
+ return ! account_to_show && disp_pred_functor(account);
}
} // namespace ledger
diff --git a/format.h b/format.h
index 65c111e1..66a7f7cf 100644
--- a/format.h
+++ b/format.h
@@ -204,9 +204,20 @@ class format_account
: output_stream(_output_stream), format(_format),
disp_pred_functor(display_predicate) {}
- void operator()(account_t * account,
- const unsigned int max_depth = 1,
- const bool report_top = false) const;
+ static bool disp_subaccounts_p(const account_t * account,
+ const item_predicate<account_t>&
+ disp_pred_functor,
+ const account_t *& to_show);
+ static bool display_account(const account_t * account,
+ const item_predicate<account_t>&
+ disp_pred_functor);
+
+ void operator()(const account_t * account) const {
+ if (display_account(account, disp_pred_functor)) {
+ format.format_elements(output_stream, details_t(account));
+ account->dflags |= ACCOUNT_DISPLAYED;
+ }
+ }
};
@@ -241,11 +252,8 @@ class format_equity
next_lines_format.format_elements(output_stream, details_t(&summary));
}
- void operator()(account_t * account,
- const unsigned int max_depth = 1,
- const bool report_top = false) const {
- if ((report_top || account->parent != NULL) &&
- disp_pred_functor(account)) {
+ void operator()(const account_t * account) const {
+ if (format_account::display_account(account, disp_pred_functor)) {
next_lines_format.format_elements(output_stream, details_t(account));
account->dflags |= ACCOUNT_DISPLAYED;
total += account->value.quantity;
diff --git a/ledger.h b/ledger.h
index ba5e5592..c9bd37ba 100644
--- a/ledger.h
+++ b/ledger.h
@@ -41,9 +41,10 @@ class transaction_t
amount_t cost;
unsigned int flags;
std::string note;
- balance_pair_t total;
- unsigned int index;
- unsigned int dflags;
+
+ mutable balance_pair_t total;
+ mutable unsigned int index;
+ mutable unsigned int dflags;
transaction_t(entry_t * _entry, account_t * _account)
: entry(_entry), account(_account), flags(TRANSACTION_NORMAL),
@@ -105,15 +106,16 @@ class account_t
account_t * parent;
std::string name;
std::string note;
- unsigned long depth;
+ unsigned int depth;
accounts_map accounts;
transactions_list transactions;
- balance_pair_t value;
- balance_pair_t total;
- unsigned long ident;
- unsigned long dflags;
- mutable std::string _fullname;
+ mutable balance_pair_t value;
+ mutable balance_pair_t total;
+ mutable unsigned long ident;
+ mutable unsigned long dflags;
+ mutable std::string _fullname;
+
static unsigned long next_ident;
account_t(account_t * _parent,
diff --git a/main.cc b/main.cc
index 31b56942..35dfd860 100644
--- a/main.cc
+++ b/main.cc
@@ -570,10 +570,19 @@ int main(int argc, char * argv[])
}
if (display_predicate_string.empty()) {
- if (command == "b" && ! show_empty)
- display_predicate_string = "T";
- else if (command == "E")
+ if (command == "b") {
+ if (! show_empty)
+ display_predicate_string = "T";
+
+ if (! show_expanded) {
+ if (! display_predicate_string.empty())
+ display_predicate_string += "&";
+ display_predicate_string += "!n";
+ }
+ }
+ else if (command == "E") {
display_predicate_string = "a";
+ }
}
if (! display_predicate_string.empty()) {
@@ -640,16 +649,12 @@ int main(int argc, char * argv[])
format_t format(first_line_format);
format_account formatter(std::cout, format, display_predicate.get());
walk_accounts(journal->master, formatter, predicate.get(),
- xact_display_flags, show_subtotals, show_expanded ? 0 : 1,
- sort_order.get());
-
- if (! display_predicate.get() ||
- item_predicate<account_t>(display_predicate.get())(journal->master)) {
- std::string end_format = "--------------------\n";
- format.reset(end_format + f);
- format_account(std::cout, format)(journal->master, true,
- display_predicate.get());
- }
+ xact_display_flags, show_subtotals, sort_order.get());
+
+ std::string end_format = "--------------------\n";
+ format.reset(end_format + f);
+ format_account(std::cout, format,
+ display_predicate.get())(journal->master);
}
else if (command == "E") {
format_t format(first_line_format);
@@ -657,7 +662,7 @@ int main(int argc, char * argv[])
format_equity formatter(std::cout, format, nformat,
display_predicate.get());
walk_accounts(journal->master, formatter, predicate.get(),
- xact_display_flags, true, 0, sort_order.get());
+ xact_display_flags, true, sort_order.get());
}
else if (command == "e") {
format_t format(first_line_format);
diff --git a/valexpr.cc b/valexpr.cc
index 6a3ccde7..15aa69f8 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -158,18 +158,46 @@ void node_t::compute(balance_t& result, const details_t& details) const
break;
case CLEARED:
- if (details.entry)
+ if (details.entry) {
result = details.entry->state == entry_t::CLEARED;
+ }
+ else if (details.account) {
+ bool all_clear = true;
+ for (transactions_list::const_iterator i
+ = details.account->transactions.begin();
+ i != details.account->transactions.end();
+ i++)
+ if ((*i)->entry->state != entry_t::CLEARED) {
+ all_clear = false;
+ break;
+ }
+ result = all_clear;
+ }
break;
case REAL:
- if (details.xact)
+ if (details.xact) {
result = ! (details.xact->flags & TRANSACTION_VIRTUAL);
+ }
+ else if (details.account) {
+ bool all_real = true;
+ for (transactions_list::const_iterator i
+ = details.account->transactions.begin();
+ i != details.account->transactions.end();
+ i++)
+ if ((*i)->flags & TRANSACTION_VIRTUAL) {
+ all_real = false;
+ break;
+ }
+ result = all_real;
+ }
break;
case INDEX:
if (details.xact)
result = details.xact->index + 1;
+ else if (details.account)
+ result = details.account->depth - 1;
break;
case F_ARITH_MEAN:
@@ -359,7 +387,7 @@ node_t * parse_term(std::istream& in)
case 'd': node = new node_t(node_t::DATE); break;
case 'X': node = new node_t(node_t::CLEARED); break;
case 'R': node = new node_t(node_t::REAL); break;
- case 'i': node = new node_t(node_t::INDEX); break;
+ case 'n': node = new node_t(node_t::INDEX); break;
case 'B': node = new node_t(node_t::BALANCE); break;
case 'T': node = new node_t(node_t::TOTAL); break;
case 'C': node = new node_t(node_t::COST_TOTAL); break;
diff --git a/valexpr.h b/valexpr.h
index a774472f..17ecc123 100644
--- a/valexpr.h
+++ b/valexpr.h
@@ -57,7 +57,7 @@ struct node_t
DATE,
CLEARED,
REAL,
- INDEX,
+ INDEX, // for accounts, this is the DEPTH
// Item totals
BALANCE,
diff --git a/walk.h b/walk.h
index d8224c3d..e01b5d97 100644
--- a/walk.h
+++ b/walk.h
@@ -154,25 +154,22 @@ inline void sort_accounts(account_t * account,
}
template <typename Function>
-void walk__accounts(account_t * account,
- const Function& functor,
- const unsigned int max_depth)
+void walk__accounts(account_t * account, const Function& functor)
{
- functor(account, max_depth);
+ functor(account);
for (accounts_map::const_iterator i = account->accounts.begin();
i != account->accounts.end();
i++)
- walk__accounts((*i).second, functor, max_depth);
+ walk__accounts((*i).second, functor);
}
template <typename Function>
-void walk__accounts_sorted(account_t * account,
- const Function& functor,
- const unsigned int max_depth,
- const node_t * sort_order)
+void walk__accounts_sorted(account_t * account,
+ const Function& functor,
+ const node_t * sort_order)
{
- functor(account, max_depth);
+ functor(account);
accounts_deque accounts;
@@ -187,7 +184,7 @@ void walk__accounts_sorted(account_t * account,
for (accounts_deque::const_iterator i = accounts.begin();
i != accounts.end();
i++)
- walk__accounts_sorted(*i, functor, max_depth, sort_order);
+ walk__accounts_sorted(*i, functor, sort_order);
}
template <typename Function>
@@ -217,13 +214,12 @@ inline void sum__accounts(account_t * account)
}
template <typename Function>
-void walk_accounts(account_t * account,
- const Function& functor,
- const node_t * predicate,
- unsigned int flags,
- const bool calc_subtotals,
- const unsigned int max_depth,
- const node_t * sort_order = NULL)
+void walk_accounts(account_t * account,
+ const Function& functor,
+ const node_t * predicate,
+ unsigned int flags,
+ const bool calc_subtotals,
+ const node_t * sort_order = NULL)
{
item_predicate<transaction_t> pred_functor(predicate);
@@ -232,9 +228,9 @@ void walk_accounts(account_t * account,
sum__accounts(account);
if (sort_order)
- walk__accounts_sorted<Function>(account, functor, max_depth, sort_order);
+ walk__accounts_sorted<Function>(account, functor, sort_order);
else
- walk__accounts<Function>(account, functor, max_depth);
+ walk__accounts<Function>(account, functor);
}
} // namespace ledger