mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
View
- Integrated ViewTask and ViewText completely. - Obsoleted Table.{h,cpp}, Grid.{h,cpp}, grid.t.cpp - Fixed ViewTask rendering bug that caused the full width to be used every time.
This commit is contained in:
parent
c8c7e02bc8
commit
6fb3bc5b03
14 changed files with 208 additions and 2002 deletions
|
@ -16,7 +16,6 @@ set (task_SRCS API.cpp API.h
|
|||
Duration.cpp Duration.h
|
||||
File.cpp File.h
|
||||
Filter.cpp Filter.h
|
||||
Grid.cpp Grid.h
|
||||
Hooks.cpp Hooks.h
|
||||
JSON.cpp JSON.h
|
||||
Location.cpp Location.h
|
||||
|
@ -29,7 +28,6 @@ set (task_SRCS API.cpp API.h
|
|||
Subst.cpp Subst.h
|
||||
TDB.cpp TDB.h
|
||||
TDB2.cpp TDB2.h
|
||||
Table.cpp Table.h
|
||||
Task.cpp Task.h
|
||||
Taskmod.cpp Taskmod.h
|
||||
Timer.cpp Timer.h
|
||||
|
|
421
src/Grid.cpp
421
src/Grid.cpp
|
@ -1,421 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - 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
|
||||
//
|
||||
//
|
||||
//
|
||||
// Grid implements a sparse 2D array of Cell objects. Grid makes every effort
|
||||
// to perform well on cell insertion and retrieval. A Cell is a variant type,
|
||||
// capable of storing char, bool, int, float, double and std::string types.
|
||||
//
|
||||
// Every cell is accessible from both mColumns and mRows. This allows the
|
||||
// client code to specify which method is used, because there will be a
|
||||
// performance penalty with one of the methods, depending on the layout of
|
||||
// cells within the grid.
|
||||
//
|
||||
// mColumns, like mRows, is a vector of a vector of Cell*.
|
||||
//
|
||||
// mColumns
|
||||
// [0..n]
|
||||
// +---+---+-----------+---+
|
||||
// | 0 | 1 | | n |
|
||||
// +---+---+-----------+---+
|
||||
// | |
|
||||
// v |
|
||||
// +---+ . +---+ . | .
|
||||
// mRows | 0 | -------> | x | v
|
||||
// [0..1] +---+ . +---+ +---+
|
||||
// | 1 | -------> | y | --------> | z |
|
||||
// +---+ . +---+ +---+
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// +---+ . . . . .
|
||||
// | n |
|
||||
// +---+ . . . . .
|
||||
//
|
||||
//
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <text.h>
|
||||
#include <Grid.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Grid::Grid ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The cells are deleted via their mRows reference, not by their mColumns
|
||||
// reference. This is because the cells are doubly-linked, and so the
|
||||
// convention is that rows own cells, columns merely own pointers.
|
||||
Grid::~Grid ()
|
||||
{
|
||||
std::vector < std::vector <Cell*>* >::iterator row;
|
||||
std::vector <Cell*>::iterator col;
|
||||
for (row = mRows.begin (); row != mRows.end (); ++row)
|
||||
if (*row)
|
||||
for (col = (*row)->begin (); col != (*row)->end (); ++col)
|
||||
if (*col)
|
||||
delete *col;
|
||||
|
||||
std::vector < std::vector <Cell*>* >::iterator it;
|
||||
for (it = mRows.begin (); it != mRows.end (); ++it)
|
||||
if (*it)
|
||||
delete *it;
|
||||
|
||||
for (it = mColumns.begin (); it != mColumns.end (); ++it)
|
||||
if (*it)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Grid::add (
|
||||
const unsigned int row,
|
||||
const unsigned int col,
|
||||
const bool value)
|
||||
{
|
||||
expandGrid (row, col);
|
||||
insertCell (row, col, new Cell (value));
|
||||
}
|
||||
|
||||
void Grid::add (
|
||||
const unsigned int row,
|
||||
const unsigned int col,
|
||||
const char value)
|
||||
{
|
||||
expandGrid (row, col);
|
||||
insertCell (row, col, new Cell (value));
|
||||
}
|
||||
|
||||
void Grid::add (
|
||||
const unsigned int row,
|
||||
const unsigned int col,
|
||||
const int value)
|
||||
{
|
||||
expandGrid (row, col);
|
||||
insertCell (row, col, new Cell (value));
|
||||
}
|
||||
|
||||
void Grid::add (
|
||||
const unsigned int row,
|
||||
const unsigned int col,
|
||||
const float value)
|
||||
{
|
||||
expandGrid (row, col);
|
||||
insertCell (row, col, new Cell (value));
|
||||
}
|
||||
|
||||
void Grid::add (
|
||||
const unsigned int row,
|
||||
const unsigned int col,
|
||||
const double value)
|
||||
{
|
||||
expandGrid (row, col);
|
||||
insertCell (row, col, new Cell (value));
|
||||
}
|
||||
|
||||
void Grid::add (
|
||||
const unsigned int row,
|
||||
const unsigned int col,
|
||||
const char* value)
|
||||
{
|
||||
expandGrid (row, col);
|
||||
insertCell (row, col, new Cell (std::string (value)));
|
||||
}
|
||||
|
||||
void Grid::add (
|
||||
const unsigned int row,
|
||||
const unsigned int col,
|
||||
const std::string& value)
|
||||
{
|
||||
expandGrid (row, col);
|
||||
insertCell (row, col, new Cell (value));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned int Grid::width () const
|
||||
{
|
||||
return mColumns.size ();
|
||||
}
|
||||
|
||||
unsigned int Grid::height () const
|
||||
{
|
||||
return mRows.size ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Grid::Cell* Grid::byRow (const unsigned int row, const unsigned int col) const
|
||||
{
|
||||
if (row < mRows.size () &&
|
||||
mRows[row] != NULL &&
|
||||
col < mRows[row]->size ())
|
||||
return (*mRows[row])[col];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Grid::Cell* Grid::byColumn (const unsigned int row, const unsigned int col) const
|
||||
{
|
||||
if (col < mColumns.size () &&
|
||||
mColumns[col] != NULL &&
|
||||
row < mColumns[col]->size ())
|
||||
return (*mColumns[col])[row];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Grid::expandGrid (const unsigned int row, const unsigned int col)
|
||||
{
|
||||
|
||||
// If the new row is outside the bounds of the current grid, add blank rows to
|
||||
// pad, then a new row vector.
|
||||
if (row >= mRows.size ())
|
||||
{
|
||||
for (unsigned int r = mRows.size (); r <= row; ++r)
|
||||
if (r < row)
|
||||
mRows.push_back (NULL);
|
||||
else
|
||||
mRows.push_back (new std::vector <Cell*>);
|
||||
}
|
||||
// If the new row is within the bounds of the current grid, ensure that the
|
||||
// row points to a vector of cells.
|
||||
else if (mRows[row] == NULL)
|
||||
mRows[row] = new std::vector <Cell*>;
|
||||
|
||||
if (col >= mRows[row]->size ())
|
||||
for (unsigned int c = mRows[row]->size (); c <= col; ++c)
|
||||
mRows[row]->push_back (NULL);
|
||||
|
||||
// If the new col is outside the bounds of the current grid, add blank cols to
|
||||
// pad, then a new col vector.
|
||||
if (col >= mColumns.size ())
|
||||
{
|
||||
for (unsigned int c = mColumns.size (); c <= col; ++c)
|
||||
if (c < col)
|
||||
mColumns.push_back (NULL);
|
||||
else
|
||||
mColumns.push_back (new std::vector <Cell*>);
|
||||
}
|
||||
// If the new col is within the bounds of the current grid, ensure that the
|
||||
// col points to a vector of cells.
|
||||
else if (mColumns[col] == NULL)
|
||||
mColumns[col] = new std::vector <Cell*>;
|
||||
|
||||
if (row >= mColumns[col]->size ())
|
||||
for (unsigned int r = mColumns[col]->size (); r <= row; ++r)
|
||||
mColumns[col]->push_back (NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Grid::insertCell (
|
||||
const unsigned int row,
|
||||
const unsigned int col,
|
||||
Cell* cell)
|
||||
{
|
||||
// Delete any existing cell, because cells are owned by rows, not columns.
|
||||
if ((*mRows[row])[col] != NULL)
|
||||
delete (*mRows[row])[col];
|
||||
|
||||
(*mRows[row])[col] = cell;
|
||||
(*mColumns[col])[row] = cell;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Grid::Cell::Cell (const bool value)
|
||||
: mType (CELL_BOOL)
|
||||
, mBool (value)
|
||||
{
|
||||
}
|
||||
|
||||
Grid::Cell::Cell (const char value)
|
||||
: mType (CELL_CHAR)
|
||||
, mChar (value)
|
||||
{
|
||||
}
|
||||
|
||||
Grid::Cell::Cell (const int value)
|
||||
: mType (CELL_INT)
|
||||
, mInt (value)
|
||||
{
|
||||
}
|
||||
|
||||
Grid::Cell::Cell (const float value)
|
||||
: mType (CELL_FLOAT)
|
||||
, mFloat (value)
|
||||
{
|
||||
}
|
||||
|
||||
Grid::Cell::Cell (const double value)
|
||||
: mType (CELL_DOUBLE)
|
||||
, mDouble (value)
|
||||
{
|
||||
}
|
||||
|
||||
Grid::Cell::Cell (const std::string& value)
|
||||
: mType (CELL_STRING)
|
||||
, mString (value)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// These cast operators make a best approximation to an appropriate rendering,
|
||||
// given the format change.
|
||||
Grid::Cell::operator bool () const
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case CELL_BOOL: return mBool;
|
||||
case CELL_CHAR: return mChar != '\0' &&
|
||||
mChar != ' ' &&
|
||||
mChar != '0';
|
||||
case CELL_INT: return mInt != 0;
|
||||
case CELL_FLOAT: return mFloat != 0.0;
|
||||
case CELL_DOUBLE: return mDouble != 0.0;
|
||||
case CELL_STRING: return mString.length () > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Grid::Cell::operator char () const
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case CELL_BOOL: return mBool ? 'Y' : 'N'; // TODO i18n
|
||||
case CELL_CHAR: return mChar;
|
||||
case CELL_INT: return (char) mInt;
|
||||
case CELL_FLOAT: return (char) (int) mFloat;
|
||||
case CELL_DOUBLE: return (char) (int) mDouble;
|
||||
case CELL_STRING: return mString[0];
|
||||
}
|
||||
|
||||
return '\0';
|
||||
}
|
||||
|
||||
Grid::Cell::operator int () const
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case CELL_BOOL: return mBool ? 1 : 0;
|
||||
case CELL_CHAR: return (int) mChar;
|
||||
case CELL_INT: return mInt;
|
||||
case CELL_FLOAT: return (int) mFloat;
|
||||
case CELL_DOUBLE: return (int) mDouble;
|
||||
case CELL_STRING: return atoi (mString.c_str ());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Grid::Cell::operator float () const
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case CELL_BOOL: return mBool ? 1.0 : 0.0;
|
||||
case CELL_CHAR: return (float) (int) mChar;
|
||||
case CELL_INT: return (float) mInt;
|
||||
case CELL_FLOAT: return mFloat;
|
||||
case CELL_DOUBLE: return (float) mDouble;
|
||||
case CELL_STRING: return (float) atof (mString.c_str ());
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
Grid::Cell::operator double () const
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case CELL_BOOL: return mBool ? 1.0 : 0.0;
|
||||
case CELL_CHAR: return (double) (int) mChar;
|
||||
case CELL_INT: return (double) mInt;
|
||||
case CELL_FLOAT: return (double) mFloat;
|
||||
case CELL_DOUBLE: return mDouble;
|
||||
case CELL_STRING: return (double) atof (mString.c_str ());
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
Grid::Cell::operator std::string () const
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case CELL_BOOL: return mBool ? "true" : "false"; // TODO i18n
|
||||
case CELL_CHAR: return format (mChar);
|
||||
case CELL_INT: return format (mInt);
|
||||
case CELL_FLOAT: return format (mFloat, 1, 6);
|
||||
case CELL_DOUBLE: return format (mDouble, 1, 8);
|
||||
case CELL_STRING: return mString;
|
||||
}
|
||||
|
||||
return std::string ("");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Grid::Cell::operator== (const Grid::Cell& rhs) const
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case CELL_BOOL: return mBool == rhs.mBool ? true : false;
|
||||
case CELL_CHAR: return mChar == rhs.mChar ? true : false;
|
||||
case CELL_INT: return mInt == rhs.mInt ? true : false;
|
||||
case CELL_FLOAT: return mFloat == rhs.mFloat ? true : false;
|
||||
case CELL_DOUBLE: return mDouble == rhs.mDouble ? true : false;
|
||||
case CELL_STRING: return mString == rhs.mString ? true : false;
|
||||
default: break; // To prevent warnings.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Grid::Cell::operator!= (const Grid::Cell& rhs) const
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case CELL_BOOL: return mBool != rhs.mBool ? true : false;
|
||||
case CELL_CHAR: return mChar != rhs.mChar ? true : false;
|
||||
case CELL_INT: return mInt != rhs.mInt ? true : false;
|
||||
case CELL_FLOAT: return mFloat != rhs.mFloat ? true : false;
|
||||
case CELL_DOUBLE: return mDouble != rhs.mDouble ? true : false;
|
||||
case CELL_STRING: return mString != rhs.mString ? true : false;
|
||||
default: break; // To prevent warnings.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Grid::Cell::cellType Grid::Cell::type () const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
106
src/Grid.h
106
src/Grid.h
|
@ -1,106 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - 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_GRID
|
||||
#define INCLUDED_GRID
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class Grid
|
||||
{
|
||||
public:
|
||||
class Cell
|
||||
{
|
||||
public:
|
||||
Cell (const bool);
|
||||
Cell (const char);
|
||||
Cell (const int);
|
||||
Cell (const float);
|
||||
Cell (const double);
|
||||
Cell (const std::string&);
|
||||
|
||||
Cell (const Cell&);
|
||||
Cell& operator= (const Cell&);
|
||||
|
||||
operator bool () const;
|
||||
operator char () const;
|
||||
operator int () const;
|
||||
operator float () const;
|
||||
operator double () const;
|
||||
operator std::string () const;
|
||||
bool operator== (const Cell&) const;
|
||||
bool operator!= (const Cell&) const;
|
||||
|
||||
enum cellType {CELL_BOOL, CELL_CHAR, CELL_INT, CELL_FLOAT, CELL_DOUBLE, CELL_STRING};
|
||||
|
||||
cellType type () const;
|
||||
|
||||
private:
|
||||
cellType mType;
|
||||
bool mBool;
|
||||
char mChar;
|
||||
int mInt;
|
||||
float mFloat;
|
||||
double mDouble;
|
||||
std::string mString;
|
||||
};
|
||||
|
||||
public:
|
||||
Grid ();
|
||||
~Grid ();
|
||||
|
||||
Grid (const Grid&);
|
||||
Grid& operator= (const Grid&);
|
||||
|
||||
void add (const unsigned int, const unsigned int, const bool);
|
||||
void add (const unsigned int, const unsigned int, const char);
|
||||
void add (const unsigned int, const unsigned int, const int);
|
||||
void add (const unsigned int, const unsigned int, const float);
|
||||
void add (const unsigned int, const unsigned int, const double);
|
||||
void add (const unsigned int, const unsigned int, const char*);
|
||||
void add (const unsigned int, const unsigned int, const std::string&);
|
||||
|
||||
unsigned int width () const;
|
||||
unsigned int height () const;
|
||||
|
||||
Cell* byRow (const unsigned int, const unsigned int) const;
|
||||
Cell* byColumn (const unsigned int, const unsigned int) const;
|
||||
|
||||
private:
|
||||
void expandGrid (const unsigned int, const unsigned int);
|
||||
void insertCell (const unsigned int, const unsigned int, Cell*);
|
||||
|
||||
private:
|
||||
std::vector < std::vector <Cell*>* > mRows;
|
||||
std::vector < std::vector <Cell*>* > mColumns;
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
139
src/TDB2.cpp
139
src/TDB2.cpp
|
@ -284,7 +284,7 @@ void TDB2::commit ()
|
|||
#include "TDB.h"
|
||||
#include "Directory.h"
|
||||
#include "File.h"
|
||||
#include "Table.h"
|
||||
#include "ViewText.h"
|
||||
#include "Timer.h"
|
||||
#include "Color.h"
|
||||
#include "main.h"
|
||||
|
@ -1000,24 +1000,12 @@ void TDB::undo ()
|
|||
|
||||
// Attributes are all there is, so figure the different attribute names
|
||||
// between before and after.
|
||||
Table table;
|
||||
table.setTableWidth (context.getWidth ());
|
||||
table.setTableIntraPadding (2);
|
||||
table.addColumn (" ");
|
||||
table.addColumn ("Prior Values");
|
||||
table.addColumn ("Current Values");
|
||||
|
||||
if (context.color () && context.config.getBoolean ("fontunderline"))
|
||||
{
|
||||
table.setColumnUnderline (1);
|
||||
table.setColumnUnderline (2);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::flexible);
|
||||
table.setColumnWidth (2, Table::flexible);
|
||||
ViewText view;
|
||||
view.width (context.getWidth ());
|
||||
view.intraPadding (2);
|
||||
view.add (Column::factory ("string", ""));
|
||||
view.add (Column::factory ("string", "Prior Values"));
|
||||
view.add (Column::factory ("string", "Current Values"));
|
||||
|
||||
Task after (current);
|
||||
|
||||
|
@ -1040,10 +1028,9 @@ void TDB::undo ()
|
|||
int row;
|
||||
foreach (name, beforeOnly)
|
||||
{
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, *name);
|
||||
table.addCell (row, 1, renderAttribute (*name, before.get (*name)));
|
||||
table.setCellColor (row, 1, color_red);
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, *name, red);
|
||||
view.set (row, 1, renderAttribute (*name, before.get (*name)), red);
|
||||
}
|
||||
|
||||
foreach (name, before)
|
||||
|
@ -1053,25 +1040,18 @@ void TDB::undo ()
|
|||
|
||||
if (currentValue != "")
|
||||
{
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, name->first);
|
||||
table.addCell (row, 1, renderAttribute (name->first, priorValue));
|
||||
table.addCell (row, 2, renderAttribute (name->first, currentValue));
|
||||
|
||||
if (priorValue != currentValue)
|
||||
{
|
||||
table.setCellColor (row, 1, color_red);
|
||||
table.setCellColor (row, 2, color_green);
|
||||
}
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, name->first);
|
||||
view.set (row, 1, renderAttribute (name->first, priorValue), priorValue != currentValue ? color_red : color_green);
|
||||
view.set (row, 2, renderAttribute (name->first, currentValue), priorValue != currentValue ? color_red : color_green);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (name, afterOnly)
|
||||
{
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, *name);
|
||||
table.addCell (row, 2, renderAttribute (*name, after.get (*name)));
|
||||
table.setCellColor (row, 2, color_green);
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, *name);
|
||||
view.set (row, 2, renderAttribute (*name, after.get (*name)), color_green);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1079,15 +1059,14 @@ void TDB::undo ()
|
|||
int row;
|
||||
foreach (name, after)
|
||||
{
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, name->first);
|
||||
table.addCell (row, 2, renderAttribute (name->first, after.get (name->first)));
|
||||
table.setCellColor (row, 2, color_green);
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, name->first);
|
||||
view.set (row, 2, renderAttribute (name->first, after.get (name->first)), color_green);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\n"
|
||||
<< table.render ()
|
||||
<< view.render ()
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
|
@ -1114,27 +1093,21 @@ void TDB::undo ()
|
|||
Task after (current);
|
||||
|
||||
// Generate table header.
|
||||
Table table;
|
||||
table.setTableWidth (context.getWidth ());
|
||||
table.setTableIntraPadding (2);
|
||||
table.addColumn (" ");
|
||||
table.addColumn (" ");
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::flexible);
|
||||
table.setColumnJustification (0, Table::right);
|
||||
table.setColumnJustification (1, Table::left);
|
||||
ViewText view
|
||||
view.width (context.getWidth ());
|
||||
view.intraPadding (2);
|
||||
view.addColumn (Column::factory ("string.right", ""));
|
||||
view.addColumn (Column::factory ("string", ""));
|
||||
|
||||
int row = table.addRow ();
|
||||
table.addCell (row, 0, "--- previous state");
|
||||
table.addCell (row, 1, "Undo will restore this state");
|
||||
table.setRowColor (row, color_red);
|
||||
int row = view.addRow ();
|
||||
view.set (row, 0, "--- previous state", color_red);
|
||||
view.set (row, 1, "Undo will restore this state", color_red);
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, "+++ current state "); // Note trailing space.
|
||||
table.addCell (row, 1, "Change made " + lastChange.toString (context.config.get ("dateformat")));
|
||||
table.setRowColor (row, color_green);
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, "+++ current state ", color_green); // Note trailing space.
|
||||
view.set (row, 1, "Change made " + lastChange.toString (context.config.get ("dateformat")), color_green);
|
||||
|
||||
table.addRow ();
|
||||
view.addRow ();
|
||||
|
||||
// Add rows to table showing diffs.
|
||||
std::vector <std::string> all;
|
||||
|
@ -1172,55 +1145,49 @@ void TDB::undo ()
|
|||
{
|
||||
// Show nothing - no point displaying that which did not change.
|
||||
|
||||
// row = table.addRow ();
|
||||
// table.addCell (row, 0, *a + ":");
|
||||
// table.addCell (row, 1, before_att);
|
||||
// row = view.addRow ();
|
||||
// view.set (row, 0, *a + ":");
|
||||
// view.set (row, 1, before_att);
|
||||
}
|
||||
|
||||
// Attribute deleted.
|
||||
else if (before_att != "" && after_att == "")
|
||||
{
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, "-" + *a + ":");
|
||||
table.addCell (row, 1, before_att);
|
||||
table.setRowColor (row, color_red);
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, "-" + *a + ":", color_red);
|
||||
view.set (row, 1, before_att, color_red);
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, "+" + *a + ":");
|
||||
table.setRowColor (row, color_green);
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, "+" + *a + ":", color_green);
|
||||
}
|
||||
|
||||
// Attribute added.
|
||||
else if (before_att == "" && after_att != "")
|
||||
{
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, "-" + *a + ":");
|
||||
table.setRowColor (row, color_red);
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, "-" + *a + ":", color_red);
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, "+" + *a + ":");
|
||||
table.addCell (row, 1, after_att);
|
||||
table.setRowColor (row, color_green);
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, "+" + *a + ":", color_green);
|
||||
view.set (row, 1, after_att, color_green);
|
||||
}
|
||||
|
||||
// Attribute changed.
|
||||
else
|
||||
{
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, "-" + *a + ":");
|
||||
table.addCell (row, 1, before_att);
|
||||
table.setRowColor (row, color_red);
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, "-" + *a + ":", color_red);
|
||||
view.set (row, 1, before_att, color_red);
|
||||
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, "+" + *a + ":");
|
||||
table.addCell (row, 1, after_att);
|
||||
table.setRowColor (row, color_green);
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, "+" + *a + ":", color_green);
|
||||
view.set (row, 1, after_att, color_green);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\n"
|
||||
<< table.render ()
|
||||
<< view.render ()
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
|
|
895
src/Table.cpp
895
src/Table.cpp
|
@ -1,895 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - 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
|
||||
//
|
||||
//
|
||||
//
|
||||
// Attributes Table Row Column Cell
|
||||
// ----------------------------------------------------
|
||||
// foreground color Y Y Y Y
|
||||
// background color Y Y Y Y
|
||||
// padding Y Y Y Y
|
||||
// wrap Y Y Y Y
|
||||
// width Y - Y Y
|
||||
// height - Y - Y
|
||||
// justification Y Y Y Y
|
||||
//
|
||||
// Precedence
|
||||
// If attributes conflict, the precedence order is:
|
||||
// cell
|
||||
// row
|
||||
// column
|
||||
// table
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include "Table.h"
|
||||
#include "Date.h"
|
||||
#include "Duration.h"
|
||||
#include "Timer.h"
|
||||
#include "text.h"
|
||||
#include "utf8.h"
|
||||
#include "util.h"
|
||||
#include "Context.h"
|
||||
|
||||
extern Context context;
|
||||
Table* table = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Table::Table ()
|
||||
: mRows (0)
|
||||
, mIntraPadding (1)
|
||||
, mDashedUnderline (false)
|
||||
, mTablePadding (0)
|
||||
, mTableWidth (0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Table::~Table ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setTableAlternateColor (const Color& c)
|
||||
{
|
||||
alternate = c;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setTablePadding (int padding)
|
||||
{
|
||||
mTablePadding = padding;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setTableIntraPadding (int padding)
|
||||
{
|
||||
mIntraPadding = padding;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setTableWidth (int width)
|
||||
{
|
||||
assert (width > 0);
|
||||
mTableWidth = width;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setTableDashedUnderline ()
|
||||
{
|
||||
mDashedUnderline = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Table::addColumn (const std::string& col)
|
||||
{
|
||||
mSpecifiedWidth.push_back (minimum);
|
||||
mMaxDataWidth.push_back (col == "" ? 1 : utf8_length (col));
|
||||
mCalculatedWidth.push_back (0);
|
||||
mColumnPadding.push_back (0);
|
||||
|
||||
mColumns.push_back (col == "" ? " " : col);
|
||||
return mColumns.size () - 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setColumnUnderline (int column)
|
||||
{
|
||||
char id[12];
|
||||
sprintf (id, "col:%d", column);
|
||||
mUnderline[id] = Color (Color::nocolor, Color::nocolor, true, false, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setColumnPadding (int column, int padding)
|
||||
{
|
||||
mColumnPadding[column] = padding;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setColumnWidth (int column, int width)
|
||||
{
|
||||
assert (width > 0);
|
||||
mSpecifiedWidth[column] = width;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setColumnWidth (int column, sizing s)
|
||||
{
|
||||
mSpecifiedWidth[column] = (int) s;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setColumnCommify (int column)
|
||||
{
|
||||
mCommify[column] = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setColumnJustification (int column, just j)
|
||||
{
|
||||
mJustification[column] = j;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::sortOn (int column, order o)
|
||||
{
|
||||
mSortColumns.push_back (column);
|
||||
mSortOrder[column] = o;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Table::addRow ()
|
||||
{
|
||||
return mRows++;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setRowColor (const int row, const Color& c)
|
||||
{
|
||||
char id[12];
|
||||
sprintf (id, "row:%d", row);
|
||||
mColor[id].blend (c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::addCell (const int row, const int col, const std::string& data)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
if (mCommify.find (col) != mCommify.end ())
|
||||
mData.add (row, col, commify (data));
|
||||
else
|
||||
mData.add (row, col, data);
|
||||
|
||||
// For multi-line cells, find the longest line.
|
||||
if (data.find ("\n") != std::string::npos)
|
||||
{
|
||||
length = 0;
|
||||
std::vector <std::string> lines;
|
||||
split (lines, data, "\n");
|
||||
for (unsigned int i = 0; i < lines.size (); ++i)
|
||||
if (utf8_length (lines[i]) > length)
|
||||
length = utf8_length (lines[i]);
|
||||
}
|
||||
else
|
||||
length = utf8_length (data);
|
||||
|
||||
// Automatically maintain max width.
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], length);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::addCell (const int row, const int col, const char data)
|
||||
{
|
||||
mData.add (row, col, data);
|
||||
|
||||
// Automatically maintain max width.
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::addCell (const int row, const int col, const int data)
|
||||
{
|
||||
char value[12];
|
||||
sprintf (value, "%d", data);
|
||||
|
||||
if (mCommify.find (col) != mCommify.end ())
|
||||
mData.add (row, col, commify (value));
|
||||
else
|
||||
mData.add (row, col, value);
|
||||
|
||||
// Automatically maintain max width.
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], (signed) strlen (value));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::addCell (const int row, const int col, const float data)
|
||||
{
|
||||
char value[24];
|
||||
sprintf (value, "%.2f", data);
|
||||
|
||||
if (mCommify.find (col) != mCommify.end ())
|
||||
mData.add (row, col, commify (value));
|
||||
else
|
||||
mData.add (row, col, value);
|
||||
|
||||
// Automatically maintain max width.
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], (signed) strlen (value));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::addCell (const int row, const int col, const double data)
|
||||
{
|
||||
char value[24];
|
||||
sprintf (value, "%.6f", data);
|
||||
|
||||
if (mCommify.find (col) != mCommify.end ())
|
||||
mData.add (row, col, commify (value));
|
||||
else
|
||||
mData.add (row, col, value);
|
||||
|
||||
// Automatically maintain max width.
|
||||
mMaxDataWidth[col] = max (mMaxDataWidth[col], (signed) strlen (value));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setCellColor (const int row, const int col, const Color& c)
|
||||
{
|
||||
char id[24];
|
||||
sprintf (id, "cell:%d,%d", row, col);
|
||||
mColor[id] = c;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string Table::getCell (const int row, const int col)
|
||||
{
|
||||
Grid::Cell* c = mData.byRow (row, col);
|
||||
if (c)
|
||||
return (std::string) *c;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color Table::getColor (const int index, const int row, const int col)
|
||||
{
|
||||
// Color defaults to trivial.
|
||||
Color c;
|
||||
|
||||
// For alternating rows, use Table::alternate.
|
||||
std::map <std::string, Color>::iterator i;
|
||||
char id[24];
|
||||
|
||||
if (index % 2)
|
||||
c = alternate;
|
||||
|
||||
// Blend with a row color, if specified.
|
||||
sprintf (id, "row:%d", row);
|
||||
if ((i = mColor.find (id)) != mColor.end ())
|
||||
c.blend (i->second);
|
||||
|
||||
// Blend with a cell color, if specified.
|
||||
sprintf (id, "cell:%d,%d", row, col);
|
||||
if ((i = mColor.find (id)) != mColor.end ())
|
||||
c.blend (i->second);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Color Table::getHeaderUnderline (int col)
|
||||
{
|
||||
char idCol[12];
|
||||
sprintf (idCol, "col:%d", col);
|
||||
|
||||
return mUnderline.find (idCol) != mUnderline.end () ? mUnderline[idCol]
|
||||
: Color ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Table::getIntraPadding ()
|
||||
{
|
||||
return mIntraPadding;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Table::getPadding (int col)
|
||||
{
|
||||
return max (mColumnPadding[col], mTablePadding);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Using mSpecifiedWidth, mMaxDataWidth, generate mCalculatedWidth.
|
||||
void Table::calculateColumnWidths ()
|
||||
{
|
||||
// Ideal case: either no table width is specified, or everything fits without
|
||||
// wrapping into mTableWidth.
|
||||
std::vector <int> ideal = mMaxDataWidth;
|
||||
int width = 0;
|
||||
int countFlexible = 0;
|
||||
for (size_t c = 0; c < mColumns.size (); ++c)
|
||||
{
|
||||
if (mSpecifiedWidth[c] == flexible)
|
||||
++countFlexible;
|
||||
|
||||
else if (mSpecifiedWidth[c] > 0)
|
||||
ideal[c] = mSpecifiedWidth[c];
|
||||
|
||||
width += mColumnPadding[c] +
|
||||
ideal[c] +
|
||||
mColumnPadding[c] +
|
||||
(c > 0 ? mIntraPadding : 0);
|
||||
}
|
||||
|
||||
if (!mTableWidth || width < mTableWidth)
|
||||
{
|
||||
mCalculatedWidth = ideal;
|
||||
return;
|
||||
}
|
||||
|
||||
// Try again, with available space divided among the flexible columns.
|
||||
if (countFlexible)
|
||||
{
|
||||
ideal = mMaxDataWidth;
|
||||
width = 0;
|
||||
for (size_t c = 0; c < mColumns.size (); ++c)
|
||||
{
|
||||
if (mSpecifiedWidth[c] > 0)
|
||||
ideal[c] = mSpecifiedWidth[c];
|
||||
else if (mSpecifiedWidth[c] == flexible)
|
||||
{
|
||||
ideal[c] = 0;
|
||||
}
|
||||
|
||||
width += mColumnPadding[c] +
|
||||
ideal[c] +
|
||||
mColumnPadding[c] +
|
||||
(c > 0 ? mIntraPadding : 0);
|
||||
}
|
||||
|
||||
int available = mTableWidth - width;
|
||||
if (width < mTableWidth) // if there is room to wiggle in
|
||||
{
|
||||
int shared = available / countFlexible;
|
||||
int remainder = available % countFlexible;
|
||||
|
||||
int lastFlexible = mColumns.size () - 1;
|
||||
for (size_t c = 0; c < mColumns.size (); ++c)
|
||||
{
|
||||
if (mSpecifiedWidth[c] == flexible)
|
||||
{
|
||||
lastFlexible = c;
|
||||
ideal[c] += shared;
|
||||
}
|
||||
}
|
||||
|
||||
// Remainder goes to last column.
|
||||
ideal[lastFlexible] += remainder;
|
||||
mCalculatedWidth = ideal;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The fallback position is to assume no width was specified, and just
|
||||
// calculate widths accordingly.
|
||||
mTableWidth = 0;
|
||||
calculateColumnWidths ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Try again, treating minimum columns as flexible.
|
||||
// std::cout << "# no flexible columns. Now what?\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Table::just Table::getJustification (const int row, const int col)
|
||||
{
|
||||
if (mJustification.find (col) != mJustification.end ())
|
||||
return mJustification[col];
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Table::just Table::getHeaderJustification (int col)
|
||||
{
|
||||
return mJustification.find (col) != mJustification.end () ? mJustification[col]
|
||||
: left;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// data One Data to be rendered
|
||||
// width 8 Max data width for column/specified width
|
||||
// padding 1 Extra padding around data
|
||||
// intraPadding 0 Extra padding between columns only
|
||||
// justification right Alignment withing padding
|
||||
//
|
||||
// Returns:
|
||||
// " One "
|
||||
// One data
|
||||
// ^ ^ padding
|
||||
// ^ intraPadding
|
||||
// ^^^^^^^^ width
|
||||
// ^ ^ fg/bg
|
||||
//
|
||||
const std::string Table::formatHeader (
|
||||
int col,
|
||||
int width,
|
||||
int padding)
|
||||
{
|
||||
assert (width > 0);
|
||||
|
||||
std::string data = mColumns[col];
|
||||
Color c = getHeaderUnderline (col);
|
||||
int gap = width - utf8_length (data);
|
||||
|
||||
std::string pad = std::string (padding, ' ');
|
||||
|
||||
// TODO When the following is replaced by:
|
||||
// std::string postJust = std::string (gap, ' ');
|
||||
// two unit tests fail.
|
||||
std::string postJust = "";
|
||||
for (int i = 0; i < gap; ++i)
|
||||
postJust += " ";
|
||||
|
||||
std::string intraPad = "";
|
||||
if (col < (signed) mColumns.size () - 1)
|
||||
intraPad = std::string (getIntraPadding (), ' ');
|
||||
|
||||
return c.colorize (pad + data + postJust + pad) + intraPad;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// data One Data to be rendered
|
||||
// width 8 Max data width for column/specified width
|
||||
// padding 1 Extra padding around data
|
||||
// intraPadding 0 Extra padding between columns only
|
||||
// justification right Alignment withing padding
|
||||
//
|
||||
// Returns:
|
||||
// "------- "
|
||||
// ------- data
|
||||
// ^ ^ padding
|
||||
// ^ intraPadding
|
||||
// ^^^^^^^^ width
|
||||
// ^ ^ fg/bg
|
||||
//
|
||||
const std::string Table::formatHeaderDashedUnderline (
|
||||
int col,
|
||||
int width,
|
||||
int padding)
|
||||
{
|
||||
assert (width > 0);
|
||||
|
||||
Color c = getHeaderUnderline (col);
|
||||
|
||||
std::string data = std::string (width, '-');
|
||||
std::string pad = std::string (padding, ' ');
|
||||
std::string intraPad = "";
|
||||
|
||||
// Place the value within the available space - justify.
|
||||
if (col < (signed) mColumns.size () - 1)
|
||||
intraPad = std::string (getIntraPadding (), ' ');
|
||||
|
||||
return c.colorize (pad + data + pad) + intraPad;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::formatCell (
|
||||
const int index,
|
||||
const int row,
|
||||
const int col,
|
||||
const int width,
|
||||
const int padding,
|
||||
std::vector <std::string>& lines,
|
||||
std::string& blank)
|
||||
{
|
||||
assert (width > 0);
|
||||
|
||||
Color c = getColor (index, row, col);
|
||||
just justification = getJustification (row, col);
|
||||
std::string data = getCell (row, col);
|
||||
|
||||
std::string pad = std::string (padding, ' ');
|
||||
std::string intraPad = "";
|
||||
|
||||
if (col < (signed) mColumns.size () - 1)
|
||||
intraPad = std::string (getIntraPadding (), ' ');
|
||||
|
||||
// Break the text into chunks of width characters.
|
||||
std::string preJust;
|
||||
std::string postJust;
|
||||
std::vector <std::string> chunks;
|
||||
wrapText (chunks, data, width);
|
||||
for (size_t chunk = 0; chunk < chunks.size (); ++chunk)
|
||||
{
|
||||
// Place the data within the available space - justify.
|
||||
int gap = width - utf8_length (chunks[chunk]);
|
||||
|
||||
preJust = "";
|
||||
postJust = "";
|
||||
|
||||
if (justification == left)
|
||||
postJust = std::string (gap, ' ');
|
||||
|
||||
else if (justification == right)
|
||||
preJust = std::string (gap, ' ');
|
||||
|
||||
else if (justification == center)
|
||||
{
|
||||
preJust = std::string (gap / 2, ' ');
|
||||
postJust = std::string (gap - preJust.length (), ' ');
|
||||
}
|
||||
|
||||
lines.push_back (c.colorize (pad + preJust + chunks[chunk] + postJust + pad + intraPad));
|
||||
}
|
||||
|
||||
// The blank is used to vertically pad cells that have blank lines.
|
||||
pad = std::string (width, ' ');
|
||||
|
||||
blank = c.colorize (pad + intraPad);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setDateFormat (const std::string& dateFormat)
|
||||
{
|
||||
mDateFormat = dateFormat;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Table::setReportName (const std::string& reportName)
|
||||
{
|
||||
mReportName = reportName;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Table::rowCount ()
|
||||
{
|
||||
return mRows;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Table::columnCount ()
|
||||
{
|
||||
return mColumns.size ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Essentially a static implementation of a dynamic operator<.
|
||||
bool sort_compare (int left, int right)
|
||||
{
|
||||
for (size_t c = 0; c < table->mSortColumns.size (); ++c)
|
||||
{
|
||||
int column = table->mSortColumns[c];
|
||||
Table::order sort_type = table->mSortOrder[column];
|
||||
|
||||
Grid::Cell* cell_left = table->mData.byRow (left, column);
|
||||
Grid::Cell* cell_right = table->mData.byRow (right, column);
|
||||
|
||||
// Equally NULL - next column.
|
||||
if (cell_left == NULL && cell_right == NULL)
|
||||
continue;
|
||||
|
||||
// Equal - next column
|
||||
if (cell_left && cell_right && *cell_left == *cell_right)
|
||||
continue;
|
||||
|
||||
// Note: Table::ascendingDueDate is not represented here because it is not
|
||||
// possible to have a NULL due date, only a blank "".
|
||||
|
||||
// nothing < something.
|
||||
if (cell_left == NULL && cell_right != NULL)
|
||||
return (sort_type == Table::ascendingNumeric ||
|
||||
sort_type == Table::ascendingCharacter ||
|
||||
sort_type == Table::ascendingPriority ||
|
||||
sort_type == Table::ascendingDate ||
|
||||
sort_type == Table::ascendingPeriod) ? true : false;
|
||||
|
||||
// something > nothing.
|
||||
if (cell_left != NULL && cell_right == NULL)
|
||||
return (sort_type == Table::ascendingNumeric ||
|
||||
sort_type == Table::ascendingCharacter ||
|
||||
sort_type == Table::ascendingPriority ||
|
||||
sort_type == Table::ascendingDate ||
|
||||
sort_type == Table::ascendingPeriod) ? false : true;
|
||||
|
||||
// Differing data - do a proper comparison.
|
||||
if (cell_left && cell_right)
|
||||
{
|
||||
switch (sort_type)
|
||||
{
|
||||
case Table::ascendingNumeric:
|
||||
return (float)*cell_left < (float)*cell_right ? true : false;
|
||||
break;
|
||||
|
||||
case Table::descendingNumeric:
|
||||
return (float)*cell_left < (float)*cell_right ? false : true;
|
||||
break;
|
||||
|
||||
case Table::ascendingCharacter:
|
||||
return (std::string)*cell_left < (std::string)*cell_right ? true : false;
|
||||
break;
|
||||
|
||||
case Table::descendingCharacter:
|
||||
return (std::string)*cell_left < (std::string)*cell_right ? false : true;
|
||||
break;
|
||||
|
||||
case Table::ascendingDate:
|
||||
{
|
||||
// something > nothing.
|
||||
if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
|
||||
return false;
|
||||
|
||||
// nothing < something.
|
||||
else if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
|
||||
return true;
|
||||
|
||||
else
|
||||
{
|
||||
Date dl ((std::string)*cell_left, table->mDateFormat);
|
||||
Date dr ((std::string)*cell_right, table->mDateFormat);
|
||||
return dl < dr ? true : false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Table::descendingDate:
|
||||
{
|
||||
// something > nothing.
|
||||
if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
|
||||
return true;
|
||||
|
||||
// nothing < something.
|
||||
else if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
|
||||
return false;
|
||||
|
||||
else
|
||||
{
|
||||
Date dl ((std::string)*cell_left, table->mDateFormat);
|
||||
Date dr ((std::string)*cell_right, table->mDateFormat);
|
||||
return dl < dr ? false : true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Table::ascendingDueDate:
|
||||
{
|
||||
// something > nothing.
|
||||
if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
|
||||
return true;
|
||||
|
||||
// nothing < something.
|
||||
else if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
|
||||
return false;
|
||||
|
||||
else
|
||||
{
|
||||
std::string format = context.config.get ("report." + table->mReportName + ".dateformat");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat.report");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat");
|
||||
|
||||
Date dl ((std::string)*cell_left, format);
|
||||
Date dr ((std::string)*cell_right, format);
|
||||
return dl < dr ? true : false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Table::descendingDueDate:
|
||||
{
|
||||
// something > nothing.
|
||||
if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
|
||||
return true;
|
||||
|
||||
// nothing < something.
|
||||
else if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
|
||||
return false;
|
||||
|
||||
else
|
||||
{
|
||||
std::string format = context.config.get ("report." + table->mReportName + ".dateformat");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat.report");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat");
|
||||
|
||||
Date dl ((std::string)*cell_left, format);
|
||||
Date dr ((std::string)*cell_right, format);
|
||||
return dl < dr ? false : true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Table::ascendingPriority:
|
||||
if (((std::string)*cell_left == "" && (std::string)*cell_right != "") ||
|
||||
((std::string)*cell_left == "L" && ((std::string)*cell_right == "M" || (std::string)*cell_right == "H")) ||
|
||||
((std::string)*cell_left == "M" && (std::string)*cell_right == "H"))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case Table::descendingPriority:
|
||||
if (((std::string)*cell_left != "" && (std::string)*cell_right == "") ||
|
||||
((std::string)*cell_left == "M" && (std::string)*cell_right == "L") ||
|
||||
((std::string)*cell_left == "H" && ((std::string)*cell_right == "L" || (std::string)*cell_right == "M")))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case Table::ascendingPeriod:
|
||||
if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
|
||||
return true;
|
||||
else if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
|
||||
return false;
|
||||
else
|
||||
return Duration ((std::string)*cell_left) < Duration ((std::string)*cell_right) ? true : false;
|
||||
break;
|
||||
|
||||
case Table::descendingPeriod:
|
||||
if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
|
||||
return false;
|
||||
else if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
|
||||
return true;
|
||||
else
|
||||
return Duration ((std::string)*cell_left) < Duration ((std::string)*cell_right) ? false : true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const std::string Table::render (int maxrows /* = 0 */, int maxlines /* = 0 */)
|
||||
{
|
||||
Timer t ("Table::render");
|
||||
|
||||
// May not exceed maxlines, if non-zero.
|
||||
int renderedlines = 0;
|
||||
|
||||
calculateColumnWidths ();
|
||||
|
||||
// Print column headers in column order.
|
||||
std::string output;
|
||||
std::string underline;
|
||||
for (size_t col = 0; col < mColumns.size (); ++col)
|
||||
{
|
||||
output += formatHeader (
|
||||
col,
|
||||
mCalculatedWidth[col],
|
||||
mColumnPadding[col]);
|
||||
|
||||
if (mDashedUnderline)
|
||||
underline += formatHeaderDashedUnderline (
|
||||
col,
|
||||
mCalculatedWidth[col],
|
||||
mColumnPadding[col]);
|
||||
}
|
||||
|
||||
output.erase (output.find_last_not_of (" ") + 1);
|
||||
output += "\n";
|
||||
++renderedlines;
|
||||
if (underline.length ())
|
||||
{
|
||||
output += underline + "\n";
|
||||
++renderedlines;
|
||||
}
|
||||
|
||||
// Determine row order, according to sort options.
|
||||
std::vector <int> order;
|
||||
{
|
||||
Timer t ("Table::render/sort");
|
||||
for (int row = 0; row < mRows; ++row)
|
||||
order.push_back (row);
|
||||
|
||||
// Only sort if necessary.
|
||||
if (mSortColumns.size ())
|
||||
{
|
||||
table = this; // Substitute for 'this' in the static 'sort_compare'.
|
||||
std::stable_sort (order.begin (), order.end (), sort_compare);
|
||||
}
|
||||
}
|
||||
|
||||
// If a non-zero maxrows is specified, then it limits the number of rows of
|
||||
// the table that are rendered.
|
||||
int limitrows = mRows;
|
||||
if (maxrows != 0)
|
||||
limitrows = min (maxrows, mRows);
|
||||
|
||||
// If a non-zero maxlines is specified, then it limits the number of lines
|
||||
// of output from the table that are rendered.
|
||||
|
||||
// Print all rows.
|
||||
Timer t2 ("Table::render/compose");
|
||||
for (int row = 0; row < limitrows; ++row)
|
||||
{
|
||||
std::vector <std::vector <std::string> > columns;
|
||||
std::vector <std::string> blanks;
|
||||
|
||||
size_t maxHeight = 0;
|
||||
for (size_t col = 0; col < mColumns.size (); ++col)
|
||||
{
|
||||
std::vector <std::string> lines;
|
||||
std::string blank;
|
||||
formatCell (
|
||||
row,
|
||||
order[row],
|
||||
col,
|
||||
mCalculatedWidth[col],
|
||||
mColumnPadding[col],
|
||||
lines,
|
||||
blank);
|
||||
|
||||
columns.push_back (lines);
|
||||
blanks.push_back (blank);
|
||||
|
||||
maxHeight = max (maxHeight, columns[col].size ());
|
||||
}
|
||||
|
||||
if (maxHeight)
|
||||
{
|
||||
for (size_t lines = 0; lines < maxHeight; ++lines)
|
||||
{
|
||||
for (size_t col = 0; col < mColumns.size (); ++col)
|
||||
if (lines < columns[col].size ())
|
||||
output += columns[col][lines];
|
||||
else
|
||||
output += blanks[col];
|
||||
|
||||
// Trim right.
|
||||
output.erase (output.find_last_not_of (" ") + 1);
|
||||
output += "\n";
|
||||
|
||||
++renderedlines;
|
||||
|
||||
if (maxlines != 0 && renderedlines >= maxlines)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Trim right.
|
||||
output.erase (output.find_last_not_of (" ") + 1);
|
||||
output += "\n";
|
||||
}
|
||||
|
||||
if (maxlines != 0 && renderedlines >= maxlines)
|
||||
break;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
141
src/Table.h
141
src/Table.h
|
@ -1,141 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - 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_TABLE
|
||||
#define INCLUDED_TABLE
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "Color.h"
|
||||
#include "Grid.h"
|
||||
|
||||
class Table
|
||||
{
|
||||
friend bool sort_compare (int, int);
|
||||
|
||||
public:
|
||||
enum just {left, center, right};
|
||||
enum order {ascendingNumeric,
|
||||
ascendingCharacter,
|
||||
ascendingPriority,
|
||||
ascendingDate,
|
||||
ascendingDueDate,
|
||||
ascendingPeriod,
|
||||
descendingNumeric,
|
||||
descendingCharacter,
|
||||
descendingPriority,
|
||||
descendingDate,
|
||||
descendingDueDate,
|
||||
descendingPeriod};
|
||||
enum sizing {minimum = -1, flexible = 0};
|
||||
|
||||
Table ();
|
||||
virtual ~Table ();
|
||||
|
||||
Table (const Table&);
|
||||
Table& operator= (const Table&);
|
||||
|
||||
void setTableAlternateColor (const Color&);
|
||||
void setTablePadding (int);
|
||||
void setTableIntraPadding (int);
|
||||
void setTableWidth (int);
|
||||
void setTableDashedUnderline ();
|
||||
|
||||
int addColumn (const std::string&);
|
||||
void setColumnUnderline (int);
|
||||
void setColumnPadding (int, int);
|
||||
void setColumnWidth (int, int);
|
||||
void setColumnWidth (int, sizing);
|
||||
void setColumnJustification (int, just);
|
||||
void setColumnCommify (int);
|
||||
void sortOn (int, order);
|
||||
|
||||
int addRow ();
|
||||
void setRowColor (int, const Color&);
|
||||
|
||||
void addCell (int, int, const std::string&);
|
||||
void addCell (int, int, char);
|
||||
void addCell (int, int, int);
|
||||
void addCell (int, int, float);
|
||||
void addCell (int, int, double);
|
||||
void setCellColor (int, int, const Color&);
|
||||
|
||||
void setDateFormat (const std::string&);
|
||||
void setReportName (const std::string&);
|
||||
|
||||
int rowCount ();
|
||||
int columnCount ();
|
||||
const std::string render (int maxrows = 0, int maxlines = 0);
|
||||
|
||||
private:
|
||||
std::string getCell (const int, const int);
|
||||
Color getColor (const int, const int, const int);
|
||||
Color getHeaderUnderline (const int);
|
||||
int getPadding (const int);
|
||||
int getIntraPadding ();
|
||||
void calculateColumnWidths ();
|
||||
just getJustification (const int, const int);
|
||||
just getHeaderJustification (const int);
|
||||
const std::string formatHeader (const int, const int, const int);
|
||||
const std::string formatHeaderDashedUnderline (const int, const int, const int);
|
||||
void formatCell (const int, const int, const int, const int, const int, std::vector <std::string>&, std::string&);
|
||||
|
||||
private:
|
||||
std::vector <std::string> mColumns;
|
||||
int mRows;
|
||||
int mIntraPadding;
|
||||
std::map <std::string, Color> mColor;
|
||||
std::map <std::string, Color> mUnderline;
|
||||
bool mDashedUnderline;
|
||||
Color alternate;
|
||||
|
||||
// Padding...
|
||||
int mTablePadding;
|
||||
std::vector <int> mColumnPadding;
|
||||
|
||||
// Width...
|
||||
int mTableWidth;
|
||||
std::vector <int> mSpecifiedWidth;
|
||||
std::vector <int> mMaxDataWidth;
|
||||
std::vector <int> mCalculatedWidth;
|
||||
|
||||
std::map <int, just> mJustification;
|
||||
std::map <int, bool> mCommify;
|
||||
Grid mData;
|
||||
|
||||
// Sorting...
|
||||
std::vector <int> mSortColumns;
|
||||
std::map <int, order> mSortOrder;
|
||||
|
||||
// Misc...
|
||||
std::string mDateFormat;
|
||||
std::string mReportName;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -111,13 +111,18 @@ std::string ViewTask::render (std::vector <Task>& data, std::vector <int>& seque
|
|||
int global_min = utf8_length ((*i)->getLabel ());
|
||||
int global_ideal = global_min;
|
||||
|
||||
std::vector <Task>::iterator d;
|
||||
for (d = data.begin (); d != data.end (); ++d)
|
||||
for (int s = 0; s < sequence.size (); ++s)
|
||||
{
|
||||
if (s >= _truncate_lines && _truncate_lines != 0)
|
||||
break;
|
||||
|
||||
if (s >= _truncate_rows && _truncate_rows != 0)
|
||||
break;
|
||||
|
||||
// Determine minimum and ideal width for this column.
|
||||
int min;
|
||||
int ideal;
|
||||
(*i)->measure (*d, min, ideal);
|
||||
(*i)->measure (data[sequence[s]], min, ideal);
|
||||
|
||||
if (min > global_min) global_min = min;
|
||||
if (ideal > global_ideal) global_ideal = ideal;
|
||||
|
@ -162,14 +167,17 @@ std::string ViewTask::render (std::vector <Task>& data, std::vector <int>& seque
|
|||
overage -= sum_minimal;
|
||||
|
||||
// Spread 'overage' among columns where width[i] < ideal[i]
|
||||
while (overage)
|
||||
bool needed = true;
|
||||
while (overage && needed)
|
||||
{
|
||||
needed = false;
|
||||
for (int i = 0; i < _columns.size () && overage; ++i)
|
||||
{
|
||||
if (widths[i] < ideal[i])
|
||||
{
|
||||
++widths[i];
|
||||
--overage;
|
||||
needed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,6 +222,10 @@ std::string ViewText::render ()
|
|||
bool odd = (row % 2) ? true : false;
|
||||
Color row_color = odd ? _odd : _even;
|
||||
|
||||
// TODO row_color.blend (provided color);
|
||||
// TODO Problem: colors for columns are specified, not rows,
|
||||
// therefore there are only cell colors, not intra colors.
|
||||
|
||||
Color cell_color;
|
||||
for (int col = 0; col < _columns.size (); ++col)
|
||||
{
|
||||
|
|
182
src/command.cpp
182
src/command.cpp
|
@ -43,6 +43,7 @@
|
|||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include "Transport.h"
|
||||
#include "ViewText.h"
|
||||
#include "../cmake.h"
|
||||
#ifdef HAVE_COMMIT
|
||||
#include "../commit.h"
|
||||
|
@ -259,41 +260,24 @@ int handleProjects (std::string& outs)
|
|||
if (unique.size ())
|
||||
{
|
||||
// Render a list of project names from the map.
|
||||
Table table;
|
||||
table.addColumn ("Project");
|
||||
table.addColumn ("Tasks");
|
||||
table.addColumn ("Pri:None");
|
||||
table.addColumn ("Pri:L");
|
||||
table.addColumn ("Pri:M");
|
||||
table.addColumn ("Pri:H");
|
||||
|
||||
if (context.color () && context.config.getBoolean ("fontunderline"))
|
||||
{
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
table.setColumnUnderline (2);
|
||||
table.setColumnUnderline (3);
|
||||
table.setColumnUnderline (4);
|
||||
table.setColumnUnderline (5);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnJustification (1, Table::right);
|
||||
table.setColumnJustification (2, Table::right);
|
||||
table.setColumnJustification (3, Table::right);
|
||||
table.setColumnJustification (4, Table::right);
|
||||
table.setColumnJustification (5, Table::right);
|
||||
ViewText view;
|
||||
view.width (context.getWidth ());
|
||||
view.add (Column::factory ("string", "Project"));
|
||||
view.add (Column::factory ("string.right", "Tasks"));
|
||||
view.add (Column::factory ("string.right", "Pri:None"));
|
||||
view.add (Column::factory ("string.right", "Pri:L"));
|
||||
view.add (Column::factory ("string.right", "Pri:M"));
|
||||
view.add (Column::factory ("string.right", "Pri:H"));
|
||||
|
||||
foreach (i, unique)
|
||||
{
|
||||
int row = table.addRow ();
|
||||
table.addCell (row, 0, (i->first == "" ? "(none)" : i->first));
|
||||
table.addCell (row, 1, i->second);
|
||||
table.addCell (row, 2, none[i->first]);
|
||||
table.addCell (row, 3, low[i->first]);
|
||||
table.addCell (row, 4, medium[i->first]);
|
||||
table.addCell (row, 5, high[i->first]);
|
||||
int row = view.addRow ();
|
||||
view.set (row, 0, (i->first == "" ? "(none)" : i->first));
|
||||
view.set (row, 1, i->second);
|
||||
view.set (row, 2, none[i->first]);
|
||||
view.set (row, 3, low[i->first]);
|
||||
view.set (row, 4, medium[i->first]);
|
||||
view.set (row, 5, high[i->first]);
|
||||
}
|
||||
|
||||
int number_projects = unique.size ();
|
||||
|
@ -301,7 +285,7 @@ int handleProjects (std::string& outs)
|
|||
--number_projects;
|
||||
|
||||
out << optionalBlankLine ()
|
||||
<< table.render ()
|
||||
<< view.render ()
|
||||
<< optionalBlankLine ()
|
||||
<< number_projects
|
||||
<< (number_projects == 1 ? " project" : " projects")
|
||||
|
@ -382,35 +366,28 @@ int handleTags (std::string& outs)
|
|||
if (unique.size ())
|
||||
{
|
||||
// Render a list of tags names from the map.
|
||||
Table table;
|
||||
table.addColumn ("Tag");
|
||||
table.addColumn ("Count");
|
||||
|
||||
if (context.color ())
|
||||
{
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
}
|
||||
|
||||
table.setColumnJustification (1, Table::right);
|
||||
ViewText view;
|
||||
view.width (context.getWidth ());
|
||||
view.add (Column::factory ("string", "Tag"));
|
||||
view.add (Column::factory ("string.right", "Count"));
|
||||
|
||||
Color bold ("bold");
|
||||
bool special = false;
|
||||
foreach (i, unique)
|
||||
{
|
||||
int row = table.addRow ();
|
||||
table.addCell (row, 0, i->first);
|
||||
table.addCell (row, 1, i->second);
|
||||
|
||||
// Highlight the special tags.
|
||||
if (context.color () && (i->first == "nocolor" ||
|
||||
i->first == "nonag"))
|
||||
{
|
||||
table.setRowColor (row, bold);
|
||||
}
|
||||
special = (context.color () &&
|
||||
(i->first == "nocolor" ||
|
||||
i->first == "nonag" ||
|
||||
i->first == "next")) ? true : false;
|
||||
|
||||
int row = view.addRow ();
|
||||
view.set (row, 0, i->first, special ? bold : Color ());
|
||||
view.set (row, 1, i->second, special ? bold : Color ());
|
||||
}
|
||||
|
||||
out << optionalBlankLine ()
|
||||
<< table.render ()
|
||||
<< view.render ()
|
||||
<< optionalBlankLine ()
|
||||
<< unique.size ()
|
||||
<< (unique.size () == 1 ? " tag" : " tags")
|
||||
|
@ -1002,22 +979,18 @@ int handleVersion (std::string& outs)
|
|||
|
||||
// Create a table for the disclaimer.
|
||||
int width = context.getWidth ();
|
||||
Table disclaimer;
|
||||
disclaimer.setTableWidth (width);
|
||||
disclaimer.addColumn (" ");
|
||||
disclaimer.setColumnWidth (0, Table::flexible);
|
||||
disclaimer.setColumnJustification (0, Table::left);
|
||||
disclaimer.addCell (disclaimer.addRow (), 0,
|
||||
ViewText disclaimer;
|
||||
disclaimer.width (width);
|
||||
disclaimer.add (Column::factory ("string", ""));
|
||||
disclaimer.set (disclaimer.addRow (), 0,
|
||||
"Taskwarrior may be copied only under the terms of the GNU General Public "
|
||||
"License, which may be found in the taskwarrior source kit.");
|
||||
|
||||
// Create a table for the URL.
|
||||
Table link;
|
||||
link.setTableWidth (width);
|
||||
link.addColumn (" ");
|
||||
link.setColumnWidth (0, Table::flexible);
|
||||
link.setColumnJustification (0, Table::left);
|
||||
link.addCell (link.addRow (), 0,
|
||||
ViewText link;
|
||||
link.width (width);
|
||||
link.add (Column::factory ("string", ""));
|
||||
link.set (link.addRow (), 0,
|
||||
"Documentation for taskwarrior can be found using 'man task', 'man taskrc', "
|
||||
"'man task-tutorial', 'man task-color', 'man task-sync', 'man task-faq' or at "
|
||||
"http://taskwarrior.org");
|
||||
|
@ -1061,7 +1034,9 @@ int handleVersion (std::string& outs)
|
|||
#ifdef HAVE_LIBLUA
|
||||
<< "Portions of this software Copyright (C) 1994 – 2008 Lua.org, PUC-Rio.\n"
|
||||
#endif
|
||||
<< "\n"
|
||||
<< disclaimer.render ()
|
||||
<< "\n"
|
||||
<< link.render ()
|
||||
<< "\n";
|
||||
|
||||
|
@ -1168,26 +1143,11 @@ int handleShow (std::string& outs)
|
|||
if (context.config.get (*i) != default_config.get (*i))
|
||||
default_values.push_back (*i);
|
||||
|
||||
// Create a table for output.
|
||||
Table table;
|
||||
table.setTableWidth (width);
|
||||
table.setDateFormat (context.config.get ("dateformat"));
|
||||
table.addColumn ("Config variable");
|
||||
table.addColumn ("Value");
|
||||
|
||||
if (context.color ())
|
||||
{
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnWidth (0, Table::minimum);
|
||||
table.setColumnWidth (1, Table::flexible);
|
||||
table.setColumnJustification (0, Table::left);
|
||||
table.setColumnJustification (1, Table::left);
|
||||
table.sortOn (0, Table::ascendingCharacter);
|
||||
// Create output view.
|
||||
ViewText view;
|
||||
view.width (width);
|
||||
view.add (Column::factory ("string", "Config variable"));
|
||||
view.add (Column::factory ("string", "Value"));
|
||||
|
||||
Color error ("bold white on red");
|
||||
Color warning ("black on yellow");
|
||||
|
@ -1206,25 +1166,22 @@ int handleShow (std::string& outs)
|
|||
|
||||
if (loc != std::string::npos)
|
||||
{
|
||||
int row = table.addRow ();
|
||||
table.addCell (row, 0, *i);
|
||||
table.addCell (row, 1, context.config.get (*i));
|
||||
|
||||
// Look for unrecognized.
|
||||
if (context.color ())
|
||||
{
|
||||
if (std::find (unrecognized.begin (), unrecognized.end (), *i) != unrecognized.end ())
|
||||
table.setRowColor (row, error);
|
||||
Color color;
|
||||
if (std::find (unrecognized.begin (), unrecognized.end (), *i) != unrecognized.end ())
|
||||
color = error;
|
||||
else if (std::find (default_values.begin (), default_values.end (), *i) != default_values.end ())
|
||||
color = warning;
|
||||
|
||||
else if (std::find (default_values.begin (), default_values.end (), *i) != default_values.end ())
|
||||
table.setRowColor (row, warning);
|
||||
}
|
||||
int row = view.addRow ();
|
||||
view.set (row, 0, *i, color);
|
||||
view.set (row, 1, context.config.get (*i), color);
|
||||
}
|
||||
}
|
||||
|
||||
out << "\n"
|
||||
<< table.render ()
|
||||
<< (table.rowCount () == 0 ? "No matching configuration variables.\n\n" : "\n");
|
||||
<< view.render ()
|
||||
<< (view.rows () == 0 ? "No matching configuration variables.\n\n" : "\n");
|
||||
|
||||
// Display the unrecognized variables.
|
||||
if (unrecognized.size ())
|
||||
|
@ -2374,17 +2331,10 @@ int handleColor (std::string& outs)
|
|||
std::vector <std::string> all;
|
||||
context.config.all (all);
|
||||
|
||||
Table table;
|
||||
table.addColumn ("Color");
|
||||
table.addColumn ("Definition");
|
||||
|
||||
if (context.color () && context.config.getBoolean ("fontunderline"))
|
||||
{
|
||||
table.setColumnUnderline (0);
|
||||
table.setColumnUnderline (1);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
ViewText view;
|
||||
view.width (context.getWidth ());
|
||||
view.add (Column::factory ("string", "Color"));
|
||||
view.add (Column::factory ("string", "Definition"));
|
||||
|
||||
foreach (item, all)
|
||||
{
|
||||
|
@ -2394,16 +2344,14 @@ int handleColor (std::string& outs)
|
|||
*item != "color" &&
|
||||
item->find ("color") == 0)
|
||||
{
|
||||
int row = table.addRow ();
|
||||
table.addCell (row, 0, *item);
|
||||
table.addCell (row, 1, context.config.get (*item));
|
||||
table.setRowColor (row, context.config.get (*item));
|
||||
Color color (context.config.get (*item));
|
||||
int row = view.addRow ();
|
||||
view.set (row, 0, *item, color);
|
||||
view.set (row, 1, context.config.get (*item), color);
|
||||
}
|
||||
}
|
||||
|
||||
out << optionalBlankLine ()
|
||||
<< table.render ()
|
||||
<< optionalBlankLine ()
|
||||
out << view.render ()
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <map>
|
||||
#include <sys/types.h>
|
||||
#include "Context.h"
|
||||
#include "Table.h"
|
||||
#include "Date.h"
|
||||
#include "Color.h"
|
||||
#include "../cmake.h"
|
||||
|
|
229
src/report.cpp
229
src/report.cpp
|
@ -42,7 +42,6 @@
|
|||
#include <File.h>
|
||||
#include <Date.h>
|
||||
#include <Duration.h>
|
||||
#include <Table.h>
|
||||
#include <ViewText.h>
|
||||
#include <text.h>
|
||||
#include <util.h>
|
||||
|
@ -787,6 +786,7 @@ int handleReportSummary (std::string& outs)
|
|||
|
||||
// Create a table for output.
|
||||
ViewText view;
|
||||
view.width (context.getWidth ());
|
||||
view.add (Column::factory ("string", "Project"));
|
||||
view.add (Column::factory ("string", "Remaining"));
|
||||
view.add (Column::factory ("string", "Avg age"));
|
||||
|
@ -900,31 +900,12 @@ int handleReportTimesheet (std::string& outs)
|
|||
<< "\n";
|
||||
|
||||
// Render the completed table.
|
||||
Table completed;
|
||||
completed.setTableWidth (width);
|
||||
completed.addColumn (" ");
|
||||
completed.addColumn ("Project");
|
||||
completed.addColumn ("Due");
|
||||
completed.addColumn ("Description");
|
||||
|
||||
if (context.color () && context.config.getBoolean ("fontunderline"))
|
||||
{
|
||||
completed.setColumnUnderline (1);
|
||||
completed.setColumnUnderline (2);
|
||||
completed.setColumnUnderline (3);
|
||||
}
|
||||
else
|
||||
completed.setTableDashedUnderline ();
|
||||
|
||||
completed.setColumnWidth (0, Table::minimum);
|
||||
completed.setColumnWidth (1, Table::minimum);
|
||||
completed.setColumnWidth (2, Table::minimum);
|
||||
completed.setColumnWidth (3, Table::flexible);
|
||||
|
||||
completed.setColumnJustification (0, Table::left);
|
||||
completed.setColumnJustification (1, Table::left);
|
||||
completed.setColumnJustification (2, Table::right);
|
||||
completed.setColumnJustification (3, Table::left);
|
||||
ViewText completed;
|
||||
completed.width (width);
|
||||
completed.add (Column::factory ("string", " "));
|
||||
completed.add (Column::factory ("string", "Project"));
|
||||
completed.add (Column::factory ("string.right", "Due"));
|
||||
completed.add (Column::factory ("string", "Description"));
|
||||
|
||||
std::vector <Task>::iterator task;
|
||||
for (task = tasks.begin (); task != tasks.end (); ++task)
|
||||
|
@ -935,56 +916,35 @@ int handleReportTimesheet (std::string& outs)
|
|||
Date compDate (atoi (task->get ("end").c_str ()));
|
||||
if (compDate >= start && compDate < end)
|
||||
{
|
||||
Color c (task->get ("fg") + " " + task->get ("bg"));
|
||||
if (context.color ())
|
||||
autoColorize (*task, c);
|
||||
|
||||
int row = completed.addRow ();
|
||||
std::string format = context.config.get ("dateformat.report");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat");
|
||||
completed.addCell (row, 1, task->get ("project"));
|
||||
completed.addCell (row, 2, getDueDate (*task, format));
|
||||
completed.addCell (row, 3, getFullDescription (*task, "timesheet"));
|
||||
|
||||
if (context.color ())
|
||||
{
|
||||
Color c (task->get ("fg") + " " + task->get ("bg"));
|
||||
autoColorize (*task, c);
|
||||
completed.setRowColor (row, c);
|
||||
}
|
||||
completed.set (row, 1, task->get ("project"), c);
|
||||
completed.set (row, 2, getDueDate (*task, format), c);
|
||||
completed.set (row, 3, getFullDescription (*task, "timesheet"), c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out << " Completed (" << completed.rowCount () << " tasks)\n";
|
||||
out << " Completed (" << completed.rows () << " tasks)\n";
|
||||
|
||||
if (completed.rowCount ())
|
||||
if (completed.rows ())
|
||||
out << completed.render ()
|
||||
<< "\n";
|
||||
|
||||
// Now render the started table.
|
||||
Table started;
|
||||
started.setTableWidth (width);
|
||||
started.addColumn (" ");
|
||||
started.addColumn ("Project");
|
||||
started.addColumn ("Due");
|
||||
started.addColumn ("Description");
|
||||
ViewText started;
|
||||
started.width (width);
|
||||
started.add (Column::factory ("string", " "));
|
||||
started.add (Column::factory ("string", "Project"));
|
||||
started.add (Column::factory ("string.right", "Due"));
|
||||
started.add (Column::factory ("string", "Description"));
|
||||
|
||||
if (context.color () && context.config.getBoolean ("fontunderline"))
|
||||
{
|
||||
started.setColumnUnderline (1);
|
||||
started.setColumnUnderline (2);
|
||||
started.setColumnUnderline (3);
|
||||
}
|
||||
else
|
||||
started.setTableDashedUnderline ();
|
||||
|
||||
started.setColumnWidth (0, Table::minimum);
|
||||
started.setColumnWidth (1, Table::minimum);
|
||||
started.setColumnWidth (2, Table::minimum);
|
||||
started.setColumnWidth (3, Table::flexible);
|
||||
|
||||
started.setColumnJustification (0, Table::left);
|
||||
started.setColumnJustification (1, Table::left);
|
||||
started.setColumnJustification (2, Table::right);
|
||||
started.setColumnJustification (3, Table::left);
|
||||
for (task = tasks.begin (); task != tasks.end (); ++task)
|
||||
{
|
||||
// If task started within range, but not completed withing range.
|
||||
|
@ -994,27 +954,25 @@ int handleReportTimesheet (std::string& outs)
|
|||
Date startDate (atoi (task->get ("start").c_str ()));
|
||||
if (startDate >= start && startDate < end)
|
||||
{
|
||||
Color c (task->get ("fg") + " " + task->get ("bg"));
|
||||
if (context.color ())
|
||||
autoColorize (*task, c);
|
||||
|
||||
int row = started.addRow ();
|
||||
std::string format = context.config.get ("dateformat.report");
|
||||
if (format == "")
|
||||
format = context.config.get ("dateformat");
|
||||
started.addCell (row, 1, task->get ("project"));
|
||||
started.addCell (row, 2, getDueDate (*task, format));
|
||||
started.addCell (row, 3, getFullDescription (*task, "timesheet"));
|
||||
started.set (row, 1, task->get ("project"), c);
|
||||
started.set (row, 2, getDueDate (*task, format), c);
|
||||
started.set (row, 3, getFullDescription (*task, "timesheet"), c);
|
||||
|
||||
if (context.color ())
|
||||
{
|
||||
Color c (task->get ("fg") + " " + task->get ("bg"));
|
||||
autoColorize (*task, c);
|
||||
started.setRowColor (row, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out << " Started (" << started.rowCount () << " tasks)\n";
|
||||
out << " Started (" << started.rows () << " tasks)\n";
|
||||
|
||||
if (started.rowCount ())
|
||||
if (started.rows ())
|
||||
out << started.render ()
|
||||
<< "\n\n";
|
||||
|
||||
|
@ -1035,9 +993,6 @@ std::string renderMonths (
|
|||
std::vector <Task>& all,
|
||||
int monthsPerLine)
|
||||
{
|
||||
Table table;
|
||||
table.setDateFormat (context.config.get ("dateformat"));
|
||||
|
||||
// What day of the week does the user consider the first?
|
||||
int weekStart = Date::dayOfWeek (context.config.get ("weekstart"));
|
||||
if (weekStart != 0 && weekStart != 1)
|
||||
|
@ -1045,64 +1000,41 @@ std::string renderMonths (
|
|||
"only contain 'Sunday' or 'Monday'.");
|
||||
|
||||
// Build table for the number of months to be displayed.
|
||||
ViewText view;
|
||||
view.width (context.getWidth ());
|
||||
for (int i = 0 ; i < (monthsPerLine * 8); i += 8)
|
||||
{
|
||||
if (weekStart == 1)
|
||||
{
|
||||
table.addColumn (" ");
|
||||
table.addColumn ("Mo");
|
||||
table.addColumn ("Tu");
|
||||
table.addColumn ("We");
|
||||
table.addColumn ("Th");
|
||||
table.addColumn ("Fr");
|
||||
table.addColumn ("Sa");
|
||||
table.addColumn ("Su");
|
||||
view.add (Column::factory ("string", " "));
|
||||
view.add (Column::factory ("string", "Mo"));
|
||||
view.add (Column::factory ("string", "Tu"));
|
||||
view.add (Column::factory ("string", "We"));
|
||||
view.add (Column::factory ("string", "Th"));
|
||||
view.add (Column::factory ("string", "Fr"));
|
||||
view.add (Column::factory ("string", "Sa"));
|
||||
view.add (Column::factory ("string", "Su"));
|
||||
}
|
||||
else
|
||||
{
|
||||
table.addColumn (" ");
|
||||
table.addColumn ("Su");
|
||||
table.addColumn ("Mo");
|
||||
table.addColumn ("Tu");
|
||||
table.addColumn ("We");
|
||||
table.addColumn ("Th");
|
||||
table.addColumn ("Fr");
|
||||
table.addColumn ("Sa");
|
||||
view.add (Column::factory ("string", " "));
|
||||
view.add (Column::factory ("string", "Su"));
|
||||
view.add (Column::factory ("string", "Mo"));
|
||||
view.add (Column::factory ("string", "Tu"));
|
||||
view.add (Column::factory ("string", "We"));
|
||||
view.add (Column::factory ("string", "Th"));
|
||||
view.add (Column::factory ("string", "Fr"));
|
||||
view.add (Column::factory ("string", "Sa"));
|
||||
}
|
||||
|
||||
if (context.color () && context.config.getBoolean ("fontunderline"))
|
||||
{
|
||||
table.setColumnUnderline (i + 1);
|
||||
table.setColumnUnderline (i + 2);
|
||||
table.setColumnUnderline (i + 3);
|
||||
table.setColumnUnderline (i + 4);
|
||||
table.setColumnUnderline (i + 5);
|
||||
table.setColumnUnderline (i + 6);
|
||||
table.setColumnUnderline (i + 7);
|
||||
}
|
||||
else
|
||||
table.setTableDashedUnderline ();
|
||||
|
||||
table.setColumnJustification (i + 0, Table::right);
|
||||
table.setColumnJustification (i + 1, Table::right);
|
||||
table.setColumnJustification (i + 2, Table::right);
|
||||
table.setColumnJustification (i + 3, Table::right);
|
||||
table.setColumnJustification (i + 4, Table::right);
|
||||
table.setColumnJustification (i + 5, Table::right);
|
||||
table.setColumnJustification (i + 6, Table::right);
|
||||
table.setColumnJustification (i + 7, Table::right);
|
||||
|
||||
// This creates a nice gap between the months.
|
||||
table.setColumnWidth (i + 0, 4);
|
||||
}
|
||||
|
||||
// At most, we need 6 rows.
|
||||
table.addRow ();
|
||||
table.addRow ();
|
||||
table.addRow ();
|
||||
table.addRow ();
|
||||
table.addRow ();
|
||||
table.addRow ();
|
||||
view.addRow ();
|
||||
view.addRow ();
|
||||
view.addRow ();
|
||||
view.addRow ();
|
||||
view.addRow ();
|
||||
view.addRow ();
|
||||
|
||||
// Set number of days per month, months to render, and years to render.
|
||||
std::vector<int> years;
|
||||
|
@ -1150,11 +1082,7 @@ std::string renderMonths (
|
|||
int woy = temp.weekOfYear (weekStart);
|
||||
|
||||
if (context.config.getBoolean ("displayweeknumber"))
|
||||
{
|
||||
table.addCell (row, (8 * mpl), woy);
|
||||
if (context.color ())
|
||||
table.setCellColor (row, (8 * mpl), color_weeknumber);
|
||||
}
|
||||
view.set (row, (8 * mpl), woy, color_weeknumber);
|
||||
|
||||
// Calculate column id.
|
||||
int thisCol = dow + // 0 = Sunday
|
||||
|
@ -1164,7 +1092,7 @@ std::string renderMonths (
|
|||
if (thisCol == (8 * mpl))
|
||||
thisCol += 7;
|
||||
|
||||
table.addCell (row, thisCol, d);
|
||||
view.set (row, thisCol, d);
|
||||
|
||||
if (context.color ())
|
||||
{
|
||||
|
@ -1237,7 +1165,8 @@ std::string renderMonths (
|
|||
}
|
||||
}
|
||||
}
|
||||
table.setCellColor (row, thisCol, cellColor);
|
||||
// TODO Solve this.
|
||||
// table.setCellColor (row, thisCol, cellColor);
|
||||
}
|
||||
|
||||
// Check for end of week, and...
|
||||
|
@ -1249,7 +1178,7 @@ std::string renderMonths (
|
|||
}
|
||||
}
|
||||
|
||||
return table.render ();
|
||||
return view.render ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1567,32 +1496,18 @@ int handleReportCalendar (std::string& outs)
|
|||
std::vector <std::string> holidays;
|
||||
context.config.all (holidays);
|
||||
|
||||
Table holTable;
|
||||
holTable.setTableWidth (context.getWidth ());
|
||||
holTable.addColumn ("Date");
|
||||
holTable.addColumn ("Holiday");
|
||||
holTable.sortOn (0, Table::ascendingDueDate);
|
||||
ViewText holTable;
|
||||
holTable.width (context.getWidth ());
|
||||
holTable.add (Column::factory ("string", "Date"));
|
||||
holTable.add (Column::factory ("string", "Holiday"));
|
||||
|
||||
if (context.color () && context.config.getBoolean ("fontunderline"))
|
||||
{
|
||||
holTable.setColumnUnderline (0);
|
||||
holTable.setColumnUnderline (1);
|
||||
}
|
||||
else
|
||||
holTable.setTableDashedUnderline ();
|
||||
|
||||
holTable.setColumnWidth (0, Table::minimum);
|
||||
holTable.setColumnWidth (1, Table::flexible);
|
||||
|
||||
holTable.setColumnJustification (0, Table::left);
|
||||
holTable.setColumnJustification (1, Table::left);
|
||||
|
||||
foreach (hol, holidays)
|
||||
if (hol->substr (0, 8) == "holiday.")
|
||||
if (hol->substr (hol->size () - 4) == "name")
|
||||
std::vector <std::string>::iterator it;
|
||||
for (it = holidays.begin (); it != holidays.end (); ++it)
|
||||
if (it->substr (0, 8) == "holiday.")
|
||||
if (it->substr (it->size () - 4) == "name")
|
||||
{
|
||||
std::string holName = context.config.get ("holiday." + hol->substr (8, hol->size () - 13) + ".name");
|
||||
std::string holDate = context.config.get ("holiday." + hol->substr (8, hol->size () - 13) + ".date");
|
||||
std::string holName = context.config.get ("holiday." + it->substr (8, it->size () - 13) + ".name");
|
||||
std::string holDate = context.config.get ("holiday." + it->substr (8, it->size () - 13) + ".date");
|
||||
Date hDate (holDate.c_str (), context.config.get ("dateformat.holiday"));
|
||||
|
||||
if (date_after < hDate && hDate < date_before)
|
||||
|
@ -1606,8 +1521,8 @@ int handleReportCalendar (std::string& outs)
|
|||
format = context.config.get ("dateformat");
|
||||
|
||||
int row = holTable.addRow ();
|
||||
holTable.addCell (row, 0, hDate.toString (format));
|
||||
holTable.addCell (row, 1, holName);
|
||||
holTable.set (row, 0, hDate.toString (format));
|
||||
holTable.set (row, 1, holName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
1
test/.gitignore
vendored
1
test/.gitignore
vendored
|
@ -12,7 +12,6 @@ dom.t
|
|||
duration.t
|
||||
file.t
|
||||
filt.t
|
||||
grid.t
|
||||
json.t
|
||||
lisp.t
|
||||
list.t
|
||||
|
|
|
@ -6,8 +6,8 @@ include_directories (${CMAKE_SOURCE_DIR}/src
|
|||
${TASK_INCLUDE_DIRS})
|
||||
|
||||
set (test_SRCS att.t autocomplete.t cmd.t color.t config.t date.t directory.t
|
||||
dom.t duration.t file.t filt.t grid.t json.t list.t nibbler.t
|
||||
path.t record.t rectangle.t rx.t seq.t subst.t t.benchmark.t t.t
|
||||
dom.t duration.t file.t filt.t json.t list.t nibbler.t path.t
|
||||
record.t rectangle.t rx.t seq.t subst.t t.benchmark.t t.t
|
||||
taskmod.t tdb.t tdb2.t text.t tree.t tree2.t uri.t util.t
|
||||
variant.t view.t)
|
||||
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// taskwarrior - 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 <Context.h>
|
||||
#include <Grid.h>
|
||||
#include <test.h>
|
||||
|
||||
Context context;
|
||||
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest ut (30);
|
||||
|
||||
Grid g;
|
||||
ut.is ((int) g.width (), 0, "Zero width for uninitialized grid");
|
||||
ut.is ((int) g.height (), 0, "Zero height for uninitialized grid");
|
||||
|
||||
g.add (2, 2, false);
|
||||
ut.is ((int) g.width (), 3, "Width of 3 columns");
|
||||
ut.is ((int) g.height (), 3, "Height of 3 rows");
|
||||
|
||||
Grid g2;
|
||||
g2.add (0, 1, "value");
|
||||
g2.add (1, 0, "value");
|
||||
ut.is ((int) g2.width (), 2, "Width of 2 columns");
|
||||
ut.is ((int) g2.height (), 2, "Height of 2 rows");
|
||||
ut.is (g2.byRow (0, 0), NULL, "Gap at 0,0");
|
||||
ut.ok (g2.byRow (0, 1), "Cell at 0,0");
|
||||
ut.ok (g2.byRow (1, 0), "Cell at 0,0");
|
||||
ut.is (g2.byRow (1, 1), NULL, "Gap at 1,1");
|
||||
|
||||
Grid g3;
|
||||
for (int i = 0; i < 14; ++i)
|
||||
g3.add (i / 4, i % 4, "value");
|
||||
|
||||
for (int i = 0; i < 20; ++i)
|
||||
if (i < 14)
|
||||
ut.ok (g3.byRow (i / 4, i % 4), "g3 good cell");
|
||||
else
|
||||
ut.is (g3.byRow (i / 4, i % 4), NULL, "g3 missing cell");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
Loading…
Add table
Add a link
Reference in a new issue