/***************************************************************************
khomeview . cpp - description
- - - - - - - - - - - - - - - - - - -
begin : Tue Jan 22 2002
copyright : ( C ) 2000 - 2002 by Michael Edwardes
email : mte @ users . sourceforge . net
Javier Campos Morales < javi_c @ users . sourceforge . net >
Felix Rodriguez < frodriguez @ users . sourceforge . net >
John C < thetacoturtle @ users . sourceforge . net >
Thomas Baumgart < ipwizard @ users . sourceforge . net >
Kevin Tambascio < ktambascio @ users . sourceforge . net >
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/***************************************************************************
* *
* 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 . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
// ----------------------------------------------------------------------------
// TQt Includes
# include <tqlayout.h>
# include <tqdatetime.h>
# include <tqapplication.h>
# include <dom/dom_element.h>
# include <dom/dom_doc.h>
# include <dom/dom_text.h>
# include <tqfile.h>
# include <tqtextstream.h>
# include <tqtimer.h>
# include <tqbuffer.h>
// ----------------------------------------------------------------------------
// TDE Includes
# include <tdeglobal.h>
# include <tdelocale.h>
# include <kstandarddirs.h>
# include <tdehtmlview.h>
# include <tdeconfig.h>
# include <kstdaction.h>
# include <tdemainwindow.h>
# include <tdeactioncollection.h>
# include <tdeapplication.h>
# include <tdemessagebox.h>
# include <kdebug.h>
# include <kmdcodec.h>
# include <tdeglobalsettings.h>
# include <kiconloader.h>
// ----------------------------------------------------------------------------
// Project Includes
# include "khomeview.h"
# include "../kmymoneyutils.h"
# include "../kmymoneyglobalsettings.h"
# include "../mymoney/mymoneyfile.h"
# include "../mymoney/mymoneyforecast.h"
# include "../kmymoney2.h"
# include "../reports/kreportchartview.h"
# include "../reports/pivottable.h"
# include "../reports/pivotgrid.h"
# include "../reports/reportaccount.h"
# include "../kmymoneyglobalsettings.h"
# define VIEW_LEDGER "ledger"
# define VIEW_SCHEDULE "schedule"
# define VIEW_WELCOME "welcome"
# define VIEW_HOME "home"
# define VIEW_REPORTS "reports"
// in KOffice version < 1.5 KDCHART_PROPSET_NORMAL_DATA was a static const
// but in 1.5 this has been changed into a #define'd value. So we have to
// make sure, we use the right one.
# ifndef KDCHART_PROPSET_NORMAL_DATA
# define KMM_KDCHART_PROPSET_NORMAL_DATA KDChartParams::KDCHART_PROPSET_NORMAL_DATA
# else
# define KMM_KDCHART_PROPSET_NORMAL_DATA KDCHART_PROPSET_NORMAL_DATA
# endif
using namespace reports ;
class KHomeView : : Private
{
public :
Private ( ) { }
void addNameIndex ( TQMap < TQString , MyMoneyAccount > & idx , const MyMoneyAccount & account ) ;
} ;
void KHomeView : : Private : : addNameIndex ( TQMap < TQString , MyMoneyAccount > & idx , const MyMoneyAccount & account )
{
TQString key = account . name ( ) ;
if ( idx [ key ] . id ( ) . isEmpty ( ) ) {
idx [ key ] = account ;
//take care of accounts with duplicate names
} else if ( idx [ key ] . id ( ) ! = account . id ( ) ) {
key = account . name ( ) + " [%1] " ;
int dup = 2 ;
while ( ! idx [ key . arg ( dup ) ] . id ( ) . isEmpty ( )
& & idx [ key . arg ( dup ) ] . id ( ) ! = account . id ( ) )
+ + dup ;
idx [ key . arg ( dup ) ] = account ;
}
}
KHomeView : : KHomeView ( TQWidget * parent , const char * name ) :
KMyMoneyViewBase ( parent , name , i18n ( " Home " ) ) ,
d ( new Private ) ,
m_showAllSchedules ( false ) ,
m_needReload ( true )
{
m_part = new TDEHTMLPart ( this , " htmlpart_km2 " ) ;
addWidget ( m_part - > view ( ) ) ;
m_filename = KMyMoneyUtils : : findResource ( " appdata " , TQString ( " html/home%1.html " ) ) ;
// m_part->openURL(m_filename);
connect ( m_part - > browserExtension ( ) , TQ_SIGNAL ( openURLRequest ( const KURL & , const KParts : : URLArgs & ) ) ,
this , TQ_SLOT ( slotOpenURL ( const KURL & , const KParts : : URLArgs & ) ) ) ;
connect ( MyMoneyFile : : instance ( ) , TQ_SIGNAL ( dataChanged ( ) ) , this , TQ_SLOT ( slotLoadView ( ) ) ) ;
}
KHomeView : : ~ KHomeView ( )
{
// if user wants to remember the font size, store it here
if ( KMyMoneyGlobalSettings : : rememberFontSize ( ) )
{
KMyMoneyGlobalSettings : : setFontSizePercentage ( m_part - > zoomFactor ( ) ) ;
//kdDebug() << "Storing font size: " << m_part->zoomFactor() << endl;
KMyMoneyGlobalSettings : : self ( ) - > writeConfig ( ) ;
}
delete d ;
}
void KHomeView : : slotLoadView ( void )
{
m_needReload = true ;
if ( isVisible ( ) ) {
loadView ( ) ;
m_needReload = false ;
}
}
void KHomeView : : show ( void )
{
if ( m_needReload ) {
loadView ( ) ;
m_needReload = false ;
}
TQWidget : : show ( ) ;
}
void KHomeView : : slotPrintView ( void )
{
if ( m_part & & m_part - > view ( ) )
m_part - > view ( ) - > print ( ) ;
}
void KHomeView : : loadView ( void )
{
m_part - > setZoomFactor ( KMyMoneyGlobalSettings : : fontSizePercentage ( ) ) ;
//kdDebug() << "Setting font size: " << m_part->zoomFactor() << endl;
TQValueList < MyMoneyAccount > list ;
MyMoneyFile : : instance ( ) - > accountList ( list ) ;
if ( list . count ( ) = = 0 )
{
m_part - > openURL ( m_filename ) ;
#if 0
// (ace) I am experimenting with replacing links in the
// html depending on the state of the engine. It's not
// working. That's why it's #if0'd out.
DOM : : Element e = m_part - > document ( ) . getElementById ( " test " ) ;
if ( e . isNull ( ) )
{
tqDebug ( " Element id=test not found " ) ;
}
else
{
tqDebug ( " Element id=test found! " ) ;
TQString tagname = e . tagName ( ) . string ( ) ;
tqDebug ( tagname ) ;
tqDebug ( TQString ( " %1 id=%2 " ) . arg ( e . tagName ( ) . string ( ) ) . arg ( e . getAttribute ( " id " ) . string ( ) ) ) ;
// Find the character data node
DOM : : Node n = e . firstChild ( ) ;
while ( ! n . isNull ( ) )
{
tqDebug ( " Child type %u " , static_cast < unsigned > ( n . nodeType ( ) ) ) ;
if ( n . nodeType ( ) = = DOM : : Node : : TEXT_NODE )
{
DOM : : Text t = n ;
t . setData ( " Success!! " ) ;
e . replaceChild ( n , t ) ;
m_part - > document ( ) . setDesignMode ( true ) ;
m_part - > document ( ) . importNode ( e , true ) ;
m_part - > document ( ) . updateRendering ( ) ;
tqDebug ( TQString ( " Data is now %1 " ) . arg ( t . data ( ) . string ( ) ) ) ;
}
n = n . nextSibling ( ) ;
}
}
# endif
} else {
//clear the forecast flag so it will be reloaded
m_forecast . setForecastDone ( false ) ;
TQString filename = TDEGlobal : : dirs ( ) - > findResource ( " appdata " , " html/kmymoney2.css " ) ;
TQString header = TQString ( " <!DOCTYPE HTML PUBLIC \" -//W3C//DTD HTML 4.0//EN \" > \n <html><head><link rel= \" stylesheet \" type= \" text/css \" href= \" %1 \" > \n " ) . arg ( filename ) ;
header + = KMyMoneyUtils : : variableCSS ( ) ;
header + = " </head><body id= \" summaryview \" > \n " ;
TQString footer = " </body></html> \n " ;
m_part - > begin ( ) ;
m_part - > write ( header ) ;
m_part - > write ( TQString ( " <div id= \" summarytitle \" >%1</div> " ) . arg ( i18n ( " Your Financial Summary " ) ) ) ;
TQStringList settings = KMyMoneyGlobalSettings : : itemList ( ) ;
TQStringList : : ConstIterator it ;
for ( it = settings . begin ( ) ; it ! = settings . end ( ) ; + + it ) {
int option = ( * it ) . toInt ( ) ;
if ( option > 0 ) {
switch ( option ) {
case 1 : // payments
showPayments ( ) ;
break ;
case 2 : // preferred accounts
showAccounts ( Preferred , i18n ( " Preferred Accounts " ) ) ;
break ;
case 3 : // payment accounts
// Check if preferred accounts are shown separately
if ( settings . find ( " 2 " ) = = settings . end ( ) ) {
showAccounts ( static_cast < paymentTypeE > ( Payment | Preferred ) ,
i18n ( " Payment Accounts " ) ) ;
} else {
showAccounts ( Payment , i18n ( " Payment Accounts " ) ) ;
}
break ;
case 4 : // favorite reports
showFavoriteReports ( ) ;
break ;
case 5 : // forecast
showForecast ( ) ;
break ;
case 6 : // net worth graph over all accounts
showNetWorthGraph ( ) ;
break ;
case 8 : // assets and liabilities
showAssetsLiabilities ( ) ;
break ;
case 9 : // budget
showBudget ( ) ;
break ;
case 10 : // cash flow summary
showCashFlowSummary ( ) ;
break ;
}
m_part - > write ( " <div class= \" gap \" > </div> \n " ) ;
}
}
m_part - > write ( " <div id= \" returnlink \" > " ) ;
m_part - > write ( link ( VIEW_WELCOME , TQString ( ) ) + i18n ( " Show KMyMoney welcome page " ) + linkend ( ) ) ;
m_part - > write ( " </div> " ) ;
m_part - > write ( " <div id= \" vieweffect \" ></div> " ) ;
m_part - > write ( footer ) ;
m_part - > end ( ) ;
}
}
void KHomeView : : showNetWorthGraph ( void )
{
# ifdef HAVE_KDCHART
m_part - > write ( TQString ( " <div class= \" shadow \" ><div class= \" displayblock \" ><div class= \" summaryheader \" >%1</div> \n <div class= \" gap \" > </div> \n " ) . arg ( i18n ( " Networth Forecast " ) ) ) ;
MyMoneyReport reportCfg = MyMoneyReport (
MyMoneyReport : : eAssetLiability ,
MyMoneyReport : : eMonths ,
MyMoneyTransactionFilter : : userDefined , // overridden by the setDateFilter() call below
MyMoneyReport : : eDetailTotal ,
i18n ( " Networth Forecast " ) ,
i18n ( " Generated Report " ) ) ;
reportCfg . setChartByDefault ( true ) ;
reportCfg . setChartGridLines ( false ) ;
reportCfg . setChartDataLabels ( false ) ;
reportCfg . setChartType ( MyMoneyReport : : eChartLine ) ;
reportCfg . setIncludingSchedules ( false ) ;
reportCfg . addAccountGroup ( MyMoneyAccount : : Asset ) ;
reportCfg . addAccountGroup ( MyMoneyAccount : : Liability ) ;
reportCfg . setColumnsAreDays ( true ) ;
reportCfg . setConvertCurrency ( true ) ;
reportCfg . setIncludingForecast ( true ) ;
reportCfg . setDateFilter ( TQDate : : currentDate ( ) , TQDate : : currentDate ( ) . addDays ( + 90 ) ) ;
reports : : PivotTable table ( reportCfg ) ;
reports : : KReportChartView * chartWidget = new reports : : KReportChartView ( 0 , 0 ) ;
table . drawChart ( * chartWidget ) ;
chartWidget - > params ( ) - > setLineMarker ( false ) ;
chartWidget - > params ( ) - > setLegendPosition ( KDChartParams : : NoLegend ) ;
chartWidget - > params ( ) - > setLineWidth ( 2 ) ;
chartWidget - > params ( ) - > setDataColor ( 0 , TDEGlobalSettings : : textColor ( ) ) ;
// draw future values in a different line style
KDChartPropertySet propSetFutureValue ( " future value " , KMM_KDCHART_PROPSET_NORMAL_DATA ) ;
propSetFutureValue . setLineStyle ( KDChartPropertySet : : OwnID , TQt : : DotLine ) ;
const int idPropFutureValue = chartWidget - > params ( ) - > registerProperties ( propSetFutureValue ) ;
//KDChartPropertySet propSetLastValue("last value", idPropFutureValue);
//propSetLastValue.setExtraLinesAlign(KDChartPropertySet::OwnID, TQt::AlignLeft | TQt::AlignBottom);
//propSetLastValue.setExtraLinesWidth(KDChartPropertySet::OwnID, -4);
//propSetLastValue.setExtraLinesColor(KDChartPropertySet::OwnID, KMyMoneyGlobalSettings::listGridColor());
// propSetLastValue.setShowMarker(KDChartPropertySet::OwnID, true);
// propSetLastValue.setMarkerStyle(KDChartPropertySet::OwnID, KDChartParams::LineMarkerDiamond);
//const int idPropLastValue = chartWidget->params()->registerProperties(propSetLastValue);
for ( int iCell = 0 ; iCell < 90 ; + + iCell ) {
chartWidget - > setProperty ( 0 , iCell , idPropFutureValue ) ;
}
//chartWidget->setProperty(0, 10, idPropLastValue);
// Adjust the size
if ( width ( ) < chartWidget - > width ( ) ) {
int nh ;
nh = ( width ( ) * chartWidget - > height ( ) ) / chartWidget - > width ( ) ;
chartWidget - > resize ( width ( ) - 80 , nh ) ;
}
TQPixmap pm ( chartWidget - > width ( ) , chartWidget - > height ( ) ) ;
pm . fill ( TDEGlobalSettings : : baseColor ( ) ) ;
TQPainter p ( & pm ) ;
chartWidget - > paintTo ( p ) ;
TQByteArray ba ;
TQBuffer buffer ( ba ) ;
buffer . open ( IO_WriteOnly ) ;
pm . save ( & buffer , " PNG " ) ; // writes pixmap into ba in PNG format
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
m_part - > write ( " <tr> " ) ;
m_part - > write ( TQString ( " <td><center><IMG SRC= \" data:image/png;base64,%1 \" ALT= \" Networth \" ></center></td> " ) . arg ( TQString ( KCodecs : : base64Encode ( ba ) ) ) ) ;
m_part - > write ( " </tr> " ) ;
m_part - > write ( " </table></div></div> " ) ;
delete chartWidget ;
# endif
}
void KHomeView : : showPayments ( void )
{
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
TQValueList < MyMoneySchedule > overdues ;
TQValueList < MyMoneySchedule > schedule ;
int i = 0 ;
//if forecast has not been executed yet, do it.
if ( ! m_forecast . isForecastDone ( ) )
doForecast ( ) ;
schedule = file - > scheduleList ( " " , MyMoneySchedule : : TYPE_ANY ,
MyMoneySchedule : : OCCUR_ANY ,
MyMoneySchedule : : STYPE_ANY ,
TQDate : : currentDate ( ) ,
TQDate : : currentDate ( ) . addMonths ( 1 ) ) ;
overdues = file - > scheduleList ( " " , MyMoneySchedule : : TYPE_ANY ,
MyMoneySchedule : : OCCUR_ANY ,
MyMoneySchedule : : STYPE_ANY ,
TQDate ( ) , TQDate ( ) , true ) ;
if ( schedule . empty ( ) & & overdues . empty ( ) )
return ;
// HACK
// Remove the finished schedules
TQValueList < MyMoneySchedule > : : Iterator d_it ;
for ( d_it = schedule . begin ( ) ; d_it ! = schedule . end ( ) ; )
{
// FIXME cleanup old code
// if ((*d_it).isFinished() || (*d_it).nextPayment((*d_it).lastPayment()) == TQDate())
if ( ( * d_it ) . isFinished ( ) )
{
d_it = schedule . remove ( d_it ) ;
continue ;
}
+ + d_it ;
}
for ( d_it = overdues . begin ( ) ; d_it ! = overdues . end ( ) ; )
{
// FIXME cleanup old code
// if ((*d_it).isFinished() || (*d_it).nextPayment((*d_it).lastPayment()) == TQDate())
if ( ( * d_it ) . isFinished ( ) )
{
d_it = overdues . remove ( d_it ) ;
continue ;
}
+ + d_it ;
}
m_part - > write ( " <div class= \" shadow \" ><div class= \" displayblock \" > " ) ;
m_part - > write ( TQString ( " <div class= \" summaryheader \" >%1</div> \n " ) . arg ( i18n ( " Payments " ) ) ) ;
if ( overdues . count ( ) > 0 ) {
m_part - > write ( " <div class= \" gap \" > </div> \n " ) ;
qBubbleSort ( overdues ) ;
TQValueList < MyMoneySchedule > : : Iterator it ;
TQValueList < MyMoneySchedule > : : Iterator it_f ;
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
m_part - > write ( TQString ( " <tr class= \" itemtitle warningtitle \" ><td colspan= \" 5 \" >%1</td></tr> \n " ) . arg ( showColoredAmount ( i18n ( " Overdue payments " ) , true ) ) ) ;
m_part - > write ( " <tr class= \" item warning \" > " ) ;
m_part - > write ( " <td class= \" left \" width= \" 10% \" > " ) ;
m_part - > write ( i18n ( " Date " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" left \" width= \" 40% \" > " ) ;
m_part - > write ( i18n ( " Schedule " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" left \" width= \" 20% \" > " ) ;
m_part - > write ( i18n ( " Account " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 15% \" > " ) ;
m_part - > write ( i18n ( " Amount " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 15% \" > " ) ;
m_part - > write ( i18n ( " Balance after " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " </tr> " ) ;
for ( it = overdues . begin ( ) ; it ! = overdues . end ( ) ; + + it ) {
// determine number of overdue payments
TQDate nextDate = ( * it ) . adjustedNextDueDate ( ) ;
int cnt = 0 ;
while ( nextDate . isValid ( ) & & nextDate < TQDate : : currentDate ( ) ) {
+ + cnt ;
nextDate = ( * it ) . nextPayment ( nextDate ) ;
// for single occurence nextDate will not change, so we
// better get out of here.
if ( ( * it ) . occurence ( ) = = MyMoneySchedule : : OCCUR_ONCE )
break ;
}
m_part - > write ( TQString ( " <tr class= \" row-%1 \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
showPaymentEntry ( * it , cnt ) ;
m_part - > write ( " </tr> " ) ;
// make sure to not repeat overdues later again
for ( it_f = schedule . begin ( ) ; it_f ! = schedule . end ( ) ; ) {
if ( ( * it ) . id ( ) = = ( * it_f ) . id ( ) ) {
it_f = schedule . remove ( it_f ) ;
continue ;
}
+ + it_f ;
}
}
m_part - > write ( " </table> " ) ;
}
if ( schedule . count ( ) > 0 ) {
qBubbleSort ( schedule ) ;
// Extract todays payments if any
TQValueList < MyMoneySchedule > todays ;
TQValueList < MyMoneySchedule > : : Iterator t_it ;
for ( t_it = schedule . begin ( ) ; t_it ! = schedule . end ( ) ; ) {
if ( ( * t_it ) . nextDueDate ( ) = = TQDate : : currentDate ( ) ) {
todays . append ( * t_it ) ;
( * t_it ) . setNextDueDate ( ( * t_it ) . nextPayment ( ( * t_it ) . nextDueDate ( ) ) ) ;
//if nextDueDate is still currentDate then remove it from scheduled payments
if ( ( * t_it ) . nextDueDate ( ) = = TQDate : : currentDate ( ) ) {
t_it = schedule . remove ( t_it ) ;
continue ;
}
}
+ + t_it ;
}
if ( todays . count ( ) > 0 ) {
m_part - > write ( " <div class= \" gap \" > </div> \n " ) ;
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
m_part - > write ( TQString ( " <tr class= \" itemtitle \" ><td class= \" left \" colspan= \" 5 \" >%1</td></tr> \n " ) . arg ( i18n ( " Today's payments " ) ) ) ;
m_part - > write ( " <tr class= \" item \" > " ) ;
m_part - > write ( " <td class= \" left \" width= \" 10% \" > " ) ;
m_part - > write ( i18n ( " Date " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" left \" width= \" 40% \" > " ) ;
m_part - > write ( i18n ( " Schedule " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" left \" width= \" 20% \" > " ) ;
m_part - > write ( i18n ( " Account " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 15% \" > " ) ;
m_part - > write ( i18n ( " Amount " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 15% \" > " ) ;
m_part - > write ( i18n ( " Balance after " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " </tr> " ) ;
for ( t_it = todays . begin ( ) ; t_it ! = todays . end ( ) ; + + t_it ) {
m_part - > write ( TQString ( " <tr class= \" row-%1 \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
showPaymentEntry ( * t_it ) ;
m_part - > write ( " </tr> " ) ;
}
m_part - > write ( " </table> " ) ;
}
if ( schedule . count ( ) > 0 )
{
m_part - > write ( " <div class= \" gap \" > </div> \n " ) ;
TQValueList < MyMoneySchedule > : : Iterator it ;
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
m_part - > write ( TQString ( " <tr class= \" itemtitle \" ><td class= \" left \" colspan= \" 5 \" >%1</td></tr> \n " ) . arg ( i18n ( " Future payments " ) ) ) ;
m_part - > write ( " <tr class= \" item \" > " ) ;
m_part - > write ( " <td class= \" left \" width= \" 10% \" > " ) ;
m_part - > write ( i18n ( " Date " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" left \" width= \" 40% \" > " ) ;
m_part - > write ( i18n ( " Schedule " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" left \" width= \" 20% \" > " ) ;
m_part - > write ( i18n ( " Account " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 15% \" > " ) ;
m_part - > write ( i18n ( " Amount " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 15% \" > " ) ;
m_part - > write ( i18n ( " Balance after " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " </tr> " ) ;
// show all or the first 6 entries
int cnt ;
cnt = ( m_showAllSchedules ) ? - 1 : 6 ;
bool needMoreLess = m_showAllSchedules ;
TQDate lastDate = TQDate : : currentDate ( ) . addMonths ( 1 ) ;
qBubbleSort ( schedule ) ;
do {
it = schedule . begin ( ) ;
if ( it = = schedule . end ( ) )
break ;
// if the next due date is invalid (schedule is finished)
// we remove it from the list
TQDate nextDate = ( * it ) . nextDueDate ( ) ;
if ( ! nextDate . isValid ( ) ) {
schedule . remove ( it ) ;
continue ;
}
if ( nextDate > lastDate )
break ;
if ( cnt = = 0 ) {
needMoreLess = true ;
break ;
}
if ( cnt > 0 )
- - cnt ;
m_part - > write ( TQString ( " <tr class= \" row-%1 \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
showPaymentEntry ( * it ) ;
m_part - > write ( " </tr> " ) ;
// for single occurence we have reported everything so we
// better get out of here.
if ( ( * it ) . occurence ( ) = = MyMoneySchedule : : OCCUR_ONCE ) {
schedule . remove ( it ) ;
continue ;
}
//if nextPayment returns an invalid date, setNextDueDate will just skip it, resulting in a loop
//we check the resulting date and erase the schedule if invalid
if ( ! ( ( * it ) . nextPayment ( ( * it ) . nextDueDate ( ) ) ) . isValid ( ) ) {
schedule . remove ( it ) ;
continue ;
}
( * it ) . setNextDueDate ( ( * it ) . nextPayment ( ( * it ) . nextDueDate ( ) ) ) ;
qBubbleSort ( schedule ) ;
}
while ( 1 ) ;
if ( needMoreLess ) {
m_part - > write ( TQString ( " <tr class= \" row-%1 \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
m_part - > write ( " <td> " ) ;
if ( m_showAllSchedules ) {
m_part - > write ( link ( VIEW_SCHEDULE , TQString ( " ?mode=%1 " ) . arg ( " reduced " ) ) + i18n ( " Less... " ) + linkend ( ) ) ;
} else {
m_part - > write ( link ( VIEW_SCHEDULE , TQString ( " ?mode=%1 " ) . arg ( " full " ) ) + i18n ( " More... " ) + linkend ( ) ) ;
}
m_part - > write ( " </td><td></td><td></td><td></td><td></td> " ) ;
m_part - > write ( " </tr> " ) ;
}
m_part - > write ( " </table> " ) ;
}
}
m_part - > write ( " </div></div> " ) ;
}
void KHomeView : : showPaymentEntry ( const MyMoneySchedule & sched , int cnt )
{
TQString tmp ;
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
try {
MyMoneyAccount acc = sched . account ( ) ;
if ( ! acc . id ( ) . isEmpty ( ) ) {
MyMoneyTransaction t = sched . transaction ( ) ;
// only show the entry, if it is still active
// FIXME clean old code
// if(!sched.isFinished() && sched.nextPayment(sched.lastPayment()) != TQDate()) {
if ( ! sched . isFinished ( ) ) {
MyMoneySplit sp = t . splitByAccount ( acc . id ( ) , true ) ;
TQString pathEnter , pathSkip ;
TDEGlobal : : iconLoader ( ) - > loadIcon ( " key_enter " , TDEIcon : : Small , TDEIcon : : SizeSmall , TDEIcon : : DefaultState , & pathEnter ) ;
Bring mail_forward, mail_new, mail_replyall, mail_reply, mail_send, player_pause, player_play, player_stop, player_rew, player_fwd, player_start, player_end, rotate_ccw, rotate_cw, window_fullscreen, window_nofullscreen, window_new, viewmagfit, viewmag+, viewmag1, and viewmag- icons into XDG compliance
10 years ago
TDEGlobal : : iconLoader ( ) - > loadIcon ( " media-seek-forward " , TDEIcon : : Small , TDEIcon : : SizeSmall , TDEIcon : : DefaultState , & pathSkip ) ;
//show payment date
tmp = TQString ( " <td> " ) +
TDEGlobal : : locale ( ) - > formatDate ( sched . adjustedNextDueDate ( ) , true ) +
" </td><td> " ;
if ( pathEnter . length ( ) > 0 )
tmp + = link ( VIEW_SCHEDULE , TQString ( " ?id=%1&mode=enter " ) . arg ( sched . id ( ) ) , i18n ( " Enter schedule " ) ) + TQString ( " <img src= \" file://%1 \" border= \" 0 \" ></a> " ) . arg ( pathEnter ) + linkend ( ) ;
if ( pathSkip . length ( ) > 0 )
tmp + = " " + link ( VIEW_SCHEDULE , TQString ( " ?id=%1&mode=skip " ) . arg ( sched . id ( ) ) , i18n ( " Skip schedule " ) ) + TQString ( " <img src= \" file://%1 \" border= \" 0 \" ></a> " ) . arg ( pathSkip ) + linkend ( ) ;
tmp + = TQString ( " " ) ;
tmp + = link ( VIEW_SCHEDULE , TQString ( " ?id=%1&mode=edit " ) . arg ( sched . id ( ) ) , i18n ( " Edit schedule " ) ) + sched . name ( ) + linkend ( ) ;
//show quantity of payments overdue if any
if ( cnt > 1 )
tmp + = i18n ( " (%1 payments) " ) . arg ( cnt ) ;
//show account of the main split
tmp + = " </td><td> " ;
tmp + = TQString ( file - > account ( acc . id ( ) ) . name ( ) ) ;
//show amount of the schedule
tmp + = " </td><td align= \" right \" > " ;
const MyMoneySecurity & currency = MyMoneyFile : : instance ( ) - > currency ( acc . currencyId ( ) ) ;
TQString amount = ( sp . value ( ) * cnt ) . formatMoney ( acc , currency ) ;
amount . replace ( " " , " " ) ;
tmp + = showColoredAmount ( amount , ( sp . value ( ) * cnt ) . isNegative ( ) ) ;
tmp + = " </td> " ;
//show balance after payments
tmp + = " <td align= \" right \" > " ;
MyMoneyMoney payment = MyMoneyMoney ( ( sp . value ( ) * cnt ) ) ;
TQDate paymentDate = TQDate ( sched . nextDueDate ( ) ) ;
MyMoneyMoney balanceAfter = forecastPaymentBalance ( acc , payment , paymentDate ) ;
TQString balance = balanceAfter . formatMoney ( acc , currency ) ;
balance . replace ( " " , " " ) ;
tmp + = showColoredAmount ( balance , balanceAfter . isNegative ( ) ) ;
tmp + = " </td> " ;
// tqDebug(TQString("paymentEntry = '%1'").arg(tmp));
m_part - > write ( tmp ) ;
}
}
} catch ( MyMoneyException * e ) {
tqDebug ( TQString ( " Unable to display schedule entry: %1 " ) . arg ( e - > what ( ) ) ) ;
delete e ;
}
}
void KHomeView : : showAccounts ( KHomeView : : paymentTypeE type , const TQString & header )
{
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
TQValueList < MyMoneyAccount > accounts ;
TQValueList < MyMoneyAccount > : : Iterator it ;
TQValueList < MyMoneyAccount > : : Iterator prevIt ;
TQMap < TQString , MyMoneyAccount > nameIdx ;
bool showClosedAccounts = kmymoney2 - > toggleAction ( " view_show_all_accounts " ) - > isChecked ( ) ;
// get list of all accounts
file - > accountList ( accounts ) ;
for ( it = accounts . begin ( ) ; it ! = accounts . end ( ) ; ) {
prevIt = it ;
if ( ! ( * it ) . isClosed ( ) | | showClosedAccounts ) {
switch ( ( * it ) . accountType ( ) ) {
case MyMoneyAccount : : Expense :
case MyMoneyAccount : : Income :
// never show a category account
// Note: This might be different in a future version when
// the homepage also shows category based information
it = accounts . remove ( it ) ;
break ;
// Asset and Liability accounts are only shown if they
// have the preferred flag set
case MyMoneyAccount : : Asset :
case MyMoneyAccount : : Liability :
case MyMoneyAccount : : Investment :
// if preferred accounts are requested, then keep in list
if ( ( * it ) . value ( " PreferredAccount " ) ! = " Yes "
| | ( type & Preferred ) = = 0 ) {
it = accounts . remove ( it ) ;
}
break ;
// Check payment accounts. If payment and preferred is selected,
// then always show them. If only payment is selected, then
// show only if preferred flag is not set.
case MyMoneyAccount : : Checkings :
case MyMoneyAccount : : Savings :
case MyMoneyAccount : : Cash :
case MyMoneyAccount : : CreditCard :
switch ( type & ( Payment | Preferred ) ) {
case Payment :
if ( ( * it ) . value ( " PreferredAccount " ) = = " Yes " )
it = accounts . remove ( it ) ;
break ;
case Preferred :
if ( ( * it ) . value ( " PreferredAccount " ) ! = " Yes " )
it = accounts . remove ( it ) ;
break ;
case Payment | Preferred :
break ;
default :
it = accounts . remove ( it ) ;
break ;
}
break ;
// filter all accounts that are not used on homepage views
default :
it = accounts . remove ( it ) ;
break ;
}
} else if ( ( * it ) . isClosed ( ) | | ( * it ) . isInvest ( ) ) {
// don't show if closed or a stock account
it = accounts . remove ( it ) ;
}
// if we still point to the same account we keep it in the list and move on ;-)
if ( prevIt = = it ) {
d - > addNameIndex ( nameIdx , * it ) ;
+ + it ;
}
}
if ( accounts . count ( ) > 0 ) {
TQString tmp ;
int i = 0 ;
tmp = " <div class= \" shadow \" ><div class= \" displayblock \" ><div class= \" summaryheader \" > " + header + " </div> \n <div class= \" gap \" > </div> \n " ;
m_part - > write ( tmp ) ;
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
m_part - > write ( " <tr class= \" item \" ><td class= \" left \" width= \" 35% \" > " ) ;
m_part - > write ( i18n ( " Account " ) ) ;
m_part - > write ( " </td><td width= \" 25% \" class= \" right \" > " ) ;
m_part - > write ( i18n ( " Current Balance " ) ) ;
m_part - > write ( " </td> " ) ;
//only show limit info if user chose to do so
if ( KMyMoneyGlobalSettings : : showLimitInfo ( ) ) {
m_part - > write ( " <td width= \" 40% \" class= \" right \" > " ) ;
m_part - > write ( i18n ( " To Minimum Balance / Maximum Credit " ) ) ;
m_part - > write ( " </td> " ) ;
}
m_part - > write ( " </tr> " ) ;
TQMap < TQString , MyMoneyAccount > : : const_iterator it_m ;
for ( it_m = nameIdx . begin ( ) ; it_m ! = nameIdx . end ( ) ; + + it_m ) {
m_part - > write ( TQString ( " <tr class= \" row-%1 \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
showAccountEntry ( * it_m ) ;
m_part - > write ( " </tr> " ) ;
}
m_part - > write ( " </table></div></div> " ) ;
}
}
void KHomeView : : showAccountEntry ( const MyMoneyAccount & acc )
{
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
MyMoneySecurity currency = file - > currency ( acc . currencyId ( ) ) ;
MyMoneyMoney value ;
bool showLimit = KMyMoneyGlobalSettings : : showLimitInfo ( ) ;
if ( acc . accountType ( ) = = MyMoneyAccount : : Investment ) {
//investment accounts show the balances of all its subaccounts
value = investmentBalance ( acc ) ;
//investment accounts have no minimum balance
showAccountEntry ( acc , value , MyMoneyMoney ( ) , showLimit ) ;
} else {
//get balance for normal accounts
value = file - > balance ( acc . id ( ) , TQDate : : currentDate ( ) ) ;
//if credit card or checkings account, show maximum credit
if ( acc . accountType ( ) = = MyMoneyAccount : : CreditCard | |
acc . accountType ( ) = = MyMoneyAccount : : Checkings ) {
TQString maximumCredit = acc . value ( " maxCreditAbsolute " ) ;
MyMoneyMoney maxCredit = MyMoneyMoney ( maximumCredit ) ;
showAccountEntry ( acc , value , value - maxCredit , showLimit ) ;
} else {
//otherwise use minimum balance
TQString minimumBalance = acc . value ( " minBalanceAbsolute " ) ;
MyMoneyMoney minBalance = MyMoneyMoney ( minimumBalance ) ;
showAccountEntry ( acc , value , value - minBalance , showLimit ) ;
}
}
}
void KHomeView : : showAccountEntry ( const MyMoneyAccount & acc , const MyMoneyMoney & value , const MyMoneyMoney & valueToMinBal , const bool showMinBal )
{
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
TQString tmp ;
MyMoneySecurity currency = file - > currency ( acc . currencyId ( ) ) ;
TQString amount ;
TQString amountToMinBal ;
//format amounts
amount = value . formatMoney ( acc , currency ) ;
amount . replace ( " " , " " ) ;
if ( showMinBal ) {
amountToMinBal = valueToMinBal . formatMoney ( acc , currency ) ;
amountToMinBal . replace ( " " , " " ) ;
}
tmp = TQString ( " <td> " ) +
link ( VIEW_LEDGER , TQString ( " ?id=%1 " ) . arg ( acc . id ( ) ) ) + acc . name ( ) + linkend ( ) + " </td> " ;
//show account balance
tmp + = TQString ( " <td class= \" right \" >%1</td> " ) . arg ( showColoredAmount ( amount , value . isNegative ( ) ) ) ;
//show minimum balance column if requested
if ( showMinBal ) {
//if it is an investment, show minimum balance empty
if ( acc . accountType ( ) = = MyMoneyAccount : : Investment ) {
tmp + = TQString ( " <td class= \" right \" > </td> " ) ;
} else {
//show minimum balance entry
tmp + = TQString ( " <td class= \" right \" >%1</td> " ) . arg ( showColoredAmount ( amountToMinBal , valueToMinBal . isNegative ( ) ) ) ;
}
}
// tqDebug(TQString("accountEntry = '%1'").arg(tmp));
m_part - > write ( tmp ) ;
}
MyMoneyMoney KHomeView : : investmentBalance ( const MyMoneyAccount & acc )
{
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
MyMoneyMoney value ;
value = file - > balance ( acc . id ( ) ) ;
TQValueList < TQString > : : const_iterator it_a ;
for ( it_a = acc . accountList ( ) . begin ( ) ; it_a ! = acc . accountList ( ) . end ( ) ; + + it_a ) {
MyMoneyAccount stock = file - > account ( * it_a ) ;
try {
MyMoneyMoney val ;
MyMoneyMoney balance = file - > balance ( stock . id ( ) ) ;
MyMoneySecurity security = file - > security ( stock . currencyId ( ) ) ;
MyMoneyPrice price = file - > price ( stock . currencyId ( ) , security . tradingCurrency ( ) ) ;
val = ( balance * price . rate ( security . tradingCurrency ( ) ) ) . convert ( MyMoneyMoney : : precToDenom ( KMyMoneyGlobalSettings : : pricePrecision ( ) ) ) ;
// adjust value of security to the currency of the account
MyMoneySecurity accountCurrency = file - > currency ( acc . currencyId ( ) ) ;
val = val * file - > price ( security . tradingCurrency ( ) , accountCurrency . id ( ) ) . rate ( accountCurrency . id ( ) ) ;
val = val . convert ( acc . fraction ( ) ) ;
value + = val ;
} catch ( MyMoneyException * e ) {
tqWarning ( TQString ( " cannot convert stock balance of %1 to base currency: %2 " ) . arg ( stock . name ( ) , e - > what ( ) ) ) ;
delete e ;
}
}
return value ;
}
void KHomeView : : showFavoriteReports ( void )
{
TQValueList < MyMoneyReport > reports = MyMoneyFile : : instance ( ) - > reportList ( ) ;
if ( reports . count ( ) > 0 )
{
bool firstTime = 1 ;
int row = 0 ;
TQValueList < MyMoneyReport > : : const_iterator it_report = reports . begin ( ) ;
while ( it_report ! = reports . end ( ) )
{
if ( ( * it_report ) . isFavorite ( ) ) {
if ( firstTime ) {
m_part - > write ( TQString ( " <div class= \" shadow \" ><div class= \" displayblock \" ><div class= \" summaryheader \" >%1</div> \n <div class= \" gap \" > </div> \n " ) . arg ( i18n ( " Favorite Reports " ) ) ) ;
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
m_part - > write ( " <tr class= \" item \" ><td class= \" left \" width= \" 40% \" > " ) ;
m_part - > write ( i18n ( " Report " ) ) ;
m_part - > write ( " </td><td width= \" 60% \" class= \" left \" > " ) ;
m_part - > write ( i18n ( " Comment " ) ) ;
m_part - > write ( " </td></tr> " ) ;
firstTime = false ;
}
m_part - > write ( TQString ( " <tr class= \" row-%1 \" ><td>%2%3%4</td><td align= \" left \" >%5</td></tr> " )
. arg ( row + + & 0x01 ? " even " : " odd " )
. arg ( link ( VIEW_REPORTS , TQString ( " ?id=%1 " ) . arg ( ( * it_report ) . id ( ) ) ) )
. arg ( ( * it_report ) . name ( ) )
. arg ( linkend ( ) )
. arg ( ( * it_report ) . comment ( ) )
) ;
}
+ + it_report ;
}
if ( ! firstTime )
m_part - > write ( " </table></div></div> " ) ;
}
}
void KHomeView : : showForecast ( void )
{
TQMap < TQString , MyMoneyAccount > nameIdx ;
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
TQValueList < MyMoneyAccount > accList ;
// if forecast has not been executed yet, do it.
if ( ! m_forecast . isForecastDone ( ) )
doForecast ( ) ;
accList = m_forecast . accountList ( ) ;
// add it to a map to have it ordered by name
TQValueList < MyMoneyAccount > : : const_iterator accList_t = accList . begin ( ) ;
for ( ; accList_t ! = accList . end ( ) ; + + accList_t ) {
d - > addNameIndex ( nameIdx , * accList_t ) ;
}
if ( nameIdx . count ( ) > 0 ) {
int i = 0 ;
int colspan = 1 ;
// get begin day
int beginDay = TQDate : : currentDate ( ) . daysTo ( m_forecast . beginForecastDate ( ) ) ;
// if begin day is today skip to next cycle
if ( beginDay = = 0 )
beginDay = m_forecast . accountsCycle ( ) ;
// Now output header
m_part - > write ( TQString ( " <div class= \" shadow \" ><div class= \" displayblock \" ><div class= \" summaryheader \" >%1</div> \n <div class= \" gap \" > </div> \n " ) . arg ( i18n ( " %1 Day Forecast " ) . arg ( m_forecast . forecastDays ( ) ) ) ) ;
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
m_part - > write ( " <tr class= \" item \" ><td class= \" left \" width= \" 40% \" > " ) ;
m_part - > write ( i18n ( " Account " ) ) ;
m_part - > write ( " </td> " ) ;
int colWidth = 55 / ( m_forecast . forecastDays ( ) / m_forecast . accountsCycle ( ) ) ;
for ( i = 0 ; ( i * m_forecast . accountsCycle ( ) + beginDay ) < = m_forecast . forecastDays ( ) ; + + i ) {
m_part - > write ( TQString ( " <td width= \" %1% \" class= \" right \" > " ) . arg ( colWidth ) ) ;
m_part - > write ( i18n ( " %1 days " ) . arg ( i * m_forecast . accountsCycle ( ) + beginDay ) ) ;
m_part - > write ( " </td> " ) ;
colspan + + ;
}
m_part - > write ( " </tr> " ) ;
// Now output entries
i = 0 ;
TQMap < TQString , MyMoneyAccount > : : ConstIterator it_account ;
for ( it_account = nameIdx . begin ( ) ; it_account ! = nameIdx . end ( ) ; + + it_account ) {
//MyMoneyAccount acc = (*it_n);
m_part - > write ( TQString ( " <tr class= \" row-%1 \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
m_part - > write ( TQString ( " <td width= \" 40% \" > " ) +
link ( VIEW_LEDGER , TQString ( " ?id=%1 " ) . arg ( ( * it_account ) . id ( ) ) ) + ( * it_account ) . name ( ) + linkend ( ) + " </td> " ) ;
int dropZero = - 1 ; //account dropped below zero
int dropMinimum = - 1 ; //account dropped below minimum balance
TQString minimumBalance = ( * it_account ) . value ( " minimumBalance " ) ;
MyMoneyMoney minBalance = MyMoneyMoney ( minimumBalance ) ;
MyMoneySecurity currency ;
MyMoneyMoney forecastBalance ;
//change account to deep currency if account is an investment
if ( ( * it_account ) . isInvest ( ) ) {
MyMoneySecurity underSecurity = file - > security ( ( * it_account ) . currencyId ( ) ) ;
currency = file - > security ( underSecurity . tradingCurrency ( ) ) ;
} else {
currency = file - > security ( ( * it_account ) . currencyId ( ) ) ;
}
for ( int f = beginDay ; f < = m_forecast . forecastDays ( ) ; f + = m_forecast . accountsCycle ( ) ) {
forecastBalance = m_forecast . forecastBalance ( * it_account , TQDate : : currentDate ( ) . addDays ( f ) ) ;
TQString amount ;
amount = forecastBalance . formatMoney ( * it_account , currency ) ;
amount . replace ( " " , " " ) ;
m_part - > write ( TQString ( " <td width= \" %1% \" align= \" right \" > " ) . arg ( colWidth ) ) ;
m_part - > write ( TQString ( " %1</td> " ) . arg ( showColoredAmount ( amount , forecastBalance . isNegative ( ) ) ) ) ;
}
m_part - > write ( " </tr> " ) ;
//Check if the account is going to be below zero or below the minimal balance in the forecast period
//Check if the account is going to be below minimal balance
dropMinimum = m_forecast . daysToMinimumBalance ( * it_account ) ;
//Check if the account is going to be below zero in the future
dropZero = m_forecast . daysToZeroBalance ( * it_account ) ;
// spit out possible warnings
TQString msg ;
// if a minimum balance has been specified, an appropriate warning will
// only be shown, if the drop below 0 is on a different day or not present
if ( dropMinimum ! = - 1
& & ! minBalance . isZero ( )
& & ( dropMinimum < dropZero
| | dropZero = = - 1 ) ) {
switch ( dropMinimum ) {
case - 1 :
break ;
case 0 :
msg = i18n ( " The balance of %1 is below the minimum balance %2 today. " ) . arg ( ( * it_account ) . name ( ) ) . arg ( minBalance . formatMoney ( * it_account , currency ) ) ;
msg = showColoredAmount ( msg , true ) ;
break ;
default :
msg = i18n ( " The balance of %1 will drop below the minimum balance %2 in %3 days. " ) . arg ( ( * it_account ) . name ( ) ) . arg ( minBalance . formatMoney ( * it_account , currency ) ) . arg ( dropMinimum - 1 ) ;
msg = showColoredAmount ( msg , true ) ;
break ;
}
if ( ! msg . isEmpty ( ) ) {
m_part - > write ( TQString ( " <tr class= \" warning \" style= \" font-weight: normal; \" ><td colspan=%2 align= \" center \" >%1</td></tr> " ) . arg ( msg ) . arg ( colspan ) ) ;
}
}
// a drop below zero is always shown
msg = TQString ( ) ;
switch ( dropZero ) {
case - 1 :
break ;
case 0 :
if ( ( * it_account ) . accountGroup ( ) = = MyMoneyAccount : : Asset ) {
msg = i18n ( " The balance of %1 is below %2 today. " ) . arg ( ( * it_account ) . name ( ) ) . arg ( MyMoneyMoney ( ) . formatMoney ( * it_account , currency ) ) ;
msg = showColoredAmount ( msg , true ) ;
break ;
}
if ( ( * it_account ) . accountGroup ( ) = = MyMoneyAccount : : Liability ) {
msg = i18n ( " The balance of %1 is above %2 today. " ) . arg ( ( * it_account ) . name ( ) ) . arg ( MyMoneyMoney ( ) . formatMoney ( * it_account , currency ) ) ;
break ;
}
break ;
default :
if ( ( * it_account ) . accountGroup ( ) = = MyMoneyAccount : : Asset ) {
msg = i18n ( " The balance of %1 will drop below %2 in %3 days. " ) . arg ( ( * it_account ) . name ( ) ) . arg ( MyMoneyMoney ( ) . formatMoney ( * it_account , currency ) ) . arg ( dropZero ) ;
msg = showColoredAmount ( msg , true ) ;
break ;
}
if ( ( * it_account ) . accountGroup ( ) = = MyMoneyAccount : : Liability ) {
msg = i18n ( " The balance of %1 will raise above %2 in %3 days. " ) . arg ( ( * it_account ) . name ( ) ) . arg ( MyMoneyMoney ( ) . formatMoney ( * it_account , currency ) ) . arg ( dropZero ) ;
break ;
}
}
if ( ! msg . isEmpty ( ) ) {
m_part - > write ( TQString ( " <tr class= \" warning \" ><td colspan=%2 align= \" center \" ><b>%1</b></td></tr> " ) . arg ( msg ) . arg ( colspan ) ) ;
}
}
m_part - > write ( " </table></div></div> " ) ;
}
}
const TQString KHomeView : : link ( const TQString & view , const TQString & query , const TQString & _title ) const
{
TQString titlePart ;
TQString title ( _title ) ;
if ( ! title . isEmpty ( ) )
titlePart = TQString ( " title= \" %1 \" " ) . arg ( title . replace ( " " , " " ) ) ;
return TQString ( " <a href= \" /%1%2 \" %3> " ) . arg ( view , query , titlePart ) ;
}
const TQString KHomeView : : linkend ( void ) const
{
return " </a> " ;
}
void KHomeView : : slotOpenURL ( const KURL & url , const KParts : : URLArgs & /* args */ )
{
TQString protocol = url . protocol ( ) ;
TQString view = url . fileName ( false ) ;
TQString id = url . queryItem ( " id " ) ;
TQString mode = url . queryItem ( " mode " ) ;
if ( protocol = = " http " )
{
TDEApplication : : kApplication ( ) - > invokeBrowser ( url . prettyURL ( ) ) ;
}
else if ( protocol = = " mailto " )
{
TDEApplication : : kApplication ( ) - > invokeMailer ( url ) ;
}
else
{
if ( view = = VIEW_LEDGER ) {
emit ledgerSelected ( id , TQString ( ) ) ;
} else if ( view = = VIEW_SCHEDULE ) {
if ( mode = = " enter " ) {
emit scheduleSelected ( id ) ;
TDEMainWindow * mw = dynamic_cast < TDEMainWindow * > ( tqApp - > mainWidget ( ) ) ;
TQ_CHECK_PTR ( mw ) ;
TQTimer : : singleShot ( 0 , mw - > actionCollection ( ) - > action ( " schedule_enter " ) , TQ_SLOT ( activate ( ) ) ) ;
} else if ( mode = = " edit " ) {
emit scheduleSelected ( id ) ;
TDEMainWindow * mw = dynamic_cast < TDEMainWindow * > ( tqApp - > mainWidget ( ) ) ;
TQ_CHECK_PTR ( mw ) ;
TQTimer : : singleShot ( 0 , mw - > actionCollection ( ) - > action ( " schedule_edit " ) , TQ_SLOT ( activate ( ) ) ) ;
} else if ( mode = = " skip " ) {
emit scheduleSelected ( id ) ;
TDEMainWindow * mw = dynamic_cast < TDEMainWindow * > ( tqApp - > mainWidget ( ) ) ;
TQ_CHECK_PTR ( mw ) ;
TQTimer : : singleShot ( 0 , mw - > actionCollection ( ) - > action ( " schedule_skip " ) , TQ_SLOT ( activate ( ) ) ) ;
} else if ( mode = = " full " ) {
m_showAllSchedules = true ;
loadView ( ) ;
} else if ( mode = = " reduced " ) {
m_showAllSchedules = false ;
loadView ( ) ;
}
} else if ( view = = VIEW_REPORTS ) {
emit reportSelected ( id ) ;
} else if ( view = = VIEW_WELCOME ) {
TDEMainWindow * mw = dynamic_cast < TDEMainWindow * > ( tqApp - > mainWidget ( ) ) ;
TQ_CHECK_PTR ( mw ) ;
if ( mode = = " whatsnew " )
{
TQString fname = KMyMoneyUtils : : findResource ( " appdata " , TQString ( " html/whats_new%1.html " ) ) ;
if ( ! fname . isEmpty ( ) )
m_part - > openURL ( fname ) ;
}
else
m_part - > openURL ( m_filename ) ;
} else if ( view = = " action " ) {
TDEMainWindow * mw = dynamic_cast < TDEMainWindow * > ( tqApp - > mainWidget ( ) ) ;
TQ_CHECK_PTR ( mw ) ;
TQTimer : : singleShot ( 0 , mw - > actionCollection ( ) - > action ( id . utf8 ( ) ) , TQ_SLOT ( activate ( ) ) ) ;
} else if ( view = = VIEW_HOME ) {
TQValueList < MyMoneyAccount > list ;
MyMoneyFile : : instance ( ) - > accountList ( list ) ;
if ( list . count ( ) = = 0 ) {
KMessageBox : : information ( this , i18n ( " Before KMyMoney can give you detailed information about your financial status, you need to create at least one account. Until then, KMyMoney shows the welcome page instead. " ) ) ;
}
loadView ( ) ;
} else {
tqDebug ( TQString ( " Unknown view '%1' in KHomeView::slotOpenURL() " ) . arg ( view ) ) ;
}
}
}
void KHomeView : : showAssetsLiabilities ( void )
{
TQValueList < MyMoneyAccount > accounts ;
TQValueList < MyMoneyAccount > : : Iterator it ;
TQMap < TQString , MyMoneyAccount > nameAssetsIdx ;
TQMap < TQString , MyMoneyAccount > nameLiabilitiesIdx ;
MyMoneyMoney netAssets ;
MyMoneyMoney netLiabilities ;
TQString fontStart , fontEnd ;
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
int prec = MyMoneyMoney : : denomToPrec ( file - > baseCurrency ( ) . smallestAccountFraction ( ) ) ;
int i = 0 ;
// get list of all accounts
file - > accountList ( accounts ) ;
for ( it = accounts . begin ( ) ; it ! = accounts . end ( ) ; ) {
if ( ! ( * it ) . isClosed ( ) ) {
switch ( ( * it ) . accountType ( ) ) {
// group all assets into one list but make sure that investment accounts always show up
case MyMoneyAccount : : Investment :
d - > addNameIndex ( nameAssetsIdx , * it ) ;
break ;
case MyMoneyAccount : : Checkings :
case MyMoneyAccount : : Savings :
case MyMoneyAccount : : Cash :
case MyMoneyAccount : : Asset :
case MyMoneyAccount : : AssetLoan :
// list account if it's the last in the hierarchy or has transactions in it
if ( ( * it ) . accountList ( ) . isEmpty ( ) | | ( file - > transactionCount ( ( * it ) . id ( ) ) > 0 ) ) {
d - > addNameIndex ( nameAssetsIdx , * it ) ;
}
break ;
// group the liabilities into the other
case MyMoneyAccount : : CreditCard :
case MyMoneyAccount : : Liability :
case MyMoneyAccount : : Loan :
// list account if it's the last in the hierarchy or has transactions in it
if ( ( * it ) . accountList ( ) . isEmpty ( ) | | ( file - > transactionCount ( ( * it ) . id ( ) ) > 0 ) ) {
d - > addNameIndex ( nameLiabilitiesIdx , * it ) ;
}
break ;
default :
break ;
}
}
+ + it ;
}
//only do it if we have assets or liabilities account
if ( nameAssetsIdx . count ( ) > 0 | | nameLiabilitiesIdx . count ( ) > 0 ) {
//print header
m_part - > write ( " <div class= \" shadow \" ><div class= \" displayblock \" ><div class= \" summaryheader \" > " + i18n ( " Assets and Liabilities Summary " ) + " </div> \n <div class= \" gap \" > </div> \n " ) ;
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
//column titles
m_part - > write ( " <tr class= \" item \" ><td class= \" left \" width= \" 30% \" > " ) ;
m_part - > write ( i18n ( " Asset Accounts " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td width= \" 15% \" class= \" right \" > " ) ;
m_part - > write ( i18n ( " Current Balance " ) ) ;
m_part - > write ( " </td> " ) ;
//intermediate row to separate both columns
m_part - > write ( " <td width= \" 10% \" class= \" setcolor \" ></td> " ) ;
m_part - > write ( " <td class= \" left \" width= \" 30% \" > " ) ;
m_part - > write ( i18n ( " Liability Accounts " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td width= \" 15% \" class= \" right \" > " ) ;
m_part - > write ( i18n ( " Current Balance " ) ) ;
m_part - > write ( " </td></tr> " ) ;
//get asset and liability accounts
TQMap < TQString , MyMoneyAccount > : : const_iterator asset_it = nameAssetsIdx . begin ( ) ;
TQMap < TQString , MyMoneyAccount > : : const_iterator liabilities_it = nameLiabilitiesIdx . begin ( ) ;
for ( ; asset_it ! = nameAssetsIdx . end ( ) | | liabilities_it ! = nameLiabilitiesIdx . end ( ) ; ) {
m_part - > write ( TQString ( " <tr class= \" row-%1 \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
//write an asset account if we still have any
if ( asset_it ! = nameAssetsIdx . end ( ) ) {
MyMoneyMoney value ;
//investment accounts consolidate the balance of its subaccounts
if ( ( * asset_it ) . accountType ( ) = = MyMoneyAccount : : Investment ) {
value = investmentBalance ( * asset_it ) ;
} else {
value = MyMoneyFile : : instance ( ) - > balance ( ( * asset_it ) . id ( ) , TQDate : : currentDate ( ) ) ;
}
//calculate balance for foreign currency accounts
if ( ( * asset_it ) . currencyId ( ) ! = file - > baseCurrency ( ) . id ( ) ) {
ReportAccount repAcc = ReportAccount ( ( * asset_it ) . id ( ) ) ;
MyMoneyMoney curPrice = repAcc . baseCurrencyPrice ( TQDate : : currentDate ( ) ) ;
MyMoneyMoney baseValue = value * curPrice ;
baseValue = baseValue . convert ( 10000 ) ;
netAssets + = baseValue ;
} else {
netAssets + = value ;
}
//show the account without minimum balance
showAccountEntry ( * asset_it , value , MyMoneyMoney ( ) , false ) ;
+ + asset_it ;
} else {
//write a white space if we don't
m_part - > write ( " <td></td><td></td> " ) ;
}
//leave the intermediate column empty
m_part - > write ( " <td class= \" setcolor \" ></td> " ) ;
//write a liability account
if ( liabilities_it ! = nameLiabilitiesIdx . end ( ) ) {
MyMoneyMoney value ;
value = MyMoneyFile : : instance ( ) - > balance ( ( * liabilities_it ) . id ( ) , TQDate : : currentDate ( ) ) ;
//calculate balance if foreign currency
if ( ( * liabilities_it ) . currencyId ( ) ! = file - > baseCurrency ( ) . id ( ) ) {
ReportAccount repAcc = ReportAccount ( ( * liabilities_it ) . id ( ) ) ;
MyMoneyMoney curPrice = repAcc . baseCurrencyPrice ( TQDate : : currentDate ( ) ) ;
MyMoneyMoney baseValue = value * curPrice ;
baseValue = baseValue . convert ( 10000 ) ;
netLiabilities + = baseValue ;
} else {
netLiabilities + = value ;
}
//show the account without minimum balance
showAccountEntry ( * liabilities_it , value , MyMoneyMoney ( ) , false ) ;
+ + liabilities_it ;
} else {
//leave the space empty if we run out of liabilities
m_part - > write ( " <td></td><td></td> " ) ;
}
m_part - > write ( " </tr> " ) ;
}
//calculate net worth
MyMoneyMoney netWorth = netAssets + netLiabilities ;
//format assets, liabilities and net worth
TQString amountAssets = netAssets . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString amountLiabilities = netLiabilities . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString amountNetWorth = netWorth . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
amountAssets . replace ( " " , " " ) ;
amountLiabilities . replace ( " " , " " ) ;
amountNetWorth . replace ( " " , " " ) ;
m_part - > write ( TQString ( " <tr class= \" row-%1 \" style= \" font-weight:bold; \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
//print total for assets
m_part - > write ( TQString ( " <td class= \" left \" >%1</td><td align= \" right \" >%2</td> " ) . arg ( i18n ( " Total Assets " ) ) . arg ( showColoredAmount ( amountAssets , netAssets . isNegative ( ) ) ) ) ;
//leave the intermediate column empty
m_part - > write ( " <td class= \" setcolor \" ></td> " ) ;
//print total liabilities
m_part - > write ( TQString ( " <td class= \" left \" >%1</td><td align= \" right \" >%2</td> " ) . arg ( i18n ( " Total Liabilities " ) ) . arg ( showColoredAmount ( amountLiabilities , netLiabilities . isNegative ( ) ) ) ) ;
m_part - > write ( " </tr> " ) ;
//print net worth
m_part - > write ( TQString ( " <tr class= \" row-%1 \" style= \" font-weight:bold; \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
m_part - > write ( " <td></td><td></td><td class= \" setcolor \" ></td> " ) ;
m_part - > write ( TQString ( " <td class= \" left \" >%1</td><td align= \" right \" >%2</td> " ) . arg ( i18n ( " Net Worth " ) ) . arg ( showColoredAmount ( amountNetWorth , netWorth . isNegative ( ) ) ) ) ;
m_part - > write ( " </tr> " ) ;
m_part - > write ( " </table> " ) ;
m_part - > write ( " </div></div> " ) ;
}
}
void KHomeView : : showBudget ( void )
{
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
if ( file - > countBudgets ( ) ) {
int prec = MyMoneyMoney : : denomToPrec ( file - > baseCurrency ( ) . smallestAccountFraction ( ) ) ;
int i = 0 ;
//config report just like "Monthly Budgeted vs Actual
MyMoneyReport reportCfg = MyMoneyReport (
MyMoneyReport : : eBudgetActual ,
MyMoneyReport : : eMonths ,
MyMoneyTransactionFilter : : currentMonth ,
MyMoneyReport : : eDetailAll ,
i18n ( " Monthly Budgeted vs. Actual " ) ,
i18n ( " Generated Report " ) ) ;
reportCfg . setBudget ( " Any " , true ) ;
reports : : PivotTable table ( reportCfg ) ;
PivotGrid grid = table . grid ( ) ;
//div header
m_part - > write ( " <div class= \" shadow \" ><div class= \" displayblock \" ><div class= \" summaryheader \" > " + i18n ( " Budget " ) + " </div> \n <div class= \" gap \" > </div> \n " ) ;
//display budget summary
m_part - > write ( " <table width= \" 75% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
m_part - > write ( " <tr class= \" itemtitle \" > " ) ;
m_part - > write ( " <td class= \" left \" colspan= \" 3 \" > " ) ;
m_part - > write ( i18n ( " Current Month Summary " ) ) ;
m_part - > write ( " </td></tr> " ) ;
m_part - > write ( " <tr class= \" item \" > " ) ;
m_part - > write ( " <td class= \" right \" width= \" 33% \" > " ) ;
m_part - > write ( i18n ( " Budgeted " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 33% \" > " ) ;
m_part - > write ( i18n ( " Actual " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 33% \" > " ) ;
m_part - > write ( i18n ( " Difference " ) ) ;
m_part - > write ( " </td></tr> " ) ;
m_part - > write ( TQString ( " <tr class= \" row-odd \" > " ) ) ;
MyMoneyMoney totalBudgetValue = grid . m_total [ eBudget ] . m_total ;
MyMoneyMoney totalActualValue = grid . m_total [ eActual ] . m_total ;
MyMoneyMoney totalBudgetDiffValue = grid . m_total [ eBudgetDiff ] . m_total ;
TQString totalBudgetAmount = totalBudgetValue . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString totalActualAmount = totalActualValue . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString totalBudgetDiffAmount = totalBudgetDiffValue . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
m_part - > write ( TQString ( " <td align= \" right \" >%1</td> " ) . arg ( showColoredAmount ( totalBudgetAmount , totalBudgetValue . isNegative ( ) ) ) ) ;
m_part - > write ( TQString ( " <td align= \" right \" >%1</td> " ) . arg ( showColoredAmount ( totalActualAmount , totalActualValue . isNegative ( ) ) ) ) ;
m_part - > write ( TQString ( " <td align= \" right \" >%1</td> " ) . arg ( showColoredAmount ( totalBudgetDiffAmount , totalBudgetDiffValue . isNegative ( ) ) ) ) ;
m_part - > write ( " </tr> " ) ;
m_part - > write ( " </table> " ) ;
//budget overrun
m_part - > write ( " <div class= \" gap \" > </div> \n " ) ;
m_part - > write ( " <table width= \" 75% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
m_part - > write ( " <tr class= \" itemtitle \" > " ) ;
m_part - > write ( " <td class= \" left \" colspan= \" 4 \" > " ) ;
m_part - > write ( i18n ( " Budget Overruns " ) ) ;
m_part - > write ( " </td></tr> " ) ;
m_part - > write ( " <tr class= \" item \" > " ) ;
m_part - > write ( " <td class= \" left \" width= \" 30% \" > " ) ;
m_part - > write ( i18n ( " Account " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 20% \" > " ) ;
m_part - > write ( i18n ( " Budgeted " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 20% \" > " ) ;
m_part - > write ( i18n ( " Actual " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td class= \" right \" width= \" 20% \" > " ) ;
m_part - > write ( i18n ( " Difference " ) ) ;
m_part - > write ( " </td></tr> " ) ;
PivotGrid : : iterator it_outergroup = grid . begin ( ) ;
while ( it_outergroup ! = grid . end ( ) )
{
i = 0 ;
PivotOuterGroup : : iterator it_innergroup = ( * it_outergroup ) . begin ( ) ;
while ( it_innergroup ! = ( * it_outergroup ) . end ( ) )
{
PivotInnerGroup : : iterator it_row = ( * it_innergroup ) . begin ( ) ;
while ( it_row ! = ( * it_innergroup ) . end ( ) )
{
//column number is 1 because the report includes only current month
if ( it_row . data ( ) [ eBudgetDiff ] [ 1 ] . isNegative ( ) ) {
//get report account to get the name later
ReportAccount rowname = it_row . key ( ) ;
//write the outergroup if it is the first row of outergroup being shown
if ( i = = 0 ) {
m_part - > write ( " <tr style= \" font-weight:bold; \" > " ) ;
m_part - > write ( TQString ( " <td class= \" left \" colspan= \" 4 \" >%1</td> " ) . arg ( KMyMoneyUtils : : accountTypeToString ( rowname . accountType ( ) ) ) ) ;
m_part - > write ( " </tr> " ) ;
}
m_part - > write ( TQString ( " <tr class= \" row-%1 \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
//get values from grid
MyMoneyMoney actualValue = it_row . data ( ) [ eActual ] [ 1 ] ;
MyMoneyMoney budgetValue = it_row . data ( ) [ eBudget ] [ 1 ] ;
MyMoneyMoney budgetDiffValue = it_row . data ( ) [ eBudgetDiff ] [ 1 ] ;
//format amounts
TQString actualAmount = actualValue . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString budgetAmount = budgetValue . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString budgetDiffAmount = budgetDiffValue . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
//account name
m_part - > write ( TQString ( " <td> " ) + link ( VIEW_LEDGER , TQString ( " ?id=%1 " ) . arg ( rowname . id ( ) ) ) + rowname . name ( ) + linkend ( ) + " </td> " ) ;
//show amounts
m_part - > write ( TQString ( " <td align= \" right \" >%1</td> " ) . arg ( showColoredAmount ( budgetAmount , budgetValue . isNegative ( ) ) ) ) ;
m_part - > write ( TQString ( " <td align= \" right \" >%1</td> " ) . arg ( showColoredAmount ( actualAmount , actualValue . isNegative ( ) ) ) ) ;
m_part - > write ( TQString ( " <td align= \" right \" >%1</td> " ) . arg ( showColoredAmount ( budgetDiffAmount , budgetDiffValue . isNegative ( ) ) ) ) ;
m_part - > write ( " </tr> " ) ;
}
+ + it_row ;
}
+ + it_innergroup ;
}
+ + it_outergroup ;
}
//if no negative differences are found, then inform that
if ( i = = 0 ) {
m_part - > write ( TQString ( " <tr class= \" row-%1 \" style= \" font-weight:bold; \" > " ) . arg ( i + + & 0x01 ? " even " : " odd " ) ) ;
m_part - > write ( TQString ( " <td class= \" center \" colspan= \" 4 \" >%1</td> " ) . arg ( i18n ( " No Budget Categories have been overrun " ) ) ) ;
m_part - > write ( " </tr> " ) ;
}
m_part - > write ( " </table></div></div> " ) ;
}
}
TQString KHomeView : : showColoredAmount ( const TQString & amount , bool isNegative )
{
if ( isNegative ) {
//if negative, get the settings for negative numbers
return TQString ( " <font color= \" %1 \" >%2</font> " ) . arg ( KMyMoneyGlobalSettings : : listNegativeValueColor ( ) . name ( ) , amount ) ;
}
//if positive, return the same string
return amount ;
}
void KHomeView : : doForecast ( void )
{
//clear m_accountList because forecast is about to changed
m_accountList . clear ( ) ;
//reinitialize the object
m_forecast = MyMoneyForecast ( ) ;
//If forecastDays lower than accountsCycle, adjust to the first cycle
if ( m_forecast . accountsCycle ( ) > m_forecast . forecastDays ( ) )
m_forecast . setForecastDays ( m_forecast . accountsCycle ( ) ) ;
//Get all accounts of the right type to calculate forecast
m_forecast . doForecast ( ) ;
}
MyMoneyMoney KHomeView : : forecastPaymentBalance ( const MyMoneyAccount & acc , const MyMoneyMoney & payment , TQDate & paymentDate )
{
//if paymentDate before or equal to currentDate set it to current date plus 1
//so we get to accumulate forecast balance correctly
if ( paymentDate < = TQDate : : currentDate ( ) )
paymentDate = TQDate : : currentDate ( ) . addDays ( 1 ) ;
//check if the account is already there
if ( m_accountList . find ( acc . id ( ) ) = = m_accountList . end ( )
| | m_accountList [ acc . id ( ) ] . find ( paymentDate ) = = m_accountList [ acc . id ( ) ] . end ( ) )
{
if ( paymentDate = = TQDate : : currentDate ( ) ) {
m_accountList [ acc . id ( ) ] [ paymentDate ] = m_forecast . forecastBalance ( acc , paymentDate ) ;
} else {
m_accountList [ acc . id ( ) ] [ paymentDate ] = m_forecast . forecastBalance ( acc , paymentDate . addDays ( - 1 ) ) ;
}
}
m_accountList [ acc . id ( ) ] [ paymentDate ] = m_accountList [ acc . id ( ) ] [ paymentDate ] + payment ;
return m_accountList [ acc . id ( ) ] [ paymentDate ] ;
}
void KHomeView : : showCashFlowSummary ( )
{
MyMoneyTransactionFilter filter ;
MyMoneyMoney incomeValue ;
MyMoneyMoney expenseValue ;
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
int prec = MyMoneyMoney : : denomToPrec ( file - > baseCurrency ( ) . smallestAccountFraction ( ) ) ;
//set start and end of month dates
TQDate startOfMonth = TQDate ( TQDate : : currentDate ( ) . year ( ) , TQDate : : currentDate ( ) . month ( ) , 1 ) ;
TQDate endOfMonth = TQDate ( TQDate : : currentDate ( ) . year ( ) , TQDate : : currentDate ( ) . month ( ) , TQDate : : currentDate ( ) . daysInMonth ( ) ) ;
//Add total income and expenses for this month
//get transactions for current month
filter . setDateFilter ( startOfMonth , endOfMonth ) ;
filter . setReportAllSplits ( false ) ;
TQValueList < MyMoneyTransaction > transactions = file - > transactionList ( filter ) ;
//if no transaction then skip and print total in zero
if ( transactions . size ( ) > 0 ) {
TQValueList < MyMoneyTransaction > : : const_iterator it_transaction ;
//get all transactions for this month
for ( it_transaction = transactions . begin ( ) ; it_transaction ! = transactions . end ( ) ; + + it_transaction ) {
//get the splits for each transaction
const TQValueList < MyMoneySplit > & splits = ( * it_transaction ) . splits ( ) ;
TQValueList < MyMoneySplit > : : const_iterator it_split ;
for ( it_split = splits . begin ( ) ; it_split ! = splits . end ( ) ; + + it_split ) {
if ( ! ( * it_split ) . shares ( ) . isZero ( ) ) {
ReportAccount repSplitAcc = ReportAccount ( ( * it_split ) . accountId ( ) ) ;
//only add if it is an income or expense
if ( repSplitAcc . isIncomeExpense ( ) ) {
MyMoneyMoney value ;
//convert to base currency if necessary
if ( repSplitAcc . currencyId ( ) ! = file - > baseCurrency ( ) . id ( ) ) {
MyMoneyMoney curPrice = repSplitAcc . baseCurrencyPrice ( ( * it_transaction ) . postDate ( ) ) ;
value = ( ( * it_split ) . shares ( ) * MyMoneyMoney ( - 1 , 1 ) ) * curPrice ;
value = value . convert ( 10000 ) ;
} else {
value = ( ( * it_split ) . shares ( ) * MyMoneyMoney ( - 1 , 1 ) ) ;
}
//store depending on account type
if ( repSplitAcc . accountType ( ) = = MyMoneyAccount : : Income ) {
incomeValue + = value ;
} else {
expenseValue + = value ;
}
}
}
}
}
}
//format income and expenses
TQString amountIncome = incomeValue . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString amountExpense = expenseValue . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
amountIncome . replace ( " " , " " ) ;
amountExpense . replace ( " " , " " ) ;
//calculate schedules
//Add all schedules for this month
MyMoneyMoney scheduledIncome ;
MyMoneyMoney scheduledExpense ;
MyMoneyMoney scheduledLiquidTransfer ;
MyMoneyMoney scheduledOtherTransfer ;
//get overdues and schedules until the end of this month
TQValueList < MyMoneySchedule > schedule = file - > scheduleList ( " " , MyMoneySchedule : : TYPE_ANY ,
MyMoneySchedule : : OCCUR_ANY ,
MyMoneySchedule : : STYPE_ANY ,
TQDate ( ) ,
endOfMonth ) ;
//Remove the finished schedules
TQValueList < MyMoneySchedule > : : Iterator finished_it ;
for ( finished_it = schedule . begin ( ) ; finished_it ! = schedule . end ( ) ; ) {
if ( ( * finished_it ) . isFinished ( ) ) {
finished_it = schedule . remove ( finished_it ) ;
continue ;
}
+ + finished_it ;
}
//add income and expenses
TQValueList < MyMoneySchedule > : : Iterator sched_it ;
for ( sched_it = schedule . begin ( ) ; sched_it ! = schedule . end ( ) ; ) {
TQDate nextDate = ( * sched_it ) . nextDueDate ( ) ;
int cnt = 0 ;
while ( nextDate . isValid ( ) & & nextDate < = endOfMonth ) {
+ + cnt ;
nextDate = ( * sched_it ) . nextPayment ( nextDate ) ;
// for single occurence nextDate will not change, so we
// better get out of here.
if ( ( * sched_it ) . occurence ( ) = = MyMoneySchedule : : OCCUR_ONCE )
break ;
}
MyMoneyAccount acc = ( * sched_it ) . account ( ) ;
if ( ! acc . id ( ) . isEmpty ( ) ) {
MyMoneyTransaction transaction = ( * sched_it ) . transaction ( ) ;
// only show the entry, if it is still active
MyMoneySplit sp = transaction . splitByAccount ( acc . id ( ) , true ) ;
// take care of the autoCalc stuff
if ( ( * sched_it ) . type ( ) = = MyMoneySchedule : : TYPE_LOANPAYMENT ) {
TQDate nextDate = ( * sched_it ) . nextPayment ( ( * sched_it ) . lastPayment ( ) ) ;
//make sure we have all 'starting balances' so that the autocalc works
TQValueList < MyMoneySplit > : : const_iterator it_s ;
TQMap < TQString , MyMoneyMoney > balanceMap ;
for ( it_s = transaction . splits ( ) . begin ( ) ; it_s ! = transaction . splits ( ) . end ( ) ; + + it_s ) {
MyMoneyAccount acc = file - > account ( ( * it_s ) . accountId ( ) ) ;
// collect all overdues on the first day
TQDate schedDate = nextDate ;
if ( TQDate : : currentDate ( ) > = nextDate )
schedDate = TQDate : : currentDate ( ) . addDays ( 1 ) ;
balanceMap [ acc . id ( ) ] + = file - > balance ( acc . id ( ) ) ;
}
KMyMoneyUtils : : calculateAutoLoan ( * sched_it , transaction , balanceMap ) ;
}
//go through the splits and assign to liquid or other transfers
const TQValueList < MyMoneySplit > splits = transaction . splits ( ) ;
TQValueList < MyMoneySplit > : : const_iterator split_it ;
for ( split_it = splits . begin ( ) ; split_it ! = splits . end ( ) ; + + split_it ) {
if ( ( * split_it ) . accountId ( ) ! = acc . id ( ) ) {
ReportAccount repSplitAcc = ReportAccount ( ( * split_it ) . accountId ( ) ) ;
//get the shares and multiply by the quantity of occurences in the period
MyMoneyMoney value = ( * split_it ) . shares ( ) * cnt ;
//convert to foreign currency if needed
if ( repSplitAcc . currencyId ( ) ! = file - > baseCurrency ( ) . id ( ) ) {
MyMoneyMoney curPrice = repSplitAcc . baseCurrencyPrice ( TQDate : : currentDate ( ) ) ;
value = value * curPrice ;
value = value . convert ( 10000 ) ;
}
if ( ( repSplitAcc . isLiquidLiability ( )
| | repSplitAcc . isLiquidAsset ( ) )
& & acc . accountGroup ( ) ! = repSplitAcc . accountGroup ( ) ) {
scheduledLiquidTransfer + = value ;
} else if ( repSplitAcc . isAssetLiability ( )
& & ! repSplitAcc . isLiquidLiability ( )
& & ! repSplitAcc . isLiquidAsset ( ) ) {
scheduledOtherTransfer + = value ;
} else if ( repSplitAcc . isIncomeExpense ( ) ) {
//income and expenses are stored as negative values
if ( repSplitAcc . accountType ( ) = = MyMoneyAccount : : Income )
scheduledIncome - = value ;
if ( repSplitAcc . accountType ( ) = = MyMoneyAccount : : Expense )
scheduledExpense - = value ;
}
}
}
}
+ + sched_it ;
}
//format the currency strings
TQString amountScheduledIncome = scheduledIncome . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString amountScheduledExpense = scheduledExpense . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString amountScheduledLiquidTransfer = scheduledLiquidTransfer . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString amountScheduledOtherTransfer = scheduledOtherTransfer . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
amountScheduledIncome . replace ( " " , " " ) ;
amountScheduledExpense . replace ( " " , " " ) ;
amountScheduledLiquidTransfer . replace ( " " , " " ) ;
amountScheduledOtherTransfer . replace ( " " , " " ) ;
//get liquid assets and liabilities
TQValueList < MyMoneyAccount > accounts ;
TQValueList < MyMoneyAccount > : : const_iterator account_it ;
MyMoneyMoney liquidAssets ;
MyMoneyMoney liquidLiabilities ;
// get list of all accounts
file - > accountList ( accounts ) ;
for ( account_it = accounts . begin ( ) ; account_it ! = accounts . end ( ) ; ) {
if ( ! ( * account_it ) . isClosed ( ) ) {
switch ( ( * account_it ) . accountType ( ) ) {
//group all assets into one list
case MyMoneyAccount : : Checkings :
case MyMoneyAccount : : Savings :
case MyMoneyAccount : : Cash :
{
MyMoneyMoney value = MyMoneyFile : : instance ( ) - > balance ( ( * account_it ) . id ( ) , TQDate : : currentDate ( ) ) ;
//calculate balance for foreign currency accounts
if ( ( * account_it ) . currencyId ( ) ! = file - > baseCurrency ( ) . id ( ) ) {
ReportAccount repAcc = ReportAccount ( ( * account_it ) . id ( ) ) ;
MyMoneyMoney curPrice = repAcc . baseCurrencyPrice ( TQDate : : currentDate ( ) ) ;
MyMoneyMoney baseValue = value * curPrice ;
liquidAssets + = baseValue ;
liquidAssets = liquidAssets . convert ( 10000 ) ;
} else {
liquidAssets + = value ;
}
break ;
}
//group the liabilities into the other
case MyMoneyAccount : : CreditCard :
{
MyMoneyMoney value ;
value = MyMoneyFile : : instance ( ) - > balance ( ( * account_it ) . id ( ) , TQDate : : currentDate ( ) ) ;
//calculate balance if foreign currency
if ( ( * account_it ) . currencyId ( ) ! = file - > baseCurrency ( ) . id ( ) ) {
ReportAccount repAcc = ReportAccount ( ( * account_it ) . id ( ) ) ;
MyMoneyMoney curPrice = repAcc . baseCurrencyPrice ( TQDate : : currentDate ( ) ) ;
MyMoneyMoney baseValue = value * curPrice ;
liquidLiabilities + = baseValue ;
liquidLiabilities = liquidLiabilities . convert ( 10000 ) ;
} else {
liquidLiabilities + = value ;
}
break ;
}
default :
break ;
}
}
+ + account_it ;
}
//calculate net worth
MyMoneyMoney liquidWorth = liquidAssets + liquidLiabilities ;
//format assets, liabilities and net worth
TQString amountLiquidAssets = liquidAssets . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString amountLiquidLiabilities = liquidLiabilities . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString amountLiquidWorth = liquidWorth . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
amountLiquidAssets . replace ( " " , " " ) ;
amountLiquidLiabilities . replace ( " " , " " ) ;
amountLiquidWorth . replace ( " " , " " ) ;
//show the summary
m_part - > write ( " <div class= \" shadow \" ><div class= \" displayblock \" ><div class= \" summaryheader \" > " + i18n ( " Cash Flow Summary " ) + " </div> \n <div class= \" gap \" > </div> \n " ) ;
//print header
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
//income and expense title
m_part - > write ( " <tr class= \" itemtitle \" > " ) ;
m_part - > write ( " <td class= \" left \" colspan= \" 4 \" > " ) ;
m_part - > write ( i18n ( " Income and Expenses of Current Month " ) ) ;
m_part - > write ( " </td></tr> " ) ;
//column titles
m_part - > write ( " <tr class= \" item \" > " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Income " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Scheduled Income " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Expenses " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Scheduled Expenses " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " </tr> " ) ;
//add row with banding
m_part - > write ( TQString ( " <tr class= \" row-even \" style= \" font-weight:bold; \" > " ) ) ;
//print current income
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountIncome , incomeValue . isNegative ( ) ) ) ) ;
//print the scheduled income
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountScheduledIncome , scheduledIncome . isNegative ( ) ) ) ) ;
//print current expenses
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountExpense , expenseValue . isNegative ( ) ) ) ) ;
//print the scheduled expenses
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountScheduledExpense , scheduledExpense . isNegative ( ) ) ) ) ;
m_part - > write ( " </tr> " ) ;
m_part - > write ( " </table> " ) ;
//print header of assets and liabilities
m_part - > write ( " <div class= \" gap \" > </div> \n " ) ;
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
//assets and liabilities title
m_part - > write ( " <tr class= \" itemtitle \" > " ) ;
m_part - > write ( " <td class= \" left \" colspan= \" 4 \" > " ) ;
m_part - > write ( i18n ( " Liquid Assets and Liabilities " ) ) ;
m_part - > write ( " </td></tr> " ) ;
//column titles
m_part - > write ( " <tr class= \" item \" > " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Liquid Assets " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Transfers to Liquid Liabilities " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Liquid Liabilities " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Other Transfers " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " </tr> " ) ;
//add row with banding
m_part - > write ( TQString ( " <tr class= \" row-even \" style= \" font-weight:bold; \" > " ) ) ;
//print current liquid assets
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountLiquidAssets , liquidAssets . isNegative ( ) ) ) ) ;
//print the scheduled transfers
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountScheduledLiquidTransfer , scheduledLiquidTransfer . isNegative ( ) ) ) ) ;
//print current liabilities
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountLiquidLiabilities , liquidLiabilities . isNegative ( ) ) ) ) ;
//print the scheduled transfers
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountScheduledOtherTransfer , scheduledOtherTransfer . isNegative ( ) ) ) ) ;
m_part - > write ( " </tr> " ) ;
m_part - > write ( " </table> " ) ;
//final conclusion
MyMoneyMoney profitValue = incomeValue + expenseValue + scheduledIncome + scheduledExpense ;
MyMoneyMoney expectedAsset = liquidAssets + scheduledIncome + scheduledExpense + scheduledLiquidTransfer + scheduledOtherTransfer ;
MyMoneyMoney expectedLiabilities = liquidLiabilities + scheduledLiquidTransfer ;
TQString amountExpectedAsset = expectedAsset . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString amountExpectedLiabilities = expectedLiabilities . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
TQString amountProfit = profitValue . formatMoney ( file - > baseCurrency ( ) . tradingSymbol ( ) , prec ) ;
amountProfit . replace ( " " , " " ) ;
amountExpectedAsset . replace ( " " , " " ) ;
amountExpectedLiabilities . replace ( " " , " " ) ;
//print header of cash flow status
m_part - > write ( " <div class= \" gap \" > </div> \n " ) ;
m_part - > write ( " <table width= \" 100% \" cellspacing= \" 0 \" cellpadding= \" 2 \" class= \" summarytable \" > " ) ;
//income and expense title
m_part - > write ( " <tr class= \" itemtitle \" > " ) ;
m_part - > write ( " <td class= \" left \" colspan= \" 4 \" > " ) ;
m_part - > write ( i18n ( " Cash Flow Status " ) ) ;
m_part - > write ( " </td></tr> " ) ;
//column titles
m_part - > write ( " <tr class= \" item \" > " ) ;
m_part - > write ( " <td> </td> " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Expected Liquid Assets " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Expected Liquid Liabilities " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " <td width= \" 25% \" class= \" center \" > " ) ;
m_part - > write ( i18n ( " Expected Profit/Loss " ) ) ;
m_part - > write ( " </td> " ) ;
m_part - > write ( " </tr> " ) ;
//add row with banding
m_part - > write ( TQString ( " <tr class= \" row-even \" style= \" font-weight:bold; \" > " ) ) ;
m_part - > write ( " <td> </td> " ) ;
//print expected assets
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountExpectedAsset , expectedAsset . isNegative ( ) ) ) ) ;
//print expected liabilities
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountExpectedLiabilities , expectedLiabilities . isNegative ( ) ) ) ) ;
//print expected profit
m_part - > write ( TQString ( " <td align= \" right \" >%2</td> " ) . arg ( showColoredAmount ( amountProfit , profitValue . isNegative ( ) ) ) ) ;
m_part - > write ( " </tr> " ) ;
m_part - > write ( " </table> " ) ;
m_part - > write ( " </div></div> " ) ;
}
// Make sure, that these definitions are only used within this file
// this does not seem to be necessary, but when building RPMs the
// build option 'final' is used and all CPP files are concatenated.
// So it could well be, that in another CPP file these definitions
// are also used.
# undef VIEW_LEDGER
# undef VIEW_SCHEDULE
# undef VIEW_WELCOME
# undef VIEW_HOME
# undef VIEW_REPORTS
# include "khomeview.moc"