From 75a24f511347a6bf6c06ac2d0d1da8457ad73ce0 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 30 May 2011 13:46:08 -0400 Subject: [PATCH] Commands - timesheet - Migrated handleReportTimesheet to CmdTimesheet. --- src/Cmd.cpp | 2 - src/Context.cpp | 3 +- src/commands/CMakeLists.txt | 1 + src/commands/CmdHelp.cpp | 4 - src/commands/CmdTimesheet.cpp | 184 ++++++++++++++++++++++++++++++++++ src/commands/CmdTimesheet.h | 42 ++++++++ src/commands/Command.cpp | 2 + src/main.h | 1 - src/report.cpp | 137 ------------------------- 9 files changed, 230 insertions(+), 146 deletions(-) create mode 100644 src/commands/CmdTimesheet.cpp create mode 100644 src/commands/CmdTimesheet.h diff --git a/src/Cmd.cpp b/src/Cmd.cpp index f5dc1d996..51b3cac28 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -131,7 +131,6 @@ void Cmd::load () { commands.push_back ("delete"); commands.push_back ("done"); - commands.push_back ("timesheet"); commands.push_back ("merge"); commands.push_back ("push"); commands.push_back ("pull"); @@ -192,7 +191,6 @@ void Cmd::allCommands (std::vector & all) const bool Cmd::isReadOnlyCommand () { if (command == "push" || - command == "timesheet" || validCustom (command)) return true; diff --git a/src/Context.cpp b/src/Context.cpp index ca1ffa7f1..ffe16f13a 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -249,8 +249,7 @@ int Context::dispatch (std::string &out) Timer t ("Context::dispatch"); // TODO Chain-of-command pattern dispatch. - if (cmd.command == "timesheet") { rc = handleReportTimesheet (out); } - else if (cmd.command == "done") { rc = handleDone (out); } + if (cmd.command == "done") { rc = handleDone (out); } else if (cmd.command == "delete") { rc = handleDelete (out); } else if (cmd.command == "merge") { tdb.gc (); handleMerge (out); } diff --git a/src/commands/CMakeLists.txt b/src/commands/CMakeLists.txt index 2b686c9f5..c36781e6e 100644 --- a/src/commands/CMakeLists.txt +++ b/src/commands/CMakeLists.txt @@ -40,6 +40,7 @@ set (commands_SRCS Command.cpp Command.h CmdStop.cpp CmdStop.h CmdSummary.cpp CmdSummary.h CmdTags.cpp CmdTags.h + CmdTimesheet.cpp CmdTimesheet.h CmdTip.cpp CmdTip.h CmdUndo.cpp CmdUndo.h CmdUrgency.cpp CmdUrgency.h diff --git a/src/commands/CmdHelp.cpp b/src/commands/CmdHelp.cpp index dc920be43..8e3b451fd 100644 --- a/src/commands/CmdHelp.cpp +++ b/src/commands/CmdHelp.cpp @@ -111,10 +111,6 @@ int CmdHelp::execute (const std::string&, std::string& output) view.set (row, 1, "task done ID [tags] [attrs] [desc...]"); view.set (row, 2, "Marks the specified task as completed."); - row = view.addRow (); - view.set (row, 1, "task timesheet [weeks]"); - view.set (row, 2, "Shows a weekly report of tasks completed and started."); - row = view.addRow (); view.set (row, 1, "task merge URL"); view.set (row, 2, "Merges the specified undo.data file with the local data files."); diff --git a/src/commands/CmdTimesheet.cpp b/src/commands/CmdTimesheet.cpp new file mode 100644 index 000000000..52b7efc95 --- /dev/null +++ b/src/commands/CmdTimesheet.cpp @@ -0,0 +1,184 @@ +//////////////////////////////////////////////////////////////////////////////// +// taskwarrior - a command line task list manager. +// +// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez. +// All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation; either version 2 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the +// +// Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, +// Boston, MA +// 02110-1301 +// USA +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +extern Context context; + +//////////////////////////////////////////////////////////////////////////////// +CmdTimesheet::CmdTimesheet () +{ + _keyword = "timesheet"; + _usage = "task timesheet [weeks]"; + _description = "Shows a weekly report of tasks completed and started."; + _read_only = true; + _displays_id = false; +} + +//////////////////////////////////////////////////////////////////////////////// +int CmdTimesheet::execute (const std::string&, std::string& output) +{ + int rc = 0; + + // Scan the pending tasks. + std::vector tasks; + context.tdb.lock (context.config.getBoolean ("locking")); + handleRecurrence (); + context.tdb.load (tasks, context.filter); + context.tdb.commit (); + context.tdb.unlock (); + + // Just do this once. + int width = context.getWidth (); + + // What day of the week does the user consider the first? + int weekStart = Date::dayOfWeek (context.config.get ("weekstart")); + if (weekStart != 0 && weekStart != 1) + throw std::string ("The 'weekstart' configuration variable may " + "only contain 'Sunday' or 'Monday'."); + + // Determine the date of the first day of the most recent report. + Date today; + Date start; + start -= (((today.dayOfWeek () - weekStart) + 7) % 7) * 86400; + + // Roll back to midnight. + start = Date (start.month (), start.day (), start.year ()); + Date end = start + (7 * 86400); + + // Determine how many reports to run. + int quantity = 1; + if (context.sequence.size () == 1) + quantity = context.sequence[0]; + + std::stringstream out; + for (int week = 0; week < quantity; ++week) + { + Date endString (end); + endString -= 86400; + + std::string title = start.toString (context.config.get ("dateformat")) + + " - " + + endString.toString (context.config.get ("dateformat")); + + Color bold (Color::nocolor, Color::nocolor, false, true, false); + out << "\n" + << (context.color () ? bold.colorize (title) : title) + << "\n"; + + // Render the completed table. + ViewText completed; + completed.width (width); + completed.add (Column::factory ("string", " ")); + completed.add (Column::factory ("string", "Project")); + completed.add (Column::factory ("string.right", "Due")); + completed.add (Column::factory ("string", "Description")); + + std::vector ::iterator task; + for (task = tasks.begin (); task != tasks.end (); ++task) + { + // If task completed within range. + if (task->getStatus () == Task::completed) + { + Date compDate (atoi (task->get ("end").c_str ())); + if (compDate >= start && compDate < end) + { + Color c (task->get ("fg") + " " + task->get ("bg")); + if (context.color ()) + autoColorize (*task, c); + + int row = completed.addRow (); + std::string format = context.config.get ("dateformat.report"); + if (format == "") + format = context.config.get ("dateformat"); + completed.set (row, 1, task->get ("project"), c); + completed.set (row, 2, getDueDate (*task, format), c); + completed.set (row, 3, getFullDescription (*task, "timesheet"), c); + } + } + } + + out << " Completed (" << completed.rows () << " tasks)\n"; + + if (completed.rows ()) + out << completed.render () + << "\n"; + + // Now render the started table. + ViewText started; + started.width (width); + started.add (Column::factory ("string", " ")); + started.add (Column::factory ("string", "Project")); + started.add (Column::factory ("string.right", "Due")); + started.add (Column::factory ("string", "Description")); + + for (task = tasks.begin (); task != tasks.end (); ++task) + { + // If task started within range, but not completed withing range. + if (task->getStatus () == Task::pending && + task->has ("start")) + { + Date startDate (atoi (task->get ("start").c_str ())); + if (startDate >= start && startDate < end) + { + Color c (task->get ("fg") + " " + task->get ("bg")); + if (context.color ()) + autoColorize (*task, c); + + int row = started.addRow (); + std::string format = context.config.get ("dateformat.report"); + if (format == "") + format = context.config.get ("dateformat"); + started.set (row, 1, task->get ("project"), c); + started.set (row, 2, getDueDate (*task, format), c); + started.set (row, 3, getFullDescription (*task, "timesheet"), c); + + } + } + } + + out << " Started (" << started.rows () << " tasks)\n"; + + if (started.rows ()) + out << started.render () + << "\n\n"; + + // Prior week. + start -= 7 * 86400; + end -= 7 * 86400; + } + + output = out.str (); + return rc; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdTimesheet.h b/src/commands/CmdTimesheet.h new file mode 100644 index 000000000..2ea5ca5bb --- /dev/null +++ b/src/commands/CmdTimesheet.h @@ -0,0 +1,42 @@ +//////////////////////////////////////////////////////////////////////////////// +// taskwarrior - a command line task list manager. +// +// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez. +// All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation; either version 2 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the +// +// Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, +// Boston, MA +// 02110-1301 +// USA +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef INCLUDED_CMDTIMESHEET +#define INCLUDED_CMDTIMESHEET +#define L10N // Localization complete. + +#include +#include + +class CmdTimesheet : public Command +{ +public: + CmdTimesheet (); + int execute (const std::string&, std::string&); +}; + +#endif +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index 30ef297ca..aee58731c 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -118,6 +119,7 @@ void Command::factory (std::map & all) c = new CmdStop (); all[c->keyword ()] = c; c = new CmdSummary (); all[c->keyword ()] = c; c = new CmdTags (); all[c->keyword ()] = c; + c = new CmdTimesheet (); all[c->keyword ()] = c; c = new CmdTip (); all[c->keyword ()] = c; c = new CmdUndo (); all[c->keyword ()] = c; c = new CmdUrgency (); all[c->keyword ()] = c; diff --git a/src/main.h b/src/main.h index 3a0e06913..0c6bef7fc 100644 --- a/src/main.h +++ b/src/main.h @@ -64,7 +64,6 @@ int deltaAttributes (Task&); int deltaSubstitutions (Task&); // report.cpp -int handleReportTimesheet (std::string&); std::string getFullDescription (Task&, const std::string&); std::string getDueDate (Task&, const std::string&); std::string onProjectChange (Task&, bool scope = true); diff --git a/src/report.cpp b/src/report.cpp index d98588f06..ac47afa0e 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -51,143 +51,6 @@ static void countTasks (const std::vector &, const std::string&, const std extern Context context; -//////////////////////////////////////////////////////////////////////////////// -int handleReportTimesheet (std::string& outs) -{ - int rc = 0; - - // Scan the pending tasks. - std::vector tasks; - context.tdb.lock (context.config.getBoolean ("locking")); - handleRecurrence (); - context.tdb.load (tasks, context.filter); - context.tdb.commit (); - context.tdb.unlock (); - - // Just do this once. - int width = context.getWidth (); - - // What day of the week does the user consider the first? - int weekStart = Date::dayOfWeek (context.config.get ("weekstart")); - if (weekStart != 0 && weekStart != 1) - throw std::string ("The 'weekstart' configuration variable may " - "only contain 'Sunday' or 'Monday'."); - - // Determine the date of the first day of the most recent report. - Date today; - Date start; - start -= (((today.dayOfWeek () - weekStart) + 7) % 7) * 86400; - - // Roll back to midnight. - start = Date (start.month (), start.day (), start.year ()); - Date end = start + (7 * 86400); - - // Determine how many reports to run. - int quantity = 1; - if (context.sequence.size () == 1) - quantity = context.sequence[0]; - - std::stringstream out; - for (int week = 0; week < quantity; ++week) - { - Date endString (end); - endString -= 86400; - - std::string title = start.toString (context.config.get ("dateformat")) - + " - " - + endString.toString (context.config.get ("dateformat")); - - Color bold (Color::nocolor, Color::nocolor, false, true, false); - out << "\n" - << (context.color () ? bold.colorize (title) : title) - << "\n"; - - // Render the completed table. - ViewText completed; - completed.width (width); - completed.add (Column::factory ("string", " ")); - completed.add (Column::factory ("string", "Project")); - completed.add (Column::factory ("string.right", "Due")); - completed.add (Column::factory ("string", "Description")); - - std::vector ::iterator task; - for (task = tasks.begin (); task != tasks.end (); ++task) - { - // If task completed within range. - if (task->getStatus () == Task::completed) - { - Date compDate (atoi (task->get ("end").c_str ())); - if (compDate >= start && compDate < end) - { - Color c (task->get ("fg") + " " + task->get ("bg")); - if (context.color ()) - autoColorize (*task, c); - - int row = completed.addRow (); - std::string format = context.config.get ("dateformat.report"); - if (format == "") - format = context.config.get ("dateformat"); - completed.set (row, 1, task->get ("project"), c); - completed.set (row, 2, getDueDate (*task, format), c); - completed.set (row, 3, getFullDescription (*task, "timesheet"), c); - } - } - } - - out << " Completed (" << completed.rows () << " tasks)\n"; - - if (completed.rows ()) - out << completed.render () - << "\n"; - - // Now render the started table. - ViewText started; - started.width (width); - started.add (Column::factory ("string", " ")); - started.add (Column::factory ("string", "Project")); - started.add (Column::factory ("string.right", "Due")); - started.add (Column::factory ("string", "Description")); - - for (task = tasks.begin (); task != tasks.end (); ++task) - { - // If task started within range, but not completed withing range. - if (task->getStatus () == Task::pending && - task->has ("start")) - { - Date startDate (atoi (task->get ("start").c_str ())); - if (startDate >= start && startDate < end) - { - Color c (task->get ("fg") + " " + task->get ("bg")); - if (context.color ()) - autoColorize (*task, c); - - int row = started.addRow (); - std::string format = context.config.get ("dateformat.report"); - if (format == "") - format = context.config.get ("dateformat"); - started.set (row, 1, task->get ("project"), c); - started.set (row, 2, getDueDate (*task, format), c); - started.set (row, 3, getFullDescription (*task, "timesheet"), c); - - } - } - } - - out << " Started (" << started.rows () << " tasks)\n"; - - if (started.rows ()) - out << started.render () - << "\n\n"; - - // Prior week. - start -= 7 * 86400; - end -= 7 * 86400; - } - - outs = out.str (); - return rc; -} - /////////////////////////////////////////////////////////////////////////////// std::string getFullDescription (Task& task, const std::string& report) {