From 9d74b55d489deaea3131cd50f39f2e1094448710 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 26 Feb 2012 13:08:40 -0500 Subject: [PATCH] Feature #725 - Added feature #725, which provides feedback when tasks become unblocked. - Added unit tests. --- ChangeLog | 1 + src/commands/CmdDelete.cpp | 6 ++++-- src/commands/CmdDone.cpp | 2 ++ src/commands/CmdModify.cpp | 10 ++++++---- src/en-US.h | 1 + src/feedback.cpp | 41 ++++++++++++++++++++++++++++++++++++++ src/main.h | 1 + 7 files changed, 56 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index e8002b40a..ef457dfce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -94,6 +94,7 @@ + Added feature #710, which adds an attribute modifier prefix to return the complement of a filtered set (thanks to Dan White). + Added feature #714, including Belarus holidays (thanks to Alexei Romanoff). + + Added feature #725, which provides feedback when tasks become unblocked. + Added feature #733, including Czech holidays (thanks to Tomas Cech). + Added feature #740, that allows for indented annotations, controlled by the 'indent.annotation' configuration variable (thanks to Steve Rader, Tomas diff --git a/src/commands/CmdDelete.cpp b/src/commands/CmdDelete.cpp index b84978c1b..f3848c474 100644 --- a/src/commands/CmdDelete.cpp +++ b/src/commands/CmdDelete.cpp @@ -94,9 +94,10 @@ int CmdDelete::execute (std::string& output) if (permission (*task, question, filtered.size ())) { updateRecurrenceMask (*task); - context.tdb2.modify (*task); ++count; + context.tdb2.modify (*task); feedback_affected (STRING_CMD_DELETE_TASK, *task); + feedback_unblocked (*task); dependencyChainOnComplete (*task); context.footnote (onProjectChange (*task, true)); @@ -117,8 +118,9 @@ int CmdDelete::execute (std::string& output) updateRecurrenceMask (*sibling); context.tdb2.modify (*sibling); - ++count; feedback_affected (STRING_CMD_DELETE_TASK_R, *sibling); + feedback_unblocked (*sibling); + ++count; } // Delete the parent diff --git a/src/commands/CmdDone.cpp b/src/commands/CmdDone.cpp index 2c70a18a9..8f3aae51c 100644 --- a/src/commands/CmdDone.cpp +++ b/src/commands/CmdDone.cpp @@ -95,6 +95,8 @@ int CmdDone::execute (std::string& output) context.tdb2.modify (*task); ++count; feedback_affected (STRING_CMD_DONE_TASK, *task); + feedback_unblocked (*task); + context.tdb2.modify (*task); if (!nagged) nagged = nag (*task); dependencyChainOnComplete (*task); diff --git a/src/commands/CmdModify.cpp b/src/commands/CmdModify.cpp index ea745c2ad..4236f32f1 100644 --- a/src/commands/CmdModify.cpp +++ b/src/commands/CmdModify.cpp @@ -104,10 +104,11 @@ int CmdModify::execute (std::string& output) if (permission (*task, taskDifferences (before, *task) + question, filtered.size ())) { updateRecurrenceMask (*task); - context.tdb2.modify (*task); + dependencyChainOnModify (before, *task); ++count; feedback_affected (STRING_CMD_MODIFY_TASK, *task); - dependencyChainOnModify (before, *task); + feedback_unblocked (*task); + context.tdb2.modify (*task); context.footnote (onProjectChange (before, *task)); // Task potentially has siblings - modify them. @@ -123,11 +124,12 @@ int CmdModify::execute (std::string& output) Task alternate (*sibling); modify_task_description_replace (*sibling, modifications); updateRecurrenceMask (*sibling); - context.tdb2.modify (*sibling); dependencyChainOnModify (alternate, *sibling); - context.footnote (onProjectChange (alternate, *sibling)); ++count; feedback_affected (STRING_CMD_MODIFY_TASK_R, *sibling); + feedback_unblocked (*sibling); + context.tdb2.modify (*sibling); + context.footnote (onProjectChange (alternate, *sibling)); } } } diff --git a/src/en-US.h b/src/en-US.h index 4ddac1c29..7193d6a7a 100644 --- a/src/en-US.h +++ b/src/en-US.h @@ -689,6 +689,7 @@ #define STRING_FEEDBACK_TAG_NONAG "The 'nonag' special tag will prevent nagging when this task is modified." #define STRING_FEEDBACK_TAG_NOCAL "The 'nocal' special tag will keep this task off the calendar report." #define STRING_FEEDBACK_TAG_NEXT "The 'next' special tag will boost the urgency of this task so it appears on the 'next' report." +#define STRING_FEEDBACK_UNBLOCKED "Unblocked {1} '{2}'." // File #define STRING_FILE_PERMS "Task does not have the correct permissions for '{1}'." diff --git a/src/feedback.cpp b/src/feedback.cpp index 95be99f3c..70c500f7f 100644 --- a/src/feedback.cpp +++ b/src/feedback.cpp @@ -365,4 +365,45 @@ void feedback_special_tags (const Task& task, const std::string& tag) } //////////////////////////////////////////////////////////////////////////////// +// Called on completion, deletion and update. If this task is blocking another +// task, then if this was the *only* blocking task, that other task is now +// unblocked. Mention it. +// +// Implements: +// Unblocked '' +void feedback_unblocked (const Task& task) +{ + if (context.verbose ("affected") || + context.config.getBoolean ("echo.command")) // Deprecated 2.0 + { + // Get a list of tasks that depended on this task. + std::vector blocked; + dependencyGetBlocked (task, blocked); + // Scan all the tasks that were blocked by this task + std::vector ::iterator i; + for (i = blocked.begin (); i != blocked.end (); ++i) + { + std::vector blocking; + dependencyGetBlocking (*i, blocking); + if (blocking.size () == 0) + { + if (i->id) + std::cout << format (STRING_FEEDBACK_UNBLOCKED, + i->id, + i->get ("description")) + << "\n"; + else + { + std::string uuid = i->get ("uuid"); + std::cout << format (STRING_FEEDBACK_UNBLOCKED, + i->get ("uuid"), + i->get ("description")) + << "\n"; + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/main.h b/src/main.h index 0a336af47..ab6d55ebb 100644 --- a/src/main.h +++ b/src/main.h @@ -78,6 +78,7 @@ void feedback_affected (const std::string&); void feedback_affected (const std::string&, int); void feedback_affected (const std::string&, const Task&); void feedback_special_tags (const Task&, const std::string&); +void feedback_unblocked (const Task&); // sort.cpp void sort_tasks (std::vector &, std::vector &, const std::string&);