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