Enhancements - custom reports

- Converted active, overdue and completed reports to custom reports.
- Added new recurring report.
- Added support for new 'end' column, which is the completion date.
This commit is contained in:
Paul Beckingham 2009-06-12 22:12:35 -04:00
parent c9807f4636
commit 788e264378
6 changed files with 69 additions and 375 deletions

View file

@ -85,10 +85,6 @@ std::string shortUsage ()
table.addCell (row, 1, "task annotate ID desc...");
table.addCell (row, 2, "Adds an annotation to an existing task");
row = table.addRow ();
table.addCell (row, 1, "task completed [tags] [attrs] desc...");
table.addCell (row, 2, "Chronological listing of all completed tasks matching the specified criteria");
row = table.addRow ();
table.addCell (row, 1, "task ID [tags] [attrs] [desc...]");
table.addCell (row, 2, "Modifies the existing task with provided arguments");
@ -169,14 +165,6 @@ std::string shortUsage ()
table.addCell (row, 1, "task calendar");
table.addCell (row, 2, "Shows a monthly calendar, with due tasks marked");
row = table.addRow ();
table.addCell (row, 1, "task active");
table.addCell (row, 2, "Shows all task that are started, but not completed");
row = table.addRow ();
table.addCell (row, 1, "task overdue");
table.addCell (row, 2, "Shows all incomplete tasks that are beyond their due date");
row = table.addRow ();
table.addCell (row, 1, "task stats");
table.addCell (row, 2, "Shows task database statistics");
@ -429,103 +417,6 @@ void filter (std::vector<T>& all, T& task)
all = filtered;
}
////////////////////////////////////////////////////////////////////////////////
// Successively apply filters based on the task object built from the command
// line. Tasks that match all the specified criteria are listed.
std::string handleCompleted ()
{
std::stringstream out;
/*
// Get the pending tasks.
std::vector <T> tasks;
tdb.completedT (tasks);
filter (tasks, task);
initializeColorRules ();
// Create a table for output.
Table table;
table.setTableWidth (context.getWidth ());
table.setDateFormat (context.config.get ("dateformat", "m/d/Y"));
table.addColumn ("Done");
table.addColumn ("Project");
table.addColumn ("Description");
if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) &&
context.config.get (std::string ("fontunderline"), "true"))
{
table.setColumnUnderline (0);
table.setColumnUnderline (1);
table.setColumnUnderline (2);
}
else
table.setTableDashedUnderline ();
table.setColumnWidth (0, Table::minimum);
table.setColumnWidth (1, Table::minimum);
table.setColumnWidth (2, Table::flexible);
table.setColumnJustification (0, Table::right);
table.setColumnJustification (1, Table::left);
table.setColumnJustification (2, Table::left);
// Note: There is deliberately no sorting. The original sorting was on the
// end date. Tasks are appended to completed.data naturally sorted by
// the end date, so that sequence is assumed to remain unchanged, and
// relied upon here.
// Iterate over each task, and apply selection criteria.
for (unsigned int i = 0; i < tasks.size (); ++i)
{
T refTask (tasks[i]);
// Now format the matching task.
Date end (::atoi (refTask.getAttribute ("end").c_str ()));
// All criteria match, so add refTask to the output table.
int row = table.addRow ();
table.addCell (row, 0, end.toString (context.config.get ("dateformat", "m/d/Y")));
table.addCell (row, 1, refTask.getAttribute ("project"));
std::string description = refTask.getDescription ();
std::string when;
std::map <time_t, std::string> annotations;
refTask.getAnnotations (annotations);
foreach (anno, annotations)
{
Date dt (anno->first);
when = dt.toString (context.config.get ("dateformat", "m/d/Y"));
description += "\n" + when + " " + anno->second;
}
table.addCell (row, 2, description);
if (context.config.get ("color", true) || context.config.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);
table.setRowFg (row, fg);
table.setRowBg (row, bg);
}
}
if (table.rowCount ())
out << optionalBlankLine ()
<< table.render ()
<< optionalBlankLine ()
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
out << "No matches."
<< std::endl;
*/
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
// Display all information for the given task.
std::string handleInfo ()
@ -1998,244 +1889,6 @@ std::string handleReportCalendar ()
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
std::string handleReportActive ()
{
std::stringstream out;
/*
// Get all the tasks.
std::vector <T> tasks;
tdb.pendingT (tasks);
filter (tasks, task);
initializeColorRules ();
// Create a table for output.
Table table;
table.setTableWidth (context.getWidth ());
table.setDateFormat (context.config.get ("dateformat", "m/d/Y"));
table.addColumn ("ID");
table.addColumn ("Project");
table.addColumn ("Pri");
table.addColumn ("Due");
table.addColumn ("Description");
if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) &&
context.config.get (std::string ("fontunderline"), "true"))
{
table.setColumnUnderline (0);
table.setColumnUnderline (1);
table.setColumnUnderline (2);
table.setColumnUnderline (3);
table.setColumnUnderline (4);
}
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::flexible);
table.setColumnJustification (0, Table::right);
table.setColumnJustification (3, Table::right);
table.sortOn (3, Table::ascendingDate);
table.sortOn (2, Table::descendingPriority);
table.sortOn (1, Table::ascendingCharacter);
// Iterate over each task, and apply selection criteria.
for (unsigned int i = 0; i < tasks.size (); ++i)
{
T refTask (tasks[i]);
if (refTask.has ("start"))
{
Date now;
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 (context.config.get ("dateformat", "m/d/Y"));
}
// 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);
std::string description = refTask.getDescription ();
std::string when;
std::map <time_t, std::string> annotations;
refTask.getAnnotations (annotations);
foreach (anno, annotations)
{
Date dt (anno->first);
when = dt.toString (context.config.get ("dateformat", "m/d/Y"));
description += "\n" + when + " " + anno->second;
}
table.addCell (row, 4, description);
if (context.config.get ("color", true) || context.config.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);
table.setRowFg (row, fg);
table.setRowBg (row, bg);
if (fg == Text::nocolor)
{
if (overdue)
table.setCellFg (row, 3, Text::colorCode (context.config.get ("color.overdue", "red")));
else if (imminent)
table.setCellFg (row, 3, Text::colorCode (context.config.get ("color.due", "yellow")));
}
}
}
}
if (table.rowCount ())
out << optionalBlankLine ()
<< table.render ()
<< optionalBlankLine ()
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
out << "No active tasks." << std::endl;
*/
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
std::string handleReportOverdue ()
{
std::stringstream out;
/*
// Get all the tasks.
std::vector <T> tasks;
tdb.pendingT (tasks);
filter (tasks, task);
initializeColorRules ();
// Create a table for output.
Table table;
table.setTableWidth (context.getWidth ());
table.setDateFormat (context.config.get ("dateformat", "m/d/Y"));
table.addColumn ("ID");
table.addColumn ("Project");
table.addColumn ("Pri");
table.addColumn ("Due");
table.addColumn ("Description");
if ((context.config.get ("color", true) || context.config.get (std::string ("_forcecolor"), false)) &&
context.config.get (std::string ("fontunderline"), "true"))
{
table.setColumnUnderline (0);
table.setColumnUnderline (1);
table.setColumnUnderline (2);
table.setColumnUnderline (3);
table.setColumnUnderline (4);
}
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::flexible);
table.setColumnJustification (0, Table::right);
table.setColumnJustification (3, Table::right);
table.sortOn (3, Table::ascendingDate);
table.sortOn (2, Table::descendingPriority);
table.sortOn (1, Table::ascendingCharacter);
Date now;
// Iterate over each task, and apply selection criteria.
for (unsigned int i = 0; i < tasks.size (); ++i)
{
T refTask (tasks[i]);
std::string due;
if ((due = refTask.has ("due")))
{
if (due.length ())
{
Date dt (::atoi (due.c_str ()));
due = dt.toString (context.config.get ("dateformat", "m/d/Y"));
// If overdue.
if (dt < now)
{
// 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);
std::string description = refTask.getDescription ();
std::string when;
std::map <time_t, std::string> annotations;
refTask.getAnnotations (annotations);
foreach (anno, annotations)
{
Date dt (anno->first);
when = dt.toString (context.config.get ("dateformat", "m/d/Y"));
description += "\n" + when + " " + anno->second;
}
table.addCell (row, 4, description);
if (context.config.get ("color", true) || context.config.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);
table.setRowFg (row, fg);
table.setRowBg (row, bg);
if (fg == Text::nocolor)
table.setCellFg (row, 3, Text::red);
}
}
}
}
}
if (table.rowCount ())
out << optionalBlankLine ()
<< table.render ()
<< optionalBlankLine ()
<< table.rowCount ()
<< (table.rowCount () == 1 ? " task" : " tasks")
<< std::endl;
else
out << "No overdue tasks." << std::endl;
*/
return out.str ();
}
////////////////////////////////////////////////////////////////////////////////
std::string handleReportStats ()
{