Convert CsvTransSettings into a c++ class

This commit is contained in:
Geert Janssens 2016-12-05 17:42:55 +01:00 committed by Geert Janssens
parent dcce2d79cd
commit 7a69d552bd
7 changed files with 364 additions and 491 deletions

View File

@ -437,7 +437,7 @@ src/import-export/csv-imp/csv-fixed-trans-import.cpp
src/import-export/csv-imp/gnc-csv-account-map.c
src/import-export/csv-imp/gnc-csv-gnumeric-popup.c
src/import-export/csv-imp/gnc-csv-tokenizer.cpp
src/import-export/csv-imp/gnc-csv-trans-settings.c
src/import-export/csv-imp/gnc-csv-trans-settings.cpp
src/import-export/csv-imp/gnc-dummy-tokenizer.cpp
src/import-export/csv-imp/gnc-fw-tokenizer.cpp
src/import-export/csv-imp/gncmod-csv-import.c

View File

@ -12,7 +12,7 @@ SET(csv_import_SOURCES
gnc-csv-account-map.c
gnc-csv-gnumeric-popup.c
gnc-csv-tokenizer.cpp
gnc-csv-trans-settings.c
gnc-csv-trans-settings.cpp
gnc-dummy-tokenizer.cpp
gnc-fw-tokenizer.cpp
gnc-tokenizer.cpp
@ -36,7 +36,7 @@ SET(csv_import_noinst_HEADERS
gnc-csv-account-map.h
gnc-csv-gnumeric-popup.h
gnc-csv-tokenizer.hpp
gnc-csv-trans-settings.h
gnc-csv-trans-settings.hpp
gnc-dummy-tokenizer.hpp
gnc-fw-tokenizer.hpp
gnc-tokenizer.hpp

View File

@ -18,7 +18,7 @@ libgncmod_csv_import_la_SOURCES = \
gnc-tokenizer.cpp \
gnc-tx-import.cpp \
gnc-trans-props.cpp \
gnc-csv-trans-settings.c
gnc-csv-trans-settings.cpp
noinst_HEADERS = \
assistant-csv-account-import.h \
@ -35,7 +35,7 @@ noinst_HEADERS = \
gnc-tokenizer.hpp \
gnc-tx-import.hpp \
gnc-trans-props.hpp \
gnc-csv-trans-settings.h
gnc-csv-trans-settings.hpp
libgncmod_csv_import_la_LDFLAGS = -avoid-version

View File

@ -47,7 +47,7 @@ extern "C"
#include "gnc-state.h"
#include "assistant-csv-trans-import.h"
#include "gnc-csv-trans-settings.h"
#include "gnc-csv-trans-settings.hpp"
#include "import-account-matcher.h"
#include "import-main-matcher.h"
@ -94,7 +94,7 @@ typedef struct
int home_account_number; /**< The number of unique home account strings */
GncTxImport *parse_data; /**< The actual data we are previewing */
CsvSettings *settings_data; /**< The settings to be saved and loaded */
CsvTransSettings settings_data; /**< The settings to be saved and loaded */
GOCharmapSel *encselector; /**< The widget for selecting the encoding */
GtkCheckButton *sep_buttons[SEP_NUM_OF_TYPES]; /**< Checkbuttons for common separators */
GtkCheckButton *custom_cbutton; /**< The checkbutton for a custom separator */
@ -203,10 +203,8 @@ csv_import_trans_load_settings (CsvImportTrans *info)
if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX(info->settings_combo), &iter))
return;
GtkTreeModel *model;
gchar *group = NULL;
model = gtk_combo_box_get_model (GTK_COMBO_BOX(info->settings_combo));
GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX(info->settings_combo));
gtk_tree_model_get (model, &iter, SET_GROUP, &group, -1);
// Test for default selection, return
@ -214,7 +212,9 @@ csv_import_trans_load_settings (CsvImportTrans *info)
return;
// Load the settings from the keyfile
if (gnc_csv_trans_load_settings (info->settings_data, group))
auto group_str = std::string{group};
g_free (group);
if (info->settings_data.load (group_str))
{
const gchar *title = _("Load the Import Settings.");
GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(info->window),
@ -227,54 +227,53 @@ csv_import_trans_load_settings (CsvImportTrans *info)
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
}
g_free (group);
// Set start row
info->parse_data->skip_start_lines = info->settings_data->header_rows;
info->parse_data->skip_start_lines = info->settings_data.header_rows;
GtkAdjustment *adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->start_row_spin));
gtk_adjustment_set_upper (adj, info->parse_data->parsed_lines.size());
gtk_spin_button_set_value (GTK_SPIN_BUTTON(info->start_row_spin),
info->settings_data->header_rows);
info->settings_data.header_rows);
// Set end row
info->parse_data->skip_end_lines = info->settings_data->footer_rows;
info->parse_data->skip_end_lines = info->settings_data.footer_rows;
adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON(info->end_row_spin));
gtk_adjustment_set_upper (adj, info->parse_data->parsed_lines.size());
gtk_spin_button_set_value (GTK_SPIN_BUTTON(info->end_row_spin),
info->settings_data->footer_rows);
info->settings_data.footer_rows);
// Set Alternate rows
info->parse_data->skip_alt_lines = info->settings_data->skip_alt_rows;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->skip_rows), info->settings_data->skip_alt_rows);
info->parse_data->skip_alt_lines = info->settings_data.skip_alt_rows;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->skip_rows), info->settings_data.skip_alt_rows);
// Set Multi-split indicator
info->parse_data->multi_split = info->settings_data->multi_split;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->multi_split_cbutton), info->settings_data->multi_split);
info->parse_data->multi_split = info->settings_data.multi_split;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->multi_split_cbutton), info->settings_data.multi_split);
// Set Import Format
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->csv_button), info->settings_data->csv_format);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->fixed_button), !info->settings_data->csv_format);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->csv_button), info->settings_data.csv_format);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->fixed_button), !info->settings_data.csv_format);
// This section deals with the combo's and character encoding
info->parse_data->date_format = info->settings_data->date_active;
gtk_combo_box_set_active (GTK_COMBO_BOX(info->date_format_combo), info->settings_data->date_active);
info->parse_data->date_format = info->settings_data.date_active;
gtk_combo_box_set_active (GTK_COMBO_BOX(info->date_format_combo), info->settings_data.date_active);
info->parse_data->currency_format = info->settings_data->currency_active;
gtk_combo_box_set_active (GTK_COMBO_BOX(info->currency_format_combo), info->settings_data->currency_active);
info->parse_data->convert_encoding (info->settings_data->encoding);
go_charmap_sel_set_encoding (info->encselector, info->settings_data->encoding);
info->parse_data->currency_format = info->settings_data.currency_active;
gtk_combo_box_set_active (GTK_COMBO_BOX(info->currency_format_combo), info->settings_data.currency_active);
info->parse_data->convert_encoding (info->settings_data.encoding);
go_charmap_sel_set_encoding (info->encselector, info->settings_data.encoding);
try
{
if (info->settings_data->csv_format)
if (info->settings_data.csv_format)
{
// Handle separators, only relevant if the file format is csv
info->parse_data->file_format (GncImpFileFormat::CSV);
for (int i = 0; i < SEP_NUM_OF_TYPES; i++)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->sep_buttons[i]), info->settings_data->separator[i]);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->custom_cbutton), info->settings_data->custom);
if (info->settings_data->custom)
gtk_entry_set_text (GTK_ENTRY(info->custom_entry), info->settings_data->custom_entry);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->sep_buttons[i]), info->settings_data.separator[i]);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(info->custom_cbutton), info->settings_data.custom);
if (info->settings_data.custom)
gtk_entry_set_text (GTK_ENTRY(info->custom_entry), info->settings_data.custom_entry);
else
gtk_entry_set_text (GTK_ENTRY(info->custom_entry), "");
@ -285,8 +284,8 @@ csv_import_trans_load_settings (CsvImportTrans *info)
// Handle column widths, only relevant if the file format is fixed width
info->parse_data->file_format (GncImpFileFormat::FIXED_WIDTH);
GncFwTokenizer *fwtok = dynamic_cast<GncFwTokenizer*>(info->parse_data->tokenizer.get());
if (info->settings_data->column_widths, NULL)
fwtok->cols_from_string (std::string(info->settings_data->column_widths));
if (info->settings_data.column_widths, NULL)
fwtok->cols_from_string (std::string(info->settings_data.column_widths));
info->parse_data->tokenize (false);
gnc_csv_preview_update_assist (info);
@ -305,7 +304,7 @@ csv_import_trans_load_settings (CsvImportTrans *info)
}
// This section deals with the column types
if (info->settings_data->column_types)
if (info->settings_data.column_types)
{
GtkTreeModel *ctstore;
GtkTreeIter iter;
@ -313,7 +312,7 @@ csv_import_trans_load_settings (CsvImportTrans *info)
uint i;
bool error = false;
columns = g_strsplit (info->settings_data->column_types, ",", -1);
columns = g_strsplit (info->settings_data.column_types, ",", -1);
// ctstore contains the column types and their (translated) string representation appearing in the column types treeview.
ctstore = gtk_tree_view_get_model (info->ctreeview);
@ -406,7 +405,7 @@ csv_import_trans_delete_settings_cb (GtkWidget *button, CsvImportTrans *info)
if (response == GTK_RESPONSE_OK)
{
g_key_file_remove_group (keyfile, group, NULL);
gnc_csv_trans_find_settings (model);
info->settings_data.find (model);
gtk_combo_box_set_active (GTK_COMBO_BOX(info->settings_combo), 0); // Default
gnc_csv_reset_preview_setting (info, false); // Reset the widgets
}
@ -542,24 +541,24 @@ csv_import_trans_save_settings_cb (GtkWidget *button, CsvImportTrans *info)
gchar *details = NULL;
/* This section deals with the header and rows */
info->settings_data->header_rows = gtk_spin_button_get_value (GTK_SPIN_BUTTON(info->start_row_spin));
info->settings_data->footer_rows = gtk_spin_button_get_value (GTK_SPIN_BUTTON(info->end_row_spin));
info->settings_data->skip_alt_rows = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->skip_rows));
info->settings_data->csv_format = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->csv_button));
info->settings_data.header_rows = gtk_spin_button_get_value (GTK_SPIN_BUTTON(info->start_row_spin));
info->settings_data.footer_rows = gtk_spin_button_get_value (GTK_SPIN_BUTTON(info->end_row_spin));
info->settings_data.skip_alt_rows = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->skip_rows));
info->settings_data.csv_format = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->csv_button));
/* This Section deals with the separators */
for (i = 0; i < SEP_NUM_OF_TYPES; i++)
{
info->settings_data->separator[i] = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->sep_buttons[i]));
info->settings_data.separator[i] = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->sep_buttons[i]));
}
info->settings_data->custom = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->custom_cbutton));
info->settings_data->custom_entry = gtk_entry_get_text (GTK_ENTRY(info->custom_entry));
info->settings_data.custom = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->custom_cbutton));
info->settings_data.custom_entry = gtk_entry_get_text (GTK_ENTRY(info->custom_entry));
/* This section deals with the combo's and character encoding */
info->settings_data->date_active = gtk_combo_box_get_active (GTK_COMBO_BOX(info->date_format_combo));
info->settings_data->currency_active = gtk_combo_box_get_active (GTK_COMBO_BOX(info->currency_format_combo));
info->settings_data->encoding = go_charmap_sel_get_encoding (info->encselector);
info->settings_data->multi_split = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->multi_split_cbutton));
info->settings_data.date_active = gtk_combo_box_get_active (GTK_COMBO_BOX(info->date_format_combo));
info->settings_data.currency_active = gtk_combo_box_get_active (GTK_COMBO_BOX(info->currency_format_combo));
info->settings_data.encoding = go_charmap_sel_get_encoding (info->encselector);
info->settings_data.multi_split = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(info->multi_split_cbutton));
/* This section deals with the Treeview column names */
columns = gtk_tree_view_get_columns (GTK_TREE_VIEW(info->ctreeview));
@ -594,20 +593,20 @@ csv_import_trans_save_settings_cb (GtkWidget *button, CsvImportTrans *info)
}
g_list_free (columns);
info->settings_data->column_types = g_strdup (details);
info->settings_data.column_types = g_strdup (details);
g_free (details);
/* Save the column widths in fixed mode */
if (info->settings_data->csv_format)
info->settings_data->column_widths = "5,10,15";
if (info->settings_data.csv_format)
info->settings_data.column_widths = "5,10,15";
else
{
GncFwTokenizer *fwtok = dynamic_cast<GncFwTokenizer*>(info->parse_data->tokenizer.get());
info->settings_data->column_widths = g_strdup (fwtok->cols_to_string().c_str());
info->settings_data.column_widths = g_strdup (fwtok->cols_to_string().c_str());
}
// Save the settings
if (!gnc_csv_trans_save_settings (info->settings_data, g_strdup (entry_text)))
if (!info->settings_data.save (g_strdup (entry_text)))
{
GtkTreeModel *model;
GtkTreeIter iter;
@ -625,7 +624,7 @@ csv_import_trans_save_settings_cb (GtkWidget *button, CsvImportTrans *info)
// Update the settings store
model = gtk_combo_box_get_model (GTK_COMBO_BOX(info->settings_combo));
gnc_csv_trans_find_settings (model);
info->settings_data.find (model);
// Get the first entry in model
valid = gtk_tree_model_get_iter_first (model, &iter);
@ -731,7 +730,7 @@ csv_import_trans_file_chooser_confirm_cb (GtkWidget *button, CsvImportTrans *inf
/* Get settings store and populate */
GtkTreeModel *settings_store = gtk_combo_box_get_model (GTK_COMBO_BOX(info->settings_combo));
gnc_csv_trans_find_settings (settings_store);
info->settings_data.find (settings_store);
gtk_combo_box_set_active (GTK_COMBO_BOX(info->settings_combo), 0);
gtk_assistant_set_page_complete (assistant, page, TRUE);
@ -1922,9 +1921,6 @@ void load_settings (CsvImportTrans *info)
if (!info->error_text.empty())
info->error_text.clear();
/* Init Settings data. */
info->settings_data = gnc_csv_trans_new_settings_data();
/* The default directory for the user to select files. */
info->starting_dir = gnc_get_default_directory (GNC_PREFS_GROUP);
}
@ -2692,9 +2688,6 @@ csv_import_trans_close_handler (gpointer user_data)
if (!(info->parse_data == NULL))
delete info->parse_data;
if (!(info->settings_data == NULL))
gnc_csv_trans_settings_data_free (info->settings_data);
if (!(info->account_picker == NULL))
info->account_picker = NULL;

View File

@ -1,390 +0,0 @@
/*******************************************************************\
* gnc-csv-trans-settings.c -- Save and Load 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@gnu.org *
\********************************************************************/
/** @file gnc-csv-trans-settings.c
@brief CSV Import Settings
@author Copyright (c) 2014 Robert Fewell
*/
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "gnc-state.h"
#include "gnc-csv-trans-settings.h"
#define CSV_GROUP_PREFIX "CSV - "
#define CSV_NAME "Name"
#define CSV_FORMAT "CsvFormat"
#define CSV_ALT_ROWS "AltRows"
#define CSV_SKIP_START "SkipStartRows"
#define CSV_SKIP_END "SkipEndRows"
#define CSV_MULTI_SPLIT "MultiSplit"
/* The following two key names are only used by gnucash 2.6
* They have been superseded by CSV_SKIP_START and CSV_SKIP_END.
*/
#define CSV_START_ROW "StartRow"
#define CSV_END_ROWS "EndRows"
#define CSV_SEP "Separator"
#define CSV_CUSTOM "Custom"
#define CSV_CUSTOM_ENTRY "CustomEntry"
#define CSV_DATE "DateActive"
#define CSV_CURRENCY "CurrencyActive"
#define CSV_ENCODING "Encoding"
#define CSV_COL_TYPES "ColumnTypes"
#define CSV_COL_WIDTHS "ColumnWidths"
/**************************************************
* gnc_csv_trans_new_settings_data
*
* Create CsvSettings structure and set defaults
**************************************************/
CsvSettings * gnc_csv_trans_new_settings_data (void)
{
CsvSettings* settings_data = g_new (CsvSettings, 1);
int i;
settings_data->header_rows = 1;
settings_data->skip_alt_rows = FALSE;
settings_data->multi_split = FALSE;
settings_data->csv_format = TRUE;
settings_data->encoding = "UTF-8";
for (i = 0; i < SEP_NUM_OF_TYPES; i++)
{
settings_data->separator[i] = FALSE;
}
settings_data->custom = FALSE;
settings_data->date_active = 0;
settings_data->currency_active = 0;
return settings_data;
}
/**************************************************
* gnc_csv_trans_settings_data_free
*
* settings_data whose memory will be freed
**************************************************/
void gnc_csv_trans_settings_data_free (CsvSettings* settings_data)
{
/* All non-NULL pointers that have been initialized and must be freed. */
g_free (settings_data);
}
/**************************************************
* gnc_csv_trans_find_settings
*
* find the setting entries in a key file
**************************************************/
void
gnc_csv_trans_find_settings (GtkTreeModel *settings_store)
{
GtkTreeIter iter;
GKeyFile *keyfile;
gchar **groups = NULL;
gint i;
gsize grouplength;
GError *key_error = NULL;
// Get the Key file
keyfile = gnc_state_get_current ();
// Find all Groups
groups = g_key_file_get_groups (keyfile, &grouplength);
// Clear the list store
gtk_list_store_clear (GTK_LIST_STORE(settings_store));
// Append the default entry
gtk_list_store_append (GTK_LIST_STORE(settings_store), &iter);
gtk_list_store_set (GTK_LIST_STORE(settings_store), &iter, SET_GROUP, NULL, SET_NAME, _("No Settings"), -1);
// Search all Groups for ones starting with prefix
for (i=0; i < grouplength; i++)
{
if (g_str_has_prefix (groups[i], CSV_GROUP_PREFIX))
{
gchar *name = g_key_file_get_string (keyfile, groups[i], CSV_NAME, &key_error);
if (key_error == NULL)
{
gtk_list_store_append (GTK_LIST_STORE(settings_store), &iter);
gtk_list_store_set (GTK_LIST_STORE(settings_store), &iter, SET_GROUP, groups[i], SET_NAME, name, -1);
}
else
{
g_warning ("Error reading group '%s' name '%s': %s", groups[i], CSV_NAME, key_error->message);
g_clear_error (&key_error);
}
g_free (name);
}
}
// free the strings
g_strfreev (groups);
}
/**************************************************
* 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.
**************************************************/
static gboolean
handle_load_error (GError **key_error, gchar *group)
{
if (!*key_error)
return FALSE;
if ((*key_error)->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)
{
g_clear_error (key_error);
return FALSE;
}
g_warning ("Error reading group '%s' : %s", group, (*key_error)->message);
g_clear_error (key_error);
return TRUE;
}
/**************************************************
* gnc_csv_trans_load_settings
*
* load the settings from a key file
**************************************************/
gboolean
gnc_csv_trans_load_settings (CsvSettings *settings_data, gchar *group)
{
GKeyFile *keyfile;
gint i;
GError *key_error = NULL;
gboolean key_boolean = FALSE;
int key_int = 0;
gchar *key_char = NULL;
gboolean error = FALSE;
// Get the Key file
keyfile = gnc_state_get_current ();
key_int = g_key_file_get_integer (keyfile, group, CSV_SKIP_START, &key_error);
settings_data->header_rows = (key_error) ? 0 : key_int;
if (key_error)
{
/* If the key was not found (in contrast to failing to interpret its value)
* perhaps the file still uses the 2.6 key format. Let's check */
gboolean tmp_err = handle_load_error (&key_error, group);
if (!tmp_err)
{
key_int = g_key_file_get_integer (keyfile, group, CSV_START_ROW, &key_error);
settings_data->header_rows = (key_error) ? 0 : key_int - 1; // Old key was 1-based, new key is 0-based !
error |= handle_load_error (&key_error, group);
}
else
error |= tmp_err;
}
key_int = g_key_file_get_integer (keyfile, group, CSV_SKIP_END, &key_error);
settings_data->footer_rows = (key_error) ? 0 : key_int;
if (key_error)
{
/* If the key was not found (in contrast to failing to interpret its value)
* perhaps the file still uses the 2.6 key format. Let's check */
gboolean tmp_err = handle_load_error (&key_error, group);
if (!tmp_err)
{
key_int = g_key_file_get_integer (keyfile, group, CSV_END_ROWS, &key_error);
settings_data->footer_rows = (key_error) ? 0 : key_int; // Old key and new key are both 0-based !
error |= handle_load_error (&key_error, group);
}
else
error |= tmp_err;
}
key_boolean = g_key_file_get_boolean (keyfile, group, CSV_ALT_ROWS, &key_error);
settings_data->skip_alt_rows = (key_error) ? FALSE : key_boolean;
error |= handle_load_error (&key_error, group);
key_boolean = g_key_file_get_boolean (keyfile, group, CSV_MULTI_SPLIT, &key_error);
settings_data->multi_split = (key_error) ? FALSE : key_boolean;
error |= handle_load_error (&key_error, group);
key_boolean = g_key_file_get_boolean (keyfile, group, CSV_FORMAT, &key_error);
settings_data->csv_format = (key_error) ? TRUE : key_boolean;
error |= handle_load_error (&key_error, group);
for (i = 0; i < SEP_NUM_OF_TYPES; i++)
{
gchar *sep;
sep = g_strdup_printf ("%s%d", CSV_SEP, i);
key_boolean = g_key_file_get_boolean (keyfile, group, sep, &key_error);
settings_data->separator[i] = (key_error) ? FALSE : key_boolean;
error |= handle_load_error (&key_error, group);
g_free (sep);
}
key_boolean = g_key_file_get_boolean (keyfile, group, CSV_CUSTOM, &key_error);
settings_data->custom = (key_error) ? FALSE : key_boolean;
error |= handle_load_error (&key_error, group);
settings_data->custom_entry = g_key_file_get_string (keyfile, group, CSV_CUSTOM_ENTRY, &key_error);
error |= handle_load_error (&key_error, group);
key_int = g_key_file_get_integer (keyfile, group, CSV_DATE, &key_error);
settings_data->date_active = (key_error) ? 0 : key_int;
error |= handle_load_error (&key_error, group);
key_int = g_key_file_get_integer (keyfile, group, CSV_CURRENCY, &key_error);
settings_data->currency_active = (key_error) ? 0 : key_int;
error |= handle_load_error (&key_error, group);
key_char = g_key_file_get_string (keyfile, group, CSV_ENCODING, &key_error);
settings_data->encoding = g_strdup((key_error) ? "UTF-8" : key_char);
error |= handle_load_error (&key_error, group);
settings_data->column_types = g_key_file_get_string (keyfile, group, CSV_COL_TYPES, &key_error);
error |= handle_load_error (&key_error, group);
settings_data->column_widths = g_key_file_get_string (keyfile, group, CSV_COL_WIDTHS, &key_error);
error |= handle_load_error (&key_error, group);
g_free (key_char);
return error;
}
/**************************************************
* gnc_csv_trans_save_settings
*
* save settings to a key file
**************************************************/
gboolean
gnc_csv_trans_save_settings (CsvSettings *settings_data, gchar *settings_name)
{
GKeyFile *keyfile;
gchar **groups = NULL;
gint i;
gsize grouplenght;
gchar *group = NULL;
gchar *test_string = NULL;
GError *key_error = NULL;
gboolean error = FALSE;
// Get the Key file
keyfile = gnc_state_get_current ();
// Find all Groups
groups = g_key_file_get_groups (keyfile, &grouplenght);
// Search all Groups for ones starting with prefix
for (i=0; i < grouplenght; i++)
{
if (g_str_has_prefix (groups[i], CSV_GROUP_PREFIX))
{
gchar *name = g_key_file_get_string (keyfile, groups[i], CSV_NAME, NULL);
if (g_strcmp0 (name, settings_name) == 0)
group = g_strdup (groups[i]);
g_free (name);
}
}
// group is NULL, saving to a new group, create a guid
if (g_strcmp0 (group, NULL) == 0)
{
GncGUID *settings_guid;
gchar *string_guid;
settings_guid = guid_new ();
string_guid = guid_to_string (settings_guid);
group = g_strconcat (CSV_GROUP_PREFIX, string_guid, NULL);
g_free (string_guid);
guid_free (settings_guid);
}
// Start Saving the settings
g_key_file_set_string (keyfile, group, CSV_NAME, settings_name);
g_key_file_set_boolean (keyfile, group, CSV_MULTI_SPLIT, settings_data->multi_split);
g_key_file_set_integer (keyfile, group, CSV_SKIP_START, settings_data->header_rows);
g_key_file_set_integer (keyfile, group, CSV_SKIP_END, settings_data->footer_rows);
g_key_file_set_boolean (keyfile, group, CSV_ALT_ROWS, settings_data->skip_alt_rows);
g_key_file_set_boolean (keyfile, group, CSV_FORMAT, settings_data->csv_format);
for (i = 0; i < SEP_NUM_OF_TYPES; i++)
{
gchar *sep;
sep = g_strdup_printf ("%s%d", CSV_SEP, i);
g_key_file_set_boolean (keyfile, group, sep, settings_data->separator[i]);
g_free (sep);
}
g_key_file_set_boolean (keyfile, group, CSV_CUSTOM, settings_data->custom);
g_key_file_set_string (keyfile, group, CSV_CUSTOM_ENTRY, settings_data->custom_entry);
g_key_file_set_integer (keyfile, group, CSV_DATE, settings_data->date_active);
g_key_file_set_integer (keyfile, group, CSV_CURRENCY, settings_data->currency_active);
g_key_file_set_string (keyfile, group, CSV_ENCODING, settings_data->encoding);
g_key_file_set_string (keyfile, group, CSV_COL_TYPES, settings_data->column_types);
g_key_file_set_string (keyfile, group, CSV_COL_WIDTHS, settings_data->column_widths);
// free the strings
g_free (settings_name);
g_strfreev (groups);
// Do a test read of column types
test_string = g_key_file_get_string (keyfile, group, CSV_COL_TYPES, &key_error);
if ((key_error) || (g_strcmp0 (test_string, settings_data->column_types) != 0))
{
if (key_error)
{
g_warning ("Error reading group %s key %s: %s", group, CSV_COL_TYPES, key_error->message);
g_error_free (key_error);
}
else
g_warning ("Error comparing group %s key %s: '%s' and '%s'", group, CSV_COL_TYPES, test_string, group);
error = TRUE;
}
g_free (group);
g_free (test_string);
return error;
}

View File

@ -0,0 +1,266 @@
/*******************************************************************\
* gnc-csv-trans-settings.c -- Save and Load 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@gnu.org *
\********************************************************************/
/** @file gnc-csv-trans-settings.c
@brief CSV Import Settings
@author Copyright (c) 2014 Robert Fewell
*/
#include "gnc-csv-trans-settings.hpp"
extern "C"
{
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "gnc-state.h"
}
const std::string csv_group_prefix{"CSV - "};
#define CSV_NAME "Name"
#define CSV_FORMAT "CsvFormat"
#define CSV_ALT_ROWS "AltRows"
#define CSV_SKIP_START "SkipStartRows"
#define CSV_SKIP_END "SkipEndRows"
#define CSV_MULTI_SPLIT "MultiSplit"
#define CSV_SEP "Separator"
#define CSV_CUSTOM "Custom"
#define CSV_CUSTOM_ENTRY "CustomEntry"
#define CSV_DATE "DateActive"
#define CSV_CURRENCY "CurrencyActive"
#define CSV_ENCODING "Encoding"
#define CSV_COL_TYPES "ColumnTypes"
#define CSV_COL_WIDTHS "ColumnWidths"
/**************************************************
* find
*
* find all settings entries in the state key file
**************************************************/
void
CsvTransSettings::find (GtkTreeModel *settings_store)
{
// Clear the list store
gtk_list_store_clear (GTK_LIST_STORE(settings_store));
// Append the default entry
GtkTreeIter iter;
gtk_list_store_append (GTK_LIST_STORE(settings_store), &iter);
gtk_list_store_set (GTK_LIST_STORE(settings_store), &iter, SET_GROUP, NULL, SET_NAME, _("No Settings"), -1);
// Search all Groups in the state key file for ones starting with prefix
GKeyFile *keyfile = gnc_state_get_current ();
gsize grouplength;
gchar **groups = g_key_file_get_groups (keyfile, &grouplength);
for (gsize i=0; i < grouplength; i++)
{
if (g_str_has_prefix (groups[i], csv_group_prefix.c_str()))
{
GError *key_error = nullptr;
gchar *name = g_key_file_get_string (keyfile, groups[i], CSV_NAME, &key_error);
if (!key_error)
{
gtk_list_store_append (GTK_LIST_STORE(settings_store), &iter);
gtk_list_store_set (GTK_LIST_STORE(settings_store), &iter, SET_GROUP, groups[i], SET_NAME, name, -1);
}
else
{
g_warning ("Error reading group '%s' name '%s': %s", groups[i], CSV_NAME, key_error->message);
g_clear_error (&key_error);
}
g_free (name);
}
}
// free the strings
g_strfreev (groups);
}
/**************************************************
* 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.
**************************************************/
static bool
handle_load_error (GError **key_error, const std::string& group)
{
if (!*key_error)
return false;
if ((*key_error)->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)
{
g_clear_error (key_error);
return false;
}
g_warning ("Error reading group '%s' : %s", group.c_str(), (*key_error)->message);
g_clear_error (key_error);
return true;
}
/**************************************************
* load
*
* load the settings from a key file
**************************************************/
bool
CsvTransSettings::load (const std::string& group)
{
GKeyFile *keyfile;
gint i;
GError *key_error = NULL;
bool key_boolean = false;
int key_int = 0;
gchar *key_char = NULL;
bool error = false;
// Get the Key file
keyfile = gnc_state_get_current ();
key_int = g_key_file_get_integer (keyfile, group.c_str(), CSV_SKIP_START, &key_error);
header_rows = (key_error) ? 0 : key_int;
error |= handle_load_error (&key_error, group);
key_int = g_key_file_get_integer (keyfile, group.c_str(), CSV_SKIP_END, &key_error);
footer_rows = (key_error) ? 0 : key_int;
error |= handle_load_error (&key_error, group);
key_boolean = g_key_file_get_boolean (keyfile, group.c_str(), CSV_ALT_ROWS, &key_error);
skip_alt_rows = (key_error) ? false : key_boolean;
error |= handle_load_error (&key_error, group);
key_boolean = g_key_file_get_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, &key_error);
multi_split = (key_error) ? false : key_boolean;
error |= handle_load_error (&key_error, group);
key_boolean = g_key_file_get_boolean (keyfile, group.c_str(), CSV_FORMAT, &key_error);
csv_format = (key_error) ? true : key_boolean;
error |= handle_load_error (&key_error, group);
for (i = 0; i < SEP_NUM_OF_TYPES; i++)
{
gchar *sep;
sep = g_strdup_printf ("%s%d", CSV_SEP, i);
key_boolean = g_key_file_get_boolean (keyfile, group.c_str(), sep, &key_error);
separator[i] = (key_error) ? false : key_boolean;
error |= handle_load_error (&key_error, group);
g_free (sep);
}
key_boolean = g_key_file_get_boolean (keyfile, group.c_str(), CSV_CUSTOM, &key_error);
custom = (key_error) ? false : key_boolean;
error |= handle_load_error (&key_error, group);
custom_entry = g_key_file_get_string (keyfile, group.c_str(), CSV_CUSTOM_ENTRY, &key_error);
error |= handle_load_error (&key_error, group);
key_int = g_key_file_get_integer (keyfile, group.c_str(), CSV_DATE, &key_error);
date_active = (key_error) ? 0 : key_int;
error |= handle_load_error (&key_error, group);
key_int = g_key_file_get_integer (keyfile, group.c_str(), CSV_CURRENCY, &key_error);
currency_active = (key_error) ? 0 : key_int;
error |= handle_load_error (&key_error, group);
key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ENCODING, &key_error);
encoding = g_strdup((key_error) ? "UTF-8" : key_char);
error |= handle_load_error (&key_error, group);
column_types = g_key_file_get_string (keyfile, group.c_str(), CSV_COL_TYPES, &key_error);
error |= handle_load_error (&key_error, group);
column_widths = g_key_file_get_string (keyfile, group.c_str(), CSV_COL_WIDTHS, &key_error);
error |= handle_load_error (&key_error, group);
g_free (key_char);
return error;
}
/**************************************************
* save
*
* save settings to a key file
**************************************************/
bool
CsvTransSettings::save (const std::string& settings_name)
{
auto keyfile = gnc_state_get_current ();
std::string group = csv_group_prefix + settings_name;
// Drop previous saved settings with this name
g_key_file_remove_group (keyfile, group.c_str(), nullptr);
// Start Saving the settings
g_key_file_set_string (keyfile, group.c_str(), CSV_NAME, settings_name.c_str());
g_key_file_set_boolean (keyfile, group.c_str(), CSV_MULTI_SPLIT, multi_split);
g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_START, header_rows);
g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_END, footer_rows);
g_key_file_set_boolean (keyfile, group.c_str(), CSV_ALT_ROWS, skip_alt_rows);
g_key_file_set_boolean (keyfile, group.c_str(), CSV_FORMAT, csv_format);
for (guint i = 0; i < SEP_NUM_OF_TYPES; i++)
{
gchar *sep;
sep = g_strdup_printf ("%s%d", CSV_SEP, i);
g_key_file_set_boolean (keyfile, group.c_str(), sep, separator[i]);
g_free (sep);
}
g_key_file_set_boolean (keyfile, group.c_str(), CSV_CUSTOM, custom);
g_key_file_set_string (keyfile, group.c_str(), CSV_CUSTOM_ENTRY, custom_entry);
g_key_file_set_integer (keyfile, group.c_str(), CSV_DATE, date_active);
g_key_file_set_integer (keyfile, group.c_str(), CSV_CURRENCY, currency_active);
g_key_file_set_string (keyfile, group.c_str(), CSV_ENCODING, encoding);
g_key_file_set_string (keyfile, group.c_str(), CSV_COL_TYPES, column_types);
g_key_file_set_string (keyfile, group.c_str(), CSV_COL_WIDTHS, column_widths);
// Do a test read of column types
GError *key_error = nullptr;
bool error = false;
gchar *test_string = g_key_file_get_string (keyfile, group.c_str(), CSV_COL_TYPES, &key_error);
if ((key_error) || (g_strcmp0 (test_string, column_types) != 0))
{
if (key_error)
{
g_warning ("Error reading group %s key %s: %s", group.c_str(), CSV_COL_TYPES, 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, test_string, group.c_str());
error = true;
}
g_free (test_string);
return error;
}

View File

@ -27,6 +27,12 @@
#ifndef GNC_CSV_TRANS_SETTINGS_H
#define GNC_CSV_TRANS_SETTINGS_H
extern "C" {
#include <gtk/gtk.h>
}
#include <string>
/** Enumeration for separator checkbutton types. These are the
* different types of checkbuttons that the user can click to
* configure separators in a delimited file. */
@ -36,66 +42,64 @@ 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};
typedef struct
struct CsvTransSettings
{
int header_rows; // Number of header rows
int footer_rows; // Number of footer rows
gboolean csv_format; // CSV import Format
gboolean skip_alt_rows; // Skip alternate rows
gboolean multi_split; // Assume multiple lines per transaction
CsvTransSettings() : header_rows{0}, footer_rows{0}, csv_format (true),
skip_alt_rows (false), multi_split (false),
encoding {"UTF-8"}, custom {false}, custom_entry {nullptr},
date_active {0}, currency_active {0},
column_types{nullptr}, column_widths{nullptr}
{
for (uint i = 0; i < SEP_NUM_OF_TYPES; i++)
{
separator[i] = false;
}
}
const gchar *encoding; // File encoding
gboolean separator[SEP_NUM_OF_TYPES]; // The separators
gboolean custom; // Custom entry set
const gchar *custom_entry; // Custom Entry
int date_active; // Date Active id
int currency_active; // Currency Active id
const gchar *column_types; // The Column types in order
const gchar *column_widths; // The Column widths
} CsvSettings;
/** Finds CSV settings entries in the key file and populates the
/** Finds CSV settings entries in the state key file and populates the
* tree model.
*
* @param settings_store The liststore that is used for the combo's
* which holds the key name and visual text.
*/
void gnc_csv_trans_find_settings (GtkTreeModel *settings_store);
void find (GtkTreeModel *settings_store);
/** Save the gathered widget properties to a key File.
*
* @param settings_data The settings structure where all the settings
* are located.
*
* @param settings_name The name the settings will be stored under.
*
* @return TRUE if there was a problem in saving.
* @return true if there was a problem in saving.
*/
gboolean gnc_csv_trans_save_settings (CsvSettings *settings_data, gchar *settings_name);
bool save (const std::string& settings_name);
/** Load the widget properties from a key File.
*
* @param settings_data The settings structure where all the settings
* are located.
*
* @param group The group name where the settings are stored in the
* key file.
*
* @return TRUE if there was a problem.
* @return true if there was a problem.
*/
gboolean gnc_csv_trans_load_settings (CsvSettings *settings_data, gchar *group);
bool load (const std::string& group);
/** Create a new CsvSettings structure and set default values.
*
* @return CsvSettings settings structure.
*/
CsvSettings * gnc_csv_trans_new_settings_data (void);
/** Free the CsvSettings structure.
*/
void gnc_csv_trans_settings_data_free (CsvSettings *settings_data);
int header_rows; // Number of header rows
int footer_rows; // Number of footer rows
bool csv_format; // CSV import Format
bool skip_alt_rows; // Skip alternate rows
bool multi_split; // Assume multiple lines per transaction
const gchar *encoding; // File encoding
bool separator[SEP_NUM_OF_TYPES]; // The separators
bool custom; // Custom entry set
const gchar *custom_entry; // Custom Entry
int date_active; // Date Active id
int currency_active; // Currency Active id
const gchar *column_types; // The Column types in order
const gchar *column_widths; // The Column widths
};
#endif