Enhancement - add

- Modified Record::get* methods to be const.
- Implemented TDB2::add.
- Renamed Task::valid to Task::validate.
- Implemented Task::setEntry to default creation time.
- Fixed bug where TDB2 was opening files "rw" instead of "r+".
This commit is contained in:
Paul Beckingham 2009-06-11 00:11:11 -04:00
parent 8728312da6
commit 7b9cb12308
8 changed files with 70 additions and 55 deletions

View file

@ -173,10 +173,12 @@ void Context::dispatch ()
else if (command == "calendar") { out = handleReportCalendar (); } else if (command == "calendar") { out = handleReportCalendar (); }
else if (command == "summary") { out = handleReportSummary (); } else if (command == "summary") { out = handleReportSummary (); }
else if (command == "timesheet") { out = handleReportTimesheet (); } else if (command == "timesheet") { out = handleReportTimesheet (); }
*/
// Commands that cause updates. // Commands that cause updates.
else if (cmd.command == "add") { cmdMod = true; out = handleAdd (); }
/*
else if (command == "" && task.getId ()) { cmdMod = true; out = handleModify (); } else if (command == "" && task.getId ()) { cmdMod = true; out = handleModify (); }
else if (command == "add") { cmdMod = true; out = handleAdd (); }
else if (command == "append") { cmdMod = true; out = handleAppend (); } else if (command == "append") { cmdMod = true; out = handleAppend (); }
else if (command == "annotate") { cmdMod = true; out = handleAnnotate (); } else if (command == "annotate") { cmdMod = true; out = handleAnnotate (); }
else if (command == "done") { cmdMod = true; out = handleDone (); } else if (command == "done") { cmdMod = true; out = handleDone (); }
@ -188,24 +190,24 @@ void Context::dispatch ()
else if (command == "import") { cmdMod = true; out = handleImport (); } else if (command == "import") { cmdMod = true; out = handleImport (); }
else if (command == "duplicate") { cmdMod = true; out = handleDuplicate (); } else if (command == "duplicate") { cmdMod = true; out = handleDuplicate (); }
else if (command == "edit") { cmdMod = true; out = handleEdit (); } else if (command == "edit") { cmdMod = true; out = handleEdit (); }
*/
// Command that display IDs and therefore need TDB::gc first. // Command that display IDs and therefore need TDB::gc first.
/*
else if (command == "completed") { if (gc) gcMod = tdb.gc (); out = handleCompleted (); } else if (command == "completed") { if (gc) gcMod = tdb.gc (); out = handleCompleted (); }
else if (command == "next") { if (gc) gcMod = tdb.gc (); out = handleReportNext (); } else if (command == "next") { if (gc) gcMod = tdb.gc (); out = handleReportNext (); }
else if (command == "active") { if (gc) gcMod = tdb.gc (); out = handleReportActive (); } else if (command == "active") { if (gc) gcMod = tdb.gc (); out = handleReportActive (); }
else if (command == "overdue") { if (gc) gcMod = tdb.gc (); out = handleReportOverdue (); } else if (command == "overdue") { if (gc) gcMod = tdb.gc (); out = handleReportOverdue (); }
else if (isCustomReport (command)) { if (gc) gcMod = tdb.gc (); out = handleCustomReport (command); } else if (cmd.validCustom (command)) { if (gc) gcMod = tdb.gc (); out = handleCustomReport (command); }
*/
// If the command is not recognized, display usage. // If the command is not recognized, display usage.
*/
else { out = shortUsage (); } else { out = shortUsage (); }
/*
// Only update the shadow file if such an update was not suppressed (shadow), // Only update the shadow file if such an update was not suppressed (shadow),
// and if an actual change occurred (gcMod || cmdMod). // and if an actual change occurred (gcMod || cmdMod).
if (shadow && (gcMod || cmdMod)) // if (shadow && (gcMod || cmdMod))
updateShadowFile (tdb); // updateShadowFile (tdb);
*/
std::cout << out; std::cout << out;
} }

View file

@ -62,12 +62,13 @@ std::string Record::composeF4 ()
std::string ff4 = "["; std::string ff4 = "[";
bool first = true; bool first = true;
foreach (r, (*this)) foreach (att, (*this))
{ {
if (r->second.value () != "") if (att->second.value () != "")
ff4 += (first ? "" : " ") + r->second.composeF4 (); {
ff4 += (first ? "" : " ") + att->second.composeF4 ();
first = false; first = false;
}
} }
ff4 += "]"; ff4 += "]";
@ -126,19 +127,21 @@ std::vector <Att> Record::all ()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const std::string Record::get (const std::string& name) const std::string Record::get (const std::string& name) const
{ {
if (this->find (name) != this->end ()) Record::const_iterator i = this->find (name);
return (*this)[name].value (); if (i != this->end ())
return i->second.value ();
return ""; return "";
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int Record::get_int (const std::string& name) int Record::get_int (const std::string& name) const
{ {
if (this->find (name) != this->end ()) Record::const_iterator i = this->find (name);
return ::atoi ((*this)[name].value ().c_str ()); if (i != this->end ())
return ::atoi (i->second.value ().c_str ());
return 0; return 0;
} }

View file

@ -44,8 +44,8 @@ public:
void parse (const std::string&); void parse (const std::string&);
std::vector <Att> all (); std::vector <Att> all ();
const std::string get (const std::string&); const std::string get (const std::string&) const;
int get_int (const std::string&); int get_int (const std::string&) const;
void set (const std::string&, const std::string&); void set (const std::string&, const std::string&);
void set (const std::string&, int); void set (const std::string&, int);
void remove (const std::string&); void remove (const std::string&);

View file

@ -342,7 +342,6 @@ bool TDB::writePending (const T& t)
delay (0.1); delay (0.1);
fputs (t.compose ().c_str (), out); fputs (t.compose ().c_str (), out);
fclose (out); fclose (out);
return true; return true;
} }

View file

@ -28,6 +28,7 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <sys/file.h> #include <sys/file.h>
#include "text.h" #include "text.h"
#include "util.h" #include "util.h"
@ -182,6 +183,8 @@ int TDB2::loadPending (std::vector <Task>& tasks, Filter& filter)
line_number = 1; line_number = 1;
file = location->path + "/pending.data"; file = location->path + "/pending.data";
fseek (location->pending, 0, SEEK_SET);
while (fgets (line, T_LINE_MAX, location->pending)) while (fgets (line, T_LINE_MAX, location->pending))
{ {
int length = ::strlen (line); int length = ::strlen (line);
@ -230,6 +233,8 @@ int TDB2::loadCompleted (std::vector <Task>& tasks, Filter& filter)
line_number = 1; line_number = 1;
file = location->path + "/completed.data"; file = location->path + "/completed.data";
fseek (location->completed, 0, SEEK_SET);
while (fgets (line, T_LINE_MAX, location->completed)) while (fgets (line, T_LINE_MAX, location->completed))
{ {
int length = ::strlen (line); int length = ::strlen (line);
@ -259,12 +264,14 @@ int TDB2::loadCompleted (std::vector <Task>& tasks, Filter& filter)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// TODO Write to transaction log. // TODO Write to transaction log.
// Note: mLocations[0] is where all tasks are written.
void TDB2::add (Task& after) void TDB2::add (Task& after)
{ {
throw std::string ("unimplemented TDB2::add"); // Seek to end of pending.
fseek (mLocations[0].pending, 0, SEEK_END);
// TODO Seek to end of pending. // Write after.composeF4 ().
// TODO write after.composeFF4 (). fputs (after.composeF4 ().c_str (), mLocations[0].pending);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -275,11 +282,11 @@ void TDB2::update (Task& before, Task& after)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// TODO writes all, including comments // TODO Writes all, including comments
int TDB2::commit () int TDB2::commit ()
{ {
// TODO Two passes: first the pending file. // TODO Two passes: first the pending file.
// then the compelted file. // then the completed file.
throw std::string ("unimplemented TDB2::commit"); throw std::string ("unimplemented TDB2::commit");
} }
@ -300,7 +307,7 @@ FILE* TDB2::openAndLock (const std::string& file)
file + "'."; file + "'.";
// Open the file. // Open the file.
FILE* in = fopen (file.c_str (), "rw"); FILE* in = fopen (file.c_str (), "r+");
if (!in) if (!in)
throw std::string ("Could not open '") + file + "'."; throw std::string ("Could not open '") + file + "'.";

View file

@ -95,6 +95,14 @@ std::string Task::statusToText (Task::status s)
return "pending"; return "pending";
} }
////////////////////////////////////////////////////////////////////////////////
void Task::setEntry ()
{
char entryTime[16];
sprintf (entryTime, "%u", (unsigned int) time (NULL));
set ("entry", entryTime);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Task::status Task::getStatus () Task::status Task::getStatus ()
{ {
@ -102,7 +110,7 @@ Task::status Task::getStatus ()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void Task::setSatus (Task::status status) void Task::setStatus (Task::status status)
{ {
set ("status", statusToText (status)); set ("status", statusToText (status));
} }
@ -422,12 +430,14 @@ void Task::removeTag (const std::string& tag)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool Task::valid () const void Task::validate () const
{ {
// TODO Verify until > due // TODO Verify until > due
// TODO Verify entry < until, due, start, end // TODO Verify entry < until, due, start, end
// TODO If name == "recur", then Duration::valid (value). // TODO If name == "recur", then Duration::valid (value).
return true;
if (get ("description") == "")
throw std::string ("Cannot add a task that is blank, or contains <CR> or <LF> characters.");
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -57,8 +57,10 @@ public:
static status textToStatus (const std::string&); static status textToStatus (const std::string&);
static std::string statusToText (status); static std::string statusToText (status);
void setEntry ();
status getStatus (); status getStatus ();
void setSatus (status); void setStatus (status);
int getTagCount (); int getTagCount ();
bool hasTag (const std::string&); bool hasTag (const std::string&);
@ -72,7 +74,7 @@ public:
void addAnnotation (const std::string&); void addAnnotation (const std::string&);
void removeAnnotations (); void removeAnnotations ();
bool valid () const; void validate () const;
private: private:
int determineVersion (const std::string&); int determineVersion (const std::string&);

View file

@ -48,44 +48,36 @@ extern Context context;
std::string handleAdd () std::string handleAdd ()
{ {
std::stringstream out; std::stringstream out;
/*
char entryTime[16];
sprintf (entryTime, "%u", (unsigned int) time (NULL));
task.setAttribute ("entry", entryTime);
std::map <std::string, std::string> atts; context.task.setEntry ();
task.getAttributes (atts);
foreach (i, atts)
if (i->second == "")
task.removeAttribute (i->first);
// Recurring tasks get a special status. // Recurring tasks get a special status.
if (task.getAttribute ("due") != "" && if (context.task.get ("due") != "" &&
task.getAttribute ("recur") != "") context.task.get ("recur") != "")
{ {
task.setStatus (T::recurring); context.task.setStatus (Task::recurring);
task.setAttribute ("mask", ""); context.task.set ("mask", "");
} }
// Override with default.project, if not specified. // Override with default.project, if not specified.
if (task.getAttribute ("project") == "") if (context.task.get ("project") == "")
task.setAttribute ("project", context.config.get ("default.project", "")); context.task.set ("project", context.config.get ("default.project", ""));
// Override with default.priority, if not specified. // Override with default.priority, if not specified.
if (task.getAttribute ("priority") == "") if (context.task.get ("priority") == "")
{ {
std::string defaultPriority = context.config.get ("default.priority", ""); std::string defaultPriority = context.config.get ("default.priority", "");
if (validPriority (defaultPriority)) if (validPriority (defaultPriority))
task.setAttribute ("priority", defaultPriority); context.task.set ("priority", defaultPriority);
} }
// Disallow blank descriptions. // Only valid tasks can be added.
if (task.getDescription () == "") context.task.validate ();
throw std::string ("Cannot add a task that is blank, or contains <CR> or <LF> characters.");
context.tdb.lock (context.config.get ("locking", true));
context.tdb.add (context.task);
context.tdb.unlock ();
if (!tdb.addT (task))
throw std::string ("Could not create new task.");
*/
return out.str (); return out.str ();
} }