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.
This commit is contained in:
Robert Fewell 2017-12-01 11:25:06 +00:00
parent 1435813f02
commit bf0c3853ac
6 changed files with 525 additions and 97 deletions

View File

@ -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());
}

View File

@ -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>
@ -811,6 +834,125 @@ For example
<property name="position">0</property>
</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">&lt;b&gt;Commodity From&lt;/b&gt;</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">&lt;b&gt;Currency To&lt;/b&gt;</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>
@ -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>

View File

@ -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();

View File

@ -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

View File

@ -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
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;
case GncPricePropType::FROM_COMMODITY:
m_from_commodity = boost::none;
comm = parse_commodity_price_sym (value, false); // Throws if parsing fails
if (comm)
m_symbol_from = 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
if (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) );
rev, gnc_commodity_get_fullname (*m_from_commodity), gnc_commodity_get_fullname (*m_to_currency),
amount.to_string().c_str());
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);
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;
}

View File

@ -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;