gnucash unstable: Multiple changes pushed

Geert Janssens gjanssens at code.gnucash.org
Fri Dec 29 10:52:17 EST 2017


Updated	 via  https://github.com/Gnucash/gnucash/commit/bab266c3 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/6774f122 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3f44552e (commit)
	 via  https://github.com/Gnucash/gnucash/commit/5aa84e13 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/ba5ca5bd (commit)
	 via  https://github.com/Gnucash/gnucash/commit/0534ba4f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8ee6783b (commit)
	 via  https://github.com/Gnucash/gnucash/commit/43f1b2fd (commit)
	 via  https://github.com/Gnucash/gnucash/commit/288563c2 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/16714a8c (commit)
	 via  https://github.com/Gnucash/gnucash/commit/ee2f3017 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/1aa3601e (commit)
	 via  https://github.com/Gnucash/gnucash/commit/71bf7d01 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/644a0aa0 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/62bbe4f9 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/aff1c0c5 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/61f860bc (commit)
	 via  https://github.com/Gnucash/gnucash/commit/1bb2d1dc (commit)
	 via  https://github.com/Gnucash/gnucash/commit/caba8c43 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3a3c2cba (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3c18b806 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/16845c3a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/1e31db74 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8f3e175f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/32799733 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/f2c78102 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3cfa9d05 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/404bc1e3 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/bec1fbd1 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/17d8d424 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/66da4ae3 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/db079b55 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/5b020215 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b94b2f8a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c3b54ab0 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c1a94645 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/6c11cfad (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b1becf3d (commit)
	 via  https://github.com/Gnucash/gnucash/commit/339fbaa5 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/9debe91e (commit)
	 via  https://github.com/Gnucash/gnucash/commit/b8bbdb2a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/a996c02e (commit)
	 via  https://github.com/Gnucash/gnucash/commit/5578da11 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/4d75259c (commit)
	 via  https://github.com/Gnucash/gnucash/commit/cd4b5a31 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/bf0c3853 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/1435813f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/cf90b8cb (commit)
	 via  https://github.com/Gnucash/gnucash/commit/393b8a12 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/4fe77a57 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/eb712dc7 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/3410a03b (commit)
	from  https://github.com/Gnucash/gnucash/commit/26b82b56 (commit)



commit bab266c307936358e8f0e782a1abe4cf61953b15
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Fri Dec 29 16:49:30 2017 +0100

    Update POTEFILES.in

diff --git a/po/POTFILES.in b/po/POTFILES.in
index b304d9f..5226d5f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -294,8 +294,10 @@ gnucash/import-export/csv-imp/assistant-csv-trans-import.glade
 gnucash/import-export/csv-imp/csv-account-import.c
 gnucash/import-export/csv-imp/gnc-csv-account-map.c
 gnucash/import-export/csv-imp/gnc-csv-gnumeric-popup.c
-gnucash/import-export/csv-imp/gnc-csv-tokenizer.cpp
 gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
+gnucash/import-export/csv-imp/gnc-csv-price-import-settings.cpp
+gnucash/import-export/csv-imp/gnc-csv-tokenizer.cpp
+gnucash/import-export/csv-imp/gnc-csv-trans-import-settings.cpp
 gnucash/import-export/csv-imp/gnc-dummy-tokenizer.cpp
 gnucash/import-export/csv-imp/gnc-fw-tokenizer.cpp
 gnucash/import-export/csv-imp/gncmod-csv-import.c

commit 6774f1223f346564caf371ef3809dc4198b39239
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Fri Dec 29 16:49:11 2017 +0100

    Fix a few compile warnings-turned-errors

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 0911233..47a6f2b 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -335,12 +335,12 @@ static void csv_price_imp_preview_commodity_sel_cb (GtkComboBox* commodity_selec
     info->preview_update_commodity();
 }
 
-void csv_price_imp_preview_col_type_changed_cb (GtkComboBox* cbox, CsvImpPriceAssist* info)
+static void csv_price_imp_preview_col_type_changed_cb (GtkComboBox* cbox, CsvImpPriceAssist* info)
 {
     info->preview_update_col_type (cbox);
 }
 
-gboolean
+static gboolean
 csv_price_imp_preview_treeview_clicked_cb (GtkTreeView* treeview, GdkEventButton* event,
                                         CsvImpPriceAssist* info)
 {
@@ -1117,7 +1117,7 @@ CsvImpPriceAssist::preview_update_commodity ()
     preview_refresh_table ();
 }
 
-gboolean
+static gboolean
 csv_imp_preview_queue_rebuild_table (CsvImpPriceAssist *assist)
 {
     assist->preview_refresh_table ();
@@ -1518,7 +1518,7 @@ CsvImpPriceAssist::preview_style_column (uint32_t col_num, GtkTreeModel* model)
 
 /* Helper to create a shared store for the header comboboxes in the preview treeview.
  * It holds the possible column types */
-GtkTreeModel*
+static GtkTreeModel*
 make_column_header_model_price (void)
 {
     auto combostore = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);

commit 3f44552e3649ec28559f2a7f7126992ee083d249
Merge: 26b82b5 5aa84e1
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Fri Dec 29 16:29:46 2017 +0100

    Merge branch 'prices-in' of https://github.com/Bob-IT/gnucash into unstable


commit 5aa84e13d610525410b031031960a7830d806e59
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Thu Dec 14 20:37:12 2017 +0000

    Change the way the import settings are handled

diff --git a/gnucash/import-export/csv-imp/CMakeLists.txt b/gnucash/import-export/csv-imp/CMakeLists.txt
index 65082be..03c6195 100644
--- a/gnucash/import-export/csv-imp/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/CMakeLists.txt
@@ -18,6 +18,8 @@ SET(csv_import_SOURCES
   gnc-csv-gnumeric-popup.c
   gnc-csv-tokenizer.cpp
   gnc-csv-import-settings.cpp
+  gnc-csv-price-import-settings.cpp
+  gnc-csv-trans-import-settings.cpp
   gnc-dummy-tokenizer.cpp
   gnc-fw-tokenizer.cpp
   gnc-price-import.cpp
@@ -46,6 +48,8 @@ SET(csv_import_noinst_HEADERS
   gnc-csv-gnumeric-popup.h
   gnc-csv-tokenizer.hpp
   gnc-csv-import-settings.hpp
+  gnc-csv-price-import-settings.hpp
+  gnc-csv-trans-import-settings.hpp
   gnc-dummy-tokenizer.hpp
   gnc-fw-tokenizer.hpp
   gnc-price-import.hpp
diff --git a/gnucash/import-export/csv-imp/Makefile.am b/gnucash/import-export/csv-imp/Makefile.am
index f1b501f..b4ab800 100644
--- a/gnucash/import-export/csv-imp/Makefile.am
+++ b/gnucash/import-export/csv-imp/Makefile.am
@@ -19,7 +19,9 @@ libgncmod_csv_import_la_SOURCES = \
   gnc-tokenizer.cpp \
   gnc-tx-import.cpp \
   gnc-trans-props.cpp \
-  gnc-csv-import-settings.cpp
+  gnc-csv-import-settings.cpp \
+  gnc-csv-price-import-settings.cpp \
+  gnc-csv-trans-import-settings.cpp
 
 noinst_HEADERS = \
   assistant-csv-account-import.h \
@@ -37,7 +39,9 @@ noinst_HEADERS = \
   gnc-tokenizer.hpp \
   gnc-tx-import.hpp \
   gnc-trans-props.hpp \
-  gnc-csv-import-settings.hpp
+  gnc-csv-import-settings.hpp \
+  gnc-csv-price-import-settings.hpp \
+  gnc-csv-trans-import-settings.hpp
 
 libgncmod_csv_import_la_LDFLAGS = -avoid-version
 
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 8bb371b..0911233 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -52,7 +52,7 @@ extern "C"
 #include "go-charmap-sel.h"
 }
 
-#include "gnc-csv-import-settings.hpp"
+#include "gnc-csv-price-import-settings.hpp"
 #include "gnc-price-import.hpp"
 #include "gnc-fw-tokenizer.hpp"
 #include "gnc-csv-tokenizer.hpp"
@@ -64,8 +64,6 @@ extern "C"
 /* This static indicates the debugging module that this .o belongs to.  */
 static QofLogModule log_module = GNC_MOD_ASSISTANT;
 
-const std::string settings_type = "PRICE";
-
 class  CsvImpPriceAssist
 {
 public:
@@ -738,7 +736,7 @@ void CsvImpPriceAssist::preview_populate_settings_combo()
     gtk_list_store_clear (GTK_LIST_STORE(model));
 
     // Append the default entry
-    auto presets = get_import_presets (settings_type);
+    auto presets = get_import_presets_price ();
     for (auto preset : presets)
     {
         GtkTreeIter iter;
@@ -766,7 +764,7 @@ void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
     /* Handle sensitivity of the delete and save button */
     if (gtk_combo_box_get_active_iter (combo, &iter))
     {
-        CsvImportSettings *preset;
+        CsvPriceImpSettings *preset;
         GtkTreeModel *model = gtk_combo_box_get_model (combo);
         gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -809,7 +807,7 @@ CsvImpPriceAssist::preview_settings_load ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvImportSettings *preset = nullptr;
+    CsvPriceImpSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -836,7 +834,7 @@ CsvImpPriceAssist::preview_settings_delete ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvImportSettings *preset = nullptr;
+    CsvPriceImpSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -870,7 +868,7 @@ CsvImpPriceAssist::preview_settings_save ()
         while (valid)
         {
             // Walk through the list, reading each row
-            CsvImportSettings *preset;
+            CsvPriceImpSettings *preset;
             gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
             if (preset && (preset->m_name == std::string(new_name)))
diff --git a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
index 41779c6..5347393 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
@@ -58,7 +58,7 @@ extern "C"
 #include "go-charmap-sel.h"
 }
 
-#include "gnc-csv-import-settings.hpp"
+#include "gnc-csv-trans-import-settings.hpp"
 #include "gnc-tx-import.hpp"
 #include "gnc-fw-tokenizer.hpp"
 #include "gnc-csv-tokenizer.hpp"
@@ -70,8 +70,6 @@ extern "C"
 /* This static indicates the debugging module that this .o belongs to.  */
 static QofLogModule log_module = GNC_MOD_ASSISTANT;
 
-const std::string settings_type = "TRANS";
-
 class  CsvImpTransAssist
 {
 public:
@@ -678,8 +676,7 @@ void CsvImpTransAssist::preview_populate_settings_combo()
     gtk_list_store_clear (GTK_LIST_STORE(model));
 
     // Append the default entry
-
-    auto presets = get_import_presets (settings_type);
+    auto presets = get_import_presets_trans ();
     for (auto preset : presets)
     {
         GtkTreeIter iter;
@@ -707,7 +704,7 @@ void CsvImpTransAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
     /* Handle sensitivity of the delete and save button */
     if (gtk_combo_box_get_active_iter (combo, &iter))
     {
-        CsvImportSettings *preset;
+        CsvTransImpSettings *preset;
         GtkTreeModel *model = gtk_combo_box_get_model (combo);
         gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -736,7 +733,7 @@ CsvImpTransAssist::preview_settings_name (GtkEntry* entry)
 
     auto box = gtk_widget_get_parent (GTK_WIDGET(entry));
     auto combo = gtk_widget_get_parent (GTK_WIDGET(box));
-    
+
     preview_handle_save_del_sensitivity (GTK_COMBO_BOX(combo));
 }
 
@@ -752,7 +749,7 @@ CsvImpTransAssist::preview_settings_load ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvImportSettings *preset = nullptr;
+    CsvTransImpSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -779,7 +776,7 @@ CsvImpTransAssist::preview_settings_delete ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvImportSettings *preset = nullptr;
+    CsvTransImpSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -812,7 +809,7 @@ CsvImpTransAssist::preview_settings_save ()
         while (valid)
         {
             // Walk through the list, reading each row
-            CsvImportSettings *preset;
+            CsvTransImpSettings *preset;
             gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
             if (preset && (preset->m_name == std::string(new_name)))
diff --git a/gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
index 0096c53..7c5e362 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
@@ -1,5 +1,5 @@
 /*******************************************************************\
- * gnc-csv-import-settings.c -- Save and Load CSV Import Settings   *
+ * gnc-csv-import-settings.cpp -- Save and Load CSV Import Settings *
  *                                                                  *
  * Copyright (C) 2014 Robert Fewell                                 *
  *                                                                  *
@@ -20,7 +20,7 @@
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
 \********************************************************************/
-/** @file gnc-csv-import-settings.c
+/** @file gnc-csv-import-settings.cpp
     @brief CSV Import Settings
     @author Copyright (c) 2014 Robert Fewell
     @author Copyright (c) 2016 Geert Janssens
@@ -44,12 +44,12 @@ extern "C"
 const std::string csv_group_prefix{"CSV-"};
 const std::string no_settings{N_("No Settings")};
 const std::string gnc_exp{N_("GnuCash Export Format")};
+
 #define CSV_NAME         "Name"
 #define CSV_FORMAT       "CsvFormat"
 #define CSV_SKIP_ALT     "SkipAltLines"
 #define CSV_SKIP_START   "SkipStartLines"
 #define CSV_SKIP_END     "SkipEndLines"
-#define CSV_MULTI_SPLIT  "MultiSplit"
 
 #define CSV_SEP          "Separators"
 
@@ -60,121 +60,10 @@ const std::string gnc_exp{N_("GnuCash Export Format")};
 #define CSV_CURRENCY     "CurrencyFormat"
 
 #define CSV_ENCODING     "Encoding"
-#define CSV_COL_TYPES    "ColumnTypes"
 #define CSV_COL_WIDTHS   "ColumnWidths"
-#define CSV_ACCOUNT      "BaseAccount"
-#define CSV_TO_CURR      "PriceToCurrency"
-#define CSV_FROM_COMM    "PriceFromCommodity"
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
-preset_vec presets;
-
-static std::shared_ptr<CsvImportSettings> create_int_no_preset(const std::string& set_type)
-{
-    auto preset = std::make_shared<CsvImportSettings>();
-    preset->m_name = no_settings;
-    preset->m_settings_type = set_type;
-
-    return preset;
-}
-
-static std::shared_ptr<CsvImportSettings> create_int_gnc_exp_preset(void)
-{
-    auto preset = std::make_shared<CsvImportSettings>();
-    preset->m_name = gnc_exp;
-    preset->m_skip_start_lines = 1;
-    preset->m_multi_split = true;
-
-    /* FIXME date and currency format should still be aligned with export format!
-     * That's currently hard to do, because the export uses whatever the user
-     * had set as global preference.
-    preset->date_active = 0;
-    preset->currency_active = 0;
-    */
-    preset->m_column_types = {
-            GncTransPropType::DATE,
-            GncTransPropType::UNIQUE_ID,
-            GncTransPropType::NUM,
-            GncTransPropType::DESCRIPTION,
-            GncTransPropType::NOTES,
-            GncTransPropType::COMMODITY,
-            GncTransPropType::VOID_REASON,
-            GncTransPropType::ACTION,
-            GncTransPropType::MEMO,
-            GncTransPropType::ACCOUNT,
-            GncTransPropType::NONE,
-            GncTransPropType::NONE,
-            GncTransPropType::DEPOSIT,
-            GncTransPropType::REC_STATE,
-            GncTransPropType::REC_DATE,
-            GncTransPropType::PRICE
-    };
-    return preset;
-}
-
-/**************************************************
- * find
- *
- * find all settings entries in the state key file
- * based on settings type.
- **************************************************/
-const preset_vec& get_import_presets (const std::string& set_type)
-{
-
-    // Search all Groups in the state key file for ones starting with prefix
-    auto preset_names = std::vector<std::string>();
-    auto keyfile = gnc_state_get_current ();
-    gsize grouplength;
-    gchar **groups = g_key_file_get_groups (keyfile, &grouplength);
-
-    /* Start by building a sorted list of candidate presets as found in the state file */
-    for (gsize i=0; i < grouplength; i++)
-    {
-        auto group = std::string(groups[i]);
-        auto gp = csv_group_prefix + set_type + " - ";
-        auto pos = group.find(gp);
-        if (pos == std::string::npos)
-            continue;
-
-        preset_names.push_back(group.substr(gp.size()));
-    }
-    // string array from the state file is no longer needed now.
-    g_strfreev (groups);
-
-    /* We want our settings to appear sorted alphabetically to the user */
-    std::sort(preset_names.begin(), preset_names.end());
-
-    /* Now add each preset to our global list */
-    presets.clear();
-
-    /* Start with the internally generated ones */
-    presets.push_back(create_int_no_preset(set_type));
-
-    if (set_type.compare("TRANS") == 0)
-        presets.push_back(create_int_gnc_exp_preset());
-
-    /* Then add all the ones we found in the state file */
-    for (auto preset_name : preset_names)
-    {
-        auto preset = std::make_shared<CsvImportSettings>();
-        preset->m_settings_type = set_type;
-        preset->m_name = preset_name;
-        preset->load();
-        presets.push_back(preset);
-    }
-    return presets;
-}
-
-bool preset_is_reserved_name (const std::string& name)
-{
-    return ((name == no_settings) ||
-            (name == _(no_settings.c_str())) ||
-            (name == gnc_exp) ||
-            (name == _(gnc_exp.c_str())));
-}
-
-
 /**************************************************
  * handle_load_error
  *
@@ -182,7 +71,7 @@ bool preset_is_reserved_name (const std::string& name)
  * ignore key-not-found errors though. We'll just
  * use a default value and go on.
  **************************************************/
-static bool
+bool
 handle_load_error (GError **key_error, const std::string& group)
 {
     if (!*key_error)
@@ -199,17 +88,37 @@ handle_load_error (GError **key_error, const std::string& group)
     return true;
 }
 
+bool preset_is_reserved_name (const std::string& name)
+{
+    return ((name == no_settings) ||
+            (name == _(no_settings.c_str())) ||
+            (name == gnc_exp) ||
+            (name == _(gnc_exp.c_str())));
+}
+
+std::string get_no_settings (void)
+{
+    return no_settings;
+}
+
+std::string get_gnc_exp (void)
+{
+    return gnc_exp;
+}
+
+std::string get_prefix (void)
+{
+    return csv_group_prefix;
+}
+
 /**************************************************
- * load
+ * load_common
  *
  * load the settings from a state key file
  **************************************************/
 bool
-CsvImportSettings::load (void)
+CsvImportSettings::load_common (void)
 {
-    if (preset_is_reserved_name (m_name))
-        return true;
-
     GError *key_error = nullptr;
     m_load_error = false;
     auto group = csv_group_prefix + m_settings_type + " - " + m_name;
@@ -224,9 +133,6 @@ CsvImportSettings::load (void)
     m_skip_alt_lines = g_key_file_get_boolean (keyfile, group.c_str(), CSV_SKIP_ALT, &key_error);
     m_load_error |= handle_load_error (&key_error, group);
 
-    m_multi_split = g_key_file_get_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, &key_error);
-    m_load_error |= handle_load_error (&key_error, group);
-
     auto csv_format = g_key_file_get_boolean (keyfile, group.c_str(), CSV_FORMAT, &key_error);
     if (key_error) csv_format = true; // default to true, but above command will return false in case of error
     m_load_error |= handle_load_error (&key_error, group);
@@ -257,82 +163,8 @@ CsvImportSettings::load (void)
     if (key_char)
         g_free (key_char);
 
-    gsize list_len;
-
-    // Transactions
-    if (m_settings_type.compare("TRANS") == 0)
-    {
-        key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ACCOUNT, &key_error);
-        if (key_char && *key_char != '\0')
-            m_base_account = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
-        m_load_error |= handle_load_error (&key_error, group);
-        if (key_char)
-            g_free (key_char);
-
-        m_column_types.clear();
-        gchar** col_types_str = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
-                &list_len, &key_error);
-        for (uint32_t i = 0; i < list_len; i++)
-        {
-            auto col_types_it = std::find_if (gnc_csv_col_type_strs.begin(),
-                    gnc_csv_col_type_strs.end(), test_prop_type_str (col_types_str[i]));
-            if (col_types_it != gnc_csv_col_type_strs.end())
-            {
-                /* Found a valid column type. Now check whether it is allowed
-                 * in the selected mode (two-split vs multi-split) */
-                auto prop = sanitize_trans_prop (col_types_it->first, m_multi_split);
-                    m_column_types.push_back(prop);
-                if (prop != col_types_it->first)
-                    PWARN("Found column type '%s', but this is blacklisted when multi-split mode is %s. "
-                            "Inserting column type 'NONE' instead'.",
-                            col_types_it->second, m_multi_split ? "enabled" : "disabled");
-            }
-            else
-                PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
-                        col_types_str[i]);
-        }
-        if (col_types_str)
-            g_strfreev (col_types_str);
-    }
-
-    // Price
-    if (m_settings_type.compare("PRICE") == 0)
-    {
-        key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_TO_CURR, &key_error);
-        if (key_char && *key_char != '\0')
-            m_to_currency = parse_commodity_price_comm (key_char);
-        m_load_error |= handle_load_error (&key_error, group);
-        if (key_char)
-            g_free (key_char);
-
-        key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_FROM_COMM, &key_error);
-        if (key_char && *key_char != '\0')
-            m_from_commodity = parse_commodity_price_comm (key_char);
-        m_load_error |= handle_load_error (&key_error, group);
-        if (key_char)
-            g_free (key_char);
-
-        m_column_types.clear();
-        gchar** col_types_str_price = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
-                &list_len, &key_error);
-        for (uint32_t i = 0; i < list_len; i++)
-        {
-            auto col_types_it = std::find_if (gnc_price_col_type_strs.begin(),
-                    gnc_price_col_type_strs.end(), test_price_prop_type_str (col_types_str_price[i]));
-            if (col_types_it != gnc_price_col_type_strs.end())
-            {
-                // Found a valid column type
-                m_column_types_price.push_back(col_types_it->first);
-            }
-            else
-                PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
-                        col_types_str_price[i]);
-        }
-        if (col_types_str_price)
-            g_strfreev (col_types_str_price);
-    }
-
     // Widths
+    gsize list_len;
     m_column_widths.clear();
     gint *col_widths_int = g_key_file_get_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS,
             &list_len, &key_error);
@@ -348,35 +180,18 @@ CsvImportSettings::load (void)
     return m_load_error;
 }
 
-
 /**************************************************
- * save
+ * save_common
  *
  * save settings to a key file
  **************************************************/
 bool
-CsvImportSettings::save (void)
+CsvImportSettings::save_common (void)
 {
-    if (preset_is_reserved_name (m_name))
-    {
-        PWARN ("Ignoring attempt to save to reserved name '%s'", m_name.c_str());
-        return true;
-    }
-
-    if ((m_name.find('[') != std::string::npos))
-    {
-        PWARN ("Name '%s' contains invalid characters '[]'. Refusing to save", m_name.c_str());
-        return true;
-    }
-
     auto keyfile = gnc_state_get_current ();
     auto group = csv_group_prefix + m_settings_type + " - " + m_name;
 
-    // Drop previous saved settings with this name
-    g_key_file_remove_group (keyfile, group.c_str(), nullptr);
-
-    // Start Saving the settings
-    // Common
+    // Start Saving the Common settings
     g_key_file_set_string (keyfile, group.c_str(), CSV_NAME, m_name.c_str());
 
     g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_START, m_skip_start_lines);
@@ -394,8 +209,7 @@ CsvImportSettings::save (void)
                     [&cmt_ss, &fmt_num](const GncDateFormat& fmt)
                         { cmt_ss << fmt_num++ << ": '" << fmt.m_fmt << "', "; });
     auto cmt = cmt_ss.str().substr(0, static_cast<long>(cmt_ss.tellp()) - 2);
-    g_key_file_set_comment (keyfile, group.c_str(), CSV_DATE,
-                            cmt.c_str(), nullptr);
+    g_key_file_set_comment (keyfile, group.c_str(), CSV_DATE, cmt.c_str(), nullptr);
     g_key_file_set_integer (keyfile, group.c_str(), CSV_CURRENCY, m_currency_format);
     g_key_file_set_string (keyfile, group.c_str(), CSV_ENCODING, m_encoding.c_str());
 
@@ -403,51 +217,6 @@ CsvImportSettings::save (void)
         g_key_file_set_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS,
                 (gint*)(m_column_widths.data()), m_column_widths.size());
 
-    // Transaction
-    if (m_settings_type.compare("TRANS") == 0)
-    {
-        g_key_file_set_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, m_multi_split);
-
-        if (m_base_account)
-            g_key_file_set_string (keyfile, group.c_str(), CSV_ACCOUNT, gnc_account_get_full_name(m_base_account));
-
-        std::vector<const char*> col_types_str;
-        for (auto col_type : m_column_types)
-            col_types_str.push_back(gnc_csv_col_type_strs[col_type]);
-
-        if (!col_types_str.empty())
-            g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
-                    col_types_str.data(), col_types_str.size());
-    }
-
-    // Price
-    if (m_settings_type.compare("PRICE") == 0)
-    {
-        if (m_to_currency)
-        {
-            auto unique_name = g_strconcat (gnc_commodity_get_namespace (m_to_currency), "::",
-                               gnc_commodity_get_mnemonic (m_to_currency), nullptr);
-            g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, unique_name);
-            g_free (unique_name);
-        }
-
-        if (m_from_commodity)
-        {
-            auto unique_name = g_strconcat (gnc_commodity_get_namespace (m_from_commodity), "::",
-                               gnc_commodity_get_mnemonic (m_from_commodity), nullptr);
-            g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, unique_name);
-            g_free (unique_name);
-        }
-
-        std::vector<const char*> col_types_str_price;
-        for (auto col_type : m_column_types_price)
-            col_types_str_price.push_back(gnc_price_col_type_strs[col_type]);
-
-        if (!col_types_str_price.empty())
-            g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
-                    col_types_str_price.data(), col_types_str_price.size());
-    }
-
     // Do a test read of encoding
     GError *key_error = nullptr;
     bool error = false;
@@ -460,33 +229,20 @@ CsvImportSettings::save (void)
     {
         if (key_error)
         {
-            g_warning ("Error reading group %s key %s: %s", group.c_str(), CSV_COL_TYPES, key_error->message);
+            g_warning ("Error reading group %s key %s: %s", group.c_str(), CSV_ENCODING, key_error->message);
             g_error_free (key_error);
         }
         else
-            g_warning ("Error comparing group %s key %s: '%s' and '%s'", group.c_str(), CSV_COL_TYPES, enc_str.c_str(), group.c_str());
+            g_warning ("Error comparing group %s key %s: '%s' and '%s'", group.c_str(), CSV_ENCODING, enc_str.c_str(), group.c_str());
         error = true;
     }
     return error;
 }
 
 void
-CsvImportSettings::remove (void)
+CsvImportSettings::remove_common (void)
 {
-    if (preset_is_reserved_name (m_name))
-        return;
-
     auto keyfile = gnc_state_get_current ();
     auto group = csv_group_prefix + m_settings_type + " - " + m_name;
     g_key_file_remove_group (keyfile, group.c_str(), nullptr);
 }
-
-
-bool
-CsvImportSettings::read_only (void)
-{
-    return ((m_name == no_settings) ||
-            (m_name == _(no_settings.c_str())) ||
-            (m_name == gnc_exp) ||
-            (m_name == _(gnc_exp.c_str())));
-}
diff --git a/gnucash/import-export/csv-imp/gnc-csv-import-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-import-settings.hpp
index e6ce4d4..6102fed 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-import-settings.hpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-import-settings.hpp
@@ -1,5 +1,5 @@
 /*******************************************************************\
- * gnc-csv-import-settings.h  -- Save and Load CSV Import Settings  *
+ * gnc-csv-import-settings.hpp -- Save and Load CSV Import Settings *
  *                                                                  *
  * Copyright (C) 2014 Robert Fewell                                 *
  *                                                                  *
@@ -20,7 +20,7 @@
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
 \********************************************************************/
-/** @file gnc-csv-import-settings.h
+/** @file gnc-csv-import-settings.hpp
     @brief CSV Import Settings
     @author Copyright (c) 2014 Robert Fewell
     @author Copyright (c) 2016 Geert Janssens
@@ -36,8 +36,8 @@ extern "C" {
 
 #include <string>
 #include <vector>
-#include "gnc-trans-props.hpp"
-#include "gnc-price-props.hpp"
+#include <boost/optional.hpp>
+#include <gnc-datetime.hpp>
 #include "gnc-tokenizer.hpp"
 
 /** Enumeration for separator checkbutton types. These are the
@@ -52,34 +52,25 @@ enum SETTINGS_COL {SET_GROUP, SET_NAME};
 struct CsvImportSettings
 {
     CsvImportSettings() : m_file_format (GncImpFileFormat::CSV), m_encoding {"UTF-8"},
-            m_multi_split (false), m_date_format {0}, m_currency_format {0},
+            m_date_format {0}, m_currency_format {0},
             m_skip_start_lines{0}, m_skip_end_lines{0}, m_skip_alt_lines (false),
-            m_separators {","}, m_load_error {false}, m_base_account {nullptr},
-            m_from_commodity {nullptr}, m_to_currency {nullptr} { }
+            m_separators {","}, m_load_error {false} { }
 
 /** Save the gathered widget properties to a key File.
  *
  *  @return true if there was a problem in saving.
  */
-bool save (void);
+bool save_common (void);
 
 /** Load the widget properties from a key File.
  *
  *  @return true if there was a problem.
  */
-bool load (void);
+bool load_common (void);
 
 /** Remove the preset from the state file.
  */
-void remove (void);
-
-/** Check whether the user is allowed to save (over) or delete this preset or not.
- *  The internally generated presets are read-only. The others
- *  can be saved to the state file or deleted.
- *
- *  @return true if there was a problem.
- */
-bool read_only (void);
+void remove_common (void);
 
 std::string   m_settings_type;                // Settings Type, TRANS, PRICE etc.
 
@@ -87,7 +78,6 @@ std::string   m_settings_type;                // Settings Type, TRANS, PRICE etc
 std::string   m_name;                         // Name given to this preset by the user
 GncImpFileFormat m_file_format;               // CSV import Format
 std::string   m_encoding;                     // File encoding
-bool          m_multi_split;                  // Assume multiple lines per transaction
 int           m_date_format;                  // Date Active id
 int           m_currency_format;              // Currency Active id
 uint32_t      m_skip_start_lines;             // Number of header rows to skip
@@ -96,28 +86,11 @@ bool          m_skip_alt_lines;               // Skip alternate rows
 std::string   m_separators;                   // Separators for csv format
 bool          m_load_error;                   // Was there an error while parsing the state file ?
 std::vector<uint32_t> m_column_widths;        // The Column widths
-
-// Transaction Settings
-Account      *m_base_account;                 // Base account
-std::vector<GncTransPropType> m_column_types; // The Column types in order
-
-// Price Settings
-gnc_commodity *m_from_commodity;              //  Price From Commodity
-gnc_commodity *m_to_currency;                 //  Price To Currency
-std::vector<GncPricePropType> m_column_types_price; // The Price Column types in order
 };
 
-using preset_vec = std::vector<std::shared_ptr<CsvImportSettings>>;
-/** Creates a vector of CsvImportSettings which combines
- *  - one or more internally defined presets
- *  - all preset found in the state key file.
- *
- *  @param set_type The type of setting stored in the
- *  key file, TRANS, PRICE, etc.
- *
- *  @return a reference to the populated vector.
- */
-const preset_vec& get_import_presets (const std::string& set_type);
+std::string get_no_settings (void);
+std::string get_gnc_exp (void);
+std::string get_prefix (void);
 
 /** Check whether name can be used as a preset name.
  *  The names of the internal presets are considered reserved.
@@ -125,4 +98,14 @@ const preset_vec& get_import_presets (const std::string& set_type);
  */
 bool preset_is_reserved_name (const std::string& name);
 
+/**************************************************
+ * handle_load_error
+ *
+ * record possible errors in the log file
+ * ignore key-not-found errors though. We'll just
+ * use a default value and go on.
+ **************************************************/
+bool
+handle_load_error (GError **key_error, const std::string& group);
+
 #endif
diff --git a/gnucash/import-export/csv-imp/gnc-csv-price-import-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-price-import-settings.cpp
new file mode 100644
index 0000000..8ebe9eb
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-csv-price-import-settings.cpp
@@ -0,0 +1,258 @@
+/*******************************************************************\
+ * gnc-csv-price-import-settings.cpp -- Price CSV Import Settings   *
+ *                                                                  *
+ * Copyright (C) 2017 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 gnc-csv-price-import-settings.cpp
+    @brief CSV Import Settings
+    @author Copyright (c) 2014 Robert Fewell
+    @author Copyright (c) 2016 Geert Janssens
+*/
+
+#include "gnc-csv-import-settings.hpp"
+#include "gnc-csv-price-import-settings.hpp"
+#include <sstream>
+
+extern "C"
+{
+#include <config.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "Account.h"
+#include "gnc-state.h"
+#include "gnc-ui-util.h"
+}
+
+const std::string settings_type{"PRICE"};
+
+#define CSV_COL_TYPES    "ColumnTypes"
+
+#define CSV_TO_CURR      "PriceToCurrency"
+#define CSV_FROM_COMM    "PriceFromCommodity"
+
+G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
+
+preset_vec_price presets_price;
+
+static std::shared_ptr<CsvPriceImpSettings> create_int_no_preset(void)
+{
+    auto preset = std::make_shared<CsvPriceImpSettings>();
+    preset->m_name = get_no_settings();
+    preset->m_settings_type = settings_type;
+
+    return preset;
+}
+
+static std::shared_ptr<CsvPriceImpSettings> create_int_gnc_exp_preset(void)
+{
+    auto preset = std::make_shared<CsvPriceImpSettings>();
+    preset->m_name = get_gnc_exp();
+    preset->m_skip_start_lines = 1;
+
+    /* FIXME date and currency format should still be aligned with export format!
+     * That's currently hard to do, because the export uses whatever the user
+     * had set as global preference.
+    preset->date_active = 0;
+    preset->currency_active = 0;
+    */
+    preset->m_column_types_price = {
+            GncPricePropType::DATE,
+            GncPricePropType::AMOUNT,
+            GncPricePropType::FROM_COMMODITY,
+            GncPricePropType::TO_CURRENCY
+    };
+    return preset;
+}
+
+/**************************************************
+ * find
+ *
+ * find all settings entries in the state key file
+ * based on settings type.
+ **************************************************/
+const preset_vec_price& get_import_presets_price (void)
+{
+    // Search all Groups in the state key file for ones starting with prefix
+    auto preset_names = std::vector<std::string>();
+    auto keyfile = gnc_state_get_current ();
+    gsize grouplength;
+    gchar **groups = g_key_file_get_groups (keyfile, &grouplength);
+
+    /* Start by building a sorted list of candidate presets as found in the state file */
+    for (gsize i=0; i < grouplength; i++)
+    {
+        auto group = std::string(groups[i]);
+        auto gp = get_prefix() + settings_type + " - ";
+        auto pos = group.find(gp);
+        if (pos == std::string::npos)
+            continue;
+
+        preset_names.push_back(group.substr(gp.size()));
+    }
+    // string array from the state file is no longer needed now.
+    g_strfreev (groups);
+
+    /* We want our settings to appear sorted alphabetically to the user */
+    std::sort(preset_names.begin(), preset_names.end());
+
+    /* Now add each preset to our global list */
+    presets_price.clear();
+
+    /* Start with the internally generated ones */
+    presets_price.push_back(create_int_no_preset());
+    //presets_price.push_back(create_int_gnc_exp_preset()); // Not Required
+
+    /* Then add all the ones we found in the state file */
+    for (auto preset_name : preset_names)
+    {
+        auto preset = std::make_shared<CsvPriceImpSettings>();
+        preset->m_settings_type = settings_type;
+        preset->m_name = preset_name;
+        preset->load();
+        presets_price.push_back(preset);
+    }
+    return presets_price;
+}
+
+/**************************************************
+ * load
+ *
+ * load the settings from a state key file
+ **************************************************/
+bool
+CsvPriceImpSettings::load (void)
+{
+    if (preset_is_reserved_name (m_name))
+        return true;
+
+    GError *key_error = nullptr;
+    m_load_error = false;
+    auto keyfile = gnc_state_get_current ();
+    auto group = get_prefix() + m_settings_type + " - " + m_name;
+
+    // Start Loading the settings
+    m_load_error = load_common(); // load the common settings
+
+    gchar *key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_TO_CURR, &key_error);
+    if (key_char && *key_char != '\0')
+        m_to_currency = parse_commodity_price_comm (key_char);
+    m_load_error |= handle_load_error (&key_error, group);
+    if (key_char)
+        g_free (key_char);
+
+    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_FROM_COMM, &key_error);
+    if (key_char && *key_char != '\0')
+        m_from_commodity = parse_commodity_price_comm (key_char);
+    m_load_error |= handle_load_error (&key_error, group);
+    if (key_char)
+        g_free (key_char);
+
+    gsize list_len;
+    m_column_types_price.clear();
+    gchar** col_types_str_price = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+            &list_len, &key_error);
+    for (uint32_t i = 0; i < list_len; i++)
+    {
+        auto col_types_it = std::find_if (gnc_price_col_type_strs.begin(),
+                gnc_price_col_type_strs.end(), test_price_prop_type_str (col_types_str_price[i]));
+        if (col_types_it != gnc_price_col_type_strs.end())
+        {
+            // Found a valid column type
+            m_column_types_price.push_back(col_types_it->first);
+        }
+        else
+            PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
+                    col_types_str_price[i]);
+    }
+    if (col_types_str_price)
+        g_strfreev (col_types_str_price);
+
+    return m_load_error;
+}
+
+/**************************************************
+ * save
+ *
+ * save settings to a key file
+ **************************************************/
+bool
+CsvPriceImpSettings::save (void)
+{
+    if (preset_is_reserved_name (m_name))
+    {
+        PWARN ("Ignoring attempt to save to reserved name '%s'", m_name.c_str());
+        return true;
+    }
+
+    if ((m_name.find('[') != std::string::npos))
+    {
+        PWARN ("Name '%s' contains invalid characters '[]'. Refusing to save", m_name.c_str());
+        return true;
+    }
+
+    auto keyfile = gnc_state_get_current ();
+    auto group = get_prefix() + m_settings_type + " - " + m_name;
+
+    // Drop previous saved settings with this name
+    g_key_file_remove_group (keyfile, group.c_str(), nullptr);
+
+    // Start Saving the settings
+    bool error = save_common(); // save the common settings
+
+    if (error)
+        return error;
+
+    if (m_to_currency)
+    {
+        auto unique_name = g_strconcat (gnc_commodity_get_namespace (m_to_currency), "::",
+                           gnc_commodity_get_mnemonic (m_to_currency), nullptr);
+        g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, unique_name);
+        g_free (unique_name);
+    }
+
+    if (m_from_commodity)
+    {
+        auto unique_name = g_strconcat (gnc_commodity_get_namespace (m_from_commodity), "::",
+                           gnc_commodity_get_mnemonic (m_from_commodity), nullptr);
+        g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, unique_name);
+        g_free (unique_name);
+    }
+
+    std::vector<const char*> col_types_str_price;
+    for (auto col_type : m_column_types_price)
+        col_types_str_price.push_back(gnc_price_col_type_strs[col_type]);
+
+    if (!col_types_str_price.empty())
+        g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+                col_types_str_price.data(), col_types_str_price.size());
+
+    return error;
+}
+
+void
+CsvPriceImpSettings::remove (void)
+{
+    if (preset_is_reserved_name (m_name))
+        return;
+
+    remove_common();
+}
diff --git a/gnucash/import-export/csv-imp/gnc-csv-price-import-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-price-import-settings.hpp
new file mode 100644
index 0000000..e0d52b4
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-csv-price-import-settings.hpp
@@ -0,0 +1,79 @@
+/*******************************************************************\
+ * gnc-csv-price-import-settings.hpp  -- Price CSV Import Settings  *
+ *                                                                  *
+ * Copyright (C) 2017 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 gnc-csv-price-import-settings.hpp
+    @brief CSV Import Settings
+    @author Copyright (c) 2014 Robert Fewell
+    @author Copyright (c) 2016 Geert Janssens
+*/
+#ifndef GNC_CSV_PRICE_IMPORT_SETTINGS_H
+#define GNC_CSV_PRICE_IMPORT_SETTINGS_H
+
+extern "C" {
+#include <config.h>
+#include "Account.h"
+#include "gnc-commodity.h"
+}
+
+#include <string>
+#include <vector>
+#include "gnc-price-props.hpp"
+#include "gnc-tokenizer.hpp"
+#include "gnc-csv-import-settings.hpp"
+
+struct CsvPriceImpSettings : public CsvImportSettings
+{
+    CsvPriceImpSettings() : m_from_commodity {nullptr}, m_to_currency {nullptr} { }
+
+/** Save the gathered widget properties to a key File.
+ *
+ *  @return true if there was a problem in saving.
+ */
+bool save (void);
+
+/** Load the widget properties from a key File.
+ *
+ *  @return true if there was a problem.
+ */
+bool load (void);
+
+/** Remove the preset from the state file.
+ */
+void remove (void);
+
+// Price Settings
+gnc_commodity *m_from_commodity;                    //  Price From Commodity
+gnc_commodity *m_to_currency;                       //  Price To Currency
+std::vector<GncPricePropType> m_column_types_price; // The Price Column types in order
+};
+
+using preset_vec_price = std::vector<std::shared_ptr<CsvPriceImpSettings>>;
+
+/** Creates a vector of CsvPriceImpSettings which combines
+ *  - one or more internally defined presets
+ *  - all preset found in the state key file.
+ *
+ *  @return a reference to the populated vector.
+ */
+const preset_vec_price& get_import_presets_price (void);
+
+#endif
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-import-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-trans-import-settings.cpp
new file mode 100644
index 0000000..17ac2b7
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-import-settings.cpp
@@ -0,0 +1,262 @@
+/*******************************************************************\
+ * gnc-csv-trans-import-settings.cpp -- Trans CSV Import Settings   *
+ *                                                                  *
+ * Copyright (C) 2014 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 gnc-csv-trans-import-settings.cpp
+    @brief CSV Import Settings
+    @author Copyright (c) 2014 Robert Fewell
+    @author Copyright (c) 2016 Geert Janssens
+*/
+
+#include "gnc-csv-import-settings.hpp"
+#include "gnc-csv-trans-import-settings.hpp"
+#include <sstream>
+
+extern "C"
+{
+#include <config.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include "Account.h"
+#include "gnc-state.h"
+#include "gnc-ui-util.h"
+}
+
+const std::string settings_type{"TRANS"};
+
+#define CSV_COL_TYPES    "ColumnTypes"
+
+#define CSV_ACCOUNT      "BaseAccount"
+#define CSV_MULTI_SPLIT  "MultiSplit"
+
+G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
+
+preset_vec_trans presets_trans;
+
+static std::shared_ptr<CsvTransImpSettings> create_int_no_preset(void)
+{
+    auto preset = std::make_shared<CsvTransImpSettings>();
+    preset->m_name = get_no_settings();
+    preset->m_settings_type = settings_type;
+
+    return preset;
+}
+
+static std::shared_ptr<CsvTransImpSettings> create_int_gnc_exp_preset(void)
+{
+    auto preset = std::make_shared<CsvTransImpSettings>();
+    preset->m_name = get_gnc_exp();
+    preset->m_skip_start_lines = 1;
+    preset->m_multi_split = true;
+
+    /* FIXME date and currency format should still be aligned with export format!
+     * That's currently hard to do, because the export uses whatever the user
+     * had set as global preference.
+    preset->date_active = 0;
+    preset->currency_active = 0;
+    */
+    preset->m_column_types = {
+            GncTransPropType::DATE,
+            GncTransPropType::UNIQUE_ID,
+            GncTransPropType::NUM,
+            GncTransPropType::DESCRIPTION,
+            GncTransPropType::NOTES,
+            GncTransPropType::COMMODITY,
+            GncTransPropType::VOID_REASON,
+            GncTransPropType::ACTION,
+            GncTransPropType::MEMO,
+            GncTransPropType::ACCOUNT,
+            GncTransPropType::NONE,
+            GncTransPropType::NONE,
+            GncTransPropType::DEPOSIT,
+            GncTransPropType::REC_STATE,
+            GncTransPropType::REC_DATE,
+            GncTransPropType::PRICE
+    };
+    return preset;
+}
+
+/**************************************************
+ * find
+ *
+ * find all settings entries in the state key file
+ * based on settings type.
+ **************************************************/
+const preset_vec_trans& get_import_presets_trans (void)
+{
+    // Search all Groups in the state key file for ones starting with prefix
+    auto preset_names = std::vector<std::string>();
+    auto keyfile = gnc_state_get_current ();
+    gsize grouplength;
+    gchar **groups = g_key_file_get_groups (keyfile, &grouplength);
+
+    /* Start by building a sorted list of candidate presets as found in the state file */
+    for (gsize i=0; i < grouplength; i++)
+    {
+        auto group = std::string(groups[i]);
+        auto gp = get_prefix() + settings_type + " - ";
+        auto pos = group.find(gp);
+        if (pos == std::string::npos)
+            continue;
+
+        preset_names.push_back(group.substr(gp.size()));
+    }
+    // string array from the state file is no longer needed now.
+    g_strfreev (groups);
+
+    /* We want our settings to appear sorted alphabetically to the user */
+    std::sort(preset_names.begin(), preset_names.end());
+
+    /* Now add each preset to our global list */
+    presets_trans.clear();
+
+    /* Start with the internally generated ones */
+    presets_trans.push_back(create_int_no_preset());
+    presets_trans.push_back(create_int_gnc_exp_preset());
+
+    /* Then add all the ones we found in the state file */
+    for (auto preset_name : preset_names)
+    {
+        auto preset = std::make_shared<CsvTransImpSettings>();
+        preset->m_settings_type = settings_type;
+        preset->m_name = preset_name;
+        preset->load();
+        presets_trans.push_back(preset);
+    }
+    return presets_trans;
+}
+
+/**************************************************
+ * load
+ *
+ * load the settings from a state key file
+ **************************************************/
+bool
+CsvTransImpSettings::load (void)
+{
+    if (preset_is_reserved_name (m_name))
+        return true;
+
+    GError *key_error = nullptr;
+    m_load_error = false;
+    auto keyfile = gnc_state_get_current ();
+    auto group = get_prefix() + m_settings_type + " - " + m_name;
+
+    // Start Loading the settings
+    m_load_error = load_common(); // load the common settings
+
+    m_multi_split = g_key_file_get_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, &key_error);
+    m_load_error |= handle_load_error (&key_error, group);
+
+    gchar *key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ACCOUNT, &key_error);
+    if (key_char && *key_char != '\0')
+        m_base_account = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
+    m_load_error |= handle_load_error (&key_error, group);
+    if (key_char)
+        g_free (key_char);
+
+    gsize list_len;
+    m_column_types.clear();
+    gchar** col_types_str = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+            &list_len, &key_error);
+    for (uint32_t i = 0; i < list_len; i++)
+    {
+        auto col_types_it = std::find_if (gnc_csv_col_type_strs.begin(),
+                gnc_csv_col_type_strs.end(), test_prop_type_str (col_types_str[i]));
+        if (col_types_it != gnc_csv_col_type_strs.end())
+        {
+            /* Found a valid column type. Now check whether it is allowed
+             * in the selected mode (two-split vs multi-split) */
+            auto prop = sanitize_trans_prop (col_types_it->first, m_multi_split);
+                m_column_types.push_back(prop);
+            if (prop != col_types_it->first)
+                PWARN("Found column type '%s', but this is blacklisted when multi-split mode is %s. "
+                      "Inserting column type 'NONE' instead'.",
+                        col_types_it->second, m_multi_split ? "enabled" : "disabled");
+        }
+        else
+            PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
+                    col_types_str[i]);
+    }
+    if (col_types_str)
+        g_strfreev (col_types_str);
+
+    return m_load_error;
+}
+
+/**************************************************
+ * save
+ *
+ * save settings to a key file
+ **************************************************/
+bool
+CsvTransImpSettings::save (void)
+{
+    if (preset_is_reserved_name (m_name))
+    {
+        PWARN ("Ignoring attempt to save to reserved name '%s'", m_name.c_str());
+        return true;
+    }
+
+    if ((m_name.find('[') != std::string::npos))
+    {
+        PWARN ("Name '%s' contains invalid characters '[]'. Refusing to save", m_name.c_str());
+        return true;
+    }
+
+    auto keyfile = gnc_state_get_current ();
+    auto group = get_prefix() + m_settings_type + " - " + m_name;
+
+    // Drop previous saved settings with this name
+    g_key_file_remove_group (keyfile, group.c_str(), nullptr);
+
+    // Start Saving the settings
+    bool error = save_common(); // save the common settings
+
+    if (error)
+        return error;
+
+    g_key_file_set_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, m_multi_split);
+
+    if (m_base_account)
+        g_key_file_set_string (keyfile, group.c_str(), CSV_ACCOUNT, gnc_account_get_full_name(m_base_account));
+
+    std::vector<const char*> col_types_str;
+    for (auto col_type : m_column_types)
+        col_types_str.push_back(gnc_csv_col_type_strs[col_type]);
+
+    if (!col_types_str.empty())
+        g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+                col_types_str.data(), col_types_str.size());
+
+    return error;
+}
+
+void
+CsvTransImpSettings::remove (void)
+{
+    if (preset_is_reserved_name (m_name))
+        return;
+
+    remove_common();
+}
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-import-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-trans-import-settings.hpp
new file mode 100644
index 0000000..c93ef3a
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-import-settings.hpp
@@ -0,0 +1,79 @@
+/*******************************************************************\
+ * gnc-csv-trans-import-settings.hpp  -- Trans CSV Import Settings  *
+ *                                                                  *
+ * Copyright (C) 2017 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 gnc-csv-trans-import-settings.hpp
+    @brief CSV Import Settings
+    @author Copyright (c) 2014 Robert Fewell
+    @author Copyright (c) 2016 Geert Janssens
+*/
+#ifndef GNC_CSV_TRANS_IMPORT_SETTINGS_H
+#define GNC_CSV_TRANS_IMPORT_SETTINGS_H
+
+extern "C" {
+#include <config.h>
+#include "Account.h"
+#include "gnc-commodity.h"
+}
+
+#include <string>
+#include <vector>
+#include "gnc-trans-props.hpp"
+#include "gnc-tokenizer.hpp"
+#include "gnc-csv-import-settings.hpp"
+
+struct CsvTransImpSettings : public CsvImportSettings
+{
+    CsvTransImpSettings() : m_base_account {nullptr}, m_multi_split (false) { }
+
+/** Save the gathered widget properties to a key File.
+ *
+ *  @return true if there was a problem in saving.
+ */
+bool save (void);
+
+/** Load the widget properties from a key File.
+ *
+ *  @return true if there was a problem.
+ */
+bool load (void);
+
+/** Remove the preset from the state file.
+ */
+void remove (void);
+
+// Transaction Settings
+Account      *m_base_account;                 // Base account
+bool          m_multi_split;                  // Assume multiple lines per transaction
+std::vector<GncTransPropType> m_column_types; // The Column types in order
+};
+
+using preset_vec_trans = std::vector<std::shared_ptr<CsvTransImpSettings>>;
+
+/** Creates a vector of CsvTransImpSettings which combines
+ *  - one or more internally defined presets
+ *  - all preset found in the state key file.
+ *
+ *  @return a reference to the populated vector.
+ */
+const preset_vec_trans& get_import_presets_trans (void);
+
+#endif
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index df91261..0bc1ead 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -42,7 +42,7 @@ extern "C" {
 #include "gnc-price-props.hpp"
 #include "gnc-csv-tokenizer.hpp"
 #include "gnc-fw-tokenizer.hpp"
-#include "gnc-csv-import-settings.hpp"
+#include "gnc-csv-price-import-settings.hpp"
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
@@ -272,7 +272,7 @@ void GncPriceImport::separators (std::string separators)
 }
 std::string GncPriceImport::separators () { return m_settings.m_separators; }
 
-void GncPriceImport::settings (const CsvImportSettings& settings)
+void GncPriceImport::settings (const CsvPriceImpSettings& settings)
 {
     /* First apply file format as this may recreate the tokenizer */
     file_format (settings.m_file_format);
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index c91943f..7d181ec 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -42,7 +42,7 @@ extern "C" {
 
 #include "gnc-tokenizer.hpp"
 #include "gnc-price-props.hpp"
-#include "gnc-csv-import-settings.hpp"
+#include "gnc-csv-price-import-settings.hpp"
 #include <boost/optional.hpp>
 
 /* A set of currency formats that the user sees. */
@@ -118,7 +118,7 @@ public:
     void separators (std::string separators);
     std::string separators ();
 
-    void settings (const CsvImportSettings& settings);
+    void settings (const CsvPriceImpSettings& settings);
     bool save_settings ();
 
     void settings_name (std::string name);
@@ -164,7 +164,7 @@ private:
      */
     void update_price_props (uint32_t row, uint32_t col, GncPricePropType prop_type);
 
-    CsvImportSettings m_settings;
+    CsvPriceImpSettings m_settings;
     bool m_skip_errors;
     bool m_over_write;
 };
diff --git a/gnucash/import-export/csv-imp/gnc-tx-import.cpp b/gnucash/import-export/csv-imp/gnc-tx-import.cpp
index eddbd75..a43f29c 100644
--- a/gnucash/import-export/csv-imp/gnc-tx-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-tx-import.cpp
@@ -39,7 +39,7 @@ extern "C" {
 #include "gnc-trans-props.hpp"
 #include "gnc-csv-tokenizer.hpp"
 #include "gnc-fw-tokenizer.hpp"
-#include "gnc-csv-import-settings.hpp"
+#include "gnc-csv-trans-import-settings.hpp"
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
@@ -293,7 +293,7 @@ void GncTxImport::separators (std::string separators)
 }
 std::string GncTxImport::separators () { return m_settings.m_separators; }
 
-void GncTxImport::settings (const CsvImportSettings& settings)
+void GncTxImport::settings (const CsvTransImpSettings& settings)
 {
     /* First apply file format as this may recreate the tokenizer */
     file_format (settings.m_file_format);
diff --git a/gnucash/import-export/csv-imp/gnc-tx-import.hpp b/gnucash/import-export/csv-imp/gnc-tx-import.hpp
index 87e4ea4..4fc339c 100644
--- a/gnucash/import-export/csv-imp/gnc-tx-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-tx-import.hpp
@@ -43,7 +43,7 @@ extern "C" {
 
 #include "gnc-tokenizer.hpp"
 #include "gnc-trans-props.hpp"
-#include "gnc-csv-import-settings.hpp"
+#include "gnc-csv-trans-import-settings.hpp"
 #include <boost/optional.hpp>
 
 
@@ -136,7 +136,7 @@ public:
     void separators (std::string separators);
     std::string separators ();
 
-    void settings (const CsvImportSettings& settings);
+    void settings (const CsvTransImpSettings& settings);
     bool save_settings ();
 
     void settings_name (std::string name);
@@ -189,8 +189,8 @@ private:
     void update_pre_trans_props (uint32_t row, uint32_t col, GncTransPropType prop_type);
     void update_pre_split_props (uint32_t row, uint32_t col, GncTransPropType prop_type);
 
-    struct CsvTranSettings;
-    CsvImportSettings m_settings;
+    struct CsvTranImpSettings; //FIXME do we need this line
+    CsvTransImpSettings m_settings;
     bool m_skip_errors;
     bool m_req_mapped_accts;
 

commit ba5ca5bd551a6bf4f8066a4533a44e792fbe09d1
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Dec 11 09:53:20 2017 +0000

    Remove surplus statement

diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index 360859d..c91943f 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -164,7 +164,6 @@ private:
      */
     void update_price_props (uint32_t row, uint32_t col, GncPricePropType prop_type);
 
-    struct CsvTranSettings;
     CsvImportSettings m_settings;
     bool m_skip_errors;
     bool m_over_write;

commit 0534ba4f8b9a69d39a524be282b2bcd737594f33
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sun Dec 10 11:59:40 2017 +0000

    Update file with changes for transient dialog changes

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 398a52c..8bb371b 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -704,13 +704,13 @@ CsvImpPriceAssist::file_confirm_cb ()
     catch (std::ifstream::failure& e)
     {
         /* File loading failed ... */
-        gnc_error_dialog (GTK_WIDGET(csv_imp_asst), "%s", e.what());
+        gnc_error_dialog (GTK_WINDOW(csv_imp_asst), "%s", e.what());
         return;
     }
     catch (std::range_error &e)
     {
         /* Parsing failed ... */
-        gnc_error_dialog (GTK_WIDGET(csv_imp_asst), "%s", e.what());
+        gnc_error_dialog (GTK_WINDOW(csv_imp_asst), "%s", e.what());
         return;
     }
     /* Get settings store and populate */
@@ -818,7 +818,7 @@ CsvImpPriceAssist::preview_settings_load ()
 
     price_imp->settings (*preset);
     if (preset->m_load_error)
-        gnc_error_dialog (GTK_WIDGET(csv_imp_asst),
+        gnc_error_dialog (GTK_WINDOW(csv_imp_asst),
             "%s", _("There were problems reading some saved settings, continuing to load.\n"
                     "Please review and save again."));
 
@@ -840,7 +840,7 @@ CsvImpPriceAssist::preview_settings_delete ()
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
-    auto response = gnc_ok_cancel_dialog (GTK_WIDGET(csv_imp_asst),
+    auto response = gnc_ok_cancel_dialog (GTK_WINDOW(csv_imp_asst),
                                 GTK_RESPONSE_CANCEL,
                                 "%s", _("Delete the Import Settings."));
     if (response == GTK_RESPONSE_OK)
@@ -875,7 +875,7 @@ CsvImpPriceAssist::preview_settings_save ()
 
             if (preset && (preset->m_name == std::string(new_name)))
             {
-                auto response = gnc_ok_cancel_dialog (GTK_WIDGET(csv_imp_asst),
+                auto response = gnc_ok_cancel_dialog (GTK_WINDOW(csv_imp_asst),
                         GTK_RESPONSE_OK,
                         "%s", _("Setting name already exists, over write?"));
                 if (response != GTK_RESPONSE_OK)
@@ -890,7 +890,7 @@ CsvImpPriceAssist::preview_settings_save ()
     /* All checks passed, let's save this preset */
     if (!price_imp->save_settings())
     {
-        gnc_info_dialog (GTK_WIDGET(csv_imp_asst),
+        gnc_info_dialog (GTK_WINDOW(csv_imp_asst),
             "%s", _("The settings have been saved."));
 
         // Update the settings store
@@ -915,7 +915,7 @@ CsvImpPriceAssist::preview_settings_save ()
         }
     }
     else
-        gnc_error_dialog (GTK_WIDGET(csv_imp_asst),
+        gnc_error_dialog (GTK_WINDOW(csv_imp_asst),
             "%s", _("There was a problem saving the settings, please try again."));
 }
 
@@ -996,7 +996,7 @@ void CsvImpPriceAssist::preview_update_separators (GtkWidget* widget)
         /* 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 (GTK_WIDGET(csv_imp_asst), "Error in parsing");
+        gnc_error_dialog (GTK_WINDOW(csv_imp_asst), "Error in parsing");
         /* If we're here because the user changed the file format, we should just wait for the user
          * to update the configuration */
         if (!widget)
@@ -1046,7 +1046,7 @@ void CsvImpPriceAssist::preview_update_file_format ()
     catch (std::range_error &e)
     {
         /* Parsing failed ... */
-        gnc_error_dialog (nullptr, "%s", e.what());
+        gnc_error_dialog (GTK_WINDOW (csv_imp_asst), "%s", e.what());
         return;
     }
     catch (...)
@@ -1082,7 +1082,7 @@ CsvImpPriceAssist::preview_update_encoding (const char* encoding)
         catch (...)
         {
             /* If it fails, change back to the old encoding. */
-            gnc_error_dialog (nullptr, "%s", _("Invalid encoding selected"));
+            gnc_error_dialog (GTK_WINDOW (csv_imp_asst), "%s", _("Invalid encoding selected"));
             go_charmap_sel_set_encoding (encselector, previous_encoding.c_str());
         }
     }
@@ -1319,7 +1319,7 @@ fixed_context_menu_handler_price (GnumericPopupMenuElement const *element,
     }
     catch(std::range_error& e)
     {
-        gnc_error_dialog (nullptr, "%s", e.what());
+        gnc_error_dialog (GTK_WINDOW (info->csv_imp_asst), "%s", e.what());
         return false;
     }
     info->preview_refresh_table ();
@@ -1364,7 +1364,7 @@ CsvImpPriceAssist::preview_split_column (int col, int offset)
     }
     catch (std::range_error& e)
     {
-        gnc_error_dialog (nullptr, "%s", e.what());
+        gnc_error_dialog (GTK_WINDOW (csv_imp_asst), "%s", e.what());
         return;
     }
     preview_refresh_table();
@@ -1799,7 +1799,7 @@ CsvImpPriceAssist::assist_finish ()
         /* Oops! This shouldn't happen when using the import assistant !
          * Inform the user and go back to the preview page.
          */
-        gnc_error_dialog (GTK_WIDGET(csv_imp_asst),
+        gnc_error_dialog (GTK_WINDOW(csv_imp_asst),
             _("An unexpected error has occurred while creating prices. Please report this as a bug.\n\n"
               "Error message:\n%s"), err.what());
         gtk_assistant_set_current_page (csv_imp_asst, 2);

commit 8ee6783b4b3e65cfaace37a5a4f9d4b31f574495
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sun Dec 10 11:58:09 2017 +0000

    Replace magic numbers used in std::get... with values from enum

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index fbc563c..398a52c 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -1564,12 +1564,12 @@ void CsvImpPriceAssist::preview_refresh_table ()
         GtkTreeIter iter;
         gtk_list_store_append (store, &iter);
         preview_row_fill_state_cells (store, &iter,
-                std::get<1>(parse_line), std::get<3>(parse_line));
+                std::get<PL_ERROR>(parse_line), std::get<PL_SKIP>(parse_line));
 
         /* Fill the data cells. */
-        for (auto cell_str_it = std::get<0>(parse_line).cbegin(); cell_str_it != std::get<0>(parse_line).cend(); cell_str_it++)
+        for (auto cell_str_it = std::get<PL_INPUT>(parse_line).cbegin(); cell_str_it != std::get<PL_INPUT>(parse_line).cend(); cell_str_it++)
         {
-            uint32_t pos = PREV_N_FIXED_COLS + cell_str_it - std::get<0>(parse_line).cbegin();
+            uint32_t pos = PREV_N_FIXED_COLS + cell_str_it - std::get<PL_INPUT>(parse_line).cbegin();
             gtk_list_store_set (store, &iter, pos, cell_str_it->c_str(), -1);
         }
     }
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 61c876d..df91261 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -54,7 +54,6 @@ const gchar* currency_format_user_price[] = {N_("Locale"),
 
 
 /** Constructor for GncPriceImport.
- * @return Pointer to a new GncCsvParseData
  */
 GncPriceImport::GncPriceImport(GncImpFileFormat format)
 {
@@ -247,12 +246,12 @@ void GncPriceImport::update_skipped_lines(boost::optional<uint32_t> start, boost
 
     for (uint32_t i = 0; i < m_parsed_lines.size(); i++)
     {
-        std::get<3>(m_parsed_lines[i]) =
+        std::get<PL_SKIP>(m_parsed_lines[i]) =
             ((i < skip_start_lines()) ||             // start rows to skip
              (i >= m_parsed_lines.size() - skip_end_lines()) ||          // end rows to skip
              (((i - skip_start_lines()) % 2 == 1) && // skip every second row...
                   skip_alt_lines()) ||                   // ...if requested
-             (m_skip_errors && !std::get<1>(m_parsed_lines[i]).empty())); // skip lines with errors
+             (m_skip_errors && !std::get<PL_ERROR>(m_parsed_lines[i]).empty())); // skip lines with errors
     }
 }
 
@@ -493,7 +492,7 @@ std::string GncPriceImport::verify ()
     auto have_line_errors = false;
     for (auto line : m_parsed_lines)
     {
-        if (!std::get<3>(line) && !std::get<1>(line).empty())
+        if (!std::get<PL_SKIP>(line) && !std::get<PL_ERROR>(line).empty())
         {
             have_line_errors = true;
             break;
@@ -624,7 +623,7 @@ void GncPriceImport::create_prices ()
             ++parsed_lines_it)
     {
         /* Skip current line if the user specified so */
-        if ((std::get<3>(*parsed_lines_it)))
+        if ((std::get<PL_SKIP>(*parsed_lines_it)))
             continue;
 
         /* Should not throw anymore, otherwise verify needs revision */
@@ -648,13 +647,13 @@ void GncPriceImport::update_price_props (uint32_t row, uint32_t col, GncPricePro
     if (prop_type == GncPricePropType::NONE)
         return; /* Only deal with price related properties. */
 
-    auto price_props = std::make_shared<GncImportPrice> (*(std::get<2>(m_parsed_lines[row])).get());
+    auto price_props = std::make_shared<GncImportPrice> (*(std::get<PL_PREPRICE>(m_parsed_lines[row])).get());
 
-    if (col >= std::get<0>(m_parsed_lines[row]).size())
+    if (col >= std::get<PL_INPUT>(m_parsed_lines[row]).size())
         price_props->reset (prop_type); //reset errors
     else
     {
-        auto value = std::get<0>(m_parsed_lines[row]).at(col);
+        auto value = std::get<PL_INPUT>(m_parsed_lines[row]).at(col);
         bool enable_test_empty = true;
         try
         {
@@ -683,12 +682,12 @@ void GncPriceImport::update_price_props (uint32_t row, uint32_t col, GncPricePro
             /* Do nothing, just prevent the exception from escalating up
              * However log the error if it happens on a row that's not skipped
              */
-            if (!std::get<3>(m_parsed_lines[row]))
+            if (!std::get<PL_SKIP>(m_parsed_lines[row]))
                 PINFO("User warning: %s", e.what());
         }
     }
     /* Store the result */
-    std::get<2>(m_parsed_lines[row]) = price_props;
+    std::get<PL_PREPRICE>(m_parsed_lines[row]) = price_props;
 }
 
 void
@@ -723,8 +722,8 @@ GncPriceImport::set_column_type_price (uint32_t position, GncPricePropType type,
         /* Reset date and currency formats for each price props object
          * to ensure column updates use the most recent one
          */
-        std::get<2>(*parsed_lines_it)->set_date_format (m_settings.m_date_format);
-        std::get<2>(*parsed_lines_it)->set_currency_format (m_settings.m_currency_format);
+        std::get<PL_PREPRICE>(*parsed_lines_it)->set_date_format (m_settings.m_date_format);
+        std::get<PL_PREPRICE>(*parsed_lines_it)->set_currency_format (m_settings.m_currency_format);
 
         uint32_t row = parsed_lines_it - m_parsed_lines.begin();
 
@@ -733,7 +732,7 @@ GncPriceImport::set_column_type_price (uint32_t position, GncPricePropType type,
          */
         if (old_type != type)
         {
-            auto old_col = std::get<0>(*parsed_lines_it).size(); // Deliberately out of bounds to trigger a reset!
+            auto old_col = std::get<PL_INPUT>(*parsed_lines_it).size(); // Deliberately out of bounds to trigger a reset!
             if ((old_type > GncPricePropType::NONE)
                     && (old_type <= GncPricePropType::PRICE_PROPS))
                 update_price_props (row, old_col, old_type);
@@ -744,8 +743,8 @@ GncPriceImport::set_column_type_price (uint32_t position, GncPricePropType type,
             update_price_props (row, position, type);
 
         /* Report errors if there are any */
-        auto price_errors = std::get<2>(*parsed_lines_it)->errors();
-        std::get<1>(*parsed_lines_it) =
+        auto price_errors = std::get<PL_PREPRICE>(*parsed_lines_it)->errors();
+        std::get<PL_ERROR>(*parsed_lines_it) =
                 price_errors +
                 (price_errors.empty() ? std::string() : "\n");
     }
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index fd8ebed..360859d 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -49,6 +49,18 @@ extern "C" {
 extern const int num_currency_formats_price;
 extern const gchar* currency_format_user_price[];
 
+/** An enum describing the columns found in a parse_line_t. Currently these are:
+ *  - a tokenized line of input
+ *  - an optional error string
+ *  - a struct to hold user selected properties for a price
+ *  - a boolean to mark the line as skipped by error and/or user or not */
+enum parse_line_cols {
+    PL_INPUT,
+    PL_ERROR,
+    PL_PREPRICE,
+    PL_SKIP
+};
+
 /** Tuple to hold
  *  - a tokenized line of input
  *  - an optional error string

commit 43f1b2fde04187f137447a9419a8938bb51e58ca
Merge: 66da4ae 288563c
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sun Dec 10 10:24:07 2017 +0000

    Merge branch 'prices-in' of /mygit/gnucash into prices-in


commit 288563c25e39be4c5a87f924d928be6689e00357
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Thu Dec 7 11:19:18 2017 +0000

    Add a test for empty values
    
    Some csv values are allowed to be empty based on options selected so
    add a test for this otherwise all values are required.

diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 705d37c..61c876d 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -649,15 +649,13 @@ void GncPriceImport::update_price_props (uint32_t row, uint32_t col, GncPricePro
         return; /* Only deal with price related properties. */
 
     auto price_props = std::make_shared<GncImportPrice> (*(std::get<2>(m_parsed_lines[row])).get());
-    auto value = std::string();
 
-    if (col < std::get<0>(m_parsed_lines[row]).size())
-        value = std::get<0>(m_parsed_lines[row]).at(col);
-
-    if (value.empty())
-        price_props->reset (prop_type);
+    if (col >= std::get<0>(m_parsed_lines[row]).size())
+        price_props->reset (prop_type); //reset errors
     else
     {
+        auto value = std::get<0>(m_parsed_lines[row]).at(col);
+        bool enable_test_empty = true;
         try
         {
             // set the from_commodity based on combo so we can test for same.
@@ -665,14 +663,20 @@ void GncPriceImport::update_price_props (uint32_t row, uint32_t col, GncPricePro
             {
                 if (m_settings.m_from_commodity)
                     price_props->set_from_commodity (m_settings.m_from_commodity);
+
+                if (m_settings.m_to_currency)
+                    enable_test_empty = false;
             }
             // set the to_currency based on combo so we can test for same.
             if (prop_type == GncPricePropType::FROM_COMMODITY)
             {
                 if (m_settings.m_to_currency)
                     price_props->set_to_currency (m_settings.m_to_currency);
+
+                if (m_settings.m_from_commodity)
+                    enable_test_empty = false;
             }
-            price_props->set(prop_type, value);
+            price_props->set(prop_type, value, enable_test_empty);
         }
         catch (const std::exception& e)
         {
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index 1ccd6e5..151bd38 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -135,13 +135,17 @@ gnc_commodity* parse_commodity_price_comm (const std::string& comm_str)
         return comm;
 }
 
-void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
+void GncImportPrice::set (GncPricePropType prop_type, const std::string& value, bool enable_test_empty)
 {
     try
     {
         // Drop any existing error for the prop_type we're about to set
         m_errors.erase(prop_type);
 
+        // conditional test for empty values
+        if (value.empty() && enable_test_empty)
+            throw std::invalid_argument (_("Column value can not be empty."));
+
         gnc_commodity *comm = nullptr;
         switch (prop_type)
         {
@@ -207,7 +211,8 @@ void GncImportPrice::reset (GncPricePropType prop_type)
 {
     try
     {
-        set (prop_type, std::string());
+        // set enable_test_empty to false to allow empty values
+        set (prop_type, std::string(), false);
     }
     catch (...)
     {
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 77e39dc..3a35861 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -86,7 +86,7 @@ public:
     GncImportPrice (int date_format, int currency_format) : m_date_format{date_format},
         m_currency_format{currency_format}{};
 
-    void set (GncPricePropType prop_type, const std::string& value);
+    void set (GncPricePropType prop_type, const std::string& value, bool enable_test_empty);
     void set_date_format (int date_format) { m_date_format = date_format ;}
     void set_currency_format (int currency_format) { m_currency_format = currency_format ;}
     void reset (GncPricePropType prop_type);

commit 16714a8c5b7e08eb727c905fce1582f68fffd5c2
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Thu Dec 7 11:17:14 2017 +0000

    Replace date parse function with one from gnc_datetime

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index af810cb..fbc563c 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -608,10 +608,8 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
 
         /* Add in the date format combo box and hook it up to an event handler. */
         date_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
-        for (int i = 0; i < num_date_formats_price; i++)
-        {
-            gtk_combo_box_text_append_text (date_format_combo, _(date_format_user_price[i]));
-        }
+        for (auto& date_fmt : GncDate::c_formats)
+            gtk_combo_box_text_append_text (date_format_combo, _(date_fmt.m_fmt.c_str()));
         gtk_combo_box_set_active (GTK_COMBO_BOX(date_format_combo), 0);
         g_signal_connect (G_OBJECT(date_format_combo), "changed",
                          G_CALLBACK(csv_price_imp_preview_date_fmt_sel_cb), this);
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 838c947..705d37c 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -46,14 +46,6 @@ extern "C" {
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
-const int num_date_formats_price = 5;
-const gchar* date_format_user_price[] = {N_("y-m-d"),
-                                   N_("d-m-y"),
-                                   N_("m-d-y"),
-                                   N_("d-m"),
-                                   N_("m-d")
-                                  };
-
 const int num_currency_formats_price = 3;
 const gchar* currency_format_user_price[] = {N_("Locale"),
                                        N_("Period: 123,456.78"),
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index 9959aaa..fd8ebed 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -49,10 +49,6 @@ extern "C" {
 extern const int num_currency_formats_price;
 extern const gchar* currency_format_user_price[];
 
-/* A set of date formats that the user sees. */
-extern const int num_date_formats_price;
-extern const gchar* date_format_user_price[];
-
 /** Tuple to hold
  *  - a tokenized line of input
  *  - an optional error string
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index 539f316..1ccd6e5 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -50,116 +50,6 @@ std::map<GncPricePropType, const char*> gnc_price_col_type_strs = {
         { GncPricePropType::TO_CURRENCY, N_("Currency To") },
 };
 
-/* Regular expressions used to parse dates per date format */
-const char* date_regex_price[] = {
-                             "(?:"                                   // either y-m-d
-                                 "(?<YEAR>[0-9]+)[-/.' ]+"
-                                 "(?<MONTH>[0-9]+)[-/.' ]+"
-                                 "(?<DAY>[0-9]+)"
-                             "|"                                     // or CCYYMMDD
-                                 "(?<YEAR>[0-9]{4})"
-                                 "(?<MONTH>[0-9]{2})"
-                                 "(?<DAY>[0-9]{2})"
-                             ")",
-
-                             "(?:"                                   // either d-m-y
-                                 "(?<DAY>[0-9]+)[-/.' ]+"
-                                 "(?<MONTH>[0-9]+)[-/.' ]+"
-                                 "(?<YEAR>[0-9]+)"
-                             "|"                                     // or DDMMCCYY
-                                 "(?<DAY>[0-9]{2})"
-                                 "(?<MONTH>[0-9]{2})"
-                                 "(?<YEAR>[0-9]{4})"
-                             ")",
-
-                             "(?:"                                   // either m-d-y
-                                 "(?<MONTH>[0-9]+)[-/.' ]+"
-                                 "(?<DAY>[0-9]+)[-/.' ]+"
-                                 "(?<YEAR>[0-9]+)"
-                             "|"                                     // or MMDDCCYY
-                                 "(?<MONTH>[0-9]{2})"
-                                 "(?<DAY>[0-9]{2})"
-                                 "(?<YEAR>[0-9]{4})"
-                             ")",
-
-                             "(?:"                                   // either d-m(-y)
-                                 "(?<DAY>[0-9]+)[-/.' ]+"
-                                 "(?<MONTH>[0-9]+)(?:[-/.' ]+"
-                                 "(?<YEAR>[0-9]+))?"
-                             "|"                                     // or DDMM(CCYY)
-                                 "(?<DAY>[0-9]{2})"
-                                 "(?<MONTH>[0-9]{2})"
-                                 "(?<YEAR>[0-9]+)?"
-                             ")",
-
-                             "(?:"                                   // either m-d(-y)
-                                 "(?<MONTH>[0-9]+)[-/.' ]+"
-                                 "(?<DAY>[0-9]+)(?:[-/.' ]+"
-                                 "(?<YEAR>[0-9]+))?"
-                             "|"                                     // or MMDD(CCYY)
-                                 "(?<MONTH>[0-9]{2})"
-                                 "(?<DAY>[0-9]{2})"
-                                 "(?<YEAR>[0-9]+)?"
-                             ")",
-};
-
-/** 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
- * @exception std::invalid_argument if the string can't be parsed into a date.
- * @return The parsed value of date_str on success, throws on failure
- */
-
-time64 parse_date_price (const std::string &date_str, int format)
-{
-    boost::regex r(date_regex_price[format]);
-    boost::smatch what;
-    if(!boost::regex_search(date_str, what, r))
-        throw std::invalid_argument (_("Value can't be parsed into a date using the selected date format."));  // regex didn't find a match
-
-    // Attention: different behavior from 2.6.x series !
-    // If date format without year was selected, the match
-    // should NOT have found a year.
-    if ((format >= 3) && (what.length("YEAR") != 0))
-        throw std::invalid_argument (_("Value appears to contain a year while the selected format forbids this."));
-
-    auto day = std::stoi (what.str("DAY"));
-    auto month = std::stoi (what.str("MONTH"));
-
-    int year;
-    if (format < 3)
-    {
-        /* The input dates have a year, so use that one */
-        year = std::stoi (what.str("YEAR"));
-
-        /* Handle two-digit years. */
-        if (year < 100)
-        {
-            /* We allow two-digit years in the range 1969 - 2068. */
-            if (year < 69)
-                year += 2000;
-            else
-                year += 1900;
-        }
-    }
-    else
-    {
-        /* The input dates don't have a year, so work with today's year.
-         */
-        gnc_timespec2dmy(timespec_now(), nullptr, nullptr, &year);
-    }
-
-    auto ts = gnc_dmy2timespec_neutral(day, month, year);
-    if (ts.tv_sec == INT64_MAX)
-        throw std::invalid_argument (_("Value can't be parsed into a date using the selected date format."));
-
-    return ts.tv_sec;
-}
-
-
 /** Convert str into a GncNumeric using the user-specified (import) currency format.
  * @param str The string to be parsed
  * @param currency_format The currency format to use.
@@ -257,7 +147,7 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
         {
             case GncPricePropType::DATE:
                 m_date = boost::none;
-                m_date = parse_date_price (value, m_date_format); // Throws if parsing fails
+                m_date = GncDate(value, GncDate::c_formats[m_date_format].m_fmt); // Throws if parsing fails
                 break;
 
             case GncPricePropType::AMOUNT:
@@ -357,7 +247,7 @@ Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
     }
 
     Timespec date;
-    timespecFromTime64 (&date, *m_date);
+    timespecFromTime64 (&date, static_cast<time64>(GncDateTime(*m_date, DayPart::neutral)));
     date.tv_nsec = 0;
 
     bool rev = false;
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 9ae4853..77e39dc 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -39,6 +39,7 @@ extern "C" {
 #include <map>
 #include <memory>
 #include <boost/optional.hpp>
+#include <gnc-datetime.hpp>
 #include <gnc-numeric.hpp>
 
 /** Enumeration for column types. These are the different types of
@@ -76,7 +77,6 @@ private:
     const char *m_name;
 };
 
-time64 parse_date_price (const std::string &date_str, int format);
 gnc_commodity* parse_commodity_price_comm (const std::string& comm_str);
 GncNumeric parse_amount_price (const std::string &str, int currency_format);
 
@@ -104,7 +104,7 @@ public:
 private:
     int m_date_format;
     int m_currency_format;
-    boost::optional<time64> m_date;
+    boost::optional<GncDate> m_date;
     boost::optional<GncNumeric> m_amount;
     boost::optional<gnc_commodity*> m_from_commodity;
     boost::optional<gnc_commodity*> m_to_currency;

commit ee2f301789b34d289743a1dd5bad4d1d07b09ba5
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Dec 4 14:25:02 2017 +0000

    Make changes for Gtk3 compatibility

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 0fa6273..af810cb 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -503,10 +503,12 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
     file_chooser = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_OPEN);
     g_signal_connect (G_OBJECT(file_chooser), "file-activated",
                       G_CALLBACK(csv_price_imp_file_confirm_cb), this);
-    auto button = gtk_button_new_from_stock (GTK_STOCK_OK);
+    auto button = gtk_button_new_with_label (_("OK"));
     gtk_widget_set_size_request (button, 100, -1);
     gtk_widget_show (button);
-    auto h_box = gtk_hbox_new (TRUE, 0);
+    auto h_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+    gtk_box_set_homogeneous (GTK_BOX (h_box), TRUE);
+    gtk_widget_set_hexpand (GTK_WIDGET(h_box), TRUE);
     gtk_box_pack_start (GTK_BOX(h_box), button, FALSE, FALSE, 0);
     gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(file_chooser), h_box);
     g_signal_connect (G_OBJECT(button), "clicked",
@@ -792,7 +794,9 @@ CsvImpPriceAssist::preview_settings_name (GtkEntry* entry)
     if (text)
         price_imp->settings_name(text);
 
-    auto combo = gtk_widget_get_parent (GTK_WIDGET(entry));
+    auto box = gtk_widget_get_parent (GTK_WIDGET(entry));
+    auto combo = gtk_widget_get_parent (GTK_WIDGET(box));
+
     preview_handle_save_del_sensitivity (GTK_COMBO_BOX(combo));
 }
 
@@ -1239,11 +1243,11 @@ enum
 static GnumericPopupMenuElement const popup_elements[] =
 {
     {
-        N_("Merge with column on _left"), GTK_STOCK_REMOVE,
+        N_("Merge with column on _left"), "list-remove",
         0, 1 << CONTEXT_STF_IMPORT_MERGE_LEFT, CONTEXT_STF_IMPORT_MERGE_LEFT
     },
     {
-        N_("Merge with column on _right"), GTK_STOCK_REMOVE,
+        N_("Merge with column on _right"), "list-remove",
         0, 1 << CONTEXT_STF_IMPORT_MERGE_RIGHT, CONTEXT_STF_IMPORT_MERGE_RIGHT
     },
     { "", nullptr, 0, 0, 0 },
@@ -1253,11 +1257,11 @@ static GnumericPopupMenuElement const popup_elements[] =
     },
     { "", nullptr, 0, 0, 0 },
     {
-        N_("_Widen this column"), GTK_STOCK_GO_FORWARD,
+        N_("_Widen this column"), "go-next",
         0, 1 << CONTEXT_STF_IMPORT_WIDEN, CONTEXT_STF_IMPORT_WIDEN
     },
     {
-        N_("_Narrow this column"), GTK_STOCK_GO_BACK,
+        N_("_Narrow this column"), "go-previous",
         0, 1 << CONTEXT_STF_IMPORT_NARROW, CONTEXT_STF_IMPORT_NARROW
     },
     { nullptr, nullptr, 0, 0, 0 },
@@ -1429,7 +1433,7 @@ CsvImpPriceAssist::preview_row_fill_state_cells (GtkListStore *store, GtkTreeIte
         fcolor = "black";
         bcolor = "pink";
         c_err_msg = err_msg.c_str();
-        icon_name = GTK_STOCK_DIALOG_ERROR;
+        icon_name = "dialog-error";
     }
     gtk_list_store_set (store, iter,
             PREV_COL_FCOLOR, fcolor,
@@ -1480,13 +1484,13 @@ void
 CsvImpPriceAssist::preview_style_column (uint32_t col_num, GtkTreeModel* model)
 {
     auto col = gtk_tree_view_get_column (treeview, col_num);
-    auto renderer = static_cast<GtkCellRenderer*>(gtk_tree_view_column_get_cell_renderers(col)->data);
+    auto renderer = static_cast<GtkCellRenderer*>(gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(col))->data);
 
     /* First column -the error status column- is rendered differently */
     if (col_num == 0)
     {
         gtk_tree_view_column_set_attributes (col, renderer,
-                "stock-id", PREV_COL_ERR_ICON,
+                "icon-name", PREV_COL_ERR_ICON,
                 "cell-background", PREV_COL_BCOLOR, nullptr);
         g_object_set (G_OBJECT(renderer), "stock-size", GTK_ICON_SIZE_MENU, nullptr);
         g_object_set (G_OBJECT(col), "sizing", GTK_TREE_VIEW_COLUMN_FIXED,
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
index 33db266..b1ba9c0 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
 <interface>
-  <requires lib="gtk+" version="2.24"/>
-  <!-- interface-naming-policy project-wide -->
+  <requires lib="gtk+" version="3.10"/>
   <object class="GtkAdjustment" id="end_row_adj">
     <property name="upper">1000</property>
     <property name="step_increment">1</property>
@@ -38,11 +38,11 @@
     <property name="title" translatable="yes">CSV Price Import</property>
     <property name="default_width">400</property>
     <property name="default_height">500</property>
+    <signal name="apply" handler="csv_price_imp_assist_finish_cb" swapped="no"/>
+    <signal name="cancel" handler="csv_price_imp_assist_cancel_cb" swapped="no"/>
     <signal name="close" handler="csv_price_imp_assist_close_cb" swapped="no"/>
     <signal name="destroy" handler="csv_price_imp_assist_destroy_cb" swapped="no"/>
-    <signal name="apply" handler="csv_price_imp_assist_finish_cb" swapped="no"/>
     <signal name="prepare" handler="csv_price_imp_assist_prepare_cb" swapped="no"/>
-    <signal name="cancel" handler="csv_price_imp_assist_cancel_cb" swapped="no"/>
     <child>
       <placeholder/>
     </child>
@@ -76,10 +76,11 @@ Click on 'Forward' to proceed or 'Cancel' to Abort Import.</property>
       </packing>
     </child>
     <child>
-      <object class="GtkVBox" id="file_page">
+      <object class="GtkBox" id="file_page">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="border_width">12</property>
+        <property name="orientation">vertical</property>
         <child>
           <object class="GtkLabel" id="label7">
             <property name="visible">True</property>
@@ -101,20 +102,19 @@ Select location and file name for the Import, then click 'OK'...
       </packing>
     </child>
     <child>
-      <object class="GtkVBox" id="preview_page">
+      <object class="GtkBox" 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="orientation">vertical</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkTable" id="table1">
+          <object class="GtkGrid" id="table1">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="n_rows">2</property>
-            <property name="n_columns">2</property>
-            <property name="column_spacing">5</property>
             <property name="row_spacing">5</property>
+            <property name="column_spacing">5</property>
             <child>
               <object class="GtkFrame" id="frame6">
                 <property name="visible">True</property>
@@ -129,7 +129,7 @@ Select location and file name for the Import, then click 'OK'...
                     <property name="left_padding">5</property>
                     <property name="right_padding">5</property>
                     <child>
-                      <object class="GtkHBox" id="combo_hbox">
+                      <object class="GtkBox" id="combo_hbox">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <child>
@@ -143,7 +143,7 @@ Select location and file name for the Import, then click 'OK'...
                               <object class="GtkImage" id="image2">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="stock">gtk-delete</property>
+                                <property name="icon_name">edit-delete</property>
                               </object>
                             </child>
                           </object>
@@ -165,7 +165,7 @@ Select location and file name for the Import, then click 'OK'...
                               <object class="GtkImage" id="image1">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="stock">gtk-save</property>
+                                <property name="icon_name">document-save</property>
                               </object>
                             </child>
                           </object>
@@ -184,6 +184,7 @@ Select location and file name for the Import, then click 'OK'...
                   <object class="GtkLabel" id="label12">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
+                    <property name="halign">start</property>
                     <property name="label" translatable="yes"> <b>Load and Save Settings</b></property>
                     <property name="use_markup">True</property>
                     <property name="track_visited_links">False</property>
@@ -191,8 +192,8 @@ Select location and file name for the Import, then click 'OK'...
                 </child>
               </object>
               <packing>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options">GTK_FILL</property>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
               </packing>
             </child>
             <child>
@@ -210,15 +211,14 @@ Select location and file name for the Import, then click 'OK'...
                     <property name="left_padding">5</property>
                     <property name="right_padding">5</property>
                     <child>
-                      <object class="GtkVBox" id="vbox1">
+                      <object class="GtkBox" id="vbox1">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
+                        <property name="orientation">vertical</property>
                         <child>
-                          <object class="GtkTable" id="table4">
+                          <object class="GtkGrid" id="table4">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
-                            <property name="n_rows">2</property>
-                            <property name="n_columns">2</property>
                             <child>
                               <object class="GtkRadioButton" id="csv_button">
                                 <property name="label" translatable="yes">Separators</property>
@@ -226,10 +226,15 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_fixed_sel_cb" swapped="no"/>
                               </object>
+                              <packing>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
+                              </packing>
                             </child>
                             <child>
                               <object class="GtkRadioButton" id="fixed_button">
@@ -238,24 +243,24 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <property name="group">csv_button</property>
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHSeparator" id="hseparator1">
+                              <object class="GtkSeparator" id="hseparator1">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                               </object>
                               <packing>
-                                <property name="right_attach">2</property>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="width">2</property>
                               </packing>
                             </child>
                           </object>
@@ -266,12 +271,10 @@ Select location and file name for the Import, then click 'OK'...
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkTable" id="separator_table">
+                          <object class="GtkGrid" id="separator_table">
                             <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>
                             <child>
                               <object class="GtkCheckButton" id="space_cbutton">
@@ -280,12 +283,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </object>
                               <packing>
-                                <property name="x_options">GTK_FILL</property>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
@@ -295,14 +299,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </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>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
@@ -312,15 +315,14 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </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>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
@@ -330,14 +332,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </object>
                               <packing>
+                                <property name="left_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>
@@ -347,16 +348,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
+                                <property name="left_attach">0</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>
@@ -366,16 +364,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </object>
                               <packing>
-                                <property name="left_attach">2</property>
-                                <property name="right_attach">3</property>
+                                <property name="left_attach">1</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>
@@ -385,14 +380,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </object>
                               <packing>
+                                <property name="left_attach">0</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>
                             <child>
@@ -401,22 +395,18 @@ Select location and file name for the Import, then click 'OK'...
                                 <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">●</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>
                                 <signal name="changed" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </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>
+                            <child>
+                              <placeholder/>
+                            </child>
                           </object>
                           <packing>
                             <property name="expand">False</property>
@@ -425,7 +415,7 @@ Select location and file name for the Import, then click 'OK'...
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkHBox" id="fw_instructions_hbox">
+                          <object class="GtkBox" id="fw_instructions_hbox">
                             <property name="can_focus">False</property>
                             <property name="no_show_all">True</property>
                             <child>
@@ -433,8 +423,7 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="yalign">0</property>
-                                <property name="stock">gtk-dialog-info</property>
+                                <property name="icon_name">dialog-information</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
@@ -444,67 +433,61 @@ Select location and file name for the Import, then click 'OK'...
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkTable" id="table2">
+                              <object class="GtkGrid" id="table2">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="n_rows">2</property>
-                                <property name="n_columns">2</property>
                                 <child>
                                   <object class="GtkLabel" id="label2">
                                     <property name="visible">True</property>
                                     <property name="can_focus">False</property>
-                                    <property name="yalign">0</property>
-                                    <property name="xpad">5</property>
                                     <property name="label" translatable="yes">•</property>
                                     <property name="use_markup">True</property>
                                     <property name="wrap">True</property>
                                   </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">0</property>
+                                  </packing>
                                 </child>
                                 <child>
                                   <object class="GtkLabel" id="label3">
                                     <property name="visible">True</property>
                                     <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
+                                    <property name="halign">start</property>
                                     <property name="label" translatable="yes">Double-click anywhere on the table below to insert a column break</property>
                                     <property name="use_markup">True</property>
                                     <property name="wrap">True</property>
                                   </object>
                                   <packing>
                                     <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="y_options"/>
+                                    <property name="top_attach">0</property>
                                   </packing>
                                 </child>
                                 <child>
                                   <object class="GtkLabel" id="label4">
                                     <property name="visible">True</property>
                                     <property name="can_focus">False</property>
-                                    <property name="yalign">0</property>
-                                    <property name="xpad">5</property>
                                     <property name="label" translatable="yes">•</property>
                                     <property name="use_markup">True</property>
                                     <property name="wrap">True</property>
                                   </object>
                                   <packing>
+                                    <property name="left_attach">0</property>
                                     <property name="top_attach">1</property>
-                                    <property name="bottom_attach">2</property>
                                   </packing>
                                 </child>
                                 <child>
                                   <object class="GtkLabel" id="label5">
                                     <property name="visible">True</property>
                                     <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
+                                    <property name="halign">start</property>
                                     <property name="label" translatable="yes">Right-click anywhere in a column to modify it (widen, narrow, merge)</property>
                                     <property name="use_markup">True</property>
                                     <property name="wrap">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="y_options"/>
                                   </packing>
                                 </child>
                               </object>
@@ -522,17 +505,17 @@ Select location and file name for the Import, then click 'OK'...
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkTable" id="table5">
+                          <object class="GtkGrid" id="table5">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
-                            <property name="n_rows">2</property>
                             <child>
-                              <object class="GtkHSeparator" id="hseparator4">
+                              <object class="GtkSeparator" id="hseparator4">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                               </object>
                               <packing>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
@@ -540,15 +523,15 @@ Select location and file name for the Import, then click 'OK'...
                                 <property name="label" translatable="yes">Allow existing prices to be over written.</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
+                                <property name="focus_on_click">False</property>
                                 <property name="receives_default">False</property>
                                 <property name="tooltip_text" translatable="yes">Normally prices are not over written, select this to change that. This setting is not saved.</property>
-                                <property name="focus_on_click">False</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_overwrite_cb" swapped="no"/>
                               </object>
                               <packing>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
                               </packing>
                             </child>
                           </object>
@@ -567,16 +550,15 @@ Select location and file name for the Import, then click 'OK'...
                     <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="halign">start</property>
                     <property name="label" translatable="yes"><b>File Format</b></property>
                     <property name="use_markup">True</property>
                   </object>
                 </child>
               </object>
               <packing>
+                <property name="left_attach">0</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>
@@ -592,18 +574,17 @@ Select location and file name for the Import, then click 'OK'...
                     <property name="left_padding">5</property>
                     <property name="right_padding">5</property>
                     <child>
-                      <object class="GtkVBox" id="vbox6">
+                      <object class="GtkBox" id="vbox6">
                         <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="orientation">vertical</property>
                         <child>
-                          <object class="GtkTable" id="table3">
+                          <object class="GtkGrid" id="table3">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
-                            <property name="n_rows">6</property>
-                            <property name="n_columns">2</property>
-                            <property name="column_spacing">5</property>
                             <property name="row_spacing">5</property>
+                            <property name="column_spacing">5</property>
                             <child>
                               <object class="GtkAlignment" id="date_format_container">
                                 <property name="visible">True</property>
@@ -613,23 +594,19 @@ Select location and file name for the Import, then click 'OK'...
                               </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>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label20">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
+                                <property name="halign">start</property>
                                 <property name="label" translatable="yes">Date Format</property>
                               </object>
                               <packing>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
@@ -640,34 +617,31 @@ Select location and file name for the Import, then click 'OK'...
                               </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="x_options">GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label21">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
+                                <property name="halign">start</property>
                                 <property name="label" translatable="yes">Currency Format</property>
                               </object>
                               <packing>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label16">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
+                                <property name="halign">start</property>
                                 <property name="label" translatable="yes">Encoding</property>
                               </object>
                               <packing>
-                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
@@ -678,38 +652,35 @@ Select location and file name for the Import, then click 'OK'...
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="x_options">GTK_FILL</property>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label17">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
+                                <property name="halign">start</property>
                                 <property name="label" translatable="yes">Leading Lines to Skip</property>
                               </object>
                               <packing>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">4</property>
-                                <property name="bottom_attach">5</property>
-                                <property name="x_options">GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label18">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
+                                <property name="halign">start</property>
                                 <property name="label" translatable="yes">Trailing Lines to Skip</property>
                               </object>
                               <packing>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">5</property>
-                                <property name="bottom_attach">6</property>
-                                <property name="x_options">GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHBox" id="hbox2">
+                              <object class="GtkBox" id="hbox2">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                                 <child>
@@ -717,11 +688,8 @@ Select location and file name for the Import, then click 'OK'...
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="invisible_char">●</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>
                                     <property name="numeric">True</property>
                                     <signal name="value-changed" handler="csv_price_imp_preview_srow_cb" swapped="no"/>
@@ -735,13 +703,11 @@ Select location and file name for the Import, then click 'OK'...
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
                                 <property name="top_attach">4</property>
-                                <property name="bottom_attach">5</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHBox" id="hbox3">
+                              <object class="GtkBox" id="hbox3">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                                 <child>
@@ -749,11 +715,8 @@ Select location and file name for the Import, then click 'OK'...
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="invisible_char">●</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>
                                     <property name="numeric">True</property>
                                     <signal name="value-changed" handler="csv_price_imp_preview_erow_cb" swapped="no"/>
@@ -767,20 +730,18 @@ Select location and file name for the Import, then click 'OK'...
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
                                 <property name="top_attach">5</property>
-                                <property name="bottom_attach">6</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHSeparator" id="hseparator2">
+                              <object class="GtkSeparator" id="hseparator2">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                               </object>
                               <packing>
-                                <property name="right_attach">2</property>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">3</property>
-                                <property name="bottom_attach">4</property>
+                                <property name="width">2</property>
                               </packing>
                             </child>
                           </object>
@@ -800,6 +761,7 @@ Select location and file name for the Import, then click 'OK'...
 For example
 * if 'Leading Lines to Skip' is set to 3, the first line to import will be line 4. Lines 5, 7, 9,... will be skipped.
 * if 'Leading Lines to Skip' is set to 4, the first line to import will be line 5. Lines 6, 8, 10,... will be skipped.</property>
+                            <property name="halign">start</property>
                             <property name="draw_indicator">True</property>
                             <signal name="toggled" handler="csv_price_imp_preview_skiprows_cb" swapped="no"/>
                           </object>
@@ -817,6 +779,7 @@ For example
                   <object class="GtkLabel" id="label13">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
+                    <property name="halign">start</property>
                     <property name="label" translatable="yes"><b>Miscellaneous</b></property>
                     <property name="use_markup">True</property>
                   </object>
@@ -824,11 +787,7 @@ For example
               </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>
@@ -842,7 +801,7 @@ For example
           </packing>
         </child>
         <child>
-          <object class="GtkHBox" id="hbox1">
+          <object class="GtkBox" id="hbox1">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <child>
@@ -859,7 +818,7 @@ For example
                     <property name="left_padding">5</property>
                     <property name="right_padding">5</property>
                     <child>
-                      <object class="GtkHBox" id="commodity_hbox">
+                      <object class="GtkBox" id="commodity_hbox">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <child>
@@ -913,7 +872,7 @@ For example
                     <property name="left_padding">5</property>
                     <property name="right_padding">5</property>
                     <child>
-                      <object class="GtkHBox" id="currency_hbox">
+                      <object class="GtkBox" id="currency_hbox">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <child>
@@ -964,16 +923,15 @@ For example
           <object class="GtkScrolledWindow" id="scrolledwindow2">
             <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="viewport2">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <child>
-                  <object class="GtkVBox" id="vbox8">
+                  <object class="GtkBox" id="vbox8">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
                     <child>
                       <object class="GtkTreeView" id="ctreeview">
                         <property name="visible">True</property>
@@ -981,6 +939,9 @@ For example
                         <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>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection"/>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -994,6 +955,9 @@ For example
                         <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>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection"/>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">True</property>
@@ -1013,7 +977,7 @@ For example
           </packing>
         </child>
         <child>
-          <object class="GtkHBox" id="hbox13">
+          <object class="GtkBox" id="hbox13">
             <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>
@@ -1022,8 +986,7 @@ For example
                 <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="yalign">0</property>
-                <property name="stock">gtk-dialog-info</property>
+                <property name="icon_name">dialog-information</property>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -1037,7 +1000,7 @@ For example
                 <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="halign">start</property>
                 <property name="label" translatable="yes">Select the type of each column to import.</property>
               </object>
               <packing>
@@ -1055,7 +1018,7 @@ For example
           </packing>
         </child>
         <child>
-          <object class="GtkHBox" id="hbox14">
+          <object class="GtkBox" id="hbox14">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <child>
@@ -1063,7 +1026,6 @@ For example
                 <property name="label" translatable="yes">Skip Errors</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">False</property>
-                <property name="xalign">1</property>
                 <property name="image_position">right</property>
                 <property name="draw_indicator">True</property>
                 <signal name="toggled" handler="csv_price_imp_preview_skiperrors_cb" swapped="no"/>
@@ -1089,10 +1051,11 @@ For example
       </packing>
     </child>
     <child>
-      <object class="GtkVBox" id="confirm_page">
+      <object class="GtkBox" id="confirm_page">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="border_width">12</property>
+        <property name="orientation">vertical</property>
         <child>
           <object class="GtkAlignment" id="alignment2">
             <property name="visible">True</property>
@@ -1122,10 +1085,11 @@ Cancel to abort.</b></property>
       </packing>
     </child>
     <child>
-      <object class="GtkVBox" id="summary_page">
+      <object class="GtkBox" id="summary_page">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="border_width">12</property>
+        <property name="orientation">vertical</property>
         <child>
           <object class="GtkLabel" id="summary_label">
             <property name="visible">True</property>
@@ -1147,5 +1111,12 @@ Cancel to abort.</b></property>
         <property name="complete">True</property>
       </packing>
     </child>
+    <child internal-child="action_area">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+      </packing>
+    </child>
   </object>
 </interface>
diff --git a/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c b/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
index c14092d..3cecf66 100644
--- a/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
+++ b/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
@@ -57,7 +57,7 @@ static GtkActionEntry gnc_plugin_actions [] =
         G_CALLBACK (gnc_plugin_csv_import_trans_cmd)
     },
     {
-        "CsvImportPriceAction", GTK_STOCK_CONVERT, N_("Import _Prices from a CSV file..."), NULL,
+        "CsvImportPriceAction", "go-previous", N_("Import _Prices from a CSV file..."), NULL,
         N_("Import Prices from a CSV file"),
         G_CALLBACK (gnc_plugin_csv_import_price_cmd)
     },

commit 1aa3601e01cc07748d7f4a70e3f9be06af3a18e3
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 12:04:51 2017 +0000

    Pot file changes for new files and settings rename

diff --git a/po/POTFILES.in b/po/POTFILES.in
index bced61f..7f74af4 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -287,17 +287,21 @@ gnucash/import-export/csv-exp/gnc-plugin-csv-export.c
 [type: gettext/gsettings]gnucash/import-export/csv-exp/gschemas/org.gnucash.dialogs.export.csv.gschema.xml.in.in
 gnucash/import-export/csv-imp/assistant-csv-account-import.c
 gnucash/import-export/csv-imp/assistant-csv-account-import.glade
+gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+gnucash/import-export/csv-imp/assistant-csv-price-import.glade
 gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
 gnucash/import-export/csv-imp/assistant-csv-trans-import.glade
 gnucash/import-export/csv-imp/csv-account-import.c
 gnucash/import-export/csv-imp/gnc-csv-account-map.c
 gnucash/import-export/csv-imp/gnc-csv-gnumeric-popup.c
 gnucash/import-export/csv-imp/gnc-csv-tokenizer.cpp
-gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
 gnucash/import-export/csv-imp/gnc-dummy-tokenizer.cpp
 gnucash/import-export/csv-imp/gnc-fw-tokenizer.cpp
 gnucash/import-export/csv-imp/gncmod-csv-import.c
 gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
+gnucash/import-export/csv-imp/gnc-price-import.cpp
+gnucash/import-export/csv-imp/gnc-price-props.cpp
 gnucash/import-export/csv-imp/gnc-tokenizer.cpp
 gnucash/import-export/csv-imp/gnc-trans-props.cpp
 gnucash/import-export/csv-imp/gnc-tx-import.cpp

commit 71bf7d01fdd1b044723daec5cfbba2cb17c061bf
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 12:03:14 2017 +0000

    Rename gnc-csv-trans-settings.* to gnc-csv-import-settings.*
    
    Change the name of the import settings files as they do not just deal
    with transactions and all associated required changes.

diff --git a/gnucash/import-export/csv-imp/CMakeLists.txt b/gnucash/import-export/csv-imp/CMakeLists.txt
index 44a14ca..65082be 100644
--- a/gnucash/import-export/csv-imp/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/CMakeLists.txt
@@ -17,7 +17,7 @@ SET(csv_import_SOURCES
   gnc-csv-account-map.c
   gnc-csv-gnumeric-popup.c
   gnc-csv-tokenizer.cpp
-  gnc-csv-trans-settings.cpp
+  gnc-csv-import-settings.cpp
   gnc-dummy-tokenizer.cpp
   gnc-fw-tokenizer.cpp
   gnc-price-import.cpp
@@ -45,7 +45,7 @@ SET(csv_import_noinst_HEADERS
   gnc-csv-account-map.h
   gnc-csv-gnumeric-popup.h
   gnc-csv-tokenizer.hpp
-  gnc-csv-trans-settings.hpp
+  gnc-csv-import-settings.hpp
   gnc-dummy-tokenizer.hpp
   gnc-fw-tokenizer.hpp
   gnc-price-import.hpp
diff --git a/gnucash/import-export/csv-imp/Makefile.am b/gnucash/import-export/csv-imp/Makefile.am
index 4b473de..f1b501f 100644
--- a/gnucash/import-export/csv-imp/Makefile.am
+++ b/gnucash/import-export/csv-imp/Makefile.am
@@ -19,7 +19,7 @@ libgncmod_csv_import_la_SOURCES = \
   gnc-tokenizer.cpp \
   gnc-tx-import.cpp \
   gnc-trans-props.cpp \
-  gnc-csv-trans-settings.cpp
+  gnc-csv-import-settings.cpp
 
 noinst_HEADERS = \
   assistant-csv-account-import.h \
@@ -37,7 +37,7 @@ noinst_HEADERS = \
   gnc-tokenizer.hpp \
   gnc-tx-import.hpp \
   gnc-trans-props.hpp \
-  gnc-csv-trans-settings.hpp
+  gnc-csv-import-settings.hpp
 
 libgncmod_csv_import_la_LDFLAGS = -avoid-version
 
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 21126ea..0fa6273 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -52,7 +52,7 @@ extern "C"
 #include "go-charmap-sel.h"
 }
 
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 #include "gnc-price-import.hpp"
 #include "gnc-fw-tokenizer.hpp"
 #include "gnc-csv-tokenizer.hpp"
@@ -738,7 +738,7 @@ void CsvImpPriceAssist::preview_populate_settings_combo()
     gtk_list_store_clear (GTK_LIST_STORE(model));
 
     // Append the default entry
-    auto presets = get_trans_presets (settings_type);
+    auto presets = get_import_presets (settings_type);
     for (auto preset : presets)
     {
         GtkTreeIter iter;
@@ -766,11 +766,11 @@ void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
     /* Handle sensitivity of the delete and save button */
     if (gtk_combo_box_get_active_iter (combo, &iter))
     {
-        CsvTransSettings *preset;
+        CsvImportSettings *preset;
         GtkTreeModel *model = gtk_combo_box_get_model (combo);
         gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
-        if (preset && !trans_preset_is_reserved_name (preset->m_name))
+        if (preset && !preset_is_reserved_name (preset->m_name))
         {
             /* Current preset is not read_only, so buttons can be enabled */
             can_delete = true;
@@ -778,7 +778,7 @@ void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
         }
     }
     else if (entry_text && (strlen (entry_text) > 0) &&
-            !trans_preset_is_reserved_name (std::string(entry_text)))
+            !preset_is_reserved_name (std::string(entry_text)))
         can_save = true;
 
     gtk_widget_set_sensitive (save_button, can_save);
@@ -807,7 +807,7 @@ CsvImpPriceAssist::preview_settings_load ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvTransSettings *preset = nullptr;
+    CsvImportSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -834,7 +834,7 @@ CsvImpPriceAssist::preview_settings_delete ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvTransSettings *preset = nullptr;
+    CsvImportSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -868,7 +868,7 @@ CsvImpPriceAssist::preview_settings_save ()
         while (valid)
         {
             // Walk through the list, reading each row
-            CsvTransSettings *preset;
+            CsvImportSettings *preset;
             gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
             if (preset && (preset->m_name == std::string(new_name)))
diff --git a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
index 07091f0..41779c6 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
@@ -58,7 +58,7 @@ extern "C"
 #include "go-charmap-sel.h"
 }
 
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 #include "gnc-tx-import.hpp"
 #include "gnc-fw-tokenizer.hpp"
 #include "gnc-csv-tokenizer.hpp"
@@ -679,7 +679,7 @@ void CsvImpTransAssist::preview_populate_settings_combo()
 
     // Append the default entry
 
-    auto presets = get_trans_presets (settings_type);
+    auto presets = get_import_presets (settings_type);
     for (auto preset : presets)
     {
         GtkTreeIter iter;
@@ -707,11 +707,11 @@ void CsvImpTransAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
     /* Handle sensitivity of the delete and save button */
     if (gtk_combo_box_get_active_iter (combo, &iter))
     {
-        CsvTransSettings *preset;
+        CsvImportSettings *preset;
         GtkTreeModel *model = gtk_combo_box_get_model (combo);
         gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
-        if (preset && !trans_preset_is_reserved_name (preset->m_name))
+        if (preset && !preset_is_reserved_name (preset->m_name))
         {
             /* Current preset is not read_only, so buttons can be enabled */
             can_delete = true;
@@ -719,7 +719,7 @@ void CsvImpTransAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
         }
     }
     else if (entry_text && (strlen (entry_text) > 0) &&
-            !trans_preset_is_reserved_name (std::string(entry_text)))
+            !preset_is_reserved_name (std::string(entry_text)))
         can_save = true;
 
     gtk_widget_set_sensitive (save_button, can_save);
@@ -752,7 +752,7 @@ CsvImpTransAssist::preview_settings_load ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvTransSettings *preset = nullptr;
+    CsvImportSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -779,7 +779,7 @@ CsvImpTransAssist::preview_settings_delete ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvTransSettings *preset = nullptr;
+    CsvImportSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -812,7 +812,7 @@ CsvImpTransAssist::preview_settings_save ()
         while (valid)
         {
             // Walk through the list, reading each row
-            CsvTransSettings *preset;
+            CsvImportSettings *preset;
             gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
             if (preset && (preset->m_name == std::string(new_name)))
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
similarity index 95%
rename from gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
rename to gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
index 3bbc984..0096c53 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
@@ -1,5 +1,5 @@
 /*******************************************************************\
- * gnc-csv-trans-settings.c -- Save and Load CSV Import Settings    *
+ * gnc-csv-import-settings.c -- Save and Load CSV Import Settings   *
  *                                                                  *
  * Copyright (C) 2014 Robert Fewell                                 *
  *                                                                  *
@@ -20,13 +20,13 @@
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
 \********************************************************************/
-/** @file gnc-csv-trans-settings.c
+/** @file gnc-csv-import-settings.c
     @brief CSV Import Settings
     @author Copyright (c) 2014 Robert Fewell
     @author Copyright (c) 2016 Geert Janssens
 */
 
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 #include <sstream>
 
 extern "C"
@@ -70,18 +70,18 @@ G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
 preset_vec presets;
 
-static std::shared_ptr<CsvTransSettings> create_int_no_preset(const std::string& set_type)
+static std::shared_ptr<CsvImportSettings> create_int_no_preset(const std::string& set_type)
 {
-    auto preset = std::make_shared<CsvTransSettings>();
+    auto preset = std::make_shared<CsvImportSettings>();
     preset->m_name = no_settings;
     preset->m_settings_type = set_type;
 
     return preset;
 }
 
-static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
+static std::shared_ptr<CsvImportSettings> create_int_gnc_exp_preset(void)
 {
-    auto preset = std::make_shared<CsvTransSettings>();
+    auto preset = std::make_shared<CsvImportSettings>();
     preset->m_name = gnc_exp;
     preset->m_skip_start_lines = 1;
     preset->m_multi_split = true;
@@ -119,7 +119,7 @@ static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
  * find all settings entries in the state key file
  * based on settings type.
  **************************************************/
-const preset_vec& get_trans_presets (const std::string& set_type)
+const preset_vec& get_import_presets (const std::string& set_type)
 {
 
     // Search all Groups in the state key file for ones starting with prefix
@@ -157,7 +157,7 @@ const preset_vec& get_trans_presets (const std::string& set_type)
     /* Then add all the ones we found in the state file */
     for (auto preset_name : preset_names)
     {
-        auto preset = std::make_shared<CsvTransSettings>();
+        auto preset = std::make_shared<CsvImportSettings>();
         preset->m_settings_type = set_type;
         preset->m_name = preset_name;
         preset->load();
@@ -166,7 +166,7 @@ const preset_vec& get_trans_presets (const std::string& set_type)
     return presets;
 }
 
-bool trans_preset_is_reserved_name (const std::string& name)
+bool preset_is_reserved_name (const std::string& name)
 {
     return ((name == no_settings) ||
             (name == _(no_settings.c_str())) ||
@@ -205,9 +205,9 @@ handle_load_error (GError **key_error, const std::string& group)
  * load the settings from a state key file
  **************************************************/
 bool
-CsvTransSettings::load (void)
+CsvImportSettings::load (void)
 {
-    if (trans_preset_is_reserved_name (m_name))
+    if (preset_is_reserved_name (m_name))
         return true;
 
     GError *key_error = nullptr;
@@ -355,9 +355,9 @@ CsvTransSettings::load (void)
  * save settings to a key file
  **************************************************/
 bool
-CsvTransSettings::save (void)
+CsvImportSettings::save (void)
 {
-    if (trans_preset_is_reserved_name (m_name))
+    if (preset_is_reserved_name (m_name))
     {
         PWARN ("Ignoring attempt to save to reserved name '%s'", m_name.c_str());
         return true;
@@ -471,9 +471,9 @@ CsvTransSettings::save (void)
 }
 
 void
-CsvTransSettings::remove (void)
+CsvImportSettings::remove (void)
 {
-    if (trans_preset_is_reserved_name (m_name))
+    if (preset_is_reserved_name (m_name))
         return;
 
     auto keyfile = gnc_state_get_current ();
@@ -483,7 +483,7 @@ CsvTransSettings::remove (void)
 
 
 bool
-CsvTransSettings::read_only (void)
+CsvImportSettings::read_only (void)
 {
     return ((m_name == no_settings) ||
             (m_name == _(no_settings.c_str())) ||
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-import-settings.hpp
similarity index 90%
rename from gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
rename to gnucash/import-export/csv-imp/gnc-csv-import-settings.hpp
index 7df293c..e6ce4d4 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-import-settings.hpp
@@ -1,5 +1,5 @@
 /*******************************************************************\
- * gnc-csv-trans-settings.h   -- Save and Load CSV Import Settings  *
+ * gnc-csv-import-settings.h  -- Save and Load CSV Import Settings  *
  *                                                                  *
  * Copyright (C) 2014 Robert Fewell                                 *
  *                                                                  *
@@ -20,13 +20,13 @@
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
 \********************************************************************/
-/** @file gnc-csv-trans-settings.h
+/** @file gnc-csv-import-settings.h
     @brief CSV Import Settings
     @author Copyright (c) 2014 Robert Fewell
     @author Copyright (c) 2016 Geert Janssens
 */
-#ifndef GNC_CSV_TRANS_SETTINGS_H
-#define GNC_CSV_TRANS_SETTINGS_H
+#ifndef GNC_CSV_IMPORT_SETTINGS_H
+#define GNC_CSV_IMPORT_SETTINGS_H
 
 extern "C" {
 #include <config.h>
@@ -49,9 +49,9 @@ enum SEP_BUTTON_TYPES {SEP_SPACE, SEP_TAB, SEP_COMMA, SEP_COLON, SEP_SEMICOLON,
 /** Enumeration for the settings combo's */
 enum SETTINGS_COL {SET_GROUP, SET_NAME};
 
-struct CsvTransSettings
+struct CsvImportSettings
 {
-    CsvTransSettings() : m_file_format (GncImpFileFormat::CSV), m_encoding {"UTF-8"},
+    CsvImportSettings() : m_file_format (GncImpFileFormat::CSV), m_encoding {"UTF-8"},
             m_multi_split (false), m_date_format {0}, m_currency_format {0},
             m_skip_start_lines{0}, m_skip_end_lines{0}, m_skip_alt_lines (false),
             m_separators {","}, m_load_error {false}, m_base_account {nullptr},
@@ -107,8 +107,8 @@ gnc_commodity *m_to_currency;                 //  Price To Currency
 std::vector<GncPricePropType> m_column_types_price; // The Price Column types in order
 };
 
-using preset_vec = std::vector<std::shared_ptr<CsvTransSettings>>;
-/** Creates a vector of CsvTransSettings which combines
+using preset_vec = std::vector<std::shared_ptr<CsvImportSettings>>;
+/** Creates a vector of CsvImportSettings which combines
  *  - one or more internally defined presets
  *  - all preset found in the state key file.
  *
@@ -117,12 +117,12 @@ using preset_vec = std::vector<std::shared_ptr<CsvTransSettings>>;
  *
  *  @return a reference to the populated vector.
  */
-const preset_vec& get_trans_presets (const std::string& set_type);
+const preset_vec& get_import_presets (const std::string& set_type);
 
 /** Check whether name can be used as a preset name.
  *  The names of the internal presets are considered reserved.
  *  A preset with such a name should not be saved or deleted.
  */
-bool trans_preset_is_reserved_name (const std::string& name);
+bool preset_is_reserved_name (const std::string& name);
 
 #endif
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 44a17b9..838c947 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -42,7 +42,7 @@ extern "C" {
 #include "gnc-price-props.hpp"
 #include "gnc-csv-tokenizer.hpp"
 #include "gnc-fw-tokenizer.hpp"
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
@@ -281,7 +281,7 @@ void GncPriceImport::separators (std::string separators)
 }
 std::string GncPriceImport::separators () { return m_settings.m_separators; }
 
-void GncPriceImport::settings (const CsvTransSettings& settings)
+void GncPriceImport::settings (const CsvImportSettings& settings)
 {
     /* First apply file format as this may recreate the tokenizer */
     file_format (settings.m_file_format);
@@ -315,7 +315,7 @@ void GncPriceImport::settings (const CsvTransSettings& settings)
 
 bool GncPriceImport::save_settings ()
 {
-    if (trans_preset_is_reserved_name (m_settings.m_name))
+    if (preset_is_reserved_name (m_settings.m_name))
         return true;
 
     /* separators are already copied to m_settings in the separators
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index be91941..9959aaa 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -42,7 +42,7 @@ extern "C" {
 
 #include "gnc-tokenizer.hpp"
 #include "gnc-price-props.hpp"
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 #include <boost/optional.hpp>
 
 /* A set of currency formats that the user sees. */
@@ -110,7 +110,7 @@ public:
     void separators (std::string separators);
     std::string separators ();
 
-    void settings (const CsvTransSettings& settings);
+    void settings (const CsvImportSettings& settings);
     bool save_settings ();
 
     void settings_name (std::string name);
@@ -157,7 +157,7 @@ private:
     void update_price_props (uint32_t row, uint32_t col, GncPricePropType prop_type);
 
     struct CsvTranSettings;
-    CsvTransSettings m_settings;
+    CsvImportSettings m_settings;
     bool m_skip_errors;
     bool m_over_write;
 };
diff --git a/gnucash/import-export/csv-imp/gnc-tx-import.cpp b/gnucash/import-export/csv-imp/gnc-tx-import.cpp
index daa85b4..eddbd75 100644
--- a/gnucash/import-export/csv-imp/gnc-tx-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-tx-import.cpp
@@ -39,7 +39,7 @@ extern "C" {
 #include "gnc-trans-props.hpp"
 #include "gnc-csv-tokenizer.hpp"
 #include "gnc-fw-tokenizer.hpp"
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
@@ -293,7 +293,7 @@ void GncTxImport::separators (std::string separators)
 }
 std::string GncTxImport::separators () { return m_settings.m_separators; }
 
-void GncTxImport::settings (const CsvTransSettings& settings)
+void GncTxImport::settings (const CsvImportSettings& settings)
 {
     /* First apply file format as this may recreate the tokenizer */
     file_format (settings.m_file_format);
@@ -329,7 +329,7 @@ void GncTxImport::settings (const CsvTransSettings& settings)
 bool GncTxImport::save_settings ()
 {
 
-    if (trans_preset_is_reserved_name (m_settings.m_name))
+    if (preset_is_reserved_name (m_settings.m_name))
         return true;
 
     /* separators are already copied to m_settings in the separators
diff --git a/gnucash/import-export/csv-imp/gnc-tx-import.hpp b/gnucash/import-export/csv-imp/gnc-tx-import.hpp
index 0c14a74..87e4ea4 100644
--- a/gnucash/import-export/csv-imp/gnc-tx-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-tx-import.hpp
@@ -43,7 +43,7 @@ extern "C" {
 
 #include "gnc-tokenizer.hpp"
 #include "gnc-trans-props.hpp"
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 #include <boost/optional.hpp>
 
 
@@ -136,7 +136,7 @@ public:
     void separators (std::string separators);
     std::string separators ();
 
-    void settings (const CsvTransSettings& settings);
+    void settings (const CsvImportSettings& settings);
     bool save_settings ();
 
     void settings_name (std::string name);
@@ -190,7 +190,7 @@ private:
     void update_pre_split_props (uint32_t row, uint32_t col, GncTransPropType prop_type);
 
     struct CsvTranSettings;
-    CsvTransSettings m_settings;
+    CsvImportSettings m_settings;
     bool m_skip_errors;
     bool m_req_mapped_accts;
 

commit 644a0aa06f09c49a99dd013f25c74af999f4fc46
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:56:25 2017 +0000

    Reorder the create price procedure.

diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index 0ea21f9..539f316 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -362,9 +362,20 @@ Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
 
     bool rev = false;
     auto amount = *m_amount;
+    Result ret_val = ADDED;
 
     GNCPrice *old_price = gnc_pricedb_lookup_day (pdb, *m_from_commodity, *m_to_currency, date);
 
+    // Should old price be over writen
+    if ((old_price != nullptr) && (over == true))
+    {
+        DEBUG("Over write");
+        gnc_pricedb_remove_price (pdb, old_price);
+        gnc_price_unref (old_price);
+        old_price = nullptr;
+        ret_val = REPLACED;
+    }
+
     if (gnc_commodity_is_currency (*m_from_commodity)) // Currency Import
     {
         // Check for currency in reverse direction.
@@ -373,9 +384,8 @@ Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
             // Check for price in reverse direction.
             if (gnc_commodity_equiv (gnc_price_get_currency (old_price), *m_from_commodity))
                 rev = true;
-
-            DEBUG("Commodity from is a Currency");
         }
+        DEBUG("Commodity from is a Currency");
 
         // Check for price less than 1, reverse if so.
         if (*m_amount < GncNumeric(1,1))
@@ -386,18 +396,6 @@ Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
         rev, gnc_commodity_get_fullname (*m_from_commodity), gnc_commodity_get_fullname (*m_to_currency),
         amount.to_string().c_str());
 
-    Result ret_val = ADDED;
-
-    // Should old price be over writen
-    if ((old_price != nullptr) && (over == true))
-    {
-        DEBUG("Over write");
-        gnc_pricedb_remove_price (pdb, old_price);
-        gnc_price_unref (old_price);
-        old_price = nullptr;
-        ret_val = REPLACED;
-    }
-
     // Create the new price
     if (old_price == nullptr)
     {

commit 62bbe4f951dbc8dbb9a1ac0b522e0fd33276e4b8
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:52:48 2017 +0000

    Add the ability to test from_commodity and to_currency being the same.
    
    To cover all combinations we need to test across the combo's and also
    the table entries when appropriate columns are set. Also need to force
    a reparse if any of the options change.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 14a8ffa..21126ea 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -94,6 +94,7 @@ public:
     void preview_update_currency_format ();
     void preview_update_currency ();
     void preview_update_commodity ();
+    void preview_reparse_col_type (GncPricePropType type);
     void preview_update_col_type (GtkComboBox* cbox);
     void preview_update_fw_columns (GtkTreeView* treeview, GdkEventButton* event);
 
@@ -1138,6 +1139,22 @@ enum PreviewDataTableCols {
     PREV_COL_ERR_ICON,
     PREV_N_FIXED_COLS };
 
+
+void
+CsvImpPriceAssist::preview_reparse_col_type (GncPricePropType type)
+{
+    auto column_types = price_imp->column_types_price();
+
+    // look for column type and force a reparse
+    auto col_type = std::find (column_types.begin(),
+                column_types.end(), type);
+    if (col_type != column_types.end())
+    {
+        price_imp->set_column_type_price (col_type -column_types.begin(),
+                        type, true);
+    }
+}
+
 /** 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 the selection, and any other columns containing that selection
@@ -1157,8 +1174,26 @@ void CsvImpPriceAssist::preview_update_col_type (GtkComboBox* cbox)
     gtk_tree_model_get (model, &iter, COL_TYPE_ID, &new_col_type, -1);
 
     auto col_num = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT(cbox), "col-num"));
+
+    auto column_types = price_imp->column_types_price();
+    auto old_col_type = column_types.at(col_num);
+
     price_imp->set_column_type_price (col_num, new_col_type);
 
+    // if old_col_type is TO_CURRENCY, force a reparse of commodity
+    if (old_col_type == GncPricePropType::TO_CURRENCY)
+    {
+        // look for a from_commodity column to reparse
+        preview_reparse_col_type (GncPricePropType::FROM_COMMODITY);
+    }
+
+    // if old_col_type is FROM_COMMODITY, force a reparse of currency
+    if (old_col_type == GncPricePropType::FROM_COMMODITY)
+    {
+        // look for a to_currency column to reparse
+        preview_reparse_col_type (GncPricePropType::TO_CURRENCY);
+    }
+
     /* Delay rebuilding our data table to avoid critical warnings due to
      * pending events still acting on them after this event is processed.
      */
@@ -1580,7 +1615,7 @@ void CsvImpPriceAssist::preview_refresh_table ()
 
     auto column_types = price_imp->column_types_price();
 
-    // look for a commodity column, clear the commdoity combo
+    // look for a commodity column, clear the commodity combo
     auto col_type_comm = std::find (column_types.begin(),
                 column_types.end(), GncPricePropType::FROM_COMMODITY);
     if (col_type_comm != column_types.end())
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index d5d3862..44a17b9 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -136,7 +136,6 @@ void GncPriceImport::over_write (bool over)
 {
     m_over_write = over;
 }
-
 bool GncPriceImport::over_write () { return m_over_write; }
 
 /** Sets a from commodity. This is the commodity all import data relates to.
@@ -147,18 +146,20 @@ bool GncPriceImport::over_write () { return m_over_write; }
 void GncPriceImport::from_commodity (gnc_commodity* from_commodity)
 {
     m_settings.m_from_commodity = from_commodity;
-
     if (m_settings.m_from_commodity)
     {
-        auto col_type = std::find (m_settings.m_column_types_price.begin(),
+        auto col_type_comm = std::find (m_settings.m_column_types_price.begin(),
                 m_settings.m_column_types_price.end(), GncPricePropType::FROM_COMMODITY);
 
-        if (col_type != m_settings.m_column_types_price.end())
-            set_column_type_price (col_type -m_settings.m_column_types_price.begin(),
+        if (col_type_comm != m_settings.m_column_types_price.end())
+            set_column_type_price (col_type_comm -m_settings.m_column_types_price.begin(),
                             GncPricePropType::NONE);
+
+        // force a refresh of the to_currency if the from_commodity is changed
+        std::vector<GncPricePropType> commodities = { GncPricePropType::TO_CURRENCY };
+        reset_formatted_column (commodities);
     }
 }
-
 gnc_commodity *GncPriceImport::from_commodity () { return m_settings.m_from_commodity; }
 
 /** Sets a to currency. This is the to currency all import data relates to.
@@ -169,18 +170,20 @@ gnc_commodity *GncPriceImport::from_commodity () { return m_settings.m_from_comm
 void GncPriceImport::to_currency (gnc_commodity* to_currency)
 {
     m_settings.m_to_currency = to_currency;
-
     if (m_settings.m_to_currency)
     {
-        auto col_type = std::find (m_settings.m_column_types_price.begin(),
+        auto col_type_currency = std::find (m_settings.m_column_types_price.begin(),
                 m_settings.m_column_types_price.end(), GncPricePropType::TO_CURRENCY);
 
-        if (col_type != m_settings.m_column_types_price.end())
-            set_column_type_price (col_type -m_settings.m_column_types_price.begin(),
+        if (col_type_currency != m_settings.m_column_types_price.end())
+            set_column_type_price (col_type_currency -m_settings.m_column_types_price.begin(),
                             GncPricePropType::NONE);
+
+        // force a refresh of the from_commodity if the to_currency is changed
+        std::vector<GncPricePropType> commodities = { GncPricePropType::FROM_COMMODITY };
+        reset_formatted_column (commodities);
     }
 }
-
 gnc_commodity *GncPriceImport::to_currency () { return m_settings.m_to_currency; }
 
 void GncPriceImport::reset_formatted_column (std::vector<GncPricePropType>& col_types)
@@ -453,6 +456,14 @@ void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
         if (!m_settings.m_from_commodity)
             error_msg.add_error( _("Please select a 'Commodity from' column or set a Commodity in the 'Commodity From' field."));
     }
+
+    /* Verify a 'Commodity from' does not equal 'Currency to'.
+     */
+    if ((m_settings.m_to_currency) && (m_settings.m_from_commodity))
+    {
+        if (gnc_commodity_equal (m_settings.m_to_currency, m_settings.m_from_commodity))
+            error_msg.add_error( _("'Commodity From' can not be the same as 'Currency To'."));
+    }
 }
 
 /* Check whether the chosen settings can successfully parse
@@ -539,7 +550,7 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
 
     error_message.clear();
 
-    // Add a CURRENCY_TO property with the selected 'currency to' if no 'currency to' column was set by the user
+    // Add a TO_CURRENCY property with the selected 'currency to' if no 'currency to' column was set by the user
     auto line_to_currency = price_props->get_to_currency();
     if (!line_to_currency)
     {
@@ -556,7 +567,7 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
         }
     }
 
-    // Add a COMMODITY_FROM property with the selected 'commodity from' if no 'commodity from' column was set by the user
+    // Add a FROM_COMMODITY property with the selected 'commodity from' if no 'commodity from' column was set by the user
     auto line_from_commodity = price_props->get_from_commodity();
     if (!line_from_commodity)
     {
@@ -657,6 +668,18 @@ void GncPriceImport::update_price_props (uint32_t row, uint32_t col, GncPricePro
     {
         try
         {
+            // set the from_commodity based on combo so we can test for same.
+            if (prop_type == GncPricePropType::TO_CURRENCY)
+            {
+                if (m_settings.m_from_commodity)
+                    price_props->set_from_commodity (m_settings.m_from_commodity);
+            }
+            // set the to_currency based on combo so we can test for same.
+            if (prop_type == GncPricePropType::FROM_COMMODITY)
+            {
+                if (m_settings.m_to_currency)
+                    price_props->set_to_currency (m_settings.m_to_currency);
+            }
             price_props->set(prop_type, value);
         }
         catch (const std::exception& e)

commit aff1c0c5a66e3d6861b25216066157754e4300d1
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:51:07 2017 +0000

    Add a test for from_commodity not being the same as to_currency

diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index 2deffb3..0ea21f9 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -269,7 +269,11 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
                 m_from_commodity = boost::none;
                 comm = parse_commodity_price_comm (value); // Throws if parsing fails
                 if (comm)
+                {
+                    if (m_to_currency == comm)
+                        throw std::invalid_argument (_("'Commodity From' can not be the same as 'Currency To' column type."));
                     m_from_commodity = comm;
+                }
                 break;
 
             case GncPricePropType::TO_CURRENCY:
@@ -277,6 +281,8 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
                 comm = parse_commodity_price_comm (value); // Throws if parsing fails
                 if (comm)
                 {
+                    if (m_from_commodity == comm)
+                        throw std::invalid_argument (_("'Currency To' can not be the same as 'Commodity From' column type."));
                     if (gnc_commodity_is_currency (comm) != true)
                         throw std::invalid_argument (_("Value parsed into an invalid currency for a currency column type."));
                     m_to_currency = comm;
@@ -332,6 +338,8 @@ std::string GncImportPrice::verify_essentials (void)
         return _("No 'Currency to' column.");
     else if (m_from_commodity == boost::none)
         return _("No 'Commodity from' column.");
+    else if (gnc_commodity_equal (*m_from_commodity, *m_to_currency))
+        return _("'Commodity from' can not be the same as 'Currency to'.");
     else
         return std::string();
 }

commit 61f860bcfcfb793a61d75fc48b7b1be47b6ae056
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:49:28 2017 +0000

    Various changes to comments in source files and displayed text.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 075f463..14a8ffa 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -434,7 +434,7 @@ GtkTreeModel *get_model (bool all_commodity)
         /* Hide the template entry */
         if (g_utf8_collate (tmp_namespace, "template" ) != 0)
         {
-            if ((g_utf8_collate (tmp_namespace, GNC_COMMODITY_NS_CURRENCY ) == 0) || (all_commodity == true)) 
+            if ((g_utf8_collate (tmp_namespace, GNC_COMMODITY_NS_CURRENCY ) == 0) || (all_commodity == true))
             {
                 commodity_list = gnc_commodity_table_get_commodities (commodity_table, tmp_namespace);
                 commodity_list  = g_list_first (commodity_list);
@@ -1727,10 +1727,10 @@ CsvImpPriceAssist::assist_summary_page_prepare ()
 {
     auto text = std::string("<span size=\"medium\"><b>");
     text += _("The prices were imported from the file '") + m_file_name + "'.";
-    text += _("\n\nThe number of Prices added was ") + std::to_string(price_imp->m_prices_added);
-    text += _(", duplicated was ") + std::to_string(price_imp->m_prices_duplicated);
-    text += _(" and replaced was ") + std::to_string(price_imp->m_prices_replaced);
-    text += ".</b></span>";
+    text += _("\n\nThere were ") + std::to_string(price_imp->m_prices_added);
+    text += _(" Prices added, ") + std::to_string(price_imp->m_prices_duplicated);
+    text += _(" duplicated and ") + std::to_string(price_imp->m_prices_replaced);
+    text += _(" replaced.</b></span>");
 
     gtk_label_set_markup (GTK_LABEL(summary_label), text.c_str());
 }
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
index 764b196..33db266 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
@@ -44,20 +44,26 @@
     <signal name="prepare" handler="csv_price_imp_assist_prepare_cb" swapped="no"/>
     <signal name="cancel" handler="csv_price_imp_assist_cancel_cb" swapped="no"/>
     <child>
+      <placeholder/>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
+    <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 Prices from a CSV file.
 
-There is a minimum number of columns that have to be present for a successful import, for Stock prices these are Date, Amount, Symbol From and for Currency they are Date, Amount, Currency From and Currency To.
+There is a minimum number of columns that have to be present for a successful import, these are Date, Amount, Commodity From and Currency To. If all entries are for the same Commodity / Currency then you can select them and then the columns will be Date and Amount.
 
-Various options exist for specifying the delimiter 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.
+Various options exist for specifying the delimiter as well as a fixed width option. With the fixed width option, double click on the table of rows displayed to set a column width, then right mouse to change if required.
 
 Examples are "RR.L","21/11/2016",5.345,"GBP" and "USD","2016-11-21",1.56,"GBP"
 
 There is an option for specifying the start row, end row and an option to skip alternate rows beginning from the start row which can be used if you have some header text. Also there is an option to over write existing prices for that day if required.
 
-On the preview page you can Load and Save the settings. To save the settings, select a previously saved entry or replace the text and press the Save Settings button.
+Lastly, for repeated imports the preview page has buttons to Load and Save the settings. To save the settings, tweak the settings to your preferences (optionally starting from an existing preset), then (optionally change the settings name and press the Save Settings button. Note you can't save to built-in presets.
 
 This operation is not reversable, so make sure you have a working backup.
 
@@ -536,6 +542,7 @@ Select location and file name for the Import, then click 'OK'...
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
                                 <property name="tooltip_text" translatable="yes">Normally prices are not over written, select this to change that. This setting is not saved.</property>
+                                <property name="focus_on_click">False</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_overwrite_cb" swapped="no"/>
                               </object>
@@ -1094,8 +1101,9 @@ For example
               <object class="GtkLabel" id="finish_label">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="label" translatable="yes">Press Apply to add Prices.
-Cancel to abort.</property>
+                <property name="label" translatable="yes"><b>Press Apply to add the Prices.
+Cancel to abort.</b></property>
+                <property name="use_markup">True</property>
                 <property name="justify">center</property>
                 <property name="wrap">True</property>
               </object>
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 38a3cbc..d5d3862 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -62,7 +62,7 @@ const gchar* currency_format_user_price[] = {N_("Locale"),
 
 
 /** Constructor for GncPriceImport.
- * @return Pointer to a new GncCSvParseData
+ * @return Pointer to a new GncCsvParseData
  */
 GncPriceImport::GncPriceImport(GncImpFileFormat format)
 {
@@ -142,7 +142,7 @@ bool GncPriceImport::over_write () { return m_over_write; }
 /** Sets a from commodity. This is the commodity all import data relates to.
  *  When a from commodity is set, there can't be any from columns selected
  *  in the import data.
- * @param from_commodity Pointer to a commodity or NULL.
+ * @param from_commodity pointer to a commodity or NULL.
  */
 void GncPriceImport::from_commodity (gnc_commodity* from_commodity)
 {
@@ -164,7 +164,7 @@ gnc_commodity *GncPriceImport::from_commodity () { return m_settings.m_from_comm
 /** Sets a to currency. This is the to currency all import data relates to.
  *  When a to currency is set, there can't be any to currency columns selected
  *  in the import data.
- * @param to_currency Pointer to a commodity or NULL.
+ * @param to_currency pointer to a commodity or NULL.
  */
 void GncPriceImport::to_currency (gnc_commodity* to_currency)
 {
@@ -221,7 +221,6 @@ int GncPriceImport::date_format () { return m_settings.m_date_format; }
  */
 void GncPriceImport::encoding (const std::string& encoding)
 {
-
     // TODO investigate if we can catch conversion errors and report them
     if (m_tokenizer)
     {
@@ -309,12 +308,10 @@ void GncPriceImport::settings (const CsvTransSettings& settings)
     std::copy_n (settings.m_column_types_price.begin(),
             std::min (m_settings.m_column_types_price.size(), settings.m_column_types_price.size()),
             m_settings.m_column_types_price.begin());
-
 }
 
 bool GncPriceImport::save_settings ()
 {
-
     if (trans_preset_is_reserved_name (m_settings.m_name))
         return true;
 
@@ -327,7 +324,6 @@ bool GncPriceImport::save_settings ()
         auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
         m_settings.m_column_widths = fwtok->get_columns();
     }
-
     return m_settings.save();
 }
 
@@ -342,7 +338,6 @@ std::string GncPriceImport::settings_name () { return m_settings.m_name; }
  */
 void GncPriceImport::load_file (const std::string& filename)
 {
-
     /* Get the raw data first and handle an error if one occurs. */
     try
     {
@@ -407,7 +402,6 @@ void GncPriceImport::tokenize (bool guessColTypes)
     }
 }
 
-
 struct ErrorListPrice
 {
 public:
@@ -428,7 +422,6 @@ std::string ErrorListPrice::str()
     return m_error.substr(0, m_error.size() - 1);
 }
 
-
 /* Test for the required minimum number of columns selected and
  * the selection is consistent.
  * @param An ErrorListPrice object to which all found issues are added.
@@ -450,7 +443,7 @@ void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
     if (!check_for_column_type(GncPricePropType::TO_CURRENCY))
     {
         if (!m_settings.m_to_currency)
-            error_msg.add_error( _("Please select a Currency to column or set a Currency in the Currency To field."));
+            error_msg.add_error( _("Please select a 'Currency to' column or set a Currency in the 'Currency To' field."));
     }
 
     /* Verify a Commodity from column is selected.
@@ -458,11 +451,10 @@ void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
     if (!check_for_column_type(GncPricePropType::FROM_COMMODITY))
     {
         if (!m_settings.m_from_commodity)
-            error_msg.add_error( _("Please select a Commodity from column or set a Commodity in the Commodity From field."));
+            error_msg.add_error( _("Please select a 'Commodity from' column or set a Commodity in the 'Commodity From' field."));
     }
 }
 
-
 /* Check whether the chosen settings can successfully parse
  * the import data. This will check:
  * - there's at least one line selected for import
@@ -547,7 +539,7 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
 
     error_message.clear();
 
-    // Add a CURRENCY_TO property with the default currency to if no currency to column was set by the user
+    // Add a CURRENCY_TO property with the selected 'currency to' if no 'currency to' column was set by the user
     auto line_to_currency = price_props->get_to_currency();
     if (!line_to_currency)
     {
@@ -555,16 +547,16 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
             price_props->set_to_currency(m_settings.m_to_currency);
         else
         {
-            // Oops - the user didn't select an Account column *and* we didn't get a default value either!
+            // Oops - the user didn't select a 'currency to' column *and* we didn't get a selected value either!
             // Note if you get here this suggests a bug in the code!
-            error_message = _("No Currency to column selected and no default Currency specified either.\n"
+            error_message = _("No 'Currency to' column selected and no selected Currency specified either.\n"
                                        "This should never happen. Please report this as a bug.");
             PINFO("User warning: %s", error_message.c_str());
             throw std::invalid_argument(error_message);
         }
     }
 
-    // Add a COMMODITY_FROM property with the default commodity from if no commodity from column was set by the user
+    // Add a COMMODITY_FROM property with the selected 'commodity from' if no 'commodity from' column was set by the user
     auto line_from_commodity = price_props->get_from_commodity();
     if (!line_from_commodity)
     {
@@ -572,9 +564,9 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
             price_props->set_from_commodity(m_settings.m_from_commodity);
         else
         {
-            // Oops - the user didn't select an Account column *and* we didn't get a default value either!
+            // Oops - the user didn't select a 'commodity from' column *and* we didn't get a selected value either!
             // Note if you get here this suggests a bug in the code!
-            error_message = _("No Commodity from column selected and no default Commodity specified either.\n"
+            error_message = _("No 'Commodity from' column selected and no selected Commodity specified either.\n"
                                        "This should never happen. Please report this as a bug.");
             PINFO("User warning: %s", error_message.c_str());
             throw std::invalid_argument(error_message);
@@ -605,7 +597,6 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
     }
 }
 
-
 /** Creates a list of prices from parsed data. The parsed data
  * will first be validated. If any errors are found in lines that are marked
  * for processing (ie not marked to skip) this function will
@@ -697,11 +688,11 @@ GncPriceImport::set_column_type_price (uint32_t position, GncPricePropType type,
 
     m_settings.m_column_types_price.at (position) = type;
 
-    // If the user has set a Commodity from column, we can't have a commodity from default set
+    // If the user has set a 'commodity from' column, we can't have a commodity from selected
     if (type == GncPricePropType::FROM_COMMODITY)
         from_commodity (nullptr);
 
-    // If the user has set a Currency to column, we can't have a currency to default set
+    // If the user has set a 'currency to' column, we can't have a currency to selected
     if (type == GncPricePropType::TO_CURRENCY)
         to_currency (nullptr);
 
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index d9293e1..2deffb3 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -160,7 +160,7 @@ time64 parse_date_price (const std::string &date_str, int format)
 }
 
 
-/** Convert str into a GncRational using the user-specified (import) currency format.
+/** Convert str into a GncNumeric using the user-specified (import) currency format.
  * @param str The string to be parsed
  * @param currency_format The currency format to use.
  * @return a GncNumeric
@@ -200,6 +200,11 @@ GncNumeric parse_amount_price (const std::string &str, int currency_format)
     return GncNumeric(val);
 }
 
+/** Convert comm_str into a gnc_commodity.
+ * @param comm_str The string to be parsed
+ * @return a gnc_commodity
+ * @exception May throw std::invalid argument if string can't be parsed properly
+ */
 gnc_commodity* parse_commodity_price_comm (const std::string& comm_str)
 {
     if (comm_str.empty())
@@ -324,9 +329,9 @@ std::string GncImportPrice::verify_essentials (void)
     else if (m_amount == boost::none)
         return _("No amount column.");
     else if (m_to_currency == boost::none)
-        return _("No Currency to column.");
+        return _("No 'Currency to' column.");
     else if (m_from_commodity == boost::none)
-        return _("No Commodity from column.");
+        return _("No 'Commodity from' column.");
     else
         return std::string();
 }
@@ -417,7 +422,6 @@ Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
 
         if (perr == false)
             throw std::invalid_argument (_("Failed to create price from selected columns."));
-//FIXME Not sure about this, should this be a PWARN
     }
     else
     {
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 1d44ff6..9ae4853 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -90,6 +90,7 @@ public:
     void set_date_format (int date_format) { m_date_format = date_format ;}
     void set_currency_format (int currency_format) { m_currency_format = currency_format ;}
     void reset (GncPricePropType prop_type);
+    std::string verify_essentials (void);
     Result create_price (QofBook* book, GNCPriceDB *pdb, bool over);
 
     gnc_commodity* get_from_commodity () { if (m_from_commodity) return *m_from_commodity; else return nullptr; }

commit 1bb2d1dc3890236aaa9f996e84723555f5c334e9
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:47:12 2017 +0000

    Change the way commodity and currency combo's are shown.
    
    Use commodity print name to show in the combo's and use a hidden field
    to sort the list grouping by namespace. Also alter the way these
    settings are saved.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 43f2d8a..075f463 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -419,11 +419,11 @@ GtkTreeModel *get_model (bool all_commodity)
 
     store = GTK_TREE_MODEL(gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER));
     model = gtk_tree_model_sort_new_with_model (store);
-    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-                                        0, GTK_SORT_ASCENDING);
+    // set sort to sort on second string, first string will be shown
+    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), 1, GTK_SORT_ASCENDING);
 
     gtk_list_store_append (GTK_LIST_STORE(store), &iter);
-    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, " ", 1, nullptr, -1);
+    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, " ", 1, " ", 2, nullptr, -1);
 
     namespace_list = g_list_first (namespace_list);
     while (namespace_list != nullptr)
@@ -440,23 +440,20 @@ GtkTreeModel *get_model (bool all_commodity)
                 commodity_list  = g_list_first (commodity_list);
                 while (commodity_list != nullptr)
                 {
-                    gchar *name_str;
-                    gchar *save_str;
-                    gchar *settings_str;
+                    const gchar *name_str;
+                    gchar *sort_str;
                     tmp_commodity = (gnc_commodity*)commodity_list->data;
                     DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (tmp_commodity));
 
-                    name_str = g_strconcat (tmp_namespace, " : (", gnc_commodity_get_mnemonic (tmp_commodity),
-                                            ") ", gnc_commodity_get_fullname (tmp_commodity), nullptr);
+                    name_str = gnc_commodity_get_printname (tmp_commodity);
 
-                    settings_str = g_strconcat (tmp_namespace, "::", gnc_commodity_get_mnemonic (tmp_commodity), nullptr);
-                    DEBUG("Name string is %s, Save string is %s", name_str, settings_str);
+                    sort_str = g_strconcat (tmp_namespace, "::", gnc_commodity_get_mnemonic (tmp_commodity), nullptr);
+                    DEBUG("Name string is %s, Sort string is %s", name_str, sort_str);
 
                     gtk_list_store_append (GTK_LIST_STORE(store), &iter);
-                    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, name_str, 1, settings_str, 2, tmp_commodity, -1);
+                    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, name_str, 1, sort_str, 2, tmp_commodity, -1);
 
-                    g_free (name_str);
-                    g_free (settings_str);
+                    g_free (sort_str);
                     commodity_list = g_list_next (commodity_list);
                 }
             }
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
index 73ab2a5..3bbc984 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
@@ -294,7 +294,7 @@ CsvTransSettings::load (void)
         if (col_types_str)
             g_strfreev (col_types_str);
     }
- 
+
     // Price
     if (m_settings_type.compare("PRICE") == 0)
     {
@@ -424,10 +424,20 @@ CsvTransSettings::save (void)
     if (m_settings_type.compare("PRICE") == 0)
     {
         if (m_to_currency)
-            g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, gnc_commodity_get_mnemonic(m_to_currency));
+        {
+            auto unique_name = g_strconcat (gnc_commodity_get_namespace (m_to_currency), "::",
+                               gnc_commodity_get_mnemonic (m_to_currency), nullptr);
+            g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, unique_name);
+            g_free (unique_name);
+        }
 
         if (m_from_commodity)
-            g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, gnc_commodity_get_mnemonic(m_from_commodity));
+        {
+            auto unique_name = g_strconcat (gnc_commodity_get_namespace (m_from_commodity), "::",
+                               gnc_commodity_get_mnemonic (m_from_commodity), nullptr);
+            g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, unique_name);
+            g_free (unique_name);
+        }
 
         std::vector<const char*> col_types_str_price;
         for (auto col_type : m_column_types_price)

commit caba8c433021673d630b4f7459ada4290c2798ef
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:44:38 2017 +0000

    Minor changes and tidy up

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index e3a5ae3..43f2d8a 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -76,7 +76,7 @@ public:
     void assist_preview_page_prepare ();
     void assist_confirm_page_prepare ();
     void assist_summary_page_prepare ();
-    void assist_finish (bool canceled);
+    void assist_finish ();
     void assist_compmgr_close ();
 
     void file_confirm_cb ();
@@ -213,7 +213,6 @@ csv_price_imp_assist_destroy_cb (GtkWidget *object, CsvImpPriceAssist* info)
 void
 csv_price_imp_assist_cancel_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
 {
-    info->assist_finish (true);
     gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS, info);
 }
 
@@ -226,7 +225,7 @@ csv_price_imp_assist_close_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
 void
 csv_price_imp_assist_finish_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
 {
-    info->assist_finish (false);
+    info->assist_finish ();
 }
 
 void csv_price_imp_file_confirm_cb (GtkWidget *button, CsvImpPriceAssist *info)
@@ -356,7 +355,7 @@ gnc_commodity *get_commodity_from_combo (GtkComboBox *combo)
     GtkTreeModel *model, *sort_model;
     GtkTreeIter  iter, siter;
     gchar *string;
-   gnc_commodity *comm;
+    gnc_commodity *comm;
 
     if (!gtk_combo_box_get_active_iter (combo, &siter))
         return nullptr;
@@ -741,7 +740,6 @@ void CsvImpPriceAssist::preview_populate_settings_combo()
     gtk_list_store_clear (GTK_LIST_STORE(model));
 
     // Append the default entry
-//FIXME get_trans_presets ????
     auto presets = get_trans_presets (settings_type);
     for (auto preset : presets)
     {
@@ -773,7 +771,7 @@ void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
         CsvTransSettings *preset;
         GtkTreeModel *model = gtk_combo_box_get_model (combo);
         gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
-//FIXME
+
         if (preset && !trans_preset_is_reserved_name (preset->m_name))
         {
             /* Current preset is not read_only, so buttons can be enabled */
@@ -781,7 +779,6 @@ void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
             can_save = true;
         }
     }
-//FIXME
     else if (entry_text && (strlen (entry_text) > 0) &&
             !trans_preset_is_reserved_name (std::string(entry_text)))
         can_save = true;
@@ -944,6 +941,8 @@ void CsvImpPriceAssist::preview_update_skipped_rows ()
     preview_refresh_table ();
 }
 
+/* Callback triggered when user clicks on Over Write option
+ */
 void CsvImpPriceAssist::preview_over_write (bool over)
 {
     price_imp->over_write (over);
@@ -1723,6 +1722,7 @@ CsvImpPriceAssist::assist_preview_page_prepare ()
 void
 CsvImpPriceAssist::assist_confirm_page_prepare ()
 {
+    /* Confirm Page */
 }
 
 void
@@ -1752,19 +1752,9 @@ CsvImpPriceAssist::assist_prepare_cb (GtkWidget *page)
 }
 
 void
-CsvImpPriceAssist::assist_finish (bool canceled)
+CsvImpPriceAssist::assist_finish ()
 {
     /* Start the import */
-//FIXME Apply button
-g_print("Finish\n");
-//    if (canceled || price_imp->m_transactions.empty())
-//        gnc_gen_trans_list_delete (gnc_csv_importer_gui);
-//    else
-//        gnc_gen_trans_assist_start (gnc_csv_importer_gui);
-
-
-//FIXME Cancel comes here to, check when nothing set, goes to catch below also
-
     /* Create prices from the parsed data */
     try
     {

commit 3a3c2cba9c55df5cb8ac0dfd9ee34801d353243f
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:43:14 2017 +0000

    Change the settings file to save and load price settings.
    
    Added a setting type to distinguish between TRANS and PRICE settings so
    it can load a specific settings type and added the price save and load
    options.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 2d2cfdd..e3a5ae3 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -64,6 +64,8 @@ extern "C"
 /* This static indicates the debugging module that this .o belongs to.  */
 static QofLogModule log_module = GNC_MOD_ASSISTANT;
 
+const std::string settings_type = "PRICE";
+
 class  CsvImpPriceAssist
 {
 public:
@@ -740,7 +742,7 @@ void CsvImpPriceAssist::preview_populate_settings_combo()
 
     // Append the default entry
 //FIXME get_trans_presets ????
-    auto presets = get_trans_presets ();
+    auto presets = get_trans_presets (settings_type);
     for (auto preset : presets)
     {
         GtkTreeIter iter;
diff --git a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
index 9402f38..07091f0 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
@@ -70,6 +70,8 @@ extern "C"
 /* This static indicates the debugging module that this .o belongs to.  */
 static QofLogModule log_module = GNC_MOD_ASSISTANT;
 
+const std::string settings_type = "TRANS";
+
 class  CsvImpTransAssist
 {
 public:
@@ -677,7 +679,7 @@ void CsvImpTransAssist::preview_populate_settings_combo()
 
     // Append the default entry
 
-    auto presets = get_trans_presets ();
+    auto presets = get_trans_presets (settings_type);
     for (auto preset : presets)
     {
         GtkTreeIter iter;
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
index 5235a4c..73ab2a5 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
@@ -41,7 +41,7 @@ extern "C"
 #include "gnc-ui-util.h"
 }
 
-const std::string csv_group_prefix{"CSV - "};
+const std::string csv_group_prefix{"CSV-"};
 const std::string no_settings{N_("No Settings")};
 const std::string gnc_exp{N_("GnuCash Export Format")};
 #define CSV_NAME         "Name"
@@ -70,10 +70,11 @@ G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
 preset_vec presets;
 
-static std::shared_ptr<CsvTransSettings> create_int_no_preset(void)
+static std::shared_ptr<CsvTransSettings> create_int_no_preset(const std::string& set_type)
 {
     auto preset = std::make_shared<CsvTransSettings>();
     preset->m_name = no_settings;
+    preset->m_settings_type = set_type;
 
     return preset;
 }
@@ -109,14 +110,6 @@ static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
             GncTransPropType::REC_DATE,
             GncTransPropType::PRICE
     };
-
-    preset->m_column_types_price = {
-            GncPricePropType::DATE,
-            GncPricePropType::AMOUNT,
-            GncPricePropType::FROM_COMMODITY,
-            GncPricePropType::TO_CURRENCY,
-    };
-
     return preset;
 }
 
@@ -124,8 +117,9 @@ static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
  * find
  *
  * find all settings entries in the state key file
+ * based on settings type.
  **************************************************/
-const preset_vec& get_trans_presets (void)
+const preset_vec& get_trans_presets (const std::string& set_type)
 {
 
     // Search all Groups in the state key file for ones starting with prefix
@@ -138,11 +132,12 @@ const preset_vec& get_trans_presets (void)
     for (gsize i=0; i < grouplength; i++)
     {
         auto group = std::string(groups[i]);
-        auto pos = group.find(csv_group_prefix);
+        auto gp = csv_group_prefix + set_type + " - ";
+        auto pos = group.find(gp);
         if (pos == std::string::npos)
             continue;
 
-        preset_names.push_back(group.substr(csv_group_prefix.size()));
+        preset_names.push_back(group.substr(gp.size()));
     }
     // string array from the state file is no longer needed now.
     g_strfreev (groups);
@@ -154,18 +149,20 @@ const preset_vec& get_trans_presets (void)
     presets.clear();
 
     /* Start with the internally generated ones */
-    presets.push_back(create_int_no_preset());
-    presets.push_back(create_int_gnc_exp_preset());
+    presets.push_back(create_int_no_preset(set_type));
+
+    if (set_type.compare("TRANS") == 0)
+        presets.push_back(create_int_gnc_exp_preset());
 
     /* Then add all the ones we found in the state file */
     for (auto preset_name : preset_names)
     {
         auto preset = std::make_shared<CsvTransSettings>();
+        preset->m_settings_type = set_type;
         preset->m_name = preset_name;
         preset->load();
         presets.push_back(preset);
     }
-
     return presets;
 }
 
@@ -215,7 +212,7 @@ CsvTransSettings::load (void)
 
     GError *key_error = nullptr;
     m_load_error = false;
-    auto group = csv_group_prefix + m_name;
+    auto group = csv_group_prefix + m_settings_type + " - " + m_name;
     auto keyfile = gnc_state_get_current ();
 
     m_skip_start_lines = g_key_file_get_integer (keyfile, group.c_str(), CSV_SKIP_START, &key_error);
@@ -260,56 +257,82 @@ CsvTransSettings::load (void)
     if (key_char)
         g_free (key_char);
 
-    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ACCOUNT, &key_error);
-    if (key_char && *key_char != '\0')
-        m_base_account = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
-    m_load_error |= handle_load_error (&key_error, group);
-    if (key_char)
-        g_free (key_char);
-
-    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_TO_CURR, &key_error);
-    if (key_char && *key_char != '\0')
-//FIXME        m_to_currency = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
-        m_to_currency = nullptr;
-    m_load_error |= handle_load_error (&key_error, group);
-    if (key_char)
-        g_free (key_char);
-
-    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_FROM_COMM, &key_error);
-    if (key_char && *key_char != '\0')
-//FIXME        m_from_commodity = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
-        m_from_commodity = nullptr;
-    m_load_error |= handle_load_error (&key_error, group);
-    if (key_char)
-        g_free (key_char);
-
-    m_column_types.clear();
     gsize list_len;
-    gchar** col_types_str = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
-            &list_len, &key_error);
-    for (uint32_t i = 0; i < list_len; i++)
+
+    // Transactions
+    if (m_settings_type.compare("TRANS") == 0)
     {
-        auto col_types_it = std::find_if (gnc_csv_col_type_strs.begin(),
-                gnc_csv_col_type_strs.end(), test_prop_type_str (col_types_str[i]));
-        if (col_types_it != gnc_csv_col_type_strs.end())
+        key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ACCOUNT, &key_error);
+        if (key_char && *key_char != '\0')
+            m_base_account = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
+        m_load_error |= handle_load_error (&key_error, group);
+        if (key_char)
+            g_free (key_char);
+
+        m_column_types.clear();
+        gchar** col_types_str = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+                &list_len, &key_error);
+        for (uint32_t i = 0; i < list_len; i++)
         {
-            /* Found a valid column type. Now check whether it is allowed
-             * in the selected mode (two-split vs multi-split) */
-            auto prop = sanitize_trans_prop (col_types_it->first, m_multi_split);
-                m_column_types.push_back(prop);
-            if (prop != col_types_it->first)
-                PWARN("Found column type '%s', but this is blacklisted when multi-split mode is %s. "
-                        "Inserting column type 'NONE' instead'.",
-                        col_types_it->second, m_multi_split ? "enabled" : "disabled");
+            auto col_types_it = std::find_if (gnc_csv_col_type_strs.begin(),
+                    gnc_csv_col_type_strs.end(), test_prop_type_str (col_types_str[i]));
+            if (col_types_it != gnc_csv_col_type_strs.end())
+            {
+                /* Found a valid column type. Now check whether it is allowed
+                 * in the selected mode (two-split vs multi-split) */
+                auto prop = sanitize_trans_prop (col_types_it->first, m_multi_split);
+                    m_column_types.push_back(prop);
+                if (prop != col_types_it->first)
+                    PWARN("Found column type '%s', but this is blacklisted when multi-split mode is %s. "
+                            "Inserting column type 'NONE' instead'.",
+                            col_types_it->second, m_multi_split ? "enabled" : "disabled");
+            }
+            else
+                PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
+                        col_types_str[i]);
         }
-        else
-            PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
-                    col_types_str[i]);
-
+        if (col_types_str)
+            g_strfreev (col_types_str);
+    }
+ 
+    // Price
+    if (m_settings_type.compare("PRICE") == 0)
+    {
+        key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_TO_CURR, &key_error);
+        if (key_char && *key_char != '\0')
+            m_to_currency = parse_commodity_price_comm (key_char);
+        m_load_error |= handle_load_error (&key_error, group);
+        if (key_char)
+            g_free (key_char);
+
+        key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_FROM_COMM, &key_error);
+        if (key_char && *key_char != '\0')
+            m_from_commodity = parse_commodity_price_comm (key_char);
+        m_load_error |= handle_load_error (&key_error, group);
+        if (key_char)
+            g_free (key_char);
+
+        m_column_types.clear();
+        gchar** col_types_str_price = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+                &list_len, &key_error);
+        for (uint32_t i = 0; i < list_len; i++)
+        {
+            auto col_types_it = std::find_if (gnc_price_col_type_strs.begin(),
+                    gnc_price_col_type_strs.end(), test_price_prop_type_str (col_types_str_price[i]));
+            if (col_types_it != gnc_price_col_type_strs.end())
+            {
+                // Found a valid column type
+                m_column_types_price.push_back(col_types_it->first);
+            }
+            else
+                PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
+                        col_types_str_price[i]);
+        }
+        if (col_types_str_price)
+            g_strfreev (col_types_str_price);
     }
-    if (col_types_str)
-        g_strfreev (col_types_str);
 
+    // Widths
     m_column_widths.clear();
     gint *col_widths_int = g_key_file_get_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS,
             &list_len, &key_error);
@@ -347,14 +370,15 @@ CsvTransSettings::save (void)
     }
 
     auto keyfile = gnc_state_get_current ();
-    auto group = csv_group_prefix + m_name;
+    auto group = csv_group_prefix + m_settings_type + " - " + m_name;
 
     // Drop previous saved settings with this name
     g_key_file_remove_group (keyfile, group.c_str(), nullptr);
 
     // Start Saving the settings
+    // Common
     g_key_file_set_string (keyfile, group.c_str(), CSV_NAME, m_name.c_str());
-    g_key_file_set_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, m_multi_split);
+
     g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_START, m_skip_start_lines);
     g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_END, m_skip_end_lines);
     g_key_file_set_boolean (keyfile, group.c_str(), CSV_SKIP_ALT, m_skip_alt_lines);
@@ -375,26 +399,44 @@ CsvTransSettings::save (void)
     g_key_file_set_integer (keyfile, group.c_str(), CSV_CURRENCY, m_currency_format);
     g_key_file_set_string (keyfile, group.c_str(), CSV_ENCODING, m_encoding.c_str());
 
-    if (m_base_account)
-        g_key_file_set_string (keyfile, group.c_str(), CSV_ACCOUNT, gnc_account_get_full_name(m_base_account));
+    if (!m_column_widths.empty())
+        g_key_file_set_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS,
+                (gint*)(m_column_widths.data()), m_column_widths.size());
 
-    if (m_to_currency)
-        g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, gnc_commodity_get_fullname(m_to_currency));
+    // Transaction
+    if (m_settings_type.compare("TRANS") == 0)
+    {
+        g_key_file_set_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, m_multi_split);
 
-    if (m_from_commodity)
-        g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, gnc_commodity_get_fullname(m_from_commodity));
+        if (m_base_account)
+            g_key_file_set_string (keyfile, group.c_str(), CSV_ACCOUNT, gnc_account_get_full_name(m_base_account));
 
-    std::vector<const char*> col_types_str;
-    for (auto col_type : m_column_types)
-        col_types_str.push_back(gnc_csv_col_type_strs[col_type]);
+        std::vector<const char*> col_types_str;
+        for (auto col_type : m_column_types)
+            col_types_str.push_back(gnc_csv_col_type_strs[col_type]);
 
-    if (!col_types_str.empty())
-        g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
-                col_types_str.data(), col_types_str.size());
+        if (!col_types_str.empty())
+            g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+                    col_types_str.data(), col_types_str.size());
+    }
 
-    if (!m_column_widths.empty())
-        g_key_file_set_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS,
-                (gint*)(m_column_widths.data()), m_column_widths.size());
+    // Price
+    if (m_settings_type.compare("PRICE") == 0)
+    {
+        if (m_to_currency)
+            g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, gnc_commodity_get_mnemonic(m_to_currency));
+
+        if (m_from_commodity)
+            g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, gnc_commodity_get_mnemonic(m_from_commodity));
+
+        std::vector<const char*> col_types_str_price;
+        for (auto col_type : m_column_types_price)
+            col_types_str_price.push_back(gnc_price_col_type_strs[col_type]);
+
+        if (!col_types_str_price.empty())
+            g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+                    col_types_str_price.data(), col_types_str_price.size());
+    }
 
     // Do a test read of encoding
     GError *key_error = nullptr;
@@ -425,7 +467,7 @@ CsvTransSettings::remove (void)
         return;
 
     auto keyfile = gnc_state_get_current ();
-    auto group = csv_group_prefix + m_name;
+    auto group = csv_group_prefix + m_settings_type + " - " + m_name;
     g_key_file_remove_group (keyfile, group.c_str(), nullptr);
 }
 
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
index dae837d..7df293c 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
@@ -54,8 +54,8 @@ struct CsvTransSettings
     CsvTransSettings() : m_file_format (GncImpFileFormat::CSV), m_encoding {"UTF-8"},
             m_multi_split (false), m_date_format {0}, m_currency_format {0},
             m_skip_start_lines{0}, m_skip_end_lines{0}, m_skip_alt_lines (false),
-            m_separators {","}, m_base_account {nullptr}, m_to_currency {nullptr},
-            m_from_commodity {nullptr}, m_load_error {false} { }
+            m_separators {","}, m_load_error {false}, m_base_account {nullptr},
+            m_from_commodity {nullptr}, m_to_currency {nullptr} { }
 
 /** Save the gathered widget properties to a key File.
  *
@@ -81,7 +81,9 @@ void remove (void);
  */
 bool read_only (void);
 
+std::string   m_settings_type;                // Settings Type, TRANS, PRICE etc.
 
+// Common Settings
 std::string   m_name;                         // Name given to this preset by the user
 GncImpFileFormat m_file_format;               // CSV import Format
 std::string   m_encoding;                     // File encoding
@@ -92,16 +94,17 @@ uint32_t      m_skip_start_lines;             // Number of header rows to skip
 uint32_t      m_skip_end_lines;               // Number of footer rows to skip
 bool          m_skip_alt_lines;               // Skip alternate rows
 std::string   m_separators;                   // Separators for csv format
+bool          m_load_error;                   // Was there an error while parsing the state file ?
+std::vector<uint32_t> m_column_widths;        // The Column widths
 
+// Transaction Settings
 Account      *m_base_account;                 // Base account
 std::vector<GncTransPropType> m_column_types; // The Column types in order
-std::vector<GncPricePropType> m_column_types_price; // The Column Price types in order
-std::vector<uint32_t> m_column_widths;        // The Column widths
 
-gnc_commodity *m_to_currency;                 //  Price To Currency
+// Price Settings
 gnc_commodity *m_from_commodity;              //  Price From Commodity
-
-bool          m_load_error;                   // Was there an error while parsing the state file ?
+gnc_commodity *m_to_currency;                 //  Price To Currency
+std::vector<GncPricePropType> m_column_types_price; // The Price Column types in order
 };
 
 using preset_vec = std::vector<std::shared_ptr<CsvTransSettings>>;
@@ -109,9 +112,12 @@ using preset_vec = std::vector<std::shared_ptr<CsvTransSettings>>;
  *  - one or more internally defined presets
  *  - all preset found in the state key file.
  *
+ *  @param set_type The type of setting stored in the
+ *  key file, TRANS, PRICE, etc.
+ *
  *  @return a reference to the populated vector.
  */
-const preset_vec& get_trans_presets (void);
+const preset_vec& get_trans_presets (const std::string& set_type);
 
 /** Check whether name can be used as a preset name.
  *  The names of the internal presets are considered reserved.

commit 3c18b8063459a2ef2634c854c065764cbaa50bf7
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:34:21 2017 +0000

    Fix some errors in conversion of some function names
    
    Some function names did not get converted to a price equivalent and
    reorder some statements.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 120367a..2d2cfdd 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -607,9 +607,9 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
 
         /* Add in the date format combo box and hook it up to an event handler. */
         date_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
-        for (int i = 0; i < num_date_formats; i++)
+        for (int i = 0; i < num_date_formats_price; i++)
         {
-            gtk_combo_box_text_append_text (date_format_combo, _(date_format_user[i]));
+            gtk_combo_box_text_append_text (date_format_combo, _(date_format_user_price[i]));
         }
         gtk_combo_box_set_active (GTK_COMBO_BOX(date_format_combo), 0);
         g_signal_connect (G_OBJECT(date_format_combo), "changed",
@@ -622,9 +622,9 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
 
         /* Add in the currency format combo box and hook it up to an event handler. */
         currency_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
-        for (int i = 0; i < num_currency_formats; i++)
+        for (int i = 0; i < num_currency_formats_price; i++)
         {
-            gtk_combo_box_text_append_text (currency_format_combo, _(currency_format_user[i]));
+            gtk_combo_box_text_append_text (currency_format_combo, _(currency_format_user_price[i]));
         }
         /* Default will the locale */
         gtk_combo_box_set_active (GTK_COMBO_BOX(currency_format_combo), 0);
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index e7bb72a..38a3cbc 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -284,9 +284,9 @@ void GncPriceImport::settings (const CsvTransSettings& settings)
     /* First apply file format as this may recreate the tokenizer */
     file_format (settings.m_file_format);
     /* Only then apply the other settings */
+    m_settings = settings;
     from_commodity (m_settings.m_from_commodity);
     to_currency (m_settings.m_to_currency);
-    m_settings = settings;
     encoding (m_settings.m_encoding);
 
     if (file_format() == GncImpFileFormat::CSV)
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index 809464e..be91941 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -46,12 +46,12 @@ extern "C" {
 #include <boost/optional.hpp>
 
 /* A set of currency formats that the user sees. */
-extern const int num_currency_formats;
-extern const gchar* currency_format_user[];
+extern const int num_currency_formats_price;
+extern const gchar* currency_format_user_price[];
 
 /* A set of date formats that the user sees. */
-extern const int num_date_formats;
-extern const gchar* date_format_user[];
+extern const int num_date_formats_price;
+extern const gchar* date_format_user_price[];
 
 /** Tuple to hold
  *  - a tokenized line of input
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 9ae4853..1d44ff6 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -90,7 +90,6 @@ public:
     void set_date_format (int date_format) { m_date_format = date_format ;}
     void set_currency_format (int currency_format) { m_currency_format = currency_format ;}
     void reset (GncPricePropType prop_type);
-    std::string verify_essentials (void);
     Result create_price (QofBook* book, GNCPriceDB *pdb, bool over);
 
     gnc_commodity* get_from_commodity () { if (m_from_commodity) return *m_from_commodity; else return nullptr; }

commit 16845c3a2096906bf1a72eb30eae997745b39c3a
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:32:48 2017 +0000

    Remove duplicated function

diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index e6f983e..d9293e1 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -240,56 +240,6 @@ gnc_commodity* parse_commodity_price_comm (const std::string& comm_str)
         return comm;
 }
 
-//FIXME can we change above to do below
-gnc_commodity * parse_commodity_price_sym (const std::string& sym_str, bool is_currency)
-{
-    if (sym_str.empty())
-        return nullptr;
-
-    auto commodity_table = gnc_get_current_commodities ();
-    GList         *namespaces;
-    gnc_commodity *retval = nullptr;
-    gnc_commodity *tmp_commodity = nullptr;
-    char  *tmp_namespace = nullptr;
-    GList *commodity_list = NULL;
-    GList *namespace_list = gnc_commodity_table_get_namespaces (commodity_table);
-
-    namespace_list = g_list_first (namespace_list);
-    while (namespace_list != NULL && retval == NULL)
-    {
-        tmp_namespace = (char*)namespace_list->data;
-        DEBUG("Looking at namespace %s", tmp_namespace);
-        commodity_list = gnc_commodity_table_get_commodities (commodity_table, tmp_namespace);
-        commodity_list  = g_list_first (commodity_list);
-        while (commodity_list != NULL && retval == NULL)
-        {
-            const char* tmp_mnemonic = NULL;
-            tmp_commodity = (gnc_commodity*)commodity_list->data;
-            DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (tmp_commodity));
-            tmp_mnemonic = gnc_commodity_get_mnemonic (tmp_commodity);
-            if (g_strcmp0 (tmp_mnemonic, sym_str.c_str()) == 0)
-            {
-                retval = tmp_commodity;
-                DEBUG("Commodity %s%s", gnc_commodity_get_fullname (retval), " matches.");
-            }
-            commodity_list = g_list_next (commodity_list);
-        }
-        namespace_list = g_list_next (namespace_list);
-    }
-    g_list_free (commodity_list);
-    g_list_free (namespace_list);
-
-    if (!retval)
-        throw std::invalid_argument (_("Value can't be parsed into a valid commodity."));
-    else
-    {
-        if ((is_currency == true) && (gnc_commodity_is_currency (retval) != true))
-                throw std::invalid_argument (_("Value parsed into an invalid currency for currency column type."));
-        else
-            return retval;
-    }
-}
-
 void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
 {
     try
@@ -307,21 +257,25 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
 
             case GncPricePropType::AMOUNT:
                 m_amount = boost::none;
-                m_amount = parse_amount_price (value, m_currency_format); // Will throw if parsing fails
+                m_amount = parse_amount_price (value, m_currency_format); // Throws if parsing fails
                 break;
 
             case GncPricePropType::FROM_COMMODITY:
                 m_from_commodity = boost::none;
-                comm = parse_commodity_price_sym (value, false); // Throws if parsing fails
+                comm = parse_commodity_price_comm (value); // Throws if parsing fails
                 if (comm)
                     m_from_commodity = comm;
                 break;
 
             case GncPricePropType::TO_CURRENCY:
                 m_to_currency = boost::none;
-                comm = parse_commodity_price_sym (value, true); // Throws if parsing fails
+                comm = parse_commodity_price_comm (value); // Throws if parsing fails
                 if (comm)
+                {
+                    if (gnc_commodity_is_currency (comm) != true)
+                        throw std::invalid_argument (_("Value parsed into an invalid currency for a currency column type."));
                     m_to_currency = comm;
+                }
                 break;
 
             default:
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index a8550ea..9ae4853 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -78,7 +78,6 @@ private:
 
 time64 parse_date_price (const std::string &date_str, int format);
 gnc_commodity* parse_commodity_price_comm (const std::string& comm_str);
-gnc_commodity* parse_commodity_price_sym (const std::string& comm_str, bool is_currency);
 GncNumeric parse_amount_price (const std::string &str, int currency_format);
 
 struct GncImportPrice

commit 1e31db74d1143b3a7cd7fe39f1e42a2f935c04d7
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:30:16 2017 +0000

    Made changes to preset column types to align with other changes
    
    These changes are to align with the changes to column types and also the
     basic setup of the new commodity from and currency to combo's. More
     changes will follow to make the saving and loading work properly.

diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
index 48cfdce..5235a4c 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
@@ -63,6 +63,8 @@ const std::string gnc_exp{N_("GnuCash Export Format")};
 #define CSV_COL_TYPES    "ColumnTypes"
 #define CSV_COL_WIDTHS   "ColumnWidths"
 #define CSV_ACCOUNT      "BaseAccount"
+#define CSV_TO_CURR      "PriceToCurrency"
+#define CSV_FROM_COMM    "PriceFromCommodity"
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
@@ -111,9 +113,8 @@ static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
     preset->m_column_types_price = {
             GncPricePropType::DATE,
             GncPricePropType::AMOUNT,
-            GncPricePropType::CURRENCY_FROM,
-            GncPricePropType::CURRENCY_TO,
-            GncPricePropType::SYMBOL_FROM
+            GncPricePropType::FROM_COMMODITY,
+            GncPricePropType::TO_CURRENCY,
     };
 
     return preset;
@@ -266,6 +267,22 @@ CsvTransSettings::load (void)
     if (key_char)
         g_free (key_char);
 
+    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_TO_CURR, &key_error);
+    if (key_char && *key_char != '\0')
+//FIXME        m_to_currency = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
+        m_to_currency = nullptr;
+    m_load_error |= handle_load_error (&key_error, group);
+    if (key_char)
+        g_free (key_char);
+
+    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_FROM_COMM, &key_error);
+    if (key_char && *key_char != '\0')
+//FIXME        m_from_commodity = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
+        m_from_commodity = nullptr;
+    m_load_error |= handle_load_error (&key_error, group);
+    if (key_char)
+        g_free (key_char);
+
     m_column_types.clear();
     gsize list_len;
     gchar** col_types_str = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
@@ -361,6 +378,12 @@ CsvTransSettings::save (void)
     if (m_base_account)
         g_key_file_set_string (keyfile, group.c_str(), CSV_ACCOUNT, gnc_account_get_full_name(m_base_account));
 
+    if (m_to_currency)
+        g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, gnc_commodity_get_fullname(m_to_currency));
+
+    if (m_from_commodity)
+        g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, gnc_commodity_get_fullname(m_from_commodity));
+
     std::vector<const char*> col_types_str;
     for (auto col_type : m_column_types)
         col_types_str.push_back(gnc_csv_col_type_strs[col_type]);
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
index 93275f2..dae837d 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
@@ -31,6 +31,7 @@
 extern "C" {
 #include <config.h>
 #include "Account.h"
+#include "gnc-commodity.h"
 }
 
 #include <string>
@@ -53,8 +54,8 @@ struct CsvTransSettings
     CsvTransSettings() : m_file_format (GncImpFileFormat::CSV), m_encoding {"UTF-8"},
             m_multi_split (false), m_date_format {0}, m_currency_format {0},
             m_skip_start_lines{0}, m_skip_end_lines{0}, m_skip_alt_lines (false),
-            m_separators {","}, m_base_account {nullptr},
-            m_load_error {false} { }
+            m_separators {","}, m_base_account {nullptr}, m_to_currency {nullptr},
+            m_from_commodity {nullptr}, m_load_error {false} { }
 
 /** Save the gathered widget properties to a key File.
  *
@@ -97,6 +98,9 @@ std::vector<GncTransPropType> m_column_types; // The Column types in order
 std::vector<GncPricePropType> m_column_types_price; // The Column Price types in order
 std::vector<uint32_t> m_column_widths;        // The Column widths
 
+gnc_commodity *m_to_currency;                 //  Price To Currency
+gnc_commodity *m_from_commodity;              //  Price From Commodity
+
 bool          m_load_error;                   // Was there an error while parsing the state file ?
 };
 

commit 8f3e175fb2d3b665e597527e52cbe1cf2e242528
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:25:06 2017 +0000

    Add option to specify Commodity from and Currency to for whole file
    
    Added two combo's to allow user to specify a Commodity from and Currency
     to for the whole file. Also reduced the property types to four and
     aligned all the commodity and currency variables.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 6c4279a..120367a 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -90,6 +90,8 @@ public:
     void preview_update_encoding (const char* encoding);
     void preview_update_date_format ();
     void preview_update_currency_format ();
+    void preview_update_currency ();
+    void preview_update_commodity ();
     void preview_update_col_type (GtkComboBox* cbox);
     void preview_update_fw_columns (GtkTreeView* treeview, GdkEventButton* event);
 
@@ -134,6 +136,8 @@ private:
     GtkWidget       *csv_button;                    /**< The widget for the CSV button */
     GtkWidget       *fixed_button;                  /**< The widget for the Fixed Width button */
     GtkWidget       *over_write_cbutton;            /**< The widget for Price Over Write */
+    GtkWidget       *commodity_selector;            /**< The widget for commodity combo box */
+    GtkWidget       *currency_selector;             /**< The widget for currency combo box */
     GOCharmapSel    *encselector;                   /**< The widget for selecting the encoding */
     GtkWidget       *separator_table;               /**< Container for the separator checkboxes */
     GtkCheckButton  *sep_button[SEP_NUM_OF_TYPES];  /**< Checkbuttons for common separators */
@@ -321,6 +325,16 @@ static void csv_price_imp_preview_currency_fmt_sel_cb (GtkComboBox* format_selec
     info->preview_update_currency_format();
 }
 
+static void csv_price_imp_preview_currency_sel_cb (GtkComboBox* currency_selector, CsvImpPriceAssist* info)
+{
+    info->preview_update_currency();
+}
+
+static void csv_price_imp_preview_commodity_sel_cb (GtkComboBox* commodity_selector, CsvImpPriceAssist* info)
+{
+    info->preview_update_commodity();
+}
+
 void csv_price_imp_preview_col_type_changed_cb (GtkComboBox* cbox, CsvImpPriceAssist* info)
 {
     info->preview_update_col_type (cbox);
@@ -334,6 +348,126 @@ csv_price_imp_preview_treeview_clicked_cb (GtkTreeView* treeview, GdkEventButton
     return false;
 }
 
+static
+gnc_commodity *get_commodity_from_combo (GtkComboBox *combo)
+{
+    GtkTreeModel *model, *sort_model;
+    GtkTreeIter  iter, siter;
+    gchar *string;
+   gnc_commodity *comm;
+
+    if (!gtk_combo_box_get_active_iter (combo, &siter))
+        return nullptr;
+
+    sort_model = gtk_combo_box_get_model (combo);
+    model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT(sort_model));
+
+    gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT(sort_model),
+                                                    &iter, &siter);
+
+    gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &string, 2, &comm, -1);
+
+    PINFO("Commodity string is %s", string);
+
+    g_free (string);
+    return comm;
+}
+
+static void
+set_commodity_for_combo (GtkComboBox *combo, gnc_commodity *comm)
+{
+    GtkTreeModel *model, *sort_model;
+    GtkTreeIter  iter, siter;
+    gnc_commodity *model_comm;
+    gboolean valid;
+
+    sort_model = gtk_combo_box_get_model (combo);
+    model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT(sort_model));
+    valid = gtk_tree_model_get_iter_first (model, &iter);
+
+    while (valid)
+    {
+        gtk_tree_model_get (model, &iter, 2, &model_comm, -1);
+        if (model_comm == comm)
+        {
+            if (gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(sort_model), &siter, &iter))
+            {
+                gtk_combo_box_set_active_iter (combo, &siter);
+                return;
+            }
+        }
+        /* Make iter point to the next row in the list store */
+        valid = gtk_tree_model_iter_next (model, &iter);
+    }
+    // Not found, set it to first iter
+    valid = gtk_tree_model_get_iter_first (model, &iter);
+    if (gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(sort_model), &siter, &iter))
+        gtk_combo_box_set_active_iter (combo, &siter);
+}
+
+static
+GtkTreeModel *get_model (bool all_commodity)
+{
+    GtkTreeModel *store, *model;
+    const gnc_commodity_table *commodity_table = gnc_get_current_commodities ();
+    gnc_commodity *tmp_commodity = nullptr;
+    char  *tmp_namespace = nullptr;
+    GList *commodity_list = nullptr;
+    GList *namespace_list = gnc_commodity_table_get_namespaces (commodity_table);
+    GtkTreeIter iter;
+
+    store = GTK_TREE_MODEL(gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER));
+    model = gtk_tree_model_sort_new_with_model (store);
+    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+                                        0, GTK_SORT_ASCENDING);
+
+    gtk_list_store_append (GTK_LIST_STORE(store), &iter);
+    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, " ", 1, nullptr, -1);
+
+    namespace_list = g_list_first (namespace_list);
+    while (namespace_list != nullptr)
+    {
+        tmp_namespace = (char*)namespace_list->data;
+        DEBUG("Looking at namespace %s", tmp_namespace);
+
+        /* Hide the template entry */
+        if (g_utf8_collate (tmp_namespace, "template" ) != 0)
+        {
+            if ((g_utf8_collate (tmp_namespace, GNC_COMMODITY_NS_CURRENCY ) == 0) || (all_commodity == true)) 
+            {
+                commodity_list = gnc_commodity_table_get_commodities (commodity_table, tmp_namespace);
+                commodity_list  = g_list_first (commodity_list);
+                while (commodity_list != nullptr)
+                {
+                    gchar *name_str;
+                    gchar *save_str;
+                    gchar *settings_str;
+                    tmp_commodity = (gnc_commodity*)commodity_list->data;
+                    DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (tmp_commodity));
+
+                    name_str = g_strconcat (tmp_namespace, " : (", gnc_commodity_get_mnemonic (tmp_commodity),
+                                            ") ", gnc_commodity_get_fullname (tmp_commodity), nullptr);
+
+                    settings_str = g_strconcat (tmp_namespace, "::", gnc_commodity_get_mnemonic (tmp_commodity), nullptr);
+                    DEBUG("Name string is %s, Save string is %s", name_str, settings_str);
+
+                    gtk_list_store_append (GTK_LIST_STORE(store), &iter);
+                    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, name_str, 1, settings_str, 2, tmp_commodity, -1);
+
+                    g_free (name_str);
+                    g_free (settings_str);
+                    commodity_list = g_list_next (commodity_list);
+                }
+            }
+        }
+        namespace_list = g_list_next (namespace_list);
+    }
+    g_list_free (commodity_list);
+    g_list_free (namespace_list);
+
+    return model;
+}
+
 
 /*******************************************************
  * Assistant Constructor
@@ -343,6 +477,8 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
     auto builder = gtk_builder_new();
     gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "start_row_adj");
     gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "end_row_adj");
+    gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "liststore1");
+    gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "liststore2");
     gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "CSV Price Assistant");
     csv_imp_asst = GTK_ASSISTANT(gtk_builder_get_object (builder, "CSV Price Assistant"));
 
@@ -453,6 +589,18 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
         gtk_container_add (encoding_container, GTK_WIDGET(encselector));
         gtk_widget_show_all (GTK_WIDGET(encoding_container));
 
+        /* Add commodity selection widget */
+        commodity_selector = GTK_WIDGET(gtk_builder_get_object (builder, "commodity_cbox"));
+        gtk_combo_box_set_model (GTK_COMBO_BOX(commodity_selector), get_model (true));
+        g_signal_connect(G_OBJECT(commodity_selector), "changed",
+                         G_CALLBACK(csv_price_imp_preview_commodity_sel_cb), this);
+
+        /* Add currency selection widget */
+        currency_selector = GTK_WIDGET(gtk_builder_get_object (builder, "currency_cbox"));
+        gtk_combo_box_set_model (GTK_COMBO_BOX(currency_selector), get_model (false));
+        g_signal_connect(G_OBJECT(currency_selector), "changed",
+                         G_CALLBACK(csv_price_imp_preview_currency_sel_cb), this);
+
         /* The instructions label and image */
         instructions_label = GTK_LABEL(gtk_builder_get_object (builder, "instructions_label"));
         instructions_image = GTK_IMAGE(gtk_builder_get_object (builder, "instructions_image"));
@@ -570,6 +718,9 @@ CsvImpPriceAssist::file_confirm_cb ()
     preview_populate_settings_combo();
     gtk_combo_box_set_active (settings_combo, 0);
 
+    // set over_write to false as default
+    price_imp->over_write (false);
+
     auto num = gtk_assistant_get_current_page (csv_imp_asst);
     gtk_assistant_set_current_page (csv_imp_asst, num + 1);
 }
@@ -951,6 +1102,22 @@ CsvImpPriceAssist::preview_update_currency_format ()
     preview_refresh_table ();
 }
 
+void
+CsvImpPriceAssist::preview_update_currency ()
+{
+    gnc_commodity *comm = get_commodity_from_combo (GTK_COMBO_BOX(currency_selector));
+    price_imp->to_currency (comm);
+    preview_refresh_table ();
+}
+
+void
+CsvImpPriceAssist::preview_update_commodity ()
+{
+    gnc_commodity *comm = get_commodity_from_combo (GTK_COMBO_BOX(commodity_selector));
+    price_imp->from_commodity (comm);
+    preview_refresh_table ();
+}
+
 gboolean
 csv_imp_preview_queue_rebuild_table (CsvImpPriceAssist *assist)
 {
@@ -1413,6 +1580,28 @@ void CsvImpPriceAssist::preview_refresh_table ()
     for (uint32_t i = 0; i < ntcols; i++)
         preview_style_column (i, combostore);
 
+    auto column_types = price_imp->column_types_price();
+
+    // look for a commodity column, clear the commdoity combo
+    auto col_type_comm = std::find (column_types.begin(),
+                column_types.end(), GncPricePropType::FROM_COMMODITY);
+    if (col_type_comm != column_types.end())
+    {
+        g_signal_handlers_block_by_func (commodity_selector, (gpointer) csv_price_imp_preview_commodity_sel_cb, this);
+        set_commodity_for_combo (GTK_COMBO_BOX(commodity_selector), nullptr);
+        g_signal_handlers_unblock_by_func (commodity_selector, (gpointer) csv_price_imp_preview_commodity_sel_cb, this);
+    }
+
+    // look for a currency column, clear the currency combo
+    auto col_type_curr = std::find (column_types.begin(),
+                column_types.end(), GncPricePropType::TO_CURRENCY);
+    if (col_type_curr != column_types.end())
+    {
+        g_signal_handlers_block_by_func (currency_selector, (gpointer) csv_price_imp_preview_currency_sel_cb, this);
+        set_commodity_for_combo (GTK_COMBO_BOX(currency_selector), nullptr);
+        g_signal_handlers_unblock_by_func (currency_selector, (gpointer) csv_price_imp_preview_currency_sel_cb, this);
+    }
+
     /* Release our reference for the stores to allow proper memory management. */
     g_object_unref (store);
     g_object_unref (combostore);
@@ -1460,6 +1649,13 @@ CsvImpPriceAssist::preview_refresh ()
             price_imp->currency_format());
     go_charmap_sel_set_encoding (encselector, price_imp->encoding().c_str());
 
+    // Set the commodity and currency combos
+    set_commodity_for_combo(GTK_COMBO_BOX(commodity_selector),
+            price_imp->from_commodity());
+
+    set_commodity_for_combo(GTK_COMBO_BOX(currency_selector),
+            price_imp->to_currency());
+
     // Handle separator checkboxes and custom field, only relevant if the file format is csv
     if (price_imp->file_format() == GncImpFileFormat::CSV)
     {
@@ -1533,9 +1729,9 @@ CsvImpPriceAssist::assist_summary_page_prepare ()
     auto text = std::string("<span size=\"medium\"><b>");
     text += _("The prices were imported from the file '") + m_file_name + "'.";
     text += _("\n\nThe number of Prices added was ") + std::to_string(price_imp->m_prices_added);
-    text += _(" and ") + std::to_string(price_imp->m_prices_duplicated);
-    text += _(" were duplicated.");
-    text += "</b></span>";
+    text += _(", duplicated was ") + std::to_string(price_imp->m_prices_duplicated);
+    text += _(" and replaced was ") + std::to_string(price_imp->m_prices_replaced);
+    text += ".</b></span>";
 
     gtk_label_set_markup (GTK_LABEL(summary_label), text.c_str());
 }
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
index 705e827..764b196 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
@@ -7,6 +7,26 @@
     <property name="step_increment">1</property>
     <property name="page_increment">10</property>
   </object>
+  <object class="GtkListStore" id="liststore1">
+    <columns>
+      <!-- column-name string -->
+      <column type="gchararray"/>
+      <!-- column-name save -->
+      <column type="gchararray"/>
+      <!-- column-name commodity -->
+      <column type="gpointer"/>
+    </columns>
+  </object>
+  <object class="GtkListStore" id="liststore2">
+    <columns>
+      <!-- column-name string -->
+      <column type="gchararray"/>
+      <!-- column-name save -->
+      <column type="gchararray"/>
+      <!-- column-name currency -->
+      <column type="gpointer"/>
+    </columns>
+  </object>
   <object class="GtkAdjustment" id="start_row_adj">
     <property name="upper">1000</property>
     <property name="step_increment">1</property>
@@ -515,7 +535,7 @@ Select location and file name for the Import, then click 'OK'...
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
-                                <property name="tooltip_text" translatable="yes">Normally prices are not over written, select this to change that.</property>
+                                <property name="tooltip_text" translatable="yes">Normally prices are not over written, select this to change that. This setting is not saved.</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_overwrite_cb" swapped="no"/>
                               </object>
@@ -804,6 +824,9 @@ For example
                 <property name="y_options">GTK_FILL</property>
               </packing>
             </child>
+            <child>
+              <placeholder/>
+            </child>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -812,6 +835,125 @@ For example
           </packing>
         </child>
         <child>
+          <object class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkFrame" id="frame1">
+                <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="alignment1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="bottom_padding">5</property>
+                    <property name="left_padding">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <object class="GtkHBox" id="commodity_hbox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkComboBox" id="commodity_cbox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="model">liststore1</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes"><b>Commodity From</b></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="alignment5">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="bottom_padding">5</property>
+                    <property name="left_padding">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <object class="GtkHBox" id="currency_hbox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkComboBox" id="currency_cbox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="model">liststore1</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="cellrenderertext3"/>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </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"><b>Currency To</b></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>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
           <object class="GtkScrolledWindow" id="scrolledwindow2">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
@@ -860,7 +1002,7 @@ For example
           <packing>
             <property name="expand">True</property>
             <property name="fill">True</property>
-            <property name="position">1</property>
+            <property name="position">2</property>
           </packing>
         </child>
         <child>
@@ -902,7 +1044,7 @@ For example
             <property name="expand">False</property>
             <property name="fill">False</property>
             <property name="padding">5</property>
-            <property name="position">2</property>
+            <property name="position">3</property>
           </packing>
         </child>
         <child>
@@ -930,7 +1072,7 @@ For example
           <packing>
             <property name="expand">False</property>
             <property name="fill">False</property>
-            <property name="position">3</property>
+            <property name="position">4</property>
           </packing>
         </child>
       </object>
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 5437237..e7bb72a 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -125,7 +125,6 @@ void GncPriceImport::file_format(GncImpFileFormat format)
         auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
         fwtok->columns (m_settings.m_column_widths);
     }
-
 }
 
 GncImpFileFormat GncPriceImport::file_format()
@@ -140,6 +139,50 @@ void GncPriceImport::over_write (bool over)
 
 bool GncPriceImport::over_write () { return m_over_write; }
 
+/** Sets a from commodity. This is the commodity all import data relates to.
+ *  When a from commodity is set, there can't be any from columns selected
+ *  in the import data.
+ * @param from_commodity Pointer to a commodity or NULL.
+ */
+void GncPriceImport::from_commodity (gnc_commodity* from_commodity)
+{
+    m_settings.m_from_commodity = from_commodity;
+
+    if (m_settings.m_from_commodity)
+    {
+        auto col_type = std::find (m_settings.m_column_types_price.begin(),
+                m_settings.m_column_types_price.end(), GncPricePropType::FROM_COMMODITY);
+
+        if (col_type != m_settings.m_column_types_price.end())
+            set_column_type_price (col_type -m_settings.m_column_types_price.begin(),
+                            GncPricePropType::NONE);
+    }
+}
+
+gnc_commodity *GncPriceImport::from_commodity () { return m_settings.m_from_commodity; }
+
+/** Sets a to currency. This is the to currency all import data relates to.
+ *  When a to currency is set, there can't be any to currency columns selected
+ *  in the import data.
+ * @param to_currency Pointer to a commodity or NULL.
+ */
+void GncPriceImport::to_currency (gnc_commodity* to_currency)
+{
+    m_settings.m_to_currency = to_currency;
+
+    if (m_settings.m_to_currency)
+    {
+        auto col_type = std::find (m_settings.m_column_types_price.begin(),
+                m_settings.m_column_types_price.end(), GncPricePropType::TO_CURRENCY);
+
+        if (col_type != m_settings.m_column_types_price.end())
+            set_column_type_price (col_type -m_settings.m_column_types_price.begin(),
+                            GncPricePropType::NONE);
+    }
+}
+
+gnc_commodity *GncPriceImport::to_currency () { return m_settings.m_to_currency; }
+
 void GncPriceImport::reset_formatted_column (std::vector<GncPricePropType>& col_types)
 {
     for (auto col_type: col_types)
@@ -241,6 +284,8 @@ void GncPriceImport::settings (const CsvTransSettings& settings)
     /* First apply file format as this may recreate the tokenizer */
     file_format (settings.m_file_format);
     /* Only then apply the other settings */
+    from_commodity (m_settings.m_from_commodity);
+    to_currency (m_settings.m_to_currency);
     m_settings = settings;
     encoding (m_settings.m_encoding);
 
@@ -402,14 +447,19 @@ void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
 
     /* Verify a Currency to column is selected.
      */
-    if (!check_for_column_type(GncPricePropType::CURRENCY_TO))
-        error_msg.add_error( _("Please select a Currency to column."));
+    if (!check_for_column_type(GncPricePropType::TO_CURRENCY))
+    {
+        if (!m_settings.m_to_currency)
+            error_msg.add_error( _("Please select a Currency to column or set a Currency in the Currency To field."));
+    }
 
-    /* Verify at least one from column (symbol_from or currency_from) column is selected.
+    /* Verify a Commodity from column is selected.
      */
-    if (!check_for_column_type(GncPricePropType::SYMBOL_FROM) &&
-        !check_for_column_type(GncPricePropType::CURRENCY_FROM))
-        error_msg.add_error( _("Please select a symbol or currency from column."));
+    if (!check_for_column_type(GncPricePropType::FROM_COMMODITY))
+    {
+        if (!m_settings.m_from_commodity)
+            error_msg.add_error( _("Please select a Commodity from column or set a Commodity in the Commodity From field."));
+    }
 }
 
 
@@ -497,6 +547,40 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
 
     error_message.clear();
 
+    // Add a CURRENCY_TO property with the default currency to if no currency to column was set by the user
+    auto line_to_currency = price_props->get_to_currency();
+    if (!line_to_currency)
+    {
+        if (m_settings.m_to_currency)
+            price_props->set_to_currency(m_settings.m_to_currency);
+        else
+        {
+            // Oops - the user didn't select an Account column *and* we didn't get a default value either!
+            // Note if you get here this suggests a bug in the code!
+            error_message = _("No Currency to column selected and no default Currency specified either.\n"
+                                       "This should never happen. Please report this as a bug.");
+            PINFO("User warning: %s", error_message.c_str());
+            throw std::invalid_argument(error_message);
+        }
+    }
+
+    // Add a COMMODITY_FROM property with the default commodity from if no commodity from column was set by the user
+    auto line_from_commodity = price_props->get_from_commodity();
+    if (!line_from_commodity)
+    {
+        if (m_settings.m_from_commodity)
+            price_props->set_from_commodity(m_settings.m_from_commodity);
+        else
+        {
+            // Oops - the user didn't select an Account column *and* we didn't get a default value either!
+            // Note if you get here this suggests a bug in the code!
+            error_message = _("No Commodity from column selected and no default Commodity specified either.\n"
+                                       "This should never happen. Please report this as a bug.");
+            PINFO("User warning: %s", error_message.c_str());
+            throw std::invalid_argument(error_message);
+        }
+    }
+
     /* If column parsing was successful, convert price properties into a price. */
     try
     {
@@ -507,11 +591,12 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
 
         /* If all went well, add this price to the list. */
         auto price_created = price_props->create_price (book, pdb, m_over_write);
-//FIXME Need to look at this
-        if (price_created)
+        if (price_created == ADDED)
             m_prices_added++;
-        else
+        else if (price_created == DUPLICATED)
             m_prices_duplicated++;
+        else if (price_created == REPLACED)
+            m_prices_replaced++;
     }
     catch (const std::invalid_argument& e)
     {
@@ -537,6 +622,7 @@ void GncPriceImport::create_prices ()
 
     m_prices_added = 0;
     m_prices_duplicated = 0;
+    m_prices_replaced = 0;
 
     /* Iterate over all parsed lines */
     for (auto parsed_lines_it = m_parsed_lines.begin();
@@ -550,8 +636,8 @@ void GncPriceImport::create_prices ()
         /* Should not throw anymore, otherwise verify needs revision */
         create_price (parsed_lines_it);
     }
-    PINFO("Number of lines is %d, added is %d, duplicates is %d",
-         (int)m_parsed_lines.size(), m_prices_added, m_prices_duplicated);
+    PINFO("Number of lines is %d, added %d, duplicated %d, replaced %d",
+         (int)m_parsed_lines.size(), m_prices_added, m_prices_duplicated, m_prices_replaced);
 }
 
 bool
@@ -611,6 +697,14 @@ GncPriceImport::set_column_type_price (uint32_t position, GncPricePropType type,
 
     m_settings.m_column_types_price.at (position) = type;
 
+    // If the user has set a Commodity from column, we can't have a commodity from default set
+    if (type == GncPricePropType::FROM_COMMODITY)
+        from_commodity (nullptr);
+
+    // If the user has set a Currency to column, we can't have a currency to default set
+    if (type == GncPricePropType::TO_CURRENCY)
+        to_currency (nullptr);
+
     /* Update the preparsed data */
     for (auto parsed_lines_it = m_parsed_lines.begin();
             parsed_lines_it != m_parsed_lines.end();
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index 60cdc27..809464e 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -32,7 +32,7 @@
 
 extern "C" {
 #include "config.h"
-
+#include "gnc-commodity.h"
 }
 
 #include <vector>
@@ -85,6 +85,12 @@ public:
     void over_write (bool over);
     bool over_write ();
 
+    void from_commodity (gnc_commodity *from_commodity);
+    gnc_commodity *from_commodity ();
+
+    void to_currency (gnc_commodity *to_currency);
+    gnc_commodity *to_currency ();
+
     void currency_format (int currency_format);
     int currency_format ();
 
@@ -131,6 +137,7 @@ public:
                                                      price properties. */
     int  m_prices_added;
     int  m_prices_duplicated;
+    int  m_prices_replaced;
 
 private:
     /** A helper function used by create_prices. It will attempt
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index a39f178..e6f983e 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -32,8 +32,6 @@ extern "C" {
 
 #include "engine-helpers.h"
 #include "gnc-ui-util.h"
-#include "gnc-pricedb.h"
-
 }
 
 #include <string>
@@ -48,9 +46,8 @@ std::map<GncPricePropType, const char*> gnc_price_col_type_strs = {
         { GncPricePropType::NONE, N_("None") },
         { GncPricePropType::DATE, N_("Date") },
         { GncPricePropType::AMOUNT, N_("Amount") },
-        { GncPricePropType::CURRENCY_FROM, N_("Currency From") },
-        { GncPricePropType::CURRENCY_TO, N_("Currency To") },
-        { GncPricePropType::SYMBOL_FROM, N_("Symbol From") },
+        { GncPricePropType::FROM_COMMODITY, N_("Commodity From") },
+        { GncPricePropType::TO_CURRENCY, N_("Currency To") },
 };
 
 /* Regular expressions used to parse dates per date format */
@@ -243,6 +240,7 @@ gnc_commodity* parse_commodity_price_comm (const std::string& comm_str)
         return comm;
 }
 
+//FIXME can we change above to do below
 gnc_commodity * parse_commodity_price_sym (const std::string& sym_str, bool is_currency)
 {
     if (sym_str.empty())
@@ -285,8 +283,8 @@ gnc_commodity * parse_commodity_price_sym (const std::string& sym_str, bool is_c
         throw std::invalid_argument (_("Value can't be parsed into a valid commodity."));
     else
     {
-        if (gnc_commodity_is_currency (retval) != is_currency)
-            throw std::invalid_argument (_("Value parsed into an invalid commodity for column type."));
+        if ((is_currency == true) && (gnc_commodity_is_currency (retval) != true))
+                throw std::invalid_argument (_("Value parsed into an invalid currency for currency column type."));
         else
             return retval;
     }
@@ -312,25 +310,18 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
                 m_amount = parse_amount_price (value, m_currency_format); // Will throw if parsing fails
                 break;
 
-            case GncPricePropType::CURRENCY_FROM:
-                m_currency_from = boost::none;
-                comm = parse_commodity_price_sym (value, true); // Throws if parsing fails
+            case GncPricePropType::FROM_COMMODITY:
+                m_from_commodity = boost::none;
+                comm = parse_commodity_price_sym (value, false); // Throws if parsing fails
                 if (comm)
-                    m_currency_from = comm;
+                    m_from_commodity = comm;
                 break;
 
-            case GncPricePropType::CURRENCY_TO:
-                m_currency_to = boost::none;
+            case GncPricePropType::TO_CURRENCY:
+                m_to_currency = boost::none;
                 comm = parse_commodity_price_sym (value, true); // Throws if parsing fails
                 if (comm)
-                    m_currency_to = comm;
-                break;
-
-            case GncPricePropType::SYMBOL_FROM:
-                m_symbol_from = boost::none;
-                comm = parse_commodity_price_sym (value, false); // Throws if parsing fails
-                if (comm)
-                    m_symbol_from = comm;
+                    m_to_currency = comm;
                 break;
 
             default:
@@ -378,15 +369,15 @@ std::string GncImportPrice::verify_essentials (void)
         return _("No date column.");
     else if (m_amount == boost::none)
         return _("No amount column.");
-    else if (m_currency_to == boost::none)
+    else if (m_to_currency == boost::none)
         return _("No Currency to column.");
-    else if ((m_symbol_from == boost::none) && (m_currency_from == boost::none))
-        return _("No from column.");
+    else if (m_from_commodity == boost::none)
+        return _("No Commodity from column.");
     else
         return std::string();
 }
 
-bool GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
+Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
 {
     /* Gently refuse to create the price if the basics are not set correctly
      * This should have been tested before calling this function though!
@@ -395,47 +386,40 @@ bool GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
     if (!check.empty())
     {
         PWARN ("Refusing to create price because essentials not set properly: %s", check.c_str());
-        return false;
+        return FAILED;
     }
 
     Timespec date;
     timespecFromTime64 (&date, *m_date);
     date.tv_nsec = 0;
 
-#ifdef skip
-//FIXME Numeric needs changing, copied from old version...
     bool rev = false;
-    gnc_commodity *comm_from = nullptr;
+    auto amount = *m_amount;
 
-    if (m_currency_from != boost::none) // Currency Import
+    GNCPrice *old_price = gnc_pricedb_lookup_day (pdb, *m_from_commodity, *m_to_currency, date);
+
+    if (gnc_commodity_is_currency (*m_from_commodity)) // Currency Import
     {
         // Check for currency in reverse direction.
-        GNCPrice *rev_price = gnc_pricedb_lookup_day (pdb, *m_currency_to, *m_currency_from, date);
-        if (rev_price != nullptr)
-            rev = true;
-        gnc_price_unref (rev_price);
+        if (old_price != nullptr)
+        {
+            // Check for price in reverse direction.
+            if (gnc_commodity_equiv (gnc_price_get_currency (old_price), *m_from_commodity))
+                rev = true;
+
+            DEBUG("Commodity from is a Currency");
+        }
 
         // Check for price less than 1, reverse if so.
-        if (gnc_numeric_compare (*m_amount, gnc_numeric_create (1, 1)) != 1)
+        if (*m_amount < GncNumeric(1,1))
             rev = true;
 
-        comm_from = *m_currency_from;
-        DEBUG("Commodity from is a Currency");
     }
-    else
-        comm_from = *m_symbol_from;
-
     DEBUG("Date is %s, Rev is %d, Commodity from is '%s', Currency is '%s', Amount is %s", gnc_print_date (date),
-          rev, gnc_commodity_get_fullname (comm_from), gnc_commodity_get_fullname (*m_currency_to),
-          gnc_num_dbg_to_string (*m_amount)           );
-
-    GNCPrice *old_price = nullptr;
+        rev, gnc_commodity_get_fullname (*m_from_commodity), gnc_commodity_get_fullname (*m_to_currency),
+        amount.to_string().c_str());
 
-    // Should the commodities be reversed
-    if (rev)
-        old_price = gnc_pricedb_lookup_day (pdb, *m_currency_to, comm_from, date);
-    else
-        old_price = gnc_pricedb_lookup_day (pdb, comm_from, *m_currency_to, date);
+    Result ret_val = ADDED;
 
     // Should old price be over writen
     if ((old_price != nullptr) && (over == true))
@@ -444,31 +428,29 @@ bool GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
         gnc_pricedb_remove_price (pdb, old_price);
         gnc_price_unref (old_price);
         old_price = nullptr;
+        ret_val = REPLACED;
     }
-#endif
-    bool ret_val = true;
-#ifdef skip
+
     // Create the new price
     if (old_price == nullptr)
     {
         DEBUG("Create");
         GNCPrice *price = gnc_price_create (book);
         gnc_price_begin_edit (price);
-
         if (rev)
         {
-            gnc_price_set_commodity (price, *m_currency_to);
-            gnc_price_set_currency (price, comm_from);
-            *m_amount = gnc_numeric_convert (gnc_numeric_invert (*m_amount),
-                                          CURRENCY_DENOM, GNC_HOW_RND_ROUND_HALF_UP);
-            gnc_price_set_value (price, *m_amount);
+            amount = amount.inv(); //invert the amount
+            gnc_price_set_commodity (price, *m_to_currency);
+            gnc_price_set_currency (price, *m_from_commodity);
         }
         else
         {
-            gnc_price_set_commodity (price, comm_from);
-            gnc_price_set_currency (price, *m_currency_to);
-            gnc_price_set_value (price, *m_amount);
+            gnc_price_set_commodity (price, *m_from_commodity);
+            gnc_price_set_currency (price, *m_to_currency);
         }
+        auto amount_conv = amount.convert<RoundType::half_up>(CURRENCY_DENOM);
+        gnc_price_set_value (price, static_cast<gnc_numeric>(amount_conv));
+
         gnc_price_set_time (price, date);
         gnc_price_set_source (price, PRICE_SOURCE_USER_PRICE);
 //FIXME Not sure which one        gnc_price_set_source (price, PRICE_SOURCE_FQ);
@@ -479,15 +461,15 @@ bool GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
 
         gnc_price_unref (price);
 
-         if (perr == false)
+        if (perr == false)
             throw std::invalid_argument (_("Failed to create price from selected columns."));
 //FIXME Not sure about this, should this be a PWARN
     }
     else
-
-#endif
-        ret_val = false;
-
+    {
+        gnc_price_unref (old_price);
+        ret_val = DUPLICATED;
+    }
     return ret_val;
 }
 
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 57083e9..a8550ea 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -49,12 +49,13 @@ enum class GncPricePropType {
     NONE,
     DATE,
     AMOUNT,
-    CURRENCY_FROM,
-    CURRENCY_TO,
-    SYMBOL_FROM,
-    PRICE_PROPS = SYMBOL_FROM
+    FROM_COMMODITY,
+    TO_CURRENCY,
+    PRICE_PROPS = TO_CURRENCY
 };
 
+enum Result { FAILED, ADDED, DUPLICATED, REPLACED };
+
 /** Maps all column types to a string representation.
  *  The actual definition is in gnc-price-props.cpp.
  *  Attention: that definition should be adjusted for any
@@ -91,7 +92,14 @@ public:
     void set_currency_format (int currency_format) { m_currency_format = currency_format ;}
     void reset (GncPricePropType prop_type);
     std::string verify_essentials (void);
-    bool create_price (QofBook* book, GNCPriceDB *pdb, bool over);
+    Result create_price (QofBook* book, GNCPriceDB *pdb, bool over);
+
+    gnc_commodity* get_from_commodity () { if (m_from_commodity) return *m_from_commodity; else return nullptr; }
+    void set_from_commodity (gnc_commodity* comm) { if (comm) m_from_commodity = comm; else m_from_commodity = boost::none; }
+
+    gnc_commodity* get_to_currency () { if (m_to_currency) return *m_to_currency; else return nullptr; }
+    void set_to_currency (gnc_commodity* curr) { if (curr) m_to_currency = curr; else m_to_currency = boost::none; }
+
     std::string errors();
 
 private:
@@ -99,9 +107,8 @@ private:
     int m_currency_format;
     boost::optional<time64> m_date;
     boost::optional<GncNumeric> m_amount;
-    boost::optional<gnc_commodity*> m_currency_from;
-    boost::optional<gnc_commodity*> m_currency_to;
-    boost::optional<gnc_commodity*> m_symbol_from;
+    boost::optional<gnc_commodity*> m_from_commodity;
+    boost::optional<gnc_commodity*> m_to_currency;
     bool created = false;
 
     std::map<GncPricePropType, std::string> m_errors;

commit 3279973329885cc63a6c7b8fb1060aacd4f2cfec
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:04:49 2017 +0000

    Some text changes

diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 09deb93..5437237 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -400,7 +400,7 @@ void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
     if (!check_for_column_type(GncPricePropType::AMOUNT))
         error_msg.add_error( _("Please select an amount column."));
 
-    /* Verify an Currency to column is selected.
+    /* Verify a Currency to column is selected.
      */
     if (!check_for_column_type(GncPricePropType::CURRENCY_TO))
         error_msg.add_error( _("Please select a Currency to column."));
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index 0898215..60cdc27 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -68,11 +68,10 @@ struct ErrorListPrice;
  * - set a file format
  * - load a file
  * - optionally convert it's encoding
- * - parse the file into lines, which in turn are split up in columns
+ * - parse the file into lines, which in turn are split up in to columns
  *   the result of this step can be queried from tokenizer
  * - the user should now map the columns to types, which is stored in column_types
- * - last step is convert the mapped columns into a list of transactions
- * - this list will then be passed on the the generic importer for further processing */
+ * - last step is convert the mapped columns into a list of prices to add */
 class GncPriceImport
 {
 public:

commit f2c78102e09c55ed1bb3243c35c87bf3293e3808
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:03:07 2017 +0000

    Remove not required account update

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index a6ba349..6c4279a 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -87,7 +87,6 @@ public:
     void preview_over_write (bool over);
     void preview_update_separators (GtkWidget* widget);
     void preview_update_file_format ();
-    void preview_update_account ();
     void preview_update_encoding (const char* encoding);
     void preview_update_date_format ();
     void preview_update_currency_format ();
@@ -306,11 +305,6 @@ void csv_price_imp_preview_sep_fixed_sel_cb (GtkToggleButton* csv_button, CsvImp
     info->preview_update_file_format();
 }
 
-void csv_price_imp_preview_acct_sel_cb (GtkWidget* widget, CsvImpPriceAssist* info)
-{
-    info->preview_update_account();
-}
-
 void csv_price_imp_preview_enc_sel_cb (GOCharmapSel* selector, const char* encoding,
                               CsvImpPriceAssist* info)
 {

commit 3cfa9d05bad517db632679ffa6127dd34066d58e
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:01:16 2017 +0000

    Add CSV Price importer assistant files
    
    These file are largely based on the csv transaction importer.
    They are just the start for subsequent changes.

diff --git a/gnucash/import-export/csv-imp/CMakeLists.txt b/gnucash/import-export/csv-imp/CMakeLists.txt
index 0bc7d29..44a14ca 100644
--- a/gnucash/import-export/csv-imp/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/CMakeLists.txt
@@ -10,6 +10,7 @@ SET(csv_import_remote_SOURCES
 SET(csv_import_SOURCES
   gncmod-csv-import.c
   assistant-csv-account-import.c
+  assistant-csv-price-import.cpp
   assistant-csv-trans-import.cpp
   gnc-plugin-csv-import.c
   csv-account-import.c
@@ -37,6 +38,7 @@ SET(csv_import_remote_HEADERS
 
 SET(csv_import_noinst_HEADERS
   assistant-csv-account-import.h
+  assistant-csv-price-import.h
   assistant-csv-trans-import.h
   gnc-plugin-csv-import.h
   csv-account-import.h
@@ -88,7 +90,7 @@ INSTALL(TARGETS gncmod-csv-import
 # No headers to install
 
 SET(csv_import_GLADE assistant-csv-account-import.glade
-      assistant-csv-trans-import.glade)
+      assistant-csv-price-import.glade assistant-csv-trans-import.glade)
 
 INSTALL(FILES ${csv_import_GLADE} DESTINATION ${CMAKE_INSTALL_DATADIR}/gnucash/gtkbuilder)
 
diff --git a/gnucash/import-export/csv-imp/Makefile.am b/gnucash/import-export/csv-imp/Makefile.am
index 4083963..4b473de 100644
--- a/gnucash/import-export/csv-imp/Makefile.am
+++ b/gnucash/import-export/csv-imp/Makefile.am
@@ -5,6 +5,7 @@ pkglib_LTLIBRARIES=libgncmod-csv-import.la
 libgncmod_csv_import_la_SOURCES = \
   gncmod-csv-import.c \
   assistant-csv-account-import.c \
+  assistant-csv-price-import.cpp \
   assistant-csv-trans-import.cpp \
   gnc-plugin-csv-import.c \
   csv-account-import.c \
@@ -22,6 +23,7 @@ libgncmod_csv_import_la_SOURCES = \
 
 noinst_HEADERS = \
   assistant-csv-account-import.h \
+  assistant-csv-price-import.h \
   assistant-csv-trans-import.h \
   gnc-plugin-csv-import.h \
   csv-account-import.h \
@@ -79,6 +81,7 @@ ui_DATA = \
 gtkbuilderdir = ${GNC_GTKBUILDER_DIR}
 gtkbuilder_DATA = \
 	assistant-csv-account-import.glade \
+	assistant-csv-price-import.glade \
 	assistant-csv-trans-import.glade
 
 EXTRA_DIST = $(ui_DATA) $(gtkbuilder_DATA) CMakeLists.txt
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
new file mode 100644
index 0000000..a6ba349
--- /dev/null
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -0,0 +1,1621 @@
+/*******************************************************************\
+ * assistant-csv-price-import.c -- An assistant for importing       *
+ *                                     Prices from a file.          *
+ *                                                                  *
+ * Copyright (C) 2017 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-price-import.cpp
+    @brief CSV Import Assistant
+    @author Copyright (c) 2016 Geert Janssens
+    @author Copyright (c) 2017 Robert Fewell
+*/
+
+#include <guid.hpp>
+
+extern "C"
+{
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <stdlib.h>
+
+#include "gnc-ui.h"
+#include "gnc-uri-utils.h"
+#include "gnc-ui-util.h"
+#include "dialog-utils.h"
+
+#include "gnc-component-manager.h"
+
+#include "gnc-state.h"
+
+#include "assistant-csv-price-import.h"
+
+#include "gnc-csv-gnumeric-popup.h"
+#include "go-charmap-sel.h"
+}
+
+#include "gnc-csv-trans-settings.hpp"
+#include "gnc-price-import.hpp"
+#include "gnc-fw-tokenizer.hpp"
+#include "gnc-csv-tokenizer.hpp"
+
+#define MIN_COL_WIDTH 70
+#define GNC_PREFS_GROUP "dialogs.import.csv"
+#define ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS "assistant-csv-price-import"
+
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = GNC_MOD_ASSISTANT;
+
+class  CsvImpPriceAssist
+{
+public:
+    CsvImpPriceAssist ();
+
+    void assist_prepare_cb (GtkWidget *page);
+    void assist_file_page_prepare ();
+    void assist_preview_page_prepare ();
+    void assist_confirm_page_prepare ();
+    void assist_summary_page_prepare ();
+    void assist_finish (bool canceled);
+    void assist_compmgr_close ();
+
+    void file_confirm_cb ();
+
+    void preview_settings_delete ();
+    void preview_settings_save ();
+    void preview_settings_name (GtkEntry* entry);
+    void preview_settings_load ();
+    void preview_update_skipped_rows ();
+    void preview_over_write (bool over);
+    void preview_update_separators (GtkWidget* widget);
+    void preview_update_file_format ();
+    void preview_update_account ();
+    void preview_update_encoding (const char* encoding);
+    void preview_update_date_format ();
+    void preview_update_currency_format ();
+    void preview_update_col_type (GtkComboBox* cbox);
+    void preview_update_fw_columns (GtkTreeView* treeview, GdkEventButton* event);
+
+    void preview_populate_settings_combo();
+    void preview_handle_save_del_sensitivity (GtkComboBox* combo);
+    void preview_split_column (int col, int offset);
+    void preview_refresh_table ();
+    void preview_refresh ();
+    void preview_validate_settings ();
+
+    friend gboolean
+    fixed_context_menu_handler_price (GnumericPopupMenuElement const *element,
+            gpointer userdata);
+private:
+    /* helper functions to manage the context menu for fixed with columns */
+    uint32_t get_new_col_rel_pos (GtkTreeViewColumn *tcol, int dx);
+    void fixed_context_menu (GdkEventButton *event, int col, int dx);
+    /* helper function to calculate row colors for the preview table (to visualize status) */
+    void preview_row_fill_state_cells (GtkListStore *store, GtkTreeIter *iter,
+            std::string& err_msg, bool skip);
+    /* helper function to create preview header cell combo boxes listing available column types */
+    GtkWidget* preview_cbox_factory (GtkTreeModel* model, uint32_t colnum);
+    /* helper function to set rendering parameters for preview data columns */
+    void preview_style_column (uint32_t col_num, GtkTreeModel* model);
+
+    GtkAssistant    *csv_imp_asst;
+
+    GtkWidget       *file_page;                     /**< Assistant file page widget */
+    GtkWidget       *file_chooser;                  /**< The widget for the file chooser */
+    std::string      m_file_name;                   /**< The import file name */
+
+    GtkWidget       *preview_page;                  /**< Assistant preview page widget */
+    GtkComboBox     *settings_combo;                /**< The Settings Combo */
+    GtkWidget       *save_button;                   /**< The Save Settings button */
+    GtkWidget       *del_button;                    /**< The Delete Settings button */
+
+    GtkWidget       *combo_hbox;                    /**< The Settings Combo hbox */
+    GtkSpinButton   *start_row_spin;                /**< The widget for the start row spinner */
+    GtkSpinButton   *end_row_spin;                  /**< The widget for the end row spinner */
+    GtkWidget       *skip_alt_rows_button;          /**< The widget for Skip alternate rows from start row */
+    GtkWidget       *skip_errors_button;            /**< The widget for Skip error rows*/
+    GtkWidget       *csv_button;                    /**< The widget for the CSV button */
+    GtkWidget       *fixed_button;                  /**< The widget for the Fixed Width button */
+    GtkWidget       *over_write_cbutton;            /**< The widget for Price Over Write */
+    GOCharmapSel    *encselector;                   /**< The widget for selecting the encoding */
+    GtkWidget       *separator_table;               /**< Container for the separator checkboxes */
+    GtkCheckButton  *sep_button[SEP_NUM_OF_TYPES];  /**< Checkbuttons for common separators */
+    GtkWidget       *fw_instructions_hbox;          /**< Container for fixed-width instructions */
+    GtkCheckButton  *custom_cbutton;                /**< The checkbutton for a custom separator */
+    GtkEntry        *custom_entry;                  /**< The entry for custom separators */
+    GtkComboBoxText *date_format_combo;             /**< The Combo Text widget for selecting the date format */
+    GtkComboBoxText *currency_format_combo;         /**< The Combo Text widget for selecting the currency format */
+    GtkTreeView     *treeview;                      /**< The treeview containing the data */
+    GtkLabel        *instructions_label;            /**< The instructions label */
+    GtkImage        *instructions_image;            /**< The instructions image */
+    bool             encoding_selected_called;      /**< Before encoding_selected is first called, this is false.
+                                                       * error lines, instead of all the file data. */
+    int              fixed_context_col;             /**< The number of the column the user has clicked */
+    int              fixed_context_offset;          /**< The offset (in characters) in the column
+                                                       * the user has clicked */
+
+    GtkWidget       *confirm_page;                  /**< Assistant confirm page widget */
+
+    GtkWidget       *summary_page;                  /**< Assistant summary page widget */
+    GtkWidget       *summary_label;                 /**< The summary text */
+
+    std::unique_ptr<GncPriceImport> price_imp;      /**< The actual data we are previewing */
+};
+
+
+/*******************************************************
+ * Assistant call back functions
+ *******************************************************/
+
+extern "C"
+{
+void csv_price_imp_assist_prepare_cb (GtkAssistant  *assistant, GtkWidget *page, CsvImpPriceAssist* info);
+void csv_price_imp_assist_destroy_cb (GtkWidget *object, CsvImpPriceAssist* info);
+void csv_price_imp_assist_cancel_cb (GtkAssistant *gtkassistant, CsvImpPriceAssist* info);
+void csv_price_imp_assist_close_cb (GtkAssistant *gtkassistant, CsvImpPriceAssist* info);
+void csv_price_imp_assist_finish_cb (GtkAssistant *gtkassistant, CsvImpPriceAssist* info);
+void csv_price_imp_file_confirm_cb (GtkWidget *button, CsvImpPriceAssist *info);
+void csv_price_imp_preview_del_settings_cb (GtkWidget *button, CsvImpPriceAssist *info);
+void csv_price_imp_preview_save_settings_cb (GtkWidget *button, CsvImpPriceAssist *info);
+void csv_price_imp_preview_settings_sel_changed_cb (GtkComboBox *combo, CsvImpPriceAssist *info);
+void csv_price_imp_preview_settings_text_inserted_cb (GtkEditable *entry, gchar *new_text,
+        gint new_text_length, gint *position, CsvImpPriceAssist *info);
+void csv_price_imp_preview_settings_text_changed_cb (GtkEntry *entry, CsvImpPriceAssist *info);
+void csv_price_imp_preview_srow_cb (GtkSpinButton *spin, CsvImpPriceAssist *info);
+void csv_price_imp_preview_erow_cb (GtkSpinButton *spin, CsvImpPriceAssist *info);
+void csv_price_imp_preview_skiprows_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info);
+void csv_price_imp_preview_skiperrors_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info);
+void csv_price_imp_preview_overwrite_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info);
+void csv_price_imp_preview_sep_button_cb (GtkWidget* widget, CsvImpPriceAssist* info);
+void csv_price_imp_preview_sep_fixed_sel_cb (GtkToggleButton* csv_button, CsvImpPriceAssist* info);
+void csv_price_imp_preview_acct_sel_cb (GtkWidget* widget, CsvImpPriceAssist* info);
+void csv_price_imp_preview_enc_sel_cb (GOCharmapSel* selector, const char* encoding,
+                              CsvImpPriceAssist* info);
+}
+
+void
+csv_price_imp_assist_prepare_cb (GtkAssistant *assistant, GtkWidget *page,
+        CsvImpPriceAssist* info)
+{
+    info->assist_prepare_cb(page);
+}
+
+void
+csv_price_imp_assist_destroy_cb (GtkWidget *object, CsvImpPriceAssist* info)
+{
+    gnc_unregister_gui_component_by_data (ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS, info);
+    delete info;
+}
+
+void
+csv_price_imp_assist_cancel_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
+{
+    info->assist_finish (true);
+    gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS, info);
+}
+
+void
+csv_price_imp_assist_close_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
+{
+    gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS, info);
+}
+
+void
+csv_price_imp_assist_finish_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
+{
+    info->assist_finish (false);
+}
+
+void csv_price_imp_file_confirm_cb (GtkWidget *button, CsvImpPriceAssist *info)
+{
+    info->file_confirm_cb();
+}
+
+void csv_price_imp_preview_del_settings_cb (GtkWidget *button, CsvImpPriceAssist *info)
+{
+    info->preview_settings_delete();
+}
+
+void csv_price_imp_preview_save_settings_cb (GtkWidget *button, CsvImpPriceAssist *info)
+{
+    info->preview_settings_save();
+}
+
+void csv_price_imp_preview_settings_sel_changed_cb (GtkComboBox *combo, CsvImpPriceAssist *info)
+{
+    info->preview_settings_load();
+}
+
+void
+csv_price_imp_preview_settings_text_inserted_cb (GtkEditable *entry, gchar *new_text,
+        gint new_text_length, gint *position, CsvImpPriceAssist *info)
+{
+    if (!new_text)
+        return;
+
+    /* Prevent entering [], which are invalid characters in key files */
+    auto base_txt = std::string (new_text);
+    auto mod_txt = base_txt;
+    std::replace (mod_txt.begin(), mod_txt.end(), '[', '(');
+    std::replace (mod_txt.begin(), mod_txt.end(), ']', ')');
+    if (base_txt == mod_txt)
+        return;
+    g_signal_handlers_block_by_func (entry, (gpointer) csv_price_imp_preview_settings_text_inserted_cb, info);
+    gtk_editable_insert_text (entry, mod_txt.c_str(), mod_txt.size() , position);
+    g_signal_handlers_unblock_by_func (entry, (gpointer) csv_price_imp_preview_settings_text_inserted_cb, info);
+
+    g_signal_stop_emission_by_name (entry, "insert_text");
+}
+
+void
+csv_price_imp_preview_settings_text_changed_cb (GtkEntry *entry, CsvImpPriceAssist *info)
+{
+    info->preview_settings_name(entry);
+}
+
+void csv_price_imp_preview_srow_cb (GtkSpinButton *spin, CsvImpPriceAssist *info)
+{
+    info->preview_update_skipped_rows();
+}
+
+void csv_price_imp_preview_erow_cb (GtkSpinButton *spin, CsvImpPriceAssist *info)
+{
+    info->preview_update_skipped_rows();
+}
+
+void csv_price_imp_preview_skiprows_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info)
+{
+    info->preview_update_skipped_rows();
+}
+
+void csv_price_imp_preview_skiperrors_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info)
+{
+    info->preview_update_skipped_rows();
+}
+
+void csv_price_imp_preview_overwrite_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info)
+{
+    info->preview_over_write (gtk_toggle_button_get_active (checkbox));
+}
+
+void csv_price_imp_preview_sep_button_cb (GtkWidget* widget, CsvImpPriceAssist* info)
+{
+    info->preview_update_separators(widget);
+}
+
+void csv_price_imp_preview_sep_fixed_sel_cb (GtkToggleButton* csv_button, CsvImpPriceAssist* info)
+{
+    info->preview_update_file_format();
+}
+
+void csv_price_imp_preview_acct_sel_cb (GtkWidget* widget, CsvImpPriceAssist* info)
+{
+    info->preview_update_account();
+}
+
+void csv_price_imp_preview_enc_sel_cb (GOCharmapSel* selector, const char* encoding,
+                              CsvImpPriceAssist* info)
+{
+    info->preview_update_encoding(encoding);
+}
+
+static void csv_price_imp_preview_date_fmt_sel_cb (GtkComboBox* format_selector, CsvImpPriceAssist* info)
+{
+    info->preview_update_date_format();
+}
+
+static void csv_price_imp_preview_currency_fmt_sel_cb (GtkComboBox* format_selector, CsvImpPriceAssist* info)
+{
+    info->preview_update_currency_format();
+}
+
+void csv_price_imp_preview_col_type_changed_cb (GtkComboBox* cbox, CsvImpPriceAssist* info)
+{
+    info->preview_update_col_type (cbox);
+}
+
+gboolean
+csv_price_imp_preview_treeview_clicked_cb (GtkTreeView* treeview, GdkEventButton* event,
+                                        CsvImpPriceAssist* info)
+{
+    info->preview_update_fw_columns(treeview, event);
+    return false;
+}
+
+
+/*******************************************************
+ * Assistant Constructor
+ *******************************************************/
+CsvImpPriceAssist::CsvImpPriceAssist ()
+{
+    auto builder = gtk_builder_new();
+    gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "start_row_adj");
+    gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "end_row_adj");
+    gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "CSV Price Assistant");
+    csv_imp_asst = GTK_ASSISTANT(gtk_builder_get_object (builder, "CSV Price Assistant"));
+
+    /* Enable buttons on all page. */
+    gtk_assistant_set_page_complete (csv_imp_asst,
+                                     GTK_WIDGET(gtk_builder_get_object (builder, "start_page")),
+                                     true);
+    gtk_assistant_set_page_complete (csv_imp_asst,
+                                     GTK_WIDGET(gtk_builder_get_object (builder, "file_page")),
+                                     false);
+    gtk_assistant_set_page_complete (csv_imp_asst,
+                                     GTK_WIDGET(gtk_builder_get_object (builder, "preview_page")),
+                                     false);
+    gtk_assistant_set_page_complete (csv_imp_asst,
+                                     GTK_WIDGET(gtk_builder_get_object (builder, "confirm_page")),
+                                     true);
+    gtk_assistant_set_page_complete (csv_imp_asst,
+                                     GTK_WIDGET(gtk_builder_get_object (builder, "summary_page")),
+                                     true);
+
+    /* File chooser Page */
+    file_page = GTK_WIDGET(gtk_builder_get_object (builder, "file_page"));
+    file_chooser = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_OPEN);
+    g_signal_connect (G_OBJECT(file_chooser), "file-activated",
+                      G_CALLBACK(csv_price_imp_file_confirm_cb), this);
+    auto button = gtk_button_new_from_stock (GTK_STOCK_OK);
+    gtk_widget_set_size_request (button, 100, -1);
+    gtk_widget_show (button);
+    auto h_box = gtk_hbox_new (TRUE, 0);
+    gtk_box_pack_start (GTK_BOX(h_box), button, FALSE, FALSE, 0);
+    gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(file_chooser), h_box);
+    g_signal_connect (G_OBJECT(button), "clicked",
+                      G_CALLBACK(csv_price_imp_file_confirm_cb), this);
+
+    auto box = GTK_WIDGET(gtk_builder_get_object (builder, "file_page"));
+    gtk_box_pack_start (GTK_BOX(box), file_chooser, TRUE, TRUE, 6);
+    gtk_widget_show (file_chooser);
+
+    /* Preview Settings Page */
+    {
+        preview_page = GTK_WIDGET(gtk_builder_get_object (builder, "preview_page"));
+
+        // Add Settings combo
+        auto settings_store = gtk_list_store_new (2, G_TYPE_POINTER, G_TYPE_STRING);
+        settings_combo = GTK_COMBO_BOX(gtk_combo_box_new_with_model_and_entry (GTK_TREE_MODEL(settings_store)));
+        gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX(settings_combo), SET_NAME);
+        gtk_combo_box_set_active (GTK_COMBO_BOX(settings_combo), 0);
+
+        combo_hbox = GTK_WIDGET(gtk_builder_get_object (builder, "combo_hbox"));
+        gtk_box_pack_start (GTK_BOX(combo_hbox), GTK_WIDGET(settings_combo), true, true, 6);
+        gtk_widget_show (GTK_WIDGET(settings_combo));
+
+        g_signal_connect (G_OBJECT(settings_combo), "changed",
+                         G_CALLBACK(csv_price_imp_preview_settings_sel_changed_cb), this);
+
+        // Additionally connect to the changed signal of the embedded GtkEntry
+        auto emb_entry = gtk_bin_get_child (GTK_BIN (settings_combo));
+        g_signal_connect (G_OBJECT(emb_entry), "changed",
+                         G_CALLBACK(csv_price_imp_preview_settings_text_changed_cb), this);
+        g_signal_connect (G_OBJECT(emb_entry), "insert-text",
+                         G_CALLBACK(csv_price_imp_preview_settings_text_inserted_cb), this);
+
+        // Add Save Settings button
+        save_button = GTK_WIDGET(gtk_builder_get_object (builder, "save_settings"));
+
+        // Add Delete Settings button
+        del_button = GTK_WIDGET(gtk_builder_get_object (builder, "delete_settings"));
+
+        /* The table containing the separator configuration widgets */
+        start_row_spin = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "start_row"));
+        end_row_spin = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "end_row"));
+        skip_alt_rows_button = GTK_WIDGET(gtk_builder_get_object (builder, "skip_rows"));
+        skip_errors_button = GTK_WIDGET(gtk_builder_get_object (builder, "skip_errors_button"));
+        over_write_cbutton = GTK_WIDGET(gtk_builder_get_object (builder, "over_write_button"));
+        separator_table = GTK_WIDGET(gtk_builder_get_object (builder, "separator_table"));
+        fw_instructions_hbox = GTK_WIDGET(gtk_builder_get_object (builder, "fw_instructions_hbox"));
+
+        /* Load the separator buttons from the glade builder file into the
+         * sep_buttons array. */
+        const char* sep_button_names[] = {
+                "space_cbutton",
+                "tab_cbutton",
+                "comma_cbutton",
+                "colon_cbutton",
+                "semicolon_cbutton",
+                "hyphen_cbutton"
+            };
+        for (int i = 0; i < SEP_NUM_OF_TYPES; i++)
+            sep_button[i]
+                = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, sep_button_names[i]));
+
+        /* Load and connect the custom separator checkbutton in the same way
+         * as the other separator buttons. */
+        custom_cbutton
+            = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_cbutton"));
+
+        /* Load the entry for the custom separator entry. Connect it to the
+         * sep_button_clicked event handler as well. */
+        custom_entry = (GtkEntry*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_entry"));
+
+        /* Create the encoding selector widget and add it to the assistant */
+        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(encselector), "charmap_changed",
+                         G_CALLBACK(csv_price_imp_preview_enc_sel_cb), this);
+
+        auto encoding_container = GTK_CONTAINER(gtk_builder_get_object (builder, "encoding_container"));
+        gtk_container_add (encoding_container, GTK_WIDGET(encselector));
+        gtk_widget_show_all (GTK_WIDGET(encoding_container));
+
+        /* The instructions label and image */
+        instructions_label = GTK_LABEL(gtk_builder_get_object (builder, "instructions_label"));
+        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. */
+        date_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
+        for (int i = 0; i < num_date_formats; i++)
+        {
+            gtk_combo_box_text_append_text (date_format_combo, _(date_format_user[i]));
+        }
+        gtk_combo_box_set_active (GTK_COMBO_BOX(date_format_combo), 0);
+        g_signal_connect (G_OBJECT(date_format_combo), "changed",
+                         G_CALLBACK(csv_price_imp_preview_date_fmt_sel_cb), this);
+
+        /* Add it to the assistant. */
+        auto date_format_container = GTK_CONTAINER(gtk_builder_get_object (builder, "date_format_container"));
+        gtk_container_add (date_format_container, GTK_WIDGET(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. */
+        currency_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
+        for (int i = 0; i < num_currency_formats; i++)
+        {
+            gtk_combo_box_text_append_text (currency_format_combo, _(currency_format_user[i]));
+        }
+        /* Default will the locale */
+        gtk_combo_box_set_active (GTK_COMBO_BOX(currency_format_combo), 0);
+        g_signal_connect (G_OBJECT(currency_format_combo), "changed",
+                         G_CALLBACK(csv_price_imp_preview_currency_fmt_sel_cb), this);
+
+        /* Add it to the assistant. */
+        auto currency_format_container = GTK_CONTAINER(gtk_builder_get_object (builder, "currency_format_container"));
+        gtk_container_add (currency_format_container, GTK_WIDGET(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"));
+        fixed_button = GTK_WIDGET(gtk_builder_get_object (builder, "fixed_button"));
+
+        /* Load the data treeview and connect it to its resizing event handler. */
+        treeview = (GtkTreeView*)GTK_WIDGET(gtk_builder_get_object (builder, "treeview"));
+        gtk_tree_view_set_headers_clickable (treeview, true);
+
+        /* This is true only after encoding_selected is called, so we must
+         * set it initially to false. */
+        encoding_selected_called = false;
+    }
+
+    /* Confirm Page */
+    confirm_page = GTK_WIDGET(gtk_builder_get_object (builder, "confirm_page"));
+
+    /* Summary Page */
+    summary_page  = GTK_WIDGET(gtk_builder_get_object (builder, "summary_page"));
+    summary_label = GTK_WIDGET(gtk_builder_get_object (builder, "summary_label"));
+
+    gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(csv_imp_asst));
+
+    gtk_builder_connect_signals (builder, this);
+    g_object_unref (G_OBJECT(builder));
+
+    gtk_widget_show_all (GTK_WIDGET(csv_imp_asst));
+    gnc_window_adjust_for_screen (GTK_WINDOW(csv_imp_asst));
+}
+
+/**************************************************
+ * Code related to the file chooser page
+ **************************************************/
+
+/* csv_price_imp_file_confirm_cb
+ *
+ * call back for ok button in file chooser widget
+ */
+void
+CsvImpPriceAssist::file_confirm_cb ()
+{
+    auto file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(file_chooser));
+    if (!file_name)
+        return;
+
+    auto filepath = gnc_uri_get_path (file_name);
+    auto starting_dir = g_path_get_dirname (filepath);
+
+    m_file_name = file_name;
+    gnc_set_default_directory (GNC_PREFS_GROUP, starting_dir);
+
+    DEBUG("file_name selected is %s", m_file_name.c_str());
+    DEBUG("starting directory is %s", starting_dir);
+
+    g_free (filepath);
+    g_free (file_name);
+    g_free (starting_dir);
+
+    /* Load the file into parse_data. */
+    price_imp = std::unique_ptr<GncPriceImport>(new GncPriceImport);
+    /* Assume data is CSV. User can later override to Fixed Width if needed */
+    try
+    {
+        price_imp->file_format (GncImpFileFormat::CSV);
+        price_imp->load_file (m_file_name);
+        price_imp->tokenize (true);
+    }
+    catch (std::ifstream::failure& e)
+    {
+        /* File loading failed ... */
+        gnc_error_dialog (GTK_WIDGET(csv_imp_asst), "%s", e.what());
+        return;
+    }
+    catch (std::range_error &e)
+    {
+        /* Parsing failed ... */
+        gnc_error_dialog (GTK_WIDGET(csv_imp_asst), "%s", e.what());
+        return;
+    }
+    /* Get settings store and populate */
+    preview_populate_settings_combo();
+    gtk_combo_box_set_active (settings_combo, 0);
+
+    auto num = gtk_assistant_get_current_page (csv_imp_asst);
+    gtk_assistant_set_current_page (csv_imp_asst, num + 1);
+}
+
+
+/**************************************************
+ * Code related to the preview page
+ **************************************************/
+
+/* Set the available presets in the settings combo box
+ */
+void CsvImpPriceAssist::preview_populate_settings_combo()
+{
+    // Clear the list store
+    auto model = gtk_combo_box_get_model (settings_combo);
+    gtk_list_store_clear (GTK_LIST_STORE(model));
+
+    // Append the default entry
+//FIXME get_trans_presets ????
+    auto presets = get_trans_presets ();
+    for (auto preset : presets)
+    {
+        GtkTreeIter iter;
+        gtk_list_store_append (GTK_LIST_STORE(model), &iter);
+        /* FIXME we store the raw pointer to the preset, while it's
+         * managed by a shared pointer. This is dangerous because
+         * when the shared pointer goes out of scope, our pointer will dangle.
+         * For now this is safe, because the shared pointers in this case are
+         * long-lived, but this may need refactoring.
+         */
+        gtk_list_store_set (GTK_LIST_STORE(model), &iter, SET_GROUP, preset.get(), SET_NAME, preset->m_name.c_str(), -1);
+    }
+}
+
+/* Enable or disable the save and delete settings buttons
+ * depending on what is selected and entered as settings name
+ */
+void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
+{
+    GtkTreeIter iter;
+    auto can_delete = false;
+    auto can_save = false;
+    auto entry = gtk_bin_get_child (GTK_BIN(combo));
+    auto entry_text = gtk_entry_get_text (GTK_ENTRY(entry));
+    /* Handle sensitivity of the delete and save button */
+    if (gtk_combo_box_get_active_iter (combo, &iter))
+    {
+        CsvTransSettings *preset;
+        GtkTreeModel *model = gtk_combo_box_get_model (combo);
+        gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
+//FIXME
+        if (preset && !trans_preset_is_reserved_name (preset->m_name))
+        {
+            /* Current preset is not read_only, so buttons can be enabled */
+            can_delete = true;
+            can_save = true;
+        }
+    }
+//FIXME
+    else if (entry_text && (strlen (entry_text) > 0) &&
+            !trans_preset_is_reserved_name (std::string(entry_text)))
+        can_save = true;
+
+    gtk_widget_set_sensitive (save_button, can_save);
+    gtk_widget_set_sensitive (del_button, can_delete);
+}
+
+void
+CsvImpPriceAssist::preview_settings_name (GtkEntry* entry)
+{
+    auto text = gtk_entry_get_text (entry);
+    if (text)
+        price_imp->settings_name(text);
+
+    auto combo = gtk_widget_get_parent (GTK_WIDGET(entry));
+    preview_handle_save_del_sensitivity (GTK_COMBO_BOX(combo));
+}
+
+/* Use selected preset to configure the import. Triggered when
+ * a preset is selected in the settings combo.
+ */
+void
+CsvImpPriceAssist::preview_settings_load ()
+{
+    // Get the Active Selection
+    GtkTreeIter iter;
+    if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
+        return;
+
+    CsvTransSettings *preset = nullptr;
+    auto model = gtk_combo_box_get_model (settings_combo);
+    gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
+
+    if (!preset)
+        return;
+
+    price_imp->settings (*preset);
+    if (preset->m_load_error)
+        gnc_error_dialog (GTK_WIDGET(csv_imp_asst),
+            "%s", _("There were problems reading some saved settings, continuing to load.\n"
+                    "Please review and save again."));
+
+    preview_refresh ();
+    preview_handle_save_del_sensitivity (settings_combo);
+}
+
+/* Callback to delete a settings entry
+ */
+void
+CsvImpPriceAssist::preview_settings_delete ()
+{
+    // Get the Active Selection
+    GtkTreeIter iter;
+    if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
+        return;
+
+    CsvTransSettings *preset = nullptr;
+    auto model = gtk_combo_box_get_model (settings_combo);
+    gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
+
+    auto response = gnc_ok_cancel_dialog (GTK_WIDGET(csv_imp_asst),
+                                GTK_RESPONSE_CANCEL,
+                                "%s", _("Delete the Import Settings."));
+    if (response == GTK_RESPONSE_OK)
+    {
+        preset->remove();
+        preview_populate_settings_combo();
+        gtk_combo_box_set_active (settings_combo, 0); // Default
+        preview_refresh (); // Reset the widgets
+    }
+}
+
+/* Callback to save the current settings to the gnucash state file.
+ */
+void
+CsvImpPriceAssist::preview_settings_save ()
+{
+    auto title = _("Save the Import Settings.");
+    auto new_name = price_imp->settings_name();
+
+    /* Check if the entry text matches an already existing preset */
+    GtkTreeIter iter;
+    if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
+    {
+
+        auto model = gtk_combo_box_get_model (settings_combo);
+        bool valid = gtk_tree_model_get_iter_first (model, &iter);
+        while (valid)
+        {
+            // Walk through the list, reading each row
+            CsvTransSettings *preset;
+            gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
+
+            if (preset && (preset->m_name == std::string(new_name)))
+            {
+                auto response = gnc_ok_cancel_dialog (GTK_WIDGET(csv_imp_asst),
+                        GTK_RESPONSE_OK,
+                        "%s", _("Setting name already exists, over write?"));
+                if (response != GTK_RESPONSE_OK)
+                    return;
+
+                break;
+            }
+            valid = gtk_tree_model_iter_next (model, &iter);
+        }
+    }
+
+    /* All checks passed, let's save this preset */
+    if (!price_imp->save_settings())
+    {
+        gnc_info_dialog (GTK_WIDGET(csv_imp_asst),
+            "%s", _("The settings have been saved."));
+
+        // Update the settings store
+        preview_populate_settings_combo();
+        auto model = gtk_combo_box_get_model (settings_combo);
+
+        // Get the first entry in model
+        GtkTreeIter   iter;
+        bool valid = gtk_tree_model_get_iter_first (model, &iter);
+        while (valid)
+        {
+            // Walk through the list, reading each row
+            gchar *name = nullptr;
+            gtk_tree_model_get (model, &iter, SET_NAME, &name, -1);
+
+            if (g_strcmp0 (name, new_name.c_str()) == 0) // Set Active, the one Saved.
+                gtk_combo_box_set_active_iter (settings_combo, &iter);
+
+            g_free (name);
+
+            valid = gtk_tree_model_iter_next (model, &iter);
+        }
+    }
+    else
+        gnc_error_dialog (GTK_WIDGET(csv_imp_asst),
+            "%s", _("There was a problem saving the settings, please try again."));
+}
+
+/* Callback triggered when user adjusts skip start lines
+ */
+void CsvImpPriceAssist::preview_update_skipped_rows ()
+{
+    /* Update skip rows in the parser */
+    price_imp->update_skipped_lines (gtk_spin_button_get_value_as_int (start_row_spin),
+        gtk_spin_button_get_value_as_int (end_row_spin),
+        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(skip_alt_rows_button)),
+        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(skip_errors_button)));
+
+    /* And adjust maximum number of lines that can be skipped at each end accordingly */
+    auto adj = gtk_spin_button_get_adjustment (end_row_spin);
+    gtk_adjustment_set_upper (adj, price_imp->m_parsed_lines.size()
+            - price_imp->skip_start_lines() -1);
+
+    adj = gtk_spin_button_get_adjustment (start_row_spin);
+    gtk_adjustment_set_upper (adj, price_imp->m_parsed_lines.size()
+            - price_imp->skip_end_lines() - 1);
+
+    preview_refresh_table ();
+}
+
+void CsvImpPriceAssist::preview_over_write (bool over)
+{
+    price_imp->over_write (over);
+}
+
+/** 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
+ */
+void CsvImpPriceAssist::preview_update_separators (GtkWidget* widget)
+{
+    /* Only manipulate separator characters if the currently open file is
+     * csv separated. */
+    if (price_imp->file_format() != GncImpFileFormat::CSV)
+        return;
+
+    /* Add the corresponding characters to checked_separators for each
+     * button that is checked. */
+    auto checked_separators = std::string();
+    const auto stock_sep_chars = std::string (" \t,:;-");
+    for (int i = 0; i < SEP_NUM_OF_TYPES; i++)
+    {
+        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(sep_button[i])))
+            checked_separators += stock_sep_chars[i];
+    }
+
+    /* Add the custom separator if the user checked its button. */
+    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(custom_cbutton)))
+    {
+        auto custom_sep = gtk_entry_get_text (custom_entry);
+        if (custom_sep[0] != '\0') /* Don't add a blank separator (bad things will happen!). */
+            checked_separators += custom_sep;
+    }
+
+    /* Set the parse options using the checked_separators list. */
+    price_imp->separators (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 intact. */
+    try
+    {
+        price_imp->tokenize (false);
+        preview_refresh_table ();
+    }
+    catch (std::range_error &e)
+    {
+        /* 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 (GTK_WIDGET(csv_imp_asst), "Error in parsing");
+        /* If we're here because the user changed the file format, we should just wait for the user
+         * to update the configuration */
+        if (!widget)
+            return;
+        /* If the user changed the custom separator, erase that custom separator. */
+        if (widget == GTK_WIDGET(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;
+    }
+}
+
+/** 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
+ */
+void CsvImpPriceAssist::preview_update_file_format ()
+{
+    /* Set the parsing type correctly. */
+    try
+    {
+        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(csv_button)))
+        {
+            price_imp->file_format (GncImpFileFormat::CSV);
+            g_signal_handlers_disconnect_by_func(G_OBJECT(treeview),
+                    (gpointer)csv_price_imp_preview_treeview_clicked_cb, (gpointer)this);
+            gtk_widget_set_visible (separator_table, true);
+            gtk_widget_set_visible (fw_instructions_hbox, false);
+        }
+        else
+        {
+            price_imp->file_format (GncImpFileFormat::FIXED_WIDTH);
+            /* Enable context menu for adding/removing columns. */
+            g_signal_connect (G_OBJECT(treeview), "button-press-event",
+                    G_CALLBACK(csv_price_imp_preview_treeview_clicked_cb), (gpointer)this);
+            gtk_widget_set_visible (separator_table, false);
+            gtk_widget_set_visible (fw_instructions_hbox, true);
+
+        }
+        price_imp->tokenize (false);
+        preview_refresh_table ();
+    }
+    catch (std::range_error &e)
+    {
+        /* Parsing failed ... */
+        gnc_error_dialog (nullptr, "%s", e.what());
+        return;
+    }
+    catch (...)
+    {
+        // FIXME Handle file loading errors (possibly thrown by file_format above)
+        PWARN("Got an error during file loading");
+    }
+}
+
+/** 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
+ */
+void
+CsvImpPriceAssist::preview_update_encoding (const char* encoding)
+{
+    /* This gets called twice every time a new encoding is selected. The
+     * second call actually passes the correct data; thus, we only do
+     * something the second time this is called. */
+
+    /* If this is the second time the function is called ... */
+    if (encoding_selected_called)
+    {
+        std::string previous_encoding = price_imp->m_tokenizer->encoding();
+        /* Try converting the new encoding and reparsing. */
+        try
+        {
+            price_imp->encoding (encoding);
+            preview_refresh_table ();
+        }
+        catch (...)
+        {
+            /* If it fails, change back to the old encoding. */
+            gnc_error_dialog (nullptr, "%s", _("Invalid encoding selected"));
+            go_charmap_sel_set_encoding (encselector, previous_encoding.c_str());
+        }
+    }
+    encoding_selected_called = !encoding_selected_called;
+}
+
+void
+CsvImpPriceAssist::preview_update_date_format ()
+{
+    price_imp->date_format (gtk_combo_box_get_active (GTK_COMBO_BOX(date_format_combo)));
+    preview_refresh_table ();
+}
+
+void
+CsvImpPriceAssist::preview_update_currency_format ()
+{
+    price_imp->currency_format (gtk_combo_box_get_active (GTK_COMBO_BOX(currency_format_combo)));
+    preview_refresh_table ();
+}
+
+gboolean
+csv_imp_preview_queue_rebuild_table (CsvImpPriceAssist *assist)
+{
+    assist->preview_refresh_table ();
+    return false;
+}
+
+/* Internally used enum to access the columns in the comboboxes
+ * the user can click to set a type for each column of the data
+ */
+enum PreviewHeaderComboCols { COL_TYPE_NAME, COL_TYPE_ID };
+/* Internally used enum to access the first two (fixed) columns
+ * in the model used to display the prased data.
+ */
+enum PreviewDataTableCols {
+    PREV_COL_FCOLOR,
+    PREV_COL_BCOLOR,
+    PREV_COL_STRIKE,
+    PREV_COL_ERROR,
+    PREV_COL_ERR_ICON,
+    PREV_N_FIXED_COLS };
+
+/** 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 the 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
+ */
+void CsvImpPriceAssist::preview_update_col_type (GtkComboBox* cbox)
+{
+    /* Get the new text */
+    GtkTreeIter iter;
+    auto model = gtk_combo_box_get_model (cbox);
+    gtk_combo_box_get_active_iter (cbox, &iter);
+    auto new_col_type = GncPricePropType::NONE;
+    gtk_tree_model_get (model, &iter, COL_TYPE_ID, &new_col_type, -1);
+
+    auto col_num = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT(cbox), "col-num"));
+    price_imp->set_column_type_price (col_num, new_col_type);
+
+    /* Delay rebuilding our data table to avoid critical warnings due to
+     * pending events still acting on them after this event is processed.
+     */
+    g_idle_add ((GSourceFunc)csv_imp_preview_queue_rebuild_table, this);
+}
+
+/*======================================================================*/
+/*================== 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/gnucash/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
+    },
+    { "", nullptr, 0, 0, 0 },
+    {
+        N_("_Split this column"), nullptr,
+        0, 1 << CONTEXT_STF_IMPORT_SPLIT, CONTEXT_STF_IMPORT_SPLIT
+    },
+    { "", nullptr, 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
+    },
+    { nullptr, nullptr, 0, 0, 0 },
+};
+
+uint32_t CsvImpPriceAssist::get_new_col_rel_pos (GtkTreeViewColumn *tcol, int dx)
+{
+    auto renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT(tcol));
+    auto cell = GTK_CELL_RENDERER(renderers->data);
+    g_list_free (renderers);
+    PangoFontDescription *font_desc;
+    g_object_get (G_OBJECT(cell), "font_desc", &font_desc, nullptr);
+
+    PangoLayout *layout = gtk_widget_create_pango_layout (GTK_WIDGET(treeview), "x");
+    pango_layout_set_font_description (layout, font_desc);
+    int width;
+    pango_layout_get_pixel_size (layout, &width, nullptr);
+    if (width < 1) width = 1;
+    uint32_t charindex = (dx + width / 2) / width;
+    g_object_unref (layout);
+    pango_font_description_free (font_desc);
+
+    return charindex;
+}
+
+gboolean
+fixed_context_menu_handler_price (GnumericPopupMenuElement const *element,
+        gpointer userdata)
+{
+    auto info = (CsvImpPriceAssist*)userdata;
+    auto fwtok = dynamic_cast<GncFwTokenizer*>(info->price_imp->m_tokenizer.get());
+
+    switch (element->index)
+    {
+    case CONTEXT_STF_IMPORT_MERGE_LEFT:
+        fwtok->col_delete (info->fixed_context_col - 1);
+        break;
+    case CONTEXT_STF_IMPORT_MERGE_RIGHT:
+        fwtok->col_delete (info->fixed_context_col);
+        break;
+    case CONTEXT_STF_IMPORT_SPLIT:
+        fwtok->col_split (info->fixed_context_col, info->fixed_context_offset);
+        break;
+    case CONTEXT_STF_IMPORT_WIDEN:
+        fwtok->col_widen (info->fixed_context_col);
+        break;
+    case CONTEXT_STF_IMPORT_NARROW:
+        fwtok->col_narrow (info->fixed_context_col);
+        break;
+    default:
+        ; /* Nothing */
+    }
+
+    try
+    {
+        info->price_imp->tokenize (false);
+    }
+    catch(std::range_error& e)
+    {
+        gnc_error_dialog (nullptr, "%s", e.what());
+        return false;
+    }
+    info->preview_refresh_table ();
+    return true;
+}
+
+void
+CsvImpPriceAssist::fixed_context_menu (GdkEventButton *event,
+                    int col, int offset)
+{
+    auto fwtok = dynamic_cast<GncFwTokenizer*>(price_imp->m_tokenizer.get());
+    fixed_context_col = col;
+    fixed_context_offset = offset;
+
+    int sensitivity_filter = 0;
+    if (!fwtok->col_can_delete (col - 1))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_LEFT);
+    if (!fwtok->col_can_delete (col))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_RIGHT);
+    if (!fwtok->col_can_split (col, offset))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_SPLIT);
+    if (!fwtok->col_can_widen (col))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_WIDEN);
+    if (!fwtok->col_can_narrow (col))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_NARROW);
+
+    gnumeric_create_popup_menu (popup_elements, &fixed_context_menu_handler_price,
+                                this, 0,
+                                sensitivity_filter, event);
+}
+
+/*===================== End of Gnumeric Code ===========================*/
+/*======================================================================*/
+void
+CsvImpPriceAssist::preview_split_column (int col, int offset)
+{
+    auto fwtok = dynamic_cast<GncFwTokenizer*>(price_imp->m_tokenizer.get());
+    fwtok->col_split (col, offset);
+    try
+    {
+        price_imp->tokenize (false);
+    }
+    catch (std::range_error& e)
+    {
+        gnc_error_dialog (nullptr, "%s", e.what());
+        return;
+    }
+    preview_refresh_table();
+}
+
+/** 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
+ * @returns true if further processing of this even should stop, false
+ *               if other event handlers can have a go at this as well
+ */
+void
+CsvImpPriceAssist::preview_update_fw_columns (GtkTreeView* treeview, GdkEventButton* event)
+{
+    /* Nothing to do if this was not triggered on our treeview body */
+    if (event->window != gtk_tree_view_get_bin_window (treeview))
+        return;
+
+    /* Find the column that was clicked. */
+    GtkTreeViewColumn *tcol = nullptr;
+    int cell_x = 0;
+    auto success = gtk_tree_view_get_path_at_pos (treeview,
+            (int)event->x, (int)event->y,
+            nullptr, &tcol, &cell_x, nullptr);
+    if (!success)
+        return;
+
+    /* Stop if no column found in this treeview (-1) or
+     * if column is the error messages column (0) */
+    auto tcol_list = gtk_tree_view_get_columns(treeview);
+    auto tcol_num = g_list_index (tcol_list, tcol);
+    g_list_free (tcol_list);
+    if (tcol_num <= 0)
+        return;
+
+    /* Data columns in the treeview are offset by one
+     * because the first column is the error column
+     */
+    auto dcol = tcol_num - 1;
+    auto offset = get_new_col_rel_pos (tcol, cell_x);
+    if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
+        /* Double clicks can split columns. */
+        preview_split_column (dcol, offset);
+    else if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+        /* Right clicking brings up a context menu. */
+        fixed_context_menu (event, dcol, offset);
+}
+
+/* Convert state info (errors/skipped) in visual feedback to decorate the preview table */
+void
+CsvImpPriceAssist::preview_row_fill_state_cells (GtkListStore *store, GtkTreeIter *iter,
+        std::string& err_msg, bool skip)
+{
+    /* Extract error status for all non-skipped lines */
+    const char *c_err_msg = nullptr;
+    const char *icon_name = nullptr;
+    const char *fcolor = nullptr;
+    const char *bcolor = nullptr;
+    if (!skip && !err_msg.empty())
+    {
+        fcolor = "black";
+        bcolor = "pink";
+        c_err_msg = err_msg.c_str();
+        icon_name = GTK_STOCK_DIALOG_ERROR;
+    }
+    gtk_list_store_set (store, iter,
+            PREV_COL_FCOLOR, fcolor,
+            PREV_COL_BCOLOR, bcolor,
+            PREV_COL_STRIKE, skip,
+            PREV_COL_ERROR, c_err_msg,
+            PREV_COL_ERR_ICON, icon_name, -1);
+}
+
+/* Helper function that creates a combo_box using a model
+ * with valid column types and selects the given column type
+ */
+GtkWidget*
+CsvImpPriceAssist::preview_cbox_factory (GtkTreeModel* model, uint32_t colnum)
+{
+    GtkTreeIter iter;
+    auto cbox = gtk_combo_box_new_with_model(model);
+
+    /* Set up a renderer for this combobox. */
+    auto renderer = gtk_cell_renderer_text_new();
+    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(cbox),
+            renderer, true);
+    gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(cbox),
+            renderer, "text", COL_TYPE_NAME);
+
+    auto valid = gtk_tree_model_get_iter_first (model, &iter);
+    while (valid)
+    {
+        gint stored_col_type;
+        gtk_tree_model_get (model, &iter,
+                COL_TYPE_ID, &stored_col_type, -1);
+        if (stored_col_type == static_cast<int>( price_imp->column_types_price()[colnum]))
+            break;
+        valid = gtk_tree_model_iter_next(model, &iter);
+    }
+    if (valid)
+        gtk_combo_box_set_active_iter (GTK_COMBO_BOX(cbox), &iter);
+
+    g_object_set_data (G_OBJECT(cbox), "col-num", GUINT_TO_POINTER(colnum));
+    g_signal_connect (G_OBJECT(cbox), "changed",
+                     G_CALLBACK(csv_price_imp_preview_col_type_changed_cb), (gpointer)this);
+
+    gtk_widget_show (cbox);
+    return cbox;
+}
+
+void
+CsvImpPriceAssist::preview_style_column (uint32_t col_num, GtkTreeModel* model)
+{
+    auto col = gtk_tree_view_get_column (treeview, col_num);
+    auto renderer = static_cast<GtkCellRenderer*>(gtk_tree_view_column_get_cell_renderers(col)->data);
+
+    /* First column -the error status column- is rendered differently */
+    if (col_num == 0)
+    {
+        gtk_tree_view_column_set_attributes (col, renderer,
+                "stock-id", PREV_COL_ERR_ICON,
+                "cell-background", PREV_COL_BCOLOR, nullptr);
+        g_object_set (G_OBJECT(renderer), "stock-size", GTK_ICON_SIZE_MENU, nullptr);
+        g_object_set (G_OBJECT(col), "sizing", GTK_TREE_VIEW_COLUMN_FIXED,
+                "fixed-width", 20, nullptr);
+        gtk_tree_view_column_set_resizable (col, false);
+    }
+    else
+    {
+        gtk_tree_view_column_set_attributes (col, renderer,
+                "foreground", PREV_COL_FCOLOR,
+                "background", PREV_COL_BCOLOR,
+                "strikethrough", PREV_COL_STRIKE,
+                "text", col_num + PREV_N_FIXED_COLS -1, nullptr);
+
+        /* We want a monospace font fixed-width data is properly displayed. */
+        g_object_set (G_OBJECT(renderer), "family", "monospace", nullptr);
+
+        /* Add a combobox to select column types as column header. Each uses the same
+         * common model for the dropdown list. The selected value is taken
+         * from the column_types vector. */
+        auto cbox = preview_cbox_factory (GTK_TREE_MODEL(model), col_num - 1);
+        gtk_tree_view_column_set_widget (col, cbox);
+
+        /* Enable resizing of the columns. */
+        gtk_tree_view_column_set_resizable (col, true);
+        gtk_tree_view_column_set_clickable (col, true);
+    }
+}
+
+/* Helper to create a shared store for the header comboboxes in the preview treeview.
+ * It holds the possible column types */
+GtkTreeModel*
+make_column_header_model_price (void)
+{
+    auto combostore = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
+    for (auto col_type : gnc_price_col_type_strs)
+    {
+        GtkTreeIter iter;
+        gtk_list_store_append (combostore, &iter);
+        gtk_list_store_set (combostore, &iter,
+                COL_TYPE_NAME, _(col_type.second),
+                COL_TYPE_ID, static_cast<int>(col_type.first), -1);
+    }
+    return GTK_TREE_MODEL(combostore);
+}
+
+/* Updates the preview treeview to show the data as parsed based on the user's
+ * import parameters.
+ */
+void CsvImpPriceAssist::preview_refresh_table ()
+{
+    preview_validate_settings ();
+
+    /* Create a new liststore to hold status and data from the file being imported.
+       The first columns hold status information (row-color, row-errors, row-error-icon,...
+       All following columns represent the tokenized data as strings. */
+    auto ncols = PREV_N_FIXED_COLS + price_imp->column_types_price().size();
+    auto model_col_types = g_new (GType, ncols);
+    model_col_types[PREV_COL_FCOLOR] = G_TYPE_STRING;
+    model_col_types[PREV_COL_BCOLOR] = G_TYPE_STRING;
+    model_col_types[PREV_COL_ERROR] = G_TYPE_STRING;
+    model_col_types[PREV_COL_ERR_ICON] = G_TYPE_STRING;
+    model_col_types[PREV_COL_STRIKE] = G_TYPE_BOOLEAN;
+    for (guint i = PREV_N_FIXED_COLS; i <  ncols; i++)
+        model_col_types[i] = G_TYPE_STRING;
+    auto store = gtk_list_store_newv (ncols, model_col_types);
+    g_free (model_col_types);
+
+    /* Fill the data liststore with data from importer object. */
+    for (auto parse_line : price_imp->m_parsed_lines)
+    {
+        /* Fill the state cells */
+        GtkTreeIter iter;
+        gtk_list_store_append (store, &iter);
+        preview_row_fill_state_cells (store, &iter,
+                std::get<1>(parse_line), std::get<3>(parse_line));
+
+        /* Fill the data cells. */
+        for (auto cell_str_it = std::get<0>(parse_line).cbegin(); cell_str_it != std::get<0>(parse_line).cend(); cell_str_it++)
+        {
+            uint32_t pos = PREV_N_FIXED_COLS + cell_str_it - std::get<0>(parse_line).cbegin();
+            gtk_list_store_set (store, &iter, pos, cell_str_it->c_str(), -1);
+        }
+    }
+    gtk_tree_view_set_model (treeview, GTK_TREE_MODEL(store));
+    gtk_tree_view_set_tooltip_column (treeview, PREV_COL_ERROR);
+
+    /* Adjust treeview to go with the just created model. This consists of adding
+     * or removing columns and resetting any parameters related to how
+     * the columns and data should be rendered.
+     */
+
+    /* Start with counting the current number of columns (ntcols)
+     * we have in the treeview */
+    auto columns = gtk_tree_view_get_columns (treeview);
+    auto ntcols = g_list_length(columns);
+    g_list_free (columns);
+
+    /* Drop redundant columns if the model has less data columns than the new model
+     * ntcols = n° of columns in treeview (1 error column + x data columns)
+     * ncols = n° of columns in model (fixed state columns + x data columns)
+     */
+    while (ntcols > ncols - PREV_N_FIXED_COLS + 1)
+    {
+        auto col = gtk_tree_view_get_column (treeview, ntcols - 1);
+        gtk_tree_view_column_clear (col);
+        ntcols = gtk_tree_view_remove_column(treeview, col);
+    }
+
+    /* Insert columns if the model has more data columns than the treeview. */
+    while (ntcols < ncols - PREV_N_FIXED_COLS + 1)
+    {
+        /* Default cell renderer is text, except for the first (error) column */
+        auto renderer = gtk_cell_renderer_text_new();
+        if (ntcols == 0)
+            renderer = gtk_cell_renderer_pixbuf_new(); // Error column uses an icon
+        auto col = gtk_tree_view_column_new ();
+        gtk_tree_view_column_pack_start (col, renderer, false);
+        ntcols = gtk_tree_view_append_column (treeview, col);
+    }
+
+    /* Reset column attributes as they are undefined after recreating the model */
+    auto combostore = make_column_header_model_price ();
+    for (uint32_t i = 0; i < ntcols; i++)
+        preview_style_column (i, combostore);
+
+    /* Release our reference for the stores to allow proper memory management. */
+    g_object_unref (store);
+    g_object_unref (combostore);
+
+    /* Make the things actually appear. */
+    gtk_widget_show_all (GTK_WIDGET(treeview));
+}
+
+/* Update the preview page based on the current state of the importer.
+ * Should be called when settings are changed.
+ */
+void
+CsvImpPriceAssist::preview_refresh ()
+{
+    // Set start row
+    auto adj = gtk_spin_button_get_adjustment (start_row_spin);
+    gtk_adjustment_set_upper (adj, price_imp->m_parsed_lines.size());
+    gtk_spin_button_set_value (start_row_spin,
+            price_imp->skip_start_lines());
+
+    // Set end row
+    adj = gtk_spin_button_get_adjustment (end_row_spin);
+    gtk_adjustment_set_upper (adj, price_imp->m_parsed_lines.size());
+    gtk_spin_button_set_value (end_row_spin,
+            price_imp->skip_end_lines());
+
+    // Set Alternate rows
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(skip_alt_rows_button),
+            price_imp->skip_alt_lines());
+
+    // Set over-write indicator
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(over_write_cbutton),
+            price_imp->over_write());
+
+    // Set Import Format
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(csv_button),
+            (price_imp->file_format() == GncImpFileFormat::CSV));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(fixed_button),
+            (price_imp->file_format() != GncImpFileFormat::CSV));
+
+    // This section deals with the combo's and character encoding
+    gtk_combo_box_set_active (GTK_COMBO_BOX(date_format_combo),
+            price_imp->date_format());
+    gtk_combo_box_set_active (GTK_COMBO_BOX(currency_format_combo),
+            price_imp->currency_format());
+    go_charmap_sel_set_encoding (encselector, price_imp->encoding().c_str());
+
+    // Handle separator checkboxes and custom field, only relevant if the file format is csv
+    if (price_imp->file_format() == GncImpFileFormat::CSV)
+    {
+        auto separators = price_imp->separators();
+        const auto stock_sep_chars = std::string (" \t,:;-");
+        for (int i = 0; i < SEP_NUM_OF_TYPES; i++)
+            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(sep_button[i]),
+                separators.find (stock_sep_chars[i]) != std::string::npos);
+
+        // If there are any other separators in the separators string,
+        // add them as custom separators
+        auto pos = separators.find_first_of (stock_sep_chars);
+        while (!separators.empty() && pos != std::string::npos)
+        {
+            separators.erase(pos);
+            pos = separators.find_first_of (stock_sep_chars);
+        }
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(custom_cbutton),
+                !separators.empty());
+        gtk_entry_set_text (GTK_ENTRY(custom_entry), separators.c_str());
+    }
+    // Repopulate the parsed data table
+    g_idle_add ((GSourceFunc)csv_imp_preview_queue_rebuild_table, this);
+}
+
+/* Check if all selected data can be parsed sufficiently to continue
+ */
+void CsvImpPriceAssist::preview_validate_settings ()
+{
+    /* Allow the user to proceed only if there are no inconsistencies in the settings */
+    auto error_msg = price_imp->verify();
+    gtk_assistant_set_page_complete (csv_imp_asst, preview_page, error_msg.empty());
+    gtk_label_set_markup(GTK_LABEL(instructions_label), error_msg.c_str());
+    gtk_widget_set_visible (GTK_WIDGET(instructions_image), !error_msg.empty());
+}
+
+/*******************************************************
+ * Assistant page prepare functions
+ *******************************************************/
+
+void
+CsvImpPriceAssist::assist_file_page_prepare ()
+{
+    /* Set the default directory */
+    auto starting_dir = gnc_get_default_directory (GNC_PREFS_GROUP);
+    if (starting_dir)
+    {
+        gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(file_chooser), starting_dir);
+        g_free (starting_dir);
+    }
+}
+
+void
+CsvImpPriceAssist::assist_preview_page_prepare ()
+{
+    /* Disable the Forward Assistant Button */
+    gtk_assistant_set_page_complete (csv_imp_asst, preview_page, false);
+
+    /* Load the data into the treeview. */
+    preview_refresh_table ();
+}
+
+void
+CsvImpPriceAssist::assist_confirm_page_prepare ()
+{
+}
+
+void
+CsvImpPriceAssist::assist_summary_page_prepare ()
+{
+    auto text = std::string("<span size=\"medium\"><b>");
+    text += _("The prices were imported from the file '") + m_file_name + "'.";
+    text += _("\n\nThe number of Prices added was ") + std::to_string(price_imp->m_prices_added);
+    text += _(" and ") + std::to_string(price_imp->m_prices_duplicated);
+    text += _(" were duplicated.");
+    text += "</b></span>";
+
+    gtk_label_set_markup (GTK_LABEL(summary_label), text.c_str());
+}
+
+void
+CsvImpPriceAssist::assist_prepare_cb (GtkWidget *page)
+{
+    if (page == file_page)
+        assist_file_page_prepare ();
+    else if (page == preview_page)
+        assist_preview_page_prepare ();
+    else if (page == confirm_page)
+        assist_confirm_page_prepare ();
+    else if (page == summary_page)
+        assist_summary_page_prepare ();
+}
+
+void
+CsvImpPriceAssist::assist_finish (bool canceled)
+{
+    /* Start the import */
+//FIXME Apply button
+g_print("Finish\n");
+//    if (canceled || price_imp->m_transactions.empty())
+//        gnc_gen_trans_list_delete (gnc_csv_importer_gui);
+//    else
+//        gnc_gen_trans_assist_start (gnc_csv_importer_gui);
+
+
+//FIXME Cancel comes here to, check when nothing set, goes to catch below also
+
+    /* Create prices from the parsed data */
+    try
+    {
+        price_imp->create_prices ();
+    }
+    catch (const std::invalid_argument& err)
+    {
+        /* Oops! This shouldn't happen when using the import assistant !
+         * Inform the user and go back to the preview page.
+         */
+        gnc_error_dialog (GTK_WIDGET(csv_imp_asst),
+            _("An unexpected error has occurred while creating prices. Please report this as a bug.\n\n"
+              "Error message:\n%s"), err.what());
+        gtk_assistant_set_current_page (csv_imp_asst, 2);
+    }
+}
+
+void
+CsvImpPriceAssist::assist_compmgr_close ()
+{
+    gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(csv_imp_asst));
+    gtk_widget_destroy (GTK_WIDGET(csv_imp_asst));
+}
+
+static void
+csv_price_imp_close_handler (gpointer user_data)
+{
+    auto info = (CsvImpPriceAssist*)user_data;
+    info->assist_compmgr_close();
+}
+
+/********************************************************************\
+ * gnc_file_csv_price_import                                        *
+ * opens up a assistant to import prices.                           *
+ *                                                                  *
+ * Args:   none                                                     *
+ * Return: nothing                                                  *
+\********************************************************************/
+void
+gnc_file_csv_price_import(void)
+{
+    auto info = new CsvImpPriceAssist;
+    gnc_register_gui_component (ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS,
+                                nullptr, csv_price_imp_close_handler,
+                                info);
+}
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
new file mode 100644
index 0000000..705e827
--- /dev/null
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
@@ -0,0 +1,1001 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.24"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkAdjustment" id="end_row_adj">
+    <property name="upper">1000</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="start_row_adj">
+    <property name="upper">1000</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAssistant" id="CSV Price Assistant">
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="title" translatable="yes">CSV Price Import</property>
+    <property name="default_width">400</property>
+    <property name="default_height">500</property>
+    <signal name="close" handler="csv_price_imp_assist_close_cb" swapped="no"/>
+    <signal name="destroy" handler="csv_price_imp_assist_destroy_cb" swapped="no"/>
+    <signal name="apply" handler="csv_price_imp_assist_finish_cb" swapped="no"/>
+    <signal name="prepare" handler="csv_price_imp_assist_prepare_cb" swapped="no"/>
+    <signal name="cancel" handler="csv_price_imp_assist_cancel_cb" 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 Prices from a CSV file.
+
+There is a minimum number of columns that have to be present for a successful import, for Stock prices these are Date, Amount, Symbol From and for Currency they are Date, Amount, Currency From and Currency To.
+
+Various options exist for specifying the delimiter 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.
+
+Examples are "RR.L","21/11/2016",5.345,"GBP" and "USD","2016-11-21",1.56,"GBP"
+
+There is an option for specifying the start row, end row and an option to skip alternate rows beginning from the start row which can be used if you have some header text. Also there is an option to over write existing prices for that day if required.
+
+On the preview page you can Load and Save the settings. To save the settings, select a previously saved entry or replace the text and press the Save Settings button.
+
+This operation is not reversable, so make sure you have a working backup.
+
+Click on 'Forward' to proceed or 'Cancel' to Abort Import.</property>
+        <property name="wrap">True</property>
+      </object>
+      <packing>
+        <property name="page_type">intro</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">
+Select location and file name for the Import, then click 'OK'...
+</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="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="GtkTable" id="table1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="n_rows">2</property>
+            <property name="n_columns">2</property>
+            <property name="column_spacing">5</property>
+            <property name="row_spacing">5</property>
+            <child>
+              <object class="GtkFrame" id="frame6">
+                <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="GtkAlignment" id="alignment4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="bottom_padding">5</property>
+                    <property name="left_padding">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <object class="GtkHBox" id="combo_hbox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkButton" id="delete_settings">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Delete Settings</property>
+                            <signal name="clicked" handler="csv_price_imp_preview_del_settings_cb" swapped="no"/>
+                            <child>
+                              <object class="GtkImage" id="image2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="stock">gtk-delete</property>
+                              </object>
+                            </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="GtkButton" id="save_settings">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Save Settings</property>
+                            <signal name="clicked" handler="csv_price_imp_preview_save_settings_cb" swapped="no"/>
+                            <child>
+                              <object class="GtkImage" id="image1">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="stock">gtk-save</property>
+                              </object>
+                            </child>
+                          </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>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label12">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes"> <b>Load and Save Settings</b></property>
+                    <property name="use_markup">True</property>
+                    <property name="track_visited_links">False</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options">GTK_FILL</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="frame10">
+                <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="alignment6">
+                    <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">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <object class="GtkVBox" id="vbox1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkTable" id="table4">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="n_rows">2</property>
+                            <property name="n_columns">2</property>
+                            <child>
+                              <object class="GtkRadioButton" id="csv_button">
+                                <property name="label" translatable="yes">Separators</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="active">True</property>
+                                <property name="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_fixed_sel_cb" swapped="no"/>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="fixed_button">
+                                <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="draw_indicator">True</property>
+                                <property name="group">csv_button</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkHSeparator" id="hseparator1">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                              </object>
+                              <packing>
+                                <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>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkTable" id="separator_table">
+                            <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>
+                            <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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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="active">True</property>
+                                <property name="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_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>
+                                <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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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">●</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>
+                                <signal name="changed" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHBox" id="fw_instructions_hbox">
+                            <property name="can_focus">False</property>
+                            <property name="no_show_all">True</property>
+                            <child>
+                              <object class="GtkImage" id="instructions_image1">
+                                <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="yalign">0</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="GtkTable" id="table2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="n_rows">2</property>
+                                <property name="n_columns">2</property>
+                                <child>
+                                  <object class="GtkLabel" id="label2">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="yalign">0</property>
+                                    <property name="xpad">5</property>
+                                    <property name="label" translatable="yes">•</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="wrap">True</property>
+                                  </object>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="label3">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">Double-click anywhere on the table below to insert a column break</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="wrap">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">1</property>
+                                    <property name="right_attach">2</property>
+                                    <property name="y_options"/>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="label4">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="yalign">0</property>
+                                    <property name="xpad">5</property>
+                                    <property name="label" translatable="yes">•</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="wrap">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="top_attach">1</property>
+                                    <property name="bottom_attach">2</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="label5">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">Right-click anywhere in a column to modify it (widen, narrow, merge)</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="wrap">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="y_options"/>
+                                  </packing>
+                                </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">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkTable" id="table5">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="n_rows">2</property>
+                            <child>
+                              <object class="GtkHSeparator" id="hseparator4">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="y_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="over_write_button">
+                                <property name="label" translatable="yes">Allow existing prices to be over written.</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="tooltip_text" translatable="yes">Normally prices are not over written, select this to change that.</property>
+                                <property name="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_overwrite_cb" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">3</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label19">
+                    <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"><b>File Format</b></property>
+                    <property name="use_markup">True</property>
+                  </object>
+                </child>
+              </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="GtkFrame" id="frame8">
+                <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="alignment8">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="left_padding">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <object class="GtkVBox" id="vbox6">
+                        <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="GtkTable" id="table3">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="n_rows">6</property>
+                            <property name="n_columns">2</property>
+                            <property name="column_spacing">5</property>
+                            <property name="row_spacing">5</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="xalign">0</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>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label20">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Date Format</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkAlignment" id="currency_format_container">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                              </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="x_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label21">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Currency Format</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
+                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label16">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Encoding</property>
+                              </object>
+                              <packing>
+                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkAlignment" id="encoding_container">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="x_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label17">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Leading Lines to Skip</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">4</property>
+                                <property name="bottom_attach">5</property>
+                                <property name="x_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label18">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Trailing Lines to Skip</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">5</property>
+                                <property name="bottom_attach">6</property>
+                                <property name="x_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkHBox" id="hbox2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkSpinButton" id="start_row">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">●</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>
+                                    <property name="numeric">True</property>
+                                    <signal name="value-changed" handler="csv_price_imp_preview_srow_cb" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">4</property>
+                                <property name="bottom_attach">5</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkHBox" id="hbox3">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkSpinButton" id="end_row">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">●</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>
+                                    <property name="numeric">True</property>
+                                    <signal name="value-changed" handler="csv_price_imp_preview_erow_cb" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">5</property>
+                                <property name="bottom_attach">6</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkHSeparator" id="hseparator2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">3</property>
+                                <property name="bottom_attach">4</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="skip_rows">
+                            <property name="label" translatable="yes">Skip alternate lines</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="tooltip_text" translatable="yes">Starting from the first line that is actually imported every second line will be skipped. This option will take the leading lines to skip into account as well.
+For example
+* if 'Leading Lines to Skip' is set to 3, the first line to import will be line 4. Lines 5, 7, 9,... will be skipped.
+* if 'Leading Lines to Skip' is set to 4, the first line to import will be line 5. Lines 6, 8, 10,... will be skipped.</property>
+                            <property name="draw_indicator">True</property>
+                            <signal name="toggled" handler="csv_price_imp_preview_skiprows_cb" swapped="no"/>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label13">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes"><b>Miscellaneous</b></property>
+                    <property name="use_markup">True</property>
+                  </object>
+                </child>
+              </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>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow2">
+            <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="viewport2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkVBox" id="vbox8">
+                    <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">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox13">
+            <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="yalign">0</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 to import.</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="padding">5</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox14">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkCheckButton" id="skip_errors_button">
+                <property name="label" translatable="yes">Skip Errors</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="xalign">1</property>
+                <property name="image_position">right</property>
+                <property name="draw_indicator">True</property>
+                <signal name="toggled" handler="csv_price_imp_preview_skiperrors_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>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">intro</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="confirm_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <child>
+          <object class="GtkAlignment" id="alignment2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkLabel" id="finish_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Press Apply to add Prices.
+Cancel to abort.</property>
+                <property name="justify">center</property>
+                <property name="wrap">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">confirm</property>
+        <property name="title" translatable="yes">Import Prices 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>
+            <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">summary</property>
+        <property name="title" translatable="yes">Import Summary</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.h b/gnucash/import-export/csv-imp/assistant-csv-price-import.h
new file mode 100644
index 0000000..213b622
--- /dev/null
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.h
@@ -0,0 +1,36 @@
+/*******************************************************************\
+ * assistant-csv-price-import.h -- An assistant for importing       *
+ *                                     Prices from a file.          *
+ *                                                                  *
+ * Copyright (C) 2017 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-price-import.h
+    @brief CSV Import Assistant
+    @author Copyright (c) 2017 Robert Fewell
+*/
+#ifndef GNC_ASSISTANT_CSV_IMPORT_PRICE_H
+#define GNC_ASSISTANT_CSV_IMPORT_PRICE_H
+
+
+/** The gnc_file_csv_price_import() will let the user import the
+ *  commodity prices from a file.
+ */
+void gnc_file_csv_price_import (void);
+#endif
diff --git a/gnucash/import-export/csv-imp/gnc-plugin-csv-import-ui.xml b/gnucash/import-export/csv-imp/gnc-plugin-csv-import-ui.xml
index c119a64..bdd3043 100644
--- a/gnucash/import-export/csv-imp/gnc-plugin-csv-import-ui.xml
+++ b/gnucash/import-export/csv-imp/gnc-plugin-csv-import-ui.xml
@@ -5,6 +5,7 @@
       	<placeholder name="FileImportPlaceholder">
       	   <menuitem name="FileCsvImportAccounts" action="CsvImportAccountAction"/>
       	   <menuitem name="FileCsvImportTrans" action="CsvImportTransAction"/>
+           <menuitem name="FileCsvImportPrice" action="CsvImportPriceAction"/>
       	</placeholder>
       </menu>
     </menu>
diff --git a/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c b/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
index 25954be..c14092d 100644
--- a/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
+++ b/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
@@ -30,6 +30,7 @@
 
 #include "assistant-csv-account-import.h"
 #include "assistant-csv-trans-import.h"
+#include "assistant-csv-price-import.h"
 
 static void gnc_plugin_csv_import_class_init (GncPluginCsvImportClass *klass);
 static void gnc_plugin_csv_import_init (GncPluginCsvImport *plugin);
@@ -38,6 +39,7 @@ 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_price_cmd (GtkAction *action, GncMainWindowActionData *data);
 
 #define PLUGIN_ACTIONS_NAME "gnc-plugin-csv-import-actions"
 #define PLUGIN_UI_FILENAME  "gnc-plugin-csv-import-ui.xml"
@@ -54,6 +56,11 @@ static GtkActionEntry gnc_plugin_actions [] =
         N_("Import Transactions from a CSV file"),
         G_CALLBACK (gnc_plugin_csv_import_trans_cmd)
     },
+    {
+        "CsvImportPriceAction", GTK_STOCK_CONVERT, N_("Import _Prices from a CSV file..."), NULL,
+        N_("Import Prices from a CSV file"),
+        G_CALLBACK (gnc_plugin_csv_import_price_cmd)
+    },
 };
 static guint gnc_plugin_n_actions = G_N_ELEMENTS (gnc_plugin_actions);
 
@@ -157,6 +164,13 @@ gnc_plugin_csv_import_trans_cmd (GtkAction *action,
     gnc_file_csv_trans_import ();
 }
 
+static void
+gnc_plugin_csv_import_price_cmd (GtkAction *action,
+                                 GncMainWindowActionData *data)
+{
+    gnc_file_csv_price_import ();
+}
+
 /************************************************************
  *                    Plugin Bootstrapping                   *
  ************************************************************/

commit 404bc1e329bddb6726cab3577f98c49ef7294ffa
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 10:55:29 2017 +0000

    Rename function gnc_csv_price_col_type_strs to gnc_price_col_type_strs

diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index 1fdcaa53..a39f178 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -44,7 +44,7 @@ extern "C" {
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
 /* This map contains a set of strings representing the different column types. */
-std::map<GncPricePropType, const char*> gnc_csv_price_col_type_strs = {
+std::map<GncPricePropType, const char*> gnc_price_col_type_strs = {
         { GncPricePropType::NONE, N_("None") },
         { GncPricePropType::DATE, N_("Date") },
         { GncPricePropType::AMOUNT, N_("Amount") },
@@ -341,7 +341,7 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
     }
     catch (const std::invalid_argument& e)
     {
-        auto err_str = std::string(_(gnc_csv_price_col_type_strs[prop_type])) +
+        auto err_str = std::string(_(gnc_price_col_type_strs[prop_type])) +
                        std::string(_(" could not be understood.\n")) +
                        e.what();
         m_errors.emplace(prop_type, err_str);
@@ -349,7 +349,7 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
     }
     catch (const std::out_of_range& e)
     {
-        auto err_str = std::string(_(gnc_csv_price_col_type_strs[prop_type])) +
+        auto err_str = std::string(_(gnc_price_col_type_strs[prop_type])) +
                        std::string(_(" could not be understood.\n")) +
                        e.what();
         m_errors.emplace(prop_type, err_str);
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index d101280..57083e9 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -56,10 +56,10 @@ enum class GncPricePropType {
 };
 
 /** Maps all column types to a string representation.
- *  The actual definition is in gnc-csv-imp-prices.cpp.
+ *  The actual definition is in gnc-price-props.cpp.
  *  Attention: that definition should be adjusted for any
  *  changes to enum class GncPricePropType ! */
-extern std::map<GncPricePropType, const char*> gnc_csv_price_col_type_strs;
+extern std::map<GncPricePropType, const char*> gnc_price_col_type_strs;
 
 /** Functor to check if the above map has an element of which
  *  the value equals name. To be used with std::find_if.

commit bec1fbd1a08cbd1c0c408df5e38a6343aa9dccd8
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 10:53:41 2017 +0000

    Add price import files for the csv price importer
    
    These files are largely based on the csv transaction importer and with
    minimum of changes to settings files.

diff --git a/gnucash/import-export/csv-imp/CMakeLists.txt b/gnucash/import-export/csv-imp/CMakeLists.txt
index e2fa97f..0bc7d29 100644
--- a/gnucash/import-export/csv-imp/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/CMakeLists.txt
@@ -19,6 +19,7 @@ SET(csv_import_SOURCES
   gnc-csv-trans-settings.cpp
   gnc-dummy-tokenizer.cpp
   gnc-fw-tokenizer.cpp
+  gnc-price-import.cpp
   gnc-price-props.cpp
   gnc-tokenizer.cpp
   gnc-trans-props.cpp
@@ -45,6 +46,7 @@ SET(csv_import_noinst_HEADERS
   gnc-csv-trans-settings.hpp
   gnc-dummy-tokenizer.hpp
   gnc-fw-tokenizer.hpp
+  gnc-price-import.hpp
   gnc-price-props.hpp
   gnc-tokenizer.hpp
   gnc-trans-props.hpp
diff --git a/gnucash/import-export/csv-imp/Makefile.am b/gnucash/import-export/csv-imp/Makefile.am
index 8b13d01..4083963 100644
--- a/gnucash/import-export/csv-imp/Makefile.am
+++ b/gnucash/import-export/csv-imp/Makefile.am
@@ -13,6 +13,7 @@ libgncmod_csv_import_la_SOURCES = \
   gnc-csv-gnumeric-popup.c \
   gnc-dummy-tokenizer.cpp \
   gnc-fw-tokenizer.cpp \
+  gnc-price-import.cpp \
   gnc-price-props.cpp \
   gnc-tokenizer.cpp \
   gnc-tx-import.cpp \
@@ -29,6 +30,7 @@ noinst_HEADERS = \
   gnc-csv-gnumeric-popup.h \
   gnc-dummy-tokenizer.hpp \
   gnc-fw-tokenizer.hpp \
+  gnc-price-import.hpp \
   gnc-price-props.hpp \
   gnc-tokenizer.hpp \
   gnc-tx-import.hpp \
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
index 6611875..48cfdce 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
@@ -108,6 +108,14 @@ static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
             GncTransPropType::PRICE
     };
 
+    preset->m_column_types_price = {
+            GncPricePropType::DATE,
+            GncPricePropType::AMOUNT,
+            GncPricePropType::CURRENCY_FROM,
+            GncPricePropType::CURRENCY_TO,
+            GncPricePropType::SYMBOL_FROM
+    };
+
     return preset;
 }
 
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
index 379c660..93275f2 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
@@ -36,6 +36,7 @@ extern "C" {
 #include <string>
 #include <vector>
 #include "gnc-trans-props.hpp"
+#include "gnc-price-props.hpp"
 #include "gnc-tokenizer.hpp"
 
 /** Enumeration for separator checkbutton types. These are the
@@ -93,7 +94,8 @@ std::string   m_separators;                   // Separators for csv format
 
 Account      *m_base_account;                 // Base account
 std::vector<GncTransPropType> m_column_types; // The Column types in order
-std::vector<uint32_t> m_column_widths;            // The Column widths
+std::vector<GncPricePropType> m_column_types_price; // The Column Price types in order
+std::vector<uint32_t> m_column_widths;        // The Column widths
 
 bool          m_load_error;                   // Was there an error while parsing the state file ?
 };
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
new file mode 100644
index 0000000..09deb93
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -0,0 +1,654 @@
+/********************************************************************\
+ * gnc-price-import.cpp - import prices from csv files              *
+ *                                                                  *
+ * 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 <guid.hpp>
+
+extern "C" {
+#include <platform.h>
+#if PLATFORM(WINDOWS)
+#include <windows.h>
+#endif
+
+#include <glib/gi18n.h>
+
+#include "gnc-ui-util.h" //get book
+#include "gnc-commodity.h"
+#include "gnc-pricedb.h"
+}
+
+#include <boost/regex.hpp>
+#include <boost/regex/icu.hpp>
+
+#include "gnc-price-import.hpp"
+#include "gnc-price-props.hpp"
+#include "gnc-csv-tokenizer.hpp"
+#include "gnc-fw-tokenizer.hpp"
+#include "gnc-csv-trans-settings.hpp"
+
+G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
+
+const int num_date_formats_price = 5;
+const gchar* date_format_user_price[] = {N_("y-m-d"),
+                                   N_("d-m-y"),
+                                   N_("m-d-y"),
+                                   N_("d-m"),
+                                   N_("m-d")
+                                  };
+
+const int num_currency_formats_price = 3;
+const gchar* currency_format_user_price[] = {N_("Locale"),
+                                       N_("Period: 123,456.78"),
+                                       N_("Comma: 123.456,78")
+                                      };
+
+
+/** Constructor for GncPriceImport.
+ * @return Pointer to a new GncCSvParseData
+ */
+GncPriceImport::GncPriceImport(GncImpFileFormat format)
+{
+    /* 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. */
+    m_skip_errors = false;
+    file_format(m_settings.m_file_format = format);
+}
+
+/** Destructor for GncPriceImport.
+ */
+GncPriceImport::~GncPriceImport()
+{
+}
+
+/** Sets the file format for the file to import, which
+ *  may cause the file to be reloaded as well if the
+ *  previously set file format was different and a
+ *  filename was already set.
+ *  @param format the new format to set
+ *  @exception std::ifstream::failure if file reloading fails
+ */
+void GncPriceImport::file_format(GncImpFileFormat format)
+{
+    if (m_tokenizer && m_settings.m_file_format == format)
+        return;
+
+    auto new_encoding = std::string("UTF-8");
+    auto new_imp_file = std::string();
+
+    // Recover common settings from old tokenizer
+    if (m_tokenizer)
+    {
+        new_encoding = m_tokenizer->encoding();
+        new_imp_file = m_tokenizer->current_file();
+        if (file_format() == GncImpFileFormat::FIXED_WIDTH)
+        {
+            auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
+            if (!fwtok->get_columns().empty())
+                m_settings.m_column_widths = fwtok->get_columns();
+        }
+    }
+
+    m_settings.m_file_format = format;
+    m_tokenizer = gnc_tokenizer_factory(m_settings.m_file_format);
+
+    // Set up new tokenizer with common settings
+    // recovered from old tokenizer
+    m_tokenizer->encoding(new_encoding);
+    load_file(new_imp_file);
+
+    // Restore potentially previously set separators or column_widths
+    if ((file_format() == GncImpFileFormat::CSV)
+        && !m_settings.m_separators.empty())
+        separators (m_settings.m_separators);
+    else if ((file_format() == GncImpFileFormat::FIXED_WIDTH)
+        && !m_settings.m_column_widths.empty())
+    {
+        auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
+        fwtok->columns (m_settings.m_column_widths);
+    }
+
+}
+
+GncImpFileFormat GncPriceImport::file_format()
+{
+    return m_settings.m_file_format;
+}
+
+void GncPriceImport::over_write (bool over)
+{
+    m_over_write = over;
+}
+
+bool GncPriceImport::over_write () { return m_over_write; }
+
+void GncPriceImport::reset_formatted_column (std::vector<GncPricePropType>& col_types)
+{
+    for (auto col_type: col_types)
+    {
+        auto col = std::find (m_settings.m_column_types_price.begin(),
+                m_settings.m_column_types_price.end(), col_type);
+        if (col != m_settings.m_column_types_price.end())
+            set_column_type_price (col - m_settings.m_column_types_price.begin(), col_type, true);
+    }
+}
+
+void GncPriceImport::currency_format (int currency_format)
+{
+    m_settings.m_currency_format = currency_format;
+
+    /* Reparse all currency related columns */
+    std::vector<GncPricePropType> commodities = { GncPricePropType::AMOUNT };
+    reset_formatted_column (commodities);
+}
+int GncPriceImport::currency_format () { return m_settings.m_currency_format; }
+
+void GncPriceImport::date_format (int date_format)
+{
+    m_settings.m_date_format = date_format;
+
+    /* Reparse all date related columns */
+    std::vector<GncPricePropType> dates = { GncPricePropType::DATE };
+    reset_formatted_column (dates);
+}
+int GncPriceImport::date_format () { return m_settings.m_date_format; }
+
+/** Converts raw file data using a new encoding. This function must be
+ * called after load_file only if load_file guessed
+ * the wrong encoding.
+ * @param encoding Encoding that data should be translated using
+ */
+void GncPriceImport::encoding (const std::string& encoding)
+{
+
+    // TODO investigate if we can catch conversion errors and report them
+    if (m_tokenizer)
+    {
+        m_tokenizer->encoding(encoding); // May throw
+        try
+        {
+            tokenize(false);
+        }
+        catch (...)
+        { };
+    }
+
+    m_settings.m_encoding = encoding;
+}
+
+std::string GncPriceImport::encoding () { return m_settings.m_encoding; }
+
+void GncPriceImport::update_skipped_lines(boost::optional<uint32_t> start, boost::optional<uint32_t> end,
+        boost::optional<bool> alt, boost::optional<bool> errors)
+{
+    if (start)
+        m_settings.m_skip_start_lines = *start;
+    if (end)
+        m_settings.m_skip_end_lines = *end;
+    if (alt)
+        m_settings.m_skip_alt_lines = *alt;
+    if (errors)
+        m_skip_errors = *errors;
+
+    for (uint32_t i = 0; i < m_parsed_lines.size(); i++)
+    {
+        std::get<3>(m_parsed_lines[i]) =
+            ((i < skip_start_lines()) ||             // start rows to skip
+             (i >= m_parsed_lines.size() - skip_end_lines()) ||          // end rows to skip
+             (((i - skip_start_lines()) % 2 == 1) && // skip every second row...
+                  skip_alt_lines()) ||                   // ...if requested
+             (m_skip_errors && !std::get<1>(m_parsed_lines[i]).empty())); // skip lines with errors
+    }
+}
+
+uint32_t GncPriceImport::skip_start_lines () { return m_settings.m_skip_start_lines; }
+uint32_t GncPriceImport::skip_end_lines () { return m_settings.m_skip_end_lines; }
+bool GncPriceImport::skip_alt_lines () { return m_settings.m_skip_alt_lines; }
+bool GncPriceImport::skip_err_lines () { return m_skip_errors; }
+
+void GncPriceImport::separators (std::string separators)
+{
+    if (file_format() != GncImpFileFormat::CSV)
+        return;
+
+    m_settings.m_separators = separators;
+    auto csvtok = dynamic_cast<GncCsvTokenizer*>(m_tokenizer.get());
+    csvtok->set_separators (separators);
+
+}
+std::string GncPriceImport::separators () { return m_settings.m_separators; }
+
+void GncPriceImport::settings (const CsvTransSettings& settings)
+{
+    /* First apply file format as this may recreate the tokenizer */
+    file_format (settings.m_file_format);
+    /* Only then apply the other settings */
+    m_settings = settings;
+    encoding (m_settings.m_encoding);
+
+    if (file_format() == GncImpFileFormat::CSV)
+        separators (m_settings.m_separators);
+    else if (file_format() == GncImpFileFormat::FIXED_WIDTH)
+    {
+        auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
+        fwtok->columns (m_settings.m_column_widths);
+    }
+    try
+    {
+        tokenize(false);
+    }
+    catch (...)
+    { };
+
+    /* Tokenizing will clear column types, reset them here
+     * based on the loaded settings.
+     */
+    std::copy_n (settings.m_column_types_price.begin(),
+            std::min (m_settings.m_column_types_price.size(), settings.m_column_types_price.size()),
+            m_settings.m_column_types_price.begin());
+
+}
+
+bool GncPriceImport::save_settings ()
+{
+
+    if (trans_preset_is_reserved_name (m_settings.m_name))
+        return true;
+
+    /* separators are already copied to m_settings in the separators
+     * function above. However this is not the case for the column
+     * widths in fw mode, so do this now.
+     */
+    if (file_format() == GncImpFileFormat::FIXED_WIDTH)
+    {
+        auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
+        m_settings.m_column_widths = fwtok->get_columns();
+    }
+
+    return m_settings.save();
+}
+
+void GncPriceImport::settings_name (std::string name) { m_settings.m_name = name; }
+std::string GncPriceImport::settings_name () { return m_settings.m_name; }
+
+/** Loads a file into a GncPriceImport. This is the first function
+ * that must be called after creating a new GncPriceImport. As long as
+ * this function didn't run successfully, the importer can't proceed.
+ * @param filename Name of the file that should be opened
+ * @exception may throw std::ifstream::failure on any io error
+ */
+void GncPriceImport::load_file (const std::string& filename)
+{
+
+    /* Get the raw data first and handle an error if one occurs. */
+    try
+    {
+        m_tokenizer->load_file (filename);
+        return;
+    }
+    catch (std::ifstream::failure& ios_err)
+    {
+        // Just log the error and pass it on the call stack for proper handling
+        PWARN ("Error: %s", ios_err.what());
+        throw;
+    }
+}
+
+/** Splits a file into cells. This requires having an encoding that
+ * works (see GncPriceImport::convert_encoding). Tokenizing related options
+ * should be set to the user's selections before calling this
+ * function.
+ * Notes: - this function must be called with guessColTypes set to true once
+ *          before calling it with guessColTypes set to false.
+ *        - if guessColTypes is true, all the column types will be set
+ *          GncPricePropType::NONE right now as real guessing isn't implemented yet
+ * @param guessColTypes true to guess what the types of columns are based on the cell contents
+ * @exception std::range_error if tokenizing failed
+ */
+void GncPriceImport::tokenize (bool guessColTypes)
+{
+    if (!m_tokenizer)
+        return;
+
+    uint32_t max_cols = 0;
+    m_tokenizer->tokenize();
+    m_parsed_lines.clear();
+    for (auto tokenized_line : m_tokenizer->get_tokens())
+    {
+        m_parsed_lines.push_back (std::make_tuple (tokenized_line, std::string(),
+                std::make_shared<GncImportPrice>(date_format(), currency_format()),
+                false));
+        auto length = tokenized_line.size();
+        if (length > max_cols)
+            max_cols = length;
+    }
+
+    /* If it failed, generate an error. */
+    if (m_parsed_lines.size() == 0)
+    {
+        throw (std::range_error ("Tokenizing failed."));
+        return;
+    }
+
+    m_settings.m_column_types_price.resize(max_cols, GncPricePropType::NONE);
+
+    /* Force reinterpretation of already set columns and/or base_account */
+    for (uint32_t i = 0; i < m_settings.m_column_types_price.size(); i++)
+        set_column_type_price (i, m_settings.m_column_types_price[i], true);
+
+    if (guessColTypes)
+    {
+        /* Guess column_types based
+         * on the contents of each column. */
+        /* TODO Make it actually guess. */
+    }
+}
+
+
+struct ErrorListPrice
+{
+public:
+    void add_error (std::string msg);
+    std::string str();
+    bool empty() { return m_error.empty(); }
+private:
+    std::string m_error;
+};
+
+void ErrorListPrice::add_error (std::string msg)
+{
+    m_error += "- " + msg + "\n";
+}
+
+std::string ErrorListPrice::str()
+{
+    return m_error.substr(0, m_error.size() - 1);
+}
+
+
+/* Test for the required minimum number of columns selected and
+ * the selection is consistent.
+ * @param An ErrorListPrice object to which all found issues are added.
+ */
+void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
+{
+    /* Verify if a date column is selected and it's parsable.
+     */
+    if (!check_for_column_type(GncPricePropType::DATE))
+        error_msg.add_error( _("Please select a date column."));
+
+    /* Verify an amount column is selected.
+     */
+    if (!check_for_column_type(GncPricePropType::AMOUNT))
+        error_msg.add_error( _("Please select an amount column."));
+
+    /* Verify an Currency to column is selected.
+     */
+    if (!check_for_column_type(GncPricePropType::CURRENCY_TO))
+        error_msg.add_error( _("Please select a Currency to column."));
+
+    /* Verify at least one from column (symbol_from or currency_from) column is selected.
+     */
+    if (!check_for_column_type(GncPricePropType::SYMBOL_FROM) &&
+        !check_for_column_type(GncPricePropType::CURRENCY_FROM))
+        error_msg.add_error( _("Please select a symbol or currency from column."));
+}
+
+
+/* Check whether the chosen settings can successfully parse
+ * the import data. This will check:
+ * - there's at least one line selected for import
+ * - the minimum number of columns is selected
+ * - the values in the selected columns can be parsed meaningfully.
+ * @return An empty string if all checks passed or the reason
+ *         verification failed otherwise.
+ */
+std::string GncPriceImport::verify ()
+{
+    auto newline = std::string();
+    auto error_msg = ErrorListPrice();
+
+    /* Check if the import file did actually contain any information */
+    if (m_parsed_lines.size() == 0)
+    {
+        error_msg.add_error(_("No valid data found in the selected file. It may be empty or the selected encoding is wrong."));
+        return error_msg.str();
+    }
+
+    /* Check if at least one line is selected for importing */
+    auto skip_alt_offset = m_settings.m_skip_alt_lines ? 1 : 0;
+    if (m_settings.m_skip_start_lines + m_settings.m_skip_end_lines + skip_alt_offset >= m_parsed_lines.size())
+    {
+        error_msg.add_error(_("No lines are selected for importing. Please reduce the number of lines to skip."));
+        return error_msg.str();
+    }
+
+    verify_column_selections (error_msg);
+
+    update_skipped_lines (boost::none, boost::none, boost::none, boost::none);
+
+    auto have_line_errors = false;
+    for (auto line : m_parsed_lines)
+    {
+        if (!std::get<3>(line) && !std::get<1>(line).empty())
+        {
+            have_line_errors = true;
+            break;
+        }
+    }
+
+    if (have_line_errors)
+        error_msg.add_error( _("Not all fields could be parsed. Please correct the issues reported for each line or adjust the lines to skip."));
+
+    return error_msg.str();
+}
+
+/** Checks whether the parsed line contains all essential properties.
+ * @param parsed_line The line we are checking
+ * @exception std::invalid_argument in an essential property is missing
+ */
+static void price_properties_verify_essentials (std::vector<parse_line_t>::iterator& parsed_line)
+{
+    std::string error_message;
+    std::shared_ptr<GncImportPrice> price_props;
+    std::tie(std::ignore, error_message, price_props, std::ignore) = *parsed_line;
+
+    auto price_error = price_props->verify_essentials();
+
+    error_message.clear();
+    if (!price_error.empty())
+    {
+        error_message += price_error;
+        error_message += "\n";
+    }
+
+    if (!error_message.empty())
+        throw std::invalid_argument(error_message);
+}
+
+void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_line)
+{
+    StrVec line;
+    std::string error_message;
+    std::shared_ptr<GncImportPrice> price_props = nullptr;
+    bool skip_line = false;
+    std::tie(line, error_message, price_props, skip_line) = *parsed_line;
+
+    if (skip_line)
+        return;
+
+    error_message.clear();
+
+    /* If column parsing was successful, convert price properties into a price. */
+    try
+    {
+        price_properties_verify_essentials (parsed_line);
+
+        QofBook* book = gnc_get_current_book();
+        GNCPriceDB *pdb = gnc_pricedb_get_db (book);
+
+        /* If all went well, add this price to the list. */
+        auto price_created = price_props->create_price (book, pdb, m_over_write);
+//FIXME Need to look at this
+        if (price_created)
+            m_prices_added++;
+        else
+            m_prices_duplicated++;
+    }
+    catch (const std::invalid_argument& e)
+    {
+        error_message = e.what();
+        PINFO("User warning: %s", error_message.c_str());
+    }
+}
+
+
+/** Creates a list of prices from parsed data. The parsed data
+ * will first be validated. If any errors are found in lines that are marked
+ * for processing (ie not marked to skip) this function will
+ * throw an error.
+ * @param skip_errors true skip over lines with errors
+ * @exception throws std::invalid_argument if data validation or processing fails.
+ */
+void GncPriceImport::create_prices ()
+{
+    /* Start with verifying the current data. */
+    auto verify_result = verify();
+    if (!verify_result.empty())
+        throw std::invalid_argument (verify_result);
+
+    m_prices_added = 0;
+    m_prices_duplicated = 0;
+
+    /* Iterate over all parsed lines */
+    for (auto parsed_lines_it = m_parsed_lines.begin();
+            parsed_lines_it != m_parsed_lines.end();
+            ++parsed_lines_it)
+    {
+        /* Skip current line if the user specified so */
+        if ((std::get<3>(*parsed_lines_it)))
+            continue;
+
+        /* Should not throw anymore, otherwise verify needs revision */
+        create_price (parsed_lines_it);
+    }
+    PINFO("Number of lines is %d, added is %d, duplicates is %d",
+         (int)m_parsed_lines.size(), m_prices_added, m_prices_duplicated);
+}
+
+bool
+GncPriceImport::check_for_column_type (GncPricePropType type)
+{
+    return (std::find (m_settings.m_column_types_price.begin(),
+                       m_settings.m_column_types_price.end(), type)
+                        != m_settings.m_column_types_price.end());
+}
+
+/* A helper function intended to be called only from set_column_type_price */
+void GncPriceImport::update_price_props (uint32_t row, uint32_t col, GncPricePropType prop_type)
+{
+    if (prop_type == GncPricePropType::NONE)
+        return; /* Only deal with price related properties. */
+
+    auto price_props = std::make_shared<GncImportPrice> (*(std::get<2>(m_parsed_lines[row])).get());
+    auto value = std::string();
+
+    if (col < std::get<0>(m_parsed_lines[row]).size())
+        value = std::get<0>(m_parsed_lines[row]).at(col);
+
+    if (value.empty())
+        price_props->reset (prop_type);
+    else
+    {
+        try
+        {
+            price_props->set(prop_type, value);
+        }
+        catch (const std::exception& e)
+        {
+            /* Do nothing, just prevent the exception from escalating up
+             * However log the error if it happens on a row that's not skipped
+             */
+            if (!std::get<3>(m_parsed_lines[row]))
+                PINFO("User warning: %s", e.what());
+        }
+    }
+    /* Store the result */
+    std::get<2>(m_parsed_lines[row]) = price_props;
+}
+
+void
+GncPriceImport::set_column_type_price (uint32_t position, GncPricePropType type, bool force)
+{
+    if (position >= m_settings.m_column_types_price.size())
+        return;
+
+    auto old_type = m_settings.m_column_types_price[position];
+    if ((type == old_type) && !force)
+        return; /* Nothing to do */
+
+    // Column types should be unique, so remove any previous occurrence of the new type
+    std::replace(m_settings.m_column_types_price.begin(), m_settings.m_column_types_price.end(),
+            type, GncPricePropType::NONE);
+
+    m_settings.m_column_types_price.at (position) = type;
+
+    /* Update the preparsed data */
+    for (auto parsed_lines_it = m_parsed_lines.begin();
+            parsed_lines_it != m_parsed_lines.end();
+            ++parsed_lines_it)
+    {
+        /* Reset date and currency formats for each price props object
+         * to ensure column updates use the most recent one
+         */
+        std::get<2>(*parsed_lines_it)->set_date_format (m_settings.m_date_format);
+        std::get<2>(*parsed_lines_it)->set_currency_format (m_settings.m_currency_format);
+
+        uint32_t row = parsed_lines_it - m_parsed_lines.begin();
+
+        /* If the column type actually changed, first reset the property
+         * represented by the old column type
+         */
+        if (old_type != type)
+        {
+            auto old_col = std::get<0>(*parsed_lines_it).size(); // Deliberately out of bounds to trigger a reset!
+            if ((old_type > GncPricePropType::NONE)
+                    && (old_type <= GncPricePropType::PRICE_PROPS))
+                update_price_props (row, old_col, old_type);
+        }
+        /* Then set the property represented by the new column type */
+        if ((type > GncPricePropType::NONE)
+                && (type <= GncPricePropType::PRICE_PROPS))
+            update_price_props (row, position, type);
+
+        /* Report errors if there are any */
+        auto price_errors = std::get<2>(*parsed_lines_it)->errors();
+        std::get<1>(*parsed_lines_it) =
+                price_errors +
+                (price_errors.empty() ? std::string() : "\n");
+    }
+}
+
+std::vector<GncPricePropType> GncPriceImport::column_types_price ()
+{
+    return m_settings.m_column_types_price;
+}
+
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
new file mode 100644
index 0000000..0898215
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -0,0 +1,160 @@
+/********************************************************************\
+ * gnc-price-import.hpp - import prices from csv files              *
+ *                                                                  *
+ * 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 Class to import prices from CSV or fixed width files
+     *
+     gnc-price-import.hpp
+     @author Copyright (c) 2015 Geert Janssens <geert at kobaltwit.be>
+     @author Copyright (c) 2017 Robert Fewell
+ */
+
+#ifndef GNC_PRICE_IMPORT_HPP
+#define GNC_PRICE_IMPORT_HPP
+
+extern "C" {
+#include "config.h"
+
+}
+
+#include <vector>
+#include <set>
+#include <map>
+#include <memory>
+
+#include "gnc-tokenizer.hpp"
+#include "gnc-price-props.hpp"
+#include "gnc-csv-trans-settings.hpp"
+#include <boost/optional.hpp>
+
+/* 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[];
+
+/** Tuple to hold
+ *  - a tokenized line of input
+ *  - an optional error string
+ *  - a struct to hold user selected properties for a price */
+using parse_line_t = std::tuple<StrVec,
+                                std::string,
+                                std::shared_ptr<GncImportPrice>,
+                                bool>;
+struct ErrorListPrice;
+
+/** The actual PriceImport class
+ * It's intended to use in the following sequence of actions:
+ * - set a file format
+ * - load a file
+ * - optionally convert it's encoding
+ * - parse the file into lines, which in turn are split up in columns
+ *   the result of this step can be queried from tokenizer
+ * - the user should now map the columns to types, which is stored in column_types
+ * - last step is convert the mapped columns into a list of transactions
+ * - this list will then be passed on the the generic importer for further processing */
+class GncPriceImport
+{
+public:
+    // Constructor - Destructor
+    GncPriceImport(GncImpFileFormat format = GncImpFileFormat::UNKNOWN);
+    ~GncPriceImport();
+
+    void file_format(GncImpFileFormat format);
+    GncImpFileFormat file_format();
+
+    void over_write (bool over);
+    bool over_write ();
+
+    void currency_format (int currency_format);
+    int currency_format ();
+
+    void date_format (int date_format);
+    int date_format ();
+
+    void encoding (const std::string& encoding);
+    std::string encoding ();
+
+    void update_skipped_lines (boost::optional<uint32_t> start, boost::optional<uint32_t> end,
+                               boost::optional<bool> alt, boost::optional<bool> errors);
+    uint32_t skip_start_lines ();
+    uint32_t skip_end_lines ();
+    bool skip_alt_lines ();
+    bool skip_err_lines ();
+
+    void separators (std::string separators);
+    std::string separators ();
+
+    void settings (const CsvTransSettings& settings);
+    bool save_settings ();
+
+    void settings_name (std::string name);
+    std::string settings_name ();
+
+
+    void load_file (const std::string& filename);
+
+    void tokenize (bool guessColTypes);
+
+    std::string verify();
+
+    /** This function will attempt to convert all tokenized lines into
+     *  prices using the column types the user has set.
+     */
+    void create_prices ();
+    bool check_for_column_type (GncPricePropType type);
+    void set_column_type_price (uint32_t position, GncPricePropType type, bool force = false);
+    std::vector<GncPricePropType> column_types_price ();
+
+    std::unique_ptr<GncTokenizer> m_tokenizer;    /**< Will handle file loading/encoding conversion/splitting into fields */
+    std::vector<parse_line_t> m_parsed_lines;     /**< source file parsed into a two-dimensional array of strings.
+                                                     Per line also holds possible error messages and objects with extracted
+                                                     price properties. */
+    int  m_prices_added;
+    int  m_prices_duplicated;
+
+private:
+    /** A helper function used by create_prices. It will attempt
+     *  to convert a single tokenized line into a price using
+     *  the column types the user has set.
+     */
+    void create_price (std::vector<parse_line_t>::iterator& parsed_line);
+
+    void verify_column_selections (ErrorListPrice& error_msg);
+
+    /* Internal helper function to force reparsing of columns subject to format changes */
+    void reset_formatted_column (std::vector<GncPricePropType>& col_types);
+
+    /* Two internal helper functions that should only be called from within
+     * set_column_type_price for consistency (otherwise error messages may not be (re)set)
+     */
+    void update_price_props (uint32_t row, uint32_t col, GncPricePropType prop_type);
+
+    struct CsvTranSettings;
+    CsvTransSettings m_settings;
+    bool m_skip_errors;
+    bool m_over_write;
+};
+
+
+#endif
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 6f1189b..d101280 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -31,7 +31,7 @@ extern "C" {
 #endif
 
 #include <glib/gi18n.h>
-
+#include "gnc-pricedb.h"
 #include "gnc-commodity.h"
 }
 

commit 17d8d424a0a6266a9790797d88452f2c356f3e0d
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 10:44:15 2017 +0000

    Add property files for the csv price importer
    
    These files are largely based on the csv transaction importer

diff --git a/gnucash/import-export/csv-imp/CMakeLists.txt b/gnucash/import-export/csv-imp/CMakeLists.txt
index c2a77b8..e2fa97f 100644
--- a/gnucash/import-export/csv-imp/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/CMakeLists.txt
@@ -19,6 +19,7 @@ SET(csv_import_SOURCES
   gnc-csv-trans-settings.cpp
   gnc-dummy-tokenizer.cpp
   gnc-fw-tokenizer.cpp
+  gnc-price-props.cpp
   gnc-tokenizer.cpp
   gnc-trans-props.cpp
   gnc-tx-import.cpp
@@ -44,6 +45,7 @@ SET(csv_import_noinst_HEADERS
   gnc-csv-trans-settings.hpp
   gnc-dummy-tokenizer.hpp
   gnc-fw-tokenizer.hpp
+  gnc-price-props.hpp
   gnc-tokenizer.hpp
   gnc-trans-props.hpp
   gnc-tx-import.hpp
diff --git a/gnucash/import-export/csv-imp/Makefile.am b/gnucash/import-export/csv-imp/Makefile.am
index 06ef43f..8b13d01 100644
--- a/gnucash/import-export/csv-imp/Makefile.am
+++ b/gnucash/import-export/csv-imp/Makefile.am
@@ -13,6 +13,7 @@ libgncmod_csv_import_la_SOURCES = \
   gnc-csv-gnumeric-popup.c \
   gnc-dummy-tokenizer.cpp \
   gnc-fw-tokenizer.cpp \
+  gnc-price-props.cpp \
   gnc-tokenizer.cpp \
   gnc-tx-import.cpp \
   gnc-trans-props.cpp \
@@ -28,6 +29,7 @@ noinst_HEADERS = \
   gnc-csv-gnumeric-popup.h \
   gnc-dummy-tokenizer.hpp \
   gnc-fw-tokenizer.hpp \
+  gnc-price-props.hpp \
   gnc-tokenizer.hpp \
   gnc-tx-import.hpp \
   gnc-trans-props.hpp \
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
new file mode 100644
index 0000000..1fdcaa53
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -0,0 +1,508 @@
+/********************************************************************\
+ * gnc-price-props.cpp - encapsulate price properties for use       *
+ *                       in the csv importer                        *
+ *                                                                  *
+ * 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                   *
+ *                                                                  *
+\********************************************************************/
+
+extern "C" {
+#include <platform.h>
+#if PLATFORM(WINDOWS)
+#include <windows.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "engine-helpers.h"
+#include "gnc-ui-util.h"
+#include "gnc-pricedb.h"
+
+}
+
+#include <string>
+#include <boost/regex.hpp>
+#include <boost/regex/icu.hpp>
+#include "gnc-price-props.hpp"
+
+G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
+
+/* This map contains a set of strings representing the different column types. */
+std::map<GncPricePropType, const char*> gnc_csv_price_col_type_strs = {
+        { GncPricePropType::NONE, N_("None") },
+        { GncPricePropType::DATE, N_("Date") },
+        { GncPricePropType::AMOUNT, N_("Amount") },
+        { GncPricePropType::CURRENCY_FROM, N_("Currency From") },
+        { GncPricePropType::CURRENCY_TO, N_("Currency To") },
+        { GncPricePropType::SYMBOL_FROM, N_("Symbol From") },
+};
+
+/* Regular expressions used to parse dates per date format */
+const char* date_regex_price[] = {
+                             "(?:"                                   // either y-m-d
+                                 "(?<YEAR>[0-9]+)[-/.' ]+"
+                                 "(?<MONTH>[0-9]+)[-/.' ]+"
+                                 "(?<DAY>[0-9]+)"
+                             "|"                                     // or CCYYMMDD
+                                 "(?<YEAR>[0-9]{4})"
+                                 "(?<MONTH>[0-9]{2})"
+                                 "(?<DAY>[0-9]{2})"
+                             ")",
+
+                             "(?:"                                   // either d-m-y
+                                 "(?<DAY>[0-9]+)[-/.' ]+"
+                                 "(?<MONTH>[0-9]+)[-/.' ]+"
+                                 "(?<YEAR>[0-9]+)"
+                             "|"                                     // or DDMMCCYY
+                                 "(?<DAY>[0-9]{2})"
+                                 "(?<MONTH>[0-9]{2})"
+                                 "(?<YEAR>[0-9]{4})"
+                             ")",
+
+                             "(?:"                                   // either m-d-y
+                                 "(?<MONTH>[0-9]+)[-/.' ]+"
+                                 "(?<DAY>[0-9]+)[-/.' ]+"
+                                 "(?<YEAR>[0-9]+)"
+                             "|"                                     // or MMDDCCYY
+                                 "(?<MONTH>[0-9]{2})"
+                                 "(?<DAY>[0-9]{2})"
+                                 "(?<YEAR>[0-9]{4})"
+                             ")",
+
+                             "(?:"                                   // either d-m(-y)
+                                 "(?<DAY>[0-9]+)[-/.' ]+"
+                                 "(?<MONTH>[0-9]+)(?:[-/.' ]+"
+                                 "(?<YEAR>[0-9]+))?"
+                             "|"                                     // or DDMM(CCYY)
+                                 "(?<DAY>[0-9]{2})"
+                                 "(?<MONTH>[0-9]{2})"
+                                 "(?<YEAR>[0-9]+)?"
+                             ")",
+
+                             "(?:"                                   // either m-d(-y)
+                                 "(?<MONTH>[0-9]+)[-/.' ]+"
+                                 "(?<DAY>[0-9]+)(?:[-/.' ]+"
+                                 "(?<YEAR>[0-9]+))?"
+                             "|"                                     // or MMDD(CCYY)
+                                 "(?<MONTH>[0-9]{2})"
+                                 "(?<DAY>[0-9]{2})"
+                                 "(?<YEAR>[0-9]+)?"
+                             ")",
+};
+
+/** 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
+ * @exception std::invalid_argument if the string can't be parsed into a date.
+ * @return The parsed value of date_str on success, throws on failure
+ */
+
+time64 parse_date_price (const std::string &date_str, int format)
+{
+    boost::regex r(date_regex_price[format]);
+    boost::smatch what;
+    if(!boost::regex_search(date_str, what, r))
+        throw std::invalid_argument (_("Value can't be parsed into a date using the selected date format."));  // regex didn't find a match
+
+    // Attention: different behavior from 2.6.x series !
+    // If date format without year was selected, the match
+    // should NOT have found a year.
+    if ((format >= 3) && (what.length("YEAR") != 0))
+        throw std::invalid_argument (_("Value appears to contain a year while the selected format forbids this."));
+
+    auto day = std::stoi (what.str("DAY"));
+    auto month = std::stoi (what.str("MONTH"));
+
+    int year;
+    if (format < 3)
+    {
+        /* The input dates have a year, so use that one */
+        year = std::stoi (what.str("YEAR"));
+
+        /* Handle two-digit years. */
+        if (year < 100)
+        {
+            /* We allow two-digit years in the range 1969 - 2068. */
+            if (year < 69)
+                year += 2000;
+            else
+                year += 1900;
+        }
+    }
+    else
+    {
+        /* The input dates don't have a year, so work with today's year.
+         */
+        gnc_timespec2dmy(timespec_now(), nullptr, nullptr, &year);
+    }
+
+    auto ts = gnc_dmy2timespec_neutral(day, month, year);
+    if (ts.tv_sec == INT64_MAX)
+        throw std::invalid_argument (_("Value can't be parsed into a date using the selected date format."));
+
+    return ts.tv_sec;
+}
+
+
+/** Convert str into a GncRational using the user-specified (import) currency format.
+ * @param str The string to be parsed
+ * @param currency_format The currency format to use.
+ * @return a GncNumeric
+ * @exception May throw std::invalid argument if string can't be parsed properly
+ */
+GncNumeric parse_amount_price (const std::string &str, int currency_format)
+{
+    /* If a cell is empty or just spaces return invalid amount */
+    if(!boost::regex_search(str, boost::regex("[0-9]")))
+        throw std::invalid_argument (_("Value doesn't appear to contain a valid number."));
+
+    auto expr = boost::make_u32regex("[[:Sc:]]");
+    std::string str_no_symbols = boost::u32regex_replace(str, expr, "");
+
+    /* Convert based on user chosen currency format */
+    gnc_numeric val;
+    char *endptr;
+    switch (currency_format)
+    {
+    case 0:
+        /* Currency locale */
+        if (!(xaccParseAmount (str_no_symbols.c_str(), TRUE, &val, &endptr)))
+            throw std::invalid_argument (_("Value can't be parsed into a number using the selected currency format."));
+        break;
+    case 1:
+        /* Currency decimal period */
+        if (!(xaccParseAmountExtended (str_no_symbols.c_str(), TRUE, '-', '.', ',', "\003\003", "$+", &val, &endptr)))
+            throw std::invalid_argument (_("Value can't be parsed into a number using the selected currency format."));
+        break;
+    case 2:
+        /* Currency decimal comma */
+        if (!(xaccParseAmountExtended (str_no_symbols.c_str(), TRUE, '-', ',', '.', "\003\003", "$+", &val, &endptr)))
+            throw std::invalid_argument (_("Value can't be parsed into a number using the selected currency format."));
+        break;
+    }
+
+    return GncNumeric(val);
+}
+
+gnc_commodity* parse_commodity_price_comm (const std::string& comm_str)
+{
+    if (comm_str.empty())
+        return nullptr;
+
+    auto table = gnc_commodity_table_get_table (gnc_get_current_book());
+    gnc_commodity* comm = nullptr;
+
+    /* First try commodity as a unique name. */
+    if (comm_str.find("::"))
+        comm = gnc_commodity_table_lookup_unique (table, comm_str.c_str());
+
+    /* Then try mnemonic in the currency namespace */
+    if (!comm)
+        comm = gnc_commodity_table_lookup (table,
+                GNC_COMMODITY_NS_CURRENCY, comm_str.c_str());
+
+    if (!comm)
+    {
+        /* If that fails try mnemonic in all other namespaces */
+        auto namespaces = gnc_commodity_table_get_namespaces(table);
+        for (auto ns = namespaces; ns; ns = ns->next)
+        {
+            gchar* ns_str = (gchar*)ns->data;
+            if (g_utf8_collate(ns_str, GNC_COMMODITY_NS_CURRENCY) == 0)
+                continue;
+
+            comm = gnc_commodity_table_lookup (table,
+                    ns_str, comm_str.c_str());
+            if (comm)
+                break;
+        }
+    }
+
+    if (!comm)
+        throw std::invalid_argument (_("Value can't be parsed into a valid commodity."));
+    else
+        return comm;
+}
+
+gnc_commodity * parse_commodity_price_sym (const std::string& sym_str, bool is_currency)
+{
+    if (sym_str.empty())
+        return nullptr;
+
+    auto commodity_table = gnc_get_current_commodities ();
+    GList         *namespaces;
+    gnc_commodity *retval = nullptr;
+    gnc_commodity *tmp_commodity = nullptr;
+    char  *tmp_namespace = nullptr;
+    GList *commodity_list = NULL;
+    GList *namespace_list = gnc_commodity_table_get_namespaces (commodity_table);
+
+    namespace_list = g_list_first (namespace_list);
+    while (namespace_list != NULL && retval == NULL)
+    {
+        tmp_namespace = (char*)namespace_list->data;
+        DEBUG("Looking at namespace %s", tmp_namespace);
+        commodity_list = gnc_commodity_table_get_commodities (commodity_table, tmp_namespace);
+        commodity_list  = g_list_first (commodity_list);
+        while (commodity_list != NULL && retval == NULL)
+        {
+            const char* tmp_mnemonic = NULL;
+            tmp_commodity = (gnc_commodity*)commodity_list->data;
+            DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (tmp_commodity));
+            tmp_mnemonic = gnc_commodity_get_mnemonic (tmp_commodity);
+            if (g_strcmp0 (tmp_mnemonic, sym_str.c_str()) == 0)
+            {
+                retval = tmp_commodity;
+                DEBUG("Commodity %s%s", gnc_commodity_get_fullname (retval), " matches.");
+            }
+            commodity_list = g_list_next (commodity_list);
+        }
+        namespace_list = g_list_next (namespace_list);
+    }
+    g_list_free (commodity_list);
+    g_list_free (namespace_list);
+
+    if (!retval)
+        throw std::invalid_argument (_("Value can't be parsed into a valid commodity."));
+    else
+    {
+        if (gnc_commodity_is_currency (retval) != is_currency)
+            throw std::invalid_argument (_("Value parsed into an invalid commodity for column type."));
+        else
+            return retval;
+    }
+}
+
+void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
+{
+    try
+    {
+        // Drop any existing error for the prop_type we're about to set
+        m_errors.erase(prop_type);
+
+        gnc_commodity *comm = nullptr;
+        switch (prop_type)
+        {
+            case GncPricePropType::DATE:
+                m_date = boost::none;
+                m_date = parse_date_price (value, m_date_format); // Throws if parsing fails
+                break;
+
+            case GncPricePropType::AMOUNT:
+                m_amount = boost::none;
+                m_amount = parse_amount_price (value, m_currency_format); // Will throw if parsing fails
+                break;
+
+            case GncPricePropType::CURRENCY_FROM:
+                m_currency_from = boost::none;
+                comm = parse_commodity_price_sym (value, true); // Throws if parsing fails
+                if (comm)
+                    m_currency_from = comm;
+                break;
+
+            case GncPricePropType::CURRENCY_TO:
+                m_currency_to = boost::none;
+                comm = parse_commodity_price_sym (value, true); // Throws if parsing fails
+                if (comm)
+                    m_currency_to = comm;
+                break;
+
+            case GncPricePropType::SYMBOL_FROM:
+                m_symbol_from = boost::none;
+                comm = parse_commodity_price_sym (value, false); // Throws if parsing fails
+                if (comm)
+                    m_symbol_from = comm;
+                break;
+
+            default:
+                /* Issue a warning for all other prop_types. */
+                PWARN ("%d is an invalid property for a Price", static_cast<int>(prop_type));
+                break;
+        }
+    }
+    catch (const std::invalid_argument& e)
+    {
+        auto err_str = std::string(_(gnc_csv_price_col_type_strs[prop_type])) +
+                       std::string(_(" could not be understood.\n")) +
+                       e.what();
+        m_errors.emplace(prop_type, err_str);
+        throw std::invalid_argument (err_str);
+    }
+    catch (const std::out_of_range& e)
+    {
+        auto err_str = std::string(_(gnc_csv_price_col_type_strs[prop_type])) +
+                       std::string(_(" could not be understood.\n")) +
+                       e.what();
+        m_errors.emplace(prop_type, err_str);
+        throw std::invalid_argument (err_str);
+    }
+}
+
+void GncImportPrice::reset (GncPricePropType prop_type)
+{
+    try
+    {
+        set (prop_type, std::string());
+    }
+    catch (...)
+    {
+        // Set with an empty string will effectively clear the property
+        // but can also set an error for the property. Clear that error here.
+        m_errors.erase(prop_type);
+    }
+}
+
+std::string GncImportPrice::verify_essentials (void)
+{
+    /* Make sure this price has the minimum required set of properties defined */
+    if (m_date == boost::none)
+        return _("No date column.");
+    else if (m_amount == boost::none)
+        return _("No amount column.");
+    else if (m_currency_to == boost::none)
+        return _("No Currency to column.");
+    else if ((m_symbol_from == boost::none) && (m_currency_from == boost::none))
+        return _("No from column.");
+    else
+        return std::string();
+}
+
+bool GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
+{
+    /* Gently refuse to create the price if the basics are not set correctly
+     * This should have been tested before calling this function though!
+     */
+    auto check = verify_essentials();
+    if (!check.empty())
+    {
+        PWARN ("Refusing to create price because essentials not set properly: %s", check.c_str());
+        return false;
+    }
+
+    Timespec date;
+    timespecFromTime64 (&date, *m_date);
+    date.tv_nsec = 0;
+
+#ifdef skip
+//FIXME Numeric needs changing, copied from old version...
+    bool rev = false;
+    gnc_commodity *comm_from = nullptr;
+
+    if (m_currency_from != boost::none) // Currency Import
+    {
+        // Check for currency in reverse direction.
+        GNCPrice *rev_price = gnc_pricedb_lookup_day (pdb, *m_currency_to, *m_currency_from, date);
+        if (rev_price != nullptr)
+            rev = true;
+        gnc_price_unref (rev_price);
+
+        // Check for price less than 1, reverse if so.
+        if (gnc_numeric_compare (*m_amount, gnc_numeric_create (1, 1)) != 1)
+            rev = true;
+
+        comm_from = *m_currency_from;
+        DEBUG("Commodity from is a Currency");
+    }
+    else
+        comm_from = *m_symbol_from;
+
+    DEBUG("Date is %s, Rev is %d, Commodity from is '%s', Currency is '%s', Amount is %s", gnc_print_date (date),
+          rev, gnc_commodity_get_fullname (comm_from), gnc_commodity_get_fullname (*m_currency_to),
+          gnc_num_dbg_to_string (*m_amount)           );
+
+    GNCPrice *old_price = nullptr;
+
+    // Should the commodities be reversed
+    if (rev)
+        old_price = gnc_pricedb_lookup_day (pdb, *m_currency_to, comm_from, date);
+    else
+        old_price = gnc_pricedb_lookup_day (pdb, comm_from, *m_currency_to, date);
+
+    // Should old price be over writen
+    if ((old_price != nullptr) && (over == true))
+    {
+        DEBUG("Over write");
+        gnc_pricedb_remove_price (pdb, old_price);
+        gnc_price_unref (old_price);
+        old_price = nullptr;
+    }
+#endif
+    bool ret_val = true;
+#ifdef skip
+    // Create the new price
+    if (old_price == nullptr)
+    {
+        DEBUG("Create");
+        GNCPrice *price = gnc_price_create (book);
+        gnc_price_begin_edit (price);
+
+        if (rev)
+        {
+            gnc_price_set_commodity (price, *m_currency_to);
+            gnc_price_set_currency (price, comm_from);
+            *m_amount = gnc_numeric_convert (gnc_numeric_invert (*m_amount),
+                                          CURRENCY_DENOM, GNC_HOW_RND_ROUND_HALF_UP);
+            gnc_price_set_value (price, *m_amount);
+        }
+        else
+        {
+            gnc_price_set_commodity (price, comm_from);
+            gnc_price_set_currency (price, *m_currency_to);
+            gnc_price_set_value (price, *m_amount);
+        }
+        gnc_price_set_time (price, date);
+        gnc_price_set_source (price, PRICE_SOURCE_USER_PRICE);
+//FIXME Not sure which one        gnc_price_set_source (price, PRICE_SOURCE_FQ);
+        gnc_price_set_typestr (price, PRICE_TYPE_LAST);
+        gnc_price_commit_edit (price);
+
+        bool perr = gnc_pricedb_add_price (pdb, price);
+
+        gnc_price_unref (price);
+
+         if (perr == false)
+            throw std::invalid_argument (_("Failed to create price from selected columns."));
+//FIXME Not sure about this, should this be a PWARN
+    }
+    else
+
+#endif
+        ret_val = false;
+
+    return ret_val;
+}
+
+static std::string gen_err_str (std::map<GncPricePropType, std::string>& errors)
+{
+    auto full_error = std::string();
+    for (auto error : errors)
+    {
+        full_error += (full_error.empty() ? "" : "\n") + error.second;
+    }
+    return full_error;
+}
+
+std::string GncImportPrice::errors ()
+{
+    return gen_err_str (m_errors);
+}
+
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
new file mode 100644
index 0000000..6f1189b
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -0,0 +1,110 @@
+/********************************************************************\
+ * gnc-price-props.hpp - encapsulate price properties for use       *
+ *                       in the csv importer                        *
+ *                                                                  *
+ * 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_PRICE_PROPS_HPP
+#define GNC_PRICE_PROPS_HPP
+
+extern "C" {
+#include <platform.h>
+#if PLATFORM(WINDOWS)
+#include <windows.h>
+#endif
+
+#include <glib/gi18n.h>
+
+#include "gnc-commodity.h"
+}
+
+#include <string>
+#include <map>
+#include <memory>
+#include <boost/optional.hpp>
+#include <gnc-numeric.hpp>
+
+/** 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 GncPricePropType::NONE
+ * type. */
+enum class GncPricePropType {
+    NONE,
+    DATE,
+    AMOUNT,
+    CURRENCY_FROM,
+    CURRENCY_TO,
+    SYMBOL_FROM,
+    PRICE_PROPS = SYMBOL_FROM
+};
+
+/** Maps all column types to a string representation.
+ *  The actual definition is in gnc-csv-imp-prices.cpp.
+ *  Attention: that definition should be adjusted for any
+ *  changes to enum class GncPricePropType ! */
+extern std::map<GncPricePropType, const char*> gnc_csv_price_col_type_strs;
+
+/** Functor to check if the above map has an element of which
+ *  the value equals name. To be used with std::find_if.
+ */
+struct test_price_prop_type_str
+{
+    test_price_prop_type_str( const char* name ) : m_name(name) {}
+    bool operator()( const std::pair<GncPricePropType, const char*>& v ) const
+    {
+        return !g_strcmp0(v.second, m_name);
+    }
+private:
+    const char *m_name;
+};
+
+time64 parse_date_price (const std::string &date_str, int format);
+gnc_commodity* parse_commodity_price_comm (const std::string& comm_str);
+gnc_commodity* parse_commodity_price_sym (const std::string& comm_str, bool is_currency);
+GncNumeric parse_amount_price (const std::string &str, int currency_format);
+
+struct GncImportPrice
+{
+public:
+    GncImportPrice (int date_format, int currency_format) : m_date_format{date_format},
+        m_currency_format{currency_format}{};
+
+    void set (GncPricePropType prop_type, const std::string& value);
+    void set_date_format (int date_format) { m_date_format = date_format ;}
+    void set_currency_format (int currency_format) { m_currency_format = currency_format ;}
+    void reset (GncPricePropType prop_type);
+    std::string verify_essentials (void);
+    bool create_price (QofBook* book, GNCPriceDB *pdb, bool over);
+    std::string errors();
+
+private:
+    int m_date_format;
+    int m_currency_format;
+    boost::optional<time64> m_date;
+    boost::optional<GncNumeric> m_amount;
+    boost::optional<gnc_commodity*> m_currency_from;
+    boost::optional<gnc_commodity*> m_currency_to;
+    boost::optional<gnc_commodity*> m_symbol_from;
+    bool created = false;
+
+    std::map<GncPricePropType, std::string> m_errors;
+};
+
+#endif

commit 66da4ae37404dc46a6ee1a81289cd2b8fd506383
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Thu Dec 7 11:19:18 2017 +0000

    Add a test for empty values
    
    Some csv values are allowed to be empty based on options selected so
    add a test for this otherwise all values are required.

diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 705d37c..61c876d 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -649,15 +649,13 @@ void GncPriceImport::update_price_props (uint32_t row, uint32_t col, GncPricePro
         return; /* Only deal with price related properties. */
 
     auto price_props = std::make_shared<GncImportPrice> (*(std::get<2>(m_parsed_lines[row])).get());
-    auto value = std::string();
 
-    if (col < std::get<0>(m_parsed_lines[row]).size())
-        value = std::get<0>(m_parsed_lines[row]).at(col);
-
-    if (value.empty())
-        price_props->reset (prop_type);
+    if (col >= std::get<0>(m_parsed_lines[row]).size())
+        price_props->reset (prop_type); //reset errors
     else
     {
+        auto value = std::get<0>(m_parsed_lines[row]).at(col);
+        bool enable_test_empty = true;
         try
         {
             // set the from_commodity based on combo so we can test for same.
@@ -665,14 +663,20 @@ void GncPriceImport::update_price_props (uint32_t row, uint32_t col, GncPricePro
             {
                 if (m_settings.m_from_commodity)
                     price_props->set_from_commodity (m_settings.m_from_commodity);
+
+                if (m_settings.m_to_currency)
+                    enable_test_empty = false;
             }
             // set the to_currency based on combo so we can test for same.
             if (prop_type == GncPricePropType::FROM_COMMODITY)
             {
                 if (m_settings.m_to_currency)
                     price_props->set_to_currency (m_settings.m_to_currency);
+
+                if (m_settings.m_from_commodity)
+                    enable_test_empty = false;
             }
-            price_props->set(prop_type, value);
+            price_props->set(prop_type, value, enable_test_empty);
         }
         catch (const std::exception& e)
         {
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index 1ccd6e5..151bd38 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -135,13 +135,17 @@ gnc_commodity* parse_commodity_price_comm (const std::string& comm_str)
         return comm;
 }
 
-void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
+void GncImportPrice::set (GncPricePropType prop_type, const std::string& value, bool enable_test_empty)
 {
     try
     {
         // Drop any existing error for the prop_type we're about to set
         m_errors.erase(prop_type);
 
+        // conditional test for empty values
+        if (value.empty() && enable_test_empty)
+            throw std::invalid_argument (_("Column value can not be empty."));
+
         gnc_commodity *comm = nullptr;
         switch (prop_type)
         {
@@ -207,7 +211,8 @@ void GncImportPrice::reset (GncPricePropType prop_type)
 {
     try
     {
-        set (prop_type, std::string());
+        // set enable_test_empty to false to allow empty values
+        set (prop_type, std::string(), false);
     }
     catch (...)
     {
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 77e39dc..3a35861 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -86,7 +86,7 @@ public:
     GncImportPrice (int date_format, int currency_format) : m_date_format{date_format},
         m_currency_format{currency_format}{};
 
-    void set (GncPricePropType prop_type, const std::string& value);
+    void set (GncPricePropType prop_type, const std::string& value, bool enable_test_empty);
     void set_date_format (int date_format) { m_date_format = date_format ;}
     void set_currency_format (int currency_format) { m_currency_format = currency_format ;}
     void reset (GncPricePropType prop_type);

commit db079b55404dfa1c04533b28d6d0ecd38da10689
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Thu Dec 7 11:17:14 2017 +0000

    Replace date parse function with one from gnc_datetime

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index af810cb..fbc563c 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -608,10 +608,8 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
 
         /* Add in the date format combo box and hook it up to an event handler. */
         date_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
-        for (int i = 0; i < num_date_formats_price; i++)
-        {
-            gtk_combo_box_text_append_text (date_format_combo, _(date_format_user_price[i]));
-        }
+        for (auto& date_fmt : GncDate::c_formats)
+            gtk_combo_box_text_append_text (date_format_combo, _(date_fmt.m_fmt.c_str()));
         gtk_combo_box_set_active (GTK_COMBO_BOX(date_format_combo), 0);
         g_signal_connect (G_OBJECT(date_format_combo), "changed",
                          G_CALLBACK(csv_price_imp_preview_date_fmt_sel_cb), this);
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 838c947..705d37c 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -46,14 +46,6 @@ extern "C" {
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
-const int num_date_formats_price = 5;
-const gchar* date_format_user_price[] = {N_("y-m-d"),
-                                   N_("d-m-y"),
-                                   N_("m-d-y"),
-                                   N_("d-m"),
-                                   N_("m-d")
-                                  };
-
 const int num_currency_formats_price = 3;
 const gchar* currency_format_user_price[] = {N_("Locale"),
                                        N_("Period: 123,456.78"),
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index 9959aaa..fd8ebed 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -49,10 +49,6 @@ extern "C" {
 extern const int num_currency_formats_price;
 extern const gchar* currency_format_user_price[];
 
-/* A set of date formats that the user sees. */
-extern const int num_date_formats_price;
-extern const gchar* date_format_user_price[];
-
 /** Tuple to hold
  *  - a tokenized line of input
  *  - an optional error string
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index 539f316..1ccd6e5 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -50,116 +50,6 @@ std::map<GncPricePropType, const char*> gnc_price_col_type_strs = {
         { GncPricePropType::TO_CURRENCY, N_("Currency To") },
 };
 
-/* Regular expressions used to parse dates per date format */
-const char* date_regex_price[] = {
-                             "(?:"                                   // either y-m-d
-                                 "(?<YEAR>[0-9]+)[-/.' ]+"
-                                 "(?<MONTH>[0-9]+)[-/.' ]+"
-                                 "(?<DAY>[0-9]+)"
-                             "|"                                     // or CCYYMMDD
-                                 "(?<YEAR>[0-9]{4})"
-                                 "(?<MONTH>[0-9]{2})"
-                                 "(?<DAY>[0-9]{2})"
-                             ")",
-
-                             "(?:"                                   // either d-m-y
-                                 "(?<DAY>[0-9]+)[-/.' ]+"
-                                 "(?<MONTH>[0-9]+)[-/.' ]+"
-                                 "(?<YEAR>[0-9]+)"
-                             "|"                                     // or DDMMCCYY
-                                 "(?<DAY>[0-9]{2})"
-                                 "(?<MONTH>[0-9]{2})"
-                                 "(?<YEAR>[0-9]{4})"
-                             ")",
-
-                             "(?:"                                   // either m-d-y
-                                 "(?<MONTH>[0-9]+)[-/.' ]+"
-                                 "(?<DAY>[0-9]+)[-/.' ]+"
-                                 "(?<YEAR>[0-9]+)"
-                             "|"                                     // or MMDDCCYY
-                                 "(?<MONTH>[0-9]{2})"
-                                 "(?<DAY>[0-9]{2})"
-                                 "(?<YEAR>[0-9]{4})"
-                             ")",
-
-                             "(?:"                                   // either d-m(-y)
-                                 "(?<DAY>[0-9]+)[-/.' ]+"
-                                 "(?<MONTH>[0-9]+)(?:[-/.' ]+"
-                                 "(?<YEAR>[0-9]+))?"
-                             "|"                                     // or DDMM(CCYY)
-                                 "(?<DAY>[0-9]{2})"
-                                 "(?<MONTH>[0-9]{2})"
-                                 "(?<YEAR>[0-9]+)?"
-                             ")",
-
-                             "(?:"                                   // either m-d(-y)
-                                 "(?<MONTH>[0-9]+)[-/.' ]+"
-                                 "(?<DAY>[0-9]+)(?:[-/.' ]+"
-                                 "(?<YEAR>[0-9]+))?"
-                             "|"                                     // or MMDD(CCYY)
-                                 "(?<MONTH>[0-9]{2})"
-                                 "(?<DAY>[0-9]{2})"
-                                 "(?<YEAR>[0-9]+)?"
-                             ")",
-};
-
-/** 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
- * @exception std::invalid_argument if the string can't be parsed into a date.
- * @return The parsed value of date_str on success, throws on failure
- */
-
-time64 parse_date_price (const std::string &date_str, int format)
-{
-    boost::regex r(date_regex_price[format]);
-    boost::smatch what;
-    if(!boost::regex_search(date_str, what, r))
-        throw std::invalid_argument (_("Value can't be parsed into a date using the selected date format."));  // regex didn't find a match
-
-    // Attention: different behavior from 2.6.x series !
-    // If date format without year was selected, the match
-    // should NOT have found a year.
-    if ((format >= 3) && (what.length("YEAR") != 0))
-        throw std::invalid_argument (_("Value appears to contain a year while the selected format forbids this."));
-
-    auto day = std::stoi (what.str("DAY"));
-    auto month = std::stoi (what.str("MONTH"));
-
-    int year;
-    if (format < 3)
-    {
-        /* The input dates have a year, so use that one */
-        year = std::stoi (what.str("YEAR"));
-
-        /* Handle two-digit years. */
-        if (year < 100)
-        {
-            /* We allow two-digit years in the range 1969 - 2068. */
-            if (year < 69)
-                year += 2000;
-            else
-                year += 1900;
-        }
-    }
-    else
-    {
-        /* The input dates don't have a year, so work with today's year.
-         */
-        gnc_timespec2dmy(timespec_now(), nullptr, nullptr, &year);
-    }
-
-    auto ts = gnc_dmy2timespec_neutral(day, month, year);
-    if (ts.tv_sec == INT64_MAX)
-        throw std::invalid_argument (_("Value can't be parsed into a date using the selected date format."));
-
-    return ts.tv_sec;
-}
-
-
 /** Convert str into a GncNumeric using the user-specified (import) currency format.
  * @param str The string to be parsed
  * @param currency_format The currency format to use.
@@ -257,7 +147,7 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
         {
             case GncPricePropType::DATE:
                 m_date = boost::none;
-                m_date = parse_date_price (value, m_date_format); // Throws if parsing fails
+                m_date = GncDate(value, GncDate::c_formats[m_date_format].m_fmt); // Throws if parsing fails
                 break;
 
             case GncPricePropType::AMOUNT:
@@ -357,7 +247,7 @@ Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
     }
 
     Timespec date;
-    timespecFromTime64 (&date, *m_date);
+    timespecFromTime64 (&date, static_cast<time64>(GncDateTime(*m_date, DayPart::neutral)));
     date.tv_nsec = 0;
 
     bool rev = false;
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 9ae4853..77e39dc 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -39,6 +39,7 @@ extern "C" {
 #include <map>
 #include <memory>
 #include <boost/optional.hpp>
+#include <gnc-datetime.hpp>
 #include <gnc-numeric.hpp>
 
 /** Enumeration for column types. These are the different types of
@@ -76,7 +77,6 @@ private:
     const char *m_name;
 };
 
-time64 parse_date_price (const std::string &date_str, int format);
 gnc_commodity* parse_commodity_price_comm (const std::string& comm_str);
 GncNumeric parse_amount_price (const std::string &str, int currency_format);
 
@@ -104,7 +104,7 @@ public:
 private:
     int m_date_format;
     int m_currency_format;
-    boost::optional<time64> m_date;
+    boost::optional<GncDate> m_date;
     boost::optional<GncNumeric> m_amount;
     boost::optional<gnc_commodity*> m_from_commodity;
     boost::optional<gnc_commodity*> m_to_currency;

commit 5b02021550dd71dd3de643a387b4c3034e6758a7
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Dec 4 14:25:02 2017 +0000

    Make changes for Gtk3 compatibility

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 0fa6273..af810cb 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -503,10 +503,12 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
     file_chooser = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_OPEN);
     g_signal_connect (G_OBJECT(file_chooser), "file-activated",
                       G_CALLBACK(csv_price_imp_file_confirm_cb), this);
-    auto button = gtk_button_new_from_stock (GTK_STOCK_OK);
+    auto button = gtk_button_new_with_label (_("OK"));
     gtk_widget_set_size_request (button, 100, -1);
     gtk_widget_show (button);
-    auto h_box = gtk_hbox_new (TRUE, 0);
+    auto h_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+    gtk_box_set_homogeneous (GTK_BOX (h_box), TRUE);
+    gtk_widget_set_hexpand (GTK_WIDGET(h_box), TRUE);
     gtk_box_pack_start (GTK_BOX(h_box), button, FALSE, FALSE, 0);
     gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(file_chooser), h_box);
     g_signal_connect (G_OBJECT(button), "clicked",
@@ -792,7 +794,9 @@ CsvImpPriceAssist::preview_settings_name (GtkEntry* entry)
     if (text)
         price_imp->settings_name(text);
 
-    auto combo = gtk_widget_get_parent (GTK_WIDGET(entry));
+    auto box = gtk_widget_get_parent (GTK_WIDGET(entry));
+    auto combo = gtk_widget_get_parent (GTK_WIDGET(box));
+
     preview_handle_save_del_sensitivity (GTK_COMBO_BOX(combo));
 }
 
@@ -1239,11 +1243,11 @@ enum
 static GnumericPopupMenuElement const popup_elements[] =
 {
     {
-        N_("Merge with column on _left"), GTK_STOCK_REMOVE,
+        N_("Merge with column on _left"), "list-remove",
         0, 1 << CONTEXT_STF_IMPORT_MERGE_LEFT, CONTEXT_STF_IMPORT_MERGE_LEFT
     },
     {
-        N_("Merge with column on _right"), GTK_STOCK_REMOVE,
+        N_("Merge with column on _right"), "list-remove",
         0, 1 << CONTEXT_STF_IMPORT_MERGE_RIGHT, CONTEXT_STF_IMPORT_MERGE_RIGHT
     },
     { "", nullptr, 0, 0, 0 },
@@ -1253,11 +1257,11 @@ static GnumericPopupMenuElement const popup_elements[] =
     },
     { "", nullptr, 0, 0, 0 },
     {
-        N_("_Widen this column"), GTK_STOCK_GO_FORWARD,
+        N_("_Widen this column"), "go-next",
         0, 1 << CONTEXT_STF_IMPORT_WIDEN, CONTEXT_STF_IMPORT_WIDEN
     },
     {
-        N_("_Narrow this column"), GTK_STOCK_GO_BACK,
+        N_("_Narrow this column"), "go-previous",
         0, 1 << CONTEXT_STF_IMPORT_NARROW, CONTEXT_STF_IMPORT_NARROW
     },
     { nullptr, nullptr, 0, 0, 0 },
@@ -1429,7 +1433,7 @@ CsvImpPriceAssist::preview_row_fill_state_cells (GtkListStore *store, GtkTreeIte
         fcolor = "black";
         bcolor = "pink";
         c_err_msg = err_msg.c_str();
-        icon_name = GTK_STOCK_DIALOG_ERROR;
+        icon_name = "dialog-error";
     }
     gtk_list_store_set (store, iter,
             PREV_COL_FCOLOR, fcolor,
@@ -1480,13 +1484,13 @@ void
 CsvImpPriceAssist::preview_style_column (uint32_t col_num, GtkTreeModel* model)
 {
     auto col = gtk_tree_view_get_column (treeview, col_num);
-    auto renderer = static_cast<GtkCellRenderer*>(gtk_tree_view_column_get_cell_renderers(col)->data);
+    auto renderer = static_cast<GtkCellRenderer*>(gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(col))->data);
 
     /* First column -the error status column- is rendered differently */
     if (col_num == 0)
     {
         gtk_tree_view_column_set_attributes (col, renderer,
-                "stock-id", PREV_COL_ERR_ICON,
+                "icon-name", PREV_COL_ERR_ICON,
                 "cell-background", PREV_COL_BCOLOR, nullptr);
         g_object_set (G_OBJECT(renderer), "stock-size", GTK_ICON_SIZE_MENU, nullptr);
         g_object_set (G_OBJECT(col), "sizing", GTK_TREE_VIEW_COLUMN_FIXED,
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
index 33db266..b1ba9c0 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
 <interface>
-  <requires lib="gtk+" version="2.24"/>
-  <!-- interface-naming-policy project-wide -->
+  <requires lib="gtk+" version="3.10"/>
   <object class="GtkAdjustment" id="end_row_adj">
     <property name="upper">1000</property>
     <property name="step_increment">1</property>
@@ -38,11 +38,11 @@
     <property name="title" translatable="yes">CSV Price Import</property>
     <property name="default_width">400</property>
     <property name="default_height">500</property>
+    <signal name="apply" handler="csv_price_imp_assist_finish_cb" swapped="no"/>
+    <signal name="cancel" handler="csv_price_imp_assist_cancel_cb" swapped="no"/>
     <signal name="close" handler="csv_price_imp_assist_close_cb" swapped="no"/>
     <signal name="destroy" handler="csv_price_imp_assist_destroy_cb" swapped="no"/>
-    <signal name="apply" handler="csv_price_imp_assist_finish_cb" swapped="no"/>
     <signal name="prepare" handler="csv_price_imp_assist_prepare_cb" swapped="no"/>
-    <signal name="cancel" handler="csv_price_imp_assist_cancel_cb" swapped="no"/>
     <child>
       <placeholder/>
     </child>
@@ -76,10 +76,11 @@ Click on 'Forward' to proceed or 'Cancel' to Abort Import.</property>
       </packing>
     </child>
     <child>
-      <object class="GtkVBox" id="file_page">
+      <object class="GtkBox" id="file_page">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="border_width">12</property>
+        <property name="orientation">vertical</property>
         <child>
           <object class="GtkLabel" id="label7">
             <property name="visible">True</property>
@@ -101,20 +102,19 @@ Select location and file name for the Import, then click 'OK'...
       </packing>
     </child>
     <child>
-      <object class="GtkVBox" id="preview_page">
+      <object class="GtkBox" 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="orientation">vertical</property>
         <property name="spacing">2</property>
         <child>
-          <object class="GtkTable" id="table1">
+          <object class="GtkGrid" id="table1">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="n_rows">2</property>
-            <property name="n_columns">2</property>
-            <property name="column_spacing">5</property>
             <property name="row_spacing">5</property>
+            <property name="column_spacing">5</property>
             <child>
               <object class="GtkFrame" id="frame6">
                 <property name="visible">True</property>
@@ -129,7 +129,7 @@ Select location and file name for the Import, then click 'OK'...
                     <property name="left_padding">5</property>
                     <property name="right_padding">5</property>
                     <child>
-                      <object class="GtkHBox" id="combo_hbox">
+                      <object class="GtkBox" id="combo_hbox">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <child>
@@ -143,7 +143,7 @@ Select location and file name for the Import, then click 'OK'...
                               <object class="GtkImage" id="image2">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="stock">gtk-delete</property>
+                                <property name="icon_name">edit-delete</property>
                               </object>
                             </child>
                           </object>
@@ -165,7 +165,7 @@ Select location and file name for the Import, then click 'OK'...
                               <object class="GtkImage" id="image1">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="stock">gtk-save</property>
+                                <property name="icon_name">document-save</property>
                               </object>
                             </child>
                           </object>
@@ -184,6 +184,7 @@ Select location and file name for the Import, then click 'OK'...
                   <object class="GtkLabel" id="label12">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
+                    <property name="halign">start</property>
                     <property name="label" translatable="yes"> <b>Load and Save Settings</b></property>
                     <property name="use_markup">True</property>
                     <property name="track_visited_links">False</property>
@@ -191,8 +192,8 @@ Select location and file name for the Import, then click 'OK'...
                 </child>
               </object>
               <packing>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options">GTK_FILL</property>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
               </packing>
             </child>
             <child>
@@ -210,15 +211,14 @@ Select location and file name for the Import, then click 'OK'...
                     <property name="left_padding">5</property>
                     <property name="right_padding">5</property>
                     <child>
-                      <object class="GtkVBox" id="vbox1">
+                      <object class="GtkBox" id="vbox1">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
+                        <property name="orientation">vertical</property>
                         <child>
-                          <object class="GtkTable" id="table4">
+                          <object class="GtkGrid" id="table4">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
-                            <property name="n_rows">2</property>
-                            <property name="n_columns">2</property>
                             <child>
                               <object class="GtkRadioButton" id="csv_button">
                                 <property name="label" translatable="yes">Separators</property>
@@ -226,10 +226,15 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_fixed_sel_cb" swapped="no"/>
                               </object>
+                              <packing>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
+                              </packing>
                             </child>
                             <child>
                               <object class="GtkRadioButton" id="fixed_button">
@@ -238,24 +243,24 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <property name="group">csv_button</property>
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHSeparator" id="hseparator1">
+                              <object class="GtkSeparator" id="hseparator1">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                               </object>
                               <packing>
-                                <property name="right_attach">2</property>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="width">2</property>
                               </packing>
                             </child>
                           </object>
@@ -266,12 +271,10 @@ Select location and file name for the Import, then click 'OK'...
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkTable" id="separator_table">
+                          <object class="GtkGrid" id="separator_table">
                             <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>
                             <child>
                               <object class="GtkCheckButton" id="space_cbutton">
@@ -280,12 +283,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </object>
                               <packing>
-                                <property name="x_options">GTK_FILL</property>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
@@ -295,14 +299,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </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>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
@@ -312,15 +315,14 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </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>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
@@ -330,14 +332,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </object>
                               <packing>
+                                <property name="left_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>
@@ -347,16 +348,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
+                                <property name="left_attach">0</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>
@@ -366,16 +364,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </object>
                               <packing>
-                                <property name="left_attach">2</property>
-                                <property name="right_attach">3</property>
+                                <property name="left_attach">1</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>
@@ -385,14 +380,13 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="halign">start</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </object>
                               <packing>
+                                <property name="left_attach">0</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>
                             <child>
@@ -401,22 +395,18 @@ Select location and file name for the Import, then click 'OK'...
                                 <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">●</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>
                                 <signal name="changed" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
                               </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>
+                            <child>
+                              <placeholder/>
+                            </child>
                           </object>
                           <packing>
                             <property name="expand">False</property>
@@ -425,7 +415,7 @@ Select location and file name for the Import, then click 'OK'...
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkHBox" id="fw_instructions_hbox">
+                          <object class="GtkBox" id="fw_instructions_hbox">
                             <property name="can_focus">False</property>
                             <property name="no_show_all">True</property>
                             <child>
@@ -433,8 +423,7 @@ Select location and file name for the Import, then click 'OK'...
                                 <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="yalign">0</property>
-                                <property name="stock">gtk-dialog-info</property>
+                                <property name="icon_name">dialog-information</property>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
@@ -444,67 +433,61 @@ Select location and file name for the Import, then click 'OK'...
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkTable" id="table2">
+                              <object class="GtkGrid" id="table2">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="n_rows">2</property>
-                                <property name="n_columns">2</property>
                                 <child>
                                   <object class="GtkLabel" id="label2">
                                     <property name="visible">True</property>
                                     <property name="can_focus">False</property>
-                                    <property name="yalign">0</property>
-                                    <property name="xpad">5</property>
                                     <property name="label" translatable="yes">•</property>
                                     <property name="use_markup">True</property>
                                     <property name="wrap">True</property>
                                   </object>
+                                  <packing>
+                                    <property name="left_attach">0</property>
+                                    <property name="top_attach">0</property>
+                                  </packing>
                                 </child>
                                 <child>
                                   <object class="GtkLabel" id="label3">
                                     <property name="visible">True</property>
                                     <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
+                                    <property name="halign">start</property>
                                     <property name="label" translatable="yes">Double-click anywhere on the table below to insert a column break</property>
                                     <property name="use_markup">True</property>
                                     <property name="wrap">True</property>
                                   </object>
                                   <packing>
                                     <property name="left_attach">1</property>
-                                    <property name="right_attach">2</property>
-                                    <property name="y_options"/>
+                                    <property name="top_attach">0</property>
                                   </packing>
                                 </child>
                                 <child>
                                   <object class="GtkLabel" id="label4">
                                     <property name="visible">True</property>
                                     <property name="can_focus">False</property>
-                                    <property name="yalign">0</property>
-                                    <property name="xpad">5</property>
                                     <property name="label" translatable="yes">•</property>
                                     <property name="use_markup">True</property>
                                     <property name="wrap">True</property>
                                   </object>
                                   <packing>
+                                    <property name="left_attach">0</property>
                                     <property name="top_attach">1</property>
-                                    <property name="bottom_attach">2</property>
                                   </packing>
                                 </child>
                                 <child>
                                   <object class="GtkLabel" id="label5">
                                     <property name="visible">True</property>
                                     <property name="can_focus">False</property>
-                                    <property name="xalign">0</property>
+                                    <property name="halign">start</property>
                                     <property name="label" translatable="yes">Right-click anywhere in a column to modify it (widen, narrow, merge)</property>
                                     <property name="use_markup">True</property>
                                     <property name="wrap">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="y_options"/>
                                   </packing>
                                 </child>
                               </object>
@@ -522,17 +505,17 @@ Select location and file name for the Import, then click 'OK'...
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkTable" id="table5">
+                          <object class="GtkGrid" id="table5">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
-                            <property name="n_rows">2</property>
                             <child>
-                              <object class="GtkHSeparator" id="hseparator4">
+                              <object class="GtkSeparator" id="hseparator4">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                               </object>
                               <packing>
-                                <property name="y_options">GTK_FILL</property>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
@@ -540,15 +523,15 @@ Select location and file name for the Import, then click 'OK'...
                                 <property name="label" translatable="yes">Allow existing prices to be over written.</property>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
+                                <property name="focus_on_click">False</property>
                                 <property name="receives_default">False</property>
                                 <property name="tooltip_text" translatable="yes">Normally prices are not over written, select this to change that. This setting is not saved.</property>
-                                <property name="focus_on_click">False</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_overwrite_cb" swapped="no"/>
                               </object>
                               <packing>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
                               </packing>
                             </child>
                           </object>
@@ -567,16 +550,15 @@ Select location and file name for the Import, then click 'OK'...
                     <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="halign">start</property>
                     <property name="label" translatable="yes"><b>File Format</b></property>
                     <property name="use_markup">True</property>
                   </object>
                 </child>
               </object>
               <packing>
+                <property name="left_attach">0</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>
@@ -592,18 +574,17 @@ Select location and file name for the Import, then click 'OK'...
                     <property name="left_padding">5</property>
                     <property name="right_padding">5</property>
                     <child>
-                      <object class="GtkVBox" id="vbox6">
+                      <object class="GtkBox" id="vbox6">
                         <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="orientation">vertical</property>
                         <child>
-                          <object class="GtkTable" id="table3">
+                          <object class="GtkGrid" id="table3">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
-                            <property name="n_rows">6</property>
-                            <property name="n_columns">2</property>
-                            <property name="column_spacing">5</property>
                             <property name="row_spacing">5</property>
+                            <property name="column_spacing">5</property>
                             <child>
                               <object class="GtkAlignment" id="date_format_container">
                                 <property name="visible">True</property>
@@ -613,23 +594,19 @@ Select location and file name for the Import, then click 'OK'...
                               </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>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label20">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
+                                <property name="halign">start</property>
                                 <property name="label" translatable="yes">Date Format</property>
                               </object>
                               <packing>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
@@ -640,34 +617,31 @@ Select location and file name for the Import, then click 'OK'...
                               </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="x_options">GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label21">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
+                                <property name="halign">start</property>
                                 <property name="label" translatable="yes">Currency Format</property>
                               </object>
                               <packing>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label16">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
+                                <property name="halign">start</property>
                                 <property name="label" translatable="yes">Encoding</property>
                               </object>
                               <packing>
-                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                                <property name="left_attach">0</property>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
@@ -678,38 +652,35 @@ Select location and file name for the Import, then click 'OK'...
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="x_options">GTK_FILL</property>
+                                <property name="top_attach">0</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label17">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
+                                <property name="halign">start</property>
                                 <property name="label" translatable="yes">Leading Lines to Skip</property>
                               </object>
                               <packing>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">4</property>
-                                <property name="bottom_attach">5</property>
-                                <property name="x_options">GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
                               <object class="GtkLabel" id="label18">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
-                                <property name="xalign">0</property>
+                                <property name="halign">start</property>
                                 <property name="label" translatable="yes">Trailing Lines to Skip</property>
                               </object>
                               <packing>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">5</property>
-                                <property name="bottom_attach">6</property>
-                                <property name="x_options">GTK_FILL</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHBox" id="hbox2">
+                              <object class="GtkBox" id="hbox2">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                                 <child>
@@ -717,11 +688,8 @@ Select location and file name for the Import, then click 'OK'...
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="invisible_char">●</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>
                                     <property name="numeric">True</property>
                                     <signal name="value-changed" handler="csv_price_imp_preview_srow_cb" swapped="no"/>
@@ -735,13 +703,11 @@ Select location and file name for the Import, then click 'OK'...
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
                                 <property name="top_attach">4</property>
-                                <property name="bottom_attach">5</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHBox" id="hbox3">
+                              <object class="GtkBox" id="hbox3">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                                 <child>
@@ -749,11 +715,8 @@ Select location and file name for the Import, then click 'OK'...
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="invisible_char">●</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>
                                     <property name="numeric">True</property>
                                     <signal name="value-changed" handler="csv_price_imp_preview_erow_cb" swapped="no"/>
@@ -767,20 +730,18 @@ Select location and file name for the Import, then click 'OK'...
                               </object>
                               <packing>
                                 <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
                                 <property name="top_attach">5</property>
-                                <property name="bottom_attach">6</property>
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHSeparator" id="hseparator2">
+                              <object class="GtkSeparator" id="hseparator2">
                                 <property name="visible">True</property>
                                 <property name="can_focus">False</property>
                               </object>
                               <packing>
-                                <property name="right_attach">2</property>
+                                <property name="left_attach">0</property>
                                 <property name="top_attach">3</property>
-                                <property name="bottom_attach">4</property>
+                                <property name="width">2</property>
                               </packing>
                             </child>
                           </object>
@@ -800,6 +761,7 @@ Select location and file name for the Import, then click 'OK'...
 For example
 * if 'Leading Lines to Skip' is set to 3, the first line to import will be line 4. Lines 5, 7, 9,... will be skipped.
 * if 'Leading Lines to Skip' is set to 4, the first line to import will be line 5. Lines 6, 8, 10,... will be skipped.</property>
+                            <property name="halign">start</property>
                             <property name="draw_indicator">True</property>
                             <signal name="toggled" handler="csv_price_imp_preview_skiprows_cb" swapped="no"/>
                           </object>
@@ -817,6 +779,7 @@ For example
                   <object class="GtkLabel" id="label13">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
+                    <property name="halign">start</property>
                     <property name="label" translatable="yes"><b>Miscellaneous</b></property>
                     <property name="use_markup">True</property>
                   </object>
@@ -824,11 +787,7 @@ For example
               </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>
@@ -842,7 +801,7 @@ For example
           </packing>
         </child>
         <child>
-          <object class="GtkHBox" id="hbox1">
+          <object class="GtkBox" id="hbox1">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <child>
@@ -859,7 +818,7 @@ For example
                     <property name="left_padding">5</property>
                     <property name="right_padding">5</property>
                     <child>
-                      <object class="GtkHBox" id="commodity_hbox">
+                      <object class="GtkBox" id="commodity_hbox">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <child>
@@ -913,7 +872,7 @@ For example
                     <property name="left_padding">5</property>
                     <property name="right_padding">5</property>
                     <child>
-                      <object class="GtkHBox" id="currency_hbox">
+                      <object class="GtkBox" id="currency_hbox">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <child>
@@ -964,16 +923,15 @@ For example
           <object class="GtkScrolledWindow" id="scrolledwindow2">
             <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="viewport2">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <child>
-                  <object class="GtkVBox" id="vbox8">
+                  <object class="GtkBox" id="vbox8">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
+                    <property name="orientation">vertical</property>
                     <child>
                       <object class="GtkTreeView" id="ctreeview">
                         <property name="visible">True</property>
@@ -981,6 +939,9 @@ For example
                         <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>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection"/>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -994,6 +955,9 @@ For example
                         <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>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection"/>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">True</property>
@@ -1013,7 +977,7 @@ For example
           </packing>
         </child>
         <child>
-          <object class="GtkHBox" id="hbox13">
+          <object class="GtkBox" id="hbox13">
             <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>
@@ -1022,8 +986,7 @@ For example
                 <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="yalign">0</property>
-                <property name="stock">gtk-dialog-info</property>
+                <property name="icon_name">dialog-information</property>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -1037,7 +1000,7 @@ For example
                 <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="halign">start</property>
                 <property name="label" translatable="yes">Select the type of each column to import.</property>
               </object>
               <packing>
@@ -1055,7 +1018,7 @@ For example
           </packing>
         </child>
         <child>
-          <object class="GtkHBox" id="hbox14">
+          <object class="GtkBox" id="hbox14">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <child>
@@ -1063,7 +1026,6 @@ For example
                 <property name="label" translatable="yes">Skip Errors</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">False</property>
-                <property name="xalign">1</property>
                 <property name="image_position">right</property>
                 <property name="draw_indicator">True</property>
                 <signal name="toggled" handler="csv_price_imp_preview_skiperrors_cb" swapped="no"/>
@@ -1089,10 +1051,11 @@ For example
       </packing>
     </child>
     <child>
-      <object class="GtkVBox" id="confirm_page">
+      <object class="GtkBox" id="confirm_page">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="border_width">12</property>
+        <property name="orientation">vertical</property>
         <child>
           <object class="GtkAlignment" id="alignment2">
             <property name="visible">True</property>
@@ -1122,10 +1085,11 @@ Cancel to abort.</b></property>
       </packing>
     </child>
     <child>
-      <object class="GtkVBox" id="summary_page">
+      <object class="GtkBox" id="summary_page">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="border_width">12</property>
+        <property name="orientation">vertical</property>
         <child>
           <object class="GtkLabel" id="summary_label">
             <property name="visible">True</property>
@@ -1147,5 +1111,12 @@ Cancel to abort.</b></property>
         <property name="complete">True</property>
       </packing>
     </child>
+    <child internal-child="action_area">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+      </object>
+      <packing>
+      </packing>
+    </child>
   </object>
 </interface>
diff --git a/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c b/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
index c14092d..3cecf66 100644
--- a/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
+++ b/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
@@ -57,7 +57,7 @@ static GtkActionEntry gnc_plugin_actions [] =
         G_CALLBACK (gnc_plugin_csv_import_trans_cmd)
     },
     {
-        "CsvImportPriceAction", GTK_STOCK_CONVERT, N_("Import _Prices from a CSV file..."), NULL,
+        "CsvImportPriceAction", "go-previous", N_("Import _Prices from a CSV file..."), NULL,
         N_("Import Prices from a CSV file"),
         G_CALLBACK (gnc_plugin_csv_import_price_cmd)
     },

commit b94b2f8ac25926f5afdc6988f952b52b998d31a8
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 12:04:51 2017 +0000

    Pot file changes for new files and settings rename

diff --git a/po/POTFILES.in b/po/POTFILES.in
index bced61f..7f74af4 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -287,17 +287,21 @@ gnucash/import-export/csv-exp/gnc-plugin-csv-export.c
 [type: gettext/gsettings]gnucash/import-export/csv-exp/gschemas/org.gnucash.dialogs.export.csv.gschema.xml.in.in
 gnucash/import-export/csv-imp/assistant-csv-account-import.c
 gnucash/import-export/csv-imp/assistant-csv-account-import.glade
+gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+gnucash/import-export/csv-imp/assistant-csv-price-import.glade
 gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
 gnucash/import-export/csv-imp/assistant-csv-trans-import.glade
 gnucash/import-export/csv-imp/csv-account-import.c
 gnucash/import-export/csv-imp/gnc-csv-account-map.c
 gnucash/import-export/csv-imp/gnc-csv-gnumeric-popup.c
 gnucash/import-export/csv-imp/gnc-csv-tokenizer.cpp
-gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
 gnucash/import-export/csv-imp/gnc-dummy-tokenizer.cpp
 gnucash/import-export/csv-imp/gnc-fw-tokenizer.cpp
 gnucash/import-export/csv-imp/gncmod-csv-import.c
 gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
+gnucash/import-export/csv-imp/gnc-price-import.cpp
+gnucash/import-export/csv-imp/gnc-price-props.cpp
 gnucash/import-export/csv-imp/gnc-tokenizer.cpp
 gnucash/import-export/csv-imp/gnc-trans-props.cpp
 gnucash/import-export/csv-imp/gnc-tx-import.cpp

commit c3b54ab05493a04621d1068dce57cc92daff5645
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 12:03:14 2017 +0000

    Rename gnc-csv-trans-settings.* to gnc-csv-import-settings.*
    
    Change the name of the import settings files as they do not just deal
    with transactions and all associated required changes.

diff --git a/gnucash/import-export/csv-imp/CMakeLists.txt b/gnucash/import-export/csv-imp/CMakeLists.txt
index 44a14ca..65082be 100644
--- a/gnucash/import-export/csv-imp/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/CMakeLists.txt
@@ -17,7 +17,7 @@ SET(csv_import_SOURCES
   gnc-csv-account-map.c
   gnc-csv-gnumeric-popup.c
   gnc-csv-tokenizer.cpp
-  gnc-csv-trans-settings.cpp
+  gnc-csv-import-settings.cpp
   gnc-dummy-tokenizer.cpp
   gnc-fw-tokenizer.cpp
   gnc-price-import.cpp
@@ -45,7 +45,7 @@ SET(csv_import_noinst_HEADERS
   gnc-csv-account-map.h
   gnc-csv-gnumeric-popup.h
   gnc-csv-tokenizer.hpp
-  gnc-csv-trans-settings.hpp
+  gnc-csv-import-settings.hpp
   gnc-dummy-tokenizer.hpp
   gnc-fw-tokenizer.hpp
   gnc-price-import.hpp
diff --git a/gnucash/import-export/csv-imp/Makefile.am b/gnucash/import-export/csv-imp/Makefile.am
index 4b473de..f1b501f 100644
--- a/gnucash/import-export/csv-imp/Makefile.am
+++ b/gnucash/import-export/csv-imp/Makefile.am
@@ -19,7 +19,7 @@ libgncmod_csv_import_la_SOURCES = \
   gnc-tokenizer.cpp \
   gnc-tx-import.cpp \
   gnc-trans-props.cpp \
-  gnc-csv-trans-settings.cpp
+  gnc-csv-import-settings.cpp
 
 noinst_HEADERS = \
   assistant-csv-account-import.h \
@@ -37,7 +37,7 @@ noinst_HEADERS = \
   gnc-tokenizer.hpp \
   gnc-tx-import.hpp \
   gnc-trans-props.hpp \
-  gnc-csv-trans-settings.hpp
+  gnc-csv-import-settings.hpp
 
 libgncmod_csv_import_la_LDFLAGS = -avoid-version
 
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 21126ea..0fa6273 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -52,7 +52,7 @@ extern "C"
 #include "go-charmap-sel.h"
 }
 
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 #include "gnc-price-import.hpp"
 #include "gnc-fw-tokenizer.hpp"
 #include "gnc-csv-tokenizer.hpp"
@@ -738,7 +738,7 @@ void CsvImpPriceAssist::preview_populate_settings_combo()
     gtk_list_store_clear (GTK_LIST_STORE(model));
 
     // Append the default entry
-    auto presets = get_trans_presets (settings_type);
+    auto presets = get_import_presets (settings_type);
     for (auto preset : presets)
     {
         GtkTreeIter iter;
@@ -766,11 +766,11 @@ void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
     /* Handle sensitivity of the delete and save button */
     if (gtk_combo_box_get_active_iter (combo, &iter))
     {
-        CsvTransSettings *preset;
+        CsvImportSettings *preset;
         GtkTreeModel *model = gtk_combo_box_get_model (combo);
         gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
-        if (preset && !trans_preset_is_reserved_name (preset->m_name))
+        if (preset && !preset_is_reserved_name (preset->m_name))
         {
             /* Current preset is not read_only, so buttons can be enabled */
             can_delete = true;
@@ -778,7 +778,7 @@ void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
         }
     }
     else if (entry_text && (strlen (entry_text) > 0) &&
-            !trans_preset_is_reserved_name (std::string(entry_text)))
+            !preset_is_reserved_name (std::string(entry_text)))
         can_save = true;
 
     gtk_widget_set_sensitive (save_button, can_save);
@@ -807,7 +807,7 @@ CsvImpPriceAssist::preview_settings_load ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvTransSettings *preset = nullptr;
+    CsvImportSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -834,7 +834,7 @@ CsvImpPriceAssist::preview_settings_delete ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvTransSettings *preset = nullptr;
+    CsvImportSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -868,7 +868,7 @@ CsvImpPriceAssist::preview_settings_save ()
         while (valid)
         {
             // Walk through the list, reading each row
-            CsvTransSettings *preset;
+            CsvImportSettings *preset;
             gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
             if (preset && (preset->m_name == std::string(new_name)))
diff --git a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
index e3d10cc..3512aba 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
@@ -58,7 +58,7 @@ extern "C"
 #include "go-charmap-sel.h"
 }
 
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 #include "gnc-tx-import.hpp"
 #include "gnc-fw-tokenizer.hpp"
 #include "gnc-csv-tokenizer.hpp"
@@ -679,7 +679,7 @@ void CsvImpTransAssist::preview_populate_settings_combo()
 
     // Append the default entry
 
-    auto presets = get_trans_presets (settings_type);
+    auto presets = get_import_presets (settings_type);
     for (auto preset : presets)
     {
         GtkTreeIter iter;
@@ -707,11 +707,11 @@ void CsvImpTransAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
     /* Handle sensitivity of the delete and save button */
     if (gtk_combo_box_get_active_iter (combo, &iter))
     {
-        CsvTransSettings *preset;
+        CsvImportSettings *preset;
         GtkTreeModel *model = gtk_combo_box_get_model (combo);
         gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
-        if (preset && !trans_preset_is_reserved_name (preset->m_name))
+        if (preset && !preset_is_reserved_name (preset->m_name))
         {
             /* Current preset is not read_only, so buttons can be enabled */
             can_delete = true;
@@ -719,7 +719,7 @@ void CsvImpTransAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
         }
     }
     else if (entry_text && (strlen (entry_text) > 0) &&
-            !trans_preset_is_reserved_name (std::string(entry_text)))
+            !preset_is_reserved_name (std::string(entry_text)))
         can_save = true;
 
     gtk_widget_set_sensitive (save_button, can_save);
@@ -752,7 +752,7 @@ CsvImpTransAssist::preview_settings_load ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvTransSettings *preset = nullptr;
+    CsvImportSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -779,7 +779,7 @@ CsvImpTransAssist::preview_settings_delete ()
     if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
         return;
 
-    CsvTransSettings *preset = nullptr;
+    CsvImportSettings *preset = nullptr;
     auto model = gtk_combo_box_get_model (settings_combo);
     gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
@@ -812,7 +812,7 @@ CsvImpTransAssist::preview_settings_save ()
         while (valid)
         {
             // Walk through the list, reading each row
-            CsvTransSettings *preset;
+            CsvImportSettings *preset;
             gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
 
             if (preset && (preset->m_name == std::string(new_name)))
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
similarity index 95%
rename from gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
rename to gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
index 3bbc984..0096c53 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-import-settings.cpp
@@ -1,5 +1,5 @@
 /*******************************************************************\
- * gnc-csv-trans-settings.c -- Save and Load CSV Import Settings    *
+ * gnc-csv-import-settings.c -- Save and Load CSV Import Settings   *
  *                                                                  *
  * Copyright (C) 2014 Robert Fewell                                 *
  *                                                                  *
@@ -20,13 +20,13 @@
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
 \********************************************************************/
-/** @file gnc-csv-trans-settings.c
+/** @file gnc-csv-import-settings.c
     @brief CSV Import Settings
     @author Copyright (c) 2014 Robert Fewell
     @author Copyright (c) 2016 Geert Janssens
 */
 
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 #include <sstream>
 
 extern "C"
@@ -70,18 +70,18 @@ G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
 preset_vec presets;
 
-static std::shared_ptr<CsvTransSettings> create_int_no_preset(const std::string& set_type)
+static std::shared_ptr<CsvImportSettings> create_int_no_preset(const std::string& set_type)
 {
-    auto preset = std::make_shared<CsvTransSettings>();
+    auto preset = std::make_shared<CsvImportSettings>();
     preset->m_name = no_settings;
     preset->m_settings_type = set_type;
 
     return preset;
 }
 
-static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
+static std::shared_ptr<CsvImportSettings> create_int_gnc_exp_preset(void)
 {
-    auto preset = std::make_shared<CsvTransSettings>();
+    auto preset = std::make_shared<CsvImportSettings>();
     preset->m_name = gnc_exp;
     preset->m_skip_start_lines = 1;
     preset->m_multi_split = true;
@@ -119,7 +119,7 @@ static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
  * find all settings entries in the state key file
  * based on settings type.
  **************************************************/
-const preset_vec& get_trans_presets (const std::string& set_type)
+const preset_vec& get_import_presets (const std::string& set_type)
 {
 
     // Search all Groups in the state key file for ones starting with prefix
@@ -157,7 +157,7 @@ const preset_vec& get_trans_presets (const std::string& set_type)
     /* Then add all the ones we found in the state file */
     for (auto preset_name : preset_names)
     {
-        auto preset = std::make_shared<CsvTransSettings>();
+        auto preset = std::make_shared<CsvImportSettings>();
         preset->m_settings_type = set_type;
         preset->m_name = preset_name;
         preset->load();
@@ -166,7 +166,7 @@ const preset_vec& get_trans_presets (const std::string& set_type)
     return presets;
 }
 
-bool trans_preset_is_reserved_name (const std::string& name)
+bool preset_is_reserved_name (const std::string& name)
 {
     return ((name == no_settings) ||
             (name == _(no_settings.c_str())) ||
@@ -205,9 +205,9 @@ handle_load_error (GError **key_error, const std::string& group)
  * load the settings from a state key file
  **************************************************/
 bool
-CsvTransSettings::load (void)
+CsvImportSettings::load (void)
 {
-    if (trans_preset_is_reserved_name (m_name))
+    if (preset_is_reserved_name (m_name))
         return true;
 
     GError *key_error = nullptr;
@@ -355,9 +355,9 @@ CsvTransSettings::load (void)
  * save settings to a key file
  **************************************************/
 bool
-CsvTransSettings::save (void)
+CsvImportSettings::save (void)
 {
-    if (trans_preset_is_reserved_name (m_name))
+    if (preset_is_reserved_name (m_name))
     {
         PWARN ("Ignoring attempt to save to reserved name '%s'", m_name.c_str());
         return true;
@@ -471,9 +471,9 @@ CsvTransSettings::save (void)
 }
 
 void
-CsvTransSettings::remove (void)
+CsvImportSettings::remove (void)
 {
-    if (trans_preset_is_reserved_name (m_name))
+    if (preset_is_reserved_name (m_name))
         return;
 
     auto keyfile = gnc_state_get_current ();
@@ -483,7 +483,7 @@ CsvTransSettings::remove (void)
 
 
 bool
-CsvTransSettings::read_only (void)
+CsvImportSettings::read_only (void)
 {
     return ((m_name == no_settings) ||
             (m_name == _(no_settings.c_str())) ||
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-import-settings.hpp
similarity index 90%
rename from gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
rename to gnucash/import-export/csv-imp/gnc-csv-import-settings.hpp
index 7df293c..e6ce4d4 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-import-settings.hpp
@@ -1,5 +1,5 @@
 /*******************************************************************\
- * gnc-csv-trans-settings.h   -- Save and Load CSV Import Settings  *
+ * gnc-csv-import-settings.h  -- Save and Load CSV Import Settings  *
  *                                                                  *
  * Copyright (C) 2014 Robert Fewell                                 *
  *                                                                  *
@@ -20,13 +20,13 @@
  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
  * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
 \********************************************************************/
-/** @file gnc-csv-trans-settings.h
+/** @file gnc-csv-import-settings.h
     @brief CSV Import Settings
     @author Copyright (c) 2014 Robert Fewell
     @author Copyright (c) 2016 Geert Janssens
 */
-#ifndef GNC_CSV_TRANS_SETTINGS_H
-#define GNC_CSV_TRANS_SETTINGS_H
+#ifndef GNC_CSV_IMPORT_SETTINGS_H
+#define GNC_CSV_IMPORT_SETTINGS_H
 
 extern "C" {
 #include <config.h>
@@ -49,9 +49,9 @@ enum SEP_BUTTON_TYPES {SEP_SPACE, SEP_TAB, SEP_COMMA, SEP_COLON, SEP_SEMICOLON,
 /** Enumeration for the settings combo's */
 enum SETTINGS_COL {SET_GROUP, SET_NAME};
 
-struct CsvTransSettings
+struct CsvImportSettings
 {
-    CsvTransSettings() : m_file_format (GncImpFileFormat::CSV), m_encoding {"UTF-8"},
+    CsvImportSettings() : m_file_format (GncImpFileFormat::CSV), m_encoding {"UTF-8"},
             m_multi_split (false), m_date_format {0}, m_currency_format {0},
             m_skip_start_lines{0}, m_skip_end_lines{0}, m_skip_alt_lines (false),
             m_separators {","}, m_load_error {false}, m_base_account {nullptr},
@@ -107,8 +107,8 @@ gnc_commodity *m_to_currency;                 //  Price To Currency
 std::vector<GncPricePropType> m_column_types_price; // The Price Column types in order
 };
 
-using preset_vec = std::vector<std::shared_ptr<CsvTransSettings>>;
-/** Creates a vector of CsvTransSettings which combines
+using preset_vec = std::vector<std::shared_ptr<CsvImportSettings>>;
+/** Creates a vector of CsvImportSettings which combines
  *  - one or more internally defined presets
  *  - all preset found in the state key file.
  *
@@ -117,12 +117,12 @@ using preset_vec = std::vector<std::shared_ptr<CsvTransSettings>>;
  *
  *  @return a reference to the populated vector.
  */
-const preset_vec& get_trans_presets (const std::string& set_type);
+const preset_vec& get_import_presets (const std::string& set_type);
 
 /** Check whether name can be used as a preset name.
  *  The names of the internal presets are considered reserved.
  *  A preset with such a name should not be saved or deleted.
  */
-bool trans_preset_is_reserved_name (const std::string& name);
+bool preset_is_reserved_name (const std::string& name);
 
 #endif
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 44a17b9..838c947 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -42,7 +42,7 @@ extern "C" {
 #include "gnc-price-props.hpp"
 #include "gnc-csv-tokenizer.hpp"
 #include "gnc-fw-tokenizer.hpp"
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
@@ -281,7 +281,7 @@ void GncPriceImport::separators (std::string separators)
 }
 std::string GncPriceImport::separators () { return m_settings.m_separators; }
 
-void GncPriceImport::settings (const CsvTransSettings& settings)
+void GncPriceImport::settings (const CsvImportSettings& settings)
 {
     /* First apply file format as this may recreate the tokenizer */
     file_format (settings.m_file_format);
@@ -315,7 +315,7 @@ void GncPriceImport::settings (const CsvTransSettings& settings)
 
 bool GncPriceImport::save_settings ()
 {
-    if (trans_preset_is_reserved_name (m_settings.m_name))
+    if (preset_is_reserved_name (m_settings.m_name))
         return true;
 
     /* separators are already copied to m_settings in the separators
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index be91941..9959aaa 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -42,7 +42,7 @@ extern "C" {
 
 #include "gnc-tokenizer.hpp"
 #include "gnc-price-props.hpp"
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 #include <boost/optional.hpp>
 
 /* A set of currency formats that the user sees. */
@@ -110,7 +110,7 @@ public:
     void separators (std::string separators);
     std::string separators ();
 
-    void settings (const CsvTransSettings& settings);
+    void settings (const CsvImportSettings& settings);
     bool save_settings ();
 
     void settings_name (std::string name);
@@ -157,7 +157,7 @@ private:
     void update_price_props (uint32_t row, uint32_t col, GncPricePropType prop_type);
 
     struct CsvTranSettings;
-    CsvTransSettings m_settings;
+    CsvImportSettings m_settings;
     bool m_skip_errors;
     bool m_over_write;
 };
diff --git a/gnucash/import-export/csv-imp/gnc-tx-import.cpp b/gnucash/import-export/csv-imp/gnc-tx-import.cpp
index daa85b4..eddbd75 100644
--- a/gnucash/import-export/csv-imp/gnc-tx-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-tx-import.cpp
@@ -39,7 +39,7 @@ extern "C" {
 #include "gnc-trans-props.hpp"
 #include "gnc-csv-tokenizer.hpp"
 #include "gnc-fw-tokenizer.hpp"
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
@@ -293,7 +293,7 @@ void GncTxImport::separators (std::string separators)
 }
 std::string GncTxImport::separators () { return m_settings.m_separators; }
 
-void GncTxImport::settings (const CsvTransSettings& settings)
+void GncTxImport::settings (const CsvImportSettings& settings)
 {
     /* First apply file format as this may recreate the tokenizer */
     file_format (settings.m_file_format);
@@ -329,7 +329,7 @@ void GncTxImport::settings (const CsvTransSettings& settings)
 bool GncTxImport::save_settings ()
 {
 
-    if (trans_preset_is_reserved_name (m_settings.m_name))
+    if (preset_is_reserved_name (m_settings.m_name))
         return true;
 
     /* separators are already copied to m_settings in the separators
diff --git a/gnucash/import-export/csv-imp/gnc-tx-import.hpp b/gnucash/import-export/csv-imp/gnc-tx-import.hpp
index 0c14a74..87e4ea4 100644
--- a/gnucash/import-export/csv-imp/gnc-tx-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-tx-import.hpp
@@ -43,7 +43,7 @@ extern "C" {
 
 #include "gnc-tokenizer.hpp"
 #include "gnc-trans-props.hpp"
-#include "gnc-csv-trans-settings.hpp"
+#include "gnc-csv-import-settings.hpp"
 #include <boost/optional.hpp>
 
 
@@ -136,7 +136,7 @@ public:
     void separators (std::string separators);
     std::string separators ();
 
-    void settings (const CsvTransSettings& settings);
+    void settings (const CsvImportSettings& settings);
     bool save_settings ();
 
     void settings_name (std::string name);
@@ -190,7 +190,7 @@ private:
     void update_pre_split_props (uint32_t row, uint32_t col, GncTransPropType prop_type);
 
     struct CsvTranSettings;
-    CsvTransSettings m_settings;
+    CsvImportSettings m_settings;
     bool m_skip_errors;
     bool m_req_mapped_accts;
 

commit c1a9464511b4bc0587a9038a214be3b8390da49f
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:56:25 2017 +0000

    Reorder the create price procedure.

diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index 0ea21f9..539f316 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -362,9 +362,20 @@ Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
 
     bool rev = false;
     auto amount = *m_amount;
+    Result ret_val = ADDED;
 
     GNCPrice *old_price = gnc_pricedb_lookup_day (pdb, *m_from_commodity, *m_to_currency, date);
 
+    // Should old price be over writen
+    if ((old_price != nullptr) && (over == true))
+    {
+        DEBUG("Over write");
+        gnc_pricedb_remove_price (pdb, old_price);
+        gnc_price_unref (old_price);
+        old_price = nullptr;
+        ret_val = REPLACED;
+    }
+
     if (gnc_commodity_is_currency (*m_from_commodity)) // Currency Import
     {
         // Check for currency in reverse direction.
@@ -373,9 +384,8 @@ Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
             // Check for price in reverse direction.
             if (gnc_commodity_equiv (gnc_price_get_currency (old_price), *m_from_commodity))
                 rev = true;
-
-            DEBUG("Commodity from is a Currency");
         }
+        DEBUG("Commodity from is a Currency");
 
         // Check for price less than 1, reverse if so.
         if (*m_amount < GncNumeric(1,1))
@@ -386,18 +396,6 @@ Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
         rev, gnc_commodity_get_fullname (*m_from_commodity), gnc_commodity_get_fullname (*m_to_currency),
         amount.to_string().c_str());
 
-    Result ret_val = ADDED;
-
-    // Should old price be over writen
-    if ((old_price != nullptr) && (over == true))
-    {
-        DEBUG("Over write");
-        gnc_pricedb_remove_price (pdb, old_price);
-        gnc_price_unref (old_price);
-        old_price = nullptr;
-        ret_val = REPLACED;
-    }
-
     // Create the new price
     if (old_price == nullptr)
     {

commit 6c11cfad852efe67aa8863685e15b9db1079036a
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:52:48 2017 +0000

    Add the ability to test from_commodity and to_currency being the same.
    
    To cover all combinations we need to test across the combo's and also
    the table entries when appropriate columns are set. Also need to force
    a reparse if any of the options change.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 14a8ffa..21126ea 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -94,6 +94,7 @@ public:
     void preview_update_currency_format ();
     void preview_update_currency ();
     void preview_update_commodity ();
+    void preview_reparse_col_type (GncPricePropType type);
     void preview_update_col_type (GtkComboBox* cbox);
     void preview_update_fw_columns (GtkTreeView* treeview, GdkEventButton* event);
 
@@ -1138,6 +1139,22 @@ enum PreviewDataTableCols {
     PREV_COL_ERR_ICON,
     PREV_N_FIXED_COLS };
 
+
+void
+CsvImpPriceAssist::preview_reparse_col_type (GncPricePropType type)
+{
+    auto column_types = price_imp->column_types_price();
+
+    // look for column type and force a reparse
+    auto col_type = std::find (column_types.begin(),
+                column_types.end(), type);
+    if (col_type != column_types.end())
+    {
+        price_imp->set_column_type_price (col_type -column_types.begin(),
+                        type, true);
+    }
+}
+
 /** 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 the selection, and any other columns containing that selection
@@ -1157,8 +1174,26 @@ void CsvImpPriceAssist::preview_update_col_type (GtkComboBox* cbox)
     gtk_tree_model_get (model, &iter, COL_TYPE_ID, &new_col_type, -1);
 
     auto col_num = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT(cbox), "col-num"));
+
+    auto column_types = price_imp->column_types_price();
+    auto old_col_type = column_types.at(col_num);
+
     price_imp->set_column_type_price (col_num, new_col_type);
 
+    // if old_col_type is TO_CURRENCY, force a reparse of commodity
+    if (old_col_type == GncPricePropType::TO_CURRENCY)
+    {
+        // look for a from_commodity column to reparse
+        preview_reparse_col_type (GncPricePropType::FROM_COMMODITY);
+    }
+
+    // if old_col_type is FROM_COMMODITY, force a reparse of currency
+    if (old_col_type == GncPricePropType::FROM_COMMODITY)
+    {
+        // look for a to_currency column to reparse
+        preview_reparse_col_type (GncPricePropType::TO_CURRENCY);
+    }
+
     /* Delay rebuilding our data table to avoid critical warnings due to
      * pending events still acting on them after this event is processed.
      */
@@ -1580,7 +1615,7 @@ void CsvImpPriceAssist::preview_refresh_table ()
 
     auto column_types = price_imp->column_types_price();
 
-    // look for a commodity column, clear the commdoity combo
+    // look for a commodity column, clear the commodity combo
     auto col_type_comm = std::find (column_types.begin(),
                 column_types.end(), GncPricePropType::FROM_COMMODITY);
     if (col_type_comm != column_types.end())
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index d5d3862..44a17b9 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -136,7 +136,6 @@ void GncPriceImport::over_write (bool over)
 {
     m_over_write = over;
 }
-
 bool GncPriceImport::over_write () { return m_over_write; }
 
 /** Sets a from commodity. This is the commodity all import data relates to.
@@ -147,18 +146,20 @@ bool GncPriceImport::over_write () { return m_over_write; }
 void GncPriceImport::from_commodity (gnc_commodity* from_commodity)
 {
     m_settings.m_from_commodity = from_commodity;
-
     if (m_settings.m_from_commodity)
     {
-        auto col_type = std::find (m_settings.m_column_types_price.begin(),
+        auto col_type_comm = std::find (m_settings.m_column_types_price.begin(),
                 m_settings.m_column_types_price.end(), GncPricePropType::FROM_COMMODITY);
 
-        if (col_type != m_settings.m_column_types_price.end())
-            set_column_type_price (col_type -m_settings.m_column_types_price.begin(),
+        if (col_type_comm != m_settings.m_column_types_price.end())
+            set_column_type_price (col_type_comm -m_settings.m_column_types_price.begin(),
                             GncPricePropType::NONE);
+
+        // force a refresh of the to_currency if the from_commodity is changed
+        std::vector<GncPricePropType> commodities = { GncPricePropType::TO_CURRENCY };
+        reset_formatted_column (commodities);
     }
 }
-
 gnc_commodity *GncPriceImport::from_commodity () { return m_settings.m_from_commodity; }
 
 /** Sets a to currency. This is the to currency all import data relates to.
@@ -169,18 +170,20 @@ gnc_commodity *GncPriceImport::from_commodity () { return m_settings.m_from_comm
 void GncPriceImport::to_currency (gnc_commodity* to_currency)
 {
     m_settings.m_to_currency = to_currency;
-
     if (m_settings.m_to_currency)
     {
-        auto col_type = std::find (m_settings.m_column_types_price.begin(),
+        auto col_type_currency = std::find (m_settings.m_column_types_price.begin(),
                 m_settings.m_column_types_price.end(), GncPricePropType::TO_CURRENCY);
 
-        if (col_type != m_settings.m_column_types_price.end())
-            set_column_type_price (col_type -m_settings.m_column_types_price.begin(),
+        if (col_type_currency != m_settings.m_column_types_price.end())
+            set_column_type_price (col_type_currency -m_settings.m_column_types_price.begin(),
                             GncPricePropType::NONE);
+
+        // force a refresh of the from_commodity if the to_currency is changed
+        std::vector<GncPricePropType> commodities = { GncPricePropType::FROM_COMMODITY };
+        reset_formatted_column (commodities);
     }
 }
-
 gnc_commodity *GncPriceImport::to_currency () { return m_settings.m_to_currency; }
 
 void GncPriceImport::reset_formatted_column (std::vector<GncPricePropType>& col_types)
@@ -453,6 +456,14 @@ void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
         if (!m_settings.m_from_commodity)
             error_msg.add_error( _("Please select a 'Commodity from' column or set a Commodity in the 'Commodity From' field."));
     }
+
+    /* Verify a 'Commodity from' does not equal 'Currency to'.
+     */
+    if ((m_settings.m_to_currency) && (m_settings.m_from_commodity))
+    {
+        if (gnc_commodity_equal (m_settings.m_to_currency, m_settings.m_from_commodity))
+            error_msg.add_error( _("'Commodity From' can not be the same as 'Currency To'."));
+    }
 }
 
 /* Check whether the chosen settings can successfully parse
@@ -539,7 +550,7 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
 
     error_message.clear();
 
-    // Add a CURRENCY_TO property with the selected 'currency to' if no 'currency to' column was set by the user
+    // Add a TO_CURRENCY property with the selected 'currency to' if no 'currency to' column was set by the user
     auto line_to_currency = price_props->get_to_currency();
     if (!line_to_currency)
     {
@@ -556,7 +567,7 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
         }
     }
 
-    // Add a COMMODITY_FROM property with the selected 'commodity from' if no 'commodity from' column was set by the user
+    // Add a FROM_COMMODITY property with the selected 'commodity from' if no 'commodity from' column was set by the user
     auto line_from_commodity = price_props->get_from_commodity();
     if (!line_from_commodity)
     {
@@ -657,6 +668,18 @@ void GncPriceImport::update_price_props (uint32_t row, uint32_t col, GncPricePro
     {
         try
         {
+            // set the from_commodity based on combo so we can test for same.
+            if (prop_type == GncPricePropType::TO_CURRENCY)
+            {
+                if (m_settings.m_from_commodity)
+                    price_props->set_from_commodity (m_settings.m_from_commodity);
+            }
+            // set the to_currency based on combo so we can test for same.
+            if (prop_type == GncPricePropType::FROM_COMMODITY)
+            {
+                if (m_settings.m_to_currency)
+                    price_props->set_to_currency (m_settings.m_to_currency);
+            }
             price_props->set(prop_type, value);
         }
         catch (const std::exception& e)

commit b1becf3dd4548f6244ce21bf62a1dcaf34b75518
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:51:07 2017 +0000

    Add a test for from_commodity not being the same as to_currency

diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index 2deffb3..0ea21f9 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -269,7 +269,11 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
                 m_from_commodity = boost::none;
                 comm = parse_commodity_price_comm (value); // Throws if parsing fails
                 if (comm)
+                {
+                    if (m_to_currency == comm)
+                        throw std::invalid_argument (_("'Commodity From' can not be the same as 'Currency To' column type."));
                     m_from_commodity = comm;
+                }
                 break;
 
             case GncPricePropType::TO_CURRENCY:
@@ -277,6 +281,8 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
                 comm = parse_commodity_price_comm (value); // Throws if parsing fails
                 if (comm)
                 {
+                    if (m_from_commodity == comm)
+                        throw std::invalid_argument (_("'Currency To' can not be the same as 'Commodity From' column type."));
                     if (gnc_commodity_is_currency (comm) != true)
                         throw std::invalid_argument (_("Value parsed into an invalid currency for a currency column type."));
                     m_to_currency = comm;
@@ -332,6 +338,8 @@ std::string GncImportPrice::verify_essentials (void)
         return _("No 'Currency to' column.");
     else if (m_from_commodity == boost::none)
         return _("No 'Commodity from' column.");
+    else if (gnc_commodity_equal (*m_from_commodity, *m_to_currency))
+        return _("'Commodity from' can not be the same as 'Currency to'.");
     else
         return std::string();
 }

commit 339fbaa587f49c91ed329b0f3a558a4c9ecc2bbb
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:49:28 2017 +0000

    Various changes to comments in source files and displayed text.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 075f463..14a8ffa 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -434,7 +434,7 @@ GtkTreeModel *get_model (bool all_commodity)
         /* Hide the template entry */
         if (g_utf8_collate (tmp_namespace, "template" ) != 0)
         {
-            if ((g_utf8_collate (tmp_namespace, GNC_COMMODITY_NS_CURRENCY ) == 0) || (all_commodity == true)) 
+            if ((g_utf8_collate (tmp_namespace, GNC_COMMODITY_NS_CURRENCY ) == 0) || (all_commodity == true))
             {
                 commodity_list = gnc_commodity_table_get_commodities (commodity_table, tmp_namespace);
                 commodity_list  = g_list_first (commodity_list);
@@ -1727,10 +1727,10 @@ CsvImpPriceAssist::assist_summary_page_prepare ()
 {
     auto text = std::string("<span size=\"medium\"><b>");
     text += _("The prices were imported from the file '") + m_file_name + "'.";
-    text += _("\n\nThe number of Prices added was ") + std::to_string(price_imp->m_prices_added);
-    text += _(", duplicated was ") + std::to_string(price_imp->m_prices_duplicated);
-    text += _(" and replaced was ") + std::to_string(price_imp->m_prices_replaced);
-    text += ".</b></span>";
+    text += _("\n\nThere were ") + std::to_string(price_imp->m_prices_added);
+    text += _(" Prices added, ") + std::to_string(price_imp->m_prices_duplicated);
+    text += _(" duplicated and ") + std::to_string(price_imp->m_prices_replaced);
+    text += _(" replaced.</b></span>");
 
     gtk_label_set_markup (GTK_LABEL(summary_label), text.c_str());
 }
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
index 764b196..33db266 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
@@ -44,20 +44,26 @@
     <signal name="prepare" handler="csv_price_imp_assist_prepare_cb" swapped="no"/>
     <signal name="cancel" handler="csv_price_imp_assist_cancel_cb" swapped="no"/>
     <child>
+      <placeholder/>
+    </child>
+    <child>
+      <placeholder/>
+    </child>
+    <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 Prices from a CSV file.
 
-There is a minimum number of columns that have to be present for a successful import, for Stock prices these are Date, Amount, Symbol From and for Currency they are Date, Amount, Currency From and Currency To.
+There is a minimum number of columns that have to be present for a successful import, these are Date, Amount, Commodity From and Currency To. If all entries are for the same Commodity / Currency then you can select them and then the columns will be Date and Amount.
 
-Various options exist for specifying the delimiter 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.
+Various options exist for specifying the delimiter as well as a fixed width option. With the fixed width option, double click on the table of rows displayed to set a column width, then right mouse to change if required.
 
 Examples are "RR.L","21/11/2016",5.345,"GBP" and "USD","2016-11-21",1.56,"GBP"
 
 There is an option for specifying the start row, end row and an option to skip alternate rows beginning from the start row which can be used if you have some header text. Also there is an option to over write existing prices for that day if required.
 
-On the preview page you can Load and Save the settings. To save the settings, select a previously saved entry or replace the text and press the Save Settings button.
+Lastly, for repeated imports the preview page has buttons to Load and Save the settings. To save the settings, tweak the settings to your preferences (optionally starting from an existing preset), then (optionally change the settings name and press the Save Settings button. Note you can't save to built-in presets.
 
 This operation is not reversable, so make sure you have a working backup.
 
@@ -536,6 +542,7 @@ Select location and file name for the Import, then click 'OK'...
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
                                 <property name="tooltip_text" translatable="yes">Normally prices are not over written, select this to change that. This setting is not saved.</property>
+                                <property name="focus_on_click">False</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_overwrite_cb" swapped="no"/>
                               </object>
@@ -1094,8 +1101,9 @@ For example
               <object class="GtkLabel" id="finish_label">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="label" translatable="yes">Press Apply to add Prices.
-Cancel to abort.</property>
+                <property name="label" translatable="yes"><b>Press Apply to add the Prices.
+Cancel to abort.</b></property>
+                <property name="use_markup">True</property>
                 <property name="justify">center</property>
                 <property name="wrap">True</property>
               </object>
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 38a3cbc..d5d3862 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -62,7 +62,7 @@ const gchar* currency_format_user_price[] = {N_("Locale"),
 
 
 /** Constructor for GncPriceImport.
- * @return Pointer to a new GncCSvParseData
+ * @return Pointer to a new GncCsvParseData
  */
 GncPriceImport::GncPriceImport(GncImpFileFormat format)
 {
@@ -142,7 +142,7 @@ bool GncPriceImport::over_write () { return m_over_write; }
 /** Sets a from commodity. This is the commodity all import data relates to.
  *  When a from commodity is set, there can't be any from columns selected
  *  in the import data.
- * @param from_commodity Pointer to a commodity or NULL.
+ * @param from_commodity pointer to a commodity or NULL.
  */
 void GncPriceImport::from_commodity (gnc_commodity* from_commodity)
 {
@@ -164,7 +164,7 @@ gnc_commodity *GncPriceImport::from_commodity () { return m_settings.m_from_comm
 /** Sets a to currency. This is the to currency all import data relates to.
  *  When a to currency is set, there can't be any to currency columns selected
  *  in the import data.
- * @param to_currency Pointer to a commodity or NULL.
+ * @param to_currency pointer to a commodity or NULL.
  */
 void GncPriceImport::to_currency (gnc_commodity* to_currency)
 {
@@ -221,7 +221,6 @@ int GncPriceImport::date_format () { return m_settings.m_date_format; }
  */
 void GncPriceImport::encoding (const std::string& encoding)
 {
-
     // TODO investigate if we can catch conversion errors and report them
     if (m_tokenizer)
     {
@@ -309,12 +308,10 @@ void GncPriceImport::settings (const CsvTransSettings& settings)
     std::copy_n (settings.m_column_types_price.begin(),
             std::min (m_settings.m_column_types_price.size(), settings.m_column_types_price.size()),
             m_settings.m_column_types_price.begin());
-
 }
 
 bool GncPriceImport::save_settings ()
 {
-
     if (trans_preset_is_reserved_name (m_settings.m_name))
         return true;
 
@@ -327,7 +324,6 @@ bool GncPriceImport::save_settings ()
         auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
         m_settings.m_column_widths = fwtok->get_columns();
     }
-
     return m_settings.save();
 }
 
@@ -342,7 +338,6 @@ std::string GncPriceImport::settings_name () { return m_settings.m_name; }
  */
 void GncPriceImport::load_file (const std::string& filename)
 {
-
     /* Get the raw data first and handle an error if one occurs. */
     try
     {
@@ -407,7 +402,6 @@ void GncPriceImport::tokenize (bool guessColTypes)
     }
 }
 
-
 struct ErrorListPrice
 {
 public:
@@ -428,7 +422,6 @@ std::string ErrorListPrice::str()
     return m_error.substr(0, m_error.size() - 1);
 }
 
-
 /* Test for the required minimum number of columns selected and
  * the selection is consistent.
  * @param An ErrorListPrice object to which all found issues are added.
@@ -450,7 +443,7 @@ void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
     if (!check_for_column_type(GncPricePropType::TO_CURRENCY))
     {
         if (!m_settings.m_to_currency)
-            error_msg.add_error( _("Please select a Currency to column or set a Currency in the Currency To field."));
+            error_msg.add_error( _("Please select a 'Currency to' column or set a Currency in the 'Currency To' field."));
     }
 
     /* Verify a Commodity from column is selected.
@@ -458,11 +451,10 @@ void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
     if (!check_for_column_type(GncPricePropType::FROM_COMMODITY))
     {
         if (!m_settings.m_from_commodity)
-            error_msg.add_error( _("Please select a Commodity from column or set a Commodity in the Commodity From field."));
+            error_msg.add_error( _("Please select a 'Commodity from' column or set a Commodity in the 'Commodity From' field."));
     }
 }
 
-
 /* Check whether the chosen settings can successfully parse
  * the import data. This will check:
  * - there's at least one line selected for import
@@ -547,7 +539,7 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
 
     error_message.clear();
 
-    // Add a CURRENCY_TO property with the default currency to if no currency to column was set by the user
+    // Add a CURRENCY_TO property with the selected 'currency to' if no 'currency to' column was set by the user
     auto line_to_currency = price_props->get_to_currency();
     if (!line_to_currency)
     {
@@ -555,16 +547,16 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
             price_props->set_to_currency(m_settings.m_to_currency);
         else
         {
-            // Oops - the user didn't select an Account column *and* we didn't get a default value either!
+            // Oops - the user didn't select a 'currency to' column *and* we didn't get a selected value either!
             // Note if you get here this suggests a bug in the code!
-            error_message = _("No Currency to column selected and no default Currency specified either.\n"
+            error_message = _("No 'Currency to' column selected and no selected Currency specified either.\n"
                                        "This should never happen. Please report this as a bug.");
             PINFO("User warning: %s", error_message.c_str());
             throw std::invalid_argument(error_message);
         }
     }
 
-    // Add a COMMODITY_FROM property with the default commodity from if no commodity from column was set by the user
+    // Add a COMMODITY_FROM property with the selected 'commodity from' if no 'commodity from' column was set by the user
     auto line_from_commodity = price_props->get_from_commodity();
     if (!line_from_commodity)
     {
@@ -572,9 +564,9 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
             price_props->set_from_commodity(m_settings.m_from_commodity);
         else
         {
-            // Oops - the user didn't select an Account column *and* we didn't get a default value either!
+            // Oops - the user didn't select a 'commodity from' column *and* we didn't get a selected value either!
             // Note if you get here this suggests a bug in the code!
-            error_message = _("No Commodity from column selected and no default Commodity specified either.\n"
+            error_message = _("No 'Commodity from' column selected and no selected Commodity specified either.\n"
                                        "This should never happen. Please report this as a bug.");
             PINFO("User warning: %s", error_message.c_str());
             throw std::invalid_argument(error_message);
@@ -605,7 +597,6 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
     }
 }
 
-
 /** Creates a list of prices from parsed data. The parsed data
  * will first be validated. If any errors are found in lines that are marked
  * for processing (ie not marked to skip) this function will
@@ -697,11 +688,11 @@ GncPriceImport::set_column_type_price (uint32_t position, GncPricePropType type,
 
     m_settings.m_column_types_price.at (position) = type;
 
-    // If the user has set a Commodity from column, we can't have a commodity from default set
+    // If the user has set a 'commodity from' column, we can't have a commodity from selected
     if (type == GncPricePropType::FROM_COMMODITY)
         from_commodity (nullptr);
 
-    // If the user has set a Currency to column, we can't have a currency to default set
+    // If the user has set a 'currency to' column, we can't have a currency to selected
     if (type == GncPricePropType::TO_CURRENCY)
         to_currency (nullptr);
 
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index d9293e1..2deffb3 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -160,7 +160,7 @@ time64 parse_date_price (const std::string &date_str, int format)
 }
 
 
-/** Convert str into a GncRational using the user-specified (import) currency format.
+/** Convert str into a GncNumeric using the user-specified (import) currency format.
  * @param str The string to be parsed
  * @param currency_format The currency format to use.
  * @return a GncNumeric
@@ -200,6 +200,11 @@ GncNumeric parse_amount_price (const std::string &str, int currency_format)
     return GncNumeric(val);
 }
 
+/** Convert comm_str into a gnc_commodity.
+ * @param comm_str The string to be parsed
+ * @return a gnc_commodity
+ * @exception May throw std::invalid argument if string can't be parsed properly
+ */
 gnc_commodity* parse_commodity_price_comm (const std::string& comm_str)
 {
     if (comm_str.empty())
@@ -324,9 +329,9 @@ std::string GncImportPrice::verify_essentials (void)
     else if (m_amount == boost::none)
         return _("No amount column.");
     else if (m_to_currency == boost::none)
-        return _("No Currency to column.");
+        return _("No 'Currency to' column.");
     else if (m_from_commodity == boost::none)
-        return _("No Commodity from column.");
+        return _("No 'Commodity from' column.");
     else
         return std::string();
 }
@@ -417,7 +422,6 @@ Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
 
         if (perr == false)
             throw std::invalid_argument (_("Failed to create price from selected columns."));
-//FIXME Not sure about this, should this be a PWARN
     }
     else
     {
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 1d44ff6..9ae4853 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -90,6 +90,7 @@ public:
     void set_date_format (int date_format) { m_date_format = date_format ;}
     void set_currency_format (int currency_format) { m_currency_format = currency_format ;}
     void reset (GncPricePropType prop_type);
+    std::string verify_essentials (void);
     Result create_price (QofBook* book, GNCPriceDB *pdb, bool over);
 
     gnc_commodity* get_from_commodity () { if (m_from_commodity) return *m_from_commodity; else return nullptr; }

commit 9debe91e990ba00c68a09449d6a4c22646faae66
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:47:12 2017 +0000

    Change the way commodity and currency combo's are shown.
    
    Use commodity print name to show in the combo's and use a hidden field
    to sort the list grouping by namespace. Also alter the way these
    settings are saved.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 43f2d8a..075f463 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -419,11 +419,11 @@ GtkTreeModel *get_model (bool all_commodity)
 
     store = GTK_TREE_MODEL(gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER));
     model = gtk_tree_model_sort_new_with_model (store);
-    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
-                                        0, GTK_SORT_ASCENDING);
+    // set sort to sort on second string, first string will be shown
+    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), 1, GTK_SORT_ASCENDING);
 
     gtk_list_store_append (GTK_LIST_STORE(store), &iter);
-    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, " ", 1, nullptr, -1);
+    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, " ", 1, " ", 2, nullptr, -1);
 
     namespace_list = g_list_first (namespace_list);
     while (namespace_list != nullptr)
@@ -440,23 +440,20 @@ GtkTreeModel *get_model (bool all_commodity)
                 commodity_list  = g_list_first (commodity_list);
                 while (commodity_list != nullptr)
                 {
-                    gchar *name_str;
-                    gchar *save_str;
-                    gchar *settings_str;
+                    const gchar *name_str;
+                    gchar *sort_str;
                     tmp_commodity = (gnc_commodity*)commodity_list->data;
                     DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (tmp_commodity));
 
-                    name_str = g_strconcat (tmp_namespace, " : (", gnc_commodity_get_mnemonic (tmp_commodity),
-                                            ") ", gnc_commodity_get_fullname (tmp_commodity), nullptr);
+                    name_str = gnc_commodity_get_printname (tmp_commodity);
 
-                    settings_str = g_strconcat (tmp_namespace, "::", gnc_commodity_get_mnemonic (tmp_commodity), nullptr);
-                    DEBUG("Name string is %s, Save string is %s", name_str, settings_str);
+                    sort_str = g_strconcat (tmp_namespace, "::", gnc_commodity_get_mnemonic (tmp_commodity), nullptr);
+                    DEBUG("Name string is %s, Sort string is %s", name_str, sort_str);
 
                     gtk_list_store_append (GTK_LIST_STORE(store), &iter);
-                    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, name_str, 1, settings_str, 2, tmp_commodity, -1);
+                    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, name_str, 1, sort_str, 2, tmp_commodity, -1);
 
-                    g_free (name_str);
-                    g_free (settings_str);
+                    g_free (sort_str);
                     commodity_list = g_list_next (commodity_list);
                 }
             }
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
index 73ab2a5..3bbc984 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
@@ -294,7 +294,7 @@ CsvTransSettings::load (void)
         if (col_types_str)
             g_strfreev (col_types_str);
     }
- 
+
     // Price
     if (m_settings_type.compare("PRICE") == 0)
     {
@@ -424,10 +424,20 @@ CsvTransSettings::save (void)
     if (m_settings_type.compare("PRICE") == 0)
     {
         if (m_to_currency)
-            g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, gnc_commodity_get_mnemonic(m_to_currency));
+        {
+            auto unique_name = g_strconcat (gnc_commodity_get_namespace (m_to_currency), "::",
+                               gnc_commodity_get_mnemonic (m_to_currency), nullptr);
+            g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, unique_name);
+            g_free (unique_name);
+        }
 
         if (m_from_commodity)
-            g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, gnc_commodity_get_mnemonic(m_from_commodity));
+        {
+            auto unique_name = g_strconcat (gnc_commodity_get_namespace (m_from_commodity), "::",
+                               gnc_commodity_get_mnemonic (m_from_commodity), nullptr);
+            g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, unique_name);
+            g_free (unique_name);
+        }
 
         std::vector<const char*> col_types_str_price;
         for (auto col_type : m_column_types_price)

commit b8bbdb2ad54e2eaf55b774b9954ab4f99775eea6
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:44:38 2017 +0000

    Minor changes and tidy up

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index e3a5ae3..43f2d8a 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -76,7 +76,7 @@ public:
     void assist_preview_page_prepare ();
     void assist_confirm_page_prepare ();
     void assist_summary_page_prepare ();
-    void assist_finish (bool canceled);
+    void assist_finish ();
     void assist_compmgr_close ();
 
     void file_confirm_cb ();
@@ -213,7 +213,6 @@ csv_price_imp_assist_destroy_cb (GtkWidget *object, CsvImpPriceAssist* info)
 void
 csv_price_imp_assist_cancel_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
 {
-    info->assist_finish (true);
     gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS, info);
 }
 
@@ -226,7 +225,7 @@ csv_price_imp_assist_close_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
 void
 csv_price_imp_assist_finish_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
 {
-    info->assist_finish (false);
+    info->assist_finish ();
 }
 
 void csv_price_imp_file_confirm_cb (GtkWidget *button, CsvImpPriceAssist *info)
@@ -356,7 +355,7 @@ gnc_commodity *get_commodity_from_combo (GtkComboBox *combo)
     GtkTreeModel *model, *sort_model;
     GtkTreeIter  iter, siter;
     gchar *string;
-   gnc_commodity *comm;
+    gnc_commodity *comm;
 
     if (!gtk_combo_box_get_active_iter (combo, &siter))
         return nullptr;
@@ -741,7 +740,6 @@ void CsvImpPriceAssist::preview_populate_settings_combo()
     gtk_list_store_clear (GTK_LIST_STORE(model));
 
     // Append the default entry
-//FIXME get_trans_presets ????
     auto presets = get_trans_presets (settings_type);
     for (auto preset : presets)
     {
@@ -773,7 +771,7 @@ void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
         CsvTransSettings *preset;
         GtkTreeModel *model = gtk_combo_box_get_model (combo);
         gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
-//FIXME
+
         if (preset && !trans_preset_is_reserved_name (preset->m_name))
         {
             /* Current preset is not read_only, so buttons can be enabled */
@@ -781,7 +779,6 @@ void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
             can_save = true;
         }
     }
-//FIXME
     else if (entry_text && (strlen (entry_text) > 0) &&
             !trans_preset_is_reserved_name (std::string(entry_text)))
         can_save = true;
@@ -944,6 +941,8 @@ void CsvImpPriceAssist::preview_update_skipped_rows ()
     preview_refresh_table ();
 }
 
+/* Callback triggered when user clicks on Over Write option
+ */
 void CsvImpPriceAssist::preview_over_write (bool over)
 {
     price_imp->over_write (over);
@@ -1723,6 +1722,7 @@ CsvImpPriceAssist::assist_preview_page_prepare ()
 void
 CsvImpPriceAssist::assist_confirm_page_prepare ()
 {
+    /* Confirm Page */
 }
 
 void
@@ -1752,19 +1752,9 @@ CsvImpPriceAssist::assist_prepare_cb (GtkWidget *page)
 }
 
 void
-CsvImpPriceAssist::assist_finish (bool canceled)
+CsvImpPriceAssist::assist_finish ()
 {
     /* Start the import */
-//FIXME Apply button
-g_print("Finish\n");
-//    if (canceled || price_imp->m_transactions.empty())
-//        gnc_gen_trans_list_delete (gnc_csv_importer_gui);
-//    else
-//        gnc_gen_trans_assist_start (gnc_csv_importer_gui);
-
-
-//FIXME Cancel comes here to, check when nothing set, goes to catch below also
-
     /* Create prices from the parsed data */
     try
     {

commit a996c02ef7da224a0a5962cb50985c1dd887df50
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:43:14 2017 +0000

    Change the settings file to save and load price settings.
    
    Added a setting type to distinguish between TRANS and PRICE settings so
    it can load a specific settings type and added the price save and load
    options.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 2d2cfdd..e3a5ae3 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -64,6 +64,8 @@ extern "C"
 /* This static indicates the debugging module that this .o belongs to.  */
 static QofLogModule log_module = GNC_MOD_ASSISTANT;
 
+const std::string settings_type = "PRICE";
+
 class  CsvImpPriceAssist
 {
 public:
@@ -740,7 +742,7 @@ void CsvImpPriceAssist::preview_populate_settings_combo()
 
     // Append the default entry
 //FIXME get_trans_presets ????
-    auto presets = get_trans_presets ();
+    auto presets = get_trans_presets (settings_type);
     for (auto preset : presets)
     {
         GtkTreeIter iter;
diff --git a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
index d52b676..e3d10cc 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
@@ -70,6 +70,8 @@ extern "C"
 /* This static indicates the debugging module that this .o belongs to.  */
 static QofLogModule log_module = GNC_MOD_ASSISTANT;
 
+const std::string settings_type = "TRANS";
+
 class  CsvImpTransAssist
 {
 public:
@@ -677,7 +679,7 @@ void CsvImpTransAssist::preview_populate_settings_combo()
 
     // Append the default entry
 
-    auto presets = get_trans_presets ();
+    auto presets = get_trans_presets (settings_type);
     for (auto preset : presets)
     {
         GtkTreeIter iter;
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
index 5235a4c..73ab2a5 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
@@ -41,7 +41,7 @@ extern "C"
 #include "gnc-ui-util.h"
 }
 
-const std::string csv_group_prefix{"CSV - "};
+const std::string csv_group_prefix{"CSV-"};
 const std::string no_settings{N_("No Settings")};
 const std::string gnc_exp{N_("GnuCash Export Format")};
 #define CSV_NAME         "Name"
@@ -70,10 +70,11 @@ G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
 preset_vec presets;
 
-static std::shared_ptr<CsvTransSettings> create_int_no_preset(void)
+static std::shared_ptr<CsvTransSettings> create_int_no_preset(const std::string& set_type)
 {
     auto preset = std::make_shared<CsvTransSettings>();
     preset->m_name = no_settings;
+    preset->m_settings_type = set_type;
 
     return preset;
 }
@@ -109,14 +110,6 @@ static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
             GncTransPropType::REC_DATE,
             GncTransPropType::PRICE
     };
-
-    preset->m_column_types_price = {
-            GncPricePropType::DATE,
-            GncPricePropType::AMOUNT,
-            GncPricePropType::FROM_COMMODITY,
-            GncPricePropType::TO_CURRENCY,
-    };
-
     return preset;
 }
 
@@ -124,8 +117,9 @@ static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
  * find
  *
  * find all settings entries in the state key file
+ * based on settings type.
  **************************************************/
-const preset_vec& get_trans_presets (void)
+const preset_vec& get_trans_presets (const std::string& set_type)
 {
 
     // Search all Groups in the state key file for ones starting with prefix
@@ -138,11 +132,12 @@ const preset_vec& get_trans_presets (void)
     for (gsize i=0; i < grouplength; i++)
     {
         auto group = std::string(groups[i]);
-        auto pos = group.find(csv_group_prefix);
+        auto gp = csv_group_prefix + set_type + " - ";
+        auto pos = group.find(gp);
         if (pos == std::string::npos)
             continue;
 
-        preset_names.push_back(group.substr(csv_group_prefix.size()));
+        preset_names.push_back(group.substr(gp.size()));
     }
     // string array from the state file is no longer needed now.
     g_strfreev (groups);
@@ -154,18 +149,20 @@ const preset_vec& get_trans_presets (void)
     presets.clear();
 
     /* Start with the internally generated ones */
-    presets.push_back(create_int_no_preset());
-    presets.push_back(create_int_gnc_exp_preset());
+    presets.push_back(create_int_no_preset(set_type));
+
+    if (set_type.compare("TRANS") == 0)
+        presets.push_back(create_int_gnc_exp_preset());
 
     /* Then add all the ones we found in the state file */
     for (auto preset_name : preset_names)
     {
         auto preset = std::make_shared<CsvTransSettings>();
+        preset->m_settings_type = set_type;
         preset->m_name = preset_name;
         preset->load();
         presets.push_back(preset);
     }
-
     return presets;
 }
 
@@ -215,7 +212,7 @@ CsvTransSettings::load (void)
 
     GError *key_error = nullptr;
     m_load_error = false;
-    auto group = csv_group_prefix + m_name;
+    auto group = csv_group_prefix + m_settings_type + " - " + m_name;
     auto keyfile = gnc_state_get_current ();
 
     m_skip_start_lines = g_key_file_get_integer (keyfile, group.c_str(), CSV_SKIP_START, &key_error);
@@ -260,56 +257,82 @@ CsvTransSettings::load (void)
     if (key_char)
         g_free (key_char);
 
-    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ACCOUNT, &key_error);
-    if (key_char && *key_char != '\0')
-        m_base_account = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
-    m_load_error |= handle_load_error (&key_error, group);
-    if (key_char)
-        g_free (key_char);
-
-    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_TO_CURR, &key_error);
-    if (key_char && *key_char != '\0')
-//FIXME        m_to_currency = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
-        m_to_currency = nullptr;
-    m_load_error |= handle_load_error (&key_error, group);
-    if (key_char)
-        g_free (key_char);
-
-    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_FROM_COMM, &key_error);
-    if (key_char && *key_char != '\0')
-//FIXME        m_from_commodity = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
-        m_from_commodity = nullptr;
-    m_load_error |= handle_load_error (&key_error, group);
-    if (key_char)
-        g_free (key_char);
-
-    m_column_types.clear();
     gsize list_len;
-    gchar** col_types_str = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
-            &list_len, &key_error);
-    for (uint32_t i = 0; i < list_len; i++)
+
+    // Transactions
+    if (m_settings_type.compare("TRANS") == 0)
     {
-        auto col_types_it = std::find_if (gnc_csv_col_type_strs.begin(),
-                gnc_csv_col_type_strs.end(), test_prop_type_str (col_types_str[i]));
-        if (col_types_it != gnc_csv_col_type_strs.end())
+        key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ACCOUNT, &key_error);
+        if (key_char && *key_char != '\0')
+            m_base_account = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
+        m_load_error |= handle_load_error (&key_error, group);
+        if (key_char)
+            g_free (key_char);
+
+        m_column_types.clear();
+        gchar** col_types_str = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+                &list_len, &key_error);
+        for (uint32_t i = 0; i < list_len; i++)
         {
-            /* Found a valid column type. Now check whether it is allowed
-             * in the selected mode (two-split vs multi-split) */
-            auto prop = sanitize_trans_prop (col_types_it->first, m_multi_split);
-                m_column_types.push_back(prop);
-            if (prop != col_types_it->first)
-                PWARN("Found column type '%s', but this is blacklisted when multi-split mode is %s. "
-                        "Inserting column type 'NONE' instead'.",
-                        col_types_it->second, m_multi_split ? "enabled" : "disabled");
+            auto col_types_it = std::find_if (gnc_csv_col_type_strs.begin(),
+                    gnc_csv_col_type_strs.end(), test_prop_type_str (col_types_str[i]));
+            if (col_types_it != gnc_csv_col_type_strs.end())
+            {
+                /* Found a valid column type. Now check whether it is allowed
+                 * in the selected mode (two-split vs multi-split) */
+                auto prop = sanitize_trans_prop (col_types_it->first, m_multi_split);
+                    m_column_types.push_back(prop);
+                if (prop != col_types_it->first)
+                    PWARN("Found column type '%s', but this is blacklisted when multi-split mode is %s. "
+                            "Inserting column type 'NONE' instead'.",
+                            col_types_it->second, m_multi_split ? "enabled" : "disabled");
+            }
+            else
+                PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
+                        col_types_str[i]);
         }
-        else
-            PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
-                    col_types_str[i]);
-
+        if (col_types_str)
+            g_strfreev (col_types_str);
+    }
+ 
+    // Price
+    if (m_settings_type.compare("PRICE") == 0)
+    {
+        key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_TO_CURR, &key_error);
+        if (key_char && *key_char != '\0')
+            m_to_currency = parse_commodity_price_comm (key_char);
+        m_load_error |= handle_load_error (&key_error, group);
+        if (key_char)
+            g_free (key_char);
+
+        key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_FROM_COMM, &key_error);
+        if (key_char && *key_char != '\0')
+            m_from_commodity = parse_commodity_price_comm (key_char);
+        m_load_error |= handle_load_error (&key_error, group);
+        if (key_char)
+            g_free (key_char);
+
+        m_column_types.clear();
+        gchar** col_types_str_price = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+                &list_len, &key_error);
+        for (uint32_t i = 0; i < list_len; i++)
+        {
+            auto col_types_it = std::find_if (gnc_price_col_type_strs.begin(),
+                    gnc_price_col_type_strs.end(), test_price_prop_type_str (col_types_str_price[i]));
+            if (col_types_it != gnc_price_col_type_strs.end())
+            {
+                // Found a valid column type
+                m_column_types_price.push_back(col_types_it->first);
+            }
+            else
+                PWARN("Found invalid column type '%s'. Inserting column type 'NONE' instead'.",
+                        col_types_str_price[i]);
+        }
+        if (col_types_str_price)
+            g_strfreev (col_types_str_price);
     }
-    if (col_types_str)
-        g_strfreev (col_types_str);
 
+    // Widths
     m_column_widths.clear();
     gint *col_widths_int = g_key_file_get_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS,
             &list_len, &key_error);
@@ -347,14 +370,15 @@ CsvTransSettings::save (void)
     }
 
     auto keyfile = gnc_state_get_current ();
-    auto group = csv_group_prefix + m_name;
+    auto group = csv_group_prefix + m_settings_type + " - " + m_name;
 
     // Drop previous saved settings with this name
     g_key_file_remove_group (keyfile, group.c_str(), nullptr);
 
     // Start Saving the settings
+    // Common
     g_key_file_set_string (keyfile, group.c_str(), CSV_NAME, m_name.c_str());
-    g_key_file_set_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, m_multi_split);
+
     g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_START, m_skip_start_lines);
     g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_END, m_skip_end_lines);
     g_key_file_set_boolean (keyfile, group.c_str(), CSV_SKIP_ALT, m_skip_alt_lines);
@@ -375,26 +399,44 @@ CsvTransSettings::save (void)
     g_key_file_set_integer (keyfile, group.c_str(), CSV_CURRENCY, m_currency_format);
     g_key_file_set_string (keyfile, group.c_str(), CSV_ENCODING, m_encoding.c_str());
 
-    if (m_base_account)
-        g_key_file_set_string (keyfile, group.c_str(), CSV_ACCOUNT, gnc_account_get_full_name(m_base_account));
+    if (!m_column_widths.empty())
+        g_key_file_set_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS,
+                (gint*)(m_column_widths.data()), m_column_widths.size());
 
-    if (m_to_currency)
-        g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, gnc_commodity_get_fullname(m_to_currency));
+    // Transaction
+    if (m_settings_type.compare("TRANS") == 0)
+    {
+        g_key_file_set_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, m_multi_split);
 
-    if (m_from_commodity)
-        g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, gnc_commodity_get_fullname(m_from_commodity));
+        if (m_base_account)
+            g_key_file_set_string (keyfile, group.c_str(), CSV_ACCOUNT, gnc_account_get_full_name(m_base_account));
 
-    std::vector<const char*> col_types_str;
-    for (auto col_type : m_column_types)
-        col_types_str.push_back(gnc_csv_col_type_strs[col_type]);
+        std::vector<const char*> col_types_str;
+        for (auto col_type : m_column_types)
+            col_types_str.push_back(gnc_csv_col_type_strs[col_type]);
 
-    if (!col_types_str.empty())
-        g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
-                col_types_str.data(), col_types_str.size());
+        if (!col_types_str.empty())
+            g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+                    col_types_str.data(), col_types_str.size());
+    }
 
-    if (!m_column_widths.empty())
-        g_key_file_set_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS,
-                (gint*)(m_column_widths.data()), m_column_widths.size());
+    // Price
+    if (m_settings_type.compare("PRICE") == 0)
+    {
+        if (m_to_currency)
+            g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, gnc_commodity_get_mnemonic(m_to_currency));
+
+        if (m_from_commodity)
+            g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, gnc_commodity_get_mnemonic(m_from_commodity));
+
+        std::vector<const char*> col_types_str_price;
+        for (auto col_type : m_column_types_price)
+            col_types_str_price.push_back(gnc_price_col_type_strs[col_type]);
+
+        if (!col_types_str_price.empty())
+            g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
+                    col_types_str_price.data(), col_types_str_price.size());
+    }
 
     // Do a test read of encoding
     GError *key_error = nullptr;
@@ -425,7 +467,7 @@ CsvTransSettings::remove (void)
         return;
 
     auto keyfile = gnc_state_get_current ();
-    auto group = csv_group_prefix + m_name;
+    auto group = csv_group_prefix + m_settings_type + " - " + m_name;
     g_key_file_remove_group (keyfile, group.c_str(), nullptr);
 }
 
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
index dae837d..7df293c 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
@@ -54,8 +54,8 @@ struct CsvTransSettings
     CsvTransSettings() : m_file_format (GncImpFileFormat::CSV), m_encoding {"UTF-8"},
             m_multi_split (false), m_date_format {0}, m_currency_format {0},
             m_skip_start_lines{0}, m_skip_end_lines{0}, m_skip_alt_lines (false),
-            m_separators {","}, m_base_account {nullptr}, m_to_currency {nullptr},
-            m_from_commodity {nullptr}, m_load_error {false} { }
+            m_separators {","}, m_load_error {false}, m_base_account {nullptr},
+            m_from_commodity {nullptr}, m_to_currency {nullptr} { }
 
 /** Save the gathered widget properties to a key File.
  *
@@ -81,7 +81,9 @@ void remove (void);
  */
 bool read_only (void);
 
+std::string   m_settings_type;                // Settings Type, TRANS, PRICE etc.
 
+// Common Settings
 std::string   m_name;                         // Name given to this preset by the user
 GncImpFileFormat m_file_format;               // CSV import Format
 std::string   m_encoding;                     // File encoding
@@ -92,16 +94,17 @@ uint32_t      m_skip_start_lines;             // Number of header rows to skip
 uint32_t      m_skip_end_lines;               // Number of footer rows to skip
 bool          m_skip_alt_lines;               // Skip alternate rows
 std::string   m_separators;                   // Separators for csv format
+bool          m_load_error;                   // Was there an error while parsing the state file ?
+std::vector<uint32_t> m_column_widths;        // The Column widths
 
+// Transaction Settings
 Account      *m_base_account;                 // Base account
 std::vector<GncTransPropType> m_column_types; // The Column types in order
-std::vector<GncPricePropType> m_column_types_price; // The Column Price types in order
-std::vector<uint32_t> m_column_widths;        // The Column widths
 
-gnc_commodity *m_to_currency;                 //  Price To Currency
+// Price Settings
 gnc_commodity *m_from_commodity;              //  Price From Commodity
-
-bool          m_load_error;                   // Was there an error while parsing the state file ?
+gnc_commodity *m_to_currency;                 //  Price To Currency
+std::vector<GncPricePropType> m_column_types_price; // The Price Column types in order
 };
 
 using preset_vec = std::vector<std::shared_ptr<CsvTransSettings>>;
@@ -109,9 +112,12 @@ using preset_vec = std::vector<std::shared_ptr<CsvTransSettings>>;
  *  - one or more internally defined presets
  *  - all preset found in the state key file.
  *
+ *  @param set_type The type of setting stored in the
+ *  key file, TRANS, PRICE, etc.
+ *
  *  @return a reference to the populated vector.
  */
-const preset_vec& get_trans_presets (void);
+const preset_vec& get_trans_presets (const std::string& set_type);
 
 /** Check whether name can be used as a preset name.
  *  The names of the internal presets are considered reserved.

commit 5578da11860737109f678443b9bf8b4e7084b2dd
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:34:21 2017 +0000

    Fix some errors in conversion of some function names
    
    Some function names did not get converted to a price equivalent and
    reorder some statements.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 120367a..2d2cfdd 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -607,9 +607,9 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
 
         /* Add in the date format combo box and hook it up to an event handler. */
         date_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
-        for (int i = 0; i < num_date_formats; i++)
+        for (int i = 0; i < num_date_formats_price; i++)
         {
-            gtk_combo_box_text_append_text (date_format_combo, _(date_format_user[i]));
+            gtk_combo_box_text_append_text (date_format_combo, _(date_format_user_price[i]));
         }
         gtk_combo_box_set_active (GTK_COMBO_BOX(date_format_combo), 0);
         g_signal_connect (G_OBJECT(date_format_combo), "changed",
@@ -622,9 +622,9 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
 
         /* Add in the currency format combo box and hook it up to an event handler. */
         currency_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
-        for (int i = 0; i < num_currency_formats; i++)
+        for (int i = 0; i < num_currency_formats_price; i++)
         {
-            gtk_combo_box_text_append_text (currency_format_combo, _(currency_format_user[i]));
+            gtk_combo_box_text_append_text (currency_format_combo, _(currency_format_user_price[i]));
         }
         /* Default will the locale */
         gtk_combo_box_set_active (GTK_COMBO_BOX(currency_format_combo), 0);
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index e7bb72a..38a3cbc 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -284,9 +284,9 @@ void GncPriceImport::settings (const CsvTransSettings& settings)
     /* First apply file format as this may recreate the tokenizer */
     file_format (settings.m_file_format);
     /* Only then apply the other settings */
+    m_settings = settings;
     from_commodity (m_settings.m_from_commodity);
     to_currency (m_settings.m_to_currency);
-    m_settings = settings;
     encoding (m_settings.m_encoding);
 
     if (file_format() == GncImpFileFormat::CSV)
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index 809464e..be91941 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -46,12 +46,12 @@ extern "C" {
 #include <boost/optional.hpp>
 
 /* A set of currency formats that the user sees. */
-extern const int num_currency_formats;
-extern const gchar* currency_format_user[];
+extern const int num_currency_formats_price;
+extern const gchar* currency_format_user_price[];
 
 /* A set of date formats that the user sees. */
-extern const int num_date_formats;
-extern const gchar* date_format_user[];
+extern const int num_date_formats_price;
+extern const gchar* date_format_user_price[];
 
 /** Tuple to hold
  *  - a tokenized line of input
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 9ae4853..1d44ff6 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -90,7 +90,6 @@ public:
     void set_date_format (int date_format) { m_date_format = date_format ;}
     void set_currency_format (int currency_format) { m_currency_format = currency_format ;}
     void reset (GncPricePropType prop_type);
-    std::string verify_essentials (void);
     Result create_price (QofBook* book, GNCPriceDB *pdb, bool over);
 
     gnc_commodity* get_from_commodity () { if (m_from_commodity) return *m_from_commodity; else return nullptr; }

commit 4d75259cb41902581bcffaf71ca2742164e635c2
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:32:48 2017 +0000

    Remove duplicated function

diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index e6f983e..d9293e1 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -240,56 +240,6 @@ gnc_commodity* parse_commodity_price_comm (const std::string& comm_str)
         return comm;
 }
 
-//FIXME can we change above to do below
-gnc_commodity * parse_commodity_price_sym (const std::string& sym_str, bool is_currency)
-{
-    if (sym_str.empty())
-        return nullptr;
-
-    auto commodity_table = gnc_get_current_commodities ();
-    GList         *namespaces;
-    gnc_commodity *retval = nullptr;
-    gnc_commodity *tmp_commodity = nullptr;
-    char  *tmp_namespace = nullptr;
-    GList *commodity_list = NULL;
-    GList *namespace_list = gnc_commodity_table_get_namespaces (commodity_table);
-
-    namespace_list = g_list_first (namespace_list);
-    while (namespace_list != NULL && retval == NULL)
-    {
-        tmp_namespace = (char*)namespace_list->data;
-        DEBUG("Looking at namespace %s", tmp_namespace);
-        commodity_list = gnc_commodity_table_get_commodities (commodity_table, tmp_namespace);
-        commodity_list  = g_list_first (commodity_list);
-        while (commodity_list != NULL && retval == NULL)
-        {
-            const char* tmp_mnemonic = NULL;
-            tmp_commodity = (gnc_commodity*)commodity_list->data;
-            DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (tmp_commodity));
-            tmp_mnemonic = gnc_commodity_get_mnemonic (tmp_commodity);
-            if (g_strcmp0 (tmp_mnemonic, sym_str.c_str()) == 0)
-            {
-                retval = tmp_commodity;
-                DEBUG("Commodity %s%s", gnc_commodity_get_fullname (retval), " matches.");
-            }
-            commodity_list = g_list_next (commodity_list);
-        }
-        namespace_list = g_list_next (namespace_list);
-    }
-    g_list_free (commodity_list);
-    g_list_free (namespace_list);
-
-    if (!retval)
-        throw std::invalid_argument (_("Value can't be parsed into a valid commodity."));
-    else
-    {
-        if ((is_currency == true) && (gnc_commodity_is_currency (retval) != true))
-                throw std::invalid_argument (_("Value parsed into an invalid currency for currency column type."));
-        else
-            return retval;
-    }
-}
-
 void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
 {
     try
@@ -307,21 +257,25 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
 
             case GncPricePropType::AMOUNT:
                 m_amount = boost::none;
-                m_amount = parse_amount_price (value, m_currency_format); // Will throw if parsing fails
+                m_amount = parse_amount_price (value, m_currency_format); // Throws if parsing fails
                 break;
 
             case GncPricePropType::FROM_COMMODITY:
                 m_from_commodity = boost::none;
-                comm = parse_commodity_price_sym (value, false); // Throws if parsing fails
+                comm = parse_commodity_price_comm (value); // Throws if parsing fails
                 if (comm)
                     m_from_commodity = comm;
                 break;
 
             case GncPricePropType::TO_CURRENCY:
                 m_to_currency = boost::none;
-                comm = parse_commodity_price_sym (value, true); // Throws if parsing fails
+                comm = parse_commodity_price_comm (value); // Throws if parsing fails
                 if (comm)
+                {
+                    if (gnc_commodity_is_currency (comm) != true)
+                        throw std::invalid_argument (_("Value parsed into an invalid currency for a currency column type."));
                     m_to_currency = comm;
+                }
                 break;
 
             default:
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index a8550ea..9ae4853 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -78,7 +78,6 @@ private:
 
 time64 parse_date_price (const std::string &date_str, int format);
 gnc_commodity* parse_commodity_price_comm (const std::string& comm_str);
-gnc_commodity* parse_commodity_price_sym (const std::string& comm_str, bool is_currency);
 GncNumeric parse_amount_price (const std::string &str, int currency_format);
 
 struct GncImportPrice

commit cd4b5a31006a36d2fdbd8f2f1ef8839a4c83bfea
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:30:16 2017 +0000

    Made changes to preset column types to align with other changes
    
    These changes are to align with the changes to column types and also the
     basic setup of the new commodity from and currency to combo's. More
     changes will follow to make the saving and loading work properly.

diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
index 48cfdce..5235a4c 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
@@ -63,6 +63,8 @@ const std::string gnc_exp{N_("GnuCash Export Format")};
 #define CSV_COL_TYPES    "ColumnTypes"
 #define CSV_COL_WIDTHS   "ColumnWidths"
 #define CSV_ACCOUNT      "BaseAccount"
+#define CSV_TO_CURR      "PriceToCurrency"
+#define CSV_FROM_COMM    "PriceFromCommodity"
 
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
@@ -111,9 +113,8 @@ static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
     preset->m_column_types_price = {
             GncPricePropType::DATE,
             GncPricePropType::AMOUNT,
-            GncPricePropType::CURRENCY_FROM,
-            GncPricePropType::CURRENCY_TO,
-            GncPricePropType::SYMBOL_FROM
+            GncPricePropType::FROM_COMMODITY,
+            GncPricePropType::TO_CURRENCY,
     };
 
     return preset;
@@ -266,6 +267,22 @@ CsvTransSettings::load (void)
     if (key_char)
         g_free (key_char);
 
+    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_TO_CURR, &key_error);
+    if (key_char && *key_char != '\0')
+//FIXME        m_to_currency = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
+        m_to_currency = nullptr;
+    m_load_error |= handle_load_error (&key_error, group);
+    if (key_char)
+        g_free (key_char);
+
+    key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_FROM_COMM, &key_error);
+    if (key_char && *key_char != '\0')
+//FIXME        m_from_commodity = gnc_account_lookup_by_full_name (gnc_get_current_root_account(), key_char);
+        m_from_commodity = nullptr;
+    m_load_error |= handle_load_error (&key_error, group);
+    if (key_char)
+        g_free (key_char);
+
     m_column_types.clear();
     gsize list_len;
     gchar** col_types_str = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
@@ -361,6 +378,12 @@ CsvTransSettings::save (void)
     if (m_base_account)
         g_key_file_set_string (keyfile, group.c_str(), CSV_ACCOUNT, gnc_account_get_full_name(m_base_account));
 
+    if (m_to_currency)
+        g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, gnc_commodity_get_fullname(m_to_currency));
+
+    if (m_from_commodity)
+        g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, gnc_commodity_get_fullname(m_from_commodity));
+
     std::vector<const char*> col_types_str;
     for (auto col_type : m_column_types)
         col_types_str.push_back(gnc_csv_col_type_strs[col_type]);
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
index 93275f2..dae837d 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
@@ -31,6 +31,7 @@
 extern "C" {
 #include <config.h>
 #include "Account.h"
+#include "gnc-commodity.h"
 }
 
 #include <string>
@@ -53,8 +54,8 @@ struct CsvTransSettings
     CsvTransSettings() : m_file_format (GncImpFileFormat::CSV), m_encoding {"UTF-8"},
             m_multi_split (false), m_date_format {0}, m_currency_format {0},
             m_skip_start_lines{0}, m_skip_end_lines{0}, m_skip_alt_lines (false),
-            m_separators {","}, m_base_account {nullptr},
-            m_load_error {false} { }
+            m_separators {","}, m_base_account {nullptr}, m_to_currency {nullptr},
+            m_from_commodity {nullptr}, m_load_error {false} { }
 
 /** Save the gathered widget properties to a key File.
  *
@@ -97,6 +98,9 @@ std::vector<GncTransPropType> m_column_types; // The Column types in order
 std::vector<GncPricePropType> m_column_types_price; // The Column Price types in order
 std::vector<uint32_t> m_column_widths;        // The Column widths
 
+gnc_commodity *m_to_currency;                 //  Price To Currency
+gnc_commodity *m_from_commodity;              //  Price From Commodity
+
 bool          m_load_error;                   // Was there an error while parsing the state file ?
 };
 

commit bf0c3853ac0d9a2f57acfd5dac61c69a583ff23b
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:25:06 2017 +0000

    Add option to specify Commodity from and Currency to for whole file
    
    Added two combo's to allow user to specify a Commodity from and Currency
     to for the whole file. Also reduced the property types to four and
     aligned all the commodity and currency variables.

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index 6c4279a..120367a 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -90,6 +90,8 @@ public:
     void preview_update_encoding (const char* encoding);
     void preview_update_date_format ();
     void preview_update_currency_format ();
+    void preview_update_currency ();
+    void preview_update_commodity ();
     void preview_update_col_type (GtkComboBox* cbox);
     void preview_update_fw_columns (GtkTreeView* treeview, GdkEventButton* event);
 
@@ -134,6 +136,8 @@ private:
     GtkWidget       *csv_button;                    /**< The widget for the CSV button */
     GtkWidget       *fixed_button;                  /**< The widget for the Fixed Width button */
     GtkWidget       *over_write_cbutton;            /**< The widget for Price Over Write */
+    GtkWidget       *commodity_selector;            /**< The widget for commodity combo box */
+    GtkWidget       *currency_selector;             /**< The widget for currency combo box */
     GOCharmapSel    *encselector;                   /**< The widget for selecting the encoding */
     GtkWidget       *separator_table;               /**< Container for the separator checkboxes */
     GtkCheckButton  *sep_button[SEP_NUM_OF_TYPES];  /**< Checkbuttons for common separators */
@@ -321,6 +325,16 @@ static void csv_price_imp_preview_currency_fmt_sel_cb (GtkComboBox* format_selec
     info->preview_update_currency_format();
 }
 
+static void csv_price_imp_preview_currency_sel_cb (GtkComboBox* currency_selector, CsvImpPriceAssist* info)
+{
+    info->preview_update_currency();
+}
+
+static void csv_price_imp_preview_commodity_sel_cb (GtkComboBox* commodity_selector, CsvImpPriceAssist* info)
+{
+    info->preview_update_commodity();
+}
+
 void csv_price_imp_preview_col_type_changed_cb (GtkComboBox* cbox, CsvImpPriceAssist* info)
 {
     info->preview_update_col_type (cbox);
@@ -334,6 +348,126 @@ csv_price_imp_preview_treeview_clicked_cb (GtkTreeView* treeview, GdkEventButton
     return false;
 }
 
+static
+gnc_commodity *get_commodity_from_combo (GtkComboBox *combo)
+{
+    GtkTreeModel *model, *sort_model;
+    GtkTreeIter  iter, siter;
+    gchar *string;
+   gnc_commodity *comm;
+
+    if (!gtk_combo_box_get_active_iter (combo, &siter))
+        return nullptr;
+
+    sort_model = gtk_combo_box_get_model (combo);
+    model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT(sort_model));
+
+    gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT(sort_model),
+                                                    &iter, &siter);
+
+    gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &string, 2, &comm, -1);
+
+    PINFO("Commodity string is %s", string);
+
+    g_free (string);
+    return comm;
+}
+
+static void
+set_commodity_for_combo (GtkComboBox *combo, gnc_commodity *comm)
+{
+    GtkTreeModel *model, *sort_model;
+    GtkTreeIter  iter, siter;
+    gnc_commodity *model_comm;
+    gboolean valid;
+
+    sort_model = gtk_combo_box_get_model (combo);
+    model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT(sort_model));
+    valid = gtk_tree_model_get_iter_first (model, &iter);
+
+    while (valid)
+    {
+        gtk_tree_model_get (model, &iter, 2, &model_comm, -1);
+        if (model_comm == comm)
+        {
+            if (gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(sort_model), &siter, &iter))
+            {
+                gtk_combo_box_set_active_iter (combo, &siter);
+                return;
+            }
+        }
+        /* Make iter point to the next row in the list store */
+        valid = gtk_tree_model_iter_next (model, &iter);
+    }
+    // Not found, set it to first iter
+    valid = gtk_tree_model_get_iter_first (model, &iter);
+    if (gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT(sort_model), &siter, &iter))
+        gtk_combo_box_set_active_iter (combo, &siter);
+}
+
+static
+GtkTreeModel *get_model (bool all_commodity)
+{
+    GtkTreeModel *store, *model;
+    const gnc_commodity_table *commodity_table = gnc_get_current_commodities ();
+    gnc_commodity *tmp_commodity = nullptr;
+    char  *tmp_namespace = nullptr;
+    GList *commodity_list = nullptr;
+    GList *namespace_list = gnc_commodity_table_get_namespaces (commodity_table);
+    GtkTreeIter iter;
+
+    store = GTK_TREE_MODEL(gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER));
+    model = gtk_tree_model_sort_new_with_model (store);
+    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
+                                        0, GTK_SORT_ASCENDING);
+
+    gtk_list_store_append (GTK_LIST_STORE(store), &iter);
+    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, " ", 1, nullptr, -1);
+
+    namespace_list = g_list_first (namespace_list);
+    while (namespace_list != nullptr)
+    {
+        tmp_namespace = (char*)namespace_list->data;
+        DEBUG("Looking at namespace %s", tmp_namespace);
+
+        /* Hide the template entry */
+        if (g_utf8_collate (tmp_namespace, "template" ) != 0)
+        {
+            if ((g_utf8_collate (tmp_namespace, GNC_COMMODITY_NS_CURRENCY ) == 0) || (all_commodity == true)) 
+            {
+                commodity_list = gnc_commodity_table_get_commodities (commodity_table, tmp_namespace);
+                commodity_list  = g_list_first (commodity_list);
+                while (commodity_list != nullptr)
+                {
+                    gchar *name_str;
+                    gchar *save_str;
+                    gchar *settings_str;
+                    tmp_commodity = (gnc_commodity*)commodity_list->data;
+                    DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (tmp_commodity));
+
+                    name_str = g_strconcat (tmp_namespace, " : (", gnc_commodity_get_mnemonic (tmp_commodity),
+                                            ") ", gnc_commodity_get_fullname (tmp_commodity), nullptr);
+
+                    settings_str = g_strconcat (tmp_namespace, "::", gnc_commodity_get_mnemonic (tmp_commodity), nullptr);
+                    DEBUG("Name string is %s, Save string is %s", name_str, settings_str);
+
+                    gtk_list_store_append (GTK_LIST_STORE(store), &iter);
+                    gtk_list_store_set (GTK_LIST_STORE(store), &iter, 0, name_str, 1, settings_str, 2, tmp_commodity, -1);
+
+                    g_free (name_str);
+                    g_free (settings_str);
+                    commodity_list = g_list_next (commodity_list);
+                }
+            }
+        }
+        namespace_list = g_list_next (namespace_list);
+    }
+    g_list_free (commodity_list);
+    g_list_free (namespace_list);
+
+    return model;
+}
+
 
 /*******************************************************
  * Assistant Constructor
@@ -343,6 +477,8 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
     auto builder = gtk_builder_new();
     gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "start_row_adj");
     gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "end_row_adj");
+    gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "liststore1");
+    gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "liststore2");
     gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "CSV Price Assistant");
     csv_imp_asst = GTK_ASSISTANT(gtk_builder_get_object (builder, "CSV Price Assistant"));
 
@@ -453,6 +589,18 @@ CsvImpPriceAssist::CsvImpPriceAssist ()
         gtk_container_add (encoding_container, GTK_WIDGET(encselector));
         gtk_widget_show_all (GTK_WIDGET(encoding_container));
 
+        /* Add commodity selection widget */
+        commodity_selector = GTK_WIDGET(gtk_builder_get_object (builder, "commodity_cbox"));
+        gtk_combo_box_set_model (GTK_COMBO_BOX(commodity_selector), get_model (true));
+        g_signal_connect(G_OBJECT(commodity_selector), "changed",
+                         G_CALLBACK(csv_price_imp_preview_commodity_sel_cb), this);
+
+        /* Add currency selection widget */
+        currency_selector = GTK_WIDGET(gtk_builder_get_object (builder, "currency_cbox"));
+        gtk_combo_box_set_model (GTK_COMBO_BOX(currency_selector), get_model (false));
+        g_signal_connect(G_OBJECT(currency_selector), "changed",
+                         G_CALLBACK(csv_price_imp_preview_currency_sel_cb), this);
+
         /* The instructions label and image */
         instructions_label = GTK_LABEL(gtk_builder_get_object (builder, "instructions_label"));
         instructions_image = GTK_IMAGE(gtk_builder_get_object (builder, "instructions_image"));
@@ -570,6 +718,9 @@ CsvImpPriceAssist::file_confirm_cb ()
     preview_populate_settings_combo();
     gtk_combo_box_set_active (settings_combo, 0);
 
+    // set over_write to false as default
+    price_imp->over_write (false);
+
     auto num = gtk_assistant_get_current_page (csv_imp_asst);
     gtk_assistant_set_current_page (csv_imp_asst, num + 1);
 }
@@ -951,6 +1102,22 @@ CsvImpPriceAssist::preview_update_currency_format ()
     preview_refresh_table ();
 }
 
+void
+CsvImpPriceAssist::preview_update_currency ()
+{
+    gnc_commodity *comm = get_commodity_from_combo (GTK_COMBO_BOX(currency_selector));
+    price_imp->to_currency (comm);
+    preview_refresh_table ();
+}
+
+void
+CsvImpPriceAssist::preview_update_commodity ()
+{
+    gnc_commodity *comm = get_commodity_from_combo (GTK_COMBO_BOX(commodity_selector));
+    price_imp->from_commodity (comm);
+    preview_refresh_table ();
+}
+
 gboolean
 csv_imp_preview_queue_rebuild_table (CsvImpPriceAssist *assist)
 {
@@ -1413,6 +1580,28 @@ void CsvImpPriceAssist::preview_refresh_table ()
     for (uint32_t i = 0; i < ntcols; i++)
         preview_style_column (i, combostore);
 
+    auto column_types = price_imp->column_types_price();
+
+    // look for a commodity column, clear the commdoity combo
+    auto col_type_comm = std::find (column_types.begin(),
+                column_types.end(), GncPricePropType::FROM_COMMODITY);
+    if (col_type_comm != column_types.end())
+    {
+        g_signal_handlers_block_by_func (commodity_selector, (gpointer) csv_price_imp_preview_commodity_sel_cb, this);
+        set_commodity_for_combo (GTK_COMBO_BOX(commodity_selector), nullptr);
+        g_signal_handlers_unblock_by_func (commodity_selector, (gpointer) csv_price_imp_preview_commodity_sel_cb, this);
+    }
+
+    // look for a currency column, clear the currency combo
+    auto col_type_curr = std::find (column_types.begin(),
+                column_types.end(), GncPricePropType::TO_CURRENCY);
+    if (col_type_curr != column_types.end())
+    {
+        g_signal_handlers_block_by_func (currency_selector, (gpointer) csv_price_imp_preview_currency_sel_cb, this);
+        set_commodity_for_combo (GTK_COMBO_BOX(currency_selector), nullptr);
+        g_signal_handlers_unblock_by_func (currency_selector, (gpointer) csv_price_imp_preview_currency_sel_cb, this);
+    }
+
     /* Release our reference for the stores to allow proper memory management. */
     g_object_unref (store);
     g_object_unref (combostore);
@@ -1460,6 +1649,13 @@ CsvImpPriceAssist::preview_refresh ()
             price_imp->currency_format());
     go_charmap_sel_set_encoding (encselector, price_imp->encoding().c_str());
 
+    // Set the commodity and currency combos
+    set_commodity_for_combo(GTK_COMBO_BOX(commodity_selector),
+            price_imp->from_commodity());
+
+    set_commodity_for_combo(GTK_COMBO_BOX(currency_selector),
+            price_imp->to_currency());
+
     // Handle separator checkboxes and custom field, only relevant if the file format is csv
     if (price_imp->file_format() == GncImpFileFormat::CSV)
     {
@@ -1533,9 +1729,9 @@ CsvImpPriceAssist::assist_summary_page_prepare ()
     auto text = std::string("<span size=\"medium\"><b>");
     text += _("The prices were imported from the file '") + m_file_name + "'.";
     text += _("\n\nThe number of Prices added was ") + std::to_string(price_imp->m_prices_added);
-    text += _(" and ") + std::to_string(price_imp->m_prices_duplicated);
-    text += _(" were duplicated.");
-    text += "</b></span>";
+    text += _(", duplicated was ") + std::to_string(price_imp->m_prices_duplicated);
+    text += _(" and replaced was ") + std::to_string(price_imp->m_prices_replaced);
+    text += ".</b></span>";
 
     gtk_label_set_markup (GTK_LABEL(summary_label), text.c_str());
 }
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
index 705e827..764b196 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
@@ -7,6 +7,26 @@
     <property name="step_increment">1</property>
     <property name="page_increment">10</property>
   </object>
+  <object class="GtkListStore" id="liststore1">
+    <columns>
+      <!-- column-name string -->
+      <column type="gchararray"/>
+      <!-- column-name save -->
+      <column type="gchararray"/>
+      <!-- column-name commodity -->
+      <column type="gpointer"/>
+    </columns>
+  </object>
+  <object class="GtkListStore" id="liststore2">
+    <columns>
+      <!-- column-name string -->
+      <column type="gchararray"/>
+      <!-- column-name save -->
+      <column type="gchararray"/>
+      <!-- column-name currency -->
+      <column type="gpointer"/>
+    </columns>
+  </object>
   <object class="GtkAdjustment" id="start_row_adj">
     <property name="upper">1000</property>
     <property name="step_increment">1</property>
@@ -515,7 +535,7 @@ Select location and file name for the Import, then click 'OK'...
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
-                                <property name="tooltip_text" translatable="yes">Normally prices are not over written, select this to change that.</property>
+                                <property name="tooltip_text" translatable="yes">Normally prices are not over written, select this to change that. This setting is not saved.</property>
                                 <property name="draw_indicator">True</property>
                                 <signal name="toggled" handler="csv_price_imp_preview_overwrite_cb" swapped="no"/>
                               </object>
@@ -804,6 +824,9 @@ For example
                 <property name="y_options">GTK_FILL</property>
               </packing>
             </child>
+            <child>
+              <placeholder/>
+            </child>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -812,6 +835,125 @@ For example
           </packing>
         </child>
         <child>
+          <object class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkFrame" id="frame1">
+                <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="alignment1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="bottom_padding">5</property>
+                    <property name="left_padding">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <object class="GtkHBox" id="commodity_hbox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkComboBox" id="commodity_cbox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="model">liststore1</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes"><b>Commodity From</b></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="alignment5">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="bottom_padding">5</property>
+                    <property name="left_padding">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <object class="GtkHBox" id="currency_hbox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkComboBox" id="currency_cbox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="model">liststore1</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="cellrenderertext3"/>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </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"><b>Currency To</b></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>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
           <object class="GtkScrolledWindow" id="scrolledwindow2">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
@@ -860,7 +1002,7 @@ For example
           <packing>
             <property name="expand">True</property>
             <property name="fill">True</property>
-            <property name="position">1</property>
+            <property name="position">2</property>
           </packing>
         </child>
         <child>
@@ -902,7 +1044,7 @@ For example
             <property name="expand">False</property>
             <property name="fill">False</property>
             <property name="padding">5</property>
-            <property name="position">2</property>
+            <property name="position">3</property>
           </packing>
         </child>
         <child>
@@ -930,7 +1072,7 @@ For example
           <packing>
             <property name="expand">False</property>
             <property name="fill">False</property>
-            <property name="position">3</property>
+            <property name="position">4</property>
           </packing>
         </child>
       </object>
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 5437237..e7bb72a 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -125,7 +125,6 @@ void GncPriceImport::file_format(GncImpFileFormat format)
         auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
         fwtok->columns (m_settings.m_column_widths);
     }
-
 }
 
 GncImpFileFormat GncPriceImport::file_format()
@@ -140,6 +139,50 @@ void GncPriceImport::over_write (bool over)
 
 bool GncPriceImport::over_write () { return m_over_write; }
 
+/** Sets a from commodity. This is the commodity all import data relates to.
+ *  When a from commodity is set, there can't be any from columns selected
+ *  in the import data.
+ * @param from_commodity Pointer to a commodity or NULL.
+ */
+void GncPriceImport::from_commodity (gnc_commodity* from_commodity)
+{
+    m_settings.m_from_commodity = from_commodity;
+
+    if (m_settings.m_from_commodity)
+    {
+        auto col_type = std::find (m_settings.m_column_types_price.begin(),
+                m_settings.m_column_types_price.end(), GncPricePropType::FROM_COMMODITY);
+
+        if (col_type != m_settings.m_column_types_price.end())
+            set_column_type_price (col_type -m_settings.m_column_types_price.begin(),
+                            GncPricePropType::NONE);
+    }
+}
+
+gnc_commodity *GncPriceImport::from_commodity () { return m_settings.m_from_commodity; }
+
+/** Sets a to currency. This is the to currency all import data relates to.
+ *  When a to currency is set, there can't be any to currency columns selected
+ *  in the import data.
+ * @param to_currency Pointer to a commodity or NULL.
+ */
+void GncPriceImport::to_currency (gnc_commodity* to_currency)
+{
+    m_settings.m_to_currency = to_currency;
+
+    if (m_settings.m_to_currency)
+    {
+        auto col_type = std::find (m_settings.m_column_types_price.begin(),
+                m_settings.m_column_types_price.end(), GncPricePropType::TO_CURRENCY);
+
+        if (col_type != m_settings.m_column_types_price.end())
+            set_column_type_price (col_type -m_settings.m_column_types_price.begin(),
+                            GncPricePropType::NONE);
+    }
+}
+
+gnc_commodity *GncPriceImport::to_currency () { return m_settings.m_to_currency; }
+
 void GncPriceImport::reset_formatted_column (std::vector<GncPricePropType>& col_types)
 {
     for (auto col_type: col_types)
@@ -241,6 +284,8 @@ void GncPriceImport::settings (const CsvTransSettings& settings)
     /* First apply file format as this may recreate the tokenizer */
     file_format (settings.m_file_format);
     /* Only then apply the other settings */
+    from_commodity (m_settings.m_from_commodity);
+    to_currency (m_settings.m_to_currency);
     m_settings = settings;
     encoding (m_settings.m_encoding);
 
@@ -402,14 +447,19 @@ void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
 
     /* Verify a Currency to column is selected.
      */
-    if (!check_for_column_type(GncPricePropType::CURRENCY_TO))
-        error_msg.add_error( _("Please select a Currency to column."));
+    if (!check_for_column_type(GncPricePropType::TO_CURRENCY))
+    {
+        if (!m_settings.m_to_currency)
+            error_msg.add_error( _("Please select a Currency to column or set a Currency in the Currency To field."));
+    }
 
-    /* Verify at least one from column (symbol_from or currency_from) column is selected.
+    /* Verify a Commodity from column is selected.
      */
-    if (!check_for_column_type(GncPricePropType::SYMBOL_FROM) &&
-        !check_for_column_type(GncPricePropType::CURRENCY_FROM))
-        error_msg.add_error( _("Please select a symbol or currency from column."));
+    if (!check_for_column_type(GncPricePropType::FROM_COMMODITY))
+    {
+        if (!m_settings.m_from_commodity)
+            error_msg.add_error( _("Please select a Commodity from column or set a Commodity in the Commodity From field."));
+    }
 }
 
 
@@ -497,6 +547,40 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
 
     error_message.clear();
 
+    // Add a CURRENCY_TO property with the default currency to if no currency to column was set by the user
+    auto line_to_currency = price_props->get_to_currency();
+    if (!line_to_currency)
+    {
+        if (m_settings.m_to_currency)
+            price_props->set_to_currency(m_settings.m_to_currency);
+        else
+        {
+            // Oops - the user didn't select an Account column *and* we didn't get a default value either!
+            // Note if you get here this suggests a bug in the code!
+            error_message = _("No Currency to column selected and no default Currency specified either.\n"
+                                       "This should never happen. Please report this as a bug.");
+            PINFO("User warning: %s", error_message.c_str());
+            throw std::invalid_argument(error_message);
+        }
+    }
+
+    // Add a COMMODITY_FROM property with the default commodity from if no commodity from column was set by the user
+    auto line_from_commodity = price_props->get_from_commodity();
+    if (!line_from_commodity)
+    {
+        if (m_settings.m_from_commodity)
+            price_props->set_from_commodity(m_settings.m_from_commodity);
+        else
+        {
+            // Oops - the user didn't select an Account column *and* we didn't get a default value either!
+            // Note if you get here this suggests a bug in the code!
+            error_message = _("No Commodity from column selected and no default Commodity specified either.\n"
+                                       "This should never happen. Please report this as a bug.");
+            PINFO("User warning: %s", error_message.c_str());
+            throw std::invalid_argument(error_message);
+        }
+    }
+
     /* If column parsing was successful, convert price properties into a price. */
     try
     {
@@ -507,11 +591,12 @@ void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_l
 
         /* If all went well, add this price to the list. */
         auto price_created = price_props->create_price (book, pdb, m_over_write);
-//FIXME Need to look at this
-        if (price_created)
+        if (price_created == ADDED)
             m_prices_added++;
-        else
+        else if (price_created == DUPLICATED)
             m_prices_duplicated++;
+        else if (price_created == REPLACED)
+            m_prices_replaced++;
     }
     catch (const std::invalid_argument& e)
     {
@@ -537,6 +622,7 @@ void GncPriceImport::create_prices ()
 
     m_prices_added = 0;
     m_prices_duplicated = 0;
+    m_prices_replaced = 0;
 
     /* Iterate over all parsed lines */
     for (auto parsed_lines_it = m_parsed_lines.begin();
@@ -550,8 +636,8 @@ void GncPriceImport::create_prices ()
         /* Should not throw anymore, otherwise verify needs revision */
         create_price (parsed_lines_it);
     }
-    PINFO("Number of lines is %d, added is %d, duplicates is %d",
-         (int)m_parsed_lines.size(), m_prices_added, m_prices_duplicated);
+    PINFO("Number of lines is %d, added %d, duplicated %d, replaced %d",
+         (int)m_parsed_lines.size(), m_prices_added, m_prices_duplicated, m_prices_replaced);
 }
 
 bool
@@ -611,6 +697,14 @@ GncPriceImport::set_column_type_price (uint32_t position, GncPricePropType type,
 
     m_settings.m_column_types_price.at (position) = type;
 
+    // If the user has set a Commodity from column, we can't have a commodity from default set
+    if (type == GncPricePropType::FROM_COMMODITY)
+        from_commodity (nullptr);
+
+    // If the user has set a Currency to column, we can't have a currency to default set
+    if (type == GncPricePropType::TO_CURRENCY)
+        to_currency (nullptr);
+
     /* Update the preparsed data */
     for (auto parsed_lines_it = m_parsed_lines.begin();
             parsed_lines_it != m_parsed_lines.end();
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index 60cdc27..809464e 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -32,7 +32,7 @@
 
 extern "C" {
 #include "config.h"
-
+#include "gnc-commodity.h"
 }
 
 #include <vector>
@@ -85,6 +85,12 @@ public:
     void over_write (bool over);
     bool over_write ();
 
+    void from_commodity (gnc_commodity *from_commodity);
+    gnc_commodity *from_commodity ();
+
+    void to_currency (gnc_commodity *to_currency);
+    gnc_commodity *to_currency ();
+
     void currency_format (int currency_format);
     int currency_format ();
 
@@ -131,6 +137,7 @@ public:
                                                      price properties. */
     int  m_prices_added;
     int  m_prices_duplicated;
+    int  m_prices_replaced;
 
 private:
     /** A helper function used by create_prices. It will attempt
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index a39f178..e6f983e 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -32,8 +32,6 @@ extern "C" {
 
 #include "engine-helpers.h"
 #include "gnc-ui-util.h"
-#include "gnc-pricedb.h"
-
 }
 
 #include <string>
@@ -48,9 +46,8 @@ std::map<GncPricePropType, const char*> gnc_price_col_type_strs = {
         { GncPricePropType::NONE, N_("None") },
         { GncPricePropType::DATE, N_("Date") },
         { GncPricePropType::AMOUNT, N_("Amount") },
-        { GncPricePropType::CURRENCY_FROM, N_("Currency From") },
-        { GncPricePropType::CURRENCY_TO, N_("Currency To") },
-        { GncPricePropType::SYMBOL_FROM, N_("Symbol From") },
+        { GncPricePropType::FROM_COMMODITY, N_("Commodity From") },
+        { GncPricePropType::TO_CURRENCY, N_("Currency To") },
 };
 
 /* Regular expressions used to parse dates per date format */
@@ -243,6 +240,7 @@ gnc_commodity* parse_commodity_price_comm (const std::string& comm_str)
         return comm;
 }
 
+//FIXME can we change above to do below
 gnc_commodity * parse_commodity_price_sym (const std::string& sym_str, bool is_currency)
 {
     if (sym_str.empty())
@@ -285,8 +283,8 @@ gnc_commodity * parse_commodity_price_sym (const std::string& sym_str, bool is_c
         throw std::invalid_argument (_("Value can't be parsed into a valid commodity."));
     else
     {
-        if (gnc_commodity_is_currency (retval) != is_currency)
-            throw std::invalid_argument (_("Value parsed into an invalid commodity for column type."));
+        if ((is_currency == true) && (gnc_commodity_is_currency (retval) != true))
+                throw std::invalid_argument (_("Value parsed into an invalid currency for currency column type."));
         else
             return retval;
     }
@@ -312,25 +310,18 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
                 m_amount = parse_amount_price (value, m_currency_format); // Will throw if parsing fails
                 break;
 
-            case GncPricePropType::CURRENCY_FROM:
-                m_currency_from = boost::none;
-                comm = parse_commodity_price_sym (value, true); // Throws if parsing fails
+            case GncPricePropType::FROM_COMMODITY:
+                m_from_commodity = boost::none;
+                comm = parse_commodity_price_sym (value, false); // Throws if parsing fails
                 if (comm)
-                    m_currency_from = comm;
+                    m_from_commodity = comm;
                 break;
 
-            case GncPricePropType::CURRENCY_TO:
-                m_currency_to = boost::none;
+            case GncPricePropType::TO_CURRENCY:
+                m_to_currency = boost::none;
                 comm = parse_commodity_price_sym (value, true); // Throws if parsing fails
                 if (comm)
-                    m_currency_to = comm;
-                break;
-
-            case GncPricePropType::SYMBOL_FROM:
-                m_symbol_from = boost::none;
-                comm = parse_commodity_price_sym (value, false); // Throws if parsing fails
-                if (comm)
-                    m_symbol_from = comm;
+                    m_to_currency = comm;
                 break;
 
             default:
@@ -378,15 +369,15 @@ std::string GncImportPrice::verify_essentials (void)
         return _("No date column.");
     else if (m_amount == boost::none)
         return _("No amount column.");
-    else if (m_currency_to == boost::none)
+    else if (m_to_currency == boost::none)
         return _("No Currency to column.");
-    else if ((m_symbol_from == boost::none) && (m_currency_from == boost::none))
-        return _("No from column.");
+    else if (m_from_commodity == boost::none)
+        return _("No Commodity from column.");
     else
         return std::string();
 }
 
-bool GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
+Result GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
 {
     /* Gently refuse to create the price if the basics are not set correctly
      * This should have been tested before calling this function though!
@@ -395,47 +386,40 @@ bool GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
     if (!check.empty())
     {
         PWARN ("Refusing to create price because essentials not set properly: %s", check.c_str());
-        return false;
+        return FAILED;
     }
 
     Timespec date;
     timespecFromTime64 (&date, *m_date);
     date.tv_nsec = 0;
 
-#ifdef skip
-//FIXME Numeric needs changing, copied from old version...
     bool rev = false;
-    gnc_commodity *comm_from = nullptr;
+    auto amount = *m_amount;
 
-    if (m_currency_from != boost::none) // Currency Import
+    GNCPrice *old_price = gnc_pricedb_lookup_day (pdb, *m_from_commodity, *m_to_currency, date);
+
+    if (gnc_commodity_is_currency (*m_from_commodity)) // Currency Import
     {
         // Check for currency in reverse direction.
-        GNCPrice *rev_price = gnc_pricedb_lookup_day (pdb, *m_currency_to, *m_currency_from, date);
-        if (rev_price != nullptr)
-            rev = true;
-        gnc_price_unref (rev_price);
+        if (old_price != nullptr)
+        {
+            // Check for price in reverse direction.
+            if (gnc_commodity_equiv (gnc_price_get_currency (old_price), *m_from_commodity))
+                rev = true;
+
+            DEBUG("Commodity from is a Currency");
+        }
 
         // Check for price less than 1, reverse if so.
-        if (gnc_numeric_compare (*m_amount, gnc_numeric_create (1, 1)) != 1)
+        if (*m_amount < GncNumeric(1,1))
             rev = true;
 
-        comm_from = *m_currency_from;
-        DEBUG("Commodity from is a Currency");
     }
-    else
-        comm_from = *m_symbol_from;
-
     DEBUG("Date is %s, Rev is %d, Commodity from is '%s', Currency is '%s', Amount is %s", gnc_print_date (date),
-          rev, gnc_commodity_get_fullname (comm_from), gnc_commodity_get_fullname (*m_currency_to),
-          gnc_num_dbg_to_string (*m_amount)           );
-
-    GNCPrice *old_price = nullptr;
+        rev, gnc_commodity_get_fullname (*m_from_commodity), gnc_commodity_get_fullname (*m_to_currency),
+        amount.to_string().c_str());
 
-    // Should the commodities be reversed
-    if (rev)
-        old_price = gnc_pricedb_lookup_day (pdb, *m_currency_to, comm_from, date);
-    else
-        old_price = gnc_pricedb_lookup_day (pdb, comm_from, *m_currency_to, date);
+    Result ret_val = ADDED;
 
     // Should old price be over writen
     if ((old_price != nullptr) && (over == true))
@@ -444,31 +428,29 @@ bool GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
         gnc_pricedb_remove_price (pdb, old_price);
         gnc_price_unref (old_price);
         old_price = nullptr;
+        ret_val = REPLACED;
     }
-#endif
-    bool ret_val = true;
-#ifdef skip
+
     // Create the new price
     if (old_price == nullptr)
     {
         DEBUG("Create");
         GNCPrice *price = gnc_price_create (book);
         gnc_price_begin_edit (price);
-
         if (rev)
         {
-            gnc_price_set_commodity (price, *m_currency_to);
-            gnc_price_set_currency (price, comm_from);
-            *m_amount = gnc_numeric_convert (gnc_numeric_invert (*m_amount),
-                                          CURRENCY_DENOM, GNC_HOW_RND_ROUND_HALF_UP);
-            gnc_price_set_value (price, *m_amount);
+            amount = amount.inv(); //invert the amount
+            gnc_price_set_commodity (price, *m_to_currency);
+            gnc_price_set_currency (price, *m_from_commodity);
         }
         else
         {
-            gnc_price_set_commodity (price, comm_from);
-            gnc_price_set_currency (price, *m_currency_to);
-            gnc_price_set_value (price, *m_amount);
+            gnc_price_set_commodity (price, *m_from_commodity);
+            gnc_price_set_currency (price, *m_to_currency);
         }
+        auto amount_conv = amount.convert<RoundType::half_up>(CURRENCY_DENOM);
+        gnc_price_set_value (price, static_cast<gnc_numeric>(amount_conv));
+
         gnc_price_set_time (price, date);
         gnc_price_set_source (price, PRICE_SOURCE_USER_PRICE);
 //FIXME Not sure which one        gnc_price_set_source (price, PRICE_SOURCE_FQ);
@@ -479,15 +461,15 @@ bool GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
 
         gnc_price_unref (price);
 
-         if (perr == false)
+        if (perr == false)
             throw std::invalid_argument (_("Failed to create price from selected columns."));
 //FIXME Not sure about this, should this be a PWARN
     }
     else
-
-#endif
-        ret_val = false;
-
+    {
+        gnc_price_unref (old_price);
+        ret_val = DUPLICATED;
+    }
     return ret_val;
 }
 
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 57083e9..a8550ea 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -49,12 +49,13 @@ enum class GncPricePropType {
     NONE,
     DATE,
     AMOUNT,
-    CURRENCY_FROM,
-    CURRENCY_TO,
-    SYMBOL_FROM,
-    PRICE_PROPS = SYMBOL_FROM
+    FROM_COMMODITY,
+    TO_CURRENCY,
+    PRICE_PROPS = TO_CURRENCY
 };
 
+enum Result { FAILED, ADDED, DUPLICATED, REPLACED };
+
 /** Maps all column types to a string representation.
  *  The actual definition is in gnc-price-props.cpp.
  *  Attention: that definition should be adjusted for any
@@ -91,7 +92,14 @@ public:
     void set_currency_format (int currency_format) { m_currency_format = currency_format ;}
     void reset (GncPricePropType prop_type);
     std::string verify_essentials (void);
-    bool create_price (QofBook* book, GNCPriceDB *pdb, bool over);
+    Result create_price (QofBook* book, GNCPriceDB *pdb, bool over);
+
+    gnc_commodity* get_from_commodity () { if (m_from_commodity) return *m_from_commodity; else return nullptr; }
+    void set_from_commodity (gnc_commodity* comm) { if (comm) m_from_commodity = comm; else m_from_commodity = boost::none; }
+
+    gnc_commodity* get_to_currency () { if (m_to_currency) return *m_to_currency; else return nullptr; }
+    void set_to_currency (gnc_commodity* curr) { if (curr) m_to_currency = curr; else m_to_currency = boost::none; }
+
     std::string errors();
 
 private:
@@ -99,9 +107,8 @@ private:
     int m_currency_format;
     boost::optional<time64> m_date;
     boost::optional<GncNumeric> m_amount;
-    boost::optional<gnc_commodity*> m_currency_from;
-    boost::optional<gnc_commodity*> m_currency_to;
-    boost::optional<gnc_commodity*> m_symbol_from;
+    boost::optional<gnc_commodity*> m_from_commodity;
+    boost::optional<gnc_commodity*> m_to_currency;
     bool created = false;
 
     std::map<GncPricePropType, std::string> m_errors;

commit 1435813f0208e69aac24705f93f03d10b9cab90b
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:04:49 2017 +0000

    Some text changes

diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
index 09deb93..5437237 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -400,7 +400,7 @@ void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
     if (!check_for_column_type(GncPricePropType::AMOUNT))
         error_msg.add_error( _("Please select an amount column."));
 
-    /* Verify an Currency to column is selected.
+    /* Verify a Currency to column is selected.
      */
     if (!check_for_column_type(GncPricePropType::CURRENCY_TO))
         error_msg.add_error( _("Please select a Currency to column."));
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
index 0898215..60cdc27 100644
--- a/gnucash/import-export/csv-imp/gnc-price-import.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -68,11 +68,10 @@ struct ErrorListPrice;
  * - set a file format
  * - load a file
  * - optionally convert it's encoding
- * - parse the file into lines, which in turn are split up in columns
+ * - parse the file into lines, which in turn are split up in to columns
  *   the result of this step can be queried from tokenizer
  * - the user should now map the columns to types, which is stored in column_types
- * - last step is convert the mapped columns into a list of transactions
- * - this list will then be passed on the the generic importer for further processing */
+ * - last step is convert the mapped columns into a list of prices to add */
 class GncPriceImport
 {
 public:

commit cf90b8cb47a6dfe38e870310534fa1a1c0e294b7
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:03:07 2017 +0000

    Remove not required account update

diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
index a6ba349..6c4279a 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -87,7 +87,6 @@ public:
     void preview_over_write (bool over);
     void preview_update_separators (GtkWidget* widget);
     void preview_update_file_format ();
-    void preview_update_account ();
     void preview_update_encoding (const char* encoding);
     void preview_update_date_format ();
     void preview_update_currency_format ();
@@ -306,11 +305,6 @@ void csv_price_imp_preview_sep_fixed_sel_cb (GtkToggleButton* csv_button, CsvImp
     info->preview_update_file_format();
 }
 
-void csv_price_imp_preview_acct_sel_cb (GtkWidget* widget, CsvImpPriceAssist* info)
-{
-    info->preview_update_account();
-}
-
 void csv_price_imp_preview_enc_sel_cb (GOCharmapSel* selector, const char* encoding,
                               CsvImpPriceAssist* info)
 {

commit 393b8a126d0dfd7236800fd2705eb8d62deeaf98
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 11:01:16 2017 +0000

    Add CSV Price importer assistant files
    
    These file are largely based on the csv transaction importer.
    They are just the start for subsequent changes.

diff --git a/gnucash/import-export/csv-imp/CMakeLists.txt b/gnucash/import-export/csv-imp/CMakeLists.txt
index 0bc7d29..44a14ca 100644
--- a/gnucash/import-export/csv-imp/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/CMakeLists.txt
@@ -10,6 +10,7 @@ SET(csv_import_remote_SOURCES
 SET(csv_import_SOURCES
   gncmod-csv-import.c
   assistant-csv-account-import.c
+  assistant-csv-price-import.cpp
   assistant-csv-trans-import.cpp
   gnc-plugin-csv-import.c
   csv-account-import.c
@@ -37,6 +38,7 @@ SET(csv_import_remote_HEADERS
 
 SET(csv_import_noinst_HEADERS
   assistant-csv-account-import.h
+  assistant-csv-price-import.h
   assistant-csv-trans-import.h
   gnc-plugin-csv-import.h
   csv-account-import.h
@@ -88,7 +90,7 @@ INSTALL(TARGETS gncmod-csv-import
 # No headers to install
 
 SET(csv_import_GLADE assistant-csv-account-import.glade
-      assistant-csv-trans-import.glade)
+      assistant-csv-price-import.glade assistant-csv-trans-import.glade)
 
 INSTALL(FILES ${csv_import_GLADE} DESTINATION ${CMAKE_INSTALL_DATADIR}/gnucash/gtkbuilder)
 
diff --git a/gnucash/import-export/csv-imp/Makefile.am b/gnucash/import-export/csv-imp/Makefile.am
index 4083963..4b473de 100644
--- a/gnucash/import-export/csv-imp/Makefile.am
+++ b/gnucash/import-export/csv-imp/Makefile.am
@@ -5,6 +5,7 @@ pkglib_LTLIBRARIES=libgncmod-csv-import.la
 libgncmod_csv_import_la_SOURCES = \
   gncmod-csv-import.c \
   assistant-csv-account-import.c \
+  assistant-csv-price-import.cpp \
   assistant-csv-trans-import.cpp \
   gnc-plugin-csv-import.c \
   csv-account-import.c \
@@ -22,6 +23,7 @@ libgncmod_csv_import_la_SOURCES = \
 
 noinst_HEADERS = \
   assistant-csv-account-import.h \
+  assistant-csv-price-import.h \
   assistant-csv-trans-import.h \
   gnc-plugin-csv-import.h \
   csv-account-import.h \
@@ -79,6 +81,7 @@ ui_DATA = \
 gtkbuilderdir = ${GNC_GTKBUILDER_DIR}
 gtkbuilder_DATA = \
 	assistant-csv-account-import.glade \
+	assistant-csv-price-import.glade \
 	assistant-csv-trans-import.glade
 
 EXTRA_DIST = $(ui_DATA) $(gtkbuilder_DATA) CMakeLists.txt
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
new file mode 100644
index 0000000..a6ba349
--- /dev/null
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.cpp
@@ -0,0 +1,1621 @@
+/*******************************************************************\
+ * assistant-csv-price-import.c -- An assistant for importing       *
+ *                                     Prices from a file.          *
+ *                                                                  *
+ * Copyright (C) 2017 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-price-import.cpp
+    @brief CSV Import Assistant
+    @author Copyright (c) 2016 Geert Janssens
+    @author Copyright (c) 2017 Robert Fewell
+*/
+
+#include <guid.hpp>
+
+extern "C"
+{
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <stdlib.h>
+
+#include "gnc-ui.h"
+#include "gnc-uri-utils.h"
+#include "gnc-ui-util.h"
+#include "dialog-utils.h"
+
+#include "gnc-component-manager.h"
+
+#include "gnc-state.h"
+
+#include "assistant-csv-price-import.h"
+
+#include "gnc-csv-gnumeric-popup.h"
+#include "go-charmap-sel.h"
+}
+
+#include "gnc-csv-trans-settings.hpp"
+#include "gnc-price-import.hpp"
+#include "gnc-fw-tokenizer.hpp"
+#include "gnc-csv-tokenizer.hpp"
+
+#define MIN_COL_WIDTH 70
+#define GNC_PREFS_GROUP "dialogs.import.csv"
+#define ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS "assistant-csv-price-import"
+
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = GNC_MOD_ASSISTANT;
+
+class  CsvImpPriceAssist
+{
+public:
+    CsvImpPriceAssist ();
+
+    void assist_prepare_cb (GtkWidget *page);
+    void assist_file_page_prepare ();
+    void assist_preview_page_prepare ();
+    void assist_confirm_page_prepare ();
+    void assist_summary_page_prepare ();
+    void assist_finish (bool canceled);
+    void assist_compmgr_close ();
+
+    void file_confirm_cb ();
+
+    void preview_settings_delete ();
+    void preview_settings_save ();
+    void preview_settings_name (GtkEntry* entry);
+    void preview_settings_load ();
+    void preview_update_skipped_rows ();
+    void preview_over_write (bool over);
+    void preview_update_separators (GtkWidget* widget);
+    void preview_update_file_format ();
+    void preview_update_account ();
+    void preview_update_encoding (const char* encoding);
+    void preview_update_date_format ();
+    void preview_update_currency_format ();
+    void preview_update_col_type (GtkComboBox* cbox);
+    void preview_update_fw_columns (GtkTreeView* treeview, GdkEventButton* event);
+
+    void preview_populate_settings_combo();
+    void preview_handle_save_del_sensitivity (GtkComboBox* combo);
+    void preview_split_column (int col, int offset);
+    void preview_refresh_table ();
+    void preview_refresh ();
+    void preview_validate_settings ();
+
+    friend gboolean
+    fixed_context_menu_handler_price (GnumericPopupMenuElement const *element,
+            gpointer userdata);
+private:
+    /* helper functions to manage the context menu for fixed with columns */
+    uint32_t get_new_col_rel_pos (GtkTreeViewColumn *tcol, int dx);
+    void fixed_context_menu (GdkEventButton *event, int col, int dx);
+    /* helper function to calculate row colors for the preview table (to visualize status) */
+    void preview_row_fill_state_cells (GtkListStore *store, GtkTreeIter *iter,
+            std::string& err_msg, bool skip);
+    /* helper function to create preview header cell combo boxes listing available column types */
+    GtkWidget* preview_cbox_factory (GtkTreeModel* model, uint32_t colnum);
+    /* helper function to set rendering parameters for preview data columns */
+    void preview_style_column (uint32_t col_num, GtkTreeModel* model);
+
+    GtkAssistant    *csv_imp_asst;
+
+    GtkWidget       *file_page;                     /**< Assistant file page widget */
+    GtkWidget       *file_chooser;                  /**< The widget for the file chooser */
+    std::string      m_file_name;                   /**< The import file name */
+
+    GtkWidget       *preview_page;                  /**< Assistant preview page widget */
+    GtkComboBox     *settings_combo;                /**< The Settings Combo */
+    GtkWidget       *save_button;                   /**< The Save Settings button */
+    GtkWidget       *del_button;                    /**< The Delete Settings button */
+
+    GtkWidget       *combo_hbox;                    /**< The Settings Combo hbox */
+    GtkSpinButton   *start_row_spin;                /**< The widget for the start row spinner */
+    GtkSpinButton   *end_row_spin;                  /**< The widget for the end row spinner */
+    GtkWidget       *skip_alt_rows_button;          /**< The widget for Skip alternate rows from start row */
+    GtkWidget       *skip_errors_button;            /**< The widget for Skip error rows*/
+    GtkWidget       *csv_button;                    /**< The widget for the CSV button */
+    GtkWidget       *fixed_button;                  /**< The widget for the Fixed Width button */
+    GtkWidget       *over_write_cbutton;            /**< The widget for Price Over Write */
+    GOCharmapSel    *encselector;                   /**< The widget for selecting the encoding */
+    GtkWidget       *separator_table;               /**< Container for the separator checkboxes */
+    GtkCheckButton  *sep_button[SEP_NUM_OF_TYPES];  /**< Checkbuttons for common separators */
+    GtkWidget       *fw_instructions_hbox;          /**< Container for fixed-width instructions */
+    GtkCheckButton  *custom_cbutton;                /**< The checkbutton for a custom separator */
+    GtkEntry        *custom_entry;                  /**< The entry for custom separators */
+    GtkComboBoxText *date_format_combo;             /**< The Combo Text widget for selecting the date format */
+    GtkComboBoxText *currency_format_combo;         /**< The Combo Text widget for selecting the currency format */
+    GtkTreeView     *treeview;                      /**< The treeview containing the data */
+    GtkLabel        *instructions_label;            /**< The instructions label */
+    GtkImage        *instructions_image;            /**< The instructions image */
+    bool             encoding_selected_called;      /**< Before encoding_selected is first called, this is false.
+                                                       * error lines, instead of all the file data. */
+    int              fixed_context_col;             /**< The number of the column the user has clicked */
+    int              fixed_context_offset;          /**< The offset (in characters) in the column
+                                                       * the user has clicked */
+
+    GtkWidget       *confirm_page;                  /**< Assistant confirm page widget */
+
+    GtkWidget       *summary_page;                  /**< Assistant summary page widget */
+    GtkWidget       *summary_label;                 /**< The summary text */
+
+    std::unique_ptr<GncPriceImport> price_imp;      /**< The actual data we are previewing */
+};
+
+
+/*******************************************************
+ * Assistant call back functions
+ *******************************************************/
+
+extern "C"
+{
+void csv_price_imp_assist_prepare_cb (GtkAssistant  *assistant, GtkWidget *page, CsvImpPriceAssist* info);
+void csv_price_imp_assist_destroy_cb (GtkWidget *object, CsvImpPriceAssist* info);
+void csv_price_imp_assist_cancel_cb (GtkAssistant *gtkassistant, CsvImpPriceAssist* info);
+void csv_price_imp_assist_close_cb (GtkAssistant *gtkassistant, CsvImpPriceAssist* info);
+void csv_price_imp_assist_finish_cb (GtkAssistant *gtkassistant, CsvImpPriceAssist* info);
+void csv_price_imp_file_confirm_cb (GtkWidget *button, CsvImpPriceAssist *info);
+void csv_price_imp_preview_del_settings_cb (GtkWidget *button, CsvImpPriceAssist *info);
+void csv_price_imp_preview_save_settings_cb (GtkWidget *button, CsvImpPriceAssist *info);
+void csv_price_imp_preview_settings_sel_changed_cb (GtkComboBox *combo, CsvImpPriceAssist *info);
+void csv_price_imp_preview_settings_text_inserted_cb (GtkEditable *entry, gchar *new_text,
+        gint new_text_length, gint *position, CsvImpPriceAssist *info);
+void csv_price_imp_preview_settings_text_changed_cb (GtkEntry *entry, CsvImpPriceAssist *info);
+void csv_price_imp_preview_srow_cb (GtkSpinButton *spin, CsvImpPriceAssist *info);
+void csv_price_imp_preview_erow_cb (GtkSpinButton *spin, CsvImpPriceAssist *info);
+void csv_price_imp_preview_skiprows_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info);
+void csv_price_imp_preview_skiperrors_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info);
+void csv_price_imp_preview_overwrite_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info);
+void csv_price_imp_preview_sep_button_cb (GtkWidget* widget, CsvImpPriceAssist* info);
+void csv_price_imp_preview_sep_fixed_sel_cb (GtkToggleButton* csv_button, CsvImpPriceAssist* info);
+void csv_price_imp_preview_acct_sel_cb (GtkWidget* widget, CsvImpPriceAssist* info);
+void csv_price_imp_preview_enc_sel_cb (GOCharmapSel* selector, const char* encoding,
+                              CsvImpPriceAssist* info);
+}
+
+void
+csv_price_imp_assist_prepare_cb (GtkAssistant *assistant, GtkWidget *page,
+        CsvImpPriceAssist* info)
+{
+    info->assist_prepare_cb(page);
+}
+
+void
+csv_price_imp_assist_destroy_cb (GtkWidget *object, CsvImpPriceAssist* info)
+{
+    gnc_unregister_gui_component_by_data (ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS, info);
+    delete info;
+}
+
+void
+csv_price_imp_assist_cancel_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
+{
+    info->assist_finish (true);
+    gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS, info);
+}
+
+void
+csv_price_imp_assist_close_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
+{
+    gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS, info);
+}
+
+void
+csv_price_imp_assist_finish_cb (GtkAssistant *assistant, CsvImpPriceAssist* info)
+{
+    info->assist_finish (false);
+}
+
+void csv_price_imp_file_confirm_cb (GtkWidget *button, CsvImpPriceAssist *info)
+{
+    info->file_confirm_cb();
+}
+
+void csv_price_imp_preview_del_settings_cb (GtkWidget *button, CsvImpPriceAssist *info)
+{
+    info->preview_settings_delete();
+}
+
+void csv_price_imp_preview_save_settings_cb (GtkWidget *button, CsvImpPriceAssist *info)
+{
+    info->preview_settings_save();
+}
+
+void csv_price_imp_preview_settings_sel_changed_cb (GtkComboBox *combo, CsvImpPriceAssist *info)
+{
+    info->preview_settings_load();
+}
+
+void
+csv_price_imp_preview_settings_text_inserted_cb (GtkEditable *entry, gchar *new_text,
+        gint new_text_length, gint *position, CsvImpPriceAssist *info)
+{
+    if (!new_text)
+        return;
+
+    /* Prevent entering [], which are invalid characters in key files */
+    auto base_txt = std::string (new_text);
+    auto mod_txt = base_txt;
+    std::replace (mod_txt.begin(), mod_txt.end(), '[', '(');
+    std::replace (mod_txt.begin(), mod_txt.end(), ']', ')');
+    if (base_txt == mod_txt)
+        return;
+    g_signal_handlers_block_by_func (entry, (gpointer) csv_price_imp_preview_settings_text_inserted_cb, info);
+    gtk_editable_insert_text (entry, mod_txt.c_str(), mod_txt.size() , position);
+    g_signal_handlers_unblock_by_func (entry, (gpointer) csv_price_imp_preview_settings_text_inserted_cb, info);
+
+    g_signal_stop_emission_by_name (entry, "insert_text");
+}
+
+void
+csv_price_imp_preview_settings_text_changed_cb (GtkEntry *entry, CsvImpPriceAssist *info)
+{
+    info->preview_settings_name(entry);
+}
+
+void csv_price_imp_preview_srow_cb (GtkSpinButton *spin, CsvImpPriceAssist *info)
+{
+    info->preview_update_skipped_rows();
+}
+
+void csv_price_imp_preview_erow_cb (GtkSpinButton *spin, CsvImpPriceAssist *info)
+{
+    info->preview_update_skipped_rows();
+}
+
+void csv_price_imp_preview_skiprows_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info)
+{
+    info->preview_update_skipped_rows();
+}
+
+void csv_price_imp_preview_skiperrors_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info)
+{
+    info->preview_update_skipped_rows();
+}
+
+void csv_price_imp_preview_overwrite_cb (GtkToggleButton *checkbox, CsvImpPriceAssist *info)
+{
+    info->preview_over_write (gtk_toggle_button_get_active (checkbox));
+}
+
+void csv_price_imp_preview_sep_button_cb (GtkWidget* widget, CsvImpPriceAssist* info)
+{
+    info->preview_update_separators(widget);
+}
+
+void csv_price_imp_preview_sep_fixed_sel_cb (GtkToggleButton* csv_button, CsvImpPriceAssist* info)
+{
+    info->preview_update_file_format();
+}
+
+void csv_price_imp_preview_acct_sel_cb (GtkWidget* widget, CsvImpPriceAssist* info)
+{
+    info->preview_update_account();
+}
+
+void csv_price_imp_preview_enc_sel_cb (GOCharmapSel* selector, const char* encoding,
+                              CsvImpPriceAssist* info)
+{
+    info->preview_update_encoding(encoding);
+}
+
+static void csv_price_imp_preview_date_fmt_sel_cb (GtkComboBox* format_selector, CsvImpPriceAssist* info)
+{
+    info->preview_update_date_format();
+}
+
+static void csv_price_imp_preview_currency_fmt_sel_cb (GtkComboBox* format_selector, CsvImpPriceAssist* info)
+{
+    info->preview_update_currency_format();
+}
+
+void csv_price_imp_preview_col_type_changed_cb (GtkComboBox* cbox, CsvImpPriceAssist* info)
+{
+    info->preview_update_col_type (cbox);
+}
+
+gboolean
+csv_price_imp_preview_treeview_clicked_cb (GtkTreeView* treeview, GdkEventButton* event,
+                                        CsvImpPriceAssist* info)
+{
+    info->preview_update_fw_columns(treeview, event);
+    return false;
+}
+
+
+/*******************************************************
+ * Assistant Constructor
+ *******************************************************/
+CsvImpPriceAssist::CsvImpPriceAssist ()
+{
+    auto builder = gtk_builder_new();
+    gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "start_row_adj");
+    gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "end_row_adj");
+    gnc_builder_add_from_file  (builder , "assistant-csv-price-import.glade", "CSV Price Assistant");
+    csv_imp_asst = GTK_ASSISTANT(gtk_builder_get_object (builder, "CSV Price Assistant"));
+
+    /* Enable buttons on all page. */
+    gtk_assistant_set_page_complete (csv_imp_asst,
+                                     GTK_WIDGET(gtk_builder_get_object (builder, "start_page")),
+                                     true);
+    gtk_assistant_set_page_complete (csv_imp_asst,
+                                     GTK_WIDGET(gtk_builder_get_object (builder, "file_page")),
+                                     false);
+    gtk_assistant_set_page_complete (csv_imp_asst,
+                                     GTK_WIDGET(gtk_builder_get_object (builder, "preview_page")),
+                                     false);
+    gtk_assistant_set_page_complete (csv_imp_asst,
+                                     GTK_WIDGET(gtk_builder_get_object (builder, "confirm_page")),
+                                     true);
+    gtk_assistant_set_page_complete (csv_imp_asst,
+                                     GTK_WIDGET(gtk_builder_get_object (builder, "summary_page")),
+                                     true);
+
+    /* File chooser Page */
+    file_page = GTK_WIDGET(gtk_builder_get_object (builder, "file_page"));
+    file_chooser = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_OPEN);
+    g_signal_connect (G_OBJECT(file_chooser), "file-activated",
+                      G_CALLBACK(csv_price_imp_file_confirm_cb), this);
+    auto button = gtk_button_new_from_stock (GTK_STOCK_OK);
+    gtk_widget_set_size_request (button, 100, -1);
+    gtk_widget_show (button);
+    auto h_box = gtk_hbox_new (TRUE, 0);
+    gtk_box_pack_start (GTK_BOX(h_box), button, FALSE, FALSE, 0);
+    gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(file_chooser), h_box);
+    g_signal_connect (G_OBJECT(button), "clicked",
+                      G_CALLBACK(csv_price_imp_file_confirm_cb), this);
+
+    auto box = GTK_WIDGET(gtk_builder_get_object (builder, "file_page"));
+    gtk_box_pack_start (GTK_BOX(box), file_chooser, TRUE, TRUE, 6);
+    gtk_widget_show (file_chooser);
+
+    /* Preview Settings Page */
+    {
+        preview_page = GTK_WIDGET(gtk_builder_get_object (builder, "preview_page"));
+
+        // Add Settings combo
+        auto settings_store = gtk_list_store_new (2, G_TYPE_POINTER, G_TYPE_STRING);
+        settings_combo = GTK_COMBO_BOX(gtk_combo_box_new_with_model_and_entry (GTK_TREE_MODEL(settings_store)));
+        gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX(settings_combo), SET_NAME);
+        gtk_combo_box_set_active (GTK_COMBO_BOX(settings_combo), 0);
+
+        combo_hbox = GTK_WIDGET(gtk_builder_get_object (builder, "combo_hbox"));
+        gtk_box_pack_start (GTK_BOX(combo_hbox), GTK_WIDGET(settings_combo), true, true, 6);
+        gtk_widget_show (GTK_WIDGET(settings_combo));
+
+        g_signal_connect (G_OBJECT(settings_combo), "changed",
+                         G_CALLBACK(csv_price_imp_preview_settings_sel_changed_cb), this);
+
+        // Additionally connect to the changed signal of the embedded GtkEntry
+        auto emb_entry = gtk_bin_get_child (GTK_BIN (settings_combo));
+        g_signal_connect (G_OBJECT(emb_entry), "changed",
+                         G_CALLBACK(csv_price_imp_preview_settings_text_changed_cb), this);
+        g_signal_connect (G_OBJECT(emb_entry), "insert-text",
+                         G_CALLBACK(csv_price_imp_preview_settings_text_inserted_cb), this);
+
+        // Add Save Settings button
+        save_button = GTK_WIDGET(gtk_builder_get_object (builder, "save_settings"));
+
+        // Add Delete Settings button
+        del_button = GTK_WIDGET(gtk_builder_get_object (builder, "delete_settings"));
+
+        /* The table containing the separator configuration widgets */
+        start_row_spin = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "start_row"));
+        end_row_spin = GTK_SPIN_BUTTON(gtk_builder_get_object (builder, "end_row"));
+        skip_alt_rows_button = GTK_WIDGET(gtk_builder_get_object (builder, "skip_rows"));
+        skip_errors_button = GTK_WIDGET(gtk_builder_get_object (builder, "skip_errors_button"));
+        over_write_cbutton = GTK_WIDGET(gtk_builder_get_object (builder, "over_write_button"));
+        separator_table = GTK_WIDGET(gtk_builder_get_object (builder, "separator_table"));
+        fw_instructions_hbox = GTK_WIDGET(gtk_builder_get_object (builder, "fw_instructions_hbox"));
+
+        /* Load the separator buttons from the glade builder file into the
+         * sep_buttons array. */
+        const char* sep_button_names[] = {
+                "space_cbutton",
+                "tab_cbutton",
+                "comma_cbutton",
+                "colon_cbutton",
+                "semicolon_cbutton",
+                "hyphen_cbutton"
+            };
+        for (int i = 0; i < SEP_NUM_OF_TYPES; i++)
+            sep_button[i]
+                = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, sep_button_names[i]));
+
+        /* Load and connect the custom separator checkbutton in the same way
+         * as the other separator buttons. */
+        custom_cbutton
+            = (GtkCheckButton*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_cbutton"));
+
+        /* Load the entry for the custom separator entry. Connect it to the
+         * sep_button_clicked event handler as well. */
+        custom_entry = (GtkEntry*)GTK_WIDGET(gtk_builder_get_object (builder, "custom_entry"));
+
+        /* Create the encoding selector widget and add it to the assistant */
+        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(encselector), "charmap_changed",
+                         G_CALLBACK(csv_price_imp_preview_enc_sel_cb), this);
+
+        auto encoding_container = GTK_CONTAINER(gtk_builder_get_object (builder, "encoding_container"));
+        gtk_container_add (encoding_container, GTK_WIDGET(encselector));
+        gtk_widget_show_all (GTK_WIDGET(encoding_container));
+
+        /* The instructions label and image */
+        instructions_label = GTK_LABEL(gtk_builder_get_object (builder, "instructions_label"));
+        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. */
+        date_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
+        for (int i = 0; i < num_date_formats; i++)
+        {
+            gtk_combo_box_text_append_text (date_format_combo, _(date_format_user[i]));
+        }
+        gtk_combo_box_set_active (GTK_COMBO_BOX(date_format_combo), 0);
+        g_signal_connect (G_OBJECT(date_format_combo), "changed",
+                         G_CALLBACK(csv_price_imp_preview_date_fmt_sel_cb), this);
+
+        /* Add it to the assistant. */
+        auto date_format_container = GTK_CONTAINER(gtk_builder_get_object (builder, "date_format_container"));
+        gtk_container_add (date_format_container, GTK_WIDGET(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. */
+        currency_format_combo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
+        for (int i = 0; i < num_currency_formats; i++)
+        {
+            gtk_combo_box_text_append_text (currency_format_combo, _(currency_format_user[i]));
+        }
+        /* Default will the locale */
+        gtk_combo_box_set_active (GTK_COMBO_BOX(currency_format_combo), 0);
+        g_signal_connect (G_OBJECT(currency_format_combo), "changed",
+                         G_CALLBACK(csv_price_imp_preview_currency_fmt_sel_cb), this);
+
+        /* Add it to the assistant. */
+        auto currency_format_container = GTK_CONTAINER(gtk_builder_get_object (builder, "currency_format_container"));
+        gtk_container_add (currency_format_container, GTK_WIDGET(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"));
+        fixed_button = GTK_WIDGET(gtk_builder_get_object (builder, "fixed_button"));
+
+        /* Load the data treeview and connect it to its resizing event handler. */
+        treeview = (GtkTreeView*)GTK_WIDGET(gtk_builder_get_object (builder, "treeview"));
+        gtk_tree_view_set_headers_clickable (treeview, true);
+
+        /* This is true only after encoding_selected is called, so we must
+         * set it initially to false. */
+        encoding_selected_called = false;
+    }
+
+    /* Confirm Page */
+    confirm_page = GTK_WIDGET(gtk_builder_get_object (builder, "confirm_page"));
+
+    /* Summary Page */
+    summary_page  = GTK_WIDGET(gtk_builder_get_object (builder, "summary_page"));
+    summary_label = GTK_WIDGET(gtk_builder_get_object (builder, "summary_label"));
+
+    gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(csv_imp_asst));
+
+    gtk_builder_connect_signals (builder, this);
+    g_object_unref (G_OBJECT(builder));
+
+    gtk_widget_show_all (GTK_WIDGET(csv_imp_asst));
+    gnc_window_adjust_for_screen (GTK_WINDOW(csv_imp_asst));
+}
+
+/**************************************************
+ * Code related to the file chooser page
+ **************************************************/
+
+/* csv_price_imp_file_confirm_cb
+ *
+ * call back for ok button in file chooser widget
+ */
+void
+CsvImpPriceAssist::file_confirm_cb ()
+{
+    auto file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(file_chooser));
+    if (!file_name)
+        return;
+
+    auto filepath = gnc_uri_get_path (file_name);
+    auto starting_dir = g_path_get_dirname (filepath);
+
+    m_file_name = file_name;
+    gnc_set_default_directory (GNC_PREFS_GROUP, starting_dir);
+
+    DEBUG("file_name selected is %s", m_file_name.c_str());
+    DEBUG("starting directory is %s", starting_dir);
+
+    g_free (filepath);
+    g_free (file_name);
+    g_free (starting_dir);
+
+    /* Load the file into parse_data. */
+    price_imp = std::unique_ptr<GncPriceImport>(new GncPriceImport);
+    /* Assume data is CSV. User can later override to Fixed Width if needed */
+    try
+    {
+        price_imp->file_format (GncImpFileFormat::CSV);
+        price_imp->load_file (m_file_name);
+        price_imp->tokenize (true);
+    }
+    catch (std::ifstream::failure& e)
+    {
+        /* File loading failed ... */
+        gnc_error_dialog (GTK_WIDGET(csv_imp_asst), "%s", e.what());
+        return;
+    }
+    catch (std::range_error &e)
+    {
+        /* Parsing failed ... */
+        gnc_error_dialog (GTK_WIDGET(csv_imp_asst), "%s", e.what());
+        return;
+    }
+    /* Get settings store and populate */
+    preview_populate_settings_combo();
+    gtk_combo_box_set_active (settings_combo, 0);
+
+    auto num = gtk_assistant_get_current_page (csv_imp_asst);
+    gtk_assistant_set_current_page (csv_imp_asst, num + 1);
+}
+
+
+/**************************************************
+ * Code related to the preview page
+ **************************************************/
+
+/* Set the available presets in the settings combo box
+ */
+void CsvImpPriceAssist::preview_populate_settings_combo()
+{
+    // Clear the list store
+    auto model = gtk_combo_box_get_model (settings_combo);
+    gtk_list_store_clear (GTK_LIST_STORE(model));
+
+    // Append the default entry
+//FIXME get_trans_presets ????
+    auto presets = get_trans_presets ();
+    for (auto preset : presets)
+    {
+        GtkTreeIter iter;
+        gtk_list_store_append (GTK_LIST_STORE(model), &iter);
+        /* FIXME we store the raw pointer to the preset, while it's
+         * managed by a shared pointer. This is dangerous because
+         * when the shared pointer goes out of scope, our pointer will dangle.
+         * For now this is safe, because the shared pointers in this case are
+         * long-lived, but this may need refactoring.
+         */
+        gtk_list_store_set (GTK_LIST_STORE(model), &iter, SET_GROUP, preset.get(), SET_NAME, preset->m_name.c_str(), -1);
+    }
+}
+
+/* Enable or disable the save and delete settings buttons
+ * depending on what is selected and entered as settings name
+ */
+void CsvImpPriceAssist::preview_handle_save_del_sensitivity (GtkComboBox* combo)
+{
+    GtkTreeIter iter;
+    auto can_delete = false;
+    auto can_save = false;
+    auto entry = gtk_bin_get_child (GTK_BIN(combo));
+    auto entry_text = gtk_entry_get_text (GTK_ENTRY(entry));
+    /* Handle sensitivity of the delete and save button */
+    if (gtk_combo_box_get_active_iter (combo, &iter))
+    {
+        CsvTransSettings *preset;
+        GtkTreeModel *model = gtk_combo_box_get_model (combo);
+        gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
+//FIXME
+        if (preset && !trans_preset_is_reserved_name (preset->m_name))
+        {
+            /* Current preset is not read_only, so buttons can be enabled */
+            can_delete = true;
+            can_save = true;
+        }
+    }
+//FIXME
+    else if (entry_text && (strlen (entry_text) > 0) &&
+            !trans_preset_is_reserved_name (std::string(entry_text)))
+        can_save = true;
+
+    gtk_widget_set_sensitive (save_button, can_save);
+    gtk_widget_set_sensitive (del_button, can_delete);
+}
+
+void
+CsvImpPriceAssist::preview_settings_name (GtkEntry* entry)
+{
+    auto text = gtk_entry_get_text (entry);
+    if (text)
+        price_imp->settings_name(text);
+
+    auto combo = gtk_widget_get_parent (GTK_WIDGET(entry));
+    preview_handle_save_del_sensitivity (GTK_COMBO_BOX(combo));
+}
+
+/* Use selected preset to configure the import. Triggered when
+ * a preset is selected in the settings combo.
+ */
+void
+CsvImpPriceAssist::preview_settings_load ()
+{
+    // Get the Active Selection
+    GtkTreeIter iter;
+    if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
+        return;
+
+    CsvTransSettings *preset = nullptr;
+    auto model = gtk_combo_box_get_model (settings_combo);
+    gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
+
+    if (!preset)
+        return;
+
+    price_imp->settings (*preset);
+    if (preset->m_load_error)
+        gnc_error_dialog (GTK_WIDGET(csv_imp_asst),
+            "%s", _("There were problems reading some saved settings, continuing to load.\n"
+                    "Please review and save again."));
+
+    preview_refresh ();
+    preview_handle_save_del_sensitivity (settings_combo);
+}
+
+/* Callback to delete a settings entry
+ */
+void
+CsvImpPriceAssist::preview_settings_delete ()
+{
+    // Get the Active Selection
+    GtkTreeIter iter;
+    if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
+        return;
+
+    CsvTransSettings *preset = nullptr;
+    auto model = gtk_combo_box_get_model (settings_combo);
+    gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
+
+    auto response = gnc_ok_cancel_dialog (GTK_WIDGET(csv_imp_asst),
+                                GTK_RESPONSE_CANCEL,
+                                "%s", _("Delete the Import Settings."));
+    if (response == GTK_RESPONSE_OK)
+    {
+        preset->remove();
+        preview_populate_settings_combo();
+        gtk_combo_box_set_active (settings_combo, 0); // Default
+        preview_refresh (); // Reset the widgets
+    }
+}
+
+/* Callback to save the current settings to the gnucash state file.
+ */
+void
+CsvImpPriceAssist::preview_settings_save ()
+{
+    auto title = _("Save the Import Settings.");
+    auto new_name = price_imp->settings_name();
+
+    /* Check if the entry text matches an already existing preset */
+    GtkTreeIter iter;
+    if (!gtk_combo_box_get_active_iter (settings_combo, &iter))
+    {
+
+        auto model = gtk_combo_box_get_model (settings_combo);
+        bool valid = gtk_tree_model_get_iter_first (model, &iter);
+        while (valid)
+        {
+            // Walk through the list, reading each row
+            CsvTransSettings *preset;
+            gtk_tree_model_get (model, &iter, SET_GROUP, &preset, -1);
+
+            if (preset && (preset->m_name == std::string(new_name)))
+            {
+                auto response = gnc_ok_cancel_dialog (GTK_WIDGET(csv_imp_asst),
+                        GTK_RESPONSE_OK,
+                        "%s", _("Setting name already exists, over write?"));
+                if (response != GTK_RESPONSE_OK)
+                    return;
+
+                break;
+            }
+            valid = gtk_tree_model_iter_next (model, &iter);
+        }
+    }
+
+    /* All checks passed, let's save this preset */
+    if (!price_imp->save_settings())
+    {
+        gnc_info_dialog (GTK_WIDGET(csv_imp_asst),
+            "%s", _("The settings have been saved."));
+
+        // Update the settings store
+        preview_populate_settings_combo();
+        auto model = gtk_combo_box_get_model (settings_combo);
+
+        // Get the first entry in model
+        GtkTreeIter   iter;
+        bool valid = gtk_tree_model_get_iter_first (model, &iter);
+        while (valid)
+        {
+            // Walk through the list, reading each row
+            gchar *name = nullptr;
+            gtk_tree_model_get (model, &iter, SET_NAME, &name, -1);
+
+            if (g_strcmp0 (name, new_name.c_str()) == 0) // Set Active, the one Saved.
+                gtk_combo_box_set_active_iter (settings_combo, &iter);
+
+            g_free (name);
+
+            valid = gtk_tree_model_iter_next (model, &iter);
+        }
+    }
+    else
+        gnc_error_dialog (GTK_WIDGET(csv_imp_asst),
+            "%s", _("There was a problem saving the settings, please try again."));
+}
+
+/* Callback triggered when user adjusts skip start lines
+ */
+void CsvImpPriceAssist::preview_update_skipped_rows ()
+{
+    /* Update skip rows in the parser */
+    price_imp->update_skipped_lines (gtk_spin_button_get_value_as_int (start_row_spin),
+        gtk_spin_button_get_value_as_int (end_row_spin),
+        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(skip_alt_rows_button)),
+        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(skip_errors_button)));
+
+    /* And adjust maximum number of lines that can be skipped at each end accordingly */
+    auto adj = gtk_spin_button_get_adjustment (end_row_spin);
+    gtk_adjustment_set_upper (adj, price_imp->m_parsed_lines.size()
+            - price_imp->skip_start_lines() -1);
+
+    adj = gtk_spin_button_get_adjustment (start_row_spin);
+    gtk_adjustment_set_upper (adj, price_imp->m_parsed_lines.size()
+            - price_imp->skip_end_lines() - 1);
+
+    preview_refresh_table ();
+}
+
+void CsvImpPriceAssist::preview_over_write (bool over)
+{
+    price_imp->over_write (over);
+}
+
+/** 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
+ */
+void CsvImpPriceAssist::preview_update_separators (GtkWidget* widget)
+{
+    /* Only manipulate separator characters if the currently open file is
+     * csv separated. */
+    if (price_imp->file_format() != GncImpFileFormat::CSV)
+        return;
+
+    /* Add the corresponding characters to checked_separators for each
+     * button that is checked. */
+    auto checked_separators = std::string();
+    const auto stock_sep_chars = std::string (" \t,:;-");
+    for (int i = 0; i < SEP_NUM_OF_TYPES; i++)
+    {
+        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(sep_button[i])))
+            checked_separators += stock_sep_chars[i];
+    }
+
+    /* Add the custom separator if the user checked its button. */
+    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(custom_cbutton)))
+    {
+        auto custom_sep = gtk_entry_get_text (custom_entry);
+        if (custom_sep[0] != '\0') /* Don't add a blank separator (bad things will happen!). */
+            checked_separators += custom_sep;
+    }
+
+    /* Set the parse options using the checked_separators list. */
+    price_imp->separators (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 intact. */
+    try
+    {
+        price_imp->tokenize (false);
+        preview_refresh_table ();
+    }
+    catch (std::range_error &e)
+    {
+        /* 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 (GTK_WIDGET(csv_imp_asst), "Error in parsing");
+        /* If we're here because the user changed the file format, we should just wait for the user
+         * to update the configuration */
+        if (!widget)
+            return;
+        /* If the user changed the custom separator, erase that custom separator. */
+        if (widget == GTK_WIDGET(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;
+    }
+}
+
+/** 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
+ */
+void CsvImpPriceAssist::preview_update_file_format ()
+{
+    /* Set the parsing type correctly. */
+    try
+    {
+        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(csv_button)))
+        {
+            price_imp->file_format (GncImpFileFormat::CSV);
+            g_signal_handlers_disconnect_by_func(G_OBJECT(treeview),
+                    (gpointer)csv_price_imp_preview_treeview_clicked_cb, (gpointer)this);
+            gtk_widget_set_visible (separator_table, true);
+            gtk_widget_set_visible (fw_instructions_hbox, false);
+        }
+        else
+        {
+            price_imp->file_format (GncImpFileFormat::FIXED_WIDTH);
+            /* Enable context menu for adding/removing columns. */
+            g_signal_connect (G_OBJECT(treeview), "button-press-event",
+                    G_CALLBACK(csv_price_imp_preview_treeview_clicked_cb), (gpointer)this);
+            gtk_widget_set_visible (separator_table, false);
+            gtk_widget_set_visible (fw_instructions_hbox, true);
+
+        }
+        price_imp->tokenize (false);
+        preview_refresh_table ();
+    }
+    catch (std::range_error &e)
+    {
+        /* Parsing failed ... */
+        gnc_error_dialog (nullptr, "%s", e.what());
+        return;
+    }
+    catch (...)
+    {
+        // FIXME Handle file loading errors (possibly thrown by file_format above)
+        PWARN("Got an error during file loading");
+    }
+}
+
+/** 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
+ */
+void
+CsvImpPriceAssist::preview_update_encoding (const char* encoding)
+{
+    /* This gets called twice every time a new encoding is selected. The
+     * second call actually passes the correct data; thus, we only do
+     * something the second time this is called. */
+
+    /* If this is the second time the function is called ... */
+    if (encoding_selected_called)
+    {
+        std::string previous_encoding = price_imp->m_tokenizer->encoding();
+        /* Try converting the new encoding and reparsing. */
+        try
+        {
+            price_imp->encoding (encoding);
+            preview_refresh_table ();
+        }
+        catch (...)
+        {
+            /* If it fails, change back to the old encoding. */
+            gnc_error_dialog (nullptr, "%s", _("Invalid encoding selected"));
+            go_charmap_sel_set_encoding (encselector, previous_encoding.c_str());
+        }
+    }
+    encoding_selected_called = !encoding_selected_called;
+}
+
+void
+CsvImpPriceAssist::preview_update_date_format ()
+{
+    price_imp->date_format (gtk_combo_box_get_active (GTK_COMBO_BOX(date_format_combo)));
+    preview_refresh_table ();
+}
+
+void
+CsvImpPriceAssist::preview_update_currency_format ()
+{
+    price_imp->currency_format (gtk_combo_box_get_active (GTK_COMBO_BOX(currency_format_combo)));
+    preview_refresh_table ();
+}
+
+gboolean
+csv_imp_preview_queue_rebuild_table (CsvImpPriceAssist *assist)
+{
+    assist->preview_refresh_table ();
+    return false;
+}
+
+/* Internally used enum to access the columns in the comboboxes
+ * the user can click to set a type for each column of the data
+ */
+enum PreviewHeaderComboCols { COL_TYPE_NAME, COL_TYPE_ID };
+/* Internally used enum to access the first two (fixed) columns
+ * in the model used to display the prased data.
+ */
+enum PreviewDataTableCols {
+    PREV_COL_FCOLOR,
+    PREV_COL_BCOLOR,
+    PREV_COL_STRIKE,
+    PREV_COL_ERROR,
+    PREV_COL_ERR_ICON,
+    PREV_N_FIXED_COLS };
+
+/** 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 the 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
+ */
+void CsvImpPriceAssist::preview_update_col_type (GtkComboBox* cbox)
+{
+    /* Get the new text */
+    GtkTreeIter iter;
+    auto model = gtk_combo_box_get_model (cbox);
+    gtk_combo_box_get_active_iter (cbox, &iter);
+    auto new_col_type = GncPricePropType::NONE;
+    gtk_tree_model_get (model, &iter, COL_TYPE_ID, &new_col_type, -1);
+
+    auto col_num = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT(cbox), "col-num"));
+    price_imp->set_column_type_price (col_num, new_col_type);
+
+    /* Delay rebuilding our data table to avoid critical warnings due to
+     * pending events still acting on them after this event is processed.
+     */
+    g_idle_add ((GSourceFunc)csv_imp_preview_queue_rebuild_table, this);
+}
+
+/*======================================================================*/
+/*================== 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/gnucash/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
+    },
+    { "", nullptr, 0, 0, 0 },
+    {
+        N_("_Split this column"), nullptr,
+        0, 1 << CONTEXT_STF_IMPORT_SPLIT, CONTEXT_STF_IMPORT_SPLIT
+    },
+    { "", nullptr, 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
+    },
+    { nullptr, nullptr, 0, 0, 0 },
+};
+
+uint32_t CsvImpPriceAssist::get_new_col_rel_pos (GtkTreeViewColumn *tcol, int dx)
+{
+    auto renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT(tcol));
+    auto cell = GTK_CELL_RENDERER(renderers->data);
+    g_list_free (renderers);
+    PangoFontDescription *font_desc;
+    g_object_get (G_OBJECT(cell), "font_desc", &font_desc, nullptr);
+
+    PangoLayout *layout = gtk_widget_create_pango_layout (GTK_WIDGET(treeview), "x");
+    pango_layout_set_font_description (layout, font_desc);
+    int width;
+    pango_layout_get_pixel_size (layout, &width, nullptr);
+    if (width < 1) width = 1;
+    uint32_t charindex = (dx + width / 2) / width;
+    g_object_unref (layout);
+    pango_font_description_free (font_desc);
+
+    return charindex;
+}
+
+gboolean
+fixed_context_menu_handler_price (GnumericPopupMenuElement const *element,
+        gpointer userdata)
+{
+    auto info = (CsvImpPriceAssist*)userdata;
+    auto fwtok = dynamic_cast<GncFwTokenizer*>(info->price_imp->m_tokenizer.get());
+
+    switch (element->index)
+    {
+    case CONTEXT_STF_IMPORT_MERGE_LEFT:
+        fwtok->col_delete (info->fixed_context_col - 1);
+        break;
+    case CONTEXT_STF_IMPORT_MERGE_RIGHT:
+        fwtok->col_delete (info->fixed_context_col);
+        break;
+    case CONTEXT_STF_IMPORT_SPLIT:
+        fwtok->col_split (info->fixed_context_col, info->fixed_context_offset);
+        break;
+    case CONTEXT_STF_IMPORT_WIDEN:
+        fwtok->col_widen (info->fixed_context_col);
+        break;
+    case CONTEXT_STF_IMPORT_NARROW:
+        fwtok->col_narrow (info->fixed_context_col);
+        break;
+    default:
+        ; /* Nothing */
+    }
+
+    try
+    {
+        info->price_imp->tokenize (false);
+    }
+    catch(std::range_error& e)
+    {
+        gnc_error_dialog (nullptr, "%s", e.what());
+        return false;
+    }
+    info->preview_refresh_table ();
+    return true;
+}
+
+void
+CsvImpPriceAssist::fixed_context_menu (GdkEventButton *event,
+                    int col, int offset)
+{
+    auto fwtok = dynamic_cast<GncFwTokenizer*>(price_imp->m_tokenizer.get());
+    fixed_context_col = col;
+    fixed_context_offset = offset;
+
+    int sensitivity_filter = 0;
+    if (!fwtok->col_can_delete (col - 1))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_LEFT);
+    if (!fwtok->col_can_delete (col))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_MERGE_RIGHT);
+    if (!fwtok->col_can_split (col, offset))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_SPLIT);
+    if (!fwtok->col_can_widen (col))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_WIDEN);
+    if (!fwtok->col_can_narrow (col))
+        sensitivity_filter |= (1 << CONTEXT_STF_IMPORT_NARROW);
+
+    gnumeric_create_popup_menu (popup_elements, &fixed_context_menu_handler_price,
+                                this, 0,
+                                sensitivity_filter, event);
+}
+
+/*===================== End of Gnumeric Code ===========================*/
+/*======================================================================*/
+void
+CsvImpPriceAssist::preview_split_column (int col, int offset)
+{
+    auto fwtok = dynamic_cast<GncFwTokenizer*>(price_imp->m_tokenizer.get());
+    fwtok->col_split (col, offset);
+    try
+    {
+        price_imp->tokenize (false);
+    }
+    catch (std::range_error& e)
+    {
+        gnc_error_dialog (nullptr, "%s", e.what());
+        return;
+    }
+    preview_refresh_table();
+}
+
+/** 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
+ * @returns true if further processing of this even should stop, false
+ *               if other event handlers can have a go at this as well
+ */
+void
+CsvImpPriceAssist::preview_update_fw_columns (GtkTreeView* treeview, GdkEventButton* event)
+{
+    /* Nothing to do if this was not triggered on our treeview body */
+    if (event->window != gtk_tree_view_get_bin_window (treeview))
+        return;
+
+    /* Find the column that was clicked. */
+    GtkTreeViewColumn *tcol = nullptr;
+    int cell_x = 0;
+    auto success = gtk_tree_view_get_path_at_pos (treeview,
+            (int)event->x, (int)event->y,
+            nullptr, &tcol, &cell_x, nullptr);
+    if (!success)
+        return;
+
+    /* Stop if no column found in this treeview (-1) or
+     * if column is the error messages column (0) */
+    auto tcol_list = gtk_tree_view_get_columns(treeview);
+    auto tcol_num = g_list_index (tcol_list, tcol);
+    g_list_free (tcol_list);
+    if (tcol_num <= 0)
+        return;
+
+    /* Data columns in the treeview are offset by one
+     * because the first column is the error column
+     */
+    auto dcol = tcol_num - 1;
+    auto offset = get_new_col_rel_pos (tcol, cell_x);
+    if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
+        /* Double clicks can split columns. */
+        preview_split_column (dcol, offset);
+    else if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+        /* Right clicking brings up a context menu. */
+        fixed_context_menu (event, dcol, offset);
+}
+
+/* Convert state info (errors/skipped) in visual feedback to decorate the preview table */
+void
+CsvImpPriceAssist::preview_row_fill_state_cells (GtkListStore *store, GtkTreeIter *iter,
+        std::string& err_msg, bool skip)
+{
+    /* Extract error status for all non-skipped lines */
+    const char *c_err_msg = nullptr;
+    const char *icon_name = nullptr;
+    const char *fcolor = nullptr;
+    const char *bcolor = nullptr;
+    if (!skip && !err_msg.empty())
+    {
+        fcolor = "black";
+        bcolor = "pink";
+        c_err_msg = err_msg.c_str();
+        icon_name = GTK_STOCK_DIALOG_ERROR;
+    }
+    gtk_list_store_set (store, iter,
+            PREV_COL_FCOLOR, fcolor,
+            PREV_COL_BCOLOR, bcolor,
+            PREV_COL_STRIKE, skip,
+            PREV_COL_ERROR, c_err_msg,
+            PREV_COL_ERR_ICON, icon_name, -1);
+}
+
+/* Helper function that creates a combo_box using a model
+ * with valid column types and selects the given column type
+ */
+GtkWidget*
+CsvImpPriceAssist::preview_cbox_factory (GtkTreeModel* model, uint32_t colnum)
+{
+    GtkTreeIter iter;
+    auto cbox = gtk_combo_box_new_with_model(model);
+
+    /* Set up a renderer for this combobox. */
+    auto renderer = gtk_cell_renderer_text_new();
+    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(cbox),
+            renderer, true);
+    gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(cbox),
+            renderer, "text", COL_TYPE_NAME);
+
+    auto valid = gtk_tree_model_get_iter_first (model, &iter);
+    while (valid)
+    {
+        gint stored_col_type;
+        gtk_tree_model_get (model, &iter,
+                COL_TYPE_ID, &stored_col_type, -1);
+        if (stored_col_type == static_cast<int>( price_imp->column_types_price()[colnum]))
+            break;
+        valid = gtk_tree_model_iter_next(model, &iter);
+    }
+    if (valid)
+        gtk_combo_box_set_active_iter (GTK_COMBO_BOX(cbox), &iter);
+
+    g_object_set_data (G_OBJECT(cbox), "col-num", GUINT_TO_POINTER(colnum));
+    g_signal_connect (G_OBJECT(cbox), "changed",
+                     G_CALLBACK(csv_price_imp_preview_col_type_changed_cb), (gpointer)this);
+
+    gtk_widget_show (cbox);
+    return cbox;
+}
+
+void
+CsvImpPriceAssist::preview_style_column (uint32_t col_num, GtkTreeModel* model)
+{
+    auto col = gtk_tree_view_get_column (treeview, col_num);
+    auto renderer = static_cast<GtkCellRenderer*>(gtk_tree_view_column_get_cell_renderers(col)->data);
+
+    /* First column -the error status column- is rendered differently */
+    if (col_num == 0)
+    {
+        gtk_tree_view_column_set_attributes (col, renderer,
+                "stock-id", PREV_COL_ERR_ICON,
+                "cell-background", PREV_COL_BCOLOR, nullptr);
+        g_object_set (G_OBJECT(renderer), "stock-size", GTK_ICON_SIZE_MENU, nullptr);
+        g_object_set (G_OBJECT(col), "sizing", GTK_TREE_VIEW_COLUMN_FIXED,
+                "fixed-width", 20, nullptr);
+        gtk_tree_view_column_set_resizable (col, false);
+    }
+    else
+    {
+        gtk_tree_view_column_set_attributes (col, renderer,
+                "foreground", PREV_COL_FCOLOR,
+                "background", PREV_COL_BCOLOR,
+                "strikethrough", PREV_COL_STRIKE,
+                "text", col_num + PREV_N_FIXED_COLS -1, nullptr);
+
+        /* We want a monospace font fixed-width data is properly displayed. */
+        g_object_set (G_OBJECT(renderer), "family", "monospace", nullptr);
+
+        /* Add a combobox to select column types as column header. Each uses the same
+         * common model for the dropdown list. The selected value is taken
+         * from the column_types vector. */
+        auto cbox = preview_cbox_factory (GTK_TREE_MODEL(model), col_num - 1);
+        gtk_tree_view_column_set_widget (col, cbox);
+
+        /* Enable resizing of the columns. */
+        gtk_tree_view_column_set_resizable (col, true);
+        gtk_tree_view_column_set_clickable (col, true);
+    }
+}
+
+/* Helper to create a shared store for the header comboboxes in the preview treeview.
+ * It holds the possible column types */
+GtkTreeModel*
+make_column_header_model_price (void)
+{
+    auto combostore = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
+    for (auto col_type : gnc_price_col_type_strs)
+    {
+        GtkTreeIter iter;
+        gtk_list_store_append (combostore, &iter);
+        gtk_list_store_set (combostore, &iter,
+                COL_TYPE_NAME, _(col_type.second),
+                COL_TYPE_ID, static_cast<int>(col_type.first), -1);
+    }
+    return GTK_TREE_MODEL(combostore);
+}
+
+/* Updates the preview treeview to show the data as parsed based on the user's
+ * import parameters.
+ */
+void CsvImpPriceAssist::preview_refresh_table ()
+{
+    preview_validate_settings ();
+
+    /* Create a new liststore to hold status and data from the file being imported.
+       The first columns hold status information (row-color, row-errors, row-error-icon,...
+       All following columns represent the tokenized data as strings. */
+    auto ncols = PREV_N_FIXED_COLS + price_imp->column_types_price().size();
+    auto model_col_types = g_new (GType, ncols);
+    model_col_types[PREV_COL_FCOLOR] = G_TYPE_STRING;
+    model_col_types[PREV_COL_BCOLOR] = G_TYPE_STRING;
+    model_col_types[PREV_COL_ERROR] = G_TYPE_STRING;
+    model_col_types[PREV_COL_ERR_ICON] = G_TYPE_STRING;
+    model_col_types[PREV_COL_STRIKE] = G_TYPE_BOOLEAN;
+    for (guint i = PREV_N_FIXED_COLS; i <  ncols; i++)
+        model_col_types[i] = G_TYPE_STRING;
+    auto store = gtk_list_store_newv (ncols, model_col_types);
+    g_free (model_col_types);
+
+    /* Fill the data liststore with data from importer object. */
+    for (auto parse_line : price_imp->m_parsed_lines)
+    {
+        /* Fill the state cells */
+        GtkTreeIter iter;
+        gtk_list_store_append (store, &iter);
+        preview_row_fill_state_cells (store, &iter,
+                std::get<1>(parse_line), std::get<3>(parse_line));
+
+        /* Fill the data cells. */
+        for (auto cell_str_it = std::get<0>(parse_line).cbegin(); cell_str_it != std::get<0>(parse_line).cend(); cell_str_it++)
+        {
+            uint32_t pos = PREV_N_FIXED_COLS + cell_str_it - std::get<0>(parse_line).cbegin();
+            gtk_list_store_set (store, &iter, pos, cell_str_it->c_str(), -1);
+        }
+    }
+    gtk_tree_view_set_model (treeview, GTK_TREE_MODEL(store));
+    gtk_tree_view_set_tooltip_column (treeview, PREV_COL_ERROR);
+
+    /* Adjust treeview to go with the just created model. This consists of adding
+     * or removing columns and resetting any parameters related to how
+     * the columns and data should be rendered.
+     */
+
+    /* Start with counting the current number of columns (ntcols)
+     * we have in the treeview */
+    auto columns = gtk_tree_view_get_columns (treeview);
+    auto ntcols = g_list_length(columns);
+    g_list_free (columns);
+
+    /* Drop redundant columns if the model has less data columns than the new model
+     * ntcols = n° of columns in treeview (1 error column + x data columns)
+     * ncols = n° of columns in model (fixed state columns + x data columns)
+     */
+    while (ntcols > ncols - PREV_N_FIXED_COLS + 1)
+    {
+        auto col = gtk_tree_view_get_column (treeview, ntcols - 1);
+        gtk_tree_view_column_clear (col);
+        ntcols = gtk_tree_view_remove_column(treeview, col);
+    }
+
+    /* Insert columns if the model has more data columns than the treeview. */
+    while (ntcols < ncols - PREV_N_FIXED_COLS + 1)
+    {
+        /* Default cell renderer is text, except for the first (error) column */
+        auto renderer = gtk_cell_renderer_text_new();
+        if (ntcols == 0)
+            renderer = gtk_cell_renderer_pixbuf_new(); // Error column uses an icon
+        auto col = gtk_tree_view_column_new ();
+        gtk_tree_view_column_pack_start (col, renderer, false);
+        ntcols = gtk_tree_view_append_column (treeview, col);
+    }
+
+    /* Reset column attributes as they are undefined after recreating the model */
+    auto combostore = make_column_header_model_price ();
+    for (uint32_t i = 0; i < ntcols; i++)
+        preview_style_column (i, combostore);
+
+    /* Release our reference for the stores to allow proper memory management. */
+    g_object_unref (store);
+    g_object_unref (combostore);
+
+    /* Make the things actually appear. */
+    gtk_widget_show_all (GTK_WIDGET(treeview));
+}
+
+/* Update the preview page based on the current state of the importer.
+ * Should be called when settings are changed.
+ */
+void
+CsvImpPriceAssist::preview_refresh ()
+{
+    // Set start row
+    auto adj = gtk_spin_button_get_adjustment (start_row_spin);
+    gtk_adjustment_set_upper (adj, price_imp->m_parsed_lines.size());
+    gtk_spin_button_set_value (start_row_spin,
+            price_imp->skip_start_lines());
+
+    // Set end row
+    adj = gtk_spin_button_get_adjustment (end_row_spin);
+    gtk_adjustment_set_upper (adj, price_imp->m_parsed_lines.size());
+    gtk_spin_button_set_value (end_row_spin,
+            price_imp->skip_end_lines());
+
+    // Set Alternate rows
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(skip_alt_rows_button),
+            price_imp->skip_alt_lines());
+
+    // Set over-write indicator
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(over_write_cbutton),
+            price_imp->over_write());
+
+    // Set Import Format
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(csv_button),
+            (price_imp->file_format() == GncImpFileFormat::CSV));
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(fixed_button),
+            (price_imp->file_format() != GncImpFileFormat::CSV));
+
+    // This section deals with the combo's and character encoding
+    gtk_combo_box_set_active (GTK_COMBO_BOX(date_format_combo),
+            price_imp->date_format());
+    gtk_combo_box_set_active (GTK_COMBO_BOX(currency_format_combo),
+            price_imp->currency_format());
+    go_charmap_sel_set_encoding (encselector, price_imp->encoding().c_str());
+
+    // Handle separator checkboxes and custom field, only relevant if the file format is csv
+    if (price_imp->file_format() == GncImpFileFormat::CSV)
+    {
+        auto separators = price_imp->separators();
+        const auto stock_sep_chars = std::string (" \t,:;-");
+        for (int i = 0; i < SEP_NUM_OF_TYPES; i++)
+            gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(sep_button[i]),
+                separators.find (stock_sep_chars[i]) != std::string::npos);
+
+        // If there are any other separators in the separators string,
+        // add them as custom separators
+        auto pos = separators.find_first_of (stock_sep_chars);
+        while (!separators.empty() && pos != std::string::npos)
+        {
+            separators.erase(pos);
+            pos = separators.find_first_of (stock_sep_chars);
+        }
+        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(custom_cbutton),
+                !separators.empty());
+        gtk_entry_set_text (GTK_ENTRY(custom_entry), separators.c_str());
+    }
+    // Repopulate the parsed data table
+    g_idle_add ((GSourceFunc)csv_imp_preview_queue_rebuild_table, this);
+}
+
+/* Check if all selected data can be parsed sufficiently to continue
+ */
+void CsvImpPriceAssist::preview_validate_settings ()
+{
+    /* Allow the user to proceed only if there are no inconsistencies in the settings */
+    auto error_msg = price_imp->verify();
+    gtk_assistant_set_page_complete (csv_imp_asst, preview_page, error_msg.empty());
+    gtk_label_set_markup(GTK_LABEL(instructions_label), error_msg.c_str());
+    gtk_widget_set_visible (GTK_WIDGET(instructions_image), !error_msg.empty());
+}
+
+/*******************************************************
+ * Assistant page prepare functions
+ *******************************************************/
+
+void
+CsvImpPriceAssist::assist_file_page_prepare ()
+{
+    /* Set the default directory */
+    auto starting_dir = gnc_get_default_directory (GNC_PREFS_GROUP);
+    if (starting_dir)
+    {
+        gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(file_chooser), starting_dir);
+        g_free (starting_dir);
+    }
+}
+
+void
+CsvImpPriceAssist::assist_preview_page_prepare ()
+{
+    /* Disable the Forward Assistant Button */
+    gtk_assistant_set_page_complete (csv_imp_asst, preview_page, false);
+
+    /* Load the data into the treeview. */
+    preview_refresh_table ();
+}
+
+void
+CsvImpPriceAssist::assist_confirm_page_prepare ()
+{
+}
+
+void
+CsvImpPriceAssist::assist_summary_page_prepare ()
+{
+    auto text = std::string("<span size=\"medium\"><b>");
+    text += _("The prices were imported from the file '") + m_file_name + "'.";
+    text += _("\n\nThe number of Prices added was ") + std::to_string(price_imp->m_prices_added);
+    text += _(" and ") + std::to_string(price_imp->m_prices_duplicated);
+    text += _(" were duplicated.");
+    text += "</b></span>";
+
+    gtk_label_set_markup (GTK_LABEL(summary_label), text.c_str());
+}
+
+void
+CsvImpPriceAssist::assist_prepare_cb (GtkWidget *page)
+{
+    if (page == file_page)
+        assist_file_page_prepare ();
+    else if (page == preview_page)
+        assist_preview_page_prepare ();
+    else if (page == confirm_page)
+        assist_confirm_page_prepare ();
+    else if (page == summary_page)
+        assist_summary_page_prepare ();
+}
+
+void
+CsvImpPriceAssist::assist_finish (bool canceled)
+{
+    /* Start the import */
+//FIXME Apply button
+g_print("Finish\n");
+//    if (canceled || price_imp->m_transactions.empty())
+//        gnc_gen_trans_list_delete (gnc_csv_importer_gui);
+//    else
+//        gnc_gen_trans_assist_start (gnc_csv_importer_gui);
+
+
+//FIXME Cancel comes here to, check when nothing set, goes to catch below also
+
+    /* Create prices from the parsed data */
+    try
+    {
+        price_imp->create_prices ();
+    }
+    catch (const std::invalid_argument& err)
+    {
+        /* Oops! This shouldn't happen when using the import assistant !
+         * Inform the user and go back to the preview page.
+         */
+        gnc_error_dialog (GTK_WIDGET(csv_imp_asst),
+            _("An unexpected error has occurred while creating prices. Please report this as a bug.\n\n"
+              "Error message:\n%s"), err.what());
+        gtk_assistant_set_current_page (csv_imp_asst, 2);
+    }
+}
+
+void
+CsvImpPriceAssist::assist_compmgr_close ()
+{
+    gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(csv_imp_asst));
+    gtk_widget_destroy (GTK_WIDGET(csv_imp_asst));
+}
+
+static void
+csv_price_imp_close_handler (gpointer user_data)
+{
+    auto info = (CsvImpPriceAssist*)user_data;
+    info->assist_compmgr_close();
+}
+
+/********************************************************************\
+ * gnc_file_csv_price_import                                        *
+ * opens up a assistant to import prices.                           *
+ *                                                                  *
+ * Args:   none                                                     *
+ * Return: nothing                                                  *
+\********************************************************************/
+void
+gnc_file_csv_price_import(void)
+{
+    auto info = new CsvImpPriceAssist;
+    gnc_register_gui_component (ASSISTANT_CSV_IMPORT_PRICE_CM_CLASS,
+                                nullptr, csv_price_imp_close_handler,
+                                info);
+}
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.glade b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
new file mode 100644
index 0000000..705e827
--- /dev/null
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.glade
@@ -0,0 +1,1001 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.24"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkAdjustment" id="end_row_adj">
+    <property name="upper">1000</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="start_row_adj">
+    <property name="upper">1000</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAssistant" id="CSV Price Assistant">
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="title" translatable="yes">CSV Price Import</property>
+    <property name="default_width">400</property>
+    <property name="default_height">500</property>
+    <signal name="close" handler="csv_price_imp_assist_close_cb" swapped="no"/>
+    <signal name="destroy" handler="csv_price_imp_assist_destroy_cb" swapped="no"/>
+    <signal name="apply" handler="csv_price_imp_assist_finish_cb" swapped="no"/>
+    <signal name="prepare" handler="csv_price_imp_assist_prepare_cb" swapped="no"/>
+    <signal name="cancel" handler="csv_price_imp_assist_cancel_cb" 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 Prices from a CSV file.
+
+There is a minimum number of columns that have to be present for a successful import, for Stock prices these are Date, Amount, Symbol From and for Currency they are Date, Amount, Currency From and Currency To.
+
+Various options exist for specifying the delimiter 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.
+
+Examples are "RR.L","21/11/2016",5.345,"GBP" and "USD","2016-11-21",1.56,"GBP"
+
+There is an option for specifying the start row, end row and an option to skip alternate rows beginning from the start row which can be used if you have some header text. Also there is an option to over write existing prices for that day if required.
+
+On the preview page you can Load and Save the settings. To save the settings, select a previously saved entry or replace the text and press the Save Settings button.
+
+This operation is not reversable, so make sure you have a working backup.
+
+Click on 'Forward' to proceed or 'Cancel' to Abort Import.</property>
+        <property name="wrap">True</property>
+      </object>
+      <packing>
+        <property name="page_type">intro</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">
+Select location and file name for the Import, then click 'OK'...
+</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="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="GtkTable" id="table1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="n_rows">2</property>
+            <property name="n_columns">2</property>
+            <property name="column_spacing">5</property>
+            <property name="row_spacing">5</property>
+            <child>
+              <object class="GtkFrame" id="frame6">
+                <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="GtkAlignment" id="alignment4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="bottom_padding">5</property>
+                    <property name="left_padding">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <object class="GtkHBox" id="combo_hbox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkButton" id="delete_settings">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Delete Settings</property>
+                            <signal name="clicked" handler="csv_price_imp_preview_del_settings_cb" swapped="no"/>
+                            <child>
+                              <object class="GtkImage" id="image2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="stock">gtk-delete</property>
+                              </object>
+                            </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="GtkButton" id="save_settings">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <property name="tooltip_text" translatable="yes">Save Settings</property>
+                            <signal name="clicked" handler="csv_price_imp_preview_save_settings_cb" swapped="no"/>
+                            <child>
+                              <object class="GtkImage" id="image1">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="stock">gtk-save</property>
+                              </object>
+                            </child>
+                          </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>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label12">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes"> <b>Load and Save Settings</b></property>
+                    <property name="use_markup">True</property>
+                    <property name="track_visited_links">False</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options">GTK_FILL</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="frame10">
+                <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="alignment6">
+                    <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">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <object class="GtkVBox" id="vbox1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <child>
+                          <object class="GtkTable" id="table4">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="n_rows">2</property>
+                            <property name="n_columns">2</property>
+                            <child>
+                              <object class="GtkRadioButton" id="csv_button">
+                                <property name="label" translatable="yes">Separators</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="active">True</property>
+                                <property name="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_fixed_sel_cb" swapped="no"/>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkRadioButton" id="fixed_button">
+                                <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="draw_indicator">True</property>
+                                <property name="group">csv_button</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkHSeparator" id="hseparator1">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                              </object>
+                              <packing>
+                                <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>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkTable" id="separator_table">
+                            <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>
+                            <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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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="active">True</property>
+                                <property name="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_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>
+                                <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="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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">●</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>
+                                <signal name="changed" handler="csv_price_imp_preview_sep_button_cb" swapped="no"/>
+                              </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>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkHBox" id="fw_instructions_hbox">
+                            <property name="can_focus">False</property>
+                            <property name="no_show_all">True</property>
+                            <child>
+                              <object class="GtkImage" id="instructions_image1">
+                                <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="yalign">0</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="GtkTable" id="table2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="n_rows">2</property>
+                                <property name="n_columns">2</property>
+                                <child>
+                                  <object class="GtkLabel" id="label2">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="yalign">0</property>
+                                    <property name="xpad">5</property>
+                                    <property name="label" translatable="yes">•</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="wrap">True</property>
+                                  </object>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="label3">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">Double-click anywhere on the table below to insert a column break</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="wrap">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="left_attach">1</property>
+                                    <property name="right_attach">2</property>
+                                    <property name="y_options"/>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="label4">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="yalign">0</property>
+                                    <property name="xpad">5</property>
+                                    <property name="label" translatable="yes">•</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="wrap">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="top_attach">1</property>
+                                    <property name="bottom_attach">2</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel" id="label5">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">Right-click anywhere in a column to modify it (widen, narrow, merge)</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="wrap">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="y_options"/>
+                                  </packing>
+                                </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">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkTable" id="table5">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="n_rows">2</property>
+                            <child>
+                              <object class="GtkHSeparator" id="hseparator4">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="y_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkCheckButton" id="over_write_button">
+                                <property name="label" translatable="yes">Allow existing prices to be over written.</property>
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">False</property>
+                                <property name="tooltip_text" translatable="yes">Normally prices are not over written, select this to change that.</property>
+                                <property name="draw_indicator">True</property>
+                                <signal name="toggled" handler="csv_price_imp_preview_overwrite_cb" swapped="no"/>
+                              </object>
+                              <packing>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">3</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label19">
+                    <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"><b>File Format</b></property>
+                    <property name="use_markup">True</property>
+                  </object>
+                </child>
+              </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="GtkFrame" id="frame8">
+                <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="alignment8">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="left_padding">5</property>
+                    <property name="right_padding">5</property>
+                    <child>
+                      <object class="GtkVBox" id="vbox6">
+                        <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="GtkTable" id="table3">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="n_rows">6</property>
+                            <property name="n_columns">2</property>
+                            <property name="column_spacing">5</property>
+                            <property name="row_spacing">5</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="xalign">0</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>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label20">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Date Format</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
+                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkAlignment" id="currency_format_container">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                              </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="x_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label21">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Currency Format</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">2</property>
+                                <property name="bottom_attach">3</property>
+                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label16">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Encoding</property>
+                              </object>
+                              <packing>
+                                <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkAlignment" id="encoding_container">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="x_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label17">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Leading Lines to Skip</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">4</property>
+                                <property name="bottom_attach">5</property>
+                                <property name="x_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="label18">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Trailing Lines to Skip</property>
+                              </object>
+                              <packing>
+                                <property name="top_attach">5</property>
+                                <property name="bottom_attach">6</property>
+                                <property name="x_options">GTK_FILL</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkHBox" id="hbox2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkSpinButton" id="start_row">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">●</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>
+                                    <property name="numeric">True</property>
+                                    <signal name="value-changed" handler="csv_price_imp_preview_srow_cb" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">4</property>
+                                <property name="bottom_attach">5</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkHBox" id="hbox3">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkSpinButton" id="end_row">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">●</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>
+                                    <property name="numeric">True</property>
+                                    <signal name="value-changed" handler="csv_price_imp_preview_erow_cb" swapped="no"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">5</property>
+                                <property name="bottom_attach">6</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkHSeparator" id="hseparator2">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">3</property>
+                                <property name="bottom_attach">4</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" id="skip_rows">
+                            <property name="label" translatable="yes">Skip alternate lines</property>
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">False</property>
+                            <property name="tooltip_text" translatable="yes">Starting from the first line that is actually imported every second line will be skipped. This option will take the leading lines to skip into account as well.
+For example
+* if 'Leading Lines to Skip' is set to 3, the first line to import will be line 4. Lines 5, 7, 9,... will be skipped.
+* if 'Leading Lines to Skip' is set to 4, the first line to import will be line 5. Lines 6, 8, 10,... will be skipped.</property>
+                            <property name="draw_indicator">True</property>
+                            <signal name="toggled" handler="csv_price_imp_preview_skiprows_cb" swapped="no"/>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label13">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes"><b>Miscellaneous</b></property>
+                    <property name="use_markup">True</property>
+                  </object>
+                </child>
+              </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>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow2">
+            <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="viewport2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkVBox" id="vbox8">
+                    <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">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox13">
+            <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="yalign">0</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 to import.</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="padding">5</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox14">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkCheckButton" id="skip_errors_button">
+                <property name="label" translatable="yes">Skip Errors</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="xalign">1</property>
+                <property name="image_position">right</property>
+                <property name="draw_indicator">True</property>
+                <signal name="toggled" handler="csv_price_imp_preview_skiperrors_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>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">intro</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkVBox" id="confirm_page">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="border_width">12</property>
+        <child>
+          <object class="GtkAlignment" id="alignment2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkLabel" id="finish_label">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes">Press Apply to add Prices.
+Cancel to abort.</property>
+                <property name="justify">center</property>
+                <property name="wrap">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page_type">confirm</property>
+        <property name="title" translatable="yes">Import Prices 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>
+            <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">summary</property>
+        <property name="title" translatable="yes">Import Summary</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/gnucash/import-export/csv-imp/assistant-csv-price-import.h b/gnucash/import-export/csv-imp/assistant-csv-price-import.h
new file mode 100644
index 0000000..213b622
--- /dev/null
+++ b/gnucash/import-export/csv-imp/assistant-csv-price-import.h
@@ -0,0 +1,36 @@
+/*******************************************************************\
+ * assistant-csv-price-import.h -- An assistant for importing       *
+ *                                     Prices from a file.          *
+ *                                                                  *
+ * Copyright (C) 2017 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-price-import.h
+    @brief CSV Import Assistant
+    @author Copyright (c) 2017 Robert Fewell
+*/
+#ifndef GNC_ASSISTANT_CSV_IMPORT_PRICE_H
+#define GNC_ASSISTANT_CSV_IMPORT_PRICE_H
+
+
+/** The gnc_file_csv_price_import() will let the user import the
+ *  commodity prices from a file.
+ */
+void gnc_file_csv_price_import (void);
+#endif
diff --git a/gnucash/import-export/csv-imp/gnc-plugin-csv-import-ui.xml b/gnucash/import-export/csv-imp/gnc-plugin-csv-import-ui.xml
index c119a64..bdd3043 100644
--- a/gnucash/import-export/csv-imp/gnc-plugin-csv-import-ui.xml
+++ b/gnucash/import-export/csv-imp/gnc-plugin-csv-import-ui.xml
@@ -5,6 +5,7 @@
       	<placeholder name="FileImportPlaceholder">
       	   <menuitem name="FileCsvImportAccounts" action="CsvImportAccountAction"/>
       	   <menuitem name="FileCsvImportTrans" action="CsvImportTransAction"/>
+           <menuitem name="FileCsvImportPrice" action="CsvImportPriceAction"/>
       	</placeholder>
       </menu>
     </menu>
diff --git a/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c b/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
index 25954be..c14092d 100644
--- a/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
+++ b/gnucash/import-export/csv-imp/gnc-plugin-csv-import.c
@@ -30,6 +30,7 @@
 
 #include "assistant-csv-account-import.h"
 #include "assistant-csv-trans-import.h"
+#include "assistant-csv-price-import.h"
 
 static void gnc_plugin_csv_import_class_init (GncPluginCsvImportClass *klass);
 static void gnc_plugin_csv_import_init (GncPluginCsvImport *plugin);
@@ -38,6 +39,7 @@ 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_price_cmd (GtkAction *action, GncMainWindowActionData *data);
 
 #define PLUGIN_ACTIONS_NAME "gnc-plugin-csv-import-actions"
 #define PLUGIN_UI_FILENAME  "gnc-plugin-csv-import-ui.xml"
@@ -54,6 +56,11 @@ static GtkActionEntry gnc_plugin_actions [] =
         N_("Import Transactions from a CSV file"),
         G_CALLBACK (gnc_plugin_csv_import_trans_cmd)
     },
+    {
+        "CsvImportPriceAction", GTK_STOCK_CONVERT, N_("Import _Prices from a CSV file..."), NULL,
+        N_("Import Prices from a CSV file"),
+        G_CALLBACK (gnc_plugin_csv_import_price_cmd)
+    },
 };
 static guint gnc_plugin_n_actions = G_N_ELEMENTS (gnc_plugin_actions);
 
@@ -157,6 +164,13 @@ gnc_plugin_csv_import_trans_cmd (GtkAction *action,
     gnc_file_csv_trans_import ();
 }
 
+static void
+gnc_plugin_csv_import_price_cmd (GtkAction *action,
+                                 GncMainWindowActionData *data)
+{
+    gnc_file_csv_price_import ();
+}
+
 /************************************************************
  *                    Plugin Bootstrapping                   *
  ************************************************************/

commit 4fe77a577ae429c0407868a62805bd4095c87ca8
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 10:55:29 2017 +0000

    Rename function gnc_csv_price_col_type_strs to gnc_price_col_type_strs

diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
index 1fdcaa53..a39f178 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.cpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -44,7 +44,7 @@ extern "C" {
 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
 
 /* This map contains a set of strings representing the different column types. */
-std::map<GncPricePropType, const char*> gnc_csv_price_col_type_strs = {
+std::map<GncPricePropType, const char*> gnc_price_col_type_strs = {
         { GncPricePropType::NONE, N_("None") },
         { GncPricePropType::DATE, N_("Date") },
         { GncPricePropType::AMOUNT, N_("Amount") },
@@ -341,7 +341,7 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
     }
     catch (const std::invalid_argument& e)
     {
-        auto err_str = std::string(_(gnc_csv_price_col_type_strs[prop_type])) +
+        auto err_str = std::string(_(gnc_price_col_type_strs[prop_type])) +
                        std::string(_(" could not be understood.\n")) +
                        e.what();
         m_errors.emplace(prop_type, err_str);
@@ -349,7 +349,7 @@ void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
     }
     catch (const std::out_of_range& e)
     {
-        auto err_str = std::string(_(gnc_csv_price_col_type_strs[prop_type])) +
+        auto err_str = std::string(_(gnc_price_col_type_strs[prop_type])) +
                        std::string(_(" could not be understood.\n")) +
                        e.what();
         m_errors.emplace(prop_type, err_str);
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index d101280..57083e9 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -56,10 +56,10 @@ enum class GncPricePropType {
 };
 
 /** Maps all column types to a string representation.
- *  The actual definition is in gnc-csv-imp-prices.cpp.
+ *  The actual definition is in gnc-price-props.cpp.
  *  Attention: that definition should be adjusted for any
  *  changes to enum class GncPricePropType ! */
-extern std::map<GncPricePropType, const char*> gnc_csv_price_col_type_strs;
+extern std::map<GncPricePropType, const char*> gnc_price_col_type_strs;
 
 /** Functor to check if the above map has an element of which
  *  the value equals name. To be used with std::find_if.

commit eb712dc7d88dc16a5c751a8fea988b35dd20da47
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 10:53:41 2017 +0000

    Add price import files for the csv price importer
    
    These files are largely based on the csv transaction importer and with
    minimum of changes to settings files.

diff --git a/gnucash/import-export/csv-imp/CMakeLists.txt b/gnucash/import-export/csv-imp/CMakeLists.txt
index e2fa97f..0bc7d29 100644
--- a/gnucash/import-export/csv-imp/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/CMakeLists.txt
@@ -19,6 +19,7 @@ SET(csv_import_SOURCES
   gnc-csv-trans-settings.cpp
   gnc-dummy-tokenizer.cpp
   gnc-fw-tokenizer.cpp
+  gnc-price-import.cpp
   gnc-price-props.cpp
   gnc-tokenizer.cpp
   gnc-trans-props.cpp
@@ -45,6 +46,7 @@ SET(csv_import_noinst_HEADERS
   gnc-csv-trans-settings.hpp
   gnc-dummy-tokenizer.hpp
   gnc-fw-tokenizer.hpp
+  gnc-price-import.hpp
   gnc-price-props.hpp
   gnc-tokenizer.hpp
   gnc-trans-props.hpp
diff --git a/gnucash/import-export/csv-imp/Makefile.am b/gnucash/import-export/csv-imp/Makefile.am
index 8b13d01..4083963 100644
--- a/gnucash/import-export/csv-imp/Makefile.am
+++ b/gnucash/import-export/csv-imp/Makefile.am
@@ -13,6 +13,7 @@ libgncmod_csv_import_la_SOURCES = \
   gnc-csv-gnumeric-popup.c \
   gnc-dummy-tokenizer.cpp \
   gnc-fw-tokenizer.cpp \
+  gnc-price-import.cpp \
   gnc-price-props.cpp \
   gnc-tokenizer.cpp \
   gnc-tx-import.cpp \
@@ -29,6 +30,7 @@ noinst_HEADERS = \
   gnc-csv-gnumeric-popup.h \
   gnc-dummy-tokenizer.hpp \
   gnc-fw-tokenizer.hpp \
+  gnc-price-import.hpp \
   gnc-price-props.hpp \
   gnc-tokenizer.hpp \
   gnc-tx-import.hpp \
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
index 6611875..48cfdce 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.cpp
@@ -108,6 +108,14 @@ static std::shared_ptr<CsvTransSettings> create_int_gnc_exp_preset(void)
             GncTransPropType::PRICE
     };
 
+    preset->m_column_types_price = {
+            GncPricePropType::DATE,
+            GncPricePropType::AMOUNT,
+            GncPricePropType::CURRENCY_FROM,
+            GncPricePropType::CURRENCY_TO,
+            GncPricePropType::SYMBOL_FROM
+    };
+
     return preset;
 }
 
diff --git a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
index 379c660..93275f2 100644
--- a/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
+++ b/gnucash/import-export/csv-imp/gnc-csv-trans-settings.hpp
@@ -36,6 +36,7 @@ extern "C" {
 #include <string>
 #include <vector>
 #include "gnc-trans-props.hpp"
+#include "gnc-price-props.hpp"
 #include "gnc-tokenizer.hpp"
 
 /** Enumeration for separator checkbutton types. These are the
@@ -93,7 +94,8 @@ std::string   m_separators;                   // Separators for csv format
 
 Account      *m_base_account;                 // Base account
 std::vector<GncTransPropType> m_column_types; // The Column types in order
-std::vector<uint32_t> m_column_widths;            // The Column widths
+std::vector<GncPricePropType> m_column_types_price; // The Column Price types in order
+std::vector<uint32_t> m_column_widths;        // The Column widths
 
 bool          m_load_error;                   // Was there an error while parsing the state file ?
 };
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.cpp b/gnucash/import-export/csv-imp/gnc-price-import.cpp
new file mode 100644
index 0000000..09deb93
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-price-import.cpp
@@ -0,0 +1,654 @@
+/********************************************************************\
+ * gnc-price-import.cpp - import prices from csv files              *
+ *                                                                  *
+ * 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 <guid.hpp>
+
+extern "C" {
+#include <platform.h>
+#if PLATFORM(WINDOWS)
+#include <windows.h>
+#endif
+
+#include <glib/gi18n.h>
+
+#include "gnc-ui-util.h" //get book
+#include "gnc-commodity.h"
+#include "gnc-pricedb.h"
+}
+
+#include <boost/regex.hpp>
+#include <boost/regex/icu.hpp>
+
+#include "gnc-price-import.hpp"
+#include "gnc-price-props.hpp"
+#include "gnc-csv-tokenizer.hpp"
+#include "gnc-fw-tokenizer.hpp"
+#include "gnc-csv-trans-settings.hpp"
+
+G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
+
+const int num_date_formats_price = 5;
+const gchar* date_format_user_price[] = {N_("y-m-d"),
+                                   N_("d-m-y"),
+                                   N_("m-d-y"),
+                                   N_("d-m"),
+                                   N_("m-d")
+                                  };
+
+const int num_currency_formats_price = 3;
+const gchar* currency_format_user_price[] = {N_("Locale"),
+                                       N_("Period: 123,456.78"),
+                                       N_("Comma: 123.456,78")
+                                      };
+
+
+/** Constructor for GncPriceImport.
+ * @return Pointer to a new GncCSvParseData
+ */
+GncPriceImport::GncPriceImport(GncImpFileFormat format)
+{
+    /* 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. */
+    m_skip_errors = false;
+    file_format(m_settings.m_file_format = format);
+}
+
+/** Destructor for GncPriceImport.
+ */
+GncPriceImport::~GncPriceImport()
+{
+}
+
+/** Sets the file format for the file to import, which
+ *  may cause the file to be reloaded as well if the
+ *  previously set file format was different and a
+ *  filename was already set.
+ *  @param format the new format to set
+ *  @exception std::ifstream::failure if file reloading fails
+ */
+void GncPriceImport::file_format(GncImpFileFormat format)
+{
+    if (m_tokenizer && m_settings.m_file_format == format)
+        return;
+
+    auto new_encoding = std::string("UTF-8");
+    auto new_imp_file = std::string();
+
+    // Recover common settings from old tokenizer
+    if (m_tokenizer)
+    {
+        new_encoding = m_tokenizer->encoding();
+        new_imp_file = m_tokenizer->current_file();
+        if (file_format() == GncImpFileFormat::FIXED_WIDTH)
+        {
+            auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
+            if (!fwtok->get_columns().empty())
+                m_settings.m_column_widths = fwtok->get_columns();
+        }
+    }
+
+    m_settings.m_file_format = format;
+    m_tokenizer = gnc_tokenizer_factory(m_settings.m_file_format);
+
+    // Set up new tokenizer with common settings
+    // recovered from old tokenizer
+    m_tokenizer->encoding(new_encoding);
+    load_file(new_imp_file);
+
+    // Restore potentially previously set separators or column_widths
+    if ((file_format() == GncImpFileFormat::CSV)
+        && !m_settings.m_separators.empty())
+        separators (m_settings.m_separators);
+    else if ((file_format() == GncImpFileFormat::FIXED_WIDTH)
+        && !m_settings.m_column_widths.empty())
+    {
+        auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
+        fwtok->columns (m_settings.m_column_widths);
+    }
+
+}
+
+GncImpFileFormat GncPriceImport::file_format()
+{
+    return m_settings.m_file_format;
+}
+
+void GncPriceImport::over_write (bool over)
+{
+    m_over_write = over;
+}
+
+bool GncPriceImport::over_write () { return m_over_write; }
+
+void GncPriceImport::reset_formatted_column (std::vector<GncPricePropType>& col_types)
+{
+    for (auto col_type: col_types)
+    {
+        auto col = std::find (m_settings.m_column_types_price.begin(),
+                m_settings.m_column_types_price.end(), col_type);
+        if (col != m_settings.m_column_types_price.end())
+            set_column_type_price (col - m_settings.m_column_types_price.begin(), col_type, true);
+    }
+}
+
+void GncPriceImport::currency_format (int currency_format)
+{
+    m_settings.m_currency_format = currency_format;
+
+    /* Reparse all currency related columns */
+    std::vector<GncPricePropType> commodities = { GncPricePropType::AMOUNT };
+    reset_formatted_column (commodities);
+}
+int GncPriceImport::currency_format () { return m_settings.m_currency_format; }
+
+void GncPriceImport::date_format (int date_format)
+{
+    m_settings.m_date_format = date_format;
+
+    /* Reparse all date related columns */
+    std::vector<GncPricePropType> dates = { GncPricePropType::DATE };
+    reset_formatted_column (dates);
+}
+int GncPriceImport::date_format () { return m_settings.m_date_format; }
+
+/** Converts raw file data using a new encoding. This function must be
+ * called after load_file only if load_file guessed
+ * the wrong encoding.
+ * @param encoding Encoding that data should be translated using
+ */
+void GncPriceImport::encoding (const std::string& encoding)
+{
+
+    // TODO investigate if we can catch conversion errors and report them
+    if (m_tokenizer)
+    {
+        m_tokenizer->encoding(encoding); // May throw
+        try
+        {
+            tokenize(false);
+        }
+        catch (...)
+        { };
+    }
+
+    m_settings.m_encoding = encoding;
+}
+
+std::string GncPriceImport::encoding () { return m_settings.m_encoding; }
+
+void GncPriceImport::update_skipped_lines(boost::optional<uint32_t> start, boost::optional<uint32_t> end,
+        boost::optional<bool> alt, boost::optional<bool> errors)
+{
+    if (start)
+        m_settings.m_skip_start_lines = *start;
+    if (end)
+        m_settings.m_skip_end_lines = *end;
+    if (alt)
+        m_settings.m_skip_alt_lines = *alt;
+    if (errors)
+        m_skip_errors = *errors;
+
+    for (uint32_t i = 0; i < m_parsed_lines.size(); i++)
+    {
+        std::get<3>(m_parsed_lines[i]) =
+            ((i < skip_start_lines()) ||             // start rows to skip
+             (i >= m_parsed_lines.size() - skip_end_lines()) ||          // end rows to skip
+             (((i - skip_start_lines()) % 2 == 1) && // skip every second row...
+                  skip_alt_lines()) ||                   // ...if requested
+             (m_skip_errors && !std::get<1>(m_parsed_lines[i]).empty())); // skip lines with errors
+    }
+}
+
+uint32_t GncPriceImport::skip_start_lines () { return m_settings.m_skip_start_lines; }
+uint32_t GncPriceImport::skip_end_lines () { return m_settings.m_skip_end_lines; }
+bool GncPriceImport::skip_alt_lines () { return m_settings.m_skip_alt_lines; }
+bool GncPriceImport::skip_err_lines () { return m_skip_errors; }
+
+void GncPriceImport::separators (std::string separators)
+{
+    if (file_format() != GncImpFileFormat::CSV)
+        return;
+
+    m_settings.m_separators = separators;
+    auto csvtok = dynamic_cast<GncCsvTokenizer*>(m_tokenizer.get());
+    csvtok->set_separators (separators);
+
+}
+std::string GncPriceImport::separators () { return m_settings.m_separators; }
+
+void GncPriceImport::settings (const CsvTransSettings& settings)
+{
+    /* First apply file format as this may recreate the tokenizer */
+    file_format (settings.m_file_format);
+    /* Only then apply the other settings */
+    m_settings = settings;
+    encoding (m_settings.m_encoding);
+
+    if (file_format() == GncImpFileFormat::CSV)
+        separators (m_settings.m_separators);
+    else if (file_format() == GncImpFileFormat::FIXED_WIDTH)
+    {
+        auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
+        fwtok->columns (m_settings.m_column_widths);
+    }
+    try
+    {
+        tokenize(false);
+    }
+    catch (...)
+    { };
+
+    /* Tokenizing will clear column types, reset them here
+     * based on the loaded settings.
+     */
+    std::copy_n (settings.m_column_types_price.begin(),
+            std::min (m_settings.m_column_types_price.size(), settings.m_column_types_price.size()),
+            m_settings.m_column_types_price.begin());
+
+}
+
+bool GncPriceImport::save_settings ()
+{
+
+    if (trans_preset_is_reserved_name (m_settings.m_name))
+        return true;
+
+    /* separators are already copied to m_settings in the separators
+     * function above. However this is not the case for the column
+     * widths in fw mode, so do this now.
+     */
+    if (file_format() == GncImpFileFormat::FIXED_WIDTH)
+    {
+        auto fwtok = dynamic_cast<GncFwTokenizer*>(m_tokenizer.get());
+        m_settings.m_column_widths = fwtok->get_columns();
+    }
+
+    return m_settings.save();
+}
+
+void GncPriceImport::settings_name (std::string name) { m_settings.m_name = name; }
+std::string GncPriceImport::settings_name () { return m_settings.m_name; }
+
+/** Loads a file into a GncPriceImport. This is the first function
+ * that must be called after creating a new GncPriceImport. As long as
+ * this function didn't run successfully, the importer can't proceed.
+ * @param filename Name of the file that should be opened
+ * @exception may throw std::ifstream::failure on any io error
+ */
+void GncPriceImport::load_file (const std::string& filename)
+{
+
+    /* Get the raw data first and handle an error if one occurs. */
+    try
+    {
+        m_tokenizer->load_file (filename);
+        return;
+    }
+    catch (std::ifstream::failure& ios_err)
+    {
+        // Just log the error and pass it on the call stack for proper handling
+        PWARN ("Error: %s", ios_err.what());
+        throw;
+    }
+}
+
+/** Splits a file into cells. This requires having an encoding that
+ * works (see GncPriceImport::convert_encoding). Tokenizing related options
+ * should be set to the user's selections before calling this
+ * function.
+ * Notes: - this function must be called with guessColTypes set to true once
+ *          before calling it with guessColTypes set to false.
+ *        - if guessColTypes is true, all the column types will be set
+ *          GncPricePropType::NONE right now as real guessing isn't implemented yet
+ * @param guessColTypes true to guess what the types of columns are based on the cell contents
+ * @exception std::range_error if tokenizing failed
+ */
+void GncPriceImport::tokenize (bool guessColTypes)
+{
+    if (!m_tokenizer)
+        return;
+
+    uint32_t max_cols = 0;
+    m_tokenizer->tokenize();
+    m_parsed_lines.clear();
+    for (auto tokenized_line : m_tokenizer->get_tokens())
+    {
+        m_parsed_lines.push_back (std::make_tuple (tokenized_line, std::string(),
+                std::make_shared<GncImportPrice>(date_format(), currency_format()),
+                false));
+        auto length = tokenized_line.size();
+        if (length > max_cols)
+            max_cols = length;
+    }
+
+    /* If it failed, generate an error. */
+    if (m_parsed_lines.size() == 0)
+    {
+        throw (std::range_error ("Tokenizing failed."));
+        return;
+    }
+
+    m_settings.m_column_types_price.resize(max_cols, GncPricePropType::NONE);
+
+    /* Force reinterpretation of already set columns and/or base_account */
+    for (uint32_t i = 0; i < m_settings.m_column_types_price.size(); i++)
+        set_column_type_price (i, m_settings.m_column_types_price[i], true);
+
+    if (guessColTypes)
+    {
+        /* Guess column_types based
+         * on the contents of each column. */
+        /* TODO Make it actually guess. */
+    }
+}
+
+
+struct ErrorListPrice
+{
+public:
+    void add_error (std::string msg);
+    std::string str();
+    bool empty() { return m_error.empty(); }
+private:
+    std::string m_error;
+};
+
+void ErrorListPrice::add_error (std::string msg)
+{
+    m_error += "- " + msg + "\n";
+}
+
+std::string ErrorListPrice::str()
+{
+    return m_error.substr(0, m_error.size() - 1);
+}
+
+
+/* Test for the required minimum number of columns selected and
+ * the selection is consistent.
+ * @param An ErrorListPrice object to which all found issues are added.
+ */
+void GncPriceImport::verify_column_selections (ErrorListPrice& error_msg)
+{
+    /* Verify if a date column is selected and it's parsable.
+     */
+    if (!check_for_column_type(GncPricePropType::DATE))
+        error_msg.add_error( _("Please select a date column."));
+
+    /* Verify an amount column is selected.
+     */
+    if (!check_for_column_type(GncPricePropType::AMOUNT))
+        error_msg.add_error( _("Please select an amount column."));
+
+    /* Verify an Currency to column is selected.
+     */
+    if (!check_for_column_type(GncPricePropType::CURRENCY_TO))
+        error_msg.add_error( _("Please select a Currency to column."));
+
+    /* Verify at least one from column (symbol_from or currency_from) column is selected.
+     */
+    if (!check_for_column_type(GncPricePropType::SYMBOL_FROM) &&
+        !check_for_column_type(GncPricePropType::CURRENCY_FROM))
+        error_msg.add_error( _("Please select a symbol or currency from column."));
+}
+
+
+/* Check whether the chosen settings can successfully parse
+ * the import data. This will check:
+ * - there's at least one line selected for import
+ * - the minimum number of columns is selected
+ * - the values in the selected columns can be parsed meaningfully.
+ * @return An empty string if all checks passed or the reason
+ *         verification failed otherwise.
+ */
+std::string GncPriceImport::verify ()
+{
+    auto newline = std::string();
+    auto error_msg = ErrorListPrice();
+
+    /* Check if the import file did actually contain any information */
+    if (m_parsed_lines.size() == 0)
+    {
+        error_msg.add_error(_("No valid data found in the selected file. It may be empty or the selected encoding is wrong."));
+        return error_msg.str();
+    }
+
+    /* Check if at least one line is selected for importing */
+    auto skip_alt_offset = m_settings.m_skip_alt_lines ? 1 : 0;
+    if (m_settings.m_skip_start_lines + m_settings.m_skip_end_lines + skip_alt_offset >= m_parsed_lines.size())
+    {
+        error_msg.add_error(_("No lines are selected for importing. Please reduce the number of lines to skip."));
+        return error_msg.str();
+    }
+
+    verify_column_selections (error_msg);
+
+    update_skipped_lines (boost::none, boost::none, boost::none, boost::none);
+
+    auto have_line_errors = false;
+    for (auto line : m_parsed_lines)
+    {
+        if (!std::get<3>(line) && !std::get<1>(line).empty())
+        {
+            have_line_errors = true;
+            break;
+        }
+    }
+
+    if (have_line_errors)
+        error_msg.add_error( _("Not all fields could be parsed. Please correct the issues reported for each line or adjust the lines to skip."));
+
+    return error_msg.str();
+}
+
+/** Checks whether the parsed line contains all essential properties.
+ * @param parsed_line The line we are checking
+ * @exception std::invalid_argument in an essential property is missing
+ */
+static void price_properties_verify_essentials (std::vector<parse_line_t>::iterator& parsed_line)
+{
+    std::string error_message;
+    std::shared_ptr<GncImportPrice> price_props;
+    std::tie(std::ignore, error_message, price_props, std::ignore) = *parsed_line;
+
+    auto price_error = price_props->verify_essentials();
+
+    error_message.clear();
+    if (!price_error.empty())
+    {
+        error_message += price_error;
+        error_message += "\n";
+    }
+
+    if (!error_message.empty())
+        throw std::invalid_argument(error_message);
+}
+
+void GncPriceImport::create_price (std::vector<parse_line_t>::iterator& parsed_line)
+{
+    StrVec line;
+    std::string error_message;
+    std::shared_ptr<GncImportPrice> price_props = nullptr;
+    bool skip_line = false;
+    std::tie(line, error_message, price_props, skip_line) = *parsed_line;
+
+    if (skip_line)
+        return;
+
+    error_message.clear();
+
+    /* If column parsing was successful, convert price properties into a price. */
+    try
+    {
+        price_properties_verify_essentials (parsed_line);
+
+        QofBook* book = gnc_get_current_book();
+        GNCPriceDB *pdb = gnc_pricedb_get_db (book);
+
+        /* If all went well, add this price to the list. */
+        auto price_created = price_props->create_price (book, pdb, m_over_write);
+//FIXME Need to look at this
+        if (price_created)
+            m_prices_added++;
+        else
+            m_prices_duplicated++;
+    }
+    catch (const std::invalid_argument& e)
+    {
+        error_message = e.what();
+        PINFO("User warning: %s", error_message.c_str());
+    }
+}
+
+
+/** Creates a list of prices from parsed data. The parsed data
+ * will first be validated. If any errors are found in lines that are marked
+ * for processing (ie not marked to skip) this function will
+ * throw an error.
+ * @param skip_errors true skip over lines with errors
+ * @exception throws std::invalid_argument if data validation or processing fails.
+ */
+void GncPriceImport::create_prices ()
+{
+    /* Start with verifying the current data. */
+    auto verify_result = verify();
+    if (!verify_result.empty())
+        throw std::invalid_argument (verify_result);
+
+    m_prices_added = 0;
+    m_prices_duplicated = 0;
+
+    /* Iterate over all parsed lines */
+    for (auto parsed_lines_it = m_parsed_lines.begin();
+            parsed_lines_it != m_parsed_lines.end();
+            ++parsed_lines_it)
+    {
+        /* Skip current line if the user specified so */
+        if ((std::get<3>(*parsed_lines_it)))
+            continue;
+
+        /* Should not throw anymore, otherwise verify needs revision */
+        create_price (parsed_lines_it);
+    }
+    PINFO("Number of lines is %d, added is %d, duplicates is %d",
+         (int)m_parsed_lines.size(), m_prices_added, m_prices_duplicated);
+}
+
+bool
+GncPriceImport::check_for_column_type (GncPricePropType type)
+{
+    return (std::find (m_settings.m_column_types_price.begin(),
+                       m_settings.m_column_types_price.end(), type)
+                        != m_settings.m_column_types_price.end());
+}
+
+/* A helper function intended to be called only from set_column_type_price */
+void GncPriceImport::update_price_props (uint32_t row, uint32_t col, GncPricePropType prop_type)
+{
+    if (prop_type == GncPricePropType::NONE)
+        return; /* Only deal with price related properties. */
+
+    auto price_props = std::make_shared<GncImportPrice> (*(std::get<2>(m_parsed_lines[row])).get());
+    auto value = std::string();
+
+    if (col < std::get<0>(m_parsed_lines[row]).size())
+        value = std::get<0>(m_parsed_lines[row]).at(col);
+
+    if (value.empty())
+        price_props->reset (prop_type);
+    else
+    {
+        try
+        {
+            price_props->set(prop_type, value);
+        }
+        catch (const std::exception& e)
+        {
+            /* Do nothing, just prevent the exception from escalating up
+             * However log the error if it happens on a row that's not skipped
+             */
+            if (!std::get<3>(m_parsed_lines[row]))
+                PINFO("User warning: %s", e.what());
+        }
+    }
+    /* Store the result */
+    std::get<2>(m_parsed_lines[row]) = price_props;
+}
+
+void
+GncPriceImport::set_column_type_price (uint32_t position, GncPricePropType type, bool force)
+{
+    if (position >= m_settings.m_column_types_price.size())
+        return;
+
+    auto old_type = m_settings.m_column_types_price[position];
+    if ((type == old_type) && !force)
+        return; /* Nothing to do */
+
+    // Column types should be unique, so remove any previous occurrence of the new type
+    std::replace(m_settings.m_column_types_price.begin(), m_settings.m_column_types_price.end(),
+            type, GncPricePropType::NONE);
+
+    m_settings.m_column_types_price.at (position) = type;
+
+    /* Update the preparsed data */
+    for (auto parsed_lines_it = m_parsed_lines.begin();
+            parsed_lines_it != m_parsed_lines.end();
+            ++parsed_lines_it)
+    {
+        /* Reset date and currency formats for each price props object
+         * to ensure column updates use the most recent one
+         */
+        std::get<2>(*parsed_lines_it)->set_date_format (m_settings.m_date_format);
+        std::get<2>(*parsed_lines_it)->set_currency_format (m_settings.m_currency_format);
+
+        uint32_t row = parsed_lines_it - m_parsed_lines.begin();
+
+        /* If the column type actually changed, first reset the property
+         * represented by the old column type
+         */
+        if (old_type != type)
+        {
+            auto old_col = std::get<0>(*parsed_lines_it).size(); // Deliberately out of bounds to trigger a reset!
+            if ((old_type > GncPricePropType::NONE)
+                    && (old_type <= GncPricePropType::PRICE_PROPS))
+                update_price_props (row, old_col, old_type);
+        }
+        /* Then set the property represented by the new column type */
+        if ((type > GncPricePropType::NONE)
+                && (type <= GncPricePropType::PRICE_PROPS))
+            update_price_props (row, position, type);
+
+        /* Report errors if there are any */
+        auto price_errors = std::get<2>(*parsed_lines_it)->errors();
+        std::get<1>(*parsed_lines_it) =
+                price_errors +
+                (price_errors.empty() ? std::string() : "\n");
+    }
+}
+
+std::vector<GncPricePropType> GncPriceImport::column_types_price ()
+{
+    return m_settings.m_column_types_price;
+}
+
diff --git a/gnucash/import-export/csv-imp/gnc-price-import.hpp b/gnucash/import-export/csv-imp/gnc-price-import.hpp
new file mode 100644
index 0000000..0898215
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-price-import.hpp
@@ -0,0 +1,160 @@
+/********************************************************************\
+ * gnc-price-import.hpp - import prices from csv files              *
+ *                                                                  *
+ * 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 Class to import prices from CSV or fixed width files
+     *
+     gnc-price-import.hpp
+     @author Copyright (c) 2015 Geert Janssens <geert at kobaltwit.be>
+     @author Copyright (c) 2017 Robert Fewell
+ */
+
+#ifndef GNC_PRICE_IMPORT_HPP
+#define GNC_PRICE_IMPORT_HPP
+
+extern "C" {
+#include "config.h"
+
+}
+
+#include <vector>
+#include <set>
+#include <map>
+#include <memory>
+
+#include "gnc-tokenizer.hpp"
+#include "gnc-price-props.hpp"
+#include "gnc-csv-trans-settings.hpp"
+#include <boost/optional.hpp>
+
+/* 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[];
+
+/** Tuple to hold
+ *  - a tokenized line of input
+ *  - an optional error string
+ *  - a struct to hold user selected properties for a price */
+using parse_line_t = std::tuple<StrVec,
+                                std::string,
+                                std::shared_ptr<GncImportPrice>,
+                                bool>;
+struct ErrorListPrice;
+
+/** The actual PriceImport class
+ * It's intended to use in the following sequence of actions:
+ * - set a file format
+ * - load a file
+ * - optionally convert it's encoding
+ * - parse the file into lines, which in turn are split up in columns
+ *   the result of this step can be queried from tokenizer
+ * - the user should now map the columns to types, which is stored in column_types
+ * - last step is convert the mapped columns into a list of transactions
+ * - this list will then be passed on the the generic importer for further processing */
+class GncPriceImport
+{
+public:
+    // Constructor - Destructor
+    GncPriceImport(GncImpFileFormat format = GncImpFileFormat::UNKNOWN);
+    ~GncPriceImport();
+
+    void file_format(GncImpFileFormat format);
+    GncImpFileFormat file_format();
+
+    void over_write (bool over);
+    bool over_write ();
+
+    void currency_format (int currency_format);
+    int currency_format ();
+
+    void date_format (int date_format);
+    int date_format ();
+
+    void encoding (const std::string& encoding);
+    std::string encoding ();
+
+    void update_skipped_lines (boost::optional<uint32_t> start, boost::optional<uint32_t> end,
+                               boost::optional<bool> alt, boost::optional<bool> errors);
+    uint32_t skip_start_lines ();
+    uint32_t skip_end_lines ();
+    bool skip_alt_lines ();
+    bool skip_err_lines ();
+
+    void separators (std::string separators);
+    std::string separators ();
+
+    void settings (const CsvTransSettings& settings);
+    bool save_settings ();
+
+    void settings_name (std::string name);
+    std::string settings_name ();
+
+
+    void load_file (const std::string& filename);
+
+    void tokenize (bool guessColTypes);
+
+    std::string verify();
+
+    /** This function will attempt to convert all tokenized lines into
+     *  prices using the column types the user has set.
+     */
+    void create_prices ();
+    bool check_for_column_type (GncPricePropType type);
+    void set_column_type_price (uint32_t position, GncPricePropType type, bool force = false);
+    std::vector<GncPricePropType> column_types_price ();
+
+    std::unique_ptr<GncTokenizer> m_tokenizer;    /**< Will handle file loading/encoding conversion/splitting into fields */
+    std::vector<parse_line_t> m_parsed_lines;     /**< source file parsed into a two-dimensional array of strings.
+                                                     Per line also holds possible error messages and objects with extracted
+                                                     price properties. */
+    int  m_prices_added;
+    int  m_prices_duplicated;
+
+private:
+    /** A helper function used by create_prices. It will attempt
+     *  to convert a single tokenized line into a price using
+     *  the column types the user has set.
+     */
+    void create_price (std::vector<parse_line_t>::iterator& parsed_line);
+
+    void verify_column_selections (ErrorListPrice& error_msg);
+
+    /* Internal helper function to force reparsing of columns subject to format changes */
+    void reset_formatted_column (std::vector<GncPricePropType>& col_types);
+
+    /* Two internal helper functions that should only be called from within
+     * set_column_type_price for consistency (otherwise error messages may not be (re)set)
+     */
+    void update_price_props (uint32_t row, uint32_t col, GncPricePropType prop_type);
+
+    struct CsvTranSettings;
+    CsvTransSettings m_settings;
+    bool m_skip_errors;
+    bool m_over_write;
+};
+
+
+#endif
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
index 6f1189b..d101280 100644
--- a/gnucash/import-export/csv-imp/gnc-price-props.hpp
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -31,7 +31,7 @@ extern "C" {
 #endif
 
 #include <glib/gi18n.h>
-
+#include "gnc-pricedb.h"
 #include "gnc-commodity.h"
 }
 

commit 3410a03b2291f6a095040dca442df1bf903a284c
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Fri Dec 1 10:44:15 2017 +0000

    Add property files for the csv price importer
    
    These files are largely based on the csv transaction importer

diff --git a/gnucash/import-export/csv-imp/CMakeLists.txt b/gnucash/import-export/csv-imp/CMakeLists.txt
index c2a77b8..e2fa97f 100644
--- a/gnucash/import-export/csv-imp/CMakeLists.txt
+++ b/gnucash/import-export/csv-imp/CMakeLists.txt
@@ -19,6 +19,7 @@ SET(csv_import_SOURCES
   gnc-csv-trans-settings.cpp
   gnc-dummy-tokenizer.cpp
   gnc-fw-tokenizer.cpp
+  gnc-price-props.cpp
   gnc-tokenizer.cpp
   gnc-trans-props.cpp
   gnc-tx-import.cpp
@@ -44,6 +45,7 @@ SET(csv_import_noinst_HEADERS
   gnc-csv-trans-settings.hpp
   gnc-dummy-tokenizer.hpp
   gnc-fw-tokenizer.hpp
+  gnc-price-props.hpp
   gnc-tokenizer.hpp
   gnc-trans-props.hpp
   gnc-tx-import.hpp
diff --git a/gnucash/import-export/csv-imp/Makefile.am b/gnucash/import-export/csv-imp/Makefile.am
index 06ef43f..8b13d01 100644
--- a/gnucash/import-export/csv-imp/Makefile.am
+++ b/gnucash/import-export/csv-imp/Makefile.am
@@ -13,6 +13,7 @@ libgncmod_csv_import_la_SOURCES = \
   gnc-csv-gnumeric-popup.c \
   gnc-dummy-tokenizer.cpp \
   gnc-fw-tokenizer.cpp \
+  gnc-price-props.cpp \
   gnc-tokenizer.cpp \
   gnc-tx-import.cpp \
   gnc-trans-props.cpp \
@@ -28,6 +29,7 @@ noinst_HEADERS = \
   gnc-csv-gnumeric-popup.h \
   gnc-dummy-tokenizer.hpp \
   gnc-fw-tokenizer.hpp \
+  gnc-price-props.hpp \
   gnc-tokenizer.hpp \
   gnc-tx-import.hpp \
   gnc-trans-props.hpp \
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.cpp b/gnucash/import-export/csv-imp/gnc-price-props.cpp
new file mode 100644
index 0000000..1fdcaa53
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-price-props.cpp
@@ -0,0 +1,508 @@
+/********************************************************************\
+ * gnc-price-props.cpp - encapsulate price properties for use       *
+ *                       in the csv importer                        *
+ *                                                                  *
+ * 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                   *
+ *                                                                  *
+\********************************************************************/
+
+extern "C" {
+#include <platform.h>
+#if PLATFORM(WINDOWS)
+#include <windows.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "engine-helpers.h"
+#include "gnc-ui-util.h"
+#include "gnc-pricedb.h"
+
+}
+
+#include <string>
+#include <boost/regex.hpp>
+#include <boost/regex/icu.hpp>
+#include "gnc-price-props.hpp"
+
+G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
+
+/* This map contains a set of strings representing the different column types. */
+std::map<GncPricePropType, const char*> gnc_csv_price_col_type_strs = {
+        { GncPricePropType::NONE, N_("None") },
+        { GncPricePropType::DATE, N_("Date") },
+        { GncPricePropType::AMOUNT, N_("Amount") },
+        { GncPricePropType::CURRENCY_FROM, N_("Currency From") },
+        { GncPricePropType::CURRENCY_TO, N_("Currency To") },
+        { GncPricePropType::SYMBOL_FROM, N_("Symbol From") },
+};
+
+/* Regular expressions used to parse dates per date format */
+const char* date_regex_price[] = {
+                             "(?:"                                   // either y-m-d
+                                 "(?<YEAR>[0-9]+)[-/.' ]+"
+                                 "(?<MONTH>[0-9]+)[-/.' ]+"
+                                 "(?<DAY>[0-9]+)"
+                             "|"                                     // or CCYYMMDD
+                                 "(?<YEAR>[0-9]{4})"
+                                 "(?<MONTH>[0-9]{2})"
+                                 "(?<DAY>[0-9]{2})"
+                             ")",
+
+                             "(?:"                                   // either d-m-y
+                                 "(?<DAY>[0-9]+)[-/.' ]+"
+                                 "(?<MONTH>[0-9]+)[-/.' ]+"
+                                 "(?<YEAR>[0-9]+)"
+                             "|"                                     // or DDMMCCYY
+                                 "(?<DAY>[0-9]{2})"
+                                 "(?<MONTH>[0-9]{2})"
+                                 "(?<YEAR>[0-9]{4})"
+                             ")",
+
+                             "(?:"                                   // either m-d-y
+                                 "(?<MONTH>[0-9]+)[-/.' ]+"
+                                 "(?<DAY>[0-9]+)[-/.' ]+"
+                                 "(?<YEAR>[0-9]+)"
+                             "|"                                     // or MMDDCCYY
+                                 "(?<MONTH>[0-9]{2})"
+                                 "(?<DAY>[0-9]{2})"
+                                 "(?<YEAR>[0-9]{4})"
+                             ")",
+
+                             "(?:"                                   // either d-m(-y)
+                                 "(?<DAY>[0-9]+)[-/.' ]+"
+                                 "(?<MONTH>[0-9]+)(?:[-/.' ]+"
+                                 "(?<YEAR>[0-9]+))?"
+                             "|"                                     // or DDMM(CCYY)
+                                 "(?<DAY>[0-9]{2})"
+                                 "(?<MONTH>[0-9]{2})"
+                                 "(?<YEAR>[0-9]+)?"
+                             ")",
+
+                             "(?:"                                   // either m-d(-y)
+                                 "(?<MONTH>[0-9]+)[-/.' ]+"
+                                 "(?<DAY>[0-9]+)(?:[-/.' ]+"
+                                 "(?<YEAR>[0-9]+))?"
+                             "|"                                     // or MMDD(CCYY)
+                                 "(?<MONTH>[0-9]{2})"
+                                 "(?<DAY>[0-9]{2})"
+                                 "(?<YEAR>[0-9]+)?"
+                             ")",
+};
+
+/** 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
+ * @exception std::invalid_argument if the string can't be parsed into a date.
+ * @return The parsed value of date_str on success, throws on failure
+ */
+
+time64 parse_date_price (const std::string &date_str, int format)
+{
+    boost::regex r(date_regex_price[format]);
+    boost::smatch what;
+    if(!boost::regex_search(date_str, what, r))
+        throw std::invalid_argument (_("Value can't be parsed into a date using the selected date format."));  // regex didn't find a match
+
+    // Attention: different behavior from 2.6.x series !
+    // If date format without year was selected, the match
+    // should NOT have found a year.
+    if ((format >= 3) && (what.length("YEAR") != 0))
+        throw std::invalid_argument (_("Value appears to contain a year while the selected format forbids this."));
+
+    auto day = std::stoi (what.str("DAY"));
+    auto month = std::stoi (what.str("MONTH"));
+
+    int year;
+    if (format < 3)
+    {
+        /* The input dates have a year, so use that one */
+        year = std::stoi (what.str("YEAR"));
+
+        /* Handle two-digit years. */
+        if (year < 100)
+        {
+            /* We allow two-digit years in the range 1969 - 2068. */
+            if (year < 69)
+                year += 2000;
+            else
+                year += 1900;
+        }
+    }
+    else
+    {
+        /* The input dates don't have a year, so work with today's year.
+         */
+        gnc_timespec2dmy(timespec_now(), nullptr, nullptr, &year);
+    }
+
+    auto ts = gnc_dmy2timespec_neutral(day, month, year);
+    if (ts.tv_sec == INT64_MAX)
+        throw std::invalid_argument (_("Value can't be parsed into a date using the selected date format."));
+
+    return ts.tv_sec;
+}
+
+
+/** Convert str into a GncRational using the user-specified (import) currency format.
+ * @param str The string to be parsed
+ * @param currency_format The currency format to use.
+ * @return a GncNumeric
+ * @exception May throw std::invalid argument if string can't be parsed properly
+ */
+GncNumeric parse_amount_price (const std::string &str, int currency_format)
+{
+    /* If a cell is empty or just spaces return invalid amount */
+    if(!boost::regex_search(str, boost::regex("[0-9]")))
+        throw std::invalid_argument (_("Value doesn't appear to contain a valid number."));
+
+    auto expr = boost::make_u32regex("[[:Sc:]]");
+    std::string str_no_symbols = boost::u32regex_replace(str, expr, "");
+
+    /* Convert based on user chosen currency format */
+    gnc_numeric val;
+    char *endptr;
+    switch (currency_format)
+    {
+    case 0:
+        /* Currency locale */
+        if (!(xaccParseAmount (str_no_symbols.c_str(), TRUE, &val, &endptr)))
+            throw std::invalid_argument (_("Value can't be parsed into a number using the selected currency format."));
+        break;
+    case 1:
+        /* Currency decimal period */
+        if (!(xaccParseAmountExtended (str_no_symbols.c_str(), TRUE, '-', '.', ',', "\003\003", "$+", &val, &endptr)))
+            throw std::invalid_argument (_("Value can't be parsed into a number using the selected currency format."));
+        break;
+    case 2:
+        /* Currency decimal comma */
+        if (!(xaccParseAmountExtended (str_no_symbols.c_str(), TRUE, '-', ',', '.', "\003\003", "$+", &val, &endptr)))
+            throw std::invalid_argument (_("Value can't be parsed into a number using the selected currency format."));
+        break;
+    }
+
+    return GncNumeric(val);
+}
+
+gnc_commodity* parse_commodity_price_comm (const std::string& comm_str)
+{
+    if (comm_str.empty())
+        return nullptr;
+
+    auto table = gnc_commodity_table_get_table (gnc_get_current_book());
+    gnc_commodity* comm = nullptr;
+
+    /* First try commodity as a unique name. */
+    if (comm_str.find("::"))
+        comm = gnc_commodity_table_lookup_unique (table, comm_str.c_str());
+
+    /* Then try mnemonic in the currency namespace */
+    if (!comm)
+        comm = gnc_commodity_table_lookup (table,
+                GNC_COMMODITY_NS_CURRENCY, comm_str.c_str());
+
+    if (!comm)
+    {
+        /* If that fails try mnemonic in all other namespaces */
+        auto namespaces = gnc_commodity_table_get_namespaces(table);
+        for (auto ns = namespaces; ns; ns = ns->next)
+        {
+            gchar* ns_str = (gchar*)ns->data;
+            if (g_utf8_collate(ns_str, GNC_COMMODITY_NS_CURRENCY) == 0)
+                continue;
+
+            comm = gnc_commodity_table_lookup (table,
+                    ns_str, comm_str.c_str());
+            if (comm)
+                break;
+        }
+    }
+
+    if (!comm)
+        throw std::invalid_argument (_("Value can't be parsed into a valid commodity."));
+    else
+        return comm;
+}
+
+gnc_commodity * parse_commodity_price_sym (const std::string& sym_str, bool is_currency)
+{
+    if (sym_str.empty())
+        return nullptr;
+
+    auto commodity_table = gnc_get_current_commodities ();
+    GList         *namespaces;
+    gnc_commodity *retval = nullptr;
+    gnc_commodity *tmp_commodity = nullptr;
+    char  *tmp_namespace = nullptr;
+    GList *commodity_list = NULL;
+    GList *namespace_list = gnc_commodity_table_get_namespaces (commodity_table);
+
+    namespace_list = g_list_first (namespace_list);
+    while (namespace_list != NULL && retval == NULL)
+    {
+        tmp_namespace = (char*)namespace_list->data;
+        DEBUG("Looking at namespace %s", tmp_namespace);
+        commodity_list = gnc_commodity_table_get_commodities (commodity_table, tmp_namespace);
+        commodity_list  = g_list_first (commodity_list);
+        while (commodity_list != NULL && retval == NULL)
+        {
+            const char* tmp_mnemonic = NULL;
+            tmp_commodity = (gnc_commodity*)commodity_list->data;
+            DEBUG("Looking at commodity %s", gnc_commodity_get_fullname (tmp_commodity));
+            tmp_mnemonic = gnc_commodity_get_mnemonic (tmp_commodity);
+            if (g_strcmp0 (tmp_mnemonic, sym_str.c_str()) == 0)
+            {
+                retval = tmp_commodity;
+                DEBUG("Commodity %s%s", gnc_commodity_get_fullname (retval), " matches.");
+            }
+            commodity_list = g_list_next (commodity_list);
+        }
+        namespace_list = g_list_next (namespace_list);
+    }
+    g_list_free (commodity_list);
+    g_list_free (namespace_list);
+
+    if (!retval)
+        throw std::invalid_argument (_("Value can't be parsed into a valid commodity."));
+    else
+    {
+        if (gnc_commodity_is_currency (retval) != is_currency)
+            throw std::invalid_argument (_("Value parsed into an invalid commodity for column type."));
+        else
+            return retval;
+    }
+}
+
+void GncImportPrice::set (GncPricePropType prop_type, const std::string& value)
+{
+    try
+    {
+        // Drop any existing error for the prop_type we're about to set
+        m_errors.erase(prop_type);
+
+        gnc_commodity *comm = nullptr;
+        switch (prop_type)
+        {
+            case GncPricePropType::DATE:
+                m_date = boost::none;
+                m_date = parse_date_price (value, m_date_format); // Throws if parsing fails
+                break;
+
+            case GncPricePropType::AMOUNT:
+                m_amount = boost::none;
+                m_amount = parse_amount_price (value, m_currency_format); // Will throw if parsing fails
+                break;
+
+            case GncPricePropType::CURRENCY_FROM:
+                m_currency_from = boost::none;
+                comm = parse_commodity_price_sym (value, true); // Throws if parsing fails
+                if (comm)
+                    m_currency_from = comm;
+                break;
+
+            case GncPricePropType::CURRENCY_TO:
+                m_currency_to = boost::none;
+                comm = parse_commodity_price_sym (value, true); // Throws if parsing fails
+                if (comm)
+                    m_currency_to = comm;
+                break;
+
+            case GncPricePropType::SYMBOL_FROM:
+                m_symbol_from = boost::none;
+                comm = parse_commodity_price_sym (value, false); // Throws if parsing fails
+                if (comm)
+                    m_symbol_from = comm;
+                break;
+
+            default:
+                /* Issue a warning for all other prop_types. */
+                PWARN ("%d is an invalid property for a Price", static_cast<int>(prop_type));
+                break;
+        }
+    }
+    catch (const std::invalid_argument& e)
+    {
+        auto err_str = std::string(_(gnc_csv_price_col_type_strs[prop_type])) +
+                       std::string(_(" could not be understood.\n")) +
+                       e.what();
+        m_errors.emplace(prop_type, err_str);
+        throw std::invalid_argument (err_str);
+    }
+    catch (const std::out_of_range& e)
+    {
+        auto err_str = std::string(_(gnc_csv_price_col_type_strs[prop_type])) +
+                       std::string(_(" could not be understood.\n")) +
+                       e.what();
+        m_errors.emplace(prop_type, err_str);
+        throw std::invalid_argument (err_str);
+    }
+}
+
+void GncImportPrice::reset (GncPricePropType prop_type)
+{
+    try
+    {
+        set (prop_type, std::string());
+    }
+    catch (...)
+    {
+        // Set with an empty string will effectively clear the property
+        // but can also set an error for the property. Clear that error here.
+        m_errors.erase(prop_type);
+    }
+}
+
+std::string GncImportPrice::verify_essentials (void)
+{
+    /* Make sure this price has the minimum required set of properties defined */
+    if (m_date == boost::none)
+        return _("No date column.");
+    else if (m_amount == boost::none)
+        return _("No amount column.");
+    else if (m_currency_to == boost::none)
+        return _("No Currency to column.");
+    else if ((m_symbol_from == boost::none) && (m_currency_from == boost::none))
+        return _("No from column.");
+    else
+        return std::string();
+}
+
+bool GncImportPrice::create_price (QofBook* book, GNCPriceDB *pdb, bool over)
+{
+    /* Gently refuse to create the price if the basics are not set correctly
+     * This should have been tested before calling this function though!
+     */
+    auto check = verify_essentials();
+    if (!check.empty())
+    {
+        PWARN ("Refusing to create price because essentials not set properly: %s", check.c_str());
+        return false;
+    }
+
+    Timespec date;
+    timespecFromTime64 (&date, *m_date);
+    date.tv_nsec = 0;
+
+#ifdef skip
+//FIXME Numeric needs changing, copied from old version...
+    bool rev = false;
+    gnc_commodity *comm_from = nullptr;
+
+    if (m_currency_from != boost::none) // Currency Import
+    {
+        // Check for currency in reverse direction.
+        GNCPrice *rev_price = gnc_pricedb_lookup_day (pdb, *m_currency_to, *m_currency_from, date);
+        if (rev_price != nullptr)
+            rev = true;
+        gnc_price_unref (rev_price);
+
+        // Check for price less than 1, reverse if so.
+        if (gnc_numeric_compare (*m_amount, gnc_numeric_create (1, 1)) != 1)
+            rev = true;
+
+        comm_from = *m_currency_from;
+        DEBUG("Commodity from is a Currency");
+    }
+    else
+        comm_from = *m_symbol_from;
+
+    DEBUG("Date is %s, Rev is %d, Commodity from is '%s', Currency is '%s', Amount is %s", gnc_print_date (date),
+          rev, gnc_commodity_get_fullname (comm_from), gnc_commodity_get_fullname (*m_currency_to),
+          gnc_num_dbg_to_string (*m_amount)           );
+
+    GNCPrice *old_price = nullptr;
+
+    // Should the commodities be reversed
+    if (rev)
+        old_price = gnc_pricedb_lookup_day (pdb, *m_currency_to, comm_from, date);
+    else
+        old_price = gnc_pricedb_lookup_day (pdb, comm_from, *m_currency_to, date);
+
+    // Should old price be over writen
+    if ((old_price != nullptr) && (over == true))
+    {
+        DEBUG("Over write");
+        gnc_pricedb_remove_price (pdb, old_price);
+        gnc_price_unref (old_price);
+        old_price = nullptr;
+    }
+#endif
+    bool ret_val = true;
+#ifdef skip
+    // Create the new price
+    if (old_price == nullptr)
+    {
+        DEBUG("Create");
+        GNCPrice *price = gnc_price_create (book);
+        gnc_price_begin_edit (price);
+
+        if (rev)
+        {
+            gnc_price_set_commodity (price, *m_currency_to);
+            gnc_price_set_currency (price, comm_from);
+            *m_amount = gnc_numeric_convert (gnc_numeric_invert (*m_amount),
+                                          CURRENCY_DENOM, GNC_HOW_RND_ROUND_HALF_UP);
+            gnc_price_set_value (price, *m_amount);
+        }
+        else
+        {
+            gnc_price_set_commodity (price, comm_from);
+            gnc_price_set_currency (price, *m_currency_to);
+            gnc_price_set_value (price, *m_amount);
+        }
+        gnc_price_set_time (price, date);
+        gnc_price_set_source (price, PRICE_SOURCE_USER_PRICE);
+//FIXME Not sure which one        gnc_price_set_source (price, PRICE_SOURCE_FQ);
+        gnc_price_set_typestr (price, PRICE_TYPE_LAST);
+        gnc_price_commit_edit (price);
+
+        bool perr = gnc_pricedb_add_price (pdb, price);
+
+        gnc_price_unref (price);
+
+         if (perr == false)
+            throw std::invalid_argument (_("Failed to create price from selected columns."));
+//FIXME Not sure about this, should this be a PWARN
+    }
+    else
+
+#endif
+        ret_val = false;
+
+    return ret_val;
+}
+
+static std::string gen_err_str (std::map<GncPricePropType, std::string>& errors)
+{
+    auto full_error = std::string();
+    for (auto error : errors)
+    {
+        full_error += (full_error.empty() ? "" : "\n") + error.second;
+    }
+    return full_error;
+}
+
+std::string GncImportPrice::errors ()
+{
+    return gen_err_str (m_errors);
+}
+
diff --git a/gnucash/import-export/csv-imp/gnc-price-props.hpp b/gnucash/import-export/csv-imp/gnc-price-props.hpp
new file mode 100644
index 0000000..6f1189b
--- /dev/null
+++ b/gnucash/import-export/csv-imp/gnc-price-props.hpp
@@ -0,0 +1,110 @@
+/********************************************************************\
+ * gnc-price-props.hpp - encapsulate price properties for use       *
+ *                       in the csv importer                        *
+ *                                                                  *
+ * 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_PRICE_PROPS_HPP
+#define GNC_PRICE_PROPS_HPP
+
+extern "C" {
+#include <platform.h>
+#if PLATFORM(WINDOWS)
+#include <windows.h>
+#endif
+
+#include <glib/gi18n.h>
+
+#include "gnc-commodity.h"
+}
+
+#include <string>
+#include <map>
+#include <memory>
+#include <boost/optional.hpp>
+#include <gnc-numeric.hpp>
+
+/** 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 GncPricePropType::NONE
+ * type. */
+enum class GncPricePropType {
+    NONE,
+    DATE,
+    AMOUNT,
+    CURRENCY_FROM,
+    CURRENCY_TO,
+    SYMBOL_FROM,
+    PRICE_PROPS = SYMBOL_FROM
+};
+
+/** Maps all column types to a string representation.
+ *  The actual definition is in gnc-csv-imp-prices.cpp.
+ *  Attention: that definition should be adjusted for any
+ *  changes to enum class GncPricePropType ! */
+extern std::map<GncPricePropType, const char*> gnc_csv_price_col_type_strs;
+
+/** Functor to check if the above map has an element of which
+ *  the value equals name. To be used with std::find_if.
+ */
+struct test_price_prop_type_str
+{
+    test_price_prop_type_str( const char* name ) : m_name(name) {}
+    bool operator()( const std::pair<GncPricePropType, const char*>& v ) const
+    {
+        return !g_strcmp0(v.second, m_name);
+    }
+private:
+    const char *m_name;
+};
+
+time64 parse_date_price (const std::string &date_str, int format);
+gnc_commodity* parse_commodity_price_comm (const std::string& comm_str);
+gnc_commodity* parse_commodity_price_sym (const std::string& comm_str, bool is_currency);
+GncNumeric parse_amount_price (const std::string &str, int currency_format);
+
+struct GncImportPrice
+{
+public:
+    GncImportPrice (int date_format, int currency_format) : m_date_format{date_format},
+        m_currency_format{currency_format}{};
+
+    void set (GncPricePropType prop_type, const std::string& value);
+    void set_date_format (int date_format) { m_date_format = date_format ;}
+    void set_currency_format (int currency_format) { m_currency_format = currency_format ;}
+    void reset (GncPricePropType prop_type);
+    std::string verify_essentials (void);
+    bool create_price (QofBook* book, GNCPriceDB *pdb, bool over);
+    std::string errors();
+
+private:
+    int m_date_format;
+    int m_currency_format;
+    boost::optional<time64> m_date;
+    boost::optional<GncNumeric> m_amount;
+    boost::optional<gnc_commodity*> m_currency_from;
+    boost::optional<gnc_commodity*> m_currency_to;
+    boost::optional<gnc_commodity*> m_symbol_from;
+    bool created = false;
+
+    std::map<GncPricePropType, std::string> m_errors;
+};
+
+#endif



Summary of changes:
 gnucash/import-export/csv-imp/CMakeLists.txt       |   16 +-
 gnucash/import-export/csv-imp/Makefile.am          |   15 +-
 ...s-import.cpp => assistant-csv-price-import.cpp} | 1139 +++++++++-----------
 ...port.glade => assistant-csv-price-import.glade} |  429 +++-----
 ...trans-import.h => assistant-csv-price-import.h} |   20 +-
 .../csv-imp/assistant-csv-trans-import.cpp         |   19 +-
 ...ns-settings.cpp => gnc-csv-import-settings.cpp} |  247 +----
 ...ns-settings.hpp => gnc-csv-import-settings.hpp} |   67 +-
 .../csv-imp/gnc-csv-price-import-settings.cpp      |  258 +++++
 .../csv-imp/gnc-csv-price-import-settings.hpp      |   79 ++
 .../csv-imp/gnc-csv-trans-import-settings.cpp      |  262 +++++
 .../csv-imp/gnc-csv-trans-import-settings.hpp      |   79 ++
 .../csv-imp/gnc-plugin-csv-import-ui.xml           |    1 +
 .../import-export/csv-imp/gnc-plugin-csv-import.c  |   14 +
 gnucash/import-export/csv-imp/gnc-price-import.cpp |  757 +++++++++++++
 gnucash/import-export/csv-imp/gnc-price-import.hpp |  173 +++
 gnucash/import-export/csv-imp/gnc-price-props.cpp  |  349 ++++++
 gnucash/import-export/csv-imp/gnc-price-props.hpp  |  116 ++
 gnucash/import-export/csv-imp/gnc-tx-import.cpp    |    6 +-
 gnucash/import-export/csv-imp/gnc-tx-import.hpp    |    8 +-
 po/POTFILES.in                                     |    8 +-
 21 files changed, 2880 insertions(+), 1182 deletions(-)
 copy gnucash/import-export/csv-imp/{assistant-csv-trans-import.cpp => assistant-csv-price-import.cpp} (62%)
 copy gnucash/import-export/csv-imp/{assistant-csv-trans-import.glade => assistant-csv-price-import.glade} (83%)
 copy gnucash/import-export/csv-imp/{assistant-csv-trans-import.h => assistant-csv-price-import.h} (73%)
 rename gnucash/import-export/csv-imp/{gnc-csv-trans-settings.cpp => gnc-csv-import-settings.cpp} (53%)
 rename gnucash/import-export/csv-imp/{gnc-csv-trans-settings.hpp => gnc-csv-import-settings.hpp} (69%)
 create mode 100644 gnucash/import-export/csv-imp/gnc-csv-price-import-settings.cpp
 create mode 100644 gnucash/import-export/csv-imp/gnc-csv-price-import-settings.hpp
 create mode 100644 gnucash/import-export/csv-imp/gnc-csv-trans-import-settings.cpp
 create mode 100644 gnucash/import-export/csv-imp/gnc-csv-trans-import-settings.hpp
 create mode 100644 gnucash/import-export/csv-imp/gnc-price-import.cpp
 create mode 100644 gnucash/import-export/csv-imp/gnc-price-import.hpp
 create mode 100644 gnucash/import-export/csv-imp/gnc-price-props.cpp
 create mode 100644 gnucash/import-export/csv-imp/gnc-price-props.hpp



More information about the gnucash-changes mailing list