Add XMLImportEngine

Fix some bugs in ImportPanel and ImportEngines
This commit is contained in:
Grégory Soutadé 2011-07-04 20:23:00 +02:00
parent ebe9ef4a62
commit 753b499b48
21 changed files with 597 additions and 117 deletions

View File

@ -1,4 +1,4 @@
v0.2 (28/05/2011) v0.2 (04/07/2011)
** User ** ** User **
Better use of sizers (so better interface!) Better use of sizers (so better interface!)
@ -14,10 +14,12 @@ v0.2 (28/05/2011)
Add Real mode Add Real mode
Database is now at ~/.kisscount/kc.bdd Database is now at ~/.kisscount/kc.bdd
Add Debian's packages !! Add Debian's packages !!
Add Import Panel, OFX and Grisbi imports Add Import Panel, XML, OFX and Grisbi imports
Add Export Panel (only XML)
Add update next months Add update next months
Change charts and real/virtual mode position Change charts and real/virtual mode position
Add "non fix" category to statistics (sum of all non fix categories) Add "non fix" category to statistics (sum of all non fix categories)
Auto completion does not require date to be set
** Dev ** ** Dev **
Use a factory to create panels (prepare for plug-in) Use a factory to create panels (prepare for plug-in)

View File

@ -104,23 +104,27 @@ double KissCount::CalcAccountAmount(const wxString& id, int month, int year, boo
return _db->CalcAccountAmount(id, month, year, had_values); return _db->CalcAccountAmount(id, month, year, had_values);
} }
void KissCount::UpdateOperation(Operation& op) void KissCount::UpdateOperation(Operation& op, bool checkTransfert)
{ {
// Unlink // Unlink
op.transfert = wxT(""); if (checkTransfert)
_user->LinkOrUnlinkOperation(op); {
op.transfert = wxT("");
_user->LinkOrUnlinkOperation(op);
}
_db->UpdateOperation(_user, op); _db->UpdateOperation(_user, op, checkTransfert);
// Link // Link
_user->LinkOrUnlinkOperation(op); if (checkTransfert)
_user->LinkOrUnlinkOperation(op);
} }
wxString KissCount::AddOperation(Operation& op) wxString KissCount::AddOperation(Operation& op, bool checkTransfert)
{ {
wxString ret = _db->AddOperation(_user, op); wxString ret = _db->AddOperation(_user, op, checkTransfert);
if (op.transfert.Length()) if (checkTransfert && op.transfert.Length())
_user->LinkOrUnlinkOperation(op); _user->LinkOrUnlinkOperation(op);
return ret; return ret;
@ -159,9 +163,9 @@ double KissCount::MetaPositiveAmount(const wxString& id)
return _db->MetaPositiveAmount(id); return _db->MetaPositiveAmount(id);
} }
void KissCount::SetAccountAmount(int month, int year, const wxString& accountId, double amount) void KissCount::SetAccountAmount(const wxString& accountId, int month, int year, double amount)
{ {
_db->SetAccountAmount(month, year, accountId, amount); _db->SetAccountAmount(accountId, month, year, amount);
} }
wxString KissCount::AddAccount(Account& ac) wxString KissCount::AddAccount(Account& ac)
@ -173,7 +177,7 @@ wxString KissCount::AddAccount(Account& ac)
curDate.SetToCurrent(); curDate.SetToCurrent();
SetAccountAmount((int)curDate.GetMonth(), curDate.GetYear(), ac.id, 0.0); SetAccountAmount(ac.id, (int)curDate.GetMonth(), curDate.GetYear(), 0.0);
return ac.id; return ac.id;
} }

View File

@ -40,6 +40,10 @@
s.Replace(wxT("\'"), wxT("\\\'"), true); \ s.Replace(wxT("\'"), wxT("\\\'"), true); \
} }
#define UNESCAPE_CHARS(s) { \
s.Replace(wxT("\\\""), wxT("\""), true); \
s.Replace(wxT("\\\'"), wxT("\'"), true); \
}
class wxUI; class wxUI;
class Database; class Database;
class ImportEngine; class ImportEngine;
@ -62,15 +66,15 @@ public:
void LoadYear(int year, bool force=false); void LoadYear(int year, bool force=false);
wxString AddOperation(Operation& op); wxString AddOperation(Operation& op, bool checkTransfert=true);
void UpdateOperation(Operation& op); void UpdateOperation(Operation& op, bool checkTransfert=true);
void DeleteOperation(Operation& op); void DeleteOperation(Operation& op);
void DeleteOperations(int month, int year); void DeleteOperations(int month, int year);
double MetaAmount(const wxString& id); double MetaAmount(const wxString& id);
double MetaPositiveAmount(const wxString& id); double MetaPositiveAmount(const wxString& id);
double GetAccountAmount(const wxString& id, int month, int year); double GetAccountAmount(const wxString& id, int month, int year);
void SetAccountAmount(int month, int year, const wxString& accountId, double value); void SetAccountAmount(const wxString& accountId, int month, int year, double value);
double CalcAccountAmount(const wxString& id, int month, int year, bool* had_values); double CalcAccountAmount(const wxString& id, int month, int year, bool* had_values);
wxString AddAccount(Account& ac); wxString AddAccount(Account& ac);

44
src/model/AccountAmount.h Normal file
View File

@ -0,0 +1,44 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef ACCOUNTAMOUNT_H
#define ACCOUNTAMOUNT_H
class AccountAmount {
public:
wxString account;
int month;
int year;
bool operator()(const AccountAmount& x, const AccountAmount& y) const
{
long x1, y1;
if (x.account != y.account)
{
x.account.ToLong(&x1);
y.account.ToLong(&y1);
return x1 < y1;
}
return (x.year < y.year || ((x.year == y.year) && x.month < y.month));
}
};
#endif

View File

@ -91,10 +91,13 @@ void Database::CreateDatabase()
wxString message = _("No database found, would you like to create a new one ?\n\n"); wxString message = _("No database found, would you like to create a new one ?\n\n");
message += _("!! Warning !! If there was a bug, the old database will be suppressed !"); message += _("!! Warning !! If there was a bug, the old database will be suppressed !");
wxMessageDialog dialog(NULL, message, wxT("KissCount"), wxYES_NO); if (dirname.DirExists())
{
wxMessageDialog dialog(NULL, message, wxT("KissCount"), wxYES_NO);
if (dialog.ShowModal() == wxID_NO) if (dialog.ShowModal() == wxID_NO)
throw std::string("No database") ; throw std::string("No database") ;
}
init_script.open(INIT_SCRIPT); init_script.open(INIT_SCRIPT);
@ -400,7 +403,7 @@ double Database::GetAccountAmount(const wxString& id, int month, int year)
res = set.GetDouble(wxT("amount")); res = set.GetDouble(wxT("amount"));
else else
{ {
SetAccountAmount(month, year, id, 0.0); SetAccountAmount(id, month, year, 0.0);
res = 0.0; res = 0.0;
} }
@ -550,11 +553,12 @@ void Database::LinkOrUnlinkOperation(User* user, Operation& op)
} }
} }
void Database::UpdateOperation(User* user, Operation& op) void Database::UpdateOperation(User* user, Operation& op, bool checkTransfert)
{ {
wxString req; wxString req;
LinkOrUnlinkOperation(user, op); if (checkTransfert)
LinkOrUnlinkOperation(user, op);
ESCAPE_CHARS(op.description); ESCAPE_CHARS(op.description);
@ -589,10 +593,11 @@ void Database::UpdateOperation(User* user, Operation& op)
EXECUTE_SQL_UPDATE(req, ); EXECUTE_SQL_UPDATE(req, );
LinkOrUnlinkOperation(user, op); if (checkTransfert)
LinkOrUnlinkOperation(user, op);
} }
wxString Database::AddOperation(User* user, Operation& op) wxString Database::AddOperation(User* user, Operation& op, bool checkTransfert)
{ {
wxString req, res; wxString req, res;
wxSQLite3ResultSet set; wxSQLite3ResultSet set;
@ -631,7 +636,8 @@ wxString Database::AddOperation(User* user, Operation& op)
op.id = res; op.id = res;
LinkOrUnlinkOperation(user, op); if (checkTransfert)
LinkOrUnlinkOperation(user, op);
return res; return res;
} }
@ -783,7 +789,7 @@ double Database::MetaPositiveAmount(const wxString& id)
return res; return res;
} }
void Database::SetAccountAmount(int month, int year, const wxString& accountId, double amount) void Database::SetAccountAmount(const wxString& accountId, int month, int year, double amount)
{ {
wxString req; wxString req;
req = wxT("UPDATE account_amount SET ") ; req = wxT("UPDATE account_amount SET ") ;

View File

@ -104,8 +104,8 @@ public:
User* LoadUser(const wxString& name); User* LoadUser(const wxString& name);
void LoadYear(User* user, int year); void LoadYear(User* user, int year);
void UpdateOperation(User* user, Operation& op); void UpdateOperation(User* user, Operation& op, bool checkTransfert=true);
wxString AddOperation(User* user, Operation& op); wxString AddOperation(User* user, Operation& op, bool checkTransfert=true);
void DeleteOperation(User* user, Operation& op); void DeleteOperation(User* user, Operation& op);
void DeleteOperations(User* user, int month, int year); void DeleteOperations(User* user, int month, int year);
bool LoadOperation(User* user, const wxString& id); bool LoadOperation(User* user, const wxString& id);
@ -113,7 +113,7 @@ public:
double MetaPositiveAmount(const wxString& id); double MetaPositiveAmount(const wxString& id);
double GetAccountAmount(const wxString& id, int month, int year); double GetAccountAmount(const wxString& id, int month, int year);
void SetAccountAmount(int month, int year, const wxString& accountId, double amount); void SetAccountAmount(const wxString& accountId, int month, int year, double amount);
double CalcAccountAmount(const wxString& id, int month, int year, bool* had_values); double CalcAccountAmount(const wxString& id, int month, int year, bool* had_values);
wxString AddAccount(User* user, Account& ac); wxString AddAccount(User* user, Account& ac);

View File

@ -42,6 +42,10 @@ bool ExportEngine::SaveFile(std::vector<Operation>* operations)
int i; int i;
wxString account, category; wxString account, category;
AccountAmount accountAmount; AccountAmount accountAmount;
int minMonth = -1, minYear = -1;
unsigned int maxMonth = -1, maxYear = -1;
unsigned int month, year;
std::map<wxString, int>::iterator it;
if (!operations) return NULL; if (!operations) return NULL;
@ -54,23 +58,45 @@ bool ExportEngine::SaveFile(std::vector<Operation>* operations)
account = (*operations)[i].account; account = (*operations)[i].account;
category = (*operations)[i].category; category = (*operations)[i].category;
accountAmount.account = account; if (minYear == -1 || (int)(*operations)[i].year < minYear)
accountAmount.month = (*operations)[i].month; maxYear = minYear = (*operations)[i].year;
accountAmount.year = (*operations)[i].year;
if (account.Length()) if (minMonth == -1 || ((int)(*operations)[i].month < minMonth && (int)(*operations)[i].year == minYear))
maxMonth = minMonth = (*operations)[i].month;
if ((*operations)[i].year > maxYear)
{ {
if (!_accounts.count(account)) maxYear = (*operations)[i].year;
_accounts[account]++; maxMonth = (*operations)[i].month;
if (!_accountAmounts.count(accountAmount))
_accountAmounts[accountAmount] = _kiss->GetAccountAmount(accountAmount.account, accountAmount.month, accountAmount.year);
} }
if ((*operations)[i].month > maxMonth && (*operations)[i].year == maxYear)
maxMonth = (*operations)[i].month;
if (account.Length() && !_accounts.count(account))
_accounts[account]++;
if (category.Length() && !_categories.count(category)) if (category.Length() && !_categories.count(category))
_categories[category]++; _categories[category]++;
} }
for(it=_accounts.begin(); it!=_accounts.end(); it++)
{
month = minMonth;
for (year = minYear; year <= maxYear; year++)
{
for (; !(month > maxMonth && year == maxYear) && month < 12; month++)
{
accountAmount.account = it->first;
accountAmount.month = month;
accountAmount.year = year;
_accountAmounts[accountAmount] = _kiss->GetAccountAmount(accountAmount.account, accountAmount.month, accountAmount.year);
}
month = 0;
}
}
return true; return true;
} }

View File

@ -22,30 +22,10 @@
#include <model/model.h> #include <model/model.h>
#include <controller/KissCount.h> #include <controller/KissCount.h>
#include <model/AccountAmount.h>
class KissCount; class KissCount;
class AccountAmount {
public:
wxString account;
int month;
int year;
bool operator()(const AccountAmount& x, const AccountAmount& y) const
{
long x1, y1;
if (x.account != y.account)
{
x.account.ToLong(&x1);
y.account.ToLong(&y1);
return x1 < y1;
}
return (x.year < y.year && x.month < y.month);
}
};
class ExportEngine { class ExportEngine {
public: public:
ExportEngine(); ExportEngine();

View File

@ -48,15 +48,16 @@ bool XMLExportEngine::SaveAccounts()
account = _user->GetAccount(it->first); account = _user->GetAccount(it->first);
ESCAPE_CHARS(account.name); ESCAPE_CHARS(account.name);
ESCAPE_CHARS(account.number);
xmlTextWriterStartElement(_writer, (const xmlChar*) "account"); xmlTextWriterStartElement(_writer, (const xmlChar*) "account");
xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "id", (const xmlChar*) account.id.utf8_str().data()); xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "id", (const xmlChar*) account.id.utf8_str().data());
xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "name", (const xmlChar*) account.name.utf8_str().data()); xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "name", (const xmlChar*) account.name.utf8_str().data());
xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "number", (const xmlChar*) account.number.utf8_str().data()); xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "number", (const xmlChar*) account.number.utf8_str().data());
xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "shared", (const xmlChar*) (account.shared ? "1" : "0")); // xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "shared", (const xmlChar*) (account.shared ? "1" : "0"));
xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "blocked", (const xmlChar*) (account.blocked ? "1" : "0")); xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "blocked", (const xmlChar*) (account.blocked ? "1" : "0"));
xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "default", (const xmlChar*) (account._default ? "1" : "0")); // xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "default", (const xmlChar*) (account._default ? "1" : "0"));
xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "is_owner", (const xmlChar*) (account.is_owner ? "1" : "0")); // xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "is_owner", (const xmlChar*) (account.is_owner ? "1" : "0"));
xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "virtual", (const xmlChar*) (account._virtual ? "1" : "0")); xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "virtual", (const xmlChar*) (account._virtual ? "1" : "0"));
xmlTextWriterEndElement(_writer); xmlTextWriterEndElement(_writer);
} }
@ -100,11 +101,11 @@ bool XMLExportEngine::SaveCategories()
rgb = category.backcolor.Blue(); rgb = category.backcolor.Blue();
rgb |= category.backcolor.Green() << 8; rgb |= category.backcolor.Green() << 8;
rgb |= category.backcolor.Red() << 16; rgb |= category.backcolor.Red() << 16;
xmlTextWriterWriteFormatAttribute(_writer, (const xmlChar*) "backcolor", "%08X", rgb); xmlTextWriterWriteFormatAttribute(_writer, (const xmlChar*) "backcolor", "0x%08X", rgb);
rgb = category.forecolor.Blue(); rgb = category.forecolor.Blue();
rgb |= category.forecolor.Green() << 8; rgb |= category.forecolor.Green() << 8;
rgb |= category.forecolor.Red() << 16; rgb |= category.forecolor.Red() << 16;
xmlTextWriterWriteFormatAttribute(_writer, (const xmlChar*) "forecolor", "%08X", rgb); xmlTextWriterWriteFormatAttribute(_writer, (const xmlChar*) "forecolor", "0x%08X", rgb);
xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "fix_cost", (const xmlChar*) (category.fix_cost ? "1" : "0")); xmlTextWriterWriteAttribute(_writer, (const xmlChar*) "fix_cost", (const xmlChar*) (category.fix_cost ? "1" : "0"));
xmlTextWriterEndElement(_writer); xmlTextWriterEndElement(_writer);
} }

View File

@ -44,6 +44,9 @@ void GrisbiImportEngine::LoadAccount(GrisbiImportEngine* _this, const char** att
account_number += key; account_number += key;
UNESCAPE_CHARS(name);
UNESCAPE_CHARS(account_number);
for (i=0; i<(int)_this->_user->_accounts.size(); i++) for (i=0; i<(int)_this->_user->_accounts.size(); i++)
{ {
if (_this->_user->_accounts[i].number == account_number) if (_this->_user->_accounts[i].number == account_number)
@ -56,6 +59,11 @@ void GrisbiImportEngine::LoadAccount(GrisbiImportEngine* _this, const char** att
_this->_accounts[id] = wxT("unknown-") + account_number; _this->_accounts[id] = wxT("unknown-") + account_number;
ac.number = account_number; ac.number = account_number;
ac.name = name; ac.name = name;
ac.shared = false;
ac.blocked = false;
ac._default = false;
ac.is_owner = true;
ac._virtual = false;
_this->_unresolvedAccounts.push_back(ac); _this->_unresolvedAccounts.push_back(ac);
} }
@ -74,6 +82,8 @@ void GrisbiImportEngine::LoadCategory(GrisbiImportEngine* _this, const char** at
id = wxString(attrs[i+1], wxConvUTF8); id = wxString(attrs[i+1], wxConvUTF8);
} }
UNESCAPE_CHARS(name);
for (i=0; i<(int)_this->_user->_categories.size(); i++) for (i=0; i<(int)_this->_user->_categories.size(); i++)
{ {
if (_this->_user->_categories[i].name == name) if (_this->_user->_categories[i].name == name)
@ -86,6 +96,10 @@ void GrisbiImportEngine::LoadCategory(GrisbiImportEngine* _this, const char** at
_this->_categories[id] = wxT("unknown-") + name; _this->_categories[id] = wxT("unknown-") + name;
cat.id = id; cat.id = id;
cat.name = name; cat.name = name;
cat.parent = wxT("0");
cat.backcolor = OWN_GREEN ;
cat.forecolor = *wxBLACK;
cat.fix_cost = false;
_this->_unresolvedCategories.push_back(cat); _this->_unresolvedCategories.push_back(cat);
} }
@ -134,6 +148,8 @@ void GrisbiImportEngine::LoadOperation(GrisbiImportEngine* _this, const char** a
op.description = wxString(attrs[i+1], wxConvUTF8); op.description = wxString(attrs[i+1], wxConvUTF8);
} }
UNESCAPE_CHARS(op.description);
_this->_operations.push_back(op); _this->_operations.push_back(op);
_this->_descriptions[op.id] = op.description; _this->_descriptions[op.id] = op.description;
@ -193,7 +209,19 @@ GrisbiImportEngine::~GrisbiImportEngine()
bool GrisbiImportEngine::HandleFile(const wxString& path, User* user, Database* db, KissCount* kiss) bool GrisbiImportEngine::HandleFile(const wxString& path, User* user, Database* db, KissCount* kiss)
{ {
int res = -1;
if (!ImportEngine::HandleFile(path, user, db, kiss)) return false; if (!ImportEngine::HandleFile(path, user, db, kiss)) return false;
return xmlSAXUserParseFile(&_sax, this, path.mb_str()) >= 0; try
{
res = xmlSAXUserParseFile(&_sax, this, path.mb_str());
}
catch (const char* s)
{
std::cout << "GrisbiImportEngine :: " << s << std::endl;
res = -1;
}
return res >= 0;
} }

View File

@ -30,8 +30,6 @@ public:
~GrisbiImportEngine(); ~GrisbiImportEngine();
virtual bool HandleFile(const wxString& path, User* user, Database* db, KissCount* kiss); virtual bool HandleFile(const wxString& path, User* user, Database* db, KissCount* kiss);
/* virtual std::vector<wxString> ParseFile(); */
/* virtual std::vector<Operation>* GetOperations(std::map<wxString, wxString>& accounts); */
private: private:
xmlSAXHandler _sax; xmlSAXHandler _sax;

View File

@ -38,6 +38,7 @@ bool ImportEngine::HandleFile(const wxString& path, User* user, Database* db, Ki
_unresolvedAccounts.clear(); _unresolvedAccounts.clear();
_operations.clear(); _operations.clear();
_descriptions.clear(); _descriptions.clear();
_accountAmounts.clear();
return path.EndsWith(_shortExt) || path.EndsWith(_shortExt.Upper()); return path.EndsWith(_shortExt) || path.EndsWith(_shortExt.Upper());
} }
@ -307,3 +308,8 @@ std::vector<Operation>* ImportEngine::GetOperations(std::map<wxString, wxString>
return &_operations; return &_operations;
} }
const std::map<AccountAmount, double, AccountAmount>& ImportEngine::GetAccountAmounts()
{
return _accountAmounts;
}

View File

@ -22,6 +22,7 @@
#include <model/model.h> #include <model/model.h>
#include <controller/KissCount.h> #include <controller/KissCount.h>
#include <model/AccountAmount.h>
class KissCount; class KissCount;
@ -52,10 +53,13 @@ public:
// Final Step // Final Step
virtual std::vector<Operation>* GetOperations(std::map<wxString, wxString>& accounts, std::map<wxString, wxString>& categories); virtual std::vector<Operation>* GetOperations(std::map<wxString, wxString>& accounts, std::map<wxString, wxString>& categories);
const std::map<AccountAmount, double, AccountAmount>& GetAccountAmounts();
void MatchPattern(wxString& key, Operation& op); void MatchPattern(wxString& key, Operation& op);
int UpdatePattern(int pos); int UpdatePattern(int pos);
static wxString RemoveUnused(const wxString& s); static wxString RemoveUnused(const wxString& s);
protected: protected:
Database* _db; Database* _db;
User* _user; User* _user;
@ -71,6 +75,7 @@ protected:
std::vector<Category> _unresolvedCategories; std::vector<Category> _unresolvedCategories;
std::vector<Operation> _operations; std::vector<Operation> _operations;
std::map<wxString, wxString> _descriptions; std::map<wxString, wxString> _descriptions;
std::map<AccountAmount, double, AccountAmount> _accountAmounts;
void ApplyPattern(ImportPattern& pattern, Operation& op); void ApplyPattern(ImportPattern& pattern, Operation& op);
wxString FindPattern(wxString& s1, wxString& s2); wxString FindPattern(wxString& s1, wxString& s2);

View File

@ -30,6 +30,8 @@ int OFXImportEngine::account_cb(const struct OfxAccountData data, void * account
_this->_curAccount = wxT(""); _this->_curAccount = wxT("");
UNESCAPE_CHARS(account_number);
for (i=0; i<(int)_this->_user->_accounts.size(); i++) for (i=0; i<(int)_this->_user->_accounts.size(); i++)
{ {
if (_this->_user->_accounts[i].number == account_number) if (_this->_user->_accounts[i].number == account_number)
@ -46,6 +48,11 @@ int OFXImportEngine::account_cb(const struct OfxAccountData data, void * account
{ {
_this->_curAccount = _this->_accounts[account_number] = wxT("unknown-") + account_number; _this->_curAccount = _this->_accounts[account_number] = wxT("unknown-") + account_number;
ac.number = account_number; ac.number = account_number;
ac.shared = false;
ac.blocked = false;
ac._default = false;
ac.is_owner = true;
ac._virtual = false;
_this->_unresolvedAccounts.push_back(ac); _this->_unresolvedAccounts.push_back(ac);
} }
@ -94,6 +101,8 @@ int OFXImportEngine::transaction_cb(const struct OfxTransactionData data, void *
op.description += wxString(data.memo, wxConvUTF8); op.description += wxString(data.memo, wxConvUTF8);
} }
UNESCAPE_CHARS(op.description);
_this->_operations.push_back(op); _this->_operations.push_back(op);
_this->_descriptions[op.id] = op.description; _this->_descriptions[op.id] = op.description;

View File

@ -0,0 +1,294 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "XMLImportEngine.h"
static XMLImportEngine xmlImportEngine;
void XMLImportEngine::LoadAccount(XMLImportEngine* _this, const char** attrs)
{
int i;
wxString account_number, name, id;
Account ac;
for (i=0; attrs[i]; i+=2)
{
if (!strcmp(attrs[i], "name"))
ac.name = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "id"))
ac.id = id = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "number"))
ac.number = account_number = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "blocked"))
ac.blocked = (wxString(attrs[i+1], wxConvUTF8) == wxT("1"));
else if (!strcmp(attrs[i], "virtual"))
ac._virtual = (wxString(attrs[i+1], wxConvUTF8) == wxT("1"));
}
UNESCAPE_CHARS(ac.name);
UNESCAPE_CHARS(ac.number);
ac._default = false;
ac.shared = false;
ac.is_owner = true;
if (account_number.Length())
{
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(ac);
}
void XMLImportEngine::LoadAccountAmount(XMLImportEngine* _this, const char** attrs)
{
AccountAmount accountAmount;
int i;
long v;
double amount;
for (i=0; attrs[i]; i+=2)
{
if (!strcmp(attrs[i], "account"))
accountAmount.account = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "month"))
{
wxString(attrs[i+1], wxConvUTF8).ToLong(&v);
accountAmount.month = v;
}
else if (!strcmp(attrs[i], "year"))
{
wxString(attrs[i+1], wxConvUTF8).ToLong(&v);
accountAmount.year = v;
}
else if (!strcmp(attrs[i], "amount"))
wxString(attrs[i+1], wxConvUTF8).ToDouble(&amount);
}
_this->_accountAmounts[accountAmount] = amount;
}
void XMLImportEngine::LoadCategory(XMLImportEngine* _this, const char** attrs)
{
wxString name, id;
int i;
long rgb;
Category cat;
for (i=0; attrs[i]; i+=2)
{
if (!strcmp(attrs[i], "name"))
cat.name = name = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "id"))
cat.id = id = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "font"))
cat.font = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "backcolor"))
{
wxString(attrs[i+1], wxConvUTF8).ToLong(&rgb, 16);
cat.backcolor = wxColour((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
}
else if (!strcmp(attrs[i], "forecolor"))
{
wxString(attrs[i+1], wxConvUTF8).ToLong(&rgb, 16);
cat.forecolor = wxColour((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF);
}
else if (!strcmp(attrs[i], "fix_cost"))
cat.fix_cost = (wxString(attrs[i+1], wxConvUTF8) == wxT("1"));
}
UNESCAPE_CHARS(cat.name);
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-") + name;
_this->_unresolvedCategories.push_back(cat);
}
void XMLImportEngine::LoadOperation(XMLImportEngine* _this, const char** attrs)
{
int i;
Operation op;
long v;
double amount;
wxString id;
for (i=0; attrs[i]; i+=2)
{
if (!strcmp(attrs[i], "id"))
op.id = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "parent"))
op.parent = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "day"))
{
wxString(attrs[i+1], wxConvUTF8).ToLong(&v);
op.day = v;
}
else if (!strcmp(attrs[i], "month"))
{
wxString(attrs[i+1], wxConvUTF8).ToLong(&v);
op.month = v;
}
else if (!strcmp(attrs[i], "year"))
{
wxString(attrs[i+1], wxConvUTF8).ToLong(&v);
op.year = v;
}
else if (!strcmp(attrs[i], "amount"))
{
wxString(attrs[i+1], wxConvUTF8).ToDouble(&amount);
op.amount = amount;
}
else if (!strcmp(attrs[i], "description"))
op.description = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "category"))
op.category = _this->_categories[wxString(attrs[i+1], wxConvUTF8)];
else if (!strcmp(attrs[i], "fix_cost"))
op.fix_cost = (wxString(attrs[i+1], wxConvUTF8) == wxT("1"));
else if (!strcmp(attrs[i], "account"))
op.account = _this->_accounts[wxString(attrs[i+1], wxConvUTF8)];
else if (!strcmp(attrs[i], "checked"))
op.checked = (wxString(attrs[i+1], wxConvUTF8) == wxT("1"));
else if (!strcmp(attrs[i], "transfert"))
op.transfert = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "formula"))
op.formula = wxString(attrs[i+1], wxConvUTF8);
else if (!strcmp(attrs[i], "meta"))
op.meta = (wxString(attrs[i+1], wxConvUTF8) == wxT("1"));
else if (!strcmp(attrs[i], "virtual"))
op._virtual = (wxString(attrs[i+1], wxConvUTF8) == wxT("1"));
}
UNESCAPE_CHARS(op.description);
_this->_operations.push_back(op);
_this->_descriptions[op.id] = op.description;
_this->MatchPattern(op.description, op);
}
void XMLImportEngine::XmlStartElement(void* user_data, const xmlChar* name_, const xmlChar** attrs_)
{
XMLImportEngine* _this = (XMLImportEngine*) user_data;
int i;
const char** attrs = (const char**) attrs_;
const char* name = (const char*) name_;
// if (!first && strcmp(name, "Xml"))
// {
// throw "Invalid file !";
// }
// else
// first = 1;
if (!strcmp(name, "kisscount"))
{
for (i=0; attrs[i]; i+=2)
{
if (!strcmp(attrs[i], "version") && strcmp(attrs[i+1], "1"))
throw "Unsupported version !";
}
}
else if (!strcmp(name, "account"))
LoadAccount(_this, attrs);
else if (!strcmp(name, "account_amount"))
LoadAccountAmount(_this, attrs);
else if (!strcmp(name, "category"))
LoadCategory(_this, attrs);
else if (!strcmp(name, "operation"))
LoadOperation(_this, attrs);
}
XMLImportEngine::XMLImportEngine()
{
KissCount::RegisterImportEngine(this);
_shortExt = wxT("xml");
_longExt = _("KissCount xml files (*.xml)|*.xml");
_sax.startElement = XmlStartElement ;
}
XMLImportEngine::~XMLImportEngine()
{
}
bool XMLImportEngine::HandleFile(const wxString& path, User* user, Database* db, KissCount* kiss)
{
int res = -1 ;
if (!ImportEngine::HandleFile(path, user, db, kiss)) return false;
try
{
res = xmlSAXUserParseFile(&_sax, this, path.mb_str()) >= 0;
}
catch (const char* s)
{
std::cout << "XMLImportEngine :: " << s << std::endl;
res = -1;
}
return res >= 0;
}

View File

@ -0,0 +1,44 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef XMLIMPORTENGINE_H
#define XMLIMPORTENGINE_H
#include <libxml/parser.h>
#include "ImportEngine.h"
class XMLImportEngine : public ImportEngine {
public:
XMLImportEngine();
~XMLImportEngine();
virtual bool HandleFile(const wxString& path, User* user, Database* db, KissCount* kiss);
private:
xmlSAXHandler _sax;
static void XmlStartElement(void* user_data, const xmlChar* name_, const xmlChar** attrs_);
static void LoadAccount(XMLImportEngine* _this, const char** attrs);
static void LoadAccountAmount(XMLImportEngine* _this, const char** attrs);
static void LoadCategory(XMLImportEngine* _this, const char** attrs);
static void LoadOperation(XMLImportEngine* _this, const char** attrs);
};
#endif

View File

@ -715,7 +715,7 @@ void AccountPanel::OnAccountModified(wxGridEvent& event)
_accountsGrid->GetCellValue(row, event.GetCol()).ToDouble(&amount); _accountsGrid->GetCellValue(row, event.GetCol()).ToDouble(&amount);
_kiss->SetAccountAmount(_curMonth, _curYear, id, amount); _kiss->SetAccountAmount(id, _curMonth, _curYear, amount);
_accountsInitValues[id] = amount; _accountsInitValues[id] = amount;
UpdateStats(); UpdateStats();
@ -1082,7 +1082,7 @@ void AccountPanel::OnUpdateNextMonths(wxCommandEvent& event)
if ((cur_amounts[i] - amount) != deltas[i]) continue; if ((cur_amounts[i] - amount) != deltas[i]) continue;
cur_amounts[i] = amount + deltas[i]; cur_amounts[i] = amount + deltas[i];
_kiss->SetAccountAmount(last_month, last_year, user->_accounts[i].id, cur_amounts[i]); _kiss->SetAccountAmount(user->_accounts[i].id, last_month, last_year, cur_amounts[i]);
cur_amounts[i] += _kiss->CalcAccountAmount(user->_accounts[i].id, last_month, last_year, &had_values); cur_amounts[i] += _kiss->CalcAccountAmount(user->_accounts[i].id, last_month, last_year, &had_values);
account_updated++; account_updated++;

View File

@ -150,8 +150,6 @@ void ImportPanel::OnFileEnter(wxCommandEvent& WXUNUSED(event))
void ImportPanel::ProcessFile() void ImportPanel::ProcessFile()
{ {
std::vector<Account> accounts;
std::vector<Category> categories;
User* user = _kiss->GetUser(); User* user = _kiss->GetUser();
int i; int i;
wxGridCellChoiceEditor* accountEditor; wxGridCellChoiceEditor* accountEditor;
@ -179,9 +177,9 @@ void ImportPanel::ProcessFile()
return ; return ;
} }
_importEngine->ParseFile(accounts, categories); _importEngine->ParseFile(_unresolvedAccounts, _unresolvedCategories);
if (accounts.size()) if (_unresolvedAccounts.size())
{ {
int nb_accounts = user->GetAccountsNumber(); int nb_accounts = user->GetAccountsNumber();
userAccounts = new wxString[nb_accounts+1]; userAccounts = new wxString[nb_accounts+1];
@ -195,13 +193,13 @@ void ImportPanel::ProcessFile()
_buttonLoadOperations->Enable(); _buttonLoadOperations->Enable();
_accountsGrid->AppendRows(accounts.size()); _accountsGrid->AppendRows(_unresolvedAccounts.size());
for (i=0; i<(int)accounts.size(); i++) for (i=0; i<(int)_unresolvedAccounts.size(); i++)
{ {
_accountsGrid->SetCellValue(i, 0, accounts[i].number); _accountsGrid->SetCellValue(i, 0, _unresolvedAccounts[i].number);
_accountsGrid->SetReadOnly(i, 0); _accountsGrid->SetReadOnly(i, 0);
_accountsGrid->SetCellValue(i, 1, accounts[i].name); _accountsGrid->SetCellValue(i, 1, _unresolvedAccounts[i].name);
_accountsGrid->SetCellValue(i, 2, userAccounts[0]); _accountsGrid->SetCellValue(i, 2, userAccounts[0]);
_accountsGrid->SetCellEditor(i, 2, accountEditor); _accountsGrid->SetCellEditor(i, 2, accountEditor);
@ -211,7 +209,7 @@ void ImportPanel::ProcessFile()
_accountsGrid->Layout(); _accountsGrid->Layout();
} }
if (categories.size()) if (_unresolvedCategories.size())
{ {
int nb_categories = user->GetCategoriesNumber(); int nb_categories = user->GetCategoriesNumber();
userCategories = new wxString[nb_categories+1]; userCategories = new wxString[nb_categories+1];
@ -225,11 +223,11 @@ void ImportPanel::ProcessFile()
_buttonLoadOperations->Enable(); _buttonLoadOperations->Enable();
_categoriesGrid->AppendRows(categories.size()); _categoriesGrid->AppendRows(_unresolvedCategories.size());
for (i=0; i<(int)categories.size(); i++) for (i=0; i<(int)_unresolvedCategories.size(); i++)
{ {
_categoriesGrid->SetCellValue(i, 0, categories[i].name); _categoriesGrid->SetCellValue(i, 0, _unresolvedCategories[i].name);
_categoriesGrid->SetReadOnly(i, 0); _categoriesGrid->SetReadOnly(i, 0);
_categoriesGrid->SetCellValue(i, 2, userCategories[0]); _categoriesGrid->SetCellValue(i, 2, userCategories[0]);
@ -240,7 +238,7 @@ void ImportPanel::ProcessFile()
_categoriesGrid->Layout(); _categoriesGrid->Layout();
} }
if (!accounts.size() && !categories.size()) if (!_unresolvedAccounts.size() && !_unresolvedCategories.size())
{ {
OnLoadOperations(event); OnLoadOperations(event);
} }
@ -249,19 +247,20 @@ void ImportPanel::ProcessFile()
void ImportPanel::OnLoadOperations(wxCommandEvent& WXUNUSED(event)) void ImportPanel::OnLoadOperations(wxCommandEvent& WXUNUSED(event))
{ {
std::map<wxString, wxString> resolvedAccounts;
std::map<wxString, wxString> resolvedCategories;
int i, nbAccounts=0, nbCategories=0; int i, nbAccounts=0, nbCategories=0;
User* user = _kiss->GetUser(); User* user = _kiss->GetUser();
Account account; Account account;
Category category; Category category;
std::map<wxString, wxString> accounts;
std::map<wxString, wxString> categories;
wxString oldid;
for(i=0; i<_accountsGrid->GetNumberRows(); i++) for(i=0; i<_accountsGrid->GetNumberRows(); i++)
{ {
if (_accountsGrid->GetCellValue(i, 2) == _("Create one")) if (_accountsGrid->GetCellValue(i, 2) == _("Create one"))
nbAccounts++; nbAccounts++;
else else
resolvedAccounts[_accountsGrid->GetCellValue(i, 0)] = accounts[_accountsGrid->GetCellValue(i, 0)] =
user->GetAccountId(_accountsGrid->GetCellValue(i, 1)); user->GetAccountId(_accountsGrid->GetCellValue(i, 1));
} }
@ -270,7 +269,7 @@ void ImportPanel::OnLoadOperations(wxCommandEvent& WXUNUSED(event))
if (_categoriesGrid->GetCellValue(i, 2) == _("Create one")) if (_categoriesGrid->GetCellValue(i, 2) == _("Create one"))
nbCategories++; nbCategories++;
else else
resolvedCategories[_categoriesGrid->GetCellValue(i, 0)] = categories[_categoriesGrid->GetCellValue(i, 0)] =
user->GetAccountId(_categoriesGrid->GetCellValue(i, 1)); user->GetAccountId(_categoriesGrid->GetCellValue(i, 1));
} }
@ -297,18 +296,15 @@ void ImportPanel::OnLoadOperations(wxCommandEvent& WXUNUSED(event))
{ {
if (_accountsGrid->GetCellValue(i, 2) == _("Create one")) if (_accountsGrid->GetCellValue(i, 2) == _("Create one"))
{ {
account = _unresolvedAccounts[i] ;
if (_accountsGrid->GetCellValue(i, 1).Length()) if (_accountsGrid->GetCellValue(i, 1).Length())
account.name = _accountsGrid->GetCellValue(i, 1); account.name = _accountsGrid->GetCellValue(i, 1);
else else
account.name = _accountsGrid->GetCellValue(i, 0); account.name = _accountsGrid->GetCellValue(i, 0);
account.number = _accountsGrid->GetCellValue(i, 0); account.number = _accountsGrid->GetCellValue(i, 0);
account.shared = false;
account.blocked = false;
account._default = false;
account.is_owner = true;
account._virtual = false;
resolvedAccounts[_accountsGrid->GetCellValue(i, 0)] = _kiss->AddAccount(account); oldid = account.id;
_resolvedAccounts[oldid] = accounts[_accountsGrid->GetCellValue(i, 0)] = _kiss->AddAccount(account);
} }
} }
@ -318,16 +314,14 @@ void ImportPanel::OnLoadOperations(wxCommandEvent& WXUNUSED(event))
{ {
if (_categoriesGrid->GetCellValue(i, 2) == _("Create one")) if (_categoriesGrid->GetCellValue(i, 2) == _("Create one"))
{ {
category = _unresolvedCategories[i] ;
if (_categoriesGrid->GetCellValue(i, 1).Length()) if (_categoriesGrid->GetCellValue(i, 1).Length())
category.name = _categoriesGrid->GetCellValue(i, 1); category.name = _categoriesGrid->GetCellValue(i, 1);
else else
category.name = _categoriesGrid->GetCellValue(i, 0); category.name = _categoriesGrid->GetCellValue(i, 0);
category.parent = wxT("0");
category.backcolor = OWN_GREEN ; oldid = category.id;
category.forecolor = *wxBLACK; _resolvedCategories[oldid] = categories[_categoriesGrid->GetCellValue(i, 0)] = category.id = _kiss->AddCategory(category);
category.fix_cost = false;
resolvedCategories[_categoriesGrid->GetCellValue(i, 0)] = category.id = _kiss->AddCategory(category);
} }
} }
@ -336,7 +330,7 @@ void ImportPanel::OnLoadOperations(wxCommandEvent& WXUNUSED(event))
_wxUI->NeedReload(); _wxUI->NeedReload();
} }
_operations = _importEngine->GetOperations(resolvedAccounts, resolvedCategories); _operations = _importEngine->GetOperations(accounts, categories);
if (_operations->size()) if (_operations->size())
{ {
@ -361,6 +355,12 @@ void ImportPanel::OnLoadOperations(wxCommandEvent& WXUNUSED(event))
void ImportPanel::OnIntegrate(wxCommandEvent& WXUNUSED(event)) void ImportPanel::OnIntegrate(wxCommandEvent& WXUNUSED(event))
{ {
int i; int i;
std::map<wxString, wxString> mapid;
wxString oldid, account;
bool update;
std::map<AccountAmount, double, AccountAmount> accountAmounts;
std::map<AccountAmount, double, AccountAmount>::iterator it;
double amount;
if (!_operations->size()) return; if (!_operations->size()) return;
@ -371,9 +371,48 @@ void ImportPanel::OnIntegrate(wxCommandEvent& WXUNUSED(event))
_buttonIntegrate->Disable(); _buttonIntegrate->Disable();
for(i=0; i<(int)_operations->size(); i++) for(i=0; i<(int)_operations->size(); i++)
_kiss->AddOperation((*_operations)[i]); {
oldid = (*_operations)[i].id;
_kiss->AddOperation((*_operations)[i], false);
mapid[oldid] = (*_operations)[i].id;
}
// if (_checkSaveImportPatterns->IsChecked()) for(i=0; i<(int)_operations->size(); i++)
{
update = false;
if ((*_operations)[i].parent.Length())
{
(*_operations)[i].parent = mapid[(*_operations)[i].parent];
update = true;
}
if ((*_operations)[i].transfert.Length())
{
(*_operations)[i].transfert = mapid[(*_operations)[i].transfert];
update = true;
}
if (update)
_kiss->UpdateOperation((*_operations)[i], false);
}
accountAmounts = _importEngine->GetAccountAmounts();
for(it=accountAmounts.begin(); it!=accountAmounts.end(); it++)
{
account = it->first.account;
if (_resolvedAccounts.count(account))
account = _resolvedAccounts[account];
amount = _kiss->GetAccountAmount(account, it->first.month, it->first.year);
if (!amount)
_kiss->SetAccountAmount(account, it->first.month, it->first.year, it->second);
}
if (_checkSaveImportPatterns->IsChecked())
_kiss->UpdateImportPattern(); _kiss->UpdateImportPattern();
_operations->clear(); _operations->clear();

View File

@ -61,6 +61,11 @@ private:
wxCheckBox *_checkSaveImportPatterns; wxCheckBox *_checkSaveImportPatterns;
std::vector<Operation>* _operations; std::vector<Operation>* _operations;
std::vector<Account> _unresolvedAccounts;
std::vector<Category> _unresolvedCategories;
std::map<wxString, wxString> _resolvedAccounts;
std::map<wxString, wxString> _resolvedCategories;
void ProcessFile(); void ProcessFile();
DECLARE_EVENT_TABLE(); DECLARE_EVENT_TABLE();

View File

@ -26,11 +26,6 @@ EVT_CALENDAR_SEL_CHANGED(CALENDAR_TO_ID, SearchBanner::OnCalendarToChange)
EVT_TEXT_ENTER(DESCRIPTION_ID, SearchBanner::OnEnter) EVT_TEXT_ENTER(DESCRIPTION_ID, SearchBanner::OnEnter)
END_EVENT_TABLE() END_EVENT_TABLE()
#define UNESCAPE_CHARS(s) { \
s.Replace(wxT("\\\""), wxT("\""), true); \
s.Replace(wxT("\\\'"), wxT("\'"), true); \
}
SearchBanner::SearchBanner(KissCount* kiss, wxPanel *parent, void* caller, OnButtonEnter enterCallback) : wxPanel(parent), _kiss(kiss), _caller(caller), _enterCallback(enterCallback), _operations(NULL) SearchBanner::SearchBanner(KissCount* kiss, wxPanel *parent, void* caller, OnButtonEnter enterCallback) : wxPanel(parent), _kiss(kiss), _caller(caller), _enterCallback(enterCallback), _operations(NULL)
{ {
DEFAULT_FONT(font); DEFAULT_FONT(font);
@ -38,7 +33,6 @@ SearchBanner::SearchBanner(KissCount* kiss, wxPanel *parent, void* caller, OnBut
std::vector<Account>::iterator accountIt; std::vector<Account>::iterator accountIt;
std::vector<Category>::iterator categoryIt; std::vector<Category>::iterator categoryIt;
wxDateTime firstOfMonth; wxDateTime firstOfMonth;
wxRect rect = wxDisplay().GetGeometry();
wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL); wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);

View File

@ -30,11 +30,6 @@
SetCellFont(row, i, font); \ SetCellFont(row, i, font); \
} }
#define UNESCAPE_CHARS(s) { \
s.Replace(wxT("\\\""), wxT("\""), true); \
s.Replace(wxT("\\\'"), wxT("\'"), true); \
}
BEGIN_EVENT_TABLE(GridAccount, wxGrid) BEGIN_EVENT_TABLE(GridAccount, wxGrid)
EVT_GRID_CELL_LEFT_CLICK(GridAccount::OnCellLeftClick ) EVT_GRID_CELL_LEFT_CLICK(GridAccount::OnCellLeftClick )
END_EVENT_TABLE() END_EVENT_TABLE()
@ -665,7 +660,7 @@ void GridAccount::OnOperationModified(wxGridEvent& event)
int op_complete = 6, i, last_day; int op_complete = 6, i, last_day;
wxString value ; wxString value ;
wxDateTime date; wxDateTime date;
bool need_insertion = false, fix_op=false; bool need_insertion = false;
static bool inModification = false ; static bool inModification = false ;
wxColour color ; wxColour color ;
unsigned char r, g, b; unsigned char r, g, b;
@ -946,8 +941,6 @@ void GridAccount::OnOperationModified(wxGridEvent& event)
UpdateOperation(new_op); UpdateOperation(new_op);
(_displayedOperations)[row] = new_op; (_displayedOperations)[row] = new_op;
} }
fix_op = true;
} }
// Add a fixCost // Add a fixCost
else if (row == _fixCosts) else if (row == _fixCosts)
@ -957,7 +950,6 @@ void GridAccount::OnOperationModified(wxGridEvent& event)
return ; return ;
} }
need_insertion = true; need_insertion = true;
fix_op = true;
new_op.fix_cost = true; new_op.fix_cost = true;
new_op.meta = false; new_op.meta = false;
new_op._virtual = false; new_op._virtual = false;
@ -1058,7 +1050,6 @@ void GridAccount::OnOperationModified(wxGridEvent& event)
return ; return ;
} }
need_insertion = true; need_insertion = true;
fix_op = false;
new_op.fix_cost = false; new_op.fix_cost = false;
new_op.meta = false; new_op.meta = false;
new_op._virtual = false; new_op._virtual = false;