/* Copyright 2010-2012 Grégory Soutadé This file is part of KissCount. KissCount 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 3 of the License, or (at your option) any later version. KissCount is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with KissCount. If not, see . */ #include #include "ImportEngine.hpp" QString ImportEngine::NULL_IMPORT_PATTERN = "(nil)"; ImportEngine::ImportEngine() { } ImportEngine::~ImportEngine() { } bool ImportEngine::HandleFile(const QString& path, User* user, Database* db, KissCount* kiss) { _path = path; _user = user; _db = db; _kiss = kiss; _accounts.clear(); _unresolvedAccounts.clear(); _operations.clear(); _descriptions.clear(); _accountAmounts.clear(); return path.endsWith(_shortExt) || path.endsWith(_shortExt.toUpper()); } QString ImportEngine::GetFileExt() { return _(_longExt.toStdString().c_str()); } std::vector ExplodeString(QString& s) { QString tmp = s, cur = ""; std::vector res; while (tmp.size()) { if (tmp.startsWith(" " ) || tmp.startsWith("\t") || tmp.startsWith("\n") || tmp.startsWith("\r")) { if (cur.size()) { res.push_back(cur); cur = ""; } tmp = tmp.right(tmp.size()-1); continue; } cur += tmp.left(1); tmp = tmp.right(tmp.size()-1); } if (cur.size()) res.push_back(cur); return res; } /* Remove : - head spaces - tail spaces - every word starting by a number */ QString ImportEngine::RemoveUnused(const QString& s) { QString tmp = s, tmp2; QString res; bool number; tmp = tmp.trimmed(); while (tmp.size()) { tmp2 = tmp.left(1); tmp2.toInt(&number); if (number) { do { tmp = tmp.right(tmp.size()-1); tmp2 = tmp.left(1); } while (tmp.size() && tmp2 != " " && tmp2 != "\t" && tmp2 != "\r" && tmp2 != "\n"); } res += tmp2; tmp = tmp.right(tmp.size()-1); } return res; } /* Find a pattern between the two strings: %mX : lower string of orig[X] %MX : upper string of orig[X] %fX : First case in upper case of orig[X] %wX : word orig[X] other : constants */ QString ImportEngine::FindPattern(QString& orig, QString& dest) { QString pattern, cur_pat; int i, a; std::vector tok1; std::vector tok2; int size1, size2; if (orig == dest) return NULL_IMPORT_PATTERN; tok1 = ExplodeString(orig); tok2 = ExplodeString(dest); size1 = tok1.size(); size2 = tok2.size(); for(i=0; i tok1; std::vector tok2; int size1, i; long pos; op.account = pattern.account; op.category = pattern.category; if (pattern.pattern == NULL_IMPORT_PATTERN) return; tok1 = ExplodeString(pattern.pattern); tok2 = ExplodeString(op.description); size1 = tok1.size(); op.description = ""; for(i=0; i_importPatterns[key1] = pattern; for(i=pos+1; i<(int)_operations.size(); i++) { key2 = RemoveUnused(_descriptions[_operations[i].id]); if (key1 == key2) { ApplyPattern(_user->_importPatterns[key2], _operations[i]); nbOpUpdated++; } } return nbOpUpdated; } void ImportEngine::MatchPattern(QString& originalKey, Operation& op) { QString key1; ImportPattern pattern; if (!_user) return; key1 = RemoveUnused(originalKey); if (!_user->_importPatterns.count(key1)) { pattern.pattern = FindPattern(originalKey, op.description); pattern.account = op.account; pattern.category = op.category; _user->_importPatterns[key1] = pattern; // std::cout << "New pattern " << key1.mb_str() << "\t" << pattern.pattern.mb_str() << std::endl; } else { op.description = _descriptions[op.id]; ApplyPattern(_user->_importPatterns[key1], op); } } void ImportEngine::ParseFile(std::vector& accounts, std::vector& categories) { accounts = _unresolvedAccounts; categories = _unresolvedCategories; } std::vector* ImportEngine::GetOperations(std::map& accounts, std::map& categories) { int i; for(i=0; i<(int)_operations.size(); i++) { if (_operations[i].account < 0) _operations[i].account = accounts[_operations[i].account]; if (_operations[i].category < 0) _operations[i].category = categories[_operations[i].category]; } if (_kiss->GetOperationOrder() == "ASC") std::sort(_operations.begin(), _operations.end(), sortOperations); else std::sort(_operations.begin(), _operations.end(), reverseSortOperations); return &_operations; } const std::map& ImportEngine::GetAccountAmounts() { return _accountAmounts; }