r22086 - gnucash/trunk - Bug #672161: New CSV account and transaction importer

Christian Stimming cstim at code.gnucash.org
Fri Mar 16 16:26:23 EDT 2012


Author: cstim
Date: 2012-03-16 16:26:22 -0400 (Fri, 16 Mar 2012)
New Revision: 22086
Trac: http://svn.gnucash.org/trac/changeset/22086

Added:
   gnucash/trunk/src/import-export/csv-import/
   gnucash/trunk/src/import-export/csv-import/Makefile.am
   gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.c
   gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.glade
   gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.h
   gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.c
   gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.glade
   gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.h
   gnucash/trunk/src/import-export/csv-import/csv-account-import.c
   gnucash/trunk/src/import-export/csv-import/csv-account-import.h
   gnucash/trunk/src/import-export/csv-import/gnc-csv-gnumeric-popup.c
   gnucash/trunk/src/import-export/csv-import/gnc-csv-gnumeric-popup.h
   gnucash/trunk/src/import-export/csv-import/gnc-csv-import.c
   gnucash/trunk/src/import-export/csv-import/gnc-csv-import.glade
   gnucash/trunk/src/import-export/csv-import/gnc-csv-import.h
   gnucash/trunk/src/import-export/csv-import/gnc-csv-model.c
   gnucash/trunk/src/import-export/csv-import/gnc-csv-model.h
   gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import-ui.xml
   gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import.c
   gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import.h
   gnucash/trunk/src/import-export/csv-import/gncmod-csv-import.c
   gnucash/trunk/src/import-export/csv-import/schemas/
   gnucash/trunk/src/import-export/csv-import/schemas/Makefile.am
   gnucash/trunk/src/import-export/csv-import/schemas/apps_gnucash_dialog_import_csv.schemas.in
Removed:
   gnucash/trunk/src/import-export/csv/Makefile.am
   gnucash/trunk/src/import-export/csv/gnc-csv-gnumeric-popup.c
   gnucash/trunk/src/import-export/csv/gnc-csv-gnumeric-popup.h
   gnucash/trunk/src/import-export/csv/gnc-csv-import.c
   gnucash/trunk/src/import-export/csv/gnc-csv-import.glade
   gnucash/trunk/src/import-export/csv/gnc-csv-import.h
   gnucash/trunk/src/import-export/csv/gnc-csv-model.c
   gnucash/trunk/src/import-export/csv/gnc-csv-model.h
   gnucash/trunk/src/import-export/csv/gnc-plugin-csv-ui.xml
   gnucash/trunk/src/import-export/csv/gnc-plugin-csv.c
   gnucash/trunk/src/import-export/csv/gnc-plugin-csv.h
   gnucash/trunk/src/import-export/csv/gncmod-csv-import.c
Modified:
   gnucash/trunk/configure.ac
   gnucash/trunk/po/POTFILES.in
   gnucash/trunk/src/bin/gnucash-bin.c
   gnucash/trunk/src/import-export/Makefile.am
   gnucash/trunk/src/import-export/dialog-import.glade
   gnucash/trunk/src/import-export/import-account-matcher.c
   gnucash/trunk/src/import-export/import-account-matcher.h
   gnucash/trunk/src/import-export/import-main-matcher.c
   gnucash/trunk/src/import-export/import-main-matcher.h
Log:
Bug #672161: New CSV account and transaction importer

Patch by Robert Fewell:

Firstly, this patch allows for the creating and updating accounts based on the CSV file
being imported. New accounts are created if the commodity required exists and
existing accounts are updated for the four fields: code, description, notes and
colour. This can be used for doing bulk updates of these fields and also for
importing the account structure from another file.

The second part is the change of the existing CSV importer to use an assistant
to guide you through the import. Additional features added is the ability to
specify the start and end row to be imported allowing you to jump over a header
or footer or just import a few rows. A currency format option was added which
was requested in another bug to overcome a problem they were having with the
downloaded format from there bank. You can also associate the account name to a
GnuCash account using the 'online_id' kvp, not sure if this is Ok or whether it
should be a different one.

To achieve the above, I split the dialogs used in import_account_matcher and
import_main_matcher into the dialog and the content so I could load the content
into the assistant saving on duplication, hope this makes sense.

Modified: gnucash/trunk/configure.ac
===================================================================
--- gnucash/trunk/configure.ac	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/configure.ac	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1278,7 +1278,8 @@
   src/import-export/schemas/Makefile
   src/import-export/ofx/Makefile
   src/import-export/ofx/test/Makefile
-  src/import-export/csv/Makefile
+  src/import-export/csv-import/Makefile
+  src/import-export/csv-import/schemas/Makefile
   src/import-export/csv-export/Makefile
   src/import-export/csv-export/schemas/Makefile
   src/import-export/log-replay/Makefile

Modified: gnucash/trunk/po/POTFILES.in
===================================================================
--- gnucash/trunk/po/POTFILES.in	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/po/POTFILES.in	2012-03-16 20:26:22 UTC (rev 22086)
@@ -371,6 +371,18 @@
 src/import-export/csv/gnc-csv-model.c
 src/import-export/csv/gncmod-csv-import.c
 src/import-export/csv/gnc-plugin-csv.c
+src/import-export/csv-import/assistant-csv-account-import.c
+src/import-export/csv-import/assistant-csv-account-import.glade
+src/import-export/csv-import/assistant-csv-trans-import.c
+src/import-export/csv-import/assistant-csv-trans-import.glade
+src/import-export/csv-import/csv-account-import.c
+src/import-export/csv-import/gnc-csv-gnumeric-popup.c
+src/import-export/csv-import/gnc-csv-import.c
+src/import-export/csv-import/gnc-csv-import.glade
+src/import-export/csv-import/gnc-csv-model.c
+src/import-export/csv-import/gncmod-csv-import.c
+src/import-export/csv-import/gnc-plugin-import-csv.c
+src/import-export/csv-import/schemas/apps_gnucash_dialog_import.schemas.in
 src/import-export/csv-export/assistant-csv-export.c
 src/import-export/csv-export/assistant-csv-export.glade
 src/import-export/csv-export/csv-transactions-export.c

Modified: gnucash/trunk/src/bin/gnucash-bin.c
===================================================================
--- gnucash/trunk/src/bin/gnucash-bin.c	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/bin/gnucash-bin.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -569,7 +569,7 @@
         { "gnucash/register/register-gnome", 0, FALSE },
         { "gnucash/import-export/qif-import", 0, FALSE },
         { "gnucash/import-export/ofx", 0, TRUE },
-        { "gnucash/import-export/csv", 0, TRUE },
+        { "gnucash/import-export/csv-import", 0, TRUE },
         { "gnucash/import-export/csv-export", 0, TRUE },
         { "gnucash/import-export/log-replay", 0, TRUE },
         { "gnucash/import-export/aqbanking", 0, TRUE },

Modified: gnucash/trunk/src/import-export/Makefile.am
===================================================================
--- gnucash/trunk/src/import-export/Makefile.am	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/Makefile.am	2012-03-16 20:26:22 UTC (rev 22086)
@@ -5,7 +5,7 @@
     AQBANKING_DIR=aqbanking
 endif
 SUBDIRS = . schemas qif qif-import \
-	${OFX_DIR} ${AQBANKING_DIR} log-replay test csv csv-export
+	${OFX_DIR} ${AQBANKING_DIR} log-replay test csv-import csv-export
 
 pkglib_LTLIBRARIES=libgncmod-generic-import.la
 

Deleted: gnucash/trunk/src/import-export/csv/Makefile.am
===================================================================
--- gnucash/trunk/src/import-export/csv/Makefile.am	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/Makefile.am	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,60 +0,0 @@
-SUBDIRS = .
-
-pkglib_LTLIBRARIES=libgncmod-csv.la
-
-libgncmod_csv_la_SOURCES = \
-  gncmod-csv-import.c \
-  gnc-plugin-csv.c \
-  gnc-csv-import.c \
-  gnc-csv-model.c \
-  gnc-csv-gnumeric-popup.c
-
-noinst_HEADERS = \
-  gnc-plugin-csv.h \
-  gnc-csv-import.h \
-  gnc-csv-model.h \
-  gnc-csv-gnumeric-popup.h
-
-libgncmod_csv_la_LDFLAGS = -avoid-version
-
-libgncmod_csv_la_LIBADD = \
-  ${top_builddir}/src/import-export/libgncmod-generic-import.la \
-  ${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la \
-  ${top_builddir}/src/app-utils/libgncmod-app-utils.la \
-  ${top_builddir}/src/engine/libgncmod-engine.la \
-  ${top_builddir}/src/core-utils/libgnc-core-utils.la \
-  ${top_builddir}/src/gnc-module/libgnc-module.la \
-  ${top_builddir}/lib/stf/libgnc-stf.la \
-  ${top_builddir}/lib/libc/libc-missing.la \
-  ${top_builddir}/src/libqof/qof/libgnc-qof.la \
-  ${GOFFICE_LIBS} \
-  ${GLIB_LIBS}
-
-AM_CPPFLAGS = \
-  -I${top_srcdir}/src \
-  -I${top_srcdir}/src/core-utils \
-  -I${top_srcdir}/src/engine \
-  -I${top_srcdir}/src/gnc-module \
-  -I${top_srcdir}/src/app-utils \
-  -I${top_srcdir}/src/gnome \
-  -I${top_srcdir}/src/gnome-utils \
-  -I${top_srcdir}/src/import-export \
-  -I${top_srcdir}/src/libqof/qof \
-  -I${top_srcdir}/lib/libc \
-  -I${top_srcdir}/lib \
-  ${GCONF_CFLAGS} \
-  ${GUILE_INCS} \
-  ${GLIB_CFLAGS} \
-  $(GOFFICE_CFLAGS)
-
-uidir = $(GNC_UI_DIR)
-ui_DATA = \
-	gnc-plugin-csv-ui.xml
-
-gtkbuilderdir = ${GNC_GTKBUILDER_DIR}
-gtkbuilder_DATA = \
-	gnc-csv-import.glade
-
-EXTRA_DIST = $(ui_DATA) $(gtkbuilder_DATA)
-
-INCLUDES = -DG_LOG_DOMAIN=\"gnc.import.csv\"

Deleted: gnucash/trunk/src/import-export/csv/gnc-csv-gnumeric-popup.c
===================================================================
--- gnucash/trunk/src/import-export/csv/gnc-csv-gnumeric-popup.c	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gnc-csv-gnumeric-popup.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,200 +0,0 @@
-/* The following is code copied from Gnumeric 1.7.8 licensed under the
- * GNU General Public License version 2 and/or version 3. It is from the file
- * gnumeric/src/gui-util.c, and it has been modified slightly to work
- * within GnuCash. */
-
-/* Miguel de Icaza is not sure specifically who from the Gnumeric
- * community is the copyright owner of the code below, so, on his
- * recommendation, here is the full list of Gnumeric authors.
- *
- * Miguel de Icaza, creator.
- * Jody Goldberg, maintainer.
- * Harald Ashburner, Options pricers
- * Sean Atkinson, functions and X-Base importing.
- * Michel Berkelaar, Simplex algorithm for Solver (LP Solve).
- * Jean Brefort, Core charting engine.
- * Grandma Chema Celorio, Tester and sheet copy.
- * Frank Chiulli, OLE support.
- * Kenneth Christiansen, i18n, misc stuff.
- * Zbigniew Chyla, plugin system, i18n.
- * J.H.M. Dassen (Ray), debian packaging.
- * Jeroen Dirks, Simplex algorithm for Solver (LP Solve).
- * Tom Dyas, plugin support.
- * Gergo Erdi, Gnumeric hacker.
- * John Gotts, rpm packaging.
- * Andreas J. Guelzow, Gnumeric hacker.
- * Jon K. Hellan, Gnumeric hacker.
- * Ross Ihaka, special functions.
- * Jukka-Pekka Iivonen, numerous functions and tools.
- * Jakub Jelinek, Gnumeric hacker.
- * Chris Lahey, number format engine.
- * Adrian Likins, documentation, debugging.
- * Takashi Matsuda, original text plugin.
- * Michael Meeks, Excel and OLE2 importing.
- * Lutz Muller, SheetObject improvements.
- * Emmanuel Pacaud, Many plot types for charting engine.
- * Federico M. Quintero, canvas support.
- * Mark Probst, Guile support.
- * Rasca, HTML, troff, LaTeX exporters.
- * Vincent Renardias, original CSV support, French localization.
- * Ariel Rios, Guile support.
- * Uwe Steinmann, Paradox Importer.
- * Arturo Tena, OLE support.
- * Almer S. Tigelaar, Gnumeric hacker.
- * Bruno Unna, Excel bits.
- * Daniel Veillard, XML support.
- * Vladimir Vuksan, financial functions.
- * Morten Welinder, Gnumeric hacker and leak plugging demi-god.
- */
-
-#include "gnc-csv-gnumeric-popup.h"
-
-#include <glib/gi18n.h>
-
-static void
-popup_item_activate (GtkWidget *item, gpointer *user_data)
-{
-    GnumericPopupMenuElement const *elem =
-        g_object_get_data (G_OBJECT (item), "descriptor");
-    GnumericPopupMenuHandler handler =
-        g_object_get_data (G_OBJECT (item), "handler");
-
-    g_return_if_fail (elem != NULL);
-    g_return_if_fail (handler != NULL);
-
-    if (handler (elem, user_data))
-        gtk_widget_destroy (gtk_widget_get_toplevel (item));
-}
-
-static void
-gnumeric_create_popup_menu_list (GSList *elements,
-                                 GnumericPopupMenuHandler handler,
-                                 gpointer user_data,
-                                 int display_filter,
-                                 int sensitive_filter,
-                                 GdkEventButton *event)
-{
-    GtkWidget *menu, *item;
-    char const *trans;
-
-    menu = gtk_menu_new ();
-
-    for (; elements != NULL ; elements = elements->next)
-    {
-        GnumericPopupMenuElement const *element = elements->data;
-        char const * const name = element->name;
-        char const * const pix_name = element->pixmap;
-
-        item = NULL;
-
-        if (element->display_filter != 0 &&
-                !(element->display_filter & display_filter))
-            continue;
-
-        if (name != NULL && *name != '\0')
-        {
-            trans = _(name);
-            item = gtk_image_menu_item_new_with_mnemonic (trans);
-            if (element->sensitive_filter != 0 &&
-                    (element->sensitive_filter & sensitive_filter))
-                gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
-            if (pix_name != NULL)
-            {
-                GtkWidget *image = gtk_image_new_from_stock (pix_name,
-                                   GTK_ICON_SIZE_MENU);
-                gtk_widget_show (image);
-                gtk_image_menu_item_set_image (
-                    GTK_IMAGE_MENU_ITEM (item),
-                    image);
-            }
-        }
-        else
-        {
-            /* separator */
-            item = gtk_menu_item_new ();
-            gtk_widget_set_sensitive (item, FALSE);
-        }
-
-        if (element->index != 0)
-        {
-            g_signal_connect (G_OBJECT (item),
-                              "activate",
-                              G_CALLBACK (&popup_item_activate), user_data);
-            g_object_set_data (
-                G_OBJECT (item), "descriptor", (gpointer)(element));
-            g_object_set_data (
-                G_OBJECT (item), "handler", (gpointer)handler);
-        }
-
-        gtk_widget_show (item);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-    }
-
-    gnumeric_popup_menu (GTK_MENU (menu), event);
-}
-
-void
-gnumeric_create_popup_menu (GnumericPopupMenuElement const *elements,
-                            GnumericPopupMenuHandler handler,
-                            gpointer user_data,
-                            int display_filter, int sensitive_filter,
-                            GdkEventButton *event)
-{
-    int i;
-    GSList *tmp = NULL;
-
-    for (i = 0; elements [i].name != NULL; i++)
-        tmp = g_slist_prepend (tmp, (gpointer)(elements + i));
-
-    tmp = g_slist_reverse (tmp);
-    gnumeric_create_popup_menu_list (tmp, handler, user_data,
-                                     display_filter, sensitive_filter, event);
-    g_slist_free (tmp);
-}
-
-static void
-kill_popup_menu (GtkWidget *widget, GtkMenu *menu)
-{
-    g_return_if_fail (menu != NULL);
-    g_return_if_fail (GTK_IS_MENU (menu));
-
-    g_object_unref (G_OBJECT (menu));
-}
-
-/**
- * gnumeric_popup_menu :
- * @menu : #GtkMenu
- * @event : #GdkEventButton optionally NULL
- *
- * Bring up a popup and if @event is non-NULL ensure that the popup is on the
- * right screen.
- **/
-void
-gnumeric_popup_menu (GtkMenu *menu, GdkEventButton *event)
-{
-    g_return_if_fail (menu != NULL);
-    g_return_if_fail (GTK_IS_MENU (menu));
-
-#if GLIB_CHECK_VERSION(2,10,0) && GTK_CHECK_VERSION(2,8,14)
-    g_object_ref_sink (menu);
-#else
-    g_object_ref (menu);
-    gtk_object_sink (GTK_OBJECT (menu));
-#endif
-
-    if (event)
-        gtk_menu_set_screen (menu,
-                             gdk_drawable_get_screen (event->window));
-
-    g_signal_connect (G_OBJECT (menu),
-                      "hide",
-                      G_CALLBACK (kill_popup_menu), menu);
-
-    /* Do NOT pass the button used to create the menu.
-     * instead pass 0.  Otherwise bringing up a menu with
-     * the right button will disable clicking on the menu with the left.
-     */
-    gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0,
-                    (event != NULL) ? event->time
-                    : gtk_get_current_event_time());
-}

Deleted: gnucash/trunk/src/import-export/csv/gnc-csv-gnumeric-popup.h
===================================================================
--- gnucash/trunk/src/import-export/csv/gnc-csv-gnumeric-popup.h	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gnc-csv-gnumeric-popup.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,79 +0,0 @@
-/* The following is code copied from Gnumeric 1.7.8 licensed under the
- * GNU General Public License version 2 and/or version 3. It is from the file
- * gnumeric/src/gui-util.h, and it has been modified slightly to work
- * within GnuCash. */
-
-/* Miguel de Icaza is not sure specifically who from the Gnumeric
- * community is the copyright owner of the code below, so, on his
- * recommendation, here is the full list of Gnumeric authors.
- *
- * Miguel de Icaza, creator.
- * Jody Goldberg, maintainer.
- * Harald Ashburner, Options pricers
- * Sean Atkinson, functions and X-Base importing.
- * Michel Berkelaar, Simplex algorithm for Solver (LP Solve).
- * Jean Brefort, Core charting engine.
- * Grandma Chema Celorio, Tester and sheet copy.
- * Frank Chiulli, OLE support.
- * Kenneth Christiansen, i18n, misc stuff.
- * Zbigniew Chyla, plugin system, i18n.
- * J.H.M. Dassen (Ray), debian packaging.
- * Jeroen Dirks, Simplex algorithm for Solver (LP Solve).
- * Tom Dyas, plugin support.
- * Gergo Erdi, Gnumeric hacker.
- * John Gotts, rpm packaging.
- * Andreas J. Guelzow, Gnumeric hacker.
- * Jon K. Hellan, Gnumeric hacker.
- * Ross Ihaka, special functions.
- * Jukka-Pekka Iivonen, numerous functions and tools.
- * Jakub Jelinek, Gnumeric hacker.
- * Chris Lahey, number format engine.
- * Adrian Likins, documentation, debugging.
- * Takashi Matsuda, original text plugin.
- * Michael Meeks, Excel and OLE2 importing.
- * Lutz Muller, SheetObject improvements.
- * Emmanuel Pacaud, Many plot types for charting engine.
- * Federico M. Quintero, canvas support.
- * Mark Probst, Guile support.
- * Rasca, HTML, troff, LaTeX exporters.
- * Vincent Renardias, original CSV support, French localization.
- * Ariel Rios, Guile support.
- * Uwe Steinmann, Paradox Importer.
- * Arturo Tena, OLE support.
- * Almer S. Tigelaar, Gnumeric hacker.
- * Bruno Unna, Excel bits.
- * Daniel Veillard, XML support.
- * Vladimir Vuksan, financial functions.
- * Morten Welinder, Gnumeric hacker and leak plugging demi-god.
- */
-
-#ifndef GNC_CSV_GNUMERIC_POPUP
-#define GNC_CSV_GNUMERIC_POPUP
-
-#include <gtk/gtk.h>
-
-typedef struct
-{
-    char const *name;
-    char const *pixmap;
-    int display_filter;
-    int sensitive_filter;
-
-    int index;
-} GnumericPopupMenuElement;
-
-typedef gboolean (*GnumericPopupMenuHandler) (GnumericPopupMenuElement const *e,
-        gpointer user_data);
-
-/* Use this on menus that are popped up */
-void gnumeric_popup_menu (GtkMenu *menu, GdkEventButton *event);
-
-void gnumeric_create_popup_menu (GnumericPopupMenuElement const *elements,
-                                 GnumericPopupMenuHandler handler,
-                                 gpointer user_data,
-                                 int display_filter,
-                                 int sensitive_filter,
-                                 GdkEventButton *event);
-
-
-#endif

Deleted: gnucash/trunk/src/import-export/csv/gnc-csv-import.c
===================================================================
--- gnucash/trunk/src/import-export/csv/gnc-csv-import.c	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gnc-csv-import.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,1216 +0,0 @@
-/*******************************************************************\
- * This program is free software; you can redistribute it and/or    *
- * modify it under the terms of the GNU General Public License as   *
- * published by the Free Software Foundation; either version 2 of   *
- * the License, or (at your option) any later version.              *
- *                                                                  *
- * This program is distributed in the hope that it will be useful,  *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
- * GNU General Public License for more details.                     *
- *                                                                  *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact:                        *
- *                                                                  *
- * Free Software Foundation           Voice:  +1-617-542-5942       *
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
- * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
-\********************************************************************/
-/** @file gnc-csv-import.c
-    @brief CSV Import GUI code
-    @author Copyright (c) 2007 Benny Sperisen <lasindi at gmail.com>
-*/
-#include "config.h"
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-#include <goffice/gtk/go-charmap-sel.h>
-
-#include "import-account-matcher.h"
-#include "import-main-matcher.h"
-
-#include "gnc-file.h"
-#include "gnc-ui-util.h"
-#include "gnc-glib-utils.h"
-#include "gnc-gui-query.h"
-#include "dialog-utils.h"
-
-#include "gnc-csv-import.h"
-#include "gnc-csv-model.h"
-#include "gnc-csv-gnumeric-popup.h"
-
-#define GCONF_SECTION "dialogs/import/csv"
-#define MIN_COL_WIDTH 70
-
-static QofLogModule log_module = GNC_MOD_IMPORT;
-
-/** Enumeration for separator checkbutton types. These are the
- * different types of checkbuttons that the user can click to
- * configure separators in a delimited file. */
-enum SEP_BUTTON_TYPES {SEP_SPACE, SEP_TAB, SEP_COMMA, SEP_COLON, SEP_SEMICOLON, SEP_HYPHEN,
-                       SEP_NUM_OF_TYPES
-                      };
-
-/** Data for the preview dialog. This struct contains all of the data
- * relevant to the preview dialog that lets the user configure an
- * import. */
-typedef struct
-{
-    GncCsvParseData* parse_data;       /**< The actual data we are previewing */
-    GtkDialog* dialog;
-    GOCharmapSel* encselector;         /**< The widget for selecting the encoding */
-    GtkComboBox* date_format_combo;    /**< The widget for selecting the date format */
-    GtkTreeView* treeview;             /**< The treeview containing the data */
-    GtkTreeView* ctreeview;            /**< The treeview containing the column types */
-    GtkCheckButton* sep_buttons[SEP_NUM_OF_TYPES]; /**< Checkbuttons for common separators */
-    GtkCheckButton* custom_cbutton;    /**< The checkbutton for a custom separator */
-    GtkEntry* custom_entry;            /**< The entry for custom separators */
-    GtkLabel* instructions_label;      /**< The instructions label */
-    GtkImage* instructions_image;      /**< The instructions image */
-    gboolean encoding_selected_called; /**< Before encoding_selected is first called, this is FALSE.
-                                        * (See description of encoding_selected.) */
-    gboolean not_empty;                /**< FALSE initially, true after the first type gnc_csv_preview_update is called. */
-    gboolean previewing_errors;        /**< TRUE if the dialog is displaying
-                                       * error lines, instead of all the file data. */
-    int code_encoding_calls;           /**< Normally this is 0. If the computer
-                                       * changes encselector, this is set to
-                                       * 2. encoding_selected is called twice,
-                                       * each time decrementing this by 1. */
-    gboolean approved;                 /**< This is FALSE until the user clicks "OK". */
-    GtkWidget** treeview_buttons;      /**< This array contains the header buttons in treeview */
-    int longest_line;                  /**< The length of the longest row */
-    int fixed_context_col;             /**< The number of the column whose the user has clicked */
-    int fixed_context_dx;              /**< The horizontal coordinate of the pixel in the header of the column
-                                       * the user has clicked */
-} GncCsvPreview;
-
-static void gnc_csv_preview_update(GncCsvPreview* preview);
-
-/** Event handler for separator changes. This function is called
- * whenever one of the widgets for configuring the separators (the
- * separator checkbuttons or the custom separator entry) is
- * changed.
- * @param widget The widget that was changed
- * @param preview The data that is being configured
- */
-static void sep_button_clicked(GtkWidget* widget, GncCsvPreview* preview)
-{
-    int i;
-    char* stock_separator_characters[] = {" ", "\t", ",", ":", ";", "-"};
-    GSList* checked_separators = NULL;
-    GError* error;
-
-    /* Add the corresponding characters to checked_separators for each
-     * button that is checked. */
-    for (i = 0; i < SEP_NUM_OF_TYPES; i++)
-    {
-        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(preview->sep_buttons[i])))
-            checked_separators = g_slist_append(checked_separators, stock_separator_characters[i]);
-    }
-
-    /* Add the custom separator if the user checked its button. */
-    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(preview->custom_cbutton)))
-    {
-        char* custom_sep = (char*)gtk_entry_get_text(preview->custom_entry);
-        if (custom_sep[0] != '\0') /* Don't add a blank separator (bad things will happen!). */
-            checked_separators = g_slist_append(checked_separators, custom_sep);
-    }
-
-    /* Set the parse options using the checked_separators list. */
-    stf_parse_options_csv_set_separators(preview->parse_data->options, NULL, checked_separators);
-    g_slist_free(checked_separators);
-
-    /* Parse the data using the new options. We don't want to reguess
-     * the column types because we want to leave the user's
-     * configurations in tact. */
-    if (gnc_csv_parse(preview->parse_data, FALSE, &error))
-    {
-        /* Warn the user there was a problem and try to undo what caused
-         * the error. (This will cause a reparsing and ideally a usable
-         * configuration.) */
-        gnc_error_dialog(NULL, "Error in parsing");
-        /* If the user changed the custom separator, erase that custom separator. */
-        if (widget == GTK_WIDGET(preview->custom_entry))
-        {
-            gtk_entry_set_text(GTK_ENTRY(widget), "");
-        }
-        /* If the user checked a checkbutton, toggle that checkbutton back. */
-        else
-        {
-            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
-                                         !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
-        }
-        return;
-    }
-
-    /* If we parsed successfully, redisplay the data. */
-    gnc_csv_preview_update(preview);
-}
-
-/** Event handler for clicking one of the format type radio
- * buttons. This occurs if the format (Fixed-Width or CSV) is changed.
- * @param csv_button The "Separated" radio button
- * @param preview The display of the data being imported
- */
-static void separated_or_fixed_selected(GtkToggleButton* csv_button, GncCsvPreview* preview)
-{
-    GError* error = NULL;
-    /* Set the parsing type correctly. */
-    if (gtk_toggle_button_get_active(csv_button)) /* If we're in CSV mode ... */
-    {
-        stf_parse_options_set_type(preview->parse_data->options, PARSE_TYPE_CSV);
-    }
-    else /* If we're in fixed-width mode ... */
-    {
-        stf_parse_options_set_type(preview->parse_data->options, PARSE_TYPE_FIXED);
-    }
-
-    /* Reparse the data. */
-    if (gnc_csv_parse(preview->parse_data, FALSE, &error))
-    {
-        /* Show an error dialog explaining the problem. */
-        gnc_error_dialog(NULL, "%s", error->message);
-        return;
-    }
-
-    /* Show the new data. */
-    gnc_csv_preview_update(preview);
-}
-
-/** Event handler for a new encoding. This is called when the user
- * selects a new encoding; the data is reparsed and shown to the
- * user.
- * @param selector The widget the user uses to select a new encoding
- * @param encoding The encoding that the user selected
- * @param preview The display of the data being imported
- */
-static void encoding_selected(GOCharmapSel* selector, const char* encoding,
-                              GncCsvPreview* preview)
-{
-    /* This gets called twice everytime a new encoding is selected. The
-     * second call actually passes the correct data; thus, we only do
-     * something the second time this is called. */
-
-    /* Prevent code-caused calls of this function from having an impact. */
-    if (preview->code_encoding_calls > 0)
-    {
-        preview->code_encoding_calls--;
-        return;
-    }
-
-    /* If this is the second time the function is called ... */
-    if (preview->encoding_selected_called)
-    {
-        const char* previous_encoding = preview->parse_data->encoding;
-        GError* error = NULL;
-        /* Try converting the new encoding and reparsing. */
-        if (gnc_csv_convert_encoding(preview->parse_data, encoding, &error) ||
-                gnc_csv_parse(preview->parse_data, FALSE, &error))
-        {
-            /* If it fails, change back to the old encoding. */
-            gnc_error_dialog(NULL, "%s", _("Invalid encoding selected"));
-            preview->encoding_selected_called = FALSE;
-            go_charmap_sel_set_encoding(selector, previous_encoding);
-            return;
-        }
-
-        gnc_csv_preview_update(preview);
-        preview->encoding_selected_called = FALSE;
-    }
-    else /* If this is the first call of the function ... */
-    {
-        preview->encoding_selected_called = TRUE; /* ... set the flag and wait for the next call. */
-    }
-}
-
-/** Event handler for selecting a new date format.
- * @param format_selector The combo box for selecting date formats
- * @param preview The display of the data being imported
- */
-static void date_format_selected(GtkComboBox* format_selector, GncCsvPreview* preview)
-{
-    preview->parse_data->date_format = gtk_combo_box_get_active(format_selector);
-}
-
-/** Event handler for the "OK" button. When "OK" is clicked, this
- * function updates the parse data with the user's column type
- * configuration and closes the preview dialog.
- * @param widget The "OK" button
- * @param preview The display of the data being imported
- */
-static void ok_button_clicked(GtkWidget* widget, GncCsvPreview* preview)
-{
-    /* Shorten the column_types identifier. */
-    GArray* column_types = preview->parse_data->column_types;
-    int i, ncols = column_types->len; /* ncols is the number of columns in the data. */
-    /* store contains the actual strings appearing in the column types treeview. */
-    GtkTreeModel* store = gtk_tree_view_get_model(preview->ctreeview);
-    GtkTreeIter iter;
-    /* Get an iterator for the first (and only) row. */
-    gtk_tree_model_get_iter_first(store, &iter);
-
-    /* Go through each of the columns. */
-    for (i = 0; i < ncols; i++)
-    {
-        int type; /* The column type contained in this column. */
-        gchar* contents = NULL; /* The column type string in this column. */
-        /* Get the type string first. (store is arranged so that every two
-         * columns is a pair of the model used for the combobox and the
-         * string that appears, so that store looks like:
-         * model 0, string 0, model 1, string 1, ..., model ncols, string ncols. */
-        gtk_tree_model_get(store, &iter, 2 * i + 1, &contents, -1);
-
-        /* Go through each column type until ... */
-        for (type = 0; type < GNC_CSV_NUM_COL_TYPES; type++)
-        {
-            /* ... we find one that matches with what's in the column. */
-            if (!safe_strcmp(contents, _(gnc_csv_column_type_strs[type])))
-            {
-                /* Set the column_types array appropriately and quit. */
-                column_types->data[i] = type;
-                break;
-            }
-        }
-        /* Free the type string created by gtk_tree_model_get() */
-        g_free(contents);
-    }
-
-    /* Close the dialog. */
-    gtk_widget_hide((GtkWidget*)(preview->dialog));
-    preview->approved = TRUE; /* The user has wants to do the import. */
-}
-
-/** Event handler for the "Cancel" button. When the user clicks
- * "Cancel", the dialog is simply closed.
- * @param widget The "Cancel" button
- * @param preview The display of the data being imported
- */
-static void cancel_button_clicked(GtkWidget* widget, GncCsvPreview* preview)
-{
-    gtk_widget_hide((GtkWidget*)(preview->dialog));
-}
-
-/** Event handler for the data treeview being resized. When the data
- * treeview is resized, the column types treeview's columns are also resized to
- * match.
- * @param widget The data treeview
- * @param allocation The size of the data treeview
- * @param preview The display of the data being imported
- */
-static void treeview_resized(GtkWidget* widget, GtkAllocation* allocation, GncCsvPreview* preview)
-{
-    /* ncols is the number of columns in the data. */
-    int i, ncols = preview->parse_data->column_types->len;
-
-    /* Go through each column except for the last. (We don't want to set
-     * the width of the last column because the user won't be able to
-     * shrink the dialog back if it's expanded.) */
-    for (i = 0; i < ncols - 1; i++)
-    {
-        gint col_width; /* The width of the column in preview->treeview. */
-        GtkTreeViewColumn* pcol;
-        GtkTreeViewColumn* ccol; /* The corresponding column in preview->ctreeview. */
-
-        /* Get the width. */
-        col_width = gtk_tree_view_column_get_width(gtk_tree_view_get_column(preview->treeview, i));
-        /* Set the minumum width for a column so that drop down selector can be seen. */
-        if (col_width < MIN_COL_WIDTH)
-        {
-            col_width = MIN_COL_WIDTH;
-        }
-        pcol = gtk_tree_view_get_column(preview->treeview, i);
-        gtk_tree_view_column_set_min_width(pcol, col_width);
-        /* Set ccol's width the same. */
-        ccol = gtk_tree_view_get_column(preview->ctreeview, i);
-        gtk_tree_view_column_set_min_width(ccol, col_width);
-        gtk_tree_view_column_set_max_width(ccol, col_width);
-    }
-}
-
-/** Event handler for the user selecting a new column type. When the
- * user selects a new column type, that column's text must be changed
- * to that selection, and any other columns containing that selection
- * must be changed to "None" because we don't allow duplicates.
- * @param renderer The renderer of the column the user changed
- * @param path There is only 1 row in preview->ctreeview, so this is always 0.
- * @param new_text The text the user selected
- * @param preview The display of the data being imported
- */
-static void column_type_changed(GtkCellRenderer* renderer, gchar* path,
-                                GtkTreeIter* new_text_iter, GncCsvPreview* preview)
-{
-    /* ncols is the number of columns in the data. */
-    int i, ncols = preview->parse_data->column_types->len;
-    /* store has the actual strings that appear in preview->ctreeview. */
-    GtkTreeModel* store = gtk_tree_view_get_model(preview->ctreeview);
-    GtkTreeModel* model;
-    gint textColumn;
-    GtkTreeIter iter;
-    gchar* new_text;
-
-    /* Get the new text */
-    g_object_get(renderer, "model", &model, "text-column", &textColumn, NULL);
-    gtk_tree_model_get(model, new_text_iter, textColumn, &new_text, -1);
-
-    /* Get an iterator for the first (and only) row. */
-    gtk_tree_model_get_iter_first(store, &iter);
-
-    /* Go through each column. */
-    for (i = 0; i < ncols; i++)
-    {
-        /* We need all this stuff so that we can find out whether or not
-         * this was the column that was changed. */
-        GtkCellRenderer* col_renderer; /* The renderer for this column. */
-        /* The column in the treeview we are looking at */
-        GtkTreeViewColumn* col = gtk_tree_view_get_column(preview->ctreeview, i);
-        /* The list of renderers for col */
-        GList* rend_list = gtk_tree_view_column_get_cell_renderers(col);
-        /* rend_list has only one entry, which we put in col_renderer. */
-        col_renderer = rend_list->data;
-        g_list_free(rend_list);
-
-        /* If this is not the column that was changed ... */
-        if (col_renderer != renderer)
-        {
-            /* The string that appears in the column */
-            gchar* contents = NULL;
-            /* Get the type string. (store is arranged so that every two
-             * columns is a pair of the model used for the combobox and the
-             * string that appears, so that store looks like:
-             * model 0, string 0, model 1, string 1, ..., model ncols, string ncols. */
-            gtk_tree_model_get(store, &iter, 2 * i + 1, &contents, -1);
-            /* If this column has the same string that the user selected ... */
-            if (!safe_strcmp(contents, new_text))
-            {
-                /* ... set this column to the "None" type. (We can't allow duplicate types.) */
-                gtk_list_store_set(GTK_LIST_STORE(store), &iter, 2 * i + 1,
-                                   _(gnc_csv_column_type_strs[GNC_CSV_NONE]), -1);
-            }
-            g_free(contents);
-        }
-        else /* If this is the column that was changed ... */
-        {
-            /* Set the text for this column to what the user selected. (See
-             * comment above "Get the type string. ..." for why we set
-             * column 2*i+1 in store.) */
-            gtk_list_store_set(GTK_LIST_STORE(store), &iter, 2 * i + 1, new_text, -1);
-        }
-    }
-}
-
-/** Constructor for GncCsvPreview.
- * @return A new GncCsvPreview* ready for use.
- */
-static GncCsvPreview* gnc_csv_preview_new()
-{
-    int i;
-    GncCsvPreview* preview = g_new(GncCsvPreview, 1);
-    GtkWidget *ok_button, *cancel_button, *csv_button;
-    GtkContainer* date_format_container;
-    GtkBuilder *builder;
-    /* The names in the glade builder file for the sep buttons. */
-    char* sep_button_names[] = {"space_cbutton",
-                                "tab_cbutton",
-                                "comma_cbutton",
-                                "colon_cbutton",
-                                "semicolon_cbutton",
-                                "hyphen_cbutton"
-                               };
-    /* The table containing preview->encselector and the separator configuration widgets */
-    GtkTable* enctable;
-    PangoContext* context; /* Used to set a monotype font on preview->treeview */
-
-    preview->encselector = GO_CHARMAP_SEL(go_charmap_sel_new(GO_CHARMAP_SEL_TO_UTF8));
-    /* Connect the selector to the encoding_selected event handler. */
-    g_signal_connect(G_OBJECT(preview->encselector), "charmap_changed",
-                     G_CALLBACK(encoding_selected), (gpointer)preview);
-
-    /* Load the Glade builder file. */
-    builder = gtk_builder_new();
-    gnc_builder_add_from_file (builder, "gnc-csv-import.glade", "preview-dialog");
-
-    /* Load the dialog. */
-    preview->dialog = GTK_DIALOG(gtk_builder_get_object (builder, "preview-dialog"));
-
-    /* Load the separator buttons from the glade builder file into the
-     * preview->sep_buttons array. */
-    for (i = 0; i < SEP_NUM_OF_TYPES; i++)
-    {
-        preview->sep_buttons[i]
-        = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, sep_button_names[i]));
-        /* Connect them to the sep_button_clicked event handler. */
-        g_signal_connect(G_OBJECT(preview->sep_buttons[i]), "toggled",
-                         G_CALLBACK(sep_button_clicked), (gpointer)preview);
-    }
-
-    /* Load and connect the custom separator checkbutton in the same way
-     * as the other separator buttons. */
-    preview->custom_cbutton
-    = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_cbutton"));
-    g_signal_connect(G_OBJECT(preview->custom_cbutton), "clicked",
-                     G_CALLBACK(sep_button_clicked), (gpointer)preview);
-
-    /* Load the entry for the custom separator entry. Connect it to the
-     * sep_button_clicked event handler as well. */
-    preview->custom_entry = (GtkEntry*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_entry"));
-    g_signal_connect(G_OBJECT(preview->custom_entry), "changed",
-                     G_CALLBACK(sep_button_clicked), (gpointer)preview);
-
-    /* Get the table from the Glade builder file. */
-    enctable = GTK_TABLE(gtk_builder_get_object (builder, "enctable"));
-    /* Put the selector in at the top. */
-    gtk_table_attach_defaults(enctable, GTK_WIDGET(preview->encselector), 1, 2, 0, 1);
-    /* Show the table in all its glory. */
-    gtk_widget_show_all(GTK_WIDGET(enctable));
-
-    /* The instructions label and image */
-    preview->instructions_label = GTK_LABEL(gtk_builder_get_object (builder, "instructions_label"));
-    preview->instructions_image = GTK_IMAGE(gtk_builder_get_object (builder, "instructions_image"));
-
-    /* Add in the date format combo box and hook it up to an event handler. */
-    preview->date_format_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
-    for (i = 0; i < num_date_formats; i++)
-    {
-        gtk_combo_box_append_text(preview->date_format_combo, _(date_format_user[i]));
-    }
-    gtk_combo_box_set_active(preview->date_format_combo, 0);
-    g_signal_connect(G_OBJECT(preview->date_format_combo), "changed",
-                     G_CALLBACK(date_format_selected), (gpointer)preview);
-
-    /* Add it to the dialog. */
-    date_format_container = GTK_CONTAINER(gtk_builder_get_object (builder, "date_format_container"));
-    gtk_container_add(date_format_container, GTK_WIDGET(preview->date_format_combo));
-    gtk_widget_show_all(GTK_WIDGET(date_format_container));
-
-    /* Connect the "OK" and "Cancel" buttons to their event handlers. */
-    ok_button = GTK_WIDGET(gtk_builder_get_object (builder, "ok_button"));
-    g_signal_connect(G_OBJECT(ok_button), "clicked",
-                     G_CALLBACK(ok_button_clicked), (gpointer)preview);
-
-    cancel_button = GTK_WIDGET(gtk_builder_get_object (builder, "cancel_button"));
-    g_signal_connect(G_OBJECT(cancel_button), "clicked",
-                     G_CALLBACK(cancel_button_clicked), (gpointer)preview);
-
-    /* Connect the CSV/Fixed-Width radio button event handler. */
-    csv_button = GTK_WIDGET(gtk_builder_get_object (builder, "csv_button"));
-    g_signal_connect(csv_button, "toggled",
-                     G_CALLBACK(separated_or_fixed_selected), (gpointer)preview);
-
-    /* Load the data treeview and connect it to its resizing event handler. */
-    preview->treeview = (GtkTreeView*)GTK_WIDGET(gtk_builder_get_object (builder, "treeview"));
-    g_signal_connect(G_OBJECT(preview->treeview), "size-allocate",
-                     G_CALLBACK(treeview_resized), (gpointer)preview);
-    context = gtk_widget_create_pango_context(GTK_WIDGET(preview->treeview));
-
-    /* Load the column type treeview. */
-    preview->ctreeview = (GtkTreeView*)GTK_WIDGET(gtk_builder_get_object (builder, "ctreeview"));
-
-    /* This is TRUE only after encoding_selected is called, so we must
-     * set it initially to FALSE. */
-    preview->encoding_selected_called = FALSE;
-
-    /* It is empty at first. */
-    preview->not_empty = FALSE;
-
-    g_object_unref(G_OBJECT(builder));
-
-    return preview;
-}
-
-/** Destructor for GncCsvPreview. This does not free
- * preview->parse_data, which must be freed separately.
- * @param preview The preview whose memory is freed.
- */
-static void gnc_csv_preview_free(GncCsvPreview* preview)
-{
-    g_free(preview);
-}
-
-/** Returns the cell renderer from a column in the preview's treeview.
- * @param preview The display of the data being imported
- * @param col The number of the column whose cell renderer is being retrieved
- * @return The cell renderer of column number col
- */
-static GtkCellRenderer* gnc_csv_preview_get_cell_renderer(GncCsvPreview* preview, int col)
-{
-    GList* renderers = gtk_tree_view_column_get_cell_renderers(gtk_tree_view_get_column(preview->treeview, col));
-    GtkCellRenderer* cell = GTK_CELL_RENDERER(renderers->data);
-    g_list_free(renderers);
-    return cell;
-}
-
-/* The following is code copied from Gnumeric 1.7.8 licensed under the
- * GNU General Public License version 2 and/or version 3. It is from the file
- * gnumeric/src/dialogs/dialog-stf-fixed-page.c, and it has been
- * modified slightly to work within GnuCash. */
-
-/* ---- Beginning of Gnumeric Code ---- */
-
-/*
- * Copyright 2001 Almer S. Tigelaar <almer at gnome.org>
- * Copyright 2003 Morten Welinder <terra at gnome.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-enum
-{
-    CONTEXT_STF_IMPORT_MERGE_LEFT = 1,
-    CONTEXT_STF_IMPORT_MERGE_RIGHT = 2,
-    CONTEXT_STF_IMPORT_SPLIT = 3,
-    CONTEXT_STF_IMPORT_WIDEN = 4,
-    CONTEXT_STF_IMPORT_NARROW = 5
-};
-
-static GnumericPopupMenuElement const popup_elements[] =
-{
-    {
-        N_("Merge with column on _left"), GTK_STOCK_REMOVE,
-        0, 1 << CONTEXT_STF_IMPORT_MERGE_LEFT, CONTEXT_STF_IMPORT_MERGE_LEFT
-    },
-    {
-        N_("Merge with column on _right"), GTK_STOCK_REMOVE,
-        0, 1 << CONTEXT_STF_IMPORT_MERGE_RIGHT, CONTEXT_STF_IMPORT_MERGE_RIGHT
-    },
-    { "", NULL, 0, 0, 0 },
-    {
-        N_("_Split this column"), NULL,
-        0, 1 << CONTEXT_STF_IMPORT_SPLIT, CONTEXT_STF_IMPORT_SPLIT
-    },
-    { "", NULL, 0, 0, 0 },
-    {
-        N_("_Widen this column"), GTK_STOCK_GO_FORWARD,
-        0, 1 << CONTEXT_STF_IMPORT_WIDEN, CONTEXT_STF_IMPORT_WIDEN
-    },
-    {
-        N_("_Narrow this column"), GTK_STOCK_GO_BACK,
-        0, 1 << CONTEXT_STF_IMPORT_NARROW, CONTEXT_STF_IMPORT_NARROW
-    },
-    { NULL, NULL, 0, 0, 0 },
-};
-
-static gboolean
-make_new_column (GncCsvPreview *preview, int col, int dx, gboolean test_only)
-{
-    PangoLayout *layout;
-    PangoFontDescription *font_desc;
-    int charindex, width;
-    GtkCellRenderer *cell =	gnc_csv_preview_get_cell_renderer(preview, col);
-    int colstart, colend;
-    GError* error = NULL;
-
-    colstart = (col == 0)
-               ? 0
-               : stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col - 1);
-    colend = stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col);
-
-    g_object_get (G_OBJECT (cell), "font_desc", &font_desc, NULL);
-    layout = gtk_widget_create_pango_layout (GTK_WIDGET (preview->treeview), "x");
-    pango_layout_set_font_description (layout, font_desc);
-    pango_layout_get_pixel_size (layout, &width, NULL);
-    if (width < 1) width = 1;
-    charindex = colstart + (dx + width / 2) / width;
-    g_object_unref (layout);
-    pango_font_description_free (font_desc);
-
-    if (charindex <= colstart || (colend != -1 && charindex >= colend))
-        return FALSE;
-
-    if (!test_only)
-    {
-        stf_parse_options_fixed_splitpositions_add (preview->parse_data->options, charindex);
-        if (gnc_csv_parse(preview->parse_data, FALSE, &error))
-        {
-            gnc_error_dialog(NULL, "%s", error->message);
-            return FALSE;
-        }
-        gnc_csv_preview_update (preview);
-    }
-
-    return TRUE;
-}
-
-
-static gboolean
-widen_column (GncCsvPreview *preview, int col, gboolean test_only)
-{
-    int colcount = stf_parse_options_fixed_splitpositions_count (preview->parse_data->options);
-    int nextstart, nextnextstart;
-    GError* error = NULL;
-
-    if (col >= colcount - 1)
-        return FALSE;
-
-    nextstart = stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col);
-
-    nextnextstart = (col == colcount - 2)
-                    ? preview->longest_line
-                    : stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col + 1);
-
-    if (nextstart + 1 >= nextnextstart)
-        return FALSE;
-
-    if (!test_only)
-    {
-        stf_parse_options_fixed_splitpositions_remove (preview->parse_data->options, nextstart);
-        stf_parse_options_fixed_splitpositions_add (preview->parse_data->options, nextstart + 1);
-        if (gnc_csv_parse(preview->parse_data, FALSE, &error))
-        {
-            gnc_error_dialog(NULL, "%s", error->message);
-            return FALSE;
-        }
-        gnc_csv_preview_update (preview);
-    }
-    return TRUE;
-}
-
-static gboolean
-narrow_column (GncCsvPreview *preview, int col, gboolean test_only)
-{
-    int colcount = stf_parse_options_fixed_splitpositions_count (preview->parse_data->options);
-    int thisstart, nextstart;
-    GError* error = NULL;
-
-    if (col >= colcount - 1)
-        return FALSE;
-
-    thisstart = (col == 0)
-                ? 0
-                : stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col - 1);
-    nextstart = stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col);
-
-    if (nextstart - 1 <= thisstart)
-        return FALSE;
-
-    if (!test_only)
-    {
-        stf_parse_options_fixed_splitpositions_remove (preview->parse_data->options, nextstart);
-        stf_parse_options_fixed_splitpositions_add (preview->parse_data->options, nextstart - 1);
-        if (gnc_csv_parse(preview->parse_data, FALSE, &error))
-        {
-            gnc_error_dialog(NULL, "%s", error->message);
-            return FALSE;
-        }
-        gnc_csv_preview_update (preview);
-    }
-    return TRUE;
-}
-
-static gboolean
-delete_column (GncCsvPreview *preview, int col, gboolean test_only)
-{
-    GError* error = NULL;
-    int colcount = stf_parse_options_fixed_splitpositions_count (preview->parse_data->options);
-    if (col < 0 || col >= colcount - 1)
-        return FALSE;
-
-    if (!test_only)
-    {
-        int nextstart = stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col);
-        stf_parse_options_fixed_splitpositions_remove (preview->parse_data->options, nextstart);
-        if (gnc_csv_parse(preview->parse_data, FALSE, &error))
-        {
-            gnc_error_dialog(NULL, "%s", error->message);
-            return FALSE;
-        }
-        gnc_csv_preview_update (preview);
-    }
-    return TRUE;
-}
-
-static void
-select_column (GncCsvPreview *preview, int col)
-{
-    GError* error = NULL;
-    int colcount = stf_parse_options_fixed_splitpositions_count (preview->parse_data->options);
-    GtkTreeViewColumn *column;
-
-    if (col < 0 || col >= colcount)
-        return;
-
-    column = gtk_tree_view_get_column (preview->treeview, col);
-    gtk_widget_grab_focus (column->button);
-}
-
-static gboolean
-fixed_context_menu_handler (GnumericPopupMenuElement const *element,
-                            gpointer user_data)
-{
-    GncCsvPreview *preview = user_data;
-    int col = preview->fixed_context_col;
-
-    switch (element->index)
-    {
-    case CONTEXT_STF_IMPORT_MERGE_LEFT:
-        delete_column (preview, col - 1, FALSE);
-        break;
-    case CONTEXT_STF_IMPORT_MERGE_RIGHT:
-        delete_column (preview, col, FALSE);
-        break;
-    case CONTEXT_STF_IMPORT_SPLIT:
-        make_new_column (preview, col, preview->fixed_context_dx, FALSE);
-        break;
-    case CONTEXT_STF_IMPORT_WIDEN:
-        widen_column (preview, col, FALSE);
-        break;
-    case CONTEXT_STF_IMPORT_NARROW:
-        narrow_column (preview, col, FALSE);
-        break;
-    default:
-        ; /* Nothing */
-    }
-    return TRUE;
-}
-
-static void
-fixed_context_menu (GncCsvPreview *preview, GdkEventButton *event,
-                    int col, int dx)
-{
-    int sensitivity_filter = 0;
-
-    preview->fixed_context_col = col;
-    preview->fixed_context_dx = dx;
-
-    if (!delete_column (preview, col - 1, TRUE))
-        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_LEFT);
-    if (!delete_column (preview, col, TRUE))
-        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_RIGHT);
-    if (!make_new_column (preview, col, dx, TRUE))
-        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_SPLIT);
-    if (!widen_column (preview, col, TRUE))
-        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_WIDEN);
-    if (!narrow_column (preview, col, TRUE))
-        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_NARROW);
-
-    select_column (preview, col);
-    gnumeric_create_popup_menu (popup_elements, &fixed_context_menu_handler,
-                                preview, 0,
-                                sensitivity_filter, event);
-}
-
-/* ---- End of Gnumeric Code ---- */
-
-/** Event handler for clicking on column headers. This function is
- * called whenever the user clicks on column headers in
- * preview->treeview to modify columns when in fixed-width mode.
- * @param button The button at the top of a column of the treeview
- * @param event The event that happened (where the user clicked)
- * @param preview The data being configured
- */
-static void header_button_press_handler(GtkWidget* button, GdkEventButton* event,
-                                        GncCsvPreview* preview)
-{
-    /* col is the number of the column that was clicked, and offset is
-       to correct for the indentation of button. */
-    int i, col = 0, offset = GTK_BIN(button)->child->allocation.x - button->allocation.x,
-           ncols = preview->parse_data->column_types->len;
-    /* Find the column that was clicked. */
-    for (i = 0; i < ncols; i++)
-    {
-        if (preview->treeview_buttons[i] == button)
-        {
-            col = i;
-            break;
-        }
-    }
-
-    /* Don't let the user affect the last column if it has error messages. */
-    if (preview->parse_data->orig_max_row < ncols && ncols - col == 1)
-    {
-        return;
-    }
-
-    /* Double clicks can split columns. */
-    if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
-    {
-        make_new_column(preview, col, (int)event->x - offset, FALSE);
-    }
-    /* Right clicking brings up a context menu. */
-    else if (event->type == GDK_BUTTON_PRESS && event->button == 3)
-    {
-        fixed_context_menu(preview, event, col, (int)event->x - offset);
-    }
-}
-
-/* Loads the preview's data into its data treeview. notEmpty is TRUE
- * when the data treeview already contains data, FALSE otherwise
- * (e.g. the first time this function is called on a preview).
- * @param preview The data being previewed
- * @param notEmpty Whether this function has been called before or not
- */
-static void gnc_csv_preview_update(GncCsvPreview* preview)
-{
-    /* store has the data from the file being imported. cstores is an
-     * array of stores that hold the combo box entries for each
-     * column. ctstore contains both pointers to models in cstore and
-     * the actual text that appears in preview->ctreeview. */
-    GtkListStore *store, **cstores, *ctstore;
-    GtkTreeIter iter;
-    /* ncols is the number of columns in the file data. */
-    int i, j, ncols = preview->parse_data->column_types->len,
-              max_str_len = preview->parse_data->file_str.end - preview->parse_data->file_str.begin;
-
-    /* store contains only strings. */
-    GType* types = g_new(GType, 2 * ncols);
-    for (i = 0; i < ncols; i++)
-        types[i] = G_TYPE_STRING;
-    store = gtk_list_store_newv(ncols, types);
-
-    /* ctstore is arranged as follows:
-     * model 0, text 0, model 1, text 1, ..., model ncols, text ncols. */
-    for (i = 0; i < 2 * ncols; i += 2)
-    {
-        types[i] = GTK_TYPE_TREE_MODEL;
-        types[i+1] = G_TYPE_STRING;
-    }
-    ctstore = gtk_list_store_newv(2 * ncols, types);
-
-    g_free(types);
-
-    /* Each element in cstores is a single column model. */
-    cstores = g_new(GtkListStore*, ncols);
-    for (i = 0; i < ncols; i++)
-    {
-        cstores[i] = gtk_list_store_new(1, G_TYPE_STRING);
-        /* Add all of the possible entries to the combo box. */
-        for (j = 0; j < GNC_CSV_NUM_COL_TYPES; j++)
-        {
-            gtk_list_store_append(cstores[i], &iter);
-            gtk_list_store_set(cstores[i], &iter, 0, _(gnc_csv_column_type_strs[j]), -1);
-        }
-    }
-
-    if (preview->not_empty)
-    {
-        GList *children, *children_begin;
-        GList *tv_columns, *tv_columns_begin, *ctv_columns, *ctv_columns_begin;
-        tv_columns = tv_columns_begin = gtk_tree_view_get_columns(preview->treeview);
-        ctv_columns = ctv_columns_begin = gtk_tree_view_get_columns(preview->ctreeview);
-        /* Clear out exisiting columns in preview->treeview. */
-        while (tv_columns != NULL)
-        {
-            gtk_tree_view_remove_column(preview->treeview, GTK_TREE_VIEW_COLUMN(tv_columns->data));
-            tv_columns = g_list_next(tv_columns);
-        }
-        /* Do the same in preview->ctreeview. */
-        while (ctv_columns != NULL)
-        {
-            gtk_tree_view_remove_column(preview->ctreeview, GTK_TREE_VIEW_COLUMN(ctv_columns->data));
-            ctv_columns = g_list_next(ctv_columns);
-        }
-        g_list_free(tv_columns_begin);
-        g_list_free(ctv_columns_begin);
-        g_free(preview->treeview_buttons);
-    }
-
-    /* Fill the data treeview with data from the file. */
-    /* Also, update the longest line value within the following loop (whichever is executed). */
-    preview->longest_line = 0;
-    if (preview->previewing_errors) /* If we are showing only errors ... */
-    {
-        /* ... only pick rows that are in preview->error_lines. */
-        GList* error_lines = preview->parse_data->error_lines;
-        while (error_lines != NULL)
-        {
-            int this_line_length = 0;
-            i = GPOINTER_TO_INT(error_lines->data);
-            gtk_list_store_append(store, &iter);
-            for (j = 0; j < ((GPtrArray*)(preview->parse_data->orig_lines->pdata[i]))->len; j++)
-            {
-                /* Add this cell's length to the row's length and set the value of the list store. */
-                gchar* cell_string = (gchar*)((GPtrArray*)(preview->parse_data->orig_lines->pdata[i]))->pdata[j];
-                this_line_length += g_utf8_strlen(cell_string, max_str_len);
-                gtk_list_store_set(store, &iter, j, cell_string, -1);
-            }
-
-            if (this_line_length > preview->longest_line)
-                preview->longest_line = this_line_length;
-
-            error_lines = g_list_next(error_lines);
-        }
-    }
-    else /* Otherwise, put in all of the data. */
-    {
-        for (i = 0; i < preview->parse_data->orig_lines->len; i++)
-        {
-            int this_line_length = 0;
-            gtk_list_store_append(store, &iter);
-            for (j = 0; j < ((GPtrArray*)(preview->parse_data->orig_lines->pdata[i]))->len; j++)
-            {
-                /* Add this cell's length to the row's length and set the value of the list store. */
-                gchar* cell_string = (gchar*)((GPtrArray*)(preview->parse_data->orig_lines->pdata[i]))->pdata[j];
-                this_line_length += g_utf8_strlen(cell_string, max_str_len);
-                gtk_list_store_set(store, &iter, j, cell_string, -1);
-            }
-
-            if (this_line_length > preview->longest_line)
-                preview->longest_line = this_line_length;
-        }
-    }
-
-    /* Set all the column types to what's in the parse data. */
-    gtk_list_store_append(ctstore, &iter);
-    for (i = 0; i < ncols; i++)
-    {
-        gtk_list_store_set(ctstore, &iter, 2 * i, cstores[i], 2 * i + 1,
-                           _(gnc_csv_column_type_strs[(int)(preview->parse_data->column_types->data[i])]),
-                           -1);
-    }
-
-    preview->treeview_buttons = g_new(GtkWidget*, ncols);
-    /* Insert columns into the data and column type treeviews. */
-    for (i = 0; i < ncols; i++)
-    {
-        GtkTreeViewColumn* col; /* The column we add to preview->treeview. */
-        /* Create renderers for the data treeview (renderer) and the
-         * column type treeview (crenderer). */
-        GtkCellRenderer* renderer = gtk_cell_renderer_text_new(),
-                         *crenderer = gtk_cell_renderer_combo_new();
-        /* We want a monospace font for the data in case of fixed-width data. */
-        g_object_set(G_OBJECT(renderer), "family", "monospace", NULL);
-        /* We are using cstores for the combo box entries, and we don't
-         * want the user to be able to manually enter their own column
-         * types. */
-        g_object_set(G_OBJECT(crenderer), "model", cstores[i], "text-column", 0,
-                     "editable", TRUE, "has-entry", FALSE, NULL);
-        g_signal_connect(G_OBJECT(crenderer), "changed",
-                         G_CALLBACK(column_type_changed), (gpointer)preview);
-
-        /* Add a single column for the treeview. */
-        col = gtk_tree_view_column_new_with_attributes("", renderer, "text", i, NULL);
-        gtk_tree_view_insert_column(preview->treeview, col, -1);
-        /* Enable resizing of the columns. */
-        gtk_tree_view_column_set_resizable(col, TRUE);
-        /* Use the alternating model and text entries from ctstore in
-         * preview->ctreeview. */
-        gtk_tree_view_insert_column_with_attributes(preview->ctreeview,
-                -1, "", crenderer, "model", 2 * i,
-                "text", 2 * i + 1, NULL);
-
-        /* We need to allow clicking on the column headers for fixed-width
-         * column splitting and merging. */
-        g_object_set(G_OBJECT(col), "clickable", TRUE, NULL);
-        g_signal_connect(G_OBJECT(col->button), "button_press_event",
-                         G_CALLBACK(header_button_press_handler), (gpointer)preview);
-        preview->treeview_buttons[i] = col->button;
-    }
-
-    /* Set the treeviews to use the models. */
-    gtk_tree_view_set_model(preview->treeview, GTK_TREE_MODEL(store));
-    gtk_tree_view_set_model(preview->ctreeview, GTK_TREE_MODEL(ctstore));
-
-    /* Free the memory for the stores. */
-    g_object_unref(GTK_TREE_MODEL(store));
-    g_object_unref(GTK_TREE_MODEL(ctstore));
-    for (i = 0; i < ncols; i++)
-        g_object_unref(GTK_TREE_MODEL(cstores[i]));
-
-    /* Make the things actually appear. */
-    gtk_widget_show_all(GTK_WIDGET(preview->treeview));
-    gtk_widget_show_all(GTK_WIDGET(preview->ctreeview));
-
-    /* Set the encoding selector to the right encoding. */
-    preview->code_encoding_calls = 2;
-    go_charmap_sel_set_encoding(preview->encselector, preview->parse_data->encoding);
-
-    /* Set the date format to what's in the combo box (since we don't
-     * necessarily know if this will always be the same). */
-    preview->parse_data->date_format = gtk_combo_box_get_active(preview->date_format_combo);
-
-    /* It's now been filled with some stuff. */
-    preview->not_empty = TRUE;
-}
-
-/** A function that lets the user preview a file's data. This function
- * is used to let the user preview and configure the data parsed from
- * the file. It doesn't return until the user clicks "OK" or "Cancel"
- * on the dialog.
- * @param preview The GUI for previewing the data
- * @param parse_data The data we want to preview
- * @return 0 if the user approved the import; 1 if the user didn't.
- */
-static int gnc_csv_preview(GncCsvPreview* preview, GncCsvParseData* parse_data)
-{
-    /* Set the preview's parse_data to the one we're getting passed. */
-    preview->parse_data = parse_data;
-    preview->previewing_errors = FALSE; /* We're looking at all the data. */
-    preview->approved = FALSE; /* This is FALSE until the user clicks "OK". */
-
-    /* Load the data into the treeview. (This is the first time we've
-     * called gnc_csv_preview_update on this preview, so we use
-     * FALSE.) */
-    gnc_csv_preview_update(preview);
-    /* Wait until the user clicks "OK" or "Cancel". */
-    gtk_dialog_run(GTK_DIALOG(preview->dialog));
-
-    if (preview->approved)
-        return 0;
-    else
-        return 1;
-}
-
-/** A function that lets the user preview rows with errors. This
- * function must only be called after calling gnc_csv_preview. It is
- * essentially identical in behavior to gnc_csv_preview except that it
- * displays lines with errors instead of all of the data.
- * @param preview The GUI for previewing the data (and the data being previewed)
- * @return 0 if the user approved of importing the lines; 1 if the user didn't.
- */
-/* TODO Let the user manually edit cells' data? */
-static int gnc_csv_preview_errors(GncCsvPreview* preview)
-{
-    gchar* name;
-    GtkIconSize size;
-    GtkTreeViewColumn* last_col;
-
-    gtk_image_get_stock(preview->instructions_image, &name, &size);
-    gtk_image_set_from_stock(preview->instructions_image, GTK_STOCK_DIALOG_ERROR, size);
-    gtk_label_set_text(preview->instructions_label,
-                       _("The rows displayed below had errors. You can attempt to correct these errors by changing the configuration."));
-    gtk_widget_show(GTK_WIDGET(preview->instructions_image));
-    gtk_widget_show(GTK_WIDGET(preview->instructions_label));
-
-    preview->previewing_errors = TRUE;
-    preview->approved = FALSE; /* This is FALSE until the user clicks "OK". */
-
-    /* Wait until the user clicks "OK" or "Cancel". */
-    gnc_csv_preview_update(preview);
-
-    /* Set the last column to have the header "Errors" so that the user
-     * doesn't find the extra column confusing. */
-    last_col = gtk_tree_view_get_column(preview->treeview,
-                                        preview->parse_data->column_types->len - 1);
-    gtk_tree_view_column_set_title(last_col, _("Errors"));
-
-    gtk_dialog_run(GTK_DIALOG(preview->dialog));
-
-    if (preview->approved)
-        return 0;
-    else
-        return 1;
-}
-
-/** Lets the user import a CSV/Fixed-Width file. */
-void gnc_file_csv_import(void)
-{
-    /* The name of the file the user selected. */
-    char* selected_filename;
-    /* The default directory for the user to select files. */
-    char* default_dir = gnc_get_default_directory(GCONF_SECTION);
-    /* The generic GUI for importing transactions. */
-    GNCImportMainMatcher* gnc_csv_importer_gui = NULL;
-
-    /* Let the user select a file. */
-    selected_filename = gnc_file_dialog(_("Select an CSV/Fixed-Width file to import"),
-                                        NULL, default_dir, GNC_FILE_DIALOG_IMPORT);
-    g_free(default_dir); /* We don't need default_dir anymore. */
-
-    /* If the user actually selected a file ... */
-    if (selected_filename != NULL)
-    {
-        int i, user_canceled = 0;
-        Account* account; /* The account the user will select */
-        GError* error = NULL;
-        GList* transactions; /* A list of the transactions we create */
-        GncCsvParseData* parse_data;
-        GncCsvPreview* preview;
-
-        /* Remember the directory of the selected file as the default. */
-        default_dir = g_path_get_dirname(selected_filename);
-        gnc_set_default_directory(GCONF_SECTION, default_dir);
-        g_free(default_dir);
-
-        /* Load the file into parse_data. */
-        parse_data = gnc_csv_new_parse_data();
-        if (gnc_csv_load_file(parse_data, selected_filename, &error))
-        {
-            /* If we couldn't load the file ... */
-            gnc_error_dialog(NULL, "%s", error->message);
-            if (error->code == GNC_CSV_FILE_OPEN_ERR)
-            {
-                gnc_csv_parse_data_free(parse_data);
-                g_free(selected_filename);
-                return;
-            }
-            /* If we couldn't guess the encoding, we are content with just
-             * displaying an error message and move on with a blank
-             * display. */
-        }
-        /* Parse the data. */
-        if (gnc_csv_parse(parse_data, TRUE, &error))
-        {
-            /* If we couldn't parse the data ... */
-            gnc_error_dialog(NULL, "%s", error->message);
-        }
-
-        /* Preview the data. */
-        preview = gnc_csv_preview_new();
-        if (gnc_csv_preview(preview, parse_data))
-        {
-            /* If the user clicked "Cancel", free everything and quit. */
-            gnc_csv_preview_free(preview);
-            gnc_csv_parse_data_free(parse_data);
-            g_free(selected_filename);
-            return;
-        }
-
-        /* Let the user select an account to put the transactions in. */
-        account = gnc_import_select_account(NULL, NULL, 1, NULL, NULL, 0, NULL, NULL);
-        if (account == NULL) /* Quit if the user canceled. */
-        {
-            gnc_csv_preview_free(preview);
-            gnc_csv_parse_data_free(parse_data);
-            g_free(selected_filename);
-            return;
-        }
-
-        /* Create transactions from the parsed data. */
-        gnc_csv_parse_to_trans(parse_data, account, FALSE);
-
-        /* If there are errors, let the user try and eliminate them by
-         * previewing them. Repeat until either there are no errors or the
-         * user gives up. */
-        while (!((parse_data->error_lines == NULL) || user_canceled))
-        {
-            user_canceled = gnc_csv_preview_errors(preview);
-            gnc_csv_parse_to_trans(parse_data, account, TRUE);
-        }
-
-        /* Create the genereic transaction importer GUI. */
-        gnc_csv_importer_gui = gnc_gen_trans_list_new(NULL, NULL, FALSE, 42);
-
-        /* Get the list of the transactions that were created. */
-        transactions = parse_data->transactions;
-        /* Copy all of the transactions to the importer GUI. */
-        while (transactions != NULL)
-        {
-            GncCsvTransLine* trans_line = transactions->data;
-            gnc_gen_trans_list_add_trans(gnc_csv_importer_gui,
-                                         trans_line->trans);
-            transactions = g_list_next(transactions);
-        }
-        /* Let the user load those transactions into the account, so long
-         * as there is at least one transaction to be loaded. */
-        if (parse_data->transactions != NULL)
-            gnc_gen_trans_list_run(gnc_csv_importer_gui);
-        else
-            gnc_gen_trans_list_delete(gnc_csv_importer_gui);
-
-        /* Free the memory we allocated. */
-        gnc_csv_preview_free(preview);
-        gnc_csv_parse_data_free(parse_data);
-        g_free(selected_filename);
-    }
-}

Deleted: gnucash/trunk/src/import-export/csv/gnc-csv-import.glade
===================================================================
--- gnucash/trunk/src/import-export/csv/gnc-csv-import.glade	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gnc-csv-import.glade	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,583 +0,0 @@
-<?xml version="1.0"?>
-<interface>
-  <requires lib="gtk+" version="2.16"/>
-  <!-- interface-naming-policy project-wide -->
-  <object class="GtkDialog" id="preview-dialog">
-    <property name="can_focus">False</property>
-    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Import CSV/Fixed-Width File</property>
-    <property name="window_position">center-on-parent</property>
-    <property name="type_hint">dialog</property>
-    <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox3">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-        <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area3">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="cancel_button">
-                <property name="label">gtk-cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="ok_button">
-                <property name="label">gtk-ok</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkVBox" id="vbox1">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <object class="GtkTable" id="enctable">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="n_rows">4</property>
-                <property name="n_columns">2</property>
-                <child>
-                  <object class="GtkHSeparator" id="hseparator1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="x_options">GTK_SHRINK | GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
-                    <property name="y_padding">3</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHSeparator" id="hseparator2">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">3</property>
-                    <property name="bottom_attach">4</property>
-                    <property name="x_options">GTK_SHRINK | GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
-                    <property name="y_padding">3</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHBox" id="hbox1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <child>
-                      <object class="GtkRadioButton" id="csv_button">
-                        <property name="label" translatable="yes">Separated</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="use_action_appearance">False</property>
-                        <property name="active">True</property>
-                        <property name="draw_indicator">True</property>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkRadioButton" id="radiobutton2">
-                        <property name="label" translatable="yes">Fixed-Width</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="receives_default">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="use_action_appearance">False</property>
-                        <property name="draw_indicator">True</property>
-                        <property name="group">csv_button</property>
-                      </object>
-                      <packing>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="y_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Data type: </property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHSeparator" id="hseparator4">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                  </object>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkHSeparator" id="hseparator5">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                  </object>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_SHRINK | GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
-                    <property name="y_padding">3</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="label3">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Encoding: </property>
-                  </object>
-                  <packing>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options">GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame1">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
-                <child>
-                  <object class="GtkAlignment" id="alignment1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="left_padding">12</property>
-                    <child>
-                      <object class="GtkTable" id="table1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="n_rows">3</property>
-                        <property name="n_columns">3</property>
-                        <property name="column_spacing">3</property>
-                        <property name="row_spacing">3</property>
-                        <child>
-                          <object class="GtkCheckButton" id="space_cbutton">
-                            <property name="label" translatable="yes">Space</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="use_action_appearance">False</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkCheckButton" id="tab_cbutton">
-                            <property name="label" translatable="yes">Tab</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="use_action_appearance">False</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="right_attach">2</property>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkCheckButton" id="comma_cbutton">
-                            <property name="label" translatable="yes">Comma (,)</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="use_action_appearance">False</property>
-                            <property name="active">True</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">2</property>
-                            <property name="right_attach">3</property>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkCheckButton" id="colon_cbutton">
-                            <property name="label" translatable="yes">Colon (:)</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="use_action_appearance">False</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="top_attach">1</property>
-                            <property name="bottom_attach">2</property>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkCheckButton" id="semicolon_cbutton">
-                            <property name="label" translatable="yes">Semicolon (;)</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="use_action_appearance">False</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="right_attach">2</property>
-                            <property name="top_attach">1</property>
-                            <property name="bottom_attach">2</property>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkCheckButton" id="hyphen_cbutton">
-                            <property name="label" translatable="yes">Hyphen (-)</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="use_action_appearance">False</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">2</property>
-                            <property name="right_attach">3</property>
-                            <property name="top_attach">1</property>
-                            <property name="bottom_attach">2</property>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkCheckButton" id="custom_cbutton">
-                            <property name="label" translatable="yes">Custom</property>
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">False</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="use_action_appearance">False</property>
-                            <property name="draw_indicator">True</property>
-                          </object>
-                          <packing>
-                            <property name="top_attach">2</property>
-                            <property name="bottom_attach">3</property>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkEntry" id="custom_entry">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="invisible_char">&#x25CF;</property>
-                            <property name="invisible_char_set">True</property>
-                            <property name="primary_icon_activatable">False</property>
-                            <property name="secondary_icon_activatable">False</property>
-                            <property name="primary_icon_sensitive">True</property>
-                            <property name="secondary_icon_sensitive">True</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="right_attach">3</property>
-                            <property name="top_attach">2</property>
-                            <property name="bottom_attach">3</property>
-                            <property name="x_options">GTK_FILL</property>
-                            <property name="y_options">GTK_FILL</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label5">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Separators</property>
-                    <property name="use_markup">True</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHBox" id="hbox2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">3</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHSeparator" id="hseparator6">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="padding">3</property>
-                <property name="position">4</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame2">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
-                <child>
-                  <object class="GtkAlignment" id="date_format_container">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="left_padding">12</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label4">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Date Format</property>
-                    <property name="use_markup">True</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">5</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHSeparator" id="hseparator3">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="padding">3</property>
-                <property name="position">6</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHBox" id="hbox3">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <child>
-                  <object class="GtkImage" id="instructions_image">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="stock">gtk-dialog-info</property>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="padding">2</property>
-                    <property name="position">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="instructions_label">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Select the type of each column below.</property>
-                    <property name="wrap">True</property>
-                  </object>
-                  <packing>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">7</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkTreeView" id="ctreeview">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="headers_visible">False</property>
-                <property name="enable_grid_lines">both</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">8</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow1">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="hscrollbar_policy">automatic</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <child>
-                  <object class="GtkViewport" id="viewport1">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="resize_mode">queue</property>
-                    <child>
-                      <object class="GtkTreeView" id="treeview">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="enable_grid_lines">both</property>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">9</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="0">cancel_button</action-widget>
-      <action-widget response="0">ok_button</action-widget>
-    </action-widgets>
-  </object>
-</interface>

Deleted: gnucash/trunk/src/import-export/csv/gnc-csv-import.h
===================================================================
--- gnucash/trunk/src/import-export/csv/gnc-csv-import.h	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gnc-csv-import.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,33 +0,0 @@
-/********************************************************************\
- * This program is free software; you can redistribute it and/or    *
- * modify it under the terms of the GNU General Public License as   *
- * published by the Free Software Foundation; either version 2 of   *
- * the License, or (at your option) any later version.              *
- *                                                                  *
- * This program is distributed in the hope that it will be useful,  *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
- * GNU General Public License for more details.                     *
- *                                                                  *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact:                        *
- *                                                                  *
- * Free Software Foundation           Voice:  +1-617-542-5942       *
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
- * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
-\********************************************************************/
-/** @file
-    @brief CSV import GUI
-    *
-    gnc-csv-import.h
-    @author Copyright (c) 2007 Benny Sperisen <lasindi at gmail.com>
-*/
-#ifndef CSV_IMPORT_H
-#define CSV_IMPORT_H
-
-/** The gnc_file_csv_import() will let the user select a
- * CSV/Fixed-Width file to open, select an account to import it to,
- * and import the transactions into the account. It also allows the
- * user to configure how the file is parsed. */
-void              gnc_file_csv_import (void);
-#endif

Deleted: gnucash/trunk/src/import-export/csv/gnc-csv-model.c
===================================================================
--- gnucash/trunk/src/import-export/csv/gnc-csv-model.c	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gnc-csv-model.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,1215 +0,0 @@
-#include "gnc-csv-model.h"
-
-
-#include <glib/gi18n.h>
-
-#include <goffice/goffice-features.h>
-#if (GO_VERSION_EPOCH == 0) && (GO_VERSION_MAJOR == 7) && (GO_VERSION_MINOR == 8)
-/* For libgoffice-0.7.8, disable its internal inclusion of <regutf8.h>
-   so to avoid clashing symbol definitions with <regex.h> */
-# define GO_REGUTF8_H
-#endif
-#include <goffice/utils/go-glib-extras.h>
-
-#include <string.h>
-#include <sys/time.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <regex.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <math.h>
-#include <time.h>
-#ifndef HAVE_LOCALTIME_R
-#include "localtime_r.h"
-#endif
-
-static QofLogModule log_module = GNC_MOD_IMPORT;
-
-const int num_date_formats = 5;
-
-const gchar* date_format_user[] = {N_("y-m-d"),
-                                   N_("d-m-y"),
-                                   N_("m-d-y"),
-                                   N_("d-m"),
-                                   N_("m-d")
-                                  };
-
-/* This array contains all of the different strings for different column types. */
-gchar* gnc_csv_column_type_strs[GNC_CSV_NUM_COL_TYPES] = {N_("None"),
-        N_("Date"),
-        N_("Description"),
-        N_("Balance"),
-        N_("Deposit"),
-        N_("Withdrawal"),
-        N_("Num")
-                                                         };
-
-/** A set of sensible defaults for parsing CSV files.
- * @return StfParseOptions_t* for parsing a file with comma separators
- */
-static StfParseOptions_t* default_parse_options(void)
-{
-    StfParseOptions_t* options = stf_parse_options_new();
-    stf_parse_options_set_type(options, PARSE_TYPE_CSV);
-    stf_parse_options_csv_set_separators(options, ",", NULL);
-    return options;
-}
-
-/** Parses a string into a date, given a format. The format must
- * include the year. This function should only be called by
- * parse_date.
- * @param date_str The string containing a date being parsed
- * @param format An index specifying a format in date_format_user
- * @return The parsed value of date_str on success or -1 on failure
- */
-static time_t parse_date_with_year(const char* date_str, int format)
-{
-    time_t rawtime; /* The integer time */
-    struct tm retvalue, test_retvalue; /* The time in a broken-down structure */
-
-    int i, j, mem_length, orig_year = -1, orig_month = -1, orig_day = -1;
-
-    /* Buffer for containing individual parts (e.g. year, month, day) of a date */
-    char date_segment[5];
-
-    /* The compiled regular expression */
-    regex_t preg = {0};
-
-    /* An array containing indices specifying the matched substrings in date_str */
-    regmatch_t pmatch[4] = { {0}, {0}, {0}, {0} };
-
-    /* The regular expression for parsing dates */
-    const char* regex = "^ *([0-9]+) *[-/.'] *([0-9]+) *[-/.'] *([0-9]+).*$|^ *([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]).*$";
-
-    /* We get our matches using the regular expression. */
-    regcomp(&preg, regex, REG_EXTENDED);
-    regexec(&preg, date_str, 4, pmatch, 0);
-    regfree(&preg);
-
-    /* If there wasn't a match, there was an error. */
-    if (pmatch[0].rm_eo == 0)
-        return -1;
-
-    /* If this is a string without separators ... */
-    if (pmatch[1].rm_so == -1)
-    {
-        /* ... we will fill in the indices based on the user's selection. */
-        int k = 0; /* k traverses date_str by keeping track of where separators "should" be. */
-        j = 1; /* j traverses pmatch. */
-        for (i = 0; date_format_user[format][i]; i++)
-        {
-            char segment_type = date_format_user[format][i];
-            /* Only do something if this is a meaningful character */
-            if (segment_type == 'y' || segment_type == 'm' || segment_type == 'd')
-            {
-                pmatch[j].rm_so = k;
-                switch (segment_type)
-                {
-                case 'm':
-                case 'd':
-                    k += 2;
-                    break;
-
-                case 'y':
-                    k += 4;
-                    break;
-                }
-
-                pmatch[j].rm_eo = k;
-                j++;
-            }
-        }
-    }
-
-    /* Put some sane values in retvalue by using the current time for
-     * the non-year-month-day parts of the date. */
-    time(&rawtime);
-    localtime_r(&rawtime, &retvalue);
-
-    /* j traverses pmatch (index 0 contains the entire string, so we
-     * start at index 1 for the first meaningful match). */
-    j = 1;
-    /* Go through the date format and interpret the matches in order of
-     * the sections in the date format. */
-    for (i = 0; date_format_user[format][i]; i++)
-    {
-        char segment_type = date_format_user[format][i];
-        /* Only do something if this is a meaningful character */
-        if (segment_type == 'y' || segment_type == 'm' || segment_type == 'd')
-        {
-            /* Copy the matching substring into date_segment so that we can
-             * convert it into an integer. */
-            mem_length = pmatch[j].rm_eo - pmatch[j].rm_so;
-            memcpy(date_segment, date_str + pmatch[j].rm_so, mem_length);
-            date_segment[mem_length] = '\0';
-
-            /* Set the appropriate member of retvalue. Save the original
-             * values so that we can check if the change when we use mktime
-             * below. */
-            switch (segment_type)
-            {
-            case 'y':
-                retvalue.tm_year = atoi(date_segment);
-
-                /* Handle two-digit years. */
-                if (retvalue.tm_year < 100)
-                {
-                    /* We allow two-digit years in the range 1969 - 2068. */
-                    if (retvalue.tm_year < 69)
-                        retvalue.tm_year += 100;
-                }
-                else
-                    retvalue.tm_year -= 1900;
-                orig_year = retvalue.tm_year;
-                break;
-
-            case 'm':
-                orig_month = retvalue.tm_mon = atoi(date_segment) - 1;
-                break;
-
-            case 'd':
-                orig_day = retvalue.tm_mday = atoi(date_segment);
-                break;
-            }
-            j++;
-        }
-    }
-    /* Convert back to an integer. If mktime leaves retvalue unchanged,
-     * everything is okay; otherwise, an error has occurred. */
-    /* We have to use a "test" date value to account for changes in
-     * daylight savings time, which can cause a date change with mktime
-     * near midnight, causing the code to incorrectly think a date is
-     * incorrect. */
-    test_retvalue = retvalue;
-    mktime(&test_retvalue);
-    retvalue.tm_isdst = test_retvalue.tm_isdst;
-    rawtime = mktime(&retvalue);
-    if (retvalue.tm_mday == orig_day &&
-    retvalue.tm_mon == orig_month &&
-    retvalue.tm_year == orig_year)
-    {
-        return rawtime;
-    }
-    else
-    {
-        return -1;
-    }
-}
-
-/** Parses a string into a date, given a format. The format cannot
- * include the year. This function should only be called by
- * parse_date.
- * @param date_str The string containing a date being parsed
- * @param format An index specifying a format in date_format_user
- * @return The parsed value of date_str on success or -1 on failure
- */
-static time_t parse_date_without_year(const char* date_str, int format)
-{
-    time_t rawtime; /* The integer time */
-    struct tm retvalue, test_retvalue; /* The time in a broken-down structure */
-
-    int i, j, mem_length, orig_year = -1, orig_month = -1, orig_day = -1;
-
-    /* Buffer for containing individual parts (e.g. year, month, day) of a date */
-    gchar* date_segment;
-
-    /* The compiled regular expression */
-    regex_t preg = {0};
-
-    /* An array containing indices specifying the matched substrings in date_str */
-    regmatch_t pmatch[3] = { {0}, {0}, {0} };
-
-    /* The regular expression for parsing dates */
-    const char* regex = "^ *([0-9]+) *[-/.'] *([0-9]+).*$";
-
-    /* We get our matches using the regular expression. */
-    regcomp(&preg, regex, REG_EXTENDED);
-    regexec(&preg, date_str, 3, pmatch, 0);
-    regfree(&preg);
-
-    /* If there wasn't a match, there was an error. */
-    if (pmatch[0].rm_eo == 0)
-        return -1;
-
-    /* Put some sane values in retvalue by using the current time for
-     * the non-year-month-day parts of the date. */
-    time(&rawtime);
-    localtime_r(&rawtime, &retvalue);
-    orig_year = retvalue.tm_year;
-
-    /* j traverses pmatch (index 0 contains the entire string, so we
-     * start at index 1 for the first meaningful match). */
-    j = 1;
-    /* Go through the date format and interpret the matches in order of
-     * the sections in the date format. */
-    for (i = 0; date_format_user[format][i]; i++)
-    {
-        char segment_type = date_format_user[format][i];
-        /* Only do something if this is a meaningful character */
-        if (segment_type == 'm' || segment_type == 'd')
-        {
-            /* Copy the matching substring into date_segment so that we can
-             * convert it into an integer. */
-            mem_length = pmatch[j].rm_eo - pmatch[j].rm_so;
-            date_segment = g_new(gchar, mem_length);
-            memcpy(date_segment, date_str + pmatch[j].rm_so, mem_length);
-            date_segment[mem_length] = '\0';
-
-            /* Set the appropriate member of retvalue. Save the original
-             * values so that we can check if the change when we use mktime
-             * below. */
-            switch (segment_type)
-            {
-            case 'm':
-                orig_month = retvalue.tm_mon = atoi(date_segment) - 1;
-                break;
-
-            case 'd':
-                orig_day = retvalue.tm_mday = atoi(date_segment);
-                break;
-            }
-            g_free(date_segment);
-            j++;
-        }
-    }
-    /* Convert back to an integer. If mktime leaves retvalue unchanged,
-     * everything is okay; otherwise, an error has occurred. */
-    /* We have to use a "test" date value to account for changes in
-     * daylight savings time, which can cause a date change with mktime
-     * near midnight, causing the code to incorrectly think a date is
-     * incorrect. */
-    test_retvalue = retvalue;
-    mktime(&test_retvalue);
-    retvalue.tm_isdst = test_retvalue.tm_isdst;
-    rawtime = mktime(&retvalue);
-    if (retvalue.tm_mday == orig_day &&
-    retvalue.tm_mon == orig_month &&
-    retvalue.tm_year == orig_year)
-    {
-        return rawtime;
-    }
-    else
-    {
-        return -1;
-    }
-}
-
-/** Parses a string into a date, given a format. This function
- * requires only knowing the order in which the year, month and day
- * appear. For example, 01-02-2003 will be parsed the same way as
- * 01/02/2003.
- * @param date_str The string containing a date being parsed
- * @param format An index specifying a format in date_format_user
- * @return The parsed value of date_str on success or -1 on failure
- */
-static time_t parse_date(const char* date_str, int format)
-{
-    if (strchr(date_format_user[format], 'y'))
-        return parse_date_with_year(date_str, format);
-    else
-        return parse_date_without_year(date_str, format);
-}
-
-/** Constructor for GncCsvParseData.
- * @return Pointer to a new GncCSvParseData
- */
-GncCsvParseData* gnc_csv_new_parse_data(void)
-{
-    GncCsvParseData* parse_data = g_new(GncCsvParseData, 1);
-    parse_data->encoding = "UTF-8";
-    /* All of the data pointers are initially NULL. This is so that, if
-     * gnc_csv_parse_data_free is called before all of the data is
-     * initialized, only the data that needs to be freed is freed. */
-    parse_data->raw_str.begin = parse_data->raw_str.end
-    = parse_data->file_str.begin = parse_data->file_str.end = NULL;
-    parse_data->orig_lines = NULL;
-    parse_data->orig_row_lengths = NULL;
-    parse_data->column_types = NULL;
-    parse_data->error_lines = parse_data->transactions = NULL;
-    parse_data->options = default_parse_options();
-    parse_data->date_format = -1;
-    parse_data->chunk = g_string_chunk_new(100 * 1024);
-    return parse_data;
-}
-
-/** Destructor for GncCsvParseData.
- * @param parse_data Parse data whose memory will be freed
- */
-void gnc_csv_parse_data_free(GncCsvParseData* parse_data)
-{
-    /* All non-NULL pointers have been initialized and must be freed. */
-
-    if (parse_data->raw_mapping != NULL)
-        g_mapped_file_free(parse_data->raw_mapping);
-
-    if (parse_data->file_str.begin != NULL)
-        g_free(parse_data->file_str.begin);
-
-    if (parse_data->orig_lines != NULL)
-        stf_parse_general_free(parse_data->orig_lines);
-
-    if (parse_data->orig_row_lengths != NULL)
-        g_array_free(parse_data->orig_row_lengths, FALSE);
-
-    if (parse_data->options != NULL)
-        stf_parse_options_free(parse_data->options);
-
-    if (parse_data->column_types != NULL)
-        g_array_free(parse_data->column_types, TRUE);
-
-    if (parse_data->error_lines != NULL)
-        g_list_free(parse_data->error_lines);
-
-    if (parse_data->transactions != NULL)
-    {
-        GList* transactions = parse_data->transactions;
-        /* We have to free the GncCsvTransLine's that are at each node in
-         * the list before freeing the entire list. */
-        do
-        {
-            g_free(transactions->data);
-            transactions = g_list_next(transactions);
-        }
-        while (transactions != NULL);
-        g_list_free(parse_data->transactions);
-    }
-
-    g_free(parse_data->chunk);
-    g_free(parse_data);
-}
-
-/** Converts raw file data using a new encoding. This function must be
- * called after gnc_csv_load_file only if gnc_csv_load_file guessed
- * the wrong encoding.
- * @param parse_data Data that is being parsed
- * @param encoding Encoding that data should be translated using
- * @param error Will point to an error on failure
- * @return 0 on success, 1 on failure
- */
-int gnc_csv_convert_encoding(GncCsvParseData* parse_data, const char* encoding,
-GError** error)
-{
-    gsize bytes_read, bytes_written;
-
-    /* If parse_data->file_str has already been initialized it must be
-     * freed first. (This should always be the case, since
-     * gnc_csv_load_file should always be called before this
-     * function.) */
-    if (parse_data->file_str.begin != NULL)
-        g_free(parse_data->file_str.begin);
-
-    /* Do the actual translation to UTF-8. */
-    parse_data->file_str.begin = g_convert(parse_data->raw_str.begin,
-    parse_data->raw_str.end - parse_data->raw_str.begin,
-    "UTF-8", encoding, &bytes_read, &bytes_written,
-    error);
-    /* Handle errors that occur. */
-    if (parse_data->file_str.begin == NULL)
-        return 1;
-
-    /* On success, save the ending pointer of the translated data and
-     * the encoding type and return 0. */
-    parse_data->file_str.end = parse_data->file_str.begin + bytes_written;
-    parse_data->encoding = (gchar*)encoding;
-    return 0;
-}
-
-/** Loads a file into a GncCsvParseData. This is the first function
- * that must be called after createing a new GncCsvParseData. If this
- * fails because the file couldn't be opened, no more functions can be
- * called on the parse data until this succeeds (or until it fails
- * because of an encoding guess error). If it fails because the
- * encoding could not be guessed, gnc_csv_convert_encoding must be
- * called until it succeeds.
- * @param parse_data Data that is being parsed
- * @param filename Name of the file that should be opened
- * @param error Will contain an error if there is a failure
- * @return 0 on success, 1 on failure
- */
-int gnc_csv_load_file(GncCsvParseData* parse_data, const char* filename,
-GError** error)
-{
-    const char* guess_enc;
-
-    /* Get the raw data first and handle an error if one occurs. */
-    parse_data->raw_mapping = g_mapped_file_new(filename, FALSE, error);
-    if (parse_data->raw_mapping == NULL)
-    {
-        /* TODO Handle file opening errors more specifically,
-         * e.g. inexistent file versus no read permission. */
-        parse_data->raw_str.begin = NULL;
-        g_set_error(error, 0, GNC_CSV_FILE_OPEN_ERR, "%s", _("File opening failed."));
-        return 1;
-    }
-
-    /* Copy the mapping's contents into parse-data->raw_str. */
-    parse_data->raw_str.begin = g_mapped_file_get_contents(parse_data->raw_mapping);
-    parse_data->raw_str.end = parse_data->raw_str.begin + g_mapped_file_get_length(parse_data->raw_mapping);
-
-    /* Make a guess at the encoding of the data. */
-    guess_enc = go_guess_encoding((const char*)(parse_data->raw_str.begin),
-    (size_t)(parse_data->raw_str.end - parse_data->raw_str.begin),
-    "UTF-8", NULL);
-    if (guess_enc == NULL)
-    {
-        g_set_error(error, 0, GNC_CSV_ENCODING_ERR, "%s", _("Unknown encoding."));
-        return 1;
-    }
-
-    /* Convert using the guessed encoding into parse_data->file_str and
-     * handle any errors that occur. */
-    gnc_csv_convert_encoding(parse_data, guess_enc, error);
-    if (parse_data->file_str.begin == NULL)
-    {
-        g_set_error(error, 0, GNC_CSV_ENCODING_ERR, "%s", _("Unknown encoding."));
-        return 1;
-    }
-    else
-        return 0;
-}
-
-/** Parses a file into cells. This requires having an encoding that
- * works (see gnc_csv_convert_encoding). parse_data->options should be
- * set according to how the user wants before calling this
- * function. (Note: this function must be called with guessColTypes as
- * TRUE before it is ever called with it as FALSE.) (Note: if
- * guessColTypes is TRUE, all the column types will be GNC_CSV_NONE
- * right now.)
- * @param parse_data Data that is being parsed
- * @param guessColTypes TRUE to guess what the types of columns are based on the cell contents
- * @param error Will contain an error if there is a failure
- * @return 0 on success, 1 on failure
- */
-int gnc_csv_parse(GncCsvParseData* parse_data, gboolean guessColTypes, GError** error)
-{
-    /* max_cols is the number of columns in the row with the most columns. */
-    int i, max_cols = 0;
-
-    if (parse_data->orig_lines != NULL)
-    {
-        stf_parse_general_free(parse_data->orig_lines);
-    }
-
-    /* If everything is fine ... */
-    if (parse_data->file_str.begin != NULL)
-    {
-        /* Do the actual parsing. */
-        parse_data->orig_lines = stf_parse_general(parse_data->options, parse_data->chunk,
-        parse_data->file_str.begin,
-        parse_data->file_str.end);
-    }
-    /* If we couldn't get the encoding right, we just want an empty array. */
-    else
-    {
-        parse_data->orig_lines = g_ptr_array_new();
-    }
-
-    /* Record the original row lengths of parse_data->orig_lines. */
-    if (parse_data->orig_row_lengths != NULL)
-        g_array_free(parse_data->orig_row_lengths, FALSE);
-
-    parse_data->orig_row_lengths =
-    g_array_sized_new(FALSE, FALSE, sizeof(int), parse_data->orig_lines->len);
-    g_array_set_size(parse_data->orig_row_lengths, parse_data->orig_lines->len);
-    parse_data->orig_max_row = 0;
-    for (i = 0; i < parse_data->orig_lines->len; i++)
-    {
-        int length = ((GPtrArray*)parse_data->orig_lines->pdata[i])->len;
-        parse_data->orig_row_lengths->data[i] = length;
-        if (length > parse_data->orig_max_row)
-            parse_data->orig_max_row = length;
-    }
-
-    /* If it failed, generate an error. */
-    if (parse_data->orig_lines == NULL)
-    {
-        g_set_error(error, 0, 0, "Parsing failed.");
-        return 1;
-    }
-
-    /* Now that we have data, let's set max_cols. */
-    for (i = 0; i < parse_data->orig_lines->len; i++)
-    {
-        if (max_cols < ((GPtrArray*)(parse_data->orig_lines->pdata[i]))->len)
-            max_cols = ((GPtrArray*)(parse_data->orig_lines->pdata[i]))->len;
-    }
-
-    if (guessColTypes)
-    {
-        /* Free parse_data->column_types if it's already been created. */
-        if (parse_data->column_types != NULL)
-            g_array_free(parse_data->column_types, TRUE);
-
-        /* Create parse_data->column_types and fill it with guesses based
-         * on the contents of each column. */
-        parse_data->column_types = g_array_sized_new(FALSE, FALSE, sizeof(int),
-        max_cols);
-        g_array_set_size(parse_data->column_types, max_cols);
-        /* TODO Make it actually guess. */
-        for (i = 0; i < parse_data->column_types->len; i++)
-        {
-            parse_data->column_types->data[i] = GNC_CSV_NONE;
-        }
-    }
-    else
-    {
-        /* If we don't need to guess column types, we will simply set any
-         * new columns that are created that didn't exist before to "None"
-         * since we don't want gibberish to appear. Note:
-         * parse_data->column_types should have already been
-         * initialized, so we don't check for it being NULL. */
-        int i = parse_data->column_types->len;
-        g_array_set_size(parse_data->column_types, max_cols);
-        for (; i < parse_data->column_types->len; i++)
-        {
-            parse_data->column_types->data[i] = GNC_CSV_NONE;
-        }
-    }
-
-    return 0;
-}
-
-/** A struct containing TransProperties that all describe a single transaction. */
-typedef struct
-{
-    int date_format; /**< The format for parsing dates */
-    Account* account; /**< The account the transaction belongs to */
-    GList* properties; /**< List of TransProperties */
-} TransPropertyList;
-
-/** A struct encapsulating a property of a transaction. */
-typedef struct
-{
-    int type; /**< A value from the GncCsvColumnType enum except
-             * GNC_CSV_NONE and GNC_CSV_NUM_COL_TYPES */
-    void* value; /**< Pointer to the data that will be used to configure a transaction */
-    TransPropertyList* list; /**< The list the property belongs to */
-} TransProperty;
-
-/** Constructor for TransProperty.
- * @param type The type of the new property (see TransProperty.type for possible values)
- */
-static TransProperty* trans_property_new(int type, TransPropertyList* list)
-{
-    TransProperty* prop = g_new(TransProperty, 1);
-    prop->type = type;
-    prop->list = list;
-    prop->value = NULL;
-    return prop;
-}
-
-/** Destructor for TransProperty.
- * @param prop The property to be freed
- */
-static void trans_property_free(TransProperty* prop)
-{
-    switch (prop->type)
-    {
-        /* The types for "Date" and "Balance" (time_t and gnc_numeric,
-         * respectively) are typically not pointed to, we have to free
-         * them, unlike types like char* ("Description"). */
-    case GNC_CSV_DATE:
-    case GNC_CSV_BALANCE:
-    case GNC_CSV_DEPOSIT:
-    case GNC_CSV_WITHDRAWAL:
-        if (prop->value != NULL)
-            g_free(prop->value);
-        break;
-    }
-    g_free(prop);
-}
-
-/** Sets the value of the property by parsing str. Note: this should
- * only be called once on an instance of TransProperty, as calling it
- * more than once can cause memory leaks.
- * @param prop The property being set
- * @param str The string to be parsed
- * @return TRUE on success, FALSE on failure
- */
-static gboolean trans_property_set(TransProperty* prop, char* str)
-{
-    char *endptr, *possible_currency_symbol, *str_dupe;
-    double value;
-    switch (prop->type)
-    {
-    case GNC_CSV_DATE:
-        prop->value = g_new(time_t, 1);
-        *((time_t*)(prop->value)) = parse_date(str, prop->list->date_format);
-        return *((time_t*)(prop->value)) != -1;
-
-    case GNC_CSV_DESCRIPTION:
-    case GNC_CSV_NUM:
-        prop->value = g_strdup(str);
-        return TRUE;
-
-    case GNC_CSV_BALANCE:
-    case GNC_CSV_DEPOSIT:
-    case GNC_CSV_WITHDRAWAL:
-        str_dupe = g_strdup(str); /* First, we make a copy so we can't mess up real data. */
-
-        /* Go through str_dupe looking for currency symbols. */
-        for (possible_currency_symbol = str_dupe; *possible_currency_symbol;
-        possible_currency_symbol = g_utf8_next_char(possible_currency_symbol))
-        {
-            if (g_unichar_type(g_utf8_get_char(possible_currency_symbol)) == G_UNICODE_CURRENCY_SYMBOL)
-            {
-                /* If we find a currency symbol, save the position just ahead
-                 * of the currency symbol (next_symbol), and find the null
-                 * terminator of the string (last_symbol). */
-                char *next_symbol = g_utf8_next_char(possible_currency_symbol), *last_symbol = next_symbol;
-                while (*last_symbol)
-                    last_symbol = g_utf8_next_char(last_symbol);
-
-                /* Move all of the string (including the null byte, which is
-                 * why we have +1 in the size parameter) following the
-                 * currency symbol back one character, thereby overwriting the
-                 * currency symbol. */
-                memmove(possible_currency_symbol, next_symbol, last_symbol - next_symbol + 1);
-                break;
-            }
-        }
-
-        /* Translate the string (now clean of currency symbols) into a number. */
-        value = strtod(str_dupe, &endptr);
-
-        /* If this isn't a valid numeric string, this is an error. */
-        if (endptr != str_dupe + strlen(str_dupe))
-        {
-            g_free(str_dupe);
-            return FALSE;
-        }
-
-        g_free(str_dupe);
-
-        /* Change abs to fabs, to fix bug 586805 */
-        if (fabs(value) > 0.00001)
-        {
-            prop->value = g_new(gnc_numeric, 1);
-            *((gnc_numeric*)(prop->value)) =
-            double_to_gnc_numeric(value, xaccAccountGetCommoditySCU(prop->list->account),
-            GNC_HOW_RND_ROUND_HALF_UP);
-        }
-        return TRUE;
-    }
-    return FALSE; /* We should never actually get here. */
-}
-
-/** Constructor for TransPropertyList.
- * @param account The account with which transactions should be built
- * @param date_format An index from date_format_user for how date properties should be parsed
- * @return A pointer to a new TransPropertyList
- */
-static TransPropertyList* trans_property_list_new(Account* account, int date_format)
-{
-    TransPropertyList* list = g_new(TransPropertyList, 1);
-    list->account = account;
-    list->date_format = date_format;
-    list->properties = NULL;
-    return list;
-}
-
-/** Destructor for TransPropertyList.
- * @param list The list to be freed
- */
-static void trans_property_list_free(TransPropertyList* list)
-{
-    /* Free all of the properties in this list before freeeing the list itself. */
-    GList* properties_begin = list->properties;
-    while (list->properties != NULL)
-    {
-        trans_property_free((TransProperty*)(list->properties->data));
-        list->properties = g_list_next(list->properties);
-    }
-    g_list_free(properties_begin);
-    g_free(list);
-}
-
-/** Adds a property to the list it's linked with.
- * (The TransPropertyList is not passed as a parameter because the property is
- * associated with a list when it's constructed.)
- * @param property The property to be added to its list
- */
-static void trans_property_list_add(TransProperty* property)
-{
-    property->list->properties = g_list_append(property->list->properties, property);
-}
-
-/** Adds a split to a transaction.
- * @param trans The transaction to add a split to
- * @param account The account used for the split
- * @param book The book where the split should be stored
- * @param amount The amount of the split
- */
-static void trans_add_split(Transaction* trans, Account* account, QofBook* book,
-gnc_numeric amount)
-{
-    Split* split = xaccMallocSplit(book);
-    xaccSplitSetAccount(split, account);
-    xaccSplitSetParent(split, trans);
-    xaccSplitSetAmount(split, amount);
-    xaccSplitSetValue(split, amount);
-    //xaccSplitSetAction(split, "Deposit");
-}
-
-/** Tests a TransPropertyList for having enough essential properties.
- * Essential properties are "Date" and one of the following: "Balance", "Deposit", or
- * "Withdrawal".
- * @param list The list we are checking
- * @param error Contains an error message on failure
- * @return TRUE if there are enough essentials; FALSE otherwise
- */
-static gboolean trans_property_list_verify_essentials(TransPropertyList* list, gchar** error)
-{
-    int i;
-    /* possible_errors lists the ways in which a list can fail this test. */
-    enum PossibleErrorTypes {NO_DATE, NO_AMOUNT, NUM_OF_POSSIBLE_ERRORS};
-    gchar* possible_errors[NUM_OF_POSSIBLE_ERRORS] =
-    {
-        N_("No date column."),
-        N_("No balance, deposit, or withdrawal column.")
-    };
-    int possible_error_lengths[NUM_OF_POSSIBLE_ERRORS] = {0};
-    GList *properties_begin = list->properties, *errors_list = NULL;
-
-    /* Go through each of the properties and erase possible errors. */
-    while (list->properties)
-    {
-        switch (((TransProperty*)(list->properties->data))->type)
-        {
-        case GNC_CSV_DATE:
-            possible_errors[NO_DATE] = NULL;
-            break;
-
-        case GNC_CSV_BALANCE:
-        case GNC_CSV_DEPOSIT:
-        case GNC_CSV_WITHDRAWAL:
-            possible_errors[NO_AMOUNT] = NULL;
-            break;
-        }
-        list->properties = g_list_next(list->properties);
-    }
-    list->properties = properties_begin;
-
-    /* Accumulate a list of the actual errors. */
-    for (i = 0; i < NUM_OF_POSSIBLE_ERRORS; i++)
-    {
-        if (possible_errors[i] != NULL)
-        {
-            errors_list = g_list_append(errors_list, GINT_TO_POINTER(i));
-            /* Since we added an error, we want to also store its length for
-             * when we construct the full error string. */
-            possible_error_lengths[i] = strlen(_(possible_errors[i]));
-        }
-    }
-
-    /* If there are no errors, we can quit now. */
-    if (errors_list == NULL)
-        return TRUE;
-    else
-    {
-        /* full_error_size is the full length of the error message. */
-        int full_error_size = 0, string_length = 0;
-        GList* errors_list_begin = errors_list;
-        gchar *error_message, *error_message_begin;
-
-        /* Find the value for full_error_size. */
-        while (errors_list)
-        {
-            /* We add an extra 1 to account for spaces in between messages. */
-            full_error_size += possible_error_lengths[GPOINTER_TO_INT(errors_list->data)] + 1;
-            errors_list = g_list_next(errors_list);
-        }
-        errors_list = errors_list_begin;
-
-        /* Append the error messages one after another. */
-        error_message = error_message_begin = g_new(gchar, full_error_size);
-        while (errors_list)
-        {
-            i = GPOINTER_TO_INT(errors_list->data);
-            string_length = possible_error_lengths[i];
-
-            /* Copy the error message and put a space after it. */
-            strncpy(error_message, _(possible_errors[i]), string_length);
-            error_message += string_length;
-            *error_message = ' ';
-            error_message++;
-
-            errors_list = g_list_next(errors_list);
-        }
-        *error_message = '\0'; /* Replace the last space with the null byte. */
-        g_list_free(errors_list_begin);
-
-        *error = error_message_begin;
-        return FALSE;
-    }
-}
-
-/** Create a Transaction from a TransPropertyList.
- * @param list The list of properties
- * @param error Contains an error on failure
- * @return On success, a GncCsvTransLine; on failure, the trans pointer is NULL
- */
-static GncCsvTransLine* trans_property_list_to_trans(TransPropertyList* list, gchar** error)
-{
-    GncCsvTransLine* trans_line = g_new(GncCsvTransLine, 1);
-    GList* properties_begin = list->properties;
-    QofBook* book = gnc_account_get_book(list->account);
-    gnc_commodity* currency = xaccAccountGetCommodity(list->account);
-    gnc_numeric amount = double_to_gnc_numeric(0.0, xaccAccountGetCommoditySCU(list->account),
-                         GNC_HOW_RND_ROUND_HALF_UP);
-
-    /* This flag is set to TRUE if we can use the "Deposit" or "Withdrawal" column. */
-    gboolean amount_set = FALSE;
-
-    /* The balance is 0 by default. */
-    trans_line->balance_set = FALSE;
-    trans_line->balance = amount;
-
-    /* We make the line_no -1 just to mark that it hasn't been set. We
-     * may get rid of line_no soon anyway, so it's not particularly
-     * important. */
-    trans_line->line_no = -1;
-
-    /* Make sure this is a transaction with all the columns we need. */
-    if (!trans_property_list_verify_essentials(list, error))
-    {
-        g_free(trans_line);
-        return NULL;
-    }
-
-    trans_line->trans = xaccMallocTransaction(book);
-    xaccTransBeginEdit(trans_line->trans);
-    xaccTransSetCurrency(trans_line->trans, currency);
-
-    /* Go through each of the properties and edit the transaction accordingly. */
-    list->properties = properties_begin;
-    while (list->properties != NULL)
-    {
-        TransProperty* prop = (TransProperty*)(list->properties->data);
-        switch (prop->type)
-        {
-        case GNC_CSV_DATE:
-            xaccTransSetDatePostedSecs(trans_line->trans, *((time_t*)(prop->value)));
-            break;
-
-        case GNC_CSV_DESCRIPTION:
-            xaccTransSetDescription(trans_line->trans, (char*)(prop->value));
-            break;
-
-        case GNC_CSV_NUM:
-            xaccTransSetNum(trans_line->trans, (char*)(prop->value));
-            break;
-
-        case GNC_CSV_DEPOSIT: /* Add deposits to the existing amount. */
-            if (prop->value != NULL)
-            {
-                amount = gnc_numeric_add(*((gnc_numeric*)(prop->value)),
-                                         amount,
-                                         xaccAccountGetCommoditySCU(list->account),
-                                         GNC_HOW_RND_ROUND_HALF_UP);
-                amount_set = TRUE;
-                /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */
-                trans_line->balance_set = FALSE;
-            }
-            break;
-
-        case GNC_CSV_WITHDRAWAL: /* Withdrawals are just negative deposits. */
-            if (prop->value != NULL)
-            {
-                amount = gnc_numeric_add(gnc_numeric_neg(*((gnc_numeric*)(prop->value))),
-                                         amount,
-                                         xaccAccountGetCommoditySCU(list->account),
-                                         GNC_HOW_RND_ROUND_HALF_UP);
-                amount_set = TRUE;
-                /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */
-                trans_line->balance_set = FALSE;
-            }
-            break;
-
-        case GNC_CSV_BALANCE: /* The balance gets stored in a separate field in trans_line. */
-            /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */
-            if (!amount_set && prop->value != NULL)
-            {
-                /* This gets put into the actual transaction at the end of gnc_csv_parse_to_trans. */
-                trans_line->balance = *((gnc_numeric*)(prop->value));
-                trans_line->balance_set = TRUE;
-            }
-            break;
-        }
-        list->properties = g_list_next(list->properties);
-    }
-
-    /* Add a split with the cumulative amount value. */
-    trans_add_split(trans_line->trans, list->account, book, amount);
-
-    return trans_line;
-}
-
-/** Creates a list of transactions from parsed data. Transactions that
- * could be created from rows are placed in parse_data->transactions;
- * rows that fail are placed in parse_data->error_lines. (Note: there
- * is no way for this function to "fail," i.e. it only returns 0, so
- * it may be changed to a void function in the future.)
- * @param parse_data Data that is being parsed
- * @param account Account with which transactions are created
- * @param redo_errors TRUE to convert only error data, FALSE for all data
- * @return 0 on success, 1 on failure
- */
-int gnc_csv_parse_to_trans(GncCsvParseData* parse_data, Account* account,
-                           gboolean redo_errors)
-{
-    gboolean hasBalanceColumn;
-    int i, j, max_cols = 0;
-    GArray* column_types = parse_data->column_types;
-    GList *error_lines = NULL, *begin_error_lines = NULL;
-
-    /* last_transaction points to the last element in
-     * parse_data->transactions, or NULL if it's empty. */
-    GList* last_transaction = NULL;
-
-    /* Free parse_data->error_lines and parse_data->transactions if they
-     * already exist. */
-    if (redo_errors) /* If we're redoing errors, we save freeing until the end. */
-    {
-        begin_error_lines = error_lines = parse_data->error_lines;
-    }
-    else
-    {
-        if (parse_data->error_lines != NULL)
-        {
-            g_list_free(parse_data->error_lines);
-        }
-        if (parse_data->transactions != NULL)
-        {
-            g_list_free(parse_data->transactions);
-        }
-    }
-    parse_data->error_lines = NULL;
-
-    if (redo_errors) /* If we're looking only at error data ... */
-    {
-        if (parse_data->transactions == NULL)
-        {
-            last_transaction = NULL;
-        }
-        else
-        {
-            /* Move last_transaction to the end. */
-            last_transaction = parse_data->transactions;
-            while (g_list_next(last_transaction) != NULL)
-            {
-                last_transaction = g_list_next(last_transaction);
-            }
-        }
-        /* ... we use only the lines in error_lines. */
-        if (error_lines == NULL)
-            i = parse_data->orig_lines->len; /* Don't go into the for loop. */
-        else
-            i = GPOINTER_TO_INT(error_lines->data);
-    }
-    else /* Otherwise, we look at all the data. */
-    {
-        /* The following while-loop effectively behaves like the following for-loop:
-         * for(i = 0; i < parse_data->orig_lines->len; i++). */
-        i = 0;
-        last_transaction = NULL;
-    }
-    while (i < parse_data->orig_lines->len)
-    {
-        GPtrArray* line = parse_data->orig_lines->pdata[i];
-        /* This flag is TRUE if there are any errors in this row. */
-        gboolean errors = FALSE;
-        gchar* error_message = NULL;
-        TransPropertyList* list = trans_property_list_new(account, parse_data->date_format);
-        GncCsvTransLine* trans_line = NULL;
-
-        for (j = 0; j < line->len; j++)
-        {
-            /* We do nothing in "None" columns. */
-            if (column_types->data[j] != GNC_CSV_NONE)
-            {
-                /* Affect the transaction appropriately. */
-                TransProperty* property = trans_property_new(column_types->data[j], list);
-                gboolean succeeded = trans_property_set(property, line->pdata[j]);
-                /* TODO Maybe move error handling to within TransPropertyList functions? */
-                if (succeeded)
-                {
-                    trans_property_list_add(property);
-                }
-                else
-                {
-                    errors = TRUE;
-                    error_message = g_strdup_printf(_("%s column could not be understood."),
-                                                    _(gnc_csv_column_type_strs[property->type]));
-                    trans_property_free(property);
-                    break;
-                }
-            }
-        }
-
-        /* If we had success, add the transaction to parse_data->transaction. */
-        if (!errors)
-        {
-            trans_line = trans_property_list_to_trans(list, &error_message);
-            errors = trans_line == NULL;
-        }
-
-        trans_property_list_free(list);
-
-        /* If there were errors, add this line to parse_data->error_lines. */
-        if (errors)
-        {
-            parse_data->error_lines = g_list_append(parse_data->error_lines,
-                                                    GINT_TO_POINTER(i));
-            /* If there's already an error message, we need to replace it. */
-            if (line->len > (int)(parse_data->orig_row_lengths->data[i]))
-            {
-                g_free(line->pdata[line->len - 1]);
-                line->pdata[line->len - 1] = error_message;
-            }
-            else
-            {
-                /* Put the error message at the end of the line. */
-                g_ptr_array_add(line, error_message);
-            }
-        }
-        else
-        {
-            /* If all went well, add this transaction to the list. */
-            trans_line->line_no = i;
-
-            /* We keep the transactions sorted by date. We start at the end
-             * of the list and go backward, simply because the file itself
-             * is probably also sorted by date (but we need to handle the
-             * exception anyway). */
-
-            /* If we can just put it at the end, do so and increment last_transaction. */
-            if (last_transaction == NULL ||
-                    xaccTransGetDate(((GncCsvTransLine*)(last_transaction->data))->trans) <= xaccTransGetDate(trans_line->trans))
-            {
-                parse_data->transactions = g_list_append(parse_data->transactions, trans_line);
-                /* If this is the first transaction, we need to get last_transaction on track. */
-                if (last_transaction == NULL)
-                    last_transaction = parse_data->transactions;
-                else /* Otherwise, we can just continue. */
-                    last_transaction = g_list_next(last_transaction);
-            }
-            /* Otherwise, search backward for the correct spot. */
-            else
-            {
-                GList* insertion_spot = last_transaction;
-                while (insertion_spot != NULL &&
-                        xaccTransGetDate(((GncCsvTransLine*)(insertion_spot->data))->trans) > xaccTransGetDate(trans_line->trans))
-                {
-                    insertion_spot = g_list_previous(insertion_spot);
-                }
-                /* Move insertion_spot one location forward since we have to
-                 * use the g_list_insert_before function. */
-                if (insertion_spot == NULL) /* We need to handle the case of inserting at the beginning of the list. */
-                    insertion_spot = parse_data->transactions;
-                else
-                    insertion_spot = g_list_next(insertion_spot);
-
-                parse_data->transactions = g_list_insert_before(parse_data->transactions, insertion_spot, trans_line);
-            }
-        }
-
-        /* Increment to the next row. */
-        if (redo_errors)
-        {
-            /* Move to the next error line in the list. */
-            error_lines = g_list_next(error_lines);
-            if (error_lines == NULL)
-                i = parse_data->orig_lines->len; /* Don't continue the for loop. */
-            else
-                i = GPOINTER_TO_INT(error_lines->data);
-        }
-        else
-        {
-            i++;
-        }
-    }
-
-    /* If we have a balance column, set the appropriate amounts on the transactions. */
-    hasBalanceColumn = FALSE;
-    for (i = 0; i < parse_data->column_types->len; i++)
-    {
-        if (parse_data->column_types->data[i] == GNC_CSV_BALANCE)
-        {
-            hasBalanceColumn = TRUE;
-            break;
-        }
-    }
-
-    if (hasBalanceColumn)
-    {
-        GList* transactions = parse_data->transactions;
-
-        /* balance_offset is how much the balance currently in the account
-         * differs from what it will be after the transactions are
-         * imported. This will be sum of all the previous transactions for
-         * any given transaction. */
-        gnc_numeric balance_offset = double_to_gnc_numeric(0.0,
-                                     xaccAccountGetCommoditySCU(account),
-                                     GNC_HOW_RND_ROUND_HALF_UP);
-        while (transactions != NULL)
-        {
-            GncCsvTransLine* trans_line = (GncCsvTransLine*)transactions->data;
-            if (trans_line->balance_set)
-            {
-                time_t date = xaccTransGetDate(trans_line->trans);
-                /* Find what the balance should be by adding the offset to the actual balance. */
-                gnc_numeric existing_balance = gnc_numeric_add(balance_offset,
-                                               xaccAccountGetBalanceAsOfDate(account, date),
-                                               xaccAccountGetCommoditySCU(account),
-                                               GNC_HOW_RND_ROUND_HALF_UP);
-
-                /* The amount of the transaction is the difference between the new and existing balance. */
-                gnc_numeric amount = gnc_numeric_sub(trans_line->balance,
-                                                     existing_balance,
-                                                     xaccAccountGetCommoditySCU(account),
-                                                     GNC_HOW_RND_ROUND_HALF_UP);
-
-                SplitList* splits = xaccTransGetSplitList(trans_line->trans);
-                while (splits)
-                {
-                    SplitList* next_splits = g_list_next(splits);
-                    xaccSplitDestroy((Split*)splits->data);
-                    splits = next_splits;
-                }
-
-                trans_add_split(trans_line->trans, account, gnc_account_get_book(account), amount);
-
-                /* This new transaction needs to be added to the balance offset. */
-                balance_offset = gnc_numeric_add(balance_offset,
-                                                 amount,
-                                                 xaccAccountGetCommoditySCU(account),
-                                                 GNC_HOW_RND_ROUND_HALF_UP);
-            }
-            transactions = g_list_next(transactions);
-        }
-    }
-
-    if (redo_errors) /* Now that we're at the end, we do the freeing. */
-    {
-        g_list_free(begin_error_lines);
-    }
-
-    /* We need to resize parse_data->column_types since errors may have added columns. */
-    for (i = 0; i < parse_data->orig_lines->len; i++)
-    {
-        if (max_cols < ((GPtrArray*)(parse_data->orig_lines->pdata[i]))->len)
-            max_cols = ((GPtrArray*)(parse_data->orig_lines->pdata[i]))->len;
-    }
-    i = parse_data->column_types->len;
-    parse_data->column_types = g_array_set_size(parse_data->column_types, max_cols);
-    for (; i < max_cols; i++)
-    {
-        parse_data->column_types->data[i] = GNC_CSV_NONE;
-    }
-
-    return 0;
-}

Deleted: gnucash/trunk/src/import-export/csv/gnc-csv-model.h
===================================================================
--- gnucash/trunk/src/import-export/csv/gnc-csv-model.h	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gnc-csv-model.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,124 +0,0 @@
-/********************************************************************\
- * This program is free software; you can redistribute it and/or    *
- * modify it under the terms of the GNU General Public License as   *
- * published by the Free Software Foundation; either version 2 of   *
- * the License, or (at your option) any later version.              *
- *                                                                  *
- * This program is distributed in the hope that it will be useful,  *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
- * GNU General Public License for more details.                     *
- *                                                                  *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact:                        *
- *                                                                  *
- * Free Software Foundation           Voice:  +1-617-542-5942       *
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
- * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
-\********************************************************************/
-
-/** @file
-     @brief CSV import GUI
-     *
-     gnc-csv-import.h
-     @author Copyright (c) 2007 Benny Sperisen <lasindi at gmail.com>
- */
-
-#ifndef GNC_CSV_MODEL_H
-#define GNC_CSV_MODEL_H
-
-#include "config.h"
-
-#include "Account.h"
-#include "Transaction.h"
-
-#include "stf/stf-parse.h"
-
-/** Enumeration for column types. These are the different types of
- * columns that can exist in a CSV/Fixed-Width file. There should be
- * no two columns with the same type except for the GNC_CSV_NONE
- * type. */
-enum GncCsvColumnType {GNC_CSV_NONE,
-                       GNC_CSV_DATE,
-                       GNC_CSV_DESCRIPTION,
-                       GNC_CSV_BALANCE,
-                       GNC_CSV_DEPOSIT,
-                       GNC_CSV_WITHDRAWAL,
-                       GNC_CSV_NUM,
-                       GNC_CSV_NUM_COL_TYPES
-                      };
-
-/** Enumeration for error types. These are the different types of
- * errors that various functions used for the CSV/Fixed-Width importer
- * can have. */
-enum GncCsvErrorType {GNC_CSV_FILE_OPEN_ERR,
-                      GNC_CSV_ENCODING_ERR
-                     };
-
-/** Struct for containing a string. This struct simply contains
- * pointers to the beginning and end of a string. We need this because
- * the STF code that gnc_csv_parse calls requires these pointers. */
-typedef struct
-{
-    char* begin;
-    char* end;
-} GncCsvStr;
-
-/* TODO We now sort transactions by date, not line number, so we
- * should probably get rid of this struct and uses of it. */
-
-/** Struct pairing a transaction with a line number. This struct is
- * used to keep the transactions in order. When rows are separated
- * into "valid" and "error" lists (in case some of the rows have cells
- * that are unparseable), we want the user to still be able to
- * "correct" the error list. If we keep the line numbers of valid
- * transactions, we can then put transactions created from the newly
- * corrected rows into the right places. */
-typedef struct
-{
-    int line_no;
-    Transaction* trans;
-    gnc_numeric balance; /**< The (supposed) balance after this transaction takes place */
-    gboolean balance_set; /**< TRUE if balance has been set from user data, FALSE otherwise */
-} GncCsvTransLine;
-
-extern const int num_date_formats;
-/* A set of date formats that the user sees. */
-extern const gchar* date_format_user[];
-
-/* This array contains all of the different strings for different column types. */
-extern gchar* gnc_csv_column_type_strs[];
-
-/** Struct containing data for parsing a CSV/Fixed-Width file. */
-typedef struct
-{
-    gchar* encoding;
-    GMappedFile* raw_mapping; /**< The mapping containing raw_str */
-    GncCsvStr raw_str; /**< Untouched data from the file as a string */
-    GncCsvStr file_str; /**< raw_str translated into UTF-8 */
-    GPtrArray* orig_lines; /**< file_str parsed into a two-dimensional array of strings */
-    GArray* orig_row_lengths; /**< The lengths of rows in orig_lines
-                             * before error messages are appended */
-    int orig_max_row; /**< Holds the maximum value in orig_row_lengths */
-    GStringChunk* chunk; /**< A chunk of memory in which the contents of orig_lines is stored */
-    StfParseOptions_t* options; /**< Options controlling how file_str should be parsed */
-    GArray* column_types; /**< Array of values from the GncCsvColumnType enumeration */
-    GList* error_lines; /**< List of row numbers in orig_lines that have errors */
-    GList* transactions; /**< List of GncCsvTransLine*s created using orig_lines and column_types */
-    int date_format; /**< The format of the text in the date columns from date_format_internal. */
-} GncCsvParseData;
-
-GncCsvParseData* gnc_csv_new_parse_data(void);
-
-void gnc_csv_parse_data_free(GncCsvParseData* parse_data);
-
-int gnc_csv_load_file(GncCsvParseData* parse_data, const char* filename,
-                      GError** error);
-
-int gnc_csv_convert_encoding(GncCsvParseData* parse_data, const char* encoding, GError** error);
-
-int gnc_csv_parse(GncCsvParseData* parse_data, gboolean guessColTypes, GError** error);
-
-int gnc_csv_parse_to_trans(GncCsvParseData* parse_data, Account* account, gboolean redo_errors);
-
-#endif

Deleted: gnucash/trunk/src/import-export/csv/gnc-plugin-csv-ui.xml
===================================================================
--- gnucash/trunk/src/import-export/csv/gnc-plugin-csv-ui.xml	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gnc-plugin-csv-ui.xml	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,11 +0,0 @@
-<ui>
-  <menubar>
-    <menu name="File" action="FileAction">
-      <menu name="FileImport" action="FileImportAction">
-      	<placeholder name="FileImportPlaceholder">
-      	   <menuitem name="FileCsvImport" action="CsvImportAction"/>
-      	</placeholder>
-      </menu>
-    </menu>
-  </menubar>
-</ui>

Deleted: gnucash/trunk/src/import-export/csv/gnc-plugin-csv.c
===================================================================
--- gnucash/trunk/src/import-export/csv/gnc-plugin-csv.c	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gnc-plugin-csv.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,165 +0,0 @@
-/*
- * gnc-plugin-csv.c --
- * Copyright (C) 2003 David Hampton <hampton at employees.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, contact:
- *
- * Free Software Foundation           Voice:  +1-617-542-5942
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
- * Boston, MA  02110-1301,  USA       gnu at gnu.org
- */
-
-#include "config.h"
-
-#include <gtk/gtk.h>
-#include <glib/gi18n.h>
-
-#include "gnc-plugin-csv.h"
-#include "gnc-plugin-manager.h"
-
-#include "gnc-csv-import.h"
-
-static void gnc_plugin_csv_class_init (GncPluginCsvClass *klass);
-static void gnc_plugin_csv_init (GncPluginCsv *plugin);
-static void gnc_plugin_csv_finalize (GObject *object);
-
-/* Command callbacks */
-static void gnc_plugin_csv_cmd_import (GtkAction *action, GncMainWindowActionData *data);
-
-
-#define PLUGIN_ACTIONS_NAME "gnc-plugin-csv-actions"
-#define PLUGIN_UI_FILENAME  "gnc-plugin-csv-ui.xml"
-
-static GtkActionEntry gnc_plugin_actions [] =
-{
-    {
-        "CsvImportAction", GTK_STOCK_CONVERT, N_("Import _CSV/Fixed-Width..."), NULL,
-        N_(" a CSV/Fixed-Width file"),
-        G_CALLBACK (gnc_plugin_csv_cmd_import)
-    },
-};
-static guint gnc_plugin_n_actions = G_N_ELEMENTS (gnc_plugin_actions);
-
-typedef struct GncPluginCsvPrivate
-{
-    gpointer dummy;
-} GncPluginCsvPrivate;
-
-#define GNC_PLUGIN_CSV_GET_PRIVATE(o)  \
-   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN_CSV, GncPluginCsvPrivate))
-
-static GObjectClass *parent_class = NULL;
-
-GType
-gnc_plugin_csv_get_type (void)
-{
-    static GType gnc_plugin_csv_type = 0;
-
-    if (gnc_plugin_csv_type == 0)
-    {
-        static const GTypeInfo our_info =
-        {
-            sizeof (GncPluginCsvClass),
-            NULL,		/* base_init */
-            NULL,		/* base_finalize */
-            (GClassInitFunc) gnc_plugin_csv_class_init,
-            NULL,		/* class_finalize */
-            NULL,		/* class_data */
-            sizeof (GncPluginCsv),
-            0,		/* n_preallocs */
-            (GInstanceInitFunc) gnc_plugin_csv_init,
-        };
-
-        gnc_plugin_csv_type = g_type_register_static (GNC_TYPE_PLUGIN,
-                              "GncPluginCsv",
-                              &our_info, 0);
-    }
-
-    return gnc_plugin_csv_type;
-}
-
-GncPlugin *
-gnc_plugin_csv_new (void)
-{
-    return GNC_PLUGIN (g_object_new (GNC_TYPE_PLUGIN_CSV, NULL));
-}
-
-static void
-gnc_plugin_csv_class_init (GncPluginCsvClass *klass)
-{
-    GObjectClass *object_class = G_OBJECT_CLASS (klass);
-    GncPluginClass *plugin_class = GNC_PLUGIN_CLASS (klass);
-
-    parent_class = g_type_class_peek_parent (klass);
-
-    object_class->finalize = gnc_plugin_csv_finalize;
-
-    /* plugin info */
-    plugin_class->plugin_name  = GNC_PLUGIN_CSV_NAME;
-
-    /* widget addition/removal */
-    plugin_class->actions_name = PLUGIN_ACTIONS_NAME;
-    plugin_class->actions      = gnc_plugin_actions;
-    plugin_class->n_actions    = gnc_plugin_n_actions;
-    plugin_class->ui_filename  = PLUGIN_UI_FILENAME;
-
-    g_type_class_add_private(klass, sizeof(GncPluginCsvPrivate));
-}
-
-static void
-gnc_plugin_csv_init (GncPluginCsv *plugin)
-{
-}
-
-static void
-gnc_plugin_csv_finalize (GObject *object)
-{
-    GncPluginCsv *plugin;
-    GncPluginCsvPrivate *priv;
-
-    g_return_if_fail (GNC_IS_PLUGIN_CSV (object));
-
-    plugin = GNC_PLUGIN_CSV (object);
-    priv = GNC_PLUGIN_CSV_GET_PRIVATE(plugin);
-
-    G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/************************************************************
- *              Plugin Function Implementation              *
- ************************************************************/
-
-/************************************************************
- *                    Command Callbacks                     *
- ************************************************************/
-
-static void
-gnc_plugin_csv_cmd_import (GtkAction *action,
-                           GncMainWindowActionData *data)
-{
-    gnc_file_csv_import();
-}
-
-
-/************************************************************
- *                    Plugin Bootstrapping                   *
- ************************************************************/
-
-void
-gnc_plugin_csv_create_plugin (void)
-{
-    GncPlugin *plugin = gnc_plugin_csv_new ();
-
-    gnc_plugin_manager_add_plugin (gnc_plugin_manager_get (), plugin);
-}

Deleted: gnucash/trunk/src/import-export/csv/gnc-plugin-csv.h
===================================================================
--- gnucash/trunk/src/import-export/csv/gnc-plugin-csv.h	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gnc-plugin-csv.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,62 +0,0 @@
-/*
- * gnc-plugin-csv.h --
- * Copyright (C) 2003 David Hampton <hampton at employees.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, contact:
- *
- * Free Software Foundation           Voice:  +1-617-542-5942
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
- * Boston, MA  02110-1301,  USA       gnu at gnu.org
- */
-
-#ifndef __GNC_PLUGIN_CSV_H
-#define __GNC_PLUGIN_CSV_H
-
-#include <gtk/gtk.h>
-
-#include "gnc-plugin.h"
-
-G_BEGIN_DECLS
-
-/* type macros */
-#define GNC_TYPE_PLUGIN_CSV            (gnc_plugin_csv_get_type ())
-#define GNC_PLUGIN_CSV(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_PLUGIN_CSV, GncPluginCsv))
-#define GNC_PLUGIN_CSV_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_PLUGIN_CSV, GncPluginCsvClass))
-#define GNC_IS_PLUGIN_CSV(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_PLUGIN_CSV))
-#define GNC_IS_PLUGIN_CSV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_CSV))
-#define GNC_PLUGIN_CSV_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_CSV, GncPluginCsvClass))
-
-#define GNC_PLUGIN_CSV_NAME "gnc-plugin-csv"
-
-/* typedefs & structures */
-typedef struct
-{
-    GncPlugin gnc_plugin;
-} GncPluginCsv;
-
-typedef struct
-{
-    GncPluginClass gnc_plugin;
-} GncPluginCsvClass;
-
-/* function prototypes */
-GType      gnc_plugin_csv_get_type (void);
-
-GncPlugin *gnc_plugin_csv_new      (void);
-
-void       gnc_plugin_csv_create_plugin (void);
-
-G_END_DECLS
-
-#endif /* __GNC_PLUGIN_CSV_H */

Deleted: gnucash/trunk/src/import-export/csv/gncmod-csv-import.c
===================================================================
--- gnucash/trunk/src/import-export/csv/gncmod-csv-import.c	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/csv/gncmod-csv-import.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,91 +0,0 @@
-/********************************************************************\
- * This program is free software; you can redistribute it and/or    *
- * modify it under the terms of the GNU General Public License as   *
- * published by the Free Software Foundation; either version 2 of   *
- * the License, or (at your option) any later version.              *
- *                                                                  *
- * This program is distributed in the hope that it will be useful,  *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
- * GNU General Public License for more details.                     *
- *                                                                  *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact:                        *
- *                                                                  *
- * Free Software Foundation           Voice:  +1-617-542-5942       *
- * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
- * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
-\********************************************************************/
-/** @addtogroup Import_Export
-    @{ */
-/**@internal
- at file gncmod-csv-import.c
- at brief module definition/initialization for the csv importer
- at author Copyright (c) 2002 Benoit Grégoire bock at step.polymtl.ca
-*/
-#include "config.h"
-
-#include <gmodule.h>
-
-#include "gnc-module.h"
-#include "gnc-module-api.h"
-#include "gnc-plugin-csv.h"
-
-GNC_MODULE_API_DECL(libgncmod_csv)
-
-/* version of the gnc module system interface we require */
-int libgncmod_csv_gnc_module_system_interface = 0;
-
-/* module versioning uses libtool semantics. */
-int libgncmod_csv_gnc_module_current  = 0;
-int libgncmod_csv_gnc_module_revision = 0;
-int libgncmod_csv_gnc_module_age      = 0;
-
-//static GNCModule bus_core;
-//static GNCModule file;
-
-
-char *
-libgncmod_csv_gnc_module_path(void)
-{
-    return g_strdup("gnucash/import-export/csv");
-}
-
-char *
-libgncmod_csv_gnc_module_description(void)
-{
-    return g_strdup("Gnome GUI and C code for CSV importer using libcsv");
-}
-
-int
-libgncmod_csv_gnc_module_init(int refcount)
-{
-    if (!gnc_module_load("gnucash/engine", 0))
-    {
-        return FALSE;
-    }
-    if (!gnc_module_load("gnucash/app-utils", 0))
-    {
-        return FALSE;
-    }
-    if (!gnc_module_load("gnucash/gnome-utils", 0))
-    {
-        return FALSE;
-    }
-    if (!gnc_module_load("gnucash/import-export", 0))
-    {
-        return FALSE;
-    }
-
-    /* Add menu items with C callbacks */
-    gnc_plugin_csv_create_plugin();
-
-    return TRUE;
-}
-
-int
-libgncmod_csv_gnc_module_end(int refcount)
-{
-    return TRUE;
-}
-/** @}*/

Copied: gnucash/trunk/src/import-export/csv-import/Makefile.am (from rev 22085, gnucash/trunk/src/import-export/csv/Makefile.am)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/Makefile.am	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/Makefile.am	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,68 @@
+SUBDIRS = . schemas
+
+pkglib_LTLIBRARIES=libgncmod-csv-import.la
+
+libgncmod_csv_import_la_SOURCES = \
+  gncmod-csv-import.c \
+  assistant-csv-account-import.c \
+  assistant-csv-trans-import.c \
+  gnc-plugin-csv-import.c \
+  csv-account-import.c \
+  gnc-csv-model.c \
+  gnc-csv-gnumeric-popup.c \
+  gnc-csv-import.c
+
+noinst_HEADERS = \
+  assistant-csv-account-import.h \
+  assistant-csv-trans-import.h \
+  gnc-plugin-csv-import.h \
+  csv-account-import.h \
+  gnc-csv-model.h \
+  gnc-csv-gnumeric-popup.h \
+  gnc-csv-import.h
+
+libgncmod_csv_import_la_LDFLAGS = -avoid-version
+
+libgncmod_csv_import_la_LIBADD = \
+  ${top_builddir}/src/import-export/libgncmod-generic-import.la \
+  ${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la \
+  ${top_builddir}/src/app-utils/libgncmod-app-utils.la \
+  ${top_builddir}/src/engine/libgncmod-engine.la \
+  ${top_builddir}/src/core-utils/libgnc-core-utils.la \
+  ${top_builddir}/src/gnc-module/libgnc-module.la \
+  ${top_builddir}/lib/stf/libgnc-stf.la \
+  ${top_builddir}/lib/libc/libc-missing.la \
+  ${top_builddir}/src/libqof/qof/libgnc-qof.la \
+  ${GOFFICE_LIBS} \
+  ${GLIB_LIBS}
+
+AM_CPPFLAGS = \
+  -I${top_srcdir}/src \
+  -I${top_srcdir}/src/core-utils \
+  -I${top_srcdir}/src/engine \
+  -I${top_srcdir}/src/gnc-module \
+  -I${top_srcdir}/src/app-utils \
+  -I${top_srcdir}/src/gnome \
+  -I${top_srcdir}/src/gnome-utils \
+  -I${top_srcdir}/src/import-export \
+  -I${top_srcdir}/src/libqof/qof \
+  -I${top_srcdir}/lib/libc \
+  -I${top_srcdir}/lib \
+  ${GCONF_CFLAGS} \
+  ${GUILE_INCS} \
+  ${GLIB_CFLAGS} \
+  $(GOFFICE_CFLAGS)
+
+uidir = $(GNC_UI_DIR)
+ui_DATA = \
+	gnc-plugin-csv-import-ui.xml
+
+gtkbuilderdir = ${GNC_GTKBUILDER_DIR}
+gtkbuilder_DATA = \
+	assistant-csv-account-import.glade \
+	assistant-csv-trans-import.glade \
+        gnc-csv-import.glade
+
+EXTRA_DIST = $(ui_DATA) $(gtkbuilder_DATA)
+
+INCLUDES = -DG_LOG_DOMAIN=\"gnc.import.csv\"

Added: gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.c
===================================================================
--- gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.c	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,599 @@
+/*******************************************************************\
+ * assistant-csv-account-import.c -- An assistant for importing     *
+ *                                         Accounts from a file.    *
+ *                                                                  *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+/** @file assistant-csv-account-import.c
+    @brief CSV Import Assistant
+    @author Copyright (c) 2012 Robert Fewell
+*/
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "dialog-utils.h"
+#include "gnc-ui.h"
+#include "gnc-uri-utils.h"
+#include "gnc-ui-util.h"
+
+#include "gnc-component-manager.h"
+
+#include "assistant-utils.h"
+#include "assistant-csv-account-import.h"
+#include "csv-account-import.h"
+
+#define GCONF_SECTION "dialogs/import/csv"
+#define ASSISTANT_CSV_IMPORT_CM_CLASS "assistant-csv-account-import"
+
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = GNC_MOD_ASSISTANT;
+
+/*************************************************************************/
+
+void csv_import_assistant_prepare (GtkAssistant  *assistant, GtkWidget *page, gpointer user_data);
+void csv_import_assistant_finish (GtkAssistant *gtkassistant, gpointer user_data);
+void csv_import_assistant_cancel (GtkAssistant *gtkassistant, gpointer user_data);
+void csv_import_assistant_close (GtkAssistant *gtkassistant, gpointer user_data);
+
+void csv_import_assistant_start_page_prepare (GtkAssistant *gtkassistant, gpointer user_data);
+void csv_import_assistant_account_page_prepare (GtkAssistant *gtkassistant, gpointer user_data);
+void csv_import_assistant_file_page_prepare (GtkAssistant *assistant, gpointer user_data);
+void csv_import_assistant_finish_page_prepare (GtkAssistant *assistant, gpointer user_data);
+void csv_import_assistant_summary_page_prepare (GtkAssistant *assistant, gpointer user_data);
+
+void csv_import_sep_cb (GtkWidget *radio, gpointer user_data );
+void csv_import_hrows_cb (GtkWidget *spin, gpointer user_data );
+
+void csv_import_file_chooser_confirm_cb (GtkWidget *button, CsvImportInfo *info);
+
+static gchar *gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input);
+
+static const gchar *finish_tree_string = N_(
+            "The accounts will be imported from the file '%s' when you click 'Apply'.\n\n"
+            "You can also go back and verify your selections by clicking on 'Back'"
+            " or 'Cancel' to Abort Import.\n");
+
+/*************************************************************************/
+
+/**************************************************
+ * csv_file_chooser_confirm_cb
+ *
+ * call back for ok button in file chooser widget
+ **************************************************/
+void
+csv_import_file_chooser_confirm_cb (GtkWidget *button, CsvImportInfo *info)
+{
+    GtkAssistant *assistant = GTK_ASSISTANT(info->window);
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+    gchar *file_name;
+    csv_import_result res;
+
+    gtk_assistant_set_page_complete (assistant, page, FALSE);
+
+    file_name = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(info->file_chooser ));
+
+    if (file_name)
+    {
+        gchar *filepath = gnc_uri_get_path ( file_name );
+        gchar *filedir = g_path_get_dirname( filepath );
+        info->starting_dir = g_strdup(filedir);
+        g_free ( filedir );
+        g_free ( filepath );
+
+        info->file_name = g_strdup(file_name);
+
+        // generate preview
+        gtk_list_store_clear (info->store);
+        res = csv_import_read_file (info->file_name, info->regexp->str, info->store, 1 );
+        if (res == RESULT_OPEN_FAILED)
+            gnc_error_dialog (info->window, _("The input file can not be opened."));
+        else if (res == RESULT_OK)
+            gtk_assistant_set_page_complete (assistant, page, TRUE);
+        else if (res == MATCH_FOUND)
+            gtk_assistant_set_page_complete (assistant, page, TRUE);
+    }
+    g_free(file_name);
+
+    DEBUG("file_name selected is %s", info->file_name);
+    DEBUG("starting directory is %s", info->starting_dir);
+}
+
+
+/*******************************************************
+ * csv_import_hrows_cb
+ *
+ * call back for the start row / number of header rows
+ *******************************************************/
+void csv_import_hrows_cb (GtkWidget *spin, gpointer user_data )
+{
+    CsvImportInfo *info = user_data;
+
+    GtkTreeIter iter;
+    gboolean valid;
+    int num_rows;
+
+    /* Get number of rows for header */
+    info->header_rows = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin));
+
+    /* Get number of rows displayed */
+    num_rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(info->store), NULL);
+
+    /* Modify background color for header rows */
+    if(info->header_rows == 0)
+    {
+        valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(info->store), &iter, NULL, 0 );
+        if(valid)
+            gtk_list_store_set (info->store, &iter, ROW_COLOR, NULL, -1);
+    }
+    else
+    {
+	if (info->header_rows - 1 < num_rows)
+        {
+            valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(info->store), &iter, NULL, info->header_rows - 1 );
+            if(valid)
+                gtk_list_store_set (info->store, &iter, ROW_COLOR, "pink", -1);
+            valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(info->store), &iter);
+            if(valid)
+                gtk_list_store_set (info->store, &iter, ROW_COLOR, NULL, -1);
+        }
+    }
+}
+
+
+/*******************************************************
+ * csv_import_sep_cb
+ *
+ * call back for type of separartor required
+ *******************************************************/
+void csv_import_sep_cb (GtkWidget *radio, gpointer user_data )
+{
+    CsvImportInfo *info = user_data;
+    const gchar *name;
+    gchar *temp;
+
+    if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio)))
+    {
+        LEAVE("1st callback of pair. Defer to 2nd callback.");
+        return;
+    }
+
+    name = gtk_buildable_get_name(GTK_BUILDABLE(radio));
+
+    if (g_strcmp0(name, g_strdup("radio_semi")) == 0)
+        g_string_assign (info->regexp, "^(?<type>[^;]*);(?<full_name>[^;]*);(?<name>[^;]*);(?<code>[^;]*);?(?<description>[^;]*);?(?<color>[^;]*);?(?<notes>[^;]*);?(?<commoditym>[^;]*);?(?<commodityn>[^;]*);?(?<hidden>[^;]*);?(?<tax>[^;]*);?(?<place_holder>[^;]*)$");
+
+    if (g_strcmp0(name, g_strdup("radio_comma")) == 0)
+        g_string_assign (info->regexp, "^(?<type>[^,]*),(?<full_name>[^,]*),(?<name>[^,]*),(?<code>[^,]*),?(?<description>[^,]*),?(?<color>[^,]*),?(?<notes>[^,]*),?(?<commoditym>[^,]*),?(?<commodityn>[^,]*),?(?<hidden>[^,]*),?(?<tax>[^,]*),?(?<place_holder>[^,]*)$");
+
+    if (g_strcmp0(name, g_strdup("radio_semiq")) == 0)
+        g_string_assign (info->regexp, "^((?<type>[^\";]*)|\"(?<type>[^\"]*)\");((?<full_name>[^\";]*)|\"(?<full_name>[^\"]*)\");((?<name>[^\";]*)|\"(?<name>[^\"]*)\");((?<code>[^\";]*)|\"(?<code>[^\"]*)\");((?<description>[^\";]*)|\"(?<description>[^\"]*)\");((?<color>[^\";]*)|\"(?<color>[^\"]*)\");((?<notes>[^\";]*)|\"(?<notes>[^\"]*)\");((?<commoditym>[^\";]*)|\"(?<commoditym>[^\"]*)\");((?<commodityn>[^\";]*)|\"(?<commodityn>[^\"]*)\");((?<hidden>[^\";]*)|\"(?<hidden>[^\"]*)\");((?<tax>[^\";]*)|\"(?<tax>[^\"]*)\");((?<place_holder>[^\";]*)|\"(?<place_holder>[^\"]*)\")$");
+
+    if (g_strcmp0(name, g_strdup("radio_commaq")) == 0)
+        g_string_assign (info->regexp, "^((?<type>[^\",]*)|\"(?<type>[^\"]*)\"),((?<full_name>[^\",]*)|\"(?<full_name>[^\"]*)\"),((?<name>[^\",]*)|\"(?<name>[^\"]*)\"),((?<code>[^\",]*)|\"(?<code>[^\"]*)\"),((?<description>[^\",]*)|\"(?<description>[^\"]*)\"),((?<color>[^\",]*)|\"(?<color>[^\"]*)\"),((?<notes>[^\",]*)|\"(?<notes>[^\"]*)\"),((?<commoditym>[^\",]*)|\"(?<commoditym>[^\"]*)\"),((?<commodityn>[^\",]*)|\"(?<commodityn>[^\"]*)\"),((?<hidden>[^\",]*)|\"(?<hidden>[^\"]*)\"),((?<tax>[^\",]*)|\"(?<tax>[^\"]*)\"),((?<place_holder>[^\",]*)|\"(?<place_holder>[^\"]*)\")$");
+
+    if (g_strcmp0(name, g_strdup("radio_custom")) == 0)
+    {
+        temp = gnc_input_dialog (0, _("Adjust regular expression used for import"), _("This regular expression is used to parse the import file. Modify according to your needs.\n"), info->regexp->str);
+        if (temp)
+        {
+            g_string_assign (info->regexp, temp);
+            g_free (temp);
+        }
+    }
+
+    /* Generate preview */
+    gtk_list_store_clear (info->store);
+
+    if(csv_import_read_file (info->file_name, info->regexp->str, info->store, 11 ) == MATCH_FOUND)
+        gtk_widget_set_sensitive (info->header_row_spin, TRUE);
+    else
+        gtk_widget_set_sensitive (info->header_row_spin, FALSE);
+
+    /* Reset Header spin to 0 */
+    gtk_spin_button_set_value( GTK_SPIN_BUTTON(info->header_row_spin), 0 );
+}
+
+
+/*******************************************************
+ * load_settings
+ *
+ * load the default settings for the assistant
+ *******************************************************/
+static
+void load_settings (CsvImportInfo *info)
+{
+    info->header_rows = 0;
+    info->error = "";
+    info->starting_dir = NULL;
+    info->file_name = NULL;
+    info->error = "";
+
+    /* The default directory for the user to select files. */
+    info->starting_dir = gnc_get_default_directory(GCONF_SECTION);
+}
+
+
+/* =============================================================== */
+
+
+/********************************************************************\
+ * gnc_input_dialog                                                 *
+ *   simple convenience dialog to get a single value from the user  *
+ *   user may choose between "Ok" and "Cancel"                      *
+ *                                                                  *
+ * NOTE: This function does not return until the dialog is closed   *
+ *                                                                  *
+ * Args:   parent  - the parent window or NULL                      *
+ *         title   - the title of the dialog                        *
+ *         msg     - the message to display                         *
+ *         default_input - will be displayed as default input       *
+ * Return: the input (text) the user entered, if pressed "Ok"       *
+ *         NULL, if pressed "Cancel"                                *
+\********************************************************************/
+static gchar *
+gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input)
+{
+    GtkWidget *dialog, *label, *content_area;
+    gint result;
+    GtkWidget *view;
+    GtkTextBuffer *buffer;
+    gchar *user_input;
+    GtkTextIter start, end;
+
+    /* Create the widgets */
+    dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
+                                          GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                                          GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+                                          NULL);
+
+    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+    // add a label
+    label = gtk_label_new (msg);
+    gtk_container_add (GTK_CONTAINER (content_area), label);
+
+    // add a textview
+    view = gtk_text_view_new ();
+    gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD_CHAR);
+    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+    gtk_text_buffer_set_text (buffer, default_input, -1);
+    gtk_container_add (GTK_CONTAINER (content_area), view);
+
+    // run the dialog
+    gtk_widget_show_all (dialog);
+    result = gtk_dialog_run (GTK_DIALOG (dialog));
+
+    if (result == GTK_RESPONSE_REJECT)
+        user_input = 0;
+    else
+    {
+        gtk_text_buffer_get_start_iter (buffer, &start);
+        gtk_text_buffer_get_end_iter (buffer, &end);
+        user_input = gtk_text_buffer_get_text (buffer,
+                                               &start, &end, FALSE);
+    }
+
+    gtk_widget_destroy (dialog);
+
+    return user_input;
+}
+
+
+/* =============================================================== */
+
+
+/*******************************************************
+ * Assistant page prepare functions
+ *******************************************************/
+void
+csv_import_assistant_start_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+    /* Enable the Assistant Buttons */
+    gtk_assistant_set_page_complete (assistant, page, TRUE);
+}
+
+
+void
+csv_import_assistant_file_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+    /* Set the default directory */
+    if (info->starting_dir)
+        gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(info->file_chooser), info->starting_dir);
+
+    /* Disable the Forward Assistant Button */
+    gtk_assistant_set_page_complete (assistant, page, FALSE);
+}
+
+
+void
+csv_import_assistant_account_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+    gtk_list_store_clear (info->store);
+
+    if(csv_import_read_file (info->file_name, info->regexp->str, info->store, 11 ) == MATCH_FOUND)
+        gtk_widget_set_sensitive (info->header_row_spin, TRUE);
+    else
+        gtk_widget_set_sensitive (info->header_row_spin, FALSE);
+}
+
+
+void
+csv_import_assistant_finish_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+    gchar *text;
+
+    /* Set Finish page text */
+    text = g_strdup_printf (gettext (finish_tree_string), info->file_name);
+    gtk_label_set_text (GTK_LABEL(info->finish_label), text);
+    g_free(text);
+
+    /* Save the Window size and directory */
+    gnc_set_default_directory(GCONF_SECTION, info->starting_dir);
+    gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(info->window));
+
+    /* Enable the Assistant Buttons */
+    gtk_assistant_set_page_complete (assistant, page, TRUE);
+}
+
+
+void
+csv_import_assistant_summary_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+    gchar *text, *errtext, *mtext;
+
+    if(!g_strcmp0(info->error,"") == 0)
+    {
+	text = g_strdup_printf(gettext ("Import completed but with errors!\n\nThe number of Accounts added was %u and "
+                                  "updated was %u.\n\nSee below for errors..." ), info->num_new, info->num_updates );
+        errtext = g_strdup_printf ( "%s", info->error);
+        gtk_label_set_text (GTK_LABEL(info->summary_error), errtext);
+        g_free(errtext);
+        g_free(info->error);
+    }
+    else
+	text = g_strdup_printf(gettext ("Import completed successfully!\n\nThe number of Accounts added was %u and "
+                                  "updated was %u.\n" ), info->num_new, info->num_updates );
+
+    mtext = g_strdup_printf("<span size=\"medium\"><b>%s</b></span>", text);
+    gtk_label_set_markup(GTK_LABEL(info->summary_label), mtext);
+
+    g_free(text);
+    g_free(mtext);
+}
+
+
+void
+csv_import_assistant_prepare (GtkAssistant *assistant, GtkWidget *page,
+                      gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+    gint currentpage = gtk_assistant_get_current_page(assistant);
+
+    switch (currentpage)
+    {
+    case 0:
+        /* Current page is Import Start page */
+        csv_import_assistant_start_page_prepare (assistant, user_data);
+        break;
+    case 1:
+        /* Current page is File select page */
+        csv_import_assistant_file_page_prepare (assistant, user_data);
+        break;
+    case 2:
+        /* Current page is Account page */
+        csv_import_assistant_account_page_prepare (assistant, user_data);
+        break;
+    case 3:
+        /* Current page is Finish page */
+        csv_import_assistant_finish_page_prepare (assistant, user_data);
+        break;
+    case 4:
+        /* Current page is Summary page */
+        csv_import_assistant_summary_page_prepare (assistant, user_data);
+        break;
+    }
+}
+
+
+/*******************************************************
+ * Assistant call back functions
+ *******************************************************/
+static void
+csv_import_assistant_destroy_cb (GtkObject *object, gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+    gnc_unregister_gui_component_by_data (ASSISTANT_CSV_IMPORT_CM_CLASS, info);
+    g_free (info);
+}
+
+void
+csv_import_assistant_cancel (GtkAssistant *assistant, gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+    gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_CM_CLASS, info);
+}
+
+void
+csv_import_assistant_close (GtkAssistant *assistant, gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+    gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_CM_CLASS, info);
+}
+
+void
+csv_import_assistant_finish (GtkAssistant *assistant, gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+
+    gtk_list_store_clear (info->store);
+    csv_import_read_file (info->file_name, info->regexp->str, info->store, 0 );
+    csv_account_import (info); 
+}
+
+static void
+csv_import_close_handler (gpointer user_data)
+{
+    CsvImportInfo *info = user_data;
+
+    g_free(info->starting_dir);
+    g_free(info->file_name);
+    g_string_free(info->regexp, TRUE);
+
+    gtk_widget_destroy (info->window);
+}
+
+/*******************************************************
+ * Create the Assistant
+ *******************************************************/
+static GtkWidget *
+csv_import_assistant_create (CsvImportInfo *info)
+{
+    GtkBuilder *builder;
+    GtkWidget *window;
+    GtkWidget *box;
+    GtkWidget *button;
+    GtkTreeIter iter;
+    GtkCellRenderer *renderer;
+    GtkTreeViewColumn *column;
+
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file  (builder , "assistant-csv-account-import.glade", "num_hrows_adj");
+    gnc_builder_add_from_file  (builder , "assistant-csv-account-import.glade", "CSV Account Import Assistant");
+    window = GTK_WIDGET(gtk_builder_get_object (builder, "CSV Account Import Assistant"));
+    info->window = window;
+
+    /* Set the assistant colors */
+    gnc_assistant_set_colors (GTK_ASSISTANT (info->window));
+
+    /* Load default settings */
+    load_settings (info);
+
+    /* Start Page */
+
+    /* File chooser Page */
+    info->file_chooser = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_OPEN);
+    button = gtk_button_new_from_stock(GTK_STOCK_OK);
+    gtk_widget_show (button);
+    gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(info->file_chooser), button);
+    g_signal_connect (G_OBJECT (button), "clicked",
+                  G_CALLBACK (csv_import_file_chooser_confirm_cb), info);
+
+    box = GTK_WIDGET(gtk_builder_get_object(builder, "file_page"));
+    gtk_box_pack_start (GTK_BOX (box), info->file_chooser, TRUE, TRUE, 6);
+    gtk_widget_show (info->file_chooser);
+
+    /* Account Tree Page */
+    info->header_row_spin = GTK_WIDGET(gtk_builder_get_object (builder, "num_hrows"));
+    info->tree_view = GTK_WIDGET(gtk_builder_get_object (builder, "treeview"));
+
+    info->regexp = g_string_new ( "^(?<type>[^;]*);(?<full_name>[^;]*);(?<name>[^;]*);(?<code>[^;]*);?(?<description>[^;]*);?(?<color>[^;]*);?(?<notes>[^;]*);?(?<commoditym>[^;]*);?(?<commodityn>[^;]*);?(?<hidden>[^;]*);?(?<tax>[^;]*);?(?<place_holder>[^;]*)$");
+
+    /* create model and bind to view */
+    info->store = gtk_list_store_new (N_COLUMNS,
+                                     G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+                                     G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    gtk_tree_view_set_model( GTK_TREE_VIEW(info->tree_view), GTK_TREE_MODEL(info->store) );
+#define CREATE_COLUMN(description,column_id) \
+  renderer = gtk_cell_renderer_text_new (); \
+  column = gtk_tree_view_column_new_with_attributes (description, renderer, "text", column_id, NULL); \
+  gtk_tree_view_column_add_attribute(column, renderer, "background", ROW_COLOR); \
+  gtk_tree_view_column_set_resizable (column, TRUE); \
+  gtk_tree_view_append_column (GTK_TREE_VIEW (info->tree_view), column);
+    CREATE_COLUMN ("type", TYPE);
+    CREATE_COLUMN ("full__name", FULL_NAME);
+    CREATE_COLUMN ("name", NAME);
+    CREATE_COLUMN ("code", CODE);
+    CREATE_COLUMN ("description", DESCRIPTION);
+    CREATE_COLUMN ("color", COLOR);
+    CREATE_COLUMN ("notes", NOTES);
+    CREATE_COLUMN ("commoditym", COMMODITYM);
+    CREATE_COLUMN ("commodityn", COMMODITYN);
+    CREATE_COLUMN ("hidden", HIDDEN);
+    CREATE_COLUMN ("tax", TAX);
+    CREATE_COLUMN ("place__holder", PLACE_HOLDER);
+
+    /* Finish Page */
+    info->finish_label = GTK_WIDGET(gtk_builder_get_object(builder, "end_page"));
+    /* Summary Page */
+    info->summary_label = GTK_WIDGET(gtk_builder_get_object(builder, "summary_label"));
+    info->summary_error = GTK_WIDGET(gtk_builder_get_object(builder, "summary_error"));
+
+    g_signal_connect (G_OBJECT(window), "destroy",
+                      G_CALLBACK (csv_import_assistant_destroy_cb), info);
+
+    gnc_restore_window_size (GCONF_SECTION, GTK_WINDOW(info->window));
+
+    gtk_builder_connect_signals(builder, info);
+    g_object_unref(G_OBJECT(builder));
+    return window;
+}
+
+
+/********************************************************************\
+ * gnc_file_csv_account_import                                      *
+ * opens up a assistant to import accounts.                         *
+ *                                                                  *
+ * Args:   import_type                                              *
+ * Return: nothing                                                  *
+\********************************************************************/
+void
+gnc_file_csv_account_import(void)
+{
+    CsvImportInfo *info;
+    gint component_id;
+
+    info = g_new0 (CsvImportInfo, 1);
+
+    csv_import_assistant_create (info);
+
+    component_id = gnc_register_gui_component (ASSISTANT_CSV_IMPORT_CM_CLASS,
+                   NULL, csv_import_close_handler,
+                   info);
+
+    gtk_widget_show_all (info->window);
+
+    gnc_window_adjust_for_screen (GTK_WINDOW(info->window));
+}


Property changes on: gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Added: gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.glade
===================================================================
--- gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.glade	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.glade	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,372 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkAssistant" id="CSV Account Import Assistant">
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="title" translatable="yes">CSV Import Assistant</property>
+    <property name="default_width">400</property>
+    <property name="default_height">500</property>
+    <signal name="close" handler="csv_import_assistant_close" swapped="no"/>
+    <signal name="apply" handler="csv_import_assistant_finish" swapped="no"/>
+    <signal name="prepare" handler="csv_import_assistant_prepare" swapped="no"/>
+    <signal name="cancel" handler="csv_import_assistant_cancel" swapped="no"/>
+    <child>
+      <object class="GtkVBox" id="start_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <child>
+          <object class="GtkLabel" id="start_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">
+This assistant will help you import Accounts from a file.
+
+The file must be in the same format as that exported as this is a fixed format import. If the account is missing, based on the full account name, it will be added as long as the security / currency specified exists. If the account exists, then four fields will be updated. These are code, description, notes and color.
+
+Click on 'Forward' to proceed or 'Cancel' to Abort Import.
+</property>
+            <property name="justify">center</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">intro</property>
+        <property name="title" translatable="yes">Import Account Assistant</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="file_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <child>
+          <object class="GtkLabel" id="label4">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">
+Enter file name and location for the Import...
+</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">progress</property>
+        <property name="title" translatable="yes">Choose File to Import</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="import_tree_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <child>
+          <object class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xpad">6</property>
+                <property name="label" translatable="yes">Number of rows for the Header</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinButton" id="num_hrows">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="editable">False</property>
+                <property name="invisible_char">&#x25CF;</property>
+                <property name="invisible_char_set">True</property>
+                <property name="primary_icon_activatable">False</property>
+                <property name="secondary_icon_activatable">False</property>
+                <property name="primary_icon_sensitive">True</property>
+                <property name="secondary_icon_sensitive">True</property>
+                <property name="adjustment">num_hrows_adj</property>
+                <signal name="value-changed" handler="csv_import_hrows_cb" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="separator_frame">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTable" id="table4">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="border_width">12</property>
+                <property name="n_rows">4</property>
+                <property name="n_columns">4</property>
+                <child>
+                  <object class="GtkRadioButton" id="radio_semi">
+                    <property name="label" translatable="yes">Semicolon Separated</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="active">True</property>
+                    <property name="draw_indicator">True</property>
+                    <signal name="toggled" handler="csv_import_sep_cb" swapped="no"/>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkRadioButton" id="radio_semiq">
+                    <property name="label" translatable="yes">Semicolon Separated with Quotes</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">radio_semi</property>
+                    <signal name="toggled" handler="csv_import_sep_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkRadioButton" id="radio_comma">
+                    <property name="label" translatable="yes">Comma Separated</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">radio_semi</property>
+                    <signal name="toggled" handler="csv_import_sep_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkRadioButton" id="radio_commaq">
+                    <property name="label" translatable="yes">Comma Separated with Quotes</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">radio_semi</property>
+                    <signal name="toggled" handler="csv_import_sep_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkRadioButton" id="radio_custom">
+                    <property name="label" translatable="yes">Custom regular Expression</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="draw_indicator">True</property>
+                    <property name="group">radio_semi</property>
+                    <signal name="toggled" handler="csv_import_sep_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label6">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Select Separator Type</property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="padding">7</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="preview_frame">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkScrolledWindow" id="scroll_window">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="border_width">6</property>
+                <property name="hscrollbar_policy">automatic</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <child>
+                  <object class="GtkTreeView" id="treeview">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label8">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Preview</property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">progress</property>
+        <property name="title" translatable="yes">Import Account Preview, first 10 rows only</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="end_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">Press Apply to create export file.
+Cancel to abort.</property>
+        <property name="wrap">True</property>
+      </object>
+      <packing>
+        <property name="page_type">confirm</property>
+        <property name="title" translatable="yes">Import Accounts Now</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="summary_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <child>
+          <object class="GtkLabel" id="summary_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">label</property>
+            <property name="use_markup">True</property>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="summary_error">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">summary</property>
+        <property name="title" translatable="yes">Import Summary</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkAdjustment" id="num_hrows_adj">
+    <property name="upper">100</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+</interface>

Added: gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.h
===================================================================
--- gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.h	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,68 @@
+/*******************************************************************\
+ * assistant-csv-account-import.h -- An assistant for importing     *
+ *                                         Accounts from a file.    *
+ *                                                                  *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+/** @file assistant-csv-account-import.h
+    @brief CSV Import Assistant
+    @author Copyright (c) 2011 Robert Fewell
+*/
+#ifndef GNC_ASSISTANT_CSV_IMPORT_H
+#define GNC_ASSISTANT_CSV_IMPORT_H
+
+
+// Account tree model
+enum tree_import_model_columns
+{
+    TYPE, FULL_NAME, NAME, CODE, DESCRIPTION, COLOR,
+    NOTES, COMMODITYM, COMMODITYN, HIDDEN, TAX, PLACE_HOLDER, ROW_COLOR,
+    N_COLUMNS
+};
+
+typedef struct
+{
+    GtkWidget    *window;
+    GtkWidget    *assistant;
+
+    GtkWidget    *file_chooser;
+    GtkWidget    *tree_view;
+    GtkListStore *store;
+    GString      *regexp;
+    GtkWidget    *header_row_spin;
+    GtkWidget    *finish_label;
+    GtkWidget    *summary_label;
+    GtkWidget    *summary_error;
+
+    gchar        *starting_dir;
+    gchar        *file_name;
+    gchar        *error;
+
+    int           header_rows;
+    int           num_new;
+    int           num_updates;
+} CsvImportInfo;
+
+
+/** The gnc_file_csv_account_import() will let the user import
+ *  accounts from a deliminated file.
+ */
+void gnc_file_csv_account_import (void);
+#endif


Property changes on: gnucash/trunk/src/import-export/csv-import/assistant-csv-account-import.h
___________________________________________________________________
Added: svn:eol-style
   + LF

Added: gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.c
===================================================================
--- gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.c	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,1842 @@
+/*******************************************************************\
+ * assistant-csv-trans-import.c -- An assistant for importing       *
+ *                                     Transactions from a file.    *
+ *                                                                  *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+/** @file assistant-csv-trans-import.c
+    @brief CSV Import Assistant
+    @author Copyright (c) 2012 Robert Fewell
+*/
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "gnc-ui.h"
+#include "gnc-uri-utils.h"
+#include "dialog-utils.h"
+
+#include "gnc-component-manager.h"
+
+#include "assistant-utils.h"
+#include "assistant-csv-trans-import.h"
+
+#include "import-account-matcher.h"
+#include "import-main-matcher.h"
+
+#include "gnc-csv-model.h"
+#include "gnc-csv-gnumeric-popup.h"
+#include <goffice/gtk/go-charmap-sel.h>
+
+#define MIN_COL_WIDTH 70
+#define GCONF_SECTION "dialogs/import/csv"
+#define ASSISTANT_CSV_IMPORT_TRANS_CM_CLASS "assistant-csv-trans-import"
+
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = GNC_MOD_ASSISTANT;
+
+/** Enumeration for separator checkbutton types. These are the
+ * different types of checkbuttons that the user can click to
+ * configure separators in a delimited file. */
+enum SEP_BUTTON_TYPES {SEP_SPACE, SEP_TAB, SEP_COMMA, SEP_COLON, SEP_SEMICOLON, SEP_HYPHEN,
+                       SEP_NUM_OF_TYPES
+                      };
+
+typedef struct
+{
+
+    GtkWidget       *window;
+
+    GtkWidget       *file_chooser;                  /**< The widget for the file chooser */
+    gchar           *starting_dir;                  /**< The starting directory for import file */
+    gchar           *file_name;                     /**< The import file name */
+
+    GtkWidget       *check_label;                   /**< The widget for the check label */
+    GtkWidget       *check_butt;                    /**< The widget for the check label button */
+    GtkWidget       *start_row_spin;                /**< The widget for the start row spinner */
+    GtkWidget       *end_row_spin;                  /**< The widget for the end row spinner */
+    int              start_row;                     /**< The start row */
+    int              end_row;                       /**< The end row */
+
+    GncCsvParseData *parse_data;                    /**< The actual data we are previewing */
+    GOCharmapSel    *encselector;                   /**< The widget for selecting the encoding */
+    GtkCheckButton  *sep_buttons[SEP_NUM_OF_TYPES]; /**< Checkbuttons for common separators */
+    GtkCheckButton  *custom_cbutton;                /**< The checkbutton for a custom separator */
+    GtkEntry        *custom_entry;                  /**< The entry for custom separators */ 
+    GtkComboBox     *date_format_combo;             /**< The widget for selecting the date format */
+    GtkComboBox     *currency_format_combo;             /**< The widget for selecting the currency format */
+    GtkTreeView     *treeview;                      /**< The treeview containing the data */
+    GtkTreeView     *ctreeview;                     /**< The treeview containing the column types */
+    GtkLabel        *instructions_label;            /**< The instructions label */
+    GtkImage        *instructions_image;            /**< The instructions image */
+    gboolean         encoding_selected_called;      /**< Before encoding_selected is first called, this is FALSE.
+                                                       * (See description of encoding_selected.) */
+    gboolean         not_empty;                     /**< FALSE initially, true after the first type gnc_csv_preview_update_assist is called. */
+    gboolean         previewing_errors;             /**< TRUE if the dialog is displaying
+                                                       * error lines, instead of all the file data. */
+    int              code_encoding_calls;           /**< Normally this is 0. If the computer
+                                                       * changes encselector, this is set to
+                                                       * 2. encoding_selected is called twice,
+                                                       * each time decrementing this by 1. */
+    gboolean         approved;                      /**< This is FALSE until the user clicks "OK". */
+    GtkWidget      **treeview_buttons;              /**< This array contains the header buttons in treeview */
+    int              num_of_rows;                   /**< The number of rows in the store */
+    int              longest_line;                  /**< The length of the longest row */
+    int              fixed_context_col;             /**< The number of the column whose the user has clicked */
+    int              fixed_context_dx;              /**< The horizontal coordinate of the pixel in the header of the column
+                                                       * the user has clicked */
+
+    GtkWidget           *account_page;              /**< The widget for the account page, to be packed with the account matcher */
+    GtkWidget           *account_label;             /**< The account page label at bottom of page */
+    AccountPickerDialog *account_picker;            /**< The AccountPickerDialog structure */
+    gboolean             account_page_step;         /**< Allows for auto stepping the account page if we match online id */
+
+    GNCImportMainMatcher *gnc_csv_importer_gui;     /**< The GNCImportMainMatcher structure */
+    GtkWidget            *match_page;               /**< The widget for the matcher page, to be packed with the transaction matcher */
+    GtkWidget            *match_label;              /**< The match label at the bottom of the page */
+    GtkWidget            *help_button;              /**< The widget for the help button on the matcher page */
+    GtkWidget            *cancel_button;            /**< The widget for the new cancel button when going back is blocked */
+    gboolean              match_parse_run;          /**< This is set after the first run */
+
+    GtkWidget            *summary_label;            /**< The summary text */
+
+} CsvImportTrans;
+
+
+/*************************************************************************/
+
+void csv_import_trans_assistant_prepare (GtkAssistant  *assistant, GtkWidget *page, gpointer user_data);
+void csv_import_trans_assistant_finish (GtkAssistant *gtkassistant, gpointer user_data);
+void csv_import_trans_assistant_cancel (GtkAssistant *gtkassistant, gpointer user_data);
+void csv_import_trans_assistant_close (GtkAssistant *gtkassistant, gpointer user_data);
+
+void csv_import_trans_assistant_start_page_prepare (GtkAssistant *gtkassistant, gpointer user_data);
+void csv_import_trans_assistant_file_page_prepare (GtkAssistant *assistant, gpointer user_data);
+void csv_import_trans_assistant_preview_page_prepare (GtkAssistant *gtkassistant, gpointer user_data);
+void csv_import_trans_assistant_account_page_prepare (GtkAssistant *assistant, gpointer user_data);
+void csv_import_trans_assistant_doc_page_prepare (GtkAssistant *assistant, gpointer user_data);
+void csv_import_trans_assistant_match_page_prepare (GtkAssistant *assistant, gpointer user_data);
+void csv_import_trans_assistant_finish_page_prepare (GtkAssistant *assistant, gpointer user_data);
+void csv_import_trans_assistant_summary_page_prepare (GtkAssistant *assistant, gpointer user_data);
+
+void csv_import_trans_srow_cb (GtkWidget *spin, gpointer user_data );
+void csv_import_trans_erow_cb (GtkWidget *spin, gpointer user_data );
+void csv_import_trans_auto_cb (GtkWidget *cb, gpointer user_data );
+void csv_import_trans_file_chooser_confirm_cb (GtkWidget *button, CsvImportTrans *info);
+
+static void gnc_csv_preview_update_assist(CsvImportTrans* info);
+gboolean preview_settings_valid (CsvImportTrans *info);
+
+/*************************************************************************/
+
+/**************************************************
+ * csv_import_trans_file_chooser_confirm_cb
+ *
+ * call back for ok button in file chooser widget
+ **************************************************/
+void
+csv_import_trans_file_chooser_confirm_cb (GtkWidget *button, CsvImportTrans *info)
+{
+    GtkAssistant *assistant = GTK_ASSISTANT(info->window);
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+    GError* error;
+    gchar *file_name;
+    GncCsvParseData* parse_data;
+
+    gtk_assistant_set_page_complete (assistant, page, FALSE);
+
+    file_name = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(info->file_chooser ));
+
+    if (file_name)
+    {
+        gchar *filepath = gnc_uri_get_path ( file_name );
+        gchar *filedir = g_path_get_dirname( filepath );
+        info->starting_dir = g_strdup(filedir);
+        g_free ( filedir );
+        g_free ( filepath );
+
+        info->file_name = g_strdup(file_name);
+        error = NULL;
+        /* Load the file into parse_data. */
+        parse_data = gnc_csv_new_parse_data();
+        if (gnc_csv_load_file(parse_data, file_name, &error))
+        {
+            /* If we couldn't load the file ... */
+            gnc_error_dialog(NULL, "%s", error->message);
+            if (error->code == GNC_CSV_FILE_OPEN_ERR)
+            {
+                gnc_csv_parse_data_free(parse_data);
+                return;
+            }
+            /* If we couldn't guess the encoding, we are content with just
+             * displaying an error message and move on with a blank
+             * display. */
+        }
+        else
+        {
+            /* Parse the data. */
+            if (gnc_csv_parse(parse_data, TRUE, &error))
+            {
+                /* If we couldn't parse the data ... */
+                gnc_error_dialog(NULL, "%s", error->message);
+                gnc_csv_parse_data_free(parse_data);
+            }
+            else
+            {
+                info->parse_data = parse_data;
+                info->previewing_errors = FALSE; /* We're looking at all the data. */
+                info->approved = FALSE; /* This is FALSE until the user clicks "OK". */
+                gtk_assistant_set_page_complete (assistant, page, TRUE);
+            }
+        }
+    }
+    g_free(file_name);
+
+    DEBUG("file_name selected is %s", info->file_name);
+    DEBUG("starting directory is %s", info->starting_dir);
+}
+
+
+/**************************************************
+ * row_selection_update
+ *
+ * refresh the start and end row highlighting
+ **************************************************/
+static
+void row_selection_update (CsvImportTrans* info)
+{
+    GtkListStore *store;
+    GtkTreeIter iter;
+    gboolean valid;
+    int i;
+
+    store = GTK_LIST_STORE( gtk_tree_view_get_model(info->treeview));
+
+    for( i = 0; i <= info->start_row; i++)
+    {
+        /* Modify background color of rows less than start row */
+        if(info->start_row == i)
+        {
+            valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i );
+            if(valid)
+                gtk_list_store_set (store, &iter, 0, NULL, -1);
+        }
+        else
+        {
+            valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i );
+            if(valid)
+                gtk_list_store_set (store, &iter, 0, "pink", -1);
+            valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
+            if(valid)
+                gtk_list_store_set (store, &iter, 0, NULL, -1);
+        }
+
+    }
+
+    for( i = info->num_of_rows - 1; i >= info->end_row; i--)
+    {
+        /* Modify background color of rows more than end row */
+        if( i == info->end_row )
+        {
+            valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i );
+            if(valid)
+                gtk_list_store_set (store, &iter, 0, NULL, -1);
+        }
+        else
+        {
+            valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i );
+            if(valid)
+                gtk_list_store_set (store, &iter, 0, "pink", -1);
+            valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, i - 1 );
+            if(valid)
+                gtk_list_store_set (store, &iter, 0, NULL, -1);
+        }
+    }
+}
+
+
+/*******************************************************
+ * csv_import_trans_srow_cb
+ *
+ * call back for import start row
+ *******************************************************/
+void csv_import_trans_srow_cb (GtkWidget *spin, gpointer user_data )
+{
+    CsvImportTrans *info = user_data;
+    GtkAdjustment *adj;
+
+    /* Get number of rows for header */
+    info->start_row = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin)) - 1;
+
+    info->parse_data->start_row = info->start_row;
+
+    adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(info->end_row_spin));
+    gtk_adjustment_set_lower(adj, info->start_row + 1 );
+
+    /* Refresh the row highlighting */
+    row_selection_update (info);
+}
+
+
+/*******************************************************
+ * csv_import_trans_erow_cb
+ *
+ * call back for import end row
+ *******************************************************/
+void csv_import_trans_erow_cb (GtkWidget *spin, gpointer user_data )
+{
+    CsvImportTrans *info = user_data;
+    GtkAdjustment *adj;
+
+    /* Get number of rows for header */
+    info->end_row = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin)) - 1;
+
+    info->parse_data->end_row = info->end_row + 1;
+
+    adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(info->start_row_spin));
+    gtk_adjustment_set_upper(adj, info->end_row + 1 );
+
+    /* Refresh the row highlighting */
+    row_selection_update (info);
+}
+
+
+/*******************************************************
+ * csv_import_trans_auto_cb
+ *
+ * call back for auto create account / Skip Errors
+ *******************************************************/
+void csv_import_trans_auto_cb (GtkWidget *cb, gpointer user_data )
+{
+    CsvImportTrans *info = user_data;
+
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cb)))
+    {
+        if(info->previewing_errors == TRUE)
+            info->approved = TRUE;
+        else
+            info->account_picker->auto_create = TRUE;
+    }
+    else
+    {
+        if(info->previewing_errors == TRUE)
+            info->approved = FALSE;
+        else
+            info->account_picker->auto_create = FALSE;
+    }
+}
+
+
+/** Returns the cell renderer from a column in the preview's treeview.
+ * @param info The display of the data being imported
+ * @param col The number of the column whose cell renderer is being retrieved
+ * @return The cell renderer of column number col
+ */
+static GtkCellRenderer* gnc_csv_preview_get_cell_renderer(CsvImportTrans* info, int col)
+{
+    GList* renderers = gtk_tree_view_column_get_cell_renderers(gtk_tree_view_get_column(info->treeview, col));
+    GtkCellRenderer* cell = GTK_CELL_RENDERER(renderers->data);
+    g_list_free(renderers);
+    return cell;
+}
+
+
+/** Event handler for separator changes. This function is called
+ * whenever one of the widgets for configuring the separators (the
+ * separator checkbuttons or the custom separator entry) is
+ * changed.
+ * @param widget The widget that was changed
+ * @param info The data that is being configured
+ */
+static void sep_button_clicked(GtkWidget* widget, CsvImportTrans* info)
+{
+    int i;
+    char* stock_separator_characters[] = {" ", "\t", ",", ":", ";", "-"};
+    GSList* checked_separators = NULL;
+    GError* error;
+
+    /* Add the corresponding characters to checked_separators for each
+     * button that is checked. */
+    for (i = 0; i < SEP_NUM_OF_TYPES; i++)
+    {
+        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info->sep_buttons[i])))
+            checked_separators = g_slist_append(checked_separators, stock_separator_characters[i]);
+    }
+
+    /* Add the custom separator if the user checked its button. */
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info->custom_cbutton)))
+    {
+        char* custom_sep = (char*)gtk_entry_get_text(info->custom_entry);
+        if (custom_sep[0] != '\0') /* Don't add a blank separator (bad things will happen!). */
+            checked_separators = g_slist_append(checked_separators, custom_sep);
+    }
+
+    /* Set the parse options using the checked_separators list. */
+    stf_parse_options_csv_set_separators(info->parse_data->options, NULL, checked_separators);
+    g_slist_free(checked_separators);
+
+    /* Parse the data using the new options. We don't want to reguess
+     * the column types because we want to leave the user's
+     * configurations in tact. */
+    if (gnc_csv_parse(info->parse_data, FALSE, &error))
+    {
+        /* Warn the user there was a problem and try to undo what caused
+         * the error. (This will cause a reparsing and ideally a usable
+         * configuration.) */
+        gnc_error_dialog(NULL, "Error in parsing");
+        /* If the user changed the custom separator, erase that custom separator. */
+        if (widget == GTK_WIDGET(info->custom_entry))
+        {
+            gtk_entry_set_text(GTK_ENTRY(widget), "");
+        }
+        /* If the user checked a checkbutton, toggle that checkbutton back. */
+        else
+        {
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
+                                         !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
+        }
+        return;
+    }
+
+    /* If we parsed successfully, redisplay the data. */
+    gnc_csv_preview_update_assist(info);
+
+    /* Refresh the row highlighting */
+    row_selection_update(info);
+}
+
+
+/** Event handler for clicking one of the format type radio
+ * buttons. This occurs if the format (Fixed-Width or CSV) is changed.
+ * @param csv_button The "Separated" radio button
+ * @param info The display of the data being imported
+ */
+static void separated_or_fixed_selected(GtkToggleButton* csv_button, CsvImportTrans* info)
+{
+    GError* error = NULL;
+    /* Set the parsing type correctly. */
+    if (gtk_toggle_button_get_active(csv_button)) /* If we're in CSV mode ... */
+    {
+        stf_parse_options_set_type(info->parse_data->options, PARSE_TYPE_CSV);
+    }
+    else /* If we're in fixed-width mode ... */
+    {
+        stf_parse_options_set_type(info->parse_data->options, PARSE_TYPE_FIXED);
+    }
+
+    /* Reparse the data. */
+    if (gnc_csv_parse(info->parse_data, FALSE, &error))
+    {
+        /* Show an error dialog explaining the problem. */
+        gnc_error_dialog(NULL, "%s", error->message);
+        return;
+    }
+
+    /* Show the new data. */
+    gnc_csv_preview_update_assist(info);
+
+    /* Refresh the row highlighting */
+    row_selection_update(info);
+}
+
+
+/** Event handler for a new encoding. This is called when the user
+ * selects a new encoding; the data is reparsed and shown to the
+ * user.
+ * @param selector The widget the user uses to select a new encoding
+ * @param encoding The encoding that the user selected
+ * @param info The display of the data being imported
+ */
+static void encoding_selected(GOCharmapSel* selector, const char* encoding,
+                              CsvImportTrans* info)
+{
+    /* This gets called twice everytime a new encoding is selected. The
+     * second call actually passes the correct data; thus, we only do
+     * something the second time this is called. */
+
+    /* Prevent code-caused calls of this function from having an impact. */
+    if (info->code_encoding_calls > 0)
+    {
+        info->code_encoding_calls--;
+        return;
+    }
+
+    /* If this is the second time the function is called ... */
+    if (info->encoding_selected_called)
+    {
+        const char* previous_encoding = info->parse_data->encoding;
+        GError* error = NULL;
+        /* Try converting the new encoding and reparsing. */
+        if (gnc_csv_convert_encoding(info->parse_data, encoding, &error) ||
+                gnc_csv_parse(info->parse_data, FALSE, &error))
+        {
+            /* If it fails, change back to the old encoding. */
+            gnc_error_dialog(NULL, "%s", _("Invalid encoding selected"));
+            info->encoding_selected_called = FALSE;
+            go_charmap_sel_set_encoding(selector, previous_encoding);
+            return;
+        }
+
+        gnc_csv_preview_update_assist(info);
+        info->encoding_selected_called = FALSE;
+    }
+    else /* If this is the first call of the function ... */
+    {
+        info->encoding_selected_called = TRUE; /* ... set the flag and wait for the next call. */
+    }
+}
+
+
+/** Event handler for selecting a new date format.
+ * @param format_selector The combo box for selecting date formats
+ * @param info The display of the data being imported
+ */
+static void date_format_selected(GtkComboBox* format_selector, CsvImportTrans* info)
+{
+    info->parse_data->date_format = gtk_combo_box_get_active(format_selector);
+}
+
+
+/** Event handler for selecting a new currency format.
+ * @param currency_selector The combo box for selecting currency formats
+ * @param info The display of the data being imported
+ */
+static void currency_format_selected(GtkComboBox* currency_selector, CsvImportTrans* info)
+{
+    info->parse_data->currency_format = gtk_combo_box_get_active(currency_selector);
+}
+
+
+/*======================================================================*/
+/*================== Beginning of Gnumeric Code ========================*/
+
+/* The following is code copied from Gnumeric 1.7.8 licensed under the
+ * GNU General Public License version 2 and/or version 3. It is from the file
+ * gnumeric/src/dialogs/dialog-stf-fixed-page.c, and it has been
+ * modified slightly to work within GnuCash. */
+
+/*
+ * Copyright 2001 Almer S. Tigelaar <almer at gnome.org>
+ * Copyright 2003 Morten Welinder <terra at gnome.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+enum
+{
+    CONTEXT_STF_IMPORT_MERGE_LEFT = 1,
+    CONTEXT_STF_IMPORT_MERGE_RIGHT = 2,
+    CONTEXT_STF_IMPORT_SPLIT = 3,
+    CONTEXT_STF_IMPORT_WIDEN = 4,
+    CONTEXT_STF_IMPORT_NARROW = 5
+};
+
+static GnumericPopupMenuElement const popup_elements[] =
+{
+    {
+        N_("Merge with column on _left"), GTK_STOCK_REMOVE,
+        0, 1 << CONTEXT_STF_IMPORT_MERGE_LEFT, CONTEXT_STF_IMPORT_MERGE_LEFT
+    },
+    {
+        N_("Merge with column on _right"), GTK_STOCK_REMOVE,
+        0, 1 << CONTEXT_STF_IMPORT_MERGE_RIGHT, CONTEXT_STF_IMPORT_MERGE_RIGHT
+    },
+    { "", NULL, 0, 0, 0 },
+    {
+        N_("_Split this column"), NULL,
+        0, 1 << CONTEXT_STF_IMPORT_SPLIT, CONTEXT_STF_IMPORT_SPLIT
+    },
+    { "", NULL, 0, 0, 0 },
+    {
+        N_("_Widen this column"), GTK_STOCK_GO_FORWARD,
+        0, 1 << CONTEXT_STF_IMPORT_WIDEN, CONTEXT_STF_IMPORT_WIDEN
+    },
+    {
+        N_("_Narrow this column"), GTK_STOCK_GO_BACK,
+        0, 1 << CONTEXT_STF_IMPORT_NARROW, CONTEXT_STF_IMPORT_NARROW
+    },
+    { NULL, NULL, 0, 0, 0 },
+};
+
+static gboolean
+make_new_column (CsvImportTrans* info, int col, int dx, gboolean test_only)
+{
+    PangoLayout *layout;
+    PangoFontDescription *font_desc;
+    int charindex, width;
+    GtkCellRenderer *cell =	gnc_csv_preview_get_cell_renderer(info, col);
+    int colstart, colend;
+    GError* error = NULL;
+
+    colstart = (col == 0)
+               ? 0
+               : stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col - 1);
+    colend = stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col);
+
+    g_object_get (G_OBJECT (cell), "font_desc", &font_desc, NULL);
+    layout = gtk_widget_create_pango_layout (GTK_WIDGET (info->treeview), "x");
+    pango_layout_set_font_description (layout, font_desc);
+    pango_layout_get_pixel_size (layout, &width, NULL);
+    if (width < 1) width = 1;
+    charindex = colstart + (dx + width / 2) / width;
+    g_object_unref (layout);
+    pango_font_description_free (font_desc);
+
+    if (charindex <= colstart || (colend != -1 && charindex >= colend))
+        return FALSE;
+
+    if (!test_only)
+    {
+        stf_parse_options_fixed_splitpositions_add (info->parse_data->options, charindex);
+        if (gnc_csv_parse(info->parse_data, FALSE, &error))
+        {
+            gnc_error_dialog(NULL, "%s", error->message);
+            return FALSE;
+        }
+        gnc_csv_preview_update_assist (info);
+    }
+
+    return TRUE;
+}
+
+static gboolean
+widen_column (CsvImportTrans* info, int col, gboolean test_only)
+{
+    int colcount = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
+    int nextstart, nextnextstart;
+    GError* error = NULL;
+
+    if (col >= colcount - 1)
+        return FALSE;
+
+    nextstart = stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col);
+
+    nextnextstart = (col == colcount - 2)
+                    ? info->longest_line
+                    : stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col + 1);
+
+    if (nextstart + 1 >= nextnextstart)
+        return FALSE;
+
+    if (!test_only)
+    {
+        stf_parse_options_fixed_splitpositions_remove (info->parse_data->options, nextstart);
+        stf_parse_options_fixed_splitpositions_add (info->parse_data->options, nextstart + 1);
+        if (gnc_csv_parse(info->parse_data, FALSE, &error))
+        {
+            gnc_error_dialog(NULL, "%s", error->message);
+            return FALSE;
+        }
+        gnc_csv_preview_update_assist (info);
+    }
+    return TRUE;
+}
+
+static gboolean
+narrow_column (CsvImportTrans* info, int col, gboolean test_only)
+{
+    int colcount = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
+    int thisstart, nextstart;
+    GError* error = NULL;
+
+    if (col >= colcount - 1)
+        return FALSE;
+
+    thisstart = (col == 0)
+                ? 0
+                : stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col - 1);
+    nextstart = stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col);
+
+    if (nextstart - 1 <= thisstart)
+        return FALSE;
+
+    if (!test_only)
+    {
+        stf_parse_options_fixed_splitpositions_remove (info->parse_data->options, nextstart);
+        stf_parse_options_fixed_splitpositions_add (info->parse_data->options, nextstart - 1);
+        if (gnc_csv_parse(info->parse_data, FALSE, &error))
+        {
+            gnc_error_dialog(NULL, "%s", error->message);
+            return FALSE;
+        }
+        gnc_csv_preview_update_assist (info);
+    }
+    return TRUE;
+}
+
+static gboolean
+delete_column (CsvImportTrans* info, int col, gboolean test_only)
+{
+    GError* error = NULL;
+    int colcount = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
+    if (col < 0 || col >= colcount - 1)
+        return FALSE;
+
+    if (!test_only)
+    {
+        int nextstart = stf_parse_options_fixed_splitpositions_nth (info->parse_data->options, col);
+        stf_parse_options_fixed_splitpositions_remove (info->parse_data->options, nextstart);
+        if (gnc_csv_parse(info->parse_data, FALSE, &error))
+        {
+            gnc_error_dialog(NULL, "%s", error->message);
+            return FALSE;
+        }
+        gnc_csv_preview_update_assist (info);
+    }
+    return TRUE;
+}
+
+static void
+select_column (CsvImportTrans* info, int col)
+{
+    GError* error = NULL;
+    int colcount = stf_parse_options_fixed_splitpositions_count (info->parse_data->options);
+    GtkTreeViewColumn *column;
+
+    if (col < 0 || col >= colcount)
+        return;
+
+    column = gtk_tree_view_get_column (info->treeview, col);
+    gtk_widget_grab_focus (column->button);
+}
+
+static gboolean
+fixed_context_menu_handler (GnumericPopupMenuElement const *element,
+                            gpointer user_data)
+{
+    CsvImportTrans* info = user_data;
+    int col = info->fixed_context_col;
+
+    switch (element->index)
+    {
+    case CONTEXT_STF_IMPORT_MERGE_LEFT:
+        delete_column (info, col - 1, FALSE);
+        break;
+    case CONTEXT_STF_IMPORT_MERGE_RIGHT:
+        delete_column (info, col, FALSE);
+        break;
+    case CONTEXT_STF_IMPORT_SPLIT:
+        make_new_column (info, col, info->fixed_context_dx, FALSE);
+        break;
+    case CONTEXT_STF_IMPORT_WIDEN:
+        widen_column (info, col, FALSE);
+        break;
+    case CONTEXT_STF_IMPORT_NARROW:
+        narrow_column (info, col, FALSE);
+        break;
+    default:
+        ; /* Nothing */
+    }
+    return TRUE;
+}
+
+static void
+fixed_context_menu (CsvImportTrans* info, GdkEventButton *event,
+                    int col, int dx)
+{
+    int sensitivity_filter = 0;
+
+    info->fixed_context_col = col;
+    info->fixed_context_dx = dx;
+
+    if (!delete_column (info, col - 1, TRUE))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_LEFT);
+    if (!delete_column (info, col, TRUE))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_RIGHT);
+    if (!make_new_column (info, col, dx, TRUE))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_SPLIT);
+    if (!widen_column (info, col, TRUE))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_WIDEN);
+    if (!narrow_column (info, col, TRUE))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_NARROW);
+
+    select_column (info, col);
+    gnumeric_create_popup_menu (popup_elements, &fixed_context_menu_handler,
+                                info, 0,
+                                sensitivity_filter, event);
+}
+
+/*===================== End of Gnumeric Code ===========================*/
+/*======================================================================*/
+
+
+/** Event handler for the data treeview being resized. When the data
+ * treeview is resized, the column types treeview's columns are also resized to
+ * match.
+ * @param widget The data treeview
+ * @param allocation The size of the data treeview
+ * @param info The display of the data being imported
+ */
+static void treeview_resized(GtkWidget* widget, GtkAllocation* allocation, CsvImportTrans* info)
+{
+    /* ncols is the number of columns in the data. */
+    int i, ncols = info->parse_data->column_types->len;
+
+    /* Go through each column except for the last. (We don't want to set
+     * the width of the last column because the user won't be able to
+     * shrink the dialog back if it's expanded.) */
+
+    for (i = 0; i < ncols - 1; i++)
+    {
+        gint col_width; /* The width of the column in info->treeview. */
+        GtkTreeViewColumn* pcol;
+        GtkTreeViewColumn* ccol; /* The corresponding column in info->ctreeview. */
+
+        /* Get the width. */
+        col_width = gtk_tree_view_column_get_width(gtk_tree_view_get_column(info->treeview, i));
+        /* Set the minumum width for a column so that drop down selector can be seen. */
+        if (col_width < MIN_COL_WIDTH)
+        {
+            col_width = MIN_COL_WIDTH;
+        }
+        pcol = gtk_tree_view_get_column(info->treeview, i);
+        gtk_tree_view_column_set_min_width(pcol, col_width);
+        /* Set ccol's width the same. */
+        ccol = gtk_tree_view_get_column(info->ctreeview, i);
+        gtk_tree_view_column_set_min_width(ccol, col_width);
+        gtk_tree_view_column_set_max_width(ccol, col_width);
+    }
+}
+
+
+/** Event handler for the user selecting a new column type. When the
+ * user selects a new column type, that column's text must be changed
+ * to that selection, and any other columns containing that selection
+ * must be changed to "None" because we don't allow duplicates.
+ * @param renderer The renderer of the column the user changed
+ * @param path There is only 1 row in info->ctreeview, so this is always 0.
+ * @param new_text The text the user selected
+ * @param info The display of the data being imported
+ */
+static void column_type_changed(GtkCellRenderer* renderer, gchar* path,
+                                GtkTreeIter* new_text_iter, CsvImportTrans* info)
+{
+    /* ncols is the number of columns in the data. */
+    int i, ncols = info->parse_data->column_types->len;
+    /* store has the actual strings that appear in info->ctreeview. */
+    GtkTreeModel* store = gtk_tree_view_get_model(info->ctreeview);
+    GtkTreeModel* model;
+    gint textColumn;
+    GtkTreeIter iter;
+    gchar* new_text;
+
+    /* Get the new text */
+    g_object_get(renderer, "model", &model, "text-column", &textColumn, NULL);
+    gtk_tree_model_get(model, new_text_iter, textColumn, &new_text, -1);
+
+    /* Get an iterator for the first (and only) row. */
+    gtk_tree_model_get_iter_first(store, &iter);
+
+    /* Go through each column. */
+    for (i = 0; i < ncols; i++)
+    {
+        /* We need all this stuff so that we can find out whether or not
+         * this was the column that was changed. */
+        GtkCellRenderer* col_renderer; /* The renderer for this column. */
+        /* The column in the treeview we are looking at */
+        GtkTreeViewColumn* col = gtk_tree_view_get_column(info->ctreeview, i);
+        /* The list of renderers for col */
+        GList* rend_list = gtk_tree_view_column_get_cell_renderers(col);
+        /* rend_list has only one entry, which we put in col_renderer. */
+        col_renderer = rend_list->data;
+        g_list_free(rend_list);
+
+        /* If this is not the column that was changed ... */
+        if (col_renderer != renderer)
+        {
+            /* The string that appears in the column */
+            gchar* contents = NULL;
+            /* Get the type string. (store is arranged so that every two
+             * columns is a pair of the model used for the combobox and the
+             * string that appears, so that store looks like:
+             * model 0, string 0, model 1, string 1, ..., model ncols, string ncols. */
+            gtk_tree_model_get(store, &iter, 2 * i + 1, &contents, -1);
+            /* If this column has the same string that the user selected ... */
+            if (!safe_strcmp(contents, new_text))
+            {
+                /* ... set this column to the "None" type. (We can't allow duplicate types.) */
+                gtk_list_store_set(GTK_LIST_STORE(store), &iter, 2 * i + 1,
+                                   _(gnc_csv_column_type_strs[GNC_CSV_NONE]), -1);
+            }
+            g_free(contents);
+        }
+        else /* If this is the column that was changed ... */
+        {
+            /* Set the text for this column to what the user selected. (See
+             * comment above "Get the type string. ..." for why we set
+             * column 2*i+1 in store.) */
+            gtk_list_store_set(GTK_LIST_STORE(store), &iter, 2 * i + 1, new_text, -1);
+        }
+    }
+}
+
+
+/** Event handler for clicking on column headers. This function is
+ * called whenever the user clicks on column headers in
+ * preview->treeview to modify columns when in fixed-width mode.
+ * @param button The button at the top of a column of the treeview
+ * @param event The event that happened (where the user clicked)
+ * @param info The data being configured
+ */
+static void header_button_press_handler(GtkWidget* button, GdkEventButton* event,
+                                        CsvImportTrans* info)
+{
+    /* col is the number of the column that was clicked, and offset is
+       to correct for the indentation of button. */
+    int i, col = 0, offset = GTK_BIN(button)->child->allocation.x - button->allocation.x,
+           ncols = info->parse_data->column_types->len;
+    /* Find the column that was clicked. */
+    for (i = 0; i < ncols; i++)
+    {
+        if (info->treeview_buttons[i] == button)
+        {
+            col = i;
+            break;
+        }
+    }
+
+    /* Don't let the user affect the last column if it has error messages. */
+    if (info->parse_data->orig_max_row < ncols && ncols - col == 1)
+    {
+        return;
+    }
+
+    /* Double clicks can split columns. */
+    if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
+    {
+        make_new_column(info, col, (int)event->x - offset, FALSE);
+    }
+    /* Right clicking brings up a context menu. */
+    else if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+    {
+        fixed_context_menu(info, event, col, (int)event->x - offset);
+    }
+}
+
+
+/* Test for the required minimum number of coloumns selected and 
+ * a valid date format.
+ * Returns TRUE if we do or FALSE if we don't.
+ *
+ * @param info The data being previewed
+ */
+gboolean preview_settings_valid (CsvImportTrans* info)
+{
+    /* Shorten the column_types identifier. */
+    GArray* column_types = info->parse_data->column_types;
+    int i, ncols = column_types->len; /* ncols is the number of columns in the data. */
+    int weight = 0;
+    gboolean valid = TRUE;
+    /* store contains the actual strings appearing in the column types treeview. */
+    GtkTreeModel* store = gtk_tree_view_get_model(info->ctreeview);
+    /* datastore contains the actual strings appearing in the preview treeview. */
+    GtkTreeModel* datastore = gtk_tree_view_get_model(info->treeview);
+    GtkTreeIter iter, iter2;
+    /* Get an iterator for the first (and only) row. */
+    gtk_tree_model_get_iter_first(store, &iter);
+
+    /* Get an iterator for the first required row in the data store. */
+    gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(datastore), &iter2, NULL, info->start_row );
+
+    /* Go through each of the columns. */
+    for (i = 0; i < ncols; i++)
+    {
+        int type; /* The column type contained in this column. */
+        gchar* contents = NULL; /* The column type string in this column. */
+        gchar* prevstr = NULL; /* The string in this column from datastore. */
+        gchar* accstr = NULL; /* The string in this column from datastore. */
+        /* Get the type string first. (store is arranged so that every two
+         * columns is a pair of the model used for the combobox and the
+         * string that appears, so that store looks like:
+         * model 0, string 0, model 1, string 1, ..., model ncols, string ncols. */
+        gtk_tree_model_get(store, &iter, 2 * i + 1, &contents, -1);
+
+        /* Go through each column type until ... */
+        for (type = 0; type < GNC_CSV_NUM_COL_TYPES; type++)
+        {
+            /* ... we find one that matches with what's in the column. */
+            if (!safe_strcmp(contents, _(gnc_csv_column_type_strs[type])))
+            {
+                /* Set the column_types array appropriately and quit. */
+                column_types->data[i] = type;
+
+                switch (type)
+                {
+                case GNC_CSV_DATE:
+                    weight = weight + 1000;
+                    gtk_tree_model_get(datastore, &iter2, i + 1, &prevstr, -1);
+
+                    if(parse_date(prevstr, info->parse_data->date_format) == -1)
+                         valid = FALSE;
+                    break;
+
+                case GNC_CSV_DESCRIPTION:
+                    weight = weight + 100;
+                    break;
+
+                case GNC_CSV_BALANCE:
+                case GNC_CSV_DEPOSIT:
+                case GNC_CSV_WITHDRAWAL:
+                    weight = weight + 10;
+                    break;
+
+                case GNC_CSV_NUM:
+                    weight = weight + 1;
+                    break;
+                case GNC_CSV_ACCOUNT:
+                    weight = weight + 1;
+                    gtk_tree_model_get(datastore, &iter2, i + 1, &accstr, -1);
+                    info->account_picker->account_online_id_value = strdup(accstr);
+                    break;
+                }
+                break;
+            }
+        }
+        /* Free the type string created by gtk_tree_model_get() */
+        g_free(contents);
+        g_free(prevstr);
+        g_free(accstr);
+    }
+    if(weight < 1109 || valid == FALSE)
+       return FALSE;
+    else
+       return TRUE;
+}
+
+
+/* Loads the preview's data into its data treeview. not_empty is TRUE
+ * when the data treeview already contains data, FALSE otherwise
+ * (e.g. the first time this function is called on a preview).
+ * @param info The data being previewed
+ */
+static void gnc_csv_preview_update_assist(CsvImportTrans* info)
+{
+    /* store has the data from the file being imported. cstores is an
+     * array of stores that hold the combo box entries for each
+     * column. ctstore contains both pointers to models in cstore and
+     * the actual text that appears in info->ctreeview. */
+    GtkListStore *store, **cstores, *ctstore;
+    GtkTreeIter iter;
+    GtkTreeSelection *selection;
+    /* ncols is the number of columns in the file data. */
+    int i, j, ncols = info->parse_data->column_types->len,
+              max_str_len = info->parse_data->file_str.end - info->parse_data->file_str.begin;
+
+    /* store contains only strings. */
+    GType* types = g_new(GType, 2 * ncols);
+    for (i = 0; i <  ncols + 1; i++)
+        types[i] = G_TYPE_STRING;
+    store = gtk_list_store_newv(ncols + 1, types);
+
+    /* ctstore is arranged as follows:
+     * model 0, text 0, model 1, text 1, ..., model ncols, text ncols. */
+    for (i = 0; i < 2 * ncols; i += 2)
+    {
+        types[i] = GTK_TYPE_TREE_MODEL;
+        types[i+1] = G_TYPE_STRING;
+    }
+    ctstore = gtk_list_store_newv(2 * ncols, types);
+
+    g_free(types);
+
+    /* Each element in cstores is a single column model. */
+    cstores = g_new(GtkListStore*, ncols);
+    for (i = 0; i < ncols; i++)
+    {
+        cstores[i] = gtk_list_store_new(1, G_TYPE_STRING);
+        /* Add all of the possible entries to the combo box. */
+        for (j = 0; j < GNC_CSV_NUM_COL_TYPES; j++)
+        {
+            gtk_list_store_append(cstores[i], &iter);
+            gtk_list_store_set(cstores[i], &iter, 0, _(gnc_csv_column_type_strs[j]), -1);
+        }
+    }
+
+    if (info->not_empty)
+    {
+        GList *children, *children_begin;
+        GList *tv_columns, *tv_columns_begin, *ctv_columns, *ctv_columns_begin;
+        tv_columns = tv_columns_begin = gtk_tree_view_get_columns(info->treeview);
+        ctv_columns = ctv_columns_begin = gtk_tree_view_get_columns(info->ctreeview);
+        /* Clear out exisiting columns in info->treeview. */
+        while (tv_columns != NULL)
+        {
+            gtk_tree_view_remove_column(info->treeview, GTK_TREE_VIEW_COLUMN(tv_columns->data));
+            tv_columns = g_list_next(tv_columns);
+        }
+        /* Do the same in info->ctreeview. */
+        while (ctv_columns != NULL)
+        {
+            gtk_tree_view_remove_column(info->ctreeview, GTK_TREE_VIEW_COLUMN(ctv_columns->data));
+            ctv_columns = g_list_next(ctv_columns);
+        }
+        g_list_free(tv_columns_begin);
+        g_list_free(ctv_columns_begin);
+        g_free(info->treeview_buttons);
+    }
+
+    /* Fill the data treeview with data from the file. */
+    /* Also, update the longest line value within the following loop (whichever is executed). */
+    info->longest_line = 0;
+    if (info->previewing_errors) /* If we are showing only errors ... */
+    {
+        /* ... only pick rows that are in info->error_lines. */
+        GList* error_lines = info->parse_data->error_lines;
+        while (error_lines != NULL)
+        {
+            int this_line_length = 0;
+            i = GPOINTER_TO_INT(error_lines->data);
+            gtk_list_store_append(store, &iter);
+
+            /* Row Color column */
+            gtk_list_store_set (store, &iter, 0, NULL, -1);
+
+            for (j = 0; j < ((GPtrArray*)(info->parse_data->orig_lines->pdata[i]))->len; j++)
+            {
+                /* Add this cell's length to the row's length and set the value of the list store. */
+                gchar* cell_string = (gchar*)((GPtrArray*)(info->parse_data->orig_lines->pdata[i]))->pdata[j];
+                this_line_length += g_utf8_strlen(cell_string, max_str_len);
+                gtk_list_store_set(store, &iter, j + 1, cell_string, -1);
+            }
+
+            if (this_line_length > info->longest_line)
+                info->longest_line = this_line_length;
+
+            error_lines = g_list_next(error_lines);
+        }
+    }
+    else /* Otherwise, put in all of the data. */
+    {
+        for (i = 0; i < info->parse_data->orig_lines->len; i++)
+        {
+            int this_line_length = 0;
+            gtk_list_store_append(store, &iter);
+
+            /* Row Color column */
+            gtk_list_store_set (store, &iter, 0, NULL, -1);
+
+            for (j = 0; j < ((GPtrArray*)(info->parse_data->orig_lines->pdata[i]))->len; j++)
+            {
+                /* Add this cell's length to the row's length and set the value of the list store. */
+                gchar* cell_string = (gchar*)((GPtrArray*)(info->parse_data->orig_lines->pdata[i]))->pdata[j];
+                this_line_length += g_utf8_strlen(cell_string, max_str_len);
+                gtk_list_store_set(store, &iter, j + 1, cell_string, -1);
+            }
+
+            if (this_line_length > info->longest_line)
+                info->longest_line = this_line_length;
+
+            /* Set the number of rows in the store */
+            info->num_of_rows = i + 1;
+        }
+    }
+
+    /* Set all the column types to what's in the parse data. */
+    gtk_list_store_append(ctstore, &iter);
+    gtk_list_store_set(ctstore, &iter, 0, NULL, -1); /* Dummy Column to match row color */
+    for (i = 0; i < ncols; i++)
+    {
+        gtk_list_store_set(ctstore, &iter, 2 * i, cstores[i], 2 * i + 1,
+                           _(gnc_csv_column_type_strs[(int)(info->parse_data->column_types->data[i])]),
+                           -1);
+    }
+
+    info->treeview_buttons = g_new(GtkWidget*, ncols);
+    /* Insert columns into the data and column type treeviews. */
+    for (i = 0; i < ncols ; i++)
+    {
+        GtkTreeViewColumn* col; /* The column we add to info->treeview. */
+        /* Create renderers for the data treeview (renderer) and the
+         * column type treeview (crenderer). */
+        GtkCellRenderer* renderer = gtk_cell_renderer_text_new(),
+                         *crenderer = gtk_cell_renderer_combo_new();
+        /* We want a monospace font for the data in case of fixed-width data. */
+        g_object_set(G_OBJECT(renderer), "family", "monospace", NULL);
+        /* We are using cstores for the combo box entries, and we don't
+         * want the user to be able to manually enter their own column
+         * types. */
+        g_object_set(G_OBJECT(crenderer), "model", cstores[i], "text-column", 0,
+                     "editable", TRUE, "has-entry", FALSE, NULL);
+        g_signal_connect(G_OBJECT(crenderer), "changed",
+                         G_CALLBACK(column_type_changed), (gpointer)info);
+
+        /* Add a single column for the treeview. */
+        col = gtk_tree_view_column_new_with_attributes("", renderer, "text", i + 1, NULL);
+
+        /* Add the Color column 0 to the renderer */
+        gtk_tree_view_column_add_attribute(col, renderer, "background", 0);
+
+        gtk_tree_view_insert_column(info->treeview, col, -1);
+        /* Enable resizing of the columns. */
+        gtk_tree_view_column_set_resizable(col, TRUE);
+        /* Use the alternating model and text entries from ctstore in
+         * info->ctreeview. */
+        gtk_tree_view_insert_column_with_attributes(info->ctreeview,
+                -1, "", crenderer, "model", 2 * i,
+                "text", 2 * i + 1, NULL);
+
+        /* We need to allow clicking on the column headers for fixed-width
+         * column splitting and merging. */
+        g_object_set(G_OBJECT(col), "clickable", TRUE, NULL);
+        g_signal_connect(G_OBJECT(col->button), "button_press_event",
+                         G_CALLBACK(header_button_press_handler), (gpointer)info);
+        info->treeview_buttons[i] = col->button;
+    }
+
+    /* Set the treeviews to use the models. */
+    gtk_tree_view_set_model(info->treeview, GTK_TREE_MODEL(store));
+    gtk_tree_view_set_model(info->ctreeview, GTK_TREE_MODEL(ctstore));
+
+    /* Select the header row */
+    gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ctstore), &iter);
+    selection = gtk_tree_view_get_selection (info->ctreeview);
+    gtk_tree_selection_select_iter ( selection, &iter);
+
+    /* Free the memory for the stores. */
+    g_object_unref(GTK_TREE_MODEL(store));
+    g_object_unref(GTK_TREE_MODEL(ctstore));
+    for (i = 0; i < ncols; i++)
+        g_object_unref(GTK_TREE_MODEL(cstores[i]));
+
+    /* Make the things actually appear. */
+    gtk_widget_show_all(GTK_WIDGET(info->treeview));
+    gtk_widget_show_all(GTK_WIDGET(info->ctreeview));
+
+    /* Set the encoding selector to the right encoding. */
+    info->code_encoding_calls = 2;
+    go_charmap_sel_set_encoding(info->encselector, info->parse_data->encoding);
+
+    /* Set the date format to what's in the combo box (since we don't
+     * necessarily know if this will always be the same). */
+    info->parse_data->date_format = gtk_combo_box_get_active(info->date_format_combo);
+
+    /* It's now been filled with some stuff. */
+    info->not_empty = TRUE;
+}
+
+
+/*******************************************************
+ * load_settings
+ *
+ * load the default settings for the assistant
+ *******************************************************/
+static
+void load_settings (CsvImportTrans *info)
+{
+    info->start_row = 0;
+    info->start_row = 0;
+    info->account_page_step = TRUE;
+    info->match_parse_run = FALSE;
+    info->file_name = NULL;
+    info->starting_dir = NULL;
+
+    /* The default directory for the user to select files. */
+    info->starting_dir = gnc_get_default_directory(GCONF_SECTION);
+}
+
+/*======================================================================*/
+/*======================================================================*/
+
+/*******************************************************
+ * Assistant page prepare functions
+ *******************************************************/
+void
+csv_import_trans_assistant_start_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+    /* Enable the Assistant Buttons */
+    gtk_assistant_set_page_complete (assistant, page, TRUE);
+}
+
+
+void
+csv_import_trans_assistant_file_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+    info->account_picker->auto_create = TRUE; /* Step over account page if we find matching online id */
+    info->previewing_errors = FALSE;          /* We're looking at all the data. */
+    info->approved = FALSE;                   /* This is FALSE until the user clicks "OK". */
+
+    /* Set the default directory */
+    if (info->starting_dir)
+        gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(info->file_chooser), info->starting_dir);
+
+    /* Disable the Forward Assistant Button */
+    gtk_assistant_set_page_complete (assistant, page, FALSE);
+}
+
+
+void
+csv_import_trans_assistant_preview_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+    GtkAdjustment *adj;
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+    g_signal_connect(G_OBJECT(info->treeview), "size-allocate",
+                     G_CALLBACK(treeview_resized), (gpointer)info);
+
+    if(info->previewing_errors == TRUE)
+    {
+        gchar* name;
+        GtkIconSize size;
+        GtkTreeViewColumn* last_col;
+
+        /* Block going back */
+        gtk_assistant_commit (GTK_ASSISTANT(info->window));
+
+        gtk_image_get_stock(info->instructions_image, &name, &size);
+        gtk_image_set_from_stock(info->instructions_image, GTK_STOCK_DIALOG_ERROR, size);
+        gtk_label_set_text(info->instructions_label,
+                       _("The rows displayed below had errors which are in the last column. You can attempt to correct them by changing the configuration."));
+        gtk_widget_show(GTK_WIDGET(info->instructions_image));
+        gtk_widget_show(GTK_WIDGET(info->instructions_label));
+
+        /* Set spin buttons not sensative */
+        gtk_widget_set_sensitive (info->start_row_spin, FALSE);
+        gtk_widget_set_sensitive (info->end_row_spin, FALSE);
+
+        /* Set check button label */
+        gtk_label_set_text(GTK_LABEL(info->check_label), _("Skip Errors"));
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->check_butt), FALSE);
+    }
+
+    /* Load the data into the treeview. */
+    gnc_csv_preview_update_assist(info);
+
+    /* Set the upper limit of spin button to number of rows */
+    adj = gtk_spin_button_get_adjustment(GTK_SPIN_BUTTON(info->end_row_spin));
+    if(gtk_adjustment_get_upper(adj) != info->num_of_rows)
+    {
+        gtk_spin_button_set_value (GTK_SPIN_BUTTON(info->end_row_spin), info->num_of_rows);
+        gtk_adjustment_set_upper(adj, info->num_of_rows);
+    }
+
+    /* Update the row selection highlight */
+    row_selection_update(info);
+}
+
+
+void
+csv_import_trans_assistant_account_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+    gchar *text, *mtext;
+    Account * account = NULL;
+
+    if(!preview_settings_valid(info) && (info->approved == FALSE))
+    {
+	text = g_strdup_printf(gettext ("There are problems with the import settings!\nThe date format could be wrong "
+                                  "or there are not enough columns set..."));
+        mtext = g_strdup_printf("<span size=\"medium\" color=\"red\"><b>%s</b></span>",text);
+        gtk_label_set_markup(GTK_LABEL(info->account_label), mtext);
+        g_free(mtext);
+        g_free(text);
+
+        gtk_widget_set_sensitive (info->account_page, FALSE);
+    }
+    else
+    {
+        text = g_strdup_printf(gettext ("To Change the account, double click on the required account, click Forward to procede."));
+        mtext = g_strdup_printf("<span size=\"medium\" color=\"red\"><b>%s</b></span>", text);
+        gtk_label_set_markup(GTK_LABEL(info->account_label), mtext );
+        g_free(mtext);
+        g_free(text);
+
+        gtk_widget_set_sensitive (info->account_page, TRUE); 
+
+        /* Let the user select an account to put the transactions in. */
+        account = gnc_import_account_assist_update (info->account_picker);
+
+        /* If we have a valid account and auto_create is TRUE, move on to matcher */
+        if(!(account == NULL) && (info->account_picker->auto_create == TRUE))
+            gtk_assistant_set_current_page (assistant, num + 1);
+    }
+
+    /* Enable the Forward Assistant Button */
+    if(account == NULL)
+        gtk_assistant_set_page_complete (assistant, page, FALSE);
+    else
+        gtk_assistant_set_page_complete (assistant, page, TRUE);
+}
+
+
+void
+csv_import_trans_assistant_doc_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+
+    /* Block going back */
+    gtk_assistant_commit (GTK_ASSISTANT(info->window));
+
+    if( info->match_parse_run == FALSE)
+    {
+        /* Add the Cancel button for the matcher */
+        info->cancel_button = gtk_button_new_with_mnemonic (_("_Cancel"));
+        gtk_assistant_add_action_widget (assistant, info->cancel_button);
+        g_signal_connect(info->cancel_button, "clicked",
+                       G_CALLBACK(csv_import_trans_assistant_cancel), info);
+        gtk_widget_show(GTK_WIDGET(info->cancel_button));
+    }
+}
+
+
+void
+csv_import_trans_assistant_match_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+    gint num = gtk_assistant_get_current_page (assistant);
+    GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+    gchar *text, *mtext;
+
+    /* Block going back */
+    gtk_assistant_commit (GTK_ASSISTANT(info->window));
+
+    /* Create transactions from the parsed data, first time with FALSE
+       Subsequent times with TRUE */
+    if( info->match_parse_run == FALSE)
+    {
+        gnc_csv_parse_to_trans(info->parse_data, info->account_picker->retAccount, FALSE);
+    }
+    else
+        gnc_csv_parse_to_trans(info->parse_data, info->account_picker->retAccount, TRUE);
+    info->match_parse_run = TRUE;
+
+    /* if there are errors, we jump back to preview to correct */
+    if(!(info->parse_data->error_lines == NULL) && (info->approved == FALSE) )
+    {
+        info->previewing_errors = TRUE; /* We're looking at errors. */
+        gtk_assistant_set_current_page (assistant, 2);
+    }
+
+    if((info->parse_data->error_lines == NULL) || (info->approved == TRUE) )
+    {
+        GList* transactions; /* A list of the transactions we create */
+
+        text =  _("Double click on rows to change, then click on Apply to Import");
+        mtext = g_strdup_printf("<span size=\"medium\" color=\"red\"><b>%s</b></span>", text);
+        gtk_label_set_markup(GTK_LABEL(info->match_label), mtext);
+        g_free(mtext);
+
+        if(info->gnc_csv_importer_gui == NULL)
+        {
+            /* Create the genereic transaction importer GUI. */
+            info->gnc_csv_importer_gui = gnc_gen_trans_assist_new (info->match_page, NULL, FALSE, 42);
+
+             /* Add the help button for the matcher */
+             info->help_button = gtk_button_new_with_mnemonic (_("_Help"));
+             gtk_assistant_add_action_widget (assistant, info->help_button);
+             g_signal_connect(info->help_button, "clicked",
+                         G_CALLBACK(on_matcher_help_clicked), info->gnc_csv_importer_gui);
+             gtk_widget_show(GTK_WIDGET(info->help_button));
+
+            /* Get the list of the transactions that were created. */
+            transactions = info->parse_data->transactions;
+            /* Copy all of the transactions to the importer GUI. */
+            while (transactions != NULL)
+            {
+                GncCsvTransLine* trans_line = transactions->data;
+                gnc_gen_trans_list_add_trans(info->gnc_csv_importer_gui, trans_line->trans);
+                transactions = g_list_next(transactions);
+            }
+            g_list_free(transactions);
+        }
+    }
+    /* Enable the Forward Assistant Button */
+    gtk_assistant_set_page_complete (assistant, page, TRUE);
+}
+
+
+void
+csv_import_trans_assistant_summary_page_prepare (GtkAssistant *assistant,
+                                   gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+    gchar *text, *mtext;
+
+    /* Save the Window size and directory */
+    gnc_set_default_directory(GCONF_SECTION, info->starting_dir);
+    gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(info->window));
+
+    /* Remove the added button */
+    gtk_assistant_remove_action_widget (assistant, info->help_button);
+    gtk_assistant_remove_action_widget (assistant, info->cancel_button);
+
+    text = g_strdup_printf(gettext ("The transactions were imported from the file '%s'."), info->file_name);
+    mtext = g_strdup_printf("<span size=\"medium\"><b>%s</b></span>", text);
+    gtk_label_set_markup(GTK_LABEL(info->summary_label), mtext);
+    g_free(text);
+    g_free(mtext);
+}
+
+
+void
+csv_import_trans_assistant_prepare (GtkAssistant *assistant, GtkWidget *page,
+                      gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+    gint currentpage = gtk_assistant_get_current_page(assistant);
+
+    switch (currentpage)
+    {
+    case 0:
+        /* Current page is Import Start page */
+        csv_import_trans_assistant_start_page_prepare (assistant, user_data);
+        break;
+    case 1:
+        /* Current page is File select page */
+        csv_import_trans_assistant_file_page_prepare (assistant, user_data);
+        break;
+    case 2:
+        /* Current page is Preview page */
+        csv_import_trans_assistant_preview_page_prepare (assistant, user_data);
+        break;
+    case 3:
+        /* Current page is Account page */
+        csv_import_trans_assistant_account_page_prepare (assistant, user_data);
+        break;
+    case 4:
+        /* Current page is Transaction Doc page */
+        csv_import_trans_assistant_doc_page_prepare (assistant, user_data);
+        break;
+    case 5:
+        /* Current page is Match page */
+        csv_import_trans_assistant_match_page_prepare (assistant, user_data);
+        break;
+    case 6:
+        /* Current page is Summary page */
+        csv_import_trans_assistant_summary_page_prepare (assistant, user_data);
+        break;
+    }
+}
+
+
+/*******************************************************
+ * Assistant call back functions
+ *******************************************************/
+static void
+csv_import_trans_assistant_destroy_cb (GtkObject *object, gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+    gnc_unregister_gui_component_by_data (ASSISTANT_CSV_IMPORT_TRANS_CM_CLASS, info);
+    g_free (info);
+}
+
+void
+csv_import_trans_assistant_cancel (GtkAssistant *assistant, gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+    gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_TRANS_CM_CLASS, info);
+}
+
+void
+csv_import_trans_assistant_close (GtkAssistant *assistant, gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+    gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_TRANS_CM_CLASS, info);
+}
+
+void
+csv_import_trans_assistant_finish (GtkAssistant *assistant, gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+
+    /* Start the import */
+    if (info->parse_data->transactions != NULL)
+        gnc_gen_trans_assist_start(info->gnc_csv_importer_gui);
+    else
+        gnc_gen_trans_list_delete(info->gnc_csv_importer_gui);
+}
+
+static void
+csv_import_trans_close_handler (gpointer user_data)
+{
+    CsvImportTrans *info = user_data;
+
+    g_free(info->file_name);
+    g_free(info->starting_dir);
+
+    /* Free the memory we allocated. */
+    if(!(info->parse_data == NULL))
+        gnc_csv_parse_data_free(info->parse_data);
+
+    if(!(info->account_picker == NULL))
+        info->account_picker = NULL;
+
+    if(!(info->gnc_csv_importer_gui == NULL))
+        info->gnc_csv_importer_gui = NULL;
+
+    gtk_widget_destroy (info->window);
+}
+
+/*******************************************************
+ * Create the Assistant
+ *******************************************************/
+static GtkWidget *
+csv_import_trans_assistant_create (CsvImportTrans *info)
+{
+    GtkBuilder *builder;
+    GtkWidget *window;
+    GtkWidget *box;
+    GtkWidget *button, *csv_button;
+    GtkTreeIter iter;
+    GtkCellRenderer *renderer;
+    GtkTreeViewColumn *column;
+
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file  (builder , "assistant-csv-trans-import.glade", "start_row_adj");
+    gnc_builder_add_from_file  (builder , "assistant-csv-trans-import.glade", "end_row_adj");
+    gnc_builder_add_from_file  (builder , "assistant-csv-trans-import.glade", "CSV Transaction Assistant");
+    window = GTK_WIDGET(gtk_builder_get_object (builder, "CSV Transaction Assistant"));
+    info->window = window;
+
+    /* Set the assistant colors */
+    gnc_assistant_set_colors (GTK_ASSISTANT (info->window));
+
+    /* Load default settings */
+    load_settings (info);
+
+    /* Enable buttons on all page. */
+    gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
+                                     GTK_WIDGET(gtk_builder_get_object(builder, "start_page")),
+                                     TRUE);
+    gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
+                                     GTK_WIDGET(gtk_builder_get_object(builder, "file_page")),
+                                     FALSE);
+    gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
+                                     GTK_WIDGET(gtk_builder_get_object(builder, "preview_page")),
+                                     TRUE);
+    gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
+                                     GTK_WIDGET(gtk_builder_get_object(builder, "account_page")),
+                                     FALSE);
+    gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
+                                     GTK_WIDGET(gtk_builder_get_object(builder, "doc_page")),
+                                     TRUE);
+    gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
+                                     GTK_WIDGET(gtk_builder_get_object(builder, "match_page")),
+                                     FALSE);
+    gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
+                                     GTK_WIDGET(gtk_builder_get_object(builder, "summary_page")),
+                                     TRUE);
+
+    /* Start Page */
+
+    /* File chooser Page */
+    info->file_chooser = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_OPEN);
+    button = gtk_button_new_from_stock(GTK_STOCK_OK);
+    gtk_widget_show (button);
+    gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(info->file_chooser), button);
+    g_signal_connect (G_OBJECT (button), "clicked",
+                  G_CALLBACK (csv_import_trans_file_chooser_confirm_cb), info);
+
+    box = GTK_WIDGET(gtk_builder_get_object(builder, "file_page"));
+    gtk_box_pack_start (GTK_BOX (box), info->file_chooser, TRUE, TRUE, 6);
+    gtk_widget_show (info->file_chooser);
+
+    /* Preview Settings Page */
+    {
+    char* sep_button_names[] = {"space_cbutton",
+                                "tab_cbutton",
+                                "comma_cbutton",
+                                "colon_cbutton",
+                                "semicolon_cbutton",
+                                "hyphen_cbutton"
+                               };
+    GtkContainer *date_format_container, *currency_format_container;
+    int i;
+
+    /* The table containing info->encselector and the separator configuration widgets */
+    GtkTable* enctable;
+    PangoContext* context; /* Used to set a monotype font on info->treeview */
+
+    info->start_row_spin = GTK_WIDGET(gtk_builder_get_object (builder, "start_row"));
+    info->end_row_spin = GTK_WIDGET(gtk_builder_get_object (builder, "end_row"));
+    info->check_label = GTK_WIDGET(gtk_builder_get_object (builder, "check_label"));
+    info->check_butt = GTK_WIDGET(gtk_builder_get_object (builder, "check_butt"));
+
+    info->encselector = GO_CHARMAP_SEL(go_charmap_sel_new(GO_CHARMAP_SEL_TO_UTF8));
+    /* Connect the selector to the encoding_selected event handler. */
+    g_signal_connect(G_OBJECT(info->encselector), "charmap_changed",
+                     G_CALLBACK(encoding_selected), (gpointer)info);
+
+    /* Load the separator buttons from the glade builder file into the
+     * info->sep_buttons array. */
+    for (i = 0; i < SEP_NUM_OF_TYPES; i++)
+    {
+        info->sep_buttons[i]
+        = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, sep_button_names[i]));
+        /* Connect them to the sep_button_clicked event handler. */
+        g_signal_connect(G_OBJECT(info->sep_buttons[i]), "toggled",
+                         G_CALLBACK(sep_button_clicked), (gpointer)info);
+    }
+
+    /* Load and connect the custom separator checkbutton in the same way
+     * as the other separator buttons. */
+    info->custom_cbutton
+    = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_cbutton"));
+    g_signal_connect(G_OBJECT(info->custom_cbutton), "clicked",
+                     G_CALLBACK(sep_button_clicked), (gpointer)info);
+
+    /* Load the entry for the custom separator entry. Connect it to the
+     * sep_button_clicked event handler as well. */
+    info->custom_entry = (GtkEntry*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_entry"));
+    g_signal_connect(G_OBJECT(info->custom_entry), "changed",
+                     G_CALLBACK(sep_button_clicked), (gpointer)info);
+
+    /* Get the table from the Glade builder file. */
+    enctable = GTK_TABLE(gtk_builder_get_object (builder, "enctable"));
+    /* Put the selector in at the top. */
+    gtk_table_attach_defaults(enctable, GTK_WIDGET(info->encselector), 1, 2, 0, 1);
+    /* Show the table in all its glory. */
+    gtk_widget_show_all(GTK_WIDGET(enctable));
+
+    /* The instructions label and image */
+    info->instructions_label = GTK_LABEL(gtk_builder_get_object (builder, "instructions_label"));
+    info->instructions_image = GTK_IMAGE(gtk_builder_get_object (builder, "instructions_image"));
+
+    /* Add in the date format combo box and hook it up to an event handler. */
+    info->date_format_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
+    for (i = 0; i < num_date_formats; i++)
+    {
+        gtk_combo_box_append_text(info->date_format_combo, _(date_format_user[i]));
+    }
+    gtk_combo_box_set_active(info->date_format_combo, 0);
+    g_signal_connect(G_OBJECT(info->date_format_combo), "changed",
+                     G_CALLBACK(date_format_selected), (gpointer)info);
+
+    /* Add it to the assistant. */
+    date_format_container = GTK_CONTAINER(gtk_builder_get_object (builder, "date_format_container"));
+    gtk_container_add(date_format_container, GTK_WIDGET(info->date_format_combo));
+    gtk_widget_show_all(GTK_WIDGET(date_format_container));
+
+    /* Add in the currency format combo box and hook it up to an event handler. */
+    info->currency_format_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
+    for (i = 0; i < num_currency_formats; i++)
+    {
+        gtk_combo_box_append_text(info->currency_format_combo, _(currency_format_user[i]));
+    }
+    /* Default will the locale */
+    gtk_combo_box_set_active(info->currency_format_combo, 0);
+    g_signal_connect(G_OBJECT(info->currency_format_combo), "changed",
+                     G_CALLBACK(currency_format_selected), (gpointer)info);
+
+    /* Add it to the assistant. */
+    currency_format_container = GTK_CONTAINER(gtk_builder_get_object (builder, "currency_format_container"));
+    gtk_container_add(currency_format_container, GTK_WIDGET(info->currency_format_combo));
+    gtk_widget_show_all(GTK_WIDGET(currency_format_container));
+
+    /* Connect the CSV/Fixed-Width radio button event handler. */
+    csv_button = GTK_WIDGET(gtk_builder_get_object (builder, "csv_button"));
+    g_signal_connect(csv_button, "toggled",
+                     G_CALLBACK(separated_or_fixed_selected), (gpointer)info);
+
+    /* Load the data treeview and connect it to its resizing event handler. */
+    info->treeview = (GtkTreeView*)GTK_WIDGET(gtk_builder_get_object (builder, "treeview"));
+    context = gtk_widget_create_pango_context(GTK_WIDGET(info->treeview));
+
+    /* Load the column type treeview. */
+    info->ctreeview = (GtkTreeView*)GTK_WIDGET(gtk_builder_get_object (builder, "ctreeview"));
+
+    /* This is TRUE only after encoding_selected is called, so we must
+     * set it initially to FALSE. */
+    info->encoding_selected_called = FALSE;
+
+    /* It is empty at first. */
+    info->not_empty = FALSE;
+    }
+
+    /* Account page */
+    /* Initialise the Account Picker and add to the Assistant */
+    info->account_page  = GTK_WIDGET(gtk_builder_get_object (builder, "account_page"));
+    info->account_picker = gnc_import_account_assist_setup(info->account_page);
+    info->account_label = GTK_WIDGET(gtk_builder_get_object (builder, "account_label"));
+
+    /* Matcher page */
+    info->match_page  = GTK_WIDGET(gtk_builder_get_object (builder, "match_page"));
+    info->match_label = GTK_WIDGET(gtk_builder_get_object (builder, "match_label"));
+
+    /* Summary Page */
+    info->summary_label = GTK_WIDGET(gtk_builder_get_object(builder, "summary_label"));
+
+    g_signal_connect (G_OBJECT(window), "destroy",
+                      G_CALLBACK (csv_import_trans_assistant_destroy_cb), info);
+
+    gnc_restore_window_size (GCONF_SECTION, GTK_WINDOW(info->window));
+
+    gtk_builder_connect_signals(builder, info);
+    g_object_unref(G_OBJECT(builder));
+    return window;
+}
+
+
+/********************************************************************\
+ * gnc_file_csv_trans_import                                        *
+ * opens up a assistant to import accounts.                         *
+ *                                                                  *
+ * Args:   import_type                                              *
+ * Return: nothing                                                  *
+\********************************************************************/
+void
+gnc_file_csv_trans_import(void)
+{
+    CsvImportTrans *info;
+    gint component_id;
+
+    info = g_new0 (CsvImportTrans, 1);
+
+    csv_import_trans_assistant_create (info);
+
+    component_id = gnc_register_gui_component (ASSISTANT_CSV_IMPORT_TRANS_CM_CLASS,
+                   NULL, csv_import_trans_close_handler,
+                   info);
+
+    gtk_widget_show_all (info->window);
+
+    gnc_window_adjust_for_screen (GTK_WINDOW(info->window));
+}


Property changes on: gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Added: gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.glade
===================================================================
--- gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.glade	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.glade	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,863 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkAssistant" id="CSV Transaction Assistant">
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="title" translatable="yes">CSV Transaction Import</property>
+    <property name="default_width">400</property>
+    <property name="default_height">500</property>
+    <signal name="close" handler="csv_import_trans_assistant_close" swapped="no"/>
+    <signal name="apply" handler="csv_import_trans_assistant_finish" swapped="no"/>
+    <signal name="prepare" handler="csv_import_trans_assistant_prepare" swapped="no"/>
+    <signal name="cancel" handler="csv_import_trans_assistant_cancel" swapped="no"/>
+    <child>
+      <object class="GtkLabel" id="start_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">This assistant will help you import a deliminated file containing a list of transactions.
+
+All transactions imported will be associated to one account for each import and if you select the account column, the account in the first row will be used for all rows.
+
+Various options exist for specifing the deliminator as well as a fixed width option. With the fixed width option, double click on the bar above the displayed rows to set the column width.
+
+There is an option for specifying the start and end row which can be used if you have some header text or multiple accounts in the same file.</property>
+        <property name="wrap">True</property>
+      </object>
+      <packing>
+        <property name="page_type">intro</property>
+        <property name="title" translatable="yes">Transaction Import Assistant</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="file_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <child>
+          <object class="GtkLabel" id="label7">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">
+Enter file name and location for the Import...
+</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Select File for Import</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="preview_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="border_width">12</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="spacing">12</property>
+            <child>
+              <object class="GtkVBox" id="vbox1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <child>
+                  <object class="GtkHBox" id="hbox6">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkLabel" id="label9">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Start import on row </property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSpinButton" id="start_row">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="editable">False</property>
+                        <property name="invisible_char">&#x25CF;</property>
+                        <property name="invisible_char_set">True</property>
+                        <property name="primary_icon_activatable">False</property>
+                        <property name="secondary_icon_activatable">False</property>
+                        <property name="primary_icon_sensitive">True</property>
+                        <property name="secondary_icon_sensitive">True</property>
+                        <property name="adjustment">start_row_adj</property>
+                        <signal name="value-changed" handler="csv_import_trans_srow_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label10">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes"> and stop on row </property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkSpinButton" id="end_row">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="editable">False</property>
+                        <property name="invisible_char">&#x25CF;</property>
+                        <property name="invisible_char_set">True</property>
+                        <property name="primary_icon_activatable">False</property>
+                        <property name="secondary_icon_activatable">False</property>
+                        <property name="primary_icon_sensitive">True</property>
+                        <property name="secondary_icon_sensitive">True</property>
+                        <property name="adjustment">end_row_adj</property>
+                        <signal name="value-changed" handler="csv_import_trans_erow_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHSeparator" id="hseparator7">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="padding">8</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHBox" id="hbox4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <child>
+                      <object class="GtkLabel" id="label1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">Data type: </property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="csv_button">
+                        <property name="label" translatable="yes">Separated</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="active">True</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton2">
+                        <property name="label" translatable="yes">Fixed-Width</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">csv_button</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHSeparator" id="hseparator6">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="padding">10</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHBox" id="hbox7">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkFrame" id="frame2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="GtkAlignment" id="date_format_container">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label4">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="label" translatable="yes">Date Format</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkFrame" id="frame3">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="GtkAlignment" id="currency_format_container">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="left_padding">12</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label2">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="label" translatable="yes">Currency format</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHSeparator" id="hseparator3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="padding">10</property>
+                    <property name="position">5</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVBox" id="vbox3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkHBox" id="hbox2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkTable" id="enctable">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <child>
+                          <object class="GtkLabel" id="label3">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="label" translatable="yes">Encoding: </property>
+                          </object>
+                          <packing>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHSeparator" id="hseparator1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="padding">5</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkFrame" id="frame1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkAlignment" id="alignment1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <object class="GtkTable" id="table1">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="n_rows">3</property>
+                            <property name="n_columns">3</property>
+                            <property name="column_spacing">3</property>
+                            <property name="row_spacing">3</property>
+                            <property name="homogeneous">True</property>
+                            <child>
+                              <object class="GtkCheckButton" id="space_cbutton">
+                                <property name="label" translatable="yes">Space</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="x_options">GTK_FILL</property>
+                                <property name="y_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="tab_cbutton">
+                                <property name="label" translatable="yes">Tab</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="x_options">GTK_FILL</property>
+                                <property name="y_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="comma_cbutton">
+                                <property name="label" translatable="yes">Comma (,)</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">2</property>
+                                <property name="right_attach">3</property>
+                                <property name="x_options">GTK_FILL</property>
+                                <property name="y_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="colon_cbutton">
+                                <property name="label" translatable="yes">Colon (:)</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                                <property name="x_options">GTK_FILL</property>
+                                <property name="y_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="semicolon_cbutton">
+                                <property name="label" translatable="yes">Semicolon (;)</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                                <property name="x_options">GTK_FILL</property>
+                                <property name="y_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="hyphen_cbutton">
+                                <property name="label" translatable="yes">Hyphen (-)</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">2</property>
+                                <property name="right_attach">3</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                                <property name="x_options">GTK_FILL</property>
+                                <property name="y_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="custom_cbutton">
+                                <property name="label" translatable="yes">Custom</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="use_action_appearance">False</property>
+                                <property name="draw_indicator">True</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
+                                <property name="x_options">GTK_FILL</property>
+                                <property name="y_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkEntry" id="custom_entry">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="invisible_char">&#x25CF;</property>
+                                <property name="invisible_char_set">True</property>
+                                <property name="primary_icon_activatable">False</property>
+                                <property name="secondary_icon_activatable">False</property>
+                                <property name="primary_icon_sensitive">True</property>
+                                <property name="secondary_icon_sensitive">True</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">3</property>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
+                                <property name="x_options">GTK_FILL</property>
+                                <property name="y_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child type="label">
+                      <object class="GtkLabel" id="label5">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="label" translatable="yes">Separators</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHSeparator" id="hseparator2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="padding">6</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox3">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <child>
+              <object class="GtkImage" id="instructions_image">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="stock">gtk-dialog-info</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="padding">2</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="instructions_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Select the type of each column below.</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow1">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">automatic</property>
+            <property name="vscrollbar_policy">automatic</property>
+            <child>
+              <object class="GtkViewport" id="viewport1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkVBox" id="vbox2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkTreeView" id="ctreeview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="headers_visible">False</property>
+                        <property name="enable_grid_lines">both</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkTreeView" id="treeview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="enable_grid_lines">both</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox5">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkCheckButton" id="check_butt">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_action_appearance">False</property>
+                <property name="xalign">1</property>
+                <property name="image_position">right</property>
+                <property name="active">True</property>
+                <property name="draw_indicator">True</property>
+                <signal name="toggled" handler="csv_import_trans_auto_cb" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="pack_type">end</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="check_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xpad">5</property>
+                <property name="label" translatable="yes">Step over Account Page if Setup</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="pack_type">end</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Preview Settings</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="account_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <object class="GtkLabel" id="account_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Error text.</property>
+            <property name="justify">center</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Account Selection</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="doc_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <object class="GtkLabel" id="label8">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">On the following page you will be able to associate each transaction to a category.
+
+If this is the first time importing, you will find that all lines may need to be associated. On subsequent imports, the importer will try to associate the transactions based on previous imports.
+
+The confidence of a correct association is displayed as a colored bar.
+
+More infomation can be displayed by using the help button.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">progress</property>
+        <property name="title" translatable="yes">Transaction Information</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="match_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <child>
+          <object class="GtkLabel" id="match_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">label</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">confirm</property>
+        <property name="title" translatable="yes">Match Transactions</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="summary_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <child>
+          <object class="GtkLabel" id="summary_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">label</property>
+            <property name="use_markup">True</property>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">summary</property>
+        <property name="title" translatable="yes">Import Summary</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+  </object>
+  <object class="GtkAdjustment" id="end_row_adj">
+    <property name="lower">1</property>
+    <property name="upper">100</property>
+    <property name="value">100</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="start_row_adj">
+    <property name="lower">1</property>
+    <property name="upper">100</property>
+    <property name="value">1</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+</interface>

Copied: gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.h (from rev 22085, gnucash/trunk/src/import-export/csv/gnc-csv-import.h)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.h	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/assistant-csv-trans-import.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,36 @@
+/*******************************************************************\
+ * assistant-csv-trans-import.h -- An assistant for importing       *
+ *                                     Transactions from a file.    *
+ *                                                                  *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+/** @file assistant-csv-trans-import.h
+    @brief CSV Import Assistant
+    @author Copyright (c) 2011 Robert Fewell
+*/
+#ifndef GNC_ASSISTANT_CSV_IMPORT_TRANS_H
+#define GNC_ASSISTANT_CSV_IMPORT_TRANS_H
+
+
+/** The gnc_file_csv_trans_import() will let the user import thte 
+ *  account tree or transactions to a deliminated file.
+ */
+void gnc_file_csv_trans_import (void);
+#endif

Added: gnucash/trunk/src/import-export/csv-import/csv-account-import.c
===================================================================
--- gnucash/trunk/src/import-export/csv-import/csv-account-import.c	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/csv-account-import.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,349 @@
+/*******************************************************************\
+ * csv-account-import.c -- Account importing from file              *
+ *                                                                  *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ *                                                                  *
+ * Based on code from bi_import written by Sebastian Held  and      *
+ * Mike Evans.                                                      *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+
+#include "gnc-ui-util.h"
+#include <regex.h>
+#include "gnc-exp-parser.h"
+#include "Account.h"
+#include "gnc-component-manager.h"
+#include "csv-account-import.h"
+
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = GNC_MOD_ASSISTANT;
+
+/* This helper macro takes a regexp match and fills the model */
+#define FILL_IN_HELPER(match_name,column) \
+            temp = g_match_info_fetch_named (match_info, match_name); \
+            if (temp) \
+            { \
+		g_strstrip( temp ); \
+                gtk_list_store_set (store, &iter, column, temp, -1); \
+                g_free (temp); \
+            }
+
+
+/*******************************************************
+ * csv_import_read_file
+ *
+ * Parse the file for a correctly formatted file
+ *******************************************************/
+csv_import_result
+csv_import_read_file (const gchar *filename, const gchar *parser_regexp,
+                         GtkListStore *store, guint max_rows )
+{
+    FILE       *f;
+    char       *line;
+    gchar      *line_utf8, *temp;
+    GMatchInfo *match_info;
+    GError     *err;
+    GRegex     *regexpat;
+    int         row = 0;
+    gboolean match_found = FALSE;
+
+    // model
+    GtkTreeIter iter;
+
+    f = g_fopen (filename, "rt");
+    if (!f)
+    {
+        //gnc_error_dialog( 0, _("File %s cannot be opened."), filename );
+        return RESULT_OPEN_FAILED;
+    }
+
+    // compile the regular expression and check for errors
+    err = NULL;
+    regexpat =
+        g_regex_new (parser_regexp, G_REGEX_EXTENDED | G_REGEX_OPTIMIZE | G_REGEX_DUPNAMES, 0, &err);
+    if (err != NULL)
+    {
+        GtkWidget *dialog;
+        gchar *errmsg;
+
+        errmsg = g_strdup_printf (_("Error in regular expression '%s':\n%s"),
+                                  parser_regexp, err->message);
+        g_error_free (err);
+        err = NULL;
+
+        dialog = gtk_message_dialog_new (NULL,
+                                         GTK_DIALOG_MODAL,
+                                         GTK_MESSAGE_ERROR,
+                                         GTK_BUTTONS_OK, "%s", errmsg);
+        gtk_dialog_run (GTK_DIALOG (dialog));
+        gtk_widget_destroy (dialog);
+        g_free (errmsg);
+        errmsg = 0;
+
+        fclose (f);
+        return RESULT_ERROR_IN_REGEXP;
+    }
+
+    // start the import
+#define buffer_size 1000
+    line = g_malloc0 (buffer_size);
+    while (!feof (f))
+    {
+        int l;
+        row++;
+	if(row == max_rows)
+	    break;
+        // read one line
+        if (!fgets (line, buffer_size, f))
+            break;			// eof
+        // now strip the '\n' from the end of the line
+        l = strlen (line);
+        if ((l > 0) && (line[l - 1] == '\n'))
+            line[l - 1] = 0;
+
+        // convert line from locale into utf8
+        line_utf8 = g_locale_to_utf8 (line, -1, NULL, NULL, NULL);
+
+        // parse the line
+        match_info = NULL;	// it seems, that in contrast to documentation, match_info is not alsways set -> g_match_info_free will segfault
+        if (g_regex_match (regexpat, line_utf8, 0, &match_info))
+        {
+            match_found = TRUE;
+            // fill in the values
+            gtk_list_store_append (store, &iter);
+            FILL_IN_HELPER ("type", TYPE);
+            FILL_IN_HELPER ("full_name", FULL_NAME);
+            FILL_IN_HELPER ("name", NAME);
+            FILL_IN_HELPER ("code", CODE);
+            FILL_IN_HELPER ("description", DESCRIPTION);
+            FILL_IN_HELPER ("color", COLOR);
+            FILL_IN_HELPER ("notes", NOTES);
+            FILL_IN_HELPER ("commoditym", COMMODITYM);
+            FILL_IN_HELPER ("commodityn", COMMODITYN);
+            FILL_IN_HELPER ("hidden", HIDDEN);
+            FILL_IN_HELPER ("tax", TAX);
+            FILL_IN_HELPER ("place_holder", PLACE_HOLDER);
+            gtk_list_store_set (store, &iter, ROW_COLOR, NULL, -1);
+        }
+
+        g_match_info_free (match_info);
+        match_info = 0;
+        g_free (line_utf8);
+        line_utf8 = 0;
+    }
+    g_free (line);
+    line = 0;
+
+    g_regex_unref (regexpat);
+    regexpat = 0;
+    fclose (f);
+    if(match_found == TRUE)
+        return MATCH_FOUND;
+    else
+        return RESULT_OK;
+}
+
+
+/*******************************************************
+ * csv_account_import
+ *
+ * Parse the liststore for account updates
+ *******************************************************/
+void
+csv_account_import (CsvImportInfo *info)
+{
+    QofBook       *book;
+    Account       *acc, *parent, *root;
+    gboolean       valid;
+    GdkColor       testcolor;
+    GtkTreeIter    iter;
+    gchar         *type, *full_name, *name, *code, *description, *color;
+    gchar         *notes, *commoditym, *commodityn, *hidden, *tax, *place_holder;
+    int            row;
+
+    ENTER("");
+    book = gnc_get_current_book();
+    root = gnc_book_get_root_account(book);
+
+    info->num_new = 0;
+    info->num_updates = 0;
+
+    /* Move to the first valid entry in store */
+    row = info->header_rows;
+    valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(info->store), &iter, NULL, row );
+    while (valid)
+    {
+        /* Walk through the list, reading each row */
+        gtk_tree_model_get (GTK_TREE_MODEL (info->store), &iter,
+                            TYPE, &type,
+                            FULL_NAME, &full_name,	
+                            NAME, &name,	
+                            CODE, &code,	
+                            DESCRIPTION, &description,	
+                            COLOR, &color,
+                            NOTES, &notes,
+                            COMMODITYM, &commoditym,
+                            COMMODITYN, &commodityn,
+                            HIDDEN, &hidden,
+                            TAX, &tax,
+                            PLACE_HOLDER, &place_holder, -1);
+
+        /* See if we can find the account by full name */
+        acc = gnc_account_lookup_by_full_name(root, full_name);
+
+        DEBUG("Row is %u and full name is %s", row, full_name);
+        if (acc == NULL)
+        {
+            /* Account does not exist, Lets try and add it */
+            if (g_strrstr(full_name, name) != NULL)
+            {
+                gint string_position;
+                gnc_commodity *commodity;
+                gnc_commodity_table *table;
+                gchar *full_parent;
+
+                /* Get full name of parent account, allow for separator */
+                string_position = strlen(full_name) - strlen(name) - 1;
+
+                if(string_position == -1)
+                    full_parent = g_strdup(full_name);
+                else
+                    full_parent = g_strndup(full_name, string_position);
+
+                parent = gnc_account_lookup_by_full_name(root, full_parent);
+                g_free (full_parent);
+                
+                if (parent == NULL && string_position != -1)
+                {
+                    gchar *text = g_strdup_printf( gettext("Row %u, path to account %s not found, added as top level\n"), row +1, name );
+                    info->error = g_strconcat(info->error, text, NULL);
+                    g_free(text);
+                    PINFO("Unable to import Row %u for account %s, path not found!", row, name);
+                }
+
+                if (parent == NULL)
+	            parent = root;
+
+                /* Do we have a valid commodity */
+                table = gnc_commodity_table_get_table (book);
+	        commodity = gnc_commodity_table_lookup( table, commodityn, commoditym);
+
+                if (commodity)
+                {
+                    DEBUG("We have a valid commodity and will add account %s", full_name);
+                    info->num_new =  info->num_new + 1;
+                    gnc_suspend_gui_refresh ();
+                    acc = xaccMallocAccount (book);
+	            xaccAccountBeginEdit (acc);
+                    xaccAccountSetName (acc, name);
+                    xaccAccountSetType(acc, xaccAccountStringToEnum (type));
+
+	            if(!g_strcmp0(notes, "") == 0)
+	                xaccAccountSetNotes (acc, notes);
+	            if(!g_strcmp0(description, "") == 0)
+                        xaccAccountSetDescription (acc, description);
+	            if(!g_strcmp0(code, "") == 0)
+	                xaccAccountSetCode (acc, code);
+
+                    if(!g_strcmp0(color, "") == 0)
+	            {
+                        if (gdk_color_parse(color, &testcolor))
+	                   xaccAccountSetColor (acc, color);
+	            }
+
+                    if(g_strcmp0(hidden, "T") == 0)
+                        xaccAccountSetHidden (acc, TRUE);
+                    if(g_strcmp0(place_holder, "T") == 0)
+                        xaccAccountSetPlaceholder (acc, TRUE);
+
+                    xaccAccountSetCommodity(acc, commodity);
+                    xaccAccountBeginEdit (parent);
+                    gnc_account_append_child (parent, acc);
+                    xaccAccountCommitEdit (parent);
+	            xaccAccountCommitEdit (acc);
+                    gnc_resume_gui_refresh ();
+                }
+                else
+                {
+                    gchar *err_string = g_strdup_printf( gettext("Row %u, commodity %s / %s not found\n"), row +1,
+									 commoditym, commodityn);
+                    info->error = g_strconcat(info->error, err_string, NULL);
+                    g_free(err_string);
+                    PINFO("Unable to import Row %u for account %s, commodity!", row, full_name);
+                }
+            }
+            else
+            {
+                gchar *err_string = g_strdup_printf( gettext("Row %u, account %s not in %s\n"), row +1, name, full_name);
+                info->error = g_strconcat(info->error, err_string, NULL);
+                g_free(err_string);
+                PINFO("Unable to import Row %u for account %s, name!", row, full_name);
+            }
+        }
+        else
+        {
+            /* Lets try and update the color, notes, description, code entries */
+            DEBUG("Existing account, will try and update account %s", full_name);
+            info->num_updates = info->num_updates +1;
+	    if(!g_strcmp0(color, "") == 0)
+	    {
+                if (gdk_color_parse(color, &testcolor))
+	            xaccAccountSetColor (acc, color);
+	    }
+
+            if(!g_strcmp0(notes, "") == 0)
+            {
+                /* Check for multiple lines */
+                gchar **parts;
+                parts = g_strsplit(notes, "\\n", -1);
+                notes = g_strjoinv("\n", parts);
+                g_strfreev(parts);
+            }
+            xaccAccountSetNotes (acc, notes);
+
+	    if(!g_strcmp0(description, "") == 0)
+                xaccAccountSetDescription (acc, description);
+	    if(!g_strcmp0(code, "") == 0)
+	        xaccAccountSetCode (acc, code);
+	}
+        valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (info->store), &iter);
+        row++;
+
+        /* free resources */
+        g_free (type);
+        g_free (full_name);
+        g_free (name);
+        g_free (code);
+        g_free (description);
+        g_free (color);
+        g_free (notes);
+        g_free (commoditym);
+        g_free (commodityn);
+        g_free (hidden);
+        g_free (tax);
+        g_free (place_holder);
+    }
+    LEAVE("");
+}


Property changes on: gnucash/trunk/src/import-export/csv-import/csv-account-import.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Copied: gnucash/trunk/src/import-export/csv-import/csv-account-import.h (from rev 22085, gnucash/trunk/src/import-export/csv/gnc-csv-import.h)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/csv-account-import.h	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/csv-account-import.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,50 @@
+/*******************************************************************\
+ * csv-account-import.h -- Account importing from file              *
+ *                                                                  *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ *                                                                  *
+ * Based on code from bi_import written by Sebastian Held  and      *
+ * Mike Evans.                                                      *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#ifndef CSV_ACCOUNT_IMPORT_H
+#define CSV_ACCOUNT_IMPORT_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include "assistant-csv-account-import.h"
+
+enum _csv_import_result
+{
+    RESULT_OK,
+    RESULT_OPEN_FAILED,
+    RESULT_ERROR_IN_REGEXP,
+    MATCH_FOUND,
+};
+typedef enum _csv_import_result csv_import_result;
+
+csv_import_result
+csv_import_read_file (const gchar *filename, const gchar *parser_regexp, GtkListStore *store, guint max_rows );
+
+void csv_account_import(CsvImportInfo *info);
+
+#endif /* CSV_ACCOUNT_IMPORT_H */
+

Copied: gnucash/trunk/src/import-export/csv-import/gnc-csv-gnumeric-popup.c (from rev 22085, gnucash/trunk/src/import-export/csv/gnc-csv-gnumeric-popup.c)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gnc-csv-gnumeric-popup.c	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gnc-csv-gnumeric-popup.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,200 @@
+/* The following is code copied from Gnumeric 1.7.8 licensed under the
+ * GNU General Public License version 2 and/or version 3. It is from the file
+ * gnumeric/src/gui-util.c, and it has been modified slightly to work
+ * within GnuCash. */
+
+/* Miguel de Icaza is not sure specifically who from the Gnumeric
+ * community is the copyright owner of the code below, so, on his
+ * recommendation, here is the full list of Gnumeric authors.
+ *
+ * Miguel de Icaza, creator.
+ * Jody Goldberg, maintainer.
+ * Harald Ashburner, Options pricers
+ * Sean Atkinson, functions and X-Base importing.
+ * Michel Berkelaar, Simplex algorithm for Solver (LP Solve).
+ * Jean Brefort, Core charting engine.
+ * Grandma Chema Celorio, Tester and sheet copy.
+ * Frank Chiulli, OLE support.
+ * Kenneth Christiansen, i18n, misc stuff.
+ * Zbigniew Chyla, plugin system, i18n.
+ * J.H.M. Dassen (Ray), debian packaging.
+ * Jeroen Dirks, Simplex algorithm for Solver (LP Solve).
+ * Tom Dyas, plugin support.
+ * Gergo Erdi, Gnumeric hacker.
+ * John Gotts, rpm packaging.
+ * Andreas J. Guelzow, Gnumeric hacker.
+ * Jon K. Hellan, Gnumeric hacker.
+ * Ross Ihaka, special functions.
+ * Jukka-Pekka Iivonen, numerous functions and tools.
+ * Jakub Jelinek, Gnumeric hacker.
+ * Chris Lahey, number format engine.
+ * Adrian Likins, documentation, debugging.
+ * Takashi Matsuda, original text plugin.
+ * Michael Meeks, Excel and OLE2 importing.
+ * Lutz Muller, SheetObject improvements.
+ * Emmanuel Pacaud, Many plot types for charting engine.
+ * Federico M. Quintero, canvas support.
+ * Mark Probst, Guile support.
+ * Rasca, HTML, troff, LaTeX exporters.
+ * Vincent Renardias, original CSV support, French localization.
+ * Ariel Rios, Guile support.
+ * Uwe Steinmann, Paradox Importer.
+ * Arturo Tena, OLE support.
+ * Almer S. Tigelaar, Gnumeric hacker.
+ * Bruno Unna, Excel bits.
+ * Daniel Veillard, XML support.
+ * Vladimir Vuksan, financial functions.
+ * Morten Welinder, Gnumeric hacker and leak plugging demi-god.
+ */
+
+#include "gnc-csv-gnumeric-popup.h"
+
+#include <glib/gi18n.h>
+
+static void
+popup_item_activate (GtkWidget *item, gpointer *user_data)
+{
+    GnumericPopupMenuElement const *elem =
+        g_object_get_data (G_OBJECT (item), "descriptor");
+    GnumericPopupMenuHandler handler =
+        g_object_get_data (G_OBJECT (item), "handler");
+
+    g_return_if_fail (elem != NULL);
+    g_return_if_fail (handler != NULL);
+
+    if (handler (elem, user_data))
+        gtk_widget_destroy (gtk_widget_get_toplevel (item));
+}
+
+static void
+gnumeric_create_popup_menu_list (GSList *elements,
+                                 GnumericPopupMenuHandler handler,
+                                 gpointer user_data,
+                                 int display_filter,
+                                 int sensitive_filter,
+                                 GdkEventButton *event)
+{
+    GtkWidget *menu, *item;
+    char const *trans;
+
+    menu = gtk_menu_new ();
+
+    for (; elements != NULL ; elements = elements->next)
+    {
+        GnumericPopupMenuElement const *element = elements->data;
+        char const * const name = element->name;
+        char const * const pix_name = element->pixmap;
+
+        item = NULL;
+
+        if (element->display_filter != 0 &&
+                !(element->display_filter & display_filter))
+            continue;
+
+        if (name != NULL && *name != '\0')
+        {
+            trans = _(name);
+            item = gtk_image_menu_item_new_with_mnemonic (trans);
+            if (element->sensitive_filter != 0 &&
+                    (element->sensitive_filter & sensitive_filter))
+                gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
+            if (pix_name != NULL)
+            {
+                GtkWidget *image = gtk_image_new_from_stock (pix_name,
+                                   GTK_ICON_SIZE_MENU);
+                gtk_widget_show (image);
+                gtk_image_menu_item_set_image (
+                    GTK_IMAGE_MENU_ITEM (item),
+                    image);
+            }
+        }
+        else
+        {
+            /* separator */
+            item = gtk_menu_item_new ();
+            gtk_widget_set_sensitive (item, FALSE);
+        }
+
+        if (element->index != 0)
+        {
+            g_signal_connect (G_OBJECT (item),
+                              "activate",
+                              G_CALLBACK (&popup_item_activate), user_data);
+            g_object_set_data (
+                G_OBJECT (item), "descriptor", (gpointer)(element));
+            g_object_set_data (
+                G_OBJECT (item), "handler", (gpointer)handler);
+        }
+
+        gtk_widget_show (item);
+        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+    }
+
+    gnumeric_popup_menu (GTK_MENU (menu), event);
+}
+
+void
+gnumeric_create_popup_menu (GnumericPopupMenuElement const *elements,
+                            GnumericPopupMenuHandler handler,
+                            gpointer user_data,
+                            int display_filter, int sensitive_filter,
+                            GdkEventButton *event)
+{
+    int i;
+    GSList *tmp = NULL;
+
+    for (i = 0; elements [i].name != NULL; i++)
+        tmp = g_slist_prepend (tmp, (gpointer)(elements + i));
+
+    tmp = g_slist_reverse (tmp);
+    gnumeric_create_popup_menu_list (tmp, handler, user_data,
+                                     display_filter, sensitive_filter, event);
+    g_slist_free (tmp);
+}
+
+static void
+kill_popup_menu (GtkWidget *widget, GtkMenu *menu)
+{
+    g_return_if_fail (menu != NULL);
+    g_return_if_fail (GTK_IS_MENU (menu));
+
+    g_object_unref (G_OBJECT (menu));
+}
+
+/**
+ * gnumeric_popup_menu :
+ * @menu : #GtkMenu
+ * @event : #GdkEventButton optionally NULL
+ *
+ * Bring up a popup and if @event is non-NULL ensure that the popup is on the
+ * right screen.
+ **/
+void
+gnumeric_popup_menu (GtkMenu *menu, GdkEventButton *event)
+{
+    g_return_if_fail (menu != NULL);
+    g_return_if_fail (GTK_IS_MENU (menu));
+
+#if GLIB_CHECK_VERSION(2,10,0) && GTK_CHECK_VERSION(2,8,14)
+    g_object_ref_sink (menu);
+#else
+    g_object_ref (menu);
+    gtk_object_sink (GTK_OBJECT (menu));
+#endif
+
+    if (event)
+        gtk_menu_set_screen (menu,
+                             gdk_drawable_get_screen (event->window));
+
+    g_signal_connect (G_OBJECT (menu),
+                      "hide",
+                      G_CALLBACK (kill_popup_menu), menu);
+
+    /* Do NOT pass the button used to create the menu.
+     * instead pass 0.  Otherwise bringing up a menu with
+     * the right button will disable clicking on the menu with the left.
+     */
+    gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0,
+                    (event != NULL) ? event->time
+                    : gtk_get_current_event_time());
+}


Property changes on: gnucash/trunk/src/import-export/csv-import/gnc-csv-gnumeric-popup.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Copied: gnucash/trunk/src/import-export/csv-import/gnc-csv-gnumeric-popup.h (from rev 22085, gnucash/trunk/src/import-export/csv/gnc-csv-gnumeric-popup.h)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gnc-csv-gnumeric-popup.h	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gnc-csv-gnumeric-popup.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,79 @@
+/* The following is code copied from Gnumeric 1.7.8 licensed under the
+ * GNU General Public License version 2 and/or version 3. It is from the file
+ * gnumeric/src/gui-util.h, and it has been modified slightly to work
+ * within GnuCash. */
+
+/* Miguel de Icaza is not sure specifically who from the Gnumeric
+ * community is the copyright owner of the code below, so, on his
+ * recommendation, here is the full list of Gnumeric authors.
+ *
+ * Miguel de Icaza, creator.
+ * Jody Goldberg, maintainer.
+ * Harald Ashburner, Options pricers
+ * Sean Atkinson, functions and X-Base importing.
+ * Michel Berkelaar, Simplex algorithm for Solver (LP Solve).
+ * Jean Brefort, Core charting engine.
+ * Grandma Chema Celorio, Tester and sheet copy.
+ * Frank Chiulli, OLE support.
+ * Kenneth Christiansen, i18n, misc stuff.
+ * Zbigniew Chyla, plugin system, i18n.
+ * J.H.M. Dassen (Ray), debian packaging.
+ * Jeroen Dirks, Simplex algorithm for Solver (LP Solve).
+ * Tom Dyas, plugin support.
+ * Gergo Erdi, Gnumeric hacker.
+ * John Gotts, rpm packaging.
+ * Andreas J. Guelzow, Gnumeric hacker.
+ * Jon K. Hellan, Gnumeric hacker.
+ * Ross Ihaka, special functions.
+ * Jukka-Pekka Iivonen, numerous functions and tools.
+ * Jakub Jelinek, Gnumeric hacker.
+ * Chris Lahey, number format engine.
+ * Adrian Likins, documentation, debugging.
+ * Takashi Matsuda, original text plugin.
+ * Michael Meeks, Excel and OLE2 importing.
+ * Lutz Muller, SheetObject improvements.
+ * Emmanuel Pacaud, Many plot types for charting engine.
+ * Federico M. Quintero, canvas support.
+ * Mark Probst, Guile support.
+ * Rasca, HTML, troff, LaTeX exporters.
+ * Vincent Renardias, original CSV support, French localization.
+ * Ariel Rios, Guile support.
+ * Uwe Steinmann, Paradox Importer.
+ * Arturo Tena, OLE support.
+ * Almer S. Tigelaar, Gnumeric hacker.
+ * Bruno Unna, Excel bits.
+ * Daniel Veillard, XML support.
+ * Vladimir Vuksan, financial functions.
+ * Morten Welinder, Gnumeric hacker and leak plugging demi-god.
+ */
+
+#ifndef GNC_CSV_GNUMERIC_POPUP
+#define GNC_CSV_GNUMERIC_POPUP
+
+#include <gtk/gtk.h>
+
+typedef struct
+{
+    char const *name;
+    char const *pixmap;
+    int display_filter;
+    int sensitive_filter;
+
+    int index;
+} GnumericPopupMenuElement;
+
+typedef gboolean (*GnumericPopupMenuHandler) (GnumericPopupMenuElement const *e,
+        gpointer user_data);
+
+/* Use this on menus that are popped up */
+void gnumeric_popup_menu (GtkMenu *menu, GdkEventButton *event);
+
+void gnumeric_create_popup_menu (GnumericPopupMenuElement const *elements,
+                                 GnumericPopupMenuHandler handler,
+                                 gpointer user_data,
+                                 int display_filter,
+                                 int sensitive_filter,
+                                 GdkEventButton *event);
+
+
+#endif


Property changes on: gnucash/trunk/src/import-export/csv-import/gnc-csv-gnumeric-popup.h
___________________________________________________________________
Added: svn:eol-style
   + LF

Copied: gnucash/trunk/src/import-export/csv-import/gnc-csv-import.c (from rev 22085, gnucash/trunk/src/import-export/csv/gnc-csv-import.c)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gnc-csv-import.c	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gnc-csv-import.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,1216 @@
+/*******************************************************************\
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+/** @file gnc-csv-import.c
+    @brief CSV Import GUI code
+    @author Copyright (c) 2007 Benny Sperisen <lasindi at gmail.com>
+*/
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <goffice/gtk/go-charmap-sel.h>
+
+#include "import-account-matcher.h"
+#include "import-main-matcher.h"
+
+#include "gnc-file.h"
+#include "gnc-ui-util.h"
+#include "gnc-glib-utils.h"
+#include "gnc-gui-query.h"
+#include "dialog-utils.h"
+
+#include "gnc-csv-import.h"
+#include "gnc-csv-model.h"
+#include "gnc-csv-gnumeric-popup.h"
+
+#define GCONF_SECTION "dialogs/import/csv"
+#define MIN_COL_WIDTH 70
+
+static QofLogModule log_module = GNC_MOD_IMPORT;
+
+/** Enumeration for separator checkbutton types. These are the
+ * different types of checkbuttons that the user can click to
+ * configure separators in a delimited file. */
+enum SEP_BUTTON_TYPES {SEP_SPACE, SEP_TAB, SEP_COMMA, SEP_COLON, SEP_SEMICOLON, SEP_HYPHEN,
+                       SEP_NUM_OF_TYPES
+                      };
+
+/** Data for the preview dialog. This struct contains all of the data
+ * relevant to the preview dialog that lets the user configure an
+ * import. */
+typedef struct
+{
+    GncCsvParseData* parse_data;       /**< The actual data we are previewing */
+    GtkDialog* dialog;
+    GOCharmapSel* encselector;         /**< The widget for selecting the encoding */
+    GtkComboBox* date_format_combo;    /**< The widget for selecting the date format */
+    GtkTreeView* treeview;             /**< The treeview containing the data */
+    GtkTreeView* ctreeview;            /**< The treeview containing the column types */
+    GtkCheckButton* sep_buttons[SEP_NUM_OF_TYPES]; /**< Checkbuttons for common separators */
+    GtkCheckButton* custom_cbutton;    /**< The checkbutton for a custom separator */
+    GtkEntry* custom_entry;            /**< The entry for custom separators */
+    GtkLabel* instructions_label;      /**< The instructions label */
+    GtkImage* instructions_image;      /**< The instructions image */
+    gboolean encoding_selected_called; /**< Before encoding_selected is first called, this is FALSE.
+                                        * (See description of encoding_selected.) */
+    gboolean not_empty;                /**< FALSE initially, true after the first type gnc_csv_preview_update is called. */
+    gboolean previewing_errors;        /**< TRUE if the dialog is displaying
+                                       * error lines, instead of all the file data. */
+    int code_encoding_calls;           /**< Normally this is 0. If the computer
+                                       * changes encselector, this is set to
+                                       * 2. encoding_selected is called twice,
+                                       * each time decrementing this by 1. */
+    gboolean approved;                 /**< This is FALSE until the user clicks "OK". */
+    GtkWidget** treeview_buttons;      /**< This array contains the header buttons in treeview */
+    int longest_line;                  /**< The length of the longest row */
+    int fixed_context_col;             /**< The number of the column whose the user has clicked */
+    int fixed_context_dx;              /**< The horizontal coordinate of the pixel in the header of the column
+                                       * the user has clicked */
+} GncCsvPreview;
+
+static void gnc_csv_preview_update(GncCsvPreview* preview);
+
+/** Event handler for separator changes. This function is called
+ * whenever one of the widgets for configuring the separators (the
+ * separator checkbuttons or the custom separator entry) is
+ * changed.
+ * @param widget The widget that was changed
+ * @param preview The data that is being configured
+ */
+static void sep_button_clicked(GtkWidget* widget, GncCsvPreview* preview)
+{
+    int i;
+    char* stock_separator_characters[] = {" ", "\t", ",", ":", ";", "-"};
+    GSList* checked_separators = NULL;
+    GError* error;
+
+    /* Add the corresponding characters to checked_separators for each
+     * button that is checked. */
+    for (i = 0; i < SEP_NUM_OF_TYPES; i++)
+    {
+        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(preview->sep_buttons[i])))
+            checked_separators = g_slist_append(checked_separators, stock_separator_characters[i]);
+    }
+
+    /* Add the custom separator if the user checked its button. */
+    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(preview->custom_cbutton)))
+    {
+        char* custom_sep = (char*)gtk_entry_get_text(preview->custom_entry);
+        if (custom_sep[0] != '\0') /* Don't add a blank separator (bad things will happen!). */
+            checked_separators = g_slist_append(checked_separators, custom_sep);
+    }
+
+    /* Set the parse options using the checked_separators list. */
+    stf_parse_options_csv_set_separators(preview->parse_data->options, NULL, checked_separators);
+    g_slist_free(checked_separators);
+
+    /* Parse the data using the new options. We don't want to reguess
+     * the column types because we want to leave the user's
+     * configurations in tact. */
+    if (gnc_csv_parse(preview->parse_data, FALSE, &error))
+    {
+        /* Warn the user there was a problem and try to undo what caused
+         * the error. (This will cause a reparsing and ideally a usable
+         * configuration.) */
+        gnc_error_dialog(NULL, "Error in parsing");
+        /* If the user changed the custom separator, erase that custom separator. */
+        if (widget == GTK_WIDGET(preview->custom_entry))
+        {
+            gtk_entry_set_text(GTK_ENTRY(widget), "");
+        }
+        /* If the user checked a checkbutton, toggle that checkbutton back. */
+        else
+        {
+            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),
+                                         !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
+        }
+        return;
+    }
+
+    /* If we parsed successfully, redisplay the data. */
+    gnc_csv_preview_update(preview);
+}
+
+/** Event handler for clicking one of the format type radio
+ * buttons. This occurs if the format (Fixed-Width or CSV) is changed.
+ * @param csv_button The "Separated" radio button
+ * @param preview The display of the data being imported
+ */
+static void separated_or_fixed_selected(GtkToggleButton* csv_button, GncCsvPreview* preview)
+{
+    GError* error = NULL;
+    /* Set the parsing type correctly. */
+    if (gtk_toggle_button_get_active(csv_button)) /* If we're in CSV mode ... */
+    {
+        stf_parse_options_set_type(preview->parse_data->options, PARSE_TYPE_CSV);
+    }
+    else /* If we're in fixed-width mode ... */
+    {
+        stf_parse_options_set_type(preview->parse_data->options, PARSE_TYPE_FIXED);
+    }
+
+    /* Reparse the data. */
+    if (gnc_csv_parse(preview->parse_data, FALSE, &error))
+    {
+        /* Show an error dialog explaining the problem. */
+        gnc_error_dialog(NULL, "%s", error->message);
+        return;
+    }
+
+    /* Show the new data. */
+    gnc_csv_preview_update(preview);
+}
+
+/** Event handler for a new encoding. This is called when the user
+ * selects a new encoding; the data is reparsed and shown to the
+ * user.
+ * @param selector The widget the user uses to select a new encoding
+ * @param encoding The encoding that the user selected
+ * @param preview The display of the data being imported
+ */
+static void encoding_selected(GOCharmapSel* selector, const char* encoding,
+                              GncCsvPreview* preview)
+{
+    /* This gets called twice everytime a new encoding is selected. The
+     * second call actually passes the correct data; thus, we only do
+     * something the second time this is called. */
+
+    /* Prevent code-caused calls of this function from having an impact. */
+    if (preview->code_encoding_calls > 0)
+    {
+        preview->code_encoding_calls--;
+        return;
+    }
+
+    /* If this is the second time the function is called ... */
+    if (preview->encoding_selected_called)
+    {
+        const char* previous_encoding = preview->parse_data->encoding;
+        GError* error = NULL;
+        /* Try converting the new encoding and reparsing. */
+        if (gnc_csv_convert_encoding(preview->parse_data, encoding, &error) ||
+                gnc_csv_parse(preview->parse_data, FALSE, &error))
+        {
+            /* If it fails, change back to the old encoding. */
+            gnc_error_dialog(NULL, "%s", _("Invalid encoding selected"));
+            preview->encoding_selected_called = FALSE;
+            go_charmap_sel_set_encoding(selector, previous_encoding);
+            return;
+        }
+
+        gnc_csv_preview_update(preview);
+        preview->encoding_selected_called = FALSE;
+    }
+    else /* If this is the first call of the function ... */
+    {
+        preview->encoding_selected_called = TRUE; /* ... set the flag and wait for the next call. */
+    }
+}
+
+/** Event handler for selecting a new date format.
+ * @param format_selector The combo box for selecting date formats
+ * @param preview The display of the data being imported
+ */
+static void date_format_selected(GtkComboBox* format_selector, GncCsvPreview* preview)
+{
+    preview->parse_data->date_format = gtk_combo_box_get_active(format_selector);
+}
+
+/** Event handler for the "OK" button. When "OK" is clicked, this
+ * function updates the parse data with the user's column type
+ * configuration and closes the preview dialog.
+ * @param widget The "OK" button
+ * @param preview The display of the data being imported
+ */
+static void ok_button_clicked(GtkWidget* widget, GncCsvPreview* preview)
+{
+    /* Shorten the column_types identifier. */
+    GArray* column_types = preview->parse_data->column_types;
+    int i, ncols = column_types->len; /* ncols is the number of columns in the data. */
+    /* store contains the actual strings appearing in the column types treeview. */
+    GtkTreeModel* store = gtk_tree_view_get_model(preview->ctreeview);
+    GtkTreeIter iter;
+    /* Get an iterator for the first (and only) row. */
+    gtk_tree_model_get_iter_first(store, &iter);
+
+    /* Go through each of the columns. */
+    for (i = 0; i < ncols; i++)
+    {
+        int type; /* The column type contained in this column. */
+        gchar* contents = NULL; /* The column type string in this column. */
+        /* Get the type string first. (store is arranged so that every two
+         * columns is a pair of the model used for the combobox and the
+         * string that appears, so that store looks like:
+         * model 0, string 0, model 1, string 1, ..., model ncols, string ncols. */
+        gtk_tree_model_get(store, &iter, 2 * i + 1, &contents, -1);
+
+        /* Go through each column type until ... */
+        for (type = 0; type < GNC_CSV_NUM_COL_TYPES; type++)
+        {
+            /* ... we find one that matches with what's in the column. */
+            if (!safe_strcmp(contents, _(gnc_csv_column_type_strs[type])))
+            {
+                /* Set the column_types array appropriately and quit. */
+                column_types->data[i] = type;
+                break;
+            }
+        }
+        /* Free the type string created by gtk_tree_model_get() */
+        g_free(contents);
+    }
+
+    /* Close the dialog. */
+    gtk_widget_hide((GtkWidget*)(preview->dialog));
+    preview->approved = TRUE; /* The user has wants to do the import. */
+}
+
+/** Event handler for the "Cancel" button. When the user clicks
+ * "Cancel", the dialog is simply closed.
+ * @param widget The "Cancel" button
+ * @param preview The display of the data being imported
+ */
+static void cancel_button_clicked(GtkWidget* widget, GncCsvPreview* preview)
+{
+    gtk_widget_hide((GtkWidget*)(preview->dialog));
+}
+
+/** Event handler for the data treeview being resized. When the data
+ * treeview is resized, the column types treeview's columns are also resized to
+ * match.
+ * @param widget The data treeview
+ * @param allocation The size of the data treeview
+ * @param preview The display of the data being imported
+ */
+static void treeview_resized(GtkWidget* widget, GtkAllocation* allocation, GncCsvPreview* preview)
+{
+    /* ncols is the number of columns in the data. */
+    int i, ncols = preview->parse_data->column_types->len;
+
+    /* Go through each column except for the last. (We don't want to set
+     * the width of the last column because the user won't be able to
+     * shrink the dialog back if it's expanded.) */
+    for (i = 0; i < ncols - 1; i++)
+    {
+        gint col_width; /* The width of the column in preview->treeview. */
+        GtkTreeViewColumn* pcol;
+        GtkTreeViewColumn* ccol; /* The corresponding column in preview->ctreeview. */
+
+        /* Get the width. */
+        col_width = gtk_tree_view_column_get_width(gtk_tree_view_get_column(preview->treeview, i));
+        /* Set the minumum width for a column so that drop down selector can be seen. */
+        if (col_width < MIN_COL_WIDTH)
+        {
+            col_width = MIN_COL_WIDTH;
+        }
+        pcol = gtk_tree_view_get_column(preview->treeview, i);
+        gtk_tree_view_column_set_min_width(pcol, col_width);
+        /* Set ccol's width the same. */
+        ccol = gtk_tree_view_get_column(preview->ctreeview, i);
+        gtk_tree_view_column_set_min_width(ccol, col_width);
+        gtk_tree_view_column_set_max_width(ccol, col_width);
+    }
+}
+
+/** Event handler for the user selecting a new column type. When the
+ * user selects a new column type, that column's text must be changed
+ * to that selection, and any other columns containing that selection
+ * must be changed to "None" because we don't allow duplicates.
+ * @param renderer The renderer of the column the user changed
+ * @param path There is only 1 row in preview->ctreeview, so this is always 0.
+ * @param new_text The text the user selected
+ * @param preview The display of the data being imported
+ */
+static void column_type_changed(GtkCellRenderer* renderer, gchar* path,
+                                GtkTreeIter* new_text_iter, GncCsvPreview* preview)
+{
+    /* ncols is the number of columns in the data. */
+    int i, ncols = preview->parse_data->column_types->len;
+    /* store has the actual strings that appear in preview->ctreeview. */
+    GtkTreeModel* store = gtk_tree_view_get_model(preview->ctreeview);
+    GtkTreeModel* model;
+    gint textColumn;
+    GtkTreeIter iter;
+    gchar* new_text;
+
+    /* Get the new text */
+    g_object_get(renderer, "model", &model, "text-column", &textColumn, NULL);
+    gtk_tree_model_get(model, new_text_iter, textColumn, &new_text, -1);
+
+    /* Get an iterator for the first (and only) row. */
+    gtk_tree_model_get_iter_first(store, &iter);
+
+    /* Go through each column. */
+    for (i = 0; i < ncols; i++)
+    {
+        /* We need all this stuff so that we can find out whether or not
+         * this was the column that was changed. */
+        GtkCellRenderer* col_renderer; /* The renderer for this column. */
+        /* The column in the treeview we are looking at */
+        GtkTreeViewColumn* col = gtk_tree_view_get_column(preview->ctreeview, i);
+        /* The list of renderers for col */
+        GList* rend_list = gtk_tree_view_column_get_cell_renderers(col);
+        /* rend_list has only one entry, which we put in col_renderer. */
+        col_renderer = rend_list->data;
+        g_list_free(rend_list);
+
+        /* If this is not the column that was changed ... */
+        if (col_renderer != renderer)
+        {
+            /* The string that appears in the column */
+            gchar* contents = NULL;
+            /* Get the type string. (store is arranged so that every two
+             * columns is a pair of the model used for the combobox and the
+             * string that appears, so that store looks like:
+             * model 0, string 0, model 1, string 1, ..., model ncols, string ncols. */
+            gtk_tree_model_get(store, &iter, 2 * i + 1, &contents, -1);
+            /* If this column has the same string that the user selected ... */
+            if (!safe_strcmp(contents, new_text))
+            {
+                /* ... set this column to the "None" type. (We can't allow duplicate types.) */
+                gtk_list_store_set(GTK_LIST_STORE(store), &iter, 2 * i + 1,
+                                   _(gnc_csv_column_type_strs[GNC_CSV_NONE]), -1);
+            }
+            g_free(contents);
+        }
+        else /* If this is the column that was changed ... */
+        {
+            /* Set the text for this column to what the user selected. (See
+             * comment above "Get the type string. ..." for why we set
+             * column 2*i+1 in store.) */
+            gtk_list_store_set(GTK_LIST_STORE(store), &iter, 2 * i + 1, new_text, -1);
+        }
+    }
+}
+
+/** Constructor for GncCsvPreview.
+ * @return A new GncCsvPreview* ready for use.
+ */
+static GncCsvPreview* gnc_csv_preview_new()
+{
+    int i;
+    GncCsvPreview* preview = g_new(GncCsvPreview, 1);
+    GtkWidget *ok_button, *cancel_button, *csv_button;
+    GtkContainer* date_format_container;
+    GtkBuilder *builder;
+    /* The names in the glade builder file for the sep buttons. */
+    char* sep_button_names[] = {"space_cbutton",
+                                "tab_cbutton",
+                                "comma_cbutton",
+                                "colon_cbutton",
+                                "semicolon_cbutton",
+                                "hyphen_cbutton"
+                               };
+    /* The table containing preview->encselector and the separator configuration widgets */
+    GtkTable* enctable;
+    PangoContext* context; /* Used to set a monotype font on preview->treeview */
+
+    preview->encselector = GO_CHARMAP_SEL(go_charmap_sel_new(GO_CHARMAP_SEL_TO_UTF8));
+    /* Connect the selector to the encoding_selected event handler. */
+    g_signal_connect(G_OBJECT(preview->encselector), "charmap_changed",
+                     G_CALLBACK(encoding_selected), (gpointer)preview);
+
+    /* Load the Glade builder file. */
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file (builder, "gnc-csv-import.glade", "preview-dialog");
+
+    /* Load the dialog. */
+    preview->dialog = GTK_DIALOG(gtk_builder_get_object (builder, "preview-dialog"));
+
+    /* Load the separator buttons from the glade builder file into the
+     * preview->sep_buttons array. */
+    for (i = 0; i < SEP_NUM_OF_TYPES; i++)
+    {
+        preview->sep_buttons[i]
+        = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, sep_button_names[i]));
+        /* Connect them to the sep_button_clicked event handler. */
+        g_signal_connect(G_OBJECT(preview->sep_buttons[i]), "toggled",
+                         G_CALLBACK(sep_button_clicked), (gpointer)preview);
+    }
+
+    /* Load and connect the custom separator checkbutton in the same way
+     * as the other separator buttons. */
+    preview->custom_cbutton
+    = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_cbutton"));
+    g_signal_connect(G_OBJECT(preview->custom_cbutton), "clicked",
+                     G_CALLBACK(sep_button_clicked), (gpointer)preview);
+
+    /* Load the entry for the custom separator entry. Connect it to the
+     * sep_button_clicked event handler as well. */
+    preview->custom_entry = (GtkEntry*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_entry"));
+    g_signal_connect(G_OBJECT(preview->custom_entry), "changed",
+                     G_CALLBACK(sep_button_clicked), (gpointer)preview);
+
+    /* Get the table from the Glade builder file. */
+    enctable = GTK_TABLE(gtk_builder_get_object (builder, "enctable"));
+    /* Put the selector in at the top. */
+    gtk_table_attach_defaults(enctable, GTK_WIDGET(preview->encselector), 1, 2, 0, 1);
+    /* Show the table in all its glory. */
+    gtk_widget_show_all(GTK_WIDGET(enctable));
+
+    /* The instructions label and image */
+    preview->instructions_label = GTK_LABEL(gtk_builder_get_object (builder, "instructions_label"));
+    preview->instructions_image = GTK_IMAGE(gtk_builder_get_object (builder, "instructions_image"));
+
+    /* Add in the date format combo box and hook it up to an event handler. */
+    preview->date_format_combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
+    for (i = 0; i < num_date_formats; i++)
+    {
+        gtk_combo_box_append_text(preview->date_format_combo, _(date_format_user[i]));
+    }
+    gtk_combo_box_set_active(preview->date_format_combo, 0);
+    g_signal_connect(G_OBJECT(preview->date_format_combo), "changed",
+                     G_CALLBACK(date_format_selected), (gpointer)preview);
+
+    /* Add it to the dialog. */
+    date_format_container = GTK_CONTAINER(gtk_builder_get_object (builder, "date_format_container"));
+    gtk_container_add(date_format_container, GTK_WIDGET(preview->date_format_combo));
+    gtk_widget_show_all(GTK_WIDGET(date_format_container));
+
+    /* Connect the "OK" and "Cancel" buttons to their event handlers. */
+    ok_button = GTK_WIDGET(gtk_builder_get_object (builder, "ok_button"));
+    g_signal_connect(G_OBJECT(ok_button), "clicked",
+                     G_CALLBACK(ok_button_clicked), (gpointer)preview);
+
+    cancel_button = GTK_WIDGET(gtk_builder_get_object (builder, "cancel_button"));
+    g_signal_connect(G_OBJECT(cancel_button), "clicked",
+                     G_CALLBACK(cancel_button_clicked), (gpointer)preview);
+
+    /* Connect the CSV/Fixed-Width radio button event handler. */
+    csv_button = GTK_WIDGET(gtk_builder_get_object (builder, "csv_button"));
+    g_signal_connect(csv_button, "toggled",
+                     G_CALLBACK(separated_or_fixed_selected), (gpointer)preview);
+
+    /* Load the data treeview and connect it to its resizing event handler. */
+    preview->treeview = (GtkTreeView*)GTK_WIDGET(gtk_builder_get_object (builder, "treeview"));
+    g_signal_connect(G_OBJECT(preview->treeview), "size-allocate",
+                     G_CALLBACK(treeview_resized), (gpointer)preview);
+    context = gtk_widget_create_pango_context(GTK_WIDGET(preview->treeview));
+
+    /* Load the column type treeview. */
+    preview->ctreeview = (GtkTreeView*)GTK_WIDGET(gtk_builder_get_object (builder, "ctreeview"));
+
+    /* This is TRUE only after encoding_selected is called, so we must
+     * set it initially to FALSE. */
+    preview->encoding_selected_called = FALSE;
+
+    /* It is empty at first. */
+    preview->not_empty = FALSE;
+
+    g_object_unref(G_OBJECT(builder));
+
+    return preview;
+}
+
+/** Destructor for GncCsvPreview. This does not free
+ * preview->parse_data, which must be freed separately.
+ * @param preview The preview whose memory is freed.
+ */
+static void gnc_csv_preview_free(GncCsvPreview* preview)
+{
+    g_free(preview);
+}
+
+/** Returns the cell renderer from a column in the preview's treeview.
+ * @param preview The display of the data being imported
+ * @param col The number of the column whose cell renderer is being retrieved
+ * @return The cell renderer of column number col
+ */
+static GtkCellRenderer* gnc_csv_preview_get_cell_renderer(GncCsvPreview* preview, int col)
+{
+    GList* renderers = gtk_tree_view_column_get_cell_renderers(gtk_tree_view_get_column(preview->treeview, col));
+    GtkCellRenderer* cell = GTK_CELL_RENDERER(renderers->data);
+    g_list_free(renderers);
+    return cell;
+}
+
+/* The following is code copied from Gnumeric 1.7.8 licensed under the
+ * GNU General Public License version 2. It is from the file
+ * gnumeric/src/dialogs/dialog-stf-fixed-page.c, and it has been
+ * modified slightly to work within GnuCash. */
+
+/* ---- Beginning of Gnumeric Code ---- */
+
+/*
+ * Copyright 2001 Almer S. Tigelaar <almer at gnome.org>
+ * Copyright 2003 Morten Welinder <terra at gnome.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+enum
+{
+    CONTEXT_STF_IMPORT_MERGE_LEFT = 1,
+    CONTEXT_STF_IMPORT_MERGE_RIGHT = 2,
+    CONTEXT_STF_IMPORT_SPLIT = 3,
+    CONTEXT_STF_IMPORT_WIDEN = 4,
+    CONTEXT_STF_IMPORT_NARROW = 5
+};
+
+static GnumericPopupMenuElement const popup_elements[] =
+{
+    {
+        N_("Merge with column on _left"), GTK_STOCK_REMOVE,
+        0, 1 << CONTEXT_STF_IMPORT_MERGE_LEFT, CONTEXT_STF_IMPORT_MERGE_LEFT
+    },
+    {
+        N_("Merge with column on _right"), GTK_STOCK_REMOVE,
+        0, 1 << CONTEXT_STF_IMPORT_MERGE_RIGHT, CONTEXT_STF_IMPORT_MERGE_RIGHT
+    },
+    { "", NULL, 0, 0, 0 },
+    {
+        N_("_Split this column"), NULL,
+        0, 1 << CONTEXT_STF_IMPORT_SPLIT, CONTEXT_STF_IMPORT_SPLIT
+    },
+    { "", NULL, 0, 0, 0 },
+    {
+        N_("_Widen this column"), GTK_STOCK_GO_FORWARD,
+        0, 1 << CONTEXT_STF_IMPORT_WIDEN, CONTEXT_STF_IMPORT_WIDEN
+    },
+    {
+        N_("_Narrow this column"), GTK_STOCK_GO_BACK,
+        0, 1 << CONTEXT_STF_IMPORT_NARROW, CONTEXT_STF_IMPORT_NARROW
+    },
+    { NULL, NULL, 0, 0, 0 },
+};
+
+static gboolean
+make_new_column (GncCsvPreview *preview, int col, int dx, gboolean test_only)
+{
+    PangoLayout *layout;
+    PangoFontDescription *font_desc;
+    int charindex, width;
+    GtkCellRenderer *cell =	gnc_csv_preview_get_cell_renderer(preview, col);
+    int colstart, colend;
+    GError* error = NULL;
+
+    colstart = (col == 0)
+               ? 0
+               : stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col - 1);
+    colend = stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col);
+
+    g_object_get (G_OBJECT (cell), "font_desc", &font_desc, NULL);
+    layout = gtk_widget_create_pango_layout (GTK_WIDGET (preview->treeview), "x");
+    pango_layout_set_font_description (layout, font_desc);
+    pango_layout_get_pixel_size (layout, &width, NULL);
+    if (width < 1) width = 1;
+    charindex = colstart + (dx + width / 2) / width;
+    g_object_unref (layout);
+    pango_font_description_free (font_desc);
+
+    if (charindex <= colstart || (colend != -1 && charindex >= colend))
+        return FALSE;
+
+    if (!test_only)
+    {
+        stf_parse_options_fixed_splitpositions_add (preview->parse_data->options, charindex);
+        if (gnc_csv_parse(preview->parse_data, FALSE, &error))
+        {
+            gnc_error_dialog(NULL, "%s", error->message);
+            return FALSE;
+        }
+        gnc_csv_preview_update (preview);
+    }
+
+    return TRUE;
+}
+
+
+static gboolean
+widen_column (GncCsvPreview *preview, int col, gboolean test_only)
+{
+    int colcount = stf_parse_options_fixed_splitpositions_count (preview->parse_data->options);
+    int nextstart, nextnextstart;
+    GError* error = NULL;
+
+    if (col >= colcount - 1)
+        return FALSE;
+
+    nextstart = stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col);
+
+    nextnextstart = (col == colcount - 2)
+                    ? preview->longest_line
+                    : stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col + 1);
+
+    if (nextstart + 1 >= nextnextstart)
+        return FALSE;
+
+    if (!test_only)
+    {
+        stf_parse_options_fixed_splitpositions_remove (preview->parse_data->options, nextstart);
+        stf_parse_options_fixed_splitpositions_add (preview->parse_data->options, nextstart + 1);
+        if (gnc_csv_parse(preview->parse_data, FALSE, &error))
+        {
+            gnc_error_dialog(NULL, "%s", error->message);
+            return FALSE;
+        }
+        gnc_csv_preview_update (preview);
+    }
+    return TRUE;
+}
+
+static gboolean
+narrow_column (GncCsvPreview *preview, int col, gboolean test_only)
+{
+    int colcount = stf_parse_options_fixed_splitpositions_count (preview->parse_data->options);
+    int thisstart, nextstart;
+    GError* error = NULL;
+
+    if (col >= colcount - 1)
+        return FALSE;
+
+    thisstart = (col == 0)
+                ? 0
+                : stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col - 1);
+    nextstart = stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col);
+
+    if (nextstart - 1 <= thisstart)
+        return FALSE;
+
+    if (!test_only)
+    {
+        stf_parse_options_fixed_splitpositions_remove (preview->parse_data->options, nextstart);
+        stf_parse_options_fixed_splitpositions_add (preview->parse_data->options, nextstart - 1);
+        if (gnc_csv_parse(preview->parse_data, FALSE, &error))
+        {
+            gnc_error_dialog(NULL, "%s", error->message);
+            return FALSE;
+        }
+        gnc_csv_preview_update (preview);
+    }
+    return TRUE;
+}
+
+static gboolean
+delete_column (GncCsvPreview *preview, int col, gboolean test_only)
+{
+    GError* error = NULL;
+    int colcount = stf_parse_options_fixed_splitpositions_count (preview->parse_data->options);
+    if (col < 0 || col >= colcount - 1)
+        return FALSE;
+
+    if (!test_only)
+    {
+        int nextstart = stf_parse_options_fixed_splitpositions_nth (preview->parse_data->options, col);
+        stf_parse_options_fixed_splitpositions_remove (preview->parse_data->options, nextstart);
+        if (gnc_csv_parse(preview->parse_data, FALSE, &error))
+        {
+            gnc_error_dialog(NULL, "%s", error->message);
+            return FALSE;
+        }
+        gnc_csv_preview_update (preview);
+    }
+    return TRUE;
+}
+
+static void
+select_column (GncCsvPreview *preview, int col)
+{
+    GError* error = NULL;
+    int colcount = stf_parse_options_fixed_splitpositions_count (preview->parse_data->options);
+    GtkTreeViewColumn *column;
+
+    if (col < 0 || col >= colcount)
+        return;
+
+    column = gtk_tree_view_get_column (preview->treeview, col);
+    gtk_widget_grab_focus (column->button);
+}
+
+static gboolean
+fixed_context_menu_handler (GnumericPopupMenuElement const *element,
+                            gpointer user_data)
+{
+    GncCsvPreview *preview = user_data;
+    int col = preview->fixed_context_col;
+
+    switch (element->index)
+    {
+    case CONTEXT_STF_IMPORT_MERGE_LEFT:
+        delete_column (preview, col - 1, FALSE);
+        break;
+    case CONTEXT_STF_IMPORT_MERGE_RIGHT:
+        delete_column (preview, col, FALSE);
+        break;
+    case CONTEXT_STF_IMPORT_SPLIT:
+        make_new_column (preview, col, preview->fixed_context_dx, FALSE);
+        break;
+    case CONTEXT_STF_IMPORT_WIDEN:
+        widen_column (preview, col, FALSE);
+        break;
+    case CONTEXT_STF_IMPORT_NARROW:
+        narrow_column (preview, col, FALSE);
+        break;
+    default:
+        ; /* Nothing */
+    }
+    return TRUE;
+}
+
+static void
+fixed_context_menu (GncCsvPreview *preview, GdkEventButton *event,
+                    int col, int dx)
+{
+    int sensitivity_filter = 0;
+
+    preview->fixed_context_col = col;
+    preview->fixed_context_dx = dx;
+
+    if (!delete_column (preview, col - 1, TRUE))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_LEFT);
+    if (!delete_column (preview, col, TRUE))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_RIGHT);
+    if (!make_new_column (preview, col, dx, TRUE))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_SPLIT);
+    if (!widen_column (preview, col, TRUE))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_WIDEN);
+    if (!narrow_column (preview, col, TRUE))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_NARROW);
+
+    select_column (preview, col);
+    gnumeric_create_popup_menu (popup_elements, &fixed_context_menu_handler,
+                                preview, 0,
+                                sensitivity_filter, event);
+}
+
+/* ---- End of Gnumeric Code ---- */
+
+/** Event handler for clicking on column headers. This function is
+ * called whenever the user clicks on column headers in
+ * preview->treeview to modify columns when in fixed-width mode.
+ * @param button The button at the top of a column of the treeview
+ * @param event The event that happened (where the user clicked)
+ * @param preview The data being configured
+ */
+static void header_button_press_handler(GtkWidget* button, GdkEventButton* event,
+                                        GncCsvPreview* preview)
+{
+    /* col is the number of the column that was clicked, and offset is
+       to correct for the indentation of button. */
+    int i, col = 0, offset = GTK_BIN(button)->child->allocation.x - button->allocation.x,
+           ncols = preview->parse_data->column_types->len;
+    /* Find the column that was clicked. */
+    for (i = 0; i < ncols; i++)
+    {
+        if (preview->treeview_buttons[i] == button)
+        {
+            col = i;
+            break;
+        }
+    }
+
+    /* Don't let the user affect the last column if it has error messages. */
+    if (preview->parse_data->orig_max_row < ncols && ncols - col == 1)
+    {
+        return;
+    }
+
+    /* Double clicks can split columns. */
+    if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
+    {
+        make_new_column(preview, col, (int)event->x - offset, FALSE);
+    }
+    /* Right clicking brings up a context menu. */
+    else if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+    {
+        fixed_context_menu(preview, event, col, (int)event->x - offset);
+    }
+}
+
+/* Loads the preview's data into its data treeview. notEmpty is TRUE
+ * when the data treeview already contains data, FALSE otherwise
+ * (e.g. the first time this function is called on a preview).
+ * @param preview The data being previewed
+ * @param notEmpty Whether this function has been called before or not
+ */
+static void gnc_csv_preview_update(GncCsvPreview* preview)
+{
+    /* store has the data from the file being imported. cstores is an
+     * array of stores that hold the combo box entries for each
+     * column. ctstore contains both pointers to models in cstore and
+     * the actual text that appears in preview->ctreeview. */
+    GtkListStore *store, **cstores, *ctstore;
+    GtkTreeIter iter;
+    /* ncols is the number of columns in the file data. */
+    int i, j, ncols = preview->parse_data->column_types->len,
+              max_str_len = preview->parse_data->file_str.end - preview->parse_data->file_str.begin;
+
+    /* store contains only strings. */
+    GType* types = g_new(GType, 2 * ncols);
+    for (i = 0; i < ncols; i++)
+        types[i] = G_TYPE_STRING;
+    store = gtk_list_store_newv(ncols, types);
+
+    /* ctstore is arranged as follows:
+     * model 0, text 0, model 1, text 1, ..., model ncols, text ncols. */
+    for (i = 0; i < 2 * ncols; i += 2)
+    {
+        types[i] = GTK_TYPE_TREE_MODEL;
+        types[i+1] = G_TYPE_STRING;
+    }
+    ctstore = gtk_list_store_newv(2 * ncols, types);
+
+    g_free(types);
+
+    /* Each element in cstores is a single column model. */
+    cstores = g_new(GtkListStore*, ncols);
+    for (i = 0; i < ncols; i++)
+    {
+        cstores[i] = gtk_list_store_new(1, G_TYPE_STRING);
+        /* Add all of the possible entries to the combo box. */
+        for (j = 0; j < GNC_CSV_NUM_COL_TYPES; j++)
+        {
+            gtk_list_store_append(cstores[i], &iter);
+            gtk_list_store_set(cstores[i], &iter, 0, _(gnc_csv_column_type_strs[j]), -1);
+        }
+    }
+
+    if (preview->not_empty)
+    {
+        GList *children, *children_begin;
+        GList *tv_columns, *tv_columns_begin, *ctv_columns, *ctv_columns_begin;
+        tv_columns = tv_columns_begin = gtk_tree_view_get_columns(preview->treeview);
+        ctv_columns = ctv_columns_begin = gtk_tree_view_get_columns(preview->ctreeview);
+        /* Clear out exisiting columns in preview->treeview. */
+        while (tv_columns != NULL)
+        {
+            gtk_tree_view_remove_column(preview->treeview, GTK_TREE_VIEW_COLUMN(tv_columns->data));
+            tv_columns = g_list_next(tv_columns);
+        }
+        /* Do the same in preview->ctreeview. */
+        while (ctv_columns != NULL)
+        {
+            gtk_tree_view_remove_column(preview->ctreeview, GTK_TREE_VIEW_COLUMN(ctv_columns->data));
+            ctv_columns = g_list_next(ctv_columns);
+        }
+        g_list_free(tv_columns_begin);
+        g_list_free(ctv_columns_begin);
+        g_free(preview->treeview_buttons);
+    }
+
+    /* Fill the data treeview with data from the file. */
+    /* Also, update the longest line value within the following loop (whichever is executed). */
+    preview->longest_line = 0;
+    if (preview->previewing_errors) /* If we are showing only errors ... */
+    {
+        /* ... only pick rows that are in preview->error_lines. */
+        GList* error_lines = preview->parse_data->error_lines;
+        while (error_lines != NULL)
+        {
+            int this_line_length = 0;
+            i = GPOINTER_TO_INT(error_lines->data);
+            gtk_list_store_append(store, &iter);
+            for (j = 0; j < ((GPtrArray*)(preview->parse_data->orig_lines->pdata[i]))->len; j++)
+            {
+                /* Add this cell's length to the row's length and set the value of the list store. */
+                gchar* cell_string = (gchar*)((GPtrArray*)(preview->parse_data->orig_lines->pdata[i]))->pdata[j];
+                this_line_length += g_utf8_strlen(cell_string, max_str_len);
+                gtk_list_store_set(store, &iter, j, cell_string, -1);
+            }
+
+            if (this_line_length > preview->longest_line)
+                preview->longest_line = this_line_length;
+
+            error_lines = g_list_next(error_lines);
+        }
+    }
+    else /* Otherwise, put in all of the data. */
+    {
+        for (i = 0; i < preview->parse_data->orig_lines->len; i++)
+        {
+            int this_line_length = 0;
+            gtk_list_store_append(store, &iter);
+            for (j = 0; j < ((GPtrArray*)(preview->parse_data->orig_lines->pdata[i]))->len; j++)
+            {
+                /* Add this cell's length to the row's length and set the value of the list store. */
+                gchar* cell_string = (gchar*)((GPtrArray*)(preview->parse_data->orig_lines->pdata[i]))->pdata[j];
+                this_line_length += g_utf8_strlen(cell_string, max_str_len);
+                gtk_list_store_set(store, &iter, j, cell_string, -1);
+            }
+
+            if (this_line_length > preview->longest_line)
+                preview->longest_line = this_line_length;
+        }
+    }
+
+    /* Set all the column types to what's in the parse data. */
+    gtk_list_store_append(ctstore, &iter);
+    for (i = 0; i < ncols; i++)
+    {
+        gtk_list_store_set(ctstore, &iter, 2 * i, cstores[i], 2 * i + 1,
+                           _(gnc_csv_column_type_strs[(int)(preview->parse_data->column_types->data[i])]),
+                           -1);
+    }
+
+    preview->treeview_buttons = g_new(GtkWidget*, ncols);
+    /* Insert columns into the data and column type treeviews. */
+    for (i = 0; i < ncols; i++)
+    {
+        GtkTreeViewColumn* col; /* The column we add to preview->treeview. */
+        /* Create renderers for the data treeview (renderer) and the
+         * column type treeview (crenderer). */
+        GtkCellRenderer* renderer = gtk_cell_renderer_text_new(),
+                         *crenderer = gtk_cell_renderer_combo_new();
+        /* We want a monospace font for the data in case of fixed-width data. */
+        g_object_set(G_OBJECT(renderer), "family", "monospace", NULL);
+        /* We are using cstores for the combo box entries, and we don't
+         * want the user to be able to manually enter their own column
+         * types. */
+        g_object_set(G_OBJECT(crenderer), "model", cstores[i], "text-column", 0,
+                     "editable", TRUE, "has-entry", FALSE, NULL);
+        g_signal_connect(G_OBJECT(crenderer), "changed",
+                         G_CALLBACK(column_type_changed), (gpointer)preview);
+
+        /* Add a single column for the treeview. */
+        col = gtk_tree_view_column_new_with_attributes("", renderer, "text", i, NULL);
+        gtk_tree_view_insert_column(preview->treeview, col, -1);
+        /* Enable resizing of the columns. */
+        gtk_tree_view_column_set_resizable(col, TRUE);
+        /* Use the alternating model and text entries from ctstore in
+         * preview->ctreeview. */
+        gtk_tree_view_insert_column_with_attributes(preview->ctreeview,
+                -1, "", crenderer, "model", 2 * i,
+                "text", 2 * i + 1, NULL);
+
+        /* We need to allow clicking on the column headers for fixed-width
+         * column splitting and merging. */
+        g_object_set(G_OBJECT(col), "clickable", TRUE, NULL);
+        g_signal_connect(G_OBJECT(col->button), "button_press_event",
+                         G_CALLBACK(header_button_press_handler), (gpointer)preview);
+        preview->treeview_buttons[i] = col->button;
+    }
+
+    /* Set the treeviews to use the models. */
+    gtk_tree_view_set_model(preview->treeview, GTK_TREE_MODEL(store));
+    gtk_tree_view_set_model(preview->ctreeview, GTK_TREE_MODEL(ctstore));
+
+    /* Free the memory for the stores. */
+    g_object_unref(GTK_TREE_MODEL(store));
+    g_object_unref(GTK_TREE_MODEL(ctstore));
+    for (i = 0; i < ncols; i++)
+        g_object_unref(GTK_TREE_MODEL(cstores[i]));
+
+    /* Make the things actually appear. */
+    gtk_widget_show_all(GTK_WIDGET(preview->treeview));
+    gtk_widget_show_all(GTK_WIDGET(preview->ctreeview));
+
+    /* Set the encoding selector to the right encoding. */
+    preview->code_encoding_calls = 2;
+    go_charmap_sel_set_encoding(preview->encselector, preview->parse_data->encoding);
+
+    /* Set the date format to what's in the combo box (since we don't
+     * necessarily know if this will always be the same). */
+    preview->parse_data->date_format = gtk_combo_box_get_active(preview->date_format_combo);
+
+    /* It's now been filled with some stuff. */
+    preview->not_empty = TRUE;
+}
+
+/** A function that lets the user preview a file's data. This function
+ * is used to let the user preview and configure the data parsed from
+ * the file. It doesn't return until the user clicks "OK" or "Cancel"
+ * on the dialog.
+ * @param preview The GUI for previewing the data
+ * @param parse_data The data we want to preview
+ * @return 0 if the user approved the import; 1 if the user didn't.
+ */
+static int gnc_csv_preview(GncCsvPreview* preview, GncCsvParseData* parse_data)
+{
+    /* Set the preview's parse_data to the one we're getting passed. */
+    preview->parse_data = parse_data;
+    preview->previewing_errors = FALSE; /* We're looking at all the data. */
+    preview->approved = FALSE; /* This is FALSE until the user clicks "OK". */
+
+    /* Load the data into the treeview. (This is the first time we've
+     * called gnc_csv_preview_update on this preview, so we use
+     * FALSE.) */
+    gnc_csv_preview_update(preview);
+    /* Wait until the user clicks "OK" or "Cancel". */
+    gtk_dialog_run(GTK_DIALOG(preview->dialog));
+
+    if (preview->approved)
+        return 0;
+    else
+        return 1;
+}
+
+/** A function that lets the user preview rows with errors. This
+ * function must only be called after calling gnc_csv_preview. It is
+ * essentially identical in behavior to gnc_csv_preview except that it
+ * displays lines with errors instead of all of the data.
+ * @param preview The GUI for previewing the data (and the data being previewed)
+ * @return 0 if the user approved of importing the lines; 1 if the user didn't.
+ */
+/* TODO Let the user manually edit cells' data? */
+static int gnc_csv_preview_errors(GncCsvPreview* preview)
+{
+    gchar* name;
+    GtkIconSize size;
+    GtkTreeViewColumn* last_col;
+
+    gtk_image_get_stock(preview->instructions_image, &name, &size);
+    gtk_image_set_from_stock(preview->instructions_image, GTK_STOCK_DIALOG_ERROR, size);
+    gtk_label_set_text(preview->instructions_label,
+                       _("The rows displayed below had errors. You can attempt to correct these errors by changing the configuration."));
+    gtk_widget_show(GTK_WIDGET(preview->instructions_image));
+    gtk_widget_show(GTK_WIDGET(preview->instructions_label));
+
+    preview->previewing_errors = TRUE;
+    preview->approved = FALSE; /* This is FALSE until the user clicks "OK". */
+
+    /* Wait until the user clicks "OK" or "Cancel". */
+    gnc_csv_preview_update(preview);
+
+    /* Set the last column to have the header "Errors" so that the user
+     * doesn't find the extra column confusing. */
+    last_col = gtk_tree_view_get_column(preview->treeview,
+                                        preview->parse_data->column_types->len - 1);
+    gtk_tree_view_column_set_title(last_col, _("Errors"));
+
+    gtk_dialog_run(GTK_DIALOG(preview->dialog));
+
+    if (preview->approved)
+        return 0;
+    else
+        return 1;
+}
+
+/** Lets the user import a CSV/Fixed-Width file. */
+void gnc_file_csv_import(void)
+{
+    /* The name of the file the user selected. */
+    char* selected_filename;
+    /* The default directory for the user to select files. */
+    char* default_dir = gnc_get_default_directory(GCONF_SECTION);
+    /* The generic GUI for importing transactions. */
+    GNCImportMainMatcher* gnc_csv_importer_gui = NULL;
+
+    /* Let the user select a file. */
+    selected_filename = gnc_file_dialog(_("Select an CSV/Fixed-Width file to import"),
+                                        NULL, default_dir, GNC_FILE_DIALOG_IMPORT);
+    g_free(default_dir); /* We don't need default_dir anymore. */
+
+    /* If the user actually selected a file ... */
+    if (selected_filename != NULL)
+    {
+        int i, user_canceled = 0;
+        Account* account; /* The account the user will select */
+        GError* error = NULL;
+        GList* transactions; /* A list of the transactions we create */
+        GncCsvParseData* parse_data;
+        GncCsvPreview* preview;
+
+        /* Remember the directory of the selected file as the default. */
+        default_dir = g_path_get_dirname(selected_filename);
+        gnc_set_default_directory(GCONF_SECTION, default_dir);
+        g_free(default_dir);
+
+        /* Load the file into parse_data. */
+        parse_data = gnc_csv_new_parse_data();
+        if (gnc_csv_load_file(parse_data, selected_filename, &error))
+        {
+            /* If we couldn't load the file ... */
+            gnc_error_dialog(NULL, "%s", error->message);
+            if (error->code == GNC_CSV_FILE_OPEN_ERR)
+            {
+                gnc_csv_parse_data_free(parse_data);
+                g_free(selected_filename);
+                return;
+            }
+            /* If we couldn't guess the encoding, we are content with just
+             * displaying an error message and move on with a blank
+             * display. */
+        }
+        /* Parse the data. */
+        if (gnc_csv_parse(parse_data, TRUE, &error))
+        {
+            /* If we couldn't parse the data ... */
+            gnc_error_dialog(NULL, "%s", error->message);
+        }
+
+        /* Preview the data. */
+        preview = gnc_csv_preview_new();
+        if (gnc_csv_preview(preview, parse_data))
+        {
+            /* If the user clicked "Cancel", free everything and quit. */
+            gnc_csv_preview_free(preview);
+            gnc_csv_parse_data_free(parse_data);
+            g_free(selected_filename);
+            return;
+        }
+
+        /* Let the user select an account to put the transactions in. */
+        account = gnc_import_select_account(NULL, NULL, 1, NULL, NULL, 0, NULL, NULL);
+        if (account == NULL) /* Quit if the user canceled. */
+        {
+            gnc_csv_preview_free(preview);
+            gnc_csv_parse_data_free(parse_data);
+            g_free(selected_filename);
+            return;
+        }
+
+        /* Create transactions from the parsed data. */
+        gnc_csv_parse_to_trans(parse_data, account, FALSE);
+
+        /* If there are errors, let the user try and eliminate them by
+         * previewing them. Repeat until either there are no errors or the
+         * user gives up. */
+        while (!((parse_data->error_lines == NULL) || user_canceled))
+        {
+            user_canceled = gnc_csv_preview_errors(preview);
+            gnc_csv_parse_to_trans(parse_data, account, TRUE);
+        }
+
+        /* Create the genereic transaction importer GUI. */
+        gnc_csv_importer_gui = gnc_gen_trans_list_new(NULL, NULL, FALSE, 42);
+
+        /* Get the list of the transactions that were created. */
+        transactions = parse_data->transactions;
+        /* Copy all of the transactions to the importer GUI. */
+        while (transactions != NULL)
+        {
+            GncCsvTransLine* trans_line = transactions->data;
+            gnc_gen_trans_list_add_trans(gnc_csv_importer_gui,
+                                         trans_line->trans);
+            transactions = g_list_next(transactions);
+        }
+        /* Let the user load those transactions into the account, so long
+         * as there is at least one transaction to be loaded. */
+        if (parse_data->transactions != NULL)
+            gnc_gen_trans_list_run(gnc_csv_importer_gui);
+        else
+            gnc_gen_trans_list_delete(gnc_csv_importer_gui);
+
+        /* Free the memory we allocated. */
+        gnc_csv_preview_free(preview);
+        gnc_csv_parse_data_free(parse_data);
+        g_free(selected_filename);
+    }
+}


Property changes on: gnucash/trunk/src/import-export/csv-import/gnc-csv-import.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Copied: gnucash/trunk/src/import-export/csv-import/gnc-csv-import.glade (from rev 22085, gnucash/trunk/src/import-export/csv/gnc-csv-import.glade)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gnc-csv-import.glade	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gnc-csv-import.glade	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,583 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkDialog" id="preview-dialog">
+    <property name="can_focus">False</property>
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Import CSV/Fixed-Width File</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox3">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area3">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancel_button">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="ok_button">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <object class="GtkTable" id="enctable">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="n_rows">4</property>
+                <property name="n_columns">2</property>
+                <child>
+                  <object class="GtkHSeparator" id="hseparator1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">3</property>
+                    <property name="bottom_attach">4</property>
+                    <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                    <property name="y_padding">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHSeparator" id="hseparator2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">3</property>
+                    <property name="bottom_attach">4</property>
+                    <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                    <property name="y_padding">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHBox" id="hbox1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <child>
+                      <object class="GtkRadioButton" id="csv_button">
+                        <property name="label" translatable="yes">Separated</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="active">True</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton2">
+                        <property name="label" translatable="yes">Fixed-Width</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">csv_button</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label" translatable="yes">Data type: </property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHSeparator" id="hseparator4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHSeparator" id="hseparator5">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                    <property name="y_padding">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label" translatable="yes">Encoding: </property>
+                  </object>
+                  <packing>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="frame1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <object class="GtkTable" id="table1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="n_rows">3</property>
+                        <property name="n_columns">3</property>
+                        <property name="column_spacing">3</property>
+                        <property name="row_spacing">3</property>
+                        <child>
+                          <object class="GtkCheckButton" id="space_cbutton">
+                            <property name="label" translatable="yes">Space</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="tab_cbutton">
+                            <property name="label" translatable="yes">Tab</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="comma_cbutton">
+                            <property name="label" translatable="yes">Comma (,)</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="active">True</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">2</property>
+                            <property name="right_attach">3</property>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="colon_cbutton">
+                            <property name="label" translatable="yes">Colon (:)</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="semicolon_cbutton">
+                            <property name="label" translatable="yes">Semicolon (;)</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="hyphen_cbutton">
+                            <property name="label" translatable="yes">Hyphen (-)</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">2</property>
+                            <property name="right_attach">3</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="custom_cbutton">
+                            <property name="label" translatable="yes">Custom</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="use_action_appearance">False</property>
+                            <property name="draw_indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="custom_entry">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="invisible_char">&#x25CF;</property>
+                            <property name="invisible_char_set">True</property>
+                            <property name="primary_icon_activatable">False</property>
+                            <property name="secondary_icon_activatable">False</property>
+                            <property name="primary_icon_sensitive">True</property>
+                            <property name="secondary_icon_sensitive">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">3</property>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label5">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label" translatable="yes">Separators</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkHBox" id="hbox2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkHSeparator" id="hseparator6">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="padding">3</property>
+                <property name="position">4</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="frame2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkAlignment" id="date_format_container">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label" translatable="yes">Date Format</property>
+                    <property name="use_markup">True</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">5</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkHSeparator" id="hseparator3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="padding">3</property>
+                <property name="position">6</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkHBox" id="hbox3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <child>
+                  <object class="GtkImage" id="instructions_image">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="stock">gtk-dialog-info</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="padding">2</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="instructions_label">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Select the type of each column below.</property>
+                    <property name="wrap">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">7</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkTreeView" id="ctreeview">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="headers_visible">False</property>
+                <property name="enable_grid_lines">both</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">8</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow" id="scrolledwindow1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="hscrollbar_policy">automatic</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <child>
+                  <object class="GtkViewport" id="viewport1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="resize_mode">queue</property>
+                    <child>
+                      <object class="GtkTreeView" id="treeview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="enable_grid_lines">both</property>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">9</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">cancel_button</action-widget>
+      <action-widget response="0">ok_button</action-widget>
+    </action-widgets>
+  </object>
+</interface>

Copied: gnucash/trunk/src/import-export/csv-import/gnc-csv-import.h (from rev 22085, gnucash/trunk/src/import-export/csv/gnc-csv-import.h)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gnc-csv-import.h	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gnc-csv-import.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,33 @@
+/********************************************************************\
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+/** @file
+    @brief CSV import GUI
+    *
+    gnc-csv-import.h
+    @author Copyright (c) 2007 Benny Sperisen <lasindi at gmail.com>
+*/
+#ifndef CSV_IMPORT_H
+#define CSV_IMPORT_H
+
+/** The gnc_file_csv_import() will let the user select a
+ * CSV/Fixed-Width file to open, select an account to import it to,
+ * and import the transactions into the account. It also allows the
+ * user to configure how the file is parsed. */
+void              gnc_file_csv_import (void);
+#endif


Property changes on: gnucash/trunk/src/import-export/csv-import/gnc-csv-import.h
___________________________________________________________________
Added: svn:eol-style
   + LF

Copied: gnucash/trunk/src/import-export/csv-import/gnc-csv-model.c (from rev 22085, gnucash/trunk/src/import-export/csv/gnc-csv-model.c)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gnc-csv-model.c	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gnc-csv-model.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,1249 @@
+#include "gnc-csv-model.h"
+
+
+#include <glib/gi18n.h>
+
+#include <goffice/goffice-features.h>
+#if (GO_VERSION_EPOCH == 0) && (GO_VERSION_MAJOR == 7) && (GO_VERSION_MINOR == 8)
+/* For libgoffice-0.7.8, disable its internal inclusion of <regutf8.h>
+   so to avoid clashing symbol definitions with <regex.h> */
+# define GO_REGUTF8_H
+#endif
+#include <goffice/utils/go-glib-extras.h>
+
+#include "gnc-ui-util.h"
+
+#include <string.h>
+#include <sys/time.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <regex.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+#ifndef HAVE_LOCALTIME_R
+#include "localtime_r.h"
+#endif
+
+static QofLogModule log_module = GNC_MOD_IMPORT;
+
+const int num_date_formats = 5;
+const gchar* date_format_user[] = {N_("y-m-d"),
+                                   N_("d-m-y"),
+                                   N_("m-d-y"),
+                                   N_("d-m"),
+                                   N_("m-d")
+                                  };
+
+const int num_currency_formats = 3;
+const gchar* currency_format_user[] = {N_("Locale"),
+                                   N_("Period: 123,456.78"),
+                                   N_("Comma: 123.456,78")
+                                  };
+
+/* This array contains all of the different strings for different column types. */
+gchar* gnc_csv_column_type_strs[GNC_CSV_NUM_COL_TYPES] = {N_("None"),
+        N_("Date"),
+        N_("Description"),
+        N_("Account"),
+        N_("Balance"),
+        N_("Deposit"),
+        N_("Withdrawal"),
+        N_("Num")
+                                                         };
+
+/** A set of sensible defaults for parsing CSV files.
+ * @return StfParseOptions_t* for parsing a file with comma separators
+ */
+static StfParseOptions_t* default_parse_options(void)
+{
+    StfParseOptions_t* options = stf_parse_options_new();
+    stf_parse_options_set_type(options, PARSE_TYPE_CSV);
+    stf_parse_options_csv_set_separators(options, ",", NULL);
+    return options;
+}
+
+/** Parses a string into a date, given a format. The format must
+ * include the year. This function should only be called by
+ * parse_date.
+ * @param date_str The string containing a date being parsed
+ * @param format An index specifying a format in date_format_user
+ * @return The parsed value of date_str on success or -1 on failure
+ */
+static time_t parse_date_with_year(const char* date_str, int format)
+{
+    time_t rawtime; /* The integer time */
+    struct tm retvalue, test_retvalue; /* The time in a broken-down structure */
+
+    int i, j, mem_length, orig_year = -1, orig_month = -1, orig_day = -1;
+
+    /* Buffer for containing individual parts (e.g. year, month, day) of a date */
+    char date_segment[5];
+
+    /* The compiled regular expression */
+    regex_t preg = {0};
+
+    /* An array containing indices specifying the matched substrings in date_str */
+    regmatch_t pmatch[4] = { {0}, {0}, {0}, {0} };
+
+    /* The regular expression for parsing dates */
+    const char* regex = "^ *([0-9]+) *[-/.'] *([0-9]+) *[-/.'] *([0-9]+).*$|^ *([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]).*$";
+
+    /* We get our matches using the regular expression. */
+    regcomp(&preg, regex, REG_EXTENDED);
+    regexec(&preg, date_str, 4, pmatch, 0);
+    regfree(&preg);
+
+    /* If there wasn't a match, there was an error. */
+    if (pmatch[0].rm_eo == 0)
+        return -1;
+
+    /* If this is a string without separators ... */
+    if (pmatch[1].rm_so == -1)
+    {
+        /* ... we will fill in the indices based on the user's selection. */
+        int k = 0; /* k traverses date_str by keeping track of where separators "should" be. */
+        j = 1; /* j traverses pmatch. */
+        for (i = 0; date_format_user[format][i]; i++)
+        {
+            char segment_type = date_format_user[format][i];
+            /* Only do something if this is a meaningful character */
+            if (segment_type == 'y' || segment_type == 'm' || segment_type == 'd')
+            {
+                pmatch[j].rm_so = k;
+                switch (segment_type)
+                {
+                case 'm':
+                case 'd':
+                    k += 2;
+                    break;
+
+                case 'y':
+                    k += 4;
+                    break;
+                }
+
+                pmatch[j].rm_eo = k;
+                j++;
+            }
+        }
+    }
+
+    /* Put some sane values in retvalue by using the current time for
+     * the non-year-month-day parts of the date. */
+    time(&rawtime);
+    localtime_r(&rawtime, &retvalue);
+
+    /* j traverses pmatch (index 0 contains the entire string, so we
+     * start at index 1 for the first meaningful match). */
+    j = 1;
+    /* Go through the date format and interpret the matches in order of
+     * the sections in the date format. */
+    for (i = 0; date_format_user[format][i]; i++)
+    {
+        char segment_type = date_format_user[format][i];
+        /* Only do something if this is a meaningful character */
+        if (segment_type == 'y' || segment_type == 'm' || segment_type == 'd')
+        {
+            /* Copy the matching substring into date_segment so that we can
+             * convert it into an integer. */
+            mem_length = pmatch[j].rm_eo - pmatch[j].rm_so;
+            memcpy(date_segment, date_str + pmatch[j].rm_so, mem_length);
+            date_segment[mem_length] = '\0';
+
+            /* Set the appropriate member of retvalue. Save the original
+             * values so that we can check if the change when we use mktime
+             * below. */
+            switch (segment_type)
+            {
+            case 'y':
+                retvalue.tm_year = atoi(date_segment);
+
+                /* Handle two-digit years. */
+                if (retvalue.tm_year < 100)
+                {
+                    /* We allow two-digit years in the range 1969 - 2068. */
+                    if (retvalue.tm_year < 69)
+                        retvalue.tm_year += 100;
+                }
+                else
+                    retvalue.tm_year -= 1900;
+                orig_year = retvalue.tm_year;
+                break;
+
+            case 'm':
+                orig_month = retvalue.tm_mon = atoi(date_segment) - 1;
+                break;
+
+            case 'd':
+                orig_day = retvalue.tm_mday = atoi(date_segment);
+                break;
+            }
+            j++;
+        }
+    }
+    /* Convert back to an integer. If mktime leaves retvalue unchanged,
+     * everything is okay; otherwise, an error has occurred. */
+    /* We have to use a "test" date value to account for changes in
+     * daylight savings time, which can cause a date change with mktime
+     * near midnight, causing the code to incorrectly think a date is
+     * incorrect. */
+    test_retvalue = retvalue;
+    mktime(&test_retvalue);
+    retvalue.tm_isdst = test_retvalue.tm_isdst;
+    rawtime = mktime(&retvalue);
+    if (retvalue.tm_mday == orig_day &&
+    retvalue.tm_mon == orig_month &&
+    retvalue.tm_year == orig_year)
+    {
+        return rawtime;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+/** Parses a string into a date, given a format. The format cannot
+ * include the year. This function should only be called by
+ * parse_date.
+ * @param date_str The string containing a date being parsed
+ * @param format An index specifying a format in date_format_user
+ * @return The parsed value of date_str on success or -1 on failure
+ */
+static time_t parse_date_without_year(const char* date_str, int format)
+{
+    time_t rawtime; /* The integer time */
+    struct tm retvalue, test_retvalue; /* The time in a broken-down structure */
+
+    int i, j, mem_length, orig_year = -1, orig_month = -1, orig_day = -1;
+
+    /* Buffer for containing individual parts (e.g. year, month, day) of a date */
+    gchar* date_segment;
+
+    /* The compiled regular expression */
+    regex_t preg = {0};
+
+    /* An array containing indices specifying the matched substrings in date_str */
+    regmatch_t pmatch[3] = { {0}, {0}, {0} };
+
+    /* The regular expression for parsing dates */
+    const char* regex = "^ *([0-9]+) *[-/.'] *([0-9]+).*$";
+
+    /* We get our matches using the regular expression. */
+    regcomp(&preg, regex, REG_EXTENDED);
+    regexec(&preg, date_str, 3, pmatch, 0);
+    regfree(&preg);
+
+    /* If there wasn't a match, there was an error. */
+    if (pmatch[0].rm_eo == 0)
+        return -1;
+
+    /* Put some sane values in retvalue by using the current time for
+     * the non-year-month-day parts of the date. */
+    time(&rawtime);
+    localtime_r(&rawtime, &retvalue);
+    orig_year = retvalue.tm_year;
+
+    /* j traverses pmatch (index 0 contains the entire string, so we
+     * start at index 1 for the first meaningful match). */
+    j = 1;
+    /* Go through the date format and interpret the matches in order of
+     * the sections in the date format. */
+    for (i = 0; date_format_user[format][i]; i++)
+    {
+        char segment_type = date_format_user[format][i];
+        /* Only do something if this is a meaningful character */
+        if (segment_type == 'm' || segment_type == 'd')
+        {
+            /* Copy the matching substring into date_segment so that we can
+             * convert it into an integer. */
+            mem_length = pmatch[j].rm_eo - pmatch[j].rm_so;
+            date_segment = g_new(gchar, mem_length);
+            memcpy(date_segment, date_str + pmatch[j].rm_so, mem_length);
+            date_segment[mem_length] = '\0';
+
+            /* Set the appropriate member of retvalue. Save the original
+             * values so that we can check if the change when we use mktime
+             * below. */
+            switch (segment_type)
+            {
+            case 'm':
+                orig_month = retvalue.tm_mon = atoi(date_segment) - 1;
+                break;
+
+            case 'd':
+                orig_day = retvalue.tm_mday = atoi(date_segment);
+                break;
+            }
+            g_free(date_segment);
+            j++;
+        }
+    }
+    /* Convert back to an integer. If mktime leaves retvalue unchanged,
+     * everything is okay; otherwise, an error has occurred. */
+    /* We have to use a "test" date value to account for changes in
+     * daylight savings time, which can cause a date change with mktime
+     * near midnight, causing the code to incorrectly think a date is
+     * incorrect. */
+    test_retvalue = retvalue;
+    mktime(&test_retvalue);
+    retvalue.tm_isdst = test_retvalue.tm_isdst;
+    rawtime = mktime(&retvalue);
+    if (retvalue.tm_mday == orig_day &&
+    retvalue.tm_mon == orig_month &&
+    retvalue.tm_year == orig_year)
+    {
+        return rawtime;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+/** Parses a string into a date, given a format. This function
+ * requires only knowing the order in which the year, month and day
+ * appear. For example, 01-02-2003 will be parsed the same way as
+ * 01/02/2003.
+ * @param date_str The string containing a date being parsed
+ * @param format An index specifying a format in date_format_user
+ * @return The parsed value of date_str on success or -1 on failure
+ */
+time_t parse_date(const char* date_str, int format)
+{
+    if (strchr(date_format_user[format], 'y'))
+        return parse_date_with_year(date_str, format);
+    else
+        return parse_date_without_year(date_str, format);
+}
+
+/** Constructor for GncCsvParseData.
+ * @return Pointer to a new GncCSvParseData
+ */
+GncCsvParseData* gnc_csv_new_parse_data(void)
+{
+    GncCsvParseData* parse_data = g_new(GncCsvParseData, 1);
+    parse_data->encoding = "UTF-8";
+    /* All of the data pointers are initially NULL. This is so that, if
+     * gnc_csv_parse_data_free is called before all of the data is
+     * initialized, only the data that needs to be freed is freed. */
+    parse_data->raw_str.begin = parse_data->raw_str.end
+    = parse_data->file_str.begin = parse_data->file_str.end = NULL;
+    parse_data->orig_lines = NULL;
+    parse_data->orig_row_lengths = NULL;
+    parse_data->column_types = NULL;
+    parse_data->error_lines = parse_data->transactions = NULL;
+    parse_data->options = default_parse_options();
+    parse_data->date_format = -1;
+    parse_data->currency_format = 0;
+    parse_data->chunk = g_string_chunk_new(100 * 1024);
+    parse_data->start_row = 0;
+    parse_data->end_row = 1000;
+    return parse_data;
+}
+
+/** Destructor for GncCsvParseData.
+ * @param parse_data Parse data whose memory will be freed
+ */
+void gnc_csv_parse_data_free(GncCsvParseData* parse_data)
+{
+    /* All non-NULL pointers have been initialized and must be freed. */
+
+    if (parse_data->raw_mapping != NULL)
+        g_mapped_file_free(parse_data->raw_mapping);
+
+    if (parse_data->file_str.begin != NULL)
+        g_free(parse_data->file_str.begin);
+
+    if (parse_data->orig_lines != NULL)
+        stf_parse_general_free(parse_data->orig_lines);
+
+    if (parse_data->orig_row_lengths != NULL)
+        g_array_free(parse_data->orig_row_lengths, FALSE);
+
+    if (parse_data->options != NULL)
+        stf_parse_options_free(parse_data->options);
+
+    if (parse_data->column_types != NULL)
+        g_array_free(parse_data->column_types, TRUE);
+
+    if (parse_data->error_lines != NULL)
+        g_list_free(parse_data->error_lines);
+
+    if (parse_data->transactions != NULL)
+    {
+        GList* transactions = parse_data->transactions;
+        /* We have to free the GncCsvTransLine's that are at each node in
+         * the list before freeing the entire list. */
+        do
+        {
+            g_free(transactions->data);
+            transactions = g_list_next(transactions);
+        }
+        while (transactions != NULL);
+        g_list_free(parse_data->transactions);
+    }
+
+    g_free(parse_data->chunk);
+    g_free(parse_data);
+}
+
+/** Converts raw file data using a new encoding. This function must be
+ * called after gnc_csv_load_file only if gnc_csv_load_file guessed
+ * the wrong encoding.
+ * @param parse_data Data that is being parsed
+ * @param encoding Encoding that data should be translated using
+ * @param error Will point to an error on failure
+ * @return 0 on success, 1 on failure
+ */
+int gnc_csv_convert_encoding(GncCsvParseData* parse_data, const char* encoding,
+GError** error)
+{
+    gsize bytes_read, bytes_written;
+
+    /* If parse_data->file_str has already been initialized it must be
+     * freed first. (This should always be the case, since
+     * gnc_csv_load_file should always be called before this
+     * function.) */
+    if (parse_data->file_str.begin != NULL)
+        g_free(parse_data->file_str.begin);
+
+    /* Do the actual translation to UTF-8. */
+    parse_data->file_str.begin = g_convert(parse_data->raw_str.begin,
+    parse_data->raw_str.end - parse_data->raw_str.begin,
+    "UTF-8", encoding, &bytes_read, &bytes_written,
+    error);
+    /* Handle errors that occur. */
+    if (parse_data->file_str.begin == NULL)
+        return 1;
+
+    /* On success, save the ending pointer of the translated data and
+     * the encoding type and return 0. */
+    parse_data->file_str.end = parse_data->file_str.begin + bytes_written;
+    parse_data->encoding = (gchar*)encoding;
+    return 0;
+}
+
+/** Loads a file into a GncCsvParseData. This is the first function
+ * that must be called after createing a new GncCsvParseData. If this
+ * fails because the file couldn't be opened, no more functions can be
+ * called on the parse data until this succeeds (or until it fails
+ * because of an encoding guess error). If it fails because the
+ * encoding could not be guessed, gnc_csv_convert_encoding must be
+ * called until it succeeds.
+ * @param parse_data Data that is being parsed
+ * @param filename Name of the file that should be opened
+ * @param error Will contain an error if there is a failure
+ * @return 0 on success, 1 on failure
+ */
+int gnc_csv_load_file(GncCsvParseData* parse_data, const char* filename,
+GError** error)
+{
+    const char* guess_enc = NULL;
+
+    /* Get the raw data first and handle an error if one occurs. */
+    parse_data->raw_mapping = g_mapped_file_new(filename, FALSE, error);
+    if (parse_data->raw_mapping == NULL)
+    {
+        /* TODO Handle file opening errors more specifically,
+         * e.g. inexistent file versus no read permission. */
+        parse_data->raw_str.begin = NULL;
+        g_clear_error (error);
+        g_set_error(error, 0, GNC_CSV_FILE_OPEN_ERR, "%s", _("File opening failed."));
+        return 1;
+    }
+
+    /* Copy the mapping's contents into parse-data->raw_str. */
+    parse_data->raw_str.begin = g_mapped_file_get_contents(parse_data->raw_mapping);
+    parse_data->raw_str.end = parse_data->raw_str.begin + g_mapped_file_get_length(parse_data->raw_mapping);
+
+    /* Make a guess at the encoding of the data. */
+    if(!g_mapped_file_get_length(parse_data->raw_mapping) == 0)
+        guess_enc = go_guess_encoding((const char*)(parse_data->raw_str.begin),
+        (size_t)(parse_data->raw_str.end - parse_data->raw_str.begin),
+        "UTF-8", NULL);
+    if (guess_enc == NULL)
+    {
+        g_set_error(error, 0, GNC_CSV_ENCODING_ERR, "%s", _("Unknown encoding."));
+        return 1;
+    }
+    /* Convert using the guessed encoding into parse_data->file_str and
+     * handle any errors that occur. */
+    gnc_csv_convert_encoding(parse_data, guess_enc, error);
+    if (parse_data->file_str.begin == NULL)
+    {
+        g_set_error(error, 0, GNC_CSV_ENCODING_ERR, "%s", _("Unknown encoding."));
+        return 1;
+    }
+    else
+        return 0;
+}
+
+/** Parses a file into cells. This requires having an encoding that
+ * works (see gnc_csv_convert_encoding). parse_data->options should be
+ * set according to how the user wants before calling this
+ * function. (Note: this function must be called with guessColTypes as
+ * TRUE before it is ever called with it as FALSE.) (Note: if
+ * guessColTypes is TRUE, all the column types will be GNC_CSV_NONE
+ * right now.)
+ * @param parse_data Data that is being parsed
+ * @param guessColTypes TRUE to guess what the types of columns are based on the cell contents
+ * @param error Will contain an error if there is a failure
+ * @return 0 on success, 1 on failure
+ */
+int gnc_csv_parse(GncCsvParseData* parse_data, gboolean guessColTypes, GError** error)
+{
+    /* max_cols is the number of columns in the row with the most columns. */
+    int i, max_cols = 0;
+
+    if (parse_data->orig_lines != NULL)
+    {
+        stf_parse_general_free(parse_data->orig_lines);
+    }
+
+    /* If everything is fine ... */
+    if (parse_data->file_str.begin != NULL)
+    {
+        /* Do the actual parsing. */
+        parse_data->orig_lines = stf_parse_general(parse_data->options, parse_data->chunk,
+        parse_data->file_str.begin,
+        parse_data->file_str.end);
+    }
+    /* If we couldn't get the encoding right, we just want an empty array. */
+    else
+    {
+        parse_data->orig_lines = g_ptr_array_new();
+    }
+
+    /* Record the original row lengths of parse_data->orig_lines. */
+    if (parse_data->orig_row_lengths != NULL)
+        g_array_free(parse_data->orig_row_lengths, FALSE);
+
+    parse_data->orig_row_lengths =
+        g_array_sized_new(FALSE, FALSE, sizeof(int), parse_data->orig_lines->len);
+
+    g_array_set_size(parse_data->orig_row_lengths, parse_data->orig_lines->len);
+    parse_data->orig_max_row = 0;
+    for (i = 0; i < parse_data->orig_lines->len; i++)
+    {
+        int length = ((GPtrArray*)parse_data->orig_lines->pdata[i])->len;
+        parse_data->orig_row_lengths->data[i] = length;
+        if (length > parse_data->orig_max_row)
+            parse_data->orig_max_row = length;
+    }
+
+    /* If it failed, generate an error. */
+    if (parse_data->orig_lines == NULL)
+    {
+        g_set_error(error, 0, 0, "Parsing failed.");
+        return 1;
+    }
+
+    /* Now that we have data, let's set max_cols. */
+    for (i = 0; i < parse_data->orig_lines->len; i++)
+    {
+        if (max_cols < ((GPtrArray*)(parse_data->orig_lines->pdata[i]))->len)
+            max_cols = ((GPtrArray*)(parse_data->orig_lines->pdata[i]))->len;
+    }
+
+    if (guessColTypes)
+    {
+        /* Free parse_data->column_types if it's already been created. */
+        if (parse_data->column_types != NULL)
+            g_array_free(parse_data->column_types, TRUE);
+
+        /* Create parse_data->column_types and fill it with guesses based
+         * on the contents of each column. */
+        parse_data->column_types = g_array_sized_new(FALSE, FALSE, sizeof(int),
+        max_cols);
+        g_array_set_size(parse_data->column_types, max_cols);
+        /* TODO Make it actually guess. */
+        for (i = 0; i < parse_data->column_types->len; i++)
+        {
+            parse_data->column_types->data[i] = GNC_CSV_NONE;
+        }
+    }
+    else
+    {
+        /* If we don't need to guess column types, we will simply set any
+         * new columns that are created that didn't exist before to "None"
+         * since we don't want gibberish to appear. Note:
+         * parse_data->column_types should have already been
+         * initialized, so we don't check for it being NULL. */
+        int i = parse_data->column_types->len;
+        g_array_set_size(parse_data->column_types, max_cols);
+        for (; i < parse_data->column_types->len; i++)
+        {
+            parse_data->column_types->data[i] = GNC_CSV_NONE;
+        }
+    }
+
+    return 0;
+}
+
+/** A struct containing TransProperties that all describe a single transaction. */
+typedef struct
+{
+    int date_format; /**< The format for parsing dates */
+    int currency_format; /**< The format for currency */
+    Account* account; /**< The account the transaction belongs to */
+    GList* properties; /**< List of TransProperties */
+} TransPropertyList;
+
+/** A struct encapsulating a property of a transaction. */
+typedef struct
+{
+    int type; /**< A value from the GncCsvColumnType enum except
+             * GNC_CSV_NONE and GNC_CSV_NUM_COL_TYPES */
+    void* value; /**< Pointer to the data that will be used to configure a transaction */
+    TransPropertyList* list; /**< The list the property belongs to */
+} TransProperty;
+
+/** Constructor for TransProperty.
+ * @param type The type of the new property (see TransProperty.type for possible values)
+ */
+static TransProperty* trans_property_new(int type, TransPropertyList* list)
+{
+    TransProperty* prop = g_new(TransProperty, 1);
+    prop->type = type;
+    prop->list = list;
+    prop->value = NULL;
+    return prop;
+}
+
+/** Destructor for TransProperty.
+ * @param prop The property to be freed
+ */
+static void trans_property_free(TransProperty* prop)
+{
+    switch (prop->type)
+    {
+        /* The types for "Date" and "Balance" (time_t and gnc_numeric,
+         * respectively) are typically not pointed to, we have to free
+         * them, unlike types like char* ("Description"). */
+    case GNC_CSV_DATE:
+    case GNC_CSV_BALANCE:
+    case GNC_CSV_DEPOSIT:
+    case GNC_CSV_WITHDRAWAL:
+        if (prop->value != NULL)
+            g_free(prop->value);
+        break;
+    }
+    g_free(prop);
+}
+
+/** Sets the value of the property by parsing str. Note: this should
+ * only be called once on an instance of TransProperty, as calling it
+ * more than once can cause memory leaks.
+ * @param prop The property being set
+ * @param str The string to be parsed
+ * @return TRUE on success, FALSE on failure
+ */
+static gboolean trans_property_set(TransProperty* prop, char* str)
+{
+    char *endptr, *possible_currency_symbol, *str_dupe;
+    gnc_numeric val;
+    switch (prop->type)
+    {
+    case GNC_CSV_DATE:
+        prop->value = g_new(time_t, 1);
+        *((time_t*)(prop->value)) = parse_date(str, prop->list->date_format);
+        return *((time_t*)(prop->value)) != -1;
+
+    case GNC_CSV_DESCRIPTION:
+    case GNC_CSV_NUM:
+        prop->value = g_strdup(str);
+        return TRUE;
+
+    case GNC_CSV_BALANCE:
+    case GNC_CSV_DEPOSIT:
+    case GNC_CSV_WITHDRAWAL:
+        str_dupe = g_strdup(str); /* First, we make a copy so we can't mess up real data. */
+
+        /* Go through str_dupe looking for currency symbols. */
+        for (possible_currency_symbol = str_dupe; *possible_currency_symbol;
+        possible_currency_symbol = g_utf8_next_char(possible_currency_symbol))
+        {
+            if (g_unichar_type(g_utf8_get_char(possible_currency_symbol)) == G_UNICODE_CURRENCY_SYMBOL)
+            {
+                /* If we find a currency symbol, save the position just ahead
+                 * of the currency symbol (next_symbol), and find the null
+                 * terminator of the string (last_symbol). */
+                char *next_symbol = g_utf8_next_char(possible_currency_symbol), *last_symbol = next_symbol;
+                while (*last_symbol)
+                    last_symbol = g_utf8_next_char(last_symbol);
+
+                /* Move all of the string (including the null byte, which is
+                 * why we have +1 in the size parameter) following the
+                 * currency symbol back one character, thereby overwriting the
+                 * currency symbol. */
+                memmove(possible_currency_symbol, next_symbol, last_symbol - next_symbol + 1);
+                break;
+            }
+        }
+
+        /* Currency format */
+        switch (prop->list->currency_format)
+        {
+        case 0:
+            /* Currancy locale */
+            if(!(xaccParseAmount(str_dupe, TRUE, &val, &endptr)))
+            {
+                g_free(str_dupe);
+                return FALSE;
+            }
+            break;
+        case 1:
+            /* Currancy decimal period */
+            if(!(xaccParseAmountExtended(str_dupe, TRUE, '-', '.', ',', "\003\003", "$+", &val, &endptr)))
+            {
+                g_free(str_dupe);
+                return FALSE;
+            }
+            break;
+        case 2:
+            /* Currancy decimal comma */
+            if(!(xaccParseAmountExtended(str_dupe, TRUE, '-', ',', '.', "\003\003", "$+", &val, &endptr)))
+            {
+                g_free(str_dupe);
+                return FALSE;
+            }
+            break;
+        }
+
+        prop->value = g_new(gnc_numeric, 1);
+        *((gnc_numeric*)(prop->value)) = val;
+        g_free(str_dupe);
+        return TRUE;
+
+    }
+    return FALSE; /* We should never actually get here. */
+}
+
+/** Constructor for TransPropertyList.
+ * @param account The account with which transactions should be built
+ * @param date_format An index from date_format_user for how date properties should be parsed
+ * @return A pointer to a new TransPropertyList
+ */
+static TransPropertyList* trans_property_list_new(Account* account, int date_format, int currency_format)
+{
+    TransPropertyList* list = g_new(TransPropertyList, 1);
+    list->account = account;
+    list->date_format = date_format;
+    list->currency_format = currency_format;
+    list->properties = NULL;
+    return list;
+}
+
+/** Destructor for TransPropertyList.
+ * @param list The list to be freed
+ */
+static void trans_property_list_free(TransPropertyList* list)
+{
+    /* Free all of the properties in this list before freeeing the list itself. */
+    GList* properties_begin = list->properties;
+    while (list->properties != NULL)
+    {
+        trans_property_free((TransProperty*)(list->properties->data));
+        list->properties = g_list_next(list->properties);
+    }
+    g_list_free(properties_begin);
+    g_free(list);
+}
+
+/** Adds a property to the list it's linked with.
+ * (The TransPropertyList is not passed as a parameter because the property is
+ * associated with a list when it's constructed.)
+ * @param property The property to be added to its list
+ */
+static void trans_property_list_add(TransProperty* property)
+{
+    property->list->properties = g_list_append(property->list->properties, property);
+}
+
+/** Adds a split to a transaction.
+ * @param trans The transaction to add a split to
+ * @param account The account used for the split
+ * @param book The book where the split should be stored
+ * @param amount The amount of the split
+ */
+static void trans_add_split(Transaction* trans, Account* account, QofBook* book,
+gnc_numeric amount)
+{
+    Split* split = xaccMallocSplit(book);
+    xaccSplitSetAccount(split, account);
+    xaccSplitSetParent(split, trans);
+    xaccSplitSetAmount(split, amount);
+    xaccSplitSetValue(split, amount);
+    //xaccSplitSetAction(split, "Deposit");
+}
+
+/** Tests a TransPropertyList for having enough essential properties.
+ * Essential properties are "Date" and one of the following: "Balance", "Deposit", or
+ * "Withdrawal".
+ * @param list The list we are checking
+ * @param error Contains an error message on failure
+ * @return TRUE if there are enough essentials; FALSE otherwise
+ */
+static gboolean trans_property_list_verify_essentials(TransPropertyList* list, gchar** error)
+{
+    int i;
+    /* possible_errors lists the ways in which a list can fail this test. */
+    enum PossibleErrorTypes {NO_DATE, NO_AMOUNT, NUM_OF_POSSIBLE_ERRORS};
+    gchar* possible_errors[NUM_OF_POSSIBLE_ERRORS] =
+    {
+        N_("No date column."),
+        N_("No balance, deposit, or withdrawal column.")
+    };
+    int possible_error_lengths[NUM_OF_POSSIBLE_ERRORS] = {0};
+    GList *properties_begin = list->properties, *errors_list = NULL;
+
+    /* Go through each of the properties and erase possible errors. */
+    while (list->properties)
+    {
+        switch (((TransProperty*)(list->properties->data))->type)
+        {
+        case GNC_CSV_DATE:
+            possible_errors[NO_DATE] = NULL;
+            break;
+
+        case GNC_CSV_BALANCE:
+        case GNC_CSV_DEPOSIT:
+        case GNC_CSV_WITHDRAWAL:
+            possible_errors[NO_AMOUNT] = NULL;
+            break;
+        }
+        list->properties = g_list_next(list->properties);
+    }
+    list->properties = properties_begin;
+
+    /* Accumulate a list of the actual errors. */
+    for (i = 0; i < NUM_OF_POSSIBLE_ERRORS; i++)
+    {
+        if (possible_errors[i] != NULL)
+        {
+            errors_list = g_list_append(errors_list, GINT_TO_POINTER(i));
+            /* Since we added an error, we want to also store its length for
+             * when we construct the full error string. */
+            possible_error_lengths[i] = strlen(_(possible_errors[i]));
+        }
+    }
+
+    /* If there are no errors, we can quit now. */
+    if (errors_list == NULL)
+        return TRUE;
+    else
+    {
+        /* full_error_size is the full length of the error message. */
+        int full_error_size = 0, string_length = 0;
+        GList* errors_list_begin = errors_list;
+        gchar *error_message, *error_message_begin;
+
+        /* Find the value for full_error_size. */
+        while (errors_list)
+        {
+            /* We add an extra 1 to account for spaces in between messages. */
+            full_error_size += possible_error_lengths[GPOINTER_TO_INT(errors_list->data)] + 1;
+            errors_list = g_list_next(errors_list);
+        }
+        errors_list = errors_list_begin;
+
+        /* Append the error messages one after another. */
+        error_message = error_message_begin = g_new(gchar, full_error_size);
+        while (errors_list)
+        {
+            i = GPOINTER_TO_INT(errors_list->data);
+            string_length = possible_error_lengths[i];
+
+            /* Copy the error message and put a space after it. */
+            strncpy(error_message, _(possible_errors[i]), string_length);
+            error_message += string_length;
+            *error_message = ' ';
+            error_message++;
+
+            errors_list = g_list_next(errors_list);
+        }
+        *error_message = '\0'; /* Replace the last space with the null byte. */
+        g_list_free(errors_list_begin);
+
+        *error = error_message_begin;
+        return FALSE;
+    }
+}
+
+/** Create a Transaction from a TransPropertyList.
+ * @param list The list of properties
+ * @param error Contains an error on failure
+ * @return On success, a GncCsvTransLine; on failure, the trans pointer is NULL
+ */
+static GncCsvTransLine* trans_property_list_to_trans(TransPropertyList* list, gchar** error)
+{
+    GncCsvTransLine* trans_line = g_new(GncCsvTransLine, 1);
+    GList* properties_begin = list->properties;
+    QofBook* book = gnc_account_get_book(list->account);
+    gnc_commodity* currency = xaccAccountGetCommodity(list->account);
+    gnc_numeric amount = double_to_gnc_numeric(0.0, xaccAccountGetCommoditySCU(list->account),
+                         GNC_HOW_RND_ROUND_HALF_UP);
+
+    /* This flag is set to TRUE if we can use the "Deposit" or "Withdrawal" column. */
+    gboolean amount_set = FALSE;
+
+    /* The balance is 0 by default. */
+    trans_line->balance_set = FALSE;
+    trans_line->balance = amount;
+
+    /* We make the line_no -1 just to mark that it hasn't been set. We
+     * may get rid of line_no soon anyway, so it's not particularly
+     * important. */
+    trans_line->line_no = -1;
+
+    /* Make sure this is a transaction with all the columns we need. */
+    if (!trans_property_list_verify_essentials(list, error))
+    {
+        g_free(trans_line);
+        return NULL;
+    }
+
+    trans_line->trans = xaccMallocTransaction(book);
+    xaccTransBeginEdit(trans_line->trans);
+    xaccTransSetCurrency(trans_line->trans, currency);
+
+    /* Go through each of the properties and edit the transaction accordingly. */
+    list->properties = properties_begin;
+    while (list->properties != NULL)
+    {
+        TransProperty* prop = (TransProperty*)(list->properties->data);
+        switch (prop->type)
+        {
+        case GNC_CSV_DATE:
+            xaccTransSetDatePostedSecs(trans_line->trans, *((time_t*)(prop->value)));
+            break;
+
+        case GNC_CSV_DESCRIPTION:
+            xaccTransSetDescription(trans_line->trans, (char*)(prop->value));
+            break;
+
+        case GNC_CSV_NUM:
+            xaccTransSetNum(trans_line->trans, (char*)(prop->value));
+            break;
+
+        case GNC_CSV_DEPOSIT: /* Add deposits to the existing amount. */
+            if (prop->value != NULL)
+            {
+                amount = gnc_numeric_add(*((gnc_numeric*)(prop->value)),
+                                         amount,
+                                         xaccAccountGetCommoditySCU(list->account),
+                                         GNC_HOW_RND_ROUND_HALF_UP);
+                amount_set = TRUE;
+                /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */
+                trans_line->balance_set = FALSE;
+            }
+            break;
+
+        case GNC_CSV_WITHDRAWAL: /* Withdrawals are just negative deposits. */
+            if (prop->value != NULL)
+            {
+                amount = gnc_numeric_add(gnc_numeric_neg(*((gnc_numeric*)(prop->value))),
+                                         amount,
+                                         xaccAccountGetCommoditySCU(list->account),
+                                         GNC_HOW_RND_ROUND_HALF_UP);
+                amount_set = TRUE;
+                /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */
+                trans_line->balance_set = FALSE;
+            }
+            break;
+
+        case GNC_CSV_BALANCE: /* The balance gets stored in a separate field in trans_line. */
+            /* We will use the "Deposit" and "Withdrawal" columns in preference to "Balance". */
+            if (!amount_set && prop->value != NULL)
+            {
+                /* This gets put into the actual transaction at the end of gnc_csv_parse_to_trans. */
+                trans_line->balance = *((gnc_numeric*)(prop->value));
+                trans_line->balance_set = TRUE;
+            }
+            break;
+        }
+        list->properties = g_list_next(list->properties);
+    }
+
+    /* Add a split with the cumulative amount value. */
+    trans_add_split(trans_line->trans, list->account, book, amount);
+
+    return trans_line;
+}
+
+/** Creates a list of transactions from parsed data. Transactions that
+ * could be created from rows are placed in parse_data->transactions;
+ * rows that fail are placed in parse_data->error_lines. (Note: there
+ * is no way for this function to "fail," i.e. it only returns 0, so
+ * it may be changed to a void function in the future.)
+ * @param parse_data Data that is being parsed
+ * @param account Account with which transactions are created
+ * @param redo_errors TRUE to convert only error data, FALSE for all data
+ * @return 0 on success, 1 on failure
+ */
+int gnc_csv_parse_to_trans(GncCsvParseData* parse_data, Account* account,
+                           gboolean redo_errors)
+{
+    gboolean hasBalanceColumn;
+    int i, j, max_cols = 0;
+    GArray* column_types = parse_data->column_types;
+    GList *error_lines = NULL, *begin_error_lines = NULL;
+
+    /* last_transaction points to the last element in
+     * parse_data->transactions, or NULL if it's empty. */
+    GList* last_transaction = NULL;
+
+    /* Free parse_data->error_lines and parse_data->transactions if they
+     * already exist. */
+    if (redo_errors) /* If we're redoing errors, we save freeing until the end. */
+    {
+        begin_error_lines = error_lines = parse_data->error_lines;
+    }
+    else
+    {
+        if (parse_data->error_lines != NULL)
+        {
+            g_list_free(parse_data->error_lines);
+        }
+        if (parse_data->transactions != NULL)
+        {
+            g_list_free(parse_data->transactions);
+        }
+    }
+    parse_data->error_lines = NULL;
+
+    if (redo_errors) /* If we're looking only at error data ... */
+    {
+        if (parse_data->transactions == NULL)
+        {
+            last_transaction = NULL;
+        }
+        else
+        {
+            /* Move last_transaction to the end. */
+            last_transaction = parse_data->transactions;
+            while (g_list_next(last_transaction) != NULL)
+            {
+                last_transaction = g_list_next(last_transaction);
+            }
+        }
+        /* ... we use only the lines in error_lines. */
+        if (error_lines == NULL)
+            i = parse_data->orig_lines->len; /* Don't go into the for loop. */
+        else
+            i = GPOINTER_TO_INT(error_lines->data);
+    }
+    else /* Otherwise, we look at all the data. */
+    {
+        /* The following while-loop effectively behaves like the following for-loop:
+         * for(i = 0; i < parse_data->orig_lines->len; i++). */
+        i = parse_data->start_row;
+        last_transaction = NULL;
+    }
+
+    /* set parse_data->end_row to number of lines */
+    if(parse_data->end_row > parse_data->orig_lines->len)
+        parse_data->end_row = parse_data->orig_lines->len;
+
+    while (i < parse_data->end_row)
+    {
+        GPtrArray* line = parse_data->orig_lines->pdata[i];
+        /* This flag is TRUE if there are any errors in this row. */
+        gboolean errors = FALSE;
+        gchar* error_message = NULL;
+        TransPropertyList* list = trans_property_list_new(account, parse_data->date_format, parse_data->currency_format );
+        GncCsvTransLine* trans_line = NULL;
+
+        for (j = 0; j < line->len; j++)
+        {
+            /* We do nothing in "None" or "Account" columns. */
+            if ((column_types->data[j] != GNC_CSV_NONE) && (column_types->data[j] != GNC_CSV_ACCOUNT))
+            {
+                /* Affect the transaction appropriately. */
+                TransProperty* property = trans_property_new(column_types->data[j], list);
+                gboolean succeeded = trans_property_set(property, line->pdata[j]);
+
+                /* TODO Maybe move error handling to within TransPropertyList functions? */
+                if (succeeded)
+                {
+                    trans_property_list_add(property);
+                }
+                else
+                {
+                    errors = TRUE;
+                    error_message = g_strdup_printf(_("%s column could not be understood."),
+                                                    _(gnc_csv_column_type_strs[property->type]));
+                    trans_property_free(property);
+                    break;
+                }
+            }
+        }
+
+        /* If we had success, add the transaction to parse_data->transaction. */
+        if (!errors)
+        {
+            trans_line = trans_property_list_to_trans(list, &error_message);
+            errors = trans_line == NULL;
+        }
+
+        trans_property_list_free(list);
+
+        /* If there were errors, add this line to parse_data->error_lines. */
+        if (errors)
+        {
+            parse_data->error_lines = g_list_append(parse_data->error_lines,
+                                                    GINT_TO_POINTER(i));
+            /* If there's already an error message, we need to replace it. */
+            if (line->len > (int)(parse_data->orig_row_lengths->data[i]))
+            {
+                g_free(line->pdata[line->len - 1]);
+                line->pdata[line->len - 1] = error_message;
+            }
+            else
+            {
+                /* Put the error message at the end of the line. */
+                g_ptr_array_add(line, error_message);
+            }
+        }
+        else
+        {
+            /* If all went well, add this transaction to the list. */
+            trans_line->line_no = i;
+
+            /* We keep the transactions sorted by date. We start at the end
+             * of the list and go backward, simply because the file itself
+             * is probably also sorted by date (but we need to handle the
+             * exception anyway). */
+
+            /* If we can just put it at the end, do so and increment last_transaction. */
+            if (last_transaction == NULL ||
+                    xaccTransGetDate(((GncCsvTransLine*)(last_transaction->data))->trans) <= xaccTransGetDate(trans_line->trans))
+            {
+                parse_data->transactions = g_list_append(parse_data->transactions, trans_line);
+                /* If this is the first transaction, we need to get last_transaction on track. */
+                if (last_transaction == NULL)
+                    last_transaction = parse_data->transactions;
+                else /* Otherwise, we can just continue. */
+                    last_transaction = g_list_next(last_transaction);
+            }
+            /* Otherwise, search backward for the correct spot. */
+            else
+            {
+                GList* insertion_spot = last_transaction;
+                while (insertion_spot != NULL &&
+                        xaccTransGetDate(((GncCsvTransLine*)(insertion_spot->data))->trans) > xaccTransGetDate(trans_line->trans))
+                {
+                    insertion_spot = g_list_previous(insertion_spot);
+                }
+                /* Move insertion_spot one location forward since we have to
+                 * use the g_list_insert_before function. */
+                if (insertion_spot == NULL) /* We need to handle the case of inserting at the beginning of the list. */
+                    insertion_spot = parse_data->transactions;
+                else
+                    insertion_spot = g_list_next(insertion_spot);
+
+                parse_data->transactions = g_list_insert_before(parse_data->transactions, insertion_spot, trans_line);
+            }
+        }
+
+        /* Increment to the next row. */
+        if (redo_errors)
+        {
+            /* Move to the next error line in the list. */
+            error_lines = g_list_next(error_lines);
+            if (error_lines == NULL)
+                i = parse_data->orig_lines->len; /* Don't continue the for loop. */
+            else
+                i = GPOINTER_TO_INT(error_lines->data);
+        }
+        else
+        {
+            i++;
+        }
+    }
+
+    /* If we have a balance column, set the appropriate amounts on the transactions. */
+    hasBalanceColumn = FALSE;
+    for (i = 0; i < parse_data->column_types->len; i++)
+    {
+        if (parse_data->column_types->data[i] == GNC_CSV_BALANCE)
+        {
+            hasBalanceColumn = TRUE;
+            break;
+        }
+    }
+
+    if (hasBalanceColumn)
+    {
+        GList* transactions = parse_data->transactions;
+
+        /* balance_offset is how much the balance currently in the account
+         * differs from what it will be after the transactions are
+         * imported. This will be sum of all the previous transactions for
+         * any given transaction. */
+        gnc_numeric balance_offset = double_to_gnc_numeric(0.0,
+                                     xaccAccountGetCommoditySCU(account),
+                                     GNC_HOW_RND_ROUND_HALF_UP);
+        while (transactions != NULL)
+        {
+            GncCsvTransLine* trans_line = (GncCsvTransLine*)transactions->data;
+            if (trans_line->balance_set)
+            {
+                time_t date = xaccTransGetDate(trans_line->trans);
+                /* Find what the balance should be by adding the offset to the actual balance. */
+                gnc_numeric existing_balance = gnc_numeric_add(balance_offset,
+                                               xaccAccountGetBalanceAsOfDate(account, date),
+                                               xaccAccountGetCommoditySCU(account),
+                                               GNC_HOW_RND_ROUND_HALF_UP);
+
+                /* The amount of the transaction is the difference between the new and existing balance. */
+                gnc_numeric amount = gnc_numeric_sub(trans_line->balance,
+                                                     existing_balance,
+                                                     xaccAccountGetCommoditySCU(account),
+                                                     GNC_HOW_RND_ROUND_HALF_UP);
+
+                SplitList* splits = xaccTransGetSplitList(trans_line->trans);
+                while (splits)
+                {
+                    SplitList* next_splits = g_list_next(splits);
+                    xaccSplitDestroy((Split*)splits->data);
+                    splits = next_splits;
+                }
+
+                trans_add_split(trans_line->trans, account, gnc_account_get_book(account), amount);
+
+                /* This new transaction needs to be added to the balance offset. */
+                balance_offset = gnc_numeric_add(balance_offset,
+                                                 amount,
+                                                 xaccAccountGetCommoditySCU(account),
+                                                 GNC_HOW_RND_ROUND_HALF_UP);
+            }
+            transactions = g_list_next(transactions);
+        }
+    }
+
+    if (redo_errors) /* Now that we're at the end, we do the freeing. */
+    {
+        g_list_free(begin_error_lines);
+    }
+
+    /* We need to resize parse_data->column_types since errors may have added columns. */
+    for (i = 0; i < parse_data->orig_lines->len; i++)
+    {
+        if (max_cols < ((GPtrArray*)(parse_data->orig_lines->pdata[i]))->len)
+            max_cols = ((GPtrArray*)(parse_data->orig_lines->pdata[i]))->len;
+    }
+    i = parse_data->column_types->len;
+    parse_data->column_types = g_array_set_size(parse_data->column_types, max_cols);
+    for (; i < max_cols; i++)
+    {
+        parse_data->column_types->data[i] = GNC_CSV_NONE;
+    }
+
+    return 0;
+}


Property changes on: gnucash/trunk/src/import-export/csv-import/gnc-csv-model.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Copied: gnucash/trunk/src/import-export/csv-import/gnc-csv-model.h (from rev 22085, gnucash/trunk/src/import-export/csv/gnc-csv-model.h)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gnc-csv-model.h	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gnc-csv-model.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,134 @@
+/********************************************************************\
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+/** @file
+     @brief CSV import GUI
+     *
+     gnc-csv-model.h
+     @author Copyright (c) 2007 Benny Sperisen <lasindi at gmail.com>
+ */
+
+#ifndef GNC_CSV_MODEL_H
+#define GNC_CSV_MODEL_H
+
+#include "config.h"
+
+#include "Account.h"
+#include "Transaction.h"
+
+#include "stf/stf-parse.h"
+
+/** Enumeration for column types. These are the different types of
+ * columns that can exist in a CSV/Fixed-Width file. There should be
+ * no two columns with the same type except for the GNC_CSV_NONE
+ * type. */
+enum GncCsvColumnType {GNC_CSV_NONE,
+                       GNC_CSV_DATE,
+                       GNC_CSV_DESCRIPTION,
+                       GNC_CSV_ACCOUNT,
+                       GNC_CSV_BALANCE,
+                       GNC_CSV_DEPOSIT,
+                       GNC_CSV_WITHDRAWAL,
+                       GNC_CSV_NUM,
+                       GNC_CSV_NUM_COL_TYPES
+                      };
+
+/** Enumeration for error types. These are the different types of
+ * errors that various functions used for the CSV/Fixed-Width importer
+ * can have. */
+enum GncCsvErrorType {GNC_CSV_FILE_OPEN_ERR,
+                      GNC_CSV_ENCODING_ERR
+                     };
+
+/** Struct for containing a string. This struct simply contains
+ * pointers to the beginning and end of a string. We need this because
+ * the STF code that gnc_csv_parse calls requires these pointers. */
+typedef struct
+{
+    char* begin;
+    char* end;
+} GncCsvStr;
+
+/* TODO We now sort transactions by date, not line number, so we
+ * should probably get rid of this struct and uses of it. */
+
+/** Struct pairing a transaction with a line number. This struct is
+ * used to keep the transactions in order. When rows are separated
+ * into "valid" and "error" lists (in case some of the rows have cells
+ * that are unparseable), we want the user to still be able to
+ * "correct" the error list. If we keep the line numbers of valid
+ * transactions, we can then put transactions created from the newly
+ * corrected rows into the right places. */
+typedef struct
+{
+    int line_no;
+    Transaction* trans;
+    gnc_numeric balance; /**< The (supposed) balance after this transaction takes place */
+    gboolean balance_set; /**< TRUE if balance has been set from user data, FALSE otherwise */
+} GncCsvTransLine;
+
+/* A set of currency formats that the user sees. */
+extern const int num_currency_formats;
+extern const gchar* currency_format_user[];
+
+/* A set of date formats that the user sees. */
+extern const int num_date_formats;
+extern const gchar* date_format_user[];
+
+/* This array contains all of the different strings for different column types. */
+extern gchar* gnc_csv_column_type_strs[];
+
+/** Struct containing data for parsing a CSV/Fixed-Width file. */
+typedef struct
+{
+    gchar* encoding;
+    GMappedFile* raw_mapping;   /**< The mapping containing raw_str */
+    GncCsvStr raw_str;          /**< Untouched data from the file as a string */
+    GncCsvStr file_str;         /**< raw_str translated into UTF-8 */
+    GPtrArray* orig_lines;      /**< file_str parsed into a two-dimensional array of strings */
+    GArray* orig_row_lengths;   /**< The lengths of rows in orig_lines
+                                      before error messages are appended */
+    int orig_max_row;           /**< Holds the maximum value in orig_row_lengths */
+    GStringChunk* chunk;        /**< A chunk of memory in which the contents of orig_lines is stored */
+    StfParseOptions_t* options; /**< Options controlling how file_str should be parsed */
+    GArray* column_types;       /**< Array of values from the GncCsvColumnType enumeration */
+    GList* error_lines;         /**< List of row numbers in orig_lines that have errors */
+    GList* transactions;        /**< List of GncCsvTransLine*s created using orig_lines and column_types */
+    int date_format;            /**< The format of the text in the date columns from date_format_internal. */
+    int start_row;              /**< The start row to generate transactions from. */
+    int end_row;                /**< The end row to generate transactions from. */
+    int currency_format;        /**< The currency format, 0 for locale, 1 for comma dec and 2 for period */
+} GncCsvParseData;
+
+GncCsvParseData* gnc_csv_new_parse_data(void);
+
+void gnc_csv_parse_data_free(GncCsvParseData* parse_data);
+
+int gnc_csv_load_file(GncCsvParseData* parse_data, const char* filename,
+                      GError** error);
+
+int gnc_csv_convert_encoding(GncCsvParseData* parse_data, const char* encoding, GError** error);
+
+int gnc_csv_parse(GncCsvParseData* parse_data, gboolean guessColTypes, GError** error);
+
+int gnc_csv_parse_to_trans(GncCsvParseData* parse_data, Account* account, gboolean redo_errors);
+
+time_t parse_date(const char* date_str, int format);
+
+#endif


Property changes on: gnucash/trunk/src/import-export/csv-import/gnc-csv-model.h
___________________________________________________________________
Added: svn:eol-style
   + LF

Added: gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import-ui.xml
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import-ui.xml	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import-ui.xml	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,13 @@
+<ui>
+  <menubar>
+    <menu name="File" action="FileAction">
+      <menu name="FileImport" action="FileImportAction">
+      	<placeholder name="FileImportPlaceholder">
+      	   <menuitem name="FileCsvImportAccounts" action="CsvImportAccountAction"/>
+      	   <menuitem name="FileCsvImportTransx" action="CsvImportTransActionx"/>
+      	   <menuitem name="FileCsvImportTrans" action="CsvImportTransAction"/>
+      	</placeholder>
+      </menu>
+    </menu>
+  </menubar>
+</ui>

Added: gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import.c
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import.c	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,189 @@
+/*
+ * gnc-plugin-csv-import.c -- csv import plugin
+ * Copyright (C) 2011 Robert Fewell
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "gnc-plugin-csv-import.h"
+#include "gnc-plugin-manager.h"
+
+
+#include "assistant-csv-account-import.h"
+#include "assistant-csv-trans-import.h"
+#include "gnc-csv-import.h"
+
+static void gnc_plugin_csv_import_class_init (GncPluginCsvImportClass *klass);
+static void gnc_plugin_csv_import_init (GncPluginCsvImport *plugin);
+static void gnc_plugin_csv_import_finalize (GObject *object);
+
+/* Command callbacks */
+static void gnc_plugin_csv_import_tree_cmd (GtkAction *action, GncMainWindowActionData *data);
+static void gnc_plugin_csv_import_trans_cmd (GtkAction *action, GncMainWindowActionData *data);
+static void gnc_plugin_csv_import_transx_cmd (GtkAction *action, GncMainWindowActionData *data);
+
+#define PLUGIN_ACTIONS_NAME "gnc-plugin-csv-import-actions"
+#define PLUGIN_UI_FILENAME  "gnc-plugin-csv-import-ui.xml"
+
+static GtkActionEntry gnc_plugin_actions [] =
+{
+    {
+        "CsvImportAccountAction", GTK_STOCK_CONVERT, N_("Import _Accounts from CSV..."), NULL,
+        N_("Import Accounts from a CSV file"),
+        G_CALLBACK (gnc_plugin_csv_import_tree_cmd)
+    },
+    {
+        "CsvImportTransActionx", GTK_STOCK_CONVERT, N_("Import _CSV/Fixed-Width..."), NULL,
+        N_("Import Transactions from a CSV file"),
+        G_CALLBACK (gnc_plugin_csv_import_transx_cmd)
+    },
+    {
+        "CsvImportTransAction", GTK_STOCK_CONVERT, N_("Import Transactions _New from CSV..."), NULL,
+        N_("Import Transactions New from a CSV file"),
+        G_CALLBACK (gnc_plugin_csv_import_trans_cmd)
+    },
+};
+static guint gnc_plugin_n_actions = G_N_ELEMENTS (gnc_plugin_actions);
+
+typedef struct GncPluginCsvImportPrivate
+{
+    gpointer dummy;
+} GncPluginCsvImportPrivate;
+
+#define GNC_PLUGIN_CSV_IMPORT_GET_PRIVATE(o)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN_CSV_IMPORT, GncPluginCsvImportPrivate))
+
+static GObjectClass *parent_class = NULL;
+
+GType
+gnc_plugin_csv_import_get_type (void)
+{
+    static GType gnc_plugin_csv_import_type = 0;
+
+    if (gnc_plugin_csv_import_type == 0)
+    {
+        static const GTypeInfo our_info =
+        {
+            sizeof (GncPluginCsvImportClass),
+            NULL,		/* base_init */
+            NULL,		/* base_finalize */
+            (GClassInitFunc) gnc_plugin_csv_import_class_init,
+            NULL,		/* class_finalize */
+            NULL,		/* class_data */
+            sizeof (GncPluginCsvImport),
+            0,		/* n_preallocs */
+            (GInstanceInitFunc) gnc_plugin_csv_import_init,
+        };
+
+        gnc_plugin_csv_import_type = g_type_register_static (GNC_TYPE_PLUGIN,
+                              "GncPluginCsvImport",
+                              &our_info, 0);
+    }
+
+    return gnc_plugin_csv_import_type;
+}
+
+GncPlugin *
+gnc_plugin_csv_import_new (void)
+{
+    return GNC_PLUGIN (g_object_new (GNC_TYPE_PLUGIN_CSV_IMPORT, NULL));
+}
+
+static void
+gnc_plugin_csv_import_class_init (GncPluginCsvImportClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    GncPluginClass *plugin_class = GNC_PLUGIN_CLASS (klass);
+
+    parent_class = g_type_class_peek_parent (klass);
+
+    object_class->finalize = gnc_plugin_csv_import_finalize;
+
+    /* plugin info */
+    plugin_class->plugin_name  = GNC_PLUGIN_CSV_IMPORT_NAME;
+
+    /* widget addition/removal */
+    plugin_class->actions_name = PLUGIN_ACTIONS_NAME;
+    plugin_class->actions      = gnc_plugin_actions;
+    plugin_class->n_actions    = gnc_plugin_n_actions;
+    plugin_class->ui_filename  = PLUGIN_UI_FILENAME;
+
+    g_type_class_add_private(klass, sizeof(GncPluginCsvImportPrivate));
+}
+
+static void
+gnc_plugin_csv_import_init (GncPluginCsvImport *plugin)
+{
+}
+
+static void
+gnc_plugin_csv_import_finalize (GObject *object)
+{
+    GncPluginCsvImport *plugin;
+    GncPluginCsvImportPrivate *priv;
+
+    g_return_if_fail (GNC_IS_PLUGIN_CSV_IMPORT (object));
+
+    plugin = GNC_PLUGIN_CSV_IMPORT (object);
+    priv = GNC_PLUGIN_CSV_IMPORT_GET_PRIVATE(plugin);
+
+    G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/************************************************************
+ *              Plugin Function Implementation              *
+ ************************************************************/
+
+/************************************************************
+ *                    Command Callbacks                     *
+ ************************************************************/
+static void
+gnc_plugin_csv_import_tree_cmd (GtkAction *action,
+                           GncMainWindowActionData *data)
+{
+   gnc_file_csv_account_import ();
+}
+
+static void
+gnc_plugin_csv_import_trans_cmd (GtkAction *action,
+                           GncMainWindowActionData *data)
+{
+   gnc_file_csv_trans_import ();
+}
+
+static void
+gnc_plugin_csv_import_transx_cmd (GtkAction *action,
+                           GncMainWindowActionData *data)
+{
+    gnc_file_csv_import();
+}
+/************************************************************
+ *                    Plugin Bootstrapping                   *
+ ************************************************************/
+void
+gnc_plugin_csv_import_create_plugin (void)
+{
+    GncPlugin *plugin = gnc_plugin_csv_import_new ();
+
+    gnc_plugin_manager_add_plugin (gnc_plugin_manager_get (), plugin);
+}


Property changes on: gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Added: gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import.h
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import.h	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,62 @@
+/*
+ * gnc-plugin-csv-import.h -- csv import plugin
+ * Copyright (C) 2011 Robert Fewell
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+#ifndef __GNC_PLUGIN_CSV_IMPORT_H
+#define __GNC_PLUGIN_CSV_IMPORT_H
+
+#include <gtk/gtk.h>
+
+#include "gnc-plugin.h"
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_PLUGIN_CSV_IMPORT            (gnc_plugin_csv_import_get_type ())
+#define GNC_PLUGIN_CSV_IMPORT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_PLUGIN_CSV_IMPORT, GncPluginCsvImport))
+#define GNC_PLUGIN_CSV_IMPORT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_PLUGIN_CSV_IMPORT, GncPluginCsvImportClass))
+#define GNC_IS_PLUGIN_CSV_IMPORT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_PLUGIN_CSV_IMPORT))
+#define GNC_IS_PLUGIN_CSV_IMPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_CSV_IMPORT))
+#define GNC_PLUGIN_CSV_IMPORT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_CSV_IMPORT, GncPluginCsvImportClass))
+
+#define GNC_PLUGIN_CSV_IMPORT_NAME "gnc-plugin-csv-import"
+
+/* typedefs & structures */
+typedef struct
+{
+    GncPlugin gnc_plugin;
+} GncPluginCsvImport;
+
+typedef struct
+{
+    GncPluginClass gnc_plugin;
+} GncPluginCsvImportClass;
+
+/* function prototypes */
+GType      gnc_plugin_csv_import_get_type (void);
+
+GncPlugin *gnc_plugin_csv_import_new      (void);
+
+void       gnc_plugin_csv_import_create_plugin (void);
+
+G_END_DECLS
+
+#endif /* __GNC_PLUGIN_CSV_IMPORT_H */


Property changes on: gnucash/trunk/src/import-export/csv-import/gnc-plugin-csv-import.h
___________________________________________________________________
Added: svn:eol-style
   + LF

Copied: gnucash/trunk/src/import-export/csv-import/gncmod-csv-import.c (from rev 22085, gnucash/trunk/src/import-export/csv/gncmod-csv-import.c)
===================================================================
--- gnucash/trunk/src/import-export/csv-import/gncmod-csv-import.c	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/gncmod-csv-import.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,90 @@
+/********************************************************************\
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+/** @addtogroup Import_Export
+    @{ */
+/**@internal
+ at file gncmod-csv-import.c
+ at brief module definition/initialization for the csv importer
+ at author Copyright (c) 2012 Robert Fewell
+*/
+#include "config.h"
+
+#include <gmodule.h>
+
+#include "gnc-module.h"
+#include "gnc-module-api.h"
+#include "gnc-plugin-csv-import.h"
+
+GNC_MODULE_API_DECL(libgncmod_csv_import)
+
+/* version of the gnc module system interface we require */
+int libgncmod_csv_import_gnc_module_system_interface = 0;
+
+/* module versioning uses libtool semantics. */
+int libgncmod_csv_import_gnc_module_current  = 0;
+int libgncmod_csv_import_gnc_module_revision = 0;
+int libgncmod_csv_import_gnc_module_age      = 0;
+
+//static GNCModule bus_core;
+//static GNCModule file;
+
+char *
+libgncmod_csv_import_gnc_module_path(void)
+{
+    return g_strdup("gnucash/import-export/csv-import");
+}
+
+char *
+libgncmod_csv_import_gnc_module_description(void)
+{
+    return g_strdup("Gnome GUI and C code for CSV importer.");
+}
+
+int
+libgncmod_csv_import_gnc_module_init(int refcount)
+{
+    if (!gnc_module_load("gnucash/engine", 0))
+    {
+        return FALSE;
+    }
+    if (!gnc_module_load("gnucash/app-utils", 0))
+    {
+        return FALSE;
+    }
+    if (!gnc_module_load("gnucash/gnome-utils", 0))
+    {
+        return FALSE;
+    }
+    if (!gnc_module_load("gnucash/import-export", 0))
+    {
+        return FALSE;
+    }
+
+    /* Add menu items with C callbacks */
+    gnc_plugin_csv_import_create_plugin();
+
+    return TRUE;
+}
+
+int
+libgncmod_csv_import_gnc_module_end(int refcount)
+{
+    return TRUE;
+}
+/** @}*/


Property changes on: gnucash/trunk/src/import-export/csv-import/gncmod-csv-import.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Added: gnucash/trunk/src/import-export/csv-import/schemas/Makefile.am
===================================================================
--- gnucash/trunk/src/import-export/csv-import/schemas/Makefile.am	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/schemas/Makefile.am	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,21 @@
+schemadir   = @GCONF_SCHEMA_FILE_DIR@
+schemas_in_files = \
+  apps_gnucash_dialog_import_csv.schemas.in
+schema_DATA = $(schemas_in_files:.schemas.in=.schemas)
+
+ at INTLTOOL_SCHEMAS_RULE@
+
+EXTRA_DIST = $(schemas_in_files)
+
+CLEANFILES = $(schema_DATA)
+
+install-data-local:
+if GCONF_SCHEMAS_INSTALL
+	-mkdir -p $(DESTDIR)$(GCONF_SCHEMA_CONFIG_SOURCE_DIRONLY)
+	GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(schema_DATA)
+endif
+
+uninstall-local:
+if GCONF_SCHEMAS_INSTALL
+	GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-uninstall-rule $(schema_DATA)
+endif

Added: gnucash/trunk/src/import-export/csv-import/schemas/apps_gnucash_dialog_import_csv.schemas.in
===================================================================
--- gnucash/trunk/src/import-export/csv-import/schemas/apps_gnucash_dialog_import_csv.schemas.in	                        (rev 0)
+++ gnucash/trunk/src/import-export/csv-import/schemas/apps_gnucash_dialog_import_csv.schemas.in	2012-03-16 20:26:22 UTC (rev 22086)
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<gconfschemafile>
+  <schemalist>
+
+    <schema>
+      <key>/schemas/apps/gnucash/dialogs/import/csv/position</key>
+      <applyto>/apps/gnucash/dialogs/import/csv/window_position</applyto>
+      <owner>gnucash</owner>
+      <type>list</type>
+      <list_type>int</list_type>
+      <locale name="C">
+        <short>Window position</short>
+        <long>
+          The X,Y coordinates of the top left corner of the window
+          when it was last closed.
+        </long>
+      </locale>
+    </schema>
+
+    <schema>
+      <key>/schemas/apps/gnucash/dialogs/import/csv/geometry</key>
+      <applyto>/apps/gnucash/dialogs/import/csv/window_geometry</applyto>
+      <owner>gnucash</owner>
+      <type>list</type>
+      <list_type>int</list_type>
+      <locale name="C">
+        <short>Window geometry</short>
+        <long>
+          The width and size of the window when it was last closed.
+        </long>
+      </locale>
+    </schema>
+
+    <schema>
+      <key>/schemas/apps/gnucash/dialogs/import/csv/last_path</key>
+      <applyto>/apps/gnucash/dialogs/import/csv/last_path</applyto>
+      <owner>gnucash</owner>
+      <type>string</type>
+      <locale name="C">
+        <short>Last pathname used</short>
+        <long>
+          This field contains the last pathname used by this window.
+          It will be used as the initial filename/pathname the next
+          time this window is opened.
+        </long>
+      </locale>
+    </schema>
+
+  </schemalist>
+</gconfschemafile>

Modified: gnucash/trunk/src/import-export/dialog-import.glade
===================================================================
--- gnucash/trunk/src/import-export/dialog-import.glade	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/dialog-import.glade	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,134 +1,7 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy project-wide -->
-  <object class="GtkDialog" id="Generic Import Account Picker">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Select Account</property>
-    <property name="default_width">800</property>
-    <property name="default_height">600</property>
-    <property name="type_hint">dialog</property>
-    <signal name="map" handler="gnc_ui_generic_account_picker_map_cb" swapped="no"/>
-    <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox8">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area8">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="layout_style">end</property>
-            <child>
-              <object class="GtkButton" id="newbutton">
-                <property name="label">gnc-new-account</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_underline">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="cancelbutton">
-                <property name="label">gtk-cancel</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="okbutton">
-                <property name="label">gtk-ok</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="label847715">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xpad">5</property>
-            <property name="ypad">3</property>
-            <property name="label" translatable="yes">Please select or create an appropriate GnuCash account for:</property>
-            <property name="justify">center</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkLabel" id="online_id_label">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="xpad">5</property>
-            <property name="ypad">3</property>
-            <property name="label" translatable="yes">Online account ID here...</property>
-            <property name="justify">center</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">3</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkScrolledWindow" id="account_tree_sw">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="hscrollbar_policy">automatic</property>
-            <property name="vscrollbar_policy">automatic</property>
-            <child>
-              <placeholder/>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">4</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <action-widgets>
-      <action-widget response="1">newbutton</action-widget>
-      <action-widget response="-6">cancelbutton</action-widget>
-      <action-widget response="-5">okbutton</action-widget>
-    </action-widgets>
-  </object>
   <object class="GtkWindow" id="Preferences">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
@@ -454,6 +327,149 @@
       </object>
     </child>
   </object>
+  <object class="GtkDialog" id="account_picker">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Select Account</property>
+    <property name="default_width">800</property>
+    <property name="default_height">600</property>
+    <property name="type_hint">dialog</property>
+    <signal name="map" handler="gnc_ui_generic_account_picker_map_cb" swapped="no"/>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="account_picker_vbox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area8">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="newbutton">
+                <property name="label">gnc-new-account</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="cancelbutton">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="okbutton">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="1">newbutton</action-widget>
+      <action-widget response="-6">cancelbutton</action-widget>
+      <action-widget response="-5">okbutton</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkVBox" id="account_picker_content">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkLabel" id="label847715">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xpad">5</property>
+        <property name="ypad">3</property>
+        <property name="label" translatable="yes">Please select or create an appropriate GnuCash account for:</property>
+        <property name="justify">center</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="online_id_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xpad">5</property>
+        <property name="ypad">3</property>
+        <property name="label" translatable="yes">Online account ID here...</property>
+        <property name="justify">center</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkScrolledWindow" id="account_tree_sw">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="hscrollbar_policy">automatic</property>
+        <property name="vscrollbar_policy">automatic</property>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">2</property>
+      </packing>
+    </child>
+  </object>
   <object class="GtkAdjustment" id="atm_fee_adj">
     <property name="upper">1000</property>
     <property name="value">2</property>
@@ -1206,7 +1222,7 @@
     <property name="type_hint">dialog</property>
     <signal name="close" handler="on_matcher_cancel_clicked" swapped="no"/>
     <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox10">
+      <object class="GtkVBox" id="transaction_matcher_vbox">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <child internal-child="action_area">
@@ -1275,56 +1291,7 @@
           </packing>
         </child>
         <child>
-          <object class="GtkVBox" id="vbox3">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <child>
-              <object class="GtkLabel" id="heading_label">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="xpad">5</property>
-                <property name="ypad">5</property>
-                <property name="label" translatable="yes">List of downloaded transactions (source split shown):</property>
-                <property name="justify">center</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow" id="scrolledwindow25">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">automatic</property>
-                <property name="vscrollbar_policy">automatic</property>
-                <property name="shadow_type">in</property>
-                <child>
-                  <object class="GtkTreeView" id="downloaded_view">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="reorderable">True</property>
-                    <property name="rules_hint">True</property>
-                    <property name="enable_search">False</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">2</property>
-          </packing>
+          <placeholder/>
         </child>
       </object>
     </child>
@@ -1334,4 +1301,49 @@
       <action-widget response="-11">matcher__help</action-widget>
     </action-widgets>
   </object>
+  <object class="GtkVBox" id="transaction_matcher_content">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkLabel" id="heading_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="xpad">5</property>
+        <property name="ypad">5</property>
+        <property name="label" translatable="yes">List of downloaded transactions (source split shown):</property>
+        <property name="justify">center</property>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">False</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkScrolledWindow" id="scrolledwindow25">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="hscrollbar_policy">automatic</property>
+        <property name="vscrollbar_policy">automatic</property>
+        <property name="shadow_type">in</property>
+        <child>
+          <object class="GtkTreeView" id="downloaded_view">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="reorderable">True</property>
+            <property name="rules_hint">True</property>
+            <property name="enable_search">False</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
+  </object>
 </interface>

Modified: gnucash/trunk/src/import-export/import-account-matcher.c
===================================================================
--- gnucash/trunk/src/import-export/import-account-matcher.c	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/import-account-matcher.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,4 +1,9 @@
 /********************************************************************\
+ * import-account-matcher.c - flexible account picker/matcher       *
+ *                                                                  *          
+ * Copyright (C) 2002 Benoit Grégoire <bock at step.polymtl.ca>        *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ *                                                                  *
  * This program is free software; you can redistribute it and/or    *
  * modify it under the terms of the GNU General Public License as   *
  * published by the Free Software Foundation; either version 2 of   *
@@ -43,27 +48,59 @@
 #define GCONF_SECTION "dialogs/import/generic_matcher/account_matcher"
 
 /*-******************************************************************\
- *   Structs   *
+ * Functions needed by gnc_import_select_account
+ *
 \********************************************************************/
+/** Constructor for AccountPickerDialog.
+ * @return Pointer to a new AccountPickerDialog
+ */
+static AccountPickerDialog* gnc_import_new_account_picker(void)
+{
+    AccountPickerDialog* picker = g_new(AccountPickerDialog, 1);
+    picker->dialog = NULL;
+    picker->assistant = NULL;
+    picker->account_tree = NULL;
+    picker->account_tree_sw = NULL;
+    picker->auto_create = TRUE;
+    picker->account_human_description = NULL;
+    picker->account_online_id_value = NULL;
+    picker->account_online_id_label = NULL;
+    picker->new_account_default_commodity = NULL;
+    picker->new_account_default_type = 0;
+    picker->default_account = NULL;
+    picker->retAccount =NULL;
+    return picker;
+}
 
-struct _accountpickerdialog
+
+/**************************************************
+ * test_acct_online_id_match
+ *
+ * test for match of kvp_frame of account
+ **************************************************/
+static gpointer test_acct_online_id_match(Account *acct, gpointer param_online_id)
 {
-    GtkWidget       * dialog;
-    GncTreeViewAccount *account_tree;
-    GtkWidget       * account_tree_sw;
-    const gchar * account_human_description;
-    const gchar * account_online_id_value;
-    const gnc_commodity * new_account_default_commodity;
-    GNCAccountType new_account_default_type;
-};
+    const gchar * current_online_id = gnc_import_get_acc_online_id(acct);
+    if ( (current_online_id != NULL
+            && param_online_id != NULL )
+            && strcmp( current_online_id, param_online_id ) == 0 )
+    {
+        return (gpointer *) acct;
+    }
+    else
+    {
+        return NULL;
+    }
+}
 
-/*-******************************************************************\
- * Functions needed by gnc_import_select_account
+
+/***********************************************************
+ * build_acct_tree
  *
-\********************************************************************/
-
+ * build the account tree with the custome column, online_id
+ ************************************************************/
 static void
-build_acct_tree(struct _accountpickerdialog * picker)
+build_acct_tree(AccountPickerDialog *picker)
 {
     GtkTreeView *account_tree;
     GtkTreeViewColumn *col;
@@ -73,7 +110,6 @@
     account_tree = gnc_tree_view_account_new(FALSE);
     picker->account_tree = GNC_TREE_VIEW_ACCOUNT(account_tree);
     gtk_tree_view_set_headers_visible (account_tree, TRUE);
-
     col = gnc_tree_view_find_column_by_name(GNC_TREE_VIEW(account_tree), "type");
     g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
 
@@ -93,14 +129,18 @@
                  (gchar*) NULL);
 }
 
-/* When user clicks to create a new account */
+
+/*******************************************************
+ * gnc_import_add_account
+ *
+ * Callback for when user clicks to create a new account
+ *******************************************************/
 static void
-gnc_import_add_account(struct _accountpickerdialog * picker)
+gnc_import_add_account(GtkWidget *button, AccountPickerDialog *picker)
 {
     Account *selected_account, *new_account;
     GList * valid_types = NULL;
     /*DEBUG("Begin");  */
-
     if (picker->new_account_default_type != ACCT_TYPE_NONE)
     {
         /*Yes, this is weird, but we really DO want to pass the value instead of the pointer...*/
@@ -115,32 +155,72 @@
     gnc_tree_view_account_set_selected_account(picker->account_tree, new_account);
 }
 
-/* When user double-clicks an account */
+
+/*******************************************************
+ * account_tree_row_activated_cb
+ *
+ * Callback for when user double clicks on an account
+ *******************************************************/
 static void
 account_tree_row_activated_cb(GtkTreeView *view, GtkTreePath *path,
                               GtkTreeViewColumn *column,
-                              struct _accountpickerdialog *picker)
+                              AccountPickerDialog *picker)
 {
-    g_return_if_fail(picker && picker->dialog);
+    const gchar *retval_name = NULL;
+    Account *old_id_acc;
 
-    gtk_dialog_response(GTK_DIALOG(picker->dialog), GTK_RESPONSE_OK);
-}
+    /* See if we have a dialog, if not we are an assistant */
+    if(picker->dialog == NULL)
+    {
+        GtkAssistant *assistant = GTK_ASSISTANT(picker->assistant);
+        gint num = gtk_assistant_get_current_page (assistant);
+        GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
 
-static gpointer test_acct_online_id_match(Account *acct, gpointer param_online_id)
-{
-    const gchar * current_online_id = gnc_import_get_acc_online_id(acct);
-    if ( (current_online_id != NULL
-            && param_online_id != NULL )
-            && strcmp( current_online_id, param_online_id ) == 0 )
-    {
-        return (gpointer *) acct;
+        picker->retAccount = gnc_tree_view_account_get_selected_account(picker->account_tree);
+        if (picker->retAccount)
+            retval_name = xaccAccountGetName(picker->retAccount);
+        if (!retval_name)
+            retval_name = "(null)";
+        DEBUG("Selected account %p, %s", picker->retAccount, retval_name);
+
+        /* See if the selected account is a placeholder. */
+        if (picker->retAccount && xaccAccountGetPlaceholder (picker->retAccount))
+        {
+            gnc_error_dialog (picker->dialog,
+                     _("The account %s is a placeholder account and does not allow "
+                       "transactions. Please choose a different account."),
+                     retval_name);
+        }
+        else if ( picker->account_online_id_value != NULL)
+        {
+            /* find the old account for this on line id value and reset it */
+            old_id_acc =
+                gnc_account_foreach_descendant_until(gnc_get_current_root_account (),
+                    test_acct_online_id_match,
+                    /* This argument will only be used as a "const char*" */
+                    (void*)picker->account_online_id_value);
+
+            if(old_id_acc != NULL)
+                gnc_import_set_acc_online_id(old_id_acc, "");
+
+            gnc_import_set_acc_online_id(picker->retAccount, picker->account_online_id_value);
+            gtk_assistant_set_page_complete (assistant, page, TRUE);
+        }
+        else
+            gtk_assistant_set_page_complete (assistant, page, TRUE);
     }
     else
     {
-        return NULL;
+        gtk_dialog_response(GTK_DIALOG(picker->dialog), GTK_RESPONSE_OK);
     }
 }
 
+
+/*******************************************************
+ * gnc_import_select_account
+ *
+ * Main call for use with a dialog
+ *******************************************************/
 Account * gnc_import_select_account(GtkWidget *parent,
                                     const gchar * account_online_id_value,
                                     gboolean auto_create,
@@ -151,18 +231,18 @@
                                     gboolean * ok_pressed)
 {
 #define ACCOUNT_DESCRIPTION_MAX_SIZE 255
-    struct _accountpickerdialog * picker;
+    AccountPickerDialog * picker;
     gint response;
     Account * retval = NULL;
     const gchar *retval_name = NULL;
     GtkBuilder *builder;
-    GtkWidget * online_id_label, *button;
+    GtkWidget * online_id_label, *button, *box, *pbox;
     gchar account_description_text[ACCOUNT_DESCRIPTION_MAX_SIZE] = "";
     gboolean ok_pressed_retval = FALSE;
 
     ENTER("Default commodity received: %s", gnc_commodity_get_fullname( new_account_default_commodity));
     DEBUG("Default account type received: %s", xaccAccountGetTypeStr( new_account_default_type));
-    picker = g_new0(struct _accountpickerdialog, 1);
+    picker = g_new0(AccountPickerDialog, 1);
 
     picker->account_online_id_value = account_online_id_value;
     picker->account_human_description =  account_human_description;
@@ -175,25 +255,30 @@
         retval =
             gnc_account_foreach_descendant_until(gnc_get_current_root_account (),
                     test_acct_online_id_match,
-                    /* This argument will only be
-                    					  used as a "const char*" */
+                    /* This argument will only be used as a "const char*" */
                     (void*)account_online_id_value);
     }
     if (retval == NULL && auto_create != 0)
     {
         /* load the interface */
         builder = gtk_builder_new();
-        gnc_builder_add_from_file (builder,"dialog-import.glade", "Generic Import Account Picker");
+        gnc_builder_add_from_file (builder,"dialog-import.glade", "account_picker");
+        gnc_builder_add_from_file (builder,"dialog-import.glade", "account_picker_content");
         /* connect the signals in the interface */
         if (builder == NULL)
         {
             PERR("Error opening the glade builder interface");
         }
-
-        picker->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Generic Import Account Picker"));
+        picker->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker"));
         if (parent)
             gtk_window_set_transient_for (GTK_WINDOW (picker->dialog),
                                           GTK_WINDOW (parent));
+
+        /* Pack the content into the dialog vbox */
+        pbox = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_vbox"));
+        box = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_content"));
+        gtk_box_pack_start( GTK_BOX(pbox), box, TRUE, TRUE,0);
+
         picker->account_tree_sw = GTK_WIDGET(gtk_builder_get_object (builder, "account_tree_sw"));
         online_id_label = GTK_WIDGET(gtk_builder_get_object (builder, "online_id_label"));
         button = GTK_WIDGET(gtk_builder_get_object (builder, "newbutton"));
@@ -256,7 +341,7 @@
                 ok_pressed_retval = TRUE;
                 break;
             case GNC_RESPONSE_NEW:
-                gnc_import_add_account(picker);
+                gnc_import_add_account(NULL, picker);
                 ok_pressed_retval = TRUE;
                 break;
             default:
@@ -284,4 +369,115 @@
     LEAVE("Selected account %p, %s", retval, retval_name ? retval_name : "(null)");
     return retval;
 }
+
+
+/**********************************************************************
+ * These are the routines for use with an Assistant page
+ **********************************************************************/
+
+/*******************************************************
+ * gnc_import_account_assist_setup
+ *
+ * Main call for page setup in an assistant
+ *******************************************************/
+AccountPickerDialog* gnc_import_account_assist_setup(GtkWidget *parent)
+{
+    AccountPickerDialog * picker;
+    GtkBuilder *builder;
+    GtkWidget  *button, *box;
+
+    /* Init the account picker structure */
+    picker = gnc_import_new_account_picker();
+
+    /* load the interface */
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file (builder,"dialog-import.glade", "account_picker_content");
+    /* connect the signals in the interface */
+    if (builder == NULL)
+    {
+        PERR("Error opening the glade builder interface");
+    }
+
+    picker->assistant = gtk_widget_get_parent(parent);
+    /* Pack content into Assistant page widget */
+    box = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_content"));
+    gtk_box_pack_start( GTK_BOX(parent), box, TRUE, TRUE, 6);
+
+    picker->account_tree_sw = GTK_WIDGET(gtk_builder_get_object (builder, "account_tree_sw"));
+    picker->account_online_id_label = GTK_WIDGET(gtk_builder_get_object (builder, "online_id_label"));
+
+    /* Add the New Account Button */
+    button = gtk_button_new_with_mnemonic ("_New Account");
+    gtk_box_pack_start( GTK_BOX(box), button, FALSE, FALSE, 6);
+    gtk_button_set_use_stock (GTK_BUTTON(button), TRUE);
+    gtk_widget_show (button);
+    g_signal_connect(button, "clicked",
+                         G_CALLBACK(gnc_import_add_account), picker);
+
+    build_acct_tree(picker);
+
+    g_signal_connect(picker->account_tree, "row-activated",
+                         G_CALLBACK(account_tree_row_activated_cb), picker);
+
+    g_object_unref(G_OBJECT(builder));
+    return picker;
+}
+
+
+/*******************************************************
+ * gnc_import_account_assist_update
+ *
+ * updates the page and returns account found.
+ *******************************************************/
+Account * gnc_import_account_assist_update (AccountPickerDialog *picker)
+{
+#define ACCOUNT_DESCRIPTION_MAX_SIZE 255
+
+    const gchar *retval_name = NULL;
+    gchar account_description_text[ACCOUNT_DESCRIPTION_MAX_SIZE] = "";
+
+    ENTER("Default commodity received: %s", gnc_commodity_get_fullname( picker->new_account_default_commodity));
+    DEBUG("Default account type received: %s", xaccAccountGetTypeStr( picker->new_account_default_type));
+
+    /*DEBUG("Looking for account with online_id: %s", picker->account_online_id_value);*/
+    if (picker->account_online_id_value != NULL)
+    {
+        picker->retAccount =
+            gnc_account_foreach_descendant_until(gnc_get_current_root_account (),
+                    test_acct_online_id_match,
+                    /* This argument will only be used as a "const char*" */
+                    (void*)picker->account_online_id_value);
+    }
+
+    if (picker->account_human_description != NULL)
+    {
+        strncat(account_description_text, picker->account_human_description,
+                    ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
+        strncat(account_description_text, "\n",
+                    ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
+    }
+    if (picker->account_online_id_value != NULL)
+    {
+        strncat(account_description_text, _("(Full account ID: "),
+                    ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
+        strncat(account_description_text, picker->account_online_id_value,
+                    ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
+        strncat(account_description_text, ")",
+                    ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
+    }
+    gtk_label_set_text(GTK_LABEL( picker->account_online_id_label), account_description_text);
+    
+    if(picker->default_account == NULL)
+        gnc_tree_view_account_set_selected_account(picker->account_tree, picker->retAccount);
+    else
+        gnc_tree_view_account_set_selected_account(picker->account_tree, picker->default_account);
+
+    /*FIXME: DEBUG("WRITEME: Here we should check if an account type is compatible, currency matches, etc.\n"); */
+
+    /*DEBUG("Return value: %p%s%s%s",picker->retAccount,", account name:",xaccAccountGetName(picker->retAccount),"\n");*/
+    retval_name = picker->retAccount ? xaccAccountGetName(picker->retAccount) : NULL;
+    LEAVE("Selected account %p, %s", picker->retAccount, retval_name ? retval_name : "(null)");
+    return picker->retAccount;
+}
+
 /**@}*/

Modified: gnucash/trunk/src/import-export/import-account-matcher.h
===================================================================
--- gnucash/trunk/src/import-export/import-account-matcher.h	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/import-account-matcher.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,4 +1,9 @@
 /********************************************************************\
+ * import-account-matcher.h - flexible account picker/matcher       *
+ *                                                                  *          
+ * Copyright (C) 2002 Benoit Grégoire <bock at step.polymtl.ca>        *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ *                                                                  *
  * This program is free software; you can redistribute it and/or    *
  * modify it under the terms of the GNU General Public License as   *
  * published by the Free Software Foundation; either version 2 of   *
@@ -22,12 +27,30 @@
   @brief  Generic and very flexible account matcher/picker
  @author Copyright (C) 2002 Benoit Grégoire <bock at step.polymtl.ca>
  */
-#ifndef ACCOUNT_MATCHER_H
-#define ACCOUNT_MATCHER_H
+#ifndef IMPORT_ACCOUNT_MATCHER_H
+#define IMPORT_ACCOUNT_MATCHER_H
 
 #include "Account.h"
 #include <gtk/gtk.h>
 
+#include "gnc-tree-view-account.h"
+
+typedef struct
+{
+    GtkWidget           *dialog;                         /* Dialog Widget */
+    GtkWidget           *assistant;                      /* assistant Widget */
+    GncTreeViewAccount  *account_tree;                   /* Account tree */
+    GtkWidget           *account_tree_sw;                /* Scroll Window for Account tree */
+    gboolean             auto_create;                    /* Auto create retAccount, can be used to step over this stage */
+    const gchar         *account_human_description;      /* description for on line id, incoming */
+    const gchar         *account_online_id_value;        /* On line id value, incoming */
+    GtkWidget           *account_online_id_label;        /* the label Widget for the on line id, incoming */
+    const gnc_commodity *new_account_default_commodity;  /* new account default commodity, incoming */
+    GNCAccountType       new_account_default_type;       /* new account default type, incoming */
+    Account             *default_account;                /* default account for selection, incoming */
+    Account             *retAccount;                     /* Account value returned to caller */
+}AccountPickerDialog;
+
 /**  Must be called with a string containing a unique identifier for the
   account.  If an account with a matching online_id kvp_frame is
   found, the function immediately returns with a pointer to that
@@ -99,5 +122,29 @@
                                     gboolean * ok_pressed
                                    );
 
+
+/**  Must be called with the parent widget, ie. a vbox that the 
+     account picker dialog will be packed into. The data structure
+     AccountPickerDialog is initialised and default values populated.
+     
+  @param parent The parent widget. This is the place the account picker dialog will
+  be packed into.
+
+  @return A pointer to the AccountPickerDialog which has been setup.
+*/
+AccountPickerDialog * gnc_import_account_assist_setup (GtkWidget *parent);
+
+
+/**  Must be called with an AccountPickerDialog structure allready setup.
+     If an account with a matching online_id kvp_frame is found, which is 
+     allready present in the dialog structure, the function returns with a 
+     pointer to that account or NULL if not found.
+
+  @param Account picker Dialog structure, AccountPickerDialog
+
+  @return A pointer to the found account, or NULL if account not found.
+*/
+Account * gnc_import_account_assist_update (AccountPickerDialog *picker);
+
 #endif
 /**@}*/

Modified: gnucash/trunk/src/import-export/import-main-matcher.c
===================================================================
--- gnucash/trunk/src/import-export/import-main-matcher.c	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/import-main-matcher.c	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,4 +1,11 @@
 /********************************************************************\
+ * import-main-matcher.c - Transaction matcher main window          *
+ *                                                                  *          
+ * Copyright (C) 2002 Benoit Grégoire <bock at step.polymtl.ca>        *
+ * Copyright (C) 2002 Christian Stimming                            *
+ * Copyright (c) 2006 David Hampton <hampton at employees.org>         *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ *                                                                  *
  * This program is free software; you can redistribute it and/or    *
  * modify it under the terms of the GNU General Public License as   *
  * published by the Free Software Foundation; either version 2 of   *
@@ -47,6 +54,7 @@
 struct _main_matcher_info
 {
     GtkWidget *dialog;
+    GtkWidget *assistant;
     GtkTreeView *view;
     GNCImportSettings *user_settings;
     GdkColor color_back_red;
@@ -125,9 +133,15 @@
         while (gtk_tree_model_iter_next (model, &iter));
     }
 
-    gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(info->dialog));
-    gnc_import_Settings_delete (info->user_settings);
-    gtk_widget_destroy (GTK_WIDGET (info->dialog));
+
+    if(!(info->dialog == NULL))
+    {
+        gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(info->dialog));
+        gnc_import_Settings_delete (info->user_settings);
+        gtk_widget_destroy (GTK_WIDGET (info->dialog));
+    }
+    else
+        gnc_import_Settings_delete (info->user_settings);
     g_free (info);
 }
 
@@ -533,7 +547,7 @@
     GNCImportMainMatcher *info;
     GtkBuilder *builder;
     GtkWidget *heading_label;
-    GtkWidget *button;
+    GtkWidget *button, *box, *pbox;
     gboolean show_update;
 
     info = g_new0 (GNCImportMainMatcher, 1);
@@ -545,9 +559,16 @@
     /* Initialize the GtkDialog. */
     builder = gtk_builder_new();
     gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher");
-
+    gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_content");
     info->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher"));
     g_assert (info->dialog != NULL);
+
+    /* Pack the content into the dialog vbox */
+    pbox = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_vbox"));
+    box = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_content"));
+    gtk_box_pack_start( GTK_BOX(pbox), box, TRUE, TRUE,0);
+
+    /* Get the view */
     info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "downloaded_view"));
     g_assert (info->view != NULL);
 
@@ -581,6 +602,74 @@
     return info;
 }
 
+/*****************************************************************
+ *                 Assistant routines Start                      *
+ *****************************************************************/
+
+GNCImportMainMatcher * gnc_gen_trans_assist_new (GtkWidget *parent,
+        const gchar* heading,
+        gboolean all_from_same_account,
+        gint match_date_hardlimit)
+{
+    GNCImportMainMatcher *info;
+    GtkBuilder *builder;
+    GtkWidget *heading_label;
+    GtkWidget *button, *box, *pbox;
+    gboolean show_update;
+
+    info = g_new0 (GNCImportMainMatcher, 1);
+
+    /* Initialize user Settings. */
+    info->user_settings = gnc_import_Settings_new ();
+    gnc_import_Settings_set_match_date_hardlimit (info->user_settings, match_date_hardlimit);
+
+    /* load the interface */
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_content");
+    if (builder == NULL)
+    {
+        PERR("Error opening the glade builder interface");
+    }
+    /* Pack content into Assistant page widget */
+    box = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_content"));
+    gtk_box_pack_start( GTK_BOX(parent), box, TRUE, TRUE, 6);
+
+    /* Get the view */
+    info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "downloaded_view"));
+    g_assert (info->view != NULL);
+
+    show_update = gnc_import_Settings_get_action_update_enabled(info->user_settings);
+    gnc_gen_trans_init_view(info, all_from_same_account, show_update);
+    heading_label = GTK_WIDGET(gtk_builder_get_object (builder, "heading_label"));
+    g_assert (heading_label != NULL);
+
+    /*Initialise the colors */
+    gdk_color_parse(COLOR_RED,    &info->color_back_red);
+    gdk_color_parse(COLOR_YELLOW, &info->color_back_yellow);
+    gdk_color_parse(COLOR_GREEN,  &info->color_back_green);
+
+    if (heading)
+        gtk_label_set_text (GTK_LABEL (heading_label), heading);
+
+    info->transaction_processed_cb = NULL;
+
+    /* Connect the signals */
+    gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, info);
+
+    g_object_unref(G_OBJECT(builder));
+
+    return info;
+}	
+
+void gnc_gen_trans_assist_start (GNCImportMainMatcher *info)
+{
+    on_matcher_ok_clicked (NULL, info);
+}
+
+/*****************************************************************
+ *                   Assistant routines End                      *
+ *****************************************************************/
+
 void gnc_gen_trans_list_add_tp_cb(GNCImportMainMatcher *info,
                                   GNCTransactionProcessedCB trans_processed_cb,
                                   gpointer user_data)
@@ -589,7 +678,6 @@
     info->transaction_processed_cb = trans_processed_cb;
 }
 
-
 gboolean gnc_gen_trans_list_run (GNCImportMainMatcher *info)
 {
     gboolean result;
@@ -604,7 +692,6 @@
     return result;
 }
 
-
 static void
 refresh_model_row (GNCImportMainMatcher *gui,
                    GtkTreeModel *model,
@@ -817,7 +904,6 @@
     gtk_tree_selection_unselect_all(selection);
 }
 
-
 void gnc_gen_trans_list_add_trans(GNCImportMainMatcher *gui, Transaction *trans)
 {
     gnc_gen_trans_list_add_trans_with_ref_id(gui, trans, 0);

Modified: gnucash/trunk/src/import-export/import-main-matcher.h
===================================================================
--- gnucash/trunk/src/import-export/import-main-matcher.h	2012-03-16 20:26:04 UTC (rev 22085)
+++ gnucash/trunk/src/import-export/import-main-matcher.h	2012-03-16 20:26:22 UTC (rev 22086)
@@ -1,4 +1,10 @@
 /********************************************************************\
+ * import-main-matcher.h - Transaction matcher main window          *
+ *                                                                  *          
+ * Copyright (C) 2002 Benoit Grégoire <bock at step.polymtl.ca>        *
+ * Copyright (C) 2002 Christian Stimming                            *
+ * Copyright (C) 2012 Robert Fewell                                 *
+ *                                                                  *
  * This program is free software; you can redistribute it and/or    *
  * modify it under the terms of the GNU General Public License as   *
  * published by the Free Software Foundation; either version 2 of   *
@@ -55,12 +61,66 @@
  * values like 14 (days) might be appropriate, whereas for use cases
  * with paper checks (e.g. OFX, QIF), values like 42 (days) seem more
  * appropriate.
+ *
+ * @return A pointer to the GNCImportMainMatcher which has been setup.
 */
 GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent,
         const gchar* heading,
         gboolean all_from_same_account,
         gint match_date_hardlimit);
 
+
+
+/**  Add the Transaction matcher to an existing page of an assistant.
+ *   Must be called with the parent widget, ie. a vbox that the 
+ *   transaction matcher will be packed into. The data structure
+ *   GNCImportMainMatcher is returned.
+ *
+ * @param parent The parent widget. This is the place the transaction
+ * matcher will be packed into.
+ *
+ * @param heading The heading label in the Importer window. May be NULL.
+ *
+ * @param all_from_same_account Set this to TRUE if ALL the
+ * transaction that will be added with gnc_gen_trans_list_add_trans
+ * are from the same source account.  This will cause the account
+ * column to be hidden.
+ *
+ * @param match_date_hardlimit The number of days that a matching
+ * split may differ from the given transaction before it is discarded
+ * immediately. In other words, any split that is more distant from
+ * the given transaction than this match_date_hardlimit days will be
+ * ignored altogether. For use cases without paper checks (e.g. HBCI),
+ * values like 14 (days) might be appropriate, whereas for use cases
+ * with paper checks (e.g. OFX, QIF), values like 42 (days) seem more
+ * appropriate.
+ *
+ * @return A pointer to the GNCImportMainMatcher which has been setup.
+*/
+GNCImportMainMatcher * gnc_gen_trans_assist_new (GtkWidget *parent,
+        const gchar* heading,
+        gboolean all_from_same_account,
+        gint match_date_hardlimit);
+
+
+/**  This starts the import process for transaction from an assistant.
+ *   assistant button callback.
+ *
+ * @param info. A pointer to a the GNCImportMainMatcher structure.
+*/
+void gnc_gen_trans_assist_start (GNCImportMainMatcher *info);
+
+
+/**  This allows for the transaction help dialog to be started from the
+ *   assistant button callback.
+ *
+ * @param button. The button widget clicked on in the call back.
+ *
+ * @param user_data. A pointer to a structure.
+*/
+void on_matcher_help_clicked (GtkButton *button, gpointer user_data);
+
+
 /** Add transaction processed callback to the transaction importer.
  *
  * @param info The Transaction Importer to use.
@@ -71,10 +131,12 @@
                                   GNCTransactionProcessedCB trans_processed_cb,
                                   gpointer user_data);
 
+
 /** Deletes the given object. */
 void gnc_gen_trans_list_delete (GNCImportMainMatcher *info);
 
-/** Add a newly imported Transaction to the Transaction Importer. The Importer takes over ownership of the passed transaction.
+/** Add a newly imported Transaction to the Transaction Importer.
+ *  The Importer takes over ownership of the passed transaction.
  *
  * @param gui The Transaction Importer to use.
  *
@@ -86,6 +148,7 @@
  */
 void gnc_gen_trans_list_add_trans(GNCImportMainMatcher *gui, Transaction *trans);
 
+
 /** Add a newly imported Transaction to the Transaction Importer and provide an
  * external reference id for it.
  * The Importer takes over ownership of the passed transaction.
@@ -102,12 +165,14 @@
  */
 void gnc_gen_trans_list_add_trans_with_ref_id(GNCImportMainMatcher *gui, Transaction *trans, guint32 ref_id);
 
+
 /** Run this dialog and return only after the user pressed Ok, Cancel,
   or closed the window. This means that all actual importing will
   have been finished upon returning.
  */
 gboolean gnc_gen_trans_list_run (GNCImportMainMatcher *info);
 
+
 /** Returns the widget of this dialog.
  */
 GtkWidget *gnc_gen_trans_list_widget (GNCImportMainMatcher *info);



More information about the gnucash-changes mailing list