X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fhomebank;a=blobdiff_plain;f=src%2Fhub-account.c;fp=src%2Fhub-account.c;h=1255437cdb013a81624691c074915005112f7492;hp=0000000000000000000000000000000000000000;hb=a6c6b0df5492c2160ed97e3a376bdb2fe7c5ebc4;hpb=cd13d9691c46c2b2d6d459e9e6a76bed1c21b7a6 diff --git a/src/hub-account.c b/src/hub-account.c new file mode 100644 index 0000000..1255437 --- /dev/null +++ b/src/hub-account.c @@ -0,0 +1,498 @@ +/* HomeBank -- Free, easy, personal accounting for everyone. + * Copyright (C) 1995-2019 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 . + */ + + +#include "homebank.h" + +#include "hub-account.h" +#include "dsp-mainwindow.h" +#include "list-account.h" + + +/****************************************************************************/ +/* Debug macros */ +/****************************************************************************/ +#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 HbKvData CYA_ACC_TYPE[]; + + +static void ui_hub_account_expand_all(GtkWidget *widget, gpointer user_data) +{ +struct hbfile_data *data; + + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); + gtk_tree_view_expand_all(GTK_TREE_VIEW(data->LV_acc)); +} + + +static void ui_hub_account_collapse_all(GtkWidget *widget, gpointer user_data) +{ +struct hbfile_data *data; + + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); + gtk_tree_view_collapse_all(GTK_TREE_VIEW(data->LV_acc)); +} + + +static void ui_hub_account_groups_free(GHashTable *h_group) +{ +GHashTableIter grp_iter; +gpointer key, value; + + DB( g_print("\n[hub-account] groups free\n") ); + + g_hash_table_iter_init (&grp_iter, h_group); + while (g_hash_table_iter_next (&grp_iter, &key, &value)) + { + PnlAccGrp *group = value; + + g_ptr_array_free (group->acclist, TRUE); + g_free(group); + } + + g_hash_table_destroy (h_group); +} + + +static GHashTable *ui_hub_account_groups_get(GtkTreeView *treeview, gint groupby, gboolean showall) +{ +GHashTable *h_group; +GList *lacc, *elt; +gchar *groupname; +gint nballoc; + + DB( g_print("\n[hub-account] groups get\n") ); + + nballoc = da_acc_length (); + + DB( g_print(" %d accounts\n", nballoc) ); + + h_group = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL); + + lacc = g_hash_table_get_values(GLOBALS->h_acc); + elt = g_list_first(lacc); + while (elt != NULL) + { + Account *acc = elt->data; + PnlAccGrp *group; + + //#1674045 ony rely on nosummary + //if( showall || !(acc->flags & (AF_CLOSED|AF_NOSUMMARY)) ) + if( showall || !(acc->flags & AF_NOSUMMARY) ) + { + switch( groupby ) + { + case DSPACC_GROUP_BY_BANK: + { + groupname = _("(no institution)"); + if( (acc->bankname != NULL) && strlen(acc->bankname) > 0 ) + groupname = acc->bankname; + } + break; + + default: + //pre 5.1.3 historical by type display + groupname = hbtk_get_label(CYA_ACC_TYPE, acc->type); + break; + } + + //#1820853 groupname could be NULL + if( groupname != NULL ) + { + if( g_hash_table_contains(h_group, groupname) == FALSE ) + { + group = g_malloc0(sizeof(PnlAccGrp)); + if( group ) + { + group->acclist = g_ptr_array_sized_new(nballoc); + group->expanded = list_account_level1_expanded(treeview, groupname); + g_hash_table_insert(h_group, g_strdup(groupname), group ); + DB( g_print(" grp '%s' exp:%d\n", groupname, group->expanded) ); + } + } + + group = g_hash_table_lookup(h_group, groupname); + if( group != NULL ) + { + g_ptr_array_add(group->acclist, (gpointer)acc); + DB( g_print(" + acc '%s'\n", acc->name) ); + } + } + } + elt = g_list_next(elt); + } + + g_list_free(lacc); + + return h_group; +} + + + + + +void ui_hub_account_populate(GtkWidget *widget, gpointer user_data) +{ +struct hbfile_data *data; +GtkTreeModel *model; +GtkTreeIter iter1, child_iter; +Account *acc; +guint j, nbtype; +gdouble gtbank, gttoday, gtfuture; +GHashTable *h_group; +GHashTableIter grp_iter; +gpointer key, value; + + DB( g_print("\n[hub-account] populate\n") ); + + data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data"); + h_group = ui_hub_account_groups_get(GTK_TREE_VIEW(data->LV_acc), PREFS->pnl_acc_show_by, data->showall); + + DB( g_print("\n\n populate listview, %d group(s)\n", g_hash_table_size(h_group)) ); + + nbtype = 0; + gtbank = gttoday = gtfuture = 0; + model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc)); + gtk_tree_store_clear (GTK_TREE_STORE(model)); + + g_hash_table_iter_init (&grp_iter, h_group); + while (g_hash_table_iter_next (&grp_iter, &key, &value)) + { + PnlAccGrp *group = value; + gdouble tbank, ttoday, tfuture; + gint position; + + if(group != NULL) + { + nbtype++; + //1: Header: Bank, Cash, ... + DB( g_print(" g '%s'\n", (gchar *)key) ); + + //#1663399 keep type position like in dropdown + position = 0; + if( PREFS->pnl_acc_show_by == DSPACC_GROUP_BY_TYPE ) + { + gint t = 0; + + while(CYA_ACC_TYPE[t].name != NULL && t < 32) + { + if( !strcmp(CYA_ACC_TYPE[t].name, key) ) + break; + t++; + } + + position = t; + } + + gtk_tree_store_append (GTK_TREE_STORE(model), &iter1, NULL); + gtk_tree_store_set (GTK_TREE_STORE(model), &iter1, + LST_DSPACC_POS, position, + LST_DSPACC_DATATYPE, DSPACC_TYPE_HEADER, + LST_DSPACC_NAME, key, + -1); + + //2: Accounts for real + tbank = ttoday = tfuture = 0; + for(j=0;jacclist->len;j++) + { + acc = g_ptr_array_index(group->acclist, j); + + //tbank += acc->bal_bank; + //ttoday += acc->bal_today; + //tfuture += acc->bal_future; + tbank += hb_amount_base(acc->bal_bank, acc->kcur); + ttoday += hb_amount_base(acc->bal_today, acc->kcur); + tfuture += hb_amount_base(acc->bal_future, acc->kcur); + + DB( g_print(" + '%s' :: %.2f %.2f %.2f\n", acc->name, acc->bal_bank, acc->bal_today, acc->bal_future) ); + + gtk_tree_store_append (GTK_TREE_STORE(model), &child_iter, &iter1); + gtk_tree_store_set (GTK_TREE_STORE(model), &child_iter, + LST_DSPACC_DATAS, acc, + LST_DSPACC_DATATYPE, DSPACC_TYPE_NORMAL, + LST_DSPACC_BANK, acc->bal_bank, + LST_DSPACC_TODAY, acc->bal_today, + LST_DSPACC_FUTURE, acc->bal_future, + -1); + } + + if(group->acclist->len > 1) + { + DB( g_print(" + total :: %.2f %.2f %.2f\n", tbank, ttoday, tfuture) ); + + // insert the total line + gtk_tree_store_append (GTK_TREE_STORE(model), &child_iter, &iter1); + gtk_tree_store_set (GTK_TREE_STORE(model), &child_iter, + LST_DSPACC_DATATYPE, DSPACC_TYPE_SUBTOTAL, + LST_DSPACC_NAME, _("Total"), + LST_DSPACC_BANK, tbank, + LST_DSPACC_TODAY, ttoday, + LST_DSPACC_FUTURE, tfuture, + -1); + } + + /* set balance to header to display when collasped */ + DB( g_print(" (enrich group total header) :: %.2f %.2f %.2f\n", tbank, ttoday, tfuture) ); + gtk_tree_store_set (GTK_TREE_STORE(model), &iter1, + LST_DSPACC_BANK, tbank, + LST_DSPACC_TODAY, ttoday, + LST_DSPACC_FUTURE, tfuture, + -1); + + if( group->expanded == TRUE ) + { + GtkTreePath *tmppath = gtk_tree_model_get_path(model, &iter1); + + DB( g_print(" expanding '%s'\n", (gchar *)key) ); + gtk_tree_view_expand_row(GTK_TREE_VIEW(data->LV_acc), tmppath, TRUE); + gtk_tree_path_free(tmppath); + } + + /* add to grand total */ + gtbank += tbank; + gttoday += ttoday; + gtfuture += tfuture; + + } + + } + + DB( g_print(" + grand total :: %.2f %.2f %.2f\n", gtbank, gttoday, gtfuture) ); + + // Grand total + if( nbtype > 1 ) + { + gtk_tree_store_append (GTK_TREE_STORE(model), &iter1, NULL); + gtk_tree_store_set (GTK_TREE_STORE(model), &iter1, + LST_DSPACC_DATATYPE, DSPACC_TYPE_SUBTOTAL, + LST_DSPACC_NAME, _("Grand total"), + LST_DSPACC_BANK, gtbank, + LST_DSPACC_TODAY, gttoday, + LST_DSPACC_FUTURE, gtfuture, + -1); + } + + //gtk_tree_view_expand_all(GTK_TREE_VIEW(data->LV_acc)); + + ui_hub_account_groups_free(h_group); + +} + + + +/* Callback function for the undo action */ +/*static void +activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) +{ + g_print ("Action %s activated\n", g_action_get_name (G_ACTION (action))); +}*/ + +static void +ui_hub_account_activate_toggle (GSimpleAction *action, GVariant *parameter, gpointer user_data) +{ +struct hbfile_data *data = user_data; + GVariant *old_state, *new_state; + + old_state = g_action_get_state (G_ACTION (action)); + new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state)); + + DB( g_print ("Toggle action %s activated, state changes from %d to %d\n", + g_action_get_name (G_ACTION (action)), + g_variant_get_boolean (old_state), + g_variant_get_boolean (new_state)) ); + + data->showall = g_variant_get_boolean (new_state); + ui_hub_account_populate(GLOBALS->mainwindow, NULL); + + g_simple_action_set_state (action, new_state); + g_variant_unref (old_state); +} + +static void +ui_hub_account_activate_radio (GSimpleAction *action, GVariant *parameter, gpointer user_data) +{ +//struct hbfile_data *data = user_data; +GVariant *old_state, *new_state; + + old_state = g_action_get_state (G_ACTION (action)); + new_state = g_variant_new_string (g_variant_get_string (parameter, NULL)); + + DB( g_print ("Radio action %s activated, state changes from %s to %s\n", + g_action_get_name (G_ACTION (action)), + g_variant_get_string (old_state, NULL), + g_variant_get_string (new_state, NULL)) ); + + PREFS->pnl_acc_show_by = DSPACC_GROUP_BY_TYPE; + if( !strcmp("bank", g_variant_get_string(new_state, NULL)) ) + PREFS->pnl_acc_show_by = DSPACC_GROUP_BY_BANK; + + ui_hub_account_populate(GLOBALS->mainwindow, NULL); + + g_simple_action_set_state (action, new_state); + g_variant_unref (old_state); +} + + +static const GActionEntry actions[] = { +// name, function(), type, state, +// { "paste", activate_action, NULL, NULL, NULL, {0,0,0} }, + { "showall", ui_hub_account_activate_toggle, NULL, "false" , NULL, {0,0,0} }, + { "groupby", ui_hub_account_activate_radio , "s", "'type'", NULL, {0,0,0} } +}; + + +void ui_hub_account_setup(struct hbfile_data *data) +{ +GAction *action; +GVariant *new_state; + + if( !G_IS_SIMPLE_ACTION_GROUP(data->action_group_acc) ) + return; + + action = g_action_map_lookup_action (G_ACTION_MAP (data->action_group_acc), "showall"); + if( action ) + { + new_state = g_variant_new_boolean (data->showall); + g_simple_action_set_state (G_SIMPLE_ACTION(action), new_state); + } + + action = g_action_map_lookup_action (G_ACTION_MAP (data->action_group_acc), "groupby"); + if( action ) + { + const gchar *value = "type"; + if( PREFS->pnl_acc_show_by == DSPACC_GROUP_BY_BANK ) + value = "bank"; + + new_state = g_variant_new_string (value); + g_simple_action_set_state (G_SIMPLE_ACTION (action), new_state); + } + +} + + +GtkWidget *ui_hub_account_create(struct hbfile_data *data) +{ +GtkWidget *hub, *label, *widget, *sw, *tbar, *hbox, *image; +GtkToolItem *toolitem; + + DB( g_print("\n[hub-account] create\n") ); + + + hub = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_container_set_border_width(GTK_CONTAINER(hub), SPACING_SMALL); + + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_box_pack_start (GTK_BOX (hub), sw, TRUE, TRUE, 0); + widget = (GtkWidget *)create_list_account(); + data->LV_acc = widget; + gtk_container_add (GTK_CONTAINER (sw), widget); + + //list toolbar + tbar = gtk_toolbar_new(); + gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar), GTK_ICON_SIZE_MENU); + gtk_toolbar_set_style(GTK_TOOLBAR(tbar), GTK_TOOLBAR_ICONS); + gtk_style_context_add_class (gtk_widget_get_style_context (tbar), GTK_STYLE_CLASS_INLINE_TOOLBAR); + gtk_box_pack_start (GTK_BOX (hub), tbar, FALSE, FALSE, 0); + + label = make_label_group(_("Your accounts")); + toolitem = gtk_tool_item_new(); + gtk_container_add (GTK_CONTAINER(toolitem), label); + gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1); + + toolitem = gtk_separator_tool_item_new (); + gtk_tool_item_set_expand (toolitem, TRUE); + gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE); + gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + toolitem = gtk_tool_item_new(); + gtk_container_add (GTK_CONTAINER(toolitem), hbox); + gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1); + + widget = make_image_button(ICONNAME_HB_BUTTON_EXPAND, _("Expand all")); + data->BT_expandall = widget; + gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); + + widget = make_image_button(ICONNAME_HB_BUTTON_COLLAPSE, _("Collapse all")); + data->BT_collapseall = widget; + gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); + + toolitem = gtk_separator_tool_item_new (); + gtk_tool_item_set_expand (toolitem, FALSE); + gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE); + gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1); + + + //gmenu test (see test folder into gtk) +GMenu *menu, *section; + + menu = g_menu_new (); + //g_menu_append (menumodel, "About", "actions.undo"); + //g_menu_append (menumodel, "Test", "actions.redo"); + section = g_menu_new (); + g_menu_append (section, _("Show all"), "actions.showall"); + g_menu_append_section(menu, NULL, G_MENU_MODEL(section)); + g_object_unref (section); + + section = g_menu_new (); + g_menu_append (section, _("By type"), "actions.groupby::type"); + g_menu_append (section, _("By institution"), "actions.groupby::bank"); + g_menu_append_section(menu, NULL, G_MENU_MODEL(section)); + g_object_unref (section); + + + GSimpleActionGroup *group = g_simple_action_group_new (); + data->action_group_acc = group; + g_action_map_add_action_entries (G_ACTION_MAP (group), actions, G_N_ELEMENTS (actions), data); + + + widget = gtk_menu_button_new(); + gtk_menu_button_set_direction (GTK_MENU_BUTTON(widget), GTK_ARROW_UP); + gtk_widget_set_halign (widget, GTK_ALIGN_END); + image = gtk_image_new_from_icon_name (ICONNAME_EMBLEM_SYSTEM, GTK_ICON_SIZE_MENU); + g_object_set (widget, "image", image, NULL); + + toolitem = gtk_tool_item_new(); + gtk_container_add (GTK_CONTAINER(toolitem), widget); + gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1); + + gtk_widget_insert_action_group (widget, "actions", G_ACTION_GROUP(group)); + gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (widget), G_MENU_MODEL (menu)); + + g_signal_connect (G_OBJECT (data->BT_expandall ), "clicked" , G_CALLBACK (ui_hub_account_expand_all), NULL); + g_signal_connect (G_OBJECT (data->BT_collapseall), "clicked" , G_CALLBACK (ui_hub_account_collapse_all), NULL); + + + return hub; +} +