From 1fd9c7358734685b6acee2df0c772041c08ab08a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Sat, 23 Apr 2011 20:16:31 +0200 Subject: [PATCH] Add Grisbi import (need to work on categories) --- Makefile | 2 + debian/control | 2 +- src/model/import/GrisbiImportEngine.cpp | 193 ++++++++++++++++++++++++ src/model/import/GrisbiImportEngine.h | 45 ++++++ src/model/import/ImportEngine.h | 2 + src/model/import/OFXImportEngine.cpp | 2 +- 6 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 src/model/import/GrisbiImportEngine.cpp create mode 100644 src/model/import/GrisbiImportEngine.h diff --git a/Makefile b/Makefile index 52ae73f..899d264 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ BIN_DIR=$(DESTDIR)"/usr/bin/" CXXFLAGS+=`wx-config --cxxflags` -Wall -Isrc -ggdb CXXFLAGS+=-I./lib/wxsqlite3-1.9.9/include CXXFLAGS+=-I./lib/freechart/include +CXXFLAGS+=-I/usr/include/libxml2 CXXFLAGS+=-Wl,--rpath,"$(LIB_DIR)" #CXXFLAGS+=-DRESSOURCES_ROOT="\"$(SHARE_DIR)\"" # For developpers @@ -13,6 +14,7 @@ CXXFLAGS+=-DRESSOURCES_ROOT="\"./ressources/\"" LDFLAGS+=`wx-config --libs` LDFLAGS+=-lofx +LDFLAGS+=-lxml2 ifdef WIN32 LDFLAGS+=-L./lib/wxsqlite3-1.9.9/lib/ -lwxcode_msw_wxsqlite3-2.8 diff --git a/debian/control b/debian/control index 0e8763c..9f5440a 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: kisscount Section: misc Priority: extra Maintainer: Grégory Soutadé -Build-Depends: debhelper (>= 7.0.50~), libsqlite3-dev, libwxgtk2.8-dev (>= 2.8.10), libofx-dev +Build-Depends: debhelper (>= 7.0.50~), libsqlite3-dev, libwxgtk2.8-dev (>= 2.8.10), libofx-dev, libxml2-dev Standards-Version: 3.9.1 Homepage: http://indefero.soutade.fr/p/kisscount/ Vcs-Git: git://soutade.fr/kisscount.git diff --git a/src/model/import/GrisbiImportEngine.cpp b/src/model/import/GrisbiImportEngine.cpp new file mode 100644 index 0000000..dcd2b2d --- /dev/null +++ b/src/model/import/GrisbiImportEngine.cpp @@ -0,0 +1,193 @@ +/* + Copyright 2010-2011 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 "GrisbiImportEngine.h" + +static GrisbiImportEngine grisbiImportEngine; + +void GrisbiImportEngine::LoadAccount(GrisbiImportEngine* _this, const char** attrs) +{ + int i; + wxString account_number, name, id, key; + + for (i=0; attrs[i]; i+=2) + { + if (!strcmp(attrs[i], "Name")) + name = wxString(attrs[i+1], wxConvUTF8); + + else if (!strcmp(attrs[i], "Number")) + id = wxString(attrs[i+1], wxConvUTF8); + + else if (!strcmp(attrs[i], "Bank_account_number")) + account_number = wxString(attrs[i+1], wxConvUTF8); + + else if (!strcmp(attrs[i], "Key")) + key = wxString(attrs[i+1], wxConvUTF8); + } + + account_number += key; + + for (i=0; i<(int)_this->_user->_accounts.size(); i++) + { + if (_this->_user->_accounts[i].number == account_number) + { + _this->_accounts[id] = _this->_user->_accounts[i].id; + return; + } + } + + _this->_accounts[id] = wxT("unknown-") + account_number; + _this->_unresolvedAccounts.push_back(account_number); +} + +void GrisbiImportEngine::LoadCategory(GrisbiImportEngine* _this, const char** attrs) +{ + wxString name, id; + int i; + + for (i=0; attrs[i]; i+=2) + { + if (!strcmp(attrs[i], "Na")) + name = wxString(attrs[i+1], wxConvUTF8); + + else if (!strcmp(attrs[i], "Nb")) + id = wxString(attrs[i+1], wxConvUTF8); + } + + for (i=0; i<(int)_this->_user->_categories.size(); i++) + { + if (_this->_user->_categories[i].name == name) + { + _this->_categories[id] = _this->_user->_categories[i].id; + return; + } + } + + _this->_categories[id] = wxT("unknown-") + id; + _this->_unresolvedCategories.push_back(name); +} + +void GrisbiImportEngine::LoadOperation(GrisbiImportEngine* _this, const char** attrs) +{ + int i; + static int id=0; + Operation op; + wxString amount; + wxDateTime date; + + op.id = wxString::Format(wxT("%d"), ++id); + op.parent = wxT(""); + op.account = wxT("0"); + op.category = wxT("0"); + op.fix_cost = false; + op.checked = false; + op.transfert = wxT(""); + op.formula = wxT(""); + op.meta = false; + op._virtual = false; + + for (i=0; attrs[i]; i+=2) + { + if (!strcmp(attrs[i], "Ac")) + op.account = _this->_accounts[wxString(attrs[i+1], wxConvUTF8)]; + + else if (!strcmp(attrs[i], "Dt")) + { + date.ParseFormat(wxString(attrs[i+1], wxConvUTF8), wxT("%m/%d/%Y")); + op.day = date.GetDay(); + op.month = date.GetMonth(); + op.year = date.GetYear(); + } + + else if (!strcmp(attrs[i], "Am")) + { + amount = wxString(attrs[i+1], wxConvUTF8); + amount.ToDouble(&op.amount); + } + + else if (!strcmp(attrs[i], "Ca")) + op.category = _this->_categories[wxString(attrs[i+1], wxConvUTF8)]; + + else if (!strcmp(attrs[i], "No")) + op.description = wxString(attrs[i+1], wxConvUTF8); + } + + _this->_operations.push_back(op); + _this->_descriptions[op.id] = op.description; + + _this->MatchPattern(op.description, op); +} + +void GrisbiImportEngine::GrisbiStartElement(void* user_data, const xmlChar* name_, const xmlChar** attrs_) +{ + GrisbiImportEngine* _this = (GrisbiImportEngine*) user_data; + static char first = 0; + int i; + const char** attrs = (const char**) attrs_; + const char* name = (const char*) name_; + + if (!first && strcmp(name, "Grisbi")) + { + throw "Invalid file !"; + } + else + first = 1; + + if (!strcmp(name, "General")) + { + for (i=0; attrs[i]; i+=2) + { + if (!strcmp(attrs[i], "File_version") && strcmp(attrs[i+1], "0.6.0") < 0) + throw "Unsupported version !"; + + else if (!strcmp(attrs[i], "Crypt_file") && !strcmp(attrs[i+1], "1")) + throw "Crypted file !"; + } + } + + else if (!strcmp(name, "Account")) + LoadAccount(_this, attrs); + + else if (!strcmp(name, "Category")) + LoadCategory(_this, attrs); + + else if (!strcmp(name, "Transaction")) + LoadOperation(_this, attrs); +} + +GrisbiImportEngine::GrisbiImportEngine() +{ + KissCount::RegisterImportEngine(this); + + _shortExt = wxT("gsb"); + _longExt = _("Grisbi files (*.gsb)|*.gsb"); + + _sax.startElement = GrisbiStartElement ; +} + +GrisbiImportEngine::~GrisbiImportEngine() +{ +} + +bool GrisbiImportEngine::HandleFile(const wxString& path, User* user, Database* db, KissCount* kiss) +{ + if (!ImportEngine::HandleFile(path, user, db, kiss)) return false; + + return xmlSAXUserParseFile(&_sax, this, path.mb_str()) >= 0; +} diff --git a/src/model/import/GrisbiImportEngine.h b/src/model/import/GrisbiImportEngine.h new file mode 100644 index 0000000..4d1c75b --- /dev/null +++ b/src/model/import/GrisbiImportEngine.h @@ -0,0 +1,45 @@ +/* + Copyright 2010-2011 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 . +*/ + +#ifndef GRISBIIMPORTENGINE_H +#define GRISBIIMPORTENGINE_H + +#include + +#include "ImportEngine.h" + +class GrisbiImportEngine : public ImportEngine { +public: + GrisbiImportEngine(); + ~GrisbiImportEngine(); + + virtual bool HandleFile(const wxString& path, User* user, Database* db, KissCount* kiss); + /* virtual std::vector ParseFile(); */ + /* virtual std::vector* GetOperations(std::map& accounts); */ + +private: + xmlSAXHandler _sax; + + static void GrisbiStartElement(void* user_data, const xmlChar* name_, const xmlChar** attrs_); + static void LoadAccount(GrisbiImportEngine* _this, const char** attrs); + static void LoadCategory(GrisbiImportEngine* _this, const char** attrs); + static void LoadOperation(GrisbiImportEngine* _this, const char** attrs); +}; + +#endif diff --git a/src/model/import/ImportEngine.h b/src/model/import/ImportEngine.h index efc54a1..9f204cd 100644 --- a/src/model/import/ImportEngine.h +++ b/src/model/import/ImportEngine.h @@ -66,7 +66,9 @@ protected: wxString _longExt; std::map _accounts; + std::map _categories; std::vector _unresolvedAccounts; + std::vector _unresolvedCategories; std::vector _operations; std::map _descriptions; diff --git a/src/model/import/OFXImportEngine.cpp b/src/model/import/OFXImportEngine.cpp index 0ad607c..2038d1f 100644 --- a/src/model/import/OFXImportEngine.cpp +++ b/src/model/import/OFXImportEngine.cpp @@ -102,7 +102,7 @@ int OFXImportEngine::transaction_cb(const struct OfxTransactionData data, void * int OFXImportEngine::account_balance_cb(const struct OfxStatementData data, void * statement_data) { - OFXImportEngine* _this = (OFXImportEngine*) statement_data; + // OFXImportEngine* _this = (OFXImportEngine*) statement_data; return 0; }