- Merged 1.4.3 to master

This commit is contained in:
Paul Beckingham
2008-11-01 16:31:30 -04:00
parent a815492111
commit 2cae1df42f
27 changed files with 950 additions and 431 deletions

View File

@@ -46,6 +46,11 @@
#include <ncurses.h>
#endif
////////////////////////////////////////////////////////////////////////////////
// Globals for exclusive use by callback function.
static TDB* gTdb = NULL;
static Config* gConf = NULL;
////////////////////////////////////////////////////////////////////////////////
static void shortUsage (Config& conf)
{
@@ -280,6 +285,7 @@ int main (int argc, char** argv)
// Load the config file from the home directory. If the file cannot be
// found, offer to create a sample one.
Config conf;
gConf = &conf;
loadConfFile (argc, argv, conf);
// When redirecting output to a file, do not use color, curses.
@@ -290,69 +296,41 @@ int main (int argc, char** argv)
}
TDB tdb;
tdb.dataDirectory (expandPath (conf.get ("data.location")));
gTdb = &tdb;
std::string dataLocation = expandPath (conf.get ("data.location"));
tdb.dataDirectory (dataLocation);
// If argc == 1 and the default.command configuration variable is set,
// then use that, otherwise stick with argc/argv.
std::vector <std::string> args;
std::string defaultCommand = conf.get ("default.command");
if (argc == 1 && defaultCommand != "")
// Log commands, if desired.
if (conf.get ("command.logging") == "on")
tdb.logCommand (argc, argv);
// Set up TDB callback.
std::string shadowFile = expandPath (conf.get ("shadow.file"));
if (shadowFile != "")
{
// Stuff the command line.
split (args, defaultCommand, ' ');
std::cout << "[task " << defaultCommand << "]" << std::endl;
}
else
{
// Parse the command line.
for (int i = 1; i < argc; ++i)
args.push_back (argv[i]);
if (shadowFile == dataLocation + "/pending.data")
throw std::string ("Configuration variable 'shadow.file' is set to "
"overwrite your pending tasks. Please change it.");
if (shadowFile == dataLocation + "/completed.data")
throw std::string ("Configuration variable 'shadow.file' is set to "
"overwrite your completed tasks. Please change it.");
tdb.onChange (&onChangeCallback);
}
std::string command;
T task;
parse (args, command, task, conf);
if (command == "add") handleAdd (tdb, task, conf);
else if (command == "projects") handleProjects (tdb, task, conf);
else if (command == "tags") handleTags (tdb, task, conf);
else if (command == "list") handleList (tdb, task, conf);
else if (command == "info") handleInfo (tdb, task, conf);
else if (command == "undelete") handleUndelete (tdb, task, conf);
else if (command == "long") handleLongList (tdb, task, conf);
else if (command == "ls") handleSmallList (tdb, task, conf);
else if (command == "colors") handleColor ( conf);
else if (command == "completed") handleCompleted (tdb, task, conf);
else if (command == "delete") handleDelete (tdb, task, conf);
else if (command == "start") handleStart (tdb, task, conf);
else if (command == "done") handleDone (tdb, task, conf);
else if (command == "undo") handleUndo (tdb, task, conf);
else if (command == "export") handleExport (tdb, task, conf);
else if (command == "version") handleVersion ( conf);
else if (command == "summary") handleReportSummary (tdb, task, conf);
else if (command == "next") handleReportNext (tdb, task, conf);
else if (command == "history") handleReportHistory (tdb, task, conf);
else if (command == "ghistory") handleReportGHistory (tdb, task, conf);
else if (command == "calendar") handleReportCalendar (tdb, task, conf);
else if (command == "active") handleReportActive (tdb, task, conf);
else if (command == "overdue") handleReportOverdue (tdb, task, conf);
else if (command == "oldest") handleReportOldest (tdb, task, conf);
else if (command == "newest") handleReportNewest (tdb, task, conf);
else if (command == "stats") handleReportStats (tdb, task, conf);
else if (command == "" && task.getId ()) handleModify (tdb, task, conf);
else if (command == "help") longUsage (conf);
else shortUsage (conf);
std::cout << runTaskCommand (argc, argv, tdb, conf);
}
catch (std::string& error)
{
std::cout << error << std::endl;
std::cerr << error << std::endl;
return -1;
}
catch (...)
{
std::cout << "Unknown error." << std::endl;
std::cerr << "Unknown error." << std::endl;
return -2;
}
@@ -391,12 +369,18 @@ int getDueState (const std::string& due)
if (due.length ())
{
Date dt (::atoi (due.c_str ()));
Date now;
if (dt < now)
// rightNow is the current date + time.
Date rightNow;
// By performing this conversion, today is set up as the same date, but
// midnight.
Date today (rightNow.month (), rightNow.day (), rightNow.year ());
if (dt < today)
return 2;
Date nextweek = now + 7 * 86400;
Date nextweek = today + 7 * 86400;
if (dt < nextweek)
return 1;
}
@@ -544,7 +528,6 @@ Date getNextRecurrence (Date& current, std::string& period)
while (! Date::valid (m, d, y))
--d;
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
return Date (m, d, y);
}
@@ -563,7 +546,6 @@ Date getNextRecurrence (Date& current, std::string& period)
while (! Date::valid (m, d, y))
--d;
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
return Date (m, d, y);
}
@@ -579,7 +561,6 @@ Date getNextRecurrence (Date& current, std::string& period)
while (! Date::valid (m, d, y))
--d;
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
return Date (m, d, y);
}
@@ -598,7 +579,6 @@ Date getNextRecurrence (Date& current, std::string& period)
while (! Date::valid (m, d, y))
--d;
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
return Date (m, d, y);
}
@@ -614,7 +594,6 @@ Date getNextRecurrence (Date& current, std::string& period)
while (! Date::valid (m, d, y))
--d;
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
return Date (m, d, y);
}
@@ -630,7 +609,6 @@ Date getNextRecurrence (Date& current, std::string& period)
while (! Date::valid (m, d, y))
--d;
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
return Date (m, d, y);
}
@@ -639,7 +617,6 @@ Date getNextRecurrence (Date& current, std::string& period)
{
y += 2;
// std::cout << "# next " << current.toString () << " + " << period << " = " << m << "/" << d << "/" << y << std::endl;
return Date (m, d, y);
}
@@ -657,7 +634,6 @@ void updateRecurrenceMask (
T& task)
{
std::string parent = task.getAttribute ("parent");
// std::cout << "# updateRecurrenceMask of " << parent << std::endl;
if (parent != "")
{
std::vector <T>::iterator it;
@@ -665,11 +641,8 @@ void updateRecurrenceMask (
{
if (it->getUUID () == parent)
{
// std::cout << "# located parent task" << std::endl;
unsigned int index = atoi (task.getAttribute ("imask").c_str ());
// std::cout << "# child imask=" << index << std::endl;
std::string mask = it->getAttribute ("mask");
// std::cout << "# parent mask=" << mask << std::endl;
if (mask.length () > index)
{
mask[index] = (task.getStatus () == T::pending) ? '-'
@@ -677,15 +650,11 @@ void updateRecurrenceMask (
: (task.getStatus () == T::deleted) ? 'X'
: '?';
// std::cout << "# setting parent mask to=" << mask << std::endl;
it->setAttribute ("mask", mask);
// std::cout << "# tdb.modifyT (parent)" << std::endl;
tdb.modifyT (*it);
}
else
{
// std::cout << "# mask of insufficient length" << std::endl;
// std::cout << "# should never occur" << std::endl;
std::string mask;
for (unsigned int i = 0; i < index; ++i)
mask += "?";
@@ -703,3 +672,129 @@ void updateRecurrenceMask (
}
////////////////////////////////////////////////////////////////////////////////
// Using gTdb and gConf, generate a report.
void onChangeCallback ()
{
try
{
if (gConf && gTdb)
{
// Determine if shadow file is enabled.
std::string shadowFile = expandPath (gConf->get ("shadow.file"));
if (shadowFile != "")
{
std::string oldCurses = gConf->get ("curses");
std::string oldColor = gConf->get ("color");
gConf->set ("curses", "off");
gConf->set ("color", "off");
// Run report. Use shadow.command, using default.command as a fallback
// with "list" as a default.
std::string command = gConf->get ("shadow.command",
gConf->get ("default.command", "list"));
std::vector <std::string> args;
split (args, command, ' ');
std::string result = runTaskCommand (args, *gTdb, *gConf);
std::ofstream out (shadowFile.c_str ());
if (out.good ())
{
out << result;
out.close ();
}
else
throw std::string ("Could not write file '") + shadowFile + "'";
gConf->set ("curses", oldCurses);
gConf->set ("color", oldColor);
}
else
throw std::string ("No specified shadow file '") + shadowFile + "'.";
}
else
throw std::string ("Internal error (TDB/Config).");
}
catch (std::string& error)
{
std::cout << error << std::endl;
}
catch (...)
{
std::cout << "Unknown error." << std::endl;
}
}
////////////////////////////////////////////////////////////////////////////////
std::string runTaskCommand (
int argc,
char** argv,
TDB& tdb,
Config& conf)
{
std::vector <std::string> args;
for (int i = 1; i < argc; ++i)
args.push_back (argv[i]);
return runTaskCommand (args, tdb, conf);
}
////////////////////////////////////////////////////////////////////////////////
std::string runTaskCommand (
std::vector <std::string>& args,
TDB& tdb,
Config& conf)
{
// If argc == 1 and the default.command configuration variable is set,
// then use that, otherwise stick with argc/argv.
std::string defaultCommand = conf.get ("default.command");
if (args.size () == 0 && defaultCommand != "")
{
// Stuff the command line.
args.clear ();
split (args, defaultCommand, ' ');
std::cout << "[task " << defaultCommand << "]" << std::endl;
}
std::string command;
T task;
parse (args, command, task, conf);
std::string out = "";
if (command == "add") handleAdd (tdb, task, conf);
else if (command == "projects") out = handleProjects (tdb, task, conf);
else if (command == "tags") out = handleTags (tdb, task, conf);
else if (command == "list") out = handleList (tdb, task, conf);
else if (command == "info") out = handleInfo (tdb, task, conf);
else if (command == "undelete") out = handleUndelete (tdb, task, conf);
else if (command == "long") out = handleLongList (tdb, task, conf);
else if (command == "ls") out = handleSmallList (tdb, task, conf);
else if (command == "colors") out = handleColor ( conf);
else if (command == "completed") out = handleCompleted (tdb, task, conf);
else if (command == "delete") out = handleDelete (tdb, task, conf);
else if (command == "start") out = handleStart (tdb, task, conf);
else if (command == "done") handleDone (tdb, task, conf);
else if (command == "undo") out = handleUndo (tdb, task, conf);
else if (command == "export") handleExport (tdb, task, conf);
else if (command == "version") out = handleVersion ( conf);
else if (command == "summary") out = handleReportSummary (tdb, task, conf);
else if (command == "next") out = handleReportNext (tdb, task, conf);
else if (command == "history") out = handleReportHistory (tdb, task, conf);
else if (command == "ghistory") out = handleReportGHistory (tdb, task, conf);
else if (command == "calendar") out = handleReportCalendar (tdb, task, conf);
else if (command == "active") out = handleReportActive (tdb, task, conf);
else if (command == "overdue") out = handleReportOverdue (tdb, task, conf);
else if (command == "oldest") out = handleReportOldest (tdb, task, conf);
else if (command == "newest") out = handleReportNewest (tdb, task, conf);
else if (command == "stats") out = handleReportStats (tdb, task, conf);
else if (command == "usage") out = handleReportUsage (tdb, task, conf);
else if (command == "" && task.getId ()) handleModify (tdb, task, conf);
else if (command == "help") longUsage (conf);
else shortUsage (conf);
return out;
}
////////////////////////////////////////////////////////////////////////////////