Custom Reports - oldest, newest

- Added support for the "report.X.limit" configuration variable, to
  restrict the number of rows a report generates.
- Added support for Table::render (limit) to limit the number of rows
  that are rendered.
- Removed "oldest" and "newest" report code.
- Added "oldest" and "newest" custom report details to Config.cpp
- Updated various documentation.
This commit is contained in:
Paul Beckingham 2009-03-12 22:34:45 -04:00
parent 8c95e82a63
commit c35a764019
14 changed files with 101 additions and 369 deletions

View file

@ -1678,302 +1678,6 @@ std::string handleReportOverdue (TDB& tdb, T& task, Config& conf)
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// Successively apply filters based on the task object built from the command
// line. Tasks that match all the specified criteria are listed.
std::string handleReportOldest (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
if (conf.get ("curses", true))
{
WINDOW* w = initscr ();
width = w->_maxx + 1;
endwin ();
}
#endif
// Get the pending tasks.
std::vector <T> tasks;
tdb.allPendingT (tasks);
handleRecurrence (tdb, tasks);
filter (tasks, task);
initializeColorRules (conf);
unsigned int quantity = conf.get ("oldest", 10);
// Create a table for output.
Table table;
table.setTableWidth (width);
table.addColumn ("ID");
table.addColumn ("Project");
table.addColumn ("Pri");
table.addColumn ("Due");
table.addColumn ("Active");
table.addColumn ("Age");
table.addColumn ("Description");
if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
{
table.setColumnUnderline (0);
table.setColumnUnderline (1);
table.setColumnUnderline (2);
table.setColumnUnderline (3);
table.setColumnUnderline (4);
table.setColumnUnderline (5);
table.setColumnUnderline (6);
}
else
table.setTableDashedUnderline ();
table.setColumnWidth (0, Table::minimum);
table.setColumnWidth (1, Table::minimum);
table.setColumnWidth (2, Table::minimum);
table.setColumnWidth (3, Table::minimum);
table.setColumnWidth (4, Table::minimum);
table.setColumnWidth (5, Table::minimum);
table.setColumnWidth (6, Table::flexible);
table.setColumnJustification (0, Table::right);
table.setColumnJustification (3, Table::right);
table.setColumnJustification (5, Table::right);
table.sortOn (3, Table::ascendingDate);
table.sortOn (2, Table::descendingPriority);
table.sortOn (1, Table::ascendingCharacter);
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
for (unsigned int i = 0; i < min (quantity, tasks.size ()); ++i)
{
T refTask (tasks[i]);
Date now;
// Now format the matching task.
bool imminent = false;
bool overdue = false;
std::string due = refTask.getAttribute ("due");
if (due.length ())
{
switch (getDueState (due))
{
case 2: overdue = true; break;
case 1: imminent = true; break;
case 0:
default: break;
}
Date dt (::atoi (due.c_str ()));
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
}
std::string active;
if (refTask.getAttribute ("start") != "")
active = "*";
std::string age;
std::string created = refTask.getAttribute ("entry");
if (created.length ())
{
Date dt (::atoi (created.c_str ()));
formatTimeDeltaDays (age, (time_t) (now - dt));
}
// All criteria match, so add refTask to the output table.
int row = table.addRow ();
table.addCell (row, 0, refTask.getId ());
table.addCell (row, 1, refTask.getAttribute ("project"));
table.addCell (row, 2, refTask.getAttribute ("priority"));
table.addCell (row, 3, due);
table.addCell (row, 4, active);
table.addCell (row, 5, age);
table.addCell (row, 6, refTask.getDescription ());
if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
{
Text::color fg = Text::colorCode (refTask.getAttribute ("fg"));
Text::color bg = Text::colorCode (refTask.getAttribute ("bg"));
autoColorize (refTask, fg, bg, conf);
table.setRowFg (row, fg);
table.setRowBg (row, bg);
if (fg == Text::nocolor)
{
if (overdue)
table.setCellFg (row, 3, Text::colorCode (conf.get ("color.overdue", "red")));
else if (imminent)
table.setCellFg (row, 3, Text::colorCode (conf.get ("color.due", "yellow")));
}
}
}
if (table.rowCount ())
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
out << "No matches."
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// Successively apply filters based on the task object built from the command
// line. Tasks that match all the specified criteria are listed.
std::string handleReportNewest (TDB& tdb, T& task, Config& conf)
{
std::stringstream out;
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
if (conf.get ("curses", true))
{
WINDOW* w = initscr ();
width = w->_maxx + 1;
endwin ();
}
#endif
// Get the pending tasks.
std::vector <T> tasks;
tdb.allPendingT (tasks);
handleRecurrence (tdb, tasks);
filter (tasks, task);
initializeColorRules (conf);
int quantity = conf.get ("newest", 10);
// Create a table for output.
Table table;
table.setTableWidth (width);
table.addColumn ("ID");
table.addColumn ("Project");
table.addColumn ("Pri");
table.addColumn ("Due");
table.addColumn ("Active");
table.addColumn ("Age");
table.addColumn ("Description");
if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
{
table.setColumnUnderline (0);
table.setColumnUnderline (1);
table.setColumnUnderline (2);
table.setColumnUnderline (3);
table.setColumnUnderline (4);
table.setColumnUnderline (5);
table.setColumnUnderline (6);
}
else
table.setTableDashedUnderline ();
table.setColumnWidth (0, Table::minimum);
table.setColumnWidth (1, Table::minimum);
table.setColumnWidth (2, Table::minimum);
table.setColumnWidth (3, Table::minimum);
table.setColumnWidth (4, Table::minimum);
table.setColumnWidth (5, Table::minimum);
table.setColumnWidth (6, Table::flexible);
table.setColumnJustification (0, Table::right);
table.setColumnJustification (3, Table::right);
table.setColumnJustification (5, Table::right);
table.sortOn (3, Table::ascendingDate);
table.sortOn (2, Table::descendingPriority);
table.sortOn (1, Table::ascendingCharacter);
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
int total = tasks.size ();
for (int i = total - 1; i >= max (0, total - quantity); --i)
{
T refTask (tasks[i]);
Date now;
// Now format the matching task.
bool imminent = false;
bool overdue = false;
std::string due = refTask.getAttribute ("due");
if (due.length ())
{
switch (getDueState (due))
{
case 2: overdue = true; break;
case 1: imminent = true; break;
case 0:
default: break;
}
Date dt (::atoi (due.c_str ()));
due = dt.toString (conf.get ("dateformat", "m/d/Y"));
}
std::string active;
if (refTask.getAttribute ("start") != "")
active = "*";
std::string age;
std::string created = refTask.getAttribute ("entry");
if (created.length ())
{
Date dt (::atoi (created.c_str ()));
formatTimeDeltaDays (age, (time_t) (now - dt));
}
// All criteria match, so add refTask to the output table.
int row = table.addRow ();
table.addCell (row, 0, refTask.getId ());
table.addCell (row, 1, refTask.getAttribute ("project"));
table.addCell (row, 2, refTask.getAttribute ("priority"));
table.addCell (row, 3, due);
table.addCell (row, 4, active);
table.addCell (row, 5, age);
table.addCell (row, 6, refTask.getDescription ());
if (conf.get ("color", true) || conf.get (std::string ("_forcecolor"), false))
{
Text::color fg = Text::colorCode (refTask.getAttribute ("fg"));
Text::color bg = Text::colorCode (refTask.getAttribute ("bg"));
autoColorize (refTask, fg, bg, conf);
table.setRowFg (row, fg);
table.setRowBg (row, bg);
if (fg == Text::nocolor)
{
if (overdue)
table.setCellFg (row, 3, Text::colorCode (conf.get ("color.overdue", "red")));
else if (imminent)
table.setCellFg (row, 3, Text::colorCode (conf.get ("color.due", "yellow")));
}
}
}
if (table.rowCount ())
out << optionalBlankLine (conf)
<< table.render ()
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
out << "No matches."
<< std::endl;
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
std::string handleReportStats (TDB& tdb, T& task, Config& conf)
{
@ -2575,10 +2279,12 @@ std::string handleCustomReport (
}
}
int maximum = conf.get (std::string ("report.") + report + ".limit", (int)0);
std::stringstream out;
if (table.rowCount ())
out << optionalBlankLine (conf)
<< table.render ()
<< table.render (maximum)
<< optionalBlankLine (conf)
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")