fixed account display bug

This commit is contained in:
John Wiegley 2004-08-09 17:32:20 -04:00
parent 2dc822291f
commit 05b2cc46fd
7 changed files with 140 additions and 86 deletions

View file

@ -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;
unsigned int counted = 0;
to_show = NULL;
for (accounts_map::const_iterator i = account->accounts.begin();
i != account->accounts.end();
i++) {
if (! (*i).second->total)
// 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 (! (*i).second->total || ! disp_pred_functor((*i).second))
continue;
if ((*i).second->total != account->total || counted > 0) {
display = true;
break;
}
to_show = (*i).second;
counted++;
}
if (counted == 1 && ! display)
output = false;
return display;
}
if (output && (max_depth == 0 || account->depth <= max_depth)) {
format.format_elements(output_stream, details_t(account));
account->dflags |= ACCOUNT_DISPLAYED;
}
}
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

View file

@ -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;

View file

@ -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 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,

25
main.cc
View file

@ -570,11 +570,20 @@ int main(int argc, char * argv[])
}
if (display_predicate_string.empty()) {
if (command == "b" && ! show_empty)
if (command == "b") {
if (! show_empty)
display_predicate_string = "T";
else if (command == "E")
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()) {
#ifdef DEBUG
@ -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());
xact_display_flags, show_subtotals, 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());
}
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);

View file

@ -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;

View file

@ -57,7 +57,7 @@ struct node_t
DATE,
CLEARED,
REAL,
INDEX,
INDEX, // for accounts, this is the DEPTH
// Item totals
BALANCE,

18
walk.h
View file

@ -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)
{
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>
@ -222,7 +219,6 @@ void walk_accounts(account_t * account,
const node_t * predicate,
unsigned int flags,
const bool calc_subtotals,
const unsigned int max_depth,
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