From 2467200a3b3eb51a715f8a6a55a8e878174b774f Mon Sep 17 00:00:00 2001 From: Tomas Babej Date: Sun, 20 Mar 2016 17:25:03 +0100 Subject: [PATCH] CmdPurge: Handle child tasks of recurrence templates --- src/commands/CmdPurge.cpp | 53 +++++++++++++++++++++++++++++++++++++++ src/commands/CmdPurge.h | 1 + src/l10n/eng-USA.h | 3 +++ 3 files changed, 57 insertions(+) diff --git a/src/commands/CmdPurge.cpp b/src/commands/CmdPurge.cpp index 040598c19..ab6d3b4b7 100644 --- a/src/commands/CmdPurge.cpp +++ b/src/commands/CmdPurge.cpp @@ -31,6 +31,7 @@ #include #include #include +#include extern Context context; @@ -54,10 +55,12 @@ CmdPurge::CmdPurge () //////////////////////////////////////////////////////////////////////////////// // Purges the task, while taking care of: // - dependencies on this task +// - child tasks void CmdPurge::purgeTask (Task& task, int& count) { context.tdb2.purge (task); handleDeps (task); + handleChildren (task, count); count++; } @@ -80,6 +83,56 @@ void CmdPurge::handleDeps (Task& task) } } +//////////////////////////////////////////////////////////////////////////////// +// Makes sure that with any recurrence parent are all the child tasks removed +// as well. If user chooses not to, the whole command is aborted. +void CmdPurge::handleChildren (Task& task, int& count) +{ + // If this is not a recurrence parent, we have no job here + if (!task.has ("mask")) + return; + + std::string uuid = task.get ("uuid"); + std::vector children; + + // Find all child tasks + for (auto& childConst: context.tdb2.all_tasks ()) + { + Task& child = const_cast (childConst); + + if (child.get ("parent") == uuid) + { + if (child.getStatus () != Task::deleted) + // In case any child task is not deleted, bail out + throw format (STRING_CMD_PURGE_NDEL_CHILD, + task.get ("description"), + child.identifier (true)); + else + children.push_back (child); + } + } + + // If there are no children, our job is done + if (children.empty ()) + return; + + // Ask for confirmation to purge them, if needed + std::string question = format (STRING_CMD_PURGE_CONFIRM_R, + task.get ("description"), + children.size ()); + + if (context.config.getBoolean ("recurrence.confirmation") || + (context.config.get ("recurrence.confirmation") == "prompt" + && confirm (question))) + { + for (auto& child: children) + purgeTask (child, count); + } + else + throw std::string (STRING_CMD_PURGE_ABRT); +} + + //////////////////////////////////////////////////////////////////////////////// int CmdPurge::execute (std::string&) { diff --git a/src/commands/CmdPurge.h b/src/commands/CmdPurge.h index 7081e9776..3bb0f2c82 100644 --- a/src/commands/CmdPurge.h +++ b/src/commands/CmdPurge.h @@ -34,6 +34,7 @@ class CmdPurge : public Command { private: void purgeTask (Task& task, int& count); + void handleChildren (Task& task, int& count); void handleDeps (Task& task); public: CmdPurge (); diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index 3bded4f9e..84de21d6b 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -397,9 +397,12 @@ #define STRING_CMD_DUPLICATE_N "Duplicated {1} tasks." #define STRING_CMD_PURGE_USAGE "Removes the specified tasks from the data files. Causes permanent loss of data." +#define STRING_CMD_PURGE_ABRT "Purge operation aborted." #define STRING_CMD_PURGE_1 "Purged {1} task." #define STRING_CMD_PURGE_N "Purged {1} tasks." #define STRING_CMD_PURGE_CONFIRM "Permanently remove task {1} '{2}'?" +#define STRING_CMD_PURGE_CONFIRM_R "Task '{1}' is a recurrence template. All its {2} deleted children tasks will be purged as well. Continue?" +#define STRING_CMD_PURGE_NDEL_CHILD "Task '{1}' is a recurrence template. Its child task {2} must be deleted before it can be purged." #define STRING_CMD_START_USAGE "Marks specified task as started" #define STRING_CMD_START_NO "Task not started."