GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
assistant-csv-trans-import.c
Go to the documentation of this file.
1 /*******************************************************************\
2  * assistant-csv-trans-import.c -- An assistant for importing *
3  * Transactions from a file. *
4  * *
5  * Copyright (C) 2012 Robert Fewell *
6  * Copyright (c) 2007 Benny Sperisen <[email protected]> *
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 \********************************************************************/
29 #include "config.h"
30 
31 #include <gtk/gtk.h>
32 #include <glib/gi18n.h>
33 #include <stdlib.h>
34 
35 #include "gnc-ui.h"
36 #include "gnc-uri-utils.h"
37 #include "gnc-ui-util.h"
38 #include "dialog-utils.h"
39 
40 #include "gnc-component-manager.h"
41 
42 #include "gnc-state.h"
43 #include "assistant-utils.h"
45 #include "gnc-csv-trans-settings.h"
46 
47 #include "import-account-matcher.h"
48 #include "import-main-matcher.h"
49 
50 #include "gnc-csv-model.h"
51 #include "gnc-csv-gnumeric-popup.h"
52 #include <goffice/gtk/go-charmap-sel.h>
53 
54 #define MIN_COL_WIDTH 70
55 #define GNC_PREFS_GROUP "dialogs.import.csv"
56 #define ASSISTANT_CSV_IMPORT_TRANS_CM_CLASS "assistant-csv-trans-import"
57 
58 /* This static indicates the debugging module that this .o belongs to. */
59 static QofLogModule log_module = GNC_MOD_ASSISTANT;
60 
61 typedef struct
62 {
63 
64  GtkWidget *window;
65 
66  GtkWidget *file_chooser;
67  gchar *starting_dir;
68  gchar *file_name;
70  GtkWidget *settings_combo;
71  GtkWidget *combo_hbox;
72  GtkWidget *check_label;
73  GtkWidget *check_butt;
74  GtkWidget *start_row_spin;
75  GtkWidget *end_row_spin;
76  GtkWidget *skip_rows;
77  GtkWidget *csv_button;
78  GtkWidget *fixed_button;
79  int start_row;
80  int end_row;
84  GOCharmapSel *encselector;
85  GtkCheckButton *sep_buttons[SEP_NUM_OF_TYPES];
86  GtkCheckButton *custom_cbutton;
87  GtkEntry *custom_entry;
88  GtkComboBoxText *date_format_combo;
89  GtkComboBoxText *currency_format_combo;
90  GtkTreeView *treeview;
91  GtkTreeView *ctreeview;
92  GtkLabel *instructions_label;
93  GtkImage *instructions_image;
96  gboolean not_empty;
97  gboolean previewing_errors;
103  gboolean approved;
104  GtkWidget **treeview_buttons;
111  GtkWidget *account_page;
112  GtkWidget *account_label;
114  gboolean account_page_step;
117  GtkWidget *match_page;
118  GtkWidget *match_label;
119  GtkWidget *help_button;
120  GtkWidget *cancel_button;
121  gboolean match_parse_run;
123  GtkWidget *summary_label;
125  gboolean new_book;
128 
129 
130 /*************************************************************************/
131 
132 void csv_import_trans_assistant_prepare (GtkAssistant *assistant, GtkWidget *page, gpointer user_data);
133 void csv_import_trans_assistant_finish (GtkAssistant *gtkassistant, gpointer user_data);
134 void csv_import_trans_assistant_cancel (GtkAssistant *gtkassistant, gpointer user_data);
135 void csv_import_trans_assistant_close (GtkAssistant *gtkassistant, gpointer user_data);
136 
137 void csv_import_trans_assistant_start_page_prepare (GtkAssistant *gtkassistant, gpointer user_data);
138 void csv_import_trans_assistant_file_page_prepare (GtkAssistant *assistant, gpointer user_data);
139 void csv_import_trans_assistant_preview_page_prepare (GtkAssistant *gtkassistant, gpointer user_data);
140 void csv_import_trans_assistant_account_page_prepare (GtkAssistant *assistant, gpointer user_data);
141 void csv_import_trans_assistant_doc_page_prepare (GtkAssistant *assistant, gpointer user_data);
142 void csv_import_trans_assistant_match_page_prepare (GtkAssistant *assistant, gpointer user_data);
143 void csv_import_trans_assistant_finish_page_prepare (GtkAssistant *assistant, gpointer user_data);
144 void csv_import_trans_assistant_summary_page_prepare (GtkAssistant *assistant, gpointer user_data);
145 
146 void csv_import_trans_srow_cb (GtkWidget *spin, gpointer user_data);
147 void csv_import_trans_erow_cb (GtkWidget *spin, gpointer user_data);
148 void csv_import_trans_skiprows_cb (GtkWidget *checkbox, gpointer user_data);
149 void csv_import_trans_auto_cb (GtkWidget *cb, gpointer user_data);
150 void csv_import_trans_file_chooser_confirm_cb (GtkWidget *button, CsvImportTrans *info);
151 
152 void csv_import_trans_delete_settings_cb (GtkWidget *button, CsvImportTrans *info);
153 void csv_import_trans_save_settings_cb (GtkWidget *button, CsvImportTrans *info);
154 void csv_import_trans_changed_settings_cb (GtkWidget *button, CsvImportTrans *info);
155 void csv_import_trans_load_settings (CsvImportTrans *info);
156 
157 static void gnc_csv_preview_update_assist (CsvImportTrans* info);
158 void gnc_csv_reset_preview_setting (CsvImportTrans* info, gboolean block);
159 gboolean preview_settings_valid (CsvImportTrans *info);
160 static gboolean delete_column (CsvImportTrans* info, int col, gboolean test_only);
161 
162 /*************************************************************************/
163 
164 
165 /*******************************************************
166  * csv_import_trans_load_settings
167  *
168  * Load the settings from a key file
169  *******************************************************/
170 void
171 csv_import_trans_load_settings (CsvImportTrans *info)
172 {
173  GtkTreeIter iter;
174  gchar *group = NULL, *name = NULL;
175 
176  // Get the Active Selection
177  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(info->settings_combo), &iter))
178  {
179  GtkTreeModel *model;
180  GtkAdjustment *adj;
181  int i;
182 
183  model = gtk_combo_box_get_model (GTK_COMBO_BOX(info->settings_combo));
184  gtk_tree_model_get (model, &iter, SET_GROUP, &group, SET_NAME, &name, -1);
185 
186  // Test for default selection, return
187  if (g_strcmp0 (group, NULL) == 0)
188  return;
189 
190  // Load the settings from the keyfile
191  if (gnc_csv_trans_load_settings (info->settings_data, group))
192  {
193  GtkWidget *dialog;
194  const gchar *title = _("Load the Import Settings.");
195 
196  dialog = gtk_message_dialog_new (GTK_WINDOW(info->window),
197  0,
198  GTK_MESSAGE_ERROR,
199  GTK_BUTTONS_OK,
200  "%s", title);
201  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
202  "%s", _("There were problems reading some saved settings, continuing to load.\n Please review and save again."));
203  gtk_dialog_run (GTK_DIALOG (dialog));
204  gtk_widget_destroy (dialog);
205  }
206 
207  // Set start row
208  adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->start_row_spin));
209  gtk_spin_button_set_value (GTK_SPIN_BUTTON(info->start_row_spin), info->settings_data->header_rows);
210 
211  // Set end row
212  adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->end_row_spin));
213  gtk_adjustment_set_upper (adj, info->num_of_rows);
214  gtk_spin_button_set_value (GTK_SPIN_BUTTON(info->end_row_spin), info->num_of_rows - info->settings_data->footer_rows);
215 
216  // Set Aternate rows
217  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->skip_rows), info->settings_data->skip_alt_rows);
218 
219  // Set Import Format
220  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->csv_button), info->settings_data->csv_format);
221  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->fixed_button), !info->settings_data->csv_format);
222 
223  // This Section deals with the separators
224  if (info->settings_data->csv_format)
225  {
226  for (i = 0; i < SEP_NUM_OF_TYPES; i++)
227  {
228  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->sep_buttons[i]), info->settings_data->separator[i]);
229  }
230  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->custom_cbutton), info->settings_data->custom);
231  if (info->settings_data->custom)
232  gtk_entry_set_text (GTK_ENTRY(info->custom_entry), info->settings_data->custom_entry);
233  else
234  gtk_entry_set_text (GTK_ENTRY(info->custom_entry), "");
235  }
236 
237  // This section deals with the combo's and character encoding
238  gtk_combo_box_set_active (GTK_COMBO_BOX(info->date_format_combo), info->settings_data->date_active);
239  gtk_combo_box_set_active (GTK_COMBO_BOX(info->currency_format_combo), info->settings_data->currency_active);
240  go_charmap_sel_set_encoding (info->encselector, info->settings_data->encoding);
241 
242  // This section deals with the column widths
243  if ((!info->settings_data->csv_format) && (!g_strcmp0 (info->settings_data->column_widths, NULL) == 0))
244  {
245  GError *error = NULL;
246  gchar **widths;
247  int i, max_line;
248  int colcount = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
249 
250  // Clear the fixed width entries, if any...
251  if (colcount != 0)
252  {
253  for (i = colcount; i >= 0; i--)
254  {
255  delete_column (info, i, FALSE);
256  }
257  }
258 
259  widths = g_strsplit (info->settings_data->column_widths, ",", -1);
260  max_line = info->longest_line;
261 
262  for (i=0; widths[i] != NULL; i++)
263  {
264  int charindex = 0;
265 
266  if (widths[i] != NULL)
267  charindex = atoi (widths[i]);
268 
269  if (max_line > charindex)
270  stf_parse_options_fixed_splitpositions_add (info->parse_data->options, charindex);
271  else
272  gnc_error_dialog (NULL, "%s", _("There was a problem with the column widths, please review."));
273 
274  if (gnc_csv_parse (info->parse_data, FALSE, &error))
275  {
276  gnc_error_dialog (NULL, "%s", _("There was a problem with the column widths, please review."));
277  g_error_free (error);
278  g_free (group);
279  g_free (name);
280  return;
281  }
282  gnc_csv_preview_update_assist (info);
283  }
284  g_strfreev (widths);
285  }
286 
287  // This section deals with the column types
288  if (!g_strcmp0 (info->settings_data->column_types, NULL) == 0)
289  {
290  GtkTreeModel *store;
291  GtkTreeIter iter;
292  gchar **columns;
293  int i, t;
294  gboolean error = FALSE;
295 
296  columns = g_strsplit (info->settings_data->column_types, ",", -1);
297 
298  // store contains the actual strings appearing in the column types treeview.
299  store = gtk_tree_view_get_model (info->ctreeview);
300 
301  // Get an iterator for the first (and only) row.
302  gtk_tree_model_get_iter_first (store, &iter);
303 
304  // Even Entries are the column types / names
305  for (i=0; columns[i] != NULL; i++)
306  {
307  int s = i * 2 + 1;
308  gboolean found = FALSE;
309 
310  for (t = 0; t < GNC_CSV_NUM_COL_TYPES; t++)
311  {
312  gchar *type = gnc_csv_column_type_strs[t];
313 
314  // Check to see if column type is valid
315  if (g_strcmp0 (type, columns[i]) == 0)
316  {
317  /* Get the type string first. (store is arranged so that every two
318  * columns is a pair of the model used for the combobox and the
319  * string that appears, so that store looks like:
320  * model 0, string 0, model 1, string 1, ..., model ncols, string ncols. */
321  if (s < gtk_tree_model_get_n_columns (store))
322  gtk_list_store_set (GTK_LIST_STORE(store), &iter, s, columns[i], -1);
323  found = TRUE;
324  }
325  }
326  if (!found)
327  error = TRUE;
328  }
329  if (error)
330  gnc_error_dialog (NULL, "%s", _("There was a problem with the column types, please review."));
331 
332  g_strfreev (columns);
333  }
334  }
335  g_free (group);
336  g_free (name);
337 }
338 
339 
340 /*******************************************************
341  * csv_import_trans_delete_settings_cb
342  *
343  * call back to delete a settings entry
344  *******************************************************/
345 void
346 csv_import_trans_delete_settings_cb (GtkWidget *button, CsvImportTrans *info)
347 {
348  GKeyFile *keyfile;
349  GtkTreeIter iter;
350  GtkWidget *dialog;
351  gint response;
352  gchar *group = NULL, *name = NULL;
353  const gchar *title = _("Delete the Import Settings.");
354 
355  // Get the Key file
356  keyfile = gnc_state_get_current ();
357 
358  // Get the Active Selection
359  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(info->settings_combo), &iter))
360  {
361  GtkTreeModel *model;
362  model = gtk_combo_box_get_model (GTK_COMBO_BOX(info->settings_combo));
363  gtk_tree_model_get (model, &iter, SET_GROUP, &group, SET_NAME, &name, -1);
364 
365  if (g_strcmp0 (group, NULL) == 0)
366  {
367  dialog = gtk_message_dialog_new (GTK_WINDOW(info->window),
368  0,
369  GTK_MESSAGE_ERROR,
370  GTK_BUTTONS_OK,
371  "%s", title);
372  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
373  "%s", _("You can not Delete the 'No Settings' entry."));
374  gtk_dialog_run (GTK_DIALOG (dialog));
375  gtk_widget_destroy (dialog);
376  }
377  else
378  {
379  dialog = gtk_message_dialog_new (GTK_WINDOW(info->window),
380  0,
381  GTK_MESSAGE_QUESTION,
382  GTK_BUTTONS_OK_CANCEL,
383  "%s", title);
384  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
385  "%s", _("Do you really want to delete the selection."));
386  response = gtk_dialog_run (GTK_DIALOG (dialog));
387  gtk_widget_destroy (dialog);
388 
389  if (response == GTK_RESPONSE_OK)
390  {
391  g_key_file_remove_group (keyfile, group, NULL);
393  gtk_combo_box_set_active (GTK_COMBO_BOX(info->settings_combo), 0); // Default
394  gnc_csv_reset_preview_setting (info, FALSE); // Reset the widgets
395  }
396  }
397  g_free (group);
398  g_free (name);
399  }
400 }
401 
402 
403 /*******************************************************
404  * csv_import_trans_changed_settings_cb
405  *
406  * Apply settings when selection changed.
407  *******************************************************/
408 void
409 csv_import_trans_changed_settings_cb (GtkWidget *button, CsvImportTrans *info)
410 {
411  csv_import_trans_load_settings (info);
412 }
413 
414 
415 /*******************************************************
416  * csv_import_trans_save_settings_cb
417  *
418  * Save the settings to a Key File.
419  *******************************************************/
420 void
421 csv_import_trans_save_settings_cb (GtkWidget *button, CsvImportTrans *info)
422 {
423  GtkTreeIter iter;
424  GtkWidget *dialog;
425  GtkWidget *entry;
426  gchar *group = NULL, *name = NULL;
427  const gchar *title = _("Save the Import Settings.");
428  gboolean error = FALSE;
429  const gchar *entry_text;
430 
431  // Get the Entry Text
432  entry = gtk_bin_get_child (GTK_BIN(info->settings_combo));
433  entry_text = gtk_entry_get_text (GTK_ENTRY(entry));
434 
435  // If entry used, this lot is by passed.
436  if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(info->settings_combo), &iter))
437  {
438  GtkTreeModel *model;
439  model = gtk_combo_box_get_model (GTK_COMBO_BOX(info->settings_combo));
440  gtk_tree_model_get (model, &iter, SET_GROUP, &group, SET_NAME, &name, -1);
441 
442  if (g_strcmp0 (group, NULL) == 0)
443  {
444  dialog = gtk_message_dialog_new (GTK_WINDOW(info->window),
445  0,
446  GTK_MESSAGE_ERROR,
447  GTK_BUTTONS_OK,
448  "%s", title);
449  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
450  "%s", _("You can not save to 'No Settings'."));
451  gtk_dialog_run (GTK_DIALOG (dialog));
452  gtk_widget_destroy (dialog);
453  error = TRUE;
454  }
455  g_free (group);
456  g_free (name);
457  }
458  else // Check for blank entry_text
459  {
460  if (strlen (entry_text) == 0 || g_strcmp0 (entry_text, NULL) == 0)
461  {
462  dialog = gtk_message_dialog_new (GTK_WINDOW(info->window),
463  0,
464  GTK_MESSAGE_ERROR,
465  GTK_BUTTONS_OK,
466  "%s", title);
467  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
468  "%s", _("The settings name is blank."));
469  gtk_dialog_run (GTK_DIALOG (dialog));
470  gtk_widget_destroy (dialog);
471  error = TRUE;
472  }
473  else // Check for entry_text in settings list
474  {
475  GtkTreeModel *model;
476  GtkTreeIter iter;
477  gboolean valid = FALSE;
478  gboolean found = FALSE;
479  gint response;
480 
481  model = gtk_combo_box_get_model (GTK_COMBO_BOX(info->settings_combo));
482 
483  valid = gtk_tree_model_get_iter_first (model, &iter);
484 
485  while (valid)
486  {
487  gchar *name = NULL;
488 
489  // Walk through the list, reading each row
490  gtk_tree_model_get (model, &iter, SET_NAME, &name, -1);
491 
492  if (g_strcmp0 (name, entry_text) == 0)
493  found = TRUE;
494 
495  g_free (name);
496 
497  valid = gtk_tree_model_iter_next (model, &iter);
498  }
499 
500  if (found) // We have found entry_text in liststore
501  {
502  dialog = gtk_message_dialog_new (GTK_WINDOW(info->window),
503  0,
504  GTK_MESSAGE_QUESTION,
505  GTK_BUTTONS_OK_CANCEL,
506  "%s", title);
507  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
508  "%s", _("Setting name already exists, over write."));
509  response = gtk_dialog_run (GTK_DIALOG (dialog));
510  gtk_widget_destroy (dialog);
511 
512  if (response != GTK_RESPONSE_OK)
513  error = TRUE;
514  }
515  }
516  }
517 
518  // Call save settings if we have no errors
519  if (error == FALSE)
520  {
521  int i;
522  GList *columns;
523  GList *column;
524  GtkTreeModel *store;
525  GtkTreeIter iter;
526  gchar *details = NULL;
527 
528  /* This section deals with the header and rows */
529  info->settings_data->header_rows = gtk_spin_button_get_value (GTK_SPIN_BUTTON(info->start_row_spin));
530  info->settings_data->footer_rows = info->num_of_rows - gtk_spin_button_get_value (GTK_SPIN_BUTTON(info->end_row_spin));
531  info->settings_data->skip_alt_rows = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->skip_rows));
532  info->settings_data->csv_format = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->csv_button));
533 
534  /* This Section deals with the separators */
535  for (i = 0; i < SEP_NUM_OF_TYPES; i++)
536  {
537  info->settings_data->separator[i] = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->sep_buttons[i]));
538  }
539  info->settings_data->custom = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->custom_cbutton));
540  info->settings_data->custom_entry = gtk_entry_get_text (GTK_ENTRY(info->custom_entry));
541 
542  /* This section deals with the combo's and character encoding */
543  info->settings_data->date_active = gtk_combo_box_get_active (GTK_COMBO_BOX(info->date_format_combo));
544  info->settings_data->currency_active = gtk_combo_box_get_active (GTK_COMBO_BOX(info->currency_format_combo));
545  info->settings_data->encoding = go_charmap_sel_get_encoding (info->encselector);
546 
547  /* This section deals with the Treeview column names */
548  columns = gtk_tree_view_get_columns (GTK_TREE_VIEW(info->ctreeview));
549  // store contains the actual strings appearing in the column types treeview.
550  store = gtk_tree_view_get_model (info->ctreeview);
551  // Get an iterator for the first (and only) row.
552  gtk_tree_model_get_iter_first (store, &iter);
553 
554  for (column = columns, i = 1; column; column = g_list_next (column), i = i + 2)
555  {
556  gchar *contents = NULL;
557 
558  /* Get the type string first. (store is arranged so that every two
559  * columns is a pair of the model used for the combobox and the
560  * string that appears, so that store looks like:
561  * model 0, string 0, model 1, string 1, ..., model ncols, string ncols. */
562  gtk_tree_model_get (store, &iter, i, &contents, -1);
563 
564  if (!details)
565  details = g_strdup (contents);
566  else
567  {
568  gchar *details_prev = details;
569  details = g_strjoin (",", details_prev, contents, NULL);
570  g_free (details_prev);
571  }
572  g_free (contents);
573  }
574  g_list_free (columns);
575 
576  info->settings_data->column_types = g_strdup (details);
577  g_free (details);
578 
579  /* Save the column widths in fixed mode */
580  if (info->settings_data->csv_format)
581  info->settings_data->column_widths = "5,10,15";
582  else
583  {
584  gchar *details = NULL;
585  int i = 0;
586  int number_of_splits = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
587 
588  for (i = 0; i < number_of_splits - 1; i++)
589  {
590  gchar *str_width = g_strdup_printf ("%d", stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, i));
591 
592  if (!details)
593  details = g_strdup (str_width);
594  else
595  {
596  gchar *details_prev = details;
597  details = g_strjoin (",", details_prev, str_width, NULL);
598  g_free (details_prev);
599  }
600  g_free (str_width);
601  }
602  info->settings_data->column_widths = g_strdup (details);
603  g_free (details);
604  }
605 
606  // Save the settings
607  if (!gnc_csv_trans_save_settings (info->settings_data, g_strdup (entry_text)))
608  {
609  GtkTreeModel *model;
610  GtkTreeIter iter;
611  gboolean valid = FALSE;
612 
613  dialog = gtk_message_dialog_new (GTK_WINDOW(info->window),
614  0,
615  GTK_MESSAGE_INFO,
616  GTK_BUTTONS_OK,
617  "%s", title);
618  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
619  "%s", _("The settings have been saved."));
620  gtk_dialog_run (GTK_DIALOG (dialog));
621  gtk_widget_destroy (dialog);
622 
623  // Update the settings store
624  model = gtk_combo_box_get_model (GTK_COMBO_BOX(info->settings_combo));
626 
627  // Get the first entry in model
628  valid = gtk_tree_model_get_iter_first (model, &iter);
629  while (valid)
630  {
631  gchar *name = NULL;
632 
633  // Walk through the list, reading each row
634  gtk_tree_model_get (model, &iter, SET_NAME, &name, -1);
635 
636  if (g_strcmp0 (name, entry_text) == 0) // Set Active, the one Saved.
637  gtk_combo_box_set_active_iter (GTK_COMBO_BOX(info->settings_combo), &iter);
638 
639  g_free (name);
640 
641  valid = gtk_tree_model_iter_next (model, &iter);
642  }
643  }
644  else
645  {
646  dialog = gtk_message_dialog_new (GTK_WINDOW(info->window),
647  0,
648  GTK_MESSAGE_ERROR,
649  GTK_BUTTONS_OK,
650  "%s", title);
651  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
652  "%s", _("There was a problem saving the settings, please try again."));
653  gtk_dialog_run (GTK_DIALOG (dialog));
654  gtk_widget_destroy (dialog);
655  }
656  }
657 }
658 
659 
660 /**************************************************
661  * csv_import_trans_file_chooser_confirm_cb
662  *
663  * call back for ok button in file chooser widget
664  **************************************************/
665 void
666 csv_import_trans_file_chooser_confirm_cb (GtkWidget *button, CsvImportTrans *info)
667 {
668  GtkAssistant *assistant = GTK_ASSISTANT(info->window);
669  gint num = gtk_assistant_get_current_page (assistant);
670  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
671  GError* error;
672  gchar *file_name;
673  GncCsvParseData* parse_data;
674 
675  gtk_assistant_set_page_complete (assistant, page, FALSE);
676 
677  file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(info->file_chooser));
678 
679  if (file_name)
680  {
681  gchar *filepath = gnc_uri_get_path (file_name);
682  gchar *filedir = g_path_get_dirname (filepath);
683  if (info->starting_dir)
684  g_free (info->starting_dir);
685  info->starting_dir = g_strdup (filedir);
686  g_free (filedir);
687  g_free (filepath);
688 
689  if (info->file_name)
690  g_free (info->file_name);
691  info->file_name = g_strdup (file_name);
692  error = NULL;
693  /* Load the file into parse_data. */
694  parse_data = gnc_csv_new_parse_data();
695  if (gnc_csv_load_file (parse_data, file_name, &error))
696  {
697  /* If we couldn't load the file ... */
698  gnc_error_dialog (NULL, "%s", error->message);
699  if (error->code == GNC_CSV_FILE_OPEN_ERR)
700  {
701  g_free (file_name);
702  gnc_csv_parse_data_free (parse_data);
703  return;
704  }
705  /* If we couldn't guess the encoding, we are content with just
706  * displaying an error message and move on with a blank
707  * display. */
708  }
709  else
710  {
711  /* Parse the data. */
712  if (gnc_csv_parse (parse_data, TRUE, &error))
713  {
714  /* If we couldn't parse the data ... */
715  gnc_error_dialog (NULL, "%s", error->message);
716  gnc_csv_parse_data_free (parse_data);
717  }
718  else
719  {
720  if (info->parse_data) // Free parse_data if we have come back here
721  {
723  gnc_csv_reset_preview_setting (info, TRUE);
724  }
725  info->parse_data = parse_data;
726  info->previewing_errors = FALSE; /* We're looking at all the data. */
727  info->approved = FALSE; /* This is FALSE until the user clicks "OK". */
728  gtk_assistant_set_page_complete (assistant, page, TRUE);
729  }
730  }
731  }
732  g_free (file_name);
733 
734  DEBUG("file_name selected is %s", info->file_name);
735  DEBUG("starting directory is %s", info->starting_dir);
736 
737  /* Step to next page if page is complete */
738  if(gtk_assistant_get_page_complete (assistant, page))
739  gtk_assistant_set_current_page (assistant, num + 1);
740 }
741 
742 
743 /**************************************************
744  * row_selection_update
745  *
746  * refresh the start and end row highlighting
747  **************************************************/
748 static
749 void row_selection_update (CsvImportTrans* info)
750 {
751  GtkListStore *store;
752  GtkTreeIter iter;
753  gboolean valid;
754  int i = 0;
755 
756  store = GTK_LIST_STORE(gtk_tree_view_get_model (info->treeview));
757 
758  /* Start of file */
759  for ( i = 0; i <= info->start_row; i++)
760  {
761  /* Modify background color of rows less than start row */
762  if (info->start_row == i)
763  {
764  valid = gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(store), &iter, NULL, i);
765  if (valid)
766  gtk_list_store_set (store, &iter, 0, NULL, -1);
767  }
768  else
769  {
770  valid = gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(store), &iter, NULL, i);
771  if (valid)
772  gtk_list_store_set (store, &iter, 0, "pink", -1);
773  valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
774  if (valid)
775  gtk_list_store_set (store, &iter, 0, NULL, -1);
776  }
777  }
778 
779  /* End of File */
780  for ( i = info->num_of_rows - 1; i >= info->end_row; i--)
781  {
782  /* Modify background color of rows more than end row */
783  if (i == info->end_row)
784  {
785  valid = gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(store), &iter, NULL, i);
786  if (valid)
787  gtk_list_store_set (store, &iter, 0, NULL, -1);
788  }
789  else
790  {
791  valid = gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(store), &iter, NULL, i);
792  if (valid)
793  gtk_list_store_set (store, &iter, 0, "pink", -1);
794  valid = gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(store), &iter, NULL, i - 1);
795  if (valid)
796  gtk_list_store_set (store, &iter, 0, NULL, -1);
797  }
798  }
799 
800  /* Remove background color from the start row to end row */
801  for ( i = info->start_row + 1; i <= info->end_row; i++)
802  {
803  valid = gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(store), &iter, NULL, i);
804  if (valid)
805  gtk_list_store_set (store, &iter, 0, NULL, -1);
806  }
807 
808  /* Skip rows */
809  if (info->parse_data->skip_rows == TRUE)
810  {
811  for ( i = info->start_row + 1; i <= info->end_row; i = i + 2)
812  {
813  /* Modify background color of alternate rows from the start row */
814  valid = gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(store), &iter, NULL, i);
815  if (valid)
816  gtk_list_store_set (store, &iter, 0, "pink", -1);
817  }
818  }
819 }
820 
821 
822 /*******************************************************
823  * csv_import_trans_srow_cb
824  *
825  * call back for import start row
826  *******************************************************/
827 void csv_import_trans_srow_cb (GtkWidget *spin, gpointer user_data)
828 {
829  CsvImportTrans *info = user_data;
830  GtkAdjustment *adj;
831 
832  /* Get number of rows for header */
833  info->start_row = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin)) - 1;
834 
835  info->parse_data->start_row = info->start_row;
836 
837  adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->end_row_spin));
838  gtk_adjustment_set_lower (adj, info->start_row + 1);
839 
840  /* Refresh the row highlighting */
841  row_selection_update (info);
842 }
843 
844 
845 /*******************************************************
846  * csv_import_trans_erow_cb
847  *
848  * call back for import end row
849  *******************************************************/
850 void csv_import_trans_erow_cb (GtkWidget *spin, gpointer user_data)
851 {
852  CsvImportTrans *info = user_data;
853  GtkAdjustment *adj;
854 
855  /* Get number of rows for header */
856  info->end_row = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin)) - 1;
857 
858  info->parse_data->end_row = info->end_row + 1;
859 
860  adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->start_row_spin));
861  gtk_adjustment_set_upper (adj, info->end_row + 1);
862 
863  /* Refresh the row highlighting */
864  row_selection_update (info);
865 }
866 
867 
868 /*******************************************************
869  * csv_import_trans_auto_cb
870  *
871  * call back for auto create account / Skip Errors
872  *******************************************************/
873 void csv_import_trans_auto_cb (GtkWidget *cb, gpointer user_data)
874 {
875  CsvImportTrans *info = user_data;
876 
877  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(cb)))
878  {
879  if (info->previewing_errors == TRUE)
880  info->approved = TRUE;
881  else
882  info->account_picker->auto_create = TRUE;
883  }
884  else
885  {
886  if (info->previewing_errors == TRUE)
887  info->approved = FALSE;
888  else
889  info->account_picker->auto_create = FALSE;
890  }
891 }
892 
893 
894 /*******************************************************
895  * csv_import_trans_skiprows_cb
896  *
897  * call back for import skip rows checkbox
898  *******************************************************/
899 void csv_import_trans_skiprows_cb (GtkWidget *checkbox, gpointer user_data)
900 {
901  CsvImportTrans *info = user_data;
902 
903  /* Set the skip_rows variable */
904  info->parse_data->skip_rows = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(checkbox));
905 
906  /* Refresh the row highlighting */
907  row_selection_update (info);
908 }
909 
910 
916 static GtkCellRenderer* gnc_csv_preview_get_cell_renderer (CsvImportTrans* info, int col)
917 {
918  GList* renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT(gtk_tree_view_get_column (info->treeview, col)));
919 
920  GtkCellRenderer* cell = GTK_CELL_RENDERER(renderers->data);
921  g_list_free (renderers);
922  return cell;
923 }
924 
925 
933 static void sep_button_clicked (GtkWidget* widget, CsvImportTrans* info)
934 {
935  int i;
936  char* stock_separator_characters[] = {" ", "\t", ",", ":", ";", "-"};
937  GSList* checked_separators = NULL;
938  GError* error;
939 
940  /* Add the corresponding characters to checked_separators for each
941  * button that is checked. */
942  for (i = 0; i < SEP_NUM_OF_TYPES; i++)
943  {
944  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->sep_buttons[i])))
945  checked_separators = g_slist_append (checked_separators, stock_separator_characters[i]);
946  }
947 
948  /* Add the custom separator if the user checked its button. */
949  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->custom_cbutton)))
950  {
951  char* custom_sep = (char*)gtk_entry_get_text (info->custom_entry);
952  if (custom_sep[0] != '\0') /* Don't add a blank separator (bad things will happen!). */
953  checked_separators = g_slist_append (checked_separators, custom_sep);
954  }
955 
956  /* Set the parse options using the checked_separators list. */
957  stf_parse_options_csv_set_separators (info->parse_data->options, NULL, checked_separators);
958  g_slist_free (checked_separators);
959 
960  /* Parse the data using the new options. We don't want to reguess
961  * the column types because we want to leave the user's
962  * configurations in tact. */
963  if (gnc_csv_parse (info->parse_data, FALSE, &error))
964  {
965  /* Warn the user there was a problem and try to undo what caused
966  * the error. (This will cause a reparsing and ideally a usable
967  * configuration.) */
968  gnc_error_dialog (NULL, "Error in parsing");
969  /* If the user changed the custom separator, erase that custom separator. */
970  if (widget == GTK_WIDGET(info->custom_entry))
971  {
972  gtk_entry_set_text (GTK_ENTRY(widget), "");
973  }
974  /* If the user checked a checkbutton, toggle that checkbutton back. */
975  else
976  {
977  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget),
978  !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget)));
979  }
980  return;
981  }
982 
983  /* If we parsed successfully, redisplay the data. */
984  gnc_csv_preview_update_assist (info);
985 
986  /* Refresh the row highlighting */
987  row_selection_update (info);
988 }
989 
990 
996 static void separated_or_fixed_selected (GtkToggleButton* csv_button, CsvImportTrans* info)
997 {
998  GError* error = NULL;
999  /* Set the parsing type correctly. */
1000  if (gtk_toggle_button_get_active (csv_button)) /* If we're in CSV mode ... */
1001  {
1002  stf_parse_options_set_type (info->parse_data->options, PARSE_TYPE_CSV);
1003  }
1004  else /* If we're in fixed-width mode ... */
1005  {
1006  stf_parse_options_set_type (info->parse_data->options, PARSE_TYPE_FIXED);
1007  }
1008 
1009  /* Reparse the data. */
1010  if (gnc_csv_parse (info->parse_data, FALSE, &error))
1011  {
1012  /* Show an error dialog explaining the problem. */
1013  gnc_error_dialog (NULL, "%s", error->message);
1014  return;
1015  }
1016 
1017  /* Show the new data. */
1018  gnc_csv_preview_update_assist (info);
1019 
1020  /* Refresh the row highlighting */
1021  row_selection_update (info);
1022 }
1023 
1024 
1032 static void encoding_selected (GOCharmapSel* selector, const char* encoding,
1033  CsvImportTrans* info)
1034 {
1035  /* This gets called twice everytime a new encoding is selected. The
1036  * second call actually passes the correct data; thus, we only do
1037  * something the second time this is called. */
1038 
1039  /* Prevent code-caused calls of this function from having an impact. */
1040  if (info->code_encoding_calls > 0)
1041  {
1042  info->code_encoding_calls--;
1043  return;
1044  }
1045 
1046  /* If this is the second time the function is called ... */
1047  if (info->encoding_selected_called)
1048  {
1049  const char* previous_encoding = info->parse_data->encoding;
1050  GError* error = NULL;
1051  /* Try converting the new encoding and reparsing. */
1052  if (gnc_csv_convert_encoding (info->parse_data, encoding, &error) ||
1053  gnc_csv_parse (info->parse_data, FALSE, &error))
1054  {
1055  /* If it fails, change back to the old encoding. */
1056  gnc_error_dialog (NULL, "%s", _("Invalid encoding selected"));
1057  info->encoding_selected_called = FALSE;
1058  go_charmap_sel_set_encoding (selector, previous_encoding);
1059  return;
1060  }
1061 
1062  gnc_csv_preview_update_assist (info);
1063 
1064  /* Refresh the row highlighting */
1065  row_selection_update (info);
1066 
1067  info->encoding_selected_called = FALSE;
1068  }
1069  else /* If this is the first call of the function ... */
1070  {
1071  info->encoding_selected_called = TRUE; /* ... set the flag and wait for the next call. */
1072  }
1073 }
1074 
1075 
1080 static void date_format_selected (GtkComboBoxText* format_selector, CsvImportTrans* info)
1081 {
1082  info->parse_data->date_format = gtk_combo_box_get_active (GTK_COMBO_BOX(format_selector));
1083 }
1084 
1085 
1090 static void currency_format_selected (GtkComboBoxText* currency_selector, CsvImportTrans* info)
1091 {
1092  info->parse_data->currency_format = gtk_combo_box_get_active (GTK_COMBO_BOX(currency_selector));
1093 }
1094 
1095 
1096 /*======================================================================*/
1097 /*================== Beginning of Gnumeric Code ========================*/
1098 
1099 /* The following is code copied from Gnumeric 1.7.8 licensed under the
1100  * GNU General Public License version 2 and/or version 3. It is from the file
1101  * gnumeric/src/dialogs/dialog-stf-fixed-page.c, and it has been
1102  * modified slightly to work within GnuCash. */
1103 
1104 /*
1105  * Copyright 2001 Almer S. Tigelaar <[email protected]>
1106  * Copyright 2003 Morten Welinder <[email protected]>
1107  *
1108  * This program is free software; you can redistribute it and/or modify
1109  * it under the terms of the GNU General Public License as published by
1110  * the Free Software Foundation; either version 2 of the License, or
1111  * (at your option) any later version.
1112  *
1113  * This program is distributed in the hope that it will be useful,
1114  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1115  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1116  * GNU General Public License for more details.
1117  *
1118  * You should have received a copy of the GNU General Public License
1119  * along with this program; if not, write to the Free Software
1120  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1121  */
1122 
1123 enum
1124 {
1125  CONTEXT_STF_IMPORT_MERGE_LEFT = 1,
1126  CONTEXT_STF_IMPORT_MERGE_RIGHT = 2,
1127  CONTEXT_STF_IMPORT_SPLIT = 3,
1128  CONTEXT_STF_IMPORT_WIDEN = 4,
1129  CONTEXT_STF_IMPORT_NARROW = 5
1130 };
1131 
1132 static GnumericPopupMenuElement const popup_elements[] =
1133 {
1134  {
1135  N_("Merge with column on _left"), GTK_STOCK_REMOVE,
1136  0, 1 << CONTEXT_STF_IMPORT_MERGE_LEFT, CONTEXT_STF_IMPORT_MERGE_LEFT
1137  },
1138  {
1139  N_("Merge with column on _right"), GTK_STOCK_REMOVE,
1140  0, 1 << CONTEXT_STF_IMPORT_MERGE_RIGHT, CONTEXT_STF_IMPORT_MERGE_RIGHT
1141  },
1142  { "", NULL, 0, 0, 0 },
1143  {
1144  N_("_Split this column"), NULL,
1145  0, 1 << CONTEXT_STF_IMPORT_SPLIT, CONTEXT_STF_IMPORT_SPLIT
1146  },
1147  { "", NULL, 0, 0, 0 },
1148  {
1149  N_("_Widen this column"), GTK_STOCK_GO_FORWARD,
1150  0, 1 << CONTEXT_STF_IMPORT_WIDEN, CONTEXT_STF_IMPORT_WIDEN
1151  },
1152  {
1153  N_("_Narrow this column"), GTK_STOCK_GO_BACK,
1154  0, 1 << CONTEXT_STF_IMPORT_NARROW, CONTEXT_STF_IMPORT_NARROW
1155  },
1156  { NULL, NULL, 0, 0, 0 },
1157 };
1158 
1159 static gboolean
1160 make_new_column (CsvImportTrans* info, int col, int dx, gboolean test_only)
1161 {
1162  PangoLayout *layout;
1163  PangoFontDescription *font_desc;
1164  int charindex, width;
1165  GtkCellRenderer *cell = gnc_csv_preview_get_cell_renderer (info, col);
1166  int colstart, colend;
1167  GError* error = NULL;
1168 
1169  colstart = (col == 0)
1170  ? 0
1171  : stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col - 1);
1172  colend = stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col);
1173 
1174  g_object_get (G_OBJECT(cell), "font_desc", &font_desc, NULL);
1175  layout = gtk_widget_create_pango_layout (GTK_WIDGET(info->treeview), "x");
1176  pango_layout_set_font_description (layout, font_desc);
1177  pango_layout_get_pixel_size (layout, &width, NULL);
1178  if (width < 1) width = 1;
1179  charindex = colstart + (dx + width / 2) / width;
1180  g_object_unref (layout);
1181  pango_font_description_free (font_desc);
1182 
1183  if (charindex <= colstart || (colend != -1 && charindex >= colend))
1184  return FALSE;
1185 
1186  if (!test_only)
1187  {
1188  stf_parse_options_fixed_splitpositions_add (info->parse_data->options, charindex);
1189  if (gnc_csv_parse (info->parse_data, FALSE, &error))
1190  {
1191  gnc_error_dialog (NULL, "%s", error->message);
1192  return FALSE;
1193  }
1194  gnc_csv_preview_update_assist (info);
1195 
1196  /* Refresh the row highlighting */
1197  row_selection_update (info);
1198  }
1199 
1200  return TRUE;
1201 }
1202 
1203 static gboolean
1204 widen_column (CsvImportTrans* info, int col, gboolean test_only)
1205 {
1206  int colcount = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
1207  int nextstart, nextnextstart;
1208  GError* error = NULL;
1209 
1210  if (col >= colcount - 1)
1211  return FALSE;
1212 
1213  nextstart = stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col);
1214 
1215  nextnextstart = (col == colcount - 2)
1216  ? info->longest_line
1217  : stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col + 1);
1218 
1219  if (nextstart + 1 >= nextnextstart)
1220  return FALSE;
1221 
1222  if (!test_only)
1223  {
1224  stf_parse_options_fixed_splitpositions_remove (info->parse_data->options, nextstart);
1225  stf_parse_options_fixed_splitpositions_add (info->parse_data->options, nextstart + 1);
1226  if (gnc_csv_parse (info->parse_data, FALSE, &error))
1227  {
1228  gnc_error_dialog (NULL, "%s", error->message);
1229  return FALSE;
1230  }
1231  gnc_csv_preview_update_assist (info);
1232 
1233  /* Refresh the row highlighting */
1234  row_selection_update (info);
1235  }
1236  return TRUE;
1237 }
1238 
1239 static gboolean
1240 narrow_column (CsvImportTrans* info, int col, gboolean test_only)
1241 {
1242  int colcount = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
1243  int thisstart, nextstart;
1244  GError* error = NULL;
1245 
1246  if (col >= colcount - 1)
1247  return FALSE;
1248 
1249  thisstart = (col == 0)
1250  ? 0
1251  : stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col - 1);
1252  nextstart = stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col);
1253 
1254  if (nextstart - 1 <= thisstart)
1255  return FALSE;
1256 
1257  if (!test_only)
1258  {
1259  stf_parse_options_fixed_splitpositions_remove (info->parse_data->options, nextstart);
1260  stf_parse_options_fixed_splitpositions_add (info->parse_data->options, nextstart - 1);
1261  if (gnc_csv_parse (info->parse_data, FALSE, &error))
1262  {
1263  gnc_error_dialog (NULL, "%s", error->message);
1264  return FALSE;
1265  }
1266  gnc_csv_preview_update_assist (info);
1267 
1268  /* Refresh the row highlighting */
1269  row_selection_update (info);
1270  }
1271  return TRUE;
1272 }
1273 
1274 static gboolean
1275 delete_column (CsvImportTrans* info, int col, gboolean test_only)
1276 {
1277  GError* error = NULL;
1278  int colcount = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
1279  if (col < 0 || col >= colcount - 1)
1280  return FALSE;
1281 
1282  if (!test_only)
1283  {
1284  int nextstart = stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col);
1285  stf_parse_options_fixed_splitpositions_remove (info->parse_data->options, nextstart);
1286  if (gnc_csv_parse (info->parse_data, FALSE, &error))
1287  {
1288  gnc_error_dialog (NULL, "%s", error->message);
1289  return FALSE;
1290  }
1291  gnc_csv_preview_update_assist (info);
1292 
1293  /* Refresh the row highlighting */
1294  row_selection_update (info);
1295  }
1296  return TRUE;
1297 }
1298 
1299 static void
1300 select_column (CsvImportTrans* info, int col)
1301 {
1302  int colcount = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
1303  GtkTreeViewColumn *column;
1304 
1305  if (col < 0 || col >= colcount)
1306  return;
1307 
1308  column = gtk_tree_view_get_column (info->treeview, col);
1309  gtk_widget_grab_focus (column->button);
1310 }
1311 
1312 static gboolean
1313 fixed_context_menu_handler (GnumericPopupMenuElement const *element,
1314  gpointer user_data)
1315 {
1316  CsvImportTrans* info = user_data;
1317  int col = info->fixed_context_col;
1318 
1319  switch (element->index)
1320  {
1321  case CONTEXT_STF_IMPORT_MERGE_LEFT:
1322  delete_column (info, col - 1, FALSE);
1323  break;
1324  case CONTEXT_STF_IMPORT_MERGE_RIGHT:
1325  delete_column (info, col, FALSE);
1326  break;
1327  case CONTEXT_STF_IMPORT_SPLIT:
1328  make_new_column (info, col, info->fixed_context_dx, FALSE);
1329  break;
1330  case CONTEXT_STF_IMPORT_WIDEN:
1331  widen_column (info, col, FALSE);
1332  break;
1333  case CONTEXT_STF_IMPORT_NARROW:
1334  narrow_column (info, col, FALSE);
1335  break;
1336  default:
1337  ; /* Nothing */
1338  }
1339  return TRUE;
1340 }
1341 
1342 static void
1343 fixed_context_menu (CsvImportTrans* info, GdkEventButton *event,
1344  int col, int dx)
1345 {
1346  int sensitivity_filter = 0;
1347 
1348  info->fixed_context_col = col;
1349  info->fixed_context_dx = dx;
1350 
1351  if (!delete_column (info, col - 1, TRUE))
1352  sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_LEFT);
1353  if (!delete_column (info, col, TRUE))
1354  sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_RIGHT);
1355  if (!make_new_column (info, col, dx, TRUE))
1356  sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_SPLIT);
1357  if (!widen_column (info, col, TRUE))
1358  sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_WIDEN);
1359  if (!narrow_column (info, col, TRUE))
1360  sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_NARROW);
1361 
1362  select_column (info, col);
1363  gnumeric_create_popup_menu (popup_elements, &fixed_context_menu_handler,
1364  info, 0,
1365  sensitivity_filter, event);
1366 }
1367 
1368 /*===================== End of Gnumeric Code ===========================*/
1369 /*======================================================================*/
1370 
1371 
1379 static void treeview_resized (GtkWidget* widget, GtkAllocation* allocation, CsvImportTrans* info)
1380 {
1381  /* ncols is the number of columns in the data. */
1382  int i, ncols = info->parse_data->column_types->len;
1383 
1384  /* Go through each column except for the last. (We don't want to set
1385  * the width of the last column because the user won't be able to
1386  * shrink the dialog back if it's expanded.) */
1387 
1388  for (i = 0; i < ncols - 1; i++)
1389  {
1390  gint col_width; /* The width of the column in info->treeview. */
1391  GtkTreeViewColumn* pcol;
1392  GtkTreeViewColumn* ccol; /* The corresponding column in info->ctreeview. */
1393 
1394  /* Get the width. */
1395  col_width = gtk_tree_view_column_get_width (gtk_tree_view_get_column (info->treeview, i));
1396  /* Set the minumum width for a column so that drop down selector can be seen. */
1397  if (col_width < MIN_COL_WIDTH)
1398  {
1399  col_width = MIN_COL_WIDTH;
1400  }
1401  pcol = gtk_tree_view_get_column (info->treeview, i);
1402  gtk_tree_view_column_set_min_width (pcol, col_width);
1403  /* Set ccol's width the same. */
1404  ccol = gtk_tree_view_get_column (info->ctreeview, i);
1405  gtk_tree_view_column_set_min_width (ccol, col_width);
1406  gtk_tree_view_column_set_max_width (ccol, col_width);
1407  }
1408 }
1409 
1410 
1420 static void column_type_changed (GtkCellRenderer* renderer, gchar* path,
1421  GtkTreeIter* new_text_iter, CsvImportTrans* info)
1422 {
1423  /* ncols is the number of columns in the data. */
1424  int i, ncols = info->parse_data->column_types->len;
1425  /* store has the actual strings that appear in info->ctreeview. */
1426  GtkTreeModel* store = gtk_tree_view_get_model (info->ctreeview);
1427  GtkTreeModel* model;
1428  gint textColumn;
1429  GtkTreeIter iter;
1430  gchar* new_text;
1431 
1432  /* Get the new text */
1433  g_object_get (renderer, "model", &model, "text-column", &textColumn, NULL);
1434  gtk_tree_model_get (model, new_text_iter, textColumn, &new_text, -1);
1435 
1436  /* Get an iterator for the first (and only) row. */
1437  gtk_tree_model_get_iter_first (store, &iter);
1438 
1439  /* Go through each column. */
1440  for (i = 0; i < ncols; i++)
1441  {
1442  /* We need all this stuff so that we can find out whether or not
1443  * this was the column that was changed. */
1444  GtkCellRenderer* col_renderer; /* The renderer for this column. */
1445  /* The column in the treeview we are looking at */
1446  GtkTreeViewColumn* col = gtk_tree_view_get_column (info->ctreeview, i);
1447  /* The list of renderers for col */
1448  GList* rend_list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT(col));
1449  /* rend_list has only one entry, which we put in col_renderer. */
1450  col_renderer = rend_list->data;
1451  g_list_free (rend_list);
1452 
1453  /* If this is not the column that was changed ... */
1454  if (col_renderer != renderer)
1455  {
1456  /* The string that appears in the column */
1457  gchar* contents = NULL;
1458  /* Get the type string. (store is arranged so that every two
1459  * columns is a pair of the model used for the combobox and the
1460  * string that appears, so that store looks like:
1461  * model 0, string 0, model 1, string 1, ..., model ncols, string ncols. */
1462  gtk_tree_model_get(store, &iter, 2 * i + 1, &contents, -1);
1463  /* If this column has the same string that the user selected ... */
1464  if (!g_strcmp0 (contents, new_text))
1465  {
1466  /* ... set this column to the "None" type. (We can't allow duplicate types.) */
1467  gtk_list_store_set (GTK_LIST_STORE(store), &iter, 2 * i + 1,
1468  _(gnc_csv_column_type_strs[GNC_CSV_NONE]), -1);
1469  }
1470  g_free (contents);
1471  }
1472  else /* If this is the column that was changed ... */
1473  {
1474  /* Set the text for this column to what the user selected. (See
1475  * comment above "Get the type string. ..." for why we set
1476  * column 2*i+1 in store.) */
1477  gtk_list_store_set (GTK_LIST_STORE(store), &iter, 2 * i + 1, new_text, -1);
1478  }
1479  }
1480 }
1481 
1482 
1490 static void header_button_press_handler (GtkWidget* button, GdkEventButton* event,
1491  CsvImportTrans* info)
1492 {
1493  /* col is the number of the column that was clicked, and offset is
1494  to correct for the indentation of button. */
1495  int i, col = 0, offset = GTK_BIN(button)->child->allocation.x - button->allocation.x,
1496  ncols = info->parse_data->column_types->len;
1497  /* Find the column that was clicked. */
1498  for (i = 0; i < ncols; i++)
1499  {
1500  if (info->treeview_buttons[i] == button)
1501  {
1502  col = i;
1503  break;
1504  }
1505  }
1506 
1507  /* Don't let the user affect the last column if it has error messages. */
1508  if (info->parse_data->orig_max_row < ncols && ncols - col == 1)
1509  {
1510  return;
1511  }
1512 
1513  /* Double clicks can split columns. */
1514  if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
1515  {
1516  make_new_column (info, col, (int)event->x - offset, FALSE);
1517  }
1518  /* Right clicking brings up a context menu. */
1519  else if (event->type == GDK_BUTTON_PRESS && event->button == 3)
1520  {
1521  fixed_context_menu (info, event, col, (int)event->x - offset);
1522  }
1523 }
1524 
1525 
1526 /* Test for the required minimum number of coloumns selected and
1527  * a valid date format.
1528  * Returns TRUE if we do or FALSE if we don't.
1529  *
1530  * @param info The data being previewed
1531  */
1532 gboolean preview_settings_valid (CsvImportTrans* info)
1533 {
1534  /* Shorten the column_types identifier. */
1535  GArray* column_types = info->parse_data->column_types;
1536  int i, ncols = column_types->len; /* ncols is the number of columns in the data. */
1537  int weight = 0;
1538  gboolean valid = TRUE;
1539  /* store contains the actual strings appearing in the column types treeview. */
1540  GtkTreeModel* store = gtk_tree_view_get_model (info->ctreeview);
1541  /* datastore contains the actual strings appearing in the preview treeview. */
1542  GtkTreeModel* datastore = gtk_tree_view_get_model (info->treeview);
1543  GtkTreeIter iter, iter2;
1544  /* Get an iterator for the first (and only) row. */
1545  gtk_tree_model_get_iter_first (store, &iter);
1546 
1547  /* Get an iterator for the first required row in the data store. */
1548  gtk_tree_model_iter_nth_child (GTK_TREE_MODEL(datastore), &iter2, NULL, info->start_row);
1549 
1550  /* Go through each of the columns. */
1551  for (i = 0; i < ncols; i++)
1552  {
1553  int type; /* The column type contained in this column. */
1554  gchar* contents = NULL; /* The column type string in this column. */
1555  gchar* prevstr = NULL; /* The string in this column from datastore. */
1556  gchar* accstr = NULL; /* The string in this column from datastore. */
1557  /* Get the type string first. (store is arranged so that every two
1558  * columns is a pair of the model used for the combobox and the
1559  * string that appears, so that store looks like:
1560  * model 0, string 0, model 1, string 1, ..., model ncols, string ncols. */
1561  gtk_tree_model_get (store, &iter, 2 * i + 1, &contents, -1);
1562 
1563  /* Go through each column type until ... */
1564  for (type = 0; type < GNC_CSV_NUM_COL_TYPES; type++)
1565  {
1566  /* ... we find one that matches with what's in the column. */
1567  if (!g_strcmp0 (contents, _(gnc_csv_column_type_strs[type])))
1568  {
1569  /* Set the column_types array appropriately and quit. */
1570  column_types->data[i] = type;
1571 
1572  switch (type)
1573  {
1574  case GNC_CSV_DATE:
1575  weight = weight + 1000;
1576  gtk_tree_model_get (datastore, &iter2, i + 1, &prevstr, -1);
1577 
1578  if (parse_date (prevstr, info->parse_data->date_format) == -1)
1579  valid = FALSE;
1580  break;
1581 
1582  case GNC_CSV_DESCRIPTION:
1583  case GNC_CSV_NOTES:
1584  weight = weight + 100;
1585  break;
1586 
1587  case GNC_CSV_BALANCE:
1588  case GNC_CSV_DEPOSIT:
1589  case GNC_CSV_WITHDRAWAL:
1590  weight = weight + 10;
1591  break;
1592 
1593  case GNC_CSV_NUM:
1594  weight = weight + 1;
1595  break;
1596  case GNC_CSV_ACCOUNT:
1597  weight = weight + 1;
1598  gtk_tree_model_get (datastore, &iter2, i + 1, &accstr, -1);
1599  info->account_picker->account_online_id_value = strdup (accstr);
1600  break;
1601  }
1602  break;
1603  }
1604  }
1605  /* Free the type string created by gtk_tree_model_get() */
1606  g_free (contents);
1607  g_free (prevstr);
1608  g_free (accstr);
1609  }
1610  if (weight < 1109 || valid == FALSE)
1611  return FALSE;
1612  else
1613  return TRUE;
1614 }
1615 
1616 
1617 /* Loads the preview's data into its data treeview. not_empty is TRUE
1618  * when the data treeview already contains data, FALSE otherwise
1619  * (e.g. the first time this function is called on a preview).
1620  * @param info The data being previewed
1621  */
1622 static void gnc_csv_preview_update_assist (CsvImportTrans* info)
1623 {
1624  /* store has the data from the file being imported. cstores is an
1625  * array of stores that hold the combo box entries for each
1626  * column. ctstore contains both pointers to models in cstore and
1627  * the actual text that appears in info->ctreeview. */
1628  GtkListStore *store, **cstores, *ctstore;
1629  GtkTreeIter iter;
1630  GtkTreeSelection *selection;
1631  /* ncols is the number of columns in the file data. */
1632  int i, j, ncols = info->parse_data->column_types->len,
1633  max_str_len = info->parse_data->file_str.end - info->parse_data->file_str.begin;
1634 
1635  /* store contains only strings. */
1636  GType* types = g_new (GType, 2 * ncols);
1637  for (i = 0; i < ncols + 1; i++)
1638  types[i] = G_TYPE_STRING;
1639  store = gtk_list_store_newv (ncols + 1, types);
1640 
1641  /* ctstore is arranged as follows:
1642  * model 0, text 0, model 1, text 1, ..., model ncols, text ncols. */
1643  for (i = 0; i < 2 * ncols; i += 2)
1644  {
1645  types[i] = GTK_TYPE_TREE_MODEL;
1646  types[i+1] = G_TYPE_STRING;
1647  }
1648  ctstore = gtk_list_store_newv (2 * ncols, types);
1649 
1650  g_free (types);
1651 
1652  /* Each element in cstores is a single column model. */
1653  cstores = g_new (GtkListStore*, ncols);
1654  for (i = 0; i < ncols; i++)
1655  {
1656  cstores[i] = gtk_list_store_new (1, G_TYPE_STRING);
1657  /* Add all of the possible entries to the combo box. */
1658  for (j = 0; j < GNC_CSV_NUM_COL_TYPES; j++)
1659  {
1660  gtk_list_store_append (cstores[i], &iter);
1661  gtk_list_store_set (cstores[i], &iter, 0, _(gnc_csv_column_type_strs[j]), -1);
1662  }
1663  }
1664 
1665  if (info->not_empty)
1666  {
1667  GList *tv_columns, *tv_columns_begin, *ctv_columns, *ctv_columns_begin;
1668  tv_columns = tv_columns_begin = gtk_tree_view_get_columns (info->treeview);
1669  ctv_columns = ctv_columns_begin = gtk_tree_view_get_columns (info->ctreeview);
1670  /* Clear out exisiting columns in info->treeview. */
1671  while (tv_columns != NULL)
1672  {
1673  gtk_tree_view_remove_column (info->treeview, GTK_TREE_VIEW_COLUMN(tv_columns->data));
1674  tv_columns = g_list_next (tv_columns);
1675  }
1676  /* Do the same in info->ctreeview. */
1677  while (ctv_columns != NULL)
1678  {
1679  gtk_tree_view_remove_column (info->ctreeview, GTK_TREE_VIEW_COLUMN(ctv_columns->data));
1680  ctv_columns = g_list_next (ctv_columns);
1681  }
1682  g_list_free (tv_columns_begin);
1683  g_list_free (ctv_columns_begin);
1684  g_free (info->treeview_buttons);
1685  }
1686 
1687  /* Fill the data treeview with data from the file. */
1688  /* Also, update the longest line value within the following loop (whichever is executed). */
1689  info->longest_line = 0;
1690  if (info->previewing_errors) /* If we are showing only errors ... */
1691  {
1692  /* ... only pick rows that are in info->error_lines. */
1693  GList* error_lines = info->parse_data->error_lines;
1694  while (error_lines != NULL)
1695  {
1696  int this_line_length = 0;
1697  i = GPOINTER_TO_INT(error_lines->data);
1698  gtk_list_store_append (store, &iter);
1699 
1700  /* Row Color column */
1701  gtk_list_store_set (store, &iter, 0, NULL, -1);
1702 
1703  for (j = 0; j < ((GPtrArray*)(info->parse_data->orig_lines->pdata[i]))->len; j++)
1704  {
1705  /* Add this cell's length to the row's length and set the value of the list store. */
1706  gchar* cell_string = (gchar*)((GPtrArray*)(info->parse_data->orig_lines->pdata[i]))->pdata[j];
1707  this_line_length += g_utf8_strlen(cell_string, max_str_len);
1708  gtk_list_store_set (store, &iter, j + 1, cell_string, -1);
1709  }
1710 
1711  if (this_line_length > info->longest_line)
1712  info->longest_line = this_line_length;
1713 
1714  error_lines = g_list_next (error_lines);
1715  }
1716  }
1717  else /* Otherwise, put in all of the data. */
1718  {
1719  for (i = 0; i < info->parse_data->orig_lines->len; i++)
1720  {
1721  int this_line_length = 0;
1722  gtk_list_store_append (store, &iter);
1723 
1724  /* Row Color column */
1725  gtk_list_store_set (store, &iter, 0, NULL, -1);
1726 
1727  for (j = 0; j < ((GPtrArray*)(info->parse_data->orig_lines->pdata[i]))->len; j++)
1728  {
1729  /* Add this cell's length to the row's length and set the value of the list store. */
1730  gchar* cell_string = (gchar*)((GPtrArray*)(info->parse_data->orig_lines->pdata[i]))->pdata[j];
1731  this_line_length += g_utf8_strlen(cell_string, max_str_len);
1732  gtk_list_store_set (store, &iter, j + 1, cell_string, -1);
1733  }
1734 
1735  if (this_line_length > info->longest_line)
1736  info->longest_line = this_line_length;
1737 
1738  /* Set the number of rows in the store */
1739  info->num_of_rows = i + 1;
1740  }
1741  }
1742 
1743  /* Set all the column types to what's in the parse data. */
1744  gtk_list_store_append (ctstore, &iter);
1745  gtk_list_store_set (ctstore, &iter, 0, NULL, -1); /* Dummy Column to match row color */
1746  for (i = 0; i < ncols; i++)
1747  {
1748  gtk_list_store_set (ctstore, &iter, 2 * i, cstores[i], 2 * i + 1,
1749  _(gnc_csv_column_type_strs[(int)(info->parse_data->column_types->data[i])]),
1750  -1);
1751  }
1752 
1753  info->treeview_buttons = g_new (GtkWidget*, ncols);
1754  /* Insert columns into the data and column type treeviews. */
1755  for (i = 0; i < ncols ; i++)
1756  {
1757  GtkTreeViewColumn* col; /* The column we add to info->treeview. */
1758  /* Create renderers for the data treeview (renderer) and the
1759  * column type treeview (crenderer). */
1760  GtkCellRenderer* renderer = gtk_cell_renderer_text_new(),
1761  *crenderer = gtk_cell_renderer_combo_new();
1762  /* We want a monospace font for the data in case of fixed-width data. */
1763  g_object_set (G_OBJECT(renderer), "family", "monospace", NULL);
1764  /* We are using cstores for the combo box entries, and we don't
1765  * want the user to be able to manually enter their own column
1766  * types. */
1767  g_object_set (G_OBJECT(crenderer), "model", cstores[i], "text-column", 0,
1768  "editable", TRUE, "has-entry", FALSE, NULL);
1769  g_signal_connect (G_OBJECT(crenderer), "changed",
1770  G_CALLBACK(column_type_changed), (gpointer)info);
1771 
1772  /* Add a single column for the treeview. */
1773  col = gtk_tree_view_column_new_with_attributes ("", renderer, "text", i + 1, NULL);
1774 
1775  /* Add the Color column 0 to the renderer */
1776  gtk_tree_view_column_add_attribute (col, renderer, "background", 0);
1777 
1778  gtk_tree_view_insert_column (info->treeview, col, -1);
1779  /* Enable resizing of the columns. */
1780  gtk_tree_view_column_set_resizable (col, TRUE);
1781  /* Use the alternating model and text entries from ctstore in
1782  * info->ctreeview. */
1783  gtk_tree_view_insert_column_with_attributes (info->ctreeview,
1784  -1, "", crenderer, "model", 2 * i,
1785  "text", 2 * i + 1, NULL);
1786 
1787  /* We need to allow clicking on the column headers for fixed-width
1788  * column splitting and merging. */
1789  g_object_set (G_OBJECT(col), "clickable", TRUE, NULL);
1790  g_signal_connect (G_OBJECT(col->button), "button_press_event",
1791  G_CALLBACK(header_button_press_handler), (gpointer)info);
1792  info->treeview_buttons[i] = col->button;
1793  }
1794 
1795  /* Set the treeviews to use the models. */
1796  gtk_tree_view_set_model (info->treeview, GTK_TREE_MODEL(store));
1797  gtk_tree_view_set_model (info->ctreeview, GTK_TREE_MODEL(ctstore));
1798 
1799  /* Select the header row */
1800  gtk_tree_model_get_iter_first (GTK_TREE_MODEL(ctstore), &iter);
1801  selection = gtk_tree_view_get_selection (info->ctreeview);
1802  gtk_tree_selection_select_iter (selection, &iter);
1803 
1804  /* Free the memory for the stores. */
1805  g_object_unref (GTK_TREE_MODEL(store));
1806  g_object_unref (GTK_TREE_MODEL(ctstore));
1807  for (i = 0; i < ncols; i++)
1808  g_object_unref (GTK_TREE_MODEL(cstores[i]));
1809 
1810  /* Make the things actually appear. */
1811  gtk_widget_show_all (GTK_WIDGET(info->treeview));
1812  gtk_widget_show_all (GTK_WIDGET(info->ctreeview));
1813 
1814  /* Set the encoding selector to the right encoding. */
1815  info->code_encoding_calls = 2;
1816  go_charmap_sel_set_encoding (info->encselector, info->parse_data->encoding);
1817 
1818  /* Set the date format to what's in the combo box (since we don't
1819  * necessarily know if this will always be the same). */
1820  info->parse_data->date_format = gtk_combo_box_get_active (GTK_COMBO_BOX(info->date_format_combo));
1821 
1822  /* It's now been filled with some stuff. */
1823  info->not_empty = TRUE;
1824 }
1825 
1826 
1827 /*******************************************************
1828  * gnc_csv_reset_preview_setting
1829  *
1830  * Reset the widgets on the preview settings page
1831  *******************************************************/
1832 void gnc_csv_reset_preview_setting (CsvImportTrans *info, gboolean block)
1833 {
1834  int i;
1835  GtkAdjustment *adj;
1836  int colcount = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
1837 
1838  // Clear the fixed width entries, if any...
1839  if (colcount != 0)
1840  {
1841  for (i = colcount; i >= 0; i--)
1842  {
1843  delete_column (info, i, FALSE);
1844  }
1845  }
1846 
1847  // Reset Start Row
1848  adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->start_row_spin));
1849  gtk_spin_button_set_value (GTK_SPIN_BUTTON(info->start_row_spin), 1);
1850 
1851  // Reset End Row
1852  adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->end_row_spin));
1853  gtk_adjustment_set_upper (adj, info->num_of_rows);
1854  gtk_spin_button_set_value (GTK_SPIN_BUTTON(info->end_row_spin), info->num_of_rows);
1855 
1856  // Reset Skip Rows
1857  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->skip_rows), FALSE);
1858 
1859  // Reset Import Format
1860  g_signal_handlers_block_by_func (info->csv_button, separated_or_fixed_selected, info);
1861  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->csv_button), TRUE);
1862  g_signal_handlers_unblock_by_func (info->csv_button, separated_or_fixed_selected, info);
1863 
1864  if (block) // We need to block these when we go back to the file page
1865  {
1866  g_signal_handlers_block_by_func (info->custom_cbutton, sep_button_clicked, info);
1867  g_signal_handlers_block_by_func (info->custom_entry, sep_button_clicked, info);
1868  }
1869 
1870  // Reset the separators
1871  for (i = 0; i < SEP_NUM_OF_TYPES; i++)
1872  {
1873  if (block) // We need to block these when we go back to the file page
1874  g_signal_handlers_block_by_func (info->sep_buttons[i], sep_button_clicked, info);
1875  if (i == 2)
1876  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->sep_buttons[i]), TRUE);
1877  else
1878  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->sep_buttons[i]), FALSE);
1879  if (block) // Now unblock
1880  g_signal_handlers_unblock_by_func (info->sep_buttons[i], sep_button_clicked, info);
1881  }
1882  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->custom_cbutton), FALSE);
1883  gtk_entry_set_text (GTK_ENTRY(info->custom_entry), "");
1884 
1885  if (block) // Now unblock
1886  {
1887  g_signal_handlers_unblock_by_func (info->custom_cbutton, sep_button_clicked, info);
1888  g_signal_handlers_unblock_by_func (info->custom_entry, sep_button_clicked, info);
1889  }
1890 
1891  // Reset the combo's and character encoding
1892  gtk_combo_box_set_active (GTK_COMBO_BOX(info->date_format_combo), 0);
1893  gtk_combo_box_set_active (GTK_COMBO_BOX(info->currency_format_combo), 0);
1894  go_charmap_sel_set_encoding (info->encselector, "UTF-8");
1895 }
1896 
1897 
1898 /*******************************************************
1899  * load_settings
1900  *
1901  * load the default settings for the assistant
1902  *******************************************************/
1903 static
1904 void load_settings (CsvImportTrans *info)
1905 {
1906  info->start_row = 0;
1907  info->account_page_step = TRUE;
1908  info->match_parse_run = FALSE;
1909  info->file_name = NULL;
1910  info->starting_dir = NULL;
1911 
1912  /* Init Settings data. */
1914 
1915  /* The default directory for the user to select files. */
1916  info->starting_dir = gnc_get_default_directory (GNC_PREFS_GROUP);
1917 }
1918 
1919 /*======================================================================*/
1920 /*======================================================================*/
1921 
1922 /*******************************************************
1923  * Assistant page prepare functions
1924  *******************************************************/
1925 void
1926 csv_import_trans_assistant_start_page_prepare (GtkAssistant *assistant,
1927  gpointer user_data)
1928 {
1929  CsvImportTrans *info = user_data;
1930 
1931  gint num = gtk_assistant_get_current_page (assistant);
1932  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1933 
1934  /* Enable the Assistant Buttons */
1935  gtk_assistant_set_page_complete (assistant, page, TRUE);
1936 }
1937 
1938 
1939 void
1940 csv_import_trans_assistant_file_page_prepare (GtkAssistant *assistant,
1941  gpointer user_data)
1942 {
1943  CsvImportTrans *info = user_data;
1944  GtkAdjustment *adj;
1945  GtkTreeModel *settings_store;
1946  gint num = gtk_assistant_get_current_page (assistant);
1947  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1948 
1949  info->account_picker->auto_create = TRUE; /* Step over account page if we find matching online id */
1950  info->previewing_errors = FALSE; /* We're looking at all the data. */
1951  info->approved = FALSE; /* This is FALSE until the user clicks "OK". */
1952 
1953  /* Set the default directory */
1954  if (info->starting_dir)
1955  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(info->file_chooser), info->starting_dir);
1956 
1957  /* Reset start row to first row 1 */
1958  adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->start_row_spin));
1959  gtk_spin_button_set_value (GTK_SPIN_BUTTON(info->start_row_spin), 1);
1960 
1961  /* Reset upper value to 999 */
1962  adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->end_row_spin));
1963  gtk_adjustment_set_upper (adj, 999);
1964 
1965  /* Get settings store and populate */
1966  settings_store = gtk_combo_box_get_model (GTK_COMBO_BOX(info->settings_combo));
1967  gnc_csv_trans_find_settings (settings_store);
1968  gtk_combo_box_set_active (GTK_COMBO_BOX(info->settings_combo), 0);
1969 
1970  /* Disable the Forward Assistant Button */
1971  gtk_assistant_set_page_complete (assistant, page, FALSE);
1972 }
1973 
1974 
1975 void
1976 csv_import_trans_assistant_preview_page_prepare (GtkAssistant *assistant,
1977  gpointer user_data)
1978 {
1979  CsvImportTrans *info = user_data;
1980  GtkAdjustment *adj;
1981 
1982  g_signal_connect (G_OBJECT(info->treeview), "size-allocate",
1983  G_CALLBACK(treeview_resized), (gpointer)info);
1984 
1985  if (info->previewing_errors == TRUE)
1986  {
1987  gchar* name;
1988  GtkIconSize size;
1989 
1990  /* Block going back */
1991  gtk_assistant_commit (GTK_ASSISTANT(info->window));
1992 
1993  gtk_image_get_stock (info->instructions_image, &name, &size);
1994  gtk_image_set_from_stock (info->instructions_image, GTK_STOCK_DIALOG_ERROR, size);
1995  gtk_label_set_text (info->instructions_label,
1996  _("The rows displayed below had errors which are in the last column. You can attempt to correct them by changing the configuration."));
1997  gtk_widget_show (GTK_WIDGET(info->instructions_image));
1998  gtk_widget_show (GTK_WIDGET(info->instructions_label));
1999 
2000  /* Reset start row */
2001  adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->start_row_spin));
2002  gtk_spin_button_set_value (GTK_SPIN_BUTTON(info->start_row_spin), 1);
2003 
2004  /* Set spin buttons and settings combo hbox not sensative */
2005  gtk_widget_set_sensitive (info->combo_hbox, FALSE);
2006  gtk_widget_set_sensitive (info->start_row_spin, FALSE);
2007  gtk_widget_set_sensitive (info->end_row_spin, FALSE);
2008  gtk_widget_set_sensitive (info->skip_rows, FALSE);
2009  info->parse_data->skip_rows = FALSE;
2010 
2011  /* Set check button label */
2012  gtk_label_set_text (GTK_LABEL(info->check_label), _("Skip Errors"));
2013  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->check_butt), FALSE);
2014  }
2015 
2016  /* Load the data into the treeview. */
2017  gnc_csv_preview_update_assist (info);
2018 
2019  /* Set the upper limit of spin button to number of rows */
2020  adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->end_row_spin));
2021  if (gtk_adjustment_get_upper (adj) != info->num_of_rows)
2022  {
2023  gtk_adjustment_set_upper (adj, info->num_of_rows);
2024  gtk_spin_button_set_value (GTK_SPIN_BUTTON(info->end_row_spin), info->num_of_rows);
2025  }
2026 
2027  /* Update the row selection highlight */
2028  row_selection_update (info);
2029 }
2030 
2031 
2032 void
2033 csv_import_trans_assistant_account_page_prepare (GtkAssistant *assistant,
2034  gpointer user_data)
2035 {
2036  CsvImportTrans *info = user_data;
2037  gint num = gtk_assistant_get_current_page (assistant);
2038  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2039  gchar *text, *mtext;
2040  Account * account = NULL;
2041 
2042  if (!preview_settings_valid (info) && (info->approved == FALSE))
2043  {
2044  text = g_strdup_printf (gettext ("There are problems with the import settings!\nThe date format could be wrong "
2045  "or there are not enough columns set..."));
2046  mtext = g_strdup_printf ("<span size=\"medium\" color=\"red\"><b>%s</b></span>", text);
2047  gtk_label_set_markup (GTK_LABEL(info->account_label), mtext);
2048  g_free (mtext);
2049  g_free (text);
2050 
2051  gtk_widget_set_sensitive (info->account_page, FALSE);
2052  }
2053  else
2054  {
2055  text = g_strdup_printf (gettext ("To Change the account, double click on the required account, click Forward to proceed."));
2056  mtext = g_strdup_printf ("<span size=\"medium\" color=\"red\"><b>%s</b></span>", text);
2057  gtk_label_set_markup (GTK_LABEL(info->account_label), mtext);
2058  g_free (mtext);
2059  g_free (text);
2060 
2061  gtk_widget_set_sensitive (info->account_page, TRUE);
2062 
2063  /* Let the user select an account to put the transactions in. */
2065 
2066  /* If we have a valid account and auto_create is TRUE, move on to matcher */
2067  if (!(account == NULL) && (info->account_picker->auto_create == TRUE))
2068  gtk_assistant_set_current_page (assistant, num + 1);
2069  }
2070 
2071  /* Enable the Forward Assistant Button */
2072  if (account == NULL)
2073  gtk_assistant_set_page_complete (assistant, page, FALSE);
2074  else
2075  gtk_assistant_set_page_complete (assistant, page, TRUE);
2076 }
2077 
2078 
2079 void
2080 csv_import_trans_assistant_doc_page_prepare (GtkAssistant *assistant,
2081  gpointer user_data)
2082 {
2083  CsvImportTrans *info = user_data;
2084 
2085  /* Block going back */
2086  gtk_assistant_commit (GTK_ASSISTANT(info->window));
2087 
2088  if ( info->match_parse_run == FALSE)
2089  {
2090  /* Add the Cancel button for the matcher */
2091  info->cancel_button = gtk_button_new_with_mnemonic (_("_Cancel"));
2092  gtk_assistant_add_action_widget (assistant, info->cancel_button);
2093  g_signal_connect (info->cancel_button, "clicked",
2094  G_CALLBACK(csv_import_trans_assistant_cancel), info);
2095  gtk_widget_show (GTK_WIDGET(info->cancel_button));
2096  }
2097 }
2098 
2099 
2100 void
2101 csv_import_trans_assistant_match_page_prepare (GtkAssistant *assistant,
2102  gpointer user_data)
2103 {
2104  CsvImportTrans *info = user_data;
2105  gint num = gtk_assistant_get_current_page (assistant);
2106  GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
2107  gchar *text, *mtext;
2108 
2109  /* Block going back */
2110  gtk_assistant_commit (GTK_ASSISTANT(info->window));
2111 
2112  /* Before creating transactions, if this is a new book, let user specify
2113  * book options, since they affect how transactions are created */
2114  if (info->new_book)
2115  info->new_book = gnc_new_book_option_display (info->window);
2116 
2117  /* Create transactions from the parsed data, first time with FALSE
2118  Subsequent times with TRUE */
2119  if ( info->match_parse_run == FALSE)
2120  {
2121  gnc_csv_parse_to_trans (info->parse_data, info->account_picker->retAccount, FALSE);
2122  }
2123  else
2124  gnc_csv_parse_to_trans (info->parse_data, info->account_picker->retAccount, TRUE);
2125  info->match_parse_run = TRUE;
2126 
2127  /* if there are errors, we jump back to preview to correct */
2128  if (!(info->parse_data->error_lines == NULL) && (info->approved == FALSE) )
2129  {
2130  info->previewing_errors = TRUE; /* We're looking at errors. */
2131  gtk_assistant_set_current_page (assistant, 2);
2132  }
2133 
2134  if ((info->parse_data->error_lines == NULL) || (info->approved == TRUE) )
2135  {
2136  GList* transactions; /* A list of the transactions we create */
2137 
2138  text = _("Double click on rows to change, then click on Apply to Import");
2139  mtext = g_strdup_printf ("<span size=\"medium\" color=\"red\"><b>%s</b></span>", text);
2140  gtk_label_set_markup (GTK_LABEL(info->match_label), mtext);
2141  g_free (mtext);
2142 
2143  if (info->gnc_csv_importer_gui == NULL)
2144  {
2145  /* Create the genereic transaction importer GUI. */
2146  info->gnc_csv_importer_gui = gnc_gen_trans_assist_new (info->match_page, NULL, FALSE, 42);
2147 
2148  /* Add the help button for the matcher */
2149  info->help_button = gtk_button_new_with_mnemonic (_("_Help"));
2150  gtk_assistant_add_action_widget (assistant, info->help_button);
2151  g_signal_connect (info->help_button, "clicked",
2152  G_CALLBACK(on_matcher_help_clicked), info->gnc_csv_importer_gui);
2153  gtk_widget_show (GTK_WIDGET(info->help_button));
2154 
2155  /* Get the list of the transactions that were created. */
2156  transactions = info->parse_data->transactions;
2157  /* Copy all of the transactions to the importer GUI. */
2158  while (transactions != NULL)
2159  {
2160  GncCsvTransLine* trans_line = transactions->data;
2161  gnc_gen_trans_list_add_trans (info->gnc_csv_importer_gui, trans_line->trans);
2162  transactions = g_list_next (transactions);
2163  }
2164  g_list_free (transactions);
2165  }
2166  }
2167  /* Enable the Forward Assistant Button */
2168  gtk_assistant_set_page_complete (assistant, page, TRUE);
2169 }
2170 
2171 
2172 void
2173 csv_import_trans_assistant_summary_page_prepare (GtkAssistant *assistant,
2174  gpointer user_data)
2175 {
2176  CsvImportTrans *info = user_data;
2177  gchar *text, *mtext;
2178 
2179  /* Save the Window size and directory */
2180  gnc_set_default_directory (GNC_PREFS_GROUP, info->starting_dir);
2181 
2182  /* Remove the added button */
2183  gtk_assistant_remove_action_widget (assistant, info->help_button);
2184  gtk_assistant_remove_action_widget (assistant, info->cancel_button);
2185 
2186  text = g_strdup_printf (gettext ("The transactions were imported from the file '%s'."), info->file_name);
2187  mtext = g_strdup_printf ("<span size=\"medium\"><b>%s</b></span>", text);
2188  gtk_label_set_markup (GTK_LABEL(info->summary_label), mtext);
2189  g_free (text);
2190  g_free (mtext);
2191 }
2192 
2193 
2194 void
2195 csv_import_trans_assistant_prepare (GtkAssistant *assistant, GtkWidget *page,
2196  gpointer user_data)
2197 {
2198  gint currentpage = gtk_assistant_get_current_page (assistant);
2199 
2200  switch (currentpage)
2201  {
2202  case 0:
2203  /* Current page is Import Start page */
2204  csv_import_trans_assistant_start_page_prepare (assistant, user_data);
2205  break;
2206  case 1:
2207  /* Current page is File select page */
2208  csv_import_trans_assistant_file_page_prepare (assistant, user_data);
2209  break;
2210  case 2:
2211  /* Current page is Preview page */
2212  csv_import_trans_assistant_preview_page_prepare (assistant, user_data);
2213  break;
2214  case 3:
2215  /* Current page is Account page */
2216  csv_import_trans_assistant_account_page_prepare (assistant, user_data);
2217  break;
2218  case 4:
2219  /* Current page is Transaction Doc page */
2220  csv_import_trans_assistant_doc_page_prepare (assistant, user_data);
2221  break;
2222  case 5:
2223  /* Current page is Match page */
2224  csv_import_trans_assistant_match_page_prepare (assistant, user_data);
2225  break;
2226  case 6:
2227  /* Current page is Summary page */
2228  csv_import_trans_assistant_summary_page_prepare (assistant, user_data);
2229  break;
2230  }
2231 }
2232 
2233 
2234 /*******************************************************
2235  * Assistant call back functions
2236  *******************************************************/
2237 static void
2238 csv_import_trans_assistant_destroy_cb (GtkObject *object, gpointer user_data)
2239 {
2240  CsvImportTrans *info = user_data;
2241  gnc_unregister_gui_component_by_data (ASSISTANT_CSV_IMPORT_TRANS_CM_CLASS, info);
2242  g_free (info);
2243 }
2244 
2245 void
2246 csv_import_trans_assistant_cancel (GtkAssistant *assistant, gpointer user_data)
2247 {
2248  CsvImportTrans *info = user_data;
2249  gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_TRANS_CM_CLASS, info);
2250 }
2251 
2252 void
2253 csv_import_trans_assistant_close (GtkAssistant *assistant, gpointer user_data)
2254 {
2255  CsvImportTrans *info = user_data;
2256  gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_TRANS_CM_CLASS, info);
2257 }
2258 
2259 void
2260 csv_import_trans_assistant_finish (GtkAssistant *assistant, gpointer user_data)
2261 {
2262  CsvImportTrans *info = user_data;
2263 
2264  /* Start the import */
2265  if (info->parse_data->transactions != NULL)
2267  else
2269 }
2270 
2271 static void
2272 csv_import_trans_close_handler (gpointer user_data)
2273 {
2274  CsvImportTrans *info = user_data;
2275 
2276  g_free(info->file_name);
2277  g_free(info->starting_dir);
2278 
2279  /* Free the memory we allocated. */
2280  if (!(info->parse_data == NULL))
2282 
2283  if (!(info->settings_data == NULL))
2285 
2286  if (!(info->account_picker == NULL))
2287  info->account_picker = NULL;
2288 
2289  if (!(info->gnc_csv_importer_gui == NULL))
2290  info->gnc_csv_importer_gui = NULL;
2291 
2292  gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(info->window));
2293  gtk_widget_destroy (info->window);
2294 }
2295 
2296 /*******************************************************
2297  * Create the Assistant
2298  *******************************************************/
2299 static GtkWidget *
2300 csv_import_trans_assistant_create (CsvImportTrans *info)
2301 {
2302  GtkBuilder *builder;
2303  GtkWidget *window;
2304  GtkWidget *box;
2305  GtkWidget *button, *h_box;
2306  GtkWidget *save_button, *del_button;
2307 
2308  builder = gtk_builder_new();
2309  gnc_builder_add_from_file (builder , "assistant-csv-trans-import.glade", "start_row_adj");
2310  gnc_builder_add_from_file (builder , "assistant-csv-trans-import.glade", "end_row_adj");
2311  gnc_builder_add_from_file (builder , "assistant-csv-trans-import.glade", "CSV Transaction Assistant");
2312  window = GTK_WIDGET(gtk_builder_get_object (builder, "CSV Transaction Assistant"));
2313  info->window = window;
2314 
2315  /* Set the assistant colors */
2316  gnc_assistant_set_colors (GTK_ASSISTANT (info->window));
2317 
2318  /* Load default settings */
2319  load_settings (info);
2320 
2321  /* Enable buttons on all page. */
2322  gtk_assistant_set_page_complete (GTK_ASSISTANT(window),
2323  GTK_WIDGET(gtk_builder_get_object (builder, "start_page")),
2324  TRUE);
2325  gtk_assistant_set_page_complete (GTK_ASSISTANT(window),
2326  GTK_WIDGET(gtk_builder_get_object (builder, "file_page")),
2327  FALSE);
2328  gtk_assistant_set_page_complete (GTK_ASSISTANT(window),
2329  GTK_WIDGET(gtk_builder_get_object (builder, "preview_page")),
2330  TRUE);
2331  gtk_assistant_set_page_complete (GTK_ASSISTANT(window),
2332  GTK_WIDGET(gtk_builder_get_object (builder, "account_page")),
2333  FALSE);
2334  gtk_assistant_set_page_complete (GTK_ASSISTANT(window),
2335  GTK_WIDGET(gtk_builder_get_object (builder, "doc_page")),
2336  TRUE);
2337  gtk_assistant_set_page_complete (GTK_ASSISTANT(window),
2338  GTK_WIDGET(gtk_builder_get_object (builder, "match_page")),
2339  FALSE);
2340  gtk_assistant_set_page_complete (GTK_ASSISTANT(window),
2341  GTK_WIDGET(gtk_builder_get_object (builder, "summary_page")),
2342  TRUE);
2343 
2344  /* Start Page */
2345 
2346  /* File chooser Page */
2347  info->file_chooser = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_OPEN);
2348  g_signal_connect (G_OBJECT(info->file_chooser), "file-activated",
2349  G_CALLBACK(csv_import_trans_file_chooser_confirm_cb), info);
2350  button = gtk_button_new_from_stock (GTK_STOCK_OK);
2351  gtk_widget_set_size_request (button, 100, -1);
2352  gtk_widget_show (button);
2353  h_box = gtk_hbox_new (TRUE, 0);
2354  gtk_box_pack_start (GTK_BOX(h_box), button, FALSE, FALSE, 0);
2355  gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(info->file_chooser), h_box);
2356  g_signal_connect (G_OBJECT(button), "clicked",
2357  G_CALLBACK(csv_import_trans_file_chooser_confirm_cb), info);
2358 
2359  box = GTK_WIDGET(gtk_builder_get_object (builder, "file_page"));
2360  gtk_box_pack_start (GTK_BOX(box), info->file_chooser, TRUE, TRUE, 6);
2361  gtk_widget_show (info->file_chooser);
2362 
2363  /* Preview Settings Page */
2364  {
2365  char* sep_button_names[] = {"space_cbutton",
2366  "tab_cbutton",
2367  "comma_cbutton",
2368  "colon_cbutton",
2369  "semicolon_cbutton",
2370  "hyphen_cbutton"
2371  };
2372  GtkContainer *date_format_container, *currency_format_container;
2373  int i;
2374  GtkTable *enctable;
2375  GtkListStore *settings_store;
2376 
2377  // Add Settings combo
2378  settings_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
2379  info->settings_combo = gtk_combo_box_new_with_model_and_entry (GTK_TREE_MODEL(settings_store));
2380  gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX(info->settings_combo), SET_NAME);
2381  gtk_combo_box_set_active (GTK_COMBO_BOX(info->settings_combo), 0);
2382 
2383  info->combo_hbox = GTK_WIDGET(gtk_builder_get_object (builder, "combo_hbox"));
2384  gtk_box_pack_start (GTK_BOX(info->combo_hbox), info->settings_combo, FALSE, FALSE, 6);
2385  gtk_widget_show (info->settings_combo);
2386 
2387  g_signal_connect (G_OBJECT(info->settings_combo), "changed",
2388  G_CALLBACK(csv_import_trans_changed_settings_cb), (gpointer)info);
2389 
2390  // Add Save Settings button
2391  save_button = gtk_button_new_with_label (_("Save Settings"));
2392  gtk_box_pack_start (GTK_BOX(info->combo_hbox), save_button, FALSE, FALSE, 6);
2393  gtk_widget_show (save_button);
2394 
2395  g_signal_connect (G_OBJECT(save_button), "clicked",
2396  G_CALLBACK(csv_import_trans_save_settings_cb), (gpointer)info);
2397 
2398  // Add Deelete Settings button
2399  del_button = gtk_button_new_with_label (_("Delete Settings"));
2400  gtk_box_pack_start (GTK_BOX(info->combo_hbox), del_button, FALSE, FALSE, 6);
2401  gtk_widget_show (del_button);
2402 
2403  g_signal_connect (G_OBJECT(del_button), "clicked",
2404  G_CALLBACK(csv_import_trans_delete_settings_cb), (gpointer)info);
2405 
2406  /* The table containing info->encselector and the separator configuration widgets */
2407  info->start_row_spin = GTK_WIDGET(gtk_builder_get_object (builder, "start_row"));
2408  info->end_row_spin = GTK_WIDGET(gtk_builder_get_object (builder, "end_row"));
2409  info->skip_rows = GTK_WIDGET(gtk_builder_get_object (builder, "skip_rows"));
2410  info->check_label = GTK_WIDGET(gtk_builder_get_object (builder, "check_label"));
2411  info->check_butt = GTK_WIDGET(gtk_builder_get_object (builder, "check_butt"));
2412 
2413  info->encselector = GO_CHARMAP_SEL(go_charmap_sel_new(GO_CHARMAP_SEL_TO_UTF8));
2414  /* Connect the selector to the encoding_selected event handler. */
2415  g_signal_connect (G_OBJECT(info->encselector), "charmap_changed",
2416  G_CALLBACK(encoding_selected), (gpointer)info);
2417 
2418  /* Load the separator buttons from the glade builder file into the
2419  * info->sep_buttons array. */
2420  for (i = 0; i < SEP_NUM_OF_TYPES; i++)
2421  {
2422  info->sep_buttons[i]
2423  = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, sep_button_names[i]));
2424  /* Connect them to the sep_button_clicked event handler. */
2425  g_signal_connect (G_OBJECT(info->sep_buttons[i]), "toggled",
2426  G_CALLBACK(sep_button_clicked), (gpointer)info);
2427  }
2428 
2429  /* Load and connect the custom separator checkbutton in the same way
2430  * as the other separator buttons. */
2431  info->custom_cbutton
2432  = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_cbutton"));
2433  g_signal_connect (G_OBJECT(info->custom_cbutton), "clicked",
2434  G_CALLBACK(sep_button_clicked), (gpointer)info);
2435 
2436  /* Load the entry for the custom separator entry. Connect it to the
2437  * sep_button_clicked event handler as well. */
2438  info->custom_entry = (GtkEntry*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_entry"));
2439  g_signal_connect (G_OBJECT(info->custom_entry), "changed",
2440  G_CALLBACK(sep_button_clicked), (gpointer)info);
2441 
2442  /* Get the table from the Glade builder file. */
2443  enctable = GTK_TABLE(gtk_builder_get_object (builder, "enctable"));
2444  /* Put the selector in at the top. */
2445  gtk_table_attach_defaults (enctable, GTK_WIDGET(info->encselector), 1, 2, 0, 1);
2446  /* Show the table in all its glory. */
2447  gtk_widget_show_all (GTK_WIDGET(enctable));
2448 
2449  /* The instructions label and image */
2450  info->instructions_label = GTK_LABEL(gtk_builder_get_object (builder, "instructions_label"));
2451  info->instructions_image = GTK_IMAGE(gtk_builder_get_object (builder, "instructions_image"));
2452 
2453  /* Add in the date format combo box and hook it up to an event handler. */
2454  info->date_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
2455  for (i = 0; i < num_date_formats; i++)
2456  {
2457  gtk_combo_box_text_append_text (info->date_format_combo, _(date_format_user[i]));
2458  }
2459  gtk_combo_box_set_active (GTK_COMBO_BOX(info->date_format_combo), 0);
2460  g_signal_connect (G_OBJECT(info->date_format_combo), "changed",
2461  G_CALLBACK(date_format_selected), (gpointer)info);
2462 
2463  /* Add it to the assistant. */
2464  date_format_container = GTK_CONTAINER(gtk_builder_get_object (builder, "date_format_container"));
2465  gtk_container_add (date_format_container, GTK_WIDGET(info->date_format_combo));
2466  gtk_widget_show_all (GTK_WIDGET(date_format_container));
2467 
2468  /* Add in the currency format combo box and hook it up to an event handler. */
2469  info->currency_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
2470  for (i = 0; i < num_currency_formats; i++)
2471  {
2472  gtk_combo_box_text_append_text (info->currency_format_combo, _(currency_format_user[i]));
2473  }
2474  /* Default will the locale */
2475  gtk_combo_box_set_active (GTK_COMBO_BOX(info->currency_format_combo), 0);
2476  g_signal_connect (G_OBJECT(info->currency_format_combo), "changed",
2477  G_CALLBACK(currency_format_selected), (gpointer)info);
2478 
2479  /* Add it to the assistant. */
2480  currency_format_container = GTK_CONTAINER(gtk_builder_get_object (builder, "currency_format_container"));
2481  gtk_container_add (currency_format_container, GTK_WIDGET(info->currency_format_combo));
2482  gtk_widget_show_all (GTK_WIDGET(currency_format_container));
2483 
2484  /* Connect the CSV/Fixed-Width radio button event handler. */
2485  info->csv_button = GTK_WIDGET(gtk_builder_get_object (builder, "csv_button"));
2486  info->fixed_button = GTK_WIDGET(gtk_builder_get_object (builder, "fixed_button"));
2487  g_signal_connect (info->csv_button, "toggled",
2488  G_CALLBACK(separated_or_fixed_selected), (gpointer)info);
2489 
2490  /* Load the data treeview and connect it to its resizing event handler. */
2491  info->treeview = (GtkTreeView*)GTK_WIDGET(gtk_builder_get_object (builder, "treeview"));
2492 
2493  /* Load the column type treeview. */
2494  info->ctreeview = (GtkTreeView*)GTK_WIDGET(gtk_builder_get_object (builder, "ctreeview"));
2495 
2496  /* This is TRUE only after encoding_selected is called, so we must
2497  * set it initially to FALSE. */
2498  info->encoding_selected_called = FALSE;
2499 
2500  /* It is empty at first. */
2501  info->not_empty = FALSE;
2502  }
2503 
2504  /* Account page */
2505  /* Initialise the Account Picker and add to the Assistant */
2506  info->account_page = GTK_WIDGET(gtk_builder_get_object (builder, "account_page"));
2508  info->account_label = GTK_WIDGET(gtk_builder_get_object (builder, "account_label"));
2509 
2510  /* Matcher page */
2511  info->match_page = GTK_WIDGET(gtk_builder_get_object (builder, "match_page"));
2512  info->match_label = GTK_WIDGET(gtk_builder_get_object (builder, "match_label"));
2513 
2514  /* Summary Page */
2515  info->summary_label = GTK_WIDGET(gtk_builder_get_object (builder, "summary_label"));
2516 
2517  g_signal_connect (G_OBJECT(window), "destroy",
2518  G_CALLBACK (csv_import_trans_assistant_destroy_cb), info);
2519 
2520  gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(info->window));
2521 
2522  gtk_builder_connect_signals (builder, info);
2523  g_object_unref (G_OBJECT(builder));
2524  return window;
2525 }
2526 
2527 
2528 /********************************************************************\
2529  * gnc_file_csv_trans_import *
2530  * opens up a assistant to import accounts. *
2531  * *
2532  * Args: import_type *
2533  * Return: nothing *
2534 \********************************************************************/
2535 void
2537 {
2538  CsvImportTrans *info;
2539 
2540  info = g_new0 (CsvImportTrans, 1);
2541 
2542  /* In order to trigger a book options display on the creation of a new book,
2543  * we need to detect when we are dealing with a new book. */
2544  info->new_book = gnc_is_new_book();
2545 
2546  csv_import_trans_assistant_create (info);
2547 
2548  gnc_register_gui_component (ASSISTANT_CSV_IMPORT_TRANS_CM_CLASS,
2549  NULL, csv_import_trans_close_handler,
2550  info);
2551 
2552  gtk_widget_show_all (info->window);
2553 
2554  gnc_window_adjust_for_screen (GTK_WINDOW(info->window));
2555 }
Functions to load, save and get gui state.
GPtrArray * orig_lines
int gnc_csv_convert_encoding(GncCsvParseData *parse_data, const char *encoding, GError **error)
utility functions for the GnuCash UI
GtkCheckButton * sep_buttons[SEP_NUM_OF_TYPES]
int gnc_csv_parse_to_trans(GncCsvParseData *parse_data, Account *account, gboolean redo_errors)
CSV Import Assistant.
#define DEBUG(format, args...)
Definition: qoflog.h:255
GncCsvParseData * parse_data
void on_matcher_help_clicked(GtkButton *button, gpointer user_data)
Transaction matcher main window.
gchar * gnc_uri_get_path(const gchar *uri)
CsvSettings * gnc_csv_trans_new_settings_data(void)
Generic and very flexible account matcher/picker.
void gnc_csv_trans_settings_data_free(CsvSettings *settings_data)
time64 parse_date(const char *date_str, int format)
GKeyFile * gnc_state_get_current(void)
Definition: gnc-state.c:252
void gnc_gen_trans_list_add_trans(GNCImportMainMatcher *gui, Transaction *trans)
void gnc_csv_parse_data_free(GncCsvParseData *parse_data)
GtkComboBoxText * date_format_combo
GNCImportMainMatcher * gnc_csv_importer_gui
GncCsvStr file_str
void gnc_gen_trans_assist_start(GNCImportMainMatcher *info)
GtkComboBoxText * currency_format_combo
AccountPickerDialog * account_picker
StfParseOptions_t * options
GncCsvParseData * gnc_csv_new_parse_data(void)
CSV Import Settings.
int gnc_csv_parse(GncCsvParseData *parse_data, gboolean guessColTypes, GError **error)
gboolean gnc_csv_trans_save_settings(CsvSettings *settings_data, gchar *settings_name)
GList * transactions
void gnc_csv_trans_find_settings(GtkTreeModel *settings_store)
GtkCheckButton * custom_cbutton
CSV import GUI.
void gnc_gen_trans_list_delete(GNCImportMainMatcher *info)
AccountPickerDialog * gnc_import_account_assist_setup(GtkWidget *parent)
Utility functions for convert uri in separate components and back.
Account * gnc_import_account_assist_update(AccountPickerDialog *picker)
GArray * column_types
void gnc_file_csv_trans_import(void)
gboolean gnc_csv_trans_load_settings(CsvSettings *settings_data, gchar *group)
gboolean skip_rows
int gnc_csv_load_file(GncCsvParseData *parse_data, const char *filename, GError **error)
GNCImportMainMatcher * gnc_gen_trans_assist_new(GtkWidget *parent, const gchar *heading, gboolean all_from_same_account, gint match_date_hardlimit)
const gchar * QofLogModule
Definition: qofid.h:89