GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-imp-settings-csv.cpp
Go to the documentation of this file.
1/*******************************************************************\
2 * gnc-imp-settings-csv.cpp -- Save and Load CSV Import Settings *
3 * *
4 * Copyright (C) 2014 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\********************************************************************/
30#include <sstream>
31
32#include <config.h>
33
34#include <gtk/gtk.h>
35#include <glib/gi18n.h>
36
37#include "Account.h"
38#include "gnc-state.h"
39#include "gnc-ui-util.h"
40
41#include <algorithm>
42#include <iostream>
43#include <string>
44
45const std::string csv_group_prefix{"CSV-"};
46const std::string no_settings{N_("No Settings")};
47const std::string gnc_exp{N_("GnuCash Export Format")};
48const std::string gnc_exp_4{N_("GnuCash Export Format (4.x and older)")};
49
50#define CSV_NAME "Name"
51#define CSV_FORMAT "CsvFormat"
52#define CSV_SKIP_ALT "SkipAltLines"
53#define CSV_SKIP_START "SkipStartLines"
54#define CSV_SKIP_END "SkipEndLines"
55
56#define CSV_SEP "Separators"
57#define CSV_ESC "EnableEscape"
58
59#define CSV_CUSTOM "Custom"
60#define CSV_CUSTOM_ENTRY "CustomEntry"
61
62#define CSV_DATE "DateFormat"
63#define CSV_CURRENCY "CurrencyFormat"
64
65#define CSV_ENCODING "Encoding"
66#define CSV_COL_WIDTHS "ColumnWidths"
67
68G_GNUC_UNUSED static QofLogModule log_module = GNC_MOD_IMPORT;
69
70/**************************************************
71 * handle_load_error
72 *
73 * record possible errors in the log file
74 * ignore key-not-found errors though. We'll just
75 * use a default value and go on.
76 **************************************************/
77bool
78handle_load_error (GError **key_error, const std::string& group)
79{
80 if (!*key_error)
81 return false;
82
83 if ((*key_error)->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)
84 {
85 g_clear_error (key_error);
86 return false;
87 }
88
89 g_warning ("Error reading group '%s' : %s", group.c_str(), (*key_error)->message);
90 g_clear_error (key_error);
91 return true;
92}
93
94bool preset_is_reserved_name (const std::string& name)
95{
96 return ((name == no_settings) ||
97 (name == _(no_settings.c_str())) ||
98 (name == gnc_exp) ||
99 (name == _(gnc_exp.c_str())));
100}
101
102std::string get_no_settings (void)
103{
104 return no_settings;
105}
106
107std::string get_gnc_exp (void)
108{
109 return gnc_exp;
110}
111
112std::string get_gnc_exp_4 (void)
113{
114 return gnc_exp_4;
115}
116
117/**************************************************
118 * load_common
119 *
120 * load the settings from a state key file
121 **************************************************/
122bool
124{
125 GError *key_error = nullptr;
126 m_load_error = false;
127 auto group = get_group_prefix() + m_name;
128 auto keyfile = gnc_state_get_current ();
129
130 m_skip_start_lines = g_key_file_get_integer (keyfile, group.c_str(), CSV_SKIP_START, &key_error);
131 m_load_error |= handle_load_error (&key_error, group);
132
133 m_skip_end_lines = g_key_file_get_integer (keyfile, group.c_str(), CSV_SKIP_END, &key_error);
134 m_load_error |= handle_load_error (&key_error, group);
135
136 m_skip_alt_lines = g_key_file_get_boolean (keyfile, group.c_str(), CSV_SKIP_ALT, &key_error);
137 m_load_error |= handle_load_error (&key_error, group);
138
139 auto csv_format = g_key_file_get_boolean (keyfile, group.c_str(), CSV_FORMAT, &key_error);
140 if (key_error) csv_format = true; // default to true, but above command will return false in case of error
141 m_load_error |= handle_load_error (&key_error, group);
142 if (csv_format)
143 m_file_format = GncImpFileFormat::CSV;
144 else
145 m_file_format = GncImpFileFormat::FIXED_WIDTH;
146
147 gchar *key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_SEP, &key_error);
148 if (key_char && *key_char != '\0')
149 m_separators = key_char;
150 m_load_error |= handle_load_error (&key_error, group);
151 if (key_char)
152 g_free (key_char);
153
154 m_enable_escape = g_key_file_get_boolean (keyfile, group.c_str(), CSV_ESC, &key_error);
155 // Older import settings will not have a value for escape processing
156 // so set it to true if no value is found in the file format settings
157 if (key_error && key_error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)
158 m_enable_escape = true;
159 else
160 m_load_error |= handle_load_error (&key_error, group);
161
162 m_date_format = g_key_file_get_integer (keyfile, group.c_str(), CSV_DATE, &key_error);
163 m_load_error |= handle_load_error (&key_error, group);
164
165 m_currency_format = g_key_file_get_integer (keyfile, group.c_str(), CSV_CURRENCY, &key_error);
166 m_load_error |= handle_load_error (&key_error, group);
167
168 key_char = g_key_file_get_string (keyfile, group.c_str(), CSV_ENCODING, &key_error);
169 if (key_char && *key_char != '\0')
170 m_encoding = key_char;
171 else
172 m_encoding = "UTF-8";
173 m_load_error |= handle_load_error (&key_error, group);
174 if (key_char)
175 g_free (key_char);
176
177 // Widths
178 gsize list_len;
179 m_column_widths.clear();
180 gint *col_widths_int = g_key_file_get_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS,
181 &list_len, &key_error);
182 for (uint32_t i = 0; i < list_len; i++)
183 {
184 if (col_widths_int[i] > 0)
185 m_column_widths.push_back(col_widths_int[i]);
186 }
187 m_load_error |= handle_load_error (&key_error, group);
188 if (col_widths_int)
189 g_free (col_widths_int);
190
191 return m_load_error;
192}
193
194/**************************************************
195 * save_common
196 *
197 * save settings to a key file
198 **************************************************/
199bool
201{
202 auto keyfile = gnc_state_get_current ();
203 auto group = get_group_prefix() + m_name;
204
205 // Start Saving the Common settings
206 g_key_file_set_string (keyfile, group.c_str(), CSV_NAME, m_name.c_str());
207
208 g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_START, m_skip_start_lines);
209 g_key_file_set_integer (keyfile, group.c_str(), CSV_SKIP_END, m_skip_end_lines);
210 g_key_file_set_boolean (keyfile, group.c_str(), CSV_SKIP_ALT, m_skip_alt_lines);
211 g_key_file_set_boolean (keyfile, group.c_str(), CSV_FORMAT,
212 (m_file_format == GncImpFileFormat::CSV) ? true : false);
213
214 g_key_file_set_string (keyfile, group.c_str(), CSV_SEP, m_separators.c_str());
215 g_key_file_set_boolean (keyfile, group.c_str(), CSV_ESC, m_enable_escape);
216 g_key_file_set_integer (keyfile, group.c_str(), CSV_DATE, m_date_format);
217 std::ostringstream cmt_ss;
218 cmt_ss << "Supported date formats: ";
219 int fmt_num = 0;
220 std::for_each (GncDate::c_formats.cbegin(), GncDate::c_formats.cend(),
221 [&cmt_ss, &fmt_num](const GncDateFormat& fmt)
222 { cmt_ss << fmt_num++ << ": '" << fmt.m_fmt << "', "; });
223 auto cmt = cmt_ss.str().substr(0, static_cast<long>(cmt_ss.tellp()) - 2);
224 g_key_file_set_comment (keyfile, group.c_str(), CSV_DATE, cmt.c_str(), nullptr);
225 g_key_file_set_integer (keyfile, group.c_str(), CSV_CURRENCY, m_currency_format);
226 g_key_file_set_string (keyfile, group.c_str(), CSV_ENCODING, m_encoding.c_str());
227
228 if (!m_column_widths.empty())
229 g_key_file_set_integer_list (keyfile, group.c_str(), CSV_COL_WIDTHS,
230 (gint*)(m_column_widths.data()), m_column_widths.size());
231
232 // Do a test read of encoding
233 GError *key_error = nullptr;
234 bool error = false;
235 auto enc_val = g_key_file_get_string (keyfile, group.c_str(), CSV_ENCODING, &key_error);
236 auto enc_str = std::string{enc_val};
237 if (enc_val)
238 g_free (enc_val);
239
240 if ((key_error) || (enc_str != m_encoding.c_str()))
241 {
242 if (key_error)
243 {
244 g_warning ("Error reading group %s key %s: %s", group.c_str(), CSV_ENCODING, key_error->message);
245 g_error_free (key_error);
246 }
247 else
248 g_warning ("Error comparing group %s key %s: '%s' and '%s'", group.c_str(), CSV_ENCODING, enc_str.c_str(), group.c_str());
249 error = true;
250 }
251 return error;
252}
253
254void
256{
257 auto keyfile = gnc_state_get_current ();
258 auto group = get_group_prefix() + m_name;
259 g_key_file_remove_group (keyfile, group.c_str(), nullptr);
260}
Account handling public routines.
const std::string m_fmt
A string representing the format.
static const std::vector< GncDateFormat > c_formats
A vector with all the date formats supported by the string constructor.
bool preset_is_reserved_name(const std::string &name)
Check whether name can be used as a preset name.
CSV Import Settings.
Functions to load, save and get gui state.
utility functions for the GnuCash UI
GKeyFile * gnc_state_get_current(void)
Returns a pointer to the most recently loaded state.
Definition gnc-state.c:248
bool save(void)
Save the gathered widget properties to a key File.
bool load(void)
Load the widget properties from a key File.
void remove(void)
Remove the preset from the state file.