You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kmymoney/kmymoney2/views/kinstitutionsview.cpp

365 lines
13 KiB

/***************************************************************************
kinstitutionsview.cpp
-------------------
copyright : (C) 2005 by Thomas Baumgart
email : ipwizard@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 <tqheader.h>
#include <tqlabel.h>
#include <tqtabwidget.h>
// ----------------------------------------------------------------------------
// TDE Includes
#include <kdebug.h>
#include <tdelocale.h>
#include <kstandarddirs.h>
// ----------------------------------------------------------------------------
// Project Includes
#include <kmymoney/mymoneyfile.h>
#include "kinstitutionsview.h"
#include "../kmymoneyglobalsettings.h"
#include "../kmymoney2.h"
KInstitutionsView::KInstitutionsView(TQWidget *parent, const char *name) :
KInstitutionsViewDecl(parent,name),
m_needReload(false)
{
m_accountTree->header()->setLabel(0, i18n("Institution/Account"));
connect(m_accountTree, TQ_SIGNAL(selectObject(const MyMoneyObject&)), this, TQ_SIGNAL(selectObject(const MyMoneyObject&)));
connect(m_accountTree, TQ_SIGNAL(openContextMenu(const MyMoneyObject&)), this, TQ_SIGNAL(openContextMenu(const MyMoneyObject&)));
connect(m_accountTree, TQ_SIGNAL(valueChanged(void)), this, TQ_SLOT(slotUpdateNetWorth(void)));
connect(m_accountTree, TQ_SIGNAL(openObject(const MyMoneyObject&)), this, TQ_SIGNAL(openObject(const MyMoneyObject&)));
connect(m_accountTree, TQ_SIGNAL(reparent(const MyMoneyAccount&, const MyMoneyInstitution&)), this, TQ_SIGNAL(reparent(const MyMoneyAccount&, const MyMoneyInstitution&)));
connect(MyMoneyFile::instance(), TQ_SIGNAL(dataChanged()), this, TQ_SLOT(slotLoadAccounts()));
}
KInstitutionsView::~KInstitutionsView()
{
}
void KInstitutionsView::show(void)
{
if(m_needReload) {
loadAccounts();
m_needReload = false;
}
// don't forget base class implementation
KInstitutionsViewDecl::show();
// if we have a selected account, let the application know about it
KMyMoneyAccountTreeBaseItem *item = m_accountTree->selectedItem();
if(item) {
emit selectObject(item->itemObject());
}
}
void KInstitutionsView::polish(void)
{
KInstitutionsViewDecl::polish();
m_accountTree->setResizeMode(TQListView::LastColumn);
m_accountTree->restoreLayout("Institution View Settings");
}
void KInstitutionsView::slotLoadAccounts(void)
{
if(isVisible()) {
loadAccounts();
} else {
m_needReload = true;
}
}
void KInstitutionsView::loadAccounts(void)
{
TQMap<TQString, bool> isOpen;
::timetrace("start load institutions view");
// remember the id of the current selected item
KMyMoneyAccountTreeBaseItem *item = m_accountTree->selectedItem();
TQString selectedItemId = (item) ? item->id() : TQString();
// keep a map of all 'expanded' accounts
TQListViewItemIterator it_lvi(m_accountTree);
while(it_lvi.current()) {
item = dynamic_cast<KMyMoneyAccountTreeItem*>(it_lvi.current());
if(item && item->isOpen()) {
isOpen[item->id()] = true;
}
++it_lvi;
}
// remember the upper left corner of the viewport
TQPoint startPoint = m_accountTree->viewportToContents(TQPoint(0, 0));
// turn off updates to avoid flickering during reload
m_accountTree->setUpdatesEnabled(false);
// clear the current contents and recreate it
m_accountTree->clear();
m_accountMap.clear();
m_securityMap.clear();
m_transactionCountMap.clear();
MyMoneyFile* file = MyMoneyFile::instance();
TQValueList<MyMoneyAccount> alist;
file->accountList(alist);
TQValueList<MyMoneyAccount>::const_iterator it_a;
for(it_a = alist.begin(); it_a != alist.end(); ++it_a) {
m_accountMap[(*it_a).id()] = *it_a;
}
// we need to make sure we show stock accounts
// under the right institution (the one of the parent account)
TQMap<TQString, MyMoneyAccount>::iterator it_am;
for(it_am = m_accountMap.begin(); it_am != m_accountMap.end(); ++it_am) {
if((*it_am).isInvest()) {
(*it_am).setInstitutionId(m_accountMap[(*it_am).parentAccountId()].institutionId());
}
}
TQValueList<MyMoneySecurity> slist = file->currencyList();
slist += file->securityList();
TQValueList<MyMoneySecurity>::const_iterator it_s;
for(it_s = slist.begin(); it_s != slist.end(); ++it_s) {
m_securityMap[(*it_s).id()] = *it_s;
}
m_transactionCountMap = file->transactionCountMap();
m_accountTree->setBaseCurrency(file->baseCurrency());
// create the items
try {
const MyMoneySecurity& security = file->baseCurrency();
m_accountTree->setBaseCurrency(security);
MyMoneyInstitution none;
none.setName(i18n("Accounts with no institution assigned"));
KMyMoneyAccountTreeItem* noInstitutionItem = new KMyMoneyAccountTreeItem(m_accountTree, none);
noInstitutionItem->setPixmap(0,none.pixmap());
loadSubAccounts(noInstitutionItem, TQString());
// hide it, if unused
noInstitutionItem->setVisible(noInstitutionItem->childCount() != 0);
bool showClosedAccounts = kmymoney2->toggleAction("view_show_all_accounts")->isChecked()
|| !KMyMoneyGlobalSettings::hideClosedAccounts();
TQValueList<MyMoneyInstitution> list = file->institutionList();
TQValueList<MyMoneyInstitution>::const_iterator it_i;
for(it_i = list.begin(); it_i != list.end(); ++it_i) {
KMyMoneyAccountTreeItem* item = new KMyMoneyAccountTreeItem(m_accountTree, *it_i);
item->setPixmap(0, none.pixmap());
loadSubAccounts(item, (*it_i).id());
if(!showClosedAccounts)
item->setVisible(item->childCount() != 0);
}
} catch(MyMoneyException *e) {
kdDebug(2) << "Problem in institutions view: " << e->what();
delete e;
}
// scan through the list of accounts and re-expand those that were
// expanded and re-select the one that was probably selected before
it_lvi = TQListViewItemIterator(m_accountTree);
while(it_lvi.current()) {
item = dynamic_cast<KMyMoneyAccountTreeItem*>(it_lvi.current());
if(item) {
if(item->id() == selectedItemId)
m_accountTree->setSelected(item, true);
if(isOpen.find(item->id()) != isOpen.end())
item->setOpen(true);
}
++it_lvi;
}
// reposition viewport
m_accountTree->setContentsPos(startPoint.x(), startPoint.y());
// turn updates back on
m_accountTree->setUpdatesEnabled(true);
m_accountTree->repaintContents();
::timetrace("done load institutions view");
}
void KInstitutionsView::loadSubAccounts(KMyMoneyAccountTreeItem* parent)
{
bool showClosedAccounts = kmymoney2->toggleAction("view_show_all_accounts")->isChecked()
|| !KMyMoneyGlobalSettings::hideClosedAccounts();
const MyMoneyAccount& account = dynamic_cast<const MyMoneyAccount&>(parent->itemObject());
TQValueList<TQString>::const_iterator it_a;
MyMoneyFile* file = MyMoneyFile::instance();
for(it_a = account.accountList().begin(); it_a != account.accountList().end(); ++it_a) {
MyMoneyAccount acc = m_accountMap[(*it_a)];
if(!acc.isInvest())
continue;
if(acc.isClosed() && !showClosedAccounts)
continue;
const MyMoneySecurity& security = m_securityMap[acc.currencyId()];
TQValueList<MyMoneyPrice> prices;
prices += file->price(acc.currencyId(), security.tradingCurrency());
if(security.tradingCurrency() != file->baseCurrency().id()) {
MyMoneySecurity sec = m_securityMap[security.tradingCurrency()];
prices += file->price(sec.id(), file->baseCurrency().id());
}
KMyMoneyAccountTreeItem* item = new KMyMoneyAccountTreeItem(parent, acc, prices, security);
if(acc.id() == m_reconciliationAccount.id())
item->setReconciliation(true);
}
}
void KInstitutionsView::loadSubAccounts(KMyMoneyAccountTreeItem* parent, const TQString& institutionId)
{
MyMoneyFile* file = MyMoneyFile::instance();
TQMap<TQString, MyMoneyAccount>::const_iterator it_a;
MyMoneyMoney value;
bool showClosedAccounts = kmymoney2->toggleAction("view_show_all_accounts")->isChecked()
|| !KMyMoneyGlobalSettings::hideClosedAccounts();
for(it_a = m_accountMap.begin(); it_a != m_accountMap.end(); ++it_a) {
const MyMoneyAccount& acc = *it_a;
MyMoneyMoney factor(1,1);
switch(acc.accountGroup()) {
case MyMoneyAccount::Liability:
factor = MyMoneyMoney(-1,1);
// tricky fall through here
case MyMoneyAccount::Asset:
if(acc.institutionId() == institutionId
&& !acc.isInvest()
&& (!acc.isClosed() || showClosedAccounts)) {
TQValueList<MyMoneyPrice> prices;
MyMoneySecurity security = file->baseCurrency();
try {
if(acc.currencyId() != file->baseCurrency().id()) {
security = m_securityMap[acc.currencyId()];
prices += file->price(acc.currencyId(), file->baseCurrency().id());
}
} catch(MyMoneyException *e) {
kdDebug(2) << __PRETTY_FUNCTION__ << " caught exception while adding " << acc.name() << "[" << acc.id() << "]: " << e->what();
delete e;
}
KMyMoneyAccountTreeItem* item = new KMyMoneyAccountTreeItem(parent, acc, prices, security);
if(acc.id() == m_reconciliationAccount.id())
item->setReconciliation(true);
if(acc.accountType() == MyMoneyAccount::Investment)
loadSubAccounts(item);
value += (item->totalValue() * factor);
}
break;
default:
break;
}
}
// the calulated value for the institution is not correct as
// it does not take the negative sign for liability accounts
// into account. So we correct this here with the value we
// have calculated while filling the list
parent->adjustTotalValue(-parent->totalValue()); // load a 0
parent->adjustTotalValue(value); // now store the new value
// we need to call slotUpdateNetWorth() here manually, because
// KMyMoneyAccountTreeItem::adjustTotalValue() does not send out
// the valueChanged() signal
slotUpdateNetWorth();
}
void KInstitutionsView::slotUpdateNetWorth(void)
{
MyMoneyMoney netWorth;
// calculate by going through the account trees top items
// and summing up the total value shown there
KMyMoneyAccountTreeItem* item = dynamic_cast<KMyMoneyAccountTreeItem*>(m_accountTree->firstChild());
while(item) {
netWorth += item->totalValue();
item = dynamic_cast<KMyMoneyAccountTreeItem*>(item->nextSibling());
}
TQString s(i18n("Net Worth: "));
// FIXME figure out how to deal with the approximate
// if(!(file->totalValueValid(assetAccount.id()) & file->totalValueValid(liabilityAccount.id())))
// s += "~ ";
s.replace(TQString(" "), TQString("&nbsp;"));
if(netWorth.isNegative()) {
s += "<b><font color=\"red\">";
}
const MyMoneySecurity& sec = MyMoneyFile::instance()->baseCurrency();
TQString v(netWorth.formatMoney(sec));
s += v.replace(TQString(" "), TQString("&nbsp;"));
if(netWorth.isNegative()) {
s += "</font></b>";
}
m_totalProfitsLabel->setFont(KMyMoneyGlobalSettings::listCellFont());
m_totalProfitsLabel->setText(s);
}
void KInstitutionsView::slotReconcileAccount(const MyMoneyAccount& acc, const TQDate& reconciliationDate, const MyMoneyMoney& endingBalance)
{
Q_UNUSED(reconciliationDate);
Q_UNUSED(endingBalance);
// scan through the list of accounts and mark all non
// expanded and re-select the one that was probably selected before
TQListViewItemIterator it_lvi(m_accountTree);
KMyMoneyAccountTreeItem* item;
while(it_lvi.current()) {
item = dynamic_cast<KMyMoneyAccountTreeItem*>(it_lvi.current());
if(item) {
item->setReconciliation(false);
}
++it_lvi;
}
m_reconciliationAccount = acc;
if(!acc.id().isEmpty()) {
it_lvi = TQListViewItemIterator(m_accountTree);
while(it_lvi.current()) {
item = dynamic_cast<KMyMoneyAccountTreeItem*>(it_lvi.current());
if(item && item->itemObject().id() == acc.id()) {
item->setReconciliation(true);
break;
}
++it_lvi;
}
}
}
#include "kinstitutionsview.moc"