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