diff --git a/ChangeLog b/ChangeLog index 7ddc30066..bd0c6ca31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -30,6 +30,9 @@ (thanks to Flavio Poletti). - TW-1857 Change Task::get call to the more efficient Task::has (thanks to Zachary Manning). +- TW‐1858 Change signature for dependencyGetBlocked +- TW-1859 Change signature of Task::getTags +- TW-1860 Change signature of Task::getAnnotations - TW-1873 Specify different path to extensions/hooks directory (thanks to Eli). - TW-1878 uuids subcommand produces a space-delimited list, not comma-delimited diff --git a/NEWS b/NEWS index 1ecb47ad9..31f2b37b2 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,7 @@ Newly Deprecated Features in Taskwarrior 2.6.0 - The use of alternate Boolean configuration settings is deprecated. Use values "0" for off, and "1" for on. Avoid used of "on", "off", "true", "t", "false", "f", "yes", "y", "no", "n". + - The 'PARENT' and 'CHILD' virtual tags are replaced by 'TEMPLATE' and 'INSTANCE'. Removed Features in 2.6.0 diff --git a/doc/man/task.1.in b/doc/man/task.1.in index 9467fdb56..dc0b2110a 100644 --- a/doc/man/task.1.in +++ b/doc/man/task.1.in @@ -677,15 +677,16 @@ are: ANNOTATED Matches if the task has annotations BLOCKED Matches if the task is blocked BLOCKING Matches if the task is blocking - CHILD Matches if the task has a parent + CHILD Matches if the task has a parent (deprecated in 2.6.0) COMPLETED Matches if the task has completed status DELETED Matches if the task has deleted status DUE Matches if the task is due + INSTANCE Matches if the task is a recurrent instance LATEST Matches if the task is the newest added task MONTH Matches if the task is due this month ORPHAN Matches if the task has any orphaned UDA values OVERDUE Matches if the task is overdue - PARENT Matches if the task is a parent + PARENT Matches if the task is a parent (deprecated in 2.6.0) PENDING Matches if the task has pending status PRIORITY Matches if the task has a priority PROJECT Matches if the task has a project @@ -693,6 +694,7 @@ are: READY Matches if the task is actionable SCHEDULED Matches if the task is scheduled TAGGED Matches if the task has tags + TEMPLATE Matches if the task is a recurrence template TODAY Matches if the task is due today TOMORROW Matches if the task is due sometime tomorrow UDA Matches if the task has any UDA values diff --git a/src/DOM.cpp b/src/DOM.cpp index cdfd34f6b..539e2fe37 100644 --- a/src/DOM.cpp +++ b/src/DOM.cpp @@ -300,8 +300,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) if (ref.data.size () && size == 3 && elements[0] == "annotations") { - std::map annos; - ref.getAnnotations (annos); + auto annos = ref.getAnnotations (); int a = strtol (elements[1].c_str (), NULL, 10); int count = 0; @@ -329,8 +328,7 @@ bool getDOM (const std::string& name, const Task& task, Variant& value) if (ref.data.size () && size == 4 && elements[0] == "annotations" && elements[2] == "entry") { - std::map annos; - ref.getAnnotations (annos); + auto annos = ref.getAnnotations (); int a = strtol (elements[1].c_str (), NULL, 10); int count = 0; diff --git a/src/TDB2.cpp b/src/TDB2.cpp index cde16fe00..5988ec0ac 100644 --- a/src/TDB2.cpp +++ b/src/TDB2.cpp @@ -528,10 +528,7 @@ void TF2::dependency_scan () { if (left.has ("depends")) { - std::vector deps; - left.getDependencies (deps); - - for (auto& dep : deps) + for (auto& dep : left.getDependencyUUIDs ()) { for (auto& right : _tasks) { diff --git a/src/Task.cpp b/src/Task.cpp index 1fa953265..35deff3da 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -1081,13 +1081,14 @@ void Task::removeAnnotations () } //////////////////////////////////////////////////////////////////////////////// -void Task::getAnnotations (std::map & annotations) const +std::map Task::getAnnotations () const { - annotations.clear (); - + std::map a; for (auto& ann : data) if (! ann.first.compare (0, 11, "annotation_", 11)) - annotations.insert (ann); + a.insert (ann); + + return a; } //////////////////////////////////////////////////////////////////////////////// @@ -1185,35 +1186,33 @@ void Task::removeDependency (int id) } //////////////////////////////////////////////////////////////////////////////// -void Task::getDependencies (std::vector & all) const +std::vector Task::getDependencyIDs () const { - auto deps = split (get ("depends"), ','); - - all.clear (); - - for (auto& dep : deps) + std::vector all; + for (auto& dep : split (get ("depends"), ',')) all.push_back (context.tdb2.pending.id (dep)); + + return all; } //////////////////////////////////////////////////////////////////////////////// -void Task::getDependencies (std::vector & all) const +std::vector Task::getDependencyUUIDs () const { - all = split (get ("depends"), ','); + return split (get ("depends"), ','); } //////////////////////////////////////////////////////////////////////////////// -void Task::getDependencies (std::vector & all) const +std::vector Task::getDependencyTasks () const { - std::vector deps = split (get ("depends"), ','); - - all.clear (); - - for (auto& dep : deps) + std::vector all; + for (auto& dep : split (get ("depends"), ',')) { Task task; context.tdb2.get (dep, task); all.push_back (task); } + + return all; } #endif @@ -1260,11 +1259,13 @@ bool Task::hasTag (const std::string& tag) const #endif if (tag == "ACTIVE") return has ("start"); if (tag == "SCHEDULED") return has ("scheduled"); - if (tag == "CHILD") return has ("parent"); + if (tag == "CHILD") return has ("parent"); // 2017-01-07: Deprecated in 2.6.0 + if (tag == "INSTANCE") return has ("template"); if (tag == "UNTIL") return has ("until"); if (tag == "ANNOTATED") return hasAnnotations (); if (tag == "TAGGED") return has ("tags"); - if (tag == "PARENT") return has ("mask"); + if (tag == "PARENT") return has ("mask"); // 2017-01-07: Deprecated in 2.6.0 + if (tag == "TEMPLATE") return has ("last"); if (tag == "WAITING") return get ("status") == "waiting"; if (tag == "PENDING") return get ("status") == "pending"; if (tag == "COMPLETED") return get ("status") == "completed"; @@ -1313,9 +1314,9 @@ void Task::addTags (const std::vector & tags) } //////////////////////////////////////////////////////////////////////////////// -void Task::getTags (std::vector& tags) const +std::vector Task::getTags () const { - tags = split (get ("tags"), ','); + return split (get ("tags"), ','); } //////////////////////////////////////////////////////////////////////////////// @@ -1336,12 +1337,15 @@ void Task::removeTag (const std::string& tag) #ifdef PRODUCT_TASKWARRIOR //////////////////////////////////////////////////////////////////////////////// // A UDA Orphan is an attribute that is not represented in context.columns. -void Task::getUDAOrphans (std::vector & names) const +std::vector Task::getUDAOrphanUUIDs () const { + std::vector orphans; for (auto& it : data) if (it.first.compare (0, 11, "annotation_", 11) != 0) if (context.columns.find (it.first) == context.columns.end ()) - names.push_back (it.first); + orphans.push_back (it.first); + + return orphans; } //////////////////////////////////////////////////////////////////////////////// @@ -1354,8 +1358,7 @@ void Task::substitute ( // Get the data to modify. std::string description = get ("description"); - std::map annotations; - getAnnotations (annotations); + auto annotations = getAnnotations (); // Count the changes, so we know whether to proceed to annotations, after // modifying description. @@ -1864,19 +1867,16 @@ float Task::urgency () //////////////////////////////////////////////////////////////////////////////// float Task::urgency_inherit () const { + float v = FLT_MIN; +#ifdef PRODUCT_TASKWARRIOR // Calling dependencyGetBlocked is rather expensive. // It is called recursively for each dependency in the chain here. - std::vector blocked; -#ifdef PRODUCT_TASKWARRIOR - dependencyGetBlocked (*this, blocked); -#endif - - float v = FLT_MIN; - for (auto& task : blocked) + for (auto& task : dependencyGetBlocked (*this)) { // Find highest urgency in all blocked tasks. v = std::max (v, task.urgency ()); } +#endif return v; } diff --git a/src/Task.h b/src/Task.h index 5d7961781..2cf4da61a 100644 --- a/src/Task.h +++ b/src/Task.h @@ -125,11 +125,11 @@ public: bool hasTag (const std::string&) const; void addTag (const std::string&); void addTags (const std::vector &); - void getTags (std::vector&) const; + std::vector getTags () const; void removeTag (const std::string&); bool hasAnnotations () const; - void getAnnotations (std::map &) const; + std::map getAnnotations () const; void setAnnotations (const std::map &); void addAnnotation (const std::string&); void removeAnnotations (); @@ -141,11 +141,11 @@ public: #ifdef PRODUCT_TASKWARRIOR void removeDependency (int); void removeDependency (const std::string&); - void getDependencies (std::vector &) const; - void getDependencies (std::vector &) const; - void getDependencies (std::vector &) const; + std::vector getDependencyIDs () const; + std::vector getDependencyUUIDs () const; + std::vector getDependencyTasks () const; - void getUDAOrphans (std::vector &) const; + std::vector getUDAOrphanUUIDs () const; void substitute (const std::string&, const std::string&, const std::string&); #endif @@ -170,17 +170,17 @@ private: const std::string decode (const std::string&) const; public: - float urgency_project () const; - float urgency_active () const; - float urgency_scheduled () const; - float urgency_waiting () const; - float urgency_blocked () const; - float urgency_inherit () const; + float urgency_project () const; + float urgency_active () const; + float urgency_scheduled () const; + float urgency_waiting () const; + float urgency_blocked () const; + float urgency_inherit () const; float urgency_annotations () const; - float urgency_tags () const; - float urgency_due () const; - float urgency_blocking () const; - float urgency_age () const; + float urgency_tags () const; + float urgency_due () const; + float urgency_blocking () const; + float urgency_age () const; }; #endif diff --git a/src/Variant.cpp b/src/Variant.cpp index 5c9def5a7..a4ae7182a 100644 --- a/src/Variant.cpp +++ b/src/Variant.cpp @@ -874,10 +874,7 @@ bool Variant::operator_match (const Variant& other, const Task& task) const // in the annotations. if (left.source () == "description") { - std::map annotations; - task.getAnnotations (annotations); - - for (auto& a : annotations) + for (auto& a : task.getAnnotations ()) if (r.match (a.second)) return true; } @@ -909,10 +906,7 @@ bool Variant::operator_match (const Variant& other, const Task& task) const // in the annotations. if (left.source () == "description") { - std::map annotations; - task.getAnnotations (annotations); - - for (auto& a : annotations) + for (auto& a : task.getAnnotations ()) if (find (a.second, pattern, searchCaseSensitive) != std::string::npos) return true; } diff --git a/src/columns/CMakeLists.txt b/src/columns/CMakeLists.txt index 0bfffc941..002982bbb 100644 --- a/src/columns/CMakeLists.txt +++ b/src/columns/CMakeLists.txt @@ -14,16 +14,18 @@ set (columns_SRCS Column.cpp Column.h ColEntry.cpp ColEntry.h ColID.cpp ColID.h ColIMask.cpp ColIMask.h + ColLast.cpp ColLast.h ColMask.cpp ColMask.h ColModified.cpp ColModified.h ColParent.cpp ColParent.h ColProject.cpp ColProject.h ColRecur.cpp ColRecur.h + ColRType.cpp ColRType.h ColScheduled.cpp ColScheduled.h ColStart.cpp ColStart.h ColStatus.cpp ColStatus.h - ColString.cpp ColString.h ColTags.cpp ColTags.h + ColTemplate.cpp ColTemplate.h ColTypeDate.cpp ColTypeDate.h ColTypeDuration.cpp ColTypeDuration.h ColTypeNumeric.cpp ColTypeNumeric.h diff --git a/src/columns/ColDepends.cpp b/src/columns/ColDepends.cpp index 16ae70ee3..1f256c086 100644 --- a/src/columns/ColDepends.cpp +++ b/src/columns/ColDepends.cpp @@ -58,7 +58,7 @@ ColumnDepends::ColumnDepends () // Note that you can not determine which gets called first. void ColumnDepends::setStyle (const std::string& value) { - _style = value; + Column::setStyle (value); if (_style == "indicator" && _label == STRING_COLUMN_LABEL_DEP) _label = _label.substr (0, context.config.get ("dependency.indicator").length ()); else if (_style == "count" && _label == STRING_COLUMN_LABEL_DEP) _label = STRING_COLUMN_LABEL_DEP_S; @@ -68,26 +68,25 @@ void ColumnDepends::setStyle (const std::string& value) // Set the minimum and maximum widths for the value. void ColumnDepends::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { - std::vector blocking; - dependencyGetBlocking (task, blocking); - - if (_style == "indicator") + minimum = maximum = 0; + if (task.has (_name)) { - if (task.has ("depends")) - minimum = maximum = utf8_width (context.config.get ("dependency.indicator")); - else - minimum = maximum = 0; - } - else if (_style == "count") - { - minimum = maximum = 2 + format ((int) blocking.size ()).length (); - } - else if (_style == "default" || - _style == "list") - { - minimum = maximum = 0; - if (task.has ("depends")) + if (_style == "indicator") { + minimum = maximum = utf8_width (context.config.get ("dependency.indicator")); + } + + else if (_style == "count") + { + minimum = maximum = 2 + format ((int) dependencyGetBlocking (task).size ()).length (); + } + + else if (_style == "default" || + _style == "list") + { + minimum = maximum = 0; + auto blocking = dependencyGetBlocking (task); + std::vector blocking_ids; for (auto& i : blocking) blocking_ids.push_back (i.id); @@ -104,8 +103,6 @@ void ColumnDepends::measure (Task& task, unsigned int& minimum, unsigned int& ma } } } - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } //////////////////////////////////////////////////////////////////////////////// @@ -118,30 +115,31 @@ void ColumnDepends::render ( if (task.has (_name)) { if (_style == "indicator") - renderStringRight (lines, width, color, context.config.get ("dependency.indicator")); - else { - std::vector blocking; - dependencyGetBlocking (task, blocking); + renderStringRight (lines, width, color, context.config.get ("dependency.indicator")); + } - if (_style == "count") - renderStringRight (lines, width, color, '[' + format (static_cast (blocking.size ())) + ']'); + else if (_style == "count") + { + renderStringRight (lines, width, color, '[' + format (static_cast (dependencyGetBlocking (task).size ())) + ']'); + } - else if (_style == "default" || - _style == "list") - { - std::vector blocking_ids; - for (const auto& t : blocking) - blocking_ids.push_back (t.id); + else if (_style == "default" || + _style == "list") + { + auto blocking = dependencyGetBlocking (task); - auto combined = join (" ", blocking_ids); + std::vector blocking_ids; + for (const auto& t : blocking) + blocking_ids.push_back (t.id); - std::vector all; - wrapText (all, combined, width, _hyphenate); + auto combined = join (" ", blocking_ids); - for (const auto& i : all) - renderStringLeft (lines, width, color, i); - } + std::vector all; + wrapText (all, combined, width, _hyphenate); + + for (const auto& i : all) + renderStringLeft (lines, width, color, i); } } } diff --git a/src/columns/ColDescription.cpp b/src/columns/ColDescription.cpp index 7dc20613e..1464592aa 100644 --- a/src/columns/ColDescription.cpp +++ b/src/columns/ColDescription.cpp @@ -40,16 +40,17 @@ extern Context context; //////////////////////////////////////////////////////////////////////////////// ColumnDescription::ColumnDescription () { - _name = "description"; - _style = "combined"; - _label = STRING_COLUMN_LABEL_DESC; + _name = "description"; + _style = "combined"; + _label = STRING_COLUMN_LABEL_DESC; + _modifiable = true; - _styles = {"combined", - "desc", - "oneline", - "truncated", - "count", - "truncated_count"}; + _styles = {"combined", + "desc", + "oneline", + "truncated", + "count", + "truncated_count"}; _dateformat = context.config.get ("dateformat.annotation"); if (_dateformat == "") @@ -101,9 +102,7 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int if (min_anno > minimum) minimum = min_anno; - std::map annos; - task.getAnnotations (annos); - for (auto& i : annos) + for (auto& i : task.getAnnotations ()) { unsigned int len = min_anno + 1 + utf8_width (i.second); if (len > maximum) @@ -128,9 +127,7 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int if (task.annotation_count) { auto min_anno = Datetime::length (_dateformat); - std::map annos; - task.getAnnotations (annos); - for (auto& i : annos) + for (auto& i : task.getAnnotations ()) maximum += min_anno + 1 + utf8_width (i.second); } } @@ -156,9 +153,6 @@ void ColumnDescription::measure (Task& task, unsigned int& minimum, unsigned int minimum = 4; maximum = utf8_width (description) + 1 + 1 + format (task.annotation_count).length () + 1; } - - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } //////////////////////////////////////////////////////////////////////////////// @@ -178,9 +172,7 @@ void ColumnDescription::render ( { if (task.annotation_count) { - std::map annos; - task.getAnnotations (annos); - for (const auto& i : annos) + for (const auto& i : task.getAnnotations ()) { Datetime dt (strtol (i.first.substr (11).c_str (), NULL, 10)); description += '\n' + std::string (_indent, ' ') + dt.toString (_dateformat) + ' ' + i.second; @@ -209,9 +201,7 @@ void ColumnDescription::render ( { if (task.annotation_count) { - std::map annos; - task.getAnnotations (annos); - for (const auto& i : annos) + for (const auto& i : task.getAnnotations ()) { Datetime dt (strtol (i.first.substr (11).c_str (), NULL, 10)); description += ' ' + dt.toString (_dateformat) + ' ' + i.second; diff --git a/src/columns/ColDue.cpp b/src/columns/ColDue.cpp index 50ffd849d..d64b7788b 100644 --- a/src/columns/ColDue.cpp +++ b/src/columns/ColDue.cpp @@ -31,8 +31,9 @@ //////////////////////////////////////////////////////////////////////////////// ColumnDue::ColumnDue () { - _name = "due"; - _label = STRING_COLUMN_LABEL_DUE; + _name = "due"; + _modifiable = true; + _label = STRING_COLUMN_LABEL_DUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColEntry.cpp b/src/columns/ColEntry.cpp index 63959fee3..a28ee3603 100644 --- a/src/columns/ColEntry.cpp +++ b/src/columns/ColEntry.cpp @@ -31,8 +31,9 @@ //////////////////////////////////////////////////////////////////////////////// ColumnEntry::ColumnEntry () { - _name = "entry"; - _label = STRING_COLUMN_LABEL_ADDED; + _name = "entry"; + _modifiable = true; + _label = STRING_COLUMN_LABEL_ADDED; } //////////////////////////////////////////////////////////////////////////////// @@ -40,7 +41,7 @@ ColumnEntry::ColumnEntry () // Note that you can not determine which gets called first. void ColumnEntry::setStyle (const std::string& value) { - _style = value; + Column::setStyle (value); if (_style == "age" && _label == STRING_COLUMN_LABEL_ADDED) diff --git a/src/columns/ColID.cpp b/src/columns/ColID.cpp index 0108facef..28d934fa0 100644 --- a/src/columns/ColID.cpp +++ b/src/columns/ColID.cpp @@ -55,10 +55,6 @@ void ColumnID::measure (Task& task, unsigned int& minimum, unsigned int& maximum else length = 1 + (int) log10 ((double) task.id); // Slow minimum = maximum = length; - - if (_style != "default" && - _style != "number") - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } //////////////////////////////////////////////////////////////////////////////// @@ -68,6 +64,7 @@ void ColumnID::render ( int width, Color& color) { + // Completed and deleted tasks have no ID. if (task.id) renderInteger (lines, width, color, task.id); else diff --git a/src/columns/ColIMask.cpp b/src/columns/ColIMask.cpp index dc14682d2..1b9c75066 100644 --- a/src/columns/ColIMask.cpp +++ b/src/columns/ColIMask.cpp @@ -45,15 +45,8 @@ ColumnIMask::ColumnIMask () void ColumnIMask::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) - { - minimum = maximum = task.get ("imask").length (); - - if (_style != "default" && - _style != "number") - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); - } + minimum = maximum = task.get (_name).length (); } //////////////////////////////////////////////////////////////////////////////// @@ -64,7 +57,7 @@ void ColumnIMask::render ( Color& color) { if (task.has (_name)) - renderStringRight (lines, width, color, task.get ("imask")); + renderStringRight (lines, width, color, task.get (_name)); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColLast.cpp b/src/columns/ColLast.cpp new file mode 100644 index 000000000..71e49b82d --- /dev/null +++ b/src/columns/ColLast.cpp @@ -0,0 +1,63 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2006 - 2016, Paul Beckingham, Federico Hernandez. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// http://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////// +ColumnLast::ColumnLast () +{ + _name = "last"; + _style = "number"; + _label = STRING_COLUMN_LABEL_LAST; + _modifiable = false; + _styles = {"number"}; + _examples = {"12"}; +} + +//////////////////////////////////////////////////////////////////////////////// +// Set the minimum and maximum widths for the value. +void ColumnLast::measure (Task& task, unsigned int& minimum, unsigned int& maximum) +{ + minimum = maximum = 0; + if (task.has (_name)) + minimum = maximum = task.get (_name).length (); +} + +//////////////////////////////////////////////////////////////////////////////// +void ColumnLast::render ( + std::vector & lines, + Task& task, + int width, + Color& color) +{ + if (task.has (_name)) + renderStringRight (lines, width, color, task.get (_name)); +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColString.h b/src/columns/ColLast.h similarity index 78% rename from src/columns/ColString.h rename to src/columns/ColLast.h index 53c637548..e75d3920a 100644 --- a/src/columns/ColString.h +++ b/src/columns/ColLast.h @@ -24,25 +24,19 @@ // //////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDED_COLSTRING -#define INCLUDED_COLSTRING +#ifndef INCLUDED_COLLAST +#define INCLUDED_COLLAST -#include -#include -#include -#include -#include +#include -class ColumnString : public Column +class ColumnLast : public ColumnTypeNumeric { public: - ColumnString (); - void setReport (const std::string&); - void measure (const std::string&, unsigned int&, unsigned int&); - void render (std::vector &, const std::string&, int, Color&); + ColumnLast (); + void measure (Task&, unsigned int&, unsigned int&); + void render (std::vector &, Task&, int, Color&); private: - bool _hyphenate; }; #endif diff --git a/src/columns/ColMask.cpp b/src/columns/ColMask.cpp index 8bbcb2a9c..25858ceae 100644 --- a/src/columns/ColMask.cpp +++ b/src/columns/ColMask.cpp @@ -46,12 +46,7 @@ void ColumnMask::measure (Task& task, unsigned int& minimum, unsigned int& maxim { minimum = maximum = 0; if (task.has (_name)) - { - minimum = maximum = task.get ("mask").length (); - - if (_style != "default") - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); - } + minimum = maximum = task.get (_name).length (); } //////////////////////////////////////////////////////////////////////////////// @@ -62,7 +57,7 @@ void ColumnMask::render ( Color& color) { if (task.has (_name)) - renderStringLeft (lines, width, color, task.get ("mask")); + renderStringLeft (lines, width, color, task.get (_name)); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColParent.cpp b/src/columns/ColParent.cpp index 5222a3636..1a18e61aa 100644 --- a/src/columns/ColParent.cpp +++ b/src/columns/ColParent.cpp @@ -45,13 +45,10 @@ ColumnParent::ColumnParent () void ColumnParent::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) { if (_style == "default" || _style == "long") minimum = maximum = 36; else if (_style == "short") minimum = maximum = 8; - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } } diff --git a/src/columns/ColProject.cpp b/src/columns/ColProject.cpp index aab4167a7..85e48cc7b 100644 --- a/src/columns/ColProject.cpp +++ b/src/columns/ColProject.cpp @@ -59,7 +59,6 @@ ColumnProject::ColumnProject () void ColumnProject::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) { std::string project = task.get (_name); @@ -74,10 +73,6 @@ void ColumnProject::measure (Task& task, unsigned int& minimum, unsigned int& ma { project = indentProject (project, " ", '.'); } - else if (_style != "default" && - _style != "full" && - _style != "indented") - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); minimum = longestWord (project); maximum = utf8_width (project); diff --git a/src/columns/ColString.cpp b/src/columns/ColRType.cpp similarity index 53% rename from src/columns/ColString.cpp rename to src/columns/ColRType.cpp index fca7a57d4..475cada94 100644 --- a/src/columns/ColString.cpp +++ b/src/columns/ColRType.cpp @@ -25,92 +25,77 @@ //////////////////////////////////////////////////////////////////////////////// #include -#include +#include #include -#include #include -#include +#include #include +#include extern Context context; //////////////////////////////////////////////////////////////////////////////// -ColumnString::ColumnString () +ColumnRType::ColumnRType () { - _name = "string"; - _type = "string"; - _style = "left"; - _label = ""; - _styles = {"left", - "right", - "left_fixed", - "right_fixed"}; - _examples = {"Hello (wrapped) ", - " Hello (wrapped)", - "Hello (no-wrap) ", - " Hello (no-wrap)"}; - _hyphenate = context.config.getBoolean ("hyphenate"); + _name = "rtype"; + _style = "default"; + _label = STRING_COLUMN_LABEL_RTYPE; + _modifiable = false; + _styles = {"default", "indicator"}; + _examples = {"periodic", "chained"}; } //////////////////////////////////////////////////////////////////////////////// -// ColumnString is unique - it copies the report name into the label. This is -// a kludgy reuse of an otherwise unused member. -void ColumnString::setReport (const std::string& value) +// Overriden so that style <----> label are linked. +// Note that you can not determine which gets called first. +void ColumnRType::setStyle (const std::string& value) { - _report = _label = value; + Column::setStyle (value); + + if (_style == "indicator" && _label == STRING_COLUMN_LABEL_RTYPE) + _label = _label.substr (0, context.config.get ("rtype.indicator").length ()); } //////////////////////////////////////////////////////////////////////////////// // Set the minimum and maximum widths for the value. -// -void ColumnString::measure (const std::string& value, unsigned int& minimum, unsigned int& maximum) +void ColumnRType::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - - if (_style == "left" || - _style == "right" || - _style == "default") + if (task.has (_name)) { - std::string stripped = Color::strip (value); - maximum = longestLine (stripped); - minimum = longestWord (stripped); + if (_style == "default") + minimum = maximum = task.get (_name).length (); + else if (_style == "indicator") + minimum = maximum = 1; } - else if (_style == "left_fixed" || - _style == "right_fixed") - minimum = maximum = strippedLength (value); - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } //////////////////////////////////////////////////////////////////////////////// -void ColumnString::render ( +void ColumnRType::render ( std::vector & lines, - const std::string& value, + Task& task, int width, Color& color) { - if (_style == "default" || _style == "left") + if (task.has (_name)) { - std::vector raw; - wrapText (raw, value, width, _hyphenate); + if (_style == "default") + renderStringRight (lines, width, color, task.get (_name)); - for (auto& i : raw) - renderStringLeft (lines, width, color, i); + else if (_style == "indicator") + { + std::string value {" "}; + value[0] = toupper (task.get (_name)[0]); + renderStringRight (lines, width, color, value); + } } - else if (_style == "right") - { - std::vector raw; - wrapText (raw, value, width, _hyphenate); - - for (auto& i : raw) - renderStringRight (lines, width, color, i); - } - - else if (_style == "left_fixed") - renderStringLeft (lines, width, color, value); - - else if (_style == "right_fixed") - renderStringRight (lines, width, color, value); +} + +//////////////////////////////////////////////////////////////////////////////// +bool ColumnRType::validate (const std::string& input) const +{ + return input == "periodic" || + input == "chained"; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColRType.h b/src/columns/ColRType.h new file mode 100644 index 000000000..e082da304 --- /dev/null +++ b/src/columns/ColRType.h @@ -0,0 +1,45 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2006 - 2016, Paul Beckingham, Federico Hernandez. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// http://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_COLRTYPE +#define INCLUDED_COLRTYPE + +#include + +class ColumnRType : public ColumnTypeString +{ +public: + ColumnRType (); + void setStyle (const std::string&); + void measure (Task&, unsigned int&, unsigned int&); + void render (std::vector &, Task&, int, Color&); + bool validate (const std::string&) const; + +private: +}; + +#endif +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColRecur.cpp b/src/columns/ColRecur.cpp index 49f34fa69..c6ba5cecf 100644 --- a/src/columns/ColRecur.cpp +++ b/src/columns/ColRecur.cpp @@ -44,11 +44,12 @@ extern Task& contextTask; //////////////////////////////////////////////////////////////////////////////// ColumnRecur::ColumnRecur () { - _name = "recur"; - _style = "duration"; - _label = STRING_COLUMN_LABEL_RECUR; - _styles = {"duration", "indicator"}; - _examples = {"weekly", context.config.get ("recurrence.indicator")}; + _name = "recur"; + _style = "duration"; + _label = STRING_COLUMN_LABEL_RECUR; + _modifiable = true; + _styles = {"duration", "indicator"}; + _examples = {"weekly", context.config.get ("recurrence.indicator")}; } //////////////////////////////////////////////////////////////////////////////// @@ -56,7 +57,7 @@ ColumnRecur::ColumnRecur () // Note that you can not determine which gets called first. void ColumnRecur::setStyle (const std::string& value) { - _style = value; + Column::setStyle (value); if (_style == "indicator" && _label == STRING_COLUMN_LABEL_RECUR) _label = _label.substr (0, context.config.get ("recurrence.indicator").length ()); @@ -67,23 +68,17 @@ void ColumnRecur::setStyle (const std::string& value) void ColumnRecur::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) { if (_style == "default" || _style == "duration") { - minimum = maximum = Duration (task.get ("recur")).formatISO ().length (); + minimum = maximum = Duration (task.get (_name)).formatISO ().length (); } else if (_style == "indicator") { - if (task.has ("recur")) - minimum = maximum = utf8_width (context.config.get ("recurrence.indicator")); - else - minimum = maximum = 0; + minimum = maximum = utf8_width (context.config.get ("recurrence.indicator")); } - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } } @@ -98,7 +93,7 @@ void ColumnRecur::render ( { if (_style == "default" || _style == "duration") - renderStringRight (lines, width, color, Duration (task.get ("recur")).formatISO ()); + renderStringRight (lines, width, color, Duration (task.get (_name)).formatISO ()); else if (_style == "indicator") renderStringRight (lines, width, color, context.config.get ("recurrence.indicator")); diff --git a/src/columns/ColScheduled.cpp b/src/columns/ColScheduled.cpp index 72970dec2..f7e726cc1 100644 --- a/src/columns/ColScheduled.cpp +++ b/src/columns/ColScheduled.cpp @@ -31,8 +31,8 @@ //////////////////////////////////////////////////////////////////////////////// ColumnScheduled::ColumnScheduled () { - _name = "scheduled"; - _label = STRING_COLUMN_LABEL_SCHED; + _name = "scheduled"; + _label = STRING_COLUMN_LABEL_SCHED; } //////////////////////////////////////////////////////////////////////////////// @@ -40,9 +40,9 @@ ColumnScheduled::ColumnScheduled () // Note that you can not determine which gets called first. void ColumnScheduled::setStyle (const std::string& value) { - _style = value; + Column::setStyle (value); - if (_style == "countdown" && _label == STRING_COLUMN_LABEL_DUE) + if (_style == "countdown" && _label == STRING_COLUMN_LABEL_SCHED) _label = STRING_COLUMN_LABEL_COUNT; } diff --git a/src/columns/ColStart.cpp b/src/columns/ColStart.cpp index 704a881d3..86929da46 100644 --- a/src/columns/ColStart.cpp +++ b/src/columns/ColStart.cpp @@ -47,7 +47,7 @@ ColumnStart::ColumnStart () // Note that you can not determine which gets called first. void ColumnStart::setStyle (const std::string& value) { - _style = value; + Column::setStyle (value); if (_style == "active" && _label == STRING_COLUMN_LABEL_STARTED) _label = STRING_COLUMN_LABEL_ACTIVE; @@ -58,18 +58,14 @@ void ColumnStart::setStyle (const std::string& value) void ColumnStart::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) { if (_style == "active") - { - if (task.has ("start")) - minimum = maximum = utf8_width (context.config.get ("active.indicator")); - else - minimum = maximum = 0; - } + minimum = maximum = utf8_width (context.config.get ("active.indicator")); else ColumnTypeDate::measure (task, minimum, maximum); + + // TODO Throw on bad format. } } diff --git a/src/columns/ColStatus.cpp b/src/columns/ColStatus.cpp index b06903648..9b41ac303 100644 --- a/src/columns/ColStatus.cpp +++ b/src/columns/ColStatus.cpp @@ -46,7 +46,7 @@ ColumnStatus::ColumnStatus () // Note that you can not determine which gets called first. void ColumnStatus::setStyle (const std::string& value) { - _style = value; + Column::setStyle (value); if (_style == "short" && _label == STRING_COLUMN_LABEL_STATUS) _label = STRING_COLUMN_LABEL_STAT; @@ -74,8 +74,6 @@ void ColumnStatus::measure (Task& task, unsigned int& minimum, unsigned int& max } else if (_style == "short") minimum = maximum = 1; - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColTags.cpp b/src/columns/ColTags.cpp index 546753077..24fa4b718 100644 --- a/src/columns/ColTags.cpp +++ b/src/columns/ColTags.cpp @@ -59,7 +59,7 @@ ColumnTags::ColumnTags () // Note that you can not determine which gets called first. void ColumnTags::setStyle (const std::string& value) { - _style = value; + Column::setStyle (value); if (_style == "indicator" && _label == STRING_COLUMN_LABEL_TAGS) @@ -75,15 +75,11 @@ void ColumnTags::setStyle (const std::string& value) void ColumnTags::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) { if (_style == "indicator") { - if (task.has ("tags")) - minimum = maximum = utf8_width (context.config.get ("tag.indicator")); - else - minimum = maximum = 0; + minimum = maximum = utf8_width (context.config.get ("tag.indicator")); } else if (_style == "count") { @@ -112,8 +108,6 @@ void ColumnTags::measure (Task& task, unsigned int& minimum, unsigned int& maxim else minimum = maximum = utf8_width (tags); } - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } } @@ -163,7 +157,7 @@ void ColumnTags::modify (Task& task, const std::string& value) std::string label = " MODIFICATION "; // TW-1701 - task.set ("tags", ""); + task.set (_name, ""); for (auto& tag : split (value, ',')) { diff --git a/src/columns/ColTemplate.cpp b/src/columns/ColTemplate.cpp new file mode 100644 index 000000000..f25e8660b --- /dev/null +++ b/src/columns/ColTemplate.cpp @@ -0,0 +1,75 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2006 - 2016, Paul Beckingham, Federico Hernandez. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// http://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////// +ColumnTemplate::ColumnTemplate () +{ + _name = "template"; + _style = "long"; + _label = STRING_COLUMN_LABEL_TEMPLATE; + _modifiable = false; + _styles = {"long", "short"}; + _examples = {"f30cb9c3-3fc0-483f-bfb2-3bf134f00694", "f30cb9c3"}; +} + +//////////////////////////////////////////////////////////////////////////////// +// Set the minimum and maximum widths for the value. +void ColumnTemplate::measure (Task& task, unsigned int& minimum, unsigned int& maximum) +{ + minimum = maximum = 0; + if (task.has (_name)) + { + if (_style == "default" || _style == "long") minimum = maximum = 36; + else if (_style == "short") minimum = maximum = 8; + } +} + +//////////////////////////////////////////////////////////////////////////////// +void ColumnTemplate::render ( + std::vector & lines, + Task& task, + int width, + Color& color) +{ + if (task.has (_name)) + { + // f30cb9c3-3fc0-483f-bfb2-3bf134f00694 default + // f30cb9c3 short + if (_style == "default" || + _style == "long") + renderStringLeft (lines, width, color, task.get(_name)); + + else if (_style == "short") + renderStringLeft (lines, width, color, task.get (_name).substr (0, 8)); + } +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColTemplate.h b/src/columns/ColTemplate.h new file mode 100644 index 000000000..956b3ce2d --- /dev/null +++ b/src/columns/ColTemplate.h @@ -0,0 +1,43 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2006 - 2016, Paul Beckingham, Federico Hernandez. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// http://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_COLTEMPLATE +#define INCLUDED_COLTEMPLATE + +#include + +class ColumnTemplate : public ColumnTypeString +{ +public: + ColumnTemplate (); + void measure (Task&, unsigned int&, unsigned int&); + void render (std::vector &, Task&, int, Color&); + +private: +}; + +#endif +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColTypeDate.cpp b/src/columns/ColTypeDate.cpp index 8aab66b62..7524ff68c 100644 --- a/src/columns/ColTypeDate.cpp +++ b/src/columns/ColTypeDate.cpp @@ -72,7 +72,6 @@ ColumnTypeDate::ColumnTypeDate () void ColumnTypeDate::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) { Datetime date (task.get_date (_name)); @@ -131,8 +130,6 @@ void ColumnTypeDate::measure (Task& task, unsigned int& minimum, unsigned int& m if (date > now) minimum = maximum = Duration (date - now).formatVague ().length (); } - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } } @@ -204,6 +201,12 @@ void ColumnTypeDate::render ( } } +//////////////////////////////////////////////////////////////////////////////// +bool ColumnTypeDate::validate (const std::string& input) const +{ + return input.length () ? true : false; +} + //////////////////////////////////////////////////////////////////////////////// void ColumnTypeDate::modify (Task& task, const std::string& value) { diff --git a/src/columns/ColTypeDate.h b/src/columns/ColTypeDate.h index 4b9b8bed5..7480fcac5 100644 --- a/src/columns/ColTypeDate.h +++ b/src/columns/ColTypeDate.h @@ -39,6 +39,7 @@ public: ColumnTypeDate (); virtual void measure (Task&, unsigned int&, unsigned int&); virtual void render (std::vector &, Task&, int, Color&); + virtual bool validate (const std::string&) const; virtual void modify (Task&, const std::string&); }; diff --git a/src/columns/ColTypeDuration.cpp b/src/columns/ColTypeDuration.cpp index 357641bd5..973d69361 100644 --- a/src/columns/ColTypeDuration.cpp +++ b/src/columns/ColTypeDuration.cpp @@ -43,6 +43,12 @@ ColumnTypeDuration::ColumnTypeDuration () _type = "duration"; } +//////////////////////////////////////////////////////////////////////////////// +bool ColumnTypeDuration::validate (const std::string& input) const +{ + return input.length () ? true : false; +} + //////////////////////////////////////////////////////////////////////////////// void ColumnTypeDuration::modify (Task& task, const std::string& value) { diff --git a/src/columns/ColTypeDuration.h b/src/columns/ColTypeDuration.h index 9a38b796b..f1f81a131 100644 --- a/src/columns/ColTypeDuration.h +++ b/src/columns/ColTypeDuration.h @@ -35,6 +35,7 @@ class ColumnTypeDuration : public Column { public: ColumnTypeDuration (); + virtual bool validate (const std::string&) const; virtual void modify (Task&, const std::string&); }; diff --git a/src/columns/ColTypeNumeric.cpp b/src/columns/ColTypeNumeric.cpp index 725fbe8b9..a79083780 100644 --- a/src/columns/ColTypeNumeric.cpp +++ b/src/columns/ColTypeNumeric.cpp @@ -43,6 +43,12 @@ ColumnTypeNumeric::ColumnTypeNumeric () _type = "numeric"; } +//////////////////////////////////////////////////////////////////////////////// +bool ColumnTypeNumeric::validate (const std::string& input) const +{ + return input.length () ? true : false; +} + //////////////////////////////////////////////////////////////////////////////// void ColumnTypeNumeric::modify (Task& task, const std::string& value) { diff --git a/src/columns/ColTypeNumeric.h b/src/columns/ColTypeNumeric.h index 1da8f0b83..52e1b5de2 100644 --- a/src/columns/ColTypeNumeric.h +++ b/src/columns/ColTypeNumeric.h @@ -35,6 +35,7 @@ class ColumnTypeNumeric : public Column { public: ColumnTypeNumeric (); + virtual bool validate (const std::string&) const; virtual void modify (Task&, const std::string&); }; diff --git a/src/columns/ColTypeString.cpp b/src/columns/ColTypeString.cpp index 18d3f67d1..cee564589 100644 --- a/src/columns/ColTypeString.cpp +++ b/src/columns/ColTypeString.cpp @@ -43,6 +43,12 @@ ColumnTypeString::ColumnTypeString () _type = "string"; } +//////////////////////////////////////////////////////////////////////////////// +bool ColumnTypeString::validate (const std::string& input) const +{ + return input.length () ? true : false; +} + //////////////////////////////////////////////////////////////////////////////// void ColumnTypeString::modify (Task& task, const std::string& value) { diff --git a/src/columns/ColTypeString.h b/src/columns/ColTypeString.h index 0f6d22164..8bc0c490d 100644 --- a/src/columns/ColTypeString.h +++ b/src/columns/ColTypeString.h @@ -35,6 +35,7 @@ class ColumnTypeString : public Column { public: ColumnTypeString (); + virtual bool validate (const std::string&) const; virtual void modify (Task&, const std::string&); }; diff --git a/src/columns/ColUDA.cpp b/src/columns/ColUDA.cpp index 88d895fe3..95175ba68 100644 --- a/src/columns/ColUDA.cpp +++ b/src/columns/ColUDA.cpp @@ -40,12 +40,13 @@ extern Context context; //////////////////////////////////////////////////////////////////////////////// ColumnUDAString::ColumnUDAString () { - _name = ""; - _style = "default"; - _label = ""; - _uda = true; - _hyphenate = true; - _styles = {_style, "indicator"}; + _name = ""; // Gets overwritten at runtime. + _style = "default"; + _label = ""; + _modifiable = true; + _uda = true; + _hyphenate = true; + _styles = {_style, "indicator"}; } //////////////////////////////////////////////////////////////////////////////// @@ -70,7 +71,6 @@ bool ColumnUDAString::validate (const std::string& value) const void ColumnUDAString::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) { if (_style == "default") @@ -78,26 +78,19 @@ void ColumnUDAString::measure (Task& task, unsigned int& minimum, unsigned int& std::string value = task.get (_name); if (value != "") { - std::string stripped = Color::strip (value); + auto stripped = Color::strip (value); maximum = longestLine (stripped); minimum = longestWord (stripped); } } else if (_style == "indicator") { - if (task.has (_name)) - { - auto indicator = context.config.get ("uda." + _name + ".indicator"); - if (indicator == "") - indicator = "U"; + auto indicator = context.config.get ("uda." + _name + ".indicator"); + if (indicator == "") + indicator = "U"; - minimum = maximum = utf8_width (indicator); - } - else - minimum = maximum = 0; + minimum = maximum = utf8_width (indicator); } - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } } @@ -121,14 +114,11 @@ void ColumnUDAString::render ( } else if (_style == "indicator") { - if (task.has (_name)) - { - auto indicator = context.config.get ("uda." + _name + ".indicator"); - if (indicator == "") - indicator = "U"; + auto indicator = context.config.get ("uda." + _name + ".indicator"); + if (indicator == "") + indicator = "U"; - renderStringRight (lines, width, color, indicator); - } + renderStringRight (lines, width, color, indicator); } } } @@ -166,30 +156,22 @@ bool ColumnUDANumeric::validate (const std::string& value) const void ColumnUDANumeric::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) { if (_style == "default") { - std::string value = task.get (_name); + auto value = task.get (_name); if (value != "") minimum = maximum = value.length (); } else if (_style == "indicator") { - if (task.has (_name)) - { - auto indicator = context.config.get ("uda." + _name + ".indicator"); - if (indicator == "") - indicator = "U"; + auto indicator = context.config.get ("uda." + _name + ".indicator"); + if (indicator == "") + indicator = "U"; - minimum = maximum = utf8_width (indicator); - } - else - minimum = maximum = 0; + minimum = maximum = utf8_width (indicator); } - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } } @@ -204,19 +186,16 @@ void ColumnUDANumeric::render ( { if (_style == "default") { - std::string value = task.get (_name); + auto value = task.get (_name); renderStringRight (lines, width, color, value); } else if (_style == "indicator") { - if (task.has (_name)) - { - auto indicator = context.config.get ("uda." + _name + ".indicator"); - if (indicator == "") - indicator = "U"; + auto indicator = context.config.get ("uda." + _name + ".indicator"); + if (indicator == "") + indicator = "U"; - renderStringRight (lines, width, color, indicator); - } + renderStringRight (lines, width, color, indicator); } } } @@ -254,12 +233,11 @@ bool ColumnUDADate::validate (const std::string& value) const void ColumnUDADate::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) { if (_style == "default") { - std::string value = task.get (_name); + auto value = task.get (_name); if (value != "") { // Determine the output date format, which uses a hierarchy of definitions. @@ -267,7 +245,7 @@ void ColumnUDADate::measure (Task& task, unsigned int& minimum, unsigned int& ma // rc.dateformat.report // rc.dateformat Datetime date ((time_t) strtol (value.c_str (), NULL, 10)); - std::string format = context.config.get ("report." + _report + ".dateformat"); + auto format = context.config.get ("report." + _report + ".dateformat"); if (format == "") format = context.config.get ("dateformat.report"); if (format == "") @@ -278,19 +256,12 @@ void ColumnUDADate::measure (Task& task, unsigned int& minimum, unsigned int& ma } else if (_style == "indicator") { - if (task.has (_name)) - { - auto indicator = context.config.get ("uda." + _name + ".indicator"); - if (indicator == "") - indicator = "U"; + auto indicator = context.config.get ("uda." + _name + ".indicator"); + if (indicator == "") + indicator = "U"; - minimum = maximum = utf8_width (indicator); - } - else - minimum = maximum = 0; + minimum = maximum = utf8_width (indicator); } - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } } @@ -305,13 +276,13 @@ void ColumnUDADate::render ( { if (_style == "default") { - std::string value = task.get (_name); + auto value = task.get (_name); // Determine the output date format, which uses a hierarchy of definitions. // rc.report..dateformat // rc.dateformat.report // rc.dateformat. - std::string format = context.config.get ("report." + _report + ".dateformat"); + auto format = context.config.get ("report." + _report + ".dateformat"); if (format == "") { format = context.config.get ("dateformat.report"); @@ -323,14 +294,11 @@ void ColumnUDADate::render ( } else if (_style == "indicator") { - if (task.has (_name)) - { - auto indicator = context.config.get ("uda." + _name + ".indicator"); - if (indicator == "") - indicator = "U"; + auto indicator = context.config.get ("uda." + _name + ".indicator"); + if (indicator == "") + indicator = "U"; - renderStringRight (lines, width, color, indicator); - } + renderStringRight (lines, width, color, indicator); } } } @@ -368,12 +336,11 @@ bool ColumnUDADuration::validate (const std::string& value) const void ColumnUDADuration::measure (Task& task, unsigned int& minimum, unsigned int& maximum) { minimum = maximum = 0; - if (task.has (_name)) { if (_style == "default") { - std::string value = task.get (_name); + auto value = task.get (_name); if (value != "") minimum = maximum = Duration (value).formatISO ().length (); } @@ -390,8 +357,6 @@ void ColumnUDADuration::measure (Task& task, unsigned int& minimum, unsigned int else minimum = maximum = 0; } - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } } @@ -406,19 +371,16 @@ void ColumnUDADuration::render ( { if (_style == "default") { - std::string value = task.get (_name); + auto value = task.get (_name); renderStringRight (lines, width, color, Duration (value).formatISO ()); } else if (_style == "indicator") { - if (task.has (_name)) - { - auto indicator = context.config.get ("uda." + _name + ".indicator"); - if (indicator == "") - indicator = "U"; + auto indicator = context.config.get ("uda." + _name + ".indicator"); + if (indicator == "") + indicator = "U"; - renderStringRight (lines, width, color, indicator); - } + renderStringRight (lines, width, color, indicator); } } } diff --git a/src/columns/ColUUID.cpp b/src/columns/ColUUID.cpp index 802ecb5fa..93fcec9d0 100644 --- a/src/columns/ColUUID.cpp +++ b/src/columns/ColUUID.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -45,10 +44,10 @@ ColumnUUID::ColumnUUID () // Set the minimum and maximum widths for the value. void ColumnUUID::measure (Task&, unsigned int& minimum, unsigned int& maximum) { + // Mandatory attribute, no need to check the value. + if (_style == "default" || _style == "long") minimum = maximum = 36; else if (_style == "short") minimum = maximum = 8; - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColUntil.cpp b/src/columns/ColUntil.cpp index 2eb094e14..f66ba288c 100644 --- a/src/columns/ColUntil.cpp +++ b/src/columns/ColUntil.cpp @@ -31,8 +31,8 @@ //////////////////////////////////////////////////////////////////////////////// ColumnUntil::ColumnUntil () { - _name = "until"; - _label = STRING_COLUMN_LABEL_UNTIL; + _name = "until"; + _label = STRING_COLUMN_LABEL_UNTIL; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColUrgency.cpp b/src/columns/ColUrgency.cpp index 8e6e0b0ca..16d7725a0 100644 --- a/src/columns/ColUrgency.cpp +++ b/src/columns/ColUrgency.cpp @@ -32,11 +32,12 @@ //////////////////////////////////////////////////////////////////////////////// ColumnUrgency::ColumnUrgency () { - _name = "urgency"; - _style = "real"; - _label = STRING_COLUMN_LABEL_URGENCY; - _styles = {"real", "integer"}; - _examples = {"4.6", "4"}; + _name = "urgency"; + _style = "real"; + _label = STRING_COLUMN_LABEL_URGENCY; + _modifiable = false; + _styles = {"real", "integer"}; + _examples = {"4.6", "4"}; } //////////////////////////////////////////////////////////////////////////////// @@ -48,9 +49,6 @@ void ColumnUrgency::measure (Task& task, unsigned int& minimum, unsigned int& ma else if (_style == "integer") minimum = maximum = format ((int)task.urgency ()).length (); - - else - throw format (STRING_COLUMN_BAD_FORMAT, _name, _style); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/ColWait.cpp b/src/columns/ColWait.cpp index 58a300e64..2275c1fc7 100644 --- a/src/columns/ColWait.cpp +++ b/src/columns/ColWait.cpp @@ -31,8 +31,8 @@ //////////////////////////////////////////////////////////////////////////////// ColumnWait::ColumnWait () { - _name = "wait"; - _label = STRING_COLUMN_LABEL_WAIT; + _name = "wait"; + _label = STRING_COLUMN_LABEL_WAIT; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/columns/Column.cpp b/src/columns/Column.cpp index 2f7dc834c..6437aa296 100644 --- a/src/columns/Column.cpp +++ b/src/columns/Column.cpp @@ -36,16 +36,18 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include -#include #include +#include #include #include #include @@ -87,23 +89,23 @@ Column* Column::factory (const std::string& name, const std::string& report) else if (column_name == "entry") c = new ColumnEntry (); else if (column_name == "id") c = new ColumnID (); else if (column_name == "imask") c = new ColumnIMask (); + else if (column_name == "last") c = new ColumnLast (); else if (column_name == "mask") c = new ColumnMask (); else if (column_name == "modified") c = new ColumnModified (); else if (column_name == "parent") c = new ColumnParent (); else if (column_name == "project") c = new ColumnProject (); else if (column_name == "recur") c = new ColumnRecur (); + else if (column_name == "rtype") c = new ColumnRType (); else if (column_name == "scheduled") c = new ColumnScheduled (); else if (column_name == "start") c = new ColumnStart (); else if (column_name == "status") c = new ColumnStatus (); else if (column_name == "tags") c = new ColumnTags (); + else if (column_name == "template") c = new ColumnTemplate (); else if (column_name == "until") c = new ColumnUntil (); else if (column_name == "urgency") c = new ColumnUrgency (); else if (column_name == "uuid") c = new ColumnUUID (); else if (column_name == "wait") c = new ColumnWait (); - // Special non-task column. - else if (column_name == "string") c = new ColumnString (); - // UDA. else if (context.config.has ("uda." + column_name + ".type")) c = Column::uda (column_name); @@ -129,15 +131,18 @@ void Column::factory (std::map & all) c = new ColumnEntry (); all[c->_name] = c; c = new ColumnID (); all[c->_name] = c; c = new ColumnIMask (); all[c->_name] = c; + c = new ColumnLast (); all[c->_name] = c; c = new ColumnMask (); all[c->_name] = c; c = new ColumnModified (); all[c->_name] = c; c = new ColumnParent (); all[c->_name] = c; c = new ColumnProject (); all[c->_name] = c; c = new ColumnRecur (); all[c->_name] = c; + c = new ColumnRType (); all[c->_name] = c; c = new ColumnScheduled (); all[c->_name] = c; c = new ColumnStart (); all[c->_name] = c; c = new ColumnStatus (); all[c->_name] = c; c = new ColumnTags (); all[c->_name] = c; + c = new ColumnTemplate (); all[c->_name] = c; c = new ColumnUntil (); all[c->_name] = c; c = new ColumnUrgency (); all[c->_name] = c; c = new ColumnUUID (); all[c->_name] = c; @@ -149,7 +154,7 @@ void Column::factory (std::map & all) //////////////////////////////////////////////////////////////////////////////// void Column::uda (std::map & all) { - // For each UDA, instantiate and initialize ColumnUDA(). + // For each UDA, instantiate and initialize ColumnUDA. std::set udas; for (const auto& i : context.config) @@ -283,12 +288,6 @@ void Column::setStyle (const std::string& style) _style = style; } -//////////////////////////////////////////////////////////////////////////////// -bool Column::validate (const std::string& input) const -{ - return input.length () ? true : false; -} - //////////////////////////////////////////////////////////////////////////////// // All integer values are right-justified. void Column::renderInteger ( diff --git a/src/columns/Column.h b/src/columns/Column.h index a5e2e0c00..9290d7a21 100644 --- a/src/columns/Column.h +++ b/src/columns/Column.h @@ -57,12 +57,12 @@ public: virtual void setLabel (const std::string& value) { _label = value; } virtual void setReport (const std::string& value) { _report = value; } - virtual bool validate (const std::string&) const; virtual void measure (const std::string&, unsigned int&, unsigned int&) {}; virtual void measure (Task&, unsigned int&, unsigned int&) {}; virtual void renderHeader (std::vector &, int, Color&); virtual void render (std::vector &, const std::string&, int, Color&) {}; virtual void render (std::vector &, Task&, int, Color&) {}; + virtual bool validate (const std::string&) const {return false;}; virtual void modify (Task&, const std::string&) {}; protected: diff --git a/src/commands/CmdCommands.cpp b/src/commands/CmdCommands.cpp index fab451b98..36f79ac19 100644 --- a/src/commands/CmdCommands.cpp +++ b/src/commands/CmdCommands.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/src/commands/CmdDenotate.cpp b/src/commands/CmdDenotate.cpp index d77b2ecec..6e679d38c 100644 --- a/src/commands/CmdDenotate.cpp +++ b/src/commands/CmdDenotate.cpp @@ -90,8 +90,7 @@ int CmdDenotate::execute (std::string&) { Task before (task); - std::map annotations; - task.getAnnotations (annotations); + auto annotations = task.getAnnotations (); if (annotations.size () == 0) throw std::string (STRING_CMD_DENO_NONE); diff --git a/src/commands/CmdDiagnostics.cpp b/src/commands/CmdDiagnostics.cpp index 95bd58314..1fa5e6ca7 100644 --- a/src/commands/CmdDiagnostics.cpp +++ b/src/commands/CmdDiagnostics.cpp @@ -456,10 +456,7 @@ int CmdDiagnostics::execute (std::string& output) for (auto& task : all) { // Check dependencies - std::vector dependencies; - task.getDependencies(dependencies); - - for (auto& uuid : dependencies) + for (auto& uuid : task.getDependencyUUIDs ()) { if (! context.tdb2.has (uuid)) { diff --git a/src/commands/CmdEdit.cpp b/src/commands/CmdEdit.cpp index 52f3d0ed2..633f02962 100644 --- a/src/commands/CmdEdit.cpp +++ b/src/commands/CmdEdit.cpp @@ -224,14 +224,10 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) << "# iMask: " << task.get ("imask") << '\n' << " Project: " << task.get ("project") << '\n'; - std::vector tags; - task.getTags (tags); - auto allTags = join (" ", tags); - if (verbose) before << "# " << STRING_EDIT_TAG_SEP << '\n'; - before << " Tags: " << allTags << '\n' + before << " Tags: " << join (" ", task.getTags ()) << '\n' << " Description: " << task.get ("description") << '\n' << " Created: " << formatDate (task, "entry", dateformat) << '\n' << " Started: " << formatDate (task, "start", dateformat) << '\n' @@ -249,9 +245,7 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) << "# " << STRING_EDIT_HEADER_14 << '\n' << "# " << STRING_EDIT_HEADER_15 << '\n'; - std::map annotations; - task.getAnnotations (annotations); - for (auto& anno : annotations) + for (auto& anno : task.getAnnotations ()) { Datetime dt (strtol (anno.first.substr (11).c_str (), NULL, 10)); before << " Annotation: " << dt.toString (dateformat) @@ -262,8 +256,7 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) before << " Annotation: " << now.toString (dateformat) << " -- \n"; // Add dependencies here. - std::vector dependencies; - task.getDependencies (dependencies); + auto dependencies = task.getDependencyUUIDs (); std::stringstream allDeps; for (unsigned int i = 0; i < dependencies.size (); ++i) { @@ -312,9 +305,7 @@ std::string CmdEdit::formatTask (Task task, const std::string& dateformat) } // UDA orphans - std::vector orphans; - task.getUDAOrphans (orphans); - + auto orphans = task.getUDAOrphanUUIDs (); if (orphans.size ()) { before << "# " << STRING_EDIT_UDA_ORPHAN_SEP << '\n'; @@ -355,9 +346,8 @@ void CmdEdit::parseTask (Task& task, const std::string& after, const std::string // tags value = findValue (after, "\n Tags:"); - auto tags = split (value, ' '); task.remove ("tags"); - task.addTags (tags); + task.addTags (split (value, ' ')); // description. value = findMultilineValue (after, "\n Description:", "\n Created:"); diff --git a/src/commands/CmdInfo.cpp b/src/commands/CmdInfo.cpp index fdb6fd981..f1ead7494 100644 --- a/src/commands/CmdInfo.cpp +++ b/src/commands/CmdInfo.cpp @@ -134,9 +134,7 @@ int CmdInfo::execute (std::string& output) std::string description = task.get ("description"); int indent = context.config.getInteger ("indent.annotation"); - std::map annotations; - task.getAnnotations (annotations); - for (auto& anno : annotations) + for (auto& anno : task.getAnnotations ()) description += '\n' + std::string (indent, ' ') + Datetime (anno.first.substr (11)).toString (dateformatanno) @@ -162,8 +160,7 @@ int CmdInfo::execute (std::string& output) // dependencies: blocked { - std::vector blocked; - dependencyGetBlocking (task, blocked); + auto blocked = dependencyGetBlocking (task); if (blocked.size ()) { std::stringstream message; @@ -178,8 +175,7 @@ int CmdInfo::execute (std::string& output) // dependencies: blocking { - std::vector blocking; - dependencyGetBlocked (task, blocking); + auto blocking = dependencyGetBlocked (task); if (blocking.size ()) { std::stringstream message; @@ -201,6 +197,7 @@ int CmdInfo::execute (std::string& output) } // parent + // 2017-01-07: Deprecated in 2.6.0 if (task.has ("parent")) { row = view.addRow (); @@ -209,6 +206,7 @@ int CmdInfo::execute (std::string& output) } // mask + // 2017-01-07: Deprecated in 2.6.0 if (task.has ("mask")) { row = view.addRow (); @@ -217,6 +215,7 @@ int CmdInfo::execute (std::string& output) } // imask + // 2017-01-07: Deprecated in 2.6.0 if (task.has ("imask")) { row = view.addRow (); @@ -224,6 +223,30 @@ int CmdInfo::execute (std::string& output) view.set (row, 1, task.get ("imask")); } + // template + if (task.has ("template")) + { + row = view.addRow (); + view.set (row, 0, STRING_COLUMN_LABEL_TEMPLATE); + view.set (row, 1, task.get ("template")); + } + + // last + if (task.has ("last")) + { + row = view.addRow (); + view.set (row, 0, STRING_COLUMN_LABEL_LAST); + view.set (row, 1, task.get ("last")); + } + + // rtype + if (task.has ("rtype")) + { + row = view.addRow (); + view.set (row, 0, STRING_COLUMN_LABEL_RTYPE); + view.set (row, 1, task.get ("rtype")); + } + // entry row = view.addRow (); view.set (row, 0, STRING_COLUMN_LABEL_ENTERED); @@ -300,8 +323,7 @@ int CmdInfo::execute (std::string& output) } // tags ... - std::vector tags; - task.getTags (tags); + auto tags = task.getTags (); if (tags.size ()) { auto allTags = join (" ", tags); @@ -320,19 +342,21 @@ int CmdInfo::execute (std::string& output) if (task.hasTag ("ANNOTATED")) virtualTags += "ANNOTATED "; if (task.hasTag ("BLOCKED")) virtualTags += "BLOCKED "; if (task.hasTag ("BLOCKING")) virtualTags += "BLOCKING "; - if (task.hasTag ("CHILD")) virtualTags += "CHILD "; + if (task.hasTag ("CHILD")) virtualTags += "CHILD "; // 2017-01-07: Deprecated in 2.6.0 if (task.hasTag ("COMPLETED")) virtualTags += "COMPLETED "; if (task.hasTag ("DELETED")) virtualTags += "DELETED "; if (task.hasTag ("DUE")) virtualTags += "DUE "; if (task.hasTag ("DUETODAY")) virtualTags += "DUETODAY "; + if (task.hasTag ("INSTANCE")) virtualTags += "INSTANCE "; if (task.hasTag ("MONTH")) virtualTags += "MONTH "; if (task.hasTag ("ORPHAN")) virtualTags += "ORPHAN "; if (task.hasTag ("OVERDUE")) virtualTags += "OVERDUE "; - if (task.hasTag ("PARENT")) virtualTags += "PARENT "; + if (task.hasTag ("PARENT")) virtualTags += "PARENT "; // 2017-01-07: Deprecated in 2.6.0 if (task.hasTag ("PENDING")) virtualTags += "PENDING "; if (task.hasTag ("READY")) virtualTags += "READY "; if (task.hasTag ("SCHEDULED")) virtualTags += "SCHEDULED "; if (task.hasTag ("TAGGED")) virtualTags += "TAGGED "; + if (task.hasTag ("TEMPLATE")) virtualTags += "TEMPLATE "; if (task.hasTag ("TODAY")) virtualTags += "TODAY "; if (task.hasTag ("TOMORROW")) virtualTags += "TOMORROW "; if (task.hasTag ("UDA")) virtualTags += "UDA "; diff --git a/src/commands/CmdStats.cpp b/src/commands/CmdStats.cpp index 599c83960..e4aea4ca0 100644 --- a/src/commands/CmdStats.cpp +++ b/src/commands/CmdStats.cpp @@ -140,13 +140,9 @@ int CmdStats::execute (std::string& output) daysPending += (now.toEpoch () - entry) / 86400.0; descLength += task.get ("description").length (); + annotationsT += task.getAnnotations ().size (); - std::map annotations; - task.getAnnotations (annotations); - annotationsT += annotations.size (); - - std::vector tags; - task.getTags (tags); + auto tags = task.getTags (); if (tags.size ()) ++taggedT; diff --git a/src/commands/CmdTags.cpp b/src/commands/CmdTags.cpp index c50d201c9..eb7bbaabc 100644 --- a/src/commands/CmdTags.cpp +++ b/src/commands/CmdTags.cpp @@ -79,10 +79,7 @@ int CmdTags::execute (std::string& output) std::map unique; for (auto& task : filtered) { - std::vector tags; - task.getTags (tags); - - for (auto& tag : tags) + for (auto& tag : task.getTags ()) if (unique.find (tag) != unique.end ()) unique[tag]++; else @@ -182,13 +179,8 @@ int CmdCompletionTags::execute (std::string& output) // names as keys. std::map unique; for (auto& task : filtered) - { - std::vector tags; - task.getTags (tags); - - for (auto& tag : tags) + for (auto& tag : task.getTags ()) unique[tag] = 0; - } // Add built-in tags to map. unique["nocolor"] = 0; @@ -199,19 +191,21 @@ int CmdCompletionTags::execute (std::string& output) unique["ANNOTATED"] = 0; unique["BLOCKED"] = 0; unique["BLOCKING"] = 0; - unique["CHILD"] = 0; + unique["CHILD"] = 0; // 2017-01-07: Deprecated in 2.6.0 unique["COMPLETED"] = 0; unique["DELETED"] = 0; unique["DUE"] = 0; unique["DUETODAY"] = 0; + unique["INSTANCE"] = 0; unique["MONTH"] = 0; unique["ORPHAN"] = 0; unique["OVERDUE"] = 0; - unique["PARENT"] = 0; + unique["PARENT"] = 0; // 2017-01-07: Deprecated in 2.6.0 unique["PENDING"] = 0; unique["READY"] = 0; unique["SCHEDULED"] = 0; unique["TAGGED"] = 0; + unique["TEMPLATE"] = 0; unique["TODAY"] = 0; unique["TOMORROW"] = 0; unique["UDA"] = 0; diff --git a/src/commands/CmdTimesheet.cpp b/src/commands/CmdTimesheet.cpp index d1493ed93..4f26ed506 100644 --- a/src/commands/CmdTimesheet.cpp +++ b/src/commands/CmdTimesheet.cpp @@ -142,9 +142,7 @@ int CmdTimesheet::execute (std::string& output) std::string description = task.get ("description"); int indent = context.config.getInteger ("indent.annotation"); - std::map annotations; - task.getAnnotations (annotations); - for (auto& ann : annotations) + for (auto& ann : task.getAnnotations ()) description += '\n' + std::string (indent, ' ') + Datetime (ann.first.substr (11)).toString (context.config.get ("dateformat")) @@ -198,9 +196,7 @@ int CmdTimesheet::execute (std::string& output) std::string description = task.get ("description"); int indent = context.config.getInteger ("indent.annotation"); - std::map annotations; - task.getAnnotations (annotations); - for (auto& ann : annotations) + for (auto& ann : task.getAnnotations ()) description += '\n' + std::string (indent, ' ') + Datetime (ann.first.substr (11)).toString (context.config.get ("dateformat")) diff --git a/src/dependency.cpp b/src/dependency.cpp index 534db4eb1..0323d1d75 100644 --- a/src/dependency.cpp +++ b/src/dependency.cpp @@ -38,29 +38,35 @@ extern Context context; //////////////////////////////////////////////////////////////////////////////// -void dependencyGetBlocked (const Task& task, std::vector & blocked) +std::vector dependencyGetBlocked (const Task& task) { std::string uuid = task.get ("uuid"); - auto all = context.tdb2.pending.get_tasks (); - for (auto& it : all) + std::vector blocked; + for (auto& it : context.tdb2.pending.get_tasks ()) if (it.getStatus () != Task::completed && it.getStatus () != Task::deleted && it.has ("depends") && it.get ("depends").find (uuid) != std::string::npos) blocked.push_back (it); + + return blocked; } //////////////////////////////////////////////////////////////////////////////// -void dependencyGetBlocking (const Task& task, std::vector & blocking) +std::vector dependencyGetBlocking (const Task& task) { std::string depends = task.get ("depends"); + std::vector blocking; + if (depends != "") for (auto& it : context.tdb2.pending.get_tasks ()) if (it.getStatus () != Task::completed && it.getStatus () != Task::deleted && depends.find (it.get ("uuid")) != std::string::npos) blocking.push_back (it); + + return blocking; } //////////////////////////////////////////////////////////////////////////////// @@ -82,8 +88,7 @@ bool dependencyIsCircular (const Task& task) while (! s.empty ()) { Task& current = s.top (); - std::vector deps_current; - current.getDependencies (deps_current); + auto deps_current = current.getDependencyUUIDs (); // This is a basic depth first search that always terminates given the // fact that we do not visit any task twice @@ -146,14 +151,12 @@ bool dependencyIsCircular (const Task& task) // void dependencyChainOnComplete (Task& task) { - std::vector blocking; - dependencyGetBlocking (task, blocking); + auto blocking = dependencyGetBlocking (task); // If the task is anything but the tail end of a dependency chain. if (blocking.size ()) { - std::vector blocked; - dependencyGetBlocked (task, blocked); + auto blocked = dependencyGetBlocked (task); // Nag about broken chain. if (context.config.getBoolean ("dependency.reminder")) @@ -206,8 +209,7 @@ void dependencyChainOnStart (Task& task) { if (context.config.getBoolean ("dependency.reminder")) { - std::vector blocking; - dependencyGetBlocking (task, blocking); + auto blocking = dependencyGetBlocking (task); // If the task is anything but the tail end of a dependency chain, nag about // broken chain. diff --git a/src/feedback.cpp b/src/feedback.cpp index d521bfe1d..69029c754 100644 --- a/src/feedback.cpp +++ b/src/feedback.cpp @@ -84,8 +84,7 @@ std::string taskDifferences (const Task& before, const Task& after) { if (name == "depends") { - std::vector deps_after; - after.getDependencies (deps_after); + auto deps_after = after.getDependencyTasks (); out << " - " << format (STRING_FEEDBACK_DEP_SET, taskIdentifiers (deps_after)) @@ -110,12 +109,10 @@ std::string taskDifferences (const Task& before, const Task& after) { if (name == "depends") { - std::vector deps_before; - before.getDependencies (deps_before); + auto deps_before = before.getDependencyTasks (); std::string from = taskIdentifiers (deps_before); - std::vector deps_after; - after.getDependencies (deps_after); + auto deps_after = after.getDependencyTasks (); std::string to = taskIdentifiers (deps_after); out << " - " @@ -169,11 +166,7 @@ std::string taskInfoDifferences ( { if (name == "depends") { - std::vector deps_before; - before.getDependencies (deps_before); - std::string from = taskIdentifiers (deps_before); - - out << format (STRING_FEEDBACK_DEP_DEL, from) + out << format (STRING_FEEDBACK_DEP_DEL, taskIdentifiers (before.getDependencyTasks ())) << "\n"; } else if (name.substr (0, 11) == "annotation_") @@ -198,11 +191,7 @@ std::string taskInfoDifferences ( { if (name == "depends") { - std::vector deps_after; - after.getDependencies (deps_after); - std::string to = taskIdentifiers (deps_after); - - out << format (STRING_FEEDBACK_DEP_WAS_SET, to) + out << format (STRING_FEEDBACK_DEP_WAS_SET, taskIdentifiers (after.getDependencyTasks ())) << "\n"; } else if (name.substr (0, 11) == "annotation_") @@ -231,13 +220,8 @@ std::string taskInfoDifferences ( { if (name == "depends") { - std::vector deps_before; - before.getDependencies (deps_before); - std::string from = taskIdentifiers (deps_before); - - std::vector deps_after; - after.getDependencies (deps_after); - std::string to = taskIdentifiers (deps_after); + auto from = taskIdentifiers (before.getDependencyTasks ()); + auto to = taskIdentifiers (after.getDependencyTasks ()); out << format (STRING_FEEDBACK_DEP_WAS_MOD, from, to) << "\n"; @@ -334,22 +318,24 @@ void feedback_reserved_tags (const std::string& tag) tag == "ANNOTATED" || tag == "BLOCKED" || tag == "BLOCKING" || - tag == "CHILD" || + tag == "CHILD" || // Deprecated 2.6.0 tag == "COMPLETED" || tag == "DELETED" || tag == "DUE" || tag == "DUETODAY" || + tag == "INSTANCE" || tag == "LATEST" || tag == "MONTH" || tag == "ORPHAN" || tag == "OVERDUE" || - tag == "PARENT" || + tag == "PARENT" || // Deprecated 2.6.0 tag == "PENDING" || tag == "PRIORITY" || tag == "PROJECT" || tag == "READY" || tag == "SCHEDULED" || tag == "TAGGED" || + tag == "TEMPLATE" || tag == "TODAY" || tag == "TOMORROW" || tag == "UDA" || @@ -397,14 +383,12 @@ void feedback_unblocked (const Task& task) if (context.verbose ("affected")) { // Get a list of tasks that depended on this task. - std::vector blocked; - dependencyGetBlocked (task, blocked); + auto blocked = dependencyGetBlocked (task); // Scan all the tasks that were blocked by this task for (auto& i : blocked) { - std::vector blocking; - dependencyGetBlocking (i, blocking); + auto blocking = dependencyGetBlocking (i); if (blocking.size () == 0) { if (i.id) diff --git a/src/l10n/check_translations.sh b/src/l10n/check_translations.sh new file mode 100755 index 000000000..2f4b59119 --- /dev/null +++ b/src/l10n/check_translations.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +REFERENCE_LANGUAGE_FILE="eng-USA.h" +TESTED_LANGUAGE_FILES=`ls *.h | grep -v $REFERENCE_LANGUAGE_FILE` + +# At the beginning, we haven't detected any invalid translation files +MISMATCHED=0 + +# Generate list of keys, not including defines that are commented out. Strips out the leading whitespace. +cat $REFERENCE_LANGUAGE_FILE | grep "^[[:space:]]*#define" | sed -e 's/^ *//' - | cut -f2 -d' ' | sort > identifiers + +# Generate report +for LANGUAGE_FILE in $TESTED_LANGUAGE_FILES +do + echo "Comparing $REFERENCE_LANGUAGE_FILE (left) to $LANGUAGE_FILE (right)" + cat $LANGUAGE_FILE | grep "^[[:space:]]*#define" | sed -e 's/^ *//' - | cut -f2 -d' ' | sort | diff identifiers - + MISMATCHED=$(($MISMATCHED+$?)) + echo "" +done + +# Cleanup +rm -f identifiers + +# Exit with number of not synced translations files +exit $MISMATCHED diff --git a/src/l10n/deu-DEU.h b/src/l10n/deu-DEU.h index b8e75f8d5..a9b9b08ac 100644 --- a/src/l10n/deu-DEU.h +++ b/src/l10n/deu-DEU.h @@ -210,7 +210,10 @@ #define STRING_COLUMN_LABEL_VALUE "Wert" #define STRING_COLUMN_LABEL_MASK "Maske" #define STRING_COLUMN_LABEL_MASK_IDX "Masken-Index" +#define STRING_COLUMN_LABEL_LAST "Last instance" +#define STRING_COLUMN_LABEL_RTYPE "Recurrence type" #define STRING_COLUMN_LABEL_PARENT "Vorgänger-Aufgabe" +#define STRING_COLUMN_LABEL_TEMPLATE "Template task" #define STRING_COLUMN_LABEL_DATE "Datum" #define STRING_COLUMN_LABEL_COLUMN "Spalten" #define STRING_COLUMN_LABEL_STYLES "Unterstützte Formate" diff --git a/src/l10n/eng-USA.h b/src/l10n/eng-USA.h index 63d30b473..b97d2af53 100644 --- a/src/l10n/eng-USA.h +++ b/src/l10n/eng-USA.h @@ -210,7 +210,10 @@ #define STRING_COLUMN_LABEL_VALUE "Value" #define STRING_COLUMN_LABEL_MASK "Mask" #define STRING_COLUMN_LABEL_MASK_IDX "Mask Index" +#define STRING_COLUMN_LABEL_LAST "Last instance" +#define STRING_COLUMN_LABEL_RTYPE "Recurrence type" #define STRING_COLUMN_LABEL_PARENT "Parent task" +#define STRING_COLUMN_LABEL_TEMPLATE "Template task" #define STRING_COLUMN_LABEL_DATE "Date" #define STRING_COLUMN_LABEL_COLUMN "Columns" #define STRING_COLUMN_LABEL_STYLES "Supported Formats" diff --git a/src/l10n/epo-RUS.h b/src/l10n/epo-RUS.h index ce3f41a18..bc042d318 100644 --- a/src/l10n/epo-RUS.h +++ b/src/l10n/epo-RUS.h @@ -210,7 +210,10 @@ #define STRING_COLUMN_LABEL_VALUE "Valoro" #define STRING_COLUMN_LABEL_MASK "Masko" #define STRING_COLUMN_LABEL_MASK_IDX "Mask-indico" +#define STRING_COLUMN_LABEL_LAST "Last instance" +#define STRING_COLUMN_LABEL_RTYPE "Recurrence type" #define STRING_COLUMN_LABEL_PARENT "Patra tasko" +#define STRING_COLUMN_LABEL_TEMPLATE "Template task" #define STRING_COLUMN_LABEL_DATE "Dato" #define STRING_COLUMN_LABEL_COLUMN "Kolumnoj" #define STRING_COLUMN_LABEL_STYLES "Formaĝoj Subtenataj" diff --git a/src/l10n/esp-ESP.h b/src/l10n/esp-ESP.h index 4ba8145ed..bec9c96a7 100644 --- a/src/l10n/esp-ESP.h +++ b/src/l10n/esp-ESP.h @@ -211,7 +211,10 @@ #define STRING_COLUMN_LABEL_VALUE "Valor" #define STRING_COLUMN_LABEL_MASK "Máscara" #define STRING_COLUMN_LABEL_MASK_IDX "Máscara de Índice" +#define STRING_COLUMN_LABEL_LAST "Last instance" +#define STRING_COLUMN_LABEL_RTYPE "Recurrence type" #define STRING_COLUMN_LABEL_PARENT "Tarea madre" +#define STRING_COLUMN_LABEL_TEMPLATE "Template task" #define STRING_COLUMN_LABEL_DATE "Fecha" #define STRING_COLUMN_LABEL_COLUMN "Columnas" #define STRING_COLUMN_LABEL_STYLES "Formatos soportados" diff --git a/src/l10n/fra-FRA.h b/src/l10n/fra-FRA.h index b83b57b90..a3b4f43ee 100644 --- a/src/l10n/fra-FRA.h +++ b/src/l10n/fra-FRA.h @@ -210,7 +210,10 @@ #define STRING_COLUMN_LABEL_VALUE "Valeur" #define STRING_COLUMN_LABEL_MASK "Masque" #define STRING_COLUMN_LABEL_MASK_IDX "Indice de masque" +#define STRING_COLUMN_LABEL_LAST "Last instance" +#define STRING_COLUMN_LABEL_RTYPE "Recurrence type" #define STRING_COLUMN_LABEL_PARENT "Tâche mère" +#define STRING_COLUMN_LABEL_TEMPLATE "Template task" #define STRING_COLUMN_LABEL_DATE "Date" #define STRING_COLUMN_LABEL_COLUMN "Colonnes" #define STRING_COLUMN_LABEL_STYLES "Formats supportés" diff --git a/src/l10n/ita-ITA.h b/src/l10n/ita-ITA.h index 324936f0d..287931916 100644 --- a/src/l10n/ita-ITA.h +++ b/src/l10n/ita-ITA.h @@ -210,7 +210,10 @@ #define STRING_COLUMN_LABEL_VALUE "Valore" #define STRING_COLUMN_LABEL_MASK "Maschera" #define STRING_COLUMN_LABEL_MASK_IDX "Indice Maschera" +#define STRING_COLUMN_LABEL_LAST "Last instance" +#define STRING_COLUMN_LABEL_RTYPE "Recurrence type" #define STRING_COLUMN_LABEL_PARENT "Task genitore" +#define STRING_COLUMN_LABEL_TEMPLATE "Template task" #define STRING_COLUMN_LABEL_DATE "Data" #define STRING_COLUMN_LABEL_COLUMN "Colonna" #define STRING_COLUMN_LABEL_STYLES "Formati Supportati" diff --git a/src/l10n/jpn-JPN.h b/src/l10n/jpn-JPN.h index 49b66d75c..4857322ae 100644 --- a/src/l10n/jpn-JPN.h +++ b/src/l10n/jpn-JPN.h @@ -210,7 +210,10 @@ #define STRING_COLUMN_LABEL_VALUE "Value" #define STRING_COLUMN_LABEL_MASK "Mask" #define STRING_COLUMN_LABEL_MASK_IDX "Mask Index" +#define STRING_COLUMN_LABEL_LAST "Last instance" +#define STRING_COLUMN_LABEL_RTYPE "Recurrence type" #define STRING_COLUMN_LABEL_PARENT "Parent task" +#define STRING_COLUMN_LABEL_TEMPLATE "Template task" #define STRING_COLUMN_LABEL_DATE "Date" #define STRING_COLUMN_LABEL_COLUMN "Columns" #define STRING_COLUMN_LABEL_STYLES "Supported Formats" diff --git a/src/l10n/pol-POL.h b/src/l10n/pol-POL.h index e78364ea4..b177b0ab9 100644 --- a/src/l10n/pol-POL.h +++ b/src/l10n/pol-POL.h @@ -210,7 +210,10 @@ #define STRING_COLUMN_LABEL_VALUE "Wartość" #define STRING_COLUMN_LABEL_MASK "Maska" #define STRING_COLUMN_LABEL_MASK_IDX "Indeks Maski" +#define STRING_COLUMN_LABEL_LAST "Last instance" +#define STRING_COLUMN_LABEL_RTYPE "Recurrence type" #define STRING_COLUMN_LABEL_PARENT "Zadanie rodzic" +#define STRING_COLUMN_LABEL_TEMPLATE "Template task" #define STRING_COLUMN_LABEL_DATE "Data" #define STRING_COLUMN_LABEL_COLUMN "Kolumny" #define STRING_COLUMN_LABEL_STYLES "Formaty" diff --git a/src/l10n/por-PRT.h b/src/l10n/por-PRT.h index 108b2b78a..909f59d2c 100644 --- a/src/l10n/por-PRT.h +++ b/src/l10n/por-PRT.h @@ -211,7 +211,10 @@ #define STRING_COLUMN_LABEL_VALUE "Valor" #define STRING_COLUMN_LABEL_MASK "Máscara" #define STRING_COLUMN_LABEL_MASK_IDX "Índice de Máscara" +#define STRING_COLUMN_LABEL_LAST "Last instance" +#define STRING_COLUMN_LABEL_RTYPE "Recurrence type" #define STRING_COLUMN_LABEL_PARENT "Tarefa mãe" +#define STRING_COLUMN_LABEL_TEMPLATE "Template task" #define STRING_COLUMN_LABEL_DATE "Data" #define STRING_COLUMN_LABEL_COLUMN "Colunas" #define STRING_COLUMN_LABEL_STYLES "Formatos Suportados" diff --git a/src/main.h b/src/main.h index d18c881a1..a48380814 100644 --- a/src/main.h +++ b/src/main.h @@ -52,8 +52,8 @@ std::string colorizeError (const std::string&); std::string colorizeDebug (const std::string&); // dependency.cpp -void dependencyGetBlocked (const Task&, std::vector &); -void dependencyGetBlocking (const Task&, std::vector &); +std::vector dependencyGetBlocked (const Task&); +std::vector dependencyGetBlocking (const Task&); bool dependencyIsCircular (const Task&); void dependencyChainOnComplete (Task&); void dependencyChainOnStart (Task&);