/***************************************************************************
                          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.                                   *
 *                                                                         *
 ***************************************************************************/

// ----------------------------------------------------------------------------
// QT 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>

// ----------------------------------------------------------------------------
// KDE 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(), TQT_SIGNAL(openURLRequest(const KURL&, const KParts::URLArgs&)),
          this, TQT_SLOT(slotOpenURL(const KURL&, const KParts::URLArgs&)));

  connect(MyMoneyFile::instance(), TQT_SIGNAL(dataChanged()), this, TQT_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("%s",tagname.latin1());
      tqDebug("%s id=%s",e.tagName().string().latin1(),e.getAttribute("id").string().latin1());

      // 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("Data is now %s",t.data().string().latin1());
        }
        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\">&nbsp;</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\">&nbsp;</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, Qt::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\">&nbsp;</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\">&nbsp;</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\">&nbsp;</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()) {
      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);
        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 += "&nbsp;" + 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("&nbsp;");
        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(" ","&nbsp;");
        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(" ","&nbsp;");
        tmp += showColoredAmount(balance, balanceAfter.isNegative());
        tmp += "</td>";

        // tqDebug("paymentEntry = '%s'", tmp.latin1());
        m_part->write(tmp);
      }
    }
  } catch(MyMoneyException* e) {
    tqDebug("Unable to display schedule entry: %s", e->what().data());
    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\">&nbsp;</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(" ","&nbsp;");
  if(showMinBal) {
    amountToMinBal = valueToMinBal.formatMoney(acc, currency);
    amountToMinBal.replace(" ","&nbsp;");
  }

  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\">&nbsp;</td>");
    } else {
      //show minimum balance entry
      tmp += TQString("<td class=\"right\">%1</td>").arg(showColoredAmount(amountToMinBal, valueToMinBal.isNegative()));
    }
  }
  // tqDebug("accountEntry = '%s'", tmp.latin1());
  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("%s", (TQString("cannot convert stock balance of %1 to base currency: %2").arg(stock.name(), e->what())).data());
      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\">&nbsp;</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\">&nbsp;</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(" ","&nbsp;");
        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(" ", "&nbsp;"));

  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"), TQT_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"), TQT_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"), TQT_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 ), TQT_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("Unknown view '%s' in KHomeView::slotOpenURL()", view.latin1());
    }
  }
}

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\">&nbsp;</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(" ","&nbsp;");
    amountLiabilities.replace(" ","&nbsp;");
    amountNetWorth.replace(" ","&nbsp;");

    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\">&nbsp;</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\">&nbsp;</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(" ","&nbsp;");
  amountExpense.replace(" ","&nbsp;");

  //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()) {
      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(" ","&nbsp;");
  amountScheduledExpense.replace(" ","&nbsp;");
  amountScheduledLiquidTransfer.replace(" ","&nbsp;");
  amountScheduledOtherTransfer.replace(" ","&nbsp;");

  //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(" ","&nbsp;");
  amountLiquidLiabilities.replace(" ","&nbsp;");
  amountLiquidWorth.replace(" ","&nbsp;");

  //show the summary
  m_part->write("<div class=\"shadow\"><div class=\"displayblock\"><div class=\"summaryheader\">" + i18n("Cash Flow Summary") + "</div>\n<div class=\"gap\">&nbsp;</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\">&nbsp;</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(" ","&nbsp;");
  amountExpectedAsset.replace(" ","&nbsp;");
  amountExpectedLiabilities.replace(" ","&nbsp;");



  //print header of cash flow status
  m_part->write("<div class=\"gap\">&nbsp;</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>&nbsp;</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>&nbsp;</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"
