From 9028ca4945251eabd9b53bb03a98d81f78d93ec1 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Sun, 15 Jul 2012 19:34:55 -0400 Subject: [PATCH] UDA Edit - Added UDA and Orphan support to the 'edit' command. It will show the data, but not yet recognize changes to that data. --- src/Task.cpp | 22 +++++++++++++ src/Task.h | 3 ++ src/commands/CmdEdit.cpp | 68 ++++++++++++++++++++++++++++++++++++++++ src/commands/CmdEdit.h | 1 + src/en-US.h | 2 ++ 5 files changed, 96 insertions(+) diff --git a/src/Task.cpp b/src/Task.cpp index 571ed904d..6ff4c9093 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -945,6 +945,28 @@ void Task::removeTag (const std::string& tag) recalc_urgency = true; } +//////////////////////////////////////////////////////////////////////////////// +// A UDA is an attribute that has supporting config entries such as a data type: +// 'uda..type' +void Task::getUDAs (std::vector & names) const +{ + Task::const_iterator it; + for (it = this->begin (); it != this->end (); ++it) + if (context.config.get ("uda." + it->first + ".type") != "") + names.push_back (it->first); +} + +//////////////////////////////////////////////////////////////////////////////// +// A UDA Orphan is an attribute that is not represented in context.columns. +void Task::getUDAOrphans (std::vector & names) const +{ + Task::const_iterator it; + for (it = this->begin (); it != this->end (); ++it) + if (it->first.substr (0, 11) != "annotation_") + if (context.columns.find (it->first) == context.columns.end ()) + names.push_back (it->first); +} + //////////////////////////////////////////////////////////////////////////////// void Task::substitute ( const std::string& from, diff --git a/src/Task.h b/src/Task.h index a607895bd..d496a8284 100644 --- a/src/Task.h +++ b/src/Task.h @@ -103,6 +103,9 @@ public: void getDependencies (std::vector &) const; void getDependencies (std::vector &) const; + void getUDAs (std::vector &) const; + void getUDAOrphans (std::vector &) const; + void substitute (const std::string&, const std::string&, bool); void validate (bool applyDefault = true); diff --git a/src/commands/CmdEdit.cpp b/src/commands/CmdEdit.cpp index 12de5a44a..6ea3a0566 100644 --- a/src/commands/CmdEdit.cpp +++ b/src/commands/CmdEdit.cpp @@ -113,6 +113,21 @@ std::string CmdEdit::formatDate ( return value; } +//////////////////////////////////////////////////////////////////////////////// +std::string CmdEdit::formatDuration ( + Task& task, + const std::string& attribute) +{ + std::string value = task.get (attribute); + if (value.length ()) + { + Duration dur (strtol (value.c_str (), NULL, 10)); + value = dur.formatPrecise (); + } + + return value; +} + //////////////////////////////////////////////////////////////////////////////// std::string CmdEdit::formatTask (Task task, const std::string& dateformat) { @@ -210,6 +225,55 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) before << " Dependencies: " << allDeps.str () << "\n"; + // UDAs + std::vector udas; + std::map ::iterator col; + for (col = context.columns.begin (); col != context.columns.end (); ++col) + if (context.config.get ("uda." + col->first + ".type") != "") + udas.push_back (col->first); + + if (udas.size ()) + { + before << "# " << STRING_EDIT_UDA_SEP << "\n"; + std::sort (udas.begin (), udas.end ()); + std::vector ::iterator uda; + for (uda = udas.begin (); uda != udas.end (); ++uda) + { + int pad = 13 - uda->length (); + std::string padding = ""; + if (pad > 0) + padding = std::string (pad, ' '); + + std::string type = context.config.get ("uda." + *uda + ".type"); + if (type == "string" || type == "numeric") + before << " UDA " << *uda << ": " << padding << task.get (*uda) << "\n"; + else if (type == "date") + before << " UDA " << *uda << ": " << padding << formatDate (task, *uda, dateformat) << "\n"; + else if (type == "duration") + before << " UDA " << *uda << ": " << padding << formatDuration (task, *uda) << "\n"; + } + } + + // UDA orphans + std::vector orphans; + task.getUDAOrphans (orphans); + + if (orphans.size ()) + { + before << "# " << STRING_EDIT_UDA_ORPHAN_SEP << "\n"; + std::sort (orphans.begin (), orphans.end ()); + std::vector ::iterator orphan; + for (orphan = orphans.begin (); orphan != orphans.end (); ++orphan) + { + int pad = 6 - orphan->length (); + std::string padding = ""; + if (pad > 0) + padding = std::string (pad, ' '); + + before << " UDA Orphan " << *orphan << ": " << padding << task.get (*orphan) << "\n"; + } + } + before << "# " << STRING_EDIT_END << "\n"; return before.str (); } @@ -616,6 +680,10 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string for (id = ids.begin (); id != ids.end(); id++) task.addDependency (*id); } + + // TODO UDAs + + // TODO UDA orphans } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/commands/CmdEdit.h b/src/commands/CmdEdit.h index 1ed7c616f..fc4599ccb 100644 --- a/src/commands/CmdEdit.h +++ b/src/commands/CmdEdit.h @@ -42,6 +42,7 @@ public: private: std::string findValue (const std::string&, const std::string&); std::string formatDate (Task&, const std::string&, const std::string&); + std::string formatDuration (Task&, const std::string&); std::string formatTask (Task, const std::string&); void parseTask (Task&, const std::string&, const std::string&); bool editFile (Task&); diff --git a/src/en-US.h b/src/en-US.h index fbaf4f022..1011a7a86 100644 --- a/src/en-US.h +++ b/src/en-US.h @@ -618,6 +618,8 @@ #define STRING_EDIT_UNWRITABLE "Your data.location directory is not writable." #define STRING_EDIT_TAG_SEP "Separate the tags with spaces, like this: tag1 tag2" #define STRING_EDIT_DEP_SEP "Dependencies should be a comma-separated list of task IDs/UUIDs or ID ranges, with no spaces." +#define STRING_EDIT_UDA_SEP "User Defined Attributes" +#define STRING_EDIT_UDA_ORPHAN_SEP "User Defined Attribute Orphans" #define STRING_EDIT_END "End" #define STRING_EDIT_PROJECT_MOD "Project modified."