diff --git a/src/Context.cpp b/src/Context.cpp index 6bb4ee418..5fdec2f6b 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -162,40 +162,38 @@ std::string Context::dispatch () int gcMod = 0; // Change occurred by way of gc. std::string out; - // Read-only commands with no side effects. + // TODO Look at this thing. It just cries out for a dispatch table. /* - if (cmd.command == "export") { out = handleExport (); } + if (cmd.command == "export") { out = handleExport (); } */ - if (cmd.command == "projects") { out = handleProjects (); } - else if (cmd.command == "tags") { out = handleTags (); } - else if (cmd.command == "colors") { out = handleColor (); } - else if (cmd.command == "version") { out = handleVersion (); } - else if (cmd.command == "help") { out = longUsage (); } - else if (cmd.command == "stats") { out = handleReportStats (); } + if (cmd.command == "projects") { out = handleProjects (); } + else if (cmd.command == "tags") { out = handleTags (); } + else if (cmd.command == "colors") { out = handleColor (); } + else if (cmd.command == "version") { out = handleVersion (); } + else if (cmd.command == "help") { out = longUsage (); } + else if (cmd.command == "stats") { out = handleReportStats (); } + else if (cmd.command == "info") { out = handleInfo (); } /* - else if (cmd.command == "info") { out = handleInfo (); } - else if (cmd.command == "history") { out = handleReportHistory (); } - else if (cmd.command == "ghistory") { out = handleReportGHistory (); } - else if (cmd.command == "calendar") { out = handleReportCalendar (); } - else if (cmd.command == "summary") { out = handleReportSummary (); } - else if (cmd.command == "timesheet") { out = handleReportTimesheet (); } + else if (cmd.command == "history") { out = handleReportHistory (); } + else if (cmd.command == "ghistory") { out = handleReportGHistory (); } + else if (cmd.command == "calendar") { out = handleReportCalendar (); } + else if (cmd.command == "summary") { out = handleReportSummary (); } + else if (cmd.command == "timesheet") { out = handleReportTimesheet (); } */ - - // Commands that cause updates. - else if (cmd.command == "add") { out = handleAdd (); } + else if (cmd.command == "add") { out = handleAdd (); } /* - else if (command == "" && task.getId ()) { out = handleModify (); } - else if (command == "append") { out = handleAppend (); } - else if (command == "annotate") { out = handleAnnotate (); } - else if (command == "done") { out = handleDone (); } - else if (command == "undelete") { out = handleUndelete (); } - else if (command == "delete") { out = handleDelete (); } - else if (command == "start") { out = handleStart (); } - else if (command == "stop") { out = handleStop (); } - else if (command == "undo") { out = handleUndo (); } - else if (command == "import") { out = handleImport (); } - else if (command == "duplicate") { out = handleDuplicate (); } - else if (command == "edit") { out = handleEdit (); } + else if (cmd.command == "" && task.getId ()) { out = handleModify (); } + else if (cmd.command == "append") { out = handleAppend (); } + else if (cmd.command == "annotate") { out = handleAnnotate (); } + else if (cmd.command == "done") { out = handleDone (); } + else if (cmd.command == "undelete") { out = handleUndelete (); } + else if (cmd.command == "delete") { out = handleDelete (); } + else if (cmd.command == "start") { out = handleStart (); } + else if (cmd.command == "stop") { out = handleStop (); } + else if (cmd.command == "undo") { out = handleUndo (); } + else if (cmd.command == "import") { out = handleImport (); } + else if (cmd.command == "duplicate") { out = handleDuplicate (); } + else if (cmd.command == "edit") { out = handleEdit (); } */ // Command that display IDs and therefore need TDB::gc first. diff --git a/src/Filter.cpp b/src/Filter.cpp index cfa17634f..4fa91419c 100644 --- a/src/Filter.cpp +++ b/src/Filter.cpp @@ -25,8 +25,10 @@ // //////////////////////////////////////////////////////////////////////////////// +#include #include "Filter.h" #include "util.h" +#include "main.h" //////////////////////////////////////////////////////////////////////////////// // For every Att in the filter, lookup the equivalent in Record, and perform a @@ -54,3 +56,42 @@ bool Filter::pass (const Record& record) const } //////////////////////////////////////////////////////////////////////////////// +void Filter::applySequence (std::vector& all, Sequence& sequence) +{ + std::vector filtered; + foreach (task, all) + foreach (i, sequence) + if (task->id == *i) + filtered.push_back (*task); + + if (sequence.size () != filtered.size ()) + { + std::vector filteredSequence; + foreach (task, filtered) + filteredSequence.push_back (task->id); + + std::vector left; + std::vector right; + listDiff (filteredSequence, (std::vector &)sequence, left, right); + if (left.size ()) + throw std::string ("Sequence filtering error - please report this error"); + + if (right.size ()) + { + std::stringstream out; + out << "Task"; + + if (right.size () > 1) out << "s"; + + foreach (r, right) + out << " " << *r; + + out << " not found"; + throw out.str (); + } + } + + all = filtered; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/Filter.h b/src/Filter.h index ef730e7fd..4e21ab265 100644 --- a/src/Filter.h +++ b/src/Filter.h @@ -29,12 +29,14 @@ #include #include "Att.h" +#include "Task.h" #include "Record.h" class Filter : public std::vector { public: bool pass (const Record&) const; + void applySequence (std::vector&, Sequence&); }; #endif diff --git a/src/TDB2.cpp b/src/TDB2.cpp index 347347aba..2c9357d89 100644 --- a/src/TDB2.cpp +++ b/src/TDB2.cpp @@ -171,7 +171,7 @@ int TDB2::loadPending (std::vector & tasks, Filter& filter) // TODO Add hidden attribute indicating source? line[length - 1] = '\0'; // Kill \n Task task (line); - task.id (mId++); + task.id = mId++; if (filter.pass (task)) tasks.push_back (task); @@ -221,7 +221,7 @@ int TDB2::loadCompleted (std::vector & tasks, Filter& filter) // TODO Add hidden attribute indicating source? line[length - 1] = '\0'; // Kill \n Task task (line); - task.id (mId++); + task.id = mId++; if (filter.pass (task)) tasks.push_back (task); diff --git a/src/Task.cpp b/src/Task.cpp index cf8a5c903..51b75f7fe 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -34,6 +34,7 @@ //////////////////////////////////////////////////////////////////////////////// Task::Task () +: id (0) { // Each new task gets a uuid. set ("uuid", uuid ()); @@ -55,19 +56,6 @@ Task::Task (const std::string& input) } } -//////////////////////////////////////////////////////////////////////////////// -Task& Task::operator= (const Task& other) -{ - throw std::string ("unimplemented Task::operator="); - if (this != &other) - { - sequence = other.sequence; - subst = other.subst; - } - - return *this; -} - //////////////////////////////////////////////////////////////////////////////// Task::~Task () { @@ -430,11 +418,7 @@ void Task::removeTag (const std::string& tag) //////////////////////////////////////////////////////////////////////////////// void Task::validate () const { - // Every task needs an ID. -/* - if (sequence[0] == 0) - throw std::string ("Every task needs an ID."); -*/ + // TODO Every task needs an ID. // TODO Every task needs an ID, entry and description attribute. diff --git a/src/Task.h b/src/Task.h index 6efb751f2..f1df36b87 100644 --- a/src/Task.h +++ b/src/Task.h @@ -37,7 +37,6 @@ class Task : public Record public: Task (); // Default constructor Task (const std::string&); // Parse - Task& operator= (const Task&); // Assignment operator ~Task (); // Destructor void parse (const std::string&); @@ -47,13 +46,9 @@ public: enum status {pending, completed, deleted, recurring /* , retired, deferred */}; // Public data. - Sequence sequence; - Subst subst; + int id; // Series of helper functions. - int id () const { return sequence.size () ? sequence[0] : 0; } - void id (int anotherId) { sequence.push_back (anotherId); } - static status textToStatus (const std::string&); static std::string statusToText (status); diff --git a/src/custom.cpp b/src/custom.cpp index 06d2cf0af..900ee9e17 100644 --- a/src/custom.cpp +++ b/src/custom.cpp @@ -128,7 +128,7 @@ std::string handleCustomReport (const std::string& report) table.setColumnJustification (columnCount, Table::right); for (unsigned int row = 0; row < tasks.size(); ++row) - table.addCell (row, columnCount, tasks[row].id ()); + table.addCell (row, columnCount, tasks[row].id); } else if (*col == "uuid") diff --git a/src/main.h b/src/main.h index 17e1507cc..07835bec1 100644 --- a/src/main.h +++ b/src/main.h @@ -90,8 +90,6 @@ std::string handleEdit (); // report.cpp std::string shortUsage (); std::string longUsage (); -void filterSequence (std::vector&, T&); -void filter (std::vector&, T&); std::string handleInfo (); std::string handleReportSummary (); std::string handleReportNext (); diff --git a/src/report.cpp b/src/report.cpp index a8e0d81a1..7ddcf12db 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -264,178 +264,26 @@ std::string longUsage () return out.str (); } -//////////////////////////////////////////////////////////////////////////////// -// TODO Obsolete -void filterSequence (std::vector& all, T& task) -{ - std::vector sequence = task.getAllIds (); - - std::vector filtered; - std::vector ::iterator t; - for (t = all.begin (); t != all.end (); ++t) - { - std::vector ::iterator s; - for (s = sequence.begin (); s != sequence.end (); ++s) - if (t->getId () == *s) - filtered.push_back (*t); - } - - if (sequence.size () != filtered.size ()) - { - std::vector filteredSequence; - std::vector ::iterator fs; - for (fs = filtered.begin (); fs != filtered.end (); ++fs) - filteredSequence.push_back (fs->getId ()); - - std::vector left; - std::vector right; - listDiff (filteredSequence, sequence, left, right); - if (left.size ()) - throw std::string ("Sequence filtering error - please report this error"); - - if (right.size ()) - { - std::stringstream out; - out << "Task"; - - if (right.size () > 1) out << "s"; - - std::vector ::iterator s; - for (s = right.begin (); s != right.end (); ++s) - out << " " << *s; - - out << " not found"; - throw out.str (); - } - } - - all = filtered; -} - -//////////////////////////////////////////////////////////////////////////////// -// TODO Obsolete -void filter (std::vector& all, T& task) -{ - std::vector filtered; - - // Split any description specified into words. - std::vector descWords; - split (descWords, lowerCase (task.getDescription ()), ' '); - - // Get all the tags to match against. - std::vector tagList; - task.getTags (tagList); - - std::vector removeTagList; - task.getRemoveTags (removeTagList); - - // Get all the attributes to match against. - std::map attrList; - task.getAttributes (attrList); - - // Iterate over each task, and apply selection criteria. - for (unsigned int i = 0; i < all.size (); ++i) - { - T refTask (all[i]); - - // Apply description filter. - std::string desc = lowerCase (refTask.getDescription ()); - unsigned int matches = 0; - for (unsigned int w = 0; w < descWords.size (); ++w) - if (desc.find (descWords[w]) != std::string::npos) - ++matches; - - if (matches == descWords.size ()) - { - // Apply attribute filter. - matches = 0; - foreach (a, attrList) - { - if (a->first == "project") - { - if (a->second.length () <= refTask.getAttribute (a->first).length ()) - if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ())) - ++matches; -/* - TODO Attempt at allowing "pri:!H", thwarted by a lack of coffee and the - validation of "!H" as a priority value. To be revisited soon. - { - if (a->second[0] == '!') // Inverted search. - { - if (a->second.substr (1, std::string::npos) != refTask.getAttribute (a->first).substr (0, a->second.length ())) - ++matches; - } - else - { - if (a->second == refTask.getAttribute (a->first).substr (0, a->second.length ())) - ++matches; - } - } -*/ - } - else if (a->second == refTask.getAttribute (a->first)) - ++matches; -/* - else - { - if (a->second[0] == '!') // Inverted search. - { - if (a->second.substr (1, std::string::npos) != refTask.getAttribute (a->first)) - ++matches; - } - else - { - if (a->second == refTask.getAttribute (a->first)) - ++matches; - } - } -*/ - } - - if (matches == attrList.size ()) - { - // Apply tag filter. - matches = 0; - for (unsigned int t = 0; t < tagList.size (); ++t) - if (refTask.hasTag (tagList[t])) - ++matches; - - if (matches == tagList.size ()) - { - matches = 0; - for (unsigned int t = 0; t < removeTagList.size (); ++t) - if (refTask.hasTag (removeTagList[t])) - ++matches; - - if (matches == 0) - filtered.push_back (refTask); - } - } - } - } - - all = filtered; -} - //////////////////////////////////////////////////////////////////////////////// // Display all information for the given task. std::string handleInfo () { std::stringstream out; -/* // Get all the tasks. - std::vector tasks; - tdb.allPendingT (tasks); - filterSequence (tasks, task); + std::vector tasks; + context.tdb.lock (context.config.get ("locking", true)); + context.tdb.loadPending (tasks, context.filter); + context.tdb.unlock (); + + // Filter sequence. + context.filter.applySequence (tasks, context.sequence); // Find the task. - foreach (t, tasks) + foreach (task, tasks) { - T refTask (*t); - Table table; - table.setTableWidth (width); + table.setTableWidth (context.getWidth ()); table.setDateFormat (context.config.get ("dateformat", "m/d/Y")); table.addColumn ("Name"); @@ -459,89 +307,89 @@ std::string handleInfo () int row = table.addRow (); table.addCell (row, 0, "ID"); - table.addCell (row, 1, refTask.getId ()); + table.addCell (row, 1, task->id); - std::string status = refTask.getStatus () == T::pending ? "Pending" - : refTask.getStatus () == T::completed ? "Completed" - : refTask.getStatus () == T::deleted ? "Deleted" - : refTask.getStatus () == T::recurring ? "Recurring" + std::string status = task->getStatus () == Task::pending ? "Pending" + : task->getStatus () == Task::completed ? "Completed" + : task->getStatus () == Task::deleted ? "Deleted" + : task->getStatus () == Task::recurring ? "Recurring" : ""; - if (refTask.has ("parent")) + if (task->has ("parent")) status += " (Recurring)"; row = table.addRow (); table.addCell (row, 0, "Status"); table.addCell (row, 1, status); - std::string description = refTask.getDescription (); + std::string description = task->get ("description"); std::string when; - std::map annotations; - refTask.getAnnotations (annotations); + std::vector annotations; + task->getAnnotations (annotations); foreach (anno, annotations) { - Date dt (anno->first); + Date dt (::atoi (anno->name ().substr (11, std::string::npos).c_str ())); when = dt.toString (context.config.get ("dateformat", "m/d/Y")); - description += "\n" + when + " " + anno->second; + description += "\n" + when + " " + anno->value (); } row = table.addRow (); table.addCell (row, 0, "Description"); table.addCell (row, 1, description); - if (refTask.has ("project")) + if (task->has ("project")) { row = table.addRow (); table.addCell (row, 0, "Project"); - table.addCell (row, 1, refTask.getAttribute ("project")); + table.addCell (row, 1, task->get ("project")); } - if (refTask.has ("priority")) + if (task->has ("priority")) { row = table.addRow (); table.addCell (row, 0, "Priority"); - table.addCell (row, 1, refTask.getAttribute ("priority")); + table.addCell (row, 1, task->get ("priority")); } - if (refTask.getStatus () == T::recurring || - refTask.has ("parent")) + if (task->getStatus () == Task::recurring || + task->has ("parent")) { - if (refTask.has ("recur")) + if (task->has ("recur")) { row = table.addRow (); table.addCell (row, 0, "Recurrence"); - table.addCell (row, 1, refTask.getAttribute ("recur")); + table.addCell (row, 1, task->get ("recur")); } - if (refTask.has ("until")) + if (task->has ("until")) { row = table.addRow (); table.addCell (row, 0, "Recur until"); - table.addCell (row, 1, refTask.getAttribute ("until")); + table.addCell (row, 1, task->get ("until")); } - if (refTask.has ("mask")) + if (task->has ("mask")) { row = table.addRow (); table.addCell (row, 0, "Mask"); - table.addCell (row, 1, refTask.getAttribute ("mask")); + table.addCell (row, 1, task->get ("mask")); } - if (refTask.has ("parent")) + if (task->has ("parent")) { row = table.addRow (); table.addCell (row, 0, "Parent task"); - table.addCell (row, 1, refTask.getAttribute ("parent")); + table.addCell (row, 1, task->get ("parent")); } row = table.addRow (); table.addCell (row, 0, "Mask Index"); - table.addCell (row, 1, refTask.getAttribute ("imask")); + table.addCell (row, 1, task->get ("imask")); } // due (colored) bool imminent = false; bool overdue = false; - std::string due = refTask.getAttribute ("due"); + std::string due = task->get ("due"); if (due != "") { row = table.addRow (); @@ -568,26 +416,26 @@ std::string handleInfo () } // start - if (refTask.has ("start")) + if (task->has ("start")) { row = table.addRow (); table.addCell (row, 0, "Start"); - Date dt (::atoi (refTask.getAttribute ("start").c_str ())); + Date dt (::atoi (task->get ("start").c_str ())); table.addCell (row, 1, dt.toString (context.config.get ("dateformat", "m/d/Y"))); } // end - if (refTask.has ("end")) + if (task->has ("end")) { row = table.addRow (); table.addCell (row, 0, "End"); - Date dt (::atoi (refTask.getAttribute ("end").c_str ())); + Date dt (::atoi (task->get ("end").c_str ())); table.addCell (row, 1, dt.toString (context.config.get ("dateformat", "m/d/Y"))); } // tags ... std::vector tags; - refTask.getTags (tags); + task->getTags (tags); if (tags.size ()) { std::string allTags; @@ -601,16 +449,16 @@ std::string handleInfo () // uuid row = table.addRow (); table.addCell (row, 0, "UUID"); - table.addCell (row, 1, refTask.getUUID ()); + table.addCell (row, 1, task->get ("uuid")); // entry row = table.addRow (); table.addCell (row, 0, "Entered"); - Date dt (::atoi (refTask.getAttribute ("entry").c_str ())); + Date dt (::atoi (task->get ("entry").c_str ())); std::string entry = dt.toString (context.config.get ("dateformat", "m/d/Y")); std::string age; - std::string created = refTask.getAttribute ("entry"); + std::string created = task->get ("entry"); if (created.length ()) { Date dt (::atoi (created.c_str ())); @@ -620,7 +468,7 @@ std::string handleInfo () table.addCell (row, 1, entry + " (" + age + ")"); // fg - std::string color = refTask.getAttribute ("fg"); + std::string color = task->get ("fg"); if (color != "") { row = table.addRow (); @@ -629,7 +477,7 @@ std::string handleInfo () } // bg - color = refTask.getAttribute ("bg"); + color = task->get ("bg"); if (color != "") { row = table.addRow (); @@ -644,7 +492,7 @@ std::string handleInfo () if (! tasks.size ()) out << "No matches." << std::endl; -*/ + return out.str (); }