X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fhomebank;a=blobdiff_plain;f=src%2Fui-split.c;fp=src%2Fui-split.c;h=c0e7928cc715f050fee923f463662aa16e4fab7b;hp=005e7e2f72bb0423a62f8b3924e6b5459b2b70df;hb=236cb5e47660876f46488ea8f76ecd5bebfa1fac;hpb=8892e90b335f94c296462a91534334b674226cd9 diff --git a/src/ui-split.c b/src/ui-split.c index 005e7e2..c0e7928 100644 --- a/src/ui-split.c +++ b/src/ui-split.c @@ -1,5 +1,5 @@ /* HomeBank -- Free, easy, personal accounting for everyone. - * Copyright (C) 1995-2018 Maxime DOYEN + * Copyright (C) 1995-2019 Maxime DOYEN * * This file is part of HomeBank. * @@ -47,10 +47,220 @@ extern struct HomeBank *GLOBALS; extern struct Preferences *PREFS; -#define GTK_RESPONSE_SPLIT_SUM 10880 #define GTK_RESPONSE_SPLIT_REM 10888 +/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ +static void list_split_number_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) +{ +GtkTreePath *path; +gint *indices; +gchar num[16]; + + path = gtk_tree_model_get_path(model, iter); + indices = gtk_tree_path_get_indices(path); + //num = gtk_tree_path_to_string(path); + g_snprintf(num, 15, "%d", 1 + *indices); + gtk_tree_path_free(path); + + g_object_set(renderer, "text", num, NULL); + +} + + +static void list_split_amount_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) +{ +Split *split; +gchar buf[G_ASCII_DTOSTR_BUF_SIZE]; +gdouble amount; +gchar *color; + + gtk_tree_model_get(model, iter, 0, &split, -1); + + //hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, amount, ope->kcur, GLOBALS->minor); + amount = split->amount; + g_snprintf(buf, G_ASCII_DTOSTR_BUF_SIZE-1, "%.2f", amount); + + color = get_normal_color_amount(amount); + g_object_set(renderer, + "foreground", color, + "text", buf, + NULL); + +} + + +static void list_split_memo_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) +{ +Split *split; + + gtk_tree_model_get(model, iter, 0, &split, -1); + + g_object_set(renderer, "text", split->memo, NULL); +} + + +static void list_split_category_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) +{ +Split *split; +Category *cat; + + gtk_tree_model_get(model, iter, 0, &split, -1); + + cat = da_cat_get(split->kcat); + if( cat != NULL ) + { + g_object_set(renderer, "text", cat->fullname, NULL); + } + else + g_object_set(renderer, "text", "", NULL); +} + + +static void list_split_populate(struct ui_split_dialog_data *data) +{ +GtkTreeModel *model; +GtkTreeIter iter; +Split *split; +gint count, i; + + DB( g_print("\n[list_split] populate\n") ); + + count = da_splits_length (data->tmp_splits); + + if( count <= 0 ) + return; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split)); + + 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(data->LV_split), NULL); /* Detach model from view */ + + /* populate */ + for(i=0 ; i < count ; i++) + { + split = da_splits_get(data->tmp_splits, i); + + DB( g_print("- set split %d : %d, %.2f, %s\n", i, split->kcat, split->amount, split->memo) ); + + gtk_list_store_append (GTK_LIST_STORE(model), &iter); + gtk_list_store_set (GTK_LIST_STORE(model), &iter, + 0, split, + -1); + + } + + gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_split), model); /* Re-attach model to view */ + g_object_unref(model); +} + + + + + +static GtkWidget * +list_split_new(void) +{ +GtkListStore *store; +GtkWidget *treeview; +GtkCellRenderer *renderer; +GtkTreeViewColumn *column; + + DB( g_print("\n[ui_split_listview] new\n") ); + + + // create list store + store = gtk_list_store_new(1, + G_TYPE_POINTER + ); + + // treeview + treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + g_object_unref(store); + + gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview), PREFS->grid_lines); + + //column 0: line number + renderer = gtk_cell_renderer_text_new (); + g_object_set(renderer, "xalign", 1.0, NULL); + column = gtk_tree_view_column_new_with_attributes("#", renderer, NULL); + gtk_tree_view_column_set_alignment (column, 1.0); + gtk_tree_view_column_set_cell_data_func(column, renderer, list_split_number_cell_data_function, NULL, NULL); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column); + + + // column 1: category + renderer = gtk_cell_renderer_text_new (); + g_object_set(renderer, + "ellipsize", PANGO_ELLIPSIZE_END, + "ellipsize-set", TRUE, + NULL); + + column = gtk_tree_view_column_new_with_attributes(_("Category"), renderer, NULL); + + //gtk_tree_view_column_set_alignment (column, 0.5); + gtk_tree_view_column_set_resizable(column, TRUE); + + //gtk_tree_view_column_set_sort_column_id (column, sortcolumnid); + //gtk_tree_view_column_set_fixed_width( column, HB_MINWIDTH_LIST); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_column_set_cell_data_func(column, renderer, list_split_category_cell_data_function, NULL, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column); + + // column 2: memo + renderer = gtk_cell_renderer_text_new (); + g_object_set(renderer, + "ellipsize", PANGO_ELLIPSIZE_END, + "ellipsize-set", TRUE, + NULL); + + column = gtk_tree_view_column_new_with_attributes(_("Memo"), renderer, NULL); + + //gtk_tree_view_column_set_alignment (column, 0.5); + gtk_tree_view_column_set_resizable(column, TRUE); + + //gtk_tree_view_column_set_sort_column_id (column, sortcolumnid); + //gtk_tree_view_column_set_fixed_width( column, HB_MINWIDTH_LIST); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_column_set_cell_data_func(column, renderer, list_split_memo_cell_data_function, NULL, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column); + + + // column 3: amount + renderer = gtk_cell_renderer_text_new (); + g_object_set(renderer, "xalign", 1.0, NULL); + + column = gtk_tree_view_column_new_with_attributes(_("Amount"), renderer, NULL); + + gtk_tree_view_column_set_alignment (column, 1.0); + gtk_tree_view_column_set_resizable(column, TRUE); + //gtk_tree_view_column_set_sort_column_id (column, sortcolumnid); + gtk_tree_view_column_set_fixed_width( column, HB_MINWIDTH_LIST); + gtk_tree_view_column_set_cell_data_func(column, renderer, list_split_amount_cell_data_function, NULL, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column); + + + // column empty + //column = gtk_tree_view_column_new(); + //gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column); + + + // treeviewattribute + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), TRUE); + gtk_tree_view_set_reorderable (GTK_TREE_VIEW(treeview), TRUE); + + //gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store), ui_acc_listview_compare_func, NULL, NULL); + //gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING); + + return treeview; +} + + + + /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ static void ui_split_dialog_filter_text_handler (GtkEntry *entry, @@ -86,278 +296,429 @@ gchar *result = g_new0 (gchar, length+1); } -void ui_split_dialog_line_sensitive(guint line, gboolean sensitive, gpointer user_data) +static void ui_split_dialog_cb_eval_order(struct ui_split_dialog_data *data) { -struct ui_split_dialog_data *data = user_data; - - if( line > TXN_MAX_SPLIT ) - return; +GtkTreeModel *model; +GtkTreeIter iter; +gboolean valid; +guint i; - if( line == 0 ) // line 0 always active ! - sensitive = TRUE; + DB( g_print("\n[ui_split_dialog] eval order\n") ); - - gtk_widget_set_sensitive(data->PO_cat[line], sensitive); - gtk_widget_set_sensitive(data->ST_amount[line], sensitive); - gtk_widget_set_sensitive(data->ST_memo[line], sensitive); - if(data->BT_rem[line]) - gtk_widget_set_sensitive(data->BT_rem[line], sensitive); - if(data->BT_add[line]) - gtk_widget_set_sensitive(data->BT_add[line], sensitive); - - if(sensitive == FALSE) + model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split)); + i=1; valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter); + while (valid) { - ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_cat[line]), 0); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->ST_amount[line]), 0.0); - gtk_entry_set_text(GTK_ENTRY(data->ST_memo[line]), ""); - } + Split *split; + + gtk_tree_model_get (model, &iter, 0, &split, -1); + split->pos = i; - if(sensitive == TRUE) - data->activeline = line; + DB( g_print("split pos: %d '%s' %.2f\n", i, split->memo, split->amount) ); + + i++; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); + } + da_splits_sort(data->tmp_splits); } -void ui_split_dialog_compute(GtkWidget *widget, gpointer user_data) +static void ui_split_dialog_cb_eval_split(GtkWidget *widget, gpointer user_data) { -struct ui_split_dialog_data *data = user_data; -gint i, count, nbvalid; -//gint j; -gchar buf[48]; -gboolean sensitive, active; -//guint32 cat[TXN_MAX_SPLIT]; -gdouble amt[TXN_MAX_SPLIT]; -gboolean valid[TXN_MAX_SPLIT]; +struct ui_split_dialog_data *data; +gboolean tmpval = FALSE; +gdouble amount; +gint count; + + DB( g_print("\n[ui_split_dialog] eval split\n") ); - DB( g_print("\n(ui_split_dialog_compute)\n") ); + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data"); - data->sumsplit = data->remsplit = 0.0; - nbvalid = 0; - for(i=0;iPO_cat[i]); - if(!active) break; - - //cat[i] = ui_cat_comboboxentry_get_key(GTK_COMBO_BOX(data->PO_cat[i])); - amt[i] = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_amount[i])); - data->sumsplit += amt[i]; - valid[i] = TRUE; + amount= g_strtod(gtk_entry_get_text(GTK_ENTRY(data->ST_amount)), NULL); - if(!amt[i]) - valid[i] = FALSE; + tmpval = hb_amount_round(amount, 2) != 0.0 ? TRUE : FALSE; + gtk_widget_set_sensitive (data->BT_apply, tmpval); - /* disable use same category several time - for(j=0;jLV_split)), NULL); + if( count >= TXN_MAX_SPLIT ) + tmpval = FALSE; + gtk_widget_set_sensitive (data->BT_add, tmpval); - if(valid[i]) - nbvalid++; + DB( g_print(" - txt='%s' amt=%.2f, nbsplit=%d, valid=%d\n", gtk_entry_get_text(GTK_ENTRY(data->ST_amount)), amount, count, tmpval) ); - DB( g_print("- nbsplit %d\n", data->nbsplit) ); +} - if(data->nbsplit == i) - { - DB( g_print("- set last split %d\n", i) ); - if(data->BT_add[i]) - gtk_widget_set_sensitive(data->BT_add[i], valid[i]); +static void ui_split_dialog_update(GtkWidget *widget, gpointer user_data) +{ +struct ui_split_dialog_data *data; +gboolean tmpval; +guint count; - if(data->BT_rem[i]) - gtk_widget_set_sensitive(data->BT_rem[i], TRUE); - } - else - { - DB( g_print("- set off to %d\n", i) ); + DB( g_print("\n[ui_split_dialog] update\n") ); - if(data->BT_add[i]) - gtk_widget_set_sensitive(data->BT_add[i], FALSE); + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data"); - if(data->BT_rem[i]) - gtk_widget_set_sensitive(data->BT_rem[i], FALSE); - } - } + count = da_splits_length (data->tmp_splits); - count = i; - DB( g_print("- count=%d, nbvalid=%d\n", count, nbvalid ) ); + //btn: edit/rem + tmpval = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_split)), NULL, NULL); + gtk_widget_set_sensitive (data->BT_edit, (data->isedited) ? FALSE : tmpval); + gtk_widget_set_sensitive (data->BT_rem, (data->isedited) ? FALSE : tmpval); + + //btn: remall + tmpval = (count > 1) ? TRUE : FALSE; + gtk_widget_set_sensitive (data->BT_remall, (data->isedited) ? FALSE : tmpval); + ui_split_dialog_cb_eval_split(widget, NULL); - if(data->splittype == TXN_SPLIT_AMOUNT) - { - data->remsplit = data->amount - data->sumsplit; - } + //btn: add/apply + /*amount = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_amount)); + tmpval = hb_amount_round(amount, 2) != 0.0 ? TRUE : FALSE; + gtk_widget_set_sensitive (data->BT_apply, tmpval); + + if( count >= TXN_MAX_SPLIT ) + tmpval = FALSE; + gtk_widget_set_sensitive (data->BT_add, tmpval); + */ - //rules validation - sensitive = ((count == nbvalid) && (count > 1)) ? TRUE : FALSE; - if(data->splittype == TXN_SPLIT_NEW) - gtk_dialog_set_response_sensitive(GTK_DIALOG(data->dialog), GTK_RESPONSE_SPLIT_SUM, sensitive); + //btn: show/hide + gtk_widget_set_sensitive (data->LV_split, !data->isedited); + + hb_widget_visible (data->BT_add, !data->isedited); - if(data->splittype == TXN_SPLIT_AMOUNT) + hb_widget_visible (data->IM_edit, data->isedited); + hb_widget_visible (data->BT_apply, data->isedited); + hb_widget_visible (data->BT_cancel, data->isedited); +} + + +static void ui_split_dialog_edit_end(GtkWidget *widget, gpointer user_data) +{ +struct ui_split_dialog_data *data; + + DB( g_print("\n[ui_split_dialog] edit_end\n") ); + + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data"); + + g_signal_handler_block(data->PO_cat, data->hid_cat); + g_signal_handler_block(data->ST_amount, data->hid_amt); + + ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_cat), 0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->ST_amount), 0.0); + gtk_entry_set_text(GTK_ENTRY(data->ST_memo), ""); + + g_signal_handler_unblock(data->ST_amount, data->hid_amt); + g_signal_handler_unblock(data->PO_cat, data->hid_cat); + + data->isedited = FALSE; +} + + +static void ui_split_dialog_edit_start(GtkWidget *widget, gpointer user_data) +{ +struct ui_split_dialog_data *data; +GtkTreeSelection *selection; +GtkTreeModel *model; +GtkTreeIter iter; + + DB( g_print("\n[ui_split_dialog] edit_start\n") ); + + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data"); + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split)); + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_split)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) { - sensitive = hb_amount_round(data->remsplit, 2) != 0.0 ? FALSE : sensitive; - gtk_dialog_set_response_sensitive(GTK_DIALOG(data->dialog), GTK_RESPONSE_ACCEPT, sensitive); + Split *split; + gchar *txt; - if(!data->remsplit) - g_sprintf(buf, "----"); - else - g_snprintf(buf, 48, "%.2f", data->remsplit); + gtk_tree_model_get(model, &iter, 0, &split, -1); - gtk_label_set_label(GTK_LABEL(data->LB_remain), buf); + ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_cat), split->kcat); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->ST_amount), split->amount); + txt = (split->memo != NULL) ? split->memo : ""; + gtk_entry_set_text(GTK_ENTRY(data->ST_memo), txt); + + data->isedited = TRUE; - g_snprintf(buf, 48, "%.2f", data->amount); - gtk_label_set_label(GTK_LABEL(data->LB_txnamount), buf); + ui_split_dialog_update (data->dialog, user_data); } - - g_snprintf(buf, 48, "%.2f", data->sumsplit); - gtk_label_set_text(GTK_LABEL(data->LB_sumsplit), buf); +} + + + +static void ui_split_dialog_cancel_cb(GtkWidget *widget, gpointer user_data) +{ +//struct ui_split_dialog_data *data; + + DB( g_print("\n[ui_split_dialog] cancel\n") ); + //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data"); + + ui_split_dialog_edit_end(widget, user_data); + ui_split_dialog_update (widget, user_data); } -void ui_split_dialog_inactiveline(GtkWidget *widget, gpointer user_data) +static void ui_split_dialog_apply_cb(GtkWidget *widget, gpointer user_data) { struct ui_split_dialog_data *data; -gint line; +GtkTreeSelection *selection; +GtkTreeModel *model; +GtkTreeIter iter; - DB( g_print("\n(ui_split_dialog_inactiveline)\n") ); + DB( g_print("\n[ui_split_dialog] apply\n") ); - data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data"); - if(data->nbsplit <= 0) //1st split always active - return; + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_split)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) + { + Split *split; + gdouble amount; - line = data->nbsplit--; + gtk_tree_model_get(model, &iter, 0, &split, -1); + gtk_spin_button_update (GTK_SPIN_BUTTON(data->ST_amount)); + amount = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_amount)); + if(amount) + { + split->kcat = ui_cat_comboboxentry_get_key_add_new(GTK_COMBO_BOX(data->PO_cat)); + g_free(split->memo); + split->memo = g_strdup((gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_memo))); + split->amount = amount; + } + } - DB( g_print("- nbsplit:%d off:%d\n", data->nbsplit, line) ); - - ui_split_dialog_line_sensitive(line, FALSE, data); - ui_split_dialog_compute(widget, data); + ui_split_dialog_edit_end(widget, user_data); + ui_split_dialog_compute (widget, data); + ui_split_dialog_update (widget, user_data); } -void ui_split_dialog_activeline(GtkWidget *widget, gpointer user_data) +static void ui_split_dialog_removeall_cb(GtkWidget *widget, gpointer user_data) { struct ui_split_dialog_data *data; -gint line; - DB( g_print("\n(ui_split_dialog_activeline)\n") ); + DB( g_print("\n[ui_split_dialog] removeall_cb\n") ); + + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data"); + + gtk_list_store_clear (GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(data->LV_split)))); + da_split_destroy(data->tmp_splits); + data->tmp_splits = da_split_new (); - data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); + ui_split_dialog_compute (widget, data); + ui_split_dialog_update (widget, user_data); +} - line = data->nbsplit; - if(line >= (TXN_MAX_SPLIT-1)) //bound - return; - line = ++data->nbsplit; +static void ui_split_dialog_remove_cb(GtkWidget *widget, gpointer user_data) +{ +struct ui_split_dialog_data *data; +GtkTreeSelection *selection; +GtkTreeModel *model; +GtkTreeIter iter; - DB( g_print("- nbsplit:%d off:%d\n", data->nbsplit-1, line) ); + DB( g_print("\n[ui_split_dialog] remove_cb\n") ); - - ui_split_dialog_line_sensitive(line, TRUE, data); + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data"); - if(data->splittype == TXN_SPLIT_AMOUNT) + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_split)); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) { - DB( g_print("- line %d :: affect remain\n", line) ); - g_signal_handler_block(data->ST_amount[line], data->handler_id[line]); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->ST_amount[line]), data->remsplit); - g_signal_handler_unblock(data->ST_amount[line], data->handler_id[line]); + Split *split; + + gtk_tree_model_get(model, &iter, 0, &split, -1); + //todo: not implemented yet + da_splits_remove(data->tmp_splits, split); + gtk_list_store_remove(GTK_LIST_STORE(model), &iter); } - ui_split_dialog_compute(widget, data); + ui_split_dialog_compute (widget, data); + ui_split_dialog_update (widget, user_data); } -void ui_split_dialog_get(struct ui_split_dialog_data *data) +static void ui_split_dialog_add_cb(GtkWidget *widget, gpointer user_data) { -guint i; +struct ui_split_dialog_data *data; +GtkTreeModel *model; +GtkTreeIter iter; Split *split; -guint32 kcat; -gchar *memo; +guint count; gdouble amount; - DB( g_print("(ui_split_dialog_get)\n") ); + DB( g_print("\n[ui_split_dialog] add\n") ); - da_splits_free(data->splits); + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data"); - for(i=0;itmp_splits); + if( count <= TXN_MAX_SPLIT ) { - kcat = ui_cat_comboboxentry_get_key_add_new(GTK_COMBO_BOX(data->PO_cat[i])); - memo = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_memo[i])); - amount = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_amount[i])); - + split = da_split_malloc (); + gtk_spin_button_update (GTK_SPIN_BUTTON(data->ST_amount)); + amount = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_amount)); if(amount) { - split = da_split_new(kcat, amount, memo); - - DB( g_print("- get split %d : %d, %.2f, %s\n", i, split->kcat, split->amount, split->memo) ); + split->amount = amount; + split->kcat = ui_cat_comboboxentry_get_key_add_new(GTK_COMBO_BOX(data->PO_cat)); + split->memo = g_strdup((gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_memo))); + + DB( g_print("- get split : %d, %.2f, %s\n", split->kcat, split->amount, split->memo) ); - da_splits_append (data->splits, split); + da_splits_append (data->tmp_splits, split); + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split)); + gtk_list_store_append (GTK_LIST_STORE(model), &iter); + gtk_list_store_set (GTK_LIST_STORE(model), &iter, + 0, split, + -1); + + ui_split_dialog_compute (widget, data); + + } + else + { + //todo: msg max number reached + da_split_free(split); } } + + ui_split_dialog_edit_end(widget, user_data); + ui_split_dialog_update (widget, user_data); } -void ui_split_dialog_set(struct ui_split_dialog_data *data) +static void ui_split_dialog_cb_activate_split(GtkWidget *widget, gpointer user_data) { -guint count, i; -Split *split; -gchar *txt; +struct ui_split_dialog_data *data; + + DB( g_print("\n[ui_split_dialog] cb activate split\n") ); - DB( g_print("(ui_split_dialog_set)\n") ); + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_WINDOW)), "inst_data"); + + if( data->isedited == TRUE ) + ui_split_dialog_apply_cb(widget, NULL); + else + ui_split_dialog_add_cb(widget, NULL); +} + + +static void ui_split_rowactivated (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data) +{ + DB( g_print("\n[ui_split_dialog] rowactivated\n") ); + + ui_split_dialog_edit_start(GTK_WIDGET(treeview), NULL); +} + + +static void ui_split_selection(GtkTreeSelection *treeselection, gpointer user_data) +{ + DB( g_print("\n[ui_split_dialog] selection\n") ); - for(i=0;isumsplit = 0.0; + data->remsplit = 0.0; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_split)); + i=0; valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter); + while (valid) { - ui_split_dialog_line_sensitive(i, FALSE, data); - ui_cat_comboboxentry_populate(GTK_COMBO_BOX(data->PO_cat[i]), GLOBALS->h_cat); - //#1258821 - //if( data->splittype == TXN_SPLIT_AMOUNT ) - //{ - //if(data->amount > 0.0) - // gtk_spin_button_set_range(GTK_SPIN_BUTTON(data->ST_amount[i]), 0.0, G_MAXDOUBLE); - //else - // gtk_spin_button_set_range(GTK_SPIN_BUTTON(data->ST_amount[i]), -G_MAXDOUBLE, 0.0); - //} + Split *split; + + gtk_tree_model_get (model, &iter, + 0, &split, + -1); + + data->sumsplit += split->amount; + if( hb_amount_round(split->amount, 2) != 0.0 ) + nbvalid++; + + /* Make iter point to the next row in the list store */ + i++; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); } + count = i; + DB( g_print("- count=%d, nbvalid=%d\n", count, nbvalid ) ); - count = da_splits_count(data->splits); - data->nbsplit = count > 1 ? count-1 : 0; - - DB( g_print("- count = %d\n", count) ); - - - for(i=0;iremsplit = data->amount - data->sumsplit; + + + //validation: 2 split min + sensitive = FALSE; + if( (count == 0) || nbvalid >= 2 ) + sensitive = TRUE; + gtk_dialog_set_response_sensitive(GTK_DIALOG(data->dialog), GTK_RESPONSE_ACCEPT, sensitive); + + if( hb_amount_round(data->amount, 2) != 0.0 ) { - split = data->splits[i]; + if(!data->remsplit) + g_sprintf(buf, "----"); + else + g_snprintf(buf, 48, "%.2f", data->remsplit); - DB( g_print("- set split %d : %d, %.2f, %s\n", i, split->kcat, split->amount, split->memo) ); + gtk_label_set_label(GTK_LABEL(data->LB_remain), buf); - ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_cat[i]), split->kcat); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->ST_amount[i]), split->amount); - txt = (split->memo != NULL) ? split->memo : ""; - gtk_entry_set_text(GTK_ENTRY(data->ST_memo[i]), txt); - ui_split_dialog_line_sensitive(i, TRUE, data); + g_snprintf(buf, 48, "%.2f", data->amount); + gtk_label_set_label(GTK_LABEL(data->LB_txnamount), buf); } + + g_snprintf(buf, 48, "%.2f", data->sumsplit); + gtk_label_set_text(GTK_LABEL(data->LB_sumsplit), buf); } +static void ui_split_dialog_setup(struct ui_split_dialog_data *data) +{ +guint count; + DB( g_print("\n[ui_split_dialog] set\n") ); -GtkWidget *ui_split_dialog (GtkWidget *parent, Split *ope_splits[], gdouble amount, void (update_callbackFunction(GtkWidget*, gdouble))) + count = da_splits_length(data->tmp_splits); + data->nbsplit = count > 1 ? count-1 : 0; + + DB( g_print("- count = %d\n", count) ); + list_split_populate (data); + + data->isedited = FALSE; + + ui_cat_comboboxentry_populate(GTK_COMBO_BOX(data->PO_cat), GLOBALS->h_cat); + + ui_split_dialog_compute(data->dialog, data); + ui_split_dialog_update (data->dialog, data); +} + + +GtkWidget *ui_split_dialog (GtkWidget *parent, GPtrArray **src_splits, gdouble amount, void (update_callbackFunction(GtkWidget*, gdouble))) { -struct ui_split_dialog_data data; -GtkWidget *dialog, *content, *mainvbox, *label; -GtkWidget *table, *widget; -gint row, i; +struct ui_split_dialog_data *data; +GtkWidget *dialog, *content, *table, *box, *scrollwin; +GtkWidget *label, *widget; +gint row; + + DB( g_print("\n[ui_split_dialog] new\n") ); + data = g_malloc0(sizeof(struct ui_split_dialog_data)); dialog = gtk_dialog_new_with_buttons (_("Transaction splits"), GTK_WINDOW(parent), @@ -366,171 +727,206 @@ gint row, i; GTK_RESPONSE_CANCEL, NULL); - data.dialog = dialog; - data.splits = ope_splits; - data.amount = amount; - data.splittype = amount ? TXN_SPLIT_AMOUNT : TXN_SPLIT_NEW; - - gtk_dialog_add_button(GTK_DIALOG(dialog), _("_Remove"), GTK_RESPONSE_SPLIT_REM); - - /* sum button must appear only when new split add */ - //#1258821 - //if(data.splittype == TXN_SPLIT_NEW) - gtk_dialog_add_button(GTK_DIALOG(dialog), _("Sum"), GTK_RESPONSE_SPLIT_SUM); - - - if(data.splittype == TXN_SPLIT_AMOUNT) - gtk_dialog_add_button(GTK_DIALOG(dialog), _("_OK"), GTK_RESPONSE_ACCEPT); - //store our dialog private data - g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)&data); - DB( g_print("(ui_split_dialog) dialog=%p, inst_data=%p\n", dialog, &data) ); + g_object_set_data(G_OBJECT(dialog), "inst_data", (gpointer)data); + DB( g_print(" - window=%p, inst_data=%p\n", dialog, data) ); g_signal_connect (dialog, "destroy", G_CALLBACK (gtk_widget_destroyed), &dialog); + data->dialog = dialog; + + //gtk_dialog_add_button(GTK_DIALOG(dialog), _("_Remove"), GTK_RESPONSE_SPLIT_REM); + gtk_dialog_add_button(GTK_DIALOG(dialog), _("_OK"), GTK_RESPONSE_ACCEPT); + + //todo: init should move + //clone splits or create new + data->src_splits = *src_splits; + data->amount = amount; + data->sumsplit = amount; + + if( *src_splits != NULL ) + data->tmp_splits = da_splits_clone(*src_splits); + else + data->tmp_splits = da_split_new(); + //dialog contents content = gtk_dialog_get_content_area(GTK_DIALOG (dialog)); - mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM); - gtk_box_pack_start (GTK_BOX (content), mainvbox, TRUE, TRUE, 0); - gtk_container_set_border_width (GTK_CONTAINER(mainvbox), SPACING_MEDIUM); - table = gtk_grid_new (); - //gtk_container_set_border_width (GTK_CONTAINER (table), SP_BORDER); - gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_SMALL/2); - gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_MEDIUM/2); - gtk_box_pack_start (GTK_BOX (mainvbox), table, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (table), SPACING_SMALL); + gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_TINY); + gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_TINY); + gtk_box_pack_start (GTK_BOX (content), table, TRUE, TRUE, 0); row = 0; + + scrollwin = gtk_scrolled_window_new(NULL,NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin), GTK_SHADOW_ETCHED_IN); + gtk_widget_set_size_request(scrollwin, HB_MINWIDTH_LIST, HB_MINHEIGHT_LIST); + gtk_widget_set_hexpand (scrollwin, TRUE); + gtk_widget_set_vexpand (scrollwin, TRUE); + data->LV_split = list_split_new(); + gtk_container_add(GTK_CONTAINER(scrollwin), data->LV_split); + gtk_grid_attach (GTK_GRID (table), scrollwin, 0, row, 4, 1); + + box = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_TINY); + gtk_widget_set_valign (box, GTK_ALIGN_CENTER); + gtk_grid_attach (GTK_GRID (table), box, 4, row, 1, 1); + + widget = make_image_button(ICONNAME_LIST_REMOVE_ALL, _("Remove all")); + data->BT_remall = widget; + gtk_box_pack_end (GTK_BOX (box), widget, FALSE, FALSE, 0); + + widget = make_image_button(ICONNAME_LIST_REMOVE, _("Remove")); + data->BT_rem = widget; + gtk_box_pack_end (GTK_BOX(box), widget, FALSE, FALSE, 0); + + widget = make_image_button(ICONNAME_HB_OPE_EDIT, _("Edit")); + data->BT_edit = widget; + gtk_box_pack_end (GTK_BOX(box), widget, FALSE, FALSE, 0); + + row++; label = gtk_label_new(_("Category")); gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1); - gtk_grid_attach (GTK_GRID (table), label, 2, row, 1, 1); + gtk_grid_attach (GTK_GRID (table), label, 0, row, 1, 1); label = gtk_label_new(_("Memo")); gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1); - gtk_grid_attach (GTK_GRID (table), label, 3, row, 1, 1); + gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1); label = gtk_label_new(_("Amount")); gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1); - gtk_grid_attach (GTK_GRID (table), label, 4, row, 1, 1); + gtk_grid_attach (GTK_GRID (table), label, 2, row, 1, 1); - for(i=0;iPO_cat = widget; + gtk_grid_attach (GTK_GRID (table), widget, 0, row, 1, 1); - if(i > 0) - { - widget = gtk_button_new_with_label ("-"); - data.BT_rem[i] = widget; - gtk_grid_attach (GTK_GRID (table), widget, 0, row, 1, 1); - } + widget = make_string(NULL); + data->ST_memo= widget; + gtk_grid_attach (GTK_GRID (table), widget, 1, row, 1, 1); - if( (i < (TXN_MAX_SPLIT-1)) ) - { - widget = gtk_button_new_with_label ("+"); - data.BT_add[i] = widget; - gtk_grid_attach (GTK_GRID (table), widget, 1, row, 1, 1); - } - - widget = ui_cat_comboboxentry_new(NULL); - data.PO_cat[i] = widget; - gtk_widget_set_hexpand (widget, TRUE); - gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1); + widget = make_amount(NULL); + data->ST_amount = widget; + gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1); - widget = make_string(NULL); - gtk_widget_set_hexpand (widget, TRUE); - data.ST_memo[i] = widget; - gtk_grid_attach (GTK_GRID (table), widget, 3, row, 1, 1); - - widget = make_amount(NULL); - data.ST_amount[i] = widget; - gtk_grid_attach (GTK_GRID (table), widget, 4, row, 1, 1); - - //connect all our signals - g_signal_connect (data.PO_cat[i], "changed", G_CALLBACK (ui_split_dialog_compute), &data); - g_signal_connect (data.ST_memo[i], "insert-text", G_CALLBACK(ui_split_dialog_filter_text_handler), NULL); - data.handler_id[i] = g_signal_connect (G_OBJECT (data.ST_amount[i]), "value-changed", G_CALLBACK (ui_split_dialog_compute), &data); - if(data.BT_rem[i]) - g_signal_connect (data.BT_rem[i], "clicked", G_CALLBACK (ui_split_dialog_inactiveline), GINT_TO_POINTER(i)); - if(data.BT_add[i]) - g_signal_connect (data.BT_add[i], "clicked", G_CALLBACK (ui_split_dialog_activeline), GINT_TO_POINTER(i)); - } - - row++; - label = gtk_label_new(_("Sum of splits:")); - gtk_widget_set_halign (label, GTK_ALIGN_END); - gtk_grid_attach (GTK_GRID (table), label, 3, row, 1, 1); - widget = gtk_label_new(NULL); - gtk_widget_set_halign (widget, GTK_ALIGN_END); - data.LB_sumsplit = widget; - gtk_grid_attach (GTK_GRID (table), widget, 4, row, 1, 1); + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_TINY); + gtk_grid_attach (GTK_GRID (table), box, 3, row, 1, 1); + + widget = gtk_image_new_from_icon_name (ICONNAME_HB_OPE_EDIT, GTK_ICON_SIZE_BUTTON); + data->IM_edit = widget; + gtk_box_pack_start (GTK_BOX(box), widget, TRUE, TRUE, 0); + + widget = make_image_button(ICONNAME_LIST_ADD, _("Add")); + data->BT_add = widget; + gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 0); + + widget = make_image_button(ICONNAME_EMBLEM_OK, _("Apply")); + data->BT_apply = widget; + gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 0); + + widget = make_image_button(ICONNAME_WINDOW_CLOSE, _("Cancel")); + data->BT_cancel = widget; + gtk_box_pack_start (GTK_BOX(box), widget, FALSE, FALSE, 0); - if( data.splittype == TXN_SPLIT_AMOUNT ) + + if( hb_amount_round(data->amount, 2) != 0.0 ) { + row++; + label = gtk_label_new(_("Transaction amount:")); + gtk_widget_set_halign (label, GTK_ALIGN_END); + gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1); + widget = gtk_label_new(NULL); + gtk_widget_set_halign (widget, GTK_ALIGN_CENTER); + data->LB_txnamount = widget; + gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1); + row++; label = gtk_label_new(_("Unassigned:")); gtk_widget_set_halign (label, GTK_ALIGN_END); - gtk_grid_attach (GTK_GRID (table), label, 3, row, 1, 1); + gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1); widget = gtk_label_new(NULL); - gtk_widget_set_halign (widget, GTK_ALIGN_END); - gtk_widget_set_margin_left(widget, 20); - gtk_widget_set_margin_right(widget, 20); - data.LB_remain = widget; - gtk_grid_attach (GTK_GRID (table), widget, 4, row, 1, 1); + gtk_widget_set_halign (widget, GTK_ALIGN_CENTER); + data->LB_remain = widget; + gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1); row++; widget = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); - gtk_grid_attach (GTK_GRID (table), widget, 4, row, 1, 1); + gtk_grid_attach (GTK_GRID (table), widget, 1, row, 2, 1); - row++; - label = gtk_label_new(_("Transaction amount:")); - gtk_widget_set_halign (label, GTK_ALIGN_END); - gtk_grid_attach (GTK_GRID (table), label, 3, row, 1, 1); - widget = gtk_label_new(NULL); - gtk_widget_set_halign (widget, GTK_ALIGN_END); - gtk_widget_set_margin_left(widget, 20); - gtk_widget_set_margin_right(widget, 20); - data.LB_txnamount = widget; - gtk_grid_attach (GTK_GRID (table), widget, 4, row, 1, 1); } + row++; + label = gtk_label_new(_("Sum of splits:")); + gtk_widget_set_halign (label, GTK_ALIGN_END); + gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1); + widget = gtk_label_new(NULL); + gtk_widget_set_halign (widget, GTK_ALIGN_CENTER); + data->LB_sumsplit = widget; + gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1); - //setup, init and show dialog - //ui_cur_manage_dialog_setup(&data); + //connect all our signals + g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_split)), "changed", G_CALLBACK (ui_split_selection), data); + g_signal_connect (GTK_TREE_VIEW(data->LV_split), "row-activated", G_CALLBACK (ui_split_rowactivated), data); - ui_split_dialog_set(&data); - ui_split_dialog_compute(NULL, &data); + g_signal_connect (data->ST_memo, "insert-text", G_CALLBACK(ui_split_dialog_filter_text_handler), data); + data->hid_cat = g_signal_connect (data->PO_cat , "changed" , G_CALLBACK (ui_split_dialog_cb_eval_split), data); + data->hid_amt = g_signal_connect (data->ST_amount, "changed", G_CALLBACK (ui_split_dialog_cb_eval_split), data); + //data->hid_amt = g_signal_connect (data->ST_amount, "value-changed", G_CALLBACK (ui_split_dialog_cb_eval_split), data); - //ui_cur_manage_dialog_update(data.LV_cur, NULL); + //todo: add enter validate + g_signal_connect (data->ST_amount, "activate", G_CALLBACK (ui_split_dialog_cb_activate_split), NULL); - gtk_window_set_default_size(GTK_WINDOW(dialog), 480, -1); + + g_signal_connect (data->BT_edit , "clicked", G_CALLBACK (ui_split_dialog_edit_start), NULL); + g_signal_connect (data->BT_rem , "clicked", G_CALLBACK (ui_split_dialog_remove_cb), NULL); + g_signal_connect (data->BT_remall, "clicked", G_CALLBACK (ui_split_dialog_removeall_cb), NULL); + g_signal_connect (data->BT_add , "clicked", G_CALLBACK (ui_split_dialog_add_cb), NULL); + g_signal_connect (data->BT_apply , "clicked", G_CALLBACK (ui_split_dialog_apply_cb), NULL); + g_signal_connect (data->BT_cancel, "clicked", G_CALLBACK (ui_split_dialog_cancel_cb), NULL); + + //gtk_window_set_default_size(GTK_WINDOW(dialog), 480, -1); gtk_widget_show_all (dialog); + //setup, init and show dialog + ui_split_dialog_setup(data); + //wait for the user gint result = gtk_dialog_run (GTK_DIALOG (dialog)); switch (result) { + // sum split and alter txn amount case GTK_RESPONSE_ACCEPT: - //do_application_specific_something (); - ui_split_dialog_get(&data); - update_callbackFunction(parent,data.sumsplit); - break; - case GTK_RESPONSE_SPLIT_REM: - da_splits_free(ope_splits); - update_callbackFunction(parent,data.sumsplit); + if( da_splits_length(data->tmp_splits) ) + { + ui_split_dialog_cb_eval_order(data); + // here we swap src_splits <> tmp_splits + *src_splits = data->tmp_splits; + data->tmp_splits = data->src_splits; + update_callbackFunction(parent, data->sumsplit); + } + else + { + //remove split and revert back original amount + da_split_destroy(*src_splits); + *src_splits = NULL; + update_callbackFunction(parent, data->amount); + } break; - case GTK_RESPONSE_SPLIT_SUM: // sum split and alter txn amount - ui_split_dialog_get(&data); - update_callbackFunction(parent,data.sumsplit); - break; + /*case GTK_RESPONSE_SPLIT_REM: + da_split_destroy(*src_splits); + *src_splits = NULL; + update_callbackFunction(parent, data->sumsplit); + break; + */ default: //do_nothing_since_dialog_was_cancelled (); break; @@ -543,8 +939,8 @@ gint row, i; for(i=0;iope_splits[i]; + if(data->ope_splits[i] == NULL) break; g_print(" split %d : %d, %.2f, %s\n", i, split->kcat, split->amount, split->memo); } @@ -552,8 +948,11 @@ gint row, i; #endif*/ // cleanup and destroy - //GLOBALS->changes_count += data.change; + //GLOBALS->changes_count += data->change; gtk_widget_destroy (dialog); + + da_split_destroy (data->tmp_splits); + g_free(data); return NULL; }