Virtual Tag

- Added 'ANNOTATED' virtual tag.  This fell out of a change mandated by #1218.
This commit is contained in:
Paul Beckingham 2013-04-01 15:15:10 -04:00
parent 6824fb1527
commit 1de2f9e6f1
4 changed files with 34 additions and 22 deletions

View file

@ -30,7 +30,7 @@ Features
+ The 'diagnostics' command now reports libuuid details. + The 'diagnostics' command now reports libuuid details.
+ New characters for parsing and formating dates ('n', 's' and 'v'). + New characters for parsing and formating dates ('n', 's' and 'v').
+ Virtual tags (BLOCKED, UNBLOCKED, BLOCKING, DUE, DUETODAY, TODAY, OVERDUE, + 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, + New 'modified' attribute, which contains the most recent modification date,
if a modification has occurred. if a modification has occurred.
+ Fixed the mechanism used for selecting translations (thanks to Fidel Mato). + Fixed the mechanism used for selecting translations (thanks to Fidel Mato).

View file

@ -580,6 +580,7 @@ are:
CHILD Matches if the task has a parent CHILD Matches if the task has a parent
UNTIL Matches if the task expires UNTIL Matches if the task expires
WAITING Matches if the task is waiting 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. You can use +BLOCKED to filter blocked tasks, or -BLOCKED for unblocked tasks.
Similarly, -BLOCKED is equivalent to +UNBLOCKED. Similarly, -BLOCKED is equivalent to +UNBLOCKED.

View file

@ -106,6 +106,7 @@ Task::Task ()
, recalc_urgency (true) , recalc_urgency (true)
, is_blocked (false) , is_blocked (false)
, is_blocking (false) , is_blocking (false)
, annotation_count (0)
{ {
} }
@ -127,6 +128,7 @@ Task& Task::operator= (const Task& other)
recalc_urgency = other.recalc_urgency; recalc_urgency = other.recalc_urgency;
is_blocked = other.is_blocked; is_blocked = other.is_blocked;
is_blocking = other.is_blocking; is_blocking = other.is_blocking;
annotation_count = other.annotation_count;
} }
return *this; return *this;
@ -156,6 +158,7 @@ Task::Task (const std::string& input)
recalc_urgency = true; recalc_urgency = true;
is_blocked = false; is_blocked = false;
is_blocking = false; is_blocking = false;
annotation_count = 0;
parse (input); parse (input);
} }
@ -436,6 +439,9 @@ void Task::parse (const std::string& input)
value[value.length () - 1] == 'm') value[value.length () - 1] == 'm')
value += 'o'; value += 'o';
if (name.substr (0, 11) == "annotation_")
++annotation_count;
(*this)[name] = decode (json::decode (value)); (*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 name = pair.substr (0, colon);
std::string value = pair.substr (colon + 2, pair.length () - colon - 3); std::string value = pair.substr (colon + 2, pair.length () - colon - 3);
set ("annotation_" + name, value); set ("annotation_" + name, value);
++annotation_count;
} }
} }
@ -676,7 +683,6 @@ std::string Task::composeJSON (bool include_id /*= false*/) const
// First the non-annotations. // First the non-annotations.
int attributes_written = 0; int attributes_written = 0;
int annotation_count = 0;
Task::const_iterator i; Task::const_iterator i;
for (i = this->begin (); i != this->end (); ++i) for (i = this->begin (); i != this->end (); ++i)
{ {
@ -685,14 +691,8 @@ std::string Task::composeJSON (bool include_id /*= false*/) const
Column* column = context.columns[i->first]; 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. // Date fields are written as ISO 8601.
else if (column && if (column &&
column->type () == "date") column->type () == "date")
{ {
Date d (i->second); Date d (i->second);
@ -776,6 +776,12 @@ std::string Task::composeJSON (bool include_id /*= false*/) const
return out.str (); return out.str ();
} }
////////////////////////////////////////////////////////////////////////////////
bool Task::hasAnnotations () const
{
return annotation_count ? true : false;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void Task::getAnnotations (std::map <std::string, std::string>& annotations) const void Task::getAnnotations (std::map <std::string, std::string>& annotations) const
{ {
@ -797,6 +803,7 @@ void Task::setAnnotations (const std::map <std::string, std::string>& annotation
for (ci = annotations.begin (); ci != annotations.end (); ++ci) for (ci = annotations.begin (); ci != annotations.end (); ++ci)
this->insert (*ci); this->insert (*ci);
annotation_count = annotations.size ();
recalc_urgency = true; recalc_urgency = true;
} }
@ -819,6 +826,7 @@ void Task::addAnnotation (const std::string& description)
while (has (key)); while (has (key));
(*this)[key] = description; (*this)[key] = description;
++annotation_count;
recalc_urgency = true; recalc_urgency = true;
} }
@ -830,7 +838,10 @@ void Task::removeAnnotations ()
while (i != this->end ()) while (i != this->end ())
{ {
if (i->first.substr (0, 11) == "annotation_") if (i->first.substr (0, 11) == "annotation_")
{
--annotation_count;
this->erase (i++); this->erase (i++);
}
else else
i++; i++;
} }
@ -960,6 +971,7 @@ bool Task::hasTag (const std::string& tag) const
if (tag == "CHILD") return has ("parent"); if (tag == "CHILD") return has ("parent");
if (tag == "UNTIL") return has ("until"); if (tag == "UNTIL") return has ("until");
if (tag == "WAITING") return has ("wait"); if (tag == "WAITING") return has ("wait");
if (tag == "ANNOTATED") return hasAnnotations ();
/* /*
TODO YESTERDAY - due yesterday TODO YESTERDAY - due yesterday
@ -967,7 +979,6 @@ bool Task::hasTag (const std::string& tag) const
TODO WEEK - due this week TODO WEEK - due this week
TODO MONTH - due this month TODO MONTH - due this month
TODO YEAR - due this year TODO YEAR - due this year
TODO ANNOTATED - has any annotations
TODO READY - is ready TODO READY - is ready
TODO WAITING - is waiting TODO WAITING - is waiting
TODO PARENT - is a parent TODO PARENT - is a parent
@ -1547,12 +1558,9 @@ float Task::urgency_blocked () const
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
float Task::urgency_annotations () const float Task::urgency_annotations () const
{ {
std::map <std::string, std::string> annos; if (annotation_count >= 3) return 1.0;
getAnnotations (annos); else if (annotation_count == 2) return 0.9;
else if (annotation_count == 1) return 0.8;
if (annos.size () >= 3) return 1.0;
else if (annos.size () == 2) return 0.9;
else if (annos.size () == 1) return 0.8;
return 0.0; return 0.0;
} }

View file

@ -62,6 +62,8 @@ public:
bool is_blocked; bool is_blocked;
bool is_blocking; bool is_blocking;
int annotation_count;
// Series of helper functions. // Series of helper functions.
static status textToStatus (const std::string&); static status textToStatus (const std::string&);
static std::string statusToText (status); static std::string statusToText (status);
@ -96,6 +98,7 @@ public:
void getTags (std::vector<std::string>&) const; void getTags (std::vector<std::string>&) const;
void removeTag (const std::string&); void removeTag (const std::string&);
bool hasAnnotations () const;
void getAnnotations (std::map <std::string, std::string>&) const; void getAnnotations (std::map <std::string, std::string>&) const;
void setAnnotations (const std::map <std::string, std::string>&); void setAnnotations (const std::map <std::string, std::string>&);
void addAnnotation (const std::string&); void addAnnotation (const std::string&);