1 /*  HomeBank -- Free, easy, personal accounting for everyone.
2  *  Copyright (C) 1995-2021 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 "rep-stats.h"
24 
25 #include "list-operation.h"
26 #include "gtk-chart.h"
27 #include "gtk-dateentry.h"
28 
29 #include "dsp-mainwindow.h"
30 #include "ui-filter.h"
31 #include "ui-transaction.h"
32 
33 
34 /****************************************************************************/
35 /* Debug macros                                                             */
36 /****************************************************************************/
37 #define MYDEBUG 0
38 
39 #if MYDEBUG
40 #define DB(x) (x);
41 #else
42 #define DB(x);
43 #endif
44 
45 /* our global datas */
46 extern struct HomeBank *GLOBALS;
47 extern struct Preferences *PREFS;
48 
49 
50 /* prototypes */
51 static void repstats_range_change(GtkWidget *widget, gpointer user_data);
52 static void repstats_filter_setup(struct repstats_data *data);
53 static void repstats_compute(GtkWidget *widget, gpointer user_data);
54 static void repstats_sensitive(GtkWidget *widget, gpointer user_data);
55 static void repstats_update_daterange(GtkWidget *widget, gpointer user_data);
56 static void repstats_update_date_widget(GtkWidget *widget, gpointer user_data);
57 
58 static GtkWidget *lst_rep_total_create(void);
59 static GString *lst_rep_total_to_string(GtkTreeView *treeview, gchar *title, gboolean clipboard);
60 
61 static GtkWidget *lst_rep_time_create(void);
62 static void lst_rep_time_renewcol(GtkTreeView *treeview, guint32 nbintvl, guint32 jfrom, gint intvl);
63 
64 
65 HbKvData CYA_REPORT_SRC[] = {
66 	{ REPORT_SRC_CATEGORY,		N_("Category") },
67 	{ REPORT_SRC_SUBCATEGORY,	N_("Subcategory") },
68 	{ REPORT_SRC_PAYEE,			N_("Payee") },
69 	{ REPORT_SRC_ACCOUNT,		N_("Account") },
70 	{ REPORT_SRC_TAG,			N_("Tag") },
71 	{ REPORT_SRC_MONTH,			N_("Month") },
72 	{ REPORT_SRC_YEAR,			N_("Year") },
73 	{ 0, NULL }
74 };
75 
76 
77 HbKvData CYA_REPORT_TYPE[] = {
78 	{ REPORT_TYPE_EXPENSE,	N_("Expense") },
79 	{ REPORT_TYPE_INCOME,	N_("Income") },
80 	{ REPORT_TYPE_TOTAL,	N_("Total")} ,
81 	{ 0, NULL }
82 };
83 
84 extern gchar *CYA_REPORT_MODE[];
85 extern HbKvData CYA_REPORT_INTVL[];
86 
87 
88 /* action functions -------------------- */
89 
90 
91 
92 
repstats_action_viewlist(GtkToolButton * toolbutton,gpointer user_data)93 static void repstats_action_viewlist(GtkToolButton *toolbutton, gpointer user_data)
94 {
95 struct repstats_data *data = user_data;
96 gint tmpmode;
97 
98 	tmpmode  = hbtk_radio_button_get_active(GTK_CONTAINER(data->RA_mode));
99 	if(tmpmode == 0 )
100 		gtk_notebook_set_current_page(GTK_NOTEBOOK(data->GR_result), 0);
101 	else
102 		gtk_notebook_set_current_page(GTK_NOTEBOOK(data->GR_result), 2);
103 	data->charttype = 0;
104 	repstats_sensitive(data->window, NULL);
105 }
106 
107 
repstats_action_mode_changed(GtkToolButton * toolbutton,gpointer user_data)108 static void repstats_action_mode_changed(GtkToolButton *toolbutton, gpointer user_data)
109 {
110 struct repstats_data *data = user_data;
111 
112 	gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(data->BT_list), TRUE);
113 	repstats_action_viewlist(toolbutton, data);
114 }
115 
116 
repstats_action_viewbar(GtkToolButton * toolbutton,gpointer user_data)117 static void repstats_action_viewbar(GtkToolButton *toolbutton, gpointer user_data)
118 {
119 struct repstats_data *data = user_data;
120 
121 	gtk_notebook_set_current_page(GTK_NOTEBOOK(data->GR_result), 1);
122 	gtk_chart_set_type (GTK_CHART(data->RE_chart), CHART_TYPE_COL);
123 	data->charttype = CHART_TYPE_COL;
124 	repstats_sensitive(data->window, NULL);
125 }
126 
127 
repstats_action_viewpie(GtkToolButton * toolbutton,gpointer user_data)128 static void repstats_action_viewpie(GtkToolButton *toolbutton, gpointer user_data)
129 {
130 struct repstats_data *data = user_data;
131 
132 	gtk_notebook_set_current_page(GTK_NOTEBOOK(data->GR_result), 1);
133 	gtk_chart_set_type (GTK_CHART(data->RE_chart), CHART_TYPE_PIE);
134 	data->charttype = CHART_TYPE_PIE;
135 	repstats_sensitive(data->window, NULL);
136 }
137 
138 
repstats_action_print(GtkToolButton * toolbutton,gpointer user_data)139 static void repstats_action_print(GtkToolButton *toolbutton, gpointer user_data)
140 {
141 struct repstats_data *data = user_data;
142 gint tmpsrc;
143 gchar *name;
144 
145 	tmpsrc  = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_src));
146 	name = g_strdup_printf("hb-repstat_%s", hbtk_get_label(CYA_REPORT_SRC,tmpsrc));
147 
148 	gtk_chart_print(GTK_CHART(data->RE_chart), GTK_WINDOW(data->window), PREFS->path_export, name);
149 
150 	g_free(name);
151 }
152 
153 
repstats_action_filter(GtkToolButton * toolbutton,gpointer user_data)154 static void repstats_action_filter(GtkToolButton *toolbutton, gpointer user_data)
155 {
156 struct repstats_data *data = user_data;
157 gint response_id;
158 
159 	DB( g_print("\n[repdist] filter\n") );
160 
161 	//debug
162 	//create_deffilter_window(data->filter, TRUE);
163 	response_id = ui_flt_manage_dialog_new(GTK_WINDOW(data->window), data->filter, TRUE, FALSE);
164 	if( response_id != GTK_RESPONSE_REJECT)
165 	{
166 		if( response_id == 55 )	//reset
167 		{
168 			DB( g_print(" reset filter\n") );
169 			repstats_filter_setup(data);
170 		}
171 		else
172 		{
173 			if( data->filter->range == FLT_RANGE_OTHER )
174 			{
175 				filter_preset_daterange_set(data->filter, data->filter->range, 0);
176 			}
177 		}
178 
179 		g_signal_handler_block(data->CY_range, data->handler_id[HID_REPDIST_RANGE]);
180 		hbtk_combo_box_set_active_id(GTK_COMBO_BOX_TEXT(data->CY_range), data->filter->range);
181 		g_signal_handler_unblock(data->CY_range, data->handler_id[HID_REPDIST_RANGE]);
182 
183 
184 		repstats_compute(data->window, NULL);
185 		repstats_update_date_widget(data->window, NULL);
186 		repstats_update_daterange(data->window, NULL);
187 	}
188 }
189 
190 
191 /*
192 ** ============================================================================
193 */
194 
195 
repstats_date_change(GtkWidget * widget,gpointer user_data)196 static void repstats_date_change(GtkWidget *widget, gpointer user_data)
197 {
198 struct repstats_data *data;
199 
200 	DB( g_print("\n[repdist] date change\n") );
201 
202 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
203 
204 	data->filter->mindate = gtk_date_entry_get_date(GTK_DATE_ENTRY(data->PO_mindate));
205 	data->filter->maxdate = gtk_date_entry_get_date(GTK_DATE_ENTRY(data->PO_maxdate));
206 
207 	// set min/max date for both widget
208 	gtk_date_entry_set_maxdate(GTK_DATE_ENTRY(data->PO_mindate), data->filter->maxdate);
209 	gtk_date_entry_set_mindate(GTK_DATE_ENTRY(data->PO_maxdate), data->filter->mindate);
210 
211 	g_signal_handler_block(data->CY_range, data->handler_id[HID_REPDIST_RANGE]);
212 	hbtk_combo_box_set_active_id(GTK_COMBO_BOX_TEXT(data->CY_range), FLT_RANGE_OTHER);
213 	g_signal_handler_unblock(data->CY_range, data->handler_id[HID_REPDIST_RANGE]);
214 
215 	repstats_compute(widget, NULL);
216 	repstats_update_daterange(widget, NULL);
217 
218 }
219 
220 
repstats_range_change(GtkWidget * widget,gpointer user_data)221 static void repstats_range_change(GtkWidget *widget, gpointer user_data)
222 {
223 struct repstats_data *data;
224 gint range;
225 
226 	DB( g_print("\n[repdist] range change\n") );
227 
228 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
229 
230 	range = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_range));
231 
232 	if(range != FLT_RANGE_OTHER)
233 	{
234 		filter_preset_daterange_set(data->filter, range, 0);
235 
236 		repstats_update_date_widget(data->window, NULL);
237 
238 		repstats_compute(data->window, NULL);
239 		repstats_update_daterange(data->window, NULL);
240 	}
241 	else
242 	{
243 		if(ui_flt_manage_dialog_new(GTK_WINDOW(data->window), data->filter, TRUE, FALSE) != GTK_RESPONSE_REJECT)
244 		{
245 			repstats_update_date_widget(data->window, NULL);
246 			repstats_compute(data->window, NULL);
247 			repstats_update_daterange(data->window, NULL);
248 		}
249 	}
250 }
251 
252 
repstats_update(GtkWidget * widget,gpointer user_data)253 static void repstats_update(GtkWidget *widget, gpointer user_data)
254 {
255 struct repstats_data *data;
256 gboolean byamount;
257 GtkTreeModel		 *model;
258 gint tmpsrc, tmptype, usrcomp, column;
259 gboolean xval;
260 gchar *title;
261 
262 	DB( g_print("\n[repdist] update\n") );
263 
264 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
265 
266 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report));
267 	byamount = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_byamount));
268 	usrcomp = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_compare));
269 	tmptype = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_type));
270 	//tmpsrc  = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_src));
271 	tmpsrc  = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_src));
272 
273 	//debug option
274 	DB( g_print(" option: byamount=%d tmptype=%d '%s' tmpsrc=%d '%s'\n\n", byamount, tmptype, hbtk_get_label(CYA_REPORT_TYPE,tmptype), tmpsrc, hbtk_get_label(CYA_REPORT_SRC,tmpsrc)) );
275 
276 	// define view/sort column
277 	column = LST_REPDIST_POS;
278 
279 	if( byamount )
280 	{
281 		switch( tmptype )
282 		{
283 			case REPORT_TYPE_TOTAL:
284 				column = LST_REPDIST_TOTAL;
285 				break;
286 			case REPORT_TYPE_EXPENSE:
287 				column = LST_REPDIST_EXPENSE;
288 				break;
289 			case REPORT_TYPE_INCOME:
290 				column = LST_REPDIST_INCOME;
291 				break;
292 		}
293 	}
294 
295 	DB( g_print(" sort on column %d\n\n", column) );
296 
297 	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model), column, GTK_SORT_DESCENDING);
298 
299 	gtk_chart_set_color_scheme(GTK_CHART(data->RE_chart), PREFS->report_color_scheme);
300 
301 	//TRANSLATORS: example 'Expense by Category'
302 	title = g_strdup_printf(_("%s by %s"), hbtk_get_label(CYA_REPORT_TYPE,tmptype), hbtk_get_label(CYA_REPORT_SRC, tmpsrc) );
303 
304 	/* update absolute or not */
305 	gboolean abs = (tmptype == REPORT_TYPE_EXPENSE || tmptype == REPORT_TYPE_INCOME) ? TRUE : FALSE;
306 	gtk_chart_set_absolute(GTK_CHART(data->RE_chart), abs);
307 
308 	/* show xval for month/year and no by amount display */
309 	xval = FALSE;
310 
311 	if( !byamount && (tmpsrc == REPORT_SRC_MONTH || tmpsrc == REPORT_SRC_YEAR) )
312 	{
313 		xval = TRUE;
314 		/*switch( tmpsrc)
315 		{
316 			case REPORT_SRC_MONTH:
317 				gtk_chart_set_every_xval(GTK_CHART(data->RE_chart), 4);
318 				break;
319 			case REPORT_SRC_YEAR:
320 				gtk_chart_set_every_xval(GTK_CHART(data->RE_chart), 2);
321 				break;
322 		}*/
323 	}
324 
325 	gtk_chart_show_xval(GTK_CHART(data->RE_chart), xval);
326 
327 
328 	/* update bar chart */
329 	if( (tmptype == REPORT_TYPE_TOTAL) && (usrcomp == TRUE) ) //dual exp/inc
330 	{
331 		DB( g_print(" set bar to dual exp %d/inc %d\n\n", LST_REPDIST_EXPENSE, LST_REPDIST_INCOME) );
332 		gtk_chart_set_dualdatas(GTK_CHART(data->RE_chart), model, LST_REPDIST_EXPENSE, LST_REPDIST_INCOME, title, NULL);
333 	}
334 	else
335 	{
336 		// /!\ hazardous here
337 		column = LST_REPDIST_EXPENSE+(tmptype)*2;
338 		DB( g_print(" set bar to %d\n\n", column) );
339 		gtk_chart_set_datas(GTK_CHART(data->RE_chart), model, column, title, NULL);
340 	}
341 
342 
343 	g_free(title);
344 
345 }
346 
347 
repstats_update_date_widget(GtkWidget * widget,gpointer user_data)348 static void repstats_update_date_widget(GtkWidget *widget, gpointer user_data)
349 {
350 struct repstats_data *data;
351 
352 	DB( g_print("\n[repdist] update date widget\n") );
353 
354 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
355 
356 	g_signal_handler_block(data->PO_mindate, data->handler_id[HID_REPDIST_MINDATE]);
357 	g_signal_handler_block(data->PO_maxdate, data->handler_id[HID_REPDIST_MAXDATE]);
358 
359 	gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_mindate), data->filter->mindate);
360 	gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_maxdate), data->filter->maxdate);
361 
362 	g_signal_handler_unblock(data->PO_mindate, data->handler_id[HID_REPDIST_MINDATE]);
363 	g_signal_handler_unblock(data->PO_maxdate, data->handler_id[HID_REPDIST_MAXDATE]);
364 
365 }
366 
367 
repstats_update_daterange(GtkWidget * widget,gpointer user_data)368 static void repstats_update_daterange(GtkWidget *widget, gpointer user_data)
369 {
370 struct repstats_data *data;
371 gchar *daterange;
372 
373 	DB( g_print("\n[repdist] update daterange\n") );
374 
375 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
376 
377 	daterange = filter_daterange_text_get(data->filter);
378 	gtk_label_set_markup(GTK_LABEL(data->TX_daterange), daterange);
379 	g_free(daterange);
380 }
381 
repstats_update_total(GtkWidget * widget,gpointer user_data)382 static void repstats_update_total(GtkWidget *widget, gpointer user_data)
383 {
384 struct repstats_data *data;
385 //gboolean minor;
386 
387 	DB( g_print("\n[repdist] update total\n") );
388 
389 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
390 
391 	//minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor));
392 
393 	hb_label_set_colvalue(GTK_LABEL(data->TX_total[0]), data->total_expense, GLOBALS->kcur, GLOBALS->minor);
394 	hb_label_set_colvalue(GTK_LABEL(data->TX_total[1]), data->total_income, GLOBALS->kcur, GLOBALS->minor);
395 	hb_label_set_colvalue(GTK_LABEL(data->TX_total[2]), data->total_expense + data->total_income, GLOBALS->kcur, GLOBALS->minor);
396 
397 
398 }
399 
400 
repstats_export_result_clipboard(GtkWidget * widget,gpointer user_data)401 static void repstats_export_result_clipboard(GtkWidget *widget, gpointer user_data)
402 {
403 struct repstats_data *data;
404 GtkClipboard *clipboard;
405 GString *node;
406 gchar *title, *catsubcat;
407 gint tmpsrc;
408 
409 	DB( g_print("\n[repdist] export result clipboard\n") );
410 
411 	data = user_data;
412 	//data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
413 
414 	tmpsrc  = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_src));
415 
416 	//#1886299/1900281
417 	catsubcat = NULL;
418 	title = hbtk_get_label(CYA_REPORT_SRC,tmpsrc);
419 	if(tmpsrc == REPORT_SRC_SUBCATEGORY)
420 	{
421 		catsubcat = g_strjoin(":",hbtk_get_label(CYA_REPORT_SRC, REPORT_SRC_CATEGORY), hbtk_get_label(CYA_REPORT_SRC, REPORT_SRC_SUBCATEGORY), NULL);
422 		title = catsubcat;
423 	}
424 
425 	node = lst_rep_total_to_string(GTK_TREE_VIEW(data->LV_report), title, TRUE);
426 
427 	clipboard = gtk_clipboard_get_default(gdk_display_get_default());
428 	gtk_clipboard_set_text(clipboard, node->str, node->len);
429 
430 	g_string_free(node, TRUE);
431 
432 	g_free(catsubcat);
433 }
434 
435 
repstats_export_result_csv(GtkWidget * widget,gpointer user_data)436 static void repstats_export_result_csv(GtkWidget *widget, gpointer user_data)
437 {
438 struct repstats_data *data;
439 gchar *filename = NULL;
440 GString *node;
441 GIOChannel *io;
442 gchar *name, *title, *catsubcat;
443 gint tmpsrc;
444 
445 	DB( g_print("\n[repdist] export result csv\n") );
446 
447 	data = user_data;
448 	//data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
449 
450 	//tmpsrc  = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_src));
451 	tmpsrc  = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_src));
452 
453 	name = g_strdup_printf("hb-repstat_%s.csv", hbtk_get_label(CYA_REPORT_SRC,tmpsrc));
454 
455 	if( ui_file_chooser_csv(GTK_WINDOW(data->window), GTK_FILE_CHOOSER_ACTION_SAVE, &filename, name) == TRUE )
456 	{
457 		DB( g_print(" + filename is %s\n", filename) );
458 		io = g_io_channel_new_file(filename, "w", NULL);
459 		if(io != NULL)
460 		{
461 
462 			//#1886299/1900281
463 			catsubcat = NULL;
464 			title = hbtk_get_label(CYA_REPORT_SRC,tmpsrc);
465 			if(tmpsrc == REPORT_SRC_SUBCATEGORY)
466 			{
467 				catsubcat = g_strjoin(":",hbtk_get_label(CYA_REPORT_SRC, REPORT_SRC_CATEGORY), hbtk_get_label(CYA_REPORT_SRC, REPORT_SRC_SUBCATEGORY), NULL);
468 				title = catsubcat;
469 			}
470 
471 			node = lst_rep_total_to_string(GTK_TREE_VIEW(data->LV_report), title, FALSE);
472 			g_io_channel_write_chars(io, node->str, -1, NULL, NULL);
473 			g_io_channel_unref (io);
474 			g_string_free(node, TRUE);
475 			g_free(catsubcat);
476 		}
477 		g_free( filename );
478 	}
479 	g_free(name);
480 }
481 
482 
repstats_export_detail_clipboard(GtkWidget * widget,gpointer user_data)483 static void repstats_export_detail_clipboard(GtkWidget *widget, gpointer user_data)
484 {
485 struct repstats_data *data;
486 GtkClipboard *clipboard;
487 GString *node;
488 
489 	DB( g_print("\n[repdist] export detail clipboard\n") );
490 
491 	data = user_data;
492 	//data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
493 
494 	node = list_txn_to_string(GTK_TREE_VIEW(data->LV_detail), TRUE, FALSE, FALSE);
495 
496 	clipboard = gtk_clipboard_get_default(gdk_display_get_default());
497 	gtk_clipboard_set_text(clipboard, node->str, node->len);
498 
499 	g_string_free(node, TRUE);
500 }
501 
502 
repstats_export_detail_csv(GtkWidget * widget,gpointer user_data)503 static void repstats_export_detail_csv(GtkWidget *widget, gpointer user_data)
504 {
505 struct repstats_data *data;
506 gchar *filename = NULL;
507 GString *node;
508 GIOChannel *io;
509 gchar *name;
510 gint tmpsrc;
511 
512 	DB( g_print("\n[repdist] export detail csv\n") );
513 
514 	data = user_data;
515 	//data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
516 
517 	//tmpsrc  = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_src));
518 	tmpsrc  = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_src));
519 	name = g_strdup_printf("hb-repstat-detail_%s.csv", hbtk_get_label(CYA_REPORT_SRC,tmpsrc));
520 
521 	if( ui_file_chooser_csv(GTK_WINDOW(data->window), GTK_FILE_CHOOSER_ACTION_SAVE, &filename, name) == TRUE )
522 	{
523 		DB( g_print(" + filename is %s\n", filename) );
524 
525 		io = g_io_channel_new_file(filename, "w", NULL);
526 		if(io != NULL)
527 		{
528 			node = list_txn_to_string(GTK_TREE_VIEW(data->LV_detail), FALSE, FALSE, FALSE);
529 			g_io_channel_write_chars(io, node->str, -1, NULL, NULL);
530 
531 			g_io_channel_unref (io);
532 			g_string_free(node, TRUE);
533 		}
534 
535 		g_free( filename );
536 	}
537 
538 	g_free(name);
539 }
540 
541 
repstats_detail(GtkWidget * widget,gpointer user_data)542 static void repstats_detail(GtkWidget *widget, gpointer user_data)
543 {
544 struct repstats_data *data;
545 guint active = GPOINTER_TO_INT(user_data);
546 guint tmpsrc;
547 GList *list;
548 GtkTreeModel *model;
549 GtkTreeIter  iter;
550 
551 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
552 
553 	DB( g_print("\n[repdist] detail\n") );
554 
555 	/* clear and detach our model */
556 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_detail));
557 	gtk_list_store_clear (GTK_LIST_STORE(model));
558 
559 	if(data->detail)
560 	{
561 		//tmpsrc  = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_src));
562 		tmpsrc  = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_src));
563 
564 		g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
565 		gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_detail), NULL); /* Detach model from view */
566 
567 		/* fill in the model */
568 		list = g_queue_peek_head_link(data->txn_queue);
569 		while (list != NULL)
570 		{
571 		Transaction *ope = list->data;
572 		gdouble dtlamt = ope->amount;
573 
574 			if(filter_txn_match(data->filter, ope) == 1)
575 			{
576 			gboolean match = FALSE;
577 			guint i, pos = 0;
578 
579 				if( tmpsrc != REPORT_SRC_TAG )
580 				{
581 					if( (tmpsrc == REPORT_SRC_CATEGORY || tmpsrc == REPORT_SRC_SUBCATEGORY) && ope->flags & OF_SPLIT )
582 					{
583 					guint nbsplit = da_splits_length(ope->splits);
584 					Split *split;
585 
586 						dtlamt = 0.0;
587 						for(i=0;i<nbsplit;i++)
588 						{
589 							split = da_splits_get(ope->splits, i);
590 							pos = category_report_id(split->kcat, (tmpsrc == REPORT_SRC_SUBCATEGORY) ? TRUE : FALSE);
591 							if( pos == active )
592 							{
593 								match = TRUE;
594 								dtlamt += split->amount;
595 								// no more break here as we need to compute split 4 cat
596 								//break;
597 							}
598 						}
599 					}
600 					else
601 					{
602 						pos = report_items_get_pos(tmpsrc, data->filter->mindate, ope);
603 						if( pos == active )
604 						{
605 							match = TRUE;
606 						}
607 					}
608 				}
609 				else
610 				/* the TAG process is particular */
611 				{
612 					if(ope->tags != NULL)
613 					{
614 					guint32 *tptr = ope->tags;
615 
616 						while(*tptr)
617 						{
618 							pos = *tptr - 1;
619 
620 							DB( g_print(" -> storing tag %d %.2f\n", pos, ope->amount) );
621 
622 							if( pos == active )
623 							{
624 								match = TRUE;
625 								break;
626 							}
627 							tptr++;
628 						}
629 					}
630 				}
631 
632 				if( match == TRUE )
633 				{
634 					gtk_list_store_insert_with_values (GTK_LIST_STORE(model), &iter, -1,
635 						MODEL_TXN_POINTER, ope,
636 						MODEL_TXN_SPLITAMT, dtlamt,
637 						-1);
638 				}
639 			}
640 
641 			list = g_list_next(list);
642 		}
643 
644 		/* Re-attach model to view */
645 		gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_detail), model);
646 		g_object_unref(model);
647 
648 		gtk_tree_view_columns_autosize( GTK_TREE_VIEW(data->LV_detail) );
649 
650 	}
651 
652 }
653 
654 
repstats_compute(GtkWidget * widget,gpointer user_data)655 static void repstats_compute(GtkWidget *widget, gpointer user_data)
656 {
657 struct repstats_data *data;
658 DataTable *dt;
659 gint tmpsrc, tmptype, tmpintvl;
660 gdouble totexp, totinc;
661 guint n_result, n_cols;
662 guint i, n_inserted;
663 GtkTreeModel *model;
664 GtkTreeIter  iter;
665 
666 	DB( g_print("\n[repdist] compute\n") );
667 
668 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
669 
670 	//tmpsrc  = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_src));
671 	tmpsrc  = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_src));
672 	tmptype = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_type));
673 
674 	//beta
675 	tmpintvl = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_intvl));
676 
677 	g_queue_free (data->txn_queue);
678 	data->txn_queue = hbfile_transaction_get_partial(data->filter->mindate, data->filter->maxdate);
679 
680 	DB( g_print(" for=%d,kind=%d\n", tmpsrc, tmptype) );
681 	DB( g_print(" nb-txn=%d\n", g_queue_get_length (data->txn_queue) ) );
682 
683 
684 	//todo: remove this later on
685 	n_result = report_items_count(tmpsrc, data->filter->mindate, data->filter->maxdate);
686 	n_cols   = report_interval_count(tmpintvl, data->filter->mindate, data->filter->maxdate);
687 	DB( g_print(" %s :: n_result=%d, n_cols=%d\n", hbtk_get_label(CYA_REPORT_SRC,tmpsrc), n_result, n_cols) );
688 
689 //TODO: add if mode==0
690 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report));
691 	n_inserted = 0;
692 
693 	totexp = totinc = 0.0;
694 
695 	dt = report_compute_total(tmpsrc, data->filter, data->txn_queue);
696 	if(dt)
697 	{
698 
699 		data->total_expense = dt->totexp;
700 		data->total_income  = dt->totinc;
701 
702 		/* clear and detach our model */
703 		gtk_list_store_clear (GTK_LIST_STORE(model));
704 		g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
705 		gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report), NULL); /* Detach model from view */
706 
707 		DB( g_print("\npopulate total listview\n") );
708 
709 		/* insert into the treeview */
710 		for(i=0; i<n_result; i++)
711 		{
712 		DataRow *dr = dt->rows[i];
713 
714 			//DB( g_print("try to insert item %d - %.2f %.2f\n", i, dr->expense[0], dr->income[1]) );
715 
716 			/* skip empty results */
717 			if( !(tmpsrc == REPORT_SRC_MONTH || tmpsrc == REPORT_SRC_YEAR) )
718 			{
719 				if( tmptype == REPORT_TYPE_EXPENSE && !dr->expense[0] ) continue;
720 				if( tmptype == REPORT_TYPE_INCOME && !dr->income[1] ) continue;
721 				if( !dr->expense[0] && !dr->income[1] ) continue;
722 			}
723 
724 			/* skip no account */
725 			if( tmpsrc == REPORT_SRC_ACCOUNT && i == 0 )
726 				continue;
727 
728 			DB( g_printf(" insert %2d, '%s', %9.2f %9.2f %9.2f\n", i, dr->label, dr->expense[0], dr->income[1], dr->expense[0] + dr->income[1]) );
729 			n_inserted++;
730 			totexp += dr->expense[0];
731 			totinc += dr->income[1];
732 	    	gtk_list_store_insert_with_values (GTK_LIST_STORE(model), &iter, -1,
733 		        LST_REPDIST_POS, dr->pos,
734 		        LST_REPDIST_KEY, i,
735 				LST_REPDIST_NAME, dr->label,
736 				LST_REPDIST_EXPENSE, dr->expense[0],
737 				LST_REPDIST_INCOME , dr->income[1],
738 				LST_REPDIST_TOTAL, dr->expense[0] + dr->income[1],
739 				LST_REPDIST_EXPRATE, hb_rate(-dr->expense[0], -data->total_expense),
740 				LST_REPDIST_INCRATE, hb_rate(dr->income[1], data->total_income),
741 				LST_REPDIST_TOTRATE, hb_rate(-dr->expense[0] + dr->income[1], -data->total_expense + data->total_income),
742 				-1);
743 		}
744 
745 		/* update column 0 title */
746 		GtkTreeViewColumn *column = gtk_tree_view_get_column( GTK_TREE_VIEW(data->LV_report), 0);
747 		gtk_tree_view_column_set_title(column, hbtk_get_label(CYA_REPORT_SRC,tmpsrc));
748 
749 		gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_report));
750 
751 		/* Re-attach model to view */
752   		gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report), model);
753 		g_object_unref(model);
754 	}
755 
756 	da_datatable_free (dt);
757 
758 	repstats_update_total(widget,NULL);
759 
760 	//insert total
761 	if( n_inserted > 1 )
762 	{
763 
764 		gtk_list_store_insert_with_values (GTK_LIST_STORE(model), &iter, -1,
765 		    LST_REPDIST_POS, LST_REPDIST_POS_TOTAL,
766 		    LST_REPDIST_KEY, -1,
767 			LST_REPDIST_NAME, _("Total"),
768 			LST_REPDIST_EXPENSE, totexp,
769 			LST_REPDIST_INCOME , totinc,
770 			LST_REPDIST_TOTAL, totexp + totinc,
771 			-1);
772 	}
773 
774 	repstats_update(widget, user_data);
775 
776 
777 
778 
779 	/* trend with test mutlti to remove */
780 	//TODO: add if mode==1 && choose a better max column value
781 
782 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report2));
783 	gtk_tree_store_clear (GTK_TREE_STORE(model));
784 	n_inserted = 0;
785 	if( n_cols > 365*4 )
786 	{
787 
788 		lst_rep_time_renewcol(GTK_TREE_VIEW(data->LV_report2), 0, data->filter->mindate, tmpintvl);
789 
790 		ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_INFO,
791 		_("Too much columns to display"),
792 		_("Please select a wider interval and / or a narrower date range")
793 		);
794 	}
795 	else
796 	{
797 		DB( g_print("\n[repdist] compute test multi\n") );
798 
799 		if(data->trend)
800 			da_datatable_free (data->trend);
801 
802 		dt = report_compute_trend(tmpsrc, tmpintvl, data->filter, data->txn_queue);
803 		data->trend = dt;
804 
805 		DB( g_print("\npopulate time listview\n") );
806 
807 		/* clear and detach our model */
808 		g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
809 		gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report2), NULL); /* Detach model from view */
810 
811 		lst_rep_time_renewcol(GTK_TREE_VIEW(data->LV_report2), n_cols, data->filter->mindate, tmpintvl);
812 
813 		/* update column 0 title */
814 		GtkTreeViewColumn *column = gtk_tree_view_get_column( GTK_TREE_VIEW(data->LV_report2), 0);
815 		gtk_tree_view_column_set_title(column, hbtk_get_label(CYA_REPORT_SRC,tmpsrc));
816 
817 		if( tmpsrc == REPORT_SRC_SUBCATEGORY )
818 		{
819 		GList *l, *clist = category_glist_sorted(1);
820 
821 			l = g_list_first(clist);
822 			while(l !=  NULL)
823 			{
824 			Category *cat = l->data;
825 
826 				if(cat)
827 				{
828 				DataRow *dr = dt->rows[cat->key];
829 				gdouble total = dr->expense[dt->nbcols+2]+dr->income[dt->nbcols+2];
830 
831 					DB( g_printf(" eval cat %4d:'%s' = '%s' %.2f\n", cat->key, cat->name, dr->label, total) );
832 
833 					if( total )
834 					{
835 						if( cat->parent == 0 )
836 						{
837 							DB( g_printf(" > insert\n") );
838 							n_inserted++;
839 							gtk_tree_store_insert_with_values(GTK_TREE_STORE(model), &iter, NULL, -1,
840 								LST_REPDIST2_ROW, dr,
841 								LST_REPDIST2_LABEL, dr->label,
842 								-1);
843 						}
844 						else
845 						{
846 						GtkTreeIter  iter2;
847 
848 							DB( g_printf(" > insert\n") );
849 							n_inserted++;
850 							gtk_tree_store_insert_with_values(GTK_TREE_STORE(model), &iter2, &iter, -1,
851 								LST_REPDIST2_ROW, dr,
852 								LST_REPDIST2_LABEL, dr->label,
853 								-1);
854 						}
855 					}
856 					else
857 					{
858 						DB( g_printf(" > skipped\n") );
859 					}
860 				}
861 				l = g_list_next(l);
862 			}
863 			g_list_free(clist);
864 		}
865 		else
866 		{
867 			for(i=0; i<n_result; i++)
868 			{
869 			DataRow *dr = dt->rows[i];
870 			gdouble total = dr->expense[dt->nbcols+2]+dr->income[dt->nbcols+2];
871 
872 				DB( g_printf(" eval item %4d:'%s' %.2f\n", i, dr->label, total ) );
873 
874 				if( !total )
875 					continue;
876 
877 				DB( g_printf(" --> insert\n") );
878 				n_inserted++;
879 				gtk_tree_store_insert_with_values(GTK_TREE_STORE(model), &iter, NULL, -1,
880 					LST_REPDIST2_ROW, dr,
881 					LST_REPDIST2_LABEL, dr->label,
882 					-1);
883 			}
884 		}
885 
886 		//insert total
887 		if( n_inserted > 1 )
888 		{
889 		DataRow *dr = dt->totrow;
890 		//gdouble total = dr->expense[dt->nbcols+2]+dr->income[dt->nbcols+2];
891 
892 			dr->pos = LST_REPDIST_POS_TOTAL;
893 
894 			DB( g_printf(" eval item total:'%s' %.2f\n", dr->label, total ) );
895 
896 			DB( g_printf(" --> insert total\n") );
897 			n_inserted++;
898 			gtk_tree_store_insert_with_values(GTK_TREE_STORE(model), &iter, NULL, -1,
899 				LST_REPDIST2_POS, LST_REPDIST_POS_TOTAL,
900 				LST_REPDIST2_ROW, dr,
901 				LST_REPDIST2_LABEL, _("Total"),
902 				-1);
903 		}
904 
905 		/* Re-attach model to view */
906 		gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report2), model);
907 		g_object_unref(model);
908 
909 		gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model), LST_REPDIST2_POS, GTK_SORT_DESCENDING);
910 
911 
912 		/* test liststore */
913 		//liststore_benchmark();
914 
915 		/* test multi end */
916 	}
917 
918 }
919 
920 
921 /*
922 ** update visibility/sensitivity
923 */
repstats_sensitive(GtkWidget * widget,gpointer user_data)924 static void repstats_sensitive(GtkWidget *widget, gpointer user_data)
925 {
926 struct repstats_data *data;
927 gboolean visible, sensitive;
928 gint mode, type, page;
929 
930 	DB( g_print("\n[repdist] sensitive\n") );
931 
932 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
933 
934 	mode = hbtk_radio_button_get_active(GTK_CONTAINER(data->RA_mode));
935 	type = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_type));
936 	page = gtk_notebook_get_current_page(GTK_NOTEBOOK(data->GR_result));
937 
938 	//total
939 	visible = mode == 0 ? TRUE : FALSE;
940 	hb_widget_visible(data->LB_type, visible);
941 	hb_widget_visible(data->CY_type, visible);
942 	hb_widget_visible(data->CM_byamount, visible);
943 	hb_widget_visible(data->CM_compare, visible);
944 	hb_widget_visible(data->BT_column, visible);
945 	hb_widget_visible(data->BT_donut, visible);
946 	hb_widget_visible(data->LB_intvl, !visible);
947 	hb_widget_visible(data->CY_intvl, !visible);
948 
949 	//zoom
950 	visible = (data->charttype == CHART_TYPE_COL) ? TRUE : FALSE;
951 	hb_widget_visible(data->LB_zoomx, visible);
952 	hb_widget_visible(data->RG_zoomx, visible);
953 
954 	//compare
955 	visible = (type == REPORT_TYPE_TOTAL) && (data->charttype == CHART_TYPE_COL) ? TRUE : FALSE;
956 	hb_widget_visible(data->CM_compare, visible);
957 
958 	visible = page == 0 ? TRUE : FALSE;
959 	hb_widget_visible (data->BT_detail, visible);
960 	hb_widget_visible (data->BT_export, visible);
961 	hb_widget_visible (data->BT_rate, visible);
962 
963 	visible = (mode==0 && page > 0) ? TRUE : FALSE;
964 	hb_widget_visible (data->BT_legend, visible);
965 	hb_widget_visible (data->BT_print, visible);
966 
967 	page = gtk_tree_model_iter_n_children(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_detail)), NULL);
968 	sensitive = ((page > 0) && data->detail) ? TRUE : FALSE;
969 	gtk_widget_set_sensitive(data->MI_detailtoclip, sensitive);
970 	gtk_widget_set_sensitive(data->MI_detailtocsv, sensitive);
971 }
972 
973 
repstats_detail_onRowActivated(GtkTreeView * treeview,GtkTreePath * path,GtkTreeViewColumn * col,gpointer userdata)974 static void repstats_detail_onRowActivated (GtkTreeView        *treeview,
975                        GtkTreePath        *path,
976                        GtkTreeViewColumn  *col,
977                        gpointer            userdata)
978 {
979 struct repstats_data *data;
980 Transaction *active_txn;
981 gboolean result;
982 
983 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(treeview), GTK_TYPE_WINDOW)), "inst_data");
984 
985 	DB( g_print ("\n[repdist] A detail row has been double-clicked!\n") );
986 
987 	active_txn = list_txn_get_active_transaction(GTK_TREE_VIEW(data->LV_detail));
988 	if(active_txn)
989 	{
990 	Transaction *old_txn, *new_txn;
991 
992 		old_txn = da_transaction_clone (active_txn);
993 		new_txn = active_txn;
994 		result = deftransaction_external_edit(GTK_WINDOW(data->window), old_txn, new_txn);
995 
996 		if(result == GTK_RESPONSE_ACCEPT)
997 		{
998 			//#1640885
999 			GLOBALS->changes_count++;
1000 			repstats_compute(data->window, NULL);
1001 		}
1002 
1003 		da_transaction_free (old_txn);
1004 	}
1005 }
1006 
1007 
repstats_update_detail(GtkWidget * widget,gpointer user_data)1008 static void repstats_update_detail(GtkWidget *widget, gpointer user_data)
1009 {
1010 struct repstats_data *data;
1011 
1012 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1013 
1014 	if(GTK_IS_TREE_VIEW(data->LV_report))
1015 	{
1016 		if(data->detail)
1017 		{
1018 		GtkTreeSelection *treeselection;
1019 		GtkTreeModel *model;
1020 		GtkTreeIter iter;
1021 		guint key;
1022 
1023 			treeselection = gtk_tree_view_get_selection (GTK_TREE_VIEW(data->LV_report));
1024 
1025 			if (gtk_tree_selection_get_selected(treeselection, &model, &iter))
1026 			{
1027 				gtk_tree_model_get(model, &iter, LST_REPDIST_KEY, &key, -1);
1028 
1029 				DB( g_print(" - active is %d\n", key) );
1030 
1031 				repstats_detail(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), GINT_TO_POINTER(key));
1032 			}
1033 
1034 
1035 
1036 			gtk_widget_show(data->GR_detail);
1037 		}
1038 		else
1039 			gtk_widget_hide(data->GR_detail);
1040 
1041 	}
1042 }
1043 
1044 
1045 
1046 
repstats_toggle_detail(GtkWidget * widget,gpointer user_data)1047 static void repstats_toggle_detail(GtkWidget *widget, gpointer user_data)
1048 {
1049 struct repstats_data *data;
1050 
1051 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1052 
1053 	data->detail ^= 1;
1054 
1055 	DB( g_print("\n[repdist] toggledetail to %d\n", data->detail) );
1056 
1057 	repstats_update_detail(widget, user_data);
1058 
1059 }
1060 
1061 /*
1062 ** change the chart legend visibility
1063 */
repstats_toggle_legend(GtkWidget * widget,gpointer user_data)1064 static void repstats_toggle_legend(GtkWidget *widget, gpointer user_data)
1065 {
1066 struct repstats_data *data;
1067 //gint active;
1068 
1069 	DB( g_print("\n[repdist] toggle legend\n") );
1070 
1071 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1072 
1073 	data->legend ^= 1;
1074 
1075 	gtk_chart_show_legend(GTK_CHART(data->RE_chart), data->legend, FALSE);
1076 	gtk_chart_queue_redraw(GTK_CHART(data->RE_chart));
1077 }
1078 
repstats_zoomx_callback(GtkWidget * widget,gpointer user_data)1079 static void repstats_zoomx_callback(GtkWidget *widget, gpointer user_data)
1080 {
1081 struct repstats_data *data;
1082 gdouble value;
1083 
1084 	DB( g_print("\n[repdist] zoomx\n") );
1085 
1086 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1087 
1088 	value = gtk_range_get_value(GTK_RANGE(data->RG_zoomx));
1089 
1090 	DB( g_print(" + scale is %.2f\n", value) );
1091 
1092 	gtk_chart_set_barw(GTK_CHART(data->RE_chart), value);
1093 
1094 }
1095 
1096 
1097 /*
1098 ** change the chart rate columns visibility
1099 */
repstats_toggle_rate(GtkWidget * widget,gpointer user_data)1100 static void repstats_toggle_rate(GtkWidget *widget, gpointer user_data)
1101 {
1102 struct repstats_data *data;
1103 GtkTreeViewColumn *column;
1104 
1105 	DB( g_print("\n[repdist] toggle rate\n") );
1106 
1107 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1108 
1109 	data->rate ^= 1;
1110 
1111 	if(GTK_IS_TREE_VIEW(data->LV_report))
1112 	{
1113 
1114 		column = gtk_tree_view_get_column (GTK_TREE_VIEW(data->LV_report), 2);
1115 		gtk_tree_view_column_set_visible(column, data->rate);
1116 
1117 		column = gtk_tree_view_get_column (GTK_TREE_VIEW(data->LV_report), 4);
1118 		gtk_tree_view_column_set_visible(column, data->rate);
1119 
1120 		column = gtk_tree_view_get_column (GTK_TREE_VIEW(data->LV_report), 6);
1121 		gtk_tree_view_column_set_visible(column, data->rate);
1122 	}
1123 
1124 }
1125 
repstats_toggle_minor(GtkWidget * widget,gpointer user_data)1126 static void repstats_toggle_minor(GtkWidget *widget, gpointer user_data)
1127 {
1128 struct repstats_data *data;
1129 
1130 	DB( g_print("\n[repdist] toggle minor\n") );
1131 
1132 	data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1133 
1134 	GLOBALS->minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor));
1135 
1136 	repstats_update_total(widget,NULL);
1137 
1138 	//hbfile_update(data->LV_acc, (gpointer)4);
1139 	gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_report));
1140 	gtk_chart_show_minor(GTK_CHART(data->RE_chart), GLOBALS->minor);
1141 	gtk_chart_queue_redraw(GTK_CHART(data->RE_chart));
1142 }
1143 
1144 
repstats_selection(GtkTreeSelection * treeselection,gpointer user_data)1145 static void repstats_selection(GtkTreeSelection *treeselection, gpointer user_data)
1146 {
1147 GtkTreeModel *model;
1148 GtkTreeIter iter;
1149 guint key = -1;
1150 
1151 	DB( g_print("\n[repdist] selection\n") );
1152 
1153 	if (gtk_tree_selection_get_selected(treeselection, &model, &iter))
1154 	{
1155 		gtk_tree_model_get(model, &iter, LST_REPDIST_KEY, &key, -1);
1156 	}
1157 
1158 	DB( g_print(" - active is %d\n", key) );
1159 
1160 	repstats_detail(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), GINT_TO_POINTER(key));
1161 	repstats_sensitive(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), NULL);
1162 }
1163 
1164 
1165 static GtkWidget *
repstats_toolbar_create(struct repstats_data * data)1166 repstats_toolbar_create(struct repstats_data *data)
1167 {
1168 GtkWidget *toolbar, *button;
1169 
1170 	toolbar = gtk_toolbar_new();
1171 
1172 	button = (GtkWidget *)gtk_radio_tool_button_new(NULL);
1173 	data->BT_list = button;
1174 	g_object_set (button, "icon-name", ICONNAME_HB_VIEW_LIST, "label", _("List"), NULL);
1175 	gtk_widget_set_tooltip_text(button, _("View results as list"));
1176 	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
1177 
1178 	button = (GtkWidget *)gtk_radio_tool_button_new_from_widget(GTK_RADIO_TOOL_BUTTON(button));
1179 	data->BT_column = button;
1180 	g_object_set (button, "icon-name", ICONNAME_HB_VIEW_COLUMN, "label", _("Column"), NULL);
1181 	gtk_widget_set_tooltip_text(button, _("View results as column"));
1182 	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
1183 
1184 	button = (GtkWidget *)gtk_radio_tool_button_new_from_widget(GTK_RADIO_TOOL_BUTTON(button));
1185 	data->BT_donut = button;
1186 	g_object_set (button, "icon-name", ICONNAME_HB_VIEW_DONUT, "label", _("Donut"), NULL);
1187 	gtk_widget_set_tooltip_text(button, _("View results as donut"));
1188 	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
1189 
1190 	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), gtk_separator_tool_item_new(), -1);
1191 
1192 	button = gtk_widget_new(GTK_TYPE_TOGGLE_TOOL_BUTTON,
1193 		"icon-name", ICONNAME_HB_OPE_SHOW,
1194 	    "label", _("Detail"),
1195 		"tooltip-text", _("Toggle detail"),
1196 		"active", PREFS->stat_showdetail,
1197 		NULL);
1198 	data->BT_detail = button;
1199 	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
1200 
1201 	button = gtk_widget_new(GTK_TYPE_TOGGLE_TOOL_BUTTON,
1202 		"icon-name", ICONNAME_HB_SHOW_LEGEND,
1203 	    "label", _("Legend"),
1204 		"tooltip-text", _("Toggle legend"),
1205 	    "active", TRUE,
1206 		NULL);
1207 	data->BT_legend = button;
1208 	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
1209 
1210 	button = gtk_widget_new(GTK_TYPE_TOGGLE_TOOL_BUTTON,
1211 		"icon-name", ICONNAME_HB_SHOW_RATE,
1212 	    "label", _("Rate"),
1213 		"tooltip-text", _("Toggle rate"),
1214 	    "active", PREFS->stat_showrate,
1215 		NULL);
1216 	data->BT_rate = button;
1217 	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(button), -1);
1218 
1219 	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), gtk_separator_tool_item_new(), -1);
1220 
1221 	button = hbtk_toolbar_add_toolbutton(GTK_TOOLBAR(toolbar), ICONNAME_HB_FILTER, _("Filter"), _("Edit filter"));
1222 	data->BT_filter = button;
1223 
1224 	button = hbtk_toolbar_add_toolbutton(GTK_TOOLBAR(toolbar), ICONNAME_HB_REFRESH, N_("Refresh"), _("Refresh results"));
1225 	data->BT_refresh = button;
1226 
1227 	GtkWidget *menu, *menuitem;
1228 
1229 	menu = gtk_menu_new ();
1230 	//gtk_widget_set_halign (menu, GTK_ALIGN_END);
1231 
1232 	menuitem = gtk_menu_item_new_with_mnemonic (_("_Result to clipboard"));
1233 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
1234 	g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (repstats_export_result_clipboard), data);
1235 
1236 	menuitem = gtk_menu_item_new_with_mnemonic (_("_Result to CSV"));
1237 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
1238 	g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (repstats_export_result_csv), data);
1239 
1240 	menuitem = gtk_menu_item_new_with_mnemonic (_("_Detail to clipboard"));
1241 	data->MI_detailtoclip = menuitem;
1242 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
1243 	g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (repstats_export_detail_clipboard), data);
1244 
1245 	menuitem = gtk_menu_item_new_with_mnemonic (_("_Detail to CSV"));
1246 	data->MI_detailtocsv = menuitem;
1247 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
1248 	g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (repstats_export_detail_csv), data);
1249 
1250 	gtk_widget_show_all (menu);
1251 
1252 
1253 
1254 	button = gtk_menu_button_new();
1255 	data->BT_export = button;
1256 	gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(button)), GTK_STYLE_CLASS_FLAT);
1257 
1258 	//gtk_menu_button_set_direction (GTK_MENU_BUTTON(widget), GTK_ARROW_DOWN);
1259 	//gtk_widget_set_halign (widget, GTK_ALIGN_END);
1260 	GtkWidget *image = gtk_image_new_from_icon_name (ICONNAME_HB_FILE_EXPORT, GTK_ICON_SIZE_LARGE_TOOLBAR);
1261 	g_object_set (button, "image", image, "popup", GTK_MENU(menu), NULL);
1262 
1263 	GtkToolItem *toolitem = gtk_tool_item_new();
1264 	gtk_container_add (GTK_CONTAINER(toolitem), button);
1265 	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(toolitem), -1);
1266 
1267 	button = hbtk_toolbar_add_toolbutton(GTK_TOOLBAR(toolbar), ICONNAME_HB_PRINT, _("Print"), _("Print"));
1268 	data->BT_print = button;
1269 
1270 
1271 	return toolbar;
1272 }
1273 
1274 
1275 //reset the filter
repstats_filter_setup(struct repstats_data * data)1276 static void repstats_filter_setup(struct repstats_data *data)
1277 {
1278 	DB( g_print("\n[repdist] reset filter\n") );
1279 
1280 	filter_reset(data->filter);
1281 	filter_preset_daterange_set(data->filter, PREFS->date_range_rep, 0);
1282 	repstats_update_date_widget(data->window, NULL);
1283 
1284 	/* 3.4 : make int transfer out of stats */
1285 	data->filter->option[FLT_GRP_TYPE] = 2;
1286 	data->filter->type = FLT_TYPE_INTXFER;
1287 
1288 }
1289 
1290 
1291 // setup default for our object/memory
repstats_window_setup(struct repstats_data * data)1292 static void repstats_window_setup(struct repstats_data *data)
1293 {
1294 	DB( g_print("\n[repdist] setup\n") );
1295 
1296 	repstats_filter_setup(data);
1297 
1298 	data->detail = PREFS->stat_showdetail;
1299 	data->legend = 1;
1300 	data->rate = PREFS->stat_showrate^1;
1301 
1302 	repstats_toggle_rate(data->window, NULL);
1303 
1304 	gtk_chart_set_smallfont (GTK_CHART(data->RE_chart), PREFS->rep_smallfont);
1305 
1306 }
1307 
1308 
repstats_window_dispose(GtkWidget * widget,GdkEvent * event,gpointer user_data)1309 static gboolean repstats_window_dispose(GtkWidget *widget, GdkEvent *event, gpointer user_data)
1310 {
1311 struct repstats_data *data = user_data;
1312 struct WinGeometry *wg;
1313 
1314 	DB( g_print("\n[repdist] dispose\n") );
1315 
1316 	/* test multi */
1317 	if(data->trend)
1318 		da_datatable_free (data->trend);
1319 
1320 
1321 	g_queue_free (data->txn_queue);
1322 
1323 	da_flt_free(data->filter);
1324 
1325 	g_free(data);
1326 
1327 	//store position and size
1328 	wg = &PREFS->sta_wg;
1329 	gtk_window_get_position(GTK_WINDOW(widget), &wg->l, &wg->t);
1330 	gtk_window_get_size(GTK_WINDOW(widget), &wg->w, &wg->h);
1331 
1332 	DB( g_print(" window: l=%d, t=%d, w=%d, h=%d\n", wg->l, wg->t, wg->w, wg->h) );
1333 
1334 
1335 
1336 	//enable define windows
1337 	GLOBALS->define_off--;
1338 	ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE));
1339 
1340 	//unref window to our open window list
1341 	GLOBALS->openwindows = g_slist_remove(GLOBALS->openwindows, widget);
1342 
1343 	return FALSE;
1344 }
1345 
1346 
1347 //allocate our object/memory
repstats_window_acquire(struct repstats_data * data)1348 static void repstats_window_acquire(struct repstats_data *data)
1349 {
1350 	DB( g_print("\n[repdist] acquire\n") );
1351 
1352 	data->txn_queue = g_queue_new ();
1353 	data->filter = da_flt_malloc();
1354 }
1355 
1356 
1357 // the window creation
repstats_window_new(void)1358 GtkWidget *repstats_window_new(void)
1359 {
1360 struct repstats_data *data;
1361 struct WinGeometry *wg;
1362 GtkWidget *window, *mainvbox, *hbox, *vbox, *notebook, *treeview, *vpaned, *sw;
1363 GtkWidget *label, *widget, *table, *entry;
1364 gint row;
1365 
1366 	DB( g_print("\n[repdist] new\n") );
1367 
1368 
1369 	data = g_malloc0(sizeof(struct repstats_data));
1370 	if(!data) return NULL;
1371 
1372 	repstats_window_acquire(data);
1373 
1374 	//disable define windows
1375 	GLOBALS->define_off++;
1376 	ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE));
1377 
1378     /* create window, etc */
1379     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1380 	data->window = window;
1381 	//ref window to our open window list
1382 	GLOBALS->openwindows = g_slist_prepend(GLOBALS->openwindows, window);
1383 
1384 	//store our window private data
1385 	g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)data);
1386 	DB( g_print(" - new window=%p, inst_data=%p\n", window, data) );
1387 
1388 	gtk_window_set_title (GTK_WINDOW (window), _("Statistics Report"));
1389 	gtk_window_set_icon_name(GTK_WINDOW (window), ICONNAME_HB_REP_STATS);
1390 
1391 
1392 	//window contents
1393 	mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1394 	gtk_container_add (GTK_CONTAINER (window), mainvbox);
1395 
1396 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
1397     gtk_box_pack_start (GTK_BOX (mainvbox), hbox, TRUE, TRUE, 0);
1398 
1399 	//control part
1400 	table = gtk_grid_new ();
1401 	gtk_widget_set_hexpand (GTK_WIDGET(table), FALSE);
1402     gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0);
1403 
1404 	gtk_container_set_border_width (GTK_CONTAINER (table), SPACING_SMALL);
1405 	gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_SMALL);
1406 	gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_MEDIUM);
1407 
1408 	row = 0;
1409 	label = make_label_group(_("Display"));
1410 	gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
1411 
1412 	row++;
1413 	label = make_label_widget(_("Mode:"));
1414 	gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1415 	widget = hbtk_radio_button_new(GTK_ORIENTATION_HORIZONTAL, CYA_REPORT_MODE, TRUE);
1416 	data->RA_mode = widget;
1417 	gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1418 
1419 	row++;
1420 	label = make_label_widget(_("_View by:"));
1421 	gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1422 	//widget = make_cycle(label, CYA_REPORT_SRC);
1423 	widget = hbtk_combo_box_new_with_data(label, CYA_REPORT_SRC);
1424 	data->CY_src = widget;
1425 	gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1426 
1427 	row++;
1428 	label = make_label_widget(_("_Type:"));
1429 	data->LB_type = label;
1430 	gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1431 	//widget = make_cycle(label, CYA_REPORT_TXN_TYPE);
1432 	widget = hbtk_combo_box_new_with_data(label, CYA_REPORT_TYPE);
1433 	data->CY_type = widget;
1434 	gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1435 
1436 	row++;
1437 	label = make_label_widget(_("Inter_val:"));
1438 	data->LB_intvl = label;
1439 	gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1440 	//widget = make_cycle(label, CYA_REPORT_INTVL);
1441 	widget = hbtk_combo_box_new_with_data(label, CYA_REPORT_INTVL);
1442 	data->CY_intvl = widget;
1443 	gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1444 	hbtk_combo_box_set_active_id(GTK_COMBO_BOX_TEXT(data->CY_intvl), REPORT_INTVL_MONTH);
1445 
1446 	row++;
1447 	widget = gtk_check_button_new_with_mnemonic (_("Sort by _amount"));
1448 	data->CM_byamount = widget;
1449 	gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1450 
1451 	row++;
1452 	widget = gtk_check_button_new_with_mnemonic (_("Compare Exp. & Inc."));
1453 	data->CM_compare = widget;
1454 	gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1455 
1456 	row++;
1457 	label = make_label_widget(_("_Zoom X:"));
1458 	data->LB_zoomx = label;
1459 	gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1460 	widget = make_scale(label);
1461 	data->RG_zoomx = widget;
1462 	gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1463 
1464 	row++;
1465 	widget = gtk_check_button_new_with_mnemonic (_("Euro _minor"));
1466 	data->CM_minor = widget;
1467 	gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1468 
1469 /*
1470 	row++;
1471 	widget = gtk_check_button_new_with_mnemonic ("Legend");
1472 	data->CM_legend = widget;
1473 	gtk_grid_attach (GTK_GRID (table), widget, 1, 2, row, row+1);
1474 */
1475 
1476 	//quick date
1477 	row++;
1478 	widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
1479 	gtk_grid_attach (GTK_GRID (table), widget, 0, row, 3, 1);
1480 
1481 	row++;
1482 	label = make_label_group(_("Date filter"));
1483 	gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
1484 
1485 	row++;
1486 	label = make_label_widget(_("_Range:"));
1487 	gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1488 	data->CY_range = make_daterange(label, DATE_RANGE_CUSTOM_DISABLE);
1489 	gtk_grid_attach (GTK_GRID (table), data->CY_range, 2, row, 1, 1);
1490 
1491 	row++;
1492 	label = make_label_widget(_("_From:"));
1493 	gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1494 	data->PO_mindate = gtk_date_entry_new(label);
1495 	gtk_grid_attach (GTK_GRID (table), data->PO_mindate, 2, row, 1, 1);
1496 
1497 	row++;
1498 	label = make_label_widget(_("_To:"));
1499 	gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1500 	data->PO_maxdate = gtk_date_entry_new(label);
1501 	gtk_grid_attach (GTK_GRID (table), data->PO_maxdate, 2, row, 1, 1);
1502 
1503 
1504 
1505 
1506 
1507 	//beta: start user filters
1508 	/*
1509 	row++;
1510 	widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
1511 	gtk_grid_attach (GTK_GRID (table), widget, 0, row, 3, 1);
1512 
1513 	row++;
1514 	label = make_label_group(_("Saved filter"));
1515 	gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
1516 
1517 	row++;
1518 	label = make_label_widget(_("_Preset:"));
1519 	gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1520 
1521 	widget = gtk_menu_button_new();
1522 	gtk_widget_set_hexpand(widget, TRUE);
1523 	gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1524 
1525 	GtkWidget *popover = gtk_popover_new(NULL);
1526 	gtk_menu_button_set_popover(GTK_MENU_BUTTON(widget), popover);
1527 
1528 	label = gtk_label_new("test popover");
1529 
1530 
1531 	gtk_widget_set_margin_start (label, SPACING_POPOVER);
1532 	gtk_widget_set_margin_end (label, SPACING_POPOVER);
1533 	gtk_widget_set_margin_top (label, SPACING_POPOVER);
1534 	gtk_widget_set_margin_bottom (label, SPACING_POPOVER);
1535 
1536 	gtk_container_add (GTK_CONTAINER (popover), label);
1537 	gtk_widget_show_all(label);
1538 	*/
1539 	//beta: end user filters
1540 
1541 
1542 
1543 	//part: info + report
1544 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1545     gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1546 
1547 	//toolbar
1548 	widget = repstats_toolbar_create(data);
1549 	data->TB_bar = widget;
1550 	gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
1551 
1552 
1553 	//infos + total
1554 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
1555 	gtk_container_set_border_width (GTK_CONTAINER(hbox), SPACING_SMALL);
1556     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1557 
1558 	widget = make_label(NULL, 0.5, 0.5);
1559 	gimp_label_set_attributes (GTK_LABEL (widget), PANGO_ATTR_SCALE,  PANGO_SCALE_SMALL, -1);
1560 	data->TX_daterange = widget;
1561 	gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
1562 
1563 	entry = gtk_label_new(NULL);
1564 	data->TX_total[2] = entry;
1565 	gtk_box_pack_end (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
1566 	label = gtk_label_new(_("Total:"));
1567 	gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1568 
1569 	entry = gtk_label_new(NULL);
1570 	data->TX_total[1] = entry;
1571 	gtk_box_pack_end (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
1572 	label = gtk_label_new(_("Income:"));
1573 	gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1574 
1575 
1576 	entry = gtk_label_new(NULL);
1577 	data->TX_total[0] = entry;
1578 	gtk_box_pack_end (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
1579 	label = gtk_label_new(_("Expense:"));
1580 	gtk_box_pack_end (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1581 
1582 
1583 	/* report area */
1584 	notebook = gtk_notebook_new();
1585 	data->GR_result = notebook;
1586 	gtk_widget_show(notebook);
1587 	gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
1588 	gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
1589     gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
1590 
1591 	// page list/detail
1592 	vpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
1593 	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vpaned, NULL);
1594 
1595 	// list
1596 	sw = gtk_scrolled_window_new (NULL, NULL);
1597 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
1598 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1599 	treeview = lst_rep_total_create();
1600 	data->LV_report = treeview;
1601 	gtk_container_add (GTK_CONTAINER(sw), treeview);
1602 	gtk_paned_pack1 (GTK_PANED(vpaned), sw, TRUE, TRUE);
1603 
1604 	//detail
1605 	sw = gtk_scrolled_window_new (NULL, NULL);
1606 	data->GR_detail = sw;
1607 	//gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW (sw), GTK_CORNER_TOP_RIGHT);
1608 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
1609 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1610 	treeview = create_list_transaction(LIST_TXN_TYPE_DETAIL, PREFS->lst_ope_columns);
1611 	data->LV_detail = treeview;
1612 	gtk_container_add (GTK_CONTAINER(sw), treeview);
1613 	gtk_paned_pack2 (GTK_PANED(vpaned), sw, TRUE, TRUE);
1614 
1615 	//page: 2d bar /pie
1616 	widget = gtk_chart_new(CHART_TYPE_COL);
1617 	data->RE_chart = widget;
1618 	gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.symbol);
1619 	gtk_chart_set_currency(GTK_CHART(widget), GLOBALS->kcur);
1620 	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), widget, NULL);
1621 
1622 
1623 	//new test multi list
1624 	widget = gtk_scrolled_window_new (NULL, NULL);
1625 	//gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW (widget), GTK_CORNER_TOP_RIGHT);
1626 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_ETCHED_IN);
1627 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1628 	treeview = lst_rep_time_create();
1629 	data->LV_report2 = treeview;
1630 	gtk_container_add (GTK_CONTAINER(widget), treeview);
1631 	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), widget, NULL);
1632 	//end test multi list
1633 
1634 
1635 
1636 	//todo: setup should move this
1637 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_minor), GLOBALS->minor);
1638 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_byamount), PREFS->stat_byamount);
1639 
1640 	hbtk_combo_box_set_active_id(GTK_COMBO_BOX_TEXT(data->CY_type), REPORT_TYPE_EXPENSE);
1641 
1642 	/* attach our minor to treeview */
1643 	g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report))), "minor", (gpointer)data->CM_minor);
1644 	g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_detail))), "minor", (gpointer)data->CM_minor);
1645 
1646 	/* signal connect */
1647     g_signal_connect (window, "delete-event", G_CALLBACK (repstats_window_dispose), (gpointer)data);
1648 
1649 	g_signal_connect (data->CM_minor, "toggled", G_CALLBACK (repstats_toggle_minor), NULL);
1650 
1651     data->handler_id[HID_REPDIST_MINDATE] = g_signal_connect (data->PO_mindate, "changed", G_CALLBACK (repstats_date_change), (gpointer)data);
1652     data->handler_id[HID_REPDIST_MAXDATE] = g_signal_connect (data->PO_maxdate, "changed", G_CALLBACK (repstats_date_change), (gpointer)data);
1653 
1654 	data->handler_id[HID_REPDIST_RANGE] = g_signal_connect (data->CY_range, "changed", G_CALLBACK (repstats_range_change), NULL);
1655 
1656     g_signal_connect (data->CY_src, "changed", G_CALLBACK (repstats_compute), (gpointer)data);
1657 
1658 	//test multi
1659 	hbtk_radio_button_connect (GTK_CONTAINER(data->RA_mode), "toggled", G_CALLBACK (repstats_action_mode_changed), (gpointer)data);
1660 
1661 	g_signal_connect (data->CY_intvl, "changed", G_CALLBACK (repstats_compute), (gpointer)data);
1662 
1663     data->handler_id[HID_REPDIST_VIEW] = g_signal_connect (data->CY_type, "changed", G_CALLBACK (repstats_compute), (gpointer)data);
1664 
1665 	g_signal_connect (data->RG_zoomx, "value-changed", G_CALLBACK (repstats_zoomx_callback), NULL);
1666 
1667 
1668 	g_signal_connect (data->CM_byamount, "toggled", G_CALLBACK (repstats_update), NULL);
1669 	g_signal_connect (data->CM_compare, "toggled", G_CALLBACK (repstats_update), NULL);
1670 
1671 	g_signal_connect (G_OBJECT (data->BT_list), "clicked", G_CALLBACK (repstats_action_viewlist), (gpointer)data);
1672 	g_signal_connect (G_OBJECT (data->BT_column), "clicked", G_CALLBACK (repstats_action_viewbar), (gpointer)data);
1673 	g_signal_connect (G_OBJECT (data->BT_donut), "clicked", G_CALLBACK (repstats_action_viewpie), (gpointer)data);
1674 	g_signal_connect (G_OBJECT (data->BT_detail), "clicked", G_CALLBACK (repstats_toggle_detail), (gpointer)data);
1675 	g_signal_connect (G_OBJECT (data->BT_legend), "clicked", G_CALLBACK (repstats_toggle_legend), (gpointer)data);
1676 	g_signal_connect (G_OBJECT (data->BT_rate), "clicked", G_CALLBACK (repstats_toggle_rate), (gpointer)data);
1677 	g_signal_connect (G_OBJECT (data->BT_filter), "clicked", G_CALLBACK (repstats_action_filter), (gpointer)data);
1678 	g_signal_connect (G_OBJECT (data->BT_refresh), "clicked", G_CALLBACK (repstats_compute), (gpointer)data);
1679 	g_signal_connect (G_OBJECT (data->BT_print), "clicked", G_CALLBACK (repstats_action_print), (gpointer)data);
1680 
1681 	//export is a menu
1682 
1683 
1684 
1685 	g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_report)), "changed", G_CALLBACK (repstats_selection), NULL);
1686 
1687 	g_signal_connect (GTK_TREE_VIEW(data->LV_detail), "row-activated", G_CALLBACK (repstats_detail_onRowActivated), NULL);
1688 
1689 	//setup, init and show window
1690 	repstats_window_setup(data);
1691 
1692 	/* toolbar */
1693 	if(PREFS->toolbar_style == 0)
1694 		gtk_toolbar_unset_style(GTK_TOOLBAR(data->TB_bar));
1695 	else
1696 		gtk_toolbar_set_style(GTK_TOOLBAR(data->TB_bar), PREFS->toolbar_style-1);
1697 
1698 
1699 	//setup, init and show window
1700 	wg = &PREFS->sta_wg;
1701 	gtk_window_move(GTK_WINDOW(window), wg->l, wg->t);
1702 	gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h);
1703 
1704 	gtk_widget_show_all (window);
1705 
1706 
1707 
1708 	//minor ?
1709 	if( PREFS->euro_active )
1710 		gtk_widget_show(data->CM_minor);
1711 	else
1712 		gtk_widget_hide(data->CM_minor);
1713 
1714 	//gtk_widget_hide(data->GR_detail);
1715 
1716 
1717 
1718 	repstats_sensitive(window, NULL);
1719 	repstats_update_detail(window, NULL);
1720 
1721 	DB( g_print("range: %d\n", PREFS->date_range_rep) );
1722 
1723 	if( PREFS->date_range_rep != 0)
1724 		hbtk_combo_box_set_active_id(GTK_COMBO_BOX_TEXT(data->CY_range), PREFS->date_range_rep);
1725 	else
1726 		repstats_compute(window, NULL);
1727 
1728 
1729 	return window;
1730 }
1731 
1732 /*
1733 ** ============================================================================
1734 */
1735 
1736 
lst_rep_total_to_string(GtkTreeView * treeview,gchar * title,gboolean clipboard)1737 static GString *lst_rep_total_to_string(GtkTreeView *treeview, gchar *title, gboolean clipboard)
1738 {
1739 GString *node;
1740 GtkTreeModel *model;
1741 GtkTreeIter	iter;
1742 gboolean valid;
1743 const gchar *format;
1744 
1745 	node = g_string_new(NULL);
1746 
1747 	// header
1748 	format = (clipboard == TRUE) ? "%s\t%s\t%s\t%s\n" : "%s;%s;%s;%s\n";
1749 	g_string_append_printf(node, format, (title == NULL) ? _("Result") : title, _("Expense"), _("Income"), _("Total"));
1750 
1751 	model = gtk_tree_view_get_model(treeview);
1752 	valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
1753 	while (valid)
1754 	{
1755 	gchar *name;
1756 	gdouble exp, inc, bal;
1757 
1758 		gtk_tree_model_get (model, &iter,
1759 			//LST_REPDIST_KEY, i,
1760 			LST_REPDIST_NAME   , &name,
1761 			LST_REPDIST_EXPENSE, &exp,
1762 			LST_REPDIST_INCOME , &inc,
1763 			LST_REPDIST_TOTAL, &bal,
1764 			-1);
1765 
1766 		format = (clipboard == TRUE) ? "%s\t%.2f\t%.2f\t%.2f\n" : "%s;%.2f;%.2f;%.2f\n";
1767 		g_string_append_printf(node, format, name, exp, inc, bal);
1768 
1769 		//leak
1770 		g_free(name);
1771 
1772 		valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
1773 	}
1774 
1775 	//DB( g_print("text is:\n%s", node->str) );
1776 
1777 	return node;
1778 }
1779 
1780 
1781 
1782 static void
lst_rep_total_name_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)1783 lst_rep_total_name_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
1784 {
1785 gint pos;
1786 gchar *text = NULL;
1787 gint weight = PANGO_WEIGHT_NORMAL;
1788 
1789 	gtk_tree_model_get(model, iter,
1790 		LST_REPDIST_POS, &pos,
1791 		LST_REPDIST_NAME, &text,
1792 		-1);
1793 
1794 	if( pos == LST_REPDIST_POS_TOTAL )
1795 	{
1796 		weight = PANGO_WEIGHT_BOLD;
1797 	}
1798 
1799 	g_object_set(renderer, "weight", weight, "text", text, NULL);
1800 
1801 	g_free(text);
1802 }
1803 
1804 
1805 
lst_rep_total_rate_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)1806 static void lst_rep_total_rate_cell_data_function (GtkTreeViewColumn *col,
1807                            GtkCellRenderer   *renderer,
1808                            GtkTreeModel      *model,
1809                            GtkTreeIter       *iter,
1810                            gpointer           user_data)
1811 {
1812 gdouble  tmp;
1813 gchar   buf[128];
1814 
1815 	gtk_tree_model_get(model, iter, GPOINTER_TO_INT(user_data), &tmp, -1);
1816 
1817 	if(tmp != 0.0)
1818 	{
1819 		g_snprintf(buf, sizeof(buf), "%.2f %%", tmp);
1820 		g_object_set(renderer, "text", buf, NULL);
1821 	}
1822 	else
1823 		g_object_set(renderer, "text", "", NULL);
1824 
1825 }
1826 
1827 
lst_rep_total_amount_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)1828 static void lst_rep_total_amount_cell_data_function (GtkTreeViewColumn *col,
1829                            GtkCellRenderer   *renderer,
1830                            GtkTreeModel      *model,
1831                            GtkTreeIter       *iter,
1832                            gpointer           user_data)
1833 {
1834 gdouble  value;
1835 gchar *color;
1836 gint pos;
1837 gint weight = PANGO_WEIGHT_NORMAL;
1838 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
1839 
1840 	gtk_tree_model_get(model, iter,
1841 		LST_REPDIST_POS, &pos,
1842 		GPOINTER_TO_INT(user_data), &value,
1843 		-1);
1844 
1845 	if( value )
1846 	{
1847 		hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, value, GLOBALS->kcur, GLOBALS->minor);
1848 
1849 		color = get_normal_color_amount(value);
1850 
1851 		if( pos == LST_REPDIST_POS_TOTAL )
1852 		{
1853 			weight = PANGO_WEIGHT_BOLD;
1854 		}
1855 
1856 		g_object_set(renderer,
1857 			"foreground",  color,
1858 			"weight", weight,
1859 			"text", buf,
1860 			NULL);	}
1861 	else
1862 	{
1863 		g_object_set(renderer, "text", "", NULL);
1864 	}
1865 }
1866 
1867 
lst_rep_total_amount_column(gchar * name,gint id)1868 static GtkTreeViewColumn *lst_rep_total_amount_column(gchar *name, gint id)
1869 {
1870 GtkTreeViewColumn  *column;
1871 GtkCellRenderer    *renderer;
1872 
1873 	column = gtk_tree_view_column_new();
1874 	gtk_tree_view_column_set_title(column, name);
1875 	renderer = gtk_cell_renderer_text_new ();
1876 	g_object_set(renderer, "xalign", 1.0, NULL);
1877 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
1878 	gtk_tree_view_column_set_cell_data_func(column, renderer, lst_rep_total_amount_cell_data_function, GINT_TO_POINTER(id), NULL);
1879 	gtk_tree_view_column_set_alignment (column, 0.5);
1880 	//gtk_tree_view_column_set_sort_column_id (column, id);
1881 	return column;
1882 }
1883 
lst_rep_total_rate_column(gint id)1884 static GtkTreeViewColumn *lst_rep_total_rate_column(gint id)
1885 {
1886 GtkTreeViewColumn  *column;
1887 GtkCellRenderer    *renderer;
1888 
1889 	column = gtk_tree_view_column_new();
1890 	gtk_tree_view_column_set_title(column, "%");
1891 	renderer = gtk_cell_renderer_text_new ();
1892 	g_object_set(renderer, "xalign", 1.0, "yalign", 1.0, "scale", 0.8, "scale-set", TRUE, NULL);
1893 
1894 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
1895 	//gtk_tree_view_column_add_attribute(column, renderer, "text", id);
1896 	gtk_tree_view_column_set_cell_data_func(column, renderer, lst_rep_total_rate_cell_data_function, GINT_TO_POINTER(id), NULL);
1897 	gtk_tree_view_column_set_alignment (column, 0.5);
1898 	//gtk_tree_view_column_set_sort_column_id (column, id);
1899 
1900 	//gtk_tree_view_column_set_visible(column, FALSE);
1901 
1902 	return column;
1903 }
1904 
1905 
lst_rep_total_compare_func(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)1906 static gint lst_rep_total_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
1907 {
1908 gint sortcol = GPOINTER_TO_INT(userdata);
1909 gint retval = 0;
1910 gint pos1, pos2;
1911 gdouble val1, val2;
1912 
1913 	gtk_tree_model_get(model, a,
1914 		LST_REPDIST_POS, &pos1,
1915 		sortcol, &val1,
1916 		-1);
1917 	gtk_tree_model_get(model, b,
1918 		LST_REPDIST_POS, &pos2,
1919 		sortcol, &val2,
1920 		-1);
1921 
1922 	//total always at bottom
1923 	if( pos1 == LST_REPDIST_POS_TOTAL )
1924 	{
1925 		retval = -1;
1926 	}
1927 	else
1928 	{
1929 		if( pos2 == LST_REPDIST_POS_TOTAL )
1930 		{
1931 			retval = 1;
1932 		}
1933 		else
1934 		{
1935 			switch(sortcol)
1936 			{
1937 				case LST_REPDIST_POS:
1938 					retval = pos2 - pos1;
1939 					//DB( g_print(" sort %3d = %3d :: %d\n", pos1, pos2, retval) );
1940 					break;
1941 				default:
1942 					retval = (ABS(val1) - ABS(val2)) > 0 ? 1 : -1;
1943 					//DB( g_print(" sort %.2f = %.2f :: %d\n", val1, val2, retval) );
1944 					break;
1945 			}
1946 		}
1947 	}
1948 
1949 	return retval;
1950 }
1951 
1952 
1953 static gboolean
lst_rep_total_selectionfunc(GtkTreeSelection * selection,GtkTreeModel * model,GtkTreePath * path,gboolean path_currently_selected,gpointer data)1954 lst_rep_total_selectionfunc(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer data)
1955 {
1956 GtkTreeIter iter;
1957 gint pos;
1958 
1959 	if(gtk_tree_model_get_iter(model, &iter, path))
1960 	{
1961 		gtk_tree_model_get(model, &iter,
1962 			LST_REPDIST_POS, &pos,
1963 			-1);
1964 
1965 		if( pos == LST_REPDIST_POS_TOTAL )
1966 			return FALSE;
1967 	}
1968 
1969 	return TRUE;
1970 }
1971 
1972 
1973 
1974 /*
1975 ** create our statistic list
1976 */
lst_rep_total_create(void)1977 static GtkWidget *lst_rep_total_create(void)
1978 {
1979 GtkListStore *store;
1980 GtkWidget *view;
1981 GtkCellRenderer    *renderer;
1982 GtkTreeViewColumn  *column;
1983 
1984 	/* create list store */
1985 	store = gtk_list_store_new(
1986 	  	NUM_LST_REPDIST,
1987 		G_TYPE_INT,			//keep for compatibility with chart
1988 	    	G_TYPE_INT,
1989 		G_TYPE_STRING,
1990 		G_TYPE_DOUBLE,
1991 		G_TYPE_DOUBLE,
1992 		G_TYPE_DOUBLE,
1993 		G_TYPE_DOUBLE,
1994 		G_TYPE_DOUBLE,
1995 		G_TYPE_DOUBLE
1996 		);
1997 
1998 	//treeview
1999 	view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
2000 	g_object_unref(store);
2001 
2002 	gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), PREFS->grid_lines);
2003 
2004 	/* column: Name */
2005 	column = gtk_tree_view_column_new();
2006 	gtk_tree_view_column_set_title(column, _("Result"));
2007 	renderer = gtk_cell_renderer_text_new ();
2008 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
2009 	gtk_tree_view_column_set_cell_data_func(column, renderer, lst_rep_total_name_cell_data_function, NULL, NULL);
2010 	//gtk_tree_view_column_add_attribute(column, renderer, "text", LST_REPDIST_NAME);
2011 	//gtk_tree_view_column_set_sort_column_id (column, LST_REPDIST_NAME);
2012 	gtk_tree_view_column_set_resizable(column, TRUE);
2013 	gtk_tree_view_column_set_alignment (column, 0.5);
2014 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2015 
2016 	/* column: Expense */
2017 	column = lst_rep_total_amount_column(_("Expense"), LST_REPDIST_EXPENSE);
2018 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2019 	column = lst_rep_total_rate_column(LST_REPDIST_EXPRATE);
2020 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2021 
2022 	/* column: Income */
2023 	column = lst_rep_total_amount_column(_("Income"), LST_REPDIST_INCOME);
2024 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2025 	column = lst_rep_total_rate_column(LST_REPDIST_INCRATE);
2026 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2027 
2028 	/* column: Total */
2029 	column = lst_rep_total_amount_column(_("Total"), LST_REPDIST_TOTAL);
2030 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2031 	column = lst_rep_total_rate_column(LST_REPDIST_TOTRATE);
2032 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2033 
2034   /* column last: empty */
2035 	column = gtk_tree_view_column_new();
2036 	gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
2037 
2038 	/* prevent selection of total */
2039 	gtk_tree_selection_set_select_function(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), lst_rep_total_selectionfunc, NULL, NULL);
2040 
2041 	/* sort */
2042 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_REPDIST_POS    , lst_rep_total_compare_func, GINT_TO_POINTER(LST_REPDIST_POS), NULL);
2043 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_REPDIST_EXPENSE, lst_rep_total_compare_func, GINT_TO_POINTER(LST_REPDIST_EXPENSE), NULL);
2044 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_REPDIST_INCOME , lst_rep_total_compare_func, GINT_TO_POINTER(LST_REPDIST_INCOME), NULL);
2045 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_REPDIST_TOTAL  , lst_rep_total_compare_func, GINT_TO_POINTER(LST_REPDIST_TOTAL), NULL);
2046 
2047 
2048 	return(view);
2049 }
2050 
2051 
2052 /*
2053 ** ============================================================================
2054 */
2055 
2056 
lst_rep_time_compare_func(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)2057 static gint lst_rep_time_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
2058 {
2059 //gint sortcol = GPOINTER_TO_INT(userdata);
2060 gint retval = 0;
2061 DataRow *dr1, *dr2;
2062 
2063 
2064 	gtk_tree_model_get(model, a,
2065 		LST_REPDIST2_ROW, &dr1,
2066 		-1);
2067 	gtk_tree_model_get(model, b,
2068 		LST_REPDIST2_ROW, &dr2,
2069 		-1);
2070 
2071 	//total always at bottom
2072 	if( dr1->pos == LST_REPDIST_POS_TOTAL )
2073 	{
2074 		retval = -1;
2075 	}
2076 	else
2077 	{
2078 		if( dr2->pos == LST_REPDIST_POS_TOTAL )
2079 		{
2080 			retval = 1;
2081 		}
2082 		else
2083 		{
2084 			retval = dr2->pos - dr1->pos;
2085 		}
2086 	}
2087 
2088 	//DB( g_print(" sort %d=%d or %.2f=%.2f :: %d\n", pos1,pos2, val1, val2, ret) );
2089 
2090     return retval;
2091   }
2092 
2093 static void
lst_rep_time_name_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)2094 lst_rep_time_name_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
2095 {
2096 gint pos;
2097 gchar *text = NULL;
2098 gint weight = PANGO_WEIGHT_NORMAL;
2099 
2100 	gtk_tree_model_get(model, iter,
2101 		LST_REPDIST2_POS, &pos,
2102 		LST_REPDIST2_LABEL, &text,
2103 		-1);
2104 
2105 	if( pos == LST_REPDIST_POS_TOTAL )
2106 	{
2107 		weight = PANGO_WEIGHT_BOLD;
2108 	}
2109 
2110 	g_object_set(renderer, "weight", weight, "text", text, NULL);
2111 
2112 	g_free(text);
2113 }
2114 
2115 
lst_rep_time_amount_cell_data_function(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer user_data)2116 static void lst_rep_time_amount_cell_data_function (GtkTreeViewColumn *col,
2117                            GtkCellRenderer   *renderer,
2118                            GtkTreeModel      *model,
2119                            GtkTreeIter       *iter,
2120                            gpointer           user_data)
2121 {
2122 DataRow *dr;
2123 gchar *color;
2124 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
2125 gint colid = GPOINTER_TO_INT(user_data);
2126 gint weight = PANGO_WEIGHT_NORMAL;
2127 gint pos;
2128 
2129 
2130 	gtk_tree_model_get(model, iter,
2131 		LST_REPDIST2_POS, &pos,
2132 		LST_REPDIST2_ROW, &dr,
2133 	    -1);
2134 
2135 	if( dr != NULL )
2136 	{
2137 	gdouble value = dr->expense[colid]+dr->income[colid];
2138 
2139 		if( value )
2140 		{
2141 			hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, value, GLOBALS->kcur, GLOBALS->minor);
2142 			color = get_normal_color_amount(value);
2143 
2144 			if( pos == LST_REPDIST_POS_TOTAL )
2145 			{
2146 				weight = PANGO_WEIGHT_BOLD;
2147 			}
2148 
2149 			g_object_set(renderer,
2150 				"foreground",  color,
2151 				"weight", weight,
2152 				"text", buf,
2153 				NULL);
2154 			return;
2155 		}
2156 	}
2157 
2158 	g_object_set(renderer, "text", "", NULL);
2159 
2160 }
2161 
2162 
lst_rep_time_column_create_amount(gchar * name,gint id)2163 static GtkTreeViewColumn *lst_rep_time_column_create_amount(gchar *name, gint id)
2164 {
2165 GtkTreeViewColumn  *column;
2166 GtkCellRenderer    *renderer;
2167 
2168 	column = gtk_tree_view_column_new();
2169 	gtk_tree_view_column_set_title(column, name);
2170 	renderer = gtk_cell_renderer_text_new ();
2171 	g_object_set(renderer, "xalign", 1.0, NULL);
2172 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
2173 	gtk_tree_view_column_set_cell_data_func(column, renderer, lst_rep_time_amount_cell_data_function, GINT_TO_POINTER(id), NULL);
2174 	gtk_tree_view_column_set_alignment (column, 0.5);
2175 	//gtk_tree_view_column_set_sort_column_id (column, id);
2176 	return column;
2177 }
2178 
2179 
2180 static gboolean
lst_rep_time_selectionfunc(GtkTreeSelection * selection,GtkTreeModel * model,GtkTreePath * path,gboolean path_currently_selected,gpointer data)2181 lst_rep_time_selectionfunc(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer data)
2182 {
2183 GtkTreeIter iter;
2184 gint pos;
2185 
2186 	if(gtk_tree_model_get_iter(model, &iter, path))
2187 	{
2188 		gtk_tree_model_get(model, &iter,
2189 			LST_REPDIST2_POS, &pos,
2190 			-1);
2191 
2192 		if( pos == LST_REPDIST_POS_TOTAL )
2193 			return FALSE;
2194 	}
2195 
2196 	return TRUE;
2197 }
2198 
2199 
2200 
2201 /* test new listview */
lst_rep_time_renewcol(GtkTreeView * treeview,guint32 nbintvl,guint32 jfrom,gint intvl)2202 static void lst_rep_time_renewcol(GtkTreeView *treeview, guint32 nbintvl, guint32 jfrom, gint intvl)
2203 {
2204 GtkCellRenderer    *renderer;
2205 GtkTreeViewColumn  *column;
2206 GList *columns, *list;
2207 guint i;
2208 
2209 	/* remove all columns */
2210 	columns = gtk_tree_view_get_columns(GTK_TREE_VIEW(treeview));
2211 
2212 	//g_printf(" removing %d columns\n", g_list_length (columns));
2213 
2214 	list = g_list_first(columns);
2215 	while(list != NULL)
2216 	{
2217 	column = list->data;
2218 
2219 		//g_printf(" removing %p\n", column);
2220 		if(column)
2221 			gtk_tree_view_remove_column(treeview, column);
2222 
2223 		list = g_list_next(list);
2224 	}
2225 	g_list_free(columns);
2226 
2227 	/* column: Name */
2228 	column = gtk_tree_view_column_new();
2229 	//gtk_tree_view_column_set_title(column, _("Acc/Cat/Pay"));
2230 	//gtk_tree_view_column_set_title(column, "ItemsType (todo)");
2231 	renderer = gtk_cell_renderer_text_new ();
2232 	/*g_object_set(renderer,
2233 		"ellipsize", PANGO_ELLIPSIZE_END,
2234 	    "ellipsize-set", TRUE,
2235 	    NULL);*/
2236 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
2237 	gtk_tree_view_column_set_cell_data_func(column, renderer, lst_rep_time_name_cell_data_function, NULL, NULL);
2238 	//gtk_tree_view_column_add_attribute(column, renderer, "text", LST_REPDIST2_LABEL);
2239 	//gtk_tree_view_column_set_sort_column_id (column, LST_REPTIME_NAME);
2240 	gtk_tree_view_column_set_resizable(column, TRUE);
2241 	gtk_tree_view_column_set_alignment (column, 0.5);
2242 	gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
2243 
2244 	/* column: Amount */
2245 	for(i=0;i<nbintvl;i++)
2246 	{
2247 	gchar intvlname[64];
2248 
2249 		report_interval_snprint_name(intvlname, sizeof(intvlname)-1, intvl, jfrom, i);
2250 
2251 		column = lst_rep_time_column_create_amount(intvlname, i);
2252 		gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
2253 	}
2254 
2255 	column = lst_rep_time_column_create_amount(_("Average"), ++i);
2256 	gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
2257 
2258 	column = lst_rep_time_column_create_amount(_("Total"), ++i);
2259 	gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
2260 
2261 
2262   /* column last: empty */
2263 	column = gtk_tree_view_column_new();
2264 	gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), column);
2265 }
2266 
2267 
lst_rep_time_create(void)2268 static GtkWidget *lst_rep_time_create(void)
2269 {
2270 GtkTreeStore *store;
2271 GtkWidget *view;
2272 
2273 	/* create list store */
2274 	store = gtk_tree_store_new(
2275 	  	NUM_LST_REPDIST2,
2276 		G_TYPE_INT,		//POS
2277 	   	G_TYPE_INT,		//TYPE
2278 		G_TYPE_POINTER,	//ROW	(pointer to DataRow)
2279 		G_TYPE_STRING	//LABEL
2280 		);
2281 
2282 	//treeview
2283 	view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
2284 	g_object_unref(store);
2285 
2286 	gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), PREFS->grid_lines);
2287 
2288 	/* prevent selection of total */
2289 	gtk_tree_selection_set_select_function(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), lst_rep_time_selectionfunc, NULL, NULL);
2290 
2291 	/* sort */
2292 	gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_REPDIST2_POS    , lst_rep_time_compare_func, GINT_TO_POINTER(LST_REPDIST2_POS), NULL);
2293 	//gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_REPTIME_AMOUNT, ui_list_reptime_compare_func, GINT_TO_POINTER(LST_REPTIME_AMOUNT), NULL);
2294 
2295 
2296 	return(view);
2297 }
2298 
2299 
2300