From 1de2f9e6f1bf36066dbff0ff059bad3e67453e96 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Mon, 1 Apr 2013 15:15:10 -0400 Subject: [PATCH] Virtual Tag - Added 'ANNOTATED' virtual tag. This fell out of a change mandated by #1218. --- ChangeLog | 2 +- doc/man/task.1.in | 1 + src/Task.cpp | 50 +++++++++++++++++++++++++++-------------------- src/Task.h | 3 +++ 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f794bd39..e2b180771 100644 --- a/ChangeLog +++ b/ChangeLog @@ -30,7 +30,7 @@ Features + The 'diagnostics' command now reports libuuid details. + New characters for parsing and formating dates ('n', 's' and 'v'). + Virtual tags (BLOCKED, UNBLOCKED, BLOCKING, DUE, DUETODAY, TODAY, OVERDUE, - ACTIVE, SCHEDULED, CHILD, UNTIL and WAITING). + ACTIVE, SCHEDULED, CHILD, UNTIL, WAITING and ANNOTATED). + New 'modified' attribute, which contains the most recent modification date, if a modification has occurred. + Fixed the mechanism used for selecting translations (thanks to Fidel Mato). diff --git a/doc/man/task.1.in b/doc/man/task.1.in index 880490f99..949417edf 100644 --- a/doc/man/task.1.in +++ b/doc/man/task.1.in @@ -580,6 +580,7 @@ are: CHILD Matches if the task has a parent UNTIL Matches if the task expires WAITING Matches if the task is waiting + ANNOTATED Matches if the task has annotations You can use +BLOCKED to filter blocked tasks, or -BLOCKED for unblocked tasks. Similarly, -BLOCKED is equivalent to +UNBLOCKED. diff --git a/src/Task.cpp b/src/Task.cpp index 1a5c121de..16dd2af28 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -106,6 +106,7 @@ Task::Task () , recalc_urgency (true) , is_blocked (false) , is_blocking (false) +, annotation_count (0) { } @@ -122,11 +123,12 @@ Task& Task::operator= (const Task& other) { std::map ::operator= (other); - id = other.id; - urgency_value = other.urgency_value; - recalc_urgency = other.recalc_urgency; - is_blocked = other.is_blocked; - is_blocking = other.is_blocking; + id = other.id; + urgency_value = other.urgency_value; + recalc_urgency = other.recalc_urgency; + is_blocked = other.is_blocked; + is_blocking = other.is_blocking; + annotation_count = other.annotation_count; } return *this; @@ -156,6 +158,7 @@ Task::Task (const std::string& input) recalc_urgency = true; is_blocked = false; is_blocking = false; + annotation_count = 0; parse (input); } @@ -436,6 +439,9 @@ void Task::parse (const std::string& input) value[value.length () - 1] == 'm') value += 'o'; + if (name.substr (0, 11) == "annotation_") + ++annotation_count; + (*this)[name] = decode (json::decode (value)); } @@ -611,6 +617,7 @@ void Task::legacyParse (const std::string& line) std::string name = pair.substr (0, colon); std::string value = pair.substr (colon + 2, pair.length () - colon - 3); set ("annotation_" + name, value); + ++annotation_count; } } @@ -676,7 +683,6 @@ std::string Task::composeJSON (bool include_id /*= false*/) const // First the non-annotations. int attributes_written = 0; - int annotation_count = 0; Task::const_iterator i; for (i = this->begin (); i != this->end (); ++i) { @@ -685,15 +691,9 @@ std::string Task::composeJSON (bool include_id /*= false*/) const Column* column = context.columns[i->first]; - // Annotations are simply counted. - if (i->first.substr (0, 11) == "annotation_") - { - ++annotation_count; - } - // Date fields are written as ISO 8601. - else if (column && - column->type () == "date") + if (column && + column->type () == "date") { Date d (i->second); out << "\"" @@ -776,6 +776,12 @@ std::string Task::composeJSON (bool include_id /*= false*/) const return out.str (); } +//////////////////////////////////////////////////////////////////////////////// +bool Task::hasAnnotations () const +{ + return annotation_count ? true : false; +} + //////////////////////////////////////////////////////////////////////////////// void Task::getAnnotations (std::map & annotations) const { @@ -797,6 +803,7 @@ void Task::setAnnotations (const std::map & annotation for (ci = annotations.begin (); ci != annotations.end (); ++ci) this->insert (*ci); + annotation_count = annotations.size (); recalc_urgency = true; } @@ -819,6 +826,7 @@ void Task::addAnnotation (const std::string& description) while (has (key)); (*this)[key] = description; + ++annotation_count; recalc_urgency = true; } @@ -830,7 +838,10 @@ void Task::removeAnnotations () while (i != this->end ()) { if (i->first.substr (0, 11) == "annotation_") + { + --annotation_count; this->erase (i++); + } else i++; } @@ -960,6 +971,7 @@ bool Task::hasTag (const std::string& tag) const if (tag == "CHILD") return has ("parent"); if (tag == "UNTIL") return has ("until"); if (tag == "WAITING") return has ("wait"); + if (tag == "ANNOTATED") return hasAnnotations (); /* TODO YESTERDAY - due yesterday @@ -967,7 +979,6 @@ bool Task::hasTag (const std::string& tag) const TODO WEEK - due this week TODO MONTH - due this month TODO YEAR - due this year - TODO ANNOTATED - has any annotations TODO READY - is ready TODO WAITING - is waiting TODO PARENT - is a parent @@ -1547,12 +1558,9 @@ float Task::urgency_blocked () const //////////////////////////////////////////////////////////////////////////////// float Task::urgency_annotations () const { - std::map annos; - getAnnotations (annos); - - if (annos.size () >= 3) return 1.0; - else if (annos.size () == 2) return 0.9; - else if (annos.size () == 1) return 0.8; + if (annotation_count >= 3) return 1.0; + else if (annotation_count == 2) return 0.9; + else if (annotation_count == 1) return 0.8; return 0.0; } diff --git a/src/Task.h b/src/Task.h index 432f0235d..3a3efce11 100644 --- a/src/Task.h +++ b/src/Task.h @@ -62,6 +62,8 @@ public: bool is_blocked; bool is_blocking; + int annotation_count; + // Series of helper functions. static status textToStatus (const std::string&); static std::string statusToText (status); @@ -96,6 +98,7 @@ public: void getTags (std::vector&) const; void removeTag (const std::string&); + bool hasAnnotations () const; void getAnnotations (std::map &) const; void setAnnotations (const std::map &); void addAnnotation (const std::string&);