1 /*************************************************************************** 2 mymoneyqifreader.h - description 3 ------------------- 4 begin : Mon Jan 27 2003 5 copyright : (C) 2000-2003 by Michael Edwardes 6 email : mte@users.sourceforge.net 7 Javier Campos Morales <javi_c@users.sourceforge.net> 8 Felix Rodriguez <frodriguez@users.sourceforge.net> 9 John C <thetacoturtle@users.sourceforge.net> 10 Thomas Baumgart <ipwizard@users.sourceforge.net> 11 Kevin Tambascio <ktambascio@users.sourceforge.net> 12 ***************************************************************************/ 13 14 /*************************************************************************** 15 * * 16 * This program is free software; you can redistribute it and/or modify * 17 * it under the terms of the GNU General Public License as published by * 18 * the Free Software Foundation; either version 2 of the License, or * 19 * (at your option) any later version. * 20 * * 21 ***************************************************************************/ 22 23 #ifndef MYMONEYQIFREADER_H 24 #define MYMONEYQIFREADER_H 25 26 // ---------------------------------------------------------------------------- 27 // QT Headers 28 29 #include <QList> 30 #include <QObject> 31 #include <QString> 32 #include <QStringList> 33 #include <QByteArray> 34 #include <QUrl> 35 #include <QFile> 36 #include <QProcess> 37 38 // ---------------------------------------------------------------------------- 39 // KDE Headers 40 41 // ---------------------------------------------------------------------------- 42 // Project Headers 43 44 #include "mymoneyaccount.h" 45 #include "mymoneytransaction.h" 46 #include "mymoneyenums.h" 47 #include "../config/mymoneyqifprofile.h" 48 49 class MyMoneyFileTransaction; 50 class MyMoneyStatement; 51 class MyMoneyQifProfile; 52 53 /** 54 * @author Thomas Baumgart 55 */ 56 class MyMoneyQifReader : public QObject 57 { 58 Q_OBJECT 59 friend class Private; 60 61 private: 62 typedef enum { 63 EntryUnknown = 0, 64 EntryAccount, 65 EntryTransaction, 66 EntryCategory, 67 EntryMemorizedTransaction, 68 EntryInvestmentTransaction, 69 EntrySecurity, 70 EntryPrice, 71 EntryPayee, 72 EntryClass, 73 EntrySkip 74 } QifEntryTypeE; 75 76 struct qSplit { 77 QString m_strCategoryName; 78 QString m_strMemo; 79 QString m_amount; 80 }; 81 82 public: 83 MyMoneyQifReader(); 84 ~MyMoneyQifReader(); 85 86 /** 87 * This method is used to store the filename into the object. 88 * The file should exist. If it does and an external filter 89 * program is specified with the current selected profile, 90 * the file is send through this filter and the result 91 * is stored in the m_tempFile file. 92 * 93 * @param url URL of the file to be imported 94 */ 95 void setURL(const QUrl &url); 96 97 /** 98 * This method is used to store the name of the profile into the object. 99 * The selected profile will be loaded if it exists. If an external 100 * filter program is specified with the current selected profile, 101 * the file is send through this filter and the result 102 * is stored in the m_tempFile file. 103 * 104 * @param name QString reference to the name of the profile 105 */ 106 void setProfile(const QString& name); 107 108 /** 109 * This method actually starts the import of data from the selected file 110 * into the MyMoney engine. 111 * 112 * This method also starts the user defined import filter program 113 * defined in the QIF profile. If none is defined, the file is read 114 * as is (actually the UNIX command 'cat -' is used as the filter). 115 * 116 * If data from the filter program is available, the slot 117 * slotReceivedDataFromFilter() will be called. 118 * 119 * Make sure to connect the signal importFinished() to detect when 120 * the import actually ended. Call the method finishImport() to clean 121 * things up and get the overall result of the import. 122 * 123 * @retval true the import was started successfully 124 * @retval false the import could not be started. 125 */ 126 bool startImport(); 127 128 void setCategoryMapping(bool map); 129 account()130 inline const MyMoneyAccount& account() const { 131 return m_account; 132 }; 133 134 int statementCount() const; 135 136 void setProgressCallback(void(*callback)(qint64, qint64, const QString&)); 137 138 private: 139 /** 140 * This method is used to update the progress information. It 141 * checks if an appropriate function is known and calls it. 142 * 143 * For a parameter description see KMyMoneyView::progressCallback(). 144 */ 145 void signalProgress(qint64 current, qint64 total, const QString& = ""); 146 147 /** 148 * This method scans a transaction contained in 149 * a QIF file formatted as an account record. This 150 * format is used by MS-Money. If the specific data 151 * is not found, then the data in the entry is treated 152 * as a transaction. In this case, the user will be asked to 153 * specify the account to which the transactions should be imported. 154 * The entry data is found in m_qifEntry. 155 * 156 * @param accountType see MyMoneyAccount() for details. Defaults to eMyMoney::Account::Type::Checkings 157 */ 158 void processMSAccountEntry(const eMyMoney::Account::Type accountType = eMyMoney::Account::Type::Checkings); 159 160 /** 161 * This method scans the m_qifEntry object as a payee record specified by Quicken 162 */ 163 void processPayeeEntry(); 164 165 /** 166 * This method scans the m_qifEntry object as an account record specified 167 * by Quicken. In case @p resetAccountId is @p true (the default), the 168 * global account id will be reset. 169 * 170 * The id of the account will be returned. 171 */ 172 const QString processAccountEntry(bool resetAccountId = true); 173 174 /** 175 * This method scans the m_qifEntry object as a category record specified 176 * by Quicken. 177 */ 178 void processCategoryEntry(); 179 180 /** 181 * This method scans the m_qifEntry object as a transaction record specified 182 * by Quicken. 183 */ 184 void processTransactionEntry(); 185 186 /** 187 * This method scans the m_qifEntry object as an investment transaction 188 * record specified by Quicken. 189 */ 190 void processInvestmentTransactionEntry(); 191 192 /** 193 * This method scans the m_qifEntry object as a price record specified 194 * by Quicken. 195 */ 196 void processPriceEntry(); 197 198 /** 199 * This method scans the m_qifEntry object as a security record specified 200 * by Quicken. 201 */ 202 void processSecurityEntry(); 203 204 /** 205 * This method processes the lines previously collected in 206 * the member variable m_qifEntry. If further information 207 * by the user is required to process the entry it will 208 * be collected. 209 */ 210 void processQifEntry(); 211 212 /** 213 * This method process a line starting with an exclamation mark 214 */ 215 void processQifSpecial(const QString& _line); 216 217 /** 218 * This method extracts the line beginning with the letter @p id 219 * from the lines contained in the QStringList object @p m_qifEntry. 220 * An empty QString is returned, if the line is not found. 221 * 222 * @param id QChar containing the letter to be found 223 * @param cnt return cnt'th of occurrence of id in lines. cnt defaults to 1. 224 * 225 * @return QString with the remainder of the line or empty if 226 * @p id is not found in @p lines 227 */ 228 const QString extractLine(const QChar& id, int cnt = 1); 229 230 /** 231 * This method examines each line in the QStringList object @p m_qifEntry, 232 * searching for split entries, which it extracts into a struct qSplit and 233 * stores all splits found in @p listqSplits . 234 */ 235 bool extractSplits(QList<qSplit>& listqSplits) const; 236 237 enum SelectCreateMode { 238 Create = 0, 239 Select 240 }; 241 242 /** 243 * This method looks up the @p searchname account by name and returns its id 244 * if it was found. If it was not found, it creates a new income account using 245 * @p searchname as a name, and returns the id if the newly created account 246 * 247 * @param searchname The name of the account to find or create 248 * @return QString id of the found or created account 249 */ 250 static const QString findOrCreateIncomeAccount(const QString& searchname); 251 252 /** 253 * This method looks up the @p searchname account by name and returns its id 254 * if it was found. If it was not found, it creates a new expense account using 255 * @p searchname as a name, and returns the id if the newly created account 256 * 257 * @param searchname The name of the account to find or create 258 * @return QString id of the found or created account 259 */ 260 static const QString findOrCreateExpenseAccount(const QString& searchname); 261 262 /** 263 * This methods returns the account from the list of accounts identified by 264 * an account id or account name including an account hierarchy. 265 * 266 * The parent account specifies from which account the search should be started. 267 * In case the parent account does not have an id, the method scans all top-level accounts. 268 * 269 * If the account is not found in the list of accounts, MyMoneyAccount() is returned. 270 * 271 * @param acc account to find 272 * @param parent parent account to search from 273 * @retval found MyMoneyAccount account instance 274 * @retval MyMoneyAccount() if not found 275 */ 276 MyMoneyAccount findAccount(const MyMoneyAccount& acc, const MyMoneyAccount& parent) const; 277 278 /** 279 * This method returns the account id for a given account @a name. In 280 * case @a name references an investment account and @a useBrokerage is @a true 281 * (the default), the id of the corresponding brokerage account will be 282 * returned. In case an account does not exist, it will be created. 283 */ 284 const QString transferAccount(const QString& name, bool useBrokerage = true); 285 286 // void processQifLine(); 287 void createOpeningBalance(eMyMoney::Account::Type accType = eMyMoney::Account::Type::Checkings); 288 289 Q_SIGNALS: 290 void statementsReady(const QList<MyMoneyStatement> &); 291 292 private Q_SLOTS: 293 void slotSendDataToFilter(); 294 void slotReceivedDataFromFilter(); 295 void slotReceivedErrorFromFilter(); 296 void slotProcessData(); 297 298 /** 299 * This slot is used to be informed about the end of the filtering process. 300 * It emits the signal importFinished() 301 */ 302 void slotImportFinished(); 303 304 305 private: 306 307 void parseReceivedData(const QByteArray& data); 308 309 310 /// \internal d-pointer class. 311 class Private; 312 /// \internal d-pointer instance. 313 Private* const d; 314 315 QProcess m_filter; 316 QString m_filename; 317 QUrl m_url; 318 MyMoneyQifProfile m_qifProfile; 319 MyMoneyAccount m_account; 320 unsigned long m_transactionsSkipped; 321 unsigned long m_transactionsProcessed; 322 QStringList m_dontAskAgain; 323 QMap<QString, QString> m_accountTranslation; 324 QMap<QString, QString> m_investmentMap; 325 QFile *m_file; 326 char m_buffer[1024]; 327 QByteArray m_lineBuffer; 328 QStringList m_qifEntry; 329 int m_extractedLine; 330 QString m_qifLine; 331 QStringList m_qifLines; 332 QifEntryTypeE m_entryType; 333 bool m_skipAccount; 334 bool m_processingData; 335 bool m_userAbort; 336 bool m_autoCreatePayee; 337 unsigned long m_pos; 338 unsigned m_linenumber; 339 bool m_warnedInvestment; 340 bool m_warnedSecurity; 341 bool m_warnedPrice; 342 QList<MyMoneyTransaction> m_transactionCache; 343 344 QList<QByteArray> m_data; 345 346 void (*m_progressCallback)(qint64, qint64, const QString&); 347 348 MyMoneyFileTransaction* m_ft; 349 }; 350 351 #endif 352