/***************************************************************************
mymoneytemplate . cpp - description
- - - - - - - - - - - - - - - - - - -
begin : Sat Aug 14 2004
copyright : ( C ) 2004 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
// ----------------------------------------------------------------------------
// QT Includes
# include <tqfile.h>
# include <tqfileinfo.h>
# include <tqapplication.h>
// ----------------------------------------------------------------------------
// KDE Includes
# include <tdelocale.h>
# include <tdemessagebox.h>
# include <tdeio/netaccess.h>
# include <ksavefile.h>
// ----------------------------------------------------------------------------
// Project Includes
# include "mymoneytemplate.h"
MyMoneyTemplate : : MyMoneyTemplate ( ) :
m_progressCallback ( 0 )
{
}
MyMoneyTemplate : : MyMoneyTemplate ( const KURL & url ) :
m_progressCallback ( 0 )
{
loadTemplate ( url ) ;
}
MyMoneyTemplate : : ~ MyMoneyTemplate ( )
{
}
bool MyMoneyTemplate : : loadTemplate ( const KURL & url )
{
TQString filename ;
if ( ! url . isValid ( ) ) {
tqDebug ( " Invalid template URL '%s' " , url . url ( ) . latin1 ( ) ) ;
return false ;
}
m_source = url ;
if ( url . isLocalFile ( ) ) {
filename = url . path ( ) ;
} else {
bool rc ;
rc = TDEIO : : NetAccess : : download ( url , filename , tqApp - > mainWidget ( ) ) ;
if ( ! rc ) {
KMessageBox : : detailedError ( tqApp - > mainWidget ( ) ,
i18n ( " Error while loading file '%1'! " ) . arg ( url . url ( ) ) ,
TDEIO : : NetAccess : : lastErrorString ( ) ,
i18n ( " File access error " ) ) ;
return false ;
}
}
bool rc = true ;
TQFile file ( filename ) ;
TQFileInfo info ( file ) ;
if ( ! info . isFile ( ) ) {
TQString msg = i18n ( " <b>%1</b> is not a template file. " ) . arg ( filename ) ;
KMessageBox : : error ( tqApp - > mainWidget ( ) , TQString ( " <p> " ) + msg , i18n ( " Filetype Error " ) ) ;
return false ;
}
if ( file . open ( IO_ReadOnly ) ) {
TQString errMsg ;
int errLine , errColumn ;
if ( ! m_doc . setContent ( & file , & errMsg , & errLine , & errColumn ) ) {
TQString msg = i18n ( " Error while reading template file <b>%1</b> in line %2, column %3 " ) . arg ( filename ) . arg ( errLine ) . arg ( errColumn ) ;
KMessageBox : : detailedError ( tqApp - > mainWidget ( ) , TQString ( " <p> " ) + msg , errMsg , i18n ( " Template Error " ) ) ;
rc = false ;
} else {
rc = loadDescription ( ) ;
}
file . close ( ) ;
} else {
KMessageBox : : sorry ( tqApp - > mainWidget ( ) , i18n ( " File '%1' not found! " ) . arg ( filename ) ) ;
rc = false ;
}
// if a temporary file was constructed by NetAccess::download,
// then it will be removed with the next call. Otherwise, it
// stays untouched on the local filesystem
TDEIO : : NetAccess : : removeTempFile ( filename ) ;
return rc ;
}
bool MyMoneyTemplate : : loadDescription ( void )
{
int validMask = 0x00 ;
const int validAccount = 0x01 ;
const int validTitle = 0x02 ;
const int validShort = 0x04 ;
const int validLong = 0x08 ;
const int invalid = 0x10 ;
const int validHeader = 0x0F ;
TQDomElement rootElement = m_doc . documentElement ( ) ;
if ( ! rootElement . isNull ( )
& & rootElement . tagName ( ) = = " kmymoney-account-template " ) {
TQDomNode child = rootElement . firstChild ( ) ;
while ( ! child . isNull ( ) & & child . isElement ( ) ) {
TQDomElement childElement = child . toElement ( ) ;
// tqDebug("MyMoneyTemplate::import: Processing child node %s", childElement.tagName().data());
if ( childElement . tagName ( ) = = " accounts " ) {
m_accounts = childElement . firstChild ( ) ;
validMask | = validAccount ;
} else if ( childElement . tagName ( ) = = " title " ) {
m_title = childElement . text ( ) ;
validMask | = validTitle ;
} else if ( childElement . tagName ( ) = = " shortdesc " ) {
m_shortDesc = childElement . text ( ) ;
validMask | = validShort ;
} else if ( childElement . tagName ( ) = = " longdesc " ) {
m_longDesc = childElement . text ( ) ;
validMask | = validLong ;
} else {
KMessageBox : : error ( tqApp - > mainWidget ( ) , TQString ( " <p> " ) + i18n ( " Invalid tag <b>%1</b> in template file <b>%2</b>! " ) . arg ( childElement . tagName ( ) ) . arg ( m_source . prettyURL ( ) ) ) ;
validMask | = invalid ;
}
child = child . nextSibling ( ) ;
}
}
return validMask = = validHeader ;
}
bool MyMoneyTemplate : : hierarchy ( TQMap < TQString , TQListViewItem * > & list , const TQString & parent , TQDomNode account )
{
bool rc = true ;
while ( rc = = true & & ! account . isNull ( ) ) {
if ( account . isElement ( ) ) {
TQDomElement accountElement = account . toElement ( ) ;
if ( accountElement . tagName ( ) = = " account " ) {
TQString name = TQString ( " %1:%2 " ) . arg ( parent ) . arg ( accountElement . attribute ( " name " ) ) ;
list [ name ] = 0 ;
hierarchy ( list , name , account . firstChild ( ) ) ;
}
}
account = account . nextSibling ( ) ;
}
return rc ;
}
void MyMoneyTemplate : : hierarchy ( TQMap < TQString , TQListViewItem * > & list )
{
bool rc = ! m_accounts . isNull ( ) ;
TQDomNode accounts = m_accounts ;
while ( rc = = true & & ! accounts . isNull ( ) & & accounts . isElement ( ) ) {
TQDomElement childElement = accounts . toElement ( ) ;
if ( childElement . tagName ( ) = = " account "
& & childElement . attribute ( " name " ) = = " " ) {
switch ( childElement . attribute ( " type " ) . toUInt ( ) ) {
case MyMoneyAccount : : Asset :
list [ i18n ( " Asset " ) ] = 0 ;
rc = hierarchy ( list , i18n ( " Asset " ) , childElement . firstChild ( ) ) ;
break ;
case MyMoneyAccount : : Liability :
list [ i18n ( " Liability " ) ] = 0 ;
rc = hierarchy ( list , i18n ( " Liability " ) , childElement . firstChild ( ) ) ;
break ;
case MyMoneyAccount : : Income :
list [ i18n ( " Income " ) ] = 0 ;
rc = hierarchy ( list , i18n ( " Income " ) , childElement . firstChild ( ) ) ;
break ;
case MyMoneyAccount : : Expense :
list [ i18n ( " Expense " ) ] = 0 ;
rc = hierarchy ( list , i18n ( " Expense " ) , childElement . firstChild ( ) ) ;
break ;
case MyMoneyAccount : : Equity :
list [ i18n ( " Equity " ) ] = 0 ;
rc = hierarchy ( list , i18n ( " Equity " ) , childElement . firstChild ( ) ) ;
break ;
default :
rc = false ;
break ;
}
} else {
rc = false ;
}
accounts = accounts . nextSibling ( ) ;
}
}
bool MyMoneyTemplate : : importTemplate ( void ( * callback ) ( int , int , const TQString & ) )
{
m_progressCallback = callback ;
bool rc = ! m_accounts . isNull ( ) ;
MyMoneyFile * file = MyMoneyFile : : instance ( ) ;
signalProgress ( 0 , m_doc . elementsByTagName ( " account " ) . count ( ) , i18n ( " Loading template %1 " ) . arg ( m_source . url ( ) ) ) ;
m_accountsRead = 0 ;
while ( rc = = true & & ! m_accounts . isNull ( ) & & m_accounts . isElement ( ) ) {
TQDomElement childElement = m_accounts . toElement ( ) ;
if ( childElement . tagName ( ) = = " account "
& & childElement . attribute ( " name " ) = = " " ) {
+ + m_accountsRead ;
MyMoneyAccount parent ;
switch ( childElement . attribute ( " type " ) . toUInt ( ) ) {
case MyMoneyAccount : : Asset :
parent = file - > asset ( ) ;
break ;
case MyMoneyAccount : : Liability :
parent = file - > liability ( ) ;
break ;
case MyMoneyAccount : : Income :
parent = file - > income ( ) ;
break ;
case MyMoneyAccount : : Expense :
parent = file - > expense ( ) ;
break ;
case MyMoneyAccount : : Equity :
parent = file - > equity ( ) ;
break ;
default :
KMessageBox : : error ( tqApp - > mainWidget ( ) , TQString ( " <p> " ) + i18n ( " Invalid top-level account type <b>%1</b> in template file <b>%2</b>! " ) . arg ( childElement . attribute ( " type " ) ) . arg ( m_source . prettyURL ( ) ) ) ;
rc = false ;
}
if ( rc = = true ) {
rc = createAccounts ( parent , childElement . firstChild ( ) ) ;
}
} else {
rc = false ;
}
m_accounts = m_accounts . nextSibling ( ) ;
}
signalProgress ( - 1 , - 1 ) ;
return rc ;
}
bool MyMoneyTemplate : : createAccounts ( MyMoneyAccount & parent , TQDomNode account )
{
bool rc = true ;
while ( rc = = true & & ! account . isNull ( ) ) {
MyMoneyAccount acc ;
if ( account . isElement ( ) ) {
TQDomElement accountElement = account . toElement ( ) ;
if ( accountElement . tagName ( ) = = " account " ) {
signalProgress ( + + m_accountsRead , 0 ) ;
TQValueList < MyMoneyAccount > subAccountList ;
TQValueList < MyMoneyAccount > : : ConstIterator it ;
it = subAccountList . end ( ) ;
if ( ! parent . accountList ( ) . isEmpty ( ) ) {
MyMoneyFile : : instance ( ) - > accountList ( subAccountList , parent . accountList ( ) ) ;
for ( it = subAccountList . begin ( ) ; it ! = subAccountList . end ( ) ; + + it ) {
if ( ( * it ) . name ( ) = = accountElement . attribute ( " name " ) ) {
acc = * it ;
break ;
}
}
}
if ( it = = subAccountList . end ( ) ) {
// not found, we need to create it
acc . setName ( accountElement . attribute ( " name " ) ) ;
acc . setAccountType ( static_cast < MyMoneyAccount : : _accountTypeE > ( accountElement . attribute ( " type " ) . toUInt ( ) ) ) ;
setFlags ( acc , account . firstChild ( ) ) ;
try {
MyMoneyFile : : instance ( ) - > addAccount ( acc , parent ) ;
} catch ( MyMoneyException * e ) {
delete e ;
}
}
createAccounts ( acc , account . firstChild ( ) ) ;
}
}
account = account . nextSibling ( ) ;
}
return rc ;
}
bool MyMoneyTemplate : : setFlags ( MyMoneyAccount & acc , TQDomNode flags )
{
bool rc = true ;
while ( rc = = true & & ! flags . isNull ( ) ) {
if ( flags . isElement ( ) ) {
TQDomElement flagElement = flags . toElement ( ) ;
if ( flagElement . tagName ( ) = = " flag " ) {
// make sure, we only store flags we know!
TQString value = flagElement . attribute ( " name " ) ;
if ( value = = " Tax " ) {
acc . setValue ( value . latin1 ( ) , " Yes " ) ;
} else {
KMessageBox : : error ( tqApp - > mainWidget ( ) , TQString ( " <p> " ) + i18n ( " Invalid flag type <b>%1</b> for account <b>%3</b> in template file <b>%2</b>! " ) . arg ( flagElement . attribute ( " name " ) ) . arg ( m_source . prettyURL ( ) ) . arg ( acc . name ( ) ) ) ;
rc = false ;
}
}
}
flags = flags . nextSibling ( ) ;
}
return rc ;
}
void MyMoneyTemplate : : signalProgress ( int current , int total , const TQString & msg )
{
if ( m_progressCallback ! = 0 )
( * m_progressCallback ) ( current , total , msg ) ;
}
bool MyMoneyTemplate : : exportTemplate ( void ( * callback ) ( int , int , const TQString & ) )
{
m_progressCallback = callback ;
m_doc = TQDomDocument ( " KMYMONEY-TEMPLATE " ) ;
TQDomProcessingInstruction instruct = m_doc . createProcessingInstruction ( TQString ( " xml " ) , TQString ( " version= \" 1.0 \" encoding= \" utf-8 \" " ) ) ;
m_doc . appendChild ( instruct ) ;
TQDomElement mainElement = m_doc . createElement ( " kmymoney-account-template " ) ;
m_doc . appendChild ( mainElement ) ;
TQDomElement title = m_doc . createElement ( " title " ) ;
mainElement . appendChild ( title ) ;
TQDomElement shortDesc = m_doc . createElement ( " shortdesc " ) ;
mainElement . appendChild ( shortDesc ) ;
TQDomElement longDesc = m_doc . createElement ( " longdesc " ) ;
mainElement . appendChild ( longDesc ) ;
TQDomElement accounts = m_doc . createElement ( " accounts " ) ;
mainElement . appendChild ( accounts ) ;
// addAccountStructure(accounts, MyMoneyFile::instance()->asset());
// addAccountStructure(accounts, MyMoneyFile::instance()->liability());
addAccountStructure ( accounts , MyMoneyFile : : instance ( ) - > income ( ) ) ;
addAccountStructure ( accounts , MyMoneyFile : : instance ( ) - > expense ( ) ) ;
// addAccountStructure(accounts, MyMoneyFile::instance()->equity());
return true ;
}
bool MyMoneyTemplate : : addAccountStructure ( TQDomElement & parent , const MyMoneyAccount & acc )
{
TQDomElement account = m_doc . createElement ( " account " ) ;
parent . appendChild ( account ) ;
if ( MyMoneyFile : : instance ( ) - > isStandardAccount ( acc . id ( ) ) )
account . setAttribute ( TQString ( " name " ) , TQString ( ) ) ;
else
account . setAttribute ( TQString ( " name " ) , acc . name ( ) ) ;
account . setAttribute ( TQString ( " type " ) , acc . accountType ( ) ) ;
// FIXME: add tax flag stuff
// any child accounts?
if ( acc . accountList ( ) . count ( ) > 0 ) {
TQValueList < MyMoneyAccount > list ;
MyMoneyFile : : instance ( ) - > accountList ( list , acc . accountList ( ) , false ) ;
TQValueList < MyMoneyAccount > : : Iterator it ;
for ( it = list . begin ( ) ; it ! = list . end ( ) ; + + it ) {
addAccountStructure ( account , * it ) ;
}
}
return true ;
}
bool MyMoneyTemplate : : saveTemplate ( const KURL & url )
{
TQString filename ;
if ( ! url . isValid ( ) ) {
tqDebug ( " Invalid template URL '%s' " , url . url ( ) . latin1 ( ) ) ;
return false ;
}
if ( url . isLocalFile ( ) ) {
filename = url . path ( ) ;
KSaveFile qfile ( filename , 0600 ) ;
if ( qfile . status ( ) = = 0 ) {
saveToLocalFile ( qfile . file ( ) ) ;
if ( ! qfile . close ( ) ) {
throw new MYMONEYEXCEPTION ( i18n ( " Unable to write changes to '%1' " ) . arg ( filename ) ) ;
}
} else {
throw new MYMONEYEXCEPTION ( i18n ( " Unable to write changes to '%1' " ) . arg ( filename ) ) ;
}
} else {
KTempFile tmpfile ;
saveToLocalFile ( tmpfile . file ( ) ) ;
if ( ! TDEIO : : NetAccess : : upload ( tmpfile . name ( ) , url , NULL ) )
throw new MYMONEYEXCEPTION ( i18n ( " Unable to upload to '%1' " ) . arg ( url . url ( ) ) ) ;
tmpfile . unlink ( ) ;
}
return true ;
}
bool MyMoneyTemplate : : saveToLocalFile ( TQFile * qfile )
{
TQTextStream stream ( qfile ) ;
stream . setEncoding ( TQTextStream : : UnicodeUTF8 ) ;
stream < < m_doc . toString ( ) ;
return true ;
}