]> Dogcows Code - chaz/homebank/blob - src/import.c
import homebank-4.6.3
[chaz/homebank] / src / import.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2014 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "homebank.h"
21
22 #include "import.h"
23
24 #include "list_account.h"
25 #include "list_operation.h"
26
27 #include "ui-account.h"
28 #include "dsp_mainwindow.h"
29 #include "imp_qif.h"
30
31 #ifndef NOOFX
32 #include <libofx/libofx.h>
33 #endif
34
35 /****************************************************************************/
36 /* Debug macros */
37 /****************************************************************************/
38 #define MYDEBUG 0
39
40 #if MYDEBUG
41 #define DB(x) (x);
42 #else
43 #define DB(x);
44 #endif
45
46 #define FORCE_SIZE 1
47 #define HEAD_IMAGE 1
48 #define SIDE_IMAGE 0
49
50 #define SCOEF 0.6
51
52 /* our global datas */
53 extern struct HomeBank *GLOBALS;
54 extern struct Preferences *PREFS;
55
56
57 static gchar *page_titles[] =
58 {
59 N_("HomeBank Import Assistant"),
60 N_("File to import"),
61 N_("File analysis results"),
62 N_("Adjust what to import"),
63 N_("Update your accounts")
64 };
65
66 extern gchar *CYA_IMPORT_DATEORDER[];
67
68 static GtkWidget *ui_acc_affect_listview_new(void);
69 guint32 ui_acc_affect_listview_get_selected_key(GtkTreeView *treeview);
70 void ui_acc_affect_listview_add(GtkTreeView *treeview, Account *item);
71
72
73 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
74
75
76
77
78 Account *import_create_account(gchar *name, gchar *number)
79 {
80 Account *accitem, *existitem;
81
82 //first check we do not have already this imported account
83 existitem = da_acc_get_by_imp_name(name);
84 if(existitem != NULL)
85 return existitem;
86
87 accitem = da_acc_malloc();
88 accitem->key = da_acc_get_max_key() + 1;
89 accitem->pos = da_acc_length() + 1;
90
91 // then we check a same named account
92 existitem = da_acc_get_by_name(name);
93 if(existitem == NULL)
94 {
95 accitem->name = g_strdup(name);
96 }
97 else
98 {
99 accitem->name = g_strdup_printf(_("(account %d)"), accitem->key);
100 }
101
102 accitem->imp_name = g_strdup(name);
103
104 if(number)
105 accitem->number = g_strdup(number);
106
107 accitem->imported = TRUE;
108 da_acc_insert(accitem);
109
110 return accitem;
111 }
112
113
114 static GList *homebank_csv_import(gchar *filename, ImportContext *ictx)
115 {
116 GIOChannel *io;
117 GList *list = NULL;
118 static gint csvtype[7] = {
119 CSV_DATE,
120 CSV_INT,
121 CSV_STRING,
122 CSV_STRING,
123 CSV_STRING,
124 CSV_DOUBLE,
125 CSV_STRING,
126 };
127
128 DB( g_print("\n[import] homebank csv\n") );
129
130 io = g_io_channel_new_file(filename, "r", NULL);
131 if(io != NULL)
132 {
133 gchar *tmpstr;
134 gint io_stat;
135 gboolean valid;
136 gint count = 0;
137 gint error = 0;
138 Account *tmp_acc;
139 Payee *payitem;
140 Category *catitem;
141 GError *err = NULL;
142
143
144 gchar *accname = g_strdup_printf(_("(account %d)"), da_acc_get_max_key() + 1);
145 tmp_acc = import_create_account(accname, NULL);
146 g_free(accname);
147
148
149 if( ictx->encoding != NULL )
150 {
151 g_io_channel_set_encoding(io, ictx->encoding, NULL);
152 }
153
154 for(;;)
155 {
156 io_stat = g_io_channel_read_line(io, &tmpstr, NULL, NULL, &err);
157 if( io_stat == G_IO_STATUS_EOF)
158 break;
159 if( io_stat == G_IO_STATUS_ERROR )
160 {
161 DB (g_print(" + ERROR %s\n",err->message));
162 break;
163 }
164 if( io_stat == G_IO_STATUS_NORMAL)
165 {
166 if( *tmpstr != '\0' )
167 {
168 gchar **str_array;
169 Transaction *newope = da_transaction_malloc();
170
171 hb_string_strip_crlf(tmpstr);
172
173 /* control validity here */
174 valid = hb_string_csv_valid(tmpstr, 8, csvtype);
175
176 //DB( g_print("valid %d, '%s'\n", valid, tmpstr) );
177
178 if( !valid )
179 {
180 error++;
181 }
182 else
183 {
184 count++;
185
186 str_array = g_strsplit (tmpstr, ";", 8);
187 // 0:date; 1:paymode; 2:info; 3:payee, 4:wording; 5:amount; 6:category; 7:tags
188
189 DB( g_print(" ->%s\n", tmpstr ) );
190
191 newope->date = hb_date_get_julian(str_array[0], ictx->datefmt);
192 if( newope->date == 0 )
193 ictx->cnt_err_date++;
194
195 newope->paymode = atoi(str_array[1]);
196 newope->info = g_strdup(str_array[2]);
197
198 /* payee */
199 g_strstrip(str_array[3]);
200 payitem = da_pay_get_by_name(str_array[3]);
201 if(payitem == NULL)
202 {
203 payitem = da_pay_malloc();
204 payitem->name = g_strdup(str_array[3]);
205 payitem->imported = TRUE;
206 da_pay_append(payitem);
207
208 if( payitem->imported == TRUE )
209 ictx->cnt_new_pay += 1;
210 }
211
212 newope->kpay = payitem->key;
213 newope->wording = g_strdup(str_array[4]);
214 newope->amount = hb_qif_parser_get_amount(str_array[5]);
215
216 /* category */
217 g_strstrip(str_array[6]);
218 catitem = da_cat_append_ifnew_by_fullname(str_array[6], TRUE);
219 if( catitem != NULL )
220 {
221 newope->kcat = catitem->key;
222
223 if( catitem->imported == TRUE && catitem->key > 0 )
224 ictx->cnt_new_cat += 1;
225 }
226
227 /* tags */
228 transaction_tags_parse(newope, str_array[7]);
229
230
231 newope->kacc = tmp_acc->key;
232 //newope->kxferacc = accnum;
233
234 newope->flags |= OF_ADDED;
235
236 if( newope->amount > 0)
237 newope->flags |= OF_INCOME;
238
239 /*
240 DB( g_print(" storing %s : %s : %s :%s : %s : %s : %s : %s\n",
241 str_array[0], str_array[1], str_array[2],
242 str_array[3], str_array[4], str_array[5],
243 str_array[6], str_array[7]
244 ) );
245 */
246
247 list = g_list_append(list, newope);
248
249 g_strfreev (str_array);
250 }
251 }
252 g_free(tmpstr);
253 }
254
255 }
256 g_io_channel_unref (io);
257
258 /*
259 ui_dialog_msg_infoerror(data->window, error > 0 ? GTK_MESSAGE_ERROR : GTK_MESSAGE_INFO,
260 _("Transaction CSV import result"),
261 _("%d transactions inserted\n%d errors in the file"),
262 count, error);
263 */
264 }
265
266
267 return list;
268 }
269
270 #ifndef NOOFX
271 /*
272 **** OFX part
273 ****
274 **** this part is quite weird,but works
275 ** id is ACCTID
276
277 */
278
279 static Account * ofx_get_account_by_id(gchar *id)
280 {
281 GList *lacc, *list;
282
283 DB( g_print("\n[import] ofx_get_account_by_id\n") );
284 DB( g_print(" -> searching for '%s'\n",id) );
285
286 lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
287 while (list != NULL)
288 {
289 Account *accitem = list->data;
290
291 if( accitem->imported == FALSE)
292 {
293 if(accitem->name && accitem->number && strlen(accitem->number) )
294 {
295 // todo: maybe smartness should be done here
296 if(g_strstr_len(id, -1, accitem->number) != NULL)
297 {
298 return accitem;
299 }
300 }
301 }
302 list = g_list_next(list);
303 }
304 g_list_free(lacc);
305 return NULL;
306 }
307
308 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
309
310 /**
311 * ofx_proc_account_cb:
312 *
313 * The ofx_proc_account_cb event is always generated first, to allow the application to create accounts
314 * or ask the user to match an existing account before the ofx_proc_statement and ofx_proc_transaction
315 * event are received. An OfxAccountData is passed to this event.
316 *
317 */
318 static LibofxProcStatementCallback
319 ofx_proc_account_cb(const struct OfxAccountData data, OfxContext *ctx)
320 {
321 Account *tmp_acc, *dst_acc;
322
323 DB( g_print("** ofx_proc_account_cb()\n") );
324
325 if(data.account_id_valid==true)
326 {
327 DB( g_print(" account_id: %s\n", data.account_id) );
328 DB( g_print(" account_name: %s\n", data.account_name) );
329 }
330
331 //if(data.account_number_valid==true)
332 //{
333 DB( g_print(" account_number: %s\n", data.account_number) );
334 //}
335
336
337 if(data.account_type_valid==true)
338 {
339 DB( g_print(" account_type: %d\n", data.account_type) );
340 }
341
342 if(data.currency_valid==true)
343 {
344 DB( g_print(" currency: %s\n", data.currency) );
345 }
346
347
348 //find target account
349 dst_acc = ofx_get_account_by_id( (gchar *)data.account_id );
350 DB( g_print(" ** hb account found result is %x\n", (unsigned int)dst_acc) );
351
352
353 // in every case we create an account here
354 tmp_acc = import_create_account((gchar *)data.account_name, (gchar *)data.account_id);
355 DB( g_print(" -> creating tmp account: %d %s - %x\n", tmp_acc->key, data.account_id, (unsigned int)tmp_acc) );
356
357 if( dst_acc != NULL )
358 {
359 tmp_acc->imp_key = dst_acc->key;
360 }
361
362
363 ctx->curr_acc = tmp_acc;
364 ctx->curr_acc_isnew = TRUE;
365
366
367
368
369
370
371
372
373 DB( fputs("\n",stdout) );
374 return 0;
375 }
376
377
378 /**
379 * ofx_proc_statement_cb:
380 *
381 * The ofx_proc_statement_cb event is sent after all ofx_proc_transaction events have been sent.
382 * An OfxStatementData is passed to this event.
383 *
384 */
385 static LibofxProcStatementCallback
386 ofx_proc_statement_cb(const struct OfxStatementData data, OfxContext *ctx)
387 {
388 DB( g_print("** ofx_proc_statement_cb()\n") );
389
390 #ifdef MYDEBUG
391 if(data.ledger_balance_date_valid==true)
392 {
393 struct tm temp_tm;
394
395 temp_tm = *localtime(&(data.ledger_balance_date));
396 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");
397 }
398 #endif
399
400 if(data.ledger_balance_valid==true)
401 {
402 if( ctx->curr_acc != NULL && ctx->curr_acc_isnew == TRUE )
403 {
404 ctx->curr_acc->initial = data.ledger_balance;
405 }
406 DB( printf("ledger_balance: $%.2f%s",data.ledger_balance,"\n") );
407 }
408
409 return 0;
410 }
411
412 /**
413 * ofx_proc_statement_cb:
414 *
415 * An ofx_proc_transaction_cb event is generated for every transaction in the ofx response,
416 * after ofx_proc_statement (and possibly ofx_proc_security is generated.
417 * An OfxTransactionData structure is passed to this event.
418 *
419 */
420 static LibofxProcStatementCallback
421 ofx_proc_transaction_cb(const struct OfxTransactionData data, OfxContext *ctx)
422 {
423 struct tm temp_tm;
424 GDate *date;
425 Transaction *newope;
426
427 DB( g_print("** ofx_proc_transaction_cb()\n") );
428
429 newope = da_transaction_malloc();
430
431 // date
432 if(data.date_posted_valid==true)
433 {
434 temp_tm = *localtime(&(data.date_posted));
435 date = g_date_new();
436 g_date_set_dmy(date, temp_tm.tm_mday, temp_tm.tm_mon+1, temp_tm.tm_year+1900);
437 newope->date = g_date_get_julian(date);
438 g_date_free(date);
439 }
440
441 // amount
442 if(data.amount_valid==true)
443 {
444 newope->amount = data.amount;
445
446 }
447 // check number
448 if(data.check_number_valid==true)
449 {
450 newope->info = g_strdup(data.check_number);
451 }
452 //todo: reference_number ?
453
454 // wording
455 if(data.name_valid==true)
456 {
457 newope->wording = g_strdup(data.name);
458 }
459
460 //memo ( new for v4.2)
461
462 DB( g_print(" -> memo is='%d'\n", data.memo_valid) );
463
464
465 if(data.memo_valid==true)
466 {
467 gchar *old = NULL;
468
469 switch(PREFS->dtex_ofxmemo)
470 {
471 case 1: //add to info
472 old = newope->info;
473 if(old == NULL)
474 newope->info = g_strdup(data.memo);
475 else
476 {
477 newope->info = g_strjoin(" ", old, data.memo, NULL);
478 g_free(old);
479 }
480 break;
481
482 case 2: //add to description
483 old = newope->wording;
484 if(old == NULL)
485 newope->wording = g_strdup(data.memo);
486 else
487 {
488 newope->wording = g_strjoin(" ", old, data.memo, NULL);
489 g_free(old);
490 }
491
492 DB( g_print(" -> should concatenate ='%s'\n", data.memo) );
493 DB( g_print(" -> old='%s', new ='%s'\n", old, newope->wording) );
494
495 break;
496 }
497 }
498
499 // payment
500 if(data.transactiontype_valid==true)
501 {
502 switch(data.transactiontype)
503 {
504 //#740373
505 case OFX_CREDIT:
506 if(newope->amount < 0)
507 newope->amount *= -1;
508 break;
509 case OFX_DEBIT:
510 if(newope->amount > 0)
511 newope->amount *= -1;
512 break;
513 case OFX_INT:
514 newope->paymode = PAYMODE_XFER;
515 break;
516 case OFX_DIV:
517 newope->paymode = PAYMODE_XFER;
518 break;
519 case OFX_FEE:
520 newope->paymode = PAYMODE_FEE;
521 break;
522 case OFX_SRVCHG:
523 newope->paymode = PAYMODE_XFER;
524 break;
525 case OFX_DEP:
526 newope->paymode = PAYMODE_DEPOSIT;
527 break;
528 case OFX_ATM:
529 newope->paymode = PAYMODE_CASH;
530 break;
531 case OFX_POS:
532 if(ctx->curr_acc && ctx->curr_acc->type == ACC_TYPE_CREDITCARD)
533 newope->paymode = PAYMODE_CCARD;
534 else
535 newope->paymode = PAYMODE_DCARD;
536 break;
537 case OFX_XFER:
538 newope->paymode = PAYMODE_XFER;
539 break;
540 case OFX_CHECK:
541 newope->paymode = PAYMODE_CHECK;
542 break;
543 case OFX_PAYMENT:
544 newope->paymode = PAYMODE_EPAYMENT;
545 break;
546 case OFX_CASH:
547 newope->paymode = PAYMODE_CASH;
548 break;
549 case OFX_DIRECTDEP:
550 newope->paymode = PAYMODE_DEPOSIT;
551 break;
552 case OFX_DIRECTDEBIT:
553 newope->paymode = PAYMODE_XFER;
554 break;
555 case OFX_REPEATPMT:
556 newope->paymode = PAYMODE_REPEATPMT;
557 break;
558 case OFX_OTHER:
559
560 break;
561 default :
562
563 break;
564 }
565 }
566
567 if( ctx->curr_acc )
568 {
569
570 newope->kacc = ctx->curr_acc->key;
571 newope->flags |= OF_ADDED;
572
573 if( newope->amount > 0)
574 newope->flags |= OF_INCOME;
575
576 /* ensure utf-8 here, has under windows, libofx not always return utf-8 as it should */
577 #ifndef G_OS_UNIX
578 DB( printf(" ensure UTF-8\n") );
579
580 newope->info = homebank_utf8_ensure(newope->info);
581 newope->wording = homebank_utf8_ensure(newope->wording);
582 #endif
583
584 ctx->trans_list = g_list_append(ctx->trans_list, newope);
585
586 DB( printf(" insert newope: acc=%d\n", newope->kacc) );
587
588 if( ctx->curr_acc_isnew == TRUE )
589 {
590 ctx->curr_acc->initial -= data.amount;
591 }
592 }
593 else
594 {
595 da_transaction_free(newope);
596 }
597
598 return 0;
599 }
600
601
602
603 static LibofxProcStatusCallback
604 ofx_proc_status_cb(const struct OfxStatusData data, OfxContext *ctx)
605 {
606 DB( g_print("** ofx_proc_status_cb()\n") );
607
608 if(data.ofx_element_name_valid==true){
609 DB( g_print(" Ofx entity this status is relevent to: '%s'\n", data.ofx_element_name) );
610 }
611 if(data.severity_valid==true){
612 DB( g_print(" Severity: ") );
613 switch(data.severity){
614 case INFO : DB( g_print("INFO\n") );
615 break;
616 case WARN : DB( g_print("WARN\n") );
617 break;
618 case ERROR : DB( g_print("ERROR\n") );
619 break;
620 default: DB( g_print("WRITEME: Unknown status severity!\n") );
621 }
622 }
623 if(data.code_valid==true){
624 DB( g_print(" Code: %d, name: %s\n Description: %s\n", data.code, data.name, data.description) );
625 }
626 if(data.server_message_valid==true){
627 DB( g_print(" Server Message: %s\n", data.server_message) );
628 }
629 DB( g_print("\n") );
630
631 return 0;
632 }
633
634
635 static GList *homebank_ofx_import(gchar *filename, ImportContext *ictx)
636 {
637 OfxContext ctx = { 0 };
638
639 /*extern int ofx_PARSER_msg;
640 extern int ofx_DEBUG_msg;
641 extern int ofx_WARNING_msg;
642 extern int ofx_ERROR_msg;
643 extern int ofx_INFO_msg;
644 extern int ofx_STATUS_msg;*/
645
646 DB( g_print("\n[import] ofx import (libofx=%s) \n", LIBOFX_VERSION_RELEASE_STRING) );
647
648 /*ofx_PARSER_msg = false;
649 ofx_DEBUG_msg = false;
650 ofx_WARNING_msg = false;
651 ofx_ERROR_msg = false;
652 ofx_INFO_msg = false;
653 ofx_STATUS_msg = false;*/
654
655 LibofxContextPtr libofx_context = libofx_get_new_context();
656
657 ofx_set_status_cb (libofx_context, (LibofxProcStatusCallback) ofx_proc_status_cb , &ctx);
658 ofx_set_statement_cb (libofx_context, (LibofxProcStatementCallback) ofx_proc_statement_cb , &ctx);
659 ofx_set_account_cb (libofx_context, (LibofxProcAccountCallback) ofx_proc_account_cb , &ctx);
660 ofx_set_transaction_cb(libofx_context, (LibofxProcTransactionCallback)ofx_proc_transaction_cb, &ctx);
661
662 #ifdef G_OS_WIN32
663 //#932959: windows don't like utf8 path, so convert
664 gchar *file = g_win32_locale_filename_from_utf8(filename);
665 libofx_proc_file(libofx_context, file, AUTODETECT);
666 g_free(file);
667 #else
668 libofx_proc_file(libofx_context, filename, AUTODETECT);
669 #endif
670
671 libofx_free_context(libofx_context);
672
673 return ctx.trans_list;
674 }
675
676 #endif
677
678
679 static GList *homebank_qif_import(gchar *filename, ImportContext *ictx)
680 {
681 GList *list = NULL;
682
683 DB( g_print("\n[import] homebank QIF\n") );
684
685 //todo: context ?
686 list = account_import_qif(filename, ictx);
687
688 return list;
689 }
690
691
692 static void import_clearall(struct import_data *data)
693 {
694 GList *lxxx, *list;
695 GtkTreeModel *model;
696
697 DB( g_print("\n[import] clear all\n") );
698
699 // clear transactions
700 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->imported_ope));
701 gtk_list_store_clear (GTK_LIST_STORE(model));
702
703 // 1: remove imported accounts
704 lxxx = list = g_hash_table_get_values(GLOBALS->h_acc);
705 while (list != NULL)
706 {
707 Account *item = list->data;
708
709 if( item->imported == TRUE )
710 {
711 //DB( g_print(" -> remove acc %x '%s'\n", item, item->name) );
712 da_acc_remove(item->key);
713 }
714 list = g_list_next(list);
715 }
716 g_list_free(lxxx);
717
718 // 2: remove imported payees
719 lxxx = list = g_hash_table_get_values(GLOBALS->h_pay);
720 while (list != NULL)
721 {
722 Payee *item = list->data;
723
724 if( item->imported == TRUE )
725 {
726 //DB( g_print(" -> remove pay '%s'\n", item->name) );
727 da_pay_remove(item->key);
728 }
729 list = g_list_next(list);
730 }
731 g_list_free(lxxx);
732
733 // 3: remove imported category
734 lxxx = list = g_hash_table_get_values(GLOBALS->h_cat);
735 while (list != NULL)
736 {
737 Category *item = list->data;
738
739 if( item->imported == TRUE )
740 {
741 //DB( g_print(" -> remove cat '%s'\n", item->name) );
742 da_cat_remove(item->key);
743 }
744 list = g_list_next(list);
745 }
746 g_list_free(lxxx);
747
748 da_transaction_destroy(data->ictx.trans_list);
749 data->ictx.trans_list = NULL;
750 data->ictx.cnt_err_date = 0;
751 data->ictx.cnt_new_pay = 0;
752 data->ictx.cnt_new_cat = 0;
753
754 data->ictx.datefmt = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_dateorder));
755
756 data->ictx.cnt_initial_acc = da_acc_length();
757
758 }
759
760
761 /*
762 * find duplicate transactions
763 *
764 * for
765 *
766 */
767 static void import_find_duplicate_transactions(struct import_data *data)
768 {
769 GList *tmplist, *implist;
770 Transaction *item;
771 guint32 mindate;
772 guint maxgap;
773
774 DB( g_print("\n[import] find duplicate\n") );
775
776 data->ictx.nb_duplicate = 0;
777 if( data->ictx.trans_list )
778 {
779 /* 1: get import min bound date */
780 tmplist = g_list_first(data->ictx.trans_list);
781 item = tmplist->data;
782 mindate = item->date;
783 maxgap = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_maxgap));
784
785 /* clear any previous same txn */
786 implist = g_list_first(data->ictx.trans_list);
787 while (implist != NULL)
788 {
789 Transaction *impope = implist->data;
790
791 if(impope->same != NULL)
792 {
793 g_list_free(impope->same);
794 impope->same = NULL;
795 }
796 implist = g_list_next(implist);
797 }
798
799 tmplist = g_list_first(GLOBALS->ope_list);
800 while (tmplist != NULL)
801 {
802 Transaction *ope = tmplist->data;
803
804 //if( ope->account == accnum && ope->date >= mindate )
805 if( ope->date >= mindate )
806 {
807 //DB( g_print("should check here %d: %s\n", ope->date, ope->wording) );
808
809 implist = g_list_first(data->ictx.trans_list);
810 while (implist != NULL)
811 {
812 Transaction *impope = implist->data;
813 Account *acc;
814 guint acckey;
815
816 //here we should test acc->imp_key and not impope->account
817 acckey = impope->kacc;
818 acc = da_acc_get(acckey);
819 if( acc )
820 {
821 if( acc->imp_key > 0 )
822 acckey = acc->imp_key;
823 }
824
825 if(
826 (acckey == ope->kacc) &&
827 (impope->amount == ope->amount) &&
828 (ope->date <= (impope->date + maxgap)) && (ope->date >= (impope->date - maxgap))
829 )
830 {
831 //DB( g_print(" found %d: %s\n", impope->date, impope->wording) );
832
833 impope->same = g_list_append(impope->same, ope);
834 data->ictx.nb_duplicate++;
835 }
836
837 implist = g_list_next(implist);
838 }
839 }
840
841 tmplist = g_list_next(tmplist);
842 }
843 }
844
845 DB( g_print(" nb_duplicate = %d\n", data->ictx.nb_duplicate) );
846
847
848 }
849
850
851 static void ui_import_populate_account(struct import_data *data)
852 {
853 GList *lacc, *list;
854
855 DB( g_print("\n[import] populate account\n") );
856
857 // clear accounts
858 gtk_list_store_clear (GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc))));
859
860
861 lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
862 while (list != NULL)
863 {
864 Account *item = list->data;
865
866 if( item->imported == TRUE )
867 {
868 ui_acc_affect_listview_add(GTK_TREE_VIEW(data->LV_acc), item);
869 }
870 list = g_list_next(list);
871 }
872 g_list_free(lacc);
873
874 }
875
876
877
878
879 /* count account to be imported */
880 static void import_analysis_count(struct import_data *data)
881 {
882 GList *lacc, *list;
883
884 DB( g_print("\n[import] count_new_account\n") );
885
886 data->ictx.cnt_new_acc = 0;
887 data->ictx.cnt_new_ope = 0;
888
889 /* count account */
890 lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
891 while (list != NULL)
892 {
893 Account *item = list->data;
894
895 if( item->imported == TRUE )
896 {
897 data->ictx.cnt_new_acc++;
898 }
899 list = g_list_next(list);
900 }
901 g_list_free(lacc);
902
903 /* count transaction */
904 data->ictx.cnt_new_ope = g_list_length(data->ictx.trans_list);
905
906 }
907
908
909
910 /* count transaction with checkbox 'import' */
911 static void import_count_changes(struct import_data *data)
912 {
913 GList *lacc, *list;
914 GtkTreeModel *model;
915 GtkTreeIter iter;
916 gboolean valid;
917
918 DB( g_print("\n[import] count_final_changes\n") );
919
920 data->imp_cnt_acc = 0;
921
922 lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
923 while (list != NULL)
924 {
925 Account *item = list->data;
926
927 if( item->imported == TRUE && item->imp_key != 0)
928 {
929 data->imp_cnt_acc++;
930 }
931 list = g_list_next(list);
932 }
933 g_list_free(lacc);
934
935
936 // then import transactions
937 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->imported_ope));
938
939 data->imp_cnt_trn = 0;
940
941 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
942 while (valid)
943 {
944 gboolean toimport;
945
946 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
947 LST_OPE_IMPTOGGLE, &toimport,
948 -1);
949
950 if(toimport == TRUE)
951 data->imp_cnt_trn++;
952
953 /* Make iter point to the next row in the list store */
954 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
955 }
956 }
957
958
959
960
961
962
963
964 static void import_apply(struct import_data *data)
965 {
966 GtkTreeModel *model;
967 GtkTreeIter iter;
968 gboolean valid;
969 GList *lxxx, *list;
970
971 DB( g_print("\n[import] apply\n") );
972
973 // 1: persist imported accounts
974 lxxx = list = g_hash_table_get_values(GLOBALS->h_acc);
975 while (list != NULL)
976 {
977 Account *item = list->data;
978
979 if( item->imported == TRUE )
980 {
981 //only persist user selected to new account
982 if( item->imp_key == 0)
983 {
984 //DB( g_print(" -> persist acc %x '%s'\n", item, item->name) );
985 item->imported = FALSE;
986 g_free(item->imp_name);
987 item->imp_name = NULL;
988 }
989 }
990 list = g_list_next(list);
991 }
992 g_list_free(lxxx);
993
994 // 2: persist imported payees
995 lxxx = list = g_hash_table_get_values(GLOBALS->h_pay);
996 while (list != NULL)
997 {
998 Payee *item = list->data;
999
1000 if( item->imported == TRUE )
1001 {
1002 //DB( g_print(" -> persist pay '%s'\n", item->name) );
1003 item->imported = FALSE;
1004 }
1005 list = g_list_next(list);
1006 }
1007 g_list_free(lxxx);
1008
1009 // 3: persist imported categories
1010 lxxx = list = g_hash_table_get_values(GLOBALS->h_cat);
1011 while (list != NULL)
1012 {
1013 Category *item = list->data;
1014
1015 if( item->imported == TRUE )
1016 {
1017 //DB( g_print(" -> persist cat '%s'\n", item->name) );
1018 item->imported = FALSE;
1019 }
1020 list = g_list_next(list);
1021 }
1022 g_list_free(lxxx);
1023
1024 // 4: insert every transactions
1025 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->imported_ope));
1026 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
1027 while (valid)
1028 {
1029 Transaction *item;
1030 gboolean toimport;
1031
1032 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
1033 LST_DSPOPE_DATAS, &item,
1034 LST_OPE_IMPTOGGLE, &toimport,
1035 -1);
1036
1037 if(toimport == TRUE)
1038 {
1039 Account *acc;
1040 //DB(g_print("import %d to acc: %d\n", data->total, item->account) );
1041
1042 //todo: here also test imp_key on account and change the key into the transaction
1043
1044 acc = da_acc_get(item->kacc);
1045 if( acc != NULL)
1046 {
1047 if( acc->imp_key > 0)
1048 {
1049 item->kacc = acc->imp_key;
1050 }
1051 }
1052
1053 transaction_add(item, NULL, 0);
1054 }
1055
1056 /* Make iter point to the next row in the list store */
1057 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
1058 }
1059
1060
1061 }
1062
1063 /*
1064 **
1065 */
1066 static gboolean
1067 import_dispose(GtkWidget *widget, gpointer user_data)
1068 {
1069 struct import_data *data = user_data;
1070
1071 DB( g_print("\n[import] dispose\n") );
1072
1073 #if MYDEBUG == 1
1074 gpointer data2 = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1075 g_print(" user_data=%08x to be free, data2=%x\n", (gint)user_data, (gint)data2);
1076 #endif
1077
1078 g_free( data->filename );
1079
1080 import_clearall(data);
1081
1082
1083
1084
1085 // todo: optimize this
1086 if(data->imp_cnt_trn > 0)
1087 {
1088 GLOBALS->changes_count += data->imp_cnt_trn;
1089
1090 //our global list has changed, so update the treeview
1091 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_REFRESHALL));
1092 }
1093
1094
1095 g_free(user_data);
1096
1097
1098 //delete-event TRUE abort/FALSE destroy
1099 return FALSE;
1100 }
1101
1102
1103 static void import_fill_imp_transactions(struct import_data *data)
1104 {
1105 GtkWidget *view;
1106 GtkTreeModel *model;
1107 GtkTreeIter iter;
1108 GList *tmplist;
1109
1110 DB( g_print("\n[import] fill imp operatoin\n") );
1111
1112 view = data->imported_ope;
1113 model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1114
1115 gtk_list_store_clear (GTK_LIST_STORE(model));
1116
1117 g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
1118 gtk_tree_view_set_model(GTK_TREE_VIEW(view), NULL); /* Detach model from view */
1119
1120 tmplist = g_list_first(data->ictx.trans_list);
1121 while (tmplist != NULL)
1122 {
1123 Transaction *item = tmplist->data;
1124
1125 /* append to our treeview */
1126 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
1127
1128 //DB( g_print(" populate: %s\n", ope->ope_Word) );
1129
1130 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
1131 LST_DSPOPE_DATAS, item,
1132 LST_OPE_IMPTOGGLE, item->same == NULL ? TRUE : FALSE,
1133 -1);
1134
1135 //DB( g_print(" - fill: %d, %s %.2f %x\n", item->account, item->wording, item->amount, item->same) );
1136
1137 tmplist = g_list_next(tmplist);
1138 }
1139
1140 gtk_tree_view_set_model(GTK_TREE_VIEW(view), model); /* Re-attach model to view */
1141
1142 g_object_unref(model);
1143
1144
1145
1146 }
1147
1148 static void import_fillsame(GtkWidget *widget, gpointer user_data)
1149 {
1150 struct import_data *data;
1151 GtkTreeSelection *selection;
1152 GtkTreeModel *model, *newmodel;
1153 GtkTreeIter iter, newiter;
1154 GList *tmplist;
1155 GtkWidget *view;
1156
1157
1158 DB( g_print("\n[import] fillsame\n") );
1159
1160 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1161
1162 view = data->duplicat_ope;
1163 newmodel = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
1164
1165 gtk_list_store_clear (GTK_LIST_STORE(newmodel));
1166
1167
1168
1169 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->imported_ope));
1170 //if true there is a selected node
1171 if (gtk_tree_selection_get_selected(selection, &model, &iter))
1172 {
1173 Transaction *item;
1174
1175 gtk_tree_model_get(model, &iter, LST_DSPOPE_DATAS, &item, -1);
1176
1177 if( item->same != NULL )
1178 {
1179 tmplist = g_list_first(item->same);
1180 while (tmplist != NULL)
1181 {
1182 Transaction *tmp = tmplist->data;
1183
1184 /* append to our treeview */
1185 gtk_list_store_append (GTK_LIST_STORE(newmodel), &newiter);
1186
1187 gtk_list_store_set (GTK_LIST_STORE(newmodel), &newiter,
1188 LST_DSPOPE_DATAS, tmp,
1189 -1);
1190
1191 DB( g_print(" - fill: %s %.2f %x\n", item->wording, item->amount, (unsigned int)item->same) );
1192
1193 tmplist = g_list_next(tmplist);
1194 }
1195 }
1196
1197 }
1198
1199
1200 }
1201
1202
1203 /*
1204 ** modify target account
1205 */
1206
1207
1208 static void on_account_type_toggled(GtkRadioButton *radiobutton, gpointer user_data)
1209 {
1210 struct import_target_data *data;
1211 gboolean new_account;
1212
1213
1214 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(radiobutton), GTK_TYPE_WINDOW)), "inst_data");
1215
1216 DB( g_print("\n[import] account type toggle\n") );
1217
1218 new_account = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->radio[0]));
1219
1220 gtk_widget_set_sensitive(data->getwidget1, new_account);
1221 gtk_widget_set_sensitive(data->getwidget2, new_account^1);
1222
1223 }
1224
1225
1226 static void import_edit_target_account(GtkWidget *widget, gpointer user_data)
1227 {
1228 struct import_data *data;
1229 struct import_target_data ddata;
1230 GtkWidget *dialog, *content, *mainvbox, *table, *label ;
1231 guint32 key;
1232 gint row;
1233
1234 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1235 DB( g_print("\n[import] edit target account\n") );
1236
1237 key = ui_acc_affect_listview_get_selected_key(GTK_TREE_VIEW(data->LV_acc));
1238 if( key > 0 )
1239 {
1240 Account *item;
1241
1242 item = da_acc_get( key );
1243
1244 dialog = gtk_dialog_new_with_buttons (_("Change HomeBank account target"),
1245 GTK_WINDOW (data->assistant),
1246 0,
1247 GTK_STOCK_CANCEL,
1248 GTK_RESPONSE_REJECT,
1249 GTK_STOCK_OK,
1250 GTK_RESPONSE_ACCEPT,
1251 NULL);
1252
1253 //store our window private data
1254 g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)&ddata);
1255
1256 content = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
1257
1258 mainvbox = gtk_vbox_new (FALSE, 0);
1259 gtk_box_pack_start (GTK_BOX (content), mainvbox, TRUE, TRUE, 0);
1260 gtk_container_set_border_width (GTK_CONTAINER(mainvbox), HB_MAINBOX_SPACING);
1261
1262 table = gtk_table_new (3, 2, FALSE);
1263 gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
1264 gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
1265 gtk_box_pack_start (GTK_BOX (mainvbox), table, TRUE, TRUE, HB_BOX_SPACING);
1266
1267 /* area 1 : file summary */
1268
1269 row = 0;
1270 ddata.radio[0] = gtk_radio_button_new_with_label (NULL, _("new account"));
1271 gtk_table_attach (GTK_TABLE (table), ddata.radio[0], 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1272
1273 label = make_label(_("_Name:"), 0, 0.5);
1274 gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1275
1276 ddata.getwidget1 = gtk_entry_new();
1277 gtk_table_attach (GTK_TABLE (table), ddata.getwidget1, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1278
1279 row++;
1280 ddata.radio[1] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON (ddata.radio[0]), _("existing account"));
1281 gtk_table_attach (GTK_TABLE (table), ddata.radio[1], 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1282
1283 label = make_label(_("A_ccount:"), 0, 0.5);
1284 gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1285
1286 ddata.getwidget2 = ui_acc_comboboxentry_new(NULL);
1287 gtk_table_attach (GTK_TABLE (table), ddata.getwidget2, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1288
1289 //initialize
1290 if( data->ictx.cnt_initial_acc > 0 ) //if there were already some accounts
1291 {
1292 gtk_widget_set_sensitive(ddata.radio[1], TRUE);
1293 if( item->imp_key > 0 )
1294 {
1295 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ddata.radio[1]), TRUE);
1296 }
1297 }
1298 else
1299 {
1300 gtk_widget_set_sensitive(ddata.radio[1], FALSE);
1301
1302 }
1303
1304 gtk_entry_set_text(GTK_ENTRY(ddata.getwidget1), item->name);
1305 ui_acc_comboboxentry_populate(GTK_COMBO_BOX(ddata.getwidget2), GLOBALS->h_acc, ACC_LST_INSERT_NORMAL);
1306 ui_acc_comboboxentry_set_active(GTK_COMBO_BOX(ddata.getwidget2), item->imp_key);
1307
1308 on_account_type_toggled(GTK_RADIO_BUTTON (ddata.radio[0]), NULL);
1309
1310 gtk_widget_show_all(mainvbox);
1311
1312 g_signal_connect (ddata.radio[0], "toggled", G_CALLBACK (on_account_type_toggled), NULL);
1313
1314
1315 //wait for the user
1316 gint result = gtk_dialog_run (GTK_DIALOG (dialog));
1317
1318 if(result == GTK_RESPONSE_ACCEPT)
1319 {
1320 gchar *name;
1321 gboolean bnew;
1322 guint key;
1323
1324 key = ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(ddata.getwidget2));
1325
1326 bnew = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ddata.radio[0]));
1327 if( bnew )
1328 {
1329
1330 name = (gchar *)gtk_entry_get_text(GTK_ENTRY(ddata.getwidget1));
1331
1332 if(strcasecmp(name, item->name))
1333 {
1334
1335 DB( g_print("name '%s', existing acc %d\n", name, key) );
1336
1337 if (name && *name)
1338 {
1339 if( account_rename(item, name) == FALSE )
1340 {
1341 ui_dialog_msg_infoerror(GTK_WINDOW(dialog), GTK_MESSAGE_ERROR,
1342 _("Error"),
1343 _("Cannot rename this Account,\n"
1344 "from '%s' to '%s',\n"
1345 "this name already exists."),
1346 item->name,
1347 name
1348 );
1349 }
1350 }
1351 }
1352 else
1353 {
1354 item->imp_key = 0;
1355 }
1356 }
1357 else
1358 {
1359 item->imp_key = key;
1360 }
1361
1362 //we should refresh duplicate
1363 import_find_duplicate_transactions(data);
1364 import_fill_imp_transactions(data);
1365
1366 }
1367
1368 // cleanup and destroy
1369 gtk_widget_destroy (dialog);
1370 }
1371
1372 }
1373
1374
1375 static void ui_import_selchange(GtkWidget *widget, gpointer user_data)
1376 {
1377 struct import_data *data = user_data;
1378 gint page_number;
1379 GtkWidget *current_page;
1380 gchar *filename;
1381
1382 page_number = gtk_assistant_get_current_page (GTK_ASSISTANT(data->assistant));
1383
1384 DB( g_print("\n[import] selchange (page %d)\n", page_number+1) );
1385
1386 data->valid = FALSE;
1387
1388 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(data->filechooser));
1389 if( filename == NULL )
1390 {
1391 gtk_label_set_text(GTK_LABEL(data->user_info), _("Please select a file..."));
1392 //current_page = gtk_assistant_get_nth_page (GTK_ASSISTANT(data->assistant), page_number);
1393 //gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), current_page, FALSE);
1394 }
1395 else
1396 {
1397 if( page_number == PAGE_FILE )
1398 {
1399 if(data->filename)
1400 g_free( data->filename );
1401 data->filename = filename;
1402 //DB( g_print(" filename -> %s\n", data->filename) );
1403
1404 data->filetype = homebank_alienfile_recognize(data->filename);
1405 switch(data->filetype)
1406 {
1407 case FILETYPE_QIF:
1408 gtk_label_set_text(GTK_LABEL(data->user_info), _("QIF file recognised !"));
1409 data->valid = TRUE;
1410 break;
1411
1412 case FILETYPE_OFX:
1413 #ifndef NOOFX
1414 gtk_label_set_text(GTK_LABEL(data->user_info), _("OFX file recognised !"));
1415 data->valid = TRUE;
1416 #else
1417 gtk_label_set_text(GTK_LABEL(data->user_info), _("** OFX support is disabled **"));
1418 #endif
1419 break;
1420
1421 case FILETYPE_CSV_HB:
1422 gtk_label_set_text(GTK_LABEL(data->user_info), _("CSV transaction file recognised !"));
1423 data->valid = TRUE;
1424 break;
1425
1426 default:
1427 data->filetype = FILETYPE_UNKNOW;
1428 gtk_label_set_text(GTK_LABEL(data->user_info), _("Unknown/Invalid file..."));
1429 break;
1430 }
1431
1432 current_page = gtk_assistant_get_nth_page (GTK_ASSISTANT(data->assistant), page_number);
1433 gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), current_page, data->valid);
1434
1435 }
1436
1437 }
1438
1439 if(data->valid == TRUE)
1440 {
1441 gtk_widget_show(data->ok_image);
1442 gtk_widget_hide(data->ko_image);
1443 }
1444 else
1445 {
1446 gtk_widget_show(data->ko_image);
1447 gtk_widget_hide(data->ok_image);
1448 }
1449
1450 }
1451
1452
1453
1454 static void ui_import_selection(GtkTreeSelection *treeselection, gpointer user_data)
1455 {
1456 import_fillsame(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), NULL);
1457 }
1458
1459
1460 static void ui_import_update_filecontent(struct import_data *data)
1461 {
1462 gchar *tmpstr;
1463
1464 /* file name & path */
1465 tmpstr = g_path_get_basename(data->filename);
1466 gtk_label_set_text(GTK_LABEL(data->TX_filename), tmpstr);
1467 g_free(tmpstr);
1468
1469 tmpstr = g_path_get_dirname(data->filename);
1470 gtk_label_set_text(GTK_LABEL(data->TX_filepath), tmpstr);
1471 g_free(tmpstr);
1472
1473 gtk_label_set_text(GTK_LABEL(data->TX_encoding), data->ictx.encoding);
1474
1475 /* file content detail */
1476 //TODO: difficult translation here
1477 tmpstr = g_strdup_printf(_("account: %d - transaction: %d - payee: %d - categorie: %d"),
1478 data->ictx.cnt_new_acc,
1479 data->ictx.cnt_new_ope,
1480 data->ictx.cnt_new_pay,
1481 data->ictx.cnt_new_cat
1482 );
1483 gtk_label_set_text(GTK_LABEL(data->TX_filedetails), tmpstr);
1484 g_free(tmpstr);
1485 }
1486
1487 static void ui_import_integer_to_label(guint value, GtkWidget *label)
1488 {
1489 gchar *tmpstr;
1490
1491 tmpstr = g_strdup_printf("%d", value);
1492 gtk_label_set_text(GTK_LABEL(label), tmpstr);
1493 g_free(tmpstr);
1494
1495 }
1496
1497
1498 static void ui_import_update_summary(struct import_data *data)
1499 {
1500
1501 /* account summary */
1502 ui_import_integer_to_label(data->imp_cnt_acc , data->TX_acc_upd);
1503 ui_import_integer_to_label(data->ictx.cnt_new_acc - data->imp_cnt_acc, data->TX_acc_new);
1504
1505 /* transaction summary */
1506 ui_import_integer_to_label(data->imp_cnt_trn , data->TX_trn_imp);
1507 ui_import_integer_to_label(data->ictx.cnt_new_ope - data->imp_cnt_trn, data->TX_trn_nop);
1508 ui_import_integer_to_label(data->imp_cnt_asg , data->TX_trn_asg);
1509
1510 }
1511
1512 static void
1513 ui_import_apply (GtkWidget *widget, gpointer user_data)
1514 {
1515 struct import_data *data;
1516
1517 DB( g_print("\n[import] apply\n") );
1518
1519 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1520
1521
1522 import_apply(data);
1523
1524 }
1525
1526 static void
1527 ui_import_close_cancel (GtkWidget *widget, gpointer user_data)
1528 {
1529 struct import_data *data;
1530 GtkWidget *assistant = (GtkWidget *) user_data;
1531
1532 DB( g_print("\n[import] close\n") );
1533
1534 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1535
1536 import_dispose(widget, data);
1537
1538
1539 //g_free(data);
1540
1541
1542 gtk_widget_destroy (assistant);
1543 //assistant = NULL;
1544 }
1545
1546 static void import_file_import(struct import_data *data)
1547 {
1548
1549 import_clearall(data);
1550
1551 DB( g_print(" -> get encoding of '%s'\n", data->filename) );
1552
1553 data->ictx.encoding = homebank_file_getencoding(data->filename);
1554 DB( g_print(" -> encoding is '%s'\n", data->ictx.encoding) );
1555
1556
1557 DB( g_print(" -> load file '%s'\n", data->filename) );
1558
1559 switch(data->filetype)
1560 {
1561 #ifndef NOOFX
1562 /* ofx_acc_list & ofx_ope_list are filled here */
1563 case FILETYPE_OFX:
1564 data->ictx.trans_list = homebank_ofx_import(data->filename, &data->ictx);
1565 break;
1566 #endif
1567 case FILETYPE_QIF:
1568 data->ictx.trans_list = homebank_qif_import(data->filename, &data->ictx);
1569 break;
1570
1571 case FILETYPE_CSV_HB:
1572 data->ictx.trans_list = homebank_csv_import(data->filename, &data->ictx);
1573 break;
1574 }
1575
1576 // sort by date
1577 data->ictx.trans_list = da_transaction_sort(data->ictx.trans_list);
1578
1579
1580
1581 }
1582
1583
1584 static void
1585 ui_import_prepare (GtkWidget *widget, GtkWidget *page, gpointer user_data)
1586 {
1587 struct import_data *data;
1588 gint current_page, n_pages;
1589 gchar *title;
1590
1591 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1592
1593 current_page = gtk_assistant_get_current_page (GTK_ASSISTANT(data->assistant));
1594 n_pages = gtk_assistant_get_n_pages (GTK_ASSISTANT(data->assistant));
1595
1596 DB( g_print("\n[import] prepare %d of %d\n", current_page, n_pages) );
1597
1598 switch( current_page )
1599 {
1600 case PAGE_INTRO:
1601 DB( g_print(" -> 1 intro\n") );
1602 gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), page, TRUE);
1603 break;
1604
1605 case PAGE_FILE:
1606 DB( g_print(" -> 2 file choose\n") );
1607
1608 gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), data->pages[PAGE_RESULT], FALSE);
1609 gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), data->pages[PAGE_OPTIONS], FALSE);
1610 gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), data->pages[PAGE_CONFIRM], FALSE);
1611
1612
1613 // the page complete is contextual in ui_import_selchange
1614 break;
1615
1616 case PAGE_RESULT:
1617 DB( g_print(" -> 3 real import\n") );
1618 //gtk_assistant_set_current_page(GTK_ASSISTANT (widget), PAGE_IMPORT);
1619
1620 /* remind folder to preference */
1621 gchar *folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(data->filechooser));
1622 g_free(PREFS->path_import);
1623 PREFS->path_import = folder;
1624
1625 import_file_import(data);
1626 import_analysis_count(data);
1627 ui_import_update_filecontent(data);
1628
1629 DB( g_print(" -> determine completion: nbtrans=%d, errors=%d\n", data->ictx.cnt_new_ope, data->ictx.cnt_err_date) );
1630
1631 gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), data->pages[PAGE_OPTIONS], FALSE);
1632 gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), page, FALSE);
1633
1634 //TODO: Check this is sufficient
1635 if( data->ictx.cnt_err_date > 0 )
1636 {
1637 gtk_widget_show(data->GR_options);
1638 gtk_widget_show(data->GR_error);
1639 }
1640 else
1641 {
1642 gtk_widget_hide(data->GR_options);
1643 gtk_widget_hide(data->GR_error);
1644 }
1645
1646 if( data->ictx.cnt_new_ope > 0 && data->ictx.cnt_err_date <= 0 )
1647 {
1648 gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), page, TRUE);
1649 }
1650 break;
1651
1652 case PAGE_OPTIONS:
1653 DB( g_print(" -> post load actions\n") );
1654
1655 //todo: should be optional
1656 data->imp_cnt_asg = transaction_auto_assign(data->ictx.trans_list, 0);
1657
1658 import_find_duplicate_transactions(data);
1659
1660 ui_import_populate_account(data);
1661 import_fill_imp_transactions(data);
1662
1663 if( data->ictx.nb_duplicate > 0 )
1664 {
1665 gtk_widget_show(data->GR_duplicate);
1666 }
1667 else
1668 {
1669 gtk_widget_hide(data->GR_duplicate);
1670 }
1671
1672 gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), page, TRUE);
1673 break;
1674
1675 case PAGE_CONFIRM:
1676 {
1677 DB( g_print(" -> 6 apply\n") );
1678
1679 //todo:rework this
1680 import_count_changes(data);
1681
1682 ui_import_update_summary(data);
1683
1684
1685
1686 gtk_assistant_set_page_complete (GTK_ASSISTANT(data->assistant), page, TRUE);
1687 break;
1688 }
1689 }
1690
1691 title = g_strdup_printf ( _("HomeBank Import Assistant - (%d of %d)"), current_page + 1 , n_pages );
1692 gtk_window_set_title (GTK_WINDOW (data->assistant), title);
1693 g_free (title);
1694 }
1695
1696
1697 /**
1698 * ui_import_forward_page_func:
1699 *
1700 * define the page to be called when the user forward
1701 *
1702 * Return value: the page number
1703 *
1704 */
1705 static gint
1706 ui_import_forward_page_func(gint current_page, gpointer func_data)
1707 {
1708 //struct import_data *data = func_data;
1709 gint next_page;
1710
1711 DB( g_print("\n[import] forward page\n") );
1712
1713 // normal forward
1714 next_page = current_page + 1;
1715
1716 DB( g_print(" -> curr page: %d ==> next page: %d\n", current_page, next_page) );
1717 DB( g_print(" -> page is %s\n", page_titles[current_page]) );
1718
1719 return next_page;
1720 }
1721
1722
1723
1724
1725
1726 static void
1727 import_refresh_transaction (GtkWidget *widget, gpointer data)
1728 {
1729
1730 DB( g_print("\n[import] refresh transaction\n") );
1731
1732 import_find_duplicate_transactions(data);
1733 import_fill_imp_transactions(data);
1734
1735 }
1736
1737 static void
1738 import_file_refresh_cb(GtkWidget *widget, gpointer user_data)
1739 {
1740 struct import_data *data;
1741
1742 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1743
1744 DB( g_print("\n[import] refresh file\n") );
1745 ui_import_prepare(data->assistant, data->pages[PAGE_RESULT], NULL);
1746 }
1747
1748
1749
1750
1751 static void import_acc_affect_onRowActivated (GtkTreeView *treeview,
1752 GtkTreePath *path,
1753 GtkTreeViewColumn *col,
1754 gpointer userdata)
1755 {
1756 //GtkTreeModel *model;
1757
1758 //model = gtk_tree_view_get_model(treeview);
1759 //gtk_tree_model_get_iter_first(model, &iter);
1760 //if(gtk_tree_selection_iter_is_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), &iter) == FALSE)
1761 //{
1762 import_edit_target_account(GTK_WIDGET(treeview), NULL);
1763 //}
1764 }
1765
1766
1767 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1768
1769 /**
1770 * create_page1:
1771 *
1772 * page 1: intro
1773 *
1774 * Return value: a vbox widget
1775 *
1776 */
1777 static GtkWidget *
1778 ui_import_page1(GtkWidget *assistant, struct import_data *data)
1779 {
1780 GtkWidget *vbox, *label, *align;
1781
1782 align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
1783 gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 0, 0);
1784
1785 vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
1786 gtk_container_set_border_width (GTK_CONTAINER(vbox), HB_MAINBOX_SPACING);
1787 gtk_container_add(GTK_CONTAINER(align), vbox);
1788
1789 label = make_label(
1790 _("Welcome to the HomeBank Import Assistant.\n\n" \
1791 "With this assistant you will be guided throught the process\n" \
1792 "of importing an external file into HomeBank.\n\n" \
1793 "No changes will be made until you click \"Apply\" at the end\n" \
1794 "of this assistant.")
1795 , 0., 0.0);
1796 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, HB_BOX_SPACING);
1797
1798 /* supported format */
1799
1800
1801 label = make_label(
1802 _("HomeBank can import files in the following formats:\n" \
1803 "- QIF\n" \
1804 "- OFX/QFX (optional at compilation time)\n" \
1805 "- CSV (format is specific to HomeBank, see the documentation)\n" \
1806 ), 0.0, 0.0);
1807
1808 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, HB_BOX_SPACING);
1809
1810
1811 gtk_widget_show_all (align);
1812
1813 gtk_assistant_append_page (GTK_ASSISTANT (assistant), align);
1814 gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), align, GTK_ASSISTANT_PAGE_INTRO);
1815 gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), align, _(page_titles[PAGE_INTRO]));
1816 //gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), align, TRUE);
1817
1818 #if HEAD_IMAGE == 1
1819 gtk_assistant_set_page_header_image (GTK_ASSISTANT (assistant), align, data->head_pixbuf);
1820 #endif
1821
1822 #if SIDE_IMAGE == 1
1823 gtk_assistant_set_page_side_image (GTK_ASSISTANT (assistant), align, data->side_pixbuf);
1824 #endif
1825
1826
1827 return align;
1828 }
1829
1830
1831 /**
1832 * create_page2:
1833 *
1834 * page 2: file selection
1835 *
1836 * Return value: a vbox widget
1837 *
1838 */
1839 static GtkWidget *
1840 ui_import_page2 (GtkWidget *assistant, struct import_data *data)
1841 {
1842 GtkWidget *vbox, *hbox, *align, *widget, *label;
1843 GtkFileFilter *filter;
1844
1845 vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
1846 gtk_container_set_border_width (GTK_CONTAINER(vbox), HB_MAINBOX_SPACING);
1847
1848
1849 // widget = gtk_file_chooser_button_new ("Pick a File", GTK_FILE_CHOOSER_ACTION_OPEN);
1850
1851 widget = gtk_file_chooser_widget_new(GTK_FILE_CHOOSER_ACTION_OPEN);
1852
1853 data->filechooser = widget;
1854 gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
1855
1856 filter = gtk_file_filter_new ();
1857 gtk_file_filter_set_name (filter, _("Known files"));
1858 gtk_file_filter_add_pattern (filter, "*.[Qq][Ii][Ff]");
1859 #ifndef NOOFX
1860 gtk_file_filter_add_pattern (filter, "*.[OoQq][Ff][Xx]");
1861 #endif
1862 gtk_file_filter_add_pattern (filter, "*.[Cc][Ss][Vv]");
1863 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(widget), filter);
1864
1865
1866 filter = gtk_file_filter_new ();
1867 gtk_file_filter_set_name (filter, _("QIF files"));
1868 gtk_file_filter_add_pattern (filter, "*.[Qq][Ii][Ff]");
1869 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(widget), filter);
1870
1871 #ifndef NOOFX
1872 filter = gtk_file_filter_new ();
1873 gtk_file_filter_set_name (filter, _("OFX/QFX files"));
1874 gtk_file_filter_add_pattern (filter, "*.[OoQq][Ff][Xx]");
1875 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(widget), filter);
1876 #endif
1877
1878 filter = gtk_file_filter_new ();
1879 gtk_file_filter_set_name (filter, _("CSV files"));
1880 gtk_file_filter_add_pattern (filter, "*.[Cc][Ss][Vv]");
1881 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(widget), filter);
1882
1883 filter = gtk_file_filter_new ();
1884 gtk_file_filter_set_name (filter, _("All files"));
1885 gtk_file_filter_add_pattern (filter, "*");
1886 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(widget), filter);
1887
1888
1889 /* our addon message */
1890 align = gtk_alignment_new(0.65, 0, 0, 0);
1891 gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
1892
1893 hbox = gtk_hbox_new (FALSE, 0);
1894 gtk_container_add(GTK_CONTAINER(align), hbox);
1895
1896 label = gtk_label_new("");
1897 data->user_info = label;
1898 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, HB_BOX_SPACING);
1899
1900 gimp_label_set_attributes (GTK_LABEL (label),
1901 PANGO_ATTR_SCALE, PANGO_SCALE_LARGE,
1902 PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
1903 -1);
1904
1905
1906
1907 widget = gtk_image_new_from_stock(GTK_STOCK_YES, GTK_ICON_SIZE_BUTTON);
1908 data->ok_image = widget;
1909 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
1910
1911 widget = gtk_image_new_from_stock(GTK_STOCK_NO, GTK_ICON_SIZE_BUTTON);
1912 data->ko_image = widget;
1913 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
1914
1915
1916 gtk_widget_show_all (vbox);
1917 gtk_widget_hide(data->ok_image);
1918 gtk_widget_hide(data->ko_image);
1919
1920
1921 gtk_assistant_append_page (GTK_ASSISTANT (assistant), vbox);
1922 //gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), vbox, GTK_ASSISTANT_PAGE_CONTENT);
1923 gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), vbox, _(page_titles[PAGE_FILE]));
1924
1925
1926 #if HEAD_IMAGE == 1
1927 gtk_assistant_set_page_header_image (GTK_ASSISTANT (assistant), vbox, data->head_pixbuf);
1928 #endif
1929
1930 #if SIDE_IMAGE == 1
1931 gtk_assistant_set_page_side_image (GTK_ASSISTANT (assistant), vbox, data->side_pixbuf);
1932 #endif
1933
1934
1935 return vbox;
1936 }
1937
1938
1939
1940
1941 static GtkWidget *
1942 ui_import_page3 (GtkWidget *assistant, struct import_data *data)
1943 {
1944 GtkWidget *container, *vbox, *hbox, *table, *label, *widget;
1945 gint row;
1946
1947 container = gtk_vbox_new (FALSE, HB_BOX_SPACING);
1948 gtk_container_set_border_width (GTK_CONTAINER(container), HB_BOX_SPACING);
1949
1950
1951 /* file informations */
1952 label = make_label(_("File to import"), 0.0, 0.5);
1953 gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
1954 gtk_box_pack_start (GTK_BOX (container), label, FALSE, FALSE, 0);
1955
1956
1957 table = gtk_table_new (2, 2, FALSE);
1958 //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
1959 gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
1960 gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
1961
1962 gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0);
1963
1964 /* area 1 : file summary */
1965 row = 0;
1966 label = make_label(_("Path:"), 0.0, 0.5);
1967 gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1968 widget = make_label(NULL, 0.0, 0.5);
1969 data->TX_filepath = widget;
1970 gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1971
1972 row++;
1973 label = make_label(_("Name:"), 0.0, 0.5);
1974 gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1975 widget = make_label(NULL, 0.0, 0.5);
1976 data->TX_filename = widget;
1977 gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1978
1979 row++;
1980 label = make_label(_("Encoding:"), 0.0, 0.5);
1981 gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1982 widget = make_label(NULL, 0.0, 0.5);
1983 data->TX_encoding = widget;
1984 gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1985
1986 row++;
1987 label = make_label(_("Content:"), 0.0, 0.5);
1988 gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1989 widget = make_label(NULL, 0.0, 0.5);
1990 data->TX_filedetails = widget;
1991 gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
1992
1993
1994 /* load options */
1995 vbox = gtk_hbox_new (FALSE, 0);
1996 data->GR_options = vbox;
1997 gtk_box_pack_start (GTK_BOX (container), vbox, FALSE, FALSE, 0);
1998
1999 label = make_label(_("Import options"), 0.0, 0.5);
2000 gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
2001 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
2002
2003 hbox = gtk_hbox_new (FALSE, HB_BOX_SPACING);
2004 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
2005
2006 label = make_label(_("Date order:"), 0.0, 0.5);
2007 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2008
2009 widget = make_cycle(label, CYA_IMPORT_DATEORDER);
2010 data->CY_dateorder = widget;
2011 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
2012
2013
2014 widget = gtk_button_new_with_label (_("Load the file again"));
2015 data->BT_refresh = widget;
2016 gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
2017
2018 g_signal_connect (widget, "clicked",
2019 G_CALLBACK (import_file_refresh_cb), data);
2020
2021 /*
2022 expander = gtk_expander_new (_("File content"));
2023 gtk_box_pack_start (GTK_BOX (container), expander, TRUE, TRUE, 0);
2024 scrollwin = gtk_scrolled_window_new(NULL,NULL);
2025 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2026 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
2027 widget = gtk_text_view_new ();
2028 gtk_container_add(GTK_CONTAINER(scrollwin), widget);
2029 gtk_container_add(GTK_CONTAINER(expander), scrollwin);
2030 */
2031
2032
2033 /* status */
2034 hbox = gtk_hbox_new (FALSE, HB_BOX_SPACING);
2035 data->GR_error = hbox;
2036 gtk_box_pack_start (GTK_BOX (container), hbox, FALSE, FALSE, 0);
2037
2038 widget = gtk_image_new_from_stock(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG );
2039 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
2040 gtk_misc_set_padding(GTK_MISC(widget), HB_BOX_SPACING, 0);
2041
2042 label = gtk_label_new(_(
2043 "Some date conversion errors were encountered during the load of the file.\n" \
2044 "Please try to change the date order format and load the file again.")
2045 );
2046 /*gimp_label_set_attributes (GTK_LABEL (label),
2047 PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
2048 -1);*/
2049 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
2050 gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
2051
2052
2053 gtk_widget_show_all (container);
2054
2055 gtk_assistant_append_page (GTK_ASSISTANT (assistant), container);
2056 //gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), container, GTK_ASSISTANT_PAGE_CONFIRM);
2057 //gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), label, TRUE);
2058 gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), container, _(page_titles[PAGE_RESULT]));
2059
2060 #if HEAD_IMAGE == 1
2061 gtk_assistant_set_page_header_image (GTK_ASSISTANT (assistant), container, data->head_pixbuf);
2062 #endif
2063
2064 #if SIDE_IMAGE == 1
2065 gtk_assistant_set_page_side_image (GTK_ASSISTANT (assistant), container, data->side_pixbuf);
2066 #endif
2067
2068 return container;
2069 }
2070
2071
2072 static GtkWidget *
2073 ui_import_page4_account (GtkWidget *assistant, struct import_data *data)
2074 {
2075 GtkWidget *vbox, *hbox, *widget, *scrollwin;
2076
2077 vbox = gtk_vbox_new(FALSE, HB_BOX_SPACING);
2078 gtk_container_set_border_width (GTK_CONTAINER (vbox), HB_BOX_SPACING);
2079
2080 scrollwin = gtk_scrolled_window_new(NULL,NULL);
2081 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2082 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
2083 widget = ui_acc_affect_listview_new();
2084 gtk_widget_set_size_request(widget, -1, 100);
2085 data->LV_acc = widget;
2086 gtk_container_add(GTK_CONTAINER(scrollwin), widget);
2087 gtk_box_pack_start (GTK_BOX (vbox), scrollwin, TRUE, TRUE, 0);
2088
2089 hbox = gtk_hbox_new(FALSE, HB_BOX_SPACING);
2090 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
2091
2092 widget = gtk_button_new_with_label (_("Edit account to import"));
2093 data->BT_edit = widget;
2094 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
2095
2096 /* signal and other stuff */
2097 g_signal_connect (G_OBJECT (data->BT_edit), "clicked", G_CALLBACK (import_edit_target_account), data);
2098 g_signal_connect (GTK_TREE_VIEW(data->LV_acc), "row-activated", G_CALLBACK (import_acc_affect_onRowActivated), NULL);
2099
2100 return vbox;
2101 }
2102
2103
2104 static GtkWidget *
2105 ui_import_page4_transaction (GtkWidget *assistant, struct import_data *data)
2106 {
2107 GtkWidget *mainbox, *vbox, *align, *hbox, *label, *sw, *widget, *expander;
2108
2109 mainbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
2110 gtk_container_set_border_width (GTK_CONTAINER(mainbox), HB_BOX_SPACING);
2111
2112 /* transaction list */
2113 sw = gtk_scrolled_window_new (NULL, NULL);
2114 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
2115 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2116
2117 widget = create_list_import_transaction();
2118 data->imported_ope = widget;
2119 gtk_container_add (GTK_CONTAINER (sw), widget);
2120
2121 gtk_box_pack_start (GTK_BOX (mainbox), sw, TRUE, TRUE, 0);
2122
2123 /* duplicate section */
2124 expander = gtk_expander_new (_("Detail of duplicate transactions"));
2125 data->GR_duplicate = expander;
2126 gtk_box_pack_start (GTK_BOX (mainbox), expander, FALSE, FALSE, 0);
2127
2128 vbox = gtk_vbox_new (FALSE, 0);
2129 gtk_container_add (GTK_CONTAINER (expander), vbox);
2130
2131 sw = gtk_scrolled_window_new (NULL, NULL);
2132 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
2133 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2134 widget = create_list_transaction(TRN_LIST_TYPE_DETAIL, PREFS->lst_ope_columns);
2135 data->duplicat_ope = widget;
2136 gtk_container_add (GTK_CONTAINER (sw), widget);
2137 gtk_widget_set_size_request(sw, -1, 80);
2138 gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
2139
2140
2141
2142 /* duplicate control */
2143 //expander = gtk_expander_new (_("Change match options"));
2144 //gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 0);
2145
2146 align = gtk_alignment_new(0.5, 0.0, 1.0, 0.0);
2147 /* -- gtk_alignment_set_padding t , b, l, r -- */
2148 gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 12, 0);
2149 //gtk_container_add(GTK_CONTAINER(expander), align);
2150 gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 0);
2151
2152 hbox = gtk_hbox_new (FALSE, HB_BOX_SPACING);
2153 gtk_container_add(GTK_CONTAINER(align), hbox);
2154
2155
2156 label = make_label(_("Date _tolerance:"), 0, 0.5);
2157 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2158 widget = make_numeric(label, 0.0, 14.0);
2159 data->NB_maxgap = widget;
2160 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
2161
2162 //TRANSLATORS: there is a spinner on the left of this label, and so you have 0....x days of date tolerance
2163 label = make_label(_("days"), 0, 0.5);
2164 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
2165
2166
2167 widget = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
2168 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
2169
2170 g_signal_connect (widget, "clicked",
2171 G_CALLBACK (import_refresh_transaction), data);
2172
2173
2174 widget = gtk_image_new_from_stock(GTK_STOCK_INFO, GTK_ICON_SIZE_SMALL_TOOLBAR );
2175 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
2176 gtk_misc_set_padding(GTK_MISC(widget), HB_BOX_SPACING, 0);
2177
2178
2179 label = gtk_label_new(_(
2180 "The match is done in order: by account, amount and date.\n" \
2181 "A date tolerance of 0 day means an exact match")
2182 );
2183 gimp_label_set_attributes (GTK_LABEL (label),
2184 PANGO_ATTR_SCALE, PANGO_SCALE_SMALL,
2185 -1);
2186 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
2187 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2188
2189 gtk_widget_show_all (mainbox);
2190
2191 return mainbox;
2192 }
2193
2194
2195 /**
2196 * create_page3:
2197 *
2198 * page 3: analysis & options
2199 *
2200 * Return value: a table widget
2201 *
2202 */
2203 static GtkWidget *
2204 ui_import_page4 (GtkWidget *assistant, struct import_data *data)
2205 {
2206 GtkWidget *vbox, *table, *label, *notebook;
2207
2208 vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
2209 gtk_container_set_border_width (GTK_CONTAINER(vbox), HB_MAINBOX_SPACING);
2210
2211 //notebook
2212 notebook = gtk_notebook_new();
2213 data->GR_page = notebook;
2214 //gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
2215 //gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
2216 gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
2217
2218 /* account selection */
2219 label = make_label(_("Account to import"), 0.0, 1.0);
2220 table = ui_import_page4_account(assistant, data);
2221 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), table, label);
2222
2223 /* transaction selection */
2224 label = make_label(_("Transaction to import"), 0.0, 1.0);
2225 table = ui_import_page4_transaction(assistant, data);
2226 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), table, label);
2227
2228
2229 gtk_widget_show_all (vbox);
2230 gtk_assistant_append_page (GTK_ASSISTANT (assistant), vbox);
2231 // gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), vbox, GTK_ASSISTANT_PAGE_PROGRESS);
2232 gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), vbox, _(page_titles[PAGE_OPTIONS]));
2233
2234 #if HEAD_IMAGE == 1
2235 gtk_assistant_set_page_header_image (GTK_ASSISTANT (assistant), vbox, data->head_pixbuf);
2236 #endif
2237
2238 #if SIDE_IMAGE == 1
2239 gtk_assistant_set_page_side_image (GTK_ASSISTANT (assistant), vbox, data->side_pixbuf);
2240 #endif
2241
2242
2243 return vbox;
2244 }
2245
2246
2247 /**
2248 * create_page6:
2249 *
2250 * page 6: confirmation
2251 *
2252 * Return value: a vbox widget
2253 *
2254 */
2255 static GtkWidget *
2256 ui_import_page6(GtkWidget *assistant, struct import_data *data)
2257 {
2258 GtkWidget *vbox, *label, *align, *widget, *table;
2259 gint row;
2260
2261 align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
2262 gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 0, 0);
2263
2264 vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
2265 gtk_container_set_border_width (GTK_CONTAINER(vbox), HB_MAINBOX_SPACING);
2266 gtk_container_add(GTK_CONTAINER(align), vbox);
2267
2268 label = make_label(
2269 _("Click \"Apply\" to update your accounts.\n"), 0.5, 0.5);
2270 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
2271
2272 /* the summary */
2273 table = gtk_table_new (7, 3, FALSE);
2274 gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
2275 gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING/2);
2276 gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
2277 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
2278
2279 row = 0;
2280 label = make_label(_("Accounts"), 0.0, 0.5);
2281 gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
2282 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
2283
2284 /* acc update */
2285 row++;
2286 label = make_label(NULL, 0.0, 0.5);
2287 //gtk_misc_set_padding (GTK_MISC (label), HB_BOX_SPACING, 0);
2288 gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
2289 widget = make_label(NULL, 1.0, 0.5);
2290 data->TX_acc_upd = widget;
2291 gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
2292 label = make_label(_("to update"), 0.0, 0.5);
2293 gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 3, row, row+1);
2294
2295 /* acc create */
2296 row++;
2297 widget = make_label(NULL, 1.0, 0.5);
2298 data->TX_acc_new = widget;
2299 gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
2300 label = make_label(_("to create"), 0.0, 0.5);
2301 gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 3, row, row+1);
2302
2303 row++;
2304 label = make_label(_("Transactions"), 0.0, 0.5);
2305 gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
2306 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
2307
2308 /* trn import */
2309 row++;
2310 widget = make_label(NULL, 1.0, 0.5);
2311 data->TX_trn_imp = widget;
2312 gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
2313 label = make_label(_("to import"), 0.0, 0.5);
2314 gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 3, row, row+1);
2315
2316 /* trn reject */
2317 row++;
2318 widget = make_label(NULL, 1.0, 0.5);
2319 data->TX_trn_nop = widget;
2320 gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
2321 label = make_label(_("to reject"), 0.0, 0.5);
2322 gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 3, row, row+1);
2323
2324 /* trn auto-assigned */
2325 row++;
2326 widget = make_label(NULL, 1.0, 0.5);
2327 data->TX_trn_asg = widget;
2328 gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (0), (GtkAttachOptions) (0), 0, 0);
2329 label = make_label(_("auto-assigned"), 0.0, 0.5);
2330 gtk_table_attach_defaults (GTK_TABLE (table), label, 2, 3, row, row+1);
2331
2332
2333 gtk_widget_show_all (align);
2334
2335 gtk_assistant_append_page (GTK_ASSISTANT (assistant), align);
2336 gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), align, GTK_ASSISTANT_PAGE_CONFIRM);
2337 //gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), label, TRUE);
2338 gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), align, _(page_titles[PAGE_CONFIRM]));
2339
2340 #if HEAD_IMAGE == 1
2341 gtk_assistant_set_page_header_image (GTK_ASSISTANT (assistant), align, data->head_pixbuf);
2342 #endif
2343
2344 #if SIDE_IMAGE == 1
2345 gtk_assistant_set_page_side_image (GTK_ASSISTANT (assistant), align, data->side_pixbuf);
2346 #endif
2347
2348 return align;
2349 }
2350
2351
2352 /* starting point of import */
2353 GtkWidget *ui_import_window_new (void)
2354 {
2355 struct import_data *data;
2356 GtkWidget *assistant;
2357 GdkScreen *screen;
2358 gint width, height;
2359 gint pos;
2360
2361 data = g_malloc0(sizeof(struct import_data));
2362 if(!data) return NULL;
2363
2364
2365 assistant = gtk_assistant_new ();
2366 data->assistant = assistant;
2367
2368 //store our window private data
2369 g_object_set_data(G_OBJECT(assistant), "inst_data", (gpointer)data);
2370 //DB( g_print("** \n[import] window=%x, inst_data=%x\n", assistant, data) );
2371
2372
2373 gtk_window_set_modal(GTK_WINDOW (assistant), TRUE);
2374 gtk_window_set_transient_for(GTK_WINDOW(assistant), GTK_WINDOW(GLOBALS->mainwindow));
2375
2376 /* set pixbuf */
2377 #if HEAD_IMAGE == 1
2378 data->head_pixbuf = gtk_widget_render_icon (assistant, "hb-file-import", GTK_ICON_SIZE_DIALOG, NULL);
2379 g_object_unref (data->head_pixbuf);
2380 #endif
2381
2382 #if SIDE_IMAGE == 1
2383 gchar *pathfilename = g_build_filename(homebank_app_get_pixmaps_dir(), "wizard.svg", NULL);
2384 data->side_pixbuf = gdk_pixbuf_new_from_file (pathfilename, NULL);
2385 g_free(pathfilename);
2386 g_object_unref (data->side_pixbuf);
2387 #endif
2388
2389 #if FORCE_SIZE == 1
2390 screen = gtk_window_get_screen(GTK_WINDOW (assistant));
2391 // fix #379372 : manage multiple monitor case
2392 if( gdk_screen_get_n_monitors(screen) > 1 )
2393 {
2394 GdkRectangle rect;
2395
2396 gdk_screen_get_monitor_geometry(screen, 1, &rect);
2397 width = rect.width;
2398 height = rect.height;
2399 }
2400 else
2401 {
2402 width = gdk_screen_get_width(screen);
2403 height = gdk_screen_get_height(screen);
2404 }
2405
2406 gtk_window_resize(GTK_WINDOW(assistant), SCOEF*width, SCOEF*height);
2407 gtk_window_set_position (GTK_WINDOW (assistant), GTK_WIN_POS_CENTER_ON_PARENT);
2408 //gtk_window_set_position (GTK_WINDOW (assistant), GTK_WIN_POS_CENTER);
2409 #endif
2410
2411
2412 pos = 0;
2413 data->pages[pos++] = ui_import_page1 (assistant, data); // intro
2414 data->pages[pos++] = ui_import_page2 (assistant, data); // file choose
2415 data->pages[pos++] = ui_import_page3 (assistant, data); // load result
2416 data->pages[pos++] = ui_import_page4 (assistant, data); // file content
2417 data->pages[pos++] = ui_import_page6 (assistant, data); // confirm
2418
2419 gtk_assistant_set_forward_page_func(GTK_ASSISTANT(assistant), ui_import_forward_page_func, data, NULL);
2420
2421 //gtk_assistant_set_current_page(GTK_ASSISTANT (assistant), PAGE_FILE);
2422
2423 //setup
2424 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(data->filechooser), PREFS->path_import);
2425 //ui_acc_comboboxentry_populate(GTK_COMBO_BOX(data->PO_acc), GLOBALS->h_acc);
2426 data->ictx.cnt_initial_acc = da_acc_length();
2427
2428 gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_dateorder), PREFS->dtex_datefmt);
2429
2430 ui_import_selchange(assistant, data);
2431
2432 //connect all our signals
2433 g_signal_connect (G_OBJECT (data->filechooser), "selection-changed",
2434 G_CALLBACK (ui_import_selchange), (gpointer)data);
2435
2436 g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->imported_ope)), "changed",
2437 G_CALLBACK (ui_import_selection), NULL);
2438
2439 g_signal_connect (G_OBJECT (assistant), "cancel",
2440 G_CALLBACK (ui_import_close_cancel), assistant);
2441
2442 g_signal_connect (G_OBJECT (assistant), "close",
2443 G_CALLBACK (ui_import_close_cancel), assistant);
2444
2445 g_signal_connect (G_OBJECT (assistant), "apply",
2446 G_CALLBACK (ui_import_apply), NULL);
2447
2448 g_signal_connect (G_OBJECT (assistant), "prepare",
2449 G_CALLBACK (ui_import_prepare), NULL);
2450
2451 // g_signal_connect (window, "delete-event", G_CALLBACK (hbfile_dispose), (gpointer)data);
2452
2453
2454 gtk_widget_show (assistant);
2455
2456 return assistant;
2457 }
2458
2459
2460
2461 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2462 /* account affect listview */
2463 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2464
2465
2466 guint32
2467 ui_acc_affect_listview_get_selected_key(GtkTreeView *treeview)
2468 {
2469 GtkTreeSelection *selection;
2470 GtkTreeModel *model;
2471 GtkTreeIter iter;
2472
2473 selection = gtk_tree_view_get_selection(treeview);
2474 if (gtk_tree_selection_get_selected(selection, &model, &iter))
2475 {
2476 Account *item;
2477
2478 gtk_tree_model_get(model, &iter, 0, &item, -1);
2479
2480 if( item!= NULL )
2481 return item->key;
2482 }
2483 return 0;
2484 }
2485
2486
2487 static void
2488 ui_acc_affect_listview_srcname_cell_data_function (GtkTreeViewColumn *col,
2489 GtkCellRenderer *renderer,
2490 GtkTreeModel *model,
2491 GtkTreeIter *iter,
2492 gpointer user_data)
2493 {
2494 Account *entry;
2495 gchar *name;
2496 gchar *string;
2497
2498 gtk_tree_model_get(model, iter, 0, &entry, -1);
2499
2500 name = entry->imp_name;
2501
2502 #if MYDEBUG
2503 string = g_markup_printf_escaped("<i>[%d] %s</i>", entry->key, name );
2504 #else
2505 string = g_markup_printf_escaped("<i>%s</i>", name);
2506 #endif
2507 g_object_set(renderer, "markup", string, NULL);
2508 g_free(string);
2509 }
2510
2511 static void
2512 ui_acc_affect_listview_new_cell_data_function (GtkTreeViewColumn *col,
2513 GtkCellRenderer *renderer,
2514 GtkTreeModel *model,
2515 GtkTreeIter *iter,
2516 gpointer user_data)
2517 {
2518 Account *entry;
2519 gchar *name;
2520
2521 gtk_tree_model_get(model, iter, 0, &entry, -1);
2522 name = NULL;
2523 if(entry->imp_key == 0)
2524 name = _("Create new");
2525 else
2526 name = _("Import into");
2527
2528 g_object_set(renderer, "markup", name, NULL);
2529
2530 }
2531
2532 static void
2533 ui_acc_affect_listview_dstname_cell_data_function (GtkTreeViewColumn *col,
2534 GtkCellRenderer *renderer,
2535 GtkTreeModel *model,
2536 GtkTreeIter *iter,
2537 gpointer user_data)
2538 {
2539 Account *entry, *dst_entry;
2540 gchar *name;
2541 #if MYDEBUG
2542 gchar *string;
2543 #endif
2544
2545 gtk_tree_model_get(model, iter, 0, &entry, -1);
2546 name = NULL;
2547 if(entry->imp_key == 0)
2548 name = entry->name;
2549 else
2550 {
2551 dst_entry = da_acc_get(entry->imp_key);
2552 if( dst_entry != NULL )
2553 name = dst_entry->name;
2554 }
2555
2556 #if MYDEBUG
2557 string = g_strdup_printf ("[%d] %s", entry->imp_key, name );
2558 g_object_set(renderer, "text", string, NULL);
2559 g_free(string);
2560 #else
2561 g_object_set(renderer, "text", name, NULL);
2562 #endif
2563
2564 }
2565
2566 void
2567 ui_acc_affect_listview_add(GtkTreeView *treeview, Account *item)
2568 {
2569 if( item->name != NULL )
2570 {
2571 GtkTreeModel *model;
2572 GtkTreeIter iter;
2573
2574 model = gtk_tree_view_get_model(treeview);
2575
2576 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
2577 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
2578 0, item,
2579 -1);
2580
2581 //gtk_tree_selection_select_iter (gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), &iter);
2582
2583 }
2584 }
2585
2586
2587 static GtkWidget *
2588 ui_acc_affect_listview_new(void)
2589 {
2590 GtkListStore *store;
2591 GtkWidget *treeview;
2592 GtkCellRenderer *renderer;
2593 GtkTreeViewColumn *column;
2594
2595 // create list store
2596 store = gtk_list_store_new(1,
2597 G_TYPE_POINTER
2598 );
2599
2600 // treeview
2601 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
2602 g_object_unref(store);
2603
2604 // column: import account
2605 renderer = gtk_cell_renderer_text_new ();
2606 column = gtk_tree_view_column_new();
2607 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2608 gtk_tree_view_column_set_title(column, _("Imported name"));
2609 gtk_tree_view_column_set_cell_data_func(column, renderer, ui_acc_affect_listview_srcname_cell_data_function, NULL, NULL);
2610 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
2611
2612 // column: target account
2613 renderer = gtk_cell_renderer_text_new ();
2614 column = gtk_tree_view_column_new();
2615 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2616 gtk_tree_view_column_set_title(column, _("Action"));
2617 gtk_tree_view_column_set_cell_data_func(column, renderer, ui_acc_affect_listview_new_cell_data_function, NULL, NULL);
2618 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
2619
2620 // column: target account
2621 renderer = gtk_cell_renderer_text_new ();
2622 column = gtk_tree_view_column_new();
2623 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2624 gtk_tree_view_column_set_title(column, _("HomeBank name"));
2625 gtk_tree_view_column_set_cell_data_func(column, renderer, ui_acc_affect_listview_dstname_cell_data_function, NULL, NULL);
2626 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
2627
2628
2629
2630 // treeviewattribute
2631 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), TRUE);
2632
2633 //gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store), ui_acc_listview_compare_func, NULL, NULL);
2634 //gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
2635
2636 return treeview;
2637 }
2638
2639
2640
This page took 0.146467 seconds and 5 git commands to generate.