GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-currency-edit.cpp
1/*
2 * gnc-currency-edit.c -- Currency editor widget
3 *
4 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
5 * All rights reserved.
6 *
7 * Gnucash is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public License
9 * as published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * Gnucash is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, contact:
19 *
20 * Free Software Foundation Voice: +1-617-542-5942
21 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
22 * Boston, MA 02110-1301, USA gnu@gnu.org
23 *
24 */
25
49#include <config.h>
50
51#include <gtk/gtk.h>
52#include <glib/gi18n.h>
53#include <string.h>
54#include <ctype.h>
55#include <stdio.h>
56
57#include "gnc-currency-edit.h"
58#include "gnc-commodity.h"
59#include "gnc-gtk-utils.h"
60#include "gnc-ui-util.h"
61#include "gnc-engine.h"
62#include "dialog-utils.h"
63
65static QofLogModule log_module = GNC_MOD_GUI;
66
67static void gnc_currency_edit_finalize (GObject *object);
68static void gnc_currency_edit_mnemonic_changed (GObject *gobject,
69 GParamSpec *pspec,
70 gpointer user_data);
71static void gnc_currency_edit_active_changed (GtkComboBox *gobject,
72 gpointer user_data);
73
75{
76 GtkComboBox combobox;
77
78 gchar *mnemonic;
79};
80
81G_DEFINE_TYPE(GNCCurrencyEdit, gnc_currency_edit, GTK_TYPE_COMBO_BOX)
82
83
86enum
87{
88 PROP_0,
89
90 PROP_GCE_MNEMONIC,
91
92 N_PROPERTIES
93};
94
95static GParamSpec *obj_properties[N_PROPERTIES] = { nullptr, };
96
97static void
98gnc_currency_edit_set_property (GObject *object,
99 guint property_id,
100 const GValue *value,
101 GParamSpec *pspec)
102{
103 GNCCurrencyEdit *self = GNC_CURRENCY_EDIT (object);
104
105 switch (property_id)
106 {
107 case PROP_GCE_MNEMONIC:
108 g_free (self->mnemonic);
109 self->mnemonic = g_value_dup_string (value);
110 DEBUG ("mnemonic: %s\n", self->mnemonic);
111 break;
112
113 default:
114 /* We don't have any other property... */
115 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
116 break;
117 }
118}
119
120static void
121gnc_currency_edit_get_property (GObject *object,
122 guint property_id,
123 GValue *value,
124 GParamSpec *pspec)
125{
126 GNCCurrencyEdit *self = GNC_CURRENCY_EDIT (object);
127
128 switch (property_id)
129 {
130 case PROP_GCE_MNEMONIC:
131 g_value_set_string (value, self->mnemonic);
132 break;
133
134 default:
135 /* We don't have any other property... */
136 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
137 break;
138 }
139}
140
147static void
148gnc_currency_edit_class_init (GNCCurrencyEditClass *klass)
149{
150 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
151
152 gobject_class->set_property = gnc_currency_edit_set_property;
153 gobject_class->get_property = gnc_currency_edit_get_property;
154 gobject_class->finalize = gnc_currency_edit_finalize;
155
156 obj_properties[PROP_GCE_MNEMONIC] =
157 g_param_spec_string ("mnemonic",
158 "Active currency's mnemonic",
159 "Active currency's mnemonic",
160 "USD" /* default value */,
161 G_PARAM_READWRITE);
162
163 g_object_class_install_properties (gobject_class,
164 N_PROPERTIES,
165 obj_properties);
166}
167
168
175static void
176gnc_currency_edit_init (GNCCurrencyEdit *gce)
177{
178 // Set the name for this widget so it can be easily manipulated with css
179 gtk_widget_set_name (GTK_WIDGET(gce), "gnc-id-currency-edit");
180
181 g_signal_connect (gce, "notify::mnemonic",
182 G_CALLBACK (gnc_currency_edit_mnemonic_changed), gce);
183 g_signal_connect (gce, "changed",
184 G_CALLBACK (gnc_currency_edit_active_changed), gce);
185}
186
187
198static void
199gnc_currency_edit_finalize (GObject *object)
200{
201 g_return_if_fail (object != nullptr);
202 g_return_if_fail (GNC_IS_CURRENCY_EDIT (object));
203
204 GNCCurrencyEdit *self = GNC_CURRENCY_EDIT(object);
205
206 g_free (self->mnemonic);
207
208 G_OBJECT_CLASS(gnc_currency_edit_parent_class)->finalize (object);
209}
210
211
212static void
213gnc_currency_edit_mnemonic_changed (GObject *gobject,
214 GParamSpec *pspec,
215 gpointer user_data)
216{
217
218 GNCCurrencyEdit *self = GNC_CURRENCY_EDIT (gobject);
219
220 gnc_commodity *currency = gnc_commodity_table_lookup (gnc_get_current_commodities (),
221 GNC_COMMODITY_NS_CURRENCY,
222 self->mnemonic);
223
224 /* If there isn't any such commodity, get the default */
225 if (!currency)
226 {
227 currency = gnc_locale_default_currency();
228 DEBUG("gce %p, default currency mnemonic %s",
229 self, gnc_commodity_get_mnemonic(currency));
230 }
231
232 g_signal_handlers_block_by_func(G_OBJECT(self),
233 (gpointer)gnc_currency_edit_mnemonic_changed,
234 user_data);
235 gnc_currency_edit_set_currency(self, currency);
236 g_signal_handlers_unblock_by_func(G_OBJECT(self),
237 (gpointer)gnc_currency_edit_mnemonic_changed,
238 user_data);
239}
240
241
242static void gnc_currency_edit_active_changed (GtkComboBox *gobject,
243 gpointer user_data)
244{
245 GNCCurrencyEdit *self = GNC_CURRENCY_EDIT (gobject);
246
247 /* Check that there is a proper selection before proceeding. Doing so allows
248 * GTK entry completion to proceed. */
249 if (gtk_combo_box_get_active(GTK_COMBO_BOX(self)) != -1)
250 {
251 gnc_commodity *currency = gnc_currency_edit_get_currency (self);
252 const gchar *mnemonic = gnc_commodity_get_mnemonic (currency);
253
254 g_signal_handlers_block_by_func(G_OBJECT(self),
255 (gpointer)gnc_currency_edit_active_changed, user_data);
256 g_object_set (G_OBJECT (self), "mnemonic", mnemonic, nullptr);
257 g_signal_handlers_unblock_by_func(G_OBJECT(self),
258 (gpointer)gnc_currency_edit_active_changed, user_data);
259 }
260}
261
262enum
263{
264 CURRENCY_COL_NAME,
265 CURRENCY_COL_NORMALIZED_FOLDED,
266 NUM_CURRENCY_COLS
267};
268
279static void
280add_item(gnc_commodity *commodity, GNCCurrencyEdit *gce)
281{
282 GtkTreeModel *model;
283 GtkTreeIter iter;
284 const char *string;
285 gchar *normalized, *normalized_folded;
286
287 model = gtk_combo_box_get_model(GTK_COMBO_BOX(gce));
288
289 string = gnc_commodity_get_printname(commodity);
290 normalized = g_utf8_normalize (string, -1, G_NORMALIZE_NFC);
291 normalized_folded = normalized ? g_utf8_casefold (normalized, -1) : nullptr;
292
293 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
294 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
295 CURRENCY_COL_NAME, string,
296 CURRENCY_COL_NORMALIZED_FOLDED, normalized_folded,
297 -1);
298 g_free (normalized_folded);
299 g_free (normalized);
300}
301
302
311static void
312fill_currencies(GNCCurrencyEdit *gce)
313{
314 GList *currencies;
315
317 (gnc_get_current_commodities (), GNC_COMMODITY_NS_CURRENCY);
318 g_list_foreach(currencies, (GFunc)add_item, gce);
319 g_list_free(currencies);
320}
321
322
323static gboolean
324match_func (GtkEntryCompletion *completion, const char *entry_str,
325 GtkTreeIter *iter, GtkTreeModel *model)
326{
327 gchar *currency_name;
328 gboolean ret = FALSE;
329 gtk_tree_model_get (model, iter,
330 CURRENCY_COL_NORMALIZED_FOLDED, &currency_name,
331 -1);
332 if (currency_name && *currency_name && strstr (currency_name, entry_str))
333 ret = TRUE;
334 g_free (currency_name);
335 return ret;
336}
337
338/* Create a new GNCCurrencyEdit widget which can be used to provide
339 * an easy way to enter ISO currency codes.
340 *
341 * @return A GNCCurrencyEdit widget.
342 */
343GtkWidget *
345{
346 GNCCurrencyEdit *gce;
347 GtkListStore *store;
348 GtkEntryCompletion* completion;
349
350 store = gtk_list_store_new (NUM_CURRENCY_COLS, G_TYPE_STRING, G_TYPE_STRING);
351 gce = GNC_CURRENCY_EDIT(g_object_new (GNC_TYPE_CURRENCY_EDIT,
352 "model", store,
353 "has-entry", true,
354 nullptr));
355 g_object_unref (store);
356
357 /* Set the column for the text */
358 gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX(gce), CURRENCY_COL_NAME);
359
360 /* Now the signals to make sure the user can't leave the
361 widget without a valid currency. */
362 gnc_cbwe_require_list_item(GTK_COMBO_BOX(gce));
363
364 /* Fill in all the data. */
365 fill_currencies (gce);
366 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
367 CURRENCY_COL_NAME,
368 GTK_SORT_ASCENDING);
369
370 completion = gtk_entry_completion_new ();
371 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL(store));
372 gtk_entry_completion_set_text_column (completion, CURRENCY_COL_NAME);
373 gtk_entry_completion_set_match_func (completion,
374 (GtkEntryCompletionMatchFunc)match_func,
375 GTK_TREE_MODEL(store), nullptr);
376 gtk_entry_set_completion (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (gce))),
377 completion);
378
379 return GTK_WIDGET (gce);
380}
381
387/* Set the widget to display a certain currency name.
388 *
389 * @param gce The currency editor widget to set.
390 *
391 * @param currency The currency to set as the displayed/selected
392 * value of the widget.
393 */
394void
395gnc_currency_edit_set_currency (GNCCurrencyEdit *gce,
396 const gnc_commodity *currency)
397{
398 const gchar *printname;
399
400 g_return_if_fail(gce != nullptr);
401 g_return_if_fail(GNC_IS_CURRENCY_EDIT(gce));
402 g_return_if_fail(currency != nullptr);
403
404 printname = gnc_commodity_get_printname(currency);
405 gnc_cbwe_set_by_string(GTK_COMBO_BOX(gce), printname);
406}
407
408
409/* Retrieve the displayed currency of the widget.
410 *
411 * @param gce The currency editor widget whose values should be retrieved.
412 *
413 * @return A pointer to the selected currency (a gnc_commodity
414 * structure).
415 */
416gnc_commodity *
417gnc_currency_edit_get_currency (GNCCurrencyEdit *gce)
418{
419 gnc_commodity *commodity;
420 char *mnemonic, *name;
421 GtkTreeModel *model;
422 GtkTreeIter iter;
423
424 g_return_val_if_fail(gce != nullptr, nullptr);
425 g_return_val_if_fail(GNC_IS_CURRENCY_EDIT(gce), nullptr);
426
427 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(gce), &iter))
428 {
429 model = gtk_combo_box_get_model(GTK_COMBO_BOX(gce));
430 gtk_tree_model_get (model, &iter, 0, &mnemonic, -1);
431
432 name = strchr(mnemonic, ' ');
433 if (name != nullptr)
434 *name = '\0';
435 commodity = gnc_commodity_table_lookup (gnc_get_current_commodities (),
436 GNC_COMMODITY_NS_CURRENCY,
437 mnemonic);
438 g_free(mnemonic);
439 }
440 else
441 {
442 g_warning("Combo box returned 'inactive'. Using locale default currency.");
443 commodity = gnc_locale_default_currency();
444 }
445
446
447 return commodity;
448}
449
457void
459{
460 GtkTreeModel *model;
461 GtkWidget *entry;
462
463 g_return_if_fail(gce != nullptr);
464 g_return_if_fail(GNC_IS_CURRENCY_EDIT(gce));
465
466 model = gtk_combo_box_get_model (GTK_COMBO_BOX(gce));
467
468 entry = gtk_bin_get_child (GTK_BIN(gce));
469
470 g_object_ref (model);
471
472 g_signal_handlers_block_by_func (G_OBJECT(gce),
473 (gpointer)gnc_currency_edit_active_changed, gce);
474
475 gtk_combo_box_set_model (GTK_COMBO_BOX(gce), nullptr);
476 gtk_entry_set_text (GTK_ENTRY(entry),"");
477 gtk_combo_box_set_active (GTK_COMBO_BOX(gce), -1);
478 gtk_combo_box_set_model (GTK_COMBO_BOX(gce), model);
479
480 g_signal_handlers_block_by_func (G_OBJECT(gce),
481 (gpointer)gnc_currency_edit_active_changed, gce);
482
483 g_object_unref (model);
484}
485
Commodity handling public routines.
Currency selection widget.
All type declarations for the whole Gnucash engine.
gtk helper routines.
utility functions for the GnuCash UI
const char * gnc_commodity_get_printname(const gnc_commodity *cm)
Retrieve the 'print' name for the specified commodity.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
CommodityList * gnc_commodity_table_get_commodities(const gnc_commodity_table *table, const char *name_space)
Return a list of all commodities in the commodity table that are in the given namespace.
void gnc_currency_edit_set_currency(GNCCurrencyEdit *gce, const gnc_commodity *currency)
Set the widget to display a certain currency name.
void gnc_currency_edit_clear_display(GNCCurrencyEdit *gce)
Clear the displayed currency of the widget.
GtkWidget * gnc_currency_edit_new(void)
Create a new GNCCurrencyEdit widget which can be used to provide an easy way to enter ISO currency co...
gnc_commodity * gnc_currency_edit_get_currency(GNCCurrencyEdit *gce)
Retrieve the displayed currency of the widget.
void gnc_cbwe_set_by_string(GtkComboBox *cbwe, const gchar *text)
Find an entry in the GtkComboBox by its text value, and set the widget to that value.
gnc_commodity * gnc_locale_default_currency(void)
Returns the default currency of the current locale.
#define DEBUG(format, args...)
Print a debugging message.
Definition qoflog.h:264