Allow user to only select column_types that make sense in the current context

The context being either multi-split or two-split. There's no use
in selecting a Transaction ID column in two-split mode for example.
Similarly none of the 'Transfer xzy' types will be used in
multi-split mode.
This commit is contained in:
Geert Janssens 2016-12-13 12:22:11 +01:00 committed by Geert Janssens
parent 0b345d471e
commit a0320d3a21
6 changed files with 79 additions and 17 deletions

View File

@ -229,25 +229,21 @@ csv_import_trans_load_settings (CsvImportTrans *info)
}
// Set start row
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);
// Set end row
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);
// 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);
// 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);
// Set Import Format
@ -818,7 +814,9 @@ void csv_import_trans_multisplit_cb (GtkWidget *checkbox, gpointer user_data)
CsvImportTrans *info = (CsvImportTrans*) user_data;
/* Set the skip_alt_lines variable */
info->parse_data->multi_split = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(checkbox));
auto multi_split = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(checkbox));
info->parse_data->set_multi_split (multi_split);
gnc_csv_preview_update_assist (info);
}
@ -1289,7 +1287,7 @@ static void column_type_changed (GtkCellRenderer* renderer, gchar* path,
g_object_get (renderer, "model", &model, "text-column", &textColumn, NULL);
gtk_tree_model_get (model, new_text_iter,
textColumn, &new_text,
1, &new_col_type, // Invisible column in the combobox' model containing the colum type
1, &new_col_type, // Invisible column in the combobox' model containing the column type
-1);
/* Get an iterator for the first (and only) row. */
@ -1615,9 +1613,7 @@ bool get_list_of_accounts (CsvImportTrans* info, GtkTreeModel *store)
}
/* Loads the preview's data into its data treeview. not_empty is true
* when the data treeview already contains data, false otherwise
* (e.g. the first time this function is called on a preview).
/* Loads the preview's data into its data treeview.
*
* @param info The data being previewed
*/
@ -1717,11 +1713,17 @@ static void gnc_csv_preview_update_assist (CsvImportTrans* info)
auto combostore = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
for (auto col_type : gnc_csv_col_type_strs)
{
GtkTreeIter iter;
gtk_list_store_append (combostore, &iter);
gtk_list_store_set (combostore, &iter, 0, _(col_type.second),
1, static_cast<int>(col_type.first),
-1);
/* Only add column types that make sense in
* the chosen import mode (multi-split vs two-split).
*/
if (sanitize_trans_prop(col_type.first, info->parse_data->multi_split) == col_type.first)
{
GtkTreeIter iter;
gtk_list_store_append (combostore, &iter);
gtk_list_store_set (combostore, &iter, 0, _(col_type.second),
1, static_cast<int>(col_type.first),
-1);
}
}
/* Insert columns into the data and column type treeviews. */

View File

@ -57,6 +57,7 @@ const std::string no_settings{N_("No Settings")};
#define CSV_COL_TYPES "ColumnTypes"
#define CSV_COL_WIDTHS "ColumnWidths"
G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
/**************************************************
* find
@ -200,7 +201,16 @@ CsvTransSettings::load (const std::string& group)
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())
column_types.push_back(col_types_it->first);
{
/* 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, multi_split);
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, multi_split ? "enabled" : "disabled");
}
}
if (col_types_str)
g_strfreev (col_types_str);

View File

@ -70,6 +70,29 @@ std::map<GncTransPropType, const char*> gnc_csv_col_type_strs = {
{ GncTransPropType::TREC_DATE, N_("Transfer Reconcile Date") }
};
/* Below two vectors define which properties the user *can't* select
* in two-split or multi-split mode (mostly because they don't make
* sense in that context).
*/
std::vector<GncTransPropType> twosplit_blacklist = {
GncTransPropType::UNIQUE_ID };
std::vector<GncTransPropType> multisplit_blacklist = {
GncTransPropType::TACTION,
GncTransPropType::TACCOUNT,
GncTransPropType::TMEMO,
GncTransPropType::TREC_STATE,
GncTransPropType::TREC_DATE
};
GncTransPropType sanitize_trans_prop (GncTransPropType prop, bool multi_split)
{
auto bl = multi_split ? multisplit_blacklist : twosplit_blacklist;
if (std::find(bl.begin(), bl.end(), prop) == bl.end())
return prop;
else
return GncTransPropType::NONE;
}
/* Regular expressions used to parse dates per date format */
const char* date_regex[] = {
"(?:" // either y-m-d

View File

@ -79,7 +79,6 @@ enum class GncTransPropType {
* changes to enum class GncTransPropType ! */
extern std::map<GncTransPropType, const char*> gnc_csv_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.
*/
@ -94,6 +93,15 @@ private:
const char *m_name;
};
/** Some properties only make sense in a multi-split context.
* Inversely some also only make sense in a two-split context.
* Below function will test a property against a given context
* and will return that property if it makes sense
* or GncTransPropType::NONE if not.
*/
GncTransPropType sanitize_trans_prop (GncTransPropType prop, bool multi_split);
time64 parse_date (const std::string &date_str, int format);
struct GncPreTrans

View File

@ -57,7 +57,6 @@ const gchar* currency_format_user[] = {N_("Locale"),
};
/** Constructor for GncTxImport.
* @return Pointer to a new GncCSvParseData
*/
@ -132,6 +131,24 @@ void GncTxImport::convert_encoding (const std::string& encoding)
tokenizer->encoding(encoding);
}
/** Toggles the multi-split state of the importer and will subsequently
* sanitize the column_types list. All types that don't make sense
* in the new state are reset to type GncTransPropType::NONE.
* @param multi_split_val Boolean value with desired state (multi-split
* vs two-split).
*/
void GncTxImport::set_multi_split (bool multi_split_val)
{
multi_split = multi_split_val;
for (auto col_it = column_types.begin(); col_it != column_types.end();
col_it++)
{
auto san_prop = sanitize_trans_prop (*col_it, multi_split);
if (san_prop != *col_it)
*col_it = san_prop;
}
}
/** Loads a file into a GncTxImport. This is the first function
* that must be called after creating a new GncTxImport. As long as
* this function didn't run successfully, the importer can't proceed.

View File

@ -98,6 +98,8 @@ public:
void load_file (const std::string& filename);
void convert_encoding (const std::string& encoding);
void set_multi_split (bool multi_split_val);
void tokenize (bool guessColTypes);
/** This function will attempt to convert all tokenized lines into