]> Dogcows Code - chaz/homebank/blobdiff - src/ui-currency.c
Merge branch 'upstream'
[chaz/homebank] / src / ui-currency.c
diff --git a/src/ui-currency.c b/src/ui-currency.c
new file mode 100644 (file)
index 0000000..2f58322
--- /dev/null
@@ -0,0 +1,1601 @@
+/*  HomeBank -- Free, easy, personal accounting for everyone.
+ *  Copyright (C) 1995-2012 Maxime DOYEN
+ *
+ *  This file is part of HomeBank.
+ *
+ *  HomeBank is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  HomeBank is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "homebank.h"
+
+#include "ui-currency.h"
+
+
+#define MYDEBUG 0
+
+#if MYDEBUG
+#define DB(x) (x);
+#else
+#define DB(x);
+#endif
+
+/* our global datas */
+extern struct HomeBank *GLOBALS;
+extern struct Preferences *PREFS;
+
+extern Currency4217 iso4217cur[];
+extern guint n_iso4217cur;
+
+static void ui_cur_manage_dialog_update(GtkWidget *treeview, gpointer user_data);
+
+/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
+/**
+ * ui_cur_combobox_get_name:
+ *
+ * get the name of the active curee or -1
+ *
+ * Return value: a new allocated name tobe freed with g_free
+ *
+ */
+gchar *
+ui_cur_combobox_get_name(GtkComboBox *entry_box)
+{
+gchar *cbname;
+gchar *name = NULL;
+
+       cbname = (gchar *)gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(GTK_BIN (entry_box))));
+
+       if( cbname != NULL)
+       {
+               name = g_strdup(cbname);
+               g_strstrip(name);
+       }
+
+       return name;
+}
+
+
+/**
+ * ui_cur_combobox_get_key:
+ *
+ * get the key of the active curee
+ *
+ * Return value: the key or 0
+ *
+ */
+guint32
+ui_cur_combobox_get_key(GtkComboBox *entry_box)
+{
+GtkTreeModel *model;
+GtkTreeIter    iter;
+guint32 key = 0;
+
+       if (gtk_combo_box_get_active_iter(entry_box, &iter) == TRUE)
+       {
+               model = gtk_combo_box_get_model(entry_box);
+               gtk_tree_model_get (model, &iter, 1, &key, -1);
+       }
+
+       return key;
+}
+
+
+gboolean
+ui_cur_combobox_set_active(GtkComboBox *entry_box, guint32 key)
+{
+GtkTreeModel *model;
+GtkTreeIter    iter;
+gboolean valid;
+guint32 cbkey;
+
+       model = gtk_combo_box_get_model(entry_box);
+       valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
+       while (valid)
+       {
+               gtk_tree_model_get (model, &iter, 1, &cbkey, -1);
+               if(cbkey == key)
+                       break;
+
+               valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
+       }
+
+       gtk_combo_box_set_active_iter(entry_box, &iter);
+
+       return FALSE;
+}
+
+
+
+
+/**
+ * ui_cur_combobox_add:
+ *
+ * Add a single element (useful for dynamics add)
+ *
+ * Return value: --
+ *
+ */
+void
+ui_cur_combobox_add(GtkComboBox *entry_box, Currency *cur)
+{
+       if( cur->name != NULL )
+       {
+       GtkTreeModel *model;
+       GtkTreeIter  iter;
+
+               model = gtk_combo_box_get_model(GTK_COMBO_BOX(entry_box));
+
+               gtk_list_store_append (GTK_LIST_STORE(model), &iter);
+               gtk_list_store_set (GTK_LIST_STORE(model), &iter, 0, cur->name, 1, cur->key, -1);
+       }
+}
+
+static void
+ui_cur_combobox_populate_ghfunc(gpointer key, gpointer value, struct curPopContext *ctx)
+{
+GtkTreeIter  iter;
+Currency *cur = value;
+
+       if( ( cur->key != ctx->except_key ) )
+       {
+               gtk_list_store_append (GTK_LIST_STORE(ctx->model), &iter);
+               gtk_list_store_set (GTK_LIST_STORE(ctx->model), &iter, 0, cur->name, 1, cur->key, -1);
+       }
+}
+
+void
+ui_cur_combobox_populate_except(GtkComboBox *entry_box, GHashTable *hash, guint32 except_key)
+{
+GtkTreeModel *model;
+struct curPopContext ctx;
+
+    DB( g_print ("ui_cur_combobox_populate\n") );
+
+       model = gtk_combo_box_get_model(GTK_COMBO_BOX(entry_box));
+
+       /* keep our model alive and detach from combobox and completion */
+       g_object_ref(model);
+       gtk_combo_box_set_model(GTK_COMBO_BOX(entry_box), NULL);
+
+       /* clear and populate */
+       ctx.model = model;
+       ctx.except_key = except_key;
+       gtk_list_store_clear (GTK_LIST_STORE(model));
+       g_hash_table_foreach(hash, (GHFunc)ui_cur_combobox_populate_ghfunc, &ctx);
+
+       /* reatach our model */
+       gtk_combo_box_set_model(GTK_COMBO_BOX(entry_box), model);
+       g_object_unref(model);
+
+       gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING);
+
+}
+
+/**
+ * ui_cur_combobox_populate:
+ *
+ * Populate the list and completion
+ *
+ * Return value: --
+ *
+ */
+void
+ui_cur_combobox_populate(GtkComboBox *entry_box, GHashTable *hash)
+{
+       ui_cur_combobox_populate_except(entry_box, hash, -1);
+}
+
+
+static gint
+ui_cur_combobox_compare_func (GtkTreeModel *model, GtkTreeIter  *a, GtkTreeIter  *b, gpointer      userdata)
+{
+gint ret = 0;
+gchar *name1, *name2;
+
+    gtk_tree_model_get(model, a, 0, &name1, -1);
+    gtk_tree_model_get(model, b, 0, &name2, -1);
+
+    if (name1 == NULL || name2 == NULL)
+    {
+        if (name1 == NULL && name2 == NULL)
+        goto end;
+
+        ret = (name1 == NULL) ? -1 : 1;
+    }
+    else
+    {
+        ret = g_utf8_collate(name1,name2);
+    }
+
+
+  end:
+
+    g_free(name1);
+    g_free(name2);
+
+       return ret;
+  }
+
+
+static void
+ui_cur_combobox_test (GtkCellLayout   *cell_layout,
+                  GtkCellRenderer *cell,
+                  GtkTreeModel    *tree_model,
+                  GtkTreeIter     *iter,
+                  gpointer         data)
+{
+gchar *name;
+
+       gtk_tree_model_get(tree_model, iter,
+               0, &name,
+               -1);
+
+       if( !name )
+               g_object_set(cell, "text", _("(none)"), NULL);
+       else
+               g_object_set(cell, "text", name, NULL);
+
+}
+
+/**
+ * ui_cur_combobox_new:
+ *
+ * Create a new curee combobox
+ *
+ * Return value: the new widget
+ *
+ */
+GtkWidget *
+ui_cur_combobox_new(GtkWidget *label)
+{
+GtkListStore *store;
+GtkWidget *combobox;
+GtkCellRenderer    *renderer;
+
+       store = gtk_list_store_new (2,
+               G_TYPE_STRING,
+           G_TYPE_INT
+               );
+       gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store), ui_cur_combobox_compare_func, NULL, NULL);
+
+       // dothe same for combobox
+
+       combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
+
+       gtk_cell_layout_clear(GTK_CELL_LAYOUT (combobox));
+
+       renderer = gtk_cell_renderer_text_new ();
+       gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, TRUE);
+       gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer, "text", 0, NULL);
+
+       gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combobox),
+                                           renderer,
+                                           ui_cur_combobox_test,
+                                           NULL, NULL);
+
+       g_object_unref(store);
+
+       if(label)
+               gtk_label_set_mnemonic_widget (GTK_LABEL(label), combobox);
+
+       gtk_widget_set_size_request (combobox, 10, -1);
+
+       return combobox;
+}
+
+
+
+/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
+
+
+
+static void
+ui_cur_listview_toggled_cb (GtkCellRendererToggle *cell,
+              gchar                 *path_str,
+              gpointer               data)
+{
+  GtkTreeModel *model = (GtkTreeModel *)data;
+  GtkTreeIter  iter;
+  GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
+  gboolean fixed;
+
+  /* get toggled iter */
+  gtk_tree_model_get_iter (model, &iter, path);
+  gtk_tree_model_get (model, &iter, LST_DEFCUR_TOGGLE, &fixed, -1);
+
+  /* do something with the value */
+  fixed ^= 1;
+
+  /* set new value */
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter, LST_DEFCUR_TOGGLE, fixed, -1);
+
+  /* clean up */
+  gtk_tree_path_free (path);
+}
+
+static gint
+ui_cur_listview_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
+{
+gint result = 0;
+Currency *entry1, *entry2;
+gchar *name1, *name2;
+
+    gtk_tree_model_get(model, a, LST_DEFCUR_DATAS, &entry1, -1);
+    gtk_tree_model_get(model, b, LST_DEFCUR_DATAS, &entry2, -1);
+
+       name1 = (entry1->key == GLOBALS->kcur) ? NULL : entry1->iso_code;
+       name2 = (entry2->key == GLOBALS->kcur) ? NULL : entry2->iso_code;
+
+    result = hb_string_compare(name1,name2);
+
+    return result;
+}
+
+static void
+ui_cur_listview_name_cell_data_function (GtkTreeViewColumn *col,
+                               GtkCellRenderer *renderer,
+                               GtkTreeModel *model,
+                               GtkTreeIter *iter,
+                               gpointer user_data)
+{
+Currency *entry;
+gchar *string;
+gint weight;
+
+       gtk_tree_model_get(model, iter, LST_DEFCUR_DATAS, &entry, -1);
+
+       weight = entry->key == GLOBALS->kcur ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
+
+       #if MYDEBUG
+               if( entry->key == GLOBALS->kcur )
+                       string = g_strdup_printf ("[%d] %s - %s<span size=\"small\">\n(%s)</span>", entry->key, entry->iso_code, entry->name, _("Base currency"));
+               else
+                       string = g_strdup_printf ("[%d] %s - %s", entry->key, entry->iso_code, entry->name);
+               g_object_set(renderer, "weight", weight, "markup", string, NULL);
+               g_free(string);
+       #else
+               if( entry->key == GLOBALS->kcur )
+                       string = g_strdup_printf ("%s - %s<span size=\"small\">\n(%s)</span>", entry->iso_code, entry->name, _("Base currency"));
+               else
+                       string = g_strdup_printf ("%s - %s", entry->iso_code, entry->name);
+               g_object_set(renderer, "weight", weight, "markup", string, NULL);
+               g_free(string);
+       #endif
+
+}
+
+
+static void
+ui_cur_listview_symbol_cell_data_function (GtkTreeViewColumn *col,
+                               GtkCellRenderer *renderer,
+                               GtkTreeModel *model,
+                               GtkTreeIter *iter,
+                               gpointer user_data)
+{
+Currency *entry;
+gint weight;
+
+       gtk_tree_model_get(model, iter, LST_DEFCUR_DATAS, &entry, -1);
+
+       weight = entry->key == GLOBALS->kcur ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
+       
+       g_object_set(renderer, "weight", weight, "text", entry->symbol, NULL);
+}
+
+
+static void
+ui_cur_listview_lastmodified_cell_data_function (GtkTreeViewColumn *col,
+                               GtkCellRenderer *renderer,
+                               GtkTreeModel *model,
+                               GtkTreeIter *iter,
+                               gpointer user_data)
+{
+Currency *entry;
+gchar buffer[256];
+GDate date;
+gint weight;
+
+       gtk_tree_model_get(model, iter, LST_DEFCUR_DATAS, &entry, -1);
+
+       weight = entry->key == GLOBALS->kcur ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
+       
+       if(entry->mdate > 0)
+       {
+               g_date_set_julian (&date, entry->mdate);
+               g_date_strftime (buffer, 256-1, PREFS->date_format, &date);
+
+               //g_snprintf(buf, sizeof(buf), "%d", ope->ope_Date);
+
+               g_object_set(renderer, "weight", weight, "text", buffer, NULL);
+    }
+    else
+               g_object_set(renderer, "weight", weight, "text", "-", NULL);
+}
+
+
+
+static void
+ui_cur_listview_rate_cell_data_function (GtkTreeViewColumn *col,
+                               GtkCellRenderer *renderer,
+                               GtkTreeModel *model,
+                               GtkTreeIter *iter,
+                               gpointer user_data)
+{
+Currency *entry;
+gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
+
+       gtk_tree_model_get(model, iter, LST_DEFCUR_DATAS, &entry, -1);
+
+       if(entry->key == GLOBALS->kcur)
+               g_object_set(renderer, "text", "-", NULL);
+       else
+       {
+               //g_ascii_formatd(formatd_buf, sizeof (formatd_buf), "%.6f", entry->rate);
+               //g_snprintf(formatd_buf, sizeof (formatd_buf), "%f", entry->rate);
+               hb_str_rate(formatd_buf, sizeof (formatd_buf), entry->rate);
+               g_object_set(renderer, "text", formatd_buf, NULL);
+       }
+       
+}
+
+
+/* = = = = = = = = = = = = = = = = */
+
+
+void
+ui_cur_listview_add(GtkTreeView *treeview, Currency *item)
+{
+       if( item->name != NULL )
+       {
+       GtkTreeModel *model;
+       GtkTreeIter     iter;
+
+               model = gtk_tree_view_get_model(treeview);
+
+               gtk_list_store_append (GTK_LIST_STORE(model), &iter);
+               gtk_list_store_set (GTK_LIST_STORE(model), &iter,
+                       LST_DEFCUR_TOGGLE, FALSE,
+                       LST_DEFCUR_DATAS, item,
+                       -1);
+       }
+}
+
+guint32
+ui_cur_listview_get_selected_key(GtkTreeView *treeview)
+{
+GtkTreeSelection *selection;
+GtkTreeModel            *model;
+GtkTreeIter                     iter;
+
+       selection = gtk_tree_view_get_selection(treeview);
+       if (gtk_tree_selection_get_selected(selection, &model, &iter))
+       {
+       Currency *item;
+
+               gtk_tree_model_get(model, &iter, LST_DEFCUR_DATAS, &item, -1);
+
+               if( item != NULL )
+                       return item->key;
+       }
+       return 0;
+}
+
+void
+ui_cur_listview_remove_selected(GtkTreeView *treeview)
+{
+GtkTreeSelection *selection;
+GtkTreeModel            *model;
+GtkTreeIter                     iter;
+
+       selection = gtk_tree_view_get_selection(treeview);
+       if (gtk_tree_selection_get_selected(selection, &model, &iter))
+       {
+               gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+       }
+}
+
+
+static void ui_cur_listview_populate_ghfunc(gpointer key, gpointer value, GtkTreeModel *model)
+{
+GtkTreeIter    iter;
+Currency *item = value;
+
+       gtk_list_store_append (GTK_LIST_STORE(model), &iter);
+       gtk_list_store_set (GTK_LIST_STORE(model), &iter,
+               LST_DEFCUR_TOGGLE       , FALSE,
+               LST_DEFCUR_DATAS, item,
+               -1);
+}
+
+void ui_cur_listview_populate(GtkWidget *view)
+{
+GtkTreeModel *model;
+
+       model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
+
+       gtk_list_store_clear (GTK_LIST_STORE(model));
+
+       g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
+       gtk_tree_view_set_model(GTK_TREE_VIEW(view), NULL); /* Detach model from view */
+
+       /* populate */
+       g_hash_table_foreach(GLOBALS->h_cur, (GHFunc)ui_cur_listview_populate_ghfunc, model);
+
+       gtk_tree_view_set_model(GTK_TREE_VIEW(view), model); /* Re-attach model to view */
+       g_object_unref(model);
+}
+
+/* test */
+/*
+static void
+ui_cur_listivew_rate_edited_func (GtkCellRendererText *cell,
+             const gchar         *path_string,
+             const gchar         *new_text,
+             gpointer             data)
+{
+  GtkTreeModel *model = (GtkTreeModel *)data;
+  GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
+  GtkTreeIter iter;
+
+       g_print("cell edited '%s' path %s\n", new_text, path_string);
+
+       
+  gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column"));
+
+  gtk_tree_model_get_iter (model, &iter, path);
+
+       Currency *item;
+
+               gtk_tree_model_get(model, &iter, LST_DEFCUR_DATAS, &item, -1);
+
+       item->rate = atof(new_text);
+
+       GLOBALS->changes_count++;
+       
+       
+  gtk_tree_path_free (path);
+}
+*/
+
+
+GtkWidget *
+ui_cur_listview_new(gboolean withtoggle)
+{
+GtkListStore *store;
+GtkWidget *treeview;
+GtkCellRenderer                *renderer;
+GtkTreeViewColumn      *column;
+
+       // create list store
+       store = gtk_list_store_new(
+               NUM_LST_DEFCUR,
+               G_TYPE_BOOLEAN,
+               G_TYPE_POINTER
+               );
+
+       // treeview
+       treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+       g_object_unref(store);
+
+       // column 1: toggle
+       if( withtoggle == TRUE )
+       {
+               renderer = gtk_cell_renderer_toggle_new ();
+               column = gtk_tree_view_column_new_with_attributes (_("Visible"),
+                                                            renderer,
+                                                            "active", LST_DEFCUR_TOGGLE,
+                                                            NULL);
+               gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
+
+               g_signal_connect (renderer, "toggled",
+                           G_CALLBACK (ui_cur_listview_toggled_cb), store);
+
+       }
+
+       gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview), PREFS->grid_lines);
+
+
+       // column 1: name
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new();
+       gtk_tree_view_column_set_title(column, _("Name"));
+       gtk_tree_view_column_set_alignment (column, 0.5);
+       gtk_tree_view_column_pack_start(column, renderer, TRUE);
+       gtk_tree_view_column_set_cell_data_func(column, renderer, ui_cur_listview_name_cell_data_function, GINT_TO_POINTER(LST_DEFCUR_DATAS), NULL);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
+
+       // column 2: code
+       renderer = gtk_cell_renderer_text_new ();
+       g_object_set(renderer, "xalign", 0.5, NULL);
+       column = gtk_tree_view_column_new();
+       gtk_tree_view_column_set_title(column, _("Symbol"));
+       gtk_tree_view_column_set_alignment (column, 0.5);
+       gtk_tree_view_column_pack_start(column, renderer, TRUE);
+       gtk_tree_view_column_set_cell_data_func(column, renderer, ui_cur_listview_symbol_cell_data_function, GINT_TO_POINTER(LST_DEFCUR_DATAS), NULL);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
+
+       // column 3: base rate
+       renderer = gtk_cell_renderer_text_new ();
+       //g_object_set (renderer, "editable", TRUE, NULL);
+       g_object_set(renderer, "xalign", 1.0, NULL);
+       column = gtk_tree_view_column_new();
+       gtk_tree_view_column_set_title(column, _("Exchange rate"));
+       gtk_tree_view_column_set_alignment (column, 0.5);
+       gtk_tree_view_column_pack_start(column, renderer, TRUE);
+       gtk_tree_view_column_set_cell_data_func(column, renderer, ui_cur_listview_rate_cell_data_function, GINT_TO_POINTER(LST_DEFCUR_DATAS), NULL);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
+
+       //g_signal_connect (renderer, "edited", G_CALLBACK (ui_cur_listivew_rate_edited_func), GTK_TREE_MODEL(store));
+
+       // column 4: last modified
+       renderer = gtk_cell_renderer_text_new ();
+       g_object_set(renderer, "xalign", 0.5, NULL);
+       column = gtk_tree_view_column_new();
+       gtk_tree_view_column_set_title(column, _("Last modfied"));
+       gtk_tree_view_column_set_alignment (column, 0.5);
+       gtk_tree_view_column_pack_start(column, renderer, TRUE);
+       gtk_tree_view_column_set_cell_data_func(column, renderer, ui_cur_listview_lastmodified_cell_data_function, GINT_TO_POINTER(LST_DEFCUR_DATAS), NULL);
+       gtk_tree_view_column_set_resizable(column, TRUE);
+       gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
+
+       
+       // treeview attribute
+       gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), 1);
+       //gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), TRUE);
+       //gtk_tree_view_set_reorderable (GTK_TREE_VIEW(view), TRUE);
+       gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_DEFCUR_DATAS, ui_cur_listview_compare_func, NULL, NULL);
+       gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), LST_DEFCUR_DATAS, GTK_SORT_ASCENDING);
+
+       return treeview;
+}
+
+
+/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+/*
+** update the number sample label
+*/
+static void ui_cur_edit_dialog_update_sample(GtkWidget *widget, gpointer user_data)
+{
+struct ui_cur_edit_dialog_data *data;
+Currency cur;
+gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
+gchar  buf[128];
+
+       DB( g_print("\n[ui-pref] number sample\n") );
+
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+
+       cur.symbol = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_symbol));
+       cur.sym_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_symisprefix));
+       cur.decimal_char  = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_decimalchar));
+       cur.grouping_char = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_groupingchar));
+       cur.frac_digits   = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_fracdigits));
+
+       da_cur_initformat (&cur);
+       DB( g_print("fmt: %s\n", cur.format) );
+       
+       g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur.format, HB_NUMBER_SAMPLE);
+       
+       hb_str_formatd(buf, 127, formatd_buf, &cur, TRUE);
+       gtk_label_set_text(GTK_LABEL(data->LB_sample), buf);
+
+}
+
+
+
+static void ui_cur_edit_dialog_set(GtkWidget *widget, Currency *cur)
+{
+struct ui_cur_edit_dialog_data *data;
+Currency *base;
+gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
+gchar label[128];
+
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+
+       g_snprintf(label, 127, "%s - %s", cur->iso_code, cur->name);
+       gtk_label_set_text (GTK_LABEL(data->LB_name), label);
+
+       base = da_cur_get(GLOBALS->kcur);
+       
+       g_snprintf(label, 127, "1 %s _=", base->iso_code);
+       gtk_label_set_text_with_mnemonic (GTK_LABEL(data->LB_rate), label);
+       gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_rate), cur->rate);
+
+       da_cur_initformat(cur);
+       g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur->format, HB_NUMBER_SAMPLE);
+       hb_str_formatd(label, 127, formatd_buf, cur, TRUE);
+       gtk_label_set_text (GTK_LABEL(data->LB_sample), label);
+
+       ui_gtk_entry_set_text(data->ST_symbol, cur->symbol);
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_symisprefix), cur->sym_prefix);
+       ui_gtk_entry_set_text(data->ST_decimalchar, cur->decimal_char);
+       ui_gtk_entry_set_text(data->ST_groupingchar, cur->grouping_char);
+       gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_fracdigits), cur->frac_digits);
+
+}
+
+
+
+static void ui_cur_edit_dialog_get(GtkWidget *widget, Currency *cur)
+{
+struct ui_cur_edit_dialog_data *data;
+gdouble rate;
+       
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+
+
+       ui_gtk_entry_replace_text(data->ST_symbol, &cur->symbol);
+       cur->sym_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_symisprefix));
+       ui_gtk_entry_replace_text(data->ST_decimalchar, &cur->decimal_char);
+       ui_gtk_entry_replace_text(data->ST_groupingchar, &cur->grouping_char);
+       cur->frac_digits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_fracdigits));
+
+       da_cur_initformat(cur);
+
+       rate = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_rate));
+       if(cur->rate != rate)
+       {
+               cur->rate = rate;
+               cur->mdate = GLOBALS->today;
+       }
+
+}
+
+
+void ui_cur_edit_dialog_new(GtkWindow *parent, Currency *cur)
+{
+struct ui_cur_edit_dialog_data data;
+GtkWidget *dialog, *content_area, *content_grid, *group_grid;
+GtkWidget *label, *widget, *expander;
+gint crow, row;
+
+       dialog = gtk_dialog_new_with_buttons (
+                       _("Edit currency"),
+                                   GTK_WINDOW (parent),
+                                   0,
+                                   _("_Cancel"),
+                                   GTK_RESPONSE_REJECT,
+                                   _("_OK"),
+                                   GTK_RESPONSE_ACCEPT,
+                                   NULL);
+
+       data.window = dialog;
+
+       //store our dialog private data
+       g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)&data);
+       DB( g_printf("(ui_cur_select_dialog_new) dialog=%x, inst_data=%x\n", (guint)dialog, (guint)&data) );
+
+
+       content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog));        // return a vbox
+
+       content_grid = gtk_grid_new();
+       gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+       gtk_container_set_border_width (GTK_CONTAINER(content_grid), SPACING_MEDIUM);
+       gtk_box_pack_start (GTK_BOX (content_area), content_grid, TRUE, TRUE, 0);
+
+       crow = 0;
+       // group :: Currency
+    group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+
+       label = make_label_group(_("Currency"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       
+       row = 1;
+       widget = make_label(NULL, 0, 0.5);
+       data.LB_name = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+
+       // group :: exchange
+    group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Exchange rate"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       
+       row = 1;
+       label = make_label(NULL, 0, 0.5);
+       data.LB_rate = label;
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_exchange_rate(label);
+       data.NB_rate = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+
+       gtk_widget_set_sensitive(group_grid, (GLOBALS->kcur == cur->key) ? FALSE : TRUE);
+
+       // group :: format
+    group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+
+       label = make_label_group(_("Format"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+
+       row++;
+       widget = make_label(NULL, 0, 0.5);
+       data.LB_sample = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+
+       row++;
+       expander = gtk_expander_new_with_mnemonic (_("_Customize"));
+       gtk_grid_attach (GTK_GRID (group_grid), expander, 1, row, 2, 1);
+
+    group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_container_add (GTK_CONTAINER (expander), group_grid);
+
+       row = 1;
+       label = make_label_widget(_("_Symbol:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_string_maxlength(label, 3);
+       data.ST_symbol = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+
+       row++;
+       widget = gtk_check_button_new_with_mnemonic (_("Is pre_fix"));
+       data.CM_symisprefix = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+
+       row++;
+       label = make_label_widget(_("_Decimal char:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_string_maxlength(label, 1);
+       data.ST_decimalchar = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+
+       row++;
+       label = make_label_widget(_("_Frac digits:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_numeric(label, 0.0, 6.0);
+       data.NB_fracdigits = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+       
+       row++;
+       label = make_label_widget(_("_Grouping char:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_string_maxlength(label, 1);
+       data.ST_groupingchar = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+
+
+       //gtk_window_resize(GTK_WINDOW(dialog), 400/PHI, 400);
+
+       ui_cur_edit_dialog_set(dialog, cur);
+
+       gtk_widget_show_all(content_area);
+
+       //signals
+    g_signal_connect (data.ST_symbol   , "changed", G_CALLBACK (ui_cur_edit_dialog_update_sample), NULL);
+       g_signal_connect (data.CM_symisprefix, "toggled", G_CALLBACK (ui_cur_edit_dialog_update_sample), NULL);
+       g_signal_connect (data.ST_decimalchar , "changed", G_CALLBACK (ui_cur_edit_dialog_update_sample), NULL);
+    g_signal_connect (data.ST_groupingchar, "changed", G_CALLBACK (ui_cur_edit_dialog_update_sample), NULL);
+    g_signal_connect (data.NB_fracdigits, "value-changed", G_CALLBACK (ui_cur_edit_dialog_update_sample), NULL);
+
+       // wait for the user
+       gint result = gtk_dialog_run (GTK_DIALOG (dialog));
+       if(result == GTK_RESPONSE_ACCEPT)
+       {
+               ui_cur_edit_dialog_get(dialog, cur);
+       }
+
+       // cleanup and destroy
+       gtk_widget_destroy (dialog);
+
+}
+
+
+/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
+enum {
+       LST_CURSEL_NAME,
+       LST_CURSEL_ISO,
+       LST_CURSEL_FULLNAME,
+       LST_CURSEL_DATA,
+       NUM_LST_CURSEL
+};
+
+
+static void ui_cur_select_rowactivated (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer userdata)
+{
+struct ui_cur_select_dialog_data *data = userdata;
+
+       gtk_dialog_response(GTK_DIALOG(data->window), GTK_RESPONSE_ACCEPT);
+}
+
+
+static GtkTreeModel *ui_cur_select_model_create (void)
+{
+guint i = 0;
+GtkListStore *store;
+GtkTreeIter iter;
+Currency4217 *cur;
+gchar buffer[255];
+
+       /* create list store */
+       store = gtk_list_store_new (NUM_LST_CURSEL,
+               G_TYPE_STRING, 
+           G_TYPE_STRING,
+           G_TYPE_STRING,
+           G_TYPE_POINTER,
+           NULL
+       );
+
+       for (i = 0; i< n_iso4217cur; i++)
+       {
+               cur = &iso4217cur[i];
+
+               g_snprintf(buffer, 255-1, "%s - %s", cur->curr_iso_code, cur->name);
+               
+               gtk_list_store_append (store, &iter);
+               gtk_list_store_set (store, &iter,
+                   LST_CURSEL_NAME, cur->name,
+                   LST_CURSEL_ISO, cur->curr_iso_code,
+                   LST_CURSEL_FULLNAME, buffer,
+                   LST_CURSEL_DATA, cur,
+                   -1);
+
+
+       }
+
+       return GTK_TREE_MODEL (store);
+}
+
+
+static Currency4217 *ui_cur_select_dialog_get_langue(struct ui_cur_select_dialog_data *data)
+{
+GtkTreeSelection *treeselection;
+gboolean selected;
+GtkTreeModel            *model;
+GtkTreeIter                     iter;
+Currency4217 *curfmt = NULL;
+
+       DB( g_printf("\n(ui_cur_select_dialog_get_langue)\n") );
+
+       treeselection = gtk_tree_view_get_selection (GTK_TREE_VIEW(data->LV_cur));
+       selected = gtk_tree_selection_get_selected(treeselection, &model, &iter);
+       if(selected)
+       {
+               gtk_tree_model_get(model, &iter, LST_CURSEL_DATA, &curfmt, -1);
+
+               DB( g_printf(" - iso is '%s'\n", curfmt->curr_iso_code) );
+       }       
+       
+       return curfmt;  
+}
+
+
+static void
+ui_cur_select_search_changed_cb (GtkWidget *widget, gpointer user_data)
+{
+struct ui_cur_select_dialog_data *data = user_data;
+
+       DB( g_print(" search changed\n") );
+
+       gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(data->modelfilter));
+       
+}
+
+
+static gboolean
+ui_cur_select_model_func_visible (GtkTreeModel *model,
+              GtkTreeIter  *iter,
+              gpointer      data)
+{
+  // Visible if row is non-empty and first column is “HI”
+  gchar *str;
+  gboolean visible = TRUE;
+  GtkEntry *entry = data;
+
+       if(!GTK_IS_ENTRY(entry))
+               return TRUE;
+
+       gchar *needle = g_ascii_strdown(gtk_entry_get_text(entry), -1);
+
+  gtk_tree_model_get (model, iter, LST_CURSEL_FULLNAME, &str, -1);
+
+       gchar *haystack = g_ascii_strdown(str, -1);
+
+       if (str && g_strrstr (haystack, needle) == NULL)
+       {
+               visible = FALSE;
+       }
+
+       DB( g_print("filter: '%s' '%s' %d\n", str, needle, visible) );
+
+       g_free(haystack);
+       g_free(needle);
+  g_free (str);
+
+  return visible;
+}
+
+
+Currency4217 * ui_cur_select_dialog_new(GtkWindow *parent, gint select_mode)
+{
+struct ui_cur_select_dialog_data data;
+GtkWidget *dialog, *content_area, *content_grid, *group_grid;
+GtkWidget *scrollwin, *treeview, *widget;
+gint crow, row;
+Currency4217 *curfmt = NULL;
+
+       dialog = gtk_dialog_new_with_buttons (
+                       (select_mode == CUR_SELECT_MODE_BASE) ? _("Select base currency") : _("Select currency"),
+                                   GTK_WINDOW (parent),
+                                   0,
+                                   _("_Cancel"),
+                                   GTK_RESPONSE_REJECT,
+                                   _("_OK"),
+                                   GTK_RESPONSE_ACCEPT,
+                                   NULL);
+
+       data.window = dialog;
+
+       //store our dialog private data
+       g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)&data);
+       DB( g_printf("(ui_cur_select_dialog_new) dialog=%x, inst_data=%x\n", (guint)dialog, (guint)&data) );
+
+
+       content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog));        // return a vbox
+
+       content_grid = gtk_grid_new();
+       gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+       gtk_container_set_border_width (GTK_CONTAINER(content_grid), SPACING_MEDIUM);
+       gtk_box_pack_start (GTK_BOX (content_area), content_grid, TRUE, TRUE, 0);
+
+       crow = 0;
+       // group :: Search
+    group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+
+       row = 1;
+       widget = gtk_search_entry_new();
+       data.ST_search = widget;
+       gtk_widget_set_hexpand (widget, TRUE);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 1, 1);
+
+
+       row++;
+       scrollwin = gtk_scrolled_window_new(NULL,NULL);
+       gtk_grid_attach (GTK_GRID (group_grid), scrollwin, 1, row, 1, 1);
+
+       gtk_widget_set_vexpand (scrollwin, TRUE);
+    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+       //test treefilter
+       data.model = ui_cur_select_model_create();
+       data.modelfilter = gtk_tree_model_filter_new(GTK_TREE_MODEL(data.model), NULL);
+       gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(data.modelfilter), ui_cur_select_model_func_visible, data.ST_search, NULL);
+       data.sortmodel = gtk_tree_model_sort_new_with_model(data.modelfilter);
+       
+       
+       //
+       
+       treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL(data.sortmodel));
+       data.LV_cur = treeview;
+       //gtk_tree_view_set_search_column (GTK_TREE_VIEW (treeview), LST_CURSEL_NAME);
+       gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(data.sortmodel), LST_CURSEL_NAME, GTK_SORT_ASCENDING);
+       //g_object_unref (model);
+       gtk_container_add(GTK_CONTAINER(scrollwin), treeview);
+       
+       // populate list
+  GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
+
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, "text", LST_CURSEL_NAME, NULL);
+       gtk_tree_view_column_set_sort_column_id (column, LST_CURSEL_NAME);
+       gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+       renderer = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes (_("ISO Code"), renderer, "text", LST_CURSEL_ISO, NULL);
+       gtk_tree_view_column_set_sort_column_id (column, LST_CURSEL_ISO);
+       gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+       
+       gtk_window_resize(GTK_WINDOW(dialog), 400/PHI, 400);
+
+
+       gtk_widget_show_all(content_area);
+
+       // signals
+       g_signal_connect (data.ST_search, "search-changed", G_CALLBACK (ui_cur_select_search_changed_cb), &data);
+       g_signal_connect (GTK_TREE_VIEW(data.LV_cur), "row-activated", G_CALLBACK (ui_cur_select_rowactivated), &data);
+
+       
+       // wait for the user
+       gint result = gtk_dialog_run (GTK_DIALOG (dialog));
+       if(result == GTK_RESPONSE_ACCEPT)
+       {
+               curfmt = ui_cur_select_dialog_get_langue(&data);
+       }
+               
+
+       // cleanup and destroy
+       gtk_widget_destroy (dialog);
+
+       return curfmt;
+}
+
+
+/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
+
+gint ui_cur_manage_dialog_update_currencies(GtkWindow *parent)
+{
+GError *error = NULL;
+gboolean retcode = FALSE;
+
+       DB( g_printf("\n(ui_cur_manage) update currencies\n") );
+
+       // do nothing if just the base currency
+       if(da_cur_length() <= 1)
+               return TRUE;
+
+       retcode = currency_sync_online(&error);
+       
+       DB( g_print("retcode: %d\n", retcode) );
+
+       if(!retcode)
+       {
+       gchar *msg = _("Unknow error");
+
+               if( error )
+                       msg = error->message;
+
+               g_warning("update online: '%s'", msg);
+
+               ui_dialog_msg_infoerror(GTK_WINDOW(parent), GTK_MESSAGE_ERROR,
+                       _("Update online error"),
+                       msg,
+                       NULL
+                       );
+       
+               if( error )
+                       g_error_free (error);
+       }
+       
+       return retcode;
+}
+
+
+static void
+ui_cur_manage_dialog_sync(GtkWidget *widget, gpointer user_data)
+{
+struct ui_cur_manage_dialog_data *data;
+gboolean retcode;
+       
+       DB( g_printf("\n(ui_cur_manage) sync online\n") );
+
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+
+       retcode = ui_cur_manage_dialog_update_currencies(GTK_WINDOW(data->window));
+
+       if(retcode == TRUE)
+       {
+               gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_cur));
+               //todo: (or not) msg with changes
+               
+       }
+}
+
+
+/**
+ * ui_cur_manage_dialog_add:
+ *
+ */
+static void
+ui_cur_manage_dialog_add(GtkWidget *widget, gpointer user_data)
+{
+struct ui_cur_manage_dialog_data *data;
+Currency4217 *curfmt;
+
+       DB( g_printf("\n(ui_cur_manage) add\n") );
+
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+
+       curfmt = ui_cur_select_dialog_new(GTK_WINDOW(data->window), CUR_SELECT_MODE_NORMAL);
+       if( curfmt != NULL )
+       {
+       Currency *item;
+
+               DB( g_printf("- user selected: '%s' '%s'\n", curfmt->curr_iso_code, curfmt->name) );
+               item = da_cur_get_by_iso_code(curfmt->curr_iso_code);
+               if( item == NULL )
+               {
+                       item = currency_add_from_user(curfmt);
+                       ui_cur_listview_add(GTK_TREE_VIEW(data->LV_cur), item);
+                       gtk_tree_sortable_sort_column_changed(GTK_TREE_SORTABLE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_cur))));
+                       
+                       ui_cur_manage_dialog_update (widget, user_data);
+                       GLOBALS->changes_count++;
+               }
+               else
+               {
+                       DB( g_printf("- already exists\n") );
+               }
+       }
+}
+
+
+
+static void
+ui_cur_manage_dialog_modify(GtkWidget *widget, gpointer user_data)
+{
+struct ui_cur_manage_dialog_data *data;
+GtkTreeSelection *selection;
+GtkTreeModel            *model;
+GtkTreeIter                     iter;
+
+       DB( g_printf("\n(ui_cur_manage) modify\n") );
+
+       
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+
+       selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_cur));
+       if (gtk_tree_selection_get_selected(selection, &model, &iter))
+       {
+       Currency *item;
+
+               gtk_tree_model_get(model, &iter, LST_DEFCUR_DATAS, &item, -1);
+
+               if( item!= NULL  )
+               {
+                       ui_cur_edit_dialog_new(GTK_WINDOW(data->window), item);
+                       GLOBALS->changes_count++;
+               }
+
+       }
+}
+
+
+/*
+** remove the selected curee to our treeview and temp GList
+*/
+static void ui_cur_manage_dialog_remove(GtkWidget *widget, gpointer user_data)
+{
+struct ui_cur_manage_dialog_data *data;
+guint32 key;
+gboolean do_remove, result;
+
+       DB( g_printf("\n(ui_cur_manage) remove\n") );
+       
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+       
+       do_remove = TRUE;
+       key = ui_cur_listview_get_selected_key(GTK_TREE_VIEW(data->LV_cur));
+       if( key > 0 )
+       {
+       Currency *cur;
+       gchar *title;
+       gchar *secondtext;
+
+               if( currency_is_used(key) == TRUE )
+               {
+                       do_remove = FALSE;
+               }
+               else
+               {
+                       cur = da_cur_get(key);
+               
+                       title = g_strdup_printf (
+                               _("Are you sure you want to permanently delete '%s'?"), cur->name);
+
+                       secondtext = _("If you delete a currency, it will be permanently lost.");
+               
+                       result = ui_dialog_msg_confirm_alert(
+                                       GTK_WINDOW(data->window),
+                                       title,
+                                       secondtext,
+                                       _("_Delete")
+                               );
+
+                       g_free(title);
+
+                       do_remove = (result == GTK_RESPONSE_OK) ? TRUE :FALSE;
+               }       
+               
+               if( do_remove )
+               {
+                       da_cur_remove(key);
+                       ui_cur_listview_remove_selected(GTK_TREE_VIEW(data->LV_cur));
+                       ui_cur_manage_dialog_update (widget, user_data);
+                       data->change++;
+               }
+       }
+
+}
+
+/*
+** button callback: set base currency
+*/
+static void ui_cur_manage_dialog_setbase(GtkWidget *widget, gpointer user_data)
+{
+struct ui_cur_manage_dialog_data *data;
+guint32 key;
+gboolean do_change;
+
+       DB( g_printf("\n(ui_cur_manage) setbase\n") );
+
+       
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+
+       key = ui_cur_listview_get_selected_key(GTK_TREE_VIEW(data->LV_cur));
+       if( key > 0 )
+       {
+               do_change = ui_dialog_msg_question(
+                       GTK_WINDOW(data->window),
+                       _("Change the base currency"),
+                       _("If you proceed, rates of other currencies\n"
+                         "will be set to 0, don't forget to update it"),
+                       NULL
+                       );
+               if(do_change == GTK_RESPONSE_YES)
+               {
+                       hbfile_change_basecurrency(key);
+                       gtk_tree_view_columns_autosize(GTK_TREE_VIEW(data->LV_cur));
+               }
+       }
+
+}
+
+
+/*
+**
+*/
+static void ui_cur_manage_dialog_update(GtkWidget *treeview, gpointer user_data)
+{
+struct ui_cur_manage_dialog_data *data;
+GtkTreeSelection *selection;
+GtkTreeModel *model;
+GtkTreeIter iter;
+Currency *item;
+gboolean sensitive;
+
+       DB( g_printf("\n(ui_cur_manage_dialog) update\n") );
+
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(treeview), GTK_TYPE_WINDOW)), "inst_data");
+
+       sensitive = da_cur_length() <= 1 ? FALSE : TRUE;
+       gtk_widget_set_sensitive (data->BB_update, sensitive);
+
+
+       selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_cur));
+
+       //if true there is a selected node
+       if (gtk_tree_selection_get_selected(selection, &model, &iter))
+       {
+               gtk_tree_model_get(model, &iter, LST_DEFCUR_DATAS, &item, -1);
+
+               gtk_widget_set_sensitive(data->BT_edit, TRUE);
+
+               sensitive = !(currency_is_used(item->key));
+               //gtk_widget_set_sensitive(data->BT_mov, sensitive);
+               //gtk_widget_set_sensitive(data->BT_mod, sensitive);
+               gtk_widget_set_sensitive(data->BT_rem, sensitive);
+
+               //disable set as base on actual base currency
+               sensitive = (item->key != GLOBALS->kcur) ? TRUE : FALSE;
+               gtk_widget_set_sensitive(data->BT_base, sensitive);
+       }
+       else
+       {
+               gtk_widget_set_sensitive(data->BT_edit, FALSE);
+               gtk_widget_set_sensitive(data->BT_rem , FALSE);
+               gtk_widget_set_sensitive(data->BT_base, FALSE);
+       }
+}
+
+
+/*
+**
+*/
+static void ui_cur_manage_dialog_selection(GtkTreeSelection *treeselection, gpointer user_data)
+{
+       ui_cur_manage_dialog_update(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), NULL);
+}
+
+static void ui_cur_manage_dialog_onRowActivated (GtkTreeView        *treeview,
+                       GtkTreePath        *path,
+                       GtkTreeViewColumn  *col,
+                       gpointer            userdata)
+{
+
+       //model = gtk_tree_view_get_model(treeview);
+       //gtk_tree_model_get_iter_first(model, &iter);
+       //if(gtk_tree_selection_iter_is_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), &iter) == FALSE)
+       //{
+               ui_cur_manage_dialog_modify(GTK_WIDGET(treeview), NULL);
+       //}
+}
+
+
+
+/*
+**
+*/
+static void ui_cur_manage_dialog_setup(struct ui_cur_manage_dialog_data *data)
+{
+
+       DB( g_printf("\n(ui_cur_manage_setup)\n") );
+
+
+       ui_cur_listview_populate(data->LV_cur);
+
+       //ui_cur_combobox_populate(data->CY_curr, GLOBALS->h_cur);
+       //ui_cur_combobox_set_active(GTK_COMBO_BOX(data->CY_curr), GLOBALS->kcur);
+
+
+
+}
+
+
+/*
+**
+*/
+GtkWidget *ui_cur_manage_dialog (void)
+{
+struct ui_cur_manage_dialog_data data;
+GtkWidget *dialog, *content_area, *content_grid, *group_grid, *bbox;
+GtkWidget *widget, *scrollwin, *treeview;
+gint crow, row, w, h;
+
+       DB( g_printf("\n(ui_cur_manage_dialog)\n") );
+       
+       dialog = gtk_dialog_new_with_buttons (_("Currencies"),
+                                           GTK_WINDOW(GLOBALS->mainwindow),
+                                           0,
+                                           _("_Close"),
+                                           GTK_RESPONSE_ACCEPT,
+                                           NULL);
+
+       data.window = dialog;
+       data.change = 0;
+
+       //set the dialog icon
+       gtk_window_set_icon_name(GTK_WINDOW (dialog), ICONNAME_HB_CURRENCY);
+
+       //set a nice dialog size
+       gtk_window_get_size(GTK_WINDOW(GLOBALS->mainwindow), &w, &h);
+       gtk_window_set_default_size (GTK_WINDOW(dialog), -1, h/PHI);
+
+       
+       //store our window private data
+       g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)&data);
+       DB( g_printf("(ui_cur_manage_dialog) dialog=%p, inst_data=%p\n", dialog, &data) );
+
+    g_signal_connect (dialog, "destroy",
+                       G_CALLBACK (gtk_widget_destroyed), &dialog);
+
+       content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog));        // return a vbox
+
+       content_grid = gtk_grid_new();
+       gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+       gtk_container_set_border_width (GTK_CONTAINER(content_grid), SPACING_MEDIUM);
+       gtk_box_pack_start (GTK_BOX (content_area), content_grid, TRUE, TRUE, 0);
+
+       crow = 0;
+       // group :: --------
+    group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+
+       row = 1;
+       bbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_MEDIUM);
+       data.BB_update = bbox;
+       gtk_grid_attach (GTK_GRID(group_grid), bbox, 0, row, 1, 1);
+
+       widget = gtk_button_new_from_icon_name (ICONNAME_REFRESH, GTK_ICON_SIZE_BUTTON);
+       gtk_container_add (GTK_CONTAINER (bbox), widget);
+       
+       g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (ui_cur_manage_dialog_sync), NULL);
+
+       widget = make_label_widget (_("Update online"));
+       gtk_container_add (GTK_CONTAINER (bbox), widget);
+       
+       row++;
+       scrollwin = gtk_scrolled_window_new(NULL,NULL);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+       gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scrollwin), HB_MINHEIGHT_LIST);
+       treeview = ui_cur_listview_new(FALSE);
+       data.LV_cur = treeview;
+       gtk_container_add(GTK_CONTAINER(scrollwin), treeview);
+       gtk_widget_set_vexpand (scrollwin, TRUE);
+       gtk_widget_set_hexpand (scrollwin, TRUE);
+       gtk_grid_attach (GTK_GRID(group_grid), scrollwin, 0, row, 2, 1);
+
+       row++;
+       bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
+       gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START);
+       gtk_box_set_spacing (GTK_BOX (bbox), SPACING_SMALL);
+       gtk_grid_attach (GTK_GRID (group_grid), bbox, 0, row, 2, 1);
+
+       widget = gtk_button_new_with_mnemonic(_("_Add"));
+       data.BT_add = widget;
+       gtk_container_add (GTK_CONTAINER (bbox), widget);
+
+       widget = gtk_button_new_with_mnemonic(_("_Edit"));
+       data.BT_edit = widget;
+       gtk_container_add (GTK_CONTAINER (bbox), widget);
+
+       widget = gtk_button_new_with_mnemonic(_("_Delete"));
+       data.BT_rem = widget;
+       gtk_container_add (GTK_CONTAINER (bbox), widget);
+
+       widget = gtk_button_new_with_mnemonic(_("Set as base"));
+       data.BT_base = widget;
+       gtk_container_add (GTK_CONTAINER (bbox), widget);
+
+
+       //connect all our signals
+       //g_signal_connect (G_OBJECT (data.ST_name), "activate", G_CALLBACK (ui_cur_manage_dialog_add), NULL);
+
+       g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data.LV_cur)), "changed", G_CALLBACK (ui_cur_manage_dialog_selection), NULL);
+       g_signal_connect (GTK_TREE_VIEW(data.LV_cur), "row-activated", G_CALLBACK (ui_cur_manage_dialog_onRowActivated), NULL);
+
+       g_signal_connect (G_OBJECT (data.BT_add), "clicked", G_CALLBACK (ui_cur_manage_dialog_add), NULL);
+       g_signal_connect (G_OBJECT (data.BT_rem), "clicked", G_CALLBACK (ui_cur_manage_dialog_remove), NULL);
+       g_signal_connect (G_OBJECT (data.BT_edit), "clicked", G_CALLBACK (ui_cur_manage_dialog_modify), NULL);
+       //g_signal_connect (G_OBJECT (data.BT_mov), "clicked", G_CALLBACK (ui_cur_manage_dialog_move), NULL);
+       g_signal_connect (G_OBJECT (data.BT_base), "clicked", G_CALLBACK (ui_cur_manage_dialog_setbase), NULL);
+
+       //setup, init and show window
+       ui_cur_manage_dialog_setup(&data);
+
+       ui_cur_manage_dialog_update(data.LV_cur, NULL);
+
+       //gtk_window_resize(GTK_WINDOW(dialog), 256, 414);
+
+       gtk_widget_show_all (dialog);
+
+       //wait for the user
+       gint result = gtk_dialog_run (GTK_DIALOG (dialog));
+
+       switch (result)
+    {
+       case GTK_RESPONSE_ACCEPT:
+          //do_application_specific_something ();
+          break;
+       default:
+          //do_nothing_since_dialog_was_cancelled ();
+          break;
+    }
+
+
+       // cleanup and destroy
+       GLOBALS->changes_count += data.change;
+       gtk_widget_destroy (dialog);
+
+       return NULL;
+}
+
+
+
This page took 0.047409 seconds and 4 git commands to generate.