/*************************************************************************** mymoneyreport.cpp ------------------- begin : Sun July 4 2004 copyright : (C) 2004-2005 by Ace Jones email : acejones@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 #endif // ---------------------------------------------------------------------------- // TQt Includes #include #include // ---------------------------------------------------------------------------- // TDE Includes // ---------------------------------------------------------------------------- // Project Includes #include "mymoneyfile.h" #include "mymoneyreport.h" const TQStringList MyMoneyReport::kRowTypeText = TQStringList::split ( ",", "none,assetliability,expenseincome,category,topcategory,account,payee,month,week,topaccount,topaccount-account,equitytype,accounttype,institution,budget,budgetactual,schedule,accountinfo,accountloaninfo,accountreconcile,cashflow", true ); const TQStringList MyMoneyReport::kColumnTypeText = TQStringList::split ( ",", "none,months,bimonths,quarters,4,5,6,weeks,8,9,10,11,years", true ); // if you add names here, don't forget to update the bitmap for EQueryColumns // and shift the bit for eTQCend one position to the left const TQStringList MyMoneyReport::kQueryColumnsText = TQStringList::split ( ",", "none,number,payee,category,memo,account,reconcileflag,action,shares,price,performance,loan,balance", true ); const MyMoneyReport::EReportType MyMoneyReport::kTypeArray[] = { eNoReport, ePivotTable, ePivotTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, eQueryTable, ePivotTable, ePivotTable, eInfoTable, eInfoTable, eInfoTable, eQueryTable, eQueryTable, eNoReport }; const TQStringList MyMoneyReport::kDetailLevelText = TQStringList::split ( ",", "none,all,top,group,total,invalid", true ); const TQStringList MyMoneyReport::kChartTypeText = TQStringList::split ( ",", "none,line,bar,pie,ring,stackedbar,invalid", true ); // This should live in mymoney/mymoneytransactionfilter.h static const TQStringList kTypeText = TQStringList::split ( ",", "all,payments,deposits,transfers,none" ); static const TQStringList kStateText = TQStringList::split ( ",", "all,notreconciled,cleared,reconciled,frozen,none" ); static const TQStringList kDateLockText = TQStringList::split ( ",", "alldates,untiltoday,currentmonth,currentyear,monthtodate,yeartodate,yeartomonth,lastmonth,lastyear,last7days,last30days,last3months,last6months,last12months,next7days,next30days,next3months,next6months,next12months,userdefined,last3tonext3months,last11Months,currentQuarter,lastQuarter,nextQuarter,currentFiscalYear,lastFiscalYear,today" ); static const TQStringList kAccountTypeText = TQStringList::split ( ",", "unknown,checkings,savings,cash,creditcard,loan,certificatedep,investment,moneymarket,asset,liability,currency,income,expense,assetloan,stock,equity,invalid" ); MyMoneyReport::MyMoneyReport() : m_name ( "Unconfigured Pivot Table Report" ), m_detailLevel ( eDetailNone ), m_convertCurrency ( true ), m_favorite ( false ), m_tax ( false ), m_investments ( false ), m_loans ( false ), m_reportType ( kTypeArray[eExpenseIncome] ), m_rowType ( eExpenseIncome ), m_columnType ( eMonths ), m_columnsAreDays ( false ), m_queryColumns ( eTQCnone ), m_dateLock ( userDefined ), m_accountGroupFilter ( false ), m_chartType ( eChartLine ), m_chartDataLabels ( true ), m_chartGridLines ( true ), m_chartByDefault ( false ), m_chartLineWidth ( 2 ), m_includeSchedules ( false ), m_includeTransfers ( false ), m_includeBudgetActuals ( false ), m_includeUnusedAccounts ( false ), m_showRowTotals ( false ), m_includeForecast ( false ), m_includeMovingAverage ( false ), m_includePrice ( false ), m_includeAveragePrice ( false ) { } MyMoneyReport::MyMoneyReport ( const TQString& id, const MyMoneyReport& right ) : MyMoneyObject ( id ) { *this = right; setId ( id ); } MyMoneyReport::MyMoneyReport ( ERowType _rt, unsigned _ct, dateOptionE _dl, EDetailLevel _ss, const TQString& _name, const TQString& _comment ) : m_name ( _name ), m_comment ( _comment ), m_detailLevel ( _ss ), m_convertCurrency ( true ), m_favorite ( false ), m_tax ( false ), m_investments ( false ), m_loans ( false ), m_reportType ( kTypeArray[_rt] ), m_rowType ( _rt ), m_columnsAreDays ( false ), m_dateLock ( _dl ), m_accountGroupFilter ( false ), m_chartType ( eChartLine ), m_chartDataLabels ( true ), m_chartGridLines ( true ), m_chartByDefault ( false ), m_chartLineWidth ( 2 ), m_includeSchedules ( false ), m_includeTransfers ( false ), m_includeBudgetActuals ( false ), m_includeUnusedAccounts ( false ), m_showRowTotals ( false ), m_includeForecast ( false ), m_includeMovingAverage ( false ), m_includePrice ( false ), m_includeAveragePrice ( false ) { if ( m_reportType == ePivotTable ) m_columnType = static_cast ( _ct ); if ( m_reportType == eQueryTable ) m_queryColumns = static_cast ( _ct ); setDateFilter ( _dl ); if ( ( _rt > static_cast ( sizeof ( kTypeArray ) / sizeof ( kTypeArray[0] ) ) ) || ( m_reportType == eNoReport ) ) throw new MYMONEYEXCEPTION ( "Invalid report type" ); if ( _rt == MyMoneyReport::eAssetLiability ) { addAccountGroup ( MyMoneyAccount::Asset ); addAccountGroup ( MyMoneyAccount::Liability ); m_showRowTotals = true; } if ( _rt == MyMoneyReport::eExpenseIncome ) { addAccountGroup ( MyMoneyAccount::Expense ); addAccountGroup ( MyMoneyAccount::Income ); m_showRowTotals = true; } //FIXME take this out once we have sorted out all issues regarding budget of assets and liabilities -- asoliverez@gmail.com if ( _rt == MyMoneyReport::eBudget || _rt == MyMoneyReport::eBudgetActual ) { addAccountGroup ( MyMoneyAccount::Expense ); addAccountGroup ( MyMoneyAccount::Income ); } if ( _rt == MyMoneyReport::eAccountInfo ) { addAccountGroup ( MyMoneyAccount::Asset ); addAccountGroup ( MyMoneyAccount::Liability ); } //cash flow reports show splits for all account groups if ( _rt == MyMoneyReport::eCashFlow ) { addAccountGroup ( MyMoneyAccount::Expense ); addAccountGroup ( MyMoneyAccount::Income ); addAccountGroup ( MyMoneyAccount::Asset ); addAccountGroup ( MyMoneyAccount::Liability ); } } MyMoneyReport::MyMoneyReport ( const TQDomElement& node ) : MyMoneyObject ( node ) { if ( !read ( node ) ) clearId(); } void MyMoneyReport::clear ( void ) { m_accountGroupFilter = false; m_accountGroups.clear(); MyMoneyTransactionFilter::clear(); } void MyMoneyReport::validDateRange ( TQDate& _db, TQDate& _de ) { _db = fromDate(); _de = toDate(); // if either begin or end date are invalid we have one of the following // possible date filters: // // a) begin date not set - first transaction until given end date // b) end date not set - from given date until last transaction // c) both not set - first transaction until last transaction // // If there is no transaction in the engine at all, we use the current // year as the filter criteria. if ( !_db.isValid() || !_de.isValid() ) { TQValueList list = MyMoneyFile::instance()->transactionList ( *this ); TQDate tmpBegin, tmpEnd; if ( !list.isEmpty() ) { qHeapSort ( list ); tmpBegin = list.front().postDate(); tmpEnd = list.back().postDate(); } else { tmpBegin = TQDate ( TQDate::currentDate().year(), 1, 1 ); // the first date in the file tmpEnd = TQDate ( TQDate::currentDate().year(), 12, 31 );// the last date in the file } if ( !_db.isValid() ) _db = tmpBegin; if ( !_de.isValid() ) _de = tmpEnd; } if ( _db > _de ) _db = _de; } void MyMoneyReport::setRowType ( ERowType _rt ) { m_rowType = _rt; m_reportType = kTypeArray[_rt]; m_accountGroupFilter = false; m_accountGroups.clear(); if ( _rt == MyMoneyReport::eAssetLiability ) { addAccountGroup ( MyMoneyAccount::Asset ); addAccountGroup ( MyMoneyAccount::Liability ); } if ( _rt == MyMoneyReport::eExpenseIncome ) { addAccountGroup ( MyMoneyAccount::Expense ); addAccountGroup ( MyMoneyAccount::Income ); } } bool MyMoneyReport::accountGroups(TQValueList& list) const { bool result = m_accountGroupFilter; if ( result ) { TQValueList::const_iterator it_group = m_accountGroups.begin(); while ( it_group != m_accountGroups.end() ) { list += ( *it_group ); ++it_group; } } return result; } void MyMoneyReport::addAccountGroup ( MyMoneyAccount::accountTypeE type ) { if ( !m_accountGroups.isEmpty() && type != MyMoneyAccount::UnknownAccountType ) { if ( m_accountGroups.contains ( type ) ) return; } m_accountGroupFilter = true; if ( type != MyMoneyAccount::UnknownAccountType ) m_accountGroups.push_back ( type ); } bool MyMoneyReport::includesAccountGroup( MyMoneyAccount::accountTypeE type ) const { bool result = ( ! m_accountGroupFilter ) || ( isIncludingTransfers() && m_rowType == MyMoneyReport::eExpenseIncome ) || m_accountGroups.contains ( type ); return result; } bool MyMoneyReport::includes( const MyMoneyAccount& acc ) const { bool result = false; if ( includesAccountGroup ( acc.accountGroup() ) ) { switch ( acc.accountGroup() ) { case MyMoneyAccount::Income: case MyMoneyAccount::Expense: if ( isTax() ) result = ( acc.value ( "Tax" ) == "Yes" ) && includesCategory ( acc.id() ); else result = includesCategory ( acc.id() ); break; case MyMoneyAccount::Asset: case MyMoneyAccount::Liability: if ( isLoansOnly() ) result = acc.isLoan() && includesAccount ( acc.id() ); else if ( isInvestmentsOnly() ) result = acc.isInvest() && includesAccount ( acc.id() ); else if ( isIncludingTransfers() && m_rowType == MyMoneyReport::eExpenseIncome ) // If transfers are included, ONLY include this account if it is NOT // included in the report itself!! result = ! includesAccount ( acc.id() ); else result = includesAccount ( acc.id() ); break; default: result = includesAccount ( acc.id() ); } } return result; } void MyMoneyReport::write ( TQDomElement& e, TQDomDocument *doc, bool anonymous ) const { // No matter what changes, be sure to have a 'type' attribute. Only change // the major type if it becomes impossible to maintain compatability with // older versions of the program as new features are added to the reports. // Feel free to change the minor type every time a change is made here. writeBaseXML ( *doc, e ); if ( anonymous ) { e.setAttribute ( "name", m_id ); e.setAttribute ( "comment", TQString ( m_comment ).fill ( 'x' ) ); } else { e.setAttribute ( "name", m_name ); e.setAttribute ( "comment", m_comment ); } e.setAttribute ( "group", m_group ); e.setAttribute ( "convertcurrency", m_convertCurrency ); e.setAttribute ( "favorite", m_favorite ); e.setAttribute ( "tax", m_tax ); e.setAttribute ( "investments", m_investments ); e.setAttribute ( "loans", m_loans ); e.setAttribute ( "rowtype", kRowTypeText[m_rowType] ); e.setAttribute ( "datelock", kDateLockText[m_dateLock] ); e.setAttribute ( "includeschedules", m_includeSchedules ); e.setAttribute ( "columnsaredays", m_columnsAreDays ); e.setAttribute ( "includestransfers", m_includeTransfers ); if ( !m_budgetId.isEmpty() ) e.setAttribute ( "budget", m_budgetId ); e.setAttribute ( "includesactuals", m_includeBudgetActuals ); e.setAttribute ( "includeunused", m_includeUnusedAccounts ); e.setAttribute ( "includesforecast", m_includeForecast ); e.setAttribute ( "includesprice", m_includePrice ); e.setAttribute ( "includesaverageprice", m_includeAveragePrice ); e.setAttribute ( "includesmovingaverage", m_includeMovingAverage ); if( m_includeMovingAverage ) e.setAttribute ( "movingaveragedays", m_movingAverageDays ); e.setAttribute ( "charttype", kChartTypeText[m_chartType] ); e.setAttribute ( "chartdatalabels", m_chartDataLabels ); e.setAttribute ( "chartgridlines", m_chartGridLines ); e.setAttribute ( "chartbydefault", m_chartByDefault ); e.setAttribute ( "chartlinewidth", m_chartLineWidth ); if ( m_reportType == ePivotTable ) { e.setAttribute ( "type", "pivottable 1.15" ); e.setAttribute ( "detail", kDetailLevelText[m_detailLevel] ); e.setAttribute ( "columntype", kColumnTypeText[m_columnType] ); e.setAttribute ( "showrowtotals", m_showRowTotals ); } else if ( m_reportType == eQueryTable ) { e.setAttribute ( "type", "querytable 1.14" ); TQStringList columns; unsigned qc = m_queryColumns; unsigned it_qc = eTQCbegin; unsigned index = 1; while ( it_qc != eTQCend ) { if ( qc & it_qc ) columns += kQueryColumnsText[index]; it_qc *= 2; index++; } e.setAttribute ( "querycolumns", columns.join ( "," ) ); } else if ( m_reportType == eInfoTable ) { e.setAttribute ( "type", "infotable 1.0" ); e.setAttribute ( "detail", kDetailLevelText[m_detailLevel] ); e.setAttribute ( "showrowtotals", m_showRowTotals ); } // // Text Filter // TQRegExp textfilter; if ( textFilter ( textfilter ) ) { TQDomElement f = doc->createElement ( "TEXT" ); f.setAttribute ( "pattern", textfilter.pattern() ); f.setAttribute ( "casesensitive", textfilter.caseSensitive() ); f.setAttribute ( "regex", !textfilter.wildcard() ); f.setAttribute ( "inverttext", m_invertText ); e.appendChild ( f ); } // // Type & State Filters // TQValueList typelist; if ( types ( typelist ) && ! typelist.empty() ) { // iterate over payees, and add each one TQValueList::const_iterator it_type = typelist.begin(); while ( it_type != typelist.end() ) { TQDomElement p = doc->createElement ( "TYPE" ); p.setAttribute ( "type", kTypeText[*it_type] ); e.appendChild ( p ); ++it_type; } } TQValueList statelist; if ( states ( statelist ) && ! statelist.empty() ) { // iterate over payees, and add each one TQValueList::const_iterator it_state = statelist.begin(); while ( it_state != statelist.end() ) { TQDomElement p = doc->createElement ( "STATE" ); p.setAttribute ( "state", kStateText[*it_state] ); e.appendChild ( p ); ++it_state; } } // // Number Filter // TQString nrFrom, nrTo; if ( numberFilter ( nrFrom, nrTo ) ) { TQDomElement f = doc->createElement ( "NUMBER" ); f.setAttribute ( "from", nrFrom ); f.setAttribute ( "to", nrTo ); e.appendChild ( f ); } // // Amount Filter // MyMoneyMoney from, to; if ( amountFilter ( from, to ) ) // bool getAmountFilter(MyMoneyMoney&,MyMoneyMoney&); { TQDomElement f = doc->createElement ( "AMOUNT" ); f.setAttribute ( "from", from.toString() ); f.setAttribute ( "to", to.toString() ); e.appendChild ( f ); } // // Payees Filter // TQStringList payeelist; if ( payees ( payeelist ) ) { if ( payeelist.empty() ) { TQDomElement p = doc->createElement ( "PAYEE" ); e.appendChild ( p ); } else { // iterate over payees, and add each one TQStringList::const_iterator it_payee = payeelist.begin(); while ( it_payee != payeelist.end() ) { TQDomElement p = doc->createElement ( "PAYEE" ); p.setAttribute ( "id", *it_payee ); e.appendChild ( p ); ++it_payee; } } } // // Account Groups Filter // TQValueList accountgrouplist; if ( accountGroups ( accountgrouplist ) ) { // iterate over accounts, and add each one TQValueList::const_iterator it_group = accountgrouplist.begin(); while ( it_group != accountgrouplist.end() ) { TQDomElement p = doc->createElement ( "ACCOUNTGROUP" ); p.setAttribute ( "group", kAccountTypeText[*it_group] ); e.appendChild ( p ); ++it_group; } } // // Accounts Filter // TQStringList accountlist; if ( accounts ( accountlist ) ) { // iterate over accounts, and add each one TQStringList::const_iterator it_account = accountlist.begin(); while ( it_account != accountlist.end() ) { TQDomElement p = doc->createElement ( "ACCOUNT" ); p.setAttribute ( "id", *it_account ); e.appendChild ( p ); ++it_account; } } // // Categories Filter // accountlist.clear(); if ( categories ( accountlist ) ) { // iterate over accounts, and add each one TQStringList::const_iterator it_account = accountlist.begin(); while ( it_account != accountlist.end() ) { TQDomElement p = doc->createElement ( "CATEGORY" ); p.setAttribute ( "id", *it_account ); e.appendChild ( p ); ++it_account; } } // // Date Filter // if ( m_dateLock == userDefined ) { TQDate dateFrom, dateTo; if ( dateFilter ( dateFrom, dateTo ) ) { TQDomElement f = doc->createElement ( "DATES" ); if ( dateFrom.isValid() ) f.setAttribute ( "from", dateFrom.toString ( TQt::ISODate ) ); if ( dateTo.isValid() ) f.setAttribute ( "to", dateTo.toString ( TQt::ISODate ) ); e.appendChild ( f ); } } } bool MyMoneyReport::read ( const TQDomElement& e ) { // The goal of this reading method is 100% backward AND 100% forward // compatability. Any report ever created with any version of KMyMoney // should be able to be loaded by this method (as long as it's one of the // report types supported in this version, of course) bool result = false; if ( "REPORT" == e.tagName() && ( ( e.attribute ( "type" ).find ( "pivottable 1." ) == 0 ) || ( e.attribute ( "type" ).find ( "querytable 1." ) == 0 ) || ( e.attribute ( "type" ).find ( "infotable 1." ) == 0 ) ) ) { result = true; clear(); int i; m_name = e.attribute ( "name" ); m_comment = e.attribute ( "comment", "Extremely old report" ); //set report type if(!e.attribute ( "type" ).find ( "pivottable" )) { m_reportType = MyMoneyReport::ePivotTable; } else if(!e.attribute ( "type" ).find ( "querytable" )) { m_reportType = MyMoneyReport::eQueryTable; } else if(!e.attribute ( "type" ).find ( "infotable" )) { m_reportType = MyMoneyReport::eInfoTable; } else { m_reportType = MyMoneyReport::eNoReport; } // Removed the line that screened out loading reports that are called // "Default Report". It's possible for the user to change the comment // to this, and we'd hate for it to break as a result. m_group = e.attribute ( "group" ); m_id = e.attribute ( "id" ); //check for reports with older settings which didn't have the detail attribute if ( e.hasAttribute ( "detail" ) ) { i = kDetailLevelText.findIndex ( e.attribute ( "detail", "all" ) ); if ( i != -1 ) m_detailLevel = static_cast ( i ); } else if ( e.attribute ( "showsubaccounts", "0" ).toUInt() ) { //set to show all accounts m_detailLevel = eDetailAll; } else { //set to show the top level account instead m_detailLevel = eDetailTop; } m_convertCurrency = e.attribute ( "convertcurrency", "1" ).toUInt(); m_favorite = e.attribute ( "favorite", "0" ).toUInt(); m_tax = e.attribute ( "tax", "0" ).toUInt(); m_investments = e.attribute ( "investments", "0" ).toUInt(); m_loans = e.attribute ( "loans", "0" ).toUInt(); m_includeSchedules = e.attribute ( "includeschedules", "0" ).toUInt(); m_columnsAreDays = e.attribute ( "columnsaredays", "0" ).toUInt(); m_includeTransfers = e.attribute ( "includestransfers", "0" ).toUInt(); if ( e.hasAttribute ( "budget" ) ) m_budgetId = e.attribute ( "budget" ); m_includeBudgetActuals = e.attribute ( "includesactuals", "0" ).toUInt(); m_includeUnusedAccounts = e.attribute ( "includeunused", "0" ).toUInt(); m_includeForecast = e.attribute ( "includesforecast", "0" ).toUInt(); m_includePrice = e.attribute ( "includesprice", "0" ).toUInt(); m_includeAveragePrice = e.attribute ( "includesaverageprice", "0" ).toUInt(); m_includeMovingAverage = e.attribute ( "includesmovingaverage", "0" ).toUInt(); if( m_includeMovingAverage ) m_movingAverageDays = e.attribute ( "movingaveragedays", "1" ).toUInt(); //only load chart data if it is a pivot table if ( m_reportType == ePivotTable ) { i = kChartTypeText.findIndex ( e.attribute ( "charttype" ) ); if ( i != -1 ) m_chartType = static_cast ( i ); //if it is invalid, set to first type if (m_chartType == eChartEnd) m_chartType = eChartLine; m_chartDataLabels = e.attribute ( "chartdatalabels", "1" ).toUInt(); m_chartGridLines = e.attribute ( "chartgridlines", "1" ).toUInt(); m_chartByDefault = e.attribute ( "chartbydefault", "0" ).toUInt(); m_chartLineWidth = e.attribute ( "chartlinewidth", "2" ).toUInt(); } else { m_chartType = static_cast ( 0 ); m_chartDataLabels = true; m_chartGridLines = true; m_chartByDefault = false; m_chartLineWidth = 1; } TQString datelockstr = e.attribute ( "datelock", "userdefined" ); // Handle the pivot 1.2/query 1.1 case where the values were saved as // numbers bool ok = false; i = datelockstr.toUInt ( &ok ); if ( !ok ) { i = kDateLockText.findIndex ( datelockstr ); if ( i == -1 ) i = userDefined; } setDateFilter ( static_cast ( i ) ); i = kRowTypeText.findIndex ( e.attribute ( "rowtype", "expenseincome" ) ); if ( i != -1 ) { setRowType ( static_cast ( i ) ); // recent versions of KMyMoney always showed a total column for // income/expense reports. We turn it on for backward compatability // here. If the total column is turned off, the flag will be reset // in the next step if ( i == eExpenseIncome ) m_showRowTotals = true; } if ( e.hasAttribute ( "showrowtotals" ) ) m_showRowTotals = e.attribute ( "showrowtotals" ).toUInt(); i = kColumnTypeText.findIndex ( e.attribute ( "columntype", "months" ) ); if ( i != -1 ) setColumnType ( static_cast ( i ) ); unsigned qc = 0; TQStringList columns = TQStringList::split ( ",", e.attribute ( "querycolumns", "none" ) ); TQStringList::const_iterator it_column = columns.begin(); while ( it_column != columns.end() ) { i = kQueryColumnsText.findIndex ( *it_column ); if ( i > 0 ) qc |= ( 1 << ( i - 1 ) ); ++it_column; } setQueryColumns ( static_cast ( qc ) ); TQDomNode child = e.firstChild(); while ( !child.isNull() && child.isElement() ) { TQDomElement c = child.toElement(); if ( "TEXT" == c.tagName() && c.hasAttribute ( "pattern" ) ) { setTextFilter ( TQRegExp ( c.attribute ( "pattern" ), c.attribute ( "casesensitive", "1" ).toUInt(), !c.attribute ( "regex", "1" ).toUInt() ), c.attribute ( "inverttext", "0" ).toUInt() ); } if ( "TYPE" == c.tagName() && c.hasAttribute ( "type" ) ) { i = kTypeText.findIndex ( c.attribute ( "type" ) ); if ( i != -1 ) addType ( i ); } if ( "STATE" == c.tagName() && c.hasAttribute ( "state" ) ) { i = kStateText.findIndex ( c.attribute ( "state" ) ); if ( i != -1 ) addState ( i ); } if ( "NUMBER" == c.tagName() ) { setNumberFilter ( c.attribute ( "from" ), c.attribute ( "to" ) ); } if ( "AMOUNT" == c.tagName() ) { setAmountFilter ( MyMoneyMoney ( c.attribute ( "from", "0/100" ) ), MyMoneyMoney ( c.attribute ( "to", "0/100" ) ) ); } if ( "DATES" == c.tagName() ) { TQDate from, to; if ( c.hasAttribute ( "from" ) ) from = TQDate::fromString ( c.attribute ( "from" ), TQt::ISODate ); if ( c.hasAttribute ( "to" ) ) to = TQDate::fromString ( c.attribute ( "to" ), TQt::ISODate ); MyMoneyTransactionFilter::setDateFilter ( from, to ); } if ( "PAYEE" == c.tagName() ) { addPayee ( c.attribute ( "id" ) ); } if ( "CATEGORY" == c.tagName() && c.hasAttribute ( "id" ) ) { addCategory ( c.attribute ( "id" ) ); } if ( "ACCOUNT" == c.tagName() && c.hasAttribute ( "id" ) ) { addAccount ( c.attribute ( "id" ) ); } if ( "ACCOUNTGROUP" == c.tagName() && c.hasAttribute ( "group" ) ) { i = kAccountTypeText.findIndex ( c.attribute ( "group" ) ); if ( i != -1 ) addAccountGroup ( static_cast ( i ) ); } child = child.nextSibling(); } } return result; } void MyMoneyReport::writeXML ( TQDomDocument& document, TQDomElement& parent ) const { TQDomElement el = document.createElement ( "REPORT" ); write ( el, &document, false ); parent.appendChild ( el ); } bool MyMoneyReport::hasReferenceTo ( const TQString& id ) const { TQStringList list; // collect all ids accounts ( list ); categories ( list ); payees ( list ); return ( list.contains ( id ) > 0 ); }