summaryrefslogtreecommitdiff
authordrw <drw>2002-11-02 21:45:56 (UTC)
committer drw <drw>2002-11-02 21:45:56 (UTC)
commit2dc81c48428222533e5479947d9ad318e464bafa (patch) (side-by-side diff)
tree2e3570d18f3574c49ffc8aaf287bac4822ff3a11
parent5e1893923a9ddf1e2bd3e8f9c0dd264d86b8d98d (diff)
downloadopie-2dc81c48428222533e5479947d9ad318e464bafa.zip
opie-2dc81c48428222533e5479947d9ad318e464bafa.tar.gz
opie-2dc81c48428222533e5479947d9ad318e464bafa.tar.bz2
Implementing charting...
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/checkbook/checkbook.cpp122
-rw-r--r--noncore/apps/checkbook/checkbook.h11
-rw-r--r--noncore/apps/checkbook/graph.cpp85
-rw-r--r--noncore/apps/checkbook/graph.h9
-rw-r--r--noncore/apps/checkbook/graphinfo.cpp45
-rw-r--r--noncore/apps/checkbook/graphinfo.h8
6 files changed, 241 insertions, 39 deletions
diff --git a/noncore/apps/checkbook/checkbook.cpp b/noncore/apps/checkbook/checkbook.cpp
index 20b42b5..77c1f57 100644
--- a/noncore/apps/checkbook/checkbook.cpp
+++ b/noncore/apps/checkbook/checkbook.cpp
@@ -223,51 +223,48 @@ QWidget *Checkbook::initTransactions()
layout->addWidget( btn, 2, 1 );
btn = new QPushButton( Resource::loadPixmap( "trash" ), tr( "Delete" ), control );
QWhatsThis::add( btn, tr( "Select a checkbook and then click here to delete it." ) );
connect( btn, SIGNAL( clicked() ), this, SLOT( slotDeleteTran() ) );
layout->addWidget( btn, 2, 2 );
return( control );
}
QWidget *Checkbook::initCharts()
{
+ graphInfo = 0x0;
+
QWidget *control = new QWidget( mainWidget );
QGridLayout *layout = new QGridLayout( control );
layout->setSpacing( 2 );
layout->setMargin( 4 );
-/*
- QLabel *label = new QLabel( control );
- label->setText( tr( "Graph type:" ) );
- layout->addWidget( label, 0, 0 );
+ graphWidget = new Graph( control );
+ QWhatsThis::add( graphWidget, tr( "Select the desired chart below and then click on the Draw button." ) );
+ layout->addMultiCellWidget( graphWidget, 0, 0, 0, 2 );
+
graphList = new QComboBox( control );
- graphList->insertItem( tr( "By category" ) );
- graphList->insertItem( tr( "..." ) );
- graphList->insertItem( tr( "..." ) );
- layout->addWidget( graphList, 0, 1 );
-*/
+ QWhatsThis::add( graphList, tr( "Click here to select the desired chart type." ) );
+ graphList->insertItem( tr( "Account balance" ) );
+ graphList->insertItem( tr( "Withdrawals by category" ) );
+ graphList->insertItem( tr( "Deposits by category" ) );
- GraphInfo* info = new GraphInfo( GraphInfo::BarChart, 0x0, tr( "Graph Title" ),
- tr( "X-Axis" ), tr( "Y-Axis" ) );
- graphWidget = new Graph( control, info );
- QWhatsThis::add( graphWidget, tr( "Charting is not implemented yet." ) );
- layout->addMultiCellWidget( graphWidget, 0, 0, 0, 1 );
+ layout->addMultiCellWidget( graphList, 1, 1, 0, 1 );
QPushButton *btn = new QPushButton( Resource::loadPixmap( "checkbook/drawbtn" ), tr( "Draw" ), control );
- QWhatsThis::add( btn, tr( "Click here to draw the chart." ) );
+ QWhatsThis::add( btn, tr( "Click here to draw the selected chart." ) );
connect( btn, SIGNAL( clicked() ), this, SLOT( slotDrawGraph() ) );
- layout->addWidget( btn, 1, 1 );
+ layout->addWidget( btn, 1, 2 );
return control;
}
void Checkbook::loadCheckbook()
{
transactions.clear();
Config config(filename, Config::File);
// Load info
config.setGroup( "Account" );
@@ -358,30 +355,28 @@ void Checkbook::accept()
Config *config = new Config(filename, Config::File);
// Save info
config->setGroup( "Account" );
config->writeEntry( "Type", typeList->currentText() );
config->writeEntry( "Bank", bankEdit->text() );
config->writeEntryCrypt( "Number", acctNumEdit->text() );
config->writeEntryCrypt( "PINNumber", pinNumEdit->text() );
config->writeEntry( "Balance", balanceEdit->text() );
config->writeEntry( "Notes", notesEdit->text() );
// Save transactions
- TranInfo *tran = transactions.first();
int i = 1;
- while ( tran )
+ for ( TranInfo *tran = transactions.first(); tran; tran = transactions.next() )
{
tran->write( config, i );
- tran = transactions.next();
i++;
}
config->write();
QDialog::accept();
}
void Checkbook::slotNameChanged( const QString &newname )
{
name = newname;
filename = filedir;
filename.append( newname );
@@ -500,13 +495,102 @@ void Checkbook::slotDeleteTran()
}
transactions.remove( traninfo );
delete traninfo;
delete curritem;
adjustBalance( amount * -1 );
}
}
void Checkbook::slotDrawGraph()
{
+ if ( graphInfo )
+ {
+ delete graphInfo;
+ }
+
+ switch ( graphList->currentItem() )
+ {
+ case 0 : drawBalanceChart();
+ break;
+ case 1 : drawCategoryChart( TRUE );
+ break;
+ case 2 : drawCategoryChart( FALSE );
+ break;
+ };
+
+ graphWidget->setGraphInfo( graphInfo );
+ graphWidget->drawGraph( TRUE );
+}
+
+void Checkbook::drawBalanceChart()
+{
+ DataPointList *list = new DataPointList();
+
+ float balance = startBalance;
+ float amount;
+ QString label;
+ int i = 0;
+ int count = transactions.count();
+
+ for ( TranInfo *tran = transactions.first(); tran; tran = transactions.next() )
+ {
+ i++;
+ balance -= tran->fee();
+ amount = tran->amount();
+ if ( tran->withdrawal() )
+ {
+ amount *= -1;
+ }
+ balance += amount;
+ if ( i == 1 || i == count / 2 || i == count )
+ {
+ label = tran->datestr();
+ }
+ else
+ {
+ label = "";
+ }
+ list->append( new DataPointInfo( label, balance ) );
+ }
+
+ graphInfo = new GraphInfo( GraphInfo::BarChart, list );
+}
+
+void Checkbook::drawCategoryChart( bool withdrawals )
+{
+ DataPointList *list = new DataPointList();
+
+ TranInfo *tran = transactions.first();
+ if ( tran->withdrawal() == withdrawals )
+ {
+ list->append( new DataPointInfo( tran->category(), tran->amount() ) );
+ }
+ tran = transactions.next();
+
+ DataPointInfo *cat;
+ for ( ; tran; tran = transactions.next() )
+ {
+ if ( tran->withdrawal() == withdrawals )
+ {
+ // Find category in list
+ for ( cat = list->first(); cat; cat = list->next() )
+ {
+ if ( cat->label() == tran->category() )
+ {
+ break;
+ }
+ }
+ if ( cat && cat->label() == tran->category() )
+ { // Found category, add to transaction to category total
+ cat->addToValue( tran->amount() );
+ }
+ else
+ { // Didn't find category, add category to list
+ list->append( new DataPointInfo( tran->category(), tran->amount() ) );
+ }
+ }
+ }
+
+ graphInfo = new GraphInfo( GraphInfo::PieChart, list );
}
diff --git a/noncore/apps/checkbook/checkbook.h b/noncore/apps/checkbook/checkbook.h
index 01f1115..287788a 100644
--- a/noncore/apps/checkbook/checkbook.h
+++ b/noncore/apps/checkbook/checkbook.h
@@ -27,24 +27,25 @@
*/
#ifndef CHECKBOOK_H
#define CHECKBOOK_H
#include "traninfo.h"
#include <qdialog.h>
class OTabWidget;
class Graph;
+class GraphInfo;
class QComboBox;
class QLabel;
class QLineEdit;
class QListView;
class QMultiLineEdit;
class QString;
class Checkbook : public QDialog
{
Q_OBJECT
public:
@@ -75,27 +76,31 @@ class Checkbook : public QDialog
QLineEdit *pinNumEdit;
QLineEdit *balanceEdit;
QMultiLineEdit *notesEdit;
float startBalance;
// Transactions tab
QWidget *initTransactions();
QListView *tranTable;
QLabel *balanceLabel;
float currBalance;
// Charts tab
- QWidget *initCharts();
- //QComboBox *graphList;
- Graph *graphWidget;
+ QWidget *initCharts();
+ GraphInfo *graphInfo;
+ QComboBox *graphList;
+ Graph *graphWidget;
+
+ void drawBalanceChart();
+ void drawCategoryChart( bool = TRUE );
protected slots:
void accept();
private slots:
void slotNameChanged( const QString & );
void slotStartingBalanceChanged( const QString & );
void slotNewTran();
void slotEditTran();
void slotDeleteTran();
void slotDrawGraph();
};
diff --git a/noncore/apps/checkbook/graph.cpp b/noncore/apps/checkbook/graph.cpp
index bae92da..a0d8b78 100644
--- a/noncore/apps/checkbook/graph.cpp
+++ b/noncore/apps/checkbook/graph.cpp
@@ -20,31 +20,31 @@
 :     =  ...= . :.=- You should have received a copy of the GNU
 -.   .:....=;==+<; General Public License along with this file;
  -_. . .   )=.  = see the file COPYING. If not, write to the
    --        :-=` Free Software Foundation, Inc.,
59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "graph.h"
#include "graphinfo.h"
+#include <qcolor.h>
+#include <qfontmetrics.h>
#include <qpainter.h>
Graph::Graph( QWidget *parent, GraphInfo *d, const QString &name, int flags )
: QWidget( parent, name, flags )
{
- setBackgroundMode( QWidget::PaletteBase );
-
data = d;
graph.setOptimization( QPixmap::BestOptim );
}
void Graph::setGraphInfo( GraphInfo *d )
{
data = d;
}
void Graph::drawGraph( bool regen )
{
@@ -73,40 +73,107 @@ void Graph::initGraph()
if ( !data )
{
return;
}
// Any common stuff here (titles, ???)
switch ( data->graphType() )
{
case GraphInfo::BarChart :
{
- drawBarChart();
+ drawBarChart( width(), height(), data->maxValue() );
}
break;
case GraphInfo::LineChart :
{
- drawLineChart();
+ //drawLineChart( p, s, min, max );
}
break;
case GraphInfo::PieChart :
{
- drawPieChart();
+ drawPieChart( width(), height(), data->totalValue() );
}
};
}
-void Graph::drawBarChart()
+void Graph::drawBarChart( int width, int height, float max )
{
- //Find max value in GraphInfo->dataPoints() - make function in GraphInfo!!!
+ QPainter p( &graph );
+
+ // Try to set the font size smaller for text
+ QFont f = font();
+ f.setPointSize( 8 );
+ p.setFont( f );
+
+ int x = 0;
+ int i = 0;
+ int n = data->numberDataPoints();
+ QFontMetrics fm=fontMetrics();
+ int fh = fm.height();
+ int fw;
+
+ QColor c( 0, 0, 255);
+ p.setBrush( c );
+
+ for (DataPointInfo *dp = data->firstDataPoint(); dp; dp = data->nextDataPoint() )
+ {
+ int bw = ( width - width / 4 - x ) / ( n - i );
+ int bh = int( ( height - height / 4 - 1 ) * dp->value() / max );
+ p.drawRect( width / 8 + x, height - height / 8 - 1 - bh, bw, bh );
+ fw = fm.width( dp->label() );
+ p.drawText( width / 8 + x - fw / 2 + bw / 2, height - height / 8, fw,
+ fh + height / 8, AlignTop | AlignHCenter, dp->label() );
+// WordBreak | AlignTop | AlignHCenter, dp->label() );
+ i++;
+ x += bw;
+ }
}
-void Graph::drawLineChart()
+void Graph::drawLineChart( int width, int height, float max )
{
}
-void Graph::drawPieChart()
+void Graph::drawPieChart( int width, int height, float sum )
{
+ QPainter p( &graph );
+
+ // Try to set the font size smaller for text
+ QFont f = font();
+ f.setPointSize( 8 );
+ p.setFont( f );
+
+ int n = data->numberDataPoints();
+
+ int apos = -90 * 16;
+
+ int xd = width - width / 5;
+ int yd = height - height / 5;
+
+ int i = 0;
+
+ QColor c;
+
+ for (DataPointInfo *dp = data->firstDataPoint(); dp; dp = data->nextDataPoint() )
+ {
+ c.setHsv( ( i *255) / n, 255, 255 );
+ p.setBrush( c );
+
+ int a = int( ( dp->value() * 360.0 ) / sum * 16.0 + 0.5 );
+ p.drawPie( width/10, height/10, xd, yd, -apos, -a );
+ apos += a;
+ i++;
+ }
+
+ double apos2 = -90 * 3.14159 / 180;
+ for (DataPointInfo *dp = data->firstDataPoint(); dp; dp = data->nextDataPoint() )
+ {
+ double a = dp->value() *360 / sum * 3.14159 / 180;
+ int x = int( cos( apos2 + a/2 ) * width * 5/16 + width/2 + 0.5 );
+ int y = int( sin( apos2 + a/2 ) * height * 5/16 + height/2 + 0.5 );
+ p.drawText( x - width/8, y - height/8, width/4, height/4, WordBreak | AlignCenter,
+ dp->label() );
+ apos2 += a;
+ }
}
diff --git a/noncore/apps/checkbook/graph.h b/noncore/apps/checkbook/graph.h
index 7379be7..40b23cd 100644
--- a/noncore/apps/checkbook/graph.h
+++ b/noncore/apps/checkbook/graph.h
@@ -24,40 +24,41 @@
59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef GRAPH_H
#define GRAPH_H
#include <qpixmap.h>
#include <qwidget.h>
class GraphInfo;
+class QPainter;
class Graph : public QWidget
{
Q_OBJECT
public:
Graph( QWidget * = 0x0, GraphInfo * = 0x0, const QString & = 0x0, int = 0 );
void setGraphInfo( GraphInfo * );
void drawGraph( bool = FALSE );
-
+
protected:
void paintEvent( QPaintEvent * );
void resizeEvent( QResizeEvent * );
private:
GraphInfo *data;
QPixmap graph;
void initGraph();
- void drawBarChart();
- void drawLineChart();
- void drawPieChart();
+ void drawBarChart( int, int, float );
+ void drawLineChart( int, int, float );
+ void drawPieChart( int, int, float );
};
#endif
diff --git a/noncore/apps/checkbook/graphinfo.cpp b/noncore/apps/checkbook/graphinfo.cpp
index 7b06bdb..ec6a465 100644
--- a/noncore/apps/checkbook/graphinfo.cpp
+++ b/noncore/apps/checkbook/graphinfo.cpp
@@ -29,52 +29,91 @@
#include "graphinfo.h"
GraphInfo::GraphInfo( GraphType type, DataPointList *data, const QString &title,
const QString &xtitle, const QString &ytitle )
{
t = type;
d = data;
gt = title;
xt = xtitle;
yt = ytitle;
}
+GraphInfo::~GraphInfo()
+{
+ if ( d )
+ {
+ for ( DataPointInfo *data = d->first(); data; data = d->next() )
+ {
+ delete data;
+ }
+ }
+}
+
GraphInfo::GraphType GraphInfo::graphType()
{
return t;
}
void GraphInfo::setGraphType( GraphType type )
{
t = type;
}
DataPointList *GraphInfo::dataPoints()
{
return d;
}
void GraphInfo::setDataPoints( DataPointList *data )
{
d = data;
}
-float GraphInfo::maxValue()
+DataPointInfo *GraphInfo::firstDataPoint()
{
- float max;
+ return( d->first() );
+}
+DataPointInfo *GraphInfo::nextDataPoint()
+{
+ return( d->next() );
+}
+
+int GraphInfo::numberDataPoints()
+{
+ return( d->count() );
+}
+
+float GraphInfo::maxValue()
+{
+ float max = 0.0;
+ for ( DataPointInfo *data = d->first(); data; data = d->next() )
+ {
+ if ( data->value() > max )
+ {
+ max = data->value();
+ }
+ }
+ return max;
}
-float GraphInfo::minValue()
+float GraphInfo::totalValue()
{
+ float sum = 0.0;
+ for ( DataPointInfo *data = d->first(); data; data = d->next() )
+ {
+ sum += data->value();
+ }
+ return sum;
}
void GraphInfo::setGraphTitle( const QString &title )
{
gt = title;
}
void GraphInfo::setXAxisTitle( const QString &xtitle )
{
xt = xtitle;
}
diff --git a/noncore/apps/checkbook/graphinfo.h b/noncore/apps/checkbook/graphinfo.h
index 4ad1dc9..620da74 100644
--- a/noncore/apps/checkbook/graphinfo.h
+++ b/noncore/apps/checkbook/graphinfo.h
@@ -33,48 +33,54 @@
#include <qstringlist.h>
class DataPointInfo
{
public:
DataPointInfo()
: l( 0x0 ), v( 0.0 ) {}
DataPointInfo( const QString &label, float value )
: l( label ), v( value ) {}
const QString &label() { return l; }
float value() { return v; }
+
+ void addToValue( float value ) { v += value; }
private:
QString l;
float v;
};
typedef QList<DataPointInfo> DataPointList;
class GraphInfo
{
public:
enum GraphType { BarChart, LineChart, PieChart };
GraphInfo( GraphType = BarChart, DataPointList * = 0x0,
const QString & = 0x0, const QString & = 0x0, const QString & = 0x0 );
+ ~GraphInfo();
GraphInfo::GraphType graphType();
void setGraphType( GraphType );
DataPointList *dataPoints();
void setDataPoints( DataPointList * );
+ DataPointInfo *firstDataPoint();
+ DataPointInfo *nextDataPoint();
+ int numberDataPoints();
float maxValue();
- float minValue();
+ float totalValue();
void setGraphTitle( const QString & );
void setXAxisTitle( const QString & );
void setYAxisTitle( const QString & );
private:
GraphType t;
DataPointList *d;
QString gt;
QString xt;
QString yt;
};