GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
assistant-qif-import.c
1 /********************************************************************\
2  * assistant-qif-import.c -- window for importing QIF files *
3  * (GnuCash) *
4  * Copyright (C) 2000 Bill Gribble <[email protected]> *
5  * Copyright (c) 2006 David Hampton <[email protected]> *
6  * Copyright (c) 2011 Robert Fewell *
7  * *
8  * This program is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU General Public License as *
10  * published by the Free Software Foundation; either version 2 of *
11  * the License, or (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License*
19  * along with this program; if not, contact: *
20  * *
21  * Free Software Foundation Voice: +1-617-542-5942 *
22  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
23  * Boston, MA 02110-1301, USA [email protected] *
24 \********************************************************************/
25 
26 #include "config.h"
27 
28 #include <gtk/gtk.h>
29 #include <glib/gi18n.h>
30 #include <glib/gstdio.h>
31 #include <libguile.h>
32 #include <sys/time.h>
33 #include <unistd.h>
34 
35 #include "Account.h"
36 #include "Transaction.h"
37 #include "dialog-account-picker.h"
38 #include "dialog-commodity.h"
39 #include "dialog-progress.h"
40 #include "dialog-utils.h"
41 #include "dialog-file-access.h"
42 #include "assistant-qif-import.h"
43 #include "assistant-utils.h"
44 #include "gnc-component-manager.h"
45 #include "qof.h"
46 #include "gnc-file.h"
47 #include "gnc-gui-query.h"
48 #include "gnc-guile-utils.h"
49 #include "gnc-currency-edit.h"
50 #include "gnc-ui-util.h"
51 #include "gnc-gtk-utils.h"
52 #include "gnc-main-window.h"
54 #include "gnc-prefs.h"
55 #include "gnc-ui.h"
56 #include "guile-mappings.h"
57 
58 #include "swig-runtime.h"
59 
60 #define ASSISTANT_QIF_IMPORT_CM_CLASS "assistant-qif-import"
61 #define GNC_PREFS_GROUP "dialogs.import.qif"
62 #define GNC_PREF_SHOW_DOC "show-doc"
63 #define GNC_PREF_DEFAULT_TRANS_STATUS_CLEARED "default-status-cleared"
64 #define GNC_PREF_DEFAULT_TRANS_STATUS_NOTCLEARED "default-status-notcleared"
65 #define GNC_PREF_DEFAULT_TRANS_STATUS_RECONCILED "default-status-reconciled"
66 
67 #define PREV_ROW "prev_row"
68 
69 static QofLogModule log_module = GNC_MOD_ASSISTANT;
70 
71 enum filename_cols
72 {
73  FILENAME_COL_INDEX = 0,
74  FILENAME_COL_NAME,
75  NUM_FILENAME_COLS
76 };
77 
78 enum account_cols
79 {
80  ACCOUNT_COL_INDEX = 0,
81  ACCOUNT_COL_QIF_NAME,
82  ACCOUNT_COL_GNC_NAME,
83  ACCOUNT_COL_NEW,
84  ACCOUNT_COL_ELLIPSIZE,
85  NUM_ACCOUNT_COLS
86 };
87 
88 enum qif_trans_cols
89 {
90  QIF_TRANS_COL_INDEX = 0,
91  QIF_TRANS_COL_DATE,
92  QIF_TRANS_COL_DESCRIPTION,
93  QIF_TRANS_COL_AMOUNT,
94  QIF_TRANS_COL_CHECKED,
95  NUM_QIF_TRANS_COLS
96 };
97 
99 {
100  GtkWidget * window;
101  GtkWidget * assistant;
102 
103  /* Widgets on the file selection page. */
104  GtkWidget * filename_entry;
105 
106  /* File loading progress page. */
107  GtkWidget * load_pause;
108  GtkWidget * load_start;
109  GtkWidget * load_log;
110  GNCProgressDialog *load_progress;
111 
112  /* Widgets on the default account page. */
113  GtkWidget * acct_entry;
114 
115  /* Widgets on the date format page. */
116  GtkWidget * date_format_combo;
117 
118  /* Widgets on the files loaded page. */
119  GtkWidget * selected_file_view;
120  GtkWidget * unload_file_btn;
121 
122  /* Widgets on the account matching page. */
123  GtkWidget * acct_view;
124  GtkWidget * acct_view_count;
125  GtkWidget * acct_view_btn;
126 
127  /* Widgets on the category matching page. */
128  GtkWidget * cat_view;
129  GtkWidget * cat_view_count;
130  GtkWidget * cat_view_btn;
131 
132  /* Widgets on the memo matching page. */
133  GtkWidget * memo_view;
134  GtkWidget * memo_view_count;
135  GtkWidget * memo_view_btn;
136 
137  /* Widgets on the currency & book options page. */
138  GtkWidget * currency_picker;
139  GtkWidget * book_option_label;
140  GtkWidget * book_option_message;
141 
142  /* Widgets on the commodity page. */
143  gint num_new_pages;
144 
145  /* Conversion progress page. */
146  GtkWidget * convert_pause;
147  GtkWidget * convert_start;
148  GtkWidget * convert_log;
149  GNCProgressDialog *convert_progress;
150 
151  /* Widgets on the duplicates page. */
152  GtkWidget * new_transaction_view;
153  GtkWidget * old_transaction_view;
154 
155  /* Widgets on the summary page. */
156  GtkWidget * summary_text;
157 
158  GList * commodity_pages;
159 
160  gboolean show_doc_pages;
161  gboolean ask_date_format;
162  gboolean busy;
163  gboolean load_stop;
164  gboolean acct_tree_found;
165  gboolean new_book;
166 
167  SCM imported_files;
168  SCM selected_file;
169 
170  SCM acct_map_info;
171  SCM acct_display_info;
172 
173  SCM cat_map_info;
174  SCM cat_display_info;
175 
176  SCM memo_map_info;
177  SCM memo_display_info;
178 
179  SCM gnc_acct_info;
180  SCM security_hash;
181  SCM security_prefs;
182  SCM new_securities;
183  GList * new_namespaces;
184  SCM ticker_map;
185 
186  SCM imported_account_tree;
187  SCM match_transactions;
188  SCM transaction_status;
189  int selected_transaction;
190 };
191 
193 {
194  GtkWidget *page;
195  GtkWidget *namespace_combo;
196  GtkWidget *name_entry;
197  GtkWidget *mnemonic_entry;
198  gnc_commodity *commodity;
199  SCM hash_key;
200 };
201 
202 typedef struct _qifassistantpage QIFAssistantPage;
203 
204 static void gnc_ui_qif_import_assistant_destroy (GtkObject *object, gpointer user_data);
205 static void gnc_ui_qif_import_assistant_close_handler (gpointer user_data );
206 
207 void gnc_ui_qif_import_cancel_cb (GtkAssistant *gtkassistant, gpointer user_data);
208 void gnc_ui_qif_import_prepare_cb (GtkAssistant *assistant, GtkWidget *page, gpointer user_data);
209 void gnc_ui_qif_import_finish_cb (GtkAssistant *gtkassistant, gpointer user_data);
210 void gnc_ui_qif_import_close_cb (GtkAssistant *gtkassistant, gpointer user_data);
211 
212 void gnc_ui_qif_import_intro_prepare (GtkAssistant *assistant, gpointer user_data);
213 
214 void gnc_ui_qif_import_load_file_prepare (GtkAssistant *assistant, gpointer user_data);
215 void gnc_ui_qif_import_select_file_cb (GtkButton *button, gpointer user_data);
216 
217 void gnc_ui_qif_import_load_progress_prepare (GtkAssistant *assistant, gpointer user_data);
218 void gnc_ui_qif_import_load_progress_pause_cb (GtkButton *button, gpointer user_data);
219 void gnc_ui_qif_import_load_progress_start_cb (GtkButton * button, gpointer user_data);
220 
221 void gnc_ui_qif_import_date_format_prepare (GtkAssistant *assistant, gpointer user_data);
222 void gnc_ui_qif_import_date_valid_cb (GtkWidget *widget, gpointer user_data);
223 
224 void gnc_ui_qif_import_account_prepare (GtkAssistant *assistant, gpointer user_data);
225 void gnc_ui_qif_import_acct_valid_cb (GtkWidget *widget, gpointer user_data);
226 
227 void gnc_ui_qif_import_loaded_files_prepare (GtkAssistant *assistant, gpointer user_data);
228 void gnc_ui_qif_import_load_another_cb (GtkButton *button, gpointer user_data);
229 void gnc_ui_qif_import_unload_file_cb (GtkButton *button, gpointer user_data);
230 
231 static void update_file_page (QIFImportWindow * wind);
232 
233 void gnc_ui_qif_import_account_match_prepare (GtkAssistant *assistant, gpointer user_data);
234 void gnc_ui_qif_import_account_doc_prepare (GtkAssistant *assistant, gpointer user_data);
235 void gnc_ui_qif_import_account_rematch_cb (GtkButton *button, gpointer user_data);
236 
237 void gnc_ui_qif_import_catagory_match_prepare (GtkAssistant *assistant, gpointer user_data);
238 void gnc_ui_qif_import_catagory_doc_prepare (GtkAssistant *assistant, gpointer user_data);
239 void gnc_ui_qif_import_category_rematch_cb (GtkButton *button, gpointer user_data);
240 
241 void gnc_ui_qif_import_memo_match_prepare (GtkAssistant *assistant, gpointer user_data);
242 void gnc_ui_qif_import_memo_doc_prepare (GtkAssistant *assistant, gpointer user_data);
243 void gnc_ui_qif_import_memo_rematch_cb (GtkButton *button, gpointer user_data);
244 
245 void gnc_ui_qif_import_currency_prepare (GtkAssistant *assistant, gpointer user_data);
246 
247 void gnc_ui_qif_import_commodity_new_prepare (GtkAssistant *assistant, gpointer user_data);
248 void gnc_ui_qif_import_commodity_doc_prepare (GtkAssistant *assistant, gpointer user_data);
249 void gnc_ui_qif_import_comm_changed_cb (GtkWidget *widget, gpointer user_data);
250 
251 void gnc_ui_qif_import_convert_progress_prepare (GtkAssistant *assistant, gpointer user_data);
252 void gnc_ui_qif_import_convert_progress_pause_cb (GtkButton * button, gpointer user_data);
253 void gnc_ui_qif_import_convert_progress_start_cb(GtkButton * button, gpointer user_data);
254 
255 void gnc_ui_qif_import_duplicates_match_prepare (GtkAssistant *assistant, gpointer user_data);
256 void gnc_ui_qif_import_duplicates_doc_prepare (GtkAssistant *assistant, gpointer user_data);
257 
258 void gnc_ui_qif_import_end_page_prepare (GtkAssistant *assistant, gpointer user_data);
259 
260 void gnc_ui_qif_import_summary_page_prepare (GtkAssistant *assistant, gpointer user_data);
261 
262 
263 /****************************************************************
264  * update_account_picker_page
265  *
266  * Generic function to update an account_picker page. This
267  * generalizes the code shared whenever any QIF -> GNC mapper is
268  * updating it's LIST STORE. It asks the Scheme side to guess some account
269  * translations and then shows the account name and suggested
270  * translation in the Accounts page view (acount picker list).
271  ****************************************************************/
272 static void
273 update_account_picker_page(QIFImportWindow * wind, SCM make_display,
274  GtkWidget *view, SCM map_info, SCM * display_info)
275 {
276 
277  SCM get_qif_name = scm_c_eval_string("qif-map-entry:qif-name");
278  SCM get_gnc_name = scm_c_eval_string("qif-map-entry:gnc-name");
279  SCM get_new = scm_c_eval_string("qif-map-entry:new-acct?");
280  SCM accts_left;
281  gchar *qif_name = NULL;
282  gchar *gnc_name = NULL;
283  gboolean checked;
284  gint row = 0;
285  gint prev_row;
286  GtkListStore *store;
287  GtkTreeIter iter;
288  GtkTreePath *path;
289  GtkTreeSelection *selection;
290 
291  store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(view)));
292 
293  /* now get the list of strings to display in the gtk_list_store widget */
294  accts_left = scm_call_3(make_display,
295  wind->imported_files,
296  map_info,
297  wind->gnc_acct_info);
298 
299  scm_gc_unprotect_object(*display_info);
300  *display_info = accts_left;
301  scm_gc_protect_object(*display_info);
302 
303  /* clear the list */
304  gtk_list_store_clear(store);
305 
306  while (!scm_is_null(accts_left))
307  {
308  qif_name = gnc_scm_call_1_to_string(get_qif_name, SCM_CAR(accts_left));
309  gnc_name = gnc_scm_call_1_to_string(get_gnc_name, SCM_CAR(accts_left));
310  checked = (scm_call_1(get_new, SCM_CAR(accts_left)) == SCM_BOOL_T);
311 
312  gtk_list_store_append(store, &iter);
313  gtk_list_store_set(store, &iter,
314  ACCOUNT_COL_INDEX, row++,
315  ACCOUNT_COL_QIF_NAME, qif_name,
316  ACCOUNT_COL_GNC_NAME, gnc_name,
317  ACCOUNT_COL_NEW, checked,
318  ACCOUNT_COL_ELLIPSIZE, PANGO_ELLIPSIZE_START,
319  -1);
320  accts_left = SCM_CDR(accts_left);
321  g_free (qif_name);
322  g_free (gnc_name);
323  }
324 
325  /* move to the old selected row */
326  prev_row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(store), PREV_ROW));
327  if (prev_row != -1)
328  {
329  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
330  path = gtk_tree_path_new_from_indices(prev_row, -1);
331  gtk_tree_selection_select_path(selection, path);
332  gtk_tree_path_free(path);
333  }
334  else
335  {
336  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
337  path = gtk_tree_path_new_from_indices( 0, -1);
338  gtk_tree_selection_select_path(selection, path);
339  gtk_tree_path_free(path);
340  }
341 }
342 
343 
344 /****************************************************************
345  * update_account_page
346  *
347  * update the QIF account -> GNC Account picker
348  ****************************************************************/
349 static void
350 update_account_page(QIFImportWindow * wind)
351 {
352 
353  SCM make_account_display = scm_c_eval_string("qif-dialog:make-account-display");
354 
355  update_account_picker_page(wind, make_account_display, wind->acct_view,
356  wind->acct_map_info, &(wind->acct_display_info));
357 }
358 
359 
360 /****************************************************************
361  * update_category_page
362  *
363  * update the QIF category -> GNC Account picker
364  ****************************************************************/
365 static void
366 update_category_page(QIFImportWindow * wind)
367 {
368  SCM make_category_display = scm_c_eval_string("qif-dialog:make-category-display");
369 
370  update_account_picker_page(wind, make_category_display, wind->cat_view,
371  wind->cat_map_info, &(wind->cat_display_info));
372 }
373 
374 
375 /****************************************************************
376  * update_memo_page
377  *
378  * update the QIF memo -> GNC Account picker
379  ****************************************************************/
380 static void
381 update_memo_page(QIFImportWindow * wind)
382 {
383  SCM make_memo_display = scm_c_eval_string("qif-dialog:make-memo-display");
384 
385  update_account_picker_page(wind, make_memo_display, wind->memo_view,
386  wind->memo_map_info, &(wind->memo_display_info));
387 }
388 
389 
390 /****************************************************************
391  * gnc_ui_qif_import_commodity_destroy
392  *
393  * This function destroys any commodity pages.
394  ****************************************************************/
395 static void
396 gnc_ui_qif_import_commodity_destroy(QIFImportWindow * wind)
397 {
398  GList *pageptr;
399  GtkWidget *gtkpage;
400  QIFAssistantPage *page;
401 
402  for (pageptr = wind->commodity_pages; pageptr; pageptr = pageptr->next)
403  {
404  gtkpage = pageptr->data;
405  page = g_object_get_data(G_OBJECT(gtkpage), "page_struct");
406 
407  /* Unprotect the Scheme hash key. */
408  scm_gc_unprotect_object(page->hash_key);
409 
410  /* Free the memory allocated for the page's struct. */
411  g_free(page);
412  }
413 
414  /* Free the list of pages. */
415  g_list_free(wind->commodity_pages);
416  wind->commodity_pages = NULL;
417 }
418 
419 
420 /**********************************************
421  * gnc_ui_qif_import_assistant_destroy
422  * close the QIF Import assistant window
423  **********************************************/
424 static void
425 gnc_ui_qif_import_assistant_destroy(GtkObject *object, gpointer user_data)
426 {
427  QIFImportWindow * wind = user_data;
428 
429  /* Destroy the progress dialog helpers. */
430  gnc_progress_dialog_destroy(wind->load_progress);
431 
432  /* Destroy any commodity pages. */
433  gnc_ui_qif_import_commodity_destroy(wind);
434 
435  gnc_unregister_gui_component_by_data(ASSISTANT_QIF_IMPORT_CM_CLASS, wind);
436 
437  gtk_widget_destroy(wind->window);
438 
439  scm_gc_unprotect_object(wind->imported_files);
440  scm_gc_unprotect_object(wind->selected_file);
441  scm_gc_unprotect_object(wind->gnc_acct_info);
442  scm_gc_unprotect_object(wind->cat_display_info);
443  scm_gc_unprotect_object(wind->cat_map_info);
444  scm_gc_unprotect_object(wind->memo_display_info);
445  scm_gc_unprotect_object(wind->memo_map_info);
446  scm_gc_unprotect_object(wind->acct_display_info);
447  scm_gc_unprotect_object(wind->acct_map_info);
448  scm_gc_unprotect_object(wind->security_hash);
449  scm_gc_unprotect_object(wind->security_prefs);
450  scm_gc_unprotect_object(wind->new_securities);
451  scm_gc_unprotect_object(wind->ticker_map);
452  scm_gc_unprotect_object(wind->imported_account_tree);
453  scm_gc_unprotect_object(wind->match_transactions);
454 
455  g_free(wind);
456 }
457 
458 
459 /****************************************************************
460  * gnc_ui_qif_import_select_loaded_file_cb
461  * callback when a file is clicked in the "loaded files" page
462  ****************************************************************/
463 static void
464 gnc_ui_qif_import_select_loaded_file_cb(GtkTreeSelection *selection,
465  gpointer user_data)
466 {
467  QIFImportWindow * wind = user_data;
468  GtkTreeModel *model;
469  GtkTreeIter iter;
470  gint row;
471  GtkWidget *button;
472 
473  button = (wind->unload_file_btn);
474  if (gtk_tree_selection_get_selected(selection, &model, &iter))
475  {
476  gtk_tree_model_get(model, &iter, FILENAME_COL_INDEX, &row, -1);
477  if (scm_is_list(wind->imported_files) &&
478  (scm_ilength(wind->imported_files) > row))
479  {
480  scm_gc_unprotect_object(wind->selected_file);
481  wind->selected_file = scm_list_ref(wind->imported_files,
482  scm_from_int (row));
483  scm_gc_protect_object(wind->selected_file);
484  g_object_set(button, "sensitive", TRUE, (gchar*)NULL);
485  }
486  }
487  else
488  {
489  scm_gc_unprotect_object(wind->selected_file);
490  wind->selected_file = SCM_BOOL_F;
491  scm_gc_protect_object(wind->selected_file);
492  g_object_set(button, "sensitive", FALSE, (gchar*)NULL);
493  }
494 }
495 
496 
497 /****************************************************
498  * create_account_picker_view
499  ****************************************************/
500 static void
501 create_account_picker_view(GtkWidget *widget,
502  const gchar *col_name,
503  GCallback activate_cb,
504  GCallback select_cb,
505  gpointer user_data)
506 {
507  GtkTreeView *view = GTK_TREE_VIEW(widget);
508  GtkTreeSelection *selection = gtk_tree_view_get_selection(view);
509  GtkListStore *store;
510  GtkCellRenderer *renderer;
511  GtkTreeViewColumn *column;
512 
513  store = gtk_list_store_new(NUM_ACCOUNT_COLS, G_TYPE_INT, G_TYPE_STRING,
514  G_TYPE_STRING, G_TYPE_BOOLEAN,
515  PANGO_TYPE_ELLIPSIZE_MODE);
516  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
517  g_object_unref(store);
518 
519  renderer = gtk_cell_renderer_text_new();
520  column = gtk_tree_view_column_new_with_attributes(col_name,
521  renderer,
522  "text",
523  ACCOUNT_COL_QIF_NAME,
524  "ellipsize",
525  ACCOUNT_COL_ELLIPSIZE,
526  NULL);
527  g_object_set(column, "expand", TRUE, NULL);
528  gtk_tree_view_column_set_resizable(column, TRUE);
529  gtk_tree_view_append_column(view, column);
530 
531  renderer = gtk_cell_renderer_text_new();
532  column = gtk_tree_view_column_new_with_attributes(_("GnuCash account name"),
533  renderer,
534  "text",
535  ACCOUNT_COL_GNC_NAME,
536  "ellipsize",
537  ACCOUNT_COL_ELLIPSIZE,
538  NULL);
539 
540  g_object_set(column, "expand", TRUE, NULL);
541  gtk_tree_view_column_set_resizable(column, TRUE);
542  gtk_tree_view_append_column(view, column);
543 
544  renderer = gtk_cell_renderer_toggle_new();
545  g_object_set(renderer, "activatable", FALSE, NULL);
546  column = gtk_tree_view_column_new_with_attributes(_("New?"),
547  renderer,
548  "active",
549  ACCOUNT_COL_NEW,
550  NULL);
551  gtk_tree_view_append_column(view, column);
552 
553  g_object_set_data(G_OBJECT(store), PREV_ROW, GINT_TO_POINTER(-1));
554 
555  /* Connect the signal handlers. */
556  g_signal_connect(view, "row-activated", G_CALLBACK(activate_cb), user_data);
557  g_signal_connect(selection, "changed", G_CALLBACK(select_cb), user_data);
558 
559  /* Allow multiple rows to be selected. */
560  gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
561 }
562 
563 
564 /********************************************************************
565  * rematch_line
566  *
567  * This is a helper function for tree controls used by some assistant
568  * pages for mapping QIF values to GnuCash accounts. It processes
569  * the selected rows when a user tries to edit the account mappings.
570  * The account picker is displayed, and the chosen GnuCash account
571  * becomes the new mapping for each row. Finally, the update_page
572  * function is called.
573  ********************************************************************/
574 static void
575 rematch_line(QIFImportWindow *wind, GtkTreeSelection *selection,
576  SCM display_info, SCM map_info,
577  void (*update_page)(QIFImportWindow *))
578 {
579  SCM get_qif_name = scm_c_eval_string("qif-map-entry:qif-name");
580  SCM get_gnc_name = scm_c_eval_string("qif-map-entry:gnc-name");
581  SCM set_gnc_name = scm_c_eval_string("qif-map-entry:set-gnc-name!");
582  SCM map_entry;
583  SCM gnc_name;
584  GList *pathlist;
585  GList *current;
586  GtkTreeModel *model;
587  GtkTreeIter iter;
588  gint row;
589 
590  /* Get a list of selected rows. */
591  pathlist = gtk_tree_selection_get_selected_rows(selection, &model);
592  if (!pathlist)
593  return;
594 
595  /*
596  * Update the first selected row.
597  */
598 
599  /* Get the row number of the first selected row. */
600  if (!gtk_tree_model_get_iter(model, &iter, (GtkTreePath *) pathlist->data))
601  return;
602  gtk_tree_model_get(model, &iter, ACCOUNT_COL_INDEX, &row, -1);
603 
604  /* Save the row number. */
605  g_object_set_data(G_OBJECT(model), PREV_ROW, GINT_TO_POINTER(row));
606  if (row == -1)
607  return;
608 
609  /* Find the <qif-map-entry> corresponding to the selected row. */
610  map_entry = scm_list_ref(display_info, scm_from_int (row));
611 
612  /* Call the account picker to update it. */
613  if (!qif_account_picker_dialog(wind, map_entry))
614  return;
615  gnc_name = scm_call_1(get_gnc_name, map_entry);
616 
617  /* Update the mapping hash table. */
618  scm_hash_set_x(map_info, scm_call_1(get_qif_name, map_entry), map_entry);
619 
620  /*
621  * Map all other selected rows to the same GnuCash account.
622  */
623  for (current = pathlist->next; current; current = current->next)
624  {
625  /* Get the row number. */
626  gtk_tree_model_get_iter(model, &iter, (GtkTreePath *) current->data);
627  gtk_tree_model_get(model, &iter, ACCOUNT_COL_INDEX, &row, -1);
628 
629  /* Update the <qif-map-entry> for the selected row. */
630  map_entry = scm_list_ref(display_info, scm_from_int (row));
631  scm_call_2(set_gnc_name, map_entry, gnc_name);
632 
633  /* Update the mapping hash table. */
634  scm_hash_set_x(map_info, scm_call_1(get_qif_name, map_entry), map_entry);
635  }
636 
637  /* Free the path list. */
638  g_list_foreach(pathlist, (GFunc) gtk_tree_path_free, NULL);
639  g_list_free(pathlist);
640 
641  /* Update the display. */
642  update_page(wind);
643 }
644 
645 
646 /********************************************************************
647  * gnc_ui_qif_import_account_activate_cb
648  *
649  * This handler is invoked when a row is double-clicked in the "Match
650  * QIF accounts to GnuCash accounts" page.
651  ********************************************************************/
652 static void
653 gnc_ui_qif_import_account_activate_cb(GtkTreeView *view, GtkTreePath *path,
654  GtkTreeViewColumn *column,
655  gpointer user_data)
656 {
657  QIFImportWindow *wind = user_data;
658 
659  g_return_if_fail(wind);
660 
661  rematch_line(wind, gtk_tree_view_get_selection(view),
662  wind->acct_display_info, wind->acct_map_info,
663  update_account_page);
664 }
665 
666 
667 /********************************************************************
668  * gnc_ui_qif_import_account_select_cb
669  *
670  * This handler is invoked when the selection of account matchings
671  * has changed. It updates the selection count and enables/disables
672  * the "Change" button.
673  ********************************************************************/
674 static void
675 gnc_ui_qif_import_account_select_cb(GtkTreeSelection *selection,
676  gpointer user_data)
677 {
678  QIFImportWindow *wind = user_data;
679  gint count = gtk_tree_selection_count_selected_rows(selection);
680  gchar *count_str;
681 
682  g_return_if_fail(wind);
683 
684  /* Update the "items selected" count. */
685  if (wind->acct_view_count)
686  {
687  count_str = g_strdup_printf("%d", count);
688  gtk_label_set_text(GTK_LABEL(wind->acct_view_count), count_str);
689  g_free(count_str);
690  }
691 
692  /* Enable/disable the Change button. */
693  if (wind->acct_view_btn)
694  {
695  if (count)
696  gtk_widget_set_sensitive(wind->acct_view_btn, TRUE);
697  else
698  gtk_widget_set_sensitive(wind->acct_view_btn, FALSE);
699  }
700 }
701 
702 
703 /********************************************************************
704  * gnc_ui_qif_import_category_activate_cb
705  *
706  * This handler is invoked when a row is double-clicked in the "Match
707  * QIF categories to GnuCash accounts" page.
708  ********************************************************************/
709 static void
710 gnc_ui_qif_import_category_activate_cb(GtkTreeView *view, GtkTreePath *path,
711  GtkTreeViewColumn *column,
712  gpointer user_data)
713 {
714  QIFImportWindow *wind = user_data;
715  GtkTreeSelection *selection;
716 
717  g_return_if_fail(view && wind);
718  selection = gtk_tree_view_get_selection(view);
719 
720  rematch_line(wind, selection, wind->cat_display_info, wind->cat_map_info,
721  update_category_page);
722 }
723 
724 
725 /********************************************************************
726  * gnc_ui_qif_import_category_select_cb
727  *
728  * This handler is invoked when the selection of category matchings
729  * has changed. It updates the selection count and enables/disables
730  * the "Change" button.
731  ********************************************************************/
732 static void
733 gnc_ui_qif_import_category_select_cb(GtkTreeSelection *selection,
734  gpointer user_data)
735 {
736  QIFImportWindow *wind = user_data;
737  gint count = gtk_tree_selection_count_selected_rows(selection);
738  gchar *count_str;
739 
740  g_return_if_fail(wind);
741 
742  /* Update the "items selected" count. */
743  if (wind->cat_view_count)
744  {
745  count_str = g_strdup_printf("%d", count);
746  gtk_label_set_text(GTK_LABEL(wind->cat_view_count), count_str);
747  g_free(count_str);
748  }
749 
750  /* Enable/disable the Change button. */
751  if (wind->cat_view_btn)
752  {
753  if (count)
754  gtk_widget_set_sensitive(wind->cat_view_btn, TRUE);
755  else
756  gtk_widget_set_sensitive(wind->cat_view_btn, FALSE);
757  }
758 }
759 
760 
761 /********************************************************************
762  * gnc_ui_qif_import_memo_activate_cb
763  *
764  * This handler is invoked when a row is double-clicked in the "Match
765  * QIF payee/memo to GnuCash accounts" page.
766  ********************************************************************/
767 static void
768 gnc_ui_qif_import_memo_activate_cb(GtkTreeView *view, GtkTreePath *path,
769  GtkTreeViewColumn *column,
770  gpointer user_data)
771 {
772  QIFImportWindow *wind = user_data;
773  GtkTreeSelection *selection;
774 
775  g_return_if_fail(view && wind);
776  selection = gtk_tree_view_get_selection(view);
777 
778  rematch_line(wind, selection, wind->memo_display_info, wind->memo_map_info,
779  update_memo_page);
780 }
781 
782 
783 /********************************************************************
784  * gnc_ui_qif_import_memo_select_cb
785  *
786  * This handler is invoked when the selection of memo matchings
787  * has changed. It updates the selection count and enables/disables
788  * the "Change" button.
789  ********************************************************************/
790 static void
791 gnc_ui_qif_import_memo_select_cb(GtkTreeSelection *selection,
792  gpointer user_data)
793 {
794  QIFImportWindow *wind = user_data;
795  gint count = gtk_tree_selection_count_selected_rows(selection);
796  gchar *count_str;
797 
798  g_return_if_fail(wind);
799 
800  /* Update the "items selected" count. */
801  if (wind->memo_view_count)
802  {
803  count_str = g_strdup_printf("%d", count);
804  gtk_label_set_text(GTK_LABEL(wind->memo_view_count), count_str);
805  g_free(count_str);
806  }
807 
808  /* Enable/disable the Change button. */
809  if (wind->memo_view_btn)
810  {
811  if (count)
812  gtk_widget_set_sensitive(wind->memo_view_btn, TRUE);
813  else
814  gtk_widget_set_sensitive(wind->memo_view_btn, FALSE);
815  }
816 }
817 
818 
819 /*********************************************
820  * new_security_page
821  *********************************************/
822 static QIFAssistantPage *
823 new_security_page(SCM security_hash_key, gnc_commodity *comm, QIFImportWindow *wind )
824 {
825 
826  QIFAssistantPage *retval = g_new0(QIFAssistantPage, 1);
827  GtkListStore *store;
828  GtkWidget *table;
829  GtkWidget *label;
830  gchar *title = NULL;
831  const char *str;
832  GtkWidget *page;
833  char *name_tooltip =
834  _("Enter a name or short description, such as \"Red Hat Stock\".");
835  char *mnemonic_tooltip =
836  _("Enter the ticker symbol or other well known abbreviation, such as"
837  " \"RHT\". If there isn't one, or you don't know it, create your own.");
838  char *namespace_tooltip =
839  _("Select the exchange on which the symbol is traded, or select the"
840  " type of investment (such as FUND for mutual funds.) If you don't"
841  " see your exchange or an appropriate investment type, you can"
842  " enter a new one.");
843 
844  /* Make the page widget. */
845  page = gtk_vbox_new( FALSE, 0 );
846  retval->page = page;
847  g_object_set_data(G_OBJECT(retval->page), "page_struct", retval);
848  page = retval->page;
849 
850  /* Insert the new page */
851  gtk_assistant_insert_page (GTK_ASSISTANT(wind->window), page, 14);
852  gtk_assistant_set_page_type(GTK_ASSISTANT(wind->window), page, GTK_ASSISTANT_PAGE_PROGRESS );
853  gtk_assistant_set_page_complete (GTK_ASSISTANT (wind->window), page, TRUE);
854  gtk_assistant_update_buttons_state (GTK_ASSISTANT (wind->window));
855 
856  /* Save the commodity and the hash table key. */
857  retval->commodity = comm;
858  retval->hash_key = security_hash_key;
859  scm_gc_protect_object(retval->hash_key);
860 
861  /* Set the page title. */
862  str = gnc_commodity_get_mnemonic(comm);
863  str = str ? str : "";
864  title = _("Enter information about");
865  title = g_strdup_printf("%s \"%s\"", title, str);
866  gtk_assistant_set_page_title(GTK_ASSISTANT(wind->window), page, title);
867  g_free(title);
868 
869  /*
870  * Add all the widgets to the page.
871  */
872  table = gtk_table_new(3, 2, FALSE);
873  gtk_table_set_row_spacings(GTK_TABLE(table), 6);
874  gtk_table_set_col_spacings(GTK_TABLE(table), 12);
875 
876  /* Name entry */
877  retval->name_entry = gtk_entry_new();
878  gtk_entry_set_text(GTK_ENTRY(retval->name_entry),
880  label = gtk_label_new_with_mnemonic(_("_Name or description:"));
881  gtk_label_set_mnemonic_widget(GTK_LABEL(label), retval->name_entry);
882  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
883 
884  gtk_widget_set_tooltip_text(label, name_tooltip);
885  gtk_widget_set_tooltip_text(retval->name_entry, name_tooltip);
886 
887  gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
888  GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
889  gtk_table_attach_defaults(GTK_TABLE(table), retval->name_entry,
890  1, 2, 0, 1);
891 
892  g_signal_connect (retval->name_entry, "changed",
893  G_CALLBACK (gnc_ui_qif_import_comm_changed_cb), wind);
894 
895  /* Mnemonic entry */
896  retval->mnemonic_entry = gtk_entry_new();
897  gtk_entry_set_text(GTK_ENTRY(retval->mnemonic_entry),
899  label = gtk_label_new_with_mnemonic(
900  _("_Ticker symbol or other abbreviation:"));
901  gtk_label_set_mnemonic_widget(GTK_LABEL(label), retval->mnemonic_entry);
902  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
903 
904  gtk_widget_set_tooltip_text(label, mnemonic_tooltip);
905  gtk_widget_set_tooltip_text(retval->mnemonic_entry, mnemonic_tooltip);
906 
907  gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
908  GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
909  gtk_table_attach_defaults(GTK_TABLE(table), retval->mnemonic_entry,
910  1, 2, 1, 2);
911 
912  g_signal_connect (retval->mnemonic_entry, "changed",
913  G_CALLBACK (gnc_ui_qif_import_comm_changed_cb), wind);
914 
915  /* Namespace entry */
916  store = gtk_list_store_new (1, G_TYPE_STRING);
917  retval->namespace_combo = gtk_combo_box_new_with_model_and_entry(GTK_TREE_MODEL(store));
918  g_object_unref(store);
919 
920  /* Set the column for the text */
921  gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX(retval->namespace_combo), 0);
922 
923  gnc_cbwe_add_completion(GTK_COMBO_BOX(retval->namespace_combo));
924  label = gtk_label_new_with_mnemonic(
925  _("_Exchange or abbreviation type:"));
926  gtk_label_set_mnemonic_widget(GTK_LABEL(label), retval->namespace_combo);
927  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
928 
929  gtk_widget_set_tooltip_text(label, namespace_tooltip);
930  gtk_widget_set_tooltip_text(retval->namespace_combo, namespace_tooltip);
931 
932  gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3,
933  GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
934  gtk_table_attach_defaults(GTK_TABLE(table), retval->namespace_combo,
935  1, 2, 2, 3);
936 
937  gtk_container_set_border_width(GTK_CONTAINER(page), 12);
938 
939  gtk_box_pack_start(GTK_BOX(page), table, FALSE, FALSE, 12);
940 
941  return retval;
942 }
943 
944 
945 /********************************************************************
946  * prepare_security_pages
947  *
948  * Prepare the assistant page for each security.
949  ********************************************************************/
950 static void
951 prepare_security_pages(QIFImportWindow * wind)
952 {
953  SCM hash_ref = scm_c_eval_string("hash-ref");
954  SCM securities;
955  SCM comm_ptr_token;
956 
957  GList * current;
958  gnc_commodity * commodity;
959  QIFAssistantPage * new_page;
960 
961  /*
962  * Make assistant pages for each new QIF security.
963  */
964  gnc_set_busy_cursor(NULL, TRUE);
965  securities = wind->new_securities;
966  current = wind->commodity_pages;
967  while (!scm_is_null(securities) && (securities != SCM_BOOL_F))
968  {
969  if (current)
970  {
971  /* The page has already been made. */
972  current = current->next;
973  }
974  else
975  {
976  /* Get the GnuCash commodity corresponding to the new QIF security. */
977  comm_ptr_token = scm_call_2(hash_ref,
978  wind->security_hash,
979  SCM_CAR(securities));
980 #define FUNC_NAME "new_security_page"
981  commodity = SWIG_MustGetPtr(comm_ptr_token,
982  SWIG_TypeQuery("_p_gnc_commodity"), 1, 0);
983 #undef FUNC_NAME
984 
985  /* Build a new security page. */
986  new_page = new_security_page(SCM_CAR(securities), commodity, wind);
987 
988  /* Add it to the list of security pages. */
989  wind->commodity_pages = g_list_append(wind->commodity_pages,
990  new_page->page);
991 
992  gtk_widget_show_all(new_page->page);
993  }
994  wind->num_new_pages = wind->num_new_pages + 1;
995  securities = SCM_CDR(securities);
996  }
997  gnc_unset_busy_cursor(NULL);
998  PINFO("Number of New Security pages is %d", wind->num_new_pages);
999 }
1000 
1001 
1002 /****************************************************************
1003  * gnc_ui_qif_import_commodity_update
1004  *
1005  * This function updates the commodities based on the values for
1006  * mnemonic, namespace, and name approved by the user.
1007  ****************************************************************/
1008 static void
1009 gnc_ui_qif_import_commodity_update(QIFImportWindow * wind)
1010 {
1011  GList *pageptr;
1012  GtkWidget *gtkpage;
1013  QIFAssistantPage *page;
1014  const gchar *mnemonic = NULL;
1015  gchar *name_space = NULL;
1016  const gchar *fullname = NULL;
1017  gnc_commodity *tab_commodity;
1018 
1019  for (pageptr = wind->commodity_pages; pageptr; pageptr = pageptr->next)
1020  {
1021  gtkpage = pageptr->data;
1022  page = g_object_get_data(G_OBJECT(gtkpage), "page_struct");
1023 
1024  /* Get any changes from the commodity page. */
1025  mnemonic = gtk_entry_get_text(GTK_ENTRY(page->mnemonic_entry));
1026  name_space = gnc_ui_namespace_picker_ns(page->namespace_combo);
1027  fullname = gtk_entry_get_text(GTK_ENTRY(page->name_entry));
1028 
1029  /* Update the commodity with the new values. */
1030  gnc_commodity_set_namespace(page->commodity, name_space);
1031  gnc_commodity_set_fullname(page->commodity, fullname);
1032  gnc_commodity_set_mnemonic(page->commodity, mnemonic);
1033 
1034  /* Add the commodity to the commodity table (if it isn't a duplicate). */
1035  tab_commodity = gnc_commodity_table_lookup(gnc_get_current_commodities(),
1036  name_space, mnemonic);
1037  if (!tab_commodity || tab_commodity == page->commodity)
1038  tab_commodity = gnc_commodity_table_insert(gnc_get_current_commodities(),
1039  page->commodity);
1040 
1041  /* Update the security hash table. */
1042  scm_hash_set_x(wind->security_hash,
1043  page->hash_key,
1044  SWIG_NewPointerObj(tab_commodity,
1045  SWIG_TypeQuery("_p_gnc_commodity"), 0));
1046 
1047  g_free(name_space);
1048  }
1049 }
1050 
1051 
1052 /****************************************************************
1053  * gnc_ui_qif_import_convert_undo
1054  *
1055  * This function launches the Scheme procedure that un-imports
1056  * any imported accounts and transactions.
1057  ****************************************************************/
1058 static void
1059 gnc_ui_qif_import_convert_undo(QIFImportWindow * wind)
1060 {
1061  SCM undo = scm_c_eval_string("qif-import:qif-to-gnc-undo");
1062 
1063  gnc_set_busy_cursor(NULL, TRUE);
1064 
1065  /* Undo the conversion. */
1066  scm_call_1(undo, wind->imported_account_tree);
1067 
1068  /* There's no imported account tree any more. */
1069  scm_gc_unprotect_object(wind->imported_account_tree);
1070  wind->imported_account_tree = SCM_BOOL_F;
1071  scm_gc_protect_object(wind->imported_account_tree);
1072 
1073  /* Get rid of the list of matched transactions. */
1074  scm_gc_unprotect_object(wind->match_transactions);
1075  wind->match_transactions = SCM_BOOL_F;
1076  scm_gc_protect_object(wind->match_transactions);
1077 
1078  gnc_unset_busy_cursor(NULL);
1079 }
1080 
1081 
1082 /****************************************************************
1083  * refresh_old_transactions
1084  *
1085  * This function launches the Scheme procedure that refreshes
1086  * the old transactions.
1087  ****************************************************************/
1088 static void
1089 refresh_old_transactions(QIFImportWindow * wind, int selection)
1090 {
1091  SCM possible_matches;
1092  SCM current_xtn;
1093  SCM selected;
1094  Transaction * gnc_xtn;
1095  Split * gnc_split;
1096  const gchar * amount_str;
1097  int rownum = 0;
1098  GtkTreeView *view;
1099  GtkListStore *store;
1100  GtkTreeIter iter;
1101 
1102  view = GTK_TREE_VIEW(wind->old_transaction_view);
1103  store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
1104  gtk_list_store_clear(store);
1105 
1106  if (wind->match_transactions != SCM_BOOL_F)
1107  {
1108  possible_matches = SCM_CDR(scm_list_ref(wind->match_transactions,
1109  scm_from_int (wind->selected_transaction)));
1110  scm_call_2(scm_c_eval_string("qif-import:refresh-match-selection"),
1111  possible_matches, scm_from_int (selection));
1112 
1113  while (!scm_is_null(possible_matches))
1114  {
1115  current_xtn = SCM_CAR(possible_matches);
1116 #define FUNC_NAME "xaccTransCountSplits"
1117  gnc_xtn = SWIG_MustGetPtr(SCM_CAR(current_xtn),
1118  SWIG_TypeQuery("_p_Transaction"), 1, 0);
1119 #undef FUNC_NAME
1120  selected = SCM_CDR(current_xtn);
1121 
1122  if (xaccTransCountSplits(gnc_xtn) > 2)
1123  {
1124  amount_str = _("(split)");
1125  }
1126  else
1127  {
1128  gnc_split = xaccTransGetSplit(gnc_xtn, 0);
1129  amount_str =
1130  xaccPrintAmount(gnc_numeric_abs(xaccSplitGetValue(gnc_split)),
1131  gnc_account_print_info
1132  (xaccSplitGetAccount(gnc_split), TRUE));
1133  }
1134 
1135  gtk_list_store_append(store, &iter);
1136  gtk_list_store_set
1137  (store, &iter,
1138  QIF_TRANS_COL_INDEX, rownum++,
1139  QIF_TRANS_COL_DATE, gnc_print_date(xaccTransRetDatePostedTS(gnc_xtn)),
1140  QIF_TRANS_COL_DESCRIPTION, xaccTransGetDescription(gnc_xtn),
1141  QIF_TRANS_COL_AMOUNT, amount_str,
1142  QIF_TRANS_COL_CHECKED, selected != SCM_BOOL_F,
1143  -1);
1144 
1145  possible_matches = SCM_CDR(possible_matches);
1146  }
1147  }
1148 }
1149 
1150 
1151 /****************************************************************
1152  * gnc_ui_qif_import_duplicate_new_select_cb
1153  *
1154  * This function is the call back for duplicate transactions.
1155  ****************************************************************/
1156 static void
1157 gnc_ui_qif_import_duplicate_new_select_cb(GtkTreeSelection *selection,
1158  QIFImportWindow *wind)
1159 {
1160  GtkTreeModel *model;
1161  GtkTreeIter iter;
1162 
1163  if (gtk_tree_selection_get_selected(selection, &model, &iter))
1164  gtk_tree_model_get(model, &iter,
1165  QIF_TRANS_COL_INDEX, &wind->selected_transaction,
1166  -1);
1167  refresh_old_transactions(wind, -1);
1168 }
1169 
1170 
1171 /****************************************************************
1172  * reset_ignore_old_select
1173  ****************************************************************/
1174 static gboolean
1175 reset_ignore_old_select(gboolean *ignore)
1176 {
1177  *ignore = FALSE;
1178  return FALSE;
1179 }
1180 
1181 
1182 /****************************************************************
1183  * gnc_ui_qif_import_duplicate_old_select_cb
1184  *
1185  * This function is the call back for duplicate transactions.
1186  ****************************************************************/
1187 static void
1188 gnc_ui_qif_import_duplicate_old_select_cb(GtkTreeSelection *selection,
1189  QIFImportWindow *wind)
1190 {
1191  GtkTreeModel *model;
1192  GtkTreeIter iter;
1193  gint row;
1194  static gboolean ignore_old_select = FALSE;
1195 
1196  /* Get the current selection then clear it. We're about to clear
1197  * the entire list store and rebuild it so this prevents errors. */
1198  if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1199  return;
1200  gtk_tree_selection_unselect_all(selection);
1201 
1202  /* Getting a weird double call the first time a line is clicked.
1203  * Once via gtk_tree_view_button_press and then again via
1204  * gtk_tree_view_grab_focus. */
1205  if (ignore_old_select)
1206  return;
1207  ignore_old_select = TRUE;
1208  g_idle_add((GSourceFunc)reset_ignore_old_select, &ignore_old_select);
1209 
1210  /* Get the row the user clicked on and update the scheme
1211  * code/rebuild the list store. */
1212  gtk_tree_model_get(model, &iter,
1213  QIF_TRANS_COL_INDEX, &row,
1214  -1);
1215  refresh_old_transactions(wind, row);
1216 }
1217 
1218 
1219 /********************************************************************
1220  * gnc_ui_qif_import_check_acct_tree
1221  *
1222  * Designed for use with gnc_main_window_foreach_page(), this
1223  * function determines whether an account tab is open in the main
1224  * window. The parameter user_data must point to a gboolean.
1225  ********************************************************************/
1226 static void
1227 gnc_ui_qif_import_check_acct_tree(GncPluginPage *page, gpointer user_data)
1228 {
1229  gboolean *found = user_data;
1230 
1231  if (GNC_IS_PLUGIN_PAGE_ACCOUNT_TREE(page) && found)
1232  *found = TRUE;
1233 }
1234 
1235 
1236 /****************************************************************
1237  * do_cancel
1238  *
1239  * Clears out any imported data and shuts down the importer.
1240  ****************************************************************/
1241 static void
1242 do_cancel(QIFImportWindow * wind)
1243 {
1244  GList *pageptr;
1245  GtkWidget *gtkpage;
1246  QIFAssistantPage *page;
1247  gnc_commodity_table *table;
1248 
1249  gnc_set_busy_cursor(NULL, TRUE);
1250 
1251  /* Remove any converted data. */
1252  gnc_ui_qif_import_convert_undo(wind);
1253 
1254  /* Remove any commodities created for assistant pages. */
1255  for (pageptr = wind->commodity_pages; pageptr; pageptr = pageptr->next)
1256  {
1257  gtkpage = pageptr->data;
1258  page = g_object_get_data(G_OBJECT(gtkpage), "page_struct");
1259  gnc_commodity_destroy(page->commodity);
1260  }
1261 
1262  /* Remove any namespaces created by the user. */
1263  table = gnc_get_current_commodities();
1264  while (wind->new_namespaces)
1265  {
1266  gnc_commodity_table_delete_namespace(table, (gchar *) wind->new_namespaces->data);
1267 
1268  /* Free the data and the list element. */
1269  g_free(wind->new_namespaces->data);
1270  wind->new_namespaces = g_list_delete_link(wind->new_namespaces,
1271  wind->new_namespaces);
1272  }
1273  gnc_unset_busy_cursor(NULL);
1274 
1275  /* Destroy the assistant. */
1276  gnc_close_gui_component_by_data(ASSISTANT_QIF_IMPORT_CM_CLASS, wind);
1277 }
1278 
1279 
1280 /****************************************************************
1281  * cancel_timeout_cb
1282  *
1283  * This timer callback function waits until the busy flag
1284  * has been cleared before acting to cancel the import.
1285  ****************************************************************/
1286 static gboolean
1287 cancel_timeout_cb(gpointer data)
1288 {
1289  QIFImportWindow *wind = data;
1290 
1291  if (wind->busy)
1292  /* Wait for timer to go off again. */
1293  return TRUE;
1294 
1295  /* The busy flag was lowered. Perform the cancel. */
1296  do_cancel(wind);
1297 
1298  /* Cancel the timer. */
1299  return FALSE;
1300 }
1301 
1302 
1303 /****************************************************************
1304  * gnc_ui_qif_import_cancel_cb
1305  *
1306  * Invoked when the "Cancel" button is clicked.
1307  ****************************************************************/
1308 void
1309 gnc_ui_qif_import_cancel_cb(GtkAssistant *gtkassistant, gpointer user_data)
1310 {
1311  QIFImportWindow *wind = user_data;
1312  gint currentpage = gtk_assistant_get_current_page(gtkassistant);
1313  GtkWidget *mypage = gtk_assistant_get_nth_page (gtkassistant, currentpage);
1314  const char *pagename = gtk_buildable_get_name(GTK_BUILDABLE(mypage));
1315 
1316  if (!g_strcmp0 (pagename, "summary_page"))
1317  {
1318  /* Hitting the window close button on the summary page should not
1319  invoke a cancel action. The import has finised at that point. */
1320  gnc_ui_qif_import_close_cb(gtkassistant, user_data);
1321  }
1322  else if (wind->busy)
1323  {
1324  /* Cancel any long-running Scheme operation. */
1325  scm_c_eval_string("(qif-import:cancel)");
1326 
1327  /* Wait for the busy flag to be lowered. */
1328  g_timeout_add(200, cancel_timeout_cb, user_data);
1329  }
1330  else
1331  do_cancel(wind);
1332 }
1333 
1334 
1335 /****************************************************************
1336  * gnc_ui_qif_import_close_cb
1337  *
1338  * Invoked when the "Close" button is clicked.
1339  ****************************************************************/
1340 void
1341 gnc_ui_qif_import_close_cb(GtkAssistant *gtkassistant, gpointer user_data)
1342 {
1343  QIFImportWindow *wind = user_data;
1344 
1345  /* If We did not have an account tree, lets save it */
1346  if (!wind->acct_tree_found)
1347  {
1348  qof_book_mark_session_dirty(gnc_get_current_book());
1349  gnc_ui_file_access_for_save_as();
1350  }
1351 
1352  gnc_close_gui_component_by_data( ASSISTANT_QIF_IMPORT_CM_CLASS, wind );
1353 }
1354 
1355 
1356 /****************************************************************
1357  * gnc_ui_qif_import_assistant_get_mappings
1358  *
1359  * SCM get mappings.
1360  ****************************************************************/
1361 SCM
1362 gnc_ui_qif_import_assistant_get_mappings(QIFImportWindow * w)
1363 {
1364  return SCM_LIST3(w->acct_map_info,
1365  w->cat_map_info,
1366  w->memo_map_info);
1367 }
1368 
1369 
1370 /* ================================================================== */
1371 /* */
1372 /* IMPORTER CREATION */
1373 /* */
1374 /* ================================================================== */
1375 
1376 /********************************************************************
1377  * get_preferences
1378  *
1379  * Get all user preferences related to QIF import.
1380  ********************************************************************/
1381 static void
1382 get_preferences(QIFImportWindow *wind)
1383 {
1384  gchar tmp_transaction_status = 'n';
1385 
1386  g_return_if_fail(wind);
1387 
1388  /* Get the user's preference for showing documentation pages. */
1389  wind->show_doc_pages =
1390  gnc_prefs_get_bool (GNC_PREFS_GROUP, GNC_PREF_SHOW_DOC);
1391 
1392  /* Clear / Reconcile transaction if not specified in QIF file. */
1393  if (gnc_prefs_get_bool (GNC_PREFS_GROUP, GNC_PREF_DEFAULT_TRANS_STATUS_CLEARED))
1394  tmp_transaction_status = 'c';
1395  else if (gnc_prefs_get_bool (GNC_PREFS_GROUP, GNC_PREF_DEFAULT_TRANS_STATUS_RECONCILED))
1396  tmp_transaction_status = 'y';
1397 
1398  wind->transaction_status = SCM_MAKE_CHAR(tmp_transaction_status);
1399 }
1400 
1401 
1402 /********************************************************************
1403  * initialize_scheme
1404  *
1405  * Initialize all Scheme-controlled objects.
1406  ********************************************************************/
1407 static void
1408 initialize_scheme(QIFImportWindow *wind)
1409 {
1410  SCM load_map_prefs;
1411  SCM mapping_info;
1412  SCM create_ticker_map;
1413 
1414  g_return_if_fail(wind);
1415 
1416  /* Initialize Scheme variables. */
1417  wind->imported_files = SCM_EOL;
1418  wind->selected_file = SCM_BOOL_F;
1419  wind->gnc_acct_info = SCM_BOOL_F;
1420  wind->cat_display_info = SCM_BOOL_F;
1421  wind->cat_map_info = SCM_BOOL_F;
1422  wind->acct_display_info = SCM_BOOL_F;
1423  wind->acct_map_info = SCM_BOOL_F;
1424  wind->memo_display_info = SCM_BOOL_F;
1425  wind->memo_map_info = SCM_BOOL_F;
1426  wind->security_hash = SCM_BOOL_F;
1427  wind->security_prefs = SCM_BOOL_F;
1428  wind->new_securities = SCM_BOOL_F;
1429  wind->ticker_map = SCM_BOOL_F;
1430  wind->imported_account_tree = SCM_BOOL_F;
1431  wind->match_transactions = SCM_BOOL_F;
1432 
1433  /* Get the saved state of mappings from Quicken accounts and
1434  * categories to GnuCash accounts. */
1435  load_map_prefs = scm_c_eval_string("qif-import:load-map-prefs");
1436  mapping_info = scm_call_0(load_map_prefs); /* <- gets/creates session/book */
1437  wind->gnc_acct_info = scm_list_ref(mapping_info, scm_from_int (0));
1438  wind->acct_map_info = scm_list_ref(mapping_info, scm_from_int (1));
1439  wind->cat_map_info = scm_list_ref(mapping_info, scm_from_int (2));
1440  wind->memo_map_info = scm_list_ref(mapping_info, scm_from_int (3));
1441  wind->security_hash = scm_list_ref(mapping_info, scm_from_int (4));
1442  wind->security_prefs = scm_list_ref(mapping_info, scm_from_int (5));
1443 
1444  /* Get the initial ticker map. */
1445  create_ticker_map = scm_c_eval_string("make-ticker-map");
1446  wind->ticker_map = scm_call_0(create_ticker_map);
1447 
1448  /* Protect our data from garbage collection. */
1449  scm_gc_protect_object(wind->imported_files);
1450  scm_gc_protect_object(wind->selected_file);
1451  scm_gc_protect_object(wind->gnc_acct_info);
1452  scm_gc_protect_object(wind->cat_display_info);
1453  scm_gc_protect_object(wind->cat_map_info);
1454  scm_gc_protect_object(wind->memo_display_info);
1455  scm_gc_protect_object(wind->memo_map_info);
1456  scm_gc_protect_object(wind->acct_display_info);
1457  scm_gc_protect_object(wind->acct_map_info);
1458  scm_gc_protect_object(wind->security_hash);
1459  scm_gc_protect_object(wind->security_prefs);
1460  scm_gc_protect_object(wind->new_securities);
1461  scm_gc_protect_object(wind->ticker_map);
1462  scm_gc_protect_object(wind->imported_account_tree);
1463  scm_gc_protect_object(wind->match_transactions);
1464 }
1465 
1466 
1467 /*****************************************
1468  * Page 0 - Intro Page Page
1469  ****************************************/
1470 
1471 /********************************************************************
1472  * gnc_ui_qif_import_intro_prepare
1473  *
1474  * Prepare the intro page for display.
1475  ********************************************************************/
1476 void
1477 gnc_ui_qif_import_intro_prepare (GtkAssistant *assistant, gpointer user_data)
1478 {
1479  QIFImportWindow *wind = user_data;
1480  SCM unload = scm_c_eval_string("qif-dialog:unload-qif-file");
1481  SCM files_list;
1482 
1483  /* Set load stop to FALSE */
1484  wind->load_stop = FALSE;
1485 
1486  files_list = scm_call_2(unload, wind->selected_file, wind->imported_files);
1487 
1488  scm_gc_unprotect_object(wind->imported_files);
1489  wind->imported_files = files_list;
1490  scm_gc_protect_object(wind->imported_files);
1491 
1492  scm_gc_unprotect_object(wind->selected_file);
1493  wind->selected_file = SCM_BOOL_F;
1494  scm_gc_protect_object(wind->selected_file);
1495 }
1496 
1497 
1498 /*****************************************
1499  * Page 1 - Load File Page Procedures
1500  ****************************************/
1501 
1502 /********************************************************************
1503  * gnc_ui_qif_import_load_file_complete
1504  *
1505  * Do we have a file to load.
1506  ********************************************************************/
1507 static gboolean
1508 gnc_ui_qif_import_load_file_complete (GtkAssistant *assistant,
1509  gpointer user_data)
1510 {
1511  QIFImportWindow * wind = user_data;
1512  const gchar * path_to_load;
1513 
1514  /* Get the file name. */
1515  path_to_load = gtk_entry_get_text(GTK_ENTRY(wind->filename_entry));
1516 
1517  /* Validate the chosen filename. */
1518  if (strlen(path_to_load) == 0)
1519  gnc_error_dialog(wind->window, "%s", _("Please select a file to load."));
1520  else if (g_access(path_to_load, R_OK) < 0)
1521  gnc_error_dialog(wind->window, "%s",
1522  _("File not found or read permission denied. "
1523  "Please select another file."));
1524  else
1525  {
1526  SCM qif_file_loaded = scm_c_eval_string("qif-dialog:qif-file-loaded?");
1527 
1528  /* See if the file is already loaded. */
1529  if (scm_call_2(qif_file_loaded,
1530  scm_from_locale_string(path_to_load ? path_to_load : ""),
1531  wind->imported_files) == SCM_BOOL_T)
1532  gnc_error_dialog(wind->window, "%s",
1533  _("That QIF file is already loaded. "
1534  "Please select another file."));
1535  else
1536  {
1537  /* Passed all checks; proceed to the next page. */
1538  return TRUE;
1539  }
1540  }
1541 
1542  /* Stay on this page. */
1543  return FALSE;
1544 }
1545 
1546 
1547 /********************************************************************
1548  * gnc_ui_qif_import_load_file_prepare
1549  *
1550  * Prepare the load file page for display.
1551  ********************************************************************/
1552 void
1553 gnc_ui_qif_import_load_file_prepare (GtkAssistant *assistant, gpointer user_data)
1554 {
1555  QIFImportWindow * wind = user_data;
1556  const gchar * path_to_load;
1557  gboolean page_status = FALSE;
1558 
1559  gint num = gtk_assistant_get_current_page (assistant);
1560  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1561 
1562  /* Get the file name. */
1563  path_to_load = gtk_entry_get_text(GTK_ENTRY(wind->filename_entry));
1564 
1565  /* Calculate status for the Assistant Forward Button */
1566  if (strlen(path_to_load) != 0)
1567  {
1568  page_status = gnc_ui_qif_import_load_file_complete(assistant, user_data);
1569  }
1570  gtk_assistant_set_page_complete (assistant, page, page_status);
1571 }
1572 
1573 
1574 /********************************************************************
1575  * gnc_ui_qif_import_select_file_cb
1576  *
1577  * invoked when the "select file" button is clicked
1578  * this is just to pick a file name and reset-to-defaults all the
1579  * fields describing how to parse the file.
1580  ********************************************************************/
1581 void
1582 gnc_ui_qif_import_select_file_cb(GtkButton * button,
1583  gpointer user_data)
1584 {
1585  QIFImportWindow * wind = user_data;
1586 
1587  GtkAssistant *assistant = GTK_ASSISTANT(wind->window);
1588  gint num = gtk_assistant_get_current_page (assistant);
1589  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1590 
1591  GtkFileFilter *filter;
1592  char * new_file_name;
1593  char *file_name, *default_dir;
1594 
1595  /* Default to whatever's already present */
1596  default_dir = gnc_get_default_directory(GNC_PREFS_GROUP);
1597 
1598  filter = gtk_file_filter_new();
1599  gtk_file_filter_set_name(filter, "*.qif");
1600  gtk_file_filter_add_pattern(filter, "*.[Qq][Ii][Ff]");
1601  new_file_name = gnc_file_dialog(_("Select QIF File"),
1602  g_list_prepend (NULL, filter),
1603  default_dir,
1604  GNC_FILE_DIALOG_IMPORT);
1605 
1606  /* Insure valid data, and something that can be freed. */
1607  if (new_file_name == NULL)
1608  {
1609  file_name = g_strdup(default_dir);
1610  }
1611  else if (!g_path_is_absolute(new_file_name))
1612  {
1613  file_name = g_build_filename(default_dir, new_file_name, NULL);
1614  g_free(new_file_name);
1615  }
1616  else
1617  {
1618  file_name = new_file_name;
1619  /* Update the working directory */
1620  g_free(default_dir);
1621  default_dir = g_path_get_dirname(file_name);
1622  gnc_set_default_directory(GNC_PREFS_GROUP, default_dir);
1623  }
1624  g_free(default_dir);
1625 
1626  /* set the filename entry for what was selected */
1627  gtk_entry_set_text(GTK_ENTRY(wind->filename_entry), file_name);
1628  g_free(file_name);
1629 
1630  gtk_assistant_set_page_complete (assistant, page,
1631  gnc_ui_qif_import_load_file_complete (assistant, user_data));
1632 }
1633 
1634 
1635 /*****************************************
1636  * Page 2 - Load Progress Page Procedures
1637  ****************************************/
1638 
1639 /********************************************************************
1640  * gnc_ui_qif_import_load_progress_pause_cb
1641  *
1642  * Invoked when the "Pause" button is clicked.
1643  ********************************************************************/
1644 void
1645 gnc_ui_qif_import_load_progress_pause_cb(GtkButton * button,
1646  gpointer user_data)
1647 {
1648  QIFImportWindow *wind = user_data;
1649  SCM toggle_pause = scm_c_eval_string("qif-import:toggle-pause");
1650  SCM progress;
1651 
1652  if (!wind->busy)
1653  return;
1654 
1655  /* Create SCM for the progress helper. */
1656  progress = SWIG_NewPointerObj(wind->load_progress,
1657  SWIG_TypeQuery("_p__GNCProgressDialog"),
1658  0);
1659 
1660  /* Pause (or resume) the currently running operation. */
1661  scm_call_1(toggle_pause, progress);
1662 
1663  /* Swap the button label between pause and resume. */
1664  if (strcmp(gtk_button_get_label(button), _("_Resume")))
1665  {
1666  gtk_button_set_use_stock(button, FALSE);
1667  gtk_button_set_use_underline(button, TRUE);
1668  gtk_button_set_label(button, _("_Resume"));
1669  }
1670  else
1671  {
1672  gtk_button_set_use_stock(button, TRUE);
1673  gtk_button_set_use_underline(button, FALSE);
1674  gtk_button_set_label(button, "gtk-media-pause");
1675  }
1676 }
1677 
1678 
1679 /********************************************************************
1680  * gnc_ui_qif_import_load_progress_start_cb
1681  *
1682  * Invoked when the "Start" button is clicked.
1683  ********************************************************************/
1684 void
1685 gnc_ui_qif_import_load_progress_start_cb(GtkButton * button,
1686  gpointer user_data)
1687 {
1688  QIFImportWindow *wind = user_data;
1689  gint num = gtk_assistant_get_current_page (GTK_ASSISTANT(wind->window));
1690  GtkWidget *page = gtk_assistant_get_nth_page (GTK_ASSISTANT(wind->window), num);
1691 
1692  const gchar * path_to_load;
1693 
1694  SCM make_qif_file = scm_c_eval_string("make-qif-file");
1695  SCM qif_file_load = scm_c_eval_string("qif-file:read-file");
1696  SCM qif_file_parse = scm_c_eval_string("qif-file:parse-fields");
1697  SCM unload_qif_file = scm_c_eval_string("qif-dialog:unload-qif-file");
1698  SCM parse_results = scm_c_eval_string("qif-file:parse-fields-results");
1699  SCM scm_qiffile;
1700  SCM imported_files = SCM_EOL;
1701  SCM load_return, parse_return;
1702  SCM progress;
1703 
1704  /* Raise the busy flag so the assistant can't be canceled unexpectedly. */
1705  wind->busy = TRUE;
1706  gtk_widget_set_sensitive(wind->load_pause, TRUE);
1707 
1708  /* Get the file name. */
1709  path_to_load = gtk_entry_get_text(GTK_ENTRY(wind->filename_entry));
1710 
1711  /* Create the <qif-file> object. */
1712  scm_qiffile = scm_call_0(make_qif_file);
1713  scm_gc_unprotect_object(wind->selected_file);
1714  wind->selected_file = scm_qiffile;
1715  scm_gc_protect_object(wind->selected_file);
1716  imported_files = scm_cons(scm_qiffile, wind->imported_files);
1717 
1718  /* Create SCM for the progress helper. */
1719  progress = SWIG_NewPointerObj(wind->load_progress,
1720  SWIG_TypeQuery("_p__GNCProgressDialog"),
1721  0);
1722 
1723  /* Clear any previous pause or cancel state. */
1724  scm_c_eval_string("(qif-import:reset-cancel-pause)");
1725 
1726  /*
1727  * Load the file.
1728  *
1729  * The loader returns:
1730  * success: ()
1731  * failure: (#f error-message)
1732  * warning: (#t error-message)
1733  * cancel: #t
1734  * exception: #f
1735  */
1736 
1737  /* This step will fill 70% of the bar. */
1738  gnc_progress_dialog_push(wind->load_progress, 0.7);
1739  load_return = scm_call_4(qif_file_load,
1740  SCM_CAR(imported_files),
1741  scm_from_locale_string(path_to_load ? path_to_load : ""),
1742  wind->ticker_map,
1743  progress);
1744  gnc_progress_dialog_pop(wind->load_progress);
1745  if (load_return == SCM_BOOL_T)
1746  {
1747  /* Canceled by the user. */
1748 
1749  /* Disable the pause button. */
1750  gtk_widget_set_sensitive(wind->load_pause, FALSE);
1751 
1752  /* Inform the user. */
1753  gnc_progress_dialog_set_sub(wind->load_progress, _("Canceled"));
1754 
1755  wind->busy = FALSE;
1756  wind->load_stop = TRUE;
1757  }
1758  else if (load_return == SCM_BOOL_F || !scm_is_list(load_return))
1759  {
1760  /* A bug was detected. */
1761 
1762  /* Disable the pause button. */
1763  gtk_widget_set_sensitive(wind->load_pause, FALSE);
1764 
1765  /* Inform the user. */
1766  gnc_progress_dialog_append_log(wind->load_progress,
1767  _( "An error occurred while loading the QIF file."));
1768  gnc_progress_dialog_set_sub(wind->load_progress, _("Failed"));
1769  gnc_progress_dialog_reset_value(wind->load_progress);
1770  gnc_error_dialog(wind->window, "%s",
1771  _( "An error occurred while loading the QIF file."));
1772  /* FIXME: How should we request that the user report this problem? */
1773 
1774  wind->busy = FALSE;
1775  wind->load_stop = TRUE;
1776  }
1777  else if (!scm_is_null(load_return))
1778  {
1779  if (SCM_CAR(load_return) == SCM_BOOL_F)
1780  {
1781  imported_files = scm_call_2(unload_qif_file, scm_qiffile, imported_files);
1782  scm_gc_unprotect_object(wind->imported_files);
1783  wind->imported_files = imported_files;
1784  scm_gc_protect_object(wind->imported_files);
1785 
1786  gnc_progress_dialog_set_sub(wind->load_progress, _("Failed"));
1787  gnc_progress_dialog_reset_value(wind->load_progress);
1788 
1789  gtk_widget_set_sensitive(wind->load_pause, FALSE);
1790  wind->busy = FALSE;
1791  wind->load_stop = TRUE;
1792  }
1793  }
1794 
1795  /*
1796  * Parse the fields.
1797  *
1798  * The parser returns:
1799  * success: ()
1800  * failure: (#f . ((type . error) ...))
1801  * warning: (#t . ((type . error) ...))
1802  * cancel: #t
1803  * exception: #f
1804  */
1805 
1806  /* This step will fill the remainder of the bar. */
1807  gnc_progress_dialog_push(wind->load_progress, 1);
1808  parse_return = scm_call_2(qif_file_parse, SCM_CAR(imported_files), progress);
1809  gnc_progress_dialog_pop(wind->load_progress);
1810  wind->ask_date_format = FALSE;
1811  if (parse_return == SCM_BOOL_T)
1812  {
1813  /* Canceled by the user. */
1814 
1815  /* Disable the pause button. */
1816  gtk_widget_set_sensitive(wind->load_pause, FALSE);
1817 
1818  /* Unload the file. */
1819  gnc_progress_dialog_set_sub(wind->load_progress, _("Cleaning up"));
1820  imported_files = scm_call_2(unload_qif_file, scm_qiffile, imported_files);
1821 
1822  /* Inform the user. */
1823  gnc_progress_dialog_set_sub(wind->load_progress, _("Canceled"));
1824 
1825  wind->busy = FALSE;
1826  wind->load_stop = TRUE;
1827  }
1828  else if (parse_return == SCM_BOOL_F || !scm_is_list(parse_return))
1829  {
1830  /* A bug was detected. */
1831 
1832  /* Disable the pause button. */
1833  gtk_widget_set_sensitive(wind->load_pause, FALSE);
1834 
1835  /* Unload the file. */
1836  gnc_progress_dialog_set_sub(wind->load_progress, _("Cleaning up"));
1837  imported_files = scm_call_2(unload_qif_file, scm_qiffile, imported_files);
1838 
1839  /* Inform the user. */
1840  gnc_progress_dialog_append_log(wind->load_progress,
1841  _( "A bug was detected while parsing the QIF file."));
1842  gnc_progress_dialog_set_sub(wind->load_progress, _("Failed"));
1843  gnc_progress_dialog_reset_value(wind->load_progress);
1844  gnc_error_dialog(wind->window, "%s",
1845  _( "A bug was detected while parsing the QIF file."));
1846  /* FIXME: How should we request that the user report this problem? */
1847 
1848  wind->busy = FALSE;
1849  wind->load_stop = TRUE;
1850  }
1851  else if (!scm_is_null(parse_return))
1852  {
1853  /* Are there only warnings? */
1854  if (SCM_CAR(parse_return) == SCM_BOOL_T)
1855  {
1856  SCM date_formats;
1857 
1858  /* A warning means that (potentially) the date format is
1859  * ambiguous. So search the results for the "date" type and if
1860  * it's found, set up the format selector page. */
1861  if ((date_formats = scm_call_2(parse_results,
1862  SCM_CDR(parse_return),
1863  scm_from_locale_symbol ("date"))) != SCM_BOOL_F)
1864  {
1865  GtkComboBox *combo_box;
1866  GtkTreeModel *model;
1867  GtkTreeIter iter;
1868 
1869  /* Block the date call back */
1870  g_signal_handlers_block_by_func( wind->date_format_combo, gnc_ui_qif_import_date_valid_cb, wind );
1871 
1872  /* Clear the date format combo box. */
1873  combo_box = GTK_COMBO_BOX(wind->date_format_combo);
1874  model = gtk_combo_box_get_model(combo_box);
1875  gtk_list_store_clear(GTK_LIST_STORE(model));
1876 
1877  gtk_combo_box_set_active(GTK_COMBO_BOX(wind->date_format_combo), -1);
1878 
1879  /* Add the formats for the user to select from. */
1880  while (scm_is_list(date_formats) && !scm_is_null(date_formats))
1881  {
1882  gtk_list_store_append(GTK_LIST_STORE(model), &iter);
1883  gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, gnc_scm_symbol_to_locale_string(SCM_CAR(date_formats)), -1);
1884 
1885  date_formats = SCM_CDR(date_formats);
1886  }
1887 
1888  /* Unblock the date call back */
1889  g_signal_handlers_unblock_by_func( wind->date_format_combo, gnc_ui_qif_import_date_valid_cb, wind );
1890 
1891  wind->ask_date_format = TRUE;
1892  }
1893  }
1894  else
1895  {
1896  /* Parsing failed. */
1897  imported_files = scm_call_2(unload_qif_file, scm_qiffile, imported_files);
1898  gnc_progress_dialog_set_sub(wind->load_progress, _("Failed"));
1899  gnc_progress_dialog_reset_value(wind->load_progress);
1900 
1901  gtk_widget_set_sensitive(wind->load_pause, FALSE);
1902  wind->busy = FALSE;
1903  wind->load_stop = TRUE;
1904  }
1905  }
1906 
1907  /* Enable the assistant Forward button */
1908  gtk_assistant_set_page_complete (GTK_ASSISTANT(wind->window), page, TRUE);
1909 
1910  /* Set Pause and Start buttons */
1911  gtk_widget_set_sensitive(wind->load_pause, FALSE);
1912  gtk_widget_set_sensitive(wind->load_start, FALSE);
1913 
1914  if (wind->load_stop == FALSE)
1915  {
1916  /* The file was loaded successfully. */
1917  gnc_progress_dialog_set_sub(wind->load_progress, _("Loading completed"));
1918  gnc_progress_dialog_set_value(wind->load_progress, 1);
1919 
1920  scm_gc_unprotect_object(wind->imported_files);
1921  wind->imported_files = imported_files;
1922  scm_gc_protect_object(wind->imported_files);
1923 
1924  gtk_widget_set_sensitive(wind->load_pause, FALSE);
1925  wind->busy = FALSE;
1926 
1927  /* Auto step to next page */
1928  gtk_assistant_set_current_page (GTK_ASSISTANT(wind->window), num + 1);
1929  }
1930 }
1931 
1932 
1933 /********************************************************************
1934  * gnc_ui_qif_import_load_progress_prepare
1935  *
1936  * Prepare the file loading progress page for display.
1937  ********************************************************************/
1938 void
1939 gnc_ui_qif_import_load_progress_prepare (GtkAssistant *assistant, gpointer user_data)
1940 {
1941  QIFImportWindow *wind = user_data;
1942  gint num = gtk_assistant_get_current_page (assistant);
1943  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1944 
1945  /* Reset the progress display. */
1946  gnc_progress_dialog_set_primary(wind->load_progress, "");
1947  gnc_progress_dialog_set_secondary(wind->load_progress,
1948  _("When you press the Start Button, GnuCash will load your QIF file. If there are no errors or warnings, you will automatically proceed to the next step. Otherwise, the details will be shown below for your review."));
1949  gnc_progress_dialog_set_sub(wind->load_progress, " ");
1950  gnc_progress_dialog_reset_value(wind->load_progress);
1951  gnc_progress_dialog_reset_log(wind->load_progress);
1952 
1953  /* Set Pause and Start buttons */
1954  gtk_widget_set_sensitive(wind->load_pause, FALSE);
1955  gtk_widget_set_sensitive(wind->load_start, TRUE);
1956 
1957  /* Disable the assistant Forward button */
1958  gtk_assistant_set_page_complete (assistant, page, FALSE);
1959 }
1960 
1961 
1962 /*****************************************
1963  * Page 3 - Date format Page Procedures
1964  ****************************************/
1965 
1966 /********************************************************************
1967  * gnc_ui_qif_import_date_format_prepare
1968  *
1969  * Determine if we need the date page and what is next page.
1970  ********************************************************************/
1971 void
1972 gnc_ui_qif_import_date_format_prepare (GtkAssistant *assistant, gpointer user_data)
1973 
1974 {
1975  QIFImportWindow *wind = user_data;
1976  gint num = gtk_assistant_get_current_page (assistant);
1977 
1978  if (wind->ask_date_format)
1979  {
1980  /* We need to get a date format, so stay here. */
1981  }
1982  else
1983  {
1984  /* Skip ahead to the Account page. */
1985  gtk_assistant_set_current_page (assistant, num + 1);
1986  }
1987 }
1988 
1989 
1990 /********************************************************************
1991  * gnc_ui_qif_import_date_valid_cb
1992  *
1993  * Reparse file with new date format.
1994  ********************************************************************/
1995 void
1996 gnc_ui_qif_import_date_valid_cb (GtkWidget *widget, gpointer user_data)
1997 {
1998  QIFImportWindow * wind = user_data;
1999  GtkTreeModel *model;
2000  GtkTreeIter iter;
2001 
2002  GtkAssistant *assistant = GTK_ASSISTANT(wind->window);
2003  gint num = gtk_assistant_get_current_page (assistant);
2004  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2005 
2006  SCM reparse_dates = scm_c_eval_string("qif-file:reparse-dates");
2007  SCM format_sym;
2008  gchar *text;
2009 
2010  /* Get the selected date format. */
2011  model = gtk_combo_box_get_model(GTK_COMBO_BOX(wind->date_format_combo));
2012  gtk_combo_box_get_active_iter (GTK_COMBO_BOX(wind->date_format_combo), &iter);
2013  gtk_tree_model_get( model, &iter, 0, &text, -1 );
2014 
2015  if (!text)
2016  {
2017  g_critical("QIF import: BUG DETECTED in gnc_ui_qif_import_date_valid_cb. Format is NULL.");
2018  }
2019  format_sym = scm_from_locale_symbol (text);
2020  g_free(text);
2021 
2022  /* Reparse the dates using the selected format. */
2023  scm_call_2(reparse_dates, wind->selected_file, format_sym);
2024 
2025  gtk_assistant_set_page_complete (assistant, page, TRUE);
2026 }
2027 
2028 
2029 /******************************************
2030  * Page 4 - Account Setup Page Procedures
2031  ******************************************/
2032 
2033 /********************************************************************
2034  * gnc_ui_qif_import_account_prepare
2035  *
2036  * Do we need to specify an account.
2037  ********************************************************************/
2038 void
2039 gnc_ui_qif_import_account_prepare (GtkAssistant *assistant, gpointer user_data)
2040 {
2041  QIFImportWindow * wind = user_data;
2042  gint num = gtk_assistant_get_current_page (assistant);
2043 
2044  SCM check_from_acct = scm_c_eval_string("qif-file:check-from-acct");
2045 
2046  /* Determine the next page to display. */
2047  if (scm_call_1(check_from_acct, wind->selected_file) != SCM_BOOL_T)
2048  {
2049  /* There is an account name missing. Ask the user to provide one. */
2050  SCM default_acct = scm_c_eval_string("qif-file:path-to-accountname");
2051  gchar * default_acctname = NULL;
2052 
2053  default_acctname = gnc_scm_call_1_to_string(default_acct, wind->selected_file);
2054  gtk_entry_set_text(GTK_ENTRY(wind->acct_entry), default_acctname);
2055  g_free (default_acctname);
2056  }
2057  else
2058  {
2059  /* Skip ahead to the "loaded files" page. */
2060  gtk_assistant_set_current_page (assistant, num + 1);
2061  }
2062 }
2063 
2064 
2065 /********************************************************************
2066  * gnc_ui_qif_import_acct_valid_cb
2067  *
2068  * Invoked when the "next" button is clicked on the default acct page.
2069  ********************************************************************/
2070 void
2071 gnc_ui_qif_import_acct_valid_cb(GtkWidget * widget,
2072  gpointer user_data)
2073 {
2074  QIFImportWindow * wind = user_data;
2075 
2076  GtkAssistant *assistant = GTK_ASSISTANT(wind->window);
2077  gint num = gtk_assistant_get_current_page (assistant);
2078  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2079 
2080  const gchar * acct_name = gtk_entry_get_text(GTK_ENTRY(wind->acct_entry));
2081 
2082  if (!acct_name || acct_name[0] == 0)
2083  {
2084  /* Disable the assistant Forward Button */
2085  gtk_assistant_set_page_complete (assistant, page, FALSE);
2086  }
2087  else
2088  {
2089  /* Enable the assistant Forward Button */
2090  gtk_assistant_set_page_complete (assistant, page, TRUE);
2091  }
2092 }
2093 
2094 
2095 /*****************************************
2096  * Page 5 - Loaded Files Page Procedures
2097  ****************************************/
2098 
2099 /********************************************************************
2100  * gnc_ui_qif_import_loaded_files_prepare
2101  *
2102  * Get the loaded files page ready for viewing
2103  ********************************************************************/
2104 void
2105 gnc_ui_qif_import_loaded_files_prepare (GtkAssistant *assistant,
2106  gpointer user_data)
2107 {
2108  QIFImportWindow * wind = user_data;
2109 
2110  gint num = gtk_assistant_get_current_page (assistant);
2111  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2112 
2113  const gchar * acct_name = gtk_entry_get_text(GTK_ENTRY(wind->acct_entry));
2114  SCM fix_default = scm_c_eval_string("qif-import:fix-from-acct");
2115  SCM scm_name;
2116 
2117  scm_name = scm_from_utf8_string(acct_name ? acct_name : "");
2118  scm_call_2(fix_default, wind->selected_file, scm_name);
2119 
2120  /* Enable the assistant Forward Button */
2121  gtk_assistant_set_page_complete (assistant, page, TRUE);
2122 
2123  update_file_page(wind);
2124 }
2125 
2126 
2127 /********************************************************************
2128  * gnc_ui_qif_import_load_another_cb
2129  * Invoked when the "load another" button is clicked on the loaded
2130  * files page.
2131  ********************************************************************/
2132 void
2133 gnc_ui_qif_import_load_another_cb(GtkButton * button,
2134  gpointer user_data)
2135 {
2136  QIFImportWindow * wind = user_data;
2137  GtkAssistant *assistant = GTK_ASSISTANT(wind->window);
2138 
2139  gtk_assistant_set_current_page (assistant, 1);
2140 }
2141 
2142 
2143 /********************************************************************
2144  * gnc_ui_qif_import_unload_cb
2145  * Invoked when the "unload" button is clicked on the loaded files
2146  * page.
2147  ********************************************************************/
2148 void
2149 gnc_ui_qif_import_unload_file_cb(GtkButton * button,
2150  gpointer user_data)
2151 {
2152  QIFImportWindow * wind = user_data;
2153 
2154  SCM unload_qif_file = scm_c_eval_string("qif-dialog:unload-qif-file");
2155  SCM imported_files;
2156 
2157  if (wind->selected_file != SCM_BOOL_F)
2158  {
2159  imported_files =
2160  scm_call_2(unload_qif_file, wind->selected_file, wind->imported_files);
2161 
2162  scm_gc_unprotect_object(wind->imported_files);
2163  wind->imported_files = imported_files;
2164  scm_gc_protect_object(wind->imported_files);
2165 
2166  scm_gc_unprotect_object(wind->selected_file);
2167  wind->selected_file = SCM_BOOL_F;
2168  scm_gc_protect_object(wind->selected_file);
2169 
2170  update_file_page(wind);
2171  }
2172 }
2173 
2174 
2175 /********************************************************************
2176  * update_file_page
2177  *
2178  * Update the list of loaded files.
2179  ********************************************************************/
2180 static void
2181 update_file_page(QIFImportWindow * wind)
2182 {
2183  SCM loaded_file_list = wind->imported_files;
2184  SCM qif_file_path;
2185  int row = 0;
2186  GtkTreeView *view;
2187  GtkListStore *store;
2188  GtkTreeIter iter;
2189  GtkTreePath *path;
2190  GtkTreeRowReference *reference = NULL;
2191 
2192  /* clear the list */
2193  view = GTK_TREE_VIEW(wind->selected_file_view);
2194  store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
2195  gtk_list_store_clear(store);
2196  qif_file_path = scm_c_eval_string("qif-file:path");
2197 
2198  while (!scm_is_null(loaded_file_list))
2199  {
2200  gchar *row_text = NULL;
2201  SCM scm_qiffile = SCM_BOOL_F;
2202 
2203  scm_qiffile = SCM_CAR(loaded_file_list);
2204  row_text = gnc_scm_call_1_to_string(qif_file_path, scm_qiffile);
2205 
2206  gtk_list_store_append(store, &iter);
2207  gtk_list_store_set(store, &iter,
2208  FILENAME_COL_INDEX, row++,
2209  FILENAME_COL_NAME, row_text,
2210  -1);
2211  g_free (row_text);
2212 
2213  if (scm_qiffile == wind->selected_file)
2214  {
2215  path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
2216  reference = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), path);
2217  gtk_tree_path_free(path);
2218  }
2219  loaded_file_list = SCM_CDR(loaded_file_list);
2220  }
2221 
2222  if (reference)
2223  {
2224  GtkTreeSelection* selection = gtk_tree_view_get_selection(view);
2225  path = gtk_tree_row_reference_get_path(reference);
2226  if (path)
2227  {
2228  gtk_tree_selection_select_path(selection, path);
2229  gtk_tree_path_free(path);
2230  }
2231  gtk_tree_row_reference_free(reference);
2232  }
2233 }
2234 
2235 
2236 /**********************************************
2237  * Page 6 - Account Doc. Page Procedures
2238  **********************************************/
2239 
2240 /********************************************************************
2241  * gnc_ui_qif_import_account_doc_prepare
2242  ********************************************************************/
2243 void
2244 gnc_ui_qif_import_account_doc_prepare (GtkAssistant *assistant,
2245  gpointer user_data)
2246 {
2247  QIFImportWindow * wind = user_data;
2248  gint num = gtk_assistant_get_current_page (assistant);
2249  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2250  gint total = gtk_assistant_get_n_pages (assistant);
2251  gtk_assistant_update_buttons_state (assistant);
2252 
2253  PINFO("Total Number of Assistant Pages is %d", gtk_assistant_get_n_pages (assistant));
2254 
2255  /* Enable the Assistant Forward Button */
2256  gtk_assistant_set_page_complete (assistant, page, TRUE);
2257 
2258  /* Jump to Summary page if load_stop TRUE */
2259  if (wind->load_stop)
2260  gtk_assistant_set_current_page (assistant, total - 1 );
2261 
2262  /* Jump over doc page if show_doc_pages FALSE */
2263  if (!wind->show_doc_pages)
2264  gtk_assistant_set_current_page (assistant, num + 1 );
2265 }
2266 
2267 
2268 /******************************************
2269  * Page 7 - Account Match Page Procedures
2270  ******************************************/
2271 
2272 /********************************************************************
2273  * gnc_ui_qif_import_account_match_prepare
2274  *
2275  * Get the matching pages ready for viewing.
2276  ********************************************************************/
2277 void
2278 gnc_ui_qif_import_account_match_prepare(GtkAssistant *assistant,
2279  gpointer user_data)
2280 {
2281  QIFImportWindow * wind = user_data;
2282  gint num = gtk_assistant_get_current_page (assistant);
2283  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2284 
2285  /* Prepare the matching pages. */
2286  gnc_set_busy_cursor(NULL, TRUE);
2287  update_account_page(wind);
2288  update_category_page(wind);
2289  update_memo_page(wind);
2290  gnc_unset_busy_cursor(NULL);
2291 
2292  /* Enable the Assistant Forward Button */
2293  gtk_assistant_set_page_complete (assistant, page, TRUE);
2294 }
2295 
2296 
2297 /****************************************************************
2298  * gnc_ui_qif_import_account_rematch_cb
2299  *
2300  * This handler is invoked when the user clicks the "Change
2301  * GnuCash account" button on the account mapping page. This
2302  * button is an alternative to double-clicking a row.
2303  ****************************************************************/
2304 void
2305 gnc_ui_qif_import_account_rematch_cb(GtkButton *button, gpointer user_data)
2306 {
2307  QIFImportWindow *wind = user_data;
2308 
2309  g_return_if_fail(wind);
2310 
2311  rematch_line(wind,
2312  gtk_tree_view_get_selection(GTK_TREE_VIEW(wind->acct_view)),
2313  wind->acct_display_info,
2314  wind->acct_map_info,
2315  update_account_page);
2316 }
2317 
2318 
2319 /*******************************************
2320  * Page 8 - Catagory Doc. Page Procedures
2321  *******************************************/
2322 
2323 /********************************************************************
2324  * gnc_ui_qif_import_catagory_doc_prepare
2325  ********************************************************************/
2326 void
2327 gnc_ui_qif_import_catagory_doc_prepare (GtkAssistant *assistant,
2328  gpointer user_data)
2329 {
2330  QIFImportWindow * wind = user_data;
2331  gint num = gtk_assistant_get_current_page (assistant);
2332  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2333  gint total = gtk_assistant_get_n_pages (assistant);
2334  gtk_assistant_update_buttons_state (assistant);
2335 
2336  PINFO("Total Number of Assistant Pages is %d", gtk_assistant_get_n_pages (assistant));
2337 
2338  /* Enable the Assistant Forward Button */
2339  gtk_assistant_set_page_complete (assistant, page, TRUE);
2340 
2341  /* Jump to Summary page if load_stop TRUE */
2342  if (wind->load_stop)
2343  gtk_assistant_set_current_page (assistant, total - 1 );
2344 
2345  /* Jump over doc page if show_doc_pages FALSE */
2346  if (!wind->show_doc_pages)
2347  gtk_assistant_set_current_page (assistant, num + 1 );
2348 
2349  /* If there are no category mappings, jump the doc page. */
2350  if (scm_is_list(wind->cat_display_info) && scm_is_null(wind->cat_display_info))
2351  gtk_assistant_set_current_page (assistant, num + 1);
2352 }
2353 
2354 
2355 /******************************************
2356  * Page 9 - Catagory Match Page Procedures
2357  ******************************************/
2358 
2359 /****************************************************************
2360  * gnc_ui_qif_import_catagory_match_prepare
2361  *
2362  * Find the next page to show, depending on whether there are
2363  * category or payee/memo mappings to be dealt with.
2364  ****************************************************************/
2365 void
2366 gnc_ui_qif_import_catagory_match_prepare(GtkAssistant *assistant,
2367  gpointer user_data)
2368 {
2369  QIFImportWindow * wind = user_data;
2370  gint num = gtk_assistant_get_current_page (assistant);
2371  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2372 
2373  /* Enable the Assistant Forward Button */
2374  gtk_assistant_set_page_complete (assistant, page, TRUE);
2375 
2376  /* If there are no category mappings, jump this step. */
2377  if (scm_is_list(wind->cat_display_info) && scm_is_null(wind->cat_display_info))
2378  gtk_assistant_set_current_page (assistant, num + 1);
2379 }
2380 
2381 
2382 /****************************************************************
2383  * gnc_ui_qif_import_category_rematch_cb
2384  *
2385  * This handler is invoked when the user clicks the "Change
2386  * GnuCash account" button on the category mapping page. This
2387  * button is an alternative to double-clicking a row.
2388  ****************************************************************/
2389 void
2390 gnc_ui_qif_import_category_rematch_cb(GtkButton *button, gpointer user_data)
2391 {
2392  QIFImportWindow *wind = user_data;
2393 
2394  g_return_if_fail(wind);
2395 
2396  rematch_line(wind,
2397  gtk_tree_view_get_selection(GTK_TREE_VIEW(wind->cat_view)),
2398  wind->cat_display_info,
2399  wind->cat_map_info,
2400  update_category_page);
2401 }
2402 
2403 
2404 /****************************************
2405  * Page 10 - Memo Doc. Page Procedures
2406  ****************************************/
2407 
2408 /********************************************************************
2409  * gnc_ui_qif_import_memo_doc_prepare
2410  ********************************************************************/
2411 void
2412 gnc_ui_qif_import_memo_doc_prepare (GtkAssistant *assistant,
2413  gpointer user_data)
2414 {
2415  QIFImportWindow * wind = user_data;
2416  gint num = gtk_assistant_get_current_page (assistant);
2417  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2418  gint total = gtk_assistant_get_n_pages (assistant);
2419  gtk_assistant_update_buttons_state (assistant);
2420 
2421  PINFO("Total Number of Assistant Pages is %d", gtk_assistant_get_n_pages (assistant));
2422 
2423  /* Enable the Assistant Forward Button */
2424  gtk_assistant_set_page_complete (assistant, page, TRUE);
2425 
2426  /* Jump to Summary page if load_stop TRUE */
2427  if (wind->load_stop)
2428  gtk_assistant_set_current_page (assistant, total - 1 );
2429 
2430  /* Jump over doc page if show_doc_pages FALSE */
2431  if (!wind->show_doc_pages)
2432  gtk_assistant_set_current_page (assistant, num + 1 );
2433 
2434  /* If there are no memo mappings, jump the doc page. */
2435  if (scm_is_list(wind->memo_display_info) && scm_is_null(wind->memo_display_info))
2436  gtk_assistant_set_current_page (assistant, num + 1);
2437 }
2438 
2439 
2440 /****************************************
2441  * Page 11 - Memo Match Page Procedures
2442  ****************************************/
2443 
2444 /****************************************************************
2445  * gnc_ui_qif_import_memo_match_prepare
2446  *
2447  * Find the next page to show, depending on whether there are
2448  * category or payee/memo mappings to be dealt with.
2449  ****************************************************************/
2450 void
2451 gnc_ui_qif_import_memo_match_prepare (GtkAssistant *assistant,
2452  gpointer user_data)
2453 {
2454  QIFImportWindow * wind = user_data;
2455  gint num = gtk_assistant_get_current_page (assistant);
2456  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2457 
2458  /* Enable the Assistant Forward Button */
2459  gtk_assistant_set_page_complete (assistant, page, TRUE);
2460 
2461  /* If there are no memo mappings, jump this step. */
2462  if (scm_is_list(wind->memo_display_info) && scm_is_null(wind->memo_display_info))
2463  gtk_assistant_set_current_page (assistant, num + 1);
2464 }
2465 
2466 
2467 /****************************************************************
2468  * gnc_ui_qif_import_memo_rematch_cb
2469  *
2470  * This handler is invoked when the user clicks the "Change
2471  * GnuCash account" button on the memo mapping page. This
2472  * button is an alternative to double-clicking a row.
2473  ****************************************************************/
2474 void
2475 gnc_ui_qif_import_memo_rematch_cb(GtkButton *button, gpointer user_data)
2476 {
2477  QIFImportWindow *wind = user_data;
2478 
2479  g_return_if_fail(wind);
2480 
2481  rematch_line(wind,
2482  gtk_tree_view_get_selection(GTK_TREE_VIEW(wind->memo_view)),
2483  wind->memo_display_info,
2484  wind->memo_map_info,
2485  update_memo_page);
2486 }
2487 
2488 
2489 /*****************************************
2490  * Page 12 - Currency Page Procedures
2491  ****************************************/
2492 
2493 /****************************************************************
2494  * gnc_ui_qif_import_currency_prepare
2495  *
2496  * Find the next page to show, depending on whether there are
2497  * category or payee/memo mappings to be dealt with.
2498  ****************************************************************/
2499 void
2500 gnc_ui_qif_import_currency_prepare(GtkAssistant *assistant,
2501  gpointer user_data)
2502 {
2503  gint num = gtk_assistant_get_current_page (assistant);
2504  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2505  QIFImportWindow *wind = user_data;
2506 
2507  g_return_if_fail(wind);
2508 
2509  /* Only display Book Option data if new book */
2510  if (wind->new_book)
2511  {
2512  gtk_assistant_set_page_title (assistant, page,
2513  _("Choose the QIF file currency and select Book Options"));
2514  gtk_widget_show (wind->book_option_label);
2515  gtk_widget_show (wind->book_option_message);
2516  }
2517  else
2518  {
2519  gtk_assistant_set_page_title (assistant, page,
2520  _("Choose the QIF file currency"));
2521  gtk_widget_hide (wind->book_option_label);
2522  gtk_widget_hide (wind->book_option_message);
2523  }
2524 
2525  /* Enable the Assistant Forward Button */
2526  gtk_assistant_set_page_complete (assistant, page, TRUE);
2527 }
2528 
2529 
2530 /**************************************************
2531  * Page 13 - Commodity Doc. Page Procedures
2532  **************************************************/
2533 
2534 /****************************************************************
2535  * gnc_ui_qif_import_new_securities
2536  *
2537  * This function creates or updates the list of QIF securities
2538  * for which no corresponding GnuCash commodity existed prior to
2539  * import. If there are any such securities, TRUE is returned.
2540  * Otherwise, FALSE is returned.
2541  ****************************************************************/
2542 static gboolean
2543 gnc_ui_qif_import_new_securities(QIFImportWindow * wind)
2544 {
2545  SCM updates;
2546  SCM update_securities = scm_c_eval_string("qif-import:update-security-hash");
2547 
2548  /* Get a list of any new QIF securities since the previous call. */
2549  updates = scm_call_4(update_securities,
2550  wind->security_hash,
2551  wind->ticker_map,
2552  wind->acct_map_info,
2553  wind->security_prefs);
2554  if (updates != SCM_BOOL_F)
2555  {
2556  /* A list of new QIF securities was returned. Save it. */
2557  scm_gc_unprotect_object(wind->new_securities);
2558  if (wind->new_securities != SCM_BOOL_F)
2559  /* There is an existing list, so append the new list. */
2560  wind->new_securities = scm_append(scm_list_2(wind->new_securities,
2561  updates));
2562  else
2563  wind->new_securities = updates;
2564  scm_gc_protect_object(wind->new_securities);
2565 
2566  return TRUE;
2567  }
2568 
2569  if (wind->new_securities != SCM_BOOL_F)
2570  return TRUE;
2571 
2572  return FALSE;
2573 }
2574 
2575 
2576 /********************************************************************
2577  * gnc_ui_qif_import_commodity_doc_prepare
2578  ********************************************************************/
2579 void
2580 gnc_ui_qif_import_commodity_doc_prepare (GtkAssistant *assistant,
2581  gpointer user_data)
2582 {
2583  QIFImportWindow * wind = user_data;
2584  gint num = gtk_assistant_get_current_page (assistant);
2585  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2586  gint total = gtk_assistant_get_n_pages (assistant);
2587  gtk_assistant_update_buttons_state (assistant);
2588 
2589  PINFO("Total Number of Assistant Pages is %d", gtk_assistant_get_n_pages (assistant));
2590 
2591  /* Enable the Assistant Forward Button */
2592  gtk_assistant_set_page_complete (assistant, page, TRUE);
2593 
2594  /* Jump to Summary page if load_stop TRUE */
2595  if (wind->load_stop)
2596  gtk_assistant_set_current_page (assistant, total - 1 );
2597 
2598  /* If there are new securities, prepare the security pages. */
2599  if (gnc_ui_qif_import_new_securities(wind))
2600  prepare_security_pages(wind);
2601  else
2602  /* If there are no securities, jump the doc page */
2603  gtk_assistant_set_current_page (assistant, num + 1 );
2604 
2605  /* Jump over doc page if show_doc_pages FALSE */
2606  if (!wind->show_doc_pages)
2607  gtk_assistant_set_current_page (assistant, num + 1 );
2608 }
2609 
2610 
2611 /********************************************
2612  * Page xx - Commodity New Pages Procedures
2613  ********************************************/
2614 
2615 /********************************************
2616  * gnc_ui_qif_import_commodity_new_prepare
2617  *******************************************/
2618 void
2619 gnc_ui_qif_import_commodity_new_prepare (GtkAssistant *assistant,
2620  gpointer user_data)
2621 {
2622  gint num = gtk_assistant_get_current_page (assistant);
2623  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2624 
2625  QIFAssistantPage *qpage = g_object_get_data(G_OBJECT(page), "page_struct");
2626  const gchar *ns;
2627 
2628  g_return_if_fail (qpage != NULL);
2629 
2630  /* Get any entered namespace. */
2631  ns = gtk_entry_get_text( GTK_ENTRY( gtk_bin_get_child( GTK_BIN( GTK_COMBO_BOX(qpage->namespace_combo)))));
2632 
2633  /* Update the namespaces available to select. */
2634  if (!ns || !ns[0])
2636  qpage->namespace_combo,
2637  gnc_commodity_get_namespace(qpage->commodity),
2638  DIAG_COMM_ALL);
2639  else
2640  gnc_ui_update_namespace_picker(qpage->namespace_combo, ns, DIAG_COMM_ALL);
2641 }
2642 
2643 
2644 /*********************************
2645  * gnc_ui_qif_import_comm_valid
2646  ********************************/
2647 static gboolean
2648 gnc_ui_qif_import_comm_valid (GtkAssistant *assistant,
2649  gpointer user_data)
2650 {
2651  QIFImportWindow *wind = user_data;
2652  gint num = gtk_assistant_get_current_page (GTK_ASSISTANT(wind->window));
2653  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2654  QIFAssistantPage *qpage = g_object_get_data(G_OBJECT(page), "page_struct");
2655 
2656  QofBook *book;
2657  gnc_commodity_table *table;
2658  gnc_commodity_namespace *newns;
2659 
2660  gchar *name_space = gnc_ui_namespace_picker_ns(qpage->namespace_combo);
2661  const gchar *name = gtk_entry_get_text(GTK_ENTRY(qpage->name_entry));
2662  const gchar *mnemonic = gtk_entry_get_text(GTK_ENTRY(qpage->mnemonic_entry));
2663 
2664  if (!name || (name[0] == 0))
2665  {
2666  gnc_warning_dialog(wind->window, "%s",
2667  _("Enter a name or short description, such as \"Red Hat Stock\"."));
2668  g_free(name_space);
2669  return FALSE;
2670  }
2671  else if (!mnemonic || (mnemonic[0] == 0))
2672  {
2673  gnc_warning_dialog(wind->window, "%s",
2674  _("Enter the ticker symbol or other well known abbreviation, such as"
2675  " \"RHT\". If there isn't one, or you don't know it, create your own."));
2676  g_free(name_space);
2677  return FALSE;
2678  }
2679  else if (!name_space || (name_space[0] == 0))
2680  {
2681  gnc_warning_dialog(wind->window, "%s",
2682  _("Select the exchange on which the symbol is traded, or select the"
2683  " type of investment (such as FUND for mutual funds.) If you don't"
2684  " see your exchange or an appropriate investment type, you can"
2685  " enter a new one."));
2686  if (name_space)
2687  g_free(name_space);
2688  return FALSE;
2689  }
2690 
2691  /* FIXME: Should check whether a commodity with this namespace and
2692  * mnemonic already exists. If so, ask the user whether to use
2693  * the existing one, or go back and change what they've entered.
2694  */
2695 
2696  book = gnc_get_current_book();
2697  table = gnc_commodity_table_get_table(book);
2698  if (gnc_commodity_namespace_is_iso(name_space) &&
2699  !gnc_commodity_table_lookup(table, name_space, mnemonic))
2700  {
2701  gnc_warning_dialog(wind->window, "%s",
2702  _("You must enter an existing national "
2703  "currency or enter a different type."));
2704 
2705  g_free(name_space);
2706  return FALSE;
2707  }
2708 
2709  /* Is the namespace a new one? */
2710  if (!gnc_commodity_table_has_namespace(table, name_space))
2711  {
2712  /* Register it so that it will appear as an option on other pages. */
2713  newns = gnc_commodity_table_add_namespace(table, name_space, book);
2714 
2715  /* Remember it so it can be removed if the import gets canceled. */
2716  if (newns)
2717  wind->new_namespaces = g_list_prepend(wind->new_namespaces, name_space);
2718  else
2719  {
2720  g_warning("QIF import: Couldn't create namespace %s", name_space);
2721  g_free(name_space);
2722  }
2723  }
2724  else
2725  g_free(name_space);
2726 
2727  return TRUE;
2728 }
2729 
2730 
2731 /*************************************
2732  * gnc_ui_qif_import_comm_changed_cb
2733  ************************************/
2734 void
2735 gnc_ui_qif_import_comm_changed_cb (GtkWidget *widget, gpointer user_data)
2736 {
2737  QIFImportWindow *wind = user_data;
2738  GtkAssistant *assistant = GTK_ASSISTANT(wind->window);
2739  gint num = gtk_assistant_get_current_page (assistant);
2740  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2741 
2742  gtk_assistant_set_page_complete (assistant, page, gnc_ui_qif_import_comm_valid (assistant, user_data));
2743 }
2744 
2745 
2746 /**********************************************
2747  * Page 14 - Convert progress Page Procedures
2748  *********************************************/
2749 
2750 /********************************************************************
2751  * gnc_ui_qif_import_convert_progress_pause_cb
2752  *
2753  * Invoked when the "Pause" button is clicked.
2754  ********************************************************************/
2755 void
2756 gnc_ui_qif_import_convert_progress_pause_cb(GtkButton * button,
2757  gpointer user_data)
2758 {
2759  QIFImportWindow *wind = user_data;
2760  SCM toggle_pause = scm_c_eval_string("qif-import:toggle-pause");
2761  SCM progress;
2762 
2763  if (!wind->busy)
2764  return;
2765 
2766  /* Create SCM for the progress helper. */
2767  progress = SWIG_NewPointerObj(wind->convert_progress,
2768  SWIG_TypeQuery("_p__GNCProgressDialog"),
2769  0);
2770 
2771  /* Pause (or resume) the currently running operation. */
2772  scm_call_1(toggle_pause, progress);
2773 
2774  /* Swap the button label between pause and resume. */
2775  if (strcmp(gtk_button_get_label(button), _("_Resume")))
2776  {
2777  gtk_button_set_use_stock(button, FALSE);
2778  gtk_button_set_use_underline(button, TRUE);
2779  gtk_button_set_label(button, _("_Resume"));
2780  }
2781  else
2782  {
2783  gtk_button_set_use_stock(button, TRUE);
2784  gtk_button_set_use_underline(button, FALSE);
2785  gtk_button_set_label(button, "gtk-media-pause");
2786  }
2787 }
2788 
2789 
2790 /********************************************************************
2791  * gnc_ui_qif_import_convert_progress_start_cb
2792  *
2793  * Invoked when the "Start" button is clicked.
2794  ********************************************************************/
2795 void
2796 gnc_ui_qif_import_convert_progress_start_cb(GtkButton * button,
2797  gpointer user_data)
2798 {
2799  QIFImportWindow *wind = user_data;
2800  gint num = gtk_assistant_get_current_page (GTK_ASSISTANT(wind->window));
2801  GtkWidget *page = gtk_assistant_get_nth_page (GTK_ASSISTANT(wind->window), num);
2802 
2803  SCM qif_to_gnc = scm_c_eval_string("qif-import:qif-to-gnc");
2804  SCM find_duplicates = scm_c_eval_string("gnc:account-tree-find-duplicates");
2805  SCM retval;
2806 
2807  /* SCM for the progress dialog. */
2808  SCM progress = SWIG_NewPointerObj(wind->convert_progress,
2809  SWIG_TypeQuery("_p__GNCProgressDialog"),
2810  0);
2811 
2812  /* The default currency. */
2813  const gchar *currname = gtk_entry_get_text( GTK_ENTRY( gtk_bin_get_child( GTK_BIN( GTK_COMBO_BOX(wind->currency_picker)))));
2814 
2815  /* Raise the busy flag so the assistant can't be canceled unexpectedly. */
2816  wind->busy = TRUE;
2817  gtk_widget_set_sensitive(wind->convert_pause, TRUE);
2818  gtk_widget_set_sensitive(wind->convert_start, FALSE);
2819 
2820  /* Clear any previous pause or cancel state. */
2821  scm_c_eval_string("(qif-import:reset-cancel-pause)");
2822 
2823  /* Update the commodities. */
2824  gnc_ui_qif_import_commodity_update(wind);
2825 
2826  /*
2827  * Convert the QIF data into GnuCash data.
2828  *
2829  * A Scheme function does all the work. The return value is the
2830  * root account of an account tree containing all the new accounts
2831  * and transactions. Upon failure, #f is returned. If the user
2832  * cancels, #t is returned.
2833  */
2834 
2835  /* This step will fill 70% of the bar. */
2836  gnc_progress_dialog_push(wind->convert_progress, 0.7);
2837  retval = scm_apply(qif_to_gnc,
2838  SCM_LIST8(wind->imported_files,
2839  wind->acct_map_info,
2840  wind->cat_map_info,
2841  wind->memo_map_info,
2842  wind->security_hash,
2843  scm_from_utf8_string(currname ? currname : ""),
2844  wind->transaction_status,
2845  progress),
2846  SCM_EOL);
2847  gnc_progress_dialog_pop(wind->convert_progress);
2848 
2849  if (retval == SCM_BOOL_T)
2850  {
2851  /* Canceled by the user. */
2852 
2853  /* Disable the pause button. */
2854  gtk_widget_set_sensitive(wind->convert_pause, FALSE);
2855 
2856  /* Remove any converted data. */
2857  gnc_progress_dialog_set_sub(wind->convert_progress, _("Cleaning up"));
2858  gnc_ui_qif_import_convert_undo(wind);
2859 
2860  /* Inform the user. */
2861  gnc_progress_dialog_set_sub(wind->convert_progress, _("Canceled"));
2862  gnc_progress_dialog_reset_value(wind->convert_progress);
2863 
2864  wind->busy = FALSE;
2865  wind->load_stop = TRUE;
2866  }
2867  else if (retval == SCM_BOOL_F)
2868  {
2869  /* An bug was encountered during conversion. */
2870 
2871  /* Disable the pause button. */
2872  gtk_widget_set_sensitive(wind->convert_pause, FALSE);
2873 
2874  /* Remove any converted data. */
2875  gnc_progress_dialog_set_sub(wind->convert_progress, _("Cleaning up"));
2876  gnc_ui_qif_import_convert_undo(wind);
2877 
2878  /* Inform the user. */
2879  gnc_progress_dialog_append_log(wind->convert_progress,
2880  _( "A bug was detected while converting the QIF data."));
2881  gnc_progress_dialog_set_sub(wind->convert_progress, _("Failed"));
2882  gnc_progress_dialog_reset_value(wind->convert_progress);
2883  gnc_error_dialog(wind->window, "%s",
2884  _( "A bug was detected while converting the QIF data."));
2885  /* FIXME: How should we request that the user report this problem? */
2886 
2887  wind->busy = FALSE;
2888  wind->load_stop = TRUE;
2889  }
2890  else if (scm_is_symbol(retval))
2891  {
2892  /* An error was encountered during conversion. */
2893 
2894  /* Disable the pause button. */
2895  gtk_widget_set_sensitive(wind->convert_pause, FALSE);
2896 
2897  /* Remove any converted data. */
2898  gnc_progress_dialog_set_sub(wind->convert_progress, _("Cleaning up"));
2899  gnc_ui_qif_import_convert_undo(wind);
2900 
2901  /* Inform the user. */
2902  gnc_progress_dialog_set_sub(wind->convert_progress, _("Failed"));
2903  gnc_progress_dialog_reset_value(wind->convert_progress);
2904 
2905  wind->busy = FALSE;
2906  wind->load_stop = TRUE;
2907  }
2908 
2909  /* Save the imported account tree. */
2910  scm_gc_unprotect_object(wind->imported_account_tree);
2911  wind->imported_account_tree = retval;
2912  scm_gc_protect_object(wind->imported_account_tree);
2913 
2914  /*
2915  * Detect potentially duplicated transactions.
2916  */
2917 
2918  /* This step will fill the remainder of the bar. */
2919  gnc_progress_dialog_push(wind->convert_progress, 1);
2920  retval = scm_call_3(find_duplicates,
2921  scm_c_eval_string("(gnc-get-current-root-account)"),
2922  wind->imported_account_tree, progress);
2923  gnc_progress_dialog_pop(wind->convert_progress);
2924 
2925  /* Save the results. */
2926  scm_gc_unprotect_object(wind->match_transactions);
2927  wind->match_transactions = retval;
2928  scm_gc_protect_object(wind->match_transactions);
2929 
2930  if (retval == SCM_BOOL_T)
2931  {
2932  /* Canceled by the user. */
2933  gtk_widget_set_sensitive(wind->convert_pause, FALSE);
2934  gnc_progress_dialog_set_sub(wind->convert_progress, _("Canceling"));
2935  wind->busy = FALSE;
2936  wind->load_stop = TRUE;
2937  }
2938  else if (retval == SCM_BOOL_F)
2939  {
2940  /* An error occurred during duplicate checking. */
2941 
2942  /* Remove any converted data. */
2943  gnc_progress_dialog_set_sub(wind->convert_progress, _("Cleaning up"));
2944  gnc_ui_qif_import_convert_undo(wind);
2945 
2946  /* Inform the user. */
2947  gnc_progress_dialog_append_log(wind->convert_progress,
2948  _( "A bug was detected while detecting duplicates."));
2949  gnc_progress_dialog_set_sub(wind->convert_progress, _("Failed"));
2950  gnc_progress_dialog_reset_value(wind->convert_progress);
2951  gnc_error_dialog(wind->window, "%s",
2952  _( "A bug was detected while detecting duplicates."));
2953  /* FIXME: How should we request that the user report this problem? */
2954 
2955  gtk_widget_set_sensitive(wind->convert_pause, FALSE);
2956  wind->busy = FALSE;
2957  wind->load_stop = TRUE;
2958  }
2959 
2960  /* Enable the Assistant Forward Button */
2961  gtk_assistant_set_page_complete (GTK_ASSISTANT(wind->window), page, TRUE);
2962 
2963  /* Set Pause and Start buttons */
2964  gtk_widget_set_sensitive(wind->convert_pause, FALSE);
2965  gtk_widget_set_sensitive(wind->convert_start, FALSE);
2966 
2967  if (wind->load_stop == FALSE)
2968  {
2969  /* The conversion completed successfully. */
2970  gnc_progress_dialog_set_sub(wind->convert_progress,
2971  _("Conversion completed"));
2972  gnc_progress_dialog_set_value(wind->convert_progress, 1);
2973 
2974  gtk_widget_set_sensitive(wind->convert_pause, FALSE);
2975  wind->busy = FALSE;
2976 
2977  /* If the log is empty, move on to the next page automatically. */
2978  if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(wind->convert_log))) == 0)
2979  gtk_assistant_set_current_page (GTK_ASSISTANT(wind->window), num + 1);
2980  }
2981 }
2982 
2983 
2984 /********************************************************************
2985  * gnc_ui_qif_import_convert_progress_prepare
2986  *
2987  * Prepare the data conversion progress page for display.
2988  ********************************************************************/
2989 void
2990 gnc_ui_qif_import_convert_progress_prepare(GtkAssistant *assistant,
2991  gpointer user_data)
2992 {
2993  QIFImportWindow *wind = user_data;
2994  gint num = gtk_assistant_get_current_page (assistant);
2995  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2996 
2997  /* Recompute assistant Buttons */
2998  gtk_assistant_update_buttons_state( assistant );
2999 
3000  /* Reset the progress display. */
3001  gnc_progress_dialog_set_primary(wind->convert_progress, "");
3002  gnc_progress_dialog_set_secondary(wind->convert_progress,
3003  _("When you press the Start Button, GnuCash will import your QIF data. If there are no errors or warnings, you will automatically proceed to the next step. Otherwise, the details will be shown below for your review."));
3004  gnc_progress_dialog_set_sub(wind->convert_progress, " ");
3005  gnc_progress_dialog_reset_value(wind->convert_progress);
3006  gnc_progress_dialog_reset_log(wind->convert_progress);
3007 
3008  /* Set Pause and Start buttons */
3009  gtk_widget_set_sensitive(wind->convert_pause, FALSE);
3010  gtk_widget_set_sensitive(wind->convert_start, TRUE);
3011 
3012  /* Disable the assistant Forward button */
3013  gtk_assistant_set_page_complete (assistant, page, FALSE);
3014 
3015  /* Before creating transactions, if this is a new book, let user specify
3016  * book options, since they affect how transactions are created */
3017  if (wind->new_book)
3018  wind->new_book = gnc_new_book_option_display(wind->window);
3019 }
3020 
3021 
3022 /*****************************************
3023  * Page 15 - Match Doc. Page Procedures
3024  *****************************************/
3025 
3026 /********************************************************************
3027  * gnc_ui_qif_import_duplicates_doc_prepare
3028  ********************************************************************/
3029 void
3030 gnc_ui_qif_import_duplicates_doc_prepare (GtkAssistant *assistant,
3031  gpointer user_data)
3032 {
3033  QIFImportWindow * wind = user_data;
3034  gint num = gtk_assistant_get_current_page (assistant);
3035  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
3036  gint total = gtk_assistant_get_n_pages (assistant);
3037  gtk_assistant_update_buttons_state (assistant);
3038 
3039  PINFO("Total Number of Assistant Pages is %d", gtk_assistant_get_n_pages (assistant));
3040 
3041  /* Enable the Assistant Forward Button */
3042  gtk_assistant_set_page_complete (assistant, page, TRUE);
3043 
3044  /* Jump to Summary page if load_stop TRUE */
3045  if (wind->load_stop)
3046  gtk_assistant_set_current_page (assistant, total - 1 );
3047 
3048  /* Jump over doc page if show_doc_pages FALSE */
3049  if (!wind->show_doc_pages)
3050  gtk_assistant_set_current_page (assistant, num + 1 );
3051 
3052  /* Don't show doc page if there are no duplicates */
3053  if (scm_is_null(wind->match_transactions))
3054  gtk_assistant_set_current_page (assistant, num + 1 );
3055 }
3056 
3057 
3058 /**********************************************
3059  * Page 16 - Match Duplicates Page Procedures
3060  **********************************************/
3061 
3062 /********************************************************************
3063  * gnc_ui_qif_import_duplicates_match_prepare
3064  ********************************************************************/
3065 void
3066 gnc_ui_qif_import_duplicates_match_prepare (GtkAssistant *assistant,
3067  gpointer user_data)
3068 {
3069  QIFImportWindow * wind = user_data;
3070  gint num = gtk_assistant_get_current_page (assistant);
3071  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
3072 
3073  GtkTreeView *view;
3074  GtkListStore *store;
3075  SCM duplicates;
3076  SCM current_xtn;
3077  Transaction *gnc_xtn;
3078  Split *gnc_split;
3079  GtkTreeIter iter;
3080  GtkTreeSelection *selection;
3081  GtkTreePath *path;
3082  const gchar *amount_str;
3083  int rownum = 0;
3084 
3085  if (!scm_is_null(wind->match_transactions))
3086  {
3087  view = GTK_TREE_VIEW(wind->new_transaction_view);
3088  store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
3089  gtk_list_store_clear(store);
3090 
3091  if (!scm_is_list(wind->match_transactions))
3092  return;
3093 
3094  /* Loop through the list of new, potentially duplicate transactions. */
3095  duplicates = wind->match_transactions;
3096  while (!scm_is_null(duplicates))
3097  {
3098  current_xtn = SCM_CAAR(duplicates);
3099 #define FUNC_NAME "xaccTransCountSplits"
3100  gnc_xtn = SWIG_MustGetPtr(current_xtn,
3101  SWIG_TypeQuery("_p_Transaction"), 1, 0);
3102 #undef FUNC_NAME
3103  if (xaccTransCountSplits(gnc_xtn) > 2)
3104  amount_str = _("(split)");
3105  else
3106  {
3107  gnc_split = xaccTransGetSplit(gnc_xtn, 0);
3108  amount_str =
3109  xaccPrintAmount(gnc_numeric_abs(xaccSplitGetValue(gnc_split)),
3110  gnc_account_print_info
3111  (xaccSplitGetAccount(gnc_split), TRUE));
3112  }
3113  gtk_list_store_append(store, &iter);
3114  gtk_list_store_set
3115  (store, &iter,
3116  QIF_TRANS_COL_INDEX, rownum++,
3117  QIF_TRANS_COL_DATE,
3119  QIF_TRANS_COL_DESCRIPTION, xaccTransGetDescription(gnc_xtn),
3120  QIF_TRANS_COL_AMOUNT, amount_str,
3121  -1);
3122 
3123  duplicates = SCM_CDR(duplicates);
3124  }
3125  selection = gtk_tree_view_get_selection(view);
3126  path = gtk_tree_path_new_from_indices(0, -1);
3127  gtk_tree_selection_select_path(selection, path);
3128  gtk_tree_path_free(path);
3129  }
3130  else
3131  gtk_assistant_set_current_page (assistant, num + 1 );
3132 
3133  /* Enable the Assistant Forward Button */
3134  gtk_assistant_set_page_complete (assistant, page, TRUE);
3135 }
3136 
3137 
3138 /*************************************
3139  * Page 17 - Apply Page Procedures
3140  *************************************/
3141 
3142 /********************************************************************
3143  * gnc_ui_qif_import_end_page_prepare
3144  ********************************************************************/
3145 void
3146 gnc_ui_qif_import_end_page_prepare (GtkAssistant *assistant,
3147  gpointer user_data)
3148 {
3149  gint num = gtk_assistant_get_current_page (assistant);
3150  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
3151 
3152  /* Enable the Assistant Forward Button */
3153  gtk_assistant_set_page_complete (assistant, page, TRUE);
3154 }
3155 
3156 
3157 /********************************************************************
3158  * gnc_ui_qif_import_finish_cb
3159  *
3160  * Invoked when the "Apply" button is clicked on the final page.
3161  ********************************************************************/
3162 void
3163 gnc_ui_qif_import_finish_cb (GtkAssistant *gtkassistant,
3164  gpointer user_data)
3165 {
3166  QIFImportWindow * wind = user_data;
3167 
3168  SCM save_map_prefs = scm_c_eval_string("qif-import:save-map-prefs");
3169  SCM cat_and_merge = scm_c_eval_string("gnc:account-tree-catenate-and-merge");
3170  SCM prune_xtns = scm_c_eval_string("gnc:prune-matching-transactions");
3171  SCM scm_result;
3172 
3173  GncPluginPage *page;
3174  gboolean acct_tree_found = FALSE;
3175 
3176  gnc_suspend_gui_refresh();
3177 
3178  /* Prune any imported transactions that were determined to be duplicates. */
3179  if (wind->match_transactions != SCM_BOOL_F)
3180  scm_call_1(prune_xtns, wind->match_transactions);
3181 
3182  /* Merge the imported account tree with the existing one. */
3183  if (wind->imported_account_tree != SCM_BOOL_F)
3184  scm_call_2(cat_and_merge,
3185  scm_c_eval_string("(gnc-get-current-root-account)"),
3186  wind->imported_account_tree);
3187 
3188  gnc_resume_gui_refresh();
3189 
3190  /* Save the user's mapping preferences. */
3191  scm_result = scm_apply(save_map_prefs,
3192  SCM_LIST5(wind->acct_map_info, wind->cat_map_info,
3193  wind->memo_map_info, wind->security_hash,
3194  wind->security_prefs),
3195  SCM_EOL);
3196 
3197  if (scm_result == SCM_BOOL_F)
3198  gnc_warning_dialog(wind->window, "%s",
3199  _("GnuCash was unable to save your mapping preferences."));
3200 
3201  /* Open an account tab in the main window if one doesn't exist already. */
3202  gnc_main_window_foreach_page(gnc_ui_qif_import_check_acct_tree,
3203  &acct_tree_found);
3204 
3205  wind->acct_tree_found = acct_tree_found;
3206  if (!acct_tree_found)
3207  {
3209  gnc_main_window_open_page(NULL, page);
3210  }
3211 }
3212 
3213 
3214 /***************************************
3215  * Page 18 - Summary Page Procedures
3216  ***************************************/
3217 
3218 /********************************************************************
3219  * gnc_ui_qif_import_summary_page_prepare
3220  ********************************************************************/
3221 void
3222 gnc_ui_qif_import_summary_page_prepare (GtkAssistant *assistant,
3223  gpointer user_data)
3224 {
3225  QIFImportWindow * wind = user_data;
3226  gint num = gtk_assistant_get_current_page (assistant);
3227  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
3228 
3229  gchar *text;
3230 
3231  if (wind->load_stop)
3232  text = g_strdup_printf(_("There was a problem with the import."));
3233  else
3234  text = g_strdup_printf(_("QIF Import Completed."));
3235 
3236  gtk_label_set_markup(GTK_LABEL(wind->summary_text), g_strdup_printf("<span size=\"large\"><b>%s</b></span>", text));
3237 
3238  g_free(text);
3239 
3240  /* Enable the Assistant Forward Button */
3241  gtk_assistant_set_page_complete (assistant, page, TRUE);
3242 }
3243 
3244 
3245 /********************************************************************
3246  * Prepare callback for assistant pages.
3247  ********************************************************************/
3248 void gnc_ui_qif_import_prepare_cb (GtkAssistant *assistant, GtkWidget *page,
3249  gpointer user_data)
3250 {
3251  gint currentpage = gtk_assistant_get_current_page(assistant);
3252  GtkWidget *mypage = gtk_assistant_get_nth_page (assistant, currentpage);
3253  const char *pagename = gtk_buildable_get_name(GTK_BUILDABLE(mypage));
3254 
3255  PINFO("Builder Page Name is %s", gtk_buildable_get_name(GTK_BUILDABLE(mypage)));
3256 
3257  if (!g_strcmp0 (pagename, "start_page"))
3258  {
3259  /* Current page is Intro page */
3260  gnc_ui_qif_import_intro_prepare (assistant, user_data);
3261  }
3262  else if (!g_strcmp0 (pagename, "load_file_page"))
3263  {
3264  /* Current page is File Load */
3265  gnc_ui_qif_import_load_file_prepare (assistant, user_data);
3266  }
3267  else if (!g_strcmp0 (pagename, "load_progress_page"))
3268  {
3269  /* Current page is Load Progress */
3270  gnc_ui_qif_import_load_progress_prepare (assistant, user_data);
3271  }
3272  else if (!g_strcmp0 (pagename, "date_format_page"))
3273  {
3274  /* Current page is date page */
3275  gnc_ui_qif_import_date_format_prepare (assistant, user_data);
3276  }
3277  else if (!g_strcmp0 (pagename, "account_name_page"))
3278  {
3279  /* Current page is account page */
3280  gnc_ui_qif_import_account_prepare (assistant, user_data);
3281  }
3282  else if (!g_strcmp0 (pagename, "loaded_files_page"))
3283  {
3284  /* Current page is loaded files page */
3285  gnc_ui_qif_import_loaded_files_prepare (assistant, user_data);
3286  }
3287  else if (!g_strcmp0 (pagename, "account_doc_page"))
3288  {
3289  /* Current page is Account Doc. page */
3290  gnc_ui_qif_import_account_doc_prepare (assistant, user_data);
3291  }
3292  else if (!g_strcmp0 (pagename, "account_match_page"))
3293  {
3294  /* Current page is Account Match page */
3295  gnc_ui_qif_import_account_match_prepare (assistant, user_data);
3296  }
3297  else if (!g_strcmp0 (pagename, "category_doc_page"))
3298  {
3299  /* Current page is Catagory Doc. page */
3300  gnc_ui_qif_import_catagory_doc_prepare (assistant, user_data);
3301  }
3302  else if (!g_strcmp0 (pagename, "category_match_page"))
3303  {
3304  /* Current page is Catagory Match page */
3305  gnc_ui_qif_import_catagory_match_prepare (assistant, user_data);
3306  }
3307  else if (!g_strcmp0 (pagename, "memo_doc_page"))
3308  {
3309  /* Current page is Memo Doc. page */
3310  gnc_ui_qif_import_memo_doc_prepare (assistant, user_data);
3311  }
3312  else if (!g_strcmp0 (pagename, "memo_match_page"))
3313  {
3314  /* Current page is Memo Match page */
3315  gnc_ui_qif_import_memo_match_prepare (assistant, user_data);
3316  }
3317  else if (!g_strcmp0 (pagename, "currency_book_option_page"))
3318  {
3319  /* Current page is Currency page */
3320  gnc_ui_qif_import_currency_prepare (assistant, user_data);
3321  }
3322  else if (!g_strcmp0 (pagename, "commodity_doc_page"))
3323  {
3324  /* Current page is Commodity Doc. page */
3325  gnc_ui_qif_import_commodity_doc_prepare (assistant, user_data);
3326  }
3327  else if (!g_strcmp0 (pagename, "commodity_page"))
3328  {
3329  /* Current page is Commodity page */
3330  /* gnc_ui_qif_import_commodity_prepare (assistant, user_data); */
3331  }
3332  else if (!g_strcmp0 (pagename, "convert_progress_page"))
3333  {
3334  /* Current page is Conversion progress page */
3335  gnc_ui_qif_import_convert_progress_prepare (assistant, user_data);
3336  }
3337  else if (!g_strcmp0 (pagename, "duplicates_doc_page"))
3338  {
3339  /* Current page is Duplicates Doc page */
3340  gnc_ui_qif_import_duplicates_doc_prepare (assistant, user_data);
3341  }
3342  else if (!g_strcmp0 (pagename, "duplicates_match_page"))
3343  {
3344  /* Current page is Duplicates Match page */
3345  gnc_ui_qif_import_duplicates_match_prepare (assistant, user_data);
3346  }
3347  else if (!g_strcmp0 (pagename, "end_page"))
3348  {
3349  /* Current page is the end page */
3350  gnc_ui_qif_import_end_page_prepare (assistant, user_data);
3351  }
3352  else if (!g_strcmp0 (pagename, "summary_page"))
3353  {
3354  /* Current page is the summary page */
3355  gnc_ui_qif_import_summary_page_prepare (assistant, user_data);
3356  }
3357  else
3358  {
3359  /* Current page is a new commodity page */
3360  gnc_ui_qif_import_commodity_new_prepare (assistant, user_data);
3361  }
3362 }
3363 
3364 
3365 /********************************************************************
3366  * get_assistant_widgets
3367  *
3368  * Get all builder-defined widgets that need to be actively managed.
3369  ********************************************************************/
3370 static void
3371 get_assistant_widgets(QIFImportWindow *wind, GtkBuilder *builder)
3372 {
3373  g_return_if_fail(wind);
3374  g_return_if_fail(builder);
3375 
3376  wind->window = GTK_WIDGET(gtk_builder_get_object (builder, "QIF Import Assistant"));
3377  wind->filename_entry = GTK_WIDGET(gtk_builder_get_object (builder, "qif_filename_entry"));
3378  wind->load_pause = GTK_WIDGET(gtk_builder_get_object (builder, "load_progress_pause"));
3379  wind->load_start = GTK_WIDGET(gtk_builder_get_object (builder, "load_progress_start"));
3380  wind->load_log = GTK_WIDGET(gtk_builder_get_object (builder, "load_progress_log"));
3381  wind->load_progress = gnc_progress_dialog_custom(
3382  GTK_LABEL(gtk_builder_get_object (builder, "load_progress_primary")),
3383  GTK_LABEL(gtk_builder_get_object (builder, "load_progress_secondary")),
3384  GTK_PROGRESS_BAR(gtk_builder_get_object (builder, "load_progress_bar")),
3385  GTK_LABEL(gtk_builder_get_object (builder, "load_progress_sub")),
3386  GTK_TEXT_VIEW(wind->load_log));
3387  wind->acct_entry = GTK_WIDGET(gtk_builder_get_object (builder, "qif_account_entry"));
3388  wind->date_format_combo = GTK_WIDGET(gtk_builder_get_object (builder, "date_format_combobox"));
3389  wind->selected_file_view = GTK_WIDGET(gtk_builder_get_object (builder, "selected_file_view"));
3390  wind->unload_file_btn = GTK_WIDGET(gtk_builder_get_object (builder, "unload_file_button"));
3391  wind->currency_picker = GTK_WIDGET(gtk_builder_get_object (builder, "currency_comboboxentry"));
3392  wind->book_option_label = GTK_WIDGET(gtk_builder_get_object (builder, "book_option_label"));
3393  wind->book_option_message = GTK_WIDGET(gtk_builder_get_object (builder, "book_option_message_label"));
3394  wind->acct_view = GTK_WIDGET(gtk_builder_get_object (builder, "account_page_view"));
3395  wind->acct_view_count = GTK_WIDGET(gtk_builder_get_object (builder, "account_page_count"));
3396  wind->acct_view_btn = GTK_WIDGET(gtk_builder_get_object (builder, "account_page_change"));
3397  wind->cat_view = GTK_WIDGET(gtk_builder_get_object (builder, "category_page_view"));
3398  wind->cat_view_count = GTK_WIDGET(gtk_builder_get_object (builder, "category_page_count"));
3399  wind->cat_view_btn = GTK_WIDGET(gtk_builder_get_object (builder, "category_page_change"));
3400  wind->memo_view = GTK_WIDGET(gtk_builder_get_object (builder, "memo_page_view"));
3401  wind->memo_view_count = GTK_WIDGET(gtk_builder_get_object (builder, "memo_page_count"));
3402  wind->memo_view_btn = GTK_WIDGET(gtk_builder_get_object (builder, "memo_page_change"));
3403  wind->convert_pause = GTK_WIDGET(gtk_builder_get_object (builder, "convert_progress_pause"));
3404  wind->convert_start = GTK_WIDGET(gtk_builder_get_object (builder, "convert_progress_start"));
3405  wind->convert_log = GTK_WIDGET(gtk_builder_get_object (builder, "convert_progress_log"));
3406  wind->convert_progress = gnc_progress_dialog_custom(
3407  GTK_LABEL(gtk_builder_get_object (builder, "convert_progress_primary")),
3408  GTK_LABEL(gtk_builder_get_object (builder, "convert_progress_secondary")),
3409  GTK_PROGRESS_BAR(gtk_builder_get_object (builder, "convert_progress_bar")),
3410  GTK_LABEL(gtk_builder_get_object (builder, "convert_progress_sub")),
3411  GTK_TEXT_VIEW(wind->convert_log));
3412  wind->summary_text = GTK_WIDGET(gtk_builder_get_object (builder, "summary_page"));
3413 
3414  wind->new_transaction_view =
3415  GTK_WIDGET(gtk_builder_get_object (builder, "new_transaction_view"));
3416  wind->old_transaction_view =
3417  GTK_WIDGET(gtk_builder_get_object (builder, "old_transaction_view"));
3418 
3419  gnc_assistant_set_colors (GTK_ASSISTANT (wind->window));
3420 }
3421 
3422 
3423 /********************************************************************
3424  * build_views
3425  *
3426  * Build the details of all GtkTreeView widgets.
3427  ********************************************************************/
3428 static void
3429 build_views(QIFImportWindow *wind)
3430 {
3431  GtkTreeView *view;
3432  GtkListStore *store;
3433  GtkCellRenderer *renderer;
3434  GtkTreeViewColumn *column;
3435  GtkTreeSelection *selection;
3436 
3437  g_return_if_fail(wind);
3438 
3439  /* Set up the selected file view */
3440  view = GTK_TREE_VIEW(wind->selected_file_view);
3441  store = gtk_list_store_new(NUM_FILENAME_COLS, G_TYPE_INT, G_TYPE_STRING);
3442  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
3443  g_object_unref(store);
3444 
3445  renderer = gtk_cell_renderer_text_new();
3446  column = gtk_tree_view_column_new_with_attributes("unused",
3447  renderer,
3448  "text",
3449  FILENAME_COL_NAME,
3450  NULL);
3451  gtk_tree_view_append_column(view, column);
3452 
3453  selection = gtk_tree_view_get_selection(view);
3454  g_signal_connect(selection, "changed",
3455  G_CALLBACK(gnc_ui_qif_import_select_loaded_file_cb),
3456  wind);
3457 
3458  /* Set up the QIF account to GnuCash account matcher. */
3459  create_account_picker_view(wind->acct_view, _("QIF account name"),
3460  G_CALLBACK(gnc_ui_qif_import_account_activate_cb),
3461  G_CALLBACK(gnc_ui_qif_import_account_select_cb),
3462  wind);
3463 
3464  /* Set up the QIF category to GnuCash account matcher. */
3465  create_account_picker_view(wind->cat_view, _("QIF category name"),
3466  G_CALLBACK(gnc_ui_qif_import_category_activate_cb),
3467  G_CALLBACK(gnc_ui_qif_import_category_select_cb),
3468  wind);
3469 
3470  /* Set up the QIF payee/memo to GnuCash account matcher. */
3471  create_account_picker_view(wind->memo_view, _("QIF payee/memo"),
3472  G_CALLBACK(gnc_ui_qif_import_memo_activate_cb),
3473  G_CALLBACK(gnc_ui_qif_import_memo_select_cb),
3474  wind);
3475 
3476  /* Set up the new transaction view */
3477  view = GTK_TREE_VIEW(wind->new_transaction_view);
3478  store = gtk_list_store_new(NUM_QIF_TRANS_COLS, G_TYPE_INT, G_TYPE_STRING,
3479  G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
3480  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
3481  g_object_unref(store);
3482 
3483  renderer = gtk_cell_renderer_text_new();
3484  column = gtk_tree_view_column_new_with_attributes(_("Date"),
3485  renderer,
3486  "text",
3487  QIF_TRANS_COL_DATE,
3488  NULL);
3489  gtk_tree_view_append_column(view, column);
3490 
3491  renderer = gtk_cell_renderer_text_new();
3492  column = gtk_tree_view_column_new_with_attributes(_("Description"),
3493  renderer,
3494  "text",
3495  QIF_TRANS_COL_DESCRIPTION,
3496  NULL);
3497  gtk_tree_view_append_column(view, column);
3498  gtk_tree_view_column_set_expand(column, TRUE);
3499 
3500  renderer = gtk_cell_renderer_text_new();
3501  column = gtk_tree_view_column_new_with_attributes(_("Amount"),
3502  renderer,
3503  "text",
3504  QIF_TRANS_COL_AMOUNT,
3505  NULL);
3506  gtk_tree_view_append_column(view, column);
3507 
3508  selection = gtk_tree_view_get_selection(view);
3509  g_signal_connect(selection, "changed",
3510  G_CALLBACK(gnc_ui_qif_import_duplicate_new_select_cb),
3511  wind);
3512 
3513  /* Set up the old transaction view */
3514  view = GTK_TREE_VIEW(wind->old_transaction_view);
3515  store = gtk_list_store_new(NUM_QIF_TRANS_COLS, G_TYPE_INT, G_TYPE_STRING,
3516  G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
3517  gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
3518  g_object_unref(store);
3519 
3520  renderer = gtk_cell_renderer_text_new();
3521  column = gtk_tree_view_column_new_with_attributes(_("Date"),
3522  renderer,
3523  "text",
3524  QIF_TRANS_COL_DATE,
3525  NULL);
3526  gtk_tree_view_append_column(view, column);
3527 
3528  renderer = gtk_cell_renderer_text_new();
3529  column = gtk_tree_view_column_new_with_attributes(_("Description"),
3530  renderer,
3531  "text",
3532  QIF_TRANS_COL_DESCRIPTION,
3533  NULL);
3534  gtk_tree_view_append_column(view, column);
3535  gtk_tree_view_column_set_expand(column, TRUE);
3536 
3537  renderer = gtk_cell_renderer_text_new();
3538  column = gtk_tree_view_column_new_with_attributes(_("Amount"),
3539  renderer,
3540  "text",
3541  QIF_TRANS_COL_AMOUNT,
3542  NULL);
3543  gtk_tree_view_append_column(view, column);
3544 
3545  renderer = gtk_cell_renderer_toggle_new();
3546  column = gtk_tree_view_column_new_with_attributes(_("Match?"),
3547  renderer,
3548  "active",
3549  QIF_TRANS_COL_CHECKED,
3550  NULL);
3551  gtk_tree_view_append_column(view, column);
3552 
3553  selection = gtk_tree_view_get_selection(view);
3554  g_signal_connect(selection, "changed",
3555  G_CALLBACK(gnc_ui_qif_import_duplicate_old_select_cb),
3556  wind);
3557 }
3558 
3559 
3560 /********************************************************************
3561  * gnc_ui_qif_import_assistant_make
3562  *
3563  * Build a new QIF import assistant.
3564  ********************************************************************/
3565 static GtkWidget *
3566 gnc_ui_qif_import_assistant_make(QIFImportWindow *qif_win)
3567 {
3568  GtkBuilder *builder;
3569  GtkWidget *box;
3570 
3571  builder = gtk_builder_new();
3572  gnc_builder_add_from_file (builder, "assistant-qif-import.glade", "currency_liststore");
3573  gnc_builder_add_from_file (builder, "assistant-qif-import.glade", "date_format_liststore");
3574  gnc_builder_add_from_file (builder, "assistant-qif-import.glade", "QIF Import Assistant");
3575 
3576  qif_win->new_namespaces = NULL;
3577  qif_win->selected_transaction = 0;
3578  qif_win->busy = FALSE;
3579  /* In order to include a book options display on the creation of a new book,
3580  * we need to detect when we are dealing with a new book. */
3581  qif_win->new_book = gnc_is_new_book();
3582 
3583  /* Get all user preferences related to QIF importing. */
3584  get_preferences(qif_win);
3585 
3586  /* Set up the Scheme side of things. Note that if a session/book did not
3587  * exist prior to this function, it is created within scheme function
3588  * "qif-import:load-map-prefs", so we need to have set the flag previously */
3589  initialize_scheme(qif_win);
3590 
3591  /* Get all interesting builder-defined widgets. */
3592  get_assistant_widgets(qif_win, builder);
3593 
3594  /* Make this window stay on top */
3595  gtk_window_set_transient_for (GTK_WINDOW (qif_win->window),
3596  GTK_WINDOW (gnc_ui_get_toplevel ()));
3597 
3598  /* Build the details of all GtkTreeView widgets. */
3599  build_views(qif_win);
3600 
3601  /* Currency Page */
3602  /* Set a default currency for new accounts */
3603  qif_win->currency_picker = gnc_currency_edit_new();
3604  gnc_currency_edit_set_currency (GNC_CURRENCY_EDIT(qif_win->currency_picker), gnc_default_currency());
3605  gtk_widget_show (qif_win->currency_picker);
3606  box = GTK_WIDGET(gtk_builder_get_object (builder, "currency_picker_hbox"));
3607  gtk_box_pack_start(GTK_BOX(box), qif_win->currency_picker, TRUE, TRUE, 0);
3608 
3609  gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(qif_win->window));
3610 
3611  g_signal_connect( qif_win->window, "destroy",
3612  G_CALLBACK(gnc_ui_qif_import_assistant_destroy), qif_win );
3613 
3614  gtk_builder_connect_signals(builder, qif_win);
3615 
3616  g_object_unref(G_OBJECT(builder));
3617 
3618  gtk_widget_show_all(qif_win->window);
3619  gtk_window_present(GTK_WINDOW(qif_win->window));
3620 
3621  return qif_win->window;
3622 }
3623 
3624 
3625 /********************************************
3626  * gnc_ui_qif_import_assistant_close_handler
3627  ********************************************/
3628 static void
3629 gnc_ui_qif_import_assistant_close_handler( gpointer user_data )
3630 {
3631  QIFImportWindow *qif_win = user_data;
3632 
3633  gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(qif_win->window));
3634  gtk_widget_destroy( qif_win->window );
3635 }
3636 
3637 
3638 /********************************************
3639  * gnc_file_qif_import
3640  ********************************************/
3641 void
3642 gnc_file_qif_import(void)
3643 {
3644  QIFImportWindow *qif_win;
3645  gint component_id;
3646 
3647  qif_win = g_new0 (QIFImportWindow, 1);
3648 
3649  /* pop up the QIF File Import dialog box */
3650  gnc_ui_qif_import_assistant_make(qif_win);
3651 
3652  component_id = gnc_register_gui_component (ASSISTANT_QIF_IMPORT_CM_CLASS,
3653  NULL, gnc_ui_qif_import_assistant_close_handler,
3654  qif_win);
3655 
3656  gnc_gui_component_watch_entity_type (component_id,
3657  GNC_ID_ACCOUNT,
3658  QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
3659 
3660  gtk_widget_show_all (qif_win->window);
3661 
3662  gnc_window_adjust_for_screen (GTK_WINDOW(qif_win->window));
3663 }
gnc_commodity * gnc_commodity_table_insert(gnc_commodity_table *table, gnc_commodity *comm)
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Split * xaccTransGetSplit(const Transaction *trans, int i)
Definition: Transaction.c:2144
const char * gnc_print_date(Timespec ts)
void gnc_currency_edit_set_currency(GNCCurrencyEdit *gce, const gnc_commodity *currency)
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
GncPluginPage * gnc_plugin_page_account_tree_new(void)
void gnc_progress_dialog_set_secondary(GNCProgressDialog *progress, const gchar *str)
void gnc_progress_dialog_append_log(GNCProgressDialog *progress, const gchar *str)
utility functions for the GnuCash UI
#define PINFO(format, args...)
Definition: qoflog.h:249
gtk helper routines.
gchar * gnc_ui_namespace_picker_ns(GtkWidget *cbwe)
void gnc_progress_dialog_destroy(GNCProgressDialog *progress)
void gnc_progress_dialog_set_value(GNCProgressDialog *progress, gdouble value)
API for displaying progress of long-running operations.
void gnc_progress_dialog_reset_value(GNCProgressDialog *progress)
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
gnc_commodity_namespace * gnc_commodity_table_add_namespace(gnc_commodity_table *table, const char *name_space, QofBook *book)
void gnc_main_window_open_page(GncMainWindow *window, GncPluginPage *page)
Functions for adding content to a window.
gnc_commodity * gnc_default_currency(void)
Definition: gnc-ui-util.c:939
GNCProgressDialog * gnc_progress_dialog_custom(GtkLabel *primary, GtkLabel *secondary, GtkProgressBar *bar, GtkLabel *suboperation, GtkTextView *log)
int xaccTransCountSplits(const Transaction *trans)
Definition: Transaction.c:2170
Currency selection widget.
Account handling public routines.
void gnc_progress_dialog_set_sub(GNCProgressDialog *progress, const gchar *str)
int gnc_commodity_table_has_namespace(const gnc_commodity_table *table, const char *name_space)
void gnc_commodity_table_delete_namespace(gnc_commodity_table *table, const char *name_space)
gboolean gnc_commodity_namespace_is_iso(const char *name_space)
const char * xaccTransGetDescription(const Transaction *trans)
Definition: Transaction.c:2184
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
void gnc_progress_dialog_reset_log(GNCProgressDialog *progress)
void gnc_progress_dialog_set_primary(GNCProgressDialog *progress, const gchar *str)
gnc_numeric gnc_numeric_abs(gnc_numeric a)
void qof_book_mark_session_dirty(QofBook *book)
Generic api to store and retrieve preferences.
Functions providing a chart of account page.
void gnc_commodity_set_fullname(gnc_commodity *cm, const char *fullname)
GtkWidget * gnc_currency_edit_new(void)
Definition: SplitP.h:71
gnc_numeric xaccSplitGetValue(const Split *split)
Definition: Split.c:1993
Account * xaccSplitGetAccount(const Split *s)
Definition: Split.c:968
void gnc_commodity_set_mnemonic(gnc_commodity *cm, const char *mnemonic)
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Definition: gnc-prefs.c:196
Timespec xaccTransRetDatePostedTS(const Transaction *trans)
Definition: Transaction.c:2243
void gnc_commodity_set_namespace(gnc_commodity *cm, const char *name_space)
GtkWidget * gnc_ui_get_toplevel(void)
guint gnc_progress_dialog_pop(GNCProgressDialog *progress)
API for Transactions and Splits (journal entries)
void gnc_ui_update_namespace_picker(GtkWidget *cbwe, const gchar *sel, dialog_commodity_mode mode)
"select" and "new" commodity windows
void gnc_commodity_destroy(gnc_commodity *cm)
guint gnc_progress_dialog_push(GNCProgressDialog *progress, gdouble weight)
const gchar * QofLogModule
Definition: qofid.h:89