/*************************************************************************** mymoneygncreader - description ------------------- begin : Wed Mar 3 2004 copyright : (C) 2000-2004 by Michael Edwardes email : mte@users.sourceforge.net Javier Campos Morales Felix Rodriguez John C Thomas Baumgart Kevin Tambascio ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ /* The main class of this module, MyMoneyGncReader, contains only a readFile() function, which controls the import of data from an XML file created by the current GnuCash version (1.8.8). The XML is processed in class XmlReader, which is an implementation of the TQt SAX2 reader class. Data in the input file is processed as a set of objects which fortunately, though perhaps not surprisingly, have almost a one-for-one correspondence with KMyMoney objects. These objects are bounded by start and end XML elements, and may contain both nested objects (described as sub objects in the code), and data items, also delimited by start and end elements. For example: * start of sub object within file Account Name * data string with start and end elements ... * end of sub objects A GnuCash file may consist of more than one 'book', or set of data. It is not clear how we could currently implement this, so only the first book in a file is processed. This should satisfy most user situations. GnuCash is somewhat inconsistent in its division of the major sections of the file. For example, multiple price history entries are delimited by elements, while each account starts with its own top-level element. In general, the 'container' elements are ignored. XmlReader This is an implementation of the TQt TQXmlDefaultHandler class, which provides three main function calls in addition to start and end of document. The startElement() and endElement() calls are self-explanatory, the characters() function provides data strings. Thus in the above example, the sequence of calls would be startElement() for gnc:account startElement() for act:name characters() for 'Account Name' endElement() for act:name ... endElement() for gnc:account Objects Since the processing requirements of XML for most elements are very similar, the common code is implemented in a GncObject class, from which the others are derived, with virtual function calls to cater for any differences. The 'grandfather' object, GncFile representing the file (or more correctly, 'book') as a whole, is created in the startDocument() function call. The constructor function of each object is responsible for providing two lists for the XmlReader to scan, a list of element names which represent sub objects (called sub elements in the code), and a similar list of names representing data elements. In addition, an array of variables (m_v) is provided and initialized, to contain the actual data strings. Implementation Since objects may be nested, a stack is used, with the top element pointing to the 'current object'. The startDocument() call creates the first, GncFile, object at the top of the stack. As each startElement() call occurs, the two element lists created by the current object are scanned. If this element represents the start of a sub object, the current object's subEl() function is called to create an instance of the appropriate type. This is then pushed to the top of the stack, and the new object's initiate() function is called. This is used to process any XML attributes attached to the element; GnuCash makes little use of these. If this represents the start of a data element, a pointer (m_dataPointer) is set to point to an entry in the array (m_v) in which a subsequent characters() call can store the actual data. When an endElement() call occurs, a check is made to see if it matches the element name which started the current object. If so, the object's terminate() function is called. If the object represents a similar KMM object, this will normally result in a call to a conversion routine in the main (MyMoneyGncReader) class to convert the data to native format and place it in storage. The stack is then popped, and the parent (now current) object notified by a call to its endSubEl() function. Again depending on the type of object, this will either delete the instance, or save it in its own storage for later processing. For example, a GncSplit object makes little sense outside the context of its transaction, so will be saved by the transaction. A GncTransaction object on the other hand will be converted, along with its attendant splits, and then deleted by its parent. Since at any one time an object will only be processing either a subobject or a data element, a single object variable, m_state, is used to determine the actual type. In effect, it acts as the current index into either the subElement or dataElement list. As an object variable, it will be saved on the stack across subobject processing. Exceptions and Problems Fatal exceptions are processed via the standard MyMoneyException method. Due to differences in implementation between GnuCash and KMM, it is not always possible to provide an absolutely correct conversion. When such a problem situation is recognized, a message, along with any relevant variable data, is passed to the main class, and used to produce a report when processing terminates. The GncMessages and GncMessageArg classes implement this. Anonymizer When debugging problems, it is often useful to have a trace of what is happening within the module. However, in view of the sensitive nature of personal finance data, most users will be reluctant to provide this. Accordingly, an anonymize (hide()) function is provided to handle data strings. These may either be passed through asis (non-personal data), blanked out (non-critical but possibly personal data), replaced with a generated version (required, but possibly personal), or randomized (monetary amounts). The action for each data item is determined in the object's constructor function along with the creation of the data element list. This module will later be used as the basis of a file anonymizer, which will enable users to safely provide us with a copy of their GnuCash files, and will allow us to test the structure, if not the data content, of the file. */ #ifndef MYMONEYSTORAGEGNC_H #define MYMONEYSTORAGEGNC_H // Some STL headers in GCC4.3 contain operator new. Memory checker mangles these #ifdef _CHECK_MEMORY #undef new #endif // system includes #include // ---------------------------------------------------------------------------- // TQt Includes #include class TQIODevice; #include #include #include #include #include #include #include // ---------------------------------------------------------------------------- // Project Includes #ifdef _CHECK_MEMORY #include #endif #ifndef _GNCFILEANON #include "../mymoney/storage/imymoneyserialize.h" // not used any more, but call interface requires it #include "../mymoney/storage/imymoneystorageformat.h" #endif // _GNCFILEANON // not sure what these are for, but leave them in #define VERSION_0_60_XML 0x10000010 // Version 0.5 file version info #define VERSION_0_61_XML 0x10000011 // use 8 bytes for MyMoneyMoney objects #define GNUCASH_ID_KEY "GNUCASH_ID" typedef TQMap map_accountIds; typedef map_accountIds::iterator map_accountIds_iter; typedef map_accountIds::const_iterator map_accountIds_citer; typedef TQMap map_elementVersions; class MyMoneyGncReader; /** GncObject is the base class for the various objects in the gnucash file Beyond the first level XML objects, elements will be of one of three types: 1. Sub object elements, which require creation of another object to process 2. Data object elements, which are only followed by data to be stored in a variable (m_v array) 3. Ignored objects, data not needed and not included herein */ class GncObject { public: GncObject(); ; // to save delete loop when finished virtual ~GncObject() {} // make sure to have impl of all virtual rtns to avoid vtable errors? protected: friend class XmlReader; friend class MyMoneyGncReader; // check for sub object element; if it is, create the object GncObject *isSubElement (const TQString &elName, const TQXmlAttributes& elAttrs); // check for data element; if so, set data pointer bool isDataElement (const TQString &elName, const TQXmlAttributes& elAttrs); // process start element for 'this'; normally for attribute checking; other initialization done in constructor virtual void initiate (const TQString&, const TQXmlAttributes&) { return ;}; // a sub object has completed; process the data it gathered virtual void endSubEl(GncObject *) {m_dataPtr = 0; return ;}; // store data for data element void storeData (const TQString& pData) // NB - data MAY come in chunks, and may need to be anonymized {if (m_dataPtr != 0) m_dataPtr->append (hide (pData, m_anonClass)); return ;} // following is provided only for a future file anonymizer TQString getData () const { return ((m_dataPtr != 0) ? *m_dataPtr : "");}; void resetDataPtr() {m_dataPtr = 0;}; // process end element for 'this'; usually to convert to KMM format virtual void terminate() { return ;}; void setVersion (const TQString& v) {m_version = v; return; }; TQString version() const {return (m_version);}; // some gnucash elements have version attribute; check it void checkVersion (const TQString&, const TQXmlAttributes&, const map_elementVersions&); // get name of element processed by 'this' TQString getElName () const { return (m_elementName);}; // pass 'main' pointer to object void setPm (MyMoneyGncReader *pM) {pMain = pM;}; // debug only void debugDump(); // called by isSubElement to create appropriate sub object virtual GncObject *startSubEl() { return (0);}; // called by isDataElement to set variable pointer virtual void dataEl(const TQXmlAttributes&) {m_dataPtr = m_v.at(m_state); m_anonClass = m_anonClassList[m_state];}; // return gnucash data string variable pointer virtual TQString var (int i) const; // anonymize data virtual TQString hide (TQString, unsigned int); MyMoneyGncReader *pMain; // pointer to 'main' class // used at start of each transaction so same money hide factor is applied to all splits void adjustHideFactor(); TQString m_elementName; // save 'this' element's name TQString m_version; // and it's gnucash version const TQString *m_subElementList; // list of sub object element names for 'this' unsigned int m_subElementListCount; // count of above const TQString *m_dataElementList; // ditto for data elements unsigned int m_dataElementListCount; TQString *m_dataPtr; // pointer to m_v variable for current data item mutable TQPtrList m_v; // storage for variable pointers unsigned int m_state; // effectively, the index to subElementList or dataElementList, whichever is currently in use const unsigned int *m_anonClassList; enum anonActions {ASIS, SUPPRESS, NXTACC, NXTEQU, NXTPAY, NXTSCHD, MAYBEQ, MONEY1, MONEY2}; // anonymize actions - see hide() unsigned int m_anonClass; // class of current data item for anonymizer static double m_moneyHideFactor; // a per-transaction factor }; // ***************************************************************************** // This is the 'grandfather' object representing the gnucash file as a whole class GncFile : public GncObject { public: GncFile (); ~GncFile(); private: enum iSubEls {BOOK, COUNT, CMDTY, PRICE, ACCT, TX, TEMPLATES, SCHEDULES, END_FILE_SELS }; virtual GncObject *startSubEl(); virtual void endSubEl(GncObject *); bool m_processingTemplates; // gnc uses same transaction element for ordinary and template tx's; this will distinguish bool m_bookFound; // to detect multi-book files }; // The following are 'utility' objects, which occur within several other object types // **************************************************************************** // commodity specification. consists of // cmdty:space - either ISO4217 if this cmdty is a currency, or, usually, the name of a stock exchange // cmdty:id - ISO4217 currency symbol, or 'ticker symbol' class GncCmdtySpec : public GncObject { public: GncCmdtySpec (); ~GncCmdtySpec (); protected: friend class MyMoneyGncReader; friend class GncTransaction; bool isCurrency() const { return (*m_v.at(CMDTYSPC) == TQString("ISO4217"));}; TQString id() const { return (*m_v.at(CMDTYID));}; TQString space() const { return (*m_v.at(CMDTYSPC));}; private: // data elements enum CmdtySpecDataEls {CMDTYSPC, CMDTYID, END_CmdtySpec_DELS}; virtual TQString hide (TQString, unsigned int); }; // ********************************************************************* // date; maybe one of two types, ts:date which is date/time, gdate which is date only // we do not preserve time data (at present) class GncDate : public GncObject { public: GncDate (); ~GncDate(); protected: friend class MyMoneyGncReader; friend class GncPrice; friend class GncTransaction; friend class GncSplit; friend class GncSchedule; friend class GncRecurrence; const TQDate date() const { return (TQDate::fromString(m_v.at(TSDATE)->section(' ', 0, 0), TQt::ISODate));}; private: // data elements enum DateDataEls {TSDATE, GDATE, END_Date_DELS}; virtual void dataEl(const TQXmlAttributes&) {m_dataPtr = m_v.at(TSDATE); m_anonClass = GncObject::ASIS;} ; // treat both date types the same }; // ************* GncKvp******************************************** // Key/value pairs, which are introduced by the 'slot' element // Consist of slot:key (the 'name' of the kvp), and slot:value (the data value) // the slot value also contains a slot type (string, integer, etc) implemented as an XML attribute // kvp's may be nested class GncKvp : public GncObject { public: GncKvp (); ~GncKvp(); protected: friend class MyMoneyGncReader; TQString key() const { return (var(KEY));}; TQString value() const { return (var(VALUE));}; TQString type() const { return (m_kvpType);}; unsigned int kvpCount() const { return (m_kvpList.count());}; const GncKvp *getKvp(unsigned int i) const { return (static_cast(m_kvpList.at(i)));}; private: // subsidiary objects/elements enum KvpSubEls {KVP, END_Kvp_SELS }; virtual GncObject *startSubEl(); virtual void endSubEl(GncObject *); // data elements enum KvpDataEls {KEY, VALUE, END_Kvp_DELS }; virtual void dataEl (const TQXmlAttributes&); mutable TQPtrList m_kvpList; TQString m_kvpType; // type is an XML attribute }; // ************* GncLot******************************************** // KMM doesn't have support for lots as yet class GncLot : public GncObject { public: GncLot (); ~GncLot(); protected: friend class MyMoneyGncReader; private: }; /** Following are the main objects within the gnucash file, which correspond largely one-for-one with similar objects in the kmymoney structure, apart from schedules which gnc splits between template (transaction data) and schedule (date data) */ //******************************************************************** class GncCountData : public GncObject { public: GncCountData (); ~GncCountData (); private: virtual void initiate (const TQString&, const TQXmlAttributes&); virtual void terminate(); TQString m_countType; // type of element being counted }; //******************************************************************** class GncCommodity : public GncObject { public: GncCommodity (); ~GncCommodity(); protected: friend class MyMoneyGncReader; // access data values bool isCurrency() const { return (var(SPACE) == TQString("ISO4217"));}; TQString space() const { return (var(SPACE));}; TQString id() const { return (var(ID));}; TQString name() const { return (var(NAME));}; TQString fraction() const { return (var(FRACTION));}; private: virtual void terminate(); // data elements enum {SPACE, ID, NAME, FRACTION, END_Commodity_DELS}; }; // ************* GncPrice******************************************** class GncPrice : public GncObject { public: GncPrice (); ~GncPrice(); protected: friend class MyMoneyGncReader; // access data values const GncCmdtySpec *commodity() const { return (m_vpCommodity);}; const GncCmdtySpec *currency() const { return (m_vpCurrency);}; TQString value() const { return (var(VALUE));}; TQDate priceDate () const { return (m_vpPriceDate->date());}; private: virtual void terminate(); // sub object elements enum PriceSubEls {CMDTY, CURR, PRICEDATE, END_Price_SELS }; virtual GncObject *startSubEl(); virtual void endSubEl(GncObject *); // data elements enum PriceDataEls {VALUE, END_Price_DELS }; GncCmdtySpec *m_vpCommodity, *m_vpCurrency; GncDate *m_vpPriceDate; }; // ************* GncAccount******************************************** class GncAccount : public GncObject { public: GncAccount (); ~GncAccount(); protected: friend class MyMoneyGncReader; // access data values GncCmdtySpec *commodity() const { return (m_vpCommodity);}; TQString id () const { return (var(ID));}; TQString name () const { return (var(NAME));}; TQString desc () const { return (var(DESC));}; TQString type () const { return (var(TYPE));}; TQString parent () const { return (var(PARENT));}; private: // subsidiary objects/elements enum AccountSubEls {CMDTY, KVP, LOTS, END_Account_SELS }; virtual GncObject *startSubEl(); virtual void endSubEl(GncObject *); virtual void terminate(); // data elements enum AccountDataEls {ID, NAME, DESC, TYPE, PARENT, END_Account_DELS }; GncCmdtySpec *m_vpCommodity; TQPtrList m_kvpList; }; // ************* GncSplit******************************************** class GncSplit : public GncObject { public: GncSplit (); ~GncSplit(); protected: friend class MyMoneyGncReader; // access data values TQString id() const { return (var(ID));}; TQString memo() const { return (var(MEMO));}; TQString recon() const { return (var(RECON));}; TQString value() const { return (var(VALUE));}; TQString qty() const { return (var(TQTY));}; TQString acct() const { return (var(ACCT));}; const TQDate reconDate() const {TQDate x = TQDate(); return (m_vpDateReconciled == NULL ? x : m_vpDateReconciled->date());}; private: // subsidiary objects/elements enum TransactionSubEls {RECDATE, END_Split_SELS }; virtual GncObject *startSubEl(); virtual void endSubEl(GncObject *); // data elements enum SplitDataEls {ID, MEMO, RECON, VALUE, TQTY, ACCT, END_Split_DELS }; GncDate *m_vpDateReconciled; }; // ************* GncTransaction******************************************** class GncTransaction : public GncObject { public: GncTransaction (bool processingTemplates); ~GncTransaction(); protected: friend class MyMoneyGncReader; // access data values TQString id() const { return (var(ID));}; TQString no() const { return (var(NO));}; TQString desc() const { return (var(DESC));}; TQString currency() const { return (m_vpCurrency == NULL ? TQString () : m_vpCurrency->id());}; TQDate dateEntered() const { return (m_vpDateEntered->date());}; TQDate datePosted() const { return (m_vpDatePosted->date());}; bool isTemplate() const { return (m_template);}; unsigned int splitCount() const { return (m_splitList.count());}; unsigned int kvpCount() const { return (m_kvpList.count());}; const GncObject *getSplit (unsigned int i) const { return (m_splitList.at(i));}; const GncKvp *getKvp(unsigned int i) const { return (static_cast(m_kvpList.at(i)));}; private: // subsidiary objects/elements enum TransactionSubEls {CURRCY, POSTED, ENTERED, SPLIT, KVP, END_Transaction_SELS }; virtual GncObject *startSubEl(); virtual void endSubEl(GncObject *); virtual void terminate(); // data elements enum TransactionDataEls {ID, NO, DESC, END_Transaction_DELS }; GncCmdtySpec *m_vpCurrency; GncDate *m_vpDateEntered, *m_vpDatePosted; mutable TQPtrList m_splitList; bool m_template; // true if this is a template for scheduled transaction mutable TQPtrList m_kvpList; }; // ************* GncTemplateSplit******************************************** class GncTemplateSplit : public GncObject { public: GncTemplateSplit (); ~GncTemplateSplit(); protected: friend class MyMoneyGncReader; // access data values TQString id() const { return (var(ID));}; TQString memo() const { return (var(MEMO));}; TQString recon() const { return (var(RECON));}; TQString value() const { return (var(VALUE));}; TQString qty() const { return (var(TQTY));}; TQString acct() const { return (var(ACCT));}; unsigned int kvpCount() const { return (m_kvpList.count());}; const GncKvp *getKvp(unsigned int i) const { return (static_cast(m_kvpList.at(i)));}; private: // subsidiary objects/elements enum TemplateSplitSubEls {KVP, END_TemplateSplit_SELS }; virtual GncObject *startSubEl(); virtual void endSubEl(GncObject *); // data elements enum TemplateSplitDataEls {ID, MEMO, RECON, VALUE, TQTY, ACCT, END_TemplateSplit_DELS }; mutable TQPtrList m_kvpList; }; // ************* GncSchedule******************************************** class GncFreqSpec; class GncRecurrence; class GncSchedDef; class GncSchedule : public GncObject { public: GncSchedule (); ~GncSchedule(); protected: friend class MyMoneyGncReader; // access data values TQString name() const { return (var(NAME));}; TQString enabled() const {return var(ENABLED);}; TQString autoCreate() const { return (var(AUTOC));}; TQString autoCrNotify() const { return (var(AUTOCN));}; TQString autoCrDays() const { return (var(AUTOCD));}; TQString advCrDays() const { return (var(ADVCD));}; TQString advCrRemindDays() const { return (var(ADVRD));}; TQString instanceCount() const { return (var(INSTC));}; TQString numOccurs() const { return (var(NUMOCC));}; TQString remOccurs() const { return (var(REMOCC));}; TQString templId() const { return (var(TEMPLID));}; TQDate startDate () const {TQDate x = TQDate(); return (m_vpStartDate == NULL ? x : m_vpStartDate->date());}; TQDate lastDate () const {TQDate x = TQDate(); return (m_vpLastDate == NULL ? x : m_vpLastDate->date());}; TQDate endDate() const {TQDate x = TQDate(); return (m_vpEndDate == NULL ? x : m_vpEndDate->date());}; const GncFreqSpec *getFreqSpec() const { return (m_vpFreqSpec);}; const GncSchedDef *getSchedDef() const { return (m_vpSchedDef);}; private: // subsidiary objects/elements enum ScheduleSubEls {STARTDATE, LASTDATE, ENDDATE, FREQ, RECURRENCE, DEFINST, END_Schedule_SELS }; virtual GncObject *startSubEl(); virtual void endSubEl(GncObject *); virtual void terminate(); // data elements enum ScheduleDataEls {NAME, ENABLED, AUTOC, AUTOCN, AUTOCD, ADVCD, ADVRD, INSTC, NUMOCC, REMOCC, TEMPLID, END_Schedule_DELS }; GncDate *m_vpStartDate, *m_vpLastDate, *m_vpEndDate; GncFreqSpec *m_vpFreqSpec; mutable TQPtrList m_vpRecurrence; // gnc handles multiple occurrences GncSchedDef *m_vpSchedDef; }; // ************* GncFreqSpec******************************************** class GncFreqSpec : public GncObject { public: GncFreqSpec (); ~GncFreqSpec(); protected: friend class MyMoneyGncReader; // access data values (only interval type used at present) TQString intervalType() const { return (var(INTVT));}; private: // subsidiary objects/elements enum FreqSpecSubEls {COMPO, END_FreqSpec_SELS }; virtual GncObject *startSubEl(); virtual void endSubEl(GncObject *); // data elements enum FreqSpecDataEls {INTVT, MONTHLY, DAILY, WEEKLY, INTVI, INTVO, INTVD, END_FreqSpec_DELS}; virtual void terminate(); mutable TQPtrList m_fsList; }; // ************* GncRecurrence******************************************** // this object replaces GncFreqSpec from Gnucash 2.2 onwards class GncRecurrence : public GncObject { public: GncRecurrence (); ~GncRecurrence(); protected: friend class MyMoneyGncReader; // access data values TQDate startDate () const {TQDate x = TQDate(); return (m_vpStartDate == NULL ? x : m_vpStartDate->date());}; TQString mult() const {return (var(MULT));}; TQString periodType() const {return (var(PERIODTYPE));}; TQString getFrequency() const; private: // subsidiary objects/elements enum RecurrenceSubEls {STARTDATE, END_Recurrence_SELS }; virtual GncObject *startSubEl(); virtual void endSubEl(GncObject *); // data elements enum RecurrenceDataEls {MULT, PERIODTYPE, END_Recurrence_DELS}; virtual void terminate(); GncDate *m_vpStartDate; }; // ************* GncSchedDef******************************************** // This is a sub-object of GncSchedule, (sx:deferredInstance) function currently unknown class GncSchedDef : public GncObject { public: GncSchedDef (); ~GncSchedDef(); protected: friend class MyMoneyGncReader; private: // subsidiary objects/elements }; // **************************************************************************************** /** XML Reader The XML reader is an implementation of the TQt SAX2 XML parser. It determines the type of object represented by the XMl, and calls the appropriate object functions */ // ***************************************************************************************** class XmlReader : public TQXmlDefaultHandler { protected: friend class MyMoneyGncReader; XmlReader (MyMoneyGncReader *pM) : pMain(pM) {} // keep pointer to 'main' void processFile (TQIODevice*); // main entry point of reader // define xml content handler functions bool startDocument (); bool startElement (const TQString&, const TQString&, const TQString&, const TQXmlAttributes&); bool endElement (const TQString&, const TQString&, const TQString&); bool characters (const TQString &); bool endDocument(); private: TQXmlInputSource *m_source; TQXmlSimpleReader *m_reader; TQPtrStack m_os; // stack of sub objects GncObject *m_co; // current object, for ease of coding (=== m_os.top) MyMoneyGncReader *pMain; // the 'main' pointer, to pass on to objects bool m_headerFound; // check for gnc-v2 header #ifdef _GNCFILEANON int lastType; // 0 = start element, 1 = data, 2 = end element int indentCount; #endif // _GNCFILEANON }; /** * private classes to define messages to be held in list for final report */ class GncMessageArgs { protected: friend class MyMoneyGncReader; TQString source; // 'type of message unsigned int code; // to identify actual message TQValueList args; // variable arguments }; class GncMessages { protected: friend class MyMoneyGncReader; static TQString text (const TQString, const unsigned int); // returns text of identified message static unsigned int argCount (const TQString, const unsigned int); // returns no. of args required private: typedef struct { const TQString source; const unsigned int code; TQString text; } messText; static messText texts []; }; /** MyMoneyGncReader - Main class for this module Controls overall operation of the importer */ #ifndef _GNCFILEANON class MyMoneyGncReader : public IMyMoneyStorageFormat { #else class MyMoneyGncReader { #endif // _GNCFILEANON public: MyMoneyGncReader(); virtual ~MyMoneyGncReader(); /** * Import a GnuCash XML file * * @param pDevice : pointer to GnuCash file * @param storage : pointer to MyMoneySerialize storage * * @return void * */ #ifndef _GNCFILEANON void readFile (TQIODevice* pDevice, IMyMoneySerialize* storage); // main entry point, IODevice is gnucash file void writeFile (TQIODevice*, IMyMoneySerialize*) { return ;}; // dummy entry needed by kmymoneywiew. we will not be writing #else void readFile (TQString, TQString); #endif // _GNCFILEANON TQTextCodec *m_decoder; protected: friend class GncObject; // pity we can't just say GncObject. And compiler doesn't like multiple friends on one line... friend class GncFile; // there must be a better way... friend class GncDate; friend class GncCmdtySpec; friend class GncKvp; friend class GncLot; friend class GncCountData; friend class GncCommodity; friend class GncPrice; friend class GncAccount; friend class GncTransaction; friend class GncSplit; friend class GncTemplateTransaction; friend class GncTemplateSplit; friend class GncSchedule; friend class GncFreqSpec; friend class GncRecurrence; friend class XmlReader; #ifndef _GNCFILEANON /** functions to convert gnc objects to our equivalent */ void convertCommodity (const GncCommodity *); void convertPrice (const GncPrice *); void convertAccount (const GncAccount *); void convertTransaction (const GncTransaction *); void convertSplit (const GncSplit *); void saveTemplateTransaction (GncTransaction *t) {m_templateList.append (t);}; void convertSchedule (const GncSchedule *); void convertFreqSpec (const GncFreqSpec *); void convertRecurrence (const GncRecurrence *); #else /** functions to convert gnc objects to our equivalent */ void convertCommodity (const GncCommodity *) {return;}; void convertPrice (const GncPrice *) {return;}; void convertAccount (const GncAccount *) {return;}; void convertTransaction (const GncTransaction *) {return;}; void convertSplit (const GncSplit *) {return;}; void saveTemplateTransaction (GncTransaction *t) {return;}; void convertSchedule (const GncSchedule *) {return;}; void convertFreqSpec (const GncFreqSpec *) {return;}; #endif // _GNCFILEANON /** to post messages for final report */ void postMessage (const TQString&, const unsigned int, const char *); void postMessage (const TQString&, const unsigned int, const char *, const char *); void postMessage (const TQString&, const unsigned int, const char *, const char *, const char *); void postMessage (const TQString&, const unsigned int, const TQStringList&); void setProgressCallback (void(*callback)(int, int, const TQString&)); void signalProgress (int current, int total, const TQString& = ""); /** user options */ /** Scheduled Transactions Due to differences in implementation, it is not always possible to import scheduled transactions correctly. Though best efforts are made, it may be that some imported transactions cause problems within kmymoney. An attempt is made within the importer to identify potential problem transactions, and setting this option will cause them to be dropped from the file. A report of which were dropped, and why, will be produced. m_dropSuspectSchedules - drop suspect scheduled transactions */ bool m_dropSuspectSchedules; /** Investments In kmymoney, all accounts representing investments (stocks, shares, bonds, etc.) must have an associated investment account (e.g. a broker account). The stock account holds the share balance, the investment account a money balance. Gnucash does not do this, so we cannot automate this function. If you have investments, you must select one of the following options. 0 - create a separate investment account for each stock with the same name as the stock 1 - create a single investment account to hold all stocks - you will be asked for a name 2 - create multiple investment accounts - you will be asked for a name for each stock N.B. :- option 2 doesn't really work quite as desired at present */ unsigned int m_investmentOption; /** Online quotes The user has the option to use the Finance::Quote system, as used by GnuCash, to retrieve online share price quotes */ bool m_useFinanceQuote; /** Tx Notes handling Under some usage conditions, non-split GnuCash transactions may contain residual, usually incorrect, memo data which is not normally visible to the user. When imported into KMyMoney however, due to display differences, this data can become visible. Often, these transactions will have a Notes field describing the real purpose of the transaction. If this option is selected, these notes, if present, will be used to override the extraneous memo data." */ bool m_useTxNotes; // set gnucash counts (not always accurate!) void setGncCommodityCount(int i) { m_gncCommodityCount = i;}; void setGncAccountCount (int i) { m_gncAccountCount = i;}; void setGncTransactionCount (int i) { m_gncTransactionCount = i;}; void setGncScheduleCount (int i) { m_gncScheduleCount = i;}; void setSmallBusinessFound (bool b) { m_smallBusinessFound = b;}; void setBudgetsFound (bool b) { m_budgetsFound = b;}; void setLotsFound (bool b) { m_lotsFound = b;}; /* Debug Options If you don't know what these are, best leave them alone. gncdebug - produce general debug messages xmldebug - produce a trace of the gnucash file XML bAnonymize - hide personal data (account names, payees, etc., randomize money amounts) */ bool gncdebug; // general debug messages bool xmldebug; // xml trace bool bAnonymize; // anonymize input static double m_fileHideFactor; // an overall anonymization factor to be applied to all items bool developerDebug; private: void setOptions (); // to set user options from dialog void setFileHideFactor (); // the following handles the gnucash indicator for a bad value (-1/0) which causes us probs TQString convBadValue (TQString gncValue) const {return (gncValue == "-1/0" ? "0/1" : gncValue); }; #ifndef _GNCFILEANON MyMoneyTransaction convertTemplateTransaction (const TQString&, const GncTransaction *); void convertTemplateSplit (const TQString&, const GncTemplateSplit *); #endif // _GNCFILEANON // wind up when all done void terminate(); TQString buildReportSection (const TQString&); bool writeReportToFile (const TQValueList&); // main storage #ifndef _GNCFILEANON IMyMoneyStorage *m_storage; #else TQTextStream oStream; #endif // _GNCFILEANON XmlReader *m_xr; /** to hold the callback pointer for the progress bar */ void (*m_progressCallback)(int, int, const TQString&); // a map of which versions of the various elements (objects) we can import map_elementVersions m_versionList; // counters holding count data from the Gnc 'count-data' section int m_gncCommodityCount; int m_gncAccountCount; int m_gncTransactionCount; int m_gncScheduleCount; // flags indicating detection of features not (yet?) supported bool m_smallBusinessFound; bool m_budgetsFound; bool m_lotsFound; /** counters for reporting */ int m_commodityCount; int m_priceCount; int m_accountCount; int m_transactionCount; int m_templateCount; int m_scheduleCount; #ifndef _GNCFILEANON // counters for error reporting int m_ccCount, m_orCount, m_scCount; // currency counter TQMap m_currencyCount; /** * Map gnucash vs. Kmm ids for accounts, equities, schedules, price sources */ TQMap m_mapIds; TQString m_rootId; // save the root id for terminate() TQMap m_mapEquities; TQMap m_mapSchedules; TQMap m_mapSources; /** * A list of stock accounts (gnc ids) which will be held till the end so we can implement the user's investment option */ TQValueList m_stockList; /** * Temporary storage areas for transaction processing */ TQString m_txCommodity; // save commodity for current transaction TQString m_txPayeeId; // gnc has payee at tx level, we need it at split level TQDate m_txDatePosted; // ditto for post date TQString m_txChequeNo; // ditto for cheque number /** In kmm, the order of splits is critical to some operations. These * areas will hold the splits until we've read them all */ TQValueList m_splitList, m_liabilitySplitList, m_otherSplitList; bool m_potentialTransfer; // to determine whether this might be a transfer /** Schedules are processed through 3 different functions, any of which may set this flag */ bool m_suspectSchedule; /** * A holding area for template txs while we're waiting for the schedules */ TQPtrList m_templateList; /** Hold a list of suspect schedule ids for later processing? */ TQValueList m_suspectList; /** * To hold message data till final report */ TQPtrList m_messageList; GncMessages *m_messageTexts; /** * Internal utility functions */ TQString createPayee (const TQString&); // create a payee and return it's id TQString createOrphanAccount (const TQString&); // create unknown account and return the id TQDate incrDate (TQDate lastDate, unsigned char interval, unsigned int intervalCount); // for date calculations MyMoneyAccount checkConsistency (MyMoneyAccount& parent, MyMoneyAccount& child); // gnucash is sometimes TOO flexible void checkInvestmentOption (TQString stockId); // implement user investment option void getPriceSource (MyMoneySecurity stock, TQString gncSource); #endif // _GNCFILEANON }; #endif // MYMONEYSTORAGEGNC_H