GnuCash  5.6-150-g038405b370+
gnc-imp-settings-csv-price.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2  * gnc-imp-settings-csv-price.cpp -- Price CSV Import Settings *
3  * *
4  * Copyright (C) 2017 Robert Fewell *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
11  * This program is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License*
17  * along with this program; if not, contact: *
18  * *
19  * Free Software Foundation Voice: +1-617-542-5942 *
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21  * Boston, MA 02110-1301, USA gnu@gnu.org *
22 \********************************************************************/
29 #include "gnc-imp-settings-csv.hpp"
31 #include <algorithm>
32 #include <memory>
33 #include <sstream>
34 #include <string>
35 #include <vector>
36 #include <cstdint>
37 
38 #include <config.h>
39 
40 #include <gtk/gtk.h>
41 #include <glib/gi18n.h>
42 
43 #include "Account.h"
44 #include "gnc-state.h"
45 #include "gnc-ui-util.h"
46 
47 constexpr auto group_prefix = "Import csv,price - ";
48 
49 #define CSV_COL_TYPES "ColumnTypes"
50 
51 #define CSV_TO_CURR "PriceToCurrency"
52 #define CSV_FROM_COMM "PriceFromCommodity"
53 
54 G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
55 
56 preset_vec_price presets_price;
57 
58 static std::shared_ptr<CsvPriceImpSettings> create_int_no_preset(void)
59 {
60  auto preset = std::make_shared<CsvPriceImpSettings>();
61  preset->m_name = get_no_settings();
62 
63  return preset;
64 }
65 
66 /**************************************************
67  * find
68  *
69  * find all settings entries in the state key file
70  * based on settings type.
71  **************************************************/
72 const preset_vec_price& get_import_presets_price (void)
73 {
74  // Search all Groups in the state key file for ones starting with prefix
75  auto preset_names = std::vector<std::string>();
76  auto keyfile = gnc_state_get_current ();
77  gsize grouplength;
78  gchar **groups = g_key_file_get_groups (keyfile, &grouplength);
79 
80  /* Start by building a sorted list of candidate presets as found in the state file */
81  for (gsize i=0; i < grouplength; i++)
82  {
83  auto group = std::string(groups[i]);
84  auto gp = std::string {group_prefix};
85  auto pos = group.find(gp);
86  if (pos == std::string::npos)
87  continue;
88 
89  preset_names.push_back(group.substr(gp.size()));
90  }
91  // string array from the state file is no longer needed now.
92  g_strfreev (groups);
93 
94  /* We want our settings to appear sorted alphabetically to the user */
95  std::sort(preset_names.begin(), preset_names.end());
96 
97  /* Now add each preset to our global list */
98  presets_price.clear();
99 
100  /* Start with the internally generated ones */
101  presets_price.push_back(create_int_no_preset());
102  //presets_price.push_back(create_int_gnc_exp_preset()); // Not Required
103 
104  /* Then add all the ones we found in the state file */
105  for (auto preset_name : preset_names)
106  {
107  auto preset = std::make_shared<CsvPriceImpSettings>();
108  preset->m_name = preset_name;
109  preset->load();
110  presets_price.push_back(preset);
111  }
112  return presets_price;
113 }
114 
115 /**************************************************
116  * load
117  *
118  * load the settings from a state key file
119  **************************************************/
120 bool
122 {
123  if (preset_is_reserved_name (m_name))
124  return true;
125 
126  GError *key_error = nullptr;
127  m_load_error = false;
128  auto keyfile = gnc_state_get_current ();
129  auto group = get_group_prefix() + m_name;
130 
131  // Start Loading the settings
132  m_load_error = CsvImportSettings::load(); // load the common settings
133 
134  gchar *key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_TO_CURR, &key_error);
135  if (key_char && *key_char != '\0')
136  m_to_currency = parse_commodity_price_comm (key_char, "");
137  m_load_error |= handle_load_error (&key_error, group);
138  if (key_char)
139  g_free (key_char);
140 
141  key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_FROM_COMM, &key_error);
142  if (key_char && *key_char != '\0')
143  m_from_commodity = parse_commodity_price_comm (key_char, "");
144  m_load_error |= handle_load_error (&key_error, group);
145  if (key_char)
146  g_free (key_char);
147 
148  gsize list_len;
149  m_column_types_price.clear();
150  gchar** col_types_str_price = g_key_file_get_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
151  &list_len, &key_error);
152  for (uint32_t i = 0; i < list_len; i++)
153  {
154  auto col_types_it = std::find_if (gnc_price_col_type_strs.begin(),
155  gnc_price_col_type_strs.end(), test_price_prop_type_str (col_types_str_price[i]));
156  auto prop = GncPricePropType::NONE;
157  if (col_types_it != gnc_price_col_type_strs.end())
158  // Found a valid column type
159  prop = col_types_it->first;
160  else
161  PWARN("Found invalid column type '%s' in group '%s'. Inserting column type 'NONE' instead'.",
162  col_types_str_price[i], group.c_str());
163  m_column_types_price.push_back(prop);
164  }
165  if (col_types_str_price)
166  g_strfreev (col_types_str_price);
167 
168  return m_load_error;
169 }
170 
171 /**************************************************
172  * save
173  *
174  * save settings to a key file
175  **************************************************/
176 bool
178 {
179  if (preset_is_reserved_name (m_name))
180  {
181  PWARN ("Ignoring attempt to save to reserved name '%s'", m_name.c_str());
182  return true;
183  }
184 
185  if ((m_name.find('[') != std::string::npos))
186  {
187  PWARN ("Name '%s' contains invalid characters '[]'. Refusing to save", m_name.c_str());
188  return true;
189  }
190 
191  auto keyfile = gnc_state_get_current ();
192  auto group = get_group_prefix() + m_name;
193 
194  // Drop previous saved settings with this name
195  g_key_file_remove_group (keyfile, group.c_str(), nullptr);
196 
197  // Start Saving the settings
198  bool error = CsvImportSettings::save(); // save the common settings
199 
200  if (error)
201  return error;
202 
203  if (m_to_currency)
204  {
205  auto unique_name = g_strconcat (gnc_commodity_get_namespace (m_to_currency), "::",
206  gnc_commodity_get_mnemonic (m_to_currency), nullptr);
207  g_key_file_set_string (keyfile, group.c_str(), CSV_TO_CURR, unique_name);
208  g_free (unique_name);
209  }
210 
211  if (m_from_commodity)
212  {
213  auto unique_name = g_strconcat (gnc_commodity_get_namespace (m_from_commodity), "::",
214  gnc_commodity_get_mnemonic (m_from_commodity), nullptr);
215  g_key_file_set_string (keyfile, group.c_str(), CSV_FROM_COMM, unique_name);
216  g_free (unique_name);
217  }
218 
219  std::vector<const char*> col_types_str_price;
220  for (auto col_type : m_column_types_price)
221  col_types_str_price.push_back(gnc_price_col_type_strs[col_type]);
222 
223  if (!col_types_str_price.empty())
224  g_key_file_set_string_list (keyfile, group.c_str(), CSV_COL_TYPES,
225  col_types_str_price.data(), col_types_str_price.size());
226 
227  return error;
228 }
229 
230 void
232 {
233  if (preset_is_reserved_name (m_name))
234  return;
235 
237 }
238 
239 const char*
240 CsvPriceImpSettings::get_group_prefix (void)
241 {
242  return group_prefix;
243 }
Functions to load, save and get gui state.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
utility functions for the GnuCash UI
bool load(void)
Load the widget properties from a key File.
CSV Import Settings.
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
Retrieve the namespace for the specified commodity.
void remove(void)
Remove the preset from the state file.
GKeyFile * gnc_state_get_current(void)
Returns a pointer to the most recently loaded state.
Definition: gnc-state.c:248
const preset_vec_price & get_import_presets_price(void)
Creates a vector of CsvPriceImpSettings which combines.
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
Account handling public routines.
bool preset_is_reserved_name(const std::string &name)
Check whether name can be used as a preset name.
bool load(void)
Load the widget properties from a key File.
void remove(void)
Remove the preset from the state file.
bool save(void)
Save the gathered widget properties to a key File.
Functor to check if the above map has an element of which the value equals name.
bool save(void)
Save the gathered widget properties to a key File.
CSV Import Settings.