/*************************************************************************** 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. * * * ***************************************************************************/ #include "kdecompat.h" // ---------------------------------------------------------------------------- // QT Includes #include #include #include // ---------------------------------------------------------------------------- // KDE Includes #include #include #include #include // ---------------------------------------------------------------------------- // 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()) { qDebug("Invalid template URL '%s'", url.url().latin1()); return false; } m_source = url; if(url.isLocalFile()) { filename = url.path(); } else { bool rc; rc = KIO::NetAccess::download(url, filename, tqApp->mainWidget()); if(!rc) { KMessageBox::detailedError(tqApp->mainWidget(), i18n("Error while loading file '%1'!").tqarg(url.url()), KIO::NetAccess::lastErrorString(), i18n("File access error")); return false; } } bool rc = true; TQFile file(filename); TQFileInfo info(file); if(!info.isFile()) { TQString msg=i18n("%1 is not a template file.").tqarg(filename); KMessageBox::error(tqApp->mainWidget(), TQString("

")+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 %1 in line %2, column %3").tqarg(filename).tqarg(errLine).tqarg(errColumn); KMessageBox::detailedError(tqApp->mainWidget(), TQString("

")+msg, errMsg, i18n("Template Error")); rc = false; } else { rc = loadDescription(); } file.close(); } else { KMessageBox::sorry(tqApp->mainWidget(), i18n("File '%1' not found!").tqarg(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 KIO::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(); // qDebug("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("

")+i18n("Invalid tag %1 in template file %2!").tqarg(childElement.tagName()).tqarg(m_source.prettyURL())); validMask |= invalid; } child = child.nextSibling(); } } return validMask == validHeader; } bool MyMoneyTemplate::hierarchy(TQMap& list, const TQString& tqparent, 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").tqarg(tqparent).tqarg(accountElement.attribute("name")); list[name] = 0; hierarchy(list, name, account.firstChild()); } } account = account.nextSibling(); } return rc; } void MyMoneyTemplate::hierarchy(TQMap& 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").tqarg(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 tqparent; switch(childElement.attribute("type").toUInt()) { case MyMoneyAccount::Asset: tqparent = file->asset(); break; case MyMoneyAccount::Liability: tqparent = file->liability(); break; case MyMoneyAccount::Income: tqparent = file->income(); break; case MyMoneyAccount::Expense: tqparent = file->expense(); break; case MyMoneyAccount::Equity: tqparent = file->equity(); break; default: KMessageBox::error(tqApp->mainWidget(), TQString("

")+i18n("Invalid top-level account type %1 in template file %2!").tqarg(childElement.attribute("type")).tqarg(m_source.prettyURL())); rc = false; } if(rc == true) { rc = createAccounts(tqparent, childElement.firstChild()); } } else { rc = false; } m_accounts = m_accounts.nextSibling(); } signalProgress(-1, -1); return rc; } bool MyMoneyTemplate::createAccounts(MyMoneyAccount& tqparent, 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 subAccountList; TQValueList::ConstIterator it; it = subAccountList.end(); if(!tqparent.accountList().isEmpty()) { MyMoneyFile::instance()->accountList(subAccountList, tqparent.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(accountElement.attribute("type").toUInt())); setFlags(acc, account.firstChild()); try { MyMoneyFile::instance()->addAccount(acc, tqparent); } 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("

")+i18n("Invalid flag type %1 for account %3 in template file %2!").tqarg(flagElement.attribute("name")).tqarg(m_source.prettyURL()).tqarg(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& tqparent, const MyMoneyAccount& acc) { TQDomElement account = m_doc.createElement("account"); tqparent.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 list; MyMoneyFile::instance()->accountList(list, acc.accountList(), false); TQValueList::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()) { qDebug("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'").tqarg(filename)); } } else { throw new MYMONEYEXCEPTION(i18n("Unable to write changes to '%1'").tqarg(filename)); } } else { KTempFile tmpfile; saveToLocalFile(tmpfile.file()); if(!KIO::NetAccess::upload(tmpfile.name(), url, NULL)) throw new MYMONEYEXCEPTION(i18n("Unable to upload to '%1'").tqarg(url.url())); tmpfile.unlink(); } return true; } bool MyMoneyTemplate::saveToLocalFile(TQFile* qfile) { TQTextStream stream(qfile); stream.setEncoding(TQTextStream::UnicodeUTF8); stream << m_doc.toString(); return true; }