Enhancement - New columns for custom reports

- Added 'entry_time', 'start_time' and 'end_time' columns that include
  the time as well as the date.
This commit is contained in:
Paul Beckingham 2009-12-11 19:08:45 -05:00
parent 81ce844d79
commit 4ea71c939a
5 changed files with 105 additions and 0 deletions

View file

@ -18,6 +18,9 @@
+ The 'version' command now complains about use of deprecated color names and + The 'version' command now complains about use of deprecated color names and
duplicate entries. duplicate entries.
+ Task now supports nested .taskrc files using the "include /path" directive. + Task now supports nested .taskrc files using the "include /path" directive.
+ The 'entry', 'start' and 'end' columns now have equivalents that include the
time, and are called 'entry_time', 'start_time', and 'end_time', for use in
custom reports.
+ Fixed bug that showed a calendar for the year 2037 when 'task calendar due' + Fixed bug that showed a calendar for the year 2037 when 'task calendar due'
was run, and there are no tasks with due dates. was run, and there are no tasks with due dates.
+ Fixed bug #316 which caused the timesheet report to display an oddly sorted + Fixed bug #316 which caused the timesheet report to display an oddly sorted

4
NEWS
View file

@ -4,6 +4,10 @@ New Features in task 1.9
- 256-color support - 256-color support
- Support for coloring alternate lines of output. Remember that old green - Support for coloring alternate lines of output. Remember that old green
and white fan-fold printer paper? and white fan-fold printer paper?
- Supports nested .taskrc files with the new "include" statement"
- New columns that include the time as well as date
- New attribute modifiers
- Improved .taskrc validation
Please refer to the ChangeLog file for full details. There are too many to Please refer to the ChangeLog file for full details. There are too many to
list here. list here.

View file

@ -271,6 +271,19 @@ const std::string Date::toString (const std::string& format /*= "m/d/Y" */) cons
return formatted; return formatted;
} }
////////////////////////////////////////////////////////////////////////////////
const std::string Date::toStringWithTime (const std::string& format /*= "m/d/Y" */) const
{
// Format as above.
std::string formatted = toString (format);
char buffer[12];
sprintf (buffer, " %d:%02d:%02d", hour (), minute (), second ());
formatted += buffer;
return formatted;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool Date::valid (const std::string& input, const std::string& format) bool Date::valid (const std::string& input, const std::string& format)
{ {
@ -456,6 +469,27 @@ int Date::year () const
return t->tm_year + 1900; return t->tm_year + 1900;
} }
////////////////////////////////////////////////////////////////////////////////
int Date::hour () const
{
struct tm* t = localtime (&mT);
return t->tm_hour;
}
////////////////////////////////////////////////////////////////////////////////
int Date::minute () const
{
struct tm* t = localtime (&mT);
return t->tm_min;
}
////////////////////////////////////////////////////////////////////////////////
int Date::second () const
{
struct tm* t = localtime (&mT);
return t->tm_sec;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool Date::operator== (const Date& rhs) bool Date::operator== (const Date& rhs)
{ {

View file

@ -47,6 +47,7 @@ public:
std::string toEpochString (); std::string toEpochString ();
void toMDY (int&, int&, int&); void toMDY (int&, int&, int&);
const std::string toString (const std::string& format = "m/d/Y") const; const std::string toString (const std::string& format = "m/d/Y") const;
const std::string toStringWithTime (const std::string& format = "m/d/Y") const;
static bool valid (const std::string&, const std::string& format = "m/d/Y"); static bool valid (const std::string&, const std::string& format = "m/d/Y");
static bool valid (const int, const int, const int); static bool valid (const int, const int, const int);
@ -63,6 +64,9 @@ public:
int year () const; int year () const;
int weekOfYear (int) const; int weekOfYear (int) const;
int dayOfWeek () const; int dayOfWeek () const;
int hour () const;
int minute () const;
int second () const;
bool operator== (const Date&); bool operator== (const Date&);
bool operator!= (const Date&); bool operator!= (const Date&);

View file

@ -237,6 +237,25 @@ int runCustomReport (
} }
} }
else if (*col == "entry_time")
{
table.addColumn (columnLabels[*col] != "" ? columnLabels[*col] : "Added");
table.setColumnWidth (columnCount, Table::minimum);
table.setColumnJustification (columnCount, Table::right);
std::string entered;
for (unsigned int row = 0; row < tasks.size(); ++row)
{
entered = tasks[row].get ("entry");
if (entered.length ())
{
Date dt (::atoi (entered.c_str ()));
entered = dt.toStringWithTime (context.config.get ("dateformat", "m/d/Y"));
table.addCell (row, columnCount, entered);
}
}
}
else if (*col == "start") else if (*col == "start")
{ {
table.addColumn (columnLabels[*col] != "" ? columnLabels[*col] : "Started"); table.addColumn (columnLabels[*col] != "" ? columnLabels[*col] : "Started");
@ -256,6 +275,25 @@ int runCustomReport (
} }
} }
else if (*col == "start_time")
{
table.addColumn (columnLabels[*col] != "" ? columnLabels[*col] : "Started");
table.setColumnWidth (columnCount, Table::minimum);
table.setColumnJustification (columnCount, Table::right);
std::string started;
for (unsigned int row = 0; row < tasks.size(); ++row)
{
started = tasks[row].get ("start");
if (started.length ())
{
Date dt (::atoi (started.c_str ()));
started = dt.toStringWithTime (context.config.get ("dateformat", "m/d/Y"));
table.addCell (row, columnCount, started);
}
}
}
else if (*col == "end") else if (*col == "end")
{ {
table.addColumn (columnLabels[*col] != "" ? columnLabels[*col] : "Completed"); table.addColumn (columnLabels[*col] != "" ? columnLabels[*col] : "Completed");
@ -275,6 +313,25 @@ int runCustomReport (
} }
} }
else if (*col == "end_time")
{
table.addColumn (columnLabels[*col] != "" ? columnLabels[*col] : "Completed");
table.setColumnWidth (columnCount, Table::minimum);
table.setColumnJustification (columnCount, Table::right);
std::string started;
for (unsigned int row = 0; row < tasks.size(); ++row)
{
started = tasks[row].get ("end");
if (started.length ())
{
Date dt (::atoi (started.c_str ()));
started = dt.toStringWithTime (context.config.get ("dateformat", "m/d/Y"));
table.addCell (row, columnCount, started);
}
}
}
else if (*col == "due") else if (*col == "due")
{ {
table.addColumn (columnLabels[*col] != "" ? columnLabels[*col] : "Due"); table.addColumn (columnLabels[*col] != "" ? columnLabels[*col] : "Due");
@ -576,8 +633,11 @@ void validReportColumns (const std::vector <std::string>& columns)
*it != "project" && *it != "project" &&
*it != "priority" && *it != "priority" &&
*it != "entry" && *it != "entry" &&
*it != "entry_time" &&
*it != "start" && *it != "start" &&
*it != "start_time" &&
*it != "end" && *it != "end" &&
*it != "end_time" &&
*it != "due" && *it != "due" &&
*it != "age" && *it != "age" &&
*it != "age_compact" && *it != "age_compact" &&