]> Dogcows Code - chaz/homebank/blob - src/ui-currency.c
Merge branch 'upstream'
[chaz/homebank] / src / ui-currency.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "homebank.h"
21
22 #include "ui-currency.h"
23
24
25 #define MYDEBUG 0
26
27 #if MYDEBUG
28 #define DB(x) (x);
29 #else
30 #define DB(x);
31 #endif
32
33 /* our global datas */
34 extern struct HomeBank *GLOBALS;
35 extern struct Preferences *PREFS;
36
37 extern Currency4217 iso4217cur[];
38 extern guint n_iso4217cur;
39
40
41 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
42
43 /**
44 * ui_cur_combobox_get_name:
45 *
46 * get the name of the active curee or -1
47 *
48 * Return value: a new allocated name tobe freed with g_free
49 *
50 */
51 gchar *
52 ui_cur_combobox_get_name(GtkComboBox *entry_box)
53 {
54 gchar *cbname;
55 gchar *name = NULL;
56
57 cbname = (gchar *)gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(GTK_BIN (entry_box))));
58
59 if( cbname != NULL)
60 {
61 name = g_strdup(cbname);
62 g_strstrip(name);
63 }
64
65 return name;
66 }
67
68
69 /**
70 * ui_cur_combobox_get_key:
71 *
72 * get the key of the active curee
73 *
74 * Return value: the key or 0
75 *
76 */
77 guint32
78 ui_cur_combobox_get_key(GtkComboBox *entry_box)
79 {
80 GtkTreeModel *model;
81 GtkTreeIter iter;
82 guint32 key = 0;
83
84 if (gtk_combo_box_get_active_iter(entry_box, &iter) == TRUE)
85 {
86 model = gtk_combo_box_get_model(entry_box);
87 gtk_tree_model_get (model, &iter, 1, &key, -1);
88 }
89
90 return key;
91 }
92
93
94 gboolean
95 ui_cur_combobox_set_active(GtkComboBox *entry_box, guint32 key)
96 {
97 GtkTreeModel *model;
98 GtkTreeIter iter;
99 gboolean valid;
100 guint32 cbkey;
101
102 model = gtk_combo_box_get_model(entry_box);
103 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
104 while (valid)
105 {
106 gtk_tree_model_get (model, &iter, 1, &cbkey, -1);
107 if(cbkey == key)
108 break;
109
110 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
111 }
112
113 gtk_combo_box_set_active_iter(entry_box, &iter);
114
115 return FALSE;
116 }
117
118
119
120
121 /**
122 * ui_cur_combobox_add:
123 *
124 * Add a single element (useful for dynamics add)
125 *
126 * Return value: --
127 *
128 */
129 void
130 ui_cur_combobox_add(GtkComboBox *entry_box, Currency *cur)
131 {
132 if( cur->name != NULL )
133 {
134 GtkTreeModel *model;
135 GtkTreeIter iter;
136
137 model = gtk_combo_box_get_model(GTK_COMBO_BOX(entry_box));
138
139 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
140 gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, cur->name, 1, cur->key, -1);
141 }
142 }
143
144 static void
145 ui_cur_combobox_populate_ghfunc(gpointer key, gpointer value, struct curPopContext *ctx)
146 {
147 GtkTreeIter iter;
148 Currency *cur = value;
149
150 if( ( cur->key != ctx->except_key ) )
151 {
152 gtk_list_store_append (GTK_LIST_STORE(ctx->model), &iter);
153 gtk_list_store_set (GTK_LIST_STORE(ctx->model), &iter, 0, cur->name, 1, cur->key, -1);
154 }
155 }
156
157 void
158 ui_cur_combobox_populate_except(GtkComboBox *entry_box, GHashTable *hash, guint32 except_key)
159 {
160 GtkTreeModel *model;
161 struct curPopContext ctx;
162
163 DB( g_print ("ui_cur_combobox_populate\n") );
164
165 model = gtk_combo_box_get_model(GTK_COMBO_BOX(entry_box));
166
167 /* keep our model alive and detach from combobox and completion */
168 g_object_ref(model);
169 gtk_combo_box_set_model(GTK_COMBO_BOX(entry_box), NULL);
170
171 /* clear and populate */
172 ctx.model = model;
173 ctx.except_key = except_key;
174 gtk_list_store_clear (GTK_LIST_STORE(model));
175 g_hash_table_foreach(hash, (GHFunc)ui_cur_combobox_populate_ghfunc, &ctx);
176
177 /* reatach our model */
178 gtk_combo_box_set_model(GTK_COMBO_BOX(entry_box), model);
179 g_object_unref(model);
180
181 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
182
183 }
184
185 /**
186 * ui_cur_combobox_populate:
187 *
188 * Populate the list and completion
189 *
190 * Return value: --
191 *
192 */
193 void
194 ui_cur_combobox_populate(GtkComboBox *entry_box, GHashTable *hash)
195 {
196 ui_cur_combobox_populate_except(entry_box, hash, -1);
197 }
198
199
200 static gint
201 ui_cur_combobox_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
202 {
203 gint ret = 0;
204 gchar *name1, *name2;
205
206 gtk_tree_model_get(model, a, 0, &name1, -1);
207 gtk_tree_model_get(model, b, 0, &name2, -1);
208
209 if (name1 == NULL || name2 == NULL)
210 {
211 if (name1 == NULL && name2 == NULL)
212 goto end;
213
214 ret = (name1 == NULL) ? -1 : 1;
215 }
216 else
217 {
218 ret = g_utf8_collate(name1,name2);
219 }
220
221
222 end:
223
224 g_free(name1);
225 g_free(name2);
226
227 return ret;
228 }
229
230
231 static void
232 ui_cur_combobox_test (GtkCellLayout *cell_layout,
233 GtkCellRenderer *cell,
234 GtkTreeModel *tree_model,
235 GtkTreeIter *iter,
236 gpointer data)
237 {
238 gchar *name;
239
240 gtk_tree_model_get(tree_model, iter,
241 0, &name,
242 -1);
243
244 if( !name )
245 g_object_set(cell, "text", _("(none)"), NULL);
246 else
247 g_object_set(cell, "text", name, NULL);
248
249 //leak
250 g_free(name);
251
252 }
253
254 /**
255 * ui_cur_combobox_new:
256 *
257 * Create a new curee combobox
258 *
259 * Return value: the new widget
260 *
261 */
262 GtkWidget *
263 ui_cur_combobox_new(GtkWidget *label)
264 {
265 GtkListStore *store;
266 GtkWidget *combobox;
267 GtkCellRenderer *renderer;
268
269 store = gtk_list_store_new (2,
270 G_TYPE_STRING,
271 G_TYPE_INT
272 );
273 gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store), ui_cur_combobox_compare_func, NULL, NULL);
274
275 // dothe same for combobox
276
277 combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
278
279 gtk_cell_layout_clear(GTK_CELL_LAYOUT (combobox));
280
281 renderer = gtk_cell_renderer_text_new ();
282 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, TRUE);
283 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer, "text", 0, NULL);
284
285 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combobox),
286 renderer,
287 ui_cur_combobox_test,
288 NULL, NULL);
289
290 g_object_unref(store);
291
292 if(label)
293 gtk_label_set_mnemonic_widget (GTK_LABEL(label), combobox);
294
295 gtk_widget_set_size_request (combobox, 10, -1);
296
297 return combobox;
298 }
299
300
301
302 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
303
304
305
306
307 static void
308 ui_cur_listview_toggled_cb (GtkCellRendererToggle *cell,
309 gchar *path_str,
310 gpointer data)
311 {
312 GtkTreeModel *model = (GtkTreeModel *)data;
313 GtkTreeIter iter;
314 GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
315 gboolean fixed;
316
317 /* get toggled iter */
318 gtk_tree_model_get_iter (model, &iter, path);
319 gtk_tree_model_get (model, &iter, LST_DEFCUR_TOGGLE, &fixed, -1);
320
321 /* do something with the value */
322 fixed ^= 1;
323
324 /* set new value */
325 gtk_list_store_set (GTK_LIST_STORE (model), &iter, LST_DEFCUR_TOGGLE, fixed, -1);
326
327 /* clean up */
328 gtk_tree_path_free (path);
329 }
330
331 static gint
332 ui_cur_listview_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
333 {
334 gint result = 0;
335 Currency *entry1, *entry2;
336 gchar *name1, *name2;
337
338 gtk_tree_model_get(model, a, LST_DEFCUR_DATAS, &entry1, -1);
339 gtk_tree_model_get(model, b, LST_DEFCUR_DATAS, &entry2, -1);
340
341 name1 = (entry1->key == GLOBALS->kcur) ? NULL : entry1->iso_code;
342 name2 = (entry2->key == GLOBALS->kcur) ? NULL : entry2->iso_code;
343
344 result = hb_string_compare(name1,name2);
345
346 return result;
347 }
348
349 static void
350 ui_cur_listview_name_cell_data_function (GtkTreeViewColumn *col,
351 GtkCellRenderer *renderer,
352 GtkTreeModel *model,
353 GtkTreeIter *iter,
354 gpointer user_data)
355 {
356 Currency *entry;
357 gchar *string;
358 gint weight;
359
360 gtk_tree_model_get(model, iter, LST_DEFCUR_DATAS, &entry, -1);
361
362 weight = entry->key == GLOBALS->kcur ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
363
364 #if MYDEBUG
365 if( entry->key == GLOBALS->kcur )
366 string = g_strdup_printf ("[%d] %s - %s<span size=\"small\">\n(%s)</span>", entry->key, entry->iso_code, entry->name, _("Base currency"));
367 else
368 string = g_strdup_printf ("[%d] %s - %s", entry->key, entry->iso_code, entry->name);
369 g_object_set(renderer, "weight", weight, "markup", string, NULL);
370 g_free(string);
371 #else
372 if( entry->key == GLOBALS->kcur )
373 string = g_strdup_printf ("%s - %s<span size=\"small\">\n(%s)</span>", entry->iso_code, entry->name, _("Base currency"));
374 else
375 string = g_strdup_printf ("%s - %s", entry->iso_code, entry->name);
376 g_object_set(renderer, "weight", weight, "markup", string, NULL);
377 g_free(string);
378 #endif
379
380 }
381
382
383 static void
384 ui_cur_listview_symbol_cell_data_function (GtkTreeViewColumn *col,
385 GtkCellRenderer *renderer,
386 GtkTreeModel *model,
387 GtkTreeIter *iter,
388 gpointer user_data)
389 {
390 Currency *entry;
391 gint weight;
392
393 gtk_tree_model_get(model, iter, LST_DEFCUR_DATAS, &entry, -1);
394
395 weight = entry->key == GLOBALS->kcur ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
396
397 g_object_set(renderer, "weight", weight, "text", entry->symbol, NULL);
398 }
399
400
401 static void
402 ui_cur_listview_lastmodified_cell_data_function (GtkTreeViewColumn *col,
403 GtkCellRenderer *renderer,
404 GtkTreeModel *model,
405 GtkTreeIter *iter,
406 gpointer user_data)
407 {
408 Currency *entry;
409 gchar buffer[256];
410 GDate date;
411 gint weight;
412
413 gtk_tree_model_get(model, iter, LST_DEFCUR_DATAS, &entry, -1);
414
415 weight = entry->key == GLOBALS->kcur ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
416
417 if(entry->mdate > 0)
418 {
419 g_date_set_julian (&date, entry->mdate);
420 g_date_strftime (buffer, 256-1, PREFS->date_format, &date);
421
422 //g_snprintf(buf, sizeof(buf), "%d", ope->ope_Date);
423
424 g_object_set(renderer, "weight", weight, "text", buffer, NULL);
425 }
426 else
427 g_object_set(renderer, "weight", weight, "text", "-", NULL);
428 }
429
430
431
432 static void
433 ui_cur_listview_rate_cell_data_function (GtkTreeViewColumn *col,
434 GtkCellRenderer *renderer,
435 GtkTreeModel *model,
436 GtkTreeIter *iter,
437 gpointer user_data)
438 {
439 Currency *entry;
440 gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
441
442 gtk_tree_model_get(model, iter, LST_DEFCUR_DATAS, &entry, -1);
443
444 if(entry->key == GLOBALS->kcur)
445 g_object_set(renderer, "text", "-", NULL);
446 else
447 {
448 //g_ascii_formatd(formatd_buf, sizeof (formatd_buf), "%.6f", entry->rate);
449 //g_snprintf(formatd_buf, sizeof (formatd_buf), "%f", entry->rate);
450 hb_str_rate(formatd_buf, sizeof (formatd_buf), entry->rate);
451 g_object_set(renderer, "text", formatd_buf, NULL);
452 }
453
454 }
455
456
457 /* = = = = = = = = = = = = = = = = */
458
459
460 void
461 ui_cur_listview_add(GtkTreeView *treeview, Currency *item)
462 {
463 if( item->name != NULL )
464 {
465 GtkTreeModel *model;
466 GtkTreeIter iter;
467
468 model = gtk_tree_view_get_model(treeview);
469
470 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
471 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
472 LST_DEFCUR_TOGGLE, FALSE,
473 LST_DEFCUR_DATAS, item,
474 -1);
475 }
476 }
477
478 guint32
479 ui_cur_listview_get_selected_key(GtkTreeView *treeview)
480 {
481 GtkTreeSelection *selection;
482 GtkTreeModel *model;
483 GtkTreeIter iter;
484
485 selection = gtk_tree_view_get_selection(treeview);
486 if (gtk_tree_selection_get_selected(selection, &model, &iter))
487 {
488 Currency *item;
489
490 gtk_tree_model_get(model, &iter, LST_DEFCUR_DATAS, &item, -1);
491
492 if( item != NULL )
493 return item->key;
494 }
495 return 0;
496 }
497
498 void
499 ui_cur_listview_remove_selected(GtkTreeView *treeview)
500 {
501 GtkTreeSelection *selection;
502 GtkTreeModel *model;
503 GtkTreeIter iter;
504
505 selection = gtk_tree_view_get_selection(treeview);
506 if (gtk_tree_selection_get_selected(selection, &model, &iter))
507 {
508 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
509 }
510 }
511
512
513 static void ui_cur_listview_populate_ghfunc(gpointer key, gpointer value, GtkTreeModel *model)
514 {
515 GtkTreeIter iter;
516 Currency *item = value;
517
518 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
519 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
520 LST_DEFCUR_TOGGLE , FALSE,
521 LST_DEFCUR_DATAS, item,
522 -1);
523 }
524
525 void ui_cur_listview_populate(GtkWidget *view)
526 {
527 GtkTreeModel *model;
528
529 model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
530
531 gtk_list_store_clear (GTK_LIST_STORE(model));
532
533 g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
534 gtk_tree_view_set_model(GTK_TREE_VIEW(view), NULL); /* Detach model from view */
535
536 /* populate */
537 g_hash_table_foreach(GLOBALS->h_cur, (GHFunc)ui_cur_listview_populate_ghfunc, model);
538
539 gtk_tree_view_set_model(GTK_TREE_VIEW(view), model); /* Re-attach model to view */
540 g_object_unref(model);
541 }
542
543 /* test */
544 /*
545 static void
546 ui_cur_listivew_rate_edited_func (GtkCellRendererText *cell,
547 const gchar *path_string,
548 const gchar *new_text,
549 gpointer data)
550 {
551 GtkTreeModel *model = (GtkTreeModel *)data;
552 GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
553 GtkTreeIter iter;
554
555 g_print("cell edited '%s' path %s\n", new_text, path_string);
556
557
558 gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column"));
559
560 gtk_tree_model_get_iter (model, &iter, path);
561
562 Currency *item;
563
564 gtk_tree_model_get(model, &iter, LST_DEFCUR_DATAS, &item, -1);
565
566 item->rate = atof(new_text);
567
568 GLOBALS->changes_count++;
569
570
571 gtk_tree_path_free (path);
572 }
573 */
574
575
576 GtkWidget *
577 ui_cur_listview_new(gboolean withtoggle)
578 {
579 GtkListStore *store;
580 GtkWidget *treeview;
581 GtkCellRenderer *renderer;
582 GtkTreeViewColumn *column;
583
584 // create list store
585 store = gtk_list_store_new(
586 NUM_LST_DEFCUR,
587 G_TYPE_BOOLEAN,
588 G_TYPE_POINTER
589 );
590
591 // treeview
592 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
593 g_object_unref(store);
594
595 // column 1: toggle
596 if( withtoggle == TRUE )
597 {
598 renderer = gtk_cell_renderer_toggle_new ();
599 column = gtk_tree_view_column_new_with_attributes (_("Visible"),
600 renderer,
601 "active", LST_DEFCUR_TOGGLE,
602 NULL);
603 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
604
605 g_signal_connect (renderer, "toggled",
606 G_CALLBACK (ui_cur_listview_toggled_cb), store);
607
608 }
609
610 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview), PREFS->grid_lines);
611
612
613 // column 1: name
614 renderer = gtk_cell_renderer_text_new ();
615 column = gtk_tree_view_column_new();
616 gtk_tree_view_column_set_title(column, _("Name"));
617 gtk_tree_view_column_set_alignment (column, 0.5);
618 gtk_tree_view_column_pack_start(column, renderer, TRUE);
619 gtk_tree_view_column_set_cell_data_func(column, renderer, ui_cur_listview_name_cell_data_function, GINT_TO_POINTER(LST_DEFCUR_DATAS), NULL);
620 gtk_tree_view_column_set_resizable(column, TRUE);
621 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
622
623 // column 2: code
624 renderer = gtk_cell_renderer_text_new ();
625 g_object_set(renderer, "xalign", 0.5, NULL);
626 column = gtk_tree_view_column_new();
627 gtk_tree_view_column_set_title(column, _("Symbol"));
628 gtk_tree_view_column_set_alignment (column, 0.5);
629 gtk_tree_view_column_pack_start(column, renderer, TRUE);
630 gtk_tree_view_column_set_cell_data_func(column, renderer, ui_cur_listview_symbol_cell_data_function, GINT_TO_POINTER(LST_DEFCUR_DATAS), NULL);
631 gtk_tree_view_column_set_resizable(column, TRUE);
632 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
633
634 // column 3: base rate
635 renderer = gtk_cell_renderer_text_new ();
636 //g_object_set (renderer, "editable", TRUE, NULL);
637 g_object_set(renderer, "xalign", 1.0, NULL);
638 column = gtk_tree_view_column_new();
639 gtk_tree_view_column_set_title(column, _("Exchange rate"));
640 gtk_tree_view_column_set_alignment (column, 0.5);
641 gtk_tree_view_column_pack_start(column, renderer, TRUE);
642 gtk_tree_view_column_set_cell_data_func(column, renderer, ui_cur_listview_rate_cell_data_function, GINT_TO_POINTER(LST_DEFCUR_DATAS), NULL);
643 gtk_tree_view_column_set_resizable(column, TRUE);
644 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
645
646 //g_signal_connect (renderer, "edited", G_CALLBACK (ui_cur_listivew_rate_edited_func), GTK_TREE_MODEL(store));
647
648 // column 4: last modified
649 renderer = gtk_cell_renderer_text_new ();
650 g_object_set(renderer, "xalign", 0.5, NULL);
651 column = gtk_tree_view_column_new();
652 gtk_tree_view_column_set_title(column, _("Last modified"));
653 gtk_tree_view_column_set_alignment (column, 0.5);
654 gtk_tree_view_column_pack_start(column, renderer, TRUE);
655 gtk_tree_view_column_set_cell_data_func(column, renderer, ui_cur_listview_lastmodified_cell_data_function, GINT_TO_POINTER(LST_DEFCUR_DATAS), NULL);
656 gtk_tree_view_column_set_resizable(column, TRUE);
657 gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
658
659
660 // treeview attribute
661 gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), 1);
662 //gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), TRUE);
663 //gtk_tree_view_set_reorderable (GTK_TREE_VIEW(view), TRUE);
664 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_DEFCUR_DATAS, ui_cur_listview_compare_func, NULL, NULL);
665 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), LST_DEFCUR_DATAS, GTK_SORT_ASCENDING);
666
667 return treeview;
668 }
669
670
671 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
672 /*
673 ** update the number sample label
674 */
675 static void ui_cur_edit_dialog_update_sample(GtkWidget *widget, gpointer user_data)
676 {
677 struct ui_cur_edit_dialog_data *data;
678 Currency cur;
679 gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
680 gchar buf[128];
681
682 DB( g_printf("[ui_cur_edit] update sample\n") );
683
684 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
685
686 cur.symbol = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_symbol));
687 cur.sym_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_symisprefix));
688 cur.decimal_char = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_decimalchar));
689 cur.grouping_char = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_groupingchar));
690 cur.frac_digits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_fracdigits));
691
692 da_cur_initformat (&cur);
693 DB( g_print("fmt: %s\n", cur.format) );
694
695 g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur.format, HB_NUMBER_SAMPLE);
696
697 hb_str_formatd(buf, 127, formatd_buf, &cur, TRUE);
698 gtk_label_set_text(GTK_LABEL(data->LB_sample), buf);
699
700 }
701
702
703
704 static void ui_cur_edit_dialog_set(GtkWidget *widget, Currency *cur)
705 {
706 struct ui_cur_edit_dialog_data *data;
707 Currency *base;
708 gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
709 gchar label[128];
710
711 DB( g_printf("[ui_cur_edit] set\n") );
712
713 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
714
715 g_snprintf(label, 127, "%s - %s", cur->iso_code, cur->name);
716 gtk_label_set_text (GTK_LABEL(data->LB_name), label);
717
718 base = da_cur_get(GLOBALS->kcur);
719
720 g_snprintf(label, 127, "1 %s _=", base->iso_code);
721 gtk_label_set_text_with_mnemonic (GTK_LABEL(data->LB_rate), label);
722 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_rate), cur->rate);
723
724 da_cur_initformat(cur);
725 g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur->format, HB_NUMBER_SAMPLE);
726 hb_str_formatd(label, 127, formatd_buf, cur, TRUE);
727 gtk_label_set_text (GTK_LABEL(data->LB_sample), label);
728
729 ui_gtk_entry_set_text(data->ST_symbol, cur->symbol);
730 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_symisprefix), cur->sym_prefix);
731 ui_gtk_entry_set_text(data->ST_decimalchar, cur->decimal_char);
732 ui_gtk_entry_set_text(data->ST_groupingchar, cur->grouping_char);
733 gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_fracdigits), cur->frac_digits);
734
735 }
736
737
738
739 static void ui_cur_edit_dialog_get(GtkWidget *widget, Currency *cur)
740 {
741 struct ui_cur_edit_dialog_data *data;
742 gdouble rate;
743
744 DB( g_printf("[ui_cur_edit] get\n") );
745
746 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
747
748 ui_gtk_entry_replace_text(data->ST_symbol, &cur->symbol);
749 cur->sym_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_symisprefix));
750 ui_gtk_entry_replace_text(data->ST_decimalchar, &cur->decimal_char);
751 ui_gtk_entry_replace_text(data->ST_groupingchar, &cur->grouping_char);
752 cur->frac_digits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_fracdigits));
753
754 da_cur_initformat(cur);
755
756 rate = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_rate));
757 if(cur->rate != rate)
758 {
759 cur->rate = rate;
760 cur->mdate = GLOBALS->today;
761 }
762
763 }
764
765
766 void ui_cur_edit_dialog_new(GtkWindow *parent, Currency *cur)
767 {
768 struct ui_cur_edit_dialog_data data;
769 GtkWidget *dialog, *content_area, *content_grid, *group_grid;
770 GtkWidget *label, *widget, *expander;
771 gint crow, row;
772
773 dialog = gtk_dialog_new_with_buttons (
774 _("Edit currency"),
775 GTK_WINDOW (parent),
776 0,
777 _("_Cancel"),
778 GTK_RESPONSE_REJECT,
779 _("_OK"),
780 GTK_RESPONSE_ACCEPT,
781 NULL);
782
783 data.window = dialog;
784
785 //store our dialog private data
786 g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)&data);
787 DB( g_printf("[ui_cur_edit] new dialog=%p, inst_data=%p\n", dialog, &data) );
788
789
790 content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog)); // return a vbox
791
792 content_grid = gtk_grid_new();
793 gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
794 gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
795 gtk_container_set_border_width (GTK_CONTAINER(content_grid), SPACING_MEDIUM);
796 gtk_box_pack_start (GTK_BOX (content_area), content_grid, TRUE, TRUE, 0);
797
798 crow = 0;
799 // group :: Currency
800 group_grid = gtk_grid_new ();
801 gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
802 gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
803 gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
804
805 label = make_label_group(_("Currency"));
806 gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
807
808 row = 1;
809 widget = make_label(NULL, 0, 0.5);
810 data.LB_name = widget;
811 gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
812
813 // group :: exchange
814 group_grid = gtk_grid_new ();
815 gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
816 gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
817 gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
818
819 label = make_label_group(_("Exchange rate"));
820 gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
821
822 row = 1;
823 label = make_label(NULL, 0, 0.5);
824 data.LB_rate = label;
825 gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
826 widget = make_exchange_rate(label);
827 data.NB_rate = widget;
828 gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
829
830 gtk_widget_set_sensitive(group_grid, (GLOBALS->kcur == cur->key) ? FALSE : TRUE);
831
832 // group :: format
833 group_grid = gtk_grid_new ();
834 gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
835 gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
836 gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
837
838 label = make_label_group(_("Format"));
839 gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
840
841 row++;
842 widget = make_label(NULL, 0, 0.5);
843 data.LB_sample = widget;
844 gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
845
846 row++;
847 expander = gtk_expander_new_with_mnemonic (_("_Customize"));
848 gtk_grid_attach (GTK_GRID (group_grid), expander, 1, row, 2, 1);
849
850 group_grid = gtk_grid_new ();
851 gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
852 gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
853 gtk_container_add (GTK_CONTAINER (expander), group_grid);
854
855 row = 1;
856 label = make_label_widget(_("_Symbol:"));
857 gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
858 widget = make_string_maxlength(label, 3);
859 data.ST_symbol = widget;
860 gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
861
862 row++;
863 widget = gtk_check_button_new_with_mnemonic (_("Is pre_fix"));
864 data.CM_symisprefix = widget;
865 gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
866
867 row++;
868 label = make_label_widget(_("_Decimal char:"));
869 gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
870 widget = make_string_maxlength(label, 1);
871 data.ST_decimalchar = widget;
872 gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
873
874 row++;
875 label = make_label_widget(_("_Frac digits:"));
876 gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
877 widget = make_numeric(label, 0.0, 8.0);
878 data.NB_fracdigits = widget;
879 gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
880
881 row++;
882 label = make_label_widget(_("_Grouping char:"));
883 gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
884 widget = make_string_maxlength(label, 1);
885 data.ST_groupingchar = widget;
886 gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
887
888
889 //gtk_window_resize(GTK_WINDOW(dialog), 400/PHI, 400);
890
891 ui_cur_edit_dialog_set(dialog, cur);
892
893 gtk_widget_show_all(content_area);
894
895 //signals
896 g_signal_connect (data.ST_symbol , "changed", G_CALLBACK (ui_cur_edit_dialog_update_sample), NULL);
897 g_signal_connect (data.CM_symisprefix, "toggled", G_CALLBACK (ui_cur_edit_dialog_update_sample), NULL);
898 g_signal_connect (data.ST_decimalchar , "changed", G_CALLBACK (ui_cur_edit_dialog_update_sample), NULL);
899 g_signal_connect (data.ST_groupingchar, "changed", G_CALLBACK (ui_cur_edit_dialog_update_sample), NULL);
900 g_signal_connect (data.NB_fracdigits, "value-changed", G_CALLBACK (ui_cur_edit_dialog_update_sample), NULL);
901
902 // wait for the user
903 gint result = gtk_dialog_run (GTK_DIALOG (dialog));
904 if(result == GTK_RESPONSE_ACCEPT)
905 {
906 ui_cur_edit_dialog_get(dialog, cur);
907 }
908
909 // cleanup and destroy
910 gtk_widget_destroy (dialog);
911
912 }
913
914
915 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
916
917 enum {
918 LST_CURSEL_NAME,
919 LST_CURSEL_ISO,
920 LST_CURSEL_FULLNAME,
921 LST_CURSEL_DATA,
922 NUM_LST_CURSEL
923 };
924
925
926 static void ui_cur_select_rowactivated (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer userdata)
927 {
928 struct ui_cur_select_dialog_data *data = userdata;
929
930 gtk_dialog_response(GTK_DIALOG(data->window), GTK_RESPONSE_ACCEPT);
931 }
932
933
934 static GtkTreeModel *ui_cur_select_model_create (void)
935 {
936 guint i = 0;
937 GtkListStore *store;
938 GtkTreeIter iter;
939 Currency4217 *cur;
940 gchar buffer[255];
941
942 /* create list store */
943 store = gtk_list_store_new (NUM_LST_CURSEL,
944 G_TYPE_STRING,
945 G_TYPE_STRING,
946 G_TYPE_STRING,
947 G_TYPE_POINTER,
948 NULL
949 );
950
951 for (i = 0; i< n_iso4217cur; i++)
952 {
953 cur = &iso4217cur[i];
954
955 g_snprintf(buffer, 255-1, "%s - %s", cur->curr_iso_code, cur->name);
956
957 gtk_list_store_append (store, &iter);
958 gtk_list_store_set (store, &iter,
959 LST_CURSEL_NAME, cur->name,
960 LST_CURSEL_ISO, cur->curr_iso_code,
961 LST_CURSEL_FULLNAME, buffer,
962 LST_CURSEL_DATA, cur,
963 -1);
964
965
966 }
967
968 return GTK_TREE_MODEL (store);
969 }
970
971
972 static Currency4217 *ui_cur_select_dialog_get_langue(struct ui_cur_select_dialog_data *data)
973 {
974 GtkTreeSelection *treeselection;
975 gboolean selected;
976 GtkTreeModel *model;
977 GtkTreeIter iter;
978 Currency4217 *curfmt = NULL;
979
980 DB( g_printf("\n[ui_cur_select] get langue\n") );
981
982 treeselection = gtk_tree_view_get_selection (GTK_TREE_VIEW(data->LV_cur));
983 selected = gtk_tree_selection_get_selected(treeselection, &model, &iter);
984 if(selected)
985 {
986 gtk_tree_model_get(model, &iter, LST_CURSEL_DATA, &curfmt, -1);
987
988 DB( g_printf(" - iso is '%s'\n", curfmt->curr_iso_code) );
989 }
990
991 return curfmt;
992 }
993
994
995 static void
996 ui_cur_select_search_changed_cb (GtkWidget *widget, gpointer user_data)
997 {
998 struct ui_cur_select_dialog_data *data = user_data;
999
1000 DB( g_printf("\n[ui_cur_select] search changed\n") );
1001
1002 gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(data->modelfilter));
1003
1004 }
1005
1006
1007 /* valid iso is empoty or 3 capital digit */
1008 static guint currency_iso_code_valid(gchar *str)
1009 {
1010 guint n = 0;
1011
1012 while( *str )
1013 {
1014 if( *str >= 'A' && *str <= 'Z' )
1015 n++;
1016 str++;
1017 }
1018 return n;
1019 }
1020
1021
1022 static void
1023 ui_cur_select_custom_validate_cb(GtkWidget *widget, gpointer user_data)
1024 {
1025 struct ui_cur_select_dialog_data *data = user_data;
1026 gboolean custom;
1027 gboolean valid = TRUE;
1028 const gchar *iso, *name;
1029 guint len;
1030
1031 DB( g_printf("\n[ui_cur_select] custom validate\n") );
1032
1033 custom = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data->CM_custom));
1034
1035 DB( g_print(" custom=%d\n", custom) );
1036
1037 //custom
1038 if( custom == TRUE )
1039 {
1040 valid = FALSE;
1041
1042 name = gtk_entry_get_text (GTK_ENTRY (data->ST_custname));
1043 iso = gtk_entry_get_text (GTK_ENTRY (data->ST_custiso));
1044
1045 len = currency_iso_code_valid((gchar *)iso);
1046
1047 DB( g_print(" name='%d', iso='%d'\n", (gint)strlen(name), len) );
1048
1049 if( (len==0 || len==3) && (strlen(name) >= 3 ) )
1050 {
1051 valid = TRUE;
1052 // don't allow to enter stand 4217 iso code
1053 if( len == 3 )
1054 {
1055 Currency4217 *stdcur = iso4217format_get((gchar *)iso);
1056 if(stdcur != NULL)
1057 valid = FALSE;
1058 }
1059 }
1060 }
1061
1062 gtk_dialog_set_response_sensitive(GTK_DIALOG(data->window), GTK_RESPONSE_ACCEPT, valid);
1063
1064 }
1065
1066
1067 static void
1068 ui_cur_select_custom_activate_cb(GtkWidget *widget, gpointer user_data)
1069 {
1070 struct ui_cur_select_dialog_data *data = user_data;
1071 gboolean custom;
1072
1073 DB( g_printf("\n[ui_cur_select] custom activate\n") );
1074
1075 custom = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data->CM_custom));
1076
1077 DB( g_print(" custom=%d\n", custom) );
1078
1079 gtk_widget_set_sensitive(data->ST_search, !custom);
1080 gtk_widget_set_sensitive(data->LV_cur, !custom);
1081
1082 hb_widget_visible (data->LB_custname, custom);
1083 hb_widget_visible (data->ST_custname, custom);
1084 hb_widget_visible (data->LB_custiso, custom);
1085 hb_widget_visible (data->ST_custiso, custom);
1086
1087 if(custom)
1088 {
1089 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection (GTK_TREE_VIEW(data->LV_cur)));
1090 gtk_window_set_focus(GTK_WINDOW(data->window), data->ST_custname);
1091 }
1092
1093 ui_cur_select_custom_validate_cb(data->window, data);
1094
1095 }
1096
1097
1098 static gboolean
1099 ui_cur_select_model_func_visible (GtkTreeModel *model,
1100 GtkTreeIter *iter,
1101 gpointer data)
1102 {
1103 // Visible if row is non-empty and first column is “HI”
1104 gchar *str;
1105 gboolean visible = TRUE;
1106 GtkEntry *entry = data;
1107
1108 if(!GTK_IS_ENTRY(entry))
1109 return TRUE;
1110
1111 gchar *needle = g_ascii_strdown(gtk_entry_get_text(entry), -1);
1112
1113 gtk_tree_model_get (model, iter, LST_CURSEL_FULLNAME, &str, -1);
1114
1115 gchar *haystack = g_ascii_strdown(str, -1);
1116
1117 if (str && g_strrstr (haystack, needle) == NULL)
1118 {
1119 visible = FALSE;
1120 }
1121
1122 DB( g_print("filter: '%s' '%s' %d\n", str, needle, visible) );
1123
1124 g_free(haystack);
1125 g_free(needle);
1126 g_free (str);
1127
1128 return visible;
1129 }
1130
1131
1132 gint ui_cur_select_dialog_new(GtkWindow *parent, gint select_mode, struct curSelectContext *ctx)
1133 {
1134 struct ui_cur_select_dialog_data data;
1135 GtkWidget *dialog, *content_area, *content_grid, *group_grid;
1136 GtkWidget *scrollwin, *treeview, *label, *widget;
1137 gint crow, row;
1138
1139 memset(&data, 0, sizeof(struct ui_cur_select_dialog_data));
1140
1141 dialog = gtk_dialog_new_with_buttons (
1142 (select_mode == CUR_SELECT_MODE_BASE) ? _("Select base currency") : _("Select currency"),
1143 GTK_WINDOW (parent),
1144 0,
1145 _("_Cancel"),
1146 GTK_RESPONSE_REJECT,
1147 _("_OK"),
1148 GTK_RESPONSE_ACCEPT,
1149 NULL);
1150
1151 data.window = dialog;
1152
1153 //store our dialog private data
1154 g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)&data);
1155 DB( g_printf("\n[ui_cur_select] new dialog=%p, inst_data=%p\n", dialog, &data) );
1156
1157
1158 content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog)); // return a vbox
1159
1160 content_grid = gtk_grid_new();
1161 gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
1162 gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
1163 gtk_container_set_border_width (GTK_CONTAINER(content_grid), SPACING_MEDIUM);
1164 gtk_box_pack_start (GTK_BOX (content_area), content_grid, TRUE, TRUE, 0);
1165
1166 crow = 0;
1167 // group :: Search
1168 group_grid = gtk_grid_new ();
1169 gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
1170 gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
1171 gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
1172
1173 row = 0;
1174 widget = make_search();
1175 data.ST_search = widget;
1176 gtk_widget_set_hexpand (widget, TRUE);
1177 gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 4, 1);
1178
1179
1180 row++;
1181 scrollwin = gtk_scrolled_window_new(NULL,NULL);
1182 gtk_grid_attach (GTK_GRID (group_grid), scrollwin, 1, row, 4, 1);
1183
1184 gtk_widget_set_vexpand (scrollwin, TRUE);
1185 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
1186 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1187
1188 //test treefilter
1189 data.model = ui_cur_select_model_create();
1190 data.modelfilter = gtk_tree_model_filter_new(GTK_TREE_MODEL(data.model), NULL);
1191 gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(data.modelfilter), ui_cur_select_model_func_visible, data.ST_search, NULL);
1192 data.sortmodel = gtk_tree_model_sort_new_with_model(data.modelfilter);
1193
1194 //treeview
1195 treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL(data.sortmodel));
1196 data.LV_cur = treeview;
1197 //gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview), LST_CURSEL_NAME);
1198 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(data.sortmodel), LST_CURSEL_NAME, GTK_SORT_ASCENDING);
1199 //g_object_unref (model);
1200 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview), PREFS->grid_lines);
1201
1202 gtk_container_add(GTK_CONTAINER(scrollwin), treeview);
1203
1204 // populate list
1205 GtkCellRenderer *renderer;
1206 GtkTreeViewColumn *column;
1207
1208 renderer = gtk_cell_renderer_text_new ();
1209 column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, "text", LST_CURSEL_NAME, NULL);
1210 gtk_tree_view_column_set_sort_column_id (column, LST_CURSEL_NAME);
1211 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1212
1213 renderer = gtk_cell_renderer_text_new ();
1214 column = gtk_tree_view_column_new_with_attributes (_("ISO Code"), renderer, "text", LST_CURSEL_ISO, NULL);
1215 gtk_tree_view_column_set_sort_column_id (column, LST_CURSEL_ISO);
1216 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1217
1218 if( select_mode == CUR_SELECT_MODE_NORMAL )
1219 {
1220 // group :: Custom
1221 row++;
1222 widget = gtk_check_button_new_with_mnemonic (_("Add a custom _currency"));
1223 data.CM_custom = widget;
1224 gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 4, 1);
1225
1226 //custom currency (crypto and discontinued)
1227 row++;
1228 label = make_label_widget(_("_Name:"));
1229 data.LB_custname = label;
1230 gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
1231 widget = make_string(label);
1232 data.ST_custname = widget;
1233 gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
1234
1235 label = make_label_widget(_("_ISO:"));
1236 data.LB_custiso = label;
1237 gtk_grid_attach (GTK_GRID (group_grid), label, 3, row, 1, 1);
1238 widget = make_string_maxlength(label, 3);
1239 data.ST_custiso = widget;
1240 gtk_grid_attach (GTK_GRID (group_grid), widget, 4, row, 1, 1);
1241
1242 g_signal_connect (G_OBJECT (data.CM_custom) , "toggled", G_CALLBACK (ui_cur_select_custom_activate_cb), &data);
1243 g_signal_connect (G_OBJECT (data.ST_custname), "changed", G_CALLBACK (ui_cur_select_custom_validate_cb), &data);
1244 g_signal_connect (G_OBJECT (data.ST_custiso) , "changed", G_CALLBACK (ui_cur_select_custom_validate_cb), &data);
1245
1246 }
1247
1248 gtk_window_resize(GTK_WINDOW(dialog), 400/PHI, 400);
1249
1250
1251 gtk_widget_show_all(content_area);
1252 hb_widget_visible (data.LB_custname, FALSE);
1253 hb_widget_visible (data.ST_custname, FALSE);
1254 hb_widget_visible (data.LB_custiso, FALSE);
1255 hb_widget_visible (data.ST_custiso, FALSE);
1256
1257
1258 // signals
1259 g_signal_connect (G_OBJECT(data.ST_search), "search-changed", G_CALLBACK (ui_cur_select_search_changed_cb), &data);
1260 g_signal_connect (G_OBJECT(data.LV_cur), "row-activated", G_CALLBACK (ui_cur_select_rowactivated), &data);
1261
1262 //init picker struct
1263 memset(ctx, 0, sizeof(struct curSelectContext));
1264
1265 // wait for the user
1266 gint result = gtk_dialog_run (GTK_DIALOG (dialog));
1267 if(result == GTK_RESPONSE_ACCEPT)
1268 {
1269 gboolean custom;
1270
1271 custom = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(data.CM_custom));
1272 if(!custom)
1273 {
1274 ctx->cur_4217 = ui_cur_select_dialog_get_langue(&data);
1275 }
1276 else
1277 //never fill custom in base mode
1278 if( select_mode != CUR_SELECT_MODE_BASE )
1279 {
1280 ctx->cur_name = g_strdup(gtk_entry_get_text (GTK_ENTRY(data.ST_custname)));
1281 ctx->cur_iso = g_strdup(gtk_entry_get_text (GTK_ENTRY(data.ST_custiso)));
1282 }
1283 }
1284
1285 // cleanup and destroy
1286 gtk_widget_destroy (dialog);
1287
1288 return result;
1289 }
1290
1291
1292 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1293
1294
1295 gint ui_cur_manage_dialog_update_currencies(GtkWindow *parent)
1296 {
1297 GError *error = NULL;
1298 gboolean retcode = FALSE;
1299
1300 DB( g_printf("\n[ui_cur_manage] update currencies\n") );
1301
1302 // do nothing if just the base currency
1303 if(da_cur_length() <= 1)
1304 return TRUE;
1305
1306 retcode = currency_online_sync(&error);
1307
1308 DB( g_print("retcode: %d\n", retcode) );
1309
1310 if(!retcode)
1311 {
1312 gchar *msg = _("Unknown error");
1313
1314 if( error )
1315 msg = error->message;
1316
1317 g_warning("update online: '%s'", msg);
1318
1319 ui_dialog_msg_infoerror(GTK_WINDOW(parent), GTK_MESSAGE_ERROR,
1320 _("Update online error"),
1321 msg,
1322 NULL
1323 );
1324
1325 if( error )
1326 g_error_free (error);
1327 }
1328
1329 return retcode;
1330 }
1331
1332
1333 static void
1334 ui_cur_manage_dialog_sync(GtkWidget *widget, gpointer user_data)
1335 {
1336 struct ui_cur_manage_dialog_data *data;
1337 gboolean retcode;
1338
1339 DB( g_printf("\n[ui_cur_manage] sync online\n") );
1340
1341 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1342
1343 retcode = ui_cur_manage_dialog_update_currencies(GTK_WINDOW(data->window));
1344
1345 if(retcode == TRUE)
1346 {
1347 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_cur));
1348 //todo: (or not) msg with changes
1349
1350 }
1351 }
1352
1353
1354 /*
1355 **
1356 */
1357 static void ui_cur_manage_dialog_update(GtkWidget *treeview, gpointer user_data)
1358 {
1359 struct ui_cur_manage_dialog_data *data;
1360 GtkTreeSelection *selection;
1361 GtkTreeModel *model;
1362 GtkTreeIter iter;
1363 Currency *item;
1364 gboolean sensitive;
1365
1366 DB( g_printf("\n[ui_cur_manage] update\n") );
1367
1368 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(treeview), GTK_TYPE_WINDOW)), "inst_data");
1369
1370 sensitive = da_cur_length() <= 1 ? FALSE : TRUE;
1371 gtk_widget_set_sensitive (data->BB_update, sensitive);
1372
1373
1374 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_cur));
1375
1376 //if true there is a selected node
1377 if (gtk_tree_selection_get_selected(selection, &model, &iter))
1378 {
1379 gtk_tree_model_get(model, &iter, LST_DEFCUR_DATAS, &item, -1);
1380
1381 gtk_widget_set_sensitive(data->BT_edit, TRUE);
1382
1383 sensitive = !(currency_is_used(item->key));
1384 //gtk_widget_set_sensitive(data->BT_mov, sensitive);
1385 //gtk_widget_set_sensitive(data->BT_mod, sensitive);
1386 gtk_widget_set_sensitive(data->BT_rem, sensitive);
1387
1388 //disable set as base on actual base currency
1389 //disable on custom currency
1390 sensitive = TRUE;
1391 if( (item->key == GLOBALS->kcur) || (item->flags & CF_CUSTOM) )
1392 sensitive = FALSE;
1393 gtk_widget_set_sensitive(data->BT_base, sensitive);
1394 }
1395 else
1396 {
1397 gtk_widget_set_sensitive(data->BT_edit, FALSE);
1398 gtk_widget_set_sensitive(data->BT_rem , FALSE);
1399 gtk_widget_set_sensitive(data->BT_base, FALSE);
1400 }
1401 }
1402
1403
1404 /**
1405 * ui_cur_manage_dialog_add:
1406 *
1407 */
1408 static void
1409 ui_cur_manage_dialog_add(GtkWidget *widget, gpointer user_data)
1410 {
1411 struct ui_cur_manage_dialog_data *data;
1412 struct curSelectContext selectCtx;
1413 gint result;
1414 gboolean added;
1415
1416 DB( g_printf("\n[ui_cur_manage] add\n") );
1417
1418 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1419
1420 result = ui_cur_select_dialog_new(GTK_WINDOW(data->window), CUR_SELECT_MODE_NORMAL, &selectCtx);
1421 if( result == GTK_RESPONSE_ACCEPT )
1422 {
1423 Currency *item = NULL;
1424
1425 added = FALSE;
1426 if( selectCtx.cur_4217 != NULL )
1427 {
1428 Currency4217 *curfmt;
1429
1430 curfmt = selectCtx.cur_4217;
1431
1432 DB( g_printf("- user selected: '%s' '%s'\n", curfmt->curr_iso_code, curfmt->name) );
1433 item = da_cur_get_by_iso_code(curfmt->curr_iso_code);
1434 if( item == NULL )
1435 {
1436 item = currency_add_from_user(curfmt);
1437 added = TRUE;
1438 }
1439 }
1440 else
1441 {
1442 DB( g_printf("- user custom: '%s' '%s'\n", selectCtx.cur_iso, selectCtx.cur_name) );
1443
1444 item = da_cur_malloc ();
1445 item->flags |= CF_CUSTOM;
1446 item->name = g_strdup(selectCtx.cur_name);
1447 item->iso_code = g_strdup(selectCtx.cur_iso);
1448 item->symbol = g_strdup(item->iso_code);
1449 item->frac_digits = 2;
1450 item->sym_prefix = FALSE;
1451 item->decimal_char = g_strdup(".");
1452 item->grouping_char = NULL;
1453
1454 added = da_cur_append(item);
1455 if( !added )
1456 {
1457 //not append (duplicate)
1458 da_cur_free (item);
1459 item = NULL;
1460 }
1461
1462 g_free(selectCtx.cur_iso);
1463 g_free(selectCtx.cur_name);
1464 }
1465
1466 if( added )
1467 {
1468 ui_cur_listview_add(GTK_TREE_VIEW(data->LV_cur), item);
1469 gtk_tree_sortable_sort_column_changed(GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_cur))));
1470
1471 ui_cur_manage_dialog_update (widget, user_data);
1472 GLOBALS->changes_count++;
1473 }
1474
1475 }
1476 }
1477
1478
1479 static void
1480 ui_cur_manage_dialog_modify(GtkWidget *widget, gpointer user_data)
1481 {
1482 struct ui_cur_manage_dialog_data *data;
1483 GtkTreeSelection *selection;
1484 GtkTreeModel *model;
1485 GtkTreeIter iter;
1486
1487 DB( g_printf("\n[ui_cur_manage] modify\n") );
1488
1489
1490 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1491
1492 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_cur));
1493 if (gtk_tree_selection_get_selected(selection, &model, &iter))
1494 {
1495 Currency *item;
1496
1497 gtk_tree_model_get(model, &iter, LST_DEFCUR_DATAS, &item, -1);
1498
1499 if( item!= NULL )
1500 {
1501 ui_cur_edit_dialog_new(GTK_WINDOW(data->window), item);
1502 GLOBALS->changes_count++;
1503 }
1504
1505 }
1506 }
1507
1508
1509 /*
1510 ** remove the selected curee to our treeview and temp GList
1511 */
1512 static void ui_cur_manage_dialog_remove(GtkWidget *widget, gpointer user_data)
1513 {
1514 struct ui_cur_manage_dialog_data *data;
1515 guint32 key;
1516 gboolean do_remove, result;
1517
1518 DB( g_printf("\n[ui_cur_manage] remove\n") );
1519
1520 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1521
1522 do_remove = TRUE;
1523 key = ui_cur_listview_get_selected_key(GTK_TREE_VIEW(data->LV_cur));
1524 if( key > 0 )
1525 {
1526 Currency *cur;
1527 gchar *title;
1528 gchar *secondtext;
1529
1530 if( currency_is_used(key) == TRUE )
1531 {
1532 do_remove = FALSE;
1533 }
1534 else
1535 {
1536 cur = da_cur_get(key);
1537
1538 title = g_strdup_printf (
1539 _("Are you sure you want to permanently delete '%s'?"), cur->name);
1540
1541 secondtext = _("If you delete a currency, it will be permanently lost.");
1542
1543 result = ui_dialog_msg_confirm_alert(
1544 GTK_WINDOW(data->window),
1545 title,
1546 secondtext,
1547 _("_Delete")
1548 );
1549
1550 g_free(title);
1551
1552 do_remove = (result == GTK_RESPONSE_OK) ? TRUE :FALSE;
1553 }
1554
1555 if( do_remove )
1556 {
1557 da_cur_remove(key);
1558 ui_cur_listview_remove_selected(GTK_TREE_VIEW(data->LV_cur));
1559 ui_cur_manage_dialog_update (widget, user_data);
1560 data->change++;
1561 }
1562 }
1563
1564 }
1565
1566 /*
1567 ** button callback: set base currency
1568 */
1569 static void ui_cur_manage_dialog_setbase(GtkWidget *widget, gpointer user_data)
1570 {
1571 struct ui_cur_manage_dialog_data *data;
1572 guint32 key;
1573 gboolean do_change;
1574
1575 DB( g_printf("\n[ui_cur_manage] setbase\n") );
1576
1577
1578 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1579
1580 key = ui_cur_listview_get_selected_key(GTK_TREE_VIEW(data->LV_cur));
1581 if( key > 0 )
1582 {
1583 do_change = ui_dialog_msg_question(
1584 GTK_WINDOW(data->window),
1585 _("Change the base currency"),
1586 _("If you proceed, rates of other currencies\n"
1587 "will be set to 0, don't forget to update it"),
1588 NULL
1589 );
1590 if(do_change == GTK_RESPONSE_YES)
1591 {
1592 hbfile_change_basecurrency(key);
1593 gtk_tree_view_columns_autosize(GTK_TREE_VIEW(data->LV_cur));
1594 }
1595 }
1596
1597 }
1598
1599
1600
1601
1602 /*
1603 **
1604 */
1605 static void ui_cur_manage_dialog_selection(GtkTreeSelection *treeselection, gpointer user_data)
1606 {
1607 ui_cur_manage_dialog_update(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), NULL);
1608 }
1609
1610 static void ui_cur_manage_dialog_onRowActivated (GtkTreeView *treeview,
1611 GtkTreePath *path,
1612 GtkTreeViewColumn *col,
1613 gpointer userdata)
1614 {
1615
1616 //model = gtk_tree_view_get_model(treeview);
1617 //gtk_tree_model_get_iter_first(model, &iter);
1618 //if(gtk_tree_selection_iter_is_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), &iter) == FALSE)
1619 //{
1620 ui_cur_manage_dialog_modify(GTK_WIDGET(treeview), NULL);
1621 //}
1622 }
1623
1624
1625
1626 /*
1627 **
1628 */
1629 static void ui_cur_manage_dialog_setup(struct ui_cur_manage_dialog_data *data)
1630 {
1631
1632 DB( g_printf("\n[ui_cur_manage] setup\n") );
1633
1634
1635 ui_cur_listview_populate(data->LV_cur);
1636
1637 //ui_cur_combobox_populate(data->CY_curr, GLOBALS->h_cur);
1638 //ui_cur_combobox_set_active(GTK_COMBO_BOX(data->CY_curr), GLOBALS->kcur);
1639
1640
1641
1642 }
1643
1644
1645 /*
1646 **
1647 */
1648 GtkWidget *ui_cur_manage_dialog (void)
1649 {
1650 struct ui_cur_manage_dialog_data data;
1651 GtkWidget *dialog, *content_area, *content_grid, *group_grid, *bbox;
1652 GtkWidget *widget, *scrollwin, *treeview;
1653 gint crow, row, w, h;
1654
1655 dialog = gtk_dialog_new_with_buttons (_("Currencies"),
1656 GTK_WINDOW(GLOBALS->mainwindow),
1657 0,
1658 _("_Close"),
1659 GTK_RESPONSE_ACCEPT,
1660 NULL);
1661
1662 data.window = dialog;
1663 data.change = 0;
1664
1665 //set the dialog icon
1666 gtk_window_set_icon_name(GTK_WINDOW (dialog), ICONNAME_HB_CURRENCY);
1667
1668 //set a nice dialog size
1669 gtk_window_get_size(GTK_WINDOW(GLOBALS->mainwindow), &w, &h);
1670 gtk_window_set_default_size (GTK_WINDOW(dialog), -1, h/PHI);
1671
1672
1673 //store our window private data
1674 g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)&data);
1675 DB( g_printf("[ui_cur_manage] new dialog=%p, inst_data=%p\n", dialog, &data) );
1676
1677 g_signal_connect (dialog, "destroy",
1678 G_CALLBACK (gtk_widget_destroyed), &dialog);
1679
1680 content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog)); // return a vbox
1681
1682 content_grid = gtk_grid_new();
1683 gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
1684 gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
1685 gtk_container_set_border_width (GTK_CONTAINER(content_grid), SPACING_MEDIUM);
1686 gtk_box_pack_start (GTK_BOX (content_area), content_grid, TRUE, TRUE, 0);
1687
1688 crow = 0;
1689 // group :: --------
1690 group_grid = gtk_grid_new ();
1691 gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
1692 gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
1693 gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
1694
1695 row = 1;
1696 bbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_MEDIUM);
1697 data.BB_update = bbox;
1698 gtk_grid_attach (GTK_GRID(group_grid), bbox, 0, row, 1, 1);
1699
1700 widget = gtk_button_new_from_icon_name (ICONNAME_HB_REFRESH, GTK_ICON_SIZE_BUTTON);
1701 gtk_container_add (GTK_CONTAINER (bbox), widget);
1702
1703 g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (ui_cur_manage_dialog_sync), NULL);
1704
1705 widget = make_label_widget (_("Update online"));
1706 gtk_container_add (GTK_CONTAINER (bbox), widget);
1707
1708 row++;
1709 scrollwin = gtk_scrolled_window_new(NULL,NULL);
1710 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
1711 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1712 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scrollwin), HB_MINHEIGHT_LIST);
1713 treeview = ui_cur_listview_new(FALSE);
1714 data.LV_cur = treeview;
1715 gtk_container_add(GTK_CONTAINER(scrollwin), treeview);
1716 gtk_widget_set_vexpand (scrollwin, TRUE);
1717 gtk_widget_set_hexpand (scrollwin, TRUE);
1718 gtk_grid_attach (GTK_GRID(group_grid), scrollwin, 0, row, 2, 1);
1719
1720 row++;
1721 bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
1722 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START);
1723 gtk_box_set_spacing (GTK_BOX (bbox), SPACING_SMALL);
1724 gtk_grid_attach (GTK_GRID (group_grid), bbox, 0, row, 2, 1);
1725
1726 widget = gtk_button_new_with_mnemonic(_("_Add"));
1727 data.BT_add = widget;
1728 gtk_container_add (GTK_CONTAINER (bbox), widget);
1729
1730 widget = gtk_button_new_with_mnemonic(_("_Edit"));
1731 data.BT_edit = widget;
1732 gtk_container_add (GTK_CONTAINER (bbox), widget);
1733
1734 widget = gtk_button_new_with_mnemonic(_("_Delete"));
1735 data.BT_rem = widget;
1736 gtk_container_add (GTK_CONTAINER (bbox), widget);
1737
1738 widget = gtk_button_new_with_mnemonic(_("Set as base"));
1739 data.BT_base = widget;
1740 gtk_container_add (GTK_CONTAINER (bbox), widget);
1741
1742
1743 //connect all our signals
1744 //g_signal_connect (G_OBJECT (data.ST_name), "activate", G_CALLBACK (ui_cur_manage_dialog_add), NULL);
1745
1746 g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data.LV_cur)), "changed", G_CALLBACK (ui_cur_manage_dialog_selection), NULL);
1747 g_signal_connect (GTK_TREE_VIEW(data.LV_cur), "row-activated", G_CALLBACK (ui_cur_manage_dialog_onRowActivated), NULL);
1748
1749 g_signal_connect (G_OBJECT (data.BT_add), "clicked", G_CALLBACK (ui_cur_manage_dialog_add), NULL);
1750 g_signal_connect (G_OBJECT (data.BT_rem), "clicked", G_CALLBACK (ui_cur_manage_dialog_remove), NULL);
1751 g_signal_connect (G_OBJECT (data.BT_edit), "clicked", G_CALLBACK (ui_cur_manage_dialog_modify), NULL);
1752 //g_signal_connect (G_OBJECT (data.BT_mov), "clicked", G_CALLBACK (ui_cur_manage_dialog_move), NULL);
1753 g_signal_connect (G_OBJECT (data.BT_base), "clicked", G_CALLBACK (ui_cur_manage_dialog_setbase), NULL);
1754
1755 //setup, init and show window
1756 ui_cur_manage_dialog_setup(&data);
1757
1758 ui_cur_manage_dialog_update(data.LV_cur, NULL);
1759
1760 //gtk_window_resize(GTK_WINDOW(dialog), 256, 414);
1761
1762 gtk_widget_show_all (dialog);
1763
1764 //wait for the user
1765 gint result = gtk_dialog_run (GTK_DIALOG (dialog));
1766
1767 switch (result)
1768 {
1769 case GTK_RESPONSE_ACCEPT:
1770 //do_application_specific_something ();
1771 break;
1772 default:
1773 //do_nothing_since_dialog_was_cancelled ();
1774 break;
1775 }
1776
1777
1778 // cleanup and destroy
1779 GLOBALS->changes_count += data.change;
1780 gtk_widget_destroy (dialog);
1781
1782 return NULL;
1783 }
1784
1785
1786
This page took 0.113817 seconds and 4 git commands to generate.