Merge branch 'recurrence' into 2.6.0

This commit is contained in:
Paul Beckingham 2017-01-07 12:29:11 -05:00
commit 4e7576cb79
65 changed files with 652 additions and 484 deletions

View file

@ -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

View file

@ -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 <Task> 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 <int> 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 <Task> blocking;
dependencyGetBlocking (task, blocking);
renderStringRight (lines, width, color, context.config.get ("dependency.indicator"));
}
if (_style == "count")
renderStringRight (lines, width, color, '[' + format (static_cast <int>(blocking.size ())) + ']');
else if (_style == "count")
{
renderStringRight (lines, width, color, '[' + format (static_cast <int>(dependencyGetBlocking (task).size ())) + ']');
}
else if (_style == "default" ||
_style == "list")
{
std::vector <int> 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 <int> blocking_ids;
for (const auto& t : blocking)
blocking_ids.push_back (t.id);
std::vector <std::string> all;
wrapText (all, combined, width, _hyphenate);
auto combined = join (" ", blocking_ids);
for (const auto& i : all)
renderStringLeft (lines, width, color, i);
}
std::vector <std::string> all;
wrapText (all, combined, width, _hyphenate);
for (const auto& i : all)
renderStringLeft (lines, width, color, i);
}
}
}

View file

@ -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 <std::string, std::string> 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 <std::string, std::string> 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 <std::string, std::string> 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 <std::string, std::string> 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;

View file

@ -31,8 +31,9 @@
////////////////////////////////////////////////////////////////////////////////
ColumnDue::ColumnDue ()
{
_name = "due";
_label = STRING_COLUMN_LABEL_DUE;
_name = "due";
_modifiable = true;
_label = STRING_COLUMN_LABEL_DUE;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -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)

View file

@ -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

View file

@ -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));
}
////////////////////////////////////////////////////////////////////////////////

63
src/columns/ColLast.cpp Normal file
View file

@ -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 <cmake.h>
#include <ColLast.h>
#include <format.h>
#include <i18n.h>
////////////////////////////////////////////////////////////////////////////////
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 <std::string>& lines,
Task& task,
int width,
Color& color)
{
if (task.has (_name))
renderStringRight (lines, width, color, task.get (_name));
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -24,25 +24,19 @@
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_COLSTRING
#define INCLUDED_COLSTRING
#ifndef INCLUDED_COLLAST
#define INCLUDED_COLLAST
#include <vector>
#include <string>
#include <Column.h>
#include <Color.h>
#include <Task.h>
#include <ColTypeNumeric.h>
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 <std::string>&, const std::string&, int, Color&);
ColumnLast ();
void measure (Task&, unsigned int&, unsigned int&);
void render (std::vector <std::string>&, Task&, int, Color&);
private:
bool _hyphenate;
};
#endif

View file

@ -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));
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -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);
}
}

View file

@ -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);

View file

@ -25,92 +25,77 @@
////////////////////////////////////////////////////////////////////////////////
#include <cmake.h>
#include <ColString.h>
#include <ColRType.h>
#include <Context.h>
#include <format.h>
#include <shared.h>
#include <util.h>
#include <format.h>
#include <i18n.h>
#include <cctype>
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 <std::string>& lines,
const std::string& value,
Task& task,
int width,
Color& color)
{
if (_style == "default" || _style == "left")
if (task.has (_name))
{
std::vector <std::string> 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 <std::string> 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";
}
////////////////////////////////////////////////////////////////////////////////

45
src/columns/ColRType.h Normal file
View file

@ -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 <ColTypeString.h>
class ColumnRType : public ColumnTypeString
{
public:
ColumnRType ();
void setStyle (const std::string&);
void measure (Task&, unsigned int&, unsigned int&);
void render (std::vector <std::string>&, Task&, int, Color&);
bool validate (const std::string&) const;
private:
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -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"));

View file

@ -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;
}

View file

@ -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.
}
}

View file

@ -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);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -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, ','))
{

View file

@ -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 <cmake.h>
#include <ColTemplate.h>
#include <format.h>
#include <i18n.h>
////////////////////////////////////////////////////////////////////////////////
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 <std::string>& 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));
}
}
////////////////////////////////////////////////////////////////////////////////

43
src/columns/ColTemplate.h Normal file
View file

@ -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 <ColTypeString.h>
class ColumnTemplate : public ColumnTypeString
{
public:
ColumnTemplate ();
void measure (Task&, unsigned int&, unsigned int&);
void render (std::vector <std::string>&, Task&, int, Color&);
private:
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -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)
{

View file

@ -39,6 +39,7 @@ public:
ColumnTypeDate ();
virtual void measure (Task&, unsigned int&, unsigned int&);
virtual void render (std::vector <std::string>&, Task&, int, Color&);
virtual bool validate (const std::string&) const;
virtual void modify (Task&, const std::string&);
};

View file

@ -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)
{

View file

@ -35,6 +35,7 @@ class ColumnTypeDuration : public Column
{
public:
ColumnTypeDuration ();
virtual bool validate (const std::string&) const;
virtual void modify (Task&, const std::string&);
};

View file

@ -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)
{

View file

@ -35,6 +35,7 @@ class ColumnTypeNumeric : public Column
{
public:
ColumnTypeNumeric ();
virtual bool validate (const std::string&) const;
virtual void modify (Task&, const std::string&);
};

View file

@ -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)
{

View file

@ -35,6 +35,7 @@ class ColumnTypeString : public Column
{
public:
ColumnTypeString ();
virtual bool validate (const std::string&) const;
virtual void modify (Task&, const std::string&);
};

View file

@ -40,12 +40,13 @@ extern Context context;
////////////////////////////////////////////////////////////////////////////////
ColumnUDAString::ColumnUDAString ()
{
_name = "<uda>";
_style = "default";
_label = "";
_uda = true;
_hyphenate = true;
_styles = {_style, "indicator"};
_name = "<uda>"; // 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.<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);
}
}
}

View file

@ -26,7 +26,6 @@
#include <cmake.h>
#include <ColUUID.h>
#include <math.h>
#include <format.h>
#include <i18n.h>
@ -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);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -31,8 +31,8 @@
////////////////////////////////////////////////////////////////////////////////
ColumnUntil::ColumnUntil ()
{
_name = "until";
_label = STRING_COLUMN_LABEL_UNTIL;
_name = "until";
_label = STRING_COLUMN_LABEL_UNTIL;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -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);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -31,8 +31,8 @@
////////////////////////////////////////////////////////////////////////////////
ColumnWait::ColumnWait ()
{
_name = "wait";
_label = STRING_COLUMN_LABEL_WAIT;
_name = "wait";
_label = STRING_COLUMN_LABEL_WAIT;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -36,16 +36,18 @@
#include <ColEntry.h>
#include <ColID.h>
#include <ColIMask.h>
#include <ColLast.h>
#include <ColMask.h>
#include <ColModified.h>
#include <ColParent.h>
#include <ColProject.h>
#include <ColRecur.h>
#include <ColRType.h>
#include <ColScheduled.h>
#include <ColStart.h>
#include <ColStatus.h>
#include <ColString.h>
#include <ColTags.h>
#include <ColTemplate.h>
#include <ColUntil.h>
#include <ColUrgency.h>
#include <ColUUID.h>
@ -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 <std::string, Column*>& 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 <std::string, Column*>& all)
////////////////////////////////////////////////////////////////////////////////
void Column::uda (std::map <std::string, Column*>& all)
{
// For each UDA, instantiate and initialize ColumnUDA().
// For each UDA, instantiate and initialize ColumnUDA.
std::set <std::string> 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 (

View file

@ -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 <std::string>&, int, Color&);
virtual void render (std::vector <std::string>&, const std::string&, int, Color&) {};
virtual void render (std::vector <std::string>&, Task&, int, Color&) {};
virtual bool validate (const std::string&) const {return false;};
virtual void modify (Task&, const std::string&) {};
protected: