]> Dogcows Code - chaz/homebank/blob - src/hub-account.c
import homebank-5.2.4
[chaz/homebank] / src / hub-account.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 #include "homebank.h"
22
23 #include "hub-account.h"
24 #include "dsp-mainwindow.h"
25 #include "list-account.h"
26
27
28 /****************************************************************************/
29 /* Debug macros */
30 /****************************************************************************/
31 #define MYDEBUG 0
32
33 #if MYDEBUG
34 #define DB(x) (x);
35 #else
36 #define DB(x);
37 #endif
38
39 /* our global datas */
40 extern struct HomeBank *GLOBALS;
41 extern struct Preferences *PREFS;
42
43
44 extern HbKvData CYA_ACC_TYPE[];
45
46
47 static void ui_hub_account_expand_all(GtkWidget *widget, gpointer user_data)
48 {
49 struct hbfile_data *data;
50
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));
53 }
54
55
56 static void ui_hub_account_collapse_all(GtkWidget *widget, gpointer user_data)
57 {
58 struct hbfile_data *data;
59
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));
62 }
63
64
65 static void ui_hub_account_groups_free(GHashTable *h_group)
66 {
67 GHashTableIter grp_iter;
68 gpointer key, value;
69
70 DB( g_print("\n[hub-account] groups free\n") );
71
72 g_hash_table_iter_init (&grp_iter, h_group);
73 while (g_hash_table_iter_next (&grp_iter, &key, &value))
74 {
75 PnlAccGrp *group = value;
76
77 g_ptr_array_free (group->acclist, TRUE);
78 g_free(group);
79 }
80
81 g_hash_table_destroy (h_group);
82 }
83
84
85 static GHashTable *ui_hub_account_groups_get(GtkTreeView *treeview, gint groupby, gboolean showall)
86 {
87 GHashTable *h_group;
88 GList *lacc, *elt;
89 gchar *groupname;
90 gint nballoc;
91
92 DB( g_print("\n[hub-account] groups get\n") );
93
94 nballoc = da_acc_length ();
95
96 DB( g_print(" %d accounts\n", nballoc) );
97
98 h_group = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, NULL);
99
100 lacc = g_hash_table_get_values(GLOBALS->h_acc);
101 elt = g_list_first(lacc);
102 while (elt != NULL)
103 {
104 Account *acc = elt->data;
105 PnlAccGrp *group;
106
107 //#1674045 ony rely on nosummary
108 //if( showall || !(acc->flags & (AF_CLOSED|AF_NOSUMMARY)) )
109 if( showall || !(acc->flags & AF_NOSUMMARY) )
110 {
111 switch( groupby )
112 {
113 case DSPACC_GROUP_BY_BANK:
114 {
115 groupname = _("(no institution)");
116 if( (acc->bankname != NULL) && strlen(acc->bankname) > 0 )
117 groupname = acc->bankname;
118 }
119 break;
120
121 default:
122 //pre 5.1.3 historical by type display
123 groupname = hbtk_get_label(CYA_ACC_TYPE, acc->type);
124 break;
125 }
126
127 //#1820853 groupname could be NULL
128 if( groupname != NULL )
129 {
130 if( g_hash_table_contains(h_group, groupname) == FALSE )
131 {
132 group = g_malloc0(sizeof(PnlAccGrp));
133 if( group )
134 {
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) );
139 }
140 }
141
142 group = g_hash_table_lookup(h_group, groupname);
143 if( group != NULL )
144 {
145 g_ptr_array_add(group->acclist, (gpointer)acc);
146 DB( g_print(" + acc '%s'\n", acc->name) );
147 }
148 }
149 }
150 elt = g_list_next(elt);
151 }
152
153 g_list_free(lacc);
154
155 return h_group;
156 }
157
158
159
160
161
162 void ui_hub_account_populate(GtkWidget *widget, gpointer user_data)
163 {
164 struct hbfile_data *data;
165 GtkTreeModel *model;
166 GtkTreeIter iter1, child_iter;
167 Account *acc;
168 guint j, nbtype;
169 gdouble gtbank, gttoday, gtfuture;
170 GHashTable *h_group;
171 GHashTableIter grp_iter;
172 gpointer key, value;
173
174 DB( g_print("\n[hub-account] populate\n") );
175
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);
178
179 DB( g_print("\n\n populate listview, %d group(s)\n", g_hash_table_size(h_group)) );
180
181 nbtype = 0;
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));
185
186 g_hash_table_iter_init (&grp_iter, h_group);
187 while (g_hash_table_iter_next (&grp_iter, &key, &value))
188 {
189 PnlAccGrp *group = value;
190 gdouble tbank, ttoday, tfuture;
191 gint position;
192
193 if(group != NULL)
194 {
195 nbtype++;
196 //1: Header: Bank, Cash, ...
197 DB( g_print(" g '%s'\n", (gchar *)key) );
198
199 //#1663399 keep type position like in dropdown
200 position = 0;
201 if( PREFS->pnl_acc_show_by == DSPACC_GROUP_BY_TYPE )
202 {
203 gint t = 0;
204
205 while(CYA_ACC_TYPE[t].name != NULL && t < 32)
206 {
207 if( !strcmp(CYA_ACC_TYPE[t].name, key) )
208 break;
209 t++;
210 }
211
212 position = t;
213 }
214
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,
220 -1);
221
222 //2: Accounts for real
223 tbank = ttoday = tfuture = 0;
224 for(j=0;j<group->acclist->len;j++)
225 {
226 acc = g_ptr_array_index(group->acclist, j);
227
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);
234
235 DB( g_print(" + '%s' :: %.2f %.2f %.2f\n", acc->name, acc->bal_bank, acc->bal_today, acc->bal_future) );
236
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,
244 -1);
245 }
246
247 if(group->acclist->len > 1)
248 {
249 DB( g_print(" + total :: %.2f %.2f %.2f\n", tbank, ttoday, tfuture) );
250
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,
259 -1);
260 }
261
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,
268 -1);
269
270 if( group->expanded == TRUE )
271 {
272 GtkTreePath *tmppath = gtk_tree_model_get_path(model, &iter1);
273
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);
277 }
278
279 /* add to grand total */
280 gtbank += tbank;
281 gttoday += ttoday;
282 gtfuture += tfuture;
283
284 }
285
286 }
287
288 DB( g_print(" + grand total :: %.2f %.2f %.2f\n", gtbank, gttoday, gtfuture) );
289
290 // Grand total
291 if( nbtype > 1 )
292 {
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,
300 -1);
301 }
302
303 //gtk_tree_view_expand_all(GTK_TREE_VIEW(data->LV_acc));
304
305 ui_hub_account_groups_free(h_group);
306
307 }
308
309
310
311 /* Callback function for the undo action */
312 /*static void
313 activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data)
314 {
315 g_print ("Action %s activated\n", g_action_get_name (G_ACTION (action)));
316 }*/
317
318 static void
319 ui_hub_account_activate_toggle (GSimpleAction *action, GVariant *parameter, gpointer user_data)
320 {
321 struct hbfile_data *data = user_data;
322 GVariant *old_state, *new_state;
323
324 old_state = g_action_get_state (G_ACTION (action));
325 new_state = g_variant_new_boolean (!g_variant_get_boolean (old_state));
326
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)) );
331
332 data->showall = g_variant_get_boolean (new_state);
333 ui_hub_account_populate(GLOBALS->mainwindow, NULL);
334
335 g_simple_action_set_state (action, new_state);
336 g_variant_unref (old_state);
337 }
338
339 static void
340 ui_hub_account_activate_radio (GSimpleAction *action, GVariant *parameter, gpointer user_data)
341 {
342 //struct hbfile_data *data = user_data;
343 GVariant *old_state, *new_state;
344
345 old_state = g_action_get_state (G_ACTION (action));
346 new_state = g_variant_new_string (g_variant_get_string (parameter, NULL));
347
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)) );
352
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;
356
357 ui_hub_account_populate(GLOBALS->mainwindow, NULL);
358
359 g_simple_action_set_state (action, new_state);
360 g_variant_unref (old_state);
361 }
362
363
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} }
369 };
370
371
372 void ui_hub_account_setup(struct hbfile_data *data)
373 {
374 GAction *action;
375 GVariant *new_state;
376
377 if( !G_IS_SIMPLE_ACTION_GROUP(data->action_group_acc) )
378 return;
379
380 action = g_action_map_lookup_action (G_ACTION_MAP (data->action_group_acc), "showall");
381 if( action )
382 {
383 new_state = g_variant_new_boolean (data->showall);
384 g_simple_action_set_state (G_SIMPLE_ACTION(action), new_state);
385 }
386
387 action = g_action_map_lookup_action (G_ACTION_MAP (data->action_group_acc), "groupby");
388 if( action )
389 {
390 const gchar *value = "type";
391 if( PREFS->pnl_acc_show_by == DSPACC_GROUP_BY_BANK )
392 value = "bank";
393
394 new_state = g_variant_new_string (value);
395 g_simple_action_set_state (G_SIMPLE_ACTION (action), new_state);
396 }
397
398 }
399
400
401 GtkWidget *ui_hub_account_create(struct hbfile_data *data)
402 {
403 GtkWidget *hub, *label, *widget, *sw, *tbar, *hbox, *image;
404 GtkToolItem *toolitem;
405
406 DB( g_print("\n[hub-account] create\n") );
407
408
409 hub = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
410 gtk_container_set_border_width(GTK_CONTAINER(hub), SPACING_SMALL);
411
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);
419
420 //list toolbar
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);
426
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);
431
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);
436
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);
441
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);
445
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);
449
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);
454
455
456 //gmenu test (see test folder into gtk)
457 GMenu *menu, *section;
458
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);
466
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);
472
473
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);
477
478
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);
484
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);
488
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));
491
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);
494
495
496 return hub;
497 }
498
This page took 0.050443 seconds and 4 git commands to generate.