summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2009-02-19 16:53:25 -0400
committerJohn Wiegley <johnw@newartisans.com>2009-02-19 16:53:25 -0400
commit9805abbf2b38d64308bac536eea40e544e8f7cfe (patch)
tree32f6b6ae629409a118efdbc99f377fa86640e33d /src
parentd67c9fee0f0f576481065c7d50182a04bf5df37e (diff)
downloadfork-ledger-9805abbf2b38d64308bac536eea40e544e8f7cfe.tar.gz
fork-ledger-9805abbf2b38d64308bac536eea40e544e8f7cfe.tar.bz2
fork-ledger-9805abbf2b38d64308bac536eea40e544e8f7cfe.zip
Allow for sorting of the balance report
Sorting is repeated at each level of the hierarchy, unless --flat was specified in which case it applies to the entire applicable accounts list.
Diffstat (limited to 'src')
-rw-r--r--src/iterators.cc30
-rw-r--r--src/iterators.h24
-rw-r--r--src/output.cc92
-rw-r--r--src/output.h10
-rw-r--r--src/report.cc4
-rw-r--r--src/value.cc5
6 files changed, 97 insertions, 68 deletions
diff --git a/src/iterators.cc b/src/iterators.cc
index 01f678d0..3a59c7aa 100644
--- a/src/iterators.cc
+++ b/src/iterators.cc
@@ -179,6 +179,33 @@ void sorted_accounts_iterator::sort_accounts(account_t& account,
compare_items<account_t>(sort_cmp));
}
+void sorted_accounts_iterator::push_all(account_t& account)
+{
+ accounts_deque_t& deque(accounts_list.back());
+
+ foreach (accounts_map::value_type& pair, account.accounts) {
+ deque.push_back(pair.second);
+ push_all(*pair.second);
+ }
+}
+
+void sorted_accounts_iterator::push_back(account_t& account)
+{
+ accounts_list.push_back(accounts_deque_t());
+
+ if (flatten_all) {
+ push_all(account);
+ std::stable_sort(accounts_list.back().begin(),
+ accounts_list.back().end(),
+ compare_items<account_t>(sort_cmp));
+ } else {
+ sort_accounts(account, accounts_list.back());
+ }
+
+ sorted_accounts_i.push_back(accounts_list.back().begin());
+ sorted_accounts_end.push_back(accounts_list.back().end());
+}
+
account_t * sorted_accounts_iterator::operator()()
{
while (! sorted_accounts_i.empty() &&
@@ -195,9 +222,10 @@ account_t * sorted_accounts_iterator::operator()()
assert(account);
// If this account has children, queue them up to be iterated next.
- if (! account->accounts.empty())
+ if (! flatten_all && ! account->accounts.empty())
push_back(*account);
+ // Make sure the sorting value gets recalculated for this account
account->xdata().drop_flags(ACCOUNT_EXT_SORT_CALC);
return account;
}
diff --git a/src/iterators.h b/src/iterators.h
index 8bf05986..92f887d0 100644
--- a/src/iterators.h
+++ b/src/iterators.h
@@ -244,6 +244,7 @@ public:
class sorted_accounts_iterator : public accounts_iterator
{
expr_t sort_cmp;
+ bool flatten_all;
typedef std::deque<account_t *> accounts_deque_t;
@@ -252,13 +253,14 @@ class sorted_accounts_iterator : public accounts_iterator
std::list<accounts_deque_t::const_iterator> sorted_accounts_end;
public:
- sorted_accounts_iterator(const string& sort_order) {
- TRACE_CTOR(sorted_accounts_iterator, "const string&");
- sort_cmp = expr_t(sort_order);
+ sorted_accounts_iterator(const expr_t& _sort_cmp, bool _flatten_all)
+ : sort_cmp(_sort_cmp), flatten_all(_flatten_all) {
+ TRACE_CTOR(sorted_accounts_iterator, "const expr_t&, bool");
}
- sorted_accounts_iterator(account_t& account, const string& sort_order) {
- TRACE_CTOR(sorted_accounts_iterator, "account_t&, const string&");
- sort_cmp = expr_t(sort_order);
+ sorted_accounts_iterator(const expr_t& _sort_cmp, bool _flatten_all,
+ account_t& account)
+ : sort_cmp(_sort_cmp), flatten_all(_flatten_all) {
+ TRACE_CTOR(sorted_accounts_iterator, "const expr_t&, bool, account_t&");
push_back(account);
}
virtual ~sorted_accounts_iterator() throw() {
@@ -266,14 +268,8 @@ public:
}
void sort_accounts(account_t& account, accounts_deque_t& deque);
-
- void push_back(account_t& account) {
- accounts_list.push_back(accounts_deque_t());
- sort_accounts(account, accounts_list.back());
-
- sorted_accounts_i.push_back(accounts_list.back().begin());
- sorted_accounts_end.push_back(accounts_list.back().end());
- }
+ void push_all(account_t& account);
+ void push_back(account_t& account);
virtual account_t * operator()();
};
diff --git a/src/output.cc b/src/output.cc
index 31208c26..bd55fe99 100644
--- a/src/output.cc
+++ b/src/output.cc
@@ -210,63 +210,64 @@ void format_entries::operator()(xact_t& xact)
last_entry = xact.entry;
}
-std::size_t format_accounts::post_accounts(account_t& account)
+void format_accounts::post_account(account_t& account)
{
- std::size_t displayed = 0;
+ bind_scope_t bound_scope(report, account);
+ bool format_account = false;
- // Don't ever print the top-most account
- if (account.parent) {
- bind_scope_t bound_scope(report, account);
- bool format_account = false;
-
- DEBUG("account.display", "Should we display " << account.fullname());
+ DEBUG("account.display", "Should we display " << account.fullname());
- if (account.has_flags(ACCOUNT_EXT_MATCHING) ||
- (! flatten_list &&
- account.children_with_flags(ACCOUNT_EXT_MATCHING) > 1)) {
- DEBUG("account.display", " Yes, because it matched");
- format_account = true;
- }
- else if (! flatten_list &&
- account.children_with_flags(ACCOUNT_EXT_VISITED) &&
- ! account.children_with_flags(ACCOUNT_EXT_MATCHING)) {
+ if (account.has_flags(ACCOUNT_EXT_MATCHING) ||
+ (! flatten_list &&
+ account.children_with_flags(ACCOUNT_EXT_MATCHING) > 1)) {
+ DEBUG("account.display", " Yes, because it matched");
+ format_account = true;
+ }
+ else if (! flatten_list &&
+ account.children_with_flags(ACCOUNT_EXT_VISITED) &&
+ ! account.children_with_flags(ACCOUNT_EXT_MATCHING)) {
+ DEBUG("account.display",
+ " Maybe, because it has visited, but no matching, children");
+ if (disp_pred(bound_scope)) {
DEBUG("account.display",
- " Maybe, because it has visited, but no matching, children");
- if (disp_pred(bound_scope)) {
- DEBUG("account.display",
- " And yes, because it matches the display predicate");
- format_account = true;
- } else {
- DEBUG("account.display",
- " And no, because it didn't match the display predicate");
- }
- }
- else {
+ " And yes, because it matches the display predicate");
+ format_account = true;
+ } else {
DEBUG("account.display",
- " No, neither it nor its children were eligible for display");
- }
-
- if (format_account) {
- account.xdata().add_flags(ACCOUNT_EXT_DISPLAYED);
- displayed++;
-
- format.format(report.output_stream, bound_scope);
+ " And no, because it didn't match the display predicate");
}
}
-
- foreach (accounts_map::value_type pair, account.accounts) {
- if (post_accounts(*pair.second) > 0)
- displayed++;
+ else {
+ DEBUG("account.display",
+ " No, neither it nor its children were eligible for display");
}
- return displayed;
+ if (format_account) {
+ account.xdata().add_flags(ACCOUNT_EXT_DISPLAYED);
+ format.format(report.output_stream, bound_scope);
+ }
}
void format_accounts::flush()
{
std::ostream& out(report.output_stream);
- std::size_t top_displayed = post_accounts(*report.session.master.get());
+ std::size_t top_displayed = 0;
+
+ foreach (account_t * account, posted_accounts) {
+ post_account(*account);
+
+ if (flatten_list && account->has_flags(ACCOUNT_EXT_DISPLAYED))
+ top_displayed++;
+ }
+
+ if (! flatten_list) {
+ foreach (accounts_map::value_type pair, report.session.master->accounts) {
+ if (pair.second->has_flags(ACCOUNT_EXT_DISPLAYED) ||
+ pair.second->children_with_flags(ACCOUNT_EXT_DISPLAYED))
+ top_displayed++;
+ }
+ }
assert(report.session.master->has_xdata());
account_t::xdata_t& xdata(report.session.master->xdata());
@@ -300,6 +301,7 @@ void format_accounts::operator()(account_t& account)
" But it did not match the display predicate");
}
}
+ posted_accounts.push_back(&account);
}
format_equity::format_equity(report_t& _report, const string& _format)
@@ -351,12 +353,12 @@ void format_equity::flush()
out.flush();
}
-std::size_t format_equity::post_accounts(account_t& account)
+void format_equity::post_account(account_t& account)
{
std::ostream& out(report.output_stream);
if (! account.has_flags(ACCOUNT_EXT_MATCHING))
- return 0;
+ return;
value_t val = account.xdata().value;
@@ -378,8 +380,6 @@ std::size_t format_equity::post_accounts(account_t& account)
next_lines_format.format(out, bound_scope);
}
total += val;
-
- return 1;
}
} // namespace ledger
diff --git a/src/output.h b/src/output.h
index ded29143..7019b7b2 100644
--- a/src/output.h
+++ b/src/output.h
@@ -165,6 +165,8 @@ protected:
item_predicate disp_pred;
bool flatten_list;
+ std::list<account_t *> posted_accounts;
+
public:
format_accounts(report_t& _report,
const string& _format = "",
@@ -184,8 +186,8 @@ public:
TRACE_DTOR(format_accounts);
}
- virtual std::size_t post_accounts(account_t& account);
- virtual void flush();
+ virtual void post_account(account_t& account);
+ virtual void flush();
virtual void operator()(account_t& account);
};
@@ -209,8 +211,8 @@ class format_equity : public format_accounts
TRACE_DTOR(format_equity);
}
- virtual std::size_t post_accounts(account_t& account);
- virtual void flush();
+ virtual void post_account(account_t& account);
+ virtual void flush();
};
} // namespace ledger
diff --git a/src/report.cc b/src/report.cc
index 565ef77e..d9e88634 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -77,8 +77,8 @@ void report_t::accounts_report(acct_handler_ptr handler)
if (! HANDLED(sort_))
iter.reset(new basic_accounts_iterator(*session.master));
else
- iter.reset(new sorted_accounts_iterator(*session.master,
- HANDLER(sort_).str()));
+ iter.reset(new sorted_accounts_iterator(HANDLER(sort_).str(),
+ HANDLED(flat), *session.master.get()));
if (HANDLED(display_))
pass_down_accounts(handler, *iter.get(),
diff --git a/src/value.cc b/src/value.cc
index 96fb6647..3b9cfb00 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -1424,6 +1424,9 @@ bool sort_value_is_less_than(const std::list<sort_value_t>& left_values,
while (left_iter != left_values.end() &&
right_iter != right_values.end()) {
+ DEBUG("value.sort",
+ "Comparing " << (*left_iter).value << " < " << (*right_iter).value);
+
if ((*left_iter).value < (*right_iter).value)
return ! (*left_iter).inverted;
else if ((*left_iter).value > (*right_iter).value)
@@ -1434,7 +1437,7 @@ bool sort_value_is_less_than(const std::list<sort_value_t>& left_values,
assert(left_iter == left_values.end());
assert(right_iter == right_values.end());
- return true;
+ return false;
}
} // namespace ledger