From 75e651626ddefaa06fdf92fb0d2b49263f6f4546 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 30 May 2011 12:49:45 -0400 Subject: [PATCH] Commands - summary - Migrated handleReportSummary to CmdSummary. --- src/Cmd.cpp | 2 - src/Context.cpp | 3 +- src/commands/CMakeLists.txt | 1 + src/commands/CmdHelp.cpp | 4 - src/commands/CmdSummary.cpp | 180 ++++++++++++++++++++++++++++++++++++ src/commands/CmdSummary.h | 42 +++++++++ src/commands/Command.cpp | 2 + src/main.h | 1 - src/report.cpp | 130 -------------------------- 9 files changed, 226 insertions(+), 139 deletions(-) create mode 100644 src/commands/CmdSummary.cpp create mode 100644 src/commands/CmdSummary.h diff --git a/src/Cmd.cpp b/src/Cmd.cpp index d0858e01b..1a711af7d 100644 --- a/src/Cmd.cpp +++ b/src/Cmd.cpp @@ -134,7 +134,6 @@ void Cmd::load () commands.push_back ("delete"); commands.push_back ("done"); commands.push_back ("import"); - commands.push_back ("summary"); commands.push_back ("timesheet"); commands.push_back ("undo"); commands.push_back ("merge"); @@ -199,7 +198,6 @@ bool Cmd::isReadOnlyCommand () if (command == "_query" || command == "calendar" || command == "push" || - command == "summary" || command == "timesheet" || validCustom (command)) return true; diff --git a/src/Context.cpp b/src/Context.cpp index 70784891e..0e04296c1 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 == "summary") { rc = handleReportSummary (out); } - else if (cmd.command == "calendar") { rc = handleReportCalendar (out); } + if (cmd.command == "calendar") { rc = handleReportCalendar (out); } else if (cmd.command == "timesheet") { rc = handleReportTimesheet (out); } else if (cmd.command == "done") { rc = handleDone (out); } else if (cmd.command == "delete") { rc = handleDelete (out); } diff --git a/src/commands/CMakeLists.txt b/src/commands/CMakeLists.txt index ffb95b52e..f270b55e4 100644 --- a/src/commands/CMakeLists.txt +++ b/src/commands/CMakeLists.txt @@ -35,6 +35,7 @@ set (commands_SRCS Command.cpp Command.h CmdStart.cpp CmdStart.h CmdStatistics.cpp CmdStatistics.h CmdStop.cpp CmdStop.h + CmdSummary.cpp CmdSummary.h CmdTags.cpp CmdTags.h CmdTip.cpp CmdTip.h CmdUrgency.cpp CmdUrgency.h diff --git a/src/commands/CmdHelp.cpp b/src/commands/CmdHelp.cpp index bb3fef578..fb64b9f1a 100644 --- a/src/commands/CmdHelp.cpp +++ b/src/commands/CmdHelp.cpp @@ -115,10 +115,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 summary"); - view.set (row, 2, "Shows a report of task status by project."); - row = view.addRow (); view.set (row, 1, "task timesheet [weeks]"); view.set (row, 2, "Shows a weekly report of tasks completed and started."); diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp new file mode 100644 index 000000000..6cffa6add --- /dev/null +++ b/src/commands/CmdSummary.cpp @@ -0,0 +1,180 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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 +#include + +extern Context context; + +//////////////////////////////////////////////////////////////////////////////// +CmdSummary::CmdSummary () +{ + _keyword = "summary"; + _usage = "task summary"; + _description = "Shows a report of task status by project."; + _read_only = true; + _displays_id = false; +} + +//////////////////////////////////////////////////////////////////////////////// +// Project Remaining Avg Age Complete 0% 100% +// A 12 13d 55% XXXXXXXXXXXXX----------- +// B 109 3d 12h 10% XXX--------------------- +int CmdSummary::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 (); + + // Generate unique list of project names from all pending tasks. + std::map allProjects; + std::vector ::iterator task; + for (task = tasks.begin (); task != tasks.end (); ++task) + if (task->getStatus () == Task::pending) + allProjects[task->get ("project")] = false; + + // Initialize counts, sum. + std::map countPending; + std::map countCompleted; + std::map sumEntry; + std::map counter; + time_t now = time (NULL); + + // Initialize counters. + std::map ::iterator project; + for (project = allProjects.begin (); project != allProjects.end (); ++project) + { + countPending [project->first] = 0; + countCompleted [project->first] = 0; + sumEntry [project->first] = 0.0; + counter [project->first] = 0; + } + + // Count the various tasks. + for (task = tasks.begin (); task != tasks.end (); ++task) + { + std::string project = task->get ("project"); + ++counter[project]; + + if (task->getStatus () == Task::pending || + task->getStatus () == Task::waiting) + { + ++countPending[project]; + + time_t entry = atoi (task->get ("entry").c_str ()); + if (entry) + sumEntry[project] = sumEntry[project] + (double) (now - entry); + } + + else if (task->getStatus () == Task::completed) + { + ++countCompleted[project]; + + time_t entry = atoi (task->get ("entry").c_str ()); + time_t end = atoi (task->get ("end").c_str ()); + if (entry && end) + sumEntry[project] = sumEntry[project] + (double) (end - entry); + } + } + + // Create a table for output. + ViewText view; + view.width (context.getWidth ()); + view.add (Column::factory ("string", "Project")); + view.add (Column::factory ("string.right", "Remaining")); + view.add (Column::factory ("string.right", "Avg age")); + view.add (Column::factory ("string.right", "Complete")); + view.add (Column::factory ("string", "0% 100%")); + + Color bar_color (context.config.get ("color.summary.bar")); + Color bg_color (context.config.get ("color.summary.background")); + + int barWidth = 30; + std::map ::iterator i; + for (i = allProjects.begin (); i != allProjects.end (); ++i) + { + if (countPending[i->first] > 0) + { + int row = view.addRow (); + view.set (row, 0, (i->first == "" ? "(none)" : i->first)); + view.set (row, 1, countPending[i->first]); + if (counter[i->first]) + view.set (row, 2, Duration ((int) (sumEntry[i->first] / (double)counter[i->first])).format ()); + + int c = countCompleted[i->first]; + int p = countPending[i->first]; + int completedBar = (c * barWidth) / (c + p); + + std::string bar; + std::string subbar; + if (context.color ()) + { + bar += bar_color.colorize (std::string ( completedBar, ' ')); + bar += bg_color.colorize (std::string (barWidth - completedBar, ' ')); + } + else + { + bar += std::string ( completedBar, '=') + + std::string (barWidth - completedBar, ' '); + } + view.set (row, 4, bar); + + char percent[12]; + sprintf (percent, "%d%%", 100 * c / (c + p)); + view.set (row, 3, percent); + } + } + + std::stringstream out; + if (view.rows ()) + out << optionalBlankLine () + << view.render () + << optionalBlankLine () + << view.rows () + << (view.rows () == 1 ? " project" : " projects") + << "\n"; + else { + out << "No projects.\n"; + rc = 1; + } + + output = out.str (); + return rc; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdSummary.h b/src/commands/CmdSummary.h new file mode 100644 index 000000000..29e6182b7 --- /dev/null +++ b/src/commands/CmdSummary.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_CMDSUMMARY +#define INCLUDED_CMDSUMMARY +#define L10N // Localization complete. + +#include +#include + +class CmdSummary : public Command +{ +public: + CmdSummary (); + int execute (const std::string&, std::string&); +}; + +#endif +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index 028055cdd..0715a183e 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,7 @@ void Command::factory (std::map & all) c = new CmdStart (); all[c->keyword ()] = c; c = new CmdStatistics (); all[c->keyword ()] = c; c = new CmdStop (); all[c->keyword ()] = c; + c = new CmdSummary (); all[c->keyword ()] = c; c = new CmdTags (); all[c->keyword ()] = c; c = new CmdTip (); all[c->keyword ()] = c; c = new CmdUrgency (); all[c->keyword ()] = c; diff --git a/src/main.h b/src/main.h index 135c35d45..b08cde9b5 100644 --- a/src/main.h +++ b/src/main.h @@ -66,7 +66,6 @@ int deltaAttributes (Task&); int deltaSubstitutions (Task&); // report.cpp -int handleReportSummary (std::string&); int handleReportCalendar (std::string&); int handleReportTimesheet (std::string&); std::string getFullDescription (Task&, const std::string&); diff --git a/src/report.cpp b/src/report.cpp index dcf62091d..7009158aa 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -51,136 +51,6 @@ static void countTasks (const std::vector &, const std::string&, const std extern Context context; -//////////////////////////////////////////////////////////////////////////////// -// Project Remaining Avg Age Complete 0% 100% -// A 12 13d 55% XXXXXXXXXXXXX----------- -// B 109 3d 12h 10% XXX--------------------- -int handleReportSummary (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 (); - - // Generate unique list of project names from all pending tasks. - std::map allProjects; - std::vector ::iterator task; - for (task = tasks.begin (); task != tasks.end (); ++task) - if (task->getStatus () == Task::pending) - allProjects[task->get ("project")] = false; - - // Initialize counts, sum. - std::map countPending; - std::map countCompleted; - std::map sumEntry; - std::map counter; - time_t now = time (NULL); - - // Initialize counters. - foreach (project, allProjects) - { - countPending [project->first] = 0; - countCompleted [project->first] = 0; - sumEntry [project->first] = 0.0; - counter [project->first] = 0; - } - - // Count the various tasks. - for (task = tasks.begin (); task != tasks.end (); ++task) - { - std::string project = task->get ("project"); - ++counter[project]; - - if (task->getStatus () == Task::pending || - task->getStatus () == Task::waiting) - { - ++countPending[project]; - - time_t entry = atoi (task->get ("entry").c_str ()); - if (entry) - sumEntry[project] = sumEntry[project] + (double) (now - entry); - } - - else if (task->getStatus () == Task::completed) - { - ++countCompleted[project]; - - time_t entry = atoi (task->get ("entry").c_str ()); - time_t end = atoi (task->get ("end").c_str ()); - if (entry && end) - sumEntry[project] = sumEntry[project] + (double) (end - entry); - } - } - - // Create a table for output. - ViewText view; - view.width (context.getWidth ()); - view.add (Column::factory ("string", "Project")); - view.add (Column::factory ("string.right", "Remaining")); - view.add (Column::factory ("string.right", "Avg age")); - view.add (Column::factory ("string.right", "Complete")); - view.add (Column::factory ("string", "0% 100%")); - - Color bar_color (context.config.get ("color.summary.bar")); - Color bg_color (context.config.get ("color.summary.background")); - - int barWidth = 30; - foreach (i, allProjects) - { - if (countPending[i->first] > 0) - { - int row = view.addRow (); - view.set (row, 0, (i->first == "" ? "(none)" : i->first)); - view.set (row, 1, countPending[i->first]); - if (counter[i->first]) - view.set (row, 2, Duration ((int) (sumEntry[i->first] / (double)counter[i->first])).format ()); - - int c = countCompleted[i->first]; - int p = countPending[i->first]; - int completedBar = (c * barWidth) / (c + p); - - std::string bar; - std::string subbar; - if (context.color ()) - { - bar += bar_color.colorize (std::string ( completedBar, ' ')); - bar += bg_color.colorize (std::string (barWidth - completedBar, ' ')); - } - else - { - bar += std::string ( completedBar, '=') - + std::string (barWidth - completedBar, ' '); - } - view.set (row, 4, bar); - - char percent[12]; - sprintf (percent, "%d%%", 100 * c / (c + p)); - view.set (row, 3, percent); - } - } - - std::stringstream out; - if (view.rows ()) - out << optionalBlankLine () - << view.render () - << optionalBlankLine () - << view.rows () - << (view.rows () == 1 ? " project" : " projects") - << "\n"; - else { - out << "No projects.\n"; - rc = 1; - } - - outs = out.str (); - return rc; -} - //////////////////////////////////////////////////////////////////////////////// int handleReportTimesheet (std::string& outs) {