1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
4 * This file is part of HomeBank.
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "hub-account.h"
24 #include "dsp-mainwindow.h"
25 #include "list-account.h"
28 /****************************************************************************/
30 /****************************************************************************/
39 /* our global datas */
40 extern struct HomeBank
*GLOBALS
;
41 extern struct Preferences
*PREFS
;
44 extern HbKvData CYA_ACC_TYPE
[];
47 static void ui_hub_account_expand_all(GtkWidget
*widget
, gpointer user_data
)
49 struct hbfile_data
*data
;
51 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
52 gtk_tree_view_expand_all(GTK_TREE_VIEW(data
->LV_acc
));
56 static void ui_hub_account_collapse_all(GtkWidget
*widget
, gpointer user_data
)
58 struct hbfile_data
*data
;
60 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
61 gtk_tree_view_collapse_all(GTK_TREE_VIEW(data
->LV_acc
));
65 static void ui_hub_account_groups_free(GHashTable
*h_group
)
67 GHashTableIter grp_iter
;
70 DB( g_print("\n[hub-account] groups free\n") );
72 g_hash_table_iter_init (&grp_iter
, h_group
);
73 while (g_hash_table_iter_next (&grp_iter
, &key
, &value
))
75 PnlAccGrp
*group
= value
;
77 g_ptr_array_free (group
->acclist
, TRUE
);
81 g_hash_table_destroy (h_group
);
85 static GHashTable
*ui_hub_account_groups_get(GtkTreeView
*treeview
, gint groupby
, gboolean showall
)
92 DB( g_print("\n[hub-account] groups get\n") );
94 nballoc
= da_acc_length ();
96 DB( g_print(" %d accounts\n", nballoc
) );
98 h_group
= g_hash_table_new_full(g_str_hash
, g_str_equal
, (GDestroyNotify
)g_free
, NULL
);
100 lacc
= g_hash_table_get_values(GLOBALS
->h_acc
);
101 elt
= g_list_first(lacc
);
104 Account
*acc
= elt
->data
;
107 //#1674045 ony rely on nosummary
108 //if( showall || !(acc->flags & (AF_CLOSED|AF_NOSUMMARY)) )
109 if( showall
|| !(acc
->flags
& AF_NOSUMMARY
) )
113 case DSPACC_GROUP_BY_BANK
:
115 groupname
= _("(no institution)");
116 if( (acc
->bankname
!= NULL
) && strlen(acc
->bankname
) > 0 )
117 groupname
= acc
->bankname
;
122 //pre 5.1.3 historical by type display
123 groupname
= hbtk_get_label(CYA_ACC_TYPE
, acc
->type
);
127 //#1820853 groupname could be NULL
128 if( groupname
!= NULL
)
130 if( g_hash_table_contains(h_group
, groupname
) == FALSE
)
132 group
= g_malloc0(sizeof(PnlAccGrp
));
135 group
->acclist
= g_ptr_array_sized_new(nballoc
);
136 group
->expanded
= list_account_level1_expanded(treeview
, groupname
);
137 g_hash_table_insert(h_group
, g_strdup(groupname
), group
);
138 DB( g_print(" grp '%s' exp:%d\n", groupname
, group
->expanded
) );
142 group
= g_hash_table_lookup(h_group
, groupname
);
145 g_ptr_array_add(group
->acclist
, (gpointer
)acc
);
146 DB( g_print(" + acc '%s'\n", acc
->name
) );
150 elt
= g_list_next(elt
);
162 void ui_hub_account_populate(GtkWidget
*widget
, gpointer user_data
)
164 struct hbfile_data
*data
;
166 GtkTreeIter iter1
, child_iter
;
169 gdouble gtbank
, gttoday
, gtfuture
;
171 GHashTableIter grp_iter
;
174 DB( g_print("\n[hub-account] populate\n") );
176 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
177 h_group
= ui_hub_account_groups_get(GTK_TREE_VIEW(data
->LV_acc
), PREFS
->pnl_acc_show_by
, data
->showall
);
179 DB( g_print("\n\n populate listview, %d group(s)\n", g_hash_table_size(h_group
)) );
182 gtbank
= gttoday
= gtfuture
= 0;
183 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_acc
));
184 gtk_tree_store_clear (GTK_TREE_STORE(model
));
186 g_hash_table_iter_init (&grp_iter
, h_group
);
187 while (g_hash_table_iter_next (&grp_iter
, &key
, &value
))
189 PnlAccGrp
*group
= value
;
190 gdouble tbank
, ttoday
, tfuture
;
196 //1: Header: Bank, Cash, ...
197 DB( g_print(" g '%s'\n", (gchar
*)key
) );
199 //#1663399 keep type position like in dropdown
201 if( PREFS
->pnl_acc_show_by
== DSPACC_GROUP_BY_TYPE
)
205 while(CYA_ACC_TYPE
[t
].name
!= NULL
&& t
< 32)
207 if( !strcmp(CYA_ACC_TYPE
[t
].name
, key
) )
215 gtk_tree_store_append (GTK_TREE_STORE(model
), &iter1
, NULL
);
216 gtk_tree_store_set (GTK_TREE_STORE(model
), &iter1
,
217 LST_DSPACC_POS
, position
,
218 LST_DSPACC_DATATYPE
, DSPACC_TYPE_HEADER
,
219 LST_DSPACC_NAME
, key
,
222 //2: Accounts for real
223 tbank
= ttoday
= tfuture
= 0;
224 for(j
=0;j
<group
->acclist
->len
;j
++)
226 acc
= g_ptr_array_index(group
->acclist
, j
);
228 //tbank += acc->bal_bank;
229 //ttoday += acc->bal_today;
230 //tfuture += acc->bal_future;
231 tbank
+= hb_amount_base(acc
->bal_bank
, acc
->kcur
);
232 ttoday
+= hb_amount_base(acc
->bal_today
, acc
->kcur
);
233 tfuture
+= hb_amount_base(acc
->bal_future
, acc
->kcur
);
235 DB( g_print(" + '%s' :: %.2f %.2f %.2f\n", acc
->name
, acc
->bal_bank
, acc
->bal_today
, acc
->bal_future
) );
237 gtk_tree_store_append (GTK_TREE_STORE(model
), &child_iter
, &iter1
);
238 gtk_tree_store_set (GTK_TREE_STORE(model
), &child_iter
,
239 LST_DSPACC_DATAS
, acc
,
240 LST_DSPACC_DATATYPE
, DSPACC_TYPE_NORMAL
,
241 LST_DSPACC_BANK
, acc
->bal_bank
,
242 LST_DSPACC_TODAY
, acc
->bal_today
,
243 LST_DSPACC_FUTURE
, acc
->bal_future
,
247 if(group
->acclist
->len
> 1)
249 DB( g_print(" + total :: %.2f %.2f %.2f\n", tbank
, ttoday
, tfuture
) );
251 // insert the total line
252 gtk_tree_store_append (GTK_TREE_STORE(model
), &child_iter
, &iter1
);
253 gtk_tree_store_set (GTK_TREE_STORE(model
), &child_iter
,
254 LST_DSPACC_DATATYPE
, DSPACC_TYPE_SUBTOTAL
,
255 LST_DSPACC_NAME
, _("Total"),
256 LST_DSPACC_BANK
, tbank
,
257 LST_DSPACC_TODAY
, ttoday
,
258 LST_DSPACC_FUTURE
, tfuture
,
262 /* set balance to header to display when collasped */
263 DB( g_print(" (enrich group total header) :: %.2f %.2f %.2f\n", tbank
, ttoday
, tfuture
) );
264 gtk_tree_store_set (GTK_TREE_STORE(model
), &iter1
,
265 LST_DSPACC_BANK
, tbank
,
266 LST_DSPACC_TODAY
, ttoday
,
267 LST_DSPACC_FUTURE
, tfuture
,
270 if( group
->expanded
== TRUE
)
272 GtkTreePath
*tmppath
= gtk_tree_model_get_path(model
, &iter1
);
274 DB( g_print(" expanding '%s'\n", (gchar
*)key
) );
275 gtk_tree_view_expand_row(GTK_TREE_VIEW(data
->LV_acc
), tmppath
, TRUE
);
276 gtk_tree_path_free(tmppath
);
279 /* add to grand total */
288 DB( g_print(" + grand total :: %.2f %.2f %.2f\n", gtbank
, gttoday
, gtfuture
) );
293 gtk_tree_store_append (GTK_TREE_STORE(model
), &iter1
, NULL
);
294 gtk_tree_store_set (GTK_TREE_STORE(model
), &iter1
,
295 LST_DSPACC_DATATYPE
, DSPACC_TYPE_SUBTOTAL
,
296 LST_DSPACC_NAME
, _("Grand total"),
297 LST_DSPACC_BANK
, gtbank
,
298 LST_DSPACC_TODAY
, gttoday
,
299 LST_DSPACC_FUTURE
, gtfuture
,
303 //gtk_tree_view_expand_all(GTK_TREE_VIEW(data->LV_acc));
305 ui_hub_account_groups_free(h_group
);
311 /* Callback function for the undo action */
313 activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data)
315 g_print ("Action %s activated\n", g_action_get_name (G_ACTION (action)));
319 ui_hub_account_activate_toggle (GSimpleAction
*action
, GVariant
*parameter
, gpointer user_data
)
321 struct hbfile_data
*data
= user_data
;
322 GVariant
*old_state
, *new_state
;
324 old_state
= g_action_get_state (G_ACTION (action
));
325 new_state
= g_variant_new_boolean (!g_variant_get_boolean (old_state
));
327 DB( g_print ("Toggle action %s activated, state changes from %d to %d\n",
328 g_action_get_name (G_ACTION (action
)),
329 g_variant_get_boolean (old_state
),
330 g_variant_get_boolean (new_state
)) );
332 data
->showall
= g_variant_get_boolean (new_state
);
333 ui_hub_account_populate(GLOBALS
->mainwindow
, NULL
);
335 g_simple_action_set_state (action
, new_state
);
336 g_variant_unref (old_state
);
340 ui_hub_account_activate_radio (GSimpleAction
*action
, GVariant
*parameter
, gpointer user_data
)
342 //struct hbfile_data *data = user_data;
343 GVariant
*old_state
, *new_state
;
345 old_state
= g_action_get_state (G_ACTION (action
));
346 new_state
= g_variant_new_string (g_variant_get_string (parameter
, NULL
));
348 DB( g_print ("Radio action %s activated, state changes from %s to %s\n",
349 g_action_get_name (G_ACTION (action
)),
350 g_variant_get_string (old_state
, NULL
),
351 g_variant_get_string (new_state
, NULL
)) );
353 PREFS
->pnl_acc_show_by
= DSPACC_GROUP_BY_TYPE
;
354 if( !strcmp("bank", g_variant_get_string(new_state
, NULL
)) )
355 PREFS
->pnl_acc_show_by
= DSPACC_GROUP_BY_BANK
;
357 ui_hub_account_populate(GLOBALS
->mainwindow
, NULL
);
359 g_simple_action_set_state (action
, new_state
);
360 g_variant_unref (old_state
);
364 static const GActionEntry actions
[] = {
365 // name, function(), type, state,
366 // { "paste", activate_action, NULL, NULL, NULL, {0,0,0} },
367 { "showall", ui_hub_account_activate_toggle
, NULL
, "false" , NULL
, {0,0,0} },
368 { "groupby", ui_hub_account_activate_radio
, "s", "'type'", NULL
, {0,0,0} }
372 void ui_hub_account_setup(struct hbfile_data
*data
)
377 if( !G_IS_SIMPLE_ACTION_GROUP(data
->action_group_acc
) )
380 action
= g_action_map_lookup_action (G_ACTION_MAP (data
->action_group_acc
), "showall");
383 new_state
= g_variant_new_boolean (data
->showall
);
384 g_simple_action_set_state (G_SIMPLE_ACTION(action
), new_state
);
387 action
= g_action_map_lookup_action (G_ACTION_MAP (data
->action_group_acc
), "groupby");
390 const gchar
*value
= "type";
391 if( PREFS
->pnl_acc_show_by
== DSPACC_GROUP_BY_BANK
)
394 new_state
= g_variant_new_string (value
);
395 g_simple_action_set_state (G_SIMPLE_ACTION (action
), new_state
);
401 GtkWidget
*ui_hub_account_create(struct hbfile_data
*data
)
403 GtkWidget
*hub
, *label
, *widget
, *sw
, *tbar
, *hbox
, *image
;
404 GtkToolItem
*toolitem
;
406 DB( g_print("\n[hub-account] create\n") );
409 hub
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 0);
410 gtk_container_set_border_width(GTK_CONTAINER(hub
), SPACING_SMALL
);
412 sw
= gtk_scrolled_window_new (NULL
, NULL
);
413 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw
), GTK_SHADOW_ETCHED_IN
);
414 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw
), GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
415 gtk_box_pack_start (GTK_BOX (hub
), sw
, TRUE
, TRUE
, 0);
416 widget
= (GtkWidget
*)create_list_account();
417 data
->LV_acc
= widget
;
418 gtk_container_add (GTK_CONTAINER (sw
), widget
);
421 tbar
= gtk_toolbar_new();
422 gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar
), GTK_ICON_SIZE_MENU
);
423 gtk_toolbar_set_style(GTK_TOOLBAR(tbar
), GTK_TOOLBAR_ICONS
);
424 gtk_style_context_add_class (gtk_widget_get_style_context (tbar
), GTK_STYLE_CLASS_INLINE_TOOLBAR
);
425 gtk_box_pack_start (GTK_BOX (hub
), tbar
, FALSE
, FALSE
, 0);
427 label
= make_label_group(_("Your accounts"));
428 toolitem
= gtk_tool_item_new();
429 gtk_container_add (GTK_CONTAINER(toolitem
), label
);
430 gtk_toolbar_insert(GTK_TOOLBAR(tbar
), GTK_TOOL_ITEM(toolitem
), -1);
432 toolitem
= gtk_separator_tool_item_new ();
433 gtk_tool_item_set_expand (toolitem
, TRUE
);
434 gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem
), FALSE
);
435 gtk_toolbar_insert(GTK_TOOLBAR(tbar
), GTK_TOOL_ITEM(toolitem
), -1);
437 hbox
= gtk_box_new (GTK_ORIENTATION_HORIZONTAL
, 0);
438 toolitem
= gtk_tool_item_new();
439 gtk_container_add (GTK_CONTAINER(toolitem
), hbox
);
440 gtk_toolbar_insert(GTK_TOOLBAR(tbar
), GTK_TOOL_ITEM(toolitem
), -1);
442 widget
= make_image_button(ICONNAME_HB_BUTTON_EXPAND
, _("Expand all"));
443 data
->BT_expandall
= widget
;
444 gtk_box_pack_start (GTK_BOX (hbox
), widget
, FALSE
, FALSE
, 0);
446 widget
= make_image_button(ICONNAME_HB_BUTTON_COLLAPSE
, _("Collapse all"));
447 data
->BT_collapseall
= widget
;
448 gtk_box_pack_start (GTK_BOX (hbox
), widget
, FALSE
, FALSE
, 0);
450 toolitem
= gtk_separator_tool_item_new ();
451 gtk_tool_item_set_expand (toolitem
, FALSE
);
452 gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem
), FALSE
);
453 gtk_toolbar_insert(GTK_TOOLBAR(tbar
), GTK_TOOL_ITEM(toolitem
), -1);
456 //gmenu test (see test folder into gtk)
457 GMenu
*menu
, *section
;
459 menu
= g_menu_new ();
460 //g_menu_append (menumodel, "About", "actions.undo");
461 //g_menu_append (menumodel, "Test", "actions.redo");
462 section
= g_menu_new ();
463 g_menu_append (section
, _("Show all"), "actions.showall");
464 g_menu_append_section(menu
, NULL
, G_MENU_MODEL(section
));
465 g_object_unref (section
);
467 section
= g_menu_new ();
468 g_menu_append (section
, _("By type"), "actions.groupby::type");
469 g_menu_append (section
, _("By institution"), "actions.groupby::bank");
470 g_menu_append_section(menu
, NULL
, G_MENU_MODEL(section
));
471 g_object_unref (section
);
474 GSimpleActionGroup
*group
= g_simple_action_group_new ();
475 data
->action_group_acc
= group
;
476 g_action_map_add_action_entries (G_ACTION_MAP (group
), actions
, G_N_ELEMENTS (actions
), data
);
479 widget
= gtk_menu_button_new();
480 gtk_menu_button_set_direction (GTK_MENU_BUTTON(widget
), GTK_ARROW_UP
);
481 gtk_widget_set_halign (widget
, GTK_ALIGN_END
);
482 image
= gtk_image_new_from_icon_name (ICONNAME_EMBLEM_SYSTEM
, GTK_ICON_SIZE_MENU
);
483 g_object_set (widget
, "image", image
, NULL
);
485 toolitem
= gtk_tool_item_new();
486 gtk_container_add (GTK_CONTAINER(toolitem
), widget
);
487 gtk_toolbar_insert(GTK_TOOLBAR(tbar
), GTK_TOOL_ITEM(toolitem
), -1);
489 gtk_widget_insert_action_group (widget
, "actions", G_ACTION_GROUP(group
));
490 gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (widget
), G_MENU_MODEL (menu
));
492 g_signal_connect (G_OBJECT (data
->BT_expandall
), "clicked" , G_CALLBACK (ui_hub_account_expand_all
), NULL
);
493 g_signal_connect (G_OBJECT (data
->BT_collapseall
), "clicked" , G_CALLBACK (ui_hub_account_collapse_all
), NULL
);