/* HomeBank -- Free, easy, personal accounting for everyone.
* Copyright (C) 1995-2014 Maxime DOYEN
*
* This file is part of HomeBank.
*
* HomeBank 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.
*
* HomeBank 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 this program. If not, see .
*/
#include "homebank.h"
#include "import.h"
#include "list_account.h"
#include "list_operation.h"
#include "ui-account.h"
#include "dsp_mainwindow.h"
#include "imp_qif.h"
#ifndef NOOFX
#include
#endif
/****************************************************************************/
/* Debug macros */
/****************************************************************************/
#define MYDEBUG 0
#if MYDEBUG
#define DB(x) (x);
#else
#define DB(x);
#endif
#define FORCE_SIZE 1
#define HEAD_IMAGE 1
#define SIDE_IMAGE 0
#define SCOEF 0.6
/* our global datas */
extern struct HomeBank *GLOBALS;
extern struct Preferences *PREFS;
static gchar *page_titles[] =
{
N_("HomeBank Import Assistant"),
N_("File to import"),
N_("File analysis results"),
N_("Adjust what to import"),
N_("Update your accounts")
};
extern gchar *CYA_IMPORT_DATEORDER[];
static GtkWidget *ui_acc_affect_listview_new(void);
guint32 ui_acc_affect_listview_get_selected_key(GtkTreeView *treeview);
void ui_acc_affect_listview_add(GtkTreeView *treeview, Account *item);
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
Account *import_create_account(gchar *name, gchar *number)
{
Account *accitem, *existitem;
//first check we do not have already this imported account
existitem = da_acc_get_by_imp_name(name);
if(existitem != NULL)
return existitem;
accitem = da_acc_malloc();
accitem->key = da_acc_get_max_key() + 1;
accitem->pos = da_acc_length() + 1;
// then we check a same named account
existitem = da_acc_get_by_name(name);
if(existitem == NULL)
{
accitem->name = g_strdup(name);
}
else
{
accitem->name = g_strdup_printf(_("(account %d)"), accitem->key);
}
accitem->imp_name = g_strdup(name);
if(number)
accitem->number = g_strdup(number);
accitem->imported = TRUE;
da_acc_insert(accitem);
return accitem;
}
static GList *homebank_csv_import(gchar *filename, ImportContext *ictx)
{
GIOChannel *io;
GList *list = NULL;
static gint csvtype[7] = {
CSV_DATE,
CSV_INT,
CSV_STRING,
CSV_STRING,
CSV_STRING,
CSV_DOUBLE,
CSV_STRING,
};
DB( g_print("\n[import] homebank csv\n") );
io = g_io_channel_new_file(filename, "r", NULL);
if(io != NULL)
{
gchar *tmpstr;
gint io_stat;
gboolean valid;
gint count = 0;
gint error = 0;
Account *tmp_acc;
Payee *payitem;
Category *catitem;
GError *err = NULL;
gchar *accname = g_strdup_printf(_("(account %d)"), da_acc_get_max_key() + 1);
tmp_acc = import_create_account(accname, NULL);
g_free(accname);
if( ictx->encoding != NULL )
{
g_io_channel_set_encoding(io, ictx->encoding, NULL);
}
for(;;)
{
io_stat = g_io_channel_read_line(io, &tmpstr, NULL, NULL, &err);
if( io_stat == G_IO_STATUS_EOF)
break;
if( io_stat == G_IO_STATUS_ERROR )
{
DB (g_print(" + ERROR %s\n",err->message));
break;
}
if( io_stat == G_IO_STATUS_NORMAL)
{
if( *tmpstr != '\0' )
{
gchar **str_array;
Transaction *newope = da_transaction_malloc();
hb_string_strip_crlf(tmpstr);
/* control validity here */
valid = hb_string_csv_valid(tmpstr, 8, csvtype);
//DB( g_print("valid %d, '%s'\n", valid, tmpstr) );
if( !valid )
{
error++;
}
else
{
count++;
str_array = g_strsplit (tmpstr, ";", 8);
// 0:date; 1:paymode; 2:info; 3:payee, 4:wording; 5:amount; 6:category; 7:tags
DB( g_print(" ->%s\n", tmpstr ) );
newope->date = hb_date_get_julian(str_array[0], ictx->datefmt);
if( newope->date == 0 )
ictx->cnt_err_date++;
newope->paymode = atoi(str_array[1]);
newope->info = g_strdup(str_array[2]);
/* payee */
g_strstrip(str_array[3]);
payitem = da_pay_get_by_name(str_array[3]);
if(payitem == NULL)
{
payitem = da_pay_malloc();
payitem->name = g_strdup(str_array[3]);
payitem->imported = TRUE;
da_pay_append(payitem);
if( payitem->imported == TRUE )
ictx->cnt_new_pay += 1;
}
newope->kpay = payitem->key;
newope->wording = g_strdup(str_array[4]);
newope->amount = hb_qif_parser_get_amount(str_array[5]);
/* category */
g_strstrip(str_array[6]);
catitem = da_cat_append_ifnew_by_fullname(str_array[6], TRUE);
if( catitem != NULL )
{
newope->kcat = catitem->key;
if( catitem->imported == TRUE && catitem->key > 0 )
ictx->cnt_new_cat += 1;
}
/* tags */
transaction_tags_parse(newope, str_array[7]);
newope->kacc = tmp_acc->key;
//newope->kxferacc = accnum;
newope->flags |= OF_ADDED;
if( newope->amount > 0)
newope->flags |= OF_INCOME;
/*
DB( g_print(" storing %s : %s : %s :%s : %s : %s : %s : %s\n",
str_array[0], str_array[1], str_array[2],
str_array[3], str_array[4], str_array[5],
str_array[6], str_array[7]
) );
*/
list = g_list_append(list, newope);
g_strfreev (str_array);
}
}
g_free(tmpstr);
}
}
g_io_channel_unref (io);
/*
ui_dialog_msg_infoerror(data->window, error > 0 ? GTK_MESSAGE_ERROR : GTK_MESSAGE_INFO,
_("Transaction CSV import result"),
_("%d transactions inserted\n%d errors in the file"),
count, error);
*/
}
return list;
}
#ifndef NOOFX
/*
**** OFX part
****
**** this part is quite weird,but works
** id is ACCTID
*/
static Account * ofx_get_account_by_id(gchar *id)
{
GList *lacc, *list;
DB( g_print("\n[import] ofx_get_account_by_id\n") );
DB( g_print(" -> searching for '%s'\n",id) );
lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
while (list != NULL)
{
Account *accitem = list->data;
if( accitem->imported == FALSE)
{
if(accitem->name && accitem->number && strlen(accitem->number) )
{
// todo: maybe smartness should be done here
if(g_strstr_len(id, -1, accitem->number) != NULL)
{
return accitem;
}
}
}
list = g_list_next(list);
}
g_list_free(lacc);
return NULL;
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
/**
* ofx_proc_account_cb:
*
* The ofx_proc_account_cb event is always generated first, to allow the application to create accounts
* or ask the user to match an existing account before the ofx_proc_statement and ofx_proc_transaction
* event are received. An OfxAccountData is passed to this event.
*
*/
static LibofxProcStatementCallback
ofx_proc_account_cb(const struct OfxAccountData data, OfxContext *ctx)
{
Account *tmp_acc, *dst_acc;
DB( g_print("** ofx_proc_account_cb()\n") );
if(data.account_id_valid==true)
{
DB( g_print(" account_id: %s\n", data.account_id) );
DB( g_print(" account_name: %s\n", data.account_name) );
}
//if(data.account_number_valid==true)
//{
DB( g_print(" account_number: %s\n", data.account_number) );
//}
if(data.account_type_valid==true)
{
DB( g_print(" account_type: %d\n", data.account_type) );
}
if(data.currency_valid==true)
{
DB( g_print(" currency: %s\n", data.currency) );
}
//find target account
dst_acc = ofx_get_account_by_id( (gchar *)data.account_id );
DB( g_print(" ** hb account found result is %x\n", (unsigned int)dst_acc) );
// in every case we create an account here
tmp_acc = import_create_account((gchar *)data.account_name, (gchar *)data.account_id);
DB( g_print(" -> creating tmp account: %d %s - %x\n", tmp_acc->key, data.account_id, (unsigned int)tmp_acc) );
if( dst_acc != NULL )
{
tmp_acc->imp_key = dst_acc->key;
}
ctx->curr_acc = tmp_acc;
ctx->curr_acc_isnew = TRUE;
DB( fputs("\n",stdout) );
return 0;
}
/**
* ofx_proc_statement_cb:
*
* The ofx_proc_statement_cb event is sent after all ofx_proc_transaction events have been sent.
* An OfxStatementData is passed to this event.
*
*/
static LibofxProcStatementCallback
ofx_proc_statement_cb(const struct OfxStatementData data, OfxContext *ctx)
{
DB( g_print("** ofx_proc_statement_cb()\n") );
#ifdef MYDEBUG
if(data.ledger_balance_date_valid==true)
{
struct tm temp_tm;
temp_tm = *localtime(&(data.ledger_balance_date));
g_print("ledger_balance_date : %d%s%d%s%d%s", temp_tm.tm_mday, "/", temp_tm.tm_mon+1, "/", temp_tm.tm_year+1900, "\n");
}
#endif
if(data.ledger_balance_valid==true)
{
if( ctx->curr_acc != NULL && ctx->curr_acc_isnew == TRUE )
{
ctx->curr_acc->initial = data.ledger_balance;
}
DB( printf("ledger_balance: $%.2f%s",data.ledger_balance,"\n") );
}
return 0;
}
/**
* ofx_proc_statement_cb:
*
* An ofx_proc_transaction_cb event is generated for every transaction in the ofx response,
* after ofx_proc_statement (and possibly ofx_proc_security is generated.
* An OfxTransactionData structure is passed to this event.
*
*/
static LibofxProcStatementCallback
ofx_proc_transaction_cb(const struct OfxTransactionData data, OfxContext *ctx)
{
struct tm temp_tm;
GDate *date;
Transaction *newope;
DB( g_print("** ofx_proc_transaction_cb()\n") );
newope = da_transaction_malloc();
// date
if(data.date_posted_valid==true)
{
temp_tm = *localtime(&(data.date_posted));
date = g_date_new();
g_date_set_dmy(date, temp_tm.tm_mday, temp_tm.tm_mon+1, temp_tm.tm_year+1900);
newope->date = g_date_get_julian(date);
g_date_free(date);
}
// amount
if(data.amount_valid==true)
{
newope->amount = data.amount;
}
// check number
if(data.check_number_valid==true)
{
newope->info = g_strdup(data.check_number);
}
//todo: reference_number ?
// wording
if(data.name_valid==true)
{
newope->wording = g_strdup(data.name);
}
//memo ( new for v4.2)
DB( g_print(" -> memo is='%d'\n", data.memo_valid) );
if(data.memo_valid==true)
{
gchar *old = NULL;
switch(PREFS->dtex_ofxmemo)
{
case 1: //add to info
old = newope->info;
if(old == NULL)
newope->info = g_strdup(data.memo);
else
{
newope->info = g_strjoin(" ", old, data.memo, NULL);
g_free(old);
}
break;
case 2: //add to description
old = newope->wording;
if(old == NULL)
newope->wording = g_strdup(data.memo);
else
{
newope->wording = g_strjoin(" ", old, data.memo, NULL);
g_free(old);
}
DB( g_print(" -> should concatenate ='%s'\n", data.memo) );
DB( g_print(" -> old='%s', new ='%s'\n", old, newope->wording) );
break;
}
}
// payment
if(data.transactiontype_valid==true)
{
switch(data.transactiontype)
{
//#740373
case OFX_CREDIT:
if(newope->amount < 0)
newope->amount *= -1;
break;
case OFX_DEBIT:
if(newope->amount > 0)
newope->amount *= -1;
break;
case OFX_INT:
newope->paymode = PAYMODE_XFER;
break;
case OFX_DIV:
newope->paymode = PAYMODE_XFER;
break;
case OFX_FEE:
newope->paymode = PAYMODE_FEE;
break;
case OFX_SRVCHG:
newope->paymode = PAYMODE_XFER;
break;
case OFX_DEP:
newope->paymode = PAYMODE_DEPOSIT;
break;
case OFX_ATM:
newope->paymode = PAYMODE_CASH;
break;
case OFX_POS:
if(ctx->curr_acc && ctx->curr_acc->type == ACC_TYPE_CREDITCARD)
newope->paymode = PAYMODE_CCARD;
else
newope->paymode = PAYMODE_DCARD;
break;
case OFX_XFER:
newope->paymode = PAYMODE_XFER;
break;
case OFX_CHECK:
newope->paymode = PAYMODE_CHECK;
break;
case OFX_PAYMENT:
newope->paymode = PAYMODE_EPAYMENT;
break;
case OFX_CASH:
newope->paymode = PAYMODE_CASH;
break;
case OFX_DIRECTDEP:
newope->paymode = PAYMODE_DEPOSIT;
break;
case OFX_DIRECTDEBIT:
newope->paymode = PAYMODE_XFER;
break;
case OFX_REPEATPMT:
newope->paymode = PAYMODE_REPEATPMT;
break;
case OFX_OTHER:
break;
default :
break;
}
}
if( ctx->curr_acc )
{
newope->kacc = ctx->curr_acc->key;
newope->flags |= OF_ADDED;
if( newope->amount > 0)
newope->flags |= OF_INCOME;
/* ensure utf-8 here, has under windows, libofx not always return utf-8 as it should */
#ifndef G_OS_UNIX
DB( printf(" ensure UTF-8\n") );
newope->info = homebank_utf8_ensure(newope->info);
newope->wording = homebank_utf8_ensure(newope->wording);
#endif
ctx->trans_list = g_list_append(ctx->trans_list, newope);
DB( printf(" insert newope: acc=%d\n", newope->kacc) );
if( ctx->curr_acc_isnew == TRUE )
{
ctx->curr_acc->initial -= data.amount;
}
}
else
{
da_transaction_free(newope);
}
return 0;
}
static LibofxProcStatusCallback
ofx_proc_status_cb(const struct OfxStatusData data, OfxContext *ctx)
{
DB( g_print("** ofx_proc_status_cb()\n") );
if(data.ofx_element_name_valid==true){
DB( g_print(" Ofx entity this status is relevent to: '%s'\n", data.ofx_element_name) );
}
if(data.severity_valid==true){
DB( g_print(" Severity: ") );
switch(data.severity){
case INFO : DB( g_print("INFO\n") );
break;
case WARN : DB( g_print("WARN\n") );
break;
case ERROR : DB( g_print("ERROR\n") );
break;
default: DB( g_print("WRITEME: Unknown status severity!\n") );
}
}
if(data.code_valid==true){
DB( g_print(" Code: %d, name: %s\n Description: %s\n", data.code, data.name, data.description) );
}
if(data.server_message_valid==true){
DB( g_print(" Server Message: %s\n", data.server_message) );
}
DB( g_print("\n") );
return 0;
}
static GList *homebank_ofx_import(gchar *filename, ImportContext *ictx)
{
OfxContext ctx = { 0 };
/*extern int ofx_PARSER_msg;
extern int ofx_DEBUG_msg;
extern int ofx_WARNING_msg;
extern int ofx_ERROR_msg;
extern int ofx_INFO_msg;
extern int ofx_STATUS_msg;*/
DB( g_print("\n[import] ofx import (libofx=%s) \n", LIBOFX_VERSION_RELEASE_STRING) );
/*ofx_PARSER_msg = false;
ofx_DEBUG_msg = false;
ofx_WARNING_msg = false;
ofx_ERROR_msg = false;
ofx_INFO_msg = false;
ofx_STATUS_msg = false;*/
LibofxContextPtr libofx_context = libofx_get_new_context();
ofx_set_status_cb (libofx_context, (LibofxProcStatusCallback) ofx_proc_status_cb , &ctx);
ofx_set_statement_cb (libofx_context, (LibofxProcStatementCallback) ofx_proc_statement_cb , &ctx);
ofx_set_account_cb (libofx_context, (LibofxProcAccountCallback) ofx_proc_account_cb , &ctx);
ofx_set_transaction_cb(libofx_context, (LibofxProcTransactionCallback)ofx_proc_transaction_cb, &ctx);
#ifdef G_OS_WIN32
//#932959: windows don't like utf8 path, so convert
gchar *file = g_win32_locale_filename_from_utf8(filename);
libofx_proc_file(libofx_context, file, AUTODETECT);
g_free(file);
#else
libofx_proc_file(libofx_context, filename, AUTODETECT);
#endif
libofx_free_context(libofx_context);
return ctx.trans_list;
}
#endif
static GList *homebank_qif_import(gchar *filename, ImportContext *ictx)
{
GList *list = NULL;
DB( g_print("\n[import] homebank QIF\n") );
//todo: context ?
list = account_import_qif(filename, ictx);
return list;
}
static void import_clearall(struct import_data *data)
{
GList *lxxx, *list;
GtkTreeModel *model;
DB( g_print("\n[import] clear all\n") );
// clear transactions
model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->imported_ope));
gtk_list_store_clear (GTK_LIST_STORE(model));
// 1: remove imported accounts
lxxx = list = g_hash_table_get_values(GLOBALS->h_acc);
while (list != NULL)
{
Account *item = list->data;
if( item->imported == TRUE )
{
//DB( g_print(" -> remove acc %x '%s'\n", item, item->name) );
da_acc_remove(item->key);
}
list = g_list_next(list);
}
g_list_free(lxxx);
// 2: remove imported payees
lxxx = list = g_hash_table_get_values(GLOBALS->h_pay);
while (list != NULL)
{
Payee *item = list->data;
if( item->imported == TRUE )
{
//DB( g_print(" -> remove pay '%s'\n", item->name) );
da_pay_remove(item->key);
}
list = g_list_next(list);
}
g_list_free(lxxx);
// 3: remove imported category
lxxx = list = g_hash_table_get_values(GLOBALS->h_cat);
while (list != NULL)
{
Category *item = list->data;
if( item->imported == TRUE )
{
//DB( g_print(" -> remove cat '%s'\n", item->name) );
da_cat_remove(item->key);
}
list = g_list_next(list);
}
g_list_free(lxxx);
da_transaction_destroy(data->ictx.trans_list);
data->ictx.trans_list = NULL;
data->ictx.cnt_err_date = 0;
data->ictx.cnt_new_pay = 0;
data->ictx.cnt_new_cat = 0;
data->ictx.datefmt = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_dateorder));
data->ictx.cnt_initial_acc = da_acc_length();
}
/*
* find duplicate transactions
*
* for
*
*/
static void import_find_duplicate_transactions(struct import_data *data)
{
GList *tmplist, *implist;
Transaction *item;
guint32 mindate;
guint maxgap;
DB( g_print("\n[import] find duplicate\n") );
data->ictx.nb_duplicate = 0;
if( data->ictx.trans_list )
{
/* 1: get import min bound date */
tmplist = g_list_first(data->ictx.trans_list);
item = tmplist->data;
mindate = item->date;
maxgap = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_maxgap));
/* clear any previous same txn */
implist = g_list_first(data->ictx.trans_list);
while (implist != NULL)
{
Transaction *impope = implist->data;
if(impope->same != NULL)
{
g_list_free(impope->same);
impope->same = NULL;
}
implist = g_list_next(implist);
}
tmplist = g_list_first(GLOBALS->ope_list);
while (tmplist != NULL)
{
Transaction *ope = tmplist->data;
//if( ope->account == accnum && ope->date >= mindate )
if( ope->date >= mindate )
{
//DB( g_print("should check here %d: %s\n", ope->date, ope->wording) );
implist = g_list_first(data->ictx.trans_list);
while (implist != NULL)
{
Transaction *impope = implist->data;
Account *acc;
guint acckey;
//here we should test acc->imp_key and not impope->account
acckey = impope->kacc;
acc = da_acc_get(acckey);
if( acc )
{
if( acc->imp_key > 0 )
acckey = acc->imp_key;
}
if(
(acckey == ope->kacc) &&
(impope->amount == ope->amount) &&
(ope->date <= (impope->date + maxgap)) && (ope->date >= (impope->date - maxgap))
)
{
//DB( g_print(" found %d: %s\n", impope->date, impope->wording) );
impope->same = g_list_append(impope->same, ope);
data->ictx.nb_duplicate++;
}
implist = g_list_next(implist);
}
}
tmplist = g_list_next(tmplist);
}
}
DB( g_print(" nb_duplicate = %d\n", data->ictx.nb_duplicate) );
}
static void ui_import_populate_account(struct import_data *data)
{
GList *lacc, *list;
DB( g_print("\n[import] populate account\n") );
// clear accounts
gtk_list_store_clear (GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc))));
lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
while (list != NULL)
{
Account *item = list->data;
if( item->imported == TRUE )
{
ui_acc_affect_listview_add(GTK_TREE_VIEW(data->LV_acc), item);
}
list = g_list_next(list);
}
g_list_free(lacc);
}
/* count account to be imported */
static void import_analysis_count(struct import_data *data)
{
GList *lacc, *list;
DB( g_print("\n[import] count_new_account\n") );
data->ictx.cnt_new_acc = 0;
data->ictx.cnt_new_ope = 0;
/* count account */
lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
while (list != NULL)
{
Account *item = list->data;
if( item->imported == TRUE )
{
data->ictx.cnt_new_acc++;
}
list = g_list_next(list);
}
g_list_free(lacc);
/* count transaction */
data->ictx.cnt_new_ope = g_list_length(data->ictx.trans_list);
}
/* count transaction with checkbox 'import' */
static void import_count_changes(struct import_data *data)
{
GList *lacc, *list;
GtkTreeModel *model;
GtkTreeIter iter;
gboolean valid;
DB( g_print("\n[import] count_final_changes\n") );
data->imp_cnt_acc = 0;
lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
while (list != NULL)
{
Account *item = list->data;
if( item->imported == TRUE && item->imp_key != 0)
{
data->imp_cnt_acc++;
}
list = g_list_next(list);
}
g_list_free(lacc);
// then import transactions
model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->imported_ope));
data->imp_cnt_trn = 0;
valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
while (valid)
{
gboolean toimport;
gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
LST_OPE_IMPTOGGLE, &toimport,
-1);
if(toimport == TRUE)
data->imp_cnt_trn++;
/* Make iter point to the next row in the list store */
valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
}
}
static void import_apply(struct import_data *data)
{
GtkTreeModel *model;
GtkTreeIter iter;
gboolean valid;
GList *lxxx, *list;
DB( g_print("\n[import] apply\n") );
// 1: persist imported accounts
lxxx = list = g_hash_table_get_values(GLOBALS->h_acc);
while (list != NULL)
{
Account *item = list->data;
if( item->imported == TRUE )
{
//only persist user selected to new account
if( item->imp_key == 0)
{
//DB( g_print(" -> persist acc %x '%s'\n", item, item->name) );
item->imported = FALSE;
g_free(item->imp_name);
item->imp_name = NULL;
}
}
list = g_list_next(list);
}
g_list_free(lxxx);
// 2: persist imported payees
lxxx = list = g_hash_table_get_values(GLOBALS->h_pay);
while (list != NULL)
{
Payee *item = list->data;
if( item->imported == TRUE )
{
//DB( g_print(" -> persist pay '%s'\n", item->name) );
item->imported = FALSE;
}
list = g_list_next(list);
}
g_list_free(lxxx);
// 3: persist imported categories
lxxx = list = g_hash_table_get_values(GLOBALS->h_cat);
while (list != NULL)
{
Category *item = list->data;
if( item->imported == TRUE )
{
//DB( g_print(" -> persist cat '%s'\n", item->name) );
item->imported = FALSE;
}
list = g_list_next(list);
}
g_list_free(lxxx);
// 4: insert every transactions
model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->imported_ope));
valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
while (valid)
{
Transaction *item;
gboolean toimport;
gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
LST_DSPOPE_DATAS, &item,
LST_OPE_IMPTOGGLE, &toimport,
-1);
if(toimport == TRUE)
{
Account *acc;
//DB(g_print("import %d to acc: %d\n", data->total, item->account) );
//todo: here also test imp_key on account and change the key into the transaction
acc = da_acc_get(item->kacc);
if( acc != NULL)
{
if( acc->imp_key > 0)
{
item->kacc = acc->imp_key;
}
}
transaction_add(item, NULL, 0);
}
/* Make iter point to the next row in the list store */
valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
}
}
/*
**
*/
static gboolean
import_dispose(GtkWidget *widget, gpointer user_data)
{
struct import_data *data = user_data;
DB( g_print("\n[import] dispose\n") );
#if MYDEBUG == 1
gpointer data2 = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
g_print(" user_data=%08x to be free, data2=%x\n", (gint)user_data, (gint)data2);
#endif
g_free( data->filename );
import_clearall(data);
// todo: optimize this
if(data->imp_cnt_trn > 0)
{
GLOBALS->changes_count += data->imp_cnt_trn;
//our global list has changed, so update the treeview
ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_REFRESHALL));
}
g_free(user_data);
//delete-event TRUE abort/FALSE destroy
return FALSE;
}
static void import_fill_imp_transactions(struct import_data *data)
{
GtkWidget *view;
GtkTreeModel *model;
GtkTreeIter iter;
GList *tmplist;
DB( g_print("\n[import] fill imp operatoin\n") );
view = data->imported_ope;
model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
gtk_list_store_clear (GTK_LIST_STORE(model));
g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
gtk_tree_view_set_model(GTK_TREE_VIEW(view), NULL); /* Detach model from view */
tmplist = g_list_first(data->ictx.trans_list);
while (tmplist != NULL)
{
Transaction *item = tmplist->data;
/* append to our treeview */
gtk_list_store_append (GTK_LIST_STORE(model), &iter);
//DB( g_print(" populate: %s\n", ope->ope_Word) );
gtk_list_store_set (GTK_LIST_STORE(model), &iter,
LST_DSPOPE_DATAS, item,
LST_OPE_IMPTOGGLE, item->same == NULL ? TRUE : FALSE,
-1);
//DB( g_print(" - fill: %d, %s %.2f %x\n", item->account, item->wording, item->amount, item->same) );
tmplist = g_list_next(tmplist);
}
gtk_tree_view_set_model(GTK_TREE_VIEW(view), model); /* Re-attach model to view */
g_object_unref(model);
}
static void import_fillsame(GtkWidget *widget, gpointer user_data)
{
struct import_data *data;
GtkTreeSelection *selection;
GtkTreeModel *model, *newmodel;
GtkTreeIter iter, newiter;
GList *tmplist;
GtkWidget *view;
DB( g_print("\n[import] fillsame\n") );
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
view = data->duplicat_ope;
newmodel = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
gtk_list_store_clear (GTK_LIST_STORE(newmodel));
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->imported_ope));
//if true there is a selected node
if (gtk_tree_selection_get_selected(selection, &model, &iter))
{
Transaction *item;
gtk_tree_model_get(model, &iter, LST_DSPOPE_DATAS, &item, -1);
if( item->same != NULL )
{
tmplist = g_list_first(item->same);
while (tmplist != NULL)
{
Transaction *tmp = tmplist->data;
/* append to our treeview */
gtk_list_store_append (GTK_LIST_STORE(newmodel), &newiter);
gtk_list_store_set (GTK_LIST_STORE(newmodel), &newiter,
LST_DSPOPE_DATAS, tmp,
-1);
DB( g_print(" - fill: %s %.2f %x\n", item->wording, item->amount, (unsigned int)item->same) );
tmplist = g_list_next(tmplist);
}
}
}
}
/*
** modify target account
*/
static void on_account_type_toggled(GtkRadioButton *radiobutton, gpointer user_data)
{
struct import_target_data *data;
gboolean new_account;
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(radiobutton), GTK_TYPE_WINDOW)), "inst_data");
DB( g_print("\n[import] account type toggle\n") );
new_account = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->radio[0]));
gtk_widget_set_sensitive(data->getwidget1, new_account);
gtk_widget_set_sensitive(data->getwidget2, new_account^1);
}
static void import_edit_target_account(GtkWidget *widget, gpointer user_data)
{
struct import_data *data;
struct import_target_data ddata;
GtkWidget *dialog, *content, *mainvbox, *table, *label ;
guint32 key;
gint row;
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
DB( g_print("\n[import] edit target account\n") );
key = ui_acc_affect_listview_get_selected_key(GTK_TREE_VIEW(data->LV_acc));
if( key > 0 )
{
Account *item;
item = da_acc_get( key );
dialog = gtk_dialog_new_with_buttons (_("Change HomeBank account target"),
GTK_WINDOW (data->assistant),
0,
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
NULL);
//store our window private data
g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)&ddata);
content = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
mainvbox = gtk_vbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (content), mainvbox, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER(mainvbox), HB_MAINBOX_SPACING);
table = gtk_table_new (3, 2, FALSE);
gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
gtk_box_pack_start (GTK_BOX (mainvbox), table, TRUE, TRUE, HB_BOX_SPACING);
/* area 1 : file summary */
row = 0;
ddata.radio[0] = gtk_radio_button_new_with_label (NULL, _("new account"));
gtk_table_attach (GTK_TABLE (table), ddata.radio[0], 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
label = make_label(_("_Name:"), 0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
ddata.getwidget1 = gtk_entry_new();
gtk_table_attach (GTK_TABLE (table), ddata.getwidget1, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
row++;
ddata.radio[1] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON (ddata.radio[0]), _("existing account"));
gtk_table_attach (GTK_TABLE (table), ddata.radio[1], 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
label = make_label(_("A_ccount:"), 0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
ddata.getwidget2 = ui_acc_comboboxentry_new(NULL);
gtk_table_attach (GTK_TABLE (table), ddata.getwidget2, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
//initialize
if( data->ictx.cnt_initial_acc > 0 ) //if there were already some accounts
{
gtk_widget_set_sensitive(ddata.radio[1], TRUE);
if( item->imp_key > 0 )
{
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ddata.radio[1]), TRUE);
}
}
else
{
gtk_widget_set_sensitive(ddata.radio[1], FALSE);
}
gtk_entry_set_text(GTK_ENTRY(ddata.getwidget1), item->name);
ui_acc_comboboxentry_populate(GTK_COMBO_BOX(ddata.getwidget2), GLOBALS->h_acc, ACC_LST_INSERT_NORMAL);
ui_acc_comboboxentry_set_active(GTK_COMBO_BOX(ddata.getwidget2), item->imp_key);
on_account_type_toggled(GTK_RADIO_BUTTON (ddata.radio[0]), NULL);
gtk_widget_show_all(mainvbox);
g_signal_connect (ddata.radio[0], "toggled", G_CALLBACK (on_account_type_toggled), NULL);
//wait for the user
gint result = gtk_dialog_run (GTK_DIALOG (dialog));
if(result == GTK_RESPONSE_ACCEPT)
{
gchar *name;
gboolean bnew;
guint key;
key = ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(ddata.getwidget2));
bnew = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ddata.radio[0]));
if( bnew )
{
name = (gchar *)gtk_entry_get_text(GTK_ENTRY(ddata.getwidget1));
if(strcasecmp(name, item->name))
{
DB( g_print("name '%s', existing acc %d\n", name, key) );
if (name && *name)
{
if( account_rename(item, name) == FALSE )
{
ui_dialog_msg_infoerror(GTK_WINDOW(dialog), GTK_MESSAGE_ERROR,
_("Error"),
_("Cannot rename this Account,\n"
"from '%s' to '%s',\n"
"this name already exists."),
item->name,
name
);
}
}
}
else
{
item->imp_key = 0;
}
}
else
{
item->imp_key = key;
}
//we should refresh duplicate
import_find_duplicate_transactions(data);
import_fill_imp_transactions(data);
}
// cleanup and destroy
gtk_widget_destroy (dialog);
}
}
static void ui_import_selchange(GtkWidget *widget, gpointer user_data)
{
struct import_data *data = user_data;
gint page_number;
GtkWidget *current_page;
gchar *filename;
page_number = gtk_assistant_get_current_page (GTK_ASSISTANT(data->assistant));
DB( g_print("\n[import] selchange (page %d)\n", page_number+1) );
data->valid = FALSE;
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(data->filechooser));
if( filename == NULL )
{
gtk_label_set_text(GTK_LABEL(data->user_info), _("Please select a file..."));
//current_page = gtk_assistant_get_nth_page (GTK_ASSISTANT(data->assistant), page_number);
//gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), current_page, FALSE);
}
else
{
if( page_number == PAGE_FILE )
{
if(data->filename)
g_free( data->filename );
data->filename = filename;
//DB( g_print(" filename -> %s\n", data->filename) );
data->filetype = homebank_alienfile_recognize(data->filename);
switch(data->filetype)
{
case FILETYPE_QIF:
gtk_label_set_text(GTK_LABEL(data->user_info), _("QIF file recognised !"));
data->valid = TRUE;
break;
case FILETYPE_OFX:
#ifndef NOOFX
gtk_label_set_text(GTK_LABEL(data->user_info), _("OFX file recognised !"));
data->valid = TRUE;
#else
gtk_label_set_text(GTK_LABEL(data->user_info), _("** OFX support is disabled **"));
#endif
break;
case FILETYPE_CSV_HB:
gtk_label_set_text(GTK_LABEL(data->user_info), _("CSV transaction file recognised !"));
data->valid = TRUE;
break;
default:
data->filetype = FILETYPE_UNKNOW;
gtk_label_set_text(GTK_LABEL(data->user_info), _("Unknown/Invalid file..."));
break;
}
current_page = gtk_assistant_get_nth_page (GTK_ASSISTANT(data->assistant), page_number);
gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), current_page, data->valid);
}
}
if(data->valid == TRUE)
{
gtk_widget_show(data->ok_image);
gtk_widget_hide(data->ko_image);
}
else
{
gtk_widget_show(data->ko_image);
gtk_widget_hide(data->ok_image);
}
}
static void ui_import_selection(GtkTreeSelection *treeselection, gpointer user_data)
{
import_fillsame(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), NULL);
}
static void ui_import_update_filecontent(struct import_data *data)
{
gchar *tmpstr;
/* file name & path */
tmpstr = g_path_get_basename(data->filename);
gtk_label_set_text(GTK_LABEL(data->TX_filename), tmpstr);
g_free(tmpstr);
tmpstr = g_path_get_dirname(data->filename);
gtk_label_set_text(GTK_LABEL(data->TX_filepath), tmpstr);
g_free(tmpstr);
gtk_label_set_text(GTK_LABEL(data->TX_encoding), data->ictx.encoding);
/* file content detail */
//TODO: difficult translation here
tmpstr = g_strdup_printf(_("account: %d - transaction: %d - payee: %d - categorie: %d"),
data->ictx.cnt_new_acc,
data->ictx.cnt_new_ope,
data->ictx.cnt_new_pay,
data->ictx.cnt_new_cat
);
gtk_label_set_text(GTK_LABEL(data->TX_filedetails), tmpstr);
g_free(tmpstr);
}
static void ui_import_integer_to_label(guint value, GtkWidget *label)
{
gchar *tmpstr;
tmpstr = g_strdup_printf("%d", value);
gtk_label_set_text(GTK_LABEL(label), tmpstr);
g_free(tmpstr);
}
static void ui_import_update_summary(struct import_data *data)
{
/* account summary */
ui_import_integer_to_label(data->imp_cnt_acc , data->TX_acc_upd);
ui_import_integer_to_label(data->ictx.cnt_new_acc - data->imp_cnt_acc, data->TX_acc_new);
/* transaction summary */
ui_import_integer_to_label(data->imp_cnt_trn , data->TX_trn_imp);
ui_import_integer_to_label(data->ictx.cnt_new_ope - data->imp_cnt_trn, data->TX_trn_nop);
ui_import_integer_to_label(data->imp_cnt_asg , data->TX_trn_asg);
}
static void
ui_import_apply (GtkWidget *widget, gpointer user_data)
{
struct import_data *data;
DB( g_print("\n[import] apply\n") );
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
import_apply(data);
}
static void
ui_import_close_cancel (GtkWidget *widget, gpointer user_data)
{
struct import_data *data;
GtkWidget *assistant = (GtkWidget *) user_data;
DB( g_print("\n[import] close\n") );
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
import_dispose(widget, data);
//g_free(data);
gtk_widget_destroy (assistant);
//assistant = NULL;
}
static void import_file_import(struct import_data *data)
{
import_clearall(data);
DB( g_print(" -> get encoding of '%s'\n", data->filename) );
data->ictx.encoding = homebank_file_getencoding(data->filename);
DB( g_print(" -> encoding is '%s'\n", data->ictx.encoding) );
DB( g_print(" -> load file '%s'\n", data->filename) );
switch(data->filetype)
{
#ifndef NOOFX
/* ofx_acc_list & ofx_ope_list are filled here */
case FILETYPE_OFX:
data->ictx.trans_list = homebank_ofx_import(data->filename, &data->ictx);
break;
#endif
case FILETYPE_QIF:
data->ictx.trans_list = homebank_qif_import(data->filename, &data->ictx);
break;
case FILETYPE_CSV_HB:
data->ictx.trans_list = homebank_csv_import(data->filename, &data->ictx);
break;
}
// sort by date
data->ictx.trans_list = da_transaction_sort(data->ictx.trans_list);
}
static void
ui_import_prepare (GtkWidget *widget, GtkWidget *page, gpointer user_data)
{
struct import_data *data;
gint current_page, n_pages;
gchar *title;
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
current_page = gtk_assistant_get_current_page (GTK_ASSISTANT(data->assistant));
n_pages = gtk_assistant_get_n_pages (GTK_ASSISTANT(data->assistant));
DB( g_print("\n[import] prepare %d of %d\n", current_page, n_pages) );
switch( current_page )
{
case PAGE_INTRO:
DB( g_print(" -> 1 intro\n") );
gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), page, TRUE);
break;
case PAGE_FILE:
DB( g_print(" -> 2 file choose\n") );
gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), data->pages[PAGE_RESULT], FALSE);
gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), data->pages[PAGE_OPTIONS], FALSE);
gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), data->pages[PAGE_CONFIRM], FALSE);
// the page complete is contextual in ui_import_selchange
break;
case PAGE_RESULT:
DB( g_print(" -> 3 real import\n") );
//gtk_assistant_set_current_page(GTK_ASSISTANT (widget), PAGE_IMPORT);
/* remind folder to preference */
gchar *folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(data->filechooser));
g_free(PREFS->path_import);
PREFS->path_import = folder;
import_file_import(data);
import_analysis_count(data);
ui_import_update_filecontent(data);
DB( g_print(" -> determine completion: nbtrans=%d, errors=%d\n", data->ictx.cnt_new_ope, data->ictx.cnt_err_date) );
gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), data->pages[PAGE_OPTIONS], FALSE);
gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), page, FALSE);
//TODO: Check this is sufficient
if( data->ictx.cnt_err_date > 0 )
{
gtk_widget_show(data->GR_options);
gtk_widget_show(data->GR_error);
}
else
{
gtk_widget_hide(data->GR_options);
gtk_widget_hide(data->GR_error);
}
if( data->ictx.cnt_new_ope > 0 && data->ictx.cnt_err_date <= 0 )
{
gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), page, TRUE);
}
break;
case PAGE_OPTIONS:
DB( g_print(" -> post load actions\n") );
//todo: should be optional
data->imp_cnt_asg = transaction_auto_assign(data->ictx.trans_list, 0);
import_find_duplicate_transactions(data);
ui_import_populate_account(data);
import_fill_imp_transactions(data);
if( data->ictx.nb_duplicate > 0 )
{
gtk_widget_show(data->GR_duplicate);
}
else
{
gtk_widget_hide(data->GR_duplicate);
}
gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), page, TRUE);
break;
case PAGE_CONFIRM:
{
DB( g_print(" -> 6 apply\n") );
//todo:rework this
import_count_changes(data);
ui_import_update_summary(data);
gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), page, TRUE);
break;
}
}
title = g_strdup_printf ( _("HomeBank Import Assistant - (%d of %d)"), current_page + 1 , n_pages );
gtk_window_set_title (GTK_WINDOW (data->assistant), title);
g_free (title);
}
/**
* ui_import_forward_page_func:
*
* define the page to be called when the user forward
*
* Return value: the page number
*
*/
static gint
ui_import_forward_page_func(gint current_page, gpointer func_data)
{
//struct import_data *data = func_data;
gint next_page;
DB( g_print("\n[import] forward page\n") );
// normal forward
next_page = current_page + 1;
DB( g_print(" -> curr page: %d ==> next page: %d\n", current_page, next_page) );
DB( g_print(" -> page is %s\n", page_titles[current_page]) );
return next_page;
}
static void
import_refresh_transaction (GtkWidget *widget, gpointer data)
{
DB( g_print("\n[import] refresh transaction\n") );
import_find_duplicate_transactions(data);
import_fill_imp_transactions(data);
}
static void
import_file_refresh_cb(GtkWidget *widget, gpointer user_data)
{
struct import_data *data;
data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
DB( g_print("\n[import] refresh file\n") );
ui_import_prepare(data->assistant, data->pages[PAGE_RESULT], NULL);
}
static void import_acc_affect_onRowActivated (GtkTreeView *treeview,
GtkTreePath *path,
GtkTreeViewColumn *col,
gpointer userdata)
{
//GtkTreeModel *model;
//model = gtk_tree_view_get_model(treeview);
//gtk_tree_model_get_iter_first(model, &iter);
//if(gtk_tree_selection_iter_is_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), &iter) == FALSE)
//{
import_edit_target_account(GTK_WIDGET(treeview), NULL);
//}
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
/**
* create_page1:
*
* page 1: intro
*
* Return value: a vbox widget
*
*/
static GtkWidget *
ui_import_page1(GtkWidget *assistant, struct import_data *data)
{
GtkWidget *vbox, *label, *align;
align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 0, 0);
vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
gtk_container_set_border_width (GTK_CONTAINER(vbox), HB_MAINBOX_SPACING);
gtk_container_add(GTK_CONTAINER(align), vbox);
label = make_label(
_("Welcome to the HomeBank Import Assistant.\n\n" \
"With this assistant you will be guided throught the process\n" \
"of importing an external file into HomeBank.\n\n" \
"No changes will be made until you click \"Apply\" at the end\n" \
"of this assistant.")
, 0., 0.0);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, HB_BOX_SPACING);
/* supported format */
label = make_label(
_("HomeBank can import files in the following formats:\n" \
"- QIF\n" \
"- OFX/QFX (optional at compilation time)\n" \
"- CSV (format is specific to HomeBank, see the documentation)\n" \
), 0.0, 0.0);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, HB_BOX_SPACING);
gtk_widget_show_all (align);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), align);
gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), align, GTK_ASSISTANT_PAGE_INTRO);
gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), align, _(page_titles[PAGE_INTRO]));
//gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), align, TRUE);
#if HEAD_IMAGE == 1
gtk_assistant_set_page_header_image (GTK_ASSISTANT (assistant), align, data->head_pixbuf);
#endif
#if SIDE_IMAGE == 1
gtk_assistant_set_page_side_image (GTK_ASSISTANT (assistant), align, data->side_pixbuf);
#endif
return align;
}
/**
* create_page2:
*
* page 2: file selection
*
* Return value: a vbox widget
*
*/
static GtkWidget *
ui_import_page2 (GtkWidget *assistant, struct import_data *data)
{
GtkWidget *vbox, *hbox, *align, *widget, *label;
GtkFileFilter *filter;
vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
gtk_container_set_border_width (GTK_CONTAINER(vbox), HB_MAINBOX_SPACING);
// widget = gtk_file_chooser_button_new ("Pick a File", GTK_FILE_CHOOSER_ACTION_OPEN);
widget = gtk_file_chooser_widget_new(GTK_FILE_CHOOSER_ACTION_OPEN);
data->filechooser = widget;
gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("Known files"));
gtk_file_filter_add_pattern (filter, "*.[Qq][Ii][Ff]");
#ifndef NOOFX
gtk_file_filter_add_pattern (filter, "*.[OoQq][Ff][Xx]");
#endif
gtk_file_filter_add_pattern (filter, "*.[Cc][Ss][Vv]");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(widget), filter);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("QIF files"));
gtk_file_filter_add_pattern (filter, "*.[Qq][Ii][Ff]");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(widget), filter);
#ifndef NOOFX
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("OFX/QFX files"));
gtk_file_filter_add_pattern (filter, "*.[OoQq][Ff][Xx]");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(widget), filter);
#endif
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("CSV files"));
gtk_file_filter_add_pattern (filter, "*.[Cc][Ss][Vv]");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(widget), filter);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("All files"));
gtk_file_filter_add_pattern (filter, "*");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(widget), filter);
/* our addon message */
align = gtk_alignment_new(0.65, 0, 0, 0);
gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, 0);
gtk_container_add(GTK_CONTAINER(align), hbox);
label = gtk_label_new("");
data->user_info = label;
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, HB_BOX_SPACING);
gimp_label_set_attributes (GTK_LABEL (label),
PANGO_ATTR_SCALE, PANGO_SCALE_LARGE,
PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
-1);
widget = gtk_image_new_from_stock(GTK_STOCK_YES, GTK_ICON_SIZE_BUTTON);
data->ok_image = widget;
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
widget = gtk_image_new_from_stock(GTK_STOCK_NO, GTK_ICON_SIZE_BUTTON);
data->ko_image = widget;
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
gtk_widget_show_all (vbox);
gtk_widget_hide(data->ok_image);
gtk_widget_hide(data->ko_image);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), vbox);
//gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), vbox, GTK_ASSISTANT_PAGE_CONTENT);
gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), vbox, _(page_titles[PAGE_FILE]));
#if HEAD_IMAGE == 1
gtk_assistant_set_page_header_image (GTK_ASSISTANT (assistant), vbox, data->head_pixbuf);
#endif
#if SIDE_IMAGE == 1
gtk_assistant_set_page_side_image (GTK_ASSISTANT (assistant), vbox, data->side_pixbuf);
#endif
return vbox;
}
static GtkWidget *
ui_import_page3 (GtkWidget *assistant, struct import_data *data)
{
GtkWidget *container, *vbox, *hbox, *table, *label, *widget;
gint row;
container = gtk_vbox_new (FALSE, HB_BOX_SPACING);
gtk_container_set_border_width (GTK_CONTAINER(container), HB_BOX_SPACING);
/* file informations */
label = make_label(_("File to import"), 0.0, 0.5);
gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
gtk_box_pack_start (GTK_BOX (container), label, FALSE, FALSE, 0);
table = gtk_table_new (2, 2, FALSE);
//gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0);
/* area 1 : file summary */
row = 0;
label = make_label(_("Path:"), 0.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
widget = make_label(NULL, 0.0, 0.5);
data->TX_filepath = widget;
gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
row++;
label = make_label(_("Name:"), 0.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
widget = make_label(NULL, 0.0, 0.5);
data->TX_filename = widget;
gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
row++;
label = make_label(_("Encoding:"), 0.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
widget = make_label(NULL, 0.0, 0.5);
data->TX_encoding = widget;
gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
row++;
label = make_label(_("Content:"), 0.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
widget = make_label(NULL, 0.0, 0.5);
data->TX_filedetails = widget;
gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
/* load options */
vbox = gtk_hbox_new (FALSE, 0);
data->GR_options = vbox;
gtk_box_pack_start (GTK_BOX (container), vbox, FALSE, FALSE, 0);
label = make_label(_("Import options"), 0.0, 0.5);
gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, HB_BOX_SPACING);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
label = make_label(_("Date order:"), 0.0, 0.5);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
widget = make_cycle(label, CYA_IMPORT_DATEORDER);
data->CY_dateorder = widget;
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
widget = gtk_button_new_with_label (_("Load the file again"));
data->BT_refresh = widget;
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
g_signal_connect (widget, "clicked",
G_CALLBACK (import_file_refresh_cb), data);
/*
expander = gtk_expander_new (_("File content"));
gtk_box_pack_start (GTK_BOX (container), expander, TRUE, TRUE, 0);
scrollwin = gtk_scrolled_window_new(NULL,NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
widget = gtk_text_view_new ();
gtk_container_add(GTK_CONTAINER(scrollwin), widget);
gtk_container_add(GTK_CONTAINER(expander), scrollwin);
*/
/* status */
hbox = gtk_hbox_new (FALSE, HB_BOX_SPACING);
data->GR_error = hbox;
gtk_box_pack_start (GTK_BOX (container), hbox, FALSE, FALSE, 0);
widget = gtk_image_new_from_stock(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG );
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
gtk_misc_set_padding(GTK_MISC(widget), HB_BOX_SPACING, 0);
label = gtk_label_new(_(
"Some date conversion errors were encountered during the load of the file.\n" \
"Please try to change the date order format and load the file again.")
);
/*gimp_label_set_attributes (GTK_LABEL (label),
PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
-1);*/
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
gtk_widget_show_all (container);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), container);
//gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), container, GTK_ASSISTANT_PAGE_CONFIRM);
//gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), label, TRUE);
gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), container, _(page_titles[PAGE_RESULT]));
#if HEAD_IMAGE == 1
gtk_assistant_set_page_header_image (GTK_ASSISTANT (assistant), container, data->head_pixbuf);
#endif
#if SIDE_IMAGE == 1
gtk_assistant_set_page_side_image (GTK_ASSISTANT (assistant), container, data->side_pixbuf);
#endif
return container;
}
static GtkWidget *
ui_import_page4_account (GtkWidget *assistant, struct import_data *data)
{
GtkWidget *vbox, *hbox, *widget, *scrollwin;
vbox = gtk_vbox_new(FALSE, HB_BOX_SPACING);
gtk_container_set_border_width (GTK_CONTAINER (vbox), HB_BOX_SPACING);
scrollwin = gtk_scrolled_window_new(NULL,NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
widget = ui_acc_affect_listview_new();
gtk_widget_set_size_request(widget, -1, 100);
data->LV_acc = widget;
gtk_container_add(GTK_CONTAINER(scrollwin), widget);
gtk_box_pack_start (GTK_BOX (vbox), scrollwin, TRUE, TRUE, 0);
hbox = gtk_hbox_new(FALSE, HB_BOX_SPACING);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
widget = gtk_button_new_with_label (_("Edit account to import"));
data->BT_edit = widget;
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
/* signal and other stuff */
g_signal_connect (G_OBJECT (data->BT_edit), "clicked", G_CALLBACK (import_edit_target_account), data);
g_signal_connect (GTK_TREE_VIEW(data->LV_acc), "row-activated", G_CALLBACK (import_acc_affect_onRowActivated), NULL);
return vbox;
}
static GtkWidget *
ui_import_page4_transaction (GtkWidget *assistant, struct import_data *data)
{
GtkWidget *mainbox, *vbox, *align, *hbox, *label, *sw, *widget, *expander;
mainbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
gtk_container_set_border_width (GTK_CONTAINER(mainbox), HB_BOX_SPACING);
/* transaction list */
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
widget = create_list_import_transaction();
data->imported_ope = widget;
gtk_container_add (GTK_CONTAINER (sw), widget);
gtk_box_pack_start (GTK_BOX (mainbox), sw, TRUE, TRUE, 0);
/* duplicate section */
expander = gtk_expander_new (_("Detail of duplicate transactions"));
data->GR_duplicate = expander;
gtk_box_pack_start (GTK_BOX (mainbox), expander, FALSE, FALSE, 0);
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (expander), vbox);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
widget = create_list_transaction(TRN_LIST_TYPE_DETAIL, PREFS->lst_ope_columns);
data->duplicat_ope = widget;
gtk_container_add (GTK_CONTAINER (sw), widget);
gtk_widget_set_size_request(sw, -1, 80);
gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
/* duplicate control */
//expander = gtk_expander_new (_("Change match options"));
//gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 0);
align = gtk_alignment_new(0.5, 0.0, 1.0, 0.0);
/* -- gtk_alignment_set_padding t , b, l, r -- */
gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 12, 0);
//gtk_container_add(GTK_CONTAINER(expander), align);
gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
hbox = gtk_hbox_new (FALSE, HB_BOX_SPACING);
gtk_container_add(GTK_CONTAINER(align), hbox);
label = make_label(_("Date _tolerance:"), 0, 0.5);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
widget = make_numeric(label, 0.0, 14.0);
data->NB_maxgap = widget;
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
//TRANSLATORS: there is a spinner on the left of this label, and so you have 0....x days of date tolerance
label = make_label(_("days"), 0, 0.5);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
widget = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
g_signal_connect (widget, "clicked",
G_CALLBACK (import_refresh_transaction), data);
widget = gtk_image_new_from_stock(GTK_STOCK_INFO, GTK_ICON_SIZE_SMALL_TOOLBAR );
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
gtk_misc_set_padding(GTK_MISC(widget), HB_BOX_SPACING, 0);
label = gtk_label_new(_(
"The match is done in order: by account, amount and date.\n" \
"A date tolerance of 0 day means an exact match")
);
gimp_label_set_attributes (GTK_LABEL (label),
PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
-1);
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_widget_show_all (mainbox);
return mainbox;
}
/**
* create_page3:
*
* page 3: analysis & options
*
* Return value: a table widget
*
*/
static GtkWidget *
ui_import_page4 (GtkWidget *assistant, struct import_data *data)
{
GtkWidget *vbox, *table, *label, *notebook;
vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
gtk_container_set_border_width (GTK_CONTAINER(vbox), HB_MAINBOX_SPACING);
//notebook
notebook = gtk_notebook_new();
data->GR_page = notebook;
//gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
//gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
/* account selection */
label = make_label(_("Account to import"), 0.0, 1.0);
table = ui_import_page4_account(assistant, data);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), table, label);
/* transaction selection */
label = make_label(_("Transaction to import"), 0.0, 1.0);
table = ui_import_page4_transaction(assistant, data);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), table, label);
gtk_widget_show_all (vbox);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), vbox);
// gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), vbox, GTK_ASSISTANT_PAGE_PROGRESS);
gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), vbox, _(page_titles[PAGE_OPTIONS]));
#if HEAD_IMAGE == 1
gtk_assistant_set_page_header_image (GTK_ASSISTANT (assistant), vbox, data->head_pixbuf);
#endif
#if SIDE_IMAGE == 1
gtk_assistant_set_page_side_image (GTK_ASSISTANT (assistant), vbox, data->side_pixbuf);
#endif
return vbox;
}
/**
* create_page6:
*
* page 6: confirmation
*
* Return value: a vbox widget
*
*/
static GtkWidget *
ui_import_page6(GtkWidget *assistant, struct import_data *data)
{
GtkWidget *vbox, *label, *align, *widget, *table;
gint row;
align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 0, 0);
vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
gtk_container_set_border_width (GTK_CONTAINER(vbox), HB_MAINBOX_SPACING);
gtk_container_add(GTK_CONTAINER(align), vbox);
label = make_label(
_("Click \"Apply\" to update your accounts.\n"), 0.5, 0.5);
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
/* the summary */
table = gtk_table_new (7, 3, FALSE);
gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING/2);
gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
row = 0;
label = make_label(_("Accounts"), 0.0, 0.5);
gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
/* acc update */
row++;
label = make_label(NULL, 0.0, 0.5);
//gtk_misc_set_padding (GTK_MISC (label), HB_BOX_SPACING, 0);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
widget = make_label(NULL, 1.0, 0.5);
data->TX_acc_upd = widget;
gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
label = make_label(_("to update"), 0.0, 0.5);
gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 3, row, row+1);
/* acc create */
row++;
widget = make_label(NULL, 1.0, 0.5);
data->TX_acc_new = widget;
gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
label = make_label(_("to create"), 0.0, 0.5);
gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 3, row, row+1);
row++;
label = make_label(_("Transactions"), 0.0, 0.5);
gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
/* trn import */
row++;
widget = make_label(NULL, 1.0, 0.5);
data->TX_trn_imp = widget;
gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
label = make_label(_("to import"), 0.0, 0.5);
gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 3, row, row+1);
/* trn reject */
row++;
widget = make_label(NULL, 1.0, 0.5);
data->TX_trn_nop = widget;
gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
label = make_label(_("to reject"), 0.0, 0.5);
gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 3, row, row+1);
/* trn auto-assigned */
row++;
widget = make_label(NULL, 1.0, 0.5);
data->TX_trn_asg = widget;
gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
label = make_label(_("auto-assigned"), 0.0, 0.5);
gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 3, row, row+1);
gtk_widget_show_all (align);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), align);
gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), align, GTK_ASSISTANT_PAGE_CONFIRM);
//gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), label, TRUE);
gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), align, _(page_titles[PAGE_CONFIRM]));
#if HEAD_IMAGE == 1
gtk_assistant_set_page_header_image (GTK_ASSISTANT (assistant), align, data->head_pixbuf);
#endif
#if SIDE_IMAGE == 1
gtk_assistant_set_page_side_image (GTK_ASSISTANT (assistant), align, data->side_pixbuf);
#endif
return align;
}
/* starting point of import */
GtkWidget *ui_import_window_new (void)
{
struct import_data *data;
GtkWidget *assistant;
GdkScreen *screen;
gint width, height;
gint pos;
data = g_malloc0(sizeof(struct import_data));
if(!data) return NULL;
assistant = gtk_assistant_new ();
data->assistant = assistant;
//store our window private data
g_object_set_data(G_OBJECT(assistant), "inst_data", (gpointer)data);
//DB( g_print("** \n[import] window=%x, inst_data=%x\n", assistant, data) );
gtk_window_set_modal(GTK_WINDOW (assistant), TRUE);
gtk_window_set_transient_for(GTK_WINDOW(assistant), GTK_WINDOW(GLOBALS->mainwindow));
/* set pixbuf */
#if HEAD_IMAGE == 1
data->head_pixbuf = gtk_widget_render_icon (assistant, "hb-file-import", GTK_ICON_SIZE_DIALOG, NULL);
g_object_unref (data->head_pixbuf);
#endif
#if SIDE_IMAGE == 1
gchar *pathfilename = g_build_filename(homebank_app_get_pixmaps_dir(), "wizard.svg", NULL);
data->side_pixbuf = gdk_pixbuf_new_from_file (pathfilename, NULL);
g_free(pathfilename);
g_object_unref (data->side_pixbuf);
#endif
#if FORCE_SIZE == 1
screen = gtk_window_get_screen(GTK_WINDOW (assistant));
// fix #379372 : manage multiple monitor case
if( gdk_screen_get_n_monitors(screen) > 1 )
{
GdkRectangle rect;
gdk_screen_get_monitor_geometry(screen, 1, &rect);
width = rect.width;
height = rect.height;
}
else
{
width = gdk_screen_get_width(screen);
height = gdk_screen_get_height(screen);
}
gtk_window_resize(GTK_WINDOW(assistant), SCOEF*width, SCOEF*height);
gtk_window_set_position (GTK_WINDOW (assistant), GTK_WIN_POS_CENTER_ON_PARENT);
//gtk_window_set_position (GTK_WINDOW (assistant), GTK_WIN_POS_CENTER);
#endif
pos = 0;
data->pages[pos++] = ui_import_page1 (assistant, data); // intro
data->pages[pos++] = ui_import_page2 (assistant, data); // file choose
data->pages[pos++] = ui_import_page3 (assistant, data); // load result
data->pages[pos++] = ui_import_page4 (assistant, data); // file content
data->pages[pos++] = ui_import_page6 (assistant, data); // confirm
gtk_assistant_set_forward_page_func(GTK_ASSISTANT(assistant), ui_import_forward_page_func, data, NULL);
//gtk_assistant_set_current_page(GTK_ASSISTANT (assistant), PAGE_FILE);
//setup
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(data->filechooser), PREFS->path_import);
//ui_acc_comboboxentry_populate(GTK_COMBO_BOX(data->PO_acc), GLOBALS->h_acc);
data->ictx.cnt_initial_acc = da_acc_length();
gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_dateorder), PREFS->dtex_datefmt);
ui_import_selchange(assistant, data);
//connect all our signals
g_signal_connect (G_OBJECT (data->filechooser), "selection-changed",
G_CALLBACK (ui_import_selchange), (gpointer)data);
g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->imported_ope)), "changed",
G_CALLBACK (ui_import_selection), NULL);
g_signal_connect (G_OBJECT (assistant), "cancel",
G_CALLBACK (ui_import_close_cancel), assistant);
g_signal_connect (G_OBJECT (assistant), "close",
G_CALLBACK (ui_import_close_cancel), assistant);
g_signal_connect (G_OBJECT (assistant), "apply",
G_CALLBACK (ui_import_apply), NULL);
g_signal_connect (G_OBJECT (assistant), "prepare",
G_CALLBACK (ui_import_prepare), NULL);
// g_signal_connect (window, "delete-event", G_CALLBACK (hbfile_dispose), (gpointer)data);
gtk_widget_show (assistant);
return assistant;
}
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
/* account affect listview */
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
guint32
ui_acc_affect_listview_get_selected_key(GtkTreeView *treeview)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
selection = gtk_tree_view_get_selection(treeview);
if (gtk_tree_selection_get_selected(selection, &model, &iter))
{
Account *item;
gtk_tree_model_get(model, &iter, 0, &item, -1);
if( item!= NULL )
return item->key;
}
return 0;
}
static void
ui_acc_affect_listview_srcname_cell_data_function (GtkTreeViewColumn *col,
GtkCellRenderer *renderer,
GtkTreeModel *model,
GtkTreeIter *iter,
gpointer user_data)
{
Account *entry;
gchar *name;
gchar *string;
gtk_tree_model_get(model, iter, 0, &entry, -1);
name = entry->imp_name;
#if MYDEBUG
string = g_markup_printf_escaped("[%d] %s", entry->key, name );
#else
string = g_markup_printf_escaped("%s", name);
#endif
g_object_set(renderer, "markup", string, NULL);
g_free(string);
}
static void
ui_acc_affect_listview_new_cell_data_function (GtkTreeViewColumn *col,
GtkCellRenderer *renderer,
GtkTreeModel *model,
GtkTreeIter *iter,
gpointer user_data)
{
Account *entry;
gchar *name;
gtk_tree_model_get(model, iter, 0, &entry, -1);
name = NULL;
if(entry->imp_key == 0)
name = _("Create new");
else
name = _("Import into");
g_object_set(renderer, "markup", name, NULL);
}
static void
ui_acc_affect_listview_dstname_cell_data_function (GtkTreeViewColumn *col,
GtkCellRenderer *renderer,
GtkTreeModel *model,
GtkTreeIter *iter,
gpointer user_data)
{
Account *entry, *dst_entry;
gchar *name;
#if MYDEBUG
gchar *string;
#endif
gtk_tree_model_get(model, iter, 0, &entry, -1);
name = NULL;
if(entry->imp_key == 0)
name = entry->name;
else
{
dst_entry = da_acc_get(entry->imp_key);
if( dst_entry != NULL )
name = dst_entry->name;
}
#if MYDEBUG
string = g_strdup_printf ("[%d] %s", entry->imp_key, name );
g_object_set(renderer, "text", string, NULL);
g_free(string);
#else
g_object_set(renderer, "text", name, NULL);
#endif
}
void
ui_acc_affect_listview_add(GtkTreeView *treeview, Account *item)
{
if( item->name != NULL )
{
GtkTreeModel *model;
GtkTreeIter iter;
model = gtk_tree_view_get_model(treeview);
gtk_list_store_append (GTK_LIST_STORE(model), &iter);
gtk_list_store_set (GTK_LIST_STORE(model), &iter,
0, item,
-1);
//gtk_tree_selection_select_iter (gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), &iter);
}
}
static GtkWidget *
ui_acc_affect_listview_new(void)
{
GtkListStore *store;
GtkWidget *treeview;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
// create list store
store = gtk_list_store_new(1,
G_TYPE_POINTER
);
// treeview
treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
g_object_unref(store);
// column: import account
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new();
gtk_tree_view_column_pack_start(column, renderer, TRUE);
gtk_tree_view_column_set_title(column, _("Imported name"));
gtk_tree_view_column_set_cell_data_func(column, renderer, ui_acc_affect_listview_srcname_cell_data_function, NULL, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
// column: target account
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new();
gtk_tree_view_column_pack_start(column, renderer, TRUE);
gtk_tree_view_column_set_title(column, _("Action"));
gtk_tree_view_column_set_cell_data_func(column, renderer, ui_acc_affect_listview_new_cell_data_function, NULL, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
// column: target account
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new();
gtk_tree_view_column_pack_start(column, renderer, TRUE);
gtk_tree_view_column_set_title(column, _("HomeBank name"));
gtk_tree_view_column_set_cell_data_func(column, renderer, ui_acc_affect_listview_dstname_cell_data_function, NULL, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
// treeviewattribute
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), TRUE);
//gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store), ui_acc_listview_compare_func, NULL, NULL);
//gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
return treeview;
}