1 /********************************************************************
2  * dialog-commodity.c -- "select" and "new" commodity windows       *
3  *                       (GnuCash)                                  *
4  * Copyright (C) 2000 Bill Gribble <grib@billgribble.com>           *
5  * Copyright (c) 2006 David Hampton <hampton@employees.org>         *
6  * Copyright (c) 2011 Robert Fewell                                 *
7  *                                                                  *
8  * This program is free software; you can redistribute it and/or    *
9  * modify it under the terms of the GNU General Public License as   *
10  * published by the Free Software Foundation; either version 2 of   *
11  * the License, or (at your option) any later version.              *
12  *                                                                  *
13  * This program is distributed in the hope that it will be useful,  *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
16  * GNU General Public License for more details.                     *
17  *                                                                  *
18  * You should have received a copy of the GNU General Public License*
19  * along with this program; if not, contact:                        *
20  *                                                                  *
21  * Free Software Foundation           Voice:  +1-617-542-5942       *
22  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
23  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
24  ********************************************************************/
25 
26 /** @addtogroup GUI
27     @{ */
28 /** @addtogroup GuiCommodity
29     @{ */
30 /** @file dialog-commodity.c
31     @brief "select" and "new" commodity windows
32     @author Copyright (C) 2000 Bill Gribble <grib@billgribble.com>
33     @author Copyright (c) 2006 David Hampton <hampton@employees.org>
34 */
35 
36 
37 #include <config.h>
38 
39 #include <gtk/gtk.h>
40 #include <glib/gi18n.h>
41 #include <stdio.h>
42 
43 #include "dialog-commodity.h"
44 #include "dialog-utils.h"
45 #include "gnc-engine.h"
46 #include "gnc-gtk-utils.h"
47 #include "gnc-gui-query.h"
48 #include "gnc-ui-util.h"
49 #include "gnc-ui.h"
50 
51 /* This static indicates the debugging module that this .o belongs to.  */
52 static QofLogModule log_module = GNC_MOD_GUI;
53 
54 enum
55 {
56     SOURCE_COL_NAME = 0,
57     SOURCE_COL_FQ_SUPPORTED,
58     NUM_SOURCE_COLS
59 };
60 
61 struct select_commodity_window
62 {
63     GtkWidget * dialog;
64     GtkWidget * namespace_combo;
65     GtkWidget * commodity_combo;
66     GtkWidget * select_user_prompt;
67     GtkWidget * ok_button;
68 
69     gnc_commodity * selection;
70 
71     const char * default_cusip;
72     const char * default_fullname;
73     const char * default_mnemonic;
74     const char * default_user_symbol;
75     int          default_fraction;
76 };
77 
78 struct commodity_window
79 {
80     GtkWidget * dialog;
81     GtkWidget * table;
82     GtkWidget * fullname_entry;
83     GtkWidget * mnemonic_entry;
84     GtkWidget * user_symbol_entry;
85     GtkWidget * namespace_combo;
86     GtkWidget * code_entry;
87     GtkWidget * fraction_spinbutton;
88     GtkWidget * get_quote_check;
89     GtkWidget * source_label;
90     GtkWidget * source_button[SOURCE_MAX];
91     GtkWidget * source_menu[SOURCE_MAX];
92     GtkWidget * quote_tz_label;
93     GtkWidget * quote_tz_menu;
94     GtkWidget * ok_button;
95 
96     guint comm_section_top;
97     guint comm_section_bottom;
98     guint comm_symbol_line;
99     guint fq_section_top;
100     guint fq_section_bottom;
101 
102     gboolean     is_currency;
103     gnc_commodity *edit_commodity;
104 };
105 
106 typedef struct select_commodity_window SelectCommodityWindow;
107 typedef struct commodity_window CommodityWindow;
108 
109 /* The commodity selection window */
110 static SelectCommodityWindow *
111 gnc_ui_select_commodity_create(const gnc_commodity * orig_sel,
112                                dialog_commodity_mode mode);
113 void gnc_ui_select_commodity_new_cb(GtkButton * button,
114                                     gpointer user_data);
115 void gnc_ui_select_commodity_changed_cb(GtkComboBox *cbwe,
116                                         gpointer user_data);
117 void gnc_ui_select_commodity_namespace_changed_cb(GtkComboBox *cbwe,
118         gpointer user_data);
119 
120 /* The commodity creation window */
121 void gnc_ui_commodity_changed_cb(GtkWidget * dummy, gpointer user_data);
122 void gnc_ui_commodity_quote_info_cb(GtkWidget *w, gpointer data);
123 gboolean gnc_ui_commodity_dialog_to_object(CommodityWindow * w);
124 
125 #if 0
126 static void gnc_ui_select_commodity_response_cb (GtkDialog * dialog, gint response, gpointer data);
127 #endif
128 
129 /********************************************************************
130  * gnc_ui_select_commodity_modal_full()
131  ********************************************************************/
132 gnc_commodity *
gnc_ui_select_commodity_modal_full(gnc_commodity * orig_sel,GtkWidget * parent,dialog_commodity_mode mode,const char * user_message,const char * cusip,const char * fullname,const char * mnemonic)133 gnc_ui_select_commodity_modal_full(gnc_commodity * orig_sel,
134                                    GtkWidget * parent,
135                                    dialog_commodity_mode mode,
136                                    const char * user_message,
137                                    const char * cusip,
138                                    const char * fullname,
139                                    const char * mnemonic)
140 {
141     gnc_commodity * retval = NULL;
142     const gchar *initial;
143     gchar *user_prompt_text;
144     SelectCommodityWindow * win;
145     gboolean done;
146     gint value;
147 
148     win = gnc_ui_select_commodity_create(orig_sel, mode);
149     win->default_cusip = cusip;
150     win->default_fullname = fullname;
151     win->default_mnemonic = mnemonic;
152     win->default_user_symbol = "";
153 
154     if (parent)
155         gtk_window_set_transient_for (GTK_WINDOW (win->dialog), GTK_WINDOW (parent));
156 
157     if (user_message != NULL)
158         initial = user_message;
159     else if ((cusip != NULL) || (fullname != NULL) || (mnemonic != NULL))
160         initial = _("\nPlease select a commodity to match");
161     else
162         initial = "";
163 
164     user_prompt_text =
165         g_strdup_printf("%s%s%s%s%s%s%s",
166                         initial,
167                         fullname ? _("\nCommodity: ") : "",
168                         fullname ? fullname : "",
169                         /* Translators: Replace here and later CUSIP by the name of your local
170                            National Securities Identifying Number
171                            like gb:SEDOL, de:WKN, ch:Valorennummer, fr:SICOVAM ...
172                            See http://en.wikipedia.org/wiki/ISIN and
173                            https://en.wikipedia.org/wiki/National_numbering_agency for hints. */
174                         cusip    ? _("\nExchange code (ISIN, CUSIP or similar): ") : "",
175                         cusip    ? cusip : "",
176                         mnemonic ? _("\nMnemonic (Ticker symbol or similar): ") : "",
177                         mnemonic ? mnemonic : "");
178     gtk_label_set_text ((GtkLabel *)(win->select_user_prompt),
179                         user_prompt_text);
180     g_free(user_prompt_text);
181 
182     /* Run the dialog, handling the terminal conditions. */
183     done = FALSE;
184     while (!done)
185     {
186         switch (value = gtk_dialog_run(GTK_DIALOG(win->dialog)))
187         {
188         case GTK_RESPONSE_OK:
189             DEBUG("case OK");
190             retval = win->selection;
191             done = TRUE;
192             break;
193         case GNC_RESPONSE_NEW:
194             DEBUG("case NEW");
195             gnc_ui_select_commodity_new_cb(NULL, win);
196             break;
197         default:	/* Cancel, Escape, Close, etc. */
198             DEBUG("default: %d", value);
199             retval = NULL;
200             done = TRUE;
201             break;
202         }
203     }
204     gtk_widget_destroy (GTK_WIDGET (win->dialog)); /* Close and destroy */
205     g_free(win);
206 
207     return retval;
208 }
209 
210 
211 /********************************************************************
212  * gnc_ui_select_commodity_modal()
213  ********************************************************************/
214 gnc_commodity *
gnc_ui_select_commodity_modal(gnc_commodity * orig_sel,GtkWidget * parent,dialog_commodity_mode mode)215 gnc_ui_select_commodity_modal(gnc_commodity * orig_sel,
216                               GtkWidget * parent,
217                               dialog_commodity_mode mode)
218 {
219     return gnc_ui_select_commodity_modal_full(orig_sel,
220             parent,
221             mode,
222             NULL,
223             NULL,
224             NULL,
225             NULL);
226 }
227 
228 
229 /********************************************************************
230  * gnc_ui_select_commodity_create()
231  ********************************************************************/
232 static SelectCommodityWindow *
gnc_ui_select_commodity_create(const gnc_commodity * orig_sel,dialog_commodity_mode mode)233 gnc_ui_select_commodity_create(const gnc_commodity * orig_sel,
234                                dialog_commodity_mode mode)
235 {
236     SelectCommodityWindow * retval = g_new0(SelectCommodityWindow, 1);
237     GtkBuilder *builder;
238     const char *title, *text;
239     gchar *name_space;
240     GtkWidget *button, *label;
241 
242     builder = gtk_builder_new();
243     gnc_builder_add_from_file (builder, "dialog-commodity.glade", "liststore1");
244     gnc_builder_add_from_file (builder, "dialog-commodity.glade", "liststore2");
245     gnc_builder_add_from_file (builder, "dialog-commodity.glade", "security_selector_dialog");
246 
247     gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, retval);
248 
249     retval->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "security_selector_dialog"));
250     retval->namespace_combo = GTK_WIDGET(gtk_builder_get_object (builder, "ss_namespace_cbwe"));
251     retval->commodity_combo = GTK_WIDGET(gtk_builder_get_object (builder, "ss_commodity_cbwe"));
252     retval->select_user_prompt = GTK_WIDGET(gtk_builder_get_object (builder, "select_user_prompt"));
253     retval->ok_button = GTK_WIDGET(gtk_builder_get_object (builder, "ss_ok_button"));
254     label = GTK_WIDGET(gtk_builder_get_object (builder, "item_label"));
255 
256     // Set the name for this dialog so it can be easily manipulated with css
257     gtk_widget_set_name (GTK_WIDGET(retval->dialog), "gnc-id-security-select");
258     gnc_widget_style_context_add_class (GTK_WIDGET(retval->dialog), "gnc-class-securities");
259 
260     gnc_cbwe_require_list_item(GTK_COMBO_BOX(retval->namespace_combo));
261     gnc_cbwe_require_list_item(GTK_COMBO_BOX(retval->commodity_combo));
262 
263     gtk_label_set_text (GTK_LABEL (retval->select_user_prompt), "");
264 
265 #ifdef DRH
266     g_signal_connect (G_OBJECT (retval->dialog), "close",
267                       G_CALLBACK (select_commodity_close), retval);
268     g_signal_connect (G_OBJECT (retval->dialog), "response",
269                       G_CALLBACK (gnc_ui_select_commodity_response_cb), retval);
270 #endif
271 
272     switch (mode)
273     {
274     case DIAG_COMM_ALL:
275         title = _("Select security/currency");
276         text = _("_Security/currency");
277         break;
278     case DIAG_COMM_NON_CURRENCY:
279     case DIAG_COMM_NON_CURRENCY_SELECT:
280         title = _("Select security");
281         text = _("_Security");
282         break;
283     case DIAG_COMM_CURRENCY:
284     default:
285         title = _("Select currency");
286         text = _("Cu_rrency");
287         button = GTK_WIDGET(gtk_builder_get_object (builder, "ss_new_button"));
288         gtk_widget_destroy(button);
289         break;
290     }
291     gtk_window_set_title (GTK_WINDOW(retval->dialog), title);
292     gtk_label_set_text_with_mnemonic (GTK_LABEL(label), text);
293 
294     /* build the menus of namespaces and commodities */
295     gnc_ui_update_namespace_picker(retval->namespace_combo,
296                                    gnc_commodity_get_namespace(orig_sel),
297                                    mode);
298     name_space = gnc_ui_namespace_picker_ns(retval->namespace_combo);
299     gnc_ui_update_commodity_picker(retval->commodity_combo, name_space,
300                                    gnc_commodity_get_printname(orig_sel));
301 
302     g_object_unref(G_OBJECT(builder));
303 
304     g_free(name_space);
305     return retval;
306 }
307 
308 
309 /**
310  *  This function is called whenever the user clicks on the "New"
311  *  button in the commodity picker.  Its function is pop up a new
312  *  dialog alling the user to create a new commodity.
313  *
314  *  @note This function is an internal helper function for the
315  *  Commodity Selection dialog.  It should not be used outside of the
316  *  dialog-commodity.c file.
317  *
318  *  @param button A pointer to the "new" button widget in the dialog.
319  *
320  *  @param user_data A pointer to the data structure describing the
321  *  current state of the commodity picker.
322  */
323 void
gnc_ui_select_commodity_new_cb(GtkButton * button,gpointer user_data)324 gnc_ui_select_commodity_new_cb(GtkButton * button,
325                                gpointer user_data)
326 {
327     SelectCommodityWindow * w = user_data;
328 
329     gchar * name_space = gnc_ui_namespace_picker_ns (w->namespace_combo);
330 
331     const gnc_commodity * new_commodity =
332         gnc_ui_new_commodity_modal_full(name_space,
333                                         w->dialog,
334                                         w->default_cusip,
335                                         w->default_fullname,
336                                         w->default_mnemonic,
337                                         w->default_user_symbol,
338                                         w->default_fraction);
339     if (new_commodity)
340     {
341         gnc_ui_update_namespace_picker(w->namespace_combo,
342                                        gnc_commodity_get_namespace(new_commodity),
343                                        DIAG_COMM_ALL);
344         gnc_ui_update_commodity_picker(w->commodity_combo,
345                                        gnc_commodity_get_namespace(new_commodity),
346                                        gnc_commodity_get_printname(new_commodity));
347     }
348     g_free(name_space);
349 }
350 
351 
352 /**
353  *  This function is called whenever the commodity combo box is
354  *  changed.  Its function is to determine if a valid commodity has
355  *  been selected, record the selection, and update the OK button.
356  *
357  *  @note This function is an internal helper function for the
358  *  Commodity Selection dialog.  It should not be used outside of the
359  *  dialog-commodity.c file.
360  *
361  *  @param cbwe A pointer to the commodity name entry widget in the
362  *  dialog.
363  *
364  *  @param user_data A pointer to the data structure describing the
365  *  current state of the commodity picker.
366  */
367 void
gnc_ui_select_commodity_changed_cb(GtkComboBox * cbwe,gpointer user_data)368 gnc_ui_select_commodity_changed_cb (GtkComboBox *cbwe,
369                                     gpointer user_data)
370 {
371     SelectCommodityWindow * w = user_data;
372     gchar *name_space;
373     const gchar *fullname;
374     gboolean ok;
375 
376     ENTER("cbwe=%p, user_data=%p", cbwe, user_data);
377     name_space = gnc_ui_namespace_picker_ns (w->namespace_combo);
378     fullname = gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(GTK_BIN (GTK_COMBO_BOX(w->commodity_combo)))));
379 
380     DEBUG("namespace=%s, name=%s", name_space, fullname);
381     w->selection = gnc_commodity_table_find_full(gnc_get_current_commodities(),
382                    name_space, fullname);
383     g_free(name_space);
384 
385     ok = (w->selection != NULL);
386     gtk_widget_set_sensitive(w->ok_button, ok);
387     gtk_dialog_set_default_response(GTK_DIALOG(w->dialog), ok ? 0 : 2);
388     LEAVE("sensitive=%d, default = %d", ok, ok ? 0 : 2);
389 }
390 
391 
392 /**
393  *  This function is called whenever the commodity namespace combo box
394  *  is changed.  Its function is to update the commodity name combo
395  *  box with the strings that are appropriate to the selected
396  *  namespace.
397  *
398  *  @note This function is an internal helper function for the
399  *  Commodity Selection dialog.  It should not be used outside of the
400  *  dialog-commodity.c file.
401  *
402  *  @param cbwe A pointer to the commodity namespace entry widget in
403  *  the dialog.
404  *
405  *  @param user_data A pointer to the data structure describing the
406  *  current state of the commodity picker.
407  */
408 void
gnc_ui_select_commodity_namespace_changed_cb(GtkComboBox * cbwe,gpointer user_data)409 gnc_ui_select_commodity_namespace_changed_cb (GtkComboBox *cbwe,
410         gpointer user_data)
411 {
412     SelectCommodityWindow * w = user_data;
413     gchar *name_space;
414 
415     ENTER("cbwe=%p, user_data=%p", cbwe, user_data);
416     name_space = gnc_ui_namespace_picker_ns (w->namespace_combo);
417     DEBUG("name_space=%s", name_space);
418     gnc_ui_update_commodity_picker(w->commodity_combo, name_space, NULL);
419     g_free(name_space);
420     LEAVE(" ");
421 }
422 
423 
424 /********************************************************************
425  * gnc_ui_update_commodity_picker
426  ********************************************************************/
427 static int
collate(gconstpointer a,gconstpointer b)428 collate(gconstpointer a, gconstpointer b)
429 {
430     if (!a)
431         return -1;
432     if (!b)
433         return 1;
434     return g_utf8_collate(a, b);
435 }
436 
437 
438 void
gnc_ui_update_commodity_picker(GtkWidget * cbwe,const gchar * name_space,const gchar * init_string)439 gnc_ui_update_commodity_picker (GtkWidget *cbwe,
440                                 const gchar * name_space,
441                                 const gchar * init_string)
442 {
443     GList      * commodities;
444     GList      * iterator = NULL;
445     GList      * commodity_items = NULL;
446     GtkComboBox *combo_box;
447     GtkEntry *entry;
448     GtkTreeModel *model;
449     GtkTreeIter iter;
450     gnc_commodity_table *table;
451     gint current = 0, match = 0;
452     gchar *name;
453 
454     g_return_if_fail(GTK_IS_COMBO_BOX(cbwe));
455     g_return_if_fail(name_space);
456 
457     /* Erase the old entries */
458     combo_box = GTK_COMBO_BOX(cbwe);
459     model = gtk_combo_box_get_model(combo_box);
460     gtk_list_store_clear(GTK_LIST_STORE(model));
461 
462     /* Erase the entry text */
463     entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(combo_box)));
464     gtk_editable_delete_text(GTK_EDITABLE(entry), 0, -1);
465 
466     gtk_combo_box_set_active(combo_box, -1);
467 
468     table = gnc_commodity_table_get_table (gnc_get_current_book ());
469     commodities = gnc_commodity_table_get_commodities(table, name_space);
470     for (iterator = commodities; iterator; iterator = iterator->next)
471     {
472         commodity_items =
473             g_list_prepend (commodity_items,
474                             (gpointer) gnc_commodity_get_printname(iterator->data));
475     }
476     g_list_free(commodities);
477 
478     commodity_items = g_list_sort(commodity_items, collate);
479     for (iterator = commodity_items; iterator; iterator = iterator->next)
480     {
481         name = (char *)iterator->data;
482         gtk_list_store_append(GTK_LIST_STORE(model), &iter);
483         gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, name, -1);
484 
485         if (init_string && g_utf8_collate(name, init_string) == 0)
486             match = current;
487         current++;
488     }
489 
490     gtk_combo_box_set_active(combo_box, match);
491     g_list_free(commodity_items);
492 }
493 
494 
495 /********************************************************************
496  *
497  * Commodity Selector dialog routines are above this line.
498  *
499  * Commodity New/Edit dialog routines are below this line.
500  *
501  ********************************************************************/
502 static void
gnc_set_commodity_section_sensitivity(GtkWidget * widget,gpointer user_data)503 gnc_set_commodity_section_sensitivity (GtkWidget *widget, gpointer user_data)
504 {
505     CommodityWindow *cw = user_data;
506     guint offset = 0;
507 
508     gtk_container_child_get(GTK_CONTAINER(cw->table), widget,
509                             "top-attach", &offset,
510                             NULL);
511 
512     if ((offset < cw->comm_section_top) || (offset >= cw->comm_section_bottom))
513         return;
514     if (cw->is_currency)
515         gtk_widget_set_sensitive(widget, offset == cw->comm_symbol_line);
516 }
517 
518 static void
gnc_ui_update_commodity_info(CommodityWindow * cw)519 gnc_ui_update_commodity_info (CommodityWindow *cw)
520 {
521     gtk_container_foreach(GTK_CONTAINER(cw->table),
522                           gnc_set_commodity_section_sensitivity, cw);
523 }
524 
525 
526 static void
gnc_set_fq_sensitivity(GtkWidget * widget,gpointer user_data)527 gnc_set_fq_sensitivity (GtkWidget *widget, gpointer user_data)
528 {
529     CommodityWindow *cw = user_data;
530     guint offset = 0;
531 
532     gtk_container_child_get(GTK_CONTAINER(cw->table), widget,
533                             "top-attach", &offset,
534                             NULL);
535 
536     if ((offset < cw->fq_section_top) || (offset >= cw->fq_section_bottom))
537         return;
538     g_object_set(widget, "sensitive", FALSE, NULL);
539 }
540 
541 
542 static void
gnc_ui_update_fq_info(CommodityWindow * cw)543 gnc_ui_update_fq_info (CommodityWindow *cw)
544 {
545     gtk_container_foreach(GTK_CONTAINER(cw->table),
546                           gnc_set_fq_sensitivity, cw);
547 }
548 
549 
550 /********************************************************************
551  * gnc_ui_update_namespace_picker
552  ********************************************************************/
553 void
gnc_ui_update_namespace_picker(GtkWidget * cbwe,const char * init_string,dialog_commodity_mode mode)554 gnc_ui_update_namespace_picker (GtkWidget *cbwe,
555                                 const char * init_string,
556                                 dialog_commodity_mode mode)
557 {
558     GtkComboBox *combo_box;
559     GtkTreeModel *model;
560     GtkTreeIter iter, match;
561     GList *namespaces, *node;
562     gboolean matched = FALSE;
563 
564     g_return_if_fail(GTK_IS_COMBO_BOX (cbwe));
565 
566     /* Erase the old entries */
567     combo_box = GTK_COMBO_BOX(cbwe);
568     model = gtk_combo_box_get_model(combo_box);
569     gtk_list_store_clear(GTK_LIST_STORE(model));
570 
571     /* fetch a list of the namespaces */
572     switch (mode)
573     {
574     case DIAG_COMM_ALL:
575         namespaces =
576             gnc_commodity_table_get_namespaces (gnc_get_current_commodities());
577         break;
578 
579     case DIAG_COMM_NON_CURRENCY:
580     case DIAG_COMM_NON_CURRENCY_SELECT:
581         namespaces =
582             gnc_commodity_table_get_namespaces (gnc_get_current_commodities());
583         node = g_list_find_custom (namespaces, GNC_COMMODITY_NS_CURRENCY, collate);
584         if (node)
585         {
586             namespaces = g_list_remove_link (namespaces, node);
587             g_list_free_1 (node);
588         }
589 
590         if (gnc_commodity_namespace_is_iso (init_string))
591             init_string = NULL;
592         break;
593 
594     case DIAG_COMM_CURRENCY:
595     default:
596         namespaces = g_list_prepend (NULL, GNC_COMMODITY_NS_CURRENCY);
597         break;
598     }
599 
600     /* First insert "Currencies" entry if requested */
601     if (mode == DIAG_COMM_CURRENCY || mode == DIAG_COMM_ALL)
602     {
603         gtk_list_store_append(GTK_LIST_STORE(model), &iter);
604         gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0,
605                             _(GNC_COMMODITY_NS_ISO_GUI), -1);
606 
607         if (init_string &&
608             (g_utf8_collate(GNC_COMMODITY_NS_ISO_GUI, init_string) == 0))
609         {
610             matched = TRUE;
611             match = iter;
612         }
613     }
614 
615     /* Next insert "All non-currency" entry if requested */
616     if (mode == DIAG_COMM_NON_CURRENCY_SELECT || mode == DIAG_COMM_ALL)
617     {
618         gtk_list_store_append(GTK_LIST_STORE(model), &iter);
619         gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0,
620                             GNC_COMMODITY_NS_NONCURRENCY, -1);
621     }
622 
623     /* add all others to the combobox */
624     namespaces = g_list_sort(namespaces, collate);
625     for (node = namespaces; node; node = node->next)
626     {
627         /* Skip template, legacy and currency namespaces.
628            The latter was added as first entry earlier */
629         if ((g_utf8_collate(node->data, GNC_COMMODITY_NS_LEGACY) == 0) ||
630             (g_utf8_collate(node->data, GNC_COMMODITY_NS_TEMPLATE ) == 0) ||
631             (g_utf8_collate(node->data, GNC_COMMODITY_NS_CURRENCY ) == 0))
632             continue;
633 
634         gtk_list_store_append(GTK_LIST_STORE(model), &iter);
635         gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, node->data, -1);
636 
637         if (init_string &&
638             (g_utf8_collate(node->data, init_string) == 0))
639         {
640             matched = TRUE;
641             match = iter;
642         }
643     }
644 
645     if (!matched)
646         gtk_tree_model_get_iter_first(model, &match);
647     gtk_combo_box_set_active_iter(combo_box, &match);
648     g_list_free(namespaces);
649 }
650 
651 
652 gchar *
gnc_ui_namespace_picker_ns(GtkWidget * cbwe)653 gnc_ui_namespace_picker_ns (GtkWidget *cbwe)
654 {
655     const gchar *name_space;
656 
657     g_return_val_if_fail(GTK_IS_COMBO_BOX (cbwe), NULL);
658 
659     name_space = gtk_entry_get_text( GTK_ENTRY( gtk_bin_get_child( GTK_BIN( GTK_COMBO_BOX(cbwe)))));
660 
661     /* Map several currency related names to one common namespace */
662     if ((g_strcmp0 (name_space, GNC_COMMODITY_NS_ISO) == 0) ||
663         (g_strcmp0 (name_space, GNC_COMMODITY_NS_ISO_GUI) == 0) ||
664         (g_strcmp0 (name_space, _(GNC_COMMODITY_NS_ISO_GUI)) == 0))
665         return g_strdup(GNC_COMMODITY_NS_CURRENCY);
666     else
667         return g_strdup(name_space);
668 }
669 
670 
671 /********************************************************************
672  * gnc_ui_commodity_quote_info_cb                                   *
673  *******************************************************************/
674 void
gnc_ui_commodity_quote_info_cb(GtkWidget * w,gpointer data)675 gnc_ui_commodity_quote_info_cb (GtkWidget *w, gpointer data)
676 {
677     CommodityWindow *cw = data;
678     gboolean get_quote, allow_src, active;
679     const gchar *text;
680     gint i;
681 
682     ENTER(" ");
683     get_quote = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
684 
685     text = gtk_entry_get_text( GTK_ENTRY( gtk_bin_get_child( GTK_BIN( GTK_COMBO_BOX(cw->namespace_combo)))));
686 
687     allow_src = !gnc_commodity_namespace_is_iso(text);
688 
689     gtk_widget_set_sensitive(cw->source_label, get_quote && allow_src);
690 
691     for (i = SOURCE_SINGLE; i < SOURCE_MAX; i++)
692     {
693         if (!cw->source_button[i])
694             continue;
695         active =
696             gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cw->source_button[i]));
697         gtk_widget_set_sensitive(cw->source_button[i], get_quote && allow_src);
698         gtk_widget_set_sensitive(cw->source_menu[i], get_quote && allow_src && active);
699     }
700     gtk_widget_set_sensitive(cw->quote_tz_label, get_quote);
701     gtk_widget_set_sensitive(cw->quote_tz_menu, get_quote);
702     LEAVE(" ");
703 }
704 
705 
706 void
gnc_ui_commodity_changed_cb(GtkWidget * dummy,gpointer user_data)707 gnc_ui_commodity_changed_cb(GtkWidget * dummy, gpointer user_data)
708 {
709     CommodityWindow * w = user_data;
710     gchar *name_space;
711     const char * fullname;
712     const char * mnemonic;
713     gboolean ok;
714 
715     ENTER("widget=%p, user_data=%p", dummy, user_data);
716     if (!w->is_currency)
717     {
718         name_space = gnc_ui_namespace_picker_ns (w->namespace_combo);
719         fullname  = gtk_entry_get_text(GTK_ENTRY(w->fullname_entry));
720         mnemonic  = gtk_entry_get_text(GTK_ENTRY(w->mnemonic_entry));
721         DEBUG("namespace=%s, name=%s, mnemonic=%s", name_space, fullname, mnemonic);
722         ok = (fullname    && name_space    && mnemonic &&
723               fullname[0] && name_space[0] && mnemonic[0]);
724         g_free(name_space);
725     }
726     else
727     {
728         ok = TRUE;
729     }
730     gtk_widget_set_sensitive(w->ok_button, ok);
731     gtk_dialog_set_default_response(GTK_DIALOG(w->dialog), ok ? 0 : 1);
732     LEAVE("sensitive=%d, default = %d", ok, ok ? 0 : 1);
733 }
734 
735 
736 /********************************************************************\
737  * gnc_ui_source_menu_create                                        *
738  *   create the menu of stock quote sources                         *
739  *                                                                  *
740  * Args:    account - account to use to set default choice          *
741  * Returns: the menu                                                *
742  \*******************************************************************/
743 static GtkWidget *
gnc_ui_source_menu_create(QuoteSourceType type)744 gnc_ui_source_menu_create(QuoteSourceType type)
745 {
746     gint i, max;
747     const gchar *name;
748     gboolean supported;
749     GtkListStore *store;
750     GtkTreeIter iter;
751     GtkWidget *combo;
752     GtkCellRenderer *renderer;
753     gnc_quote_source *source;
754 
755     store = gtk_list_store_new(NUM_SOURCE_COLS, G_TYPE_STRING, G_TYPE_BOOLEAN);
756     if (type == SOURCE_CURRENCY)
757     {
758         gtk_list_store_append(store, &iter);
759         gtk_list_store_set(store, &iter,
760                            SOURCE_COL_NAME, _("Currency"),
761                            SOURCE_COL_FQ_SUPPORTED, TRUE,
762                            -1);
763     }
764     else
765     {
766         max = gnc_quote_source_num_entries(type);
767         for (i = 0; i < max; i++)
768         {
769             source = gnc_quote_source_lookup_by_ti(type, i);
770             if (source == NULL)
771                 break;
772             name = gnc_quote_source_get_user_name(source);
773             supported = gnc_quote_source_get_supported(source);
774             gtk_list_store_append(store, &iter);
775             gtk_list_store_set(store, &iter,
776                                SOURCE_COL_NAME, name,
777                                SOURCE_COL_FQ_SUPPORTED, supported,
778                                -1);
779         }
780     }
781 
782     combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
783     g_object_unref(store);
784     renderer = gtk_cell_renderer_text_new();
785     gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE);
786     gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo), renderer,
787                                   "text", SOURCE_COL_NAME);
788     gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo), renderer,
789                                   "sensitive", SOURCE_COL_FQ_SUPPORTED);
790     gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
791     gtk_widget_show(combo);
792     return combo;
793 }
794 
795 
796 /********************************************************************
797  * price quote timezone handling                                    *
798  *******************************************************************/
799 static gchar *
800 known_timezones[] =
801 {
802     "Asia/Tokyo",
803     "Australia/Sydney",
804     "America/New_York",
805     "America/Chicago",
806     "Europe/London",
807     "Europe/Paris",
808     NULL
809 };
810 
811 
812 static guint
gnc_find_timezone_menu_position(const gchar * timezone)813 gnc_find_timezone_menu_position(const gchar *timezone)
814 {
815     /* returns 0 on failure, position otherwise. */
816     gboolean found = FALSE;
817     guint i = 0;
818     while (!found && known_timezones[i])
819     {
820         if (g_strcmp0(timezone, known_timezones[i]) != 0)
821         {
822             i++;
823         }
824         else
825         {
826             found = TRUE;
827         }
828     }
829     if (found) return i + 1;
830     return 0;
831 }
832 
833 
834 static gchar *
gnc_timezone_menu_position_to_string(guint pos)835 gnc_timezone_menu_position_to_string(guint pos)
836 {
837     if (pos == 0) return NULL;
838     return known_timezones[pos - 1];
839 }
840 
841 
842 static GtkWidget *
gnc_ui_quote_tz_menu_create(void)843 gnc_ui_quote_tz_menu_create(void)
844 {
845     GtkWidget  *combo;
846     gchar     **itemstr;
847 
848     /* add items here as needed, but bear in mind that right now these
849        must be timezones that GNU libc understands.  Also, I'd prefer if
850        we only add things here we *know* we need.  That's because in
851        order to be portable to non GNU OSes, we may have to support
852        whatever we add here manually on those systems. */
853 
854     combo = gtk_combo_box_text_new();
855     gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Use local time"));
856     for (itemstr = &known_timezones[0]; *itemstr; itemstr++)
857     {
858         gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), *itemstr);
859     }
860 
861     gtk_widget_show(combo);
862     return combo;
863 }
864 
865 
866 /*******************************************************
867  * Build the new/edit commodity dialog box             *
868  *******************************************************/
869 static CommodityWindow *
gnc_ui_build_commodity_dialog(const char * selected_namespace,GtkWidget * parent,const char * fullname,const char * mnemonic,const char * user_symbol,const char * cusip,int fraction,gboolean edit)870 gnc_ui_build_commodity_dialog(const char * selected_namespace,
871                               GtkWidget  *parent,
872                               const char * fullname,
873                               const char * mnemonic,
874                               const char * user_symbol,
875                               const char * cusip,
876                               int          fraction,
877                               gboolean     edit)
878 {
879     CommodityWindow * retval = g_new0(CommodityWindow, 1);
880     GtkWidget *box;
881     GtkWidget *menu;
882     GtkWidget *widget, *sec_label;
883     GtkBuilder *builder;
884     gboolean include_iso;
885     const gchar *title;
886     gchar *text;
887 
888     ENTER("widget=%p, selected namespace=%s, fullname=%s, mnemonic=%s",
889           parent, selected_namespace, fullname, mnemonic);
890 
891     builder = gtk_builder_new();
892     gnc_builder_add_from_file (builder, "dialog-commodity.glade", "liststore2");
893     gnc_builder_add_from_file (builder, "dialog-commodity.glade", "adjustment1");
894     gnc_builder_add_from_file (builder, "dialog-commodity.glade", "security_dialog");
895 
896     gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, retval);
897 
898     retval->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "security_dialog"));
899 
900     // Set the name for this dialog so it can be easily manipulated with css
901     gtk_widget_set_name (GTK_WIDGET(retval->dialog), "gnc-id-security");
902     gnc_widget_style_context_add_class (GTK_WIDGET(retval->dialog), "gnc-class-securities");
903 
904     if (parent != NULL)
905         gtk_window_set_transient_for (GTK_WINDOW (retval->dialog), GTK_WINDOW (parent));
906 
907     retval->edit_commodity = NULL;
908 
909     /* Get widget pointers */
910     retval->fullname_entry = GTK_WIDGET(gtk_builder_get_object (builder, "fullname_entry"));
911     retval->mnemonic_entry = GTK_WIDGET(gtk_builder_get_object (builder, "mnemonic_entry"));
912     retval->user_symbol_entry = GTK_WIDGET(gtk_builder_get_object (builder, "user_symbol_entry"));
913     retval->namespace_combo = GTK_WIDGET(gtk_builder_get_object (builder, "namespace_cbwe"));
914     retval->code_entry = GTK_WIDGET(gtk_builder_get_object (builder, "code_entry"));
915     retval->fraction_spinbutton = GTK_WIDGET(gtk_builder_get_object (builder, "fraction_spinbutton"));
916     retval->ok_button = GTK_WIDGET(gtk_builder_get_object (builder, "ok_button"));
917     retval->get_quote_check = GTK_WIDGET(gtk_builder_get_object (builder, "get_quote_check"));
918     retval->source_label = GTK_WIDGET(gtk_builder_get_object (builder, "source_label"));
919     retval->source_button[SOURCE_SINGLE] = GTK_WIDGET(gtk_builder_get_object (builder, "single_source_button"));
920     retval->source_button[SOURCE_MULTI] = GTK_WIDGET(gtk_builder_get_object (builder, "multi_source_button"));
921     retval->quote_tz_label = GTK_WIDGET(gtk_builder_get_object (builder, "quote_tz_label"));
922 
923     /* Determine the commodity section of the dialog */
924     retval->table = GTK_WIDGET(gtk_builder_get_object (builder, "edit_table"));
925     sec_label = GTK_WIDGET(gtk_builder_get_object (builder, "security_label"));
926     gtk_container_child_get(GTK_CONTAINER(retval->table), sec_label,
927                             "top-attach", &retval->comm_section_top, NULL);
928 
929     widget = GTK_WIDGET(gtk_builder_get_object (builder, "quote_label"));
930     gtk_container_child_get(GTK_CONTAINER(retval->table), widget,
931                             "top-attach", &retval->comm_section_bottom, NULL);
932 
933     gtk_container_child_get(GTK_CONTAINER(retval->table),
934                             retval->user_symbol_entry, "top-attach",
935                             &retval->comm_symbol_line, NULL);
936 
937     /* Build custom widgets */
938     box = GTK_WIDGET(gtk_builder_get_object (builder, "single_source_box"));
939     if (gnc_commodity_namespace_is_iso(selected_namespace))
940     {
941         menu = gnc_ui_source_menu_create(SOURCE_CURRENCY);
942     }
943     else
944     {
945         menu = gnc_ui_source_menu_create(SOURCE_SINGLE);
946     }
947     retval->source_menu[SOURCE_SINGLE] = menu;
948     gtk_box_pack_start(GTK_BOX(box), menu, TRUE, TRUE, 0);
949 
950     box = GTK_WIDGET(gtk_builder_get_object (builder, "multi_source_box"));
951     menu = gnc_ui_source_menu_create(SOURCE_MULTI);
952     retval->source_menu[SOURCE_MULTI] = menu;
953     gtk_box_pack_start(GTK_BOX(box), menu, TRUE, TRUE, 0);
954 
955     if (gnc_quote_source_num_entries(SOURCE_UNKNOWN))
956     {
957         retval->source_button[SOURCE_UNKNOWN] =
958             GTK_WIDGET(gtk_builder_get_object (builder, "unknown_source_button"));
959         box = GTK_WIDGET(gtk_builder_get_object (builder, "unknown_source_box"));
960         menu = gnc_ui_source_menu_create(SOURCE_UNKNOWN);
961         retval->source_menu[SOURCE_UNKNOWN] = menu;
962         gtk_box_pack_start(GTK_BOX(box), menu, TRUE, TRUE, 0);
963     }
964     else
965     {
966         gtk_grid_set_row_spacing(GTK_GRID(retval->table), 0);
967 
968         widget = GTK_WIDGET(gtk_builder_get_object (builder, "unknown_source_alignment"));
969         gtk_widget_destroy(widget);
970 
971         widget = GTK_WIDGET(gtk_builder_get_object (builder, "unknown_source_box"));
972         gtk_widget_destroy(widget);
973     }
974 
975     box = GTK_WIDGET(gtk_builder_get_object (builder, "quote_tz_box"));
976     retval->quote_tz_menu = gnc_ui_quote_tz_menu_create();
977     gtk_box_pack_start(GTK_BOX(box), retval->quote_tz_menu, TRUE, TRUE, 0);
978 
979     /* Commodity editing is next to nil */
980     if (gnc_commodity_namespace_is_iso(selected_namespace))
981     {
982         retval->is_currency = TRUE;
983         gnc_ui_update_commodity_info (retval);
984         include_iso = TRUE;
985         title = _("Edit currency");
986         text = g_strdup_printf("<b>%s</b>", _("Currency Information"));
987     }
988     else
989     {
990         include_iso = FALSE;
991         title = edit ? _("Edit security") : _("New security");
992         text = g_strdup_printf("<b>%s</b>", _("Security Information"));
993     }
994     gtk_window_set_title(GTK_WINDOW(retval->dialog), title);
995     gtk_label_set_markup(GTK_LABEL(sec_label), text);
996     g_free(text);
997 
998     /* Are price quotes supported */
999     if (gnc_quote_source_fq_installed())
1000     {
1001         gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object (builder, "finance_quote_warning")));
1002     }
1003     else
1004     {
1005         /* Determine the price quote of the dialog */
1006         widget = GTK_WIDGET(gtk_builder_get_object (builder, "fq_warning_alignment"));
1007         gtk_container_child_get(GTK_CONTAINER(retval->table), widget,
1008                                 "top-attach", &retval->fq_section_top, NULL);
1009 
1010         widget = GTK_WIDGET(gtk_builder_get_object (builder, "bottom_alignment"));
1011         gtk_container_child_get(GTK_CONTAINER(retval->table), widget,
1012                                 "top-attach", &retval->fq_section_bottom, NULL);
1013 
1014         gnc_ui_update_fq_info (retval);
1015     }
1016 
1017 #ifdef DRH
1018     g_signal_connect (G_OBJECT (retval->dialog), "close",
1019                       G_CALLBACK (commodity_close), retval);
1020 #endif
1021     /* Fill in any data, top to bottom */
1022     gtk_entry_set_text (GTK_ENTRY (retval->fullname_entry), fullname ? fullname : "");
1023     gtk_entry_set_text (GTK_ENTRY (retval->mnemonic_entry), mnemonic ? mnemonic : "");
1024     gtk_entry_set_text (GTK_ENTRY (retval->user_symbol_entry), user_symbol ? user_symbol : "");
1025     gnc_cbwe_add_completion(GTK_COMBO_BOX(retval->namespace_combo));
1026     gnc_ui_update_namespace_picker(retval->namespace_combo,
1027                                    selected_namespace,
1028                                    include_iso ? DIAG_COMM_ALL : DIAG_COMM_NON_CURRENCY);
1029     gtk_entry_set_text (GTK_ENTRY (retval->code_entry), cusip ? cusip : "");
1030 
1031     if (fraction > 0)
1032         gtk_spin_button_set_value (GTK_SPIN_BUTTON (retval->fraction_spinbutton),
1033                                    fraction);
1034 
1035     g_object_unref(G_OBJECT(builder));
1036 
1037     LEAVE(" ");
1038     return retval;
1039 }
1040 
1041 
1042 static void
gnc_ui_commodity_update_quote_info(CommodityWindow * win,gnc_commodity * commodity)1043 gnc_ui_commodity_update_quote_info(CommodityWindow *win,
1044                                    gnc_commodity *commodity)
1045 {
1046     gnc_quote_source *source;
1047     QuoteSourceType type;
1048     gboolean has_quote_src;
1049     const char *quote_tz;
1050     int pos = 0;
1051 
1052     ENTER(" ");
1053     has_quote_src = gnc_commodity_get_quote_flag (commodity);
1054     source = gnc_commodity_get_quote_source (commodity);
1055     if (source == NULL)
1056         source = gnc_commodity_get_default_quote_source (commodity);
1057     quote_tz = gnc_commodity_get_quote_tz (commodity);
1058 
1059     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (win->get_quote_check),
1060                                   has_quote_src);
1061     if (!gnc_commodity_is_iso(commodity))
1062     {
1063         type = gnc_quote_source_get_type(source);
1064         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->source_button[type]), TRUE);
1065         gtk_combo_box_set_active(GTK_COMBO_BOX(win->source_menu[type]),
1066                                  gnc_quote_source_get_index(source));
1067     }
1068 
1069     if (quote_tz)
1070     {
1071         pos = gnc_find_timezone_menu_position(quote_tz);
1072 //    if(pos == 0) {
1073 //      PWARN("Unknown price quote timezone (%s), resetting to default.",
1074 //	    quote_tz ? quote_tz : "(null)");
1075 //    }
1076     }
1077     gtk_combo_box_set_active(GTK_COMBO_BOX(win->quote_tz_menu), pos);
1078     LEAVE(" ");
1079 }
1080 
1081 
1082 static gnc_commodity *
gnc_ui_common_commodity_modal(gnc_commodity * commodity,GtkWidget * parent,const char * name_space,const char * cusip,const char * fullname,const char * mnemonic,const char * user_symbol,int fraction)1083 gnc_ui_common_commodity_modal(gnc_commodity *commodity,
1084                               GtkWidget * parent,
1085                               const char * name_space,
1086                               const char * cusip,
1087                               const char * fullname,
1088                               const char * mnemonic,
1089                               const char * user_symbol,
1090                               int fraction)
1091 {
1092     CommodityWindow * win;
1093     gnc_commodity *retval = NULL;
1094     gboolean done;
1095     gint value;
1096 
1097     ENTER(" ");
1098 
1099     /* If a commodity was provided, copy out the existing info */
1100     if (commodity)
1101     {
1102         name_space = gnc_commodity_get_namespace (commodity);
1103         fullname = gnc_commodity_get_fullname (commodity);
1104         mnemonic = gnc_commodity_get_mnemonic (commodity);
1105         user_symbol = gnc_commodity_get_nice_symbol (commodity);
1106         cusip = gnc_commodity_get_cusip (commodity);
1107         fraction = gnc_commodity_get_fraction (commodity);
1108     }
1109     else
1110     {
1111         /* Not allowed to create new currencies */
1112         if (gnc_commodity_namespace_is_iso(name_space))
1113         {
1114             name_space = NULL;
1115         }
1116     }
1117 
1118     win = gnc_ui_build_commodity_dialog(name_space, parent, fullname,
1119                                         mnemonic, user_symbol, cusip,
1120                                         fraction, (commodity != NULL));
1121 
1122     /* Update stock quote info based on existing commodity */
1123     gnc_ui_commodity_update_quote_info(win, commodity);
1124     win->edit_commodity = commodity;
1125 
1126     /* Update stock quote sensitivities based on check box */
1127     gnc_ui_commodity_quote_info_cb(win->get_quote_check, win);
1128 
1129     /* Run the dialog, handling the terminal conditions. */
1130     done = FALSE;
1131     while (!done)
1132     {
1133         value = gtk_dialog_run(GTK_DIALOG(win->dialog));
1134         switch (value)
1135         {
1136         case GTK_RESPONSE_OK:
1137             DEBUG("case OK");
1138             done = gnc_ui_commodity_dialog_to_object(win);
1139             retval = win->edit_commodity;
1140             break;
1141         case GTK_RESPONSE_HELP:
1142             DEBUG("case HELP");
1143             gnc_gnome_help (GTK_WINDOW(win->dialog), HF_HELP, HL_COMMODITY);
1144             break;
1145         default:	/* Cancel, Escape, Close, etc. */
1146             DEBUG("default: %d", value);
1147             retval = NULL;
1148             done = TRUE;
1149             break;
1150         }
1151     }
1152     gtk_widget_destroy (GTK_WIDGET (win->dialog)); /* Close and destroy */
1153     g_free(win);
1154 
1155     LEAVE(" ");
1156     return retval;
1157 }
1158 
1159 
1160 /********************************************************
1161  * Create and run the new/edit commodity dialog.        *
1162  ********************************************************/
1163 gnc_commodity *
gnc_ui_new_commodity_modal_full(const char * name_space,GtkWidget * parent,const char * cusip,const char * fullname,const char * mnemonic,const char * user_symbol,int fraction)1164 gnc_ui_new_commodity_modal_full(const char * name_space,
1165                                 GtkWidget * parent,
1166                                 const char * cusip,
1167                                 const char * fullname,
1168                                 const char * mnemonic,
1169                                 const char * user_symbol,
1170                                 int fraction)
1171 {
1172     gnc_commodity *result;
1173 
1174     ENTER(" ");
1175     result = gnc_ui_common_commodity_modal(NULL, parent, name_space, cusip,
1176                                            fullname, mnemonic, user_symbol,
1177                                            10000);
1178     LEAVE(" ");
1179     return result;
1180 }
1181 
1182 
1183 /********************************************************************
1184  * External routine for popping up the new commodity dialog box.    *
1185  ********************************************************************/
1186 gnc_commodity *
gnc_ui_new_commodity_modal(const char * default_namespace,GtkWidget * parent)1187 gnc_ui_new_commodity_modal(const char * default_namespace,
1188                            GtkWidget * parent)
1189 {
1190     gnc_commodity *result;
1191 
1192     ENTER(" ");
1193     result = gnc_ui_common_commodity_modal(NULL, parent, default_namespace, NULL,
1194                                            NULL, NULL, NULL, 0);
1195     LEAVE(" ");
1196     return result;
1197 }
1198 
1199 
1200 /********************************************************************
1201  * gnc_ui_edit_commodity_modal()
1202  ********************************************************************/
1203 /** Given an existing commodity, uses the
1204  *  gnc_ui_build_commodity_dialog() routine to build a basic edit
1205  *  dialog, then fills in the price quote information at the bottom of
1206  *  the dialog.
1207  */
1208 gboolean
gnc_ui_edit_commodity_modal(gnc_commodity * commodity,GtkWidget * parent)1209 gnc_ui_edit_commodity_modal(gnc_commodity *commodity,
1210                             GtkWidget * parent)
1211 {
1212     gnc_commodity *result;
1213 
1214     ENTER(" ");
1215     result = gnc_ui_common_commodity_modal(commodity, parent, NULL, NULL,
1216                                            NULL, NULL, NULL, 0);
1217     LEAVE(" ");
1218     return result != NULL;
1219 }
1220 
1221 
1222 /********************************************************************
1223  * gnc_ui_commodity_dialog_to_object()
1224  ********************************************************************/
1225 gboolean
gnc_ui_commodity_dialog_to_object(CommodityWindow * w)1226 gnc_ui_commodity_dialog_to_object(CommodityWindow * w)
1227 {
1228     gnc_quote_source *source;
1229     QuoteSourceType type;
1230     const char * fullname  = gtk_entry_get_text(GTK_ENTRY(w->fullname_entry));
1231     gchar *name_space = gnc_ui_namespace_picker_ns (w->namespace_combo);
1232     const char * mnemonic  = gtk_entry_get_text(GTK_ENTRY(w->mnemonic_entry));
1233     const char * user_symbol = gtk_entry_get_text(GTK_ENTRY(w->user_symbol_entry));
1234     const char * code      = gtk_entry_get_text(GTK_ENTRY(w->code_entry));
1235     QofBook * book = gnc_get_current_book ();
1236     int fraction = gtk_spin_button_get_value_as_int
1237                    (GTK_SPIN_BUTTON(w->fraction_spinbutton));
1238     const char *string;
1239     gnc_commodity * c;
1240     gint selection;
1241 
1242     ENTER(" ");
1243     /* Special case currencies */
1244     if (gnc_commodity_namespace_is_iso (name_space))
1245     {
1246         if (w->edit_commodity)
1247         {
1248             gboolean quote_set;
1249             quote_set = gtk_toggle_button_get_active
1250                         (GTK_TOGGLE_BUTTON (w->get_quote_check));
1251             c = w->edit_commodity;
1252             gnc_commodity_begin_edit(c);
1253             gnc_commodity_user_set_quote_flag (c, quote_set);
1254             if (quote_set)
1255             {
1256                 selection = gtk_combo_box_get_active(GTK_COMBO_BOX(w->quote_tz_menu));
1257                 string = gnc_timezone_menu_position_to_string(selection);
1258                 gnc_commodity_set_quote_tz(c, string);
1259             }
1260             else
1261                 gnc_commodity_set_quote_tz(c, NULL);
1262 
1263 	    gnc_commodity_set_user_symbol(c, user_symbol);
1264 
1265             gnc_commodity_commit_edit(c);
1266             return TRUE;
1267         }
1268         gnc_warning_dialog (GTK_WINDOW (w->dialog), "%s",
1269                             _("You may not create a new national currency."));
1270         return FALSE;
1271     }
1272 
1273     /* Don't allow user to create commodities in namespace
1274      * "template". That's reserved for scheduled transaction use.
1275      */
1276     if (g_utf8_collate(name_space, GNC_COMMODITY_NS_TEMPLATE) == 0)
1277     {
1278         gnc_warning_dialog (GTK_WINDOW (w->dialog),
1279                             _("%s is a reserved commodity type."
1280                             " Please use something else."), GNC_COMMODITY_NS_TEMPLATE);
1281         return FALSE;
1282     }
1283 
1284     if (fullname && fullname[0] &&
1285             name_space && name_space[0] &&
1286             mnemonic && mnemonic[0])
1287     {
1288         c = gnc_commodity_table_lookup (gnc_get_current_commodities(),
1289                                         name_space, mnemonic);
1290 
1291         if ((!w->edit_commodity && c) ||
1292                 (w->edit_commodity && c && (c != w->edit_commodity)))
1293         {
1294             gnc_warning_dialog (GTK_WINDOW (w->dialog), "%s",  _("That commodity already exists."));
1295             g_free(name_space);
1296             return FALSE;
1297         }
1298 
1299         if (!w->edit_commodity)
1300         {
1301             c = gnc_commodity_new(book, fullname, name_space, mnemonic, code, fraction);
1302             w->edit_commodity = c;
1303             gnc_commodity_begin_edit(c);
1304 
1305             gnc_commodity_set_user_symbol(c, user_symbol);
1306         }
1307         else
1308         {
1309             c = w->edit_commodity;
1310             gnc_commodity_begin_edit(c);
1311 
1312             gnc_commodity_table_remove (gnc_get_current_commodities(), c);
1313 
1314             gnc_commodity_set_fullname (c, fullname);
1315             gnc_commodity_set_mnemonic (c, mnemonic);
1316             gnc_commodity_set_namespace (c, name_space);
1317             gnc_commodity_set_cusip (c, code);
1318             gnc_commodity_set_fraction (c, fraction);
1319             gnc_commodity_set_user_symbol(c, user_symbol);
1320         }
1321 
1322         gnc_commodity_user_set_quote_flag (c, gtk_toggle_button_get_active
1323                                            (GTK_TOGGLE_BUTTON (w->get_quote_check)));
1324 
1325         for (type = SOURCE_SINGLE; type < SOURCE_MAX; type=type+1)
1326         {
1327             if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->source_button[type])))
1328                 break;
1329         }
1330         selection = gtk_combo_box_get_active(GTK_COMBO_BOX(w->source_menu[type]));
1331         source = gnc_quote_source_lookup_by_ti (type, selection);
1332         gnc_commodity_set_quote_source(c, source);
1333 
1334         selection = gtk_combo_box_get_active(GTK_COMBO_BOX(w->quote_tz_menu));
1335         string = gnc_timezone_menu_position_to_string(selection);
1336         gnc_commodity_set_quote_tz(c, string);
1337         gnc_commodity_commit_edit(c);
1338 
1339         /* remember the commodity */
1340         gnc_commodity_table_insert(gnc_get_current_commodities(), c);
1341     }
1342     else
1343     {
1344         gnc_warning_dialog (GTK_WINDOW (w->dialog), "%s",
1345                             _("You must enter a non-empty \"Full name\", "
1346                               "\"Symbol/abbreviation\", "
1347                               "and \"Type\" for the commodity."));
1348         g_free(name_space);
1349         return FALSE;
1350     }
1351     g_free(name_space);
1352     LEAVE(" ");
1353     return TRUE;
1354 }
1355 
1356 /** @} */
1357 /** @} */
1358