Code Cleanup

- Eliminated 'Sensor' code and tests, which would only have been used
  for the interactive version.
- Eliminated obsolete ui code.
This commit is contained in:
Paul Beckingham 2011-03-27 12:36:25 -04:00
parent c502f0216a
commit 84fb46f233
29 changed files with 10 additions and 2919 deletions

View file

@ -8,15 +8,15 @@ set (task_SRCS API.cpp API.h Att.cpp Att.h Cmd.cpp Cmd.h Color.cpp Color.h
JSON.cpp JSON.h Keymap.cpp Keymap.h Lisp.cpp Lisp.h Location.cpp
Location.h Nibbler.cpp Nibbler.h Path.cpp Path.h Permission.cpp
Permission.h Record.cpp Record.h Rectangle.cpp Rectangle.h
Sensor.cpp Sensor.h Sequence.cpp Sequence.h Subst.cpp Subst.h
TDB.cpp TDB.h Table.cpp Table.h Task.cpp Task.h Taskmod.cpp
Taskmod.h Thread.cpp Thread.h Timer.cpp Timer.h Transport.cpp
Transport.h TransportSSH.cpp TransportSSH.h TransportRSYNC.cpp
TransportRSYNC.h TransportCurl.cpp TransportCurl.h Tree.cpp
Tree.h burndown.cpp command.cpp custom.cpp dependency.cpp
diag.cpp edit.cpp export.cpp history.cpp i18n.h import.cpp
interactive.cpp recur.cpp report.cpp rules.cpp rx.cpp rx.h
text.cpp text.h utf8.cpp utf8.h util.cpp util.h Uri.cpp Uri.h)
Sequence.cpp Sequence.h Subst.cpp Subst.h TDB.cpp TDB.h Table.cpp
Table.h Task.cpp Task.h Taskmod.cpp Taskmod.h Thread.cpp Thread.h
Timer.cpp Timer.h Transport.cpp Transport.h TransportSSH.cpp
TransportSSH.h TransportRSYNC.cpp TransportRSYNC.h
TransportCurl.cpp TransportCurl.h Tree.cpp Tree.h burndown.cpp
command.cpp custom.cpp dependency.cpp diag.cpp edit.cpp
export.cpp history.cpp i18n.h import.cpp interactive.cpp
recur.cpp report.cpp rules.cpp rx.cpp rx.h text.cpp text.h
utf8.cpp utf8.h util.cpp util.h Uri.cpp Uri.h)
add_library (task STATIC ${task_SRCS})
add_executable (task_executable main.cpp)

View file

@ -1,90 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2010 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <sys/stat.h>
#include <File.h>
#include <Sensor.h>
////////////////////////////////////////////////////////////////////////////////
Sensor::Sensor ()
: _changed (false)
, _file ("")
, _was (0)
, _is (0)
{
}
////////////////////////////////////////////////////////////////////////////////
Sensor::~Sensor ()
{
}
////////////////////////////////////////////////////////////////////////////////
bool Sensor::changed ()
{
_is = getModification ();
if (_is != _was)
_changed = true;
return _changed;
}
////////////////////////////////////////////////////////////////////////////////
void Sensor::reset ()
{
_changed = false;
_was = _is;
}
////////////////////////////////////////////////////////////////////////////////
/*
void Sensor::fileCreation (const std::string&)
{
}
*/
////////////////////////////////////////////////////////////////////////////////
void Sensor::fileModification (const std::string& file)
{
_file = file;
_was = getModification ();
}
////////////////////////////////////////////////////////////////////////////////
/*
void Sensor::fileDeletion (const std::string&)
{
}
*/
////////////////////////////////////////////////////////////////////////////////
time_t Sensor::getModification ()
{
return File (_file).mtime ();
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,59 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2010 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_SENSOR
#define INCLUDED_SENSOR
#include <string>
class Sensor
{
public:
Sensor ();
~Sensor ();
Sensor (const Sensor&);
Sensor& operator= (const Sensor&);
bool changed ();
void reset ();
// void fileCreation (const std::string&);
void fileModification (const std::string&);
// void fileDeletion (const std::string&);
private:
time_t getModification ();
private:
bool _changed;
std::string _file;
time_t _was;
time_t _is;
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,138 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include "log.h"
#include "Clock.h"
#include "Context.h"
// Constriction point for ncurses calls.
extern pthread_mutex_t conch;
extern Context context;
static int refreshDelay; // Override with ui.clock.refresh
////////////////////////////////////////////////////////////////////////////////
// This thread sleeps and updates the time every second.
static void tick (int* arg)
{
Clock* c = (Clock*) arg;
while (c)
{
sleep (refreshDelay);
// If the element is deinitialized the window goes away, but the thread does
// not. Protect against an attempted redraw of a dead window.
if (c->window != NULL)
c->redraw ();
}
}
////////////////////////////////////////////////////////////////////////////////
// Create thread to track time.
Clock::Clock ()
{
refreshDelay = context.config.getInteger ("ui.clock.refresh");
logWrite ("Clock::Clock refreshDelay=%d", refreshDelay);
pthread_create (&ticker, NULL, (void*(*)(void*)) tick, (void*) this);
}
////////////////////////////////////////////////////////////////////////////////
Clock::~Clock ()
{
pthread_kill (ticker, SIGQUIT);
}
////////////////////////////////////////////////////////////////////////////////
void Clock::redraw ()
{
logWrite ("Clock::redraw");
time_t now;
time (&now);
struct tm* t = localtime (&now);
// TODO Load these from config.
const char* formats[] =
{
// These should remain sorted from longest
// to shortest, in their expanded form,
// shown below.
" %A %e %B %Y, wk%U, %H:%M:%S %z ", // " Sunday 18 October 2009, wk42, 22:42:39 -0400 "
" %A %e %B %Y, wk%U, %H:%M:%S %Z ", // " Sunday 18 October 2009, wk42, 22:42:39 EDT "
" %A %e %B %Y wk%U, %H:%M:%S %Z ", // " Sunday 18 October 2009 wk42, 22:42:39 EDT "
" %A %e %B %Y wk%U %H:%M:%S %Z ", // " Sunday 18 October 2009 wk42 22:42:39 EDT "
" %A %e %B %Y, wk%U, %H:%M:%S ", // " Sunday 18 October 2009, wk42, 22:42:39 "
" %A %e %B %Y, wk%U, %H:%M:%S ", // " Sunday 18 October 2009, wk42, 22:42:39 "
" %A %e %B %Y wk%U, %H:%M:%S ", // " Sunday 18 October 2009 wk42, 22:42:39 "
" %A %e %B %Y wk%U %H:%M:%S ", // " Sunday 18 October 2009 wk42 22:42:39 "
" %A %e %b %Y,wk%U, %H:%M:%S ", // " Sunday 18 Oct 2009, wk42, 22:42:39 "
" %A %e %b %Y wk%U, %H:%M:%S ", // " Sunday 18 Oct 2009 wk42, 22:42:39 "
" %A %e %b %Y wk%U %H:%M:%S ", // " Sunday 18 Oct 2009 wk42 22:42:39 "
" %a %e %b %Y, wk%U, %H:%M:%S ", // " Sun 18 Oct 2009, wk42, 22:42:39 "
" %a %e %b %Y wk%U, %H:%M:%S ", // " Sun 18 Oct 2009 wk42, 22:42:39 "
" %a %e %b %Y, %H:%M:%S ", // " Sun 18 Oct 2009, 22:42:39 "
" %a %e %b %Y %H:%M:%S ", // " Sun 18 Oct 2009 22:42:39 "
" %a %e %b, %H:%M:%S ", // " Sun 18 Oct, 22:42:39 "
" %a %e %b %H:%M:%S ", // " Sun 18 Oct 22:42:39 "
" %e %b, %H:%M:%S ", // " 18 Oct, 22:42:39 "
" %e %b %H:%M:%S ", // " 18 Oct 22:42:39 "
" %H:%M:%S ", // " 22:42:39 "
"%H:%M:%S", // "22:42:39"
" %H:%M ", // " 22:42 "
"%H:%M", // "22:42"
"",
};
// TODO %U (Sun), $W (Mon)
// TODO i18n "wk"
// Render them all, but only keep the longest one that fits.
std::string keeper = "";
char buffer[128];
for (int i = 0; formats[i][0]; ++i)
{
strftime (buffer, 128, formats[i], t);
size_t len = strlen (buffer);
if (len <= (size_t) width && len > keeper.length ())
keeper = buffer;
}
pthread_mutex_lock (&conch);
wbkgd (window, COLOR_PAIR (5));
wbkgdset (window, COLOR_PAIR(5) | A_DIM);
mvwaddstr (window, 0, width - keeper.length (), keeper.c_str ());
wrefresh (window);
pthread_mutex_unlock (&conch);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,49 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_CLOCK
#define INCLUDED_CLOCK
#include <pthread.h>
#include "Element.h"
class Clock : public Element
{
public:
Clock ();
Clock (const Clock&);
Clock& operator= (const Clock&);
~Clock ();
void redraw ();
private:
pthread_t ticker;
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,152 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <pthread.h>
#include "log.h"
#include "Element.h"
#include "Report.h"
#include "ReportStats.h"
#include "Title.h"
#include "Clock.h"
#include "Keys.h"
#include "Message.h"
#include "Stats.h"
// Constriction point for ncurses calls.
extern pthread_mutex_t conch;
////////////////////////////////////////////////////////////////////////////////
// Factory for Element construction, based on spec.
Element* Element::factory (const std::string& name)
{
// logWrite ("Element::factory %s", name.c_str ());
Element* e;
if (name == "report") e = new Report (); // TODO Remove.
else if (name == "report.stats") e = new ReportStats ();
else if (name == "title") e = new Title ();
else if (name == "clock") e = new Clock ();
else if (name == "keys") e = new Keys ();
else if (name == "message") e = new Message ();
else if (name == "stats") e = new Stats ();
else
throw std::string ("Unrecognized element type: '") + name + "'";
e->type = name;
return e;
}
////////////////////////////////////////////////////////////////////////////////
Element::Element ()
: left (0)
, top (0)
, width (0)
, height (0)
, type ("")
, window (NULL)
{
// logWrite ("Element::Element");
}
////////////////////////////////////////////////////////////////////////////////
Element::~Element ()
{
deinitialize ();
}
////////////////////////////////////////////////////////////////////////////////
// When a layout is selected, all the elements are initialized, which means the
// window is created.
void Element::initialize ()
{
// logWrite ("Element::initialize %s", type.c_str ());
window = newwin (height, width, top, left);
}
////////////////////////////////////////////////////////////////////////////////
// When a layout is switched out, the elements are deinitialized, which means
// the window is deleted. The original specs are preserved, and ready for a
// possible later initialize if the layout is switched in.
void Element::deinitialize ()
{
// logWrite ("Element::deinitialize %s", type.c_str ());
if (window)
{
pthread_mutex_lock (&conch);
delwin (window);
pthread_mutex_unlock (&conch);
window = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////
// Notification of new size for stdscr, triggering a size recalc.
void Element::recalc (int l, int t, int w, int h)
{
left = l;
top = t;
width = w;
height = h;
logWrite ("Element::recalc %-7s [l%d,t%d,w%d,h%d]", type.c_str (), left, top, width, height);
}
////////////////////////////////////////////////////////////////////////////////
void Element::relocate ()
{
// logWrite ("Element::relocate %s", type.c_str ());
if (window)
{
pthread_mutex_lock (&conch);
mvwin (window, top, left);
wresize (window, height, width);
pthread_mutex_unlock (&conch);
logWrite ("Element::relocate %-7s [l%d,t%d,w%d,h%d]", type.c_str (), left, top, height, width);
}
}
////////////////////////////////////////////////////////////////////////////////
// Default event handler for Element.
bool Element::event (int e)
{
// logWrite ("Element::event %s %d", type.c_str (), e);
return false;
}
////////////////////////////////////////////////////////////////////////////////
// Default repaint handler for Element.
void Element::redraw ()
{
logWrite ("Element::redraw %s", type.c_str ());
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,64 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_ELEMENT
#define INCLUDED_ELEMENT
#include <string>
#include <ncurses.h>
class Layout;
class Element
{
public:
static Element* factory (const std::string&);
Element ();
Element (const Element&); // Unimplemented
Element& operator= (const Element&); // Unimplemented
virtual ~Element ();
virtual void initialize ();
virtual void deinitialize ();
virtual void recalc (int, int, int, int);
virtual void relocate ();
virtual bool event (int);
virtual void redraw ();
public:
// The actual dimensions of the window. These change when stdscr resizes.
int left;
int top;
int width;
int height;
std::string type;
WINDOW* window;
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,85 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <pthread.h>
#include "log.h"
#include "Keys.h"
// Constriction point for ncurses calls.
extern pthread_mutex_t conch;
////////////////////////////////////////////////////////////////////////////////
Keys::Keys ()
{
// logWrite ("Keys::Keys");
}
////////////////////////////////////////////////////////////////////////////////
Keys::~Keys ()
{
}
////////////////////////////////////////////////////////////////////////////////
void Keys::redraw ()
{
logWrite ("Keys::redraw");
pthread_mutex_lock (&conch);
wbkgd (window, COLOR_PAIR (1));
if (width >= 5)
{
wbkgdset (window, COLOR_PAIR(1) | A_BOLD);
mvwaddstr (window, 0, 0, " q");
wbkgdset (window, COLOR_PAIR(1));
mvwaddstr (window, 0, 2, "uit");
if (width >= 13)
{
wbkgdset (window, COLOR_PAIR(1) | A_BOLD);
mvwaddstr (window, 0, 5, " d");
wbkgdset (window, COLOR_PAIR(1));
mvwaddstr (window, 0, 7, "efault");
if (width >= 20)
{
wbkgdset (window, COLOR_PAIR(1) | A_BOLD);
mvwaddstr (window, 0, 13, " s");
wbkgdset (window, COLOR_PAIR(1));
mvwaddstr (window, 0, 15, "tats");
}
}
}
wrefresh (window);
pthread_mutex_unlock (&conch);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,48 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_KEYS
#define INCLUDED_KEYS
#include <string>
#include "Element.h"
class Keys : public Element
{
public:
Keys ();
Keys (const Keys&);
Keys& operator= (const Keys&);
~Keys ();
void redraw ();
private:
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,172 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <ncurses.h>
#include <stdlib.h>
#include <ctype.h>
#include <pthread.h>
#include "log.h"
#include "Rectangle.h"
#include "Layout.h"
// Constriction point for ncurses calls.
extern pthread_mutex_t conch;
////////////////////////////////////////////////////////////////////////////////
Layout::Layout (const std::string& spec)
: definition (spec)
{
logWrite ("Layout::Layout %s", spec.c_str ());
// Invoke the resize just to extract the element names.
void resize (const std::string&, const int, const int, std::string& name, std::map <std::string, Rectangle>&);
std::map <std::string, Rectangle> defs;
resize (definition, 80, 24, name, defs);
logWrite ("Layout::Layout name=%s", name.c_str ());
// Create an element for each panel in the definition.
std::map <std::string, Rectangle>::iterator it;
for (it = defs.begin (); it != defs.end (); ++it)
{
Element* e = Element::factory (it->first);
elements[e->type] = e;
}
}
////////////////////////////////////////////////////////////////////////////////
Layout::~Layout ()
{
std::map <std::string, Element*>::iterator it;
for (it = elements.begin (); it != elements.end (); ++it)
delete it->second;
elements.clear ();
}
////////////////////////////////////////////////////////////////////////////////
void Layout::initialize ()
{
logWrite ("Layout::initialize");
// Iterate over elements[] (specs) and create windows.
std::map <std::string, Element*>::iterator it;
for (it = elements.begin (); it != elements.end (); ++it)
it->second->initialize ();
}
////////////////////////////////////////////////////////////////////////////////
void Layout::deinitialize ()
{
logWrite ("Layout::deinitialize");
std::map <std::string, Element*>::iterator it;
for (it = elements.begin (); it != elements.end (); ++it)
it->second->deinitialize ();
// At this point the display should be stale but not cleared.
}
////////////////////////////////////////////////////////////////////////////////
bool Layout::event (int e)
{
switch (e)
{
case 12:
logWrite ("Layout::event Ctrl-L");
this->redraw (true);
return true; // handled.
break;
default:
logWrite ("Layout::event %d delegated", e);
{
std::map <std::string, Element*>::iterator it;
for (it = elements.begin (); it != elements.end (); ++it)
it->second->event (e);
}
return true; // handled.
break;
}
return false; // not handled.
}
////////////////////////////////////////////////////////////////////////////////
void Layout::recalc (int w, int h)
{
logWrite ("Layout::recalc %d,%d", w, h);
// Apply layout definition to [w,h], yielding rectangles for each element.
void resize (const std::string&, const int, const int, std::string& name, std::map <std::string, Rectangle>&);
std::string name;
std::map <std::string, Rectangle> defs;
resize (definition, w, h, name, defs);
// Relocate each element.
std::map <std::string, Rectangle>::iterator it;
for (it = defs.begin (); it != defs.end (); ++it)
{
Element* e = elements[it->first];
if (e)
{
e->recalc (
it->second.left,
it->second.top,
it->second.width,
it->second.height);
e->relocate ();
}
}
}
////////////////////////////////////////////////////////////////////////////////
// Redrawing the layout consists of touching and refreshing all the elements.
void Layout::redraw (bool force /* = false */)
{
logWrite ("Layout::redraw");
// This is the magic line that makes resize work. I wish I knew why.
refresh ();
std::map <std::string, Element*>::iterator it;
for (it = elements.begin (); it != elements.end (); ++it)
{
it->second->redraw ();
if (force)
{
pthread_mutex_lock (&conch);
touchwin (it->second->window);
pthread_mutex_unlock (&conch);
}
pthread_mutex_lock (&conch);
wrefresh (it->second->window);
pthread_mutex_unlock (&conch);
}
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,57 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_LAYOUT
#define INCLUDED_LAYOUT
#include <map>
#include <vector>
#include <string>
#include "Element.h"
class Layout
{
public:
Layout (const std::string&);
Layout (const Layout&);
Layout& operator= (const Layout&);
~Layout ();
void initialize ();
void deinitialize ();
bool event (int);
void recalc (int, int);
void redraw (bool force = false);
private:
std::string definition;
std::string name;
std::map <std::string, Element*> elements;
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,73 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <pthread.h>
#include "log.h"
#include "Message.h"
// Constriction point for ncurses calls.
extern pthread_mutex_t conch;
////////////////////////////////////////////////////////////////////////////////
Message::Message ()
{
// logWrite ("Message::Message");
}
////////////////////////////////////////////////////////////////////////////////
Message::~Message ()
{
}
////////////////////////////////////////////////////////////////////////////////
void Message::redraw ()
{
logWrite ("Message::redraw");
// Truncate the message, if necessary.
std::string s = "Using database ~/.task";
if (width - 1 < (int) s.length ())
s = s.substr (0, width - 4) + "...";
// Need at least space for blank + 1 char + ellipsis.
if (width <= 5)
s = "";
pthread_mutex_lock (&conch);
wbkgd (window, COLOR_PAIR (5));
wbkgdset (window, COLOR_PAIR(5) | A_DIM);
if (width <= 5)
touchwin (window);
mvwaddstr (window, 0, 1, s.c_str ());
wrefresh (window);
pthread_mutex_unlock (&conch);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,48 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_MESSAGE
#define INCLUDED_MESSAGE
#include <string>
#include "Element.h"
class Message : public Element
{
public:
Message ();
Message (const Message&);
Message& operator= (const Message&);
~Message ();
void redraw ();
private:
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,80 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <pthread.h>
#include "log.h"
#include "Report.h"
// Constriction point for ncurses calls.
extern pthread_mutex_t conch;
////////////////////////////////////////////////////////////////////////////////
Report::Report ()
{
// logWrite ("Report::Report");
}
////////////////////////////////////////////////////////////////////////////////
Report::~Report ()
{
}
////////////////////////////////////////////////////////////////////////////////
bool Report::event (int e)
{
switch (e)
{
case KEY_MOUSE:
{
MEVENT m;
getmouse (&m);
logWrite ("Report::event KEY_MOUSE [%d,%d] %x (%s)",
m.x,
m.y,
m.bstate,
((m.x >= left && m.x < left + width && m.y >= top && m.y < top + height) ? "hit" : "miss"));
}
return true;
break;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
void Report::redraw ()
{
logWrite ("Report::redraw");
pthread_mutex_lock (&conch);
wbkgd (window, COLOR_PAIR (20));
mvwaddstr (window, 0, 0, "default report");
wrefresh (window);
pthread_mutex_unlock (&conch);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,50 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_REPORT
#define INCLUDED_REPORT
#include <string>
#include "Element.h"
class Report : public Element
{
public:
Report ();
Report (const Report&);
Report& operator= (const Report&);
~Report ();
bool event (int);
void redraw ();
private:
bool value;
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,387 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <sstream>
#include <iomanip>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include "log.h"
#include "ReportStats.h"
#include "Context.h"
#include "File.h"
#include "Path.h"
#include "util.h"
#include "text.h"
#include "main.h"
// Constriction point for ncurses calls.
extern pthread_mutex_t conch;
extern Context context;
static int refreshDelay; // Override with ui.stats.refresh
////////////////////////////////////////////////////////////////////////////////
// This thread sleeps and updates the time every second.
static void tick (int* arg)
{
ReportStats* r = (ReportStats *) arg;
do
{
// If the element is deinitialized the window goes away, but the thread does
// not. Protect against an attempted redraw of a dead window.
if (r->window != NULL &&
r->dataChanged ())
{
r->gatherStats ();
r->redraw ();
}
sleep (refreshDelay);
}
while (arg);
}
////////////////////////////////////////////////////////////////////////////////
ReportStats::ReportStats ()
: highlight_shown (false)
{
// logWrite ("ReportStats::ReportStats");
refreshDelay = context.config.getInteger ("ui.stats.refresh");
logWrite ("ReportStats::ReportStats refreshDelay=%d", refreshDelay);
pthread_create (&ticker, NULL, (void*(*)(void*)) tick, (void*) this);
}
////////////////////////////////////////////////////////////////////////////////
ReportStats::~ReportStats ()
{
pthread_kill (ticker, SIGQUIT);
}
////////////////////////////////////////////////////////////////////////////////
void ReportStats::initialize ()
{
Element::initialize ();
scrollok (window, TRUE);
// idlok (window, TRUE);
}
////////////////////////////////////////////////////////////////////////////////
// TODO Replace with Sensor object.
bool ReportStats::dataChanged ()
{
bool status = false;
struct stat s;
std::string location = Path::expand (context.config.get ("data.location"));
std::string file = location + "/pending.data";
stat (file.c_str (), &s);
if (s.st_mtime != stat_pending.st_mtime)
{
stat_pending = s;
status = true;
}
file = location + "/completed.data";
stat (file.c_str (), &s);
if (s.st_mtime != stat_completed.st_mtime)
{
stat_completed = s;
status = true;
}
file = location + "/undo.data";
stat (file.c_str (), &s);
if (s.st_mtime != stat_undo.st_mtime)
{
stat_undo = s;
status = true;
}
if (highlight_shown)
status = true;
return status;
}
////////////////////////////////////////////////////////////////////////////////
// Maintains two sets of data, previous and current. All newly gathered data
// goes into current. Next iteration, the current is moved to previous.
//
// This two-stage tracking allows detection of changes from one refresh to the
// next, and therefore the highlighting.
void ReportStats::gatherStats ()
{
// The new becomes the old.
previous = current;
// Data size
size_t dataSize = stat_pending.st_size +
stat_completed.st_size +
stat_undo.st_size;
// Undo transactions
std::string location = Path::expand (context.config.get ("data.location"));
std::string file = location + "/undo.data";
std::vector <std::string> undo;
File::read (file, undo);
int undoCount = 0;
std::vector <std::string>::iterator tx;
for (tx = undo.begin (); tx != undo.end (); ++tx)
if (tx->substr (0, 3) == "---")
++undoCount;
// Get all the tasks.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
Date now;
time_t earliest = time (NULL);
time_t latest = 1;
int totalT = 0;
int deletedT = 0;
int pendingT = 0;
int completedT = 0;
int waitingT = 0;
int taggedT = 0;
int annotationsT = 0;
int recurringT = 0;
float daysPending = 0.0;
int descLength = 0;
std::map <std::string, int> allTags;
std::map <std::string, int> allProjects;
std::vector <Task>::iterator it;
for (it = tasks.begin (); it != tasks.end (); ++it)
{
++totalT;
if (it->getStatus () == Task::deleted) ++deletedT;
if (it->getStatus () == Task::pending) ++pendingT;
if (it->getStatus () == Task::completed) ++completedT;
if (it->getStatus () == Task::recurring) ++recurringT;
if (it->getStatus () == Task::waiting) ++waitingT;
time_t entry = atoi (it->get ("entry").c_str ());
if (entry < earliest) earliest = entry;
if (entry > latest) latest = entry;
if (it->getStatus () == Task::completed)
{
time_t end = atoi (it->get ("end").c_str ());
daysPending += (end - entry) / 86400.0;
}
if (it->getStatus () == Task::pending)
daysPending += (now - entry) / 86400.0;
descLength += it->get ("description").length ();
std::vector <Att> annotations;
it->getAnnotations (annotations);
annotationsT += annotations.size ();
std::vector <std::string> tags;
it->getTags (tags);
if (tags.size ()) ++taggedT;
std::vector <std::string>::iterator t;
for (t = tags.begin (); t != tags.end (); ++t)
allTags[*t] = 0;
std::string project = it->get ("project");
if (project != "")
allProjects[project] = 0;
}
current["pending"] = commify (pendingT);
current["waiting"] = commify (waitingT);
current["recurring"] = commify (recurringT);
current["completed"] = commify (completedT);
current["deleted"] = commify (deletedT);
current["total"] = commify (totalT);
current["annotations"] = commify (annotationsT);
current["tags"] = commify ((int)allTags.size ());
current["projects"] = commify ((int)allProjects.size ());
current["size"] = formatBytes (dataSize);
current["undo"] = commify (undoCount);
std::stringstream s;
if (totalT)
s << std::setprecision (3) << (100.0 * taggedT / totalT);
else
s << 0;
s << "%";
current["tagged"] = s.str ();
if (tasks.size ())
{
Date e (earliest);
Date l (latest);
current["oldest"] = e.toString (context.config.get ("dateformat"));
current["newest"] = l.toString (context.config.get ("dateformat"));
current["since"] = formatSeconds (latest - earliest);
}
else
{
current["oldest"] = "-";
current["newest"] = "-";
current["since"] = "-";
}
if (totalT)
current["add_every"] = formatSeconds ((latest - earliest) / totalT);
else
current["add_every"] = "-";
if (completedT)
current["complete_every"] = formatSeconds ((latest - earliest) / completedT);
else
current["complete_every"] = "-";
if (deletedT)
current["delete_every"] = formatSeconds ((latest - earliest) / deletedT);
else
current["delete_every"] = "-";
if (pendingT || completedT)
current["time"] = formatSeconds ((int) ((daysPending / (pendingT + completedT)) * 86400));
else
current["time"] = "-";
if (totalT)
{
std::stringstream value;
value << (int) (descLength / totalT) << " characters";
current["desc"] = value.str ();
}
else
current["desc"] = "-";
}
////////////////////////////////////////////////////////////////////////////////
bool ReportStats::event (int e)
{
switch (e)
{
case KEY_UP:
logWrite ("ReportStats::event KEY_UP");
wscrl (window, -1);
wrefresh (window);
break;
case KEY_DOWN:
logWrite ("ReportStats::event KEY_DOWN");
wscrl (window, 1);
wrefresh (window);
break;
case KEY_MOUSE:
{
MEVENT m;
getmouse (&m);
logWrite ("ReportStats::event KEY_MOUSE [%d,%d] %x (%s)",
m.x,
m.y,
m.bstate,
((m.x >= left && m.x < left + width && m.y >= top && m.y < top + height) ? "hit" : "miss"));
}
return true;
break;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
void ReportStats::redraw ()
{
logWrite ("ReportStats::redraw");
pthread_mutex_lock (&conch);
wbkgd (window, COLOR_PAIR (20) | A_DIM);
wbkgdset (window, COLOR_PAIR(20) | A_DIM);
std::stringstream title;
title << "Live Statistics (updates every "
<< refreshDelay
<< " seconds)";
mvwaddstr (window, 0, 0, title.str ().c_str ());
highlight_shown = false;
renderItem (2, 24, "Pending tasks", "pending");
renderItem (3, 24, "Waiting tasks", "waiting");
renderItem (4, 24, "Recurring tasks", "recurring");
renderItem (5, 24, "Completed tasks", "completed");
renderItem (6, 24, "Deleted tasks", "deleted");
renderItem (7, 24, "Total tasks", "total");
renderItem (8, 24, "Total annotations", "annotations");
renderItem (9, 24, "Unique tags", "tags");
renderItem (10, 24, "Projects", "projects");
renderItem (11, 24, "Data size", "size");
renderItem (12, 24, "Undo transactions", "undo");
renderItem (13, 24, "Tasks tagged", "tagged");
renderItem (14, 24, "Oldest task", "oldest");
renderItem (15, 24, "Newest task", "newest");
renderItem (16, 24, "Task used for", "since");
renderItem (17, 24, "Task added every", "add_every");
renderItem (18, 24, "Task completed every", "complete_every");
renderItem (19, 24, "Task deleted every", "delete_every");
renderItem (20, 24, "Average time pending", "time");
renderItem (21, 24, "Average desc length", "desc");
wrefresh (window);
pthread_mutex_unlock (&conch);
}
////////////////////////////////////////////////////////////////////////////////
void ReportStats::renderItem (
int row,
int col,
const std::string& description,
const std::string& key)
{
wbkgdset (window, COLOR_PAIR(20) | A_DIM);
mvwaddstr (window, row, 0, description.c_str ());
if (current[key] != previous[key])
{
wbkgdset (window, COLOR_PAIR(3) | A_BOLD);
highlight_shown = true;
}
mvwaddstr (window, row, col, current[key].c_str ());
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,66 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_REPORTSTATS
#define INCLUDED_REPORTSTATS
#include <map>
#include <string>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "Element.h"
class ReportStats : public Element
{
public:
ReportStats ();
ReportStats (const ReportStats&);
ReportStats& operator= (const ReportStats&);
~ReportStats ();
void initialize ();
bool dataChanged ();
void gatherStats ();
bool event (int);
void redraw ();
void renderItem (int, int, const std::string&, const std::string&);
public:
struct stat stat_pending;
struct stat stat_completed;
struct stat stat_undo;
private:
pthread_t ticker;
std::map <std::string, std::string> previous;
std::map <std::string, std::string> current;
bool highlight_shown;
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,88 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <pthread.h>
#include "log.h"
#include "Stats.h"
// Constriction point for ncurses calls.
extern pthread_mutex_t conch;
////////////////////////////////////////////////////////////////////////////////
Stats::Stats ()
{
// logWrite ("Stats::Stats");
}
////////////////////////////////////////////////////////////////////////////////
Stats::~Stats ()
{
}
////////////////////////////////////////////////////////////////////////////////
void Stats::redraw ()
{
logWrite ("Stats::redraw");
pthread_mutex_lock (&conch);
wbkgd (window, COLOR_PAIR(1) | A_DIM);
// Allowing 5-digits for tasks.
if (height >= 3)
{
if (width >= 19) mvwaddstr (window, 2, 6, "Waiting tasks");
else if (width >= 13) mvwaddstr (window, 2, 6, "Waiting");
else if (width >= 10) mvwaddstr (window, 2, 6, "Wait");
else if (width >= 7) mvwaddstr (window, 2, 6, "W");
}
if (height >= 2)
{
if (width >= 21) mvwaddstr (window, 1, 6, "Completed tasks");
else if (width >= 15) mvwaddstr (window, 1, 6, "Completed");
else if (width >= 10) mvwaddstr (window, 1, 6, "Comp");
else if (width >= 7) mvwaddstr (window, 1, 6, "C");
}
if (width >= 19) mvwaddstr (window, 0, 6, "Pending tasks");
else if (width >= 13) mvwaddstr (window, 0, 6, "Pending");
else if (width >= 10) mvwaddstr (window, 0, 6, "Pend");
else if (width >= 7) mvwaddstr (window, 0, 6, "P");
if (width >= 7)
{
wbkgdset (window, COLOR_PAIR(1) | A_BOLD);
mvwaddstr (window, 0, 0, "_____");
if (height >= 2) mvwaddstr (window, 1, 0, "_____");
if (height >= 3) mvwaddstr (window, 2, 0, "_____");
}
wrefresh (window);
pthread_mutex_unlock (&conch);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,48 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_STATS
#define INCLUDED_STATS
#include <string>
#include "Element.h"
class Stats : public Element
{
public:
Stats ();
Stats (const Stats&);
Stats& operator= (const Stats&);
~Stats ();
void redraw ();
private:
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,69 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <pthread.h>
#include "log.h"
#include "Title.h"
// Constriction point for ncurses calls.
extern pthread_mutex_t conch;
////////////////////////////////////////////////////////////////////////////////
Title::Title ()
{
// logWrite ("Title::Title");
}
////////////////////////////////////////////////////////////////////////////////
Title::~Title ()
{
}
////////////////////////////////////////////////////////////////////////////////
void Title::redraw ()
{
logWrite ("Title::redraw [%d,%d]", width, height);
pthread_mutex_lock (&conch);
wbkgd (window, COLOR_PAIR (1) | ' ');
if (width >= 21) mvwaddstr (window, 0, 1, "task 2.0.0 pre-alpha");
else if (width >= 11) mvwaddstr (window, 0, 1, "task 2.0.0");
else if (width >= 9) mvwaddstr (window, 0, 1, "task 2.0");
else if (width >= 5) mvwaddstr (window, 0, 1, "task");
if (height >= 2)
{
wbkgdset (window, COLOR_PAIR(8));
if (width >= 23) mvwaddstr (window, 1, 1, "http://taskwarrior.org");
else if (width >= 16) mvwaddstr (window, 1, 1, "taskwarrior.org");
}
wrefresh (window);
pthread_mutex_unlock (&conch);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,48 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_TITLE
#define INCLUDED_TITLE
#include <string>
#include "Element.h"
class Title : public Element
{
public:
Title ();
Title (const Title&);
Title& operator= (const Title&);
~Title ();
void redraw ();
private:
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,221 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <ncurses.h>
#include <ctype.h>
#include <pthread.h>
#include "log.h"
#include "UI.h"
// Constriction point for ncurses calls.
pthread_mutex_t conch = PTHREAD_MUTEX_INITIALIZER;
////////////////////////////////////////////////////////////////////////////////
UI::UI ()
: current (NULL)
{
}
////////////////////////////////////////////////////////////////////////////////
UI::~UI ()
{
std::map <std::string, Layout*>::iterator it;
for (it = layouts.begin (); it != layouts.end (); ++it)
delete it->second;
layouts.clear ();
}
////////////////////////////////////////////////////////////////////////////////
void UI::add (const std::string& name, Layout* layout)
{
logWrite ("UI::add %s", name.c_str ());
layouts[name] = layout;
// First layout added automatically becomes the current layout. Subsequent
// layouts accumulate.
if (current == NULL)
current = layout;
}
////////////////////////////////////////////////////////////////////////////////
void UI::switchLayout (const std::string& name)
{
logWrite ("UI::switchLayout %s", name.c_str ());
if (layouts.find (name) == layouts.end ())
throw std::string ("Cannot switch to non-existent layout '") + name + "'";
// Only switch if the proposed layout is not the current layout.
if (layouts[name] != current)
{
// Close the old windows.
current->deinitialize ();
// Set the new current layout.
current = layouts[name];
// Create the new windows.
current->initialize ();
// Need a size recalc, because the new current layout may have been used
// before at a different size.
this->recalc (COLS, LINES);
}
}
////////////////////////////////////////////////////////////////////////////////
void UI::initialize ()
{
logWrite ("UI::initialize");
// Rainbow.
init_pair (1, COLOR_WHITE, COLOR_BLUE);
init_pair (2, COLOR_WHITE, COLOR_RED);
init_pair (3, COLOR_BLACK, COLOR_GREEN);
init_pair (4, COLOR_WHITE, COLOR_MAGENTA);
init_pair (5, COLOR_BLACK, COLOR_CYAN);
init_pair (6, COLOR_BLACK, COLOR_YELLOW);
init_pair (7, COLOR_BLACK, COLOR_WHITE);
init_pair (8, COLOR_CYAN, COLOR_BLUE);
init_pair (9, COLOR_BLUE, COLOR_CYAN);
init_pair (10, COLOR_YELLOW, COLOR_BLUE);
// init_pair (11, COLOR_GREEN, COLOR_BLACK);
// Plain.
init_pair (20, COLOR_WHITE, COLOR_BLACK);
// Propagate to current layout.
current->initialize ();
}
////////////////////////////////////////////////////////////////////////////////
void UI::deinitialize ()
{
logWrite ("UI::deinitialize");
current->deinitialize ();
}
////////////////////////////////////////////////////////////////////////////////
void UI::interactive ()
{
logWrite ("UI::interactive");
if (!current)
throw std::string ("Cannot start interactive mode without an initial layout.");
initscr ();
logWrite ("UI::interactive ncurses started");
refresh (); // Blank screen.
curs_set (0);
if (has_colors ())
start_color ();
this->recalc (COLS, LINES);
this->initialize ();
current->redraw ();
keypad (stdscr, TRUE);
noecho ();
nl ();
raw ();
cbreak ();
mousemask (ALL_MOUSE_EVENTS, NULL);
while (this->event (getch ()))
;
this->deinitialize ();
endwin ();
logWrite ("UI::interactive ncurses stopped");
}
////////////////////////////////////////////////////////////////////////////////
bool UI::event (int e)
{
switch (e)
{
case 'd': // Default layout
switchLayout ("default");
this->recalc (COLS, LINES);
current->redraw (true);
break;
case 's': // report.stats layout
switchLayout ("report.stats");
this->recalc (COLS, LINES);
current->redraw (true);
break;
case 'Q': // Quit.
case 'q': // quit.
logWrite ("UI::event %c", (char)e);
return false;
break;
case ERR: // No need to propagate this.
logWrite ("UI::event ERR ignored");
break;
case KEY_RESIZE: // This gets propagated through UI::recalc.
logWrite ("UI::event KEY_RESIZE");
this->recalc (COLS, LINES);
current->redraw (true); // TODO has no apparent effect.
break;
default: // Unhandled events are propagated.
// Ctrl-L is handled by the layout.
logWrite ("UI::event %d delegated", e);
current->event (e);
break;
}
return true; // Continue;
}
////////////////////////////////////////////////////////////////////////////////
// This is called at the beginning, to calculate element sizes, and on every
// window resize.
void UI::recalc (int w, int h)
{
logWrite ("UI::recalc %d,%d", w, h);
// The current layout needs to know.
current->recalc (w, h);
// Park the cursor.
// TODO Evaluate whether this is needed.
pthread_mutex_lock (&conch);
move (h - 1, w - 1);
pthread_mutex_unlock (&conch);
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,57 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_UI
#define INCLUDED_UI
#include <map>
#include <string>
#include "Layout.h"
class UI
{
public:
UI ();
UI (const UI&);
UI& operator= (const UI&);
~UI ();
void add (const std::string&, Layout*);
void switchLayout (const std::string&);
void initialize ();
void deinitialize ();
void interactive ();
void recalc (int, int);
bool event (int);
private:
std::map <std::string, Layout*> layouts;
Layout* current; // Points to one of the layouts.
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,132 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <sstream>
#include <string>
#include "Context.h"
#include "main.h"
#include "log.h"
#include "Layout.h"
#include "i18n.h"
#include "../cmake.h"
#ifdef HAVE_LIBNCURSES
#include <ncurses.h>
#endif
////////////////////////////////////////////////////////////////////////////////
int Context::handleInteractive ()
{
#ifdef HAVE_LIBNCURSES
// TODO Need to wrap all UI code with HAVE_LIBNCURSES.
// TODO Load this, and all others from .taskrc to override the defaults.
logSetDirectory (".");
logSetName ("task");
logDuplicates (false);
logEnable (false);
try
{
// TODO Ick. Clean this up.
std::string prefix = " (vertical (horizontal 2 (panel title *) (panel stats 22)) (horizontal 1 (panel message 60%) (panel clock *)) ";
std::string suffix = " (panel keys 2)))";
std::string layout_def = "(layout default" + prefix + "(panel report *)" + suffix;
std::string layout_report_stats = "(layout report.stats" + prefix + "(panel report.stats *)" + suffix;
UI ui; // Construct a UI coordinator.
createLayout (ui, "default", layout_def);
createLayout (ui, "report.stats", layout_report_stats);
ui.interactive (); // Start ncurses, event loop.
}
// TODO Integrate regular task error handling, using Context::debug.
catch (int e) { std::cout << e << "\n"; }
catch (const char* e) { std::cout << e << "\n"; }
catch (std::string& e) { std::cout << e << "\n"; }
catch (...) { std::cout << "Unknown error.\n"; }
logWrite ("---");
#else
throw std::string ("Interactive task is only available when built with "
"ncurses support.");
#endif
return 0;
}
////////////////////////////////////////////////////////////////////////////////
void Context::createLayout (
UI& ui,
const std::string& name,
const std::string& def)
{
// A layout named 'foo' can be overridden with a .taskrc config variable that
// is named 'layout.foo'.
std::string definition = config.get ("layout." + name);
if (definition == "")
definition = def;
Layout* l = new Layout (definition);
ui.add (name, l);
}
////////////////////////////////////////////////////////////////////////////////
int Context::getWidth ()
{
// Determine window size, and set table accordingly.
int width = config.getInteger ("defaultwidth");
#ifdef HAVE_LIBNCURSES
if (config.getBoolean ("curses"))
{
initscr ();
width = COLS;
endwin ();
std::stringstream out;
out << "Context::getWidth: ncurses determined width of " << width << " characters";
debug (out.str ());
}
else
debug ("Context::getWidth: ncurses available but disabled.");
#else
std::stringstream out;
out << "Context::getWidth: no ncurses, using width of " << width << " characters";
debug (out.str ());
#endif
return width;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,217 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <sys/file.h>
#include <sys/stat.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <string>
////////////////////////////////////////////////////////////////////////////////
// Global data.
static std::string gLogDir = ".";
static std::string gLogName = "default";
static bool gEnabled = true;
static const unsigned int maxMessageLength = 128;
static bool bDuplicates = false;
static std::string gPrior = "none";
static int gRepetitionCount = 0;
////////////////////////////////////////////////////////////////////////////////
void logSetDirectory (const std::string& dir)
{
gLogDir = dir;
}
////////////////////////////////////////////////////////////////////////////////
void logSetName (const std::string& name)
{
gLogName = name;
}
////////////////////////////////////////////////////////////////////////////////
void logEnable (const bool value)
{
gEnabled = value;
}
////////////////////////////////////////////////////////////////////////////////
void logDuplicates (const bool value)
{
bDuplicates = value;
}
////////////////////////////////////////////////////////////////////////////////
void getTimeStamp (std::string& ts)
{
// Get time info.
time_t now;
time (&now);
struct tm* t = localtime (&now);
// Generate timestamp.
char timestamp[20];
sprintf (timestamp, "%04d-%02d-%02d %02d:%02d:%02d",
t->tm_year + 1900,
t->tm_mon + 1,
t->tm_mday,
t->tm_hour,
t->tm_min,
t->tm_sec);
ts = timestamp;
}
////////////////////////////////////////////////////////////////////////////////
// #Version: 1.0
// #Date: 17-Oct-2004
// #Fields: date time x-pid x-message
// 2004-10-18 00:12:00 12345 "Message"
void logWrite (const std::string& message)
{
if (!gEnabled) return;
if (!bDuplicates)
{
if (message == gPrior)
{
++gRepetitionCount;
return;
}
else
gPrior = message;
}
// Get time info.
time_t now;
time (&now);
struct tm* t = localtime (&now);
// Sanitize 'message'.
std::string sanitized = message;
std::string::size_type bad;
while ((bad = sanitized.find ("\"")) != std::string::npos)
sanitized.replace (bad, 1, "'");
if (sanitized.length () > maxMessageLength)
sanitized = sanitized.substr (0, maxMessageLength) + "...";
// Generate timestamp.
char timestamp[20];
sprintf (timestamp, "%04d-%02d-%02d %02d:%02d:%02d",
t->tm_year + 1900,
t->tm_mon + 1,
t->tm_mday,
t->tm_hour,
t->tm_min,
t->tm_sec);
// Determine file name.
char file[_POSIX_PATH_MAX];
sprintf (file, "%s/%s.%04d%02d%02d.log",
gLogDir.c_str (),
gLogName.c_str (),
t->tm_year + 1900,
t->tm_mon + 1,
t->tm_mday);
// Determine whether file exists.
bool exists = access (file, F_OK) != -1 ? true : false;
// Create file if necessary, with header.
FILE* log = fopen (file, "a");
if (log)
{
// Lock file.
#if defined (__SVR4) && defined (__sun)
#else
int fn = fileno (log);
if (! flock (fn, LOCK_EX))
{
#endif
// Create the header, if the file did not exist.
if (! exists)
{
fprintf (log, "# File: %s.%04d%02d%02d.log\n",
gLogName.c_str (),
t->tm_year + 1900,
t->tm_mon + 1,
t->tm_mday);
fprintf (log, "# Fields: date time x-pid x-message\n");
}
// Optionally write a repetition message.
if (gRepetitionCount)
{
fprintf (log, "%s %d \"(Repeated %d times)\"\n",
timestamp,
(int) getpid (),
gRepetitionCount);
gRepetitionCount = 0;
}
// Write entry.
fprintf (log, "%s %d \"%s\"\n",
timestamp,
(int) getpid (),
sanitized.c_str ());
#if defined (__SVR4) && defined (__sun)
#else
}
#endif
// close file.
fclose (log);
if (! exists)
chmod (file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
}
}
////////////////////////////////////////////////////////////////////////////////
void logWrite (const char* message, ...)
{
if (!gEnabled) return;
// Crude and mostly ineffective check for buffer overrun.
if (::strlen (message) >= 65536)
throw std::string ("Data exceeds 65,536 bytes. Break data into smaller chunks.");
char buffer[65536];
va_list args;
va_start (args, message);
vsnprintf (buffer, 65536, message, args);
va_end (args);
logWrite (std::string (buffer));
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,42 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_LOG
#define INCLUDED_LOG
#include <string>
void logSetDirectory (const std::string&);
void logSetName (const std::string&);
void logEnable (const bool);
void logDuplicates (const bool);
void getTimeStamp (std::string&);
void logWrite (const std::string&);
void logWrite (const char*, ...);
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -1,284 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <map>
#include <vector>
#include <string>
#include <stdlib.h>
#include "Rectangle.h"
#include "Tree.h"
#include "Lisp.h"
static void recalcNode (Tree*, int, int, int, int);
static void distribute (const int, const std::vector <std::string>&, std::vector <int>&);
static void getRequests (Tree*, std::vector <std::string>&);
////////////////////////////////////////////////////////////////////////////////
void resize (
const std::string& input,
const int width,
const int height,
std::string& name,
std::map <std::string, Rectangle>& panels)
{
// Parse the input into a tree.
Lisp l;
Tree* root = l.parse (input);
// Navigate the tree and calculate sizes. This requires a breadth-first
// traversal, so that calculations at one level are then propagated down.
// After all, the window dimensions dictate the layout size, and so on down.
Tree* layout = (*root)[0];
layout->attribute ("left", 0);
layout->attribute ("top", 0);
layout->attribute ("width", width);
layout->attribute ("height", height);
recalcNode (layout, 0, 0, width, height);
// Extract the name of the layout.
std::vector <std::string> tags = layout->allTags ();
if (tags.size () >= 2)
name = tags[1];
else
name = "anonymous";
// Extract panels.
panels.clear ();
std::vector <Tree*> nodes;
layout->enumerate (nodes);
std::vector <Tree*>::iterator it;
for (it = nodes.begin (); it != nodes.end (); ++it)
{
tags = (*it)->allTags ();
if (tags[0] == "panel")
panels[tags[1]] =
Rectangle (
atoi ((*it)->attribute ("left").c_str ()),
atoi ((*it)->attribute ("top").c_str ()),
atoi ((*it)->attribute ("width").c_str ()),
atoi ((*it)->attribute ("height").c_str ()));
}
delete root;
}
////////////////////////////////////////////////////////////////////////////////
// Specified node has associated width and height. Subdivide either width or
// height across all tree branches depending on which container the parent is.
static void recalcNode (Tree* parent, int left, int top, int width, int height)
{
// What kind of parent is this? layout, horizontal or vertical?
std::string parent_type = "?";
std::vector <std::string> parent_tags = parent->allTags ();
if (parent_tags.size ())
parent_type = parent_tags[0];
else
throw std::string ("Error: node has no specified type");
if (parent_type == "horizontal")
{
std::vector <std::string> requested;
getRequests (parent, requested);
std::vector <int> allocated;
distribute (width, requested, allocated);
int current_left = left;
for (int i = 0; i < parent->branches (); ++i)
{
(*parent)[i]->attribute ("left", current_left);
(*parent)[i]->attribute ("top", top);
(*parent)[i]->attribute ("width", allocated[i]);
(*parent)[i]->attribute ("height", height);
current_left += allocated[i];
}
}
else if (parent_type == "vertical")
{
std::vector <std::string> requested;
getRequests (parent, requested);
std::vector <int> allocated;
distribute (height, requested, allocated);
int current_top = top;
for (int i = 0; i < parent->branches (); ++i)
{
(*parent)[i]->attribute ("left", left);
(*parent)[i]->attribute ("top", current_top);
(*parent)[i]->attribute ("width", width);
(*parent)[i]->attribute ("height", allocated[i]);
current_top += allocated[i];
}
}
else if (parent_type == "layout")
{
if (! (*parent)[0])
throw std::string ("Error: layout has no contents.");
(*parent)[0]->attribute ("left", left);
(*parent)[0]->attribute ("top", top);
(*parent)[0]->attribute ("width", width);
(*parent)[0]->attribute ("height", height);
}
// Now recurse to each branch of parent that is a container.
for (int i = 0; i < parent->branches (); ++i)
{
Tree* child = (*parent)[i];
if (child->hasTag ("horizontal") ||
child->hasTag ("vertical"))
{
recalcNode (child,
atoi (child->attribute ("left").c_str ()),
atoi (child->attribute ("top").c_str ()),
atoi (child->attribute ("width").c_str ()),
atoi (child->attribute ("height").c_str ()));
}
}
}
////////////////////////////////////////////////////////////////////////////////
// If the call looks like this:
// distribute (60, [10, *, *, *, *, *, 50%], [])
//
// Then the result is:
// distribute (60, [10, *, 50%], [10, 5, 5, 5, 5, 5, 25])
//
// A literal number is a request. It will be granted, provided there is space.
// A percentage is a request for a portion of the unallocated amount.
// A wildcard is a request for an equal share, among all wildcards, of the
// unallocated amount.
//
static void distribute (
const int total,
const std::vector <std::string>& input,
std::vector <int>& output)
{
int allocated = 0;
int unallocated = total;
output.clear ();
// First count up the requested.
for (unsigned int i = 0; i < input.size (); ++i)
if (input[i] == "*" || input[i].find ("%") != std::string::npos)
output.push_back (0);
else
{
int value = atoi (input[i].c_str ());
output.push_back (value);
allocated += value;
unallocated -= value;
}
if (allocated > total)
throw std::string ("Error: over allocation by request.");
// Now include the proportional.
int before_allocated = allocated;
for (unsigned int i = 0; i < input.size (); ++i)
{
if (input[i].find ("%") != std::string::npos)
{
int value = atoi (input[i].c_str ());
value = (value * unallocated) / 100;
output[i] = value;
allocated += value;
}
}
unallocated -= (allocated - before_allocated);
if (allocated > total)
throw std::string ("Error: over allocation by request.");
// Count the wildcards.
int wildcards = 0;
for (unsigned int i = 0; i < input.size (); ++i)
if (input[i] == "*")
++wildcards;
// Evenly distribute unallocated among the wildcards.
for (unsigned int i = 0; i < input.size (); ++i)
{
if (input[i] == "*")
{
if (wildcards > 1)
{
int portion = unallocated / wildcards;
--wildcards;
output[i] = portion;
allocated += portion;
unallocated -= portion;
}
else
{
output[i] = unallocated;
allocated += unallocated;
unallocated = 0;
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
static void getRequests (Tree* node, std::vector <std::string>& requested)
{
requested.clear ();
for (int i = 0; i < node->branches (); ++i)
{
Tree* child = (*node)[i];
std::vector <std::string> child_tags = child->allTags ();
switch (child_tags.size ())
{
case 1: // (xcontainer (...))
requested.push_back ("*");
break;
case 2: // (xcontainer size (...))
requested.push_back (child_tags[1]);
break;
case 3: // (panel name size)
requested.push_back (child_tags[2]);
break;
default:
throw std::string ("Error: unexpected number of tags in a node");
break;
}
}
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -6,8 +6,7 @@ include_directories (${CMAKE_SOURCE_DIR}/src
set (test_SRCS date.t t.t tdb.t duration.t t.benchmark.t text.t autocomplete.t
seq.t record.t att.t subst.t nibbler.t filt.t cmd.t config.t
util.t color.t list.t path.t file.t grid.t directory.t rx.t
taskmod.t lisp.t rectangle.t sensor.t tree.t tree2.t uri.t
json.t)
taskmod.t lisp.t rectangle.t tree.t tree2.t uri.t json.t)
add_custom_target (test ./run_all DEPENDS ${test_SRCS}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/test)

View file

@ -1,84 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2010 - 2011, Paul Beckingham, Federico Hernandez, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <fstream>
#include <unistd.h>
#include "Context.h"
#include "Sensor.h"
#include "test.h"
Context context;
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
UnitTest ut (7);
// Make sure there is no file.
unlink ("./sensor.foo");
// Create sensor for missing file.
Sensor s;
s.fileModification ("./sensor.foo");
ut.ok (!s.changed (), "file not yet changed");
// Create the file.
std::ofstream one ("./sensor.foo", std::ios_base::out | std::ios_base::app);
if (one.good ())
{
one << "touch\n";
one.close ();
}
// Should register the change, so reset.
ut.ok (s.changed (), "file changed");
s.reset ();
ut.ok (!s.changed (), "file not yet changed");
// Wait a little, then modify the file.
ut.diag ("sleep 2");
sleep (2);
std::ofstream two ("./sensor.foo", std::ios_base::out | std::ios_base::app);
if (two.good ())
{
two << "touch\n";
two.close ();
}
ut.ok (s.changed (), "file changed");
ut.ok (s.changed (), "file still changed");
s.reset ();
ut.ok (!s.changed (), "file not changed again");
unlink ("./sensor.foo");
ut.ok (s.changed (), "file changed");
return 0;
}
////////////////////////////////////////////////////////////////////////////////