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/mymoney/storage/mymoneystoragexml.cpp

910 lines
28 KiB

/***************************************************************************
mymoneystoragexml.cpp - description
-------------------
begin : Thu Oct 24 2002
copyright : (C) 2002 by Kevin Tambascio
(C) 2004 by Thomas Baumgart
email : Thomas Baumgart <ipwizard@users.sourceforge.net>
Kevin Tambascio <ktambascio@users.sourceforge.net>
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
// ----------------------------------------------------------------------------
// TQt Includes
#include <tqfile.h>
#include <tqdom.h>
#include <tqmap.h>
#include <tqxml.h>
// ----------------------------------------------------------------------------
// TDE Includes
#include <tdelocale.h>
#include <kdebug.h>
// ----------------------------------------------------------------------------
// Project Includes
#include "mymoneystoragexml.h"
#include "../mymoneyreport.h"
#include "../mymoneybudget.h"
#include "../mymoneyinstitution.h"
unsigned int MyMoneyStorageXML::fileVersionRead = 0;
unsigned int MyMoneyStorageXML::fileVersionWrite = 0;
class MyMoneyStorageXML::Private
{
friend class MyMoneyStorageXML;
public:
Private() {}
TQMap<TQString, MyMoneyInstitution> iList;
TQMap<TQString, MyMoneyAccount> aList;
TQMap<TQString, MyMoneyTransaction> tList;
TQMap<TQString, MyMoneyPayee> pList;
TQMap<TQString, MyMoneySchedule> sList;
TQMap<TQString, MyMoneySecurity> secList;
TQMap<TQString, MyMoneyReport> rList;
TQMap<TQString, MyMoneyBudget> bList;
TQMap<MyMoneySecurityPair, MyMoneyPriceEntries> prList;
TQString m_fromSecurity;
TQString m_toSecurity;
};
class MyMoneyXmlContentHandler : public TQXmlContentHandler
{
public:
MyMoneyXmlContentHandler(MyMoneyStorageXML* reader);
virtual ~MyMoneyXmlContentHandler() {}
virtual void setDocumentLocator (TQXmlLocator * locator) { m_loc = locator; }
virtual bool startDocument (void);
virtual bool endDocument (void);
virtual bool startPrefixMapping(const TQString & prefix, const TQString & uri);
virtual bool endPrefixMapping(const TQString & prefix);
virtual bool startElement(const TQString & namespaceURI, const TQString & localName, const TQString & qName, const TQXmlAttributes & atts);
virtual bool endElement(const TQString & namespaceURI, const TQString & localName, const TQString & qName);
virtual bool characters(const TQString & ch);
virtual bool ignorableWhitespace(const TQString & ch);
virtual bool processingInstruction(const TQString & target, const TQString & data);
virtual bool skippedEntity(const TQString & name);
virtual TQString errorString(void);
private:
MyMoneyStorageXML* m_reader;
TQXmlLocator* m_loc;
int m_level;
int m_elementCount;
TQDomDocument m_doc;
TQDomElement m_baseNode;
TQDomElement m_currNode;
TQString m_errMsg;
};
MyMoneyXmlContentHandler::MyMoneyXmlContentHandler(MyMoneyStorageXML* reader) :
m_reader(reader),
m_loc(0),
m_level(0),
m_elementCount(0)
{
}
bool MyMoneyXmlContentHandler::startDocument(void)
{
tqDebug("startDocument");
return true;
}
bool MyMoneyXmlContentHandler::endDocument(void)
{
tqDebug("endDocument");
return true;
}
bool MyMoneyXmlContentHandler::skippedEntity (const TQString & /* name */)
{
// tqDebug(TQString("Skipped entity '%1'").arg(name));
return true;
}
bool MyMoneyXmlContentHandler::startPrefixMapping (const TQString& /*prefix */, const TQString & /* uri */)
{
// tqDebug(TQString("start prefix '%1', '%2'").arg(prefix).arg(uri));
return true;
}
bool MyMoneyXmlContentHandler::endPrefixMapping (const TQString& /* prefix */)
{
// tqDebug(TQString("end prefix '%1'").arg(prefix));
return true;
}
bool MyMoneyXmlContentHandler::startElement (const TQString& /* namespaceURI */, const TQString& /* localName */, const TQString& qName, const TQXmlAttributes & atts)
{
if(m_level == 0) {
TQString s = qName.lower();
if(s == "transaction"
|| s == "account"
|| s == "price"
|| s == "payee"
|| s == "currency"
|| s == "security"
|| s == "keyvaluepairs"
|| s == "institution"
|| s == "report"
|| s == "budget"
|| s == "fileinfo"
|| s == "user"
|| s == "scheduled_tx") {
m_baseNode = m_doc.createElement(qName);
for(int i=0; i < atts.count(); ++i) {
m_baseNode.setAttribute(atts.qName(i), atts.value(i));
}
m_currNode = m_baseNode;
m_level = 1;
} else if(s == "transactions") {
tqDebug("reading transactions");
if(atts.count()) {
int count = atts.value(TQString("count")).toUInt();
m_reader->signalProgress(0, count, i18n("Loading transactions..."));
m_elementCount = 0;
}
} else if(s == "accounts") {
tqDebug("reading accounts");
if(atts.count()) {
int count = atts.value(TQString("count")).toUInt();
m_reader->signalProgress(0, count, i18n("Loading accounts..."));
m_elementCount = 0;
}
} else if(s == "securities") {
tqDebug("reading securities");
if(atts.count()) {
int count = atts.value(TQString("count")).toUInt();
m_reader->signalProgress(0, count, i18n("Loading securities..."));
m_elementCount = 0;
}
} else if(s == "reports") {
tqDebug("reading reports");
if(atts.count()) {
int count = atts.value(TQString("count")).toUInt();
m_reader->signalProgress(0, count, i18n("Loading reports..."));
m_elementCount = 0;
}
} else if(s == "prices") {
tqDebug("reading prices");
m_elementCount = 0;
} else if(s == "pricepair") {
if(atts.count()) {
m_reader->d->m_fromSecurity = atts.value(TQString("from"));
m_reader->d->m_toSecurity = atts.value(TQString("to"));
}
}
} else {
m_level++;
TQDomElement node = m_doc.createElement(qName);
for(int i=0; i < atts.count(); ++i) {
node.setAttribute(atts.qName(i), atts.value(i));
}
m_currNode.appendChild(node);
m_currNode = node;
}
return true;
}
bool MyMoneyXmlContentHandler::endElement(const TQString& /* namespaceURI */, const TQString& /* localName */, const TQString& qName)
{
bool rc = true;
TQString s = qName.lower();
if(m_level) {
m_currNode = m_currNode.parentNode().toElement();
m_level--;
if(!m_level) {
try {
if(s == "transaction") {
MyMoneyTransaction t(m_baseNode);
if(!t.id().isEmpty())
m_reader->d->tList[t.uniqueSortKey()] = t;
} else if(s == "account") {
MyMoneyAccount a(m_baseNode);
if(!a.id().isEmpty())
m_reader->d->aList[a.id()] = a;
} else if(s == "payee") {
MyMoneyPayee p(m_baseNode);
if(!p.id().isEmpty())
m_reader->d->pList[p.id()] = p;
} else if(s == "currency") {
MyMoneySecurity s(m_baseNode);
if(!s.id().isEmpty())
m_reader->d->secList[s.id()] = s;
} else if(s == "security") {
MyMoneySecurity s(m_baseNode);
if(!s.id().isEmpty())
m_reader->d->secList[s.id()] = s;
} else if(s == "keyvaluepairs") {
MyMoneyKeyValueContainer kvp(m_baseNode);
m_reader->m_storage->setPairs(kvp.pairs());
} else if(s == "institution") {
MyMoneyInstitution i(m_baseNode);
if(!i.id().isEmpty())
m_reader->d->iList[i.id()] = i;
} else if(s == "report") {
MyMoneyReport r(m_baseNode);
if(!r.id().isEmpty())
m_reader->d->rList[r.id()] = r;
} else if(s == "budget") {
MyMoneyBudget b(m_baseNode);
if(!b.id().isEmpty())
m_reader->d->bList[b.id()] = b;
} else if(s == "fileinfo") {
rc = m_reader->readFileInformation(m_baseNode);
} else if(s == "user") {
rc = m_reader->readUserInformation(m_baseNode);
} else if(s == "scheduled_tx") {
MyMoneySchedule s(m_baseNode);
if(!s.id().isEmpty())
m_reader->d->sList[s.id()] = s;
} else if(s == "price") {
MyMoneyPrice p(m_reader->d->m_fromSecurity, m_reader->d->m_toSecurity, m_baseNode);
m_reader->d->prList[MyMoneySecurityPair(m_reader->d->m_fromSecurity, m_reader->d->m_toSecurity)][p.date()] = p;
} else {
m_errMsg = i18n("Unknown XML tag %1 found in line %2").arg(qName).arg(m_loc->lineNumber());
kdWarning() << m_errMsg << endl;
rc = false;
}
m_reader->signalProgress(++m_elementCount, 0);
} catch(MyMoneyException* e) {
m_errMsg = i18n("Exception while creating a %1 element: %2").arg(s).arg(e->what());
kdWarning() << m_errMsg << endl;
delete e;
rc = false;
}
m_doc = TQDomDocument();
}
} else {
if(s == "institutions") {
// last institution read, now dump them into the engine
m_reader->m_storage->loadInstitutions(m_reader->d->iList);
m_reader->d->iList.clear();
m_reader->signalProgress(-1, -1);
} else if(s == "accounts") {
// last account read, now dump them into the engine
m_reader->m_storage->loadAccounts(m_reader->d->aList);
m_reader->d->aList.clear();
m_reader->signalProgress(-1, -1);
} else if(s == "payees") {
// last payee read, now dump them into the engine
m_reader->m_storage->loadPayees(m_reader->d->pList);
m_reader->d->pList.clear();
m_reader->signalProgress(-1, -1);
} else if(s == "transactions") {
// last transaction read, now dump them into the engine
m_reader->m_storage->loadTransactions(m_reader->d->tList);
m_reader->d->tList.clear();
m_reader->signalProgress(-1, -1);
} else if(s == "schedules") {
// last schedule read, now dump them into the engine
m_reader->m_storage->loadSchedules(m_reader->d->sList);
m_reader->d->sList.clear();
m_reader->signalProgress(-1, -1);
} else if(s == "securities") {
// last security read, now dump them into the engine
m_reader->m_storage->loadSecurities(m_reader->d->secList);
m_reader->d->secList.clear();
m_reader->signalProgress(-1, -1);
} else if(s == "currencies") {
// last currency read, now dump them into the engine
m_reader->m_storage->loadCurrencies(m_reader->d->secList);
m_reader->d->secList.clear();
m_reader->signalProgress(-1, -1);
} else if(s == "reports") {
// last report read, now dump them into the engine
m_reader->m_storage->loadReports(m_reader->d->rList);
m_reader->d->rList.clear();
m_reader->signalProgress(-1, -1);
} else if(s == "budgets") {
// last budget read, now dump them into the engine
m_reader->m_storage->loadBudgets(m_reader->d->bList);
m_reader->d->bList.clear();
m_reader->signalProgress(-1, -1);
} else if(s == "prices") {
// last price read, now dump them into the engine
m_reader->m_storage->loadPrices(m_reader->d->prList);
m_reader->d->bList.clear();
m_reader->signalProgress(-1, -1);
}
}
return rc;
}
bool MyMoneyXmlContentHandler::characters(const TQString& /* ch */)
{
return true;
}
bool MyMoneyXmlContentHandler::ignorableWhitespace(const TQString& /* ch */)
{
return true;
}
bool MyMoneyXmlContentHandler::processingInstruction(const TQString& /* target */, const TQString& /* data */)
{
return true;
}
TQString MyMoneyXmlContentHandler::errorString(void)
{
return m_errMsg;
}
MyMoneyStorageXML::MyMoneyStorageXML() :
m_storage(0),
m_doc(0),
d(new Private())
{
}
MyMoneyStorageXML::~MyMoneyStorageXML()
{
delete d;
}
// Function to read in the file, send to XML parser.
void MyMoneyStorageXML::readFile(TQIODevice* pDevice, IMyMoneySerialize* storage)
{
TQ_CHECK_PTR(storage);
TQ_CHECK_PTR(pDevice);
if(!storage)
return;
m_storage = storage;
m_doc = new TQDomDocument;
TQ_CHECK_PTR(m_doc);
tqDebug("reading file");
// creating the TQXmlInputSource object based on a TQIODevice object
// reads all data of the underlying object into memory. I have not
// found an object that reads on the fly. I tried to derive one myself,
// but there could be a severe problem with decoding when reading
// blocks of data and not a stream. So I left it the way it is. (ipwizard)
TQXmlInputSource xml(pDevice);
tqDebug("start parsing file");
MyMoneyXmlContentHandler mmxml(this);
TQXmlSimpleReader reader;
reader.setContentHandler(&mmxml);
if(!reader.parse(&xml, false)) {
delete m_doc;
m_doc = NULL;
signalProgress(-1, -1);
throw new MYMONEYEXCEPTION("File was not parsable!");
}
// check if we need to build up the account balances
if(fileVersionRead < 2)
m_storage->rebuildAccountBalances();
delete m_doc;
m_doc = NULL;
// this seems to be nonsense, but it clears the dirty flag
// as a side-effect.
m_storage->setLastModificationDate(m_storage->lastModificationDate());
m_storage = NULL;
//hides the progress bar.
signalProgress(-1, -1);
}
void MyMoneyStorageXML::writeFile(TQIODevice* qf, IMyMoneySerialize* storage)
{
TQ_CHECK_PTR(qf);
TQ_CHECK_PTR(storage);
if(!storage)
{
return;
}
m_storage = storage;
// tqDebug("XMLWRITER: Starting file write");
m_doc = new TQDomDocument("KMYMONEY-FILE");
TQ_CHECK_PTR(m_doc);
TQDomProcessingInstruction instruct = m_doc->createProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
m_doc->appendChild(instruct);
TQDomElement mainElement = m_doc->createElement("KMYMONEY-FILE");
m_doc->appendChild(mainElement);
TQDomElement fileInfo = m_doc->createElement("FILEINFO");
writeFileInformation(fileInfo);
mainElement.appendChild(fileInfo);
TQDomElement userInfo = m_doc->createElement("USER");
writeUserInformation(userInfo);
mainElement.appendChild(userInfo);
TQDomElement institutions = m_doc->createElement("INSTITUTIONS");
writeInstitutions(institutions);
mainElement.appendChild(institutions);
TQDomElement payees = m_doc->createElement("PAYEES");
writePayees(payees);
mainElement.appendChild(payees);
TQDomElement accounts = m_doc->createElement("ACCOUNTS");
writeAccounts(accounts);
mainElement.appendChild(accounts);
TQDomElement transactions = m_doc->createElement("TRANSACTIONS");
writeTransactions(transactions);
mainElement.appendChild(transactions);
TQDomElement keyvalpairs = writeKeyValuePairs(m_storage->pairs());
mainElement.appendChild(keyvalpairs);
TQDomElement schedules = m_doc->createElement("SCHEDULES");
writeSchedules(schedules);
mainElement.appendChild(schedules);
TQDomElement equities = m_doc->createElement("SECURITIES");
writeSecurities(equities);
mainElement.appendChild(equities);
TQDomElement currencies = m_doc->createElement("CURRENCIES");
writeCurrencies(currencies);
mainElement.appendChild(currencies);
TQDomElement prices = m_doc->createElement("PRICES");
writePrices(prices);
mainElement.appendChild(prices);
TQDomElement reports = m_doc->createElement("REPORTS");
writeReports(reports);
mainElement.appendChild(reports);
TQDomElement budgets = m_doc->createElement("BUDGETS");
writeBudgets(budgets);
mainElement.appendChild(budgets);
TQTextStream stream(qf);
stream.setEncoding(TQTextStream::UnicodeUTF8);
stream << m_doc->toString();
delete m_doc;
m_doc = NULL;
//hides the progress bar.
signalProgress(-1, -1);
// this seems to be nonsense, but it clears the dirty flag
// as a side-effect.
m_storage->setLastModificationDate(m_storage->lastModificationDate());
m_storage = NULL;
}
bool MyMoneyStorageXML::readFileInformation(const TQDomElement& fileInfo)
{
signalProgress(0, 3, i18n("Loading file information..."));
bool rc = true;
TQDomElement temp = findChildElement("CREATION_DATE", fileInfo);
if (temp == TQDomElement()) {
rc = false;
}
TQString strDate = TQStringEmpty(temp.attribute("date"));
m_storage->setCreationDate(stringToDate(strDate));
signalProgress(1, 0);
temp = findChildElement("LAST_MODIFIED_DATE", fileInfo);
if (temp == TQDomElement()) {
rc = false;
}
strDate = TQStringEmpty(temp.attribute("date"));
m_storage->setLastModificationDate(stringToDate(strDate));
signalProgress(2, 0);
temp = findChildElement("VERSION", fileInfo);
if (temp == TQDomElement()) {
rc = false;
}
TQString strVersion = TQStringEmpty(temp.attribute("id"));
fileVersionRead = strVersion.toUInt(NULL, 16);
temp = findChildElement("FIXVERSION", fileInfo);
if (temp != TQDomElement()) {
TQString strFixVersion = TQStringEmpty(temp.attribute("id"));
m_storage->setFileFixVersion (strFixVersion.toUInt());
}
// FIXME The old version stuff used this rather odd number
// We now use increments
if(fileVersionRead == VERSION_0_60_XML)
fileVersionRead = 1;
signalProgress(3, 0);
return rc;
}
void MyMoneyStorageXML::writeFileInformation(TQDomElement& fileInfo)
{
TQDomElement creationDate = m_doc->createElement("CREATION_DATE");
creationDate.setAttribute("date", dateToString(m_storage->creationDate()));
fileInfo.appendChild(creationDate);
TQDomElement lastModifiedDate = m_doc->createElement("LAST_MODIFIED_DATE");
lastModifiedDate.setAttribute("date", dateToString(m_storage->lastModificationDate()));
fileInfo.appendChild(lastModifiedDate);
TQDomElement version = m_doc->createElement("VERSION");
version.setAttribute("id", "1");
fileInfo.appendChild(version);
TQDomElement fixVersion = m_doc->createElement("FIXVERSION");
fixVersion.setAttribute("id", m_storage->fileFixVersion());
fileInfo.appendChild(fixVersion);
}
void MyMoneyStorageXML::writeUserInformation(TQDomElement& userInfo)
{
MyMoneyPayee user = m_storage->user();
userInfo.setAttribute("name", user.name());
userInfo.setAttribute("email", user.email());
TQDomElement address = m_doc->createElement("ADDRESS");
address.setAttribute("street", user.address());
address.setAttribute("city", user.city());
address.setAttribute("county", user.state());
address.setAttribute("zipcode", user.postcode());
address.setAttribute("telephone", user.telephone());
userInfo.appendChild(address);
}
bool MyMoneyStorageXML::readUserInformation(const TQDomElement& userElement)
{
bool rc = true;
signalProgress(0, 1, i18n("Loading user information..."));
MyMoneyPayee user;
user.setName(TQStringEmpty(userElement.attribute("name")));
user.setEmail(TQStringEmpty(userElement.attribute("email")));
TQDomElement addressNode = findChildElement("ADDRESS", userElement);
if(!addressNode.isNull()) {
user.setAddress(TQStringEmpty(addressNode.attribute("street")));
user.setCity(TQStringEmpty(addressNode.attribute("city")));
user.setState(TQStringEmpty(addressNode.attribute("county")));
user.setPostcode(TQStringEmpty(addressNode.attribute("zipcode")));
user.setTelephone(TQStringEmpty(addressNode.attribute("telephone")));
}
m_storage->setUser(user);
signalProgress(1, 0);
return rc;
}
void MyMoneyStorageXML::writeInstitutions(TQDomElement& institutions)
{
const TQValueList<MyMoneyInstitution> list = m_storage->institutionList();
TQValueList<MyMoneyInstitution>::ConstIterator it;
institutions.setAttribute("count", list.count());
for(it = list.begin(); it != list.end(); ++it)
writeInstitution(institutions, *it);
}
void MyMoneyStorageXML::writeInstitution(TQDomElement& institution, const MyMoneyInstitution& i)
{
i.writeXML(*m_doc, institution);
}
void MyMoneyStorageXML::writePayees(TQDomElement& payees)
{
const TQValueList<MyMoneyPayee> list = m_storage->payeeList();
TQValueList<MyMoneyPayee>::ConstIterator it;
payees.setAttribute("count", list.count());
for(it = list.begin(); it != list.end(); ++it)
writePayee(payees, *it);
}
void MyMoneyStorageXML::writePayee(TQDomElement& payee, const MyMoneyPayee& p)
{
p.writeXML(*m_doc, payee);
}
void MyMoneyStorageXML::writeAccounts(TQDomElement& accounts)
{
TQValueList<MyMoneyAccount> list;
m_storage->accountList(list);
TQValueList<MyMoneyAccount>::ConstIterator it;
accounts.setAttribute("count", list.count()+5);
writeAccount(accounts, m_storage->asset());
writeAccount(accounts, m_storage->liability());
writeAccount(accounts, m_storage->expense());
writeAccount(accounts, m_storage->income());
writeAccount(accounts, m_storage->equity());
signalProgress(0, list.count(), i18n("Saving accounts..."));
int i = 0;
for(it = list.begin(); it != list.end(); ++it, ++i) {
writeAccount(accounts, *it);
signalProgress(i, 0);
}
}
void MyMoneyStorageXML::writeAccount(TQDomElement& account, const MyMoneyAccount& p)
{
p.writeXML(*m_doc, account);
}
void MyMoneyStorageXML::writeTransactions(TQDomElement& transactions)
{
MyMoneyTransactionFilter filter;
filter.setReportAllSplits(false);
TQValueList<MyMoneyTransaction> list;
m_storage->transactionList(list, filter);
transactions.setAttribute("count", list.count());
TQValueList<MyMoneyTransaction>::ConstIterator it;
signalProgress(0, list.count(), i18n("Saving transactions..."));
int i = 0;
for(it = list.begin(); it != list.end(); ++it, ++i)
{
writeTransaction(transactions, *it);
signalProgress(i, 0);
}
}
void MyMoneyStorageXML::writeTransaction(TQDomElement& transaction, const MyMoneyTransaction& tx)
{
tx.writeXML(*m_doc, transaction);
}
void MyMoneyStorageXML::writeSchedules(TQDomElement& scheduled)
{
const TQValueList<MyMoneySchedule> list = m_storage->scheduleList();
TQValueList<MyMoneySchedule>::ConstIterator it;
scheduled.setAttribute("count", list.count());
for(it = list.begin(); it != list.end(); ++it)
{
this->writeSchedule(scheduled, *it);
}
}
void MyMoneyStorageXML::writeSchedule(TQDomElement& scheduledTx, const MyMoneySchedule& tx)
{
tx.writeXML(*m_doc, scheduledTx);
}
void MyMoneyStorageXML::writeSecurities(TQDomElement& equities)
{
const TQValueList<MyMoneySecurity> securityList = m_storage->securityList();
equities.setAttribute("count", securityList.count());
if(securityList.size())
{
for(TQValueList<MyMoneySecurity>::ConstIterator it = securityList.begin(); it != securityList.end(); ++it)
{
writeSecurity(equities, (*it));
}
}
}
void MyMoneyStorageXML::writeSecurity(TQDomElement& securityElement, const MyMoneySecurity& security)
{
security.writeXML(*m_doc, securityElement);
}
void MyMoneyStorageXML::writeCurrencies(TQDomElement& currencies)
{
const TQValueList<MyMoneySecurity> currencyList = m_storage->currencyList();
currencies.setAttribute("count", currencyList.count());
if(currencyList.size())
{
for(TQValueList<MyMoneySecurity>::ConstIterator it = currencyList.begin(); it != currencyList.end(); ++it)
{
writeSecurity(currencies, (*it));
}
}
}
void MyMoneyStorageXML::writeReports(TQDomElement& parent)
{
const TQValueList<MyMoneyReport> list = m_storage->reportList();
TQValueList<MyMoneyReport>::ConstIterator it;
parent.setAttribute("count", list.count());
signalProgress(0, list.count(), i18n("Saving reports..."));
unsigned i = 0;
for(it = list.begin(); it != list.end(); ++it)
{
(*it).writeXML(*m_doc, parent);
signalProgress(++i, 0);
}
}
void MyMoneyStorageXML::writeBudgets(TQDomElement& parent)
{
const TQValueList<MyMoneyBudget> list = m_storage->budgetList();
TQValueList<MyMoneyBudget>::ConstIterator it;
parent.setAttribute("count", list.count());
signalProgress(0, list.count(), i18n("Saving budgets..."));
unsigned i = 0;
for(it = list.begin(); it != list.end(); ++it)
{
writeBudget(parent, (*it));
signalProgress(++i, 0);
}
}
void MyMoneyStorageXML::writeBudget(TQDomElement& budget, const MyMoneyBudget& b)
{
b.writeXML(*m_doc, budget);
}
TQDomElement MyMoneyStorageXML::findChildElement(const TQString& name, const TQDomElement& root)
{
TQDomNode child = root.firstChild();
while(!child.isNull())
{
if(child.isElement())
{
TQDomElement childElement = child.toElement();
if(name == childElement.tagName())
{
return childElement;
}
}
child = child.nextSibling();
}
return TQDomElement();
}
TQDomElement MyMoneyStorageXML::writeKeyValuePairs(const TQMap<TQString, TQString> pairs)
{
if(m_doc)
{
TQDomElement keyValPairs = m_doc->createElement("KEYVALUEPAIRS");
TQMap<TQString, TQString>::const_iterator it;
for(it = pairs.begin(); it != pairs.end(); ++it)
{
TQDomElement pair = m_doc->createElement("PAIR");
pair.setAttribute("key", it.key());
pair.setAttribute("value", it.data());
keyValPairs.appendChild(pair);
}
return keyValPairs;
}
return TQDomElement();
}
void MyMoneyStorageXML::writePrices(TQDomElement& prices)
{
const MyMoneyPriceList list = m_storage->priceList();
MyMoneyPriceList::ConstIterator it;
prices.setAttribute("count", list.count());
for(it = list.begin(); it != list.end(); ++it)
{
TQDomElement price = m_doc->createElement("PRICEPAIR");
price.setAttribute("from", it.key().first);
price.setAttribute("to", it.key().second);
writePricePair(price, *it);
prices.appendChild(price);
}
}
void MyMoneyStorageXML::writePricePair(TQDomElement& price, const MyMoneyPriceEntries& p)
{
MyMoneyPriceEntries::ConstIterator it;
for(it = p.begin(); it != p.end(); ++it) {
TQDomElement entry = m_doc->createElement("PRICE");
writePrice(entry, *it);
price.appendChild(entry);
}
}
void MyMoneyStorageXML::writePrice(TQDomElement& price, const MyMoneyPrice& p)
{
price.setAttribute("date", p.date().toString(TQt::ISODate));
price.setAttribute("price", p.rate(TQString()).toString());
price.setAttribute("source", p.source());
}
void MyMoneyStorageXML::setProgressCallback(void(*callback)(int, int, const TQString&))
{
m_progressCallback = callback;
}
void MyMoneyStorageXML::signalProgress(int current, int total, const TQString& msg)
{
if(m_progressCallback != 0)
(*m_progressCallback)(current, total, msg);
}
/*!
This convenience function returns all of the remaining data in the
device.
@note It's copied from the original TQt sources and modified to
fix a problem with KFilterDev that does not correctly return
atEnd() status in certain circumstances which caused our
application to lock at startup.
*/
TQByteArray TQIODevice::readAll()
{
if ( this->isDirectAccess() ) {
// we know the size
int n = size()-this->at(); // ### fix for 64-bit or large files?
int totalRead = 0;
TQByteArray ba( n );
char* c = ba.data();
while ( n ) {
int r = this->readBlock( c, n );
if ( r < 0 )
return TQByteArray();
n -= r;
c += r;
totalRead += r;
// If we have a translated file, then it is possible that
// we read less bytes than size() reports
if ( atEnd() ) {
ba.resize( totalRead );
break;
}
}
return ba;
} else {
// read until we reach the end
const int blocksize = 512;
int nread = 0;
TQByteArray ba;
int r = 1;
while ( !atEnd() && r != 0) {
ba.resize( nread + blocksize );
r = this->readBlock( ba.data()+nread, blocksize );
if ( r < 0 )
return TQByteArray();
nread += r;
}
ba.resize( nread );
return ba;
}
}