/*************************************************************************** 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. * * * ***************************************************************************/ #include "config.h" // ---------------------------------------------------------------------------- // QT Includes #include <tqfile.h> #include <tqdom.h> #include <tqmap.h> #include <tqxml.h> // ---------------------------------------------------------------------------- // KDE Includes #include "kdecompat.h" #include <klocale.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) { qDebug("startDocument"); return true; } bool MyMoneyXmlContentHandler::endDocument(void) { qDebug("endDocument"); return true; } bool MyMoneyXmlContentHandler::skippedEntity (const TQString & /* name */) { // qDebug(TQString("Skipped entity '%1'").tqarg(name)); return true; } bool MyMoneyXmlContentHandler::startPrefixMapping (const TQString& /*prefix */, const TQString & /* uri */) { // qDebug(TQString("start prefix '%1', '%2'").tqarg(prefix).tqarg(uri)); return true; } bool MyMoneyXmlContentHandler::endPrefixMapping (const TQString& /* prefix */) { // qDebug(TQString("end prefix '%1'").tqarg(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") { qDebug("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") { qDebug("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") { qDebug("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") { qDebug("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") { qDebug("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").tqarg(qName).tqarg(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").tqarg(s).tqarg(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) { Q_CHECK_PTR(storage); Q_CHECK_PTR(pDevice); if(!storage) return; m_storage = storage; m_doc = new TQDomDocument; Q_CHECK_PTR(m_doc); qDebug("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); qDebug("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) { Q_CHECK_PTR(qf); Q_CHECK_PTR(storage); if(!storage) { return; } m_storage = storage; // qDebug("XMLWRITER: Starting file write"); m_doc = new TQDomDocument("KMYMONEY-FILE"); Q_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& tqparent) { const TQValueList<MyMoneyReport> list = m_storage->reportList(); TQValueList<MyMoneyReport>::ConstIterator it; tqparent.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, tqparent); signalProgress(++i, 0); } } void MyMoneyStorageXML::writeBudgets(TQDomElement& tqparent) { const TQValueList<MyMoneyBudget> list = m_storage->budgetList(); TQValueList<MyMoneyBudget>::ConstIterator it; tqparent.setAttribute("count", list.count()); signalProgress(0, list.count(), i18n("Saving budgets...")); unsigned i = 0; for(it = list.begin(); it != list.end(); ++it) { writeBudget(tqparent, (*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(Qt::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. */ QByteArray QIODevice::readAll() { if ( TQT_TQIODEVICE(this)->isDirectAccess() ) { // we know the size int n = size()-TQT_TQIODEVICE(this)->at(); // ### fix for 64-bit or large files? int totalRead = 0; TQByteArray ba( n ); char* c = ba.data(); while ( n ) { int r = TQT_TQIODEVICE(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 = TQT_TQIODEVICE(this)->readBlock( ba.data()+nread, blocksize ); if ( r < 0 ) return TQByteArray(); nread += r; } ba.resize( nread ); return ba; } }