]> Dogcows Code - chaz/homebank/blob - src/rep_time.c
import homebank-5.1.3
[chaz/homebank] / src / rep_time.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2017 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_time.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-account.h"
31 #include "ui-payee.h"
32 #include "ui-category.h"
33 #include "ui-filter.h"
34 #include "ui-transaction.h"
35
36
37 /****************************************************************************/
38 /* Debug macros */
39 /****************************************************************************/
40 #define MYDEBUG 0
41
42 #if MYDEBUG
43 #define DB(x) (x);
44 #else
45 #define DB(x);
46 #endif
47
48 /* our global datas */
49 extern struct HomeBank *GLOBALS;
50 extern struct Preferences *PREFS;
51
52
53 /* prototypes */
54 static void ui_reptime_action_viewlist(GtkAction *action, gpointer user_data);
55 //static void ui_reptime_action_viewcolumn(GtkAction *action, gpointer user_data);
56 static void ui_reptime_action_viewline(GtkAction *action, gpointer user_data);
57 static void ui_reptime_action_detail(GtkAction *action, gpointer user_data);
58 //static void ui_reptime_action_filter(GtkAction *action, gpointer user_data);
59 static void ui_reptime_action_refresh(GtkAction *action, gpointer user_data);
60 static void ui_reptime_action_export(GtkAction *action, gpointer user_data);
61
62 static void ui_reptime_list_set_cur(GtkTreeView *treeview, guint32 kcur);
63
64
65 static GtkActionEntry entries[] = {
66 { "List" , ICONNAME_HB_VIEW_LIST , N_("List") , NULL, N_("View results as list") , G_CALLBACK (ui_reptime_action_viewlist) },
67 { "Line" , ICONNAME_HB_VIEW_LINE , N_("Line") , NULL, N_("View results as lines") , G_CALLBACK (ui_reptime_action_viewline) },
68 // { "Column" , ICONNAME_HB_VIEW_COLUMN, N_("Column") , NULL, N_("View results as column"), G_CALLBACK (ui_reptime_action_viewcolumn) },
69
70 // { "Filter" , ICONNAME_HB_FILTER , N_("Filter") , NULL, N_("Edit the filter"), G_CALLBACK (ui_reptime_action_filter) },
71 { "Refresh" , ICONNAME_REFRESH , N_("Refresh"), NULL, N_("Refresh results"), G_CALLBACK (ui_reptime_action_refresh) },
72
73 { "Export" , ICONNAME_HB_FILE_EXPORT, N_("Export") , NULL, N_("Export as CSV"), G_CALLBACK (ui_reptime_action_export) },
74 };
75 static guint n_entries = G_N_ELEMENTS (entries);
76
77 static GtkToggleActionEntry toggle_entries[] = {
78 { "Detail", ICONNAME_HB_OPE_SHOW, /* name, icon-name */
79 N_("Detail"), NULL, /* label, accelerator */
80 N_("Toggle detail"), /* tooltip */
81 G_CALLBACK (ui_reptime_action_detail),
82 FALSE }, /* is_active */
83
84 };
85 static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries);
86
87
88 static const gchar *ui_info =
89 "<ui>"
90 " <toolbar name='ToolBar'>"
91 " <toolitem action='List'/>"
92 " <toolitem action='Line'/>"
93 //" <toolitem action='Column'/>"
94 " <separator/>"
95 " <toolitem action='Detail'/>"
96 " <separator/>"
97 //" <toolitem action='Filter'/>"
98 " <toolitem action='Refresh'/>"
99 " <separator/>"
100 " <toolitem action='Export'/>"
101 " </toolbar>"
102 "</ui>";
103
104
105 static void ui_reptime_date_change(GtkWidget *widget, gpointer user_data);
106 static void ui_reptime_range_change(GtkWidget *widget, gpointer user_data);
107 static void ui_reptime_detail(GtkWidget *widget, gpointer user_data);
108 static void ui_reptime_update(GtkWidget *widget, gpointer user_data);
109 static void ui_reptime_export_csv(GtkWidget *widget, gpointer user_data);
110 static void ui_reptime_compute(GtkWidget *widget, gpointer user_data);
111 static void ui_reptime_sensitive(GtkWidget *widget, gpointer user_data);
112 static void ui_reptime_toggle_detail(GtkWidget *widget, gpointer user_data);
113 static void ui_reptime_toggle_minor(GtkWidget *widget, gpointer user_data);
114 static void ui_reptime_update_daterange(GtkWidget *widget, gpointer user_data);
115 static GtkWidget *ui_list_reptime_create(void);
116
117 static gint ui_list_reptime_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata);
118
119
120
121 gchar *CYA_TIMESELECT[] = { N_("Account"), N_("Category"), N_("Payee"), NULL };
122
123
124
125 gchar *CYA_VIEWBY[] = { N_("Day"), N_("Week"), N_("Month"), N_("Quarter"), N_("Year"), NULL };
126
127 //extern gchar *CYA_FLT_SELECT[];
128
129 gchar *CYA_ABMONTHS[] =
130 {
131 NULL,
132 N_("Jan"),
133 N_("Feb"),
134 N_("Mar"),
135 N_("Apr"),
136 N_("May"),
137 N_("Jun"),
138 N_("Jul"),
139 N_("Aug"),
140 N_("Sep"),
141 N_("Oct"),
142 N_("Nov"),
143 N_("Dec"),
144 };
145
146 /* action functions -------------------- */
147
148 static void ui_reptime_action_viewlist(GtkAction *action, gpointer user_data)
149 {
150 struct ui_reptime_data *data = user_data;
151
152 data->charttype = CHART_TYPE_NONE;
153 gtk_notebook_set_current_page(GTK_NOTEBOOK(data->GR_result), 0);
154 ui_reptime_sensitive(data->window, NULL);
155 }
156
157 static void ui_reptime_action_viewline(GtkAction *action, gpointer user_data)
158 {
159 struct ui_reptime_data *data = user_data;
160
161 data->charttype = CHART_TYPE_LINE;
162 gtk_notebook_set_current_page(GTK_NOTEBOOK(data->GR_result), 1);
163 ui_reptime_sensitive(data->window, NULL);
164 ui_reptime_update(data->window, NULL);
165 }
166
167
168 /*static void ui_reptime_action_viewcolumn(GtkAction *action, gpointer user_data)
169 {
170 struct ui_reptime_data *data = user_data;
171
172 data->charttype = CHART_TYPE_COL;
173 gtk_notebook_set_current_page(GTK_NOTEBOOK(data->GR_result), 1);
174 ui_reptime_sensitive(data->window, NULL);
175 ui_reptime_update(data->window, NULL);
176
177 }*/
178
179
180 static void ui_reptime_action_detail(GtkAction *action, gpointer user_data)
181 {
182 struct ui_reptime_data *data = user_data;
183
184 ui_reptime_toggle_detail(data->window, NULL);
185 }
186
187 /*
188 static void ui_reptime_action_filter(GtkAction *action, gpointer user_data)
189 {
190 struct ui_reptime_data *data = user_data;
191
192 //debug
193 //create_deffilter_window(data->filter, TRUE);
194
195 if(create_deffilter_window(data->filter, TRUE) != GTK_RESPONSE_REJECT)
196 ui_reptime_compute(data->window, NULL);
197 }
198 */
199
200 static void ui_reptime_action_refresh(GtkAction *action, gpointer user_data)
201 {
202 struct ui_reptime_data *data = user_data;
203
204 ui_reptime_compute(data->window, NULL);
205 }
206
207 static void ui_reptime_action_export(GtkAction *action, gpointer user_data)
208 {
209 struct ui_reptime_data *data = user_data;
210
211 ui_reptime_export_csv(data->window, NULL);
212 }
213
214
215
216 /* ======================== */
217
218
219
220 /*
221 ** ============================================================================
222 */
223
224
225
226
227 /*
228 ** return the month list position correponding to the passed date
229 */
230 static gint DateInMonth(guint32 from, guint32 opedate)
231 {
232 GDate *date1, *date2;
233 gint pos;
234
235 //debug
236 // this return sometimes -1, -2 which is wrong
237
238 date1 = g_date_new_julian(from);
239 date2 = g_date_new_julian(opedate);
240
241 pos = ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1);
242
243 //g_print(" from=%d-%d ope=%d-%d => %d\n", g_date_get_month(date1), g_date_get_year(date1), g_date_get_month(date2), g_date_get_year(date2), pos);
244
245 g_date_free(date2);
246 g_date_free(date1);
247
248 return(pos);
249 }
250
251 static gint DateInQuarter(guint32 from, guint32 opedate)
252 {
253 GDate *date1, *date2;
254 gint pos;
255
256 //debug
257 // this return sometimes -1, -2 which is wrong
258
259 date1 = g_date_new_julian(from);
260 date2 = g_date_new_julian(opedate);
261
262 pos = (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/3;
263
264 DB( g_print(" from=%d-%d ope=%d-%d => %d\n", g_date_get_month(date1), g_date_get_year(date1), g_date_get_month(date2), g_date_get_year(date2), pos) );
265
266 g_date_free(date2);
267 g_date_free(date1);
268
269 return(pos);
270 }
271 /*
272 ** return the year list position correponding to the passed date
273 */
274 static gint DateInYear(guint32 from, guint32 opedate)
275 {
276 GDate *date;
277 gint year_from, year_ope, pos;
278
279 date = g_date_new_julian(from);
280 year_from = g_date_get_year(date);
281 g_date_set_julian(date, opedate);
282 year_ope = g_date_get_year(date);
283 g_date_free(date);
284
285 pos = year_ope - year_from;
286
287 //g_print(" from=%d ope=%d => %d\n", year_from, year_ope, pos);
288
289 return(pos);
290 }
291
292 static void ui_reptime_date_change(GtkWidget *widget, gpointer user_data)
293 {
294 struct ui_reptime_data *data;
295
296 DB( g_print("\n[reptime] date change\n") );
297
298 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
299
300 data->filter->mindate = gtk_date_entry_get_date(GTK_DATE_ENTRY(data->PO_mindate));
301 data->filter->maxdate = gtk_date_entry_get_date(GTK_DATE_ENTRY(data->PO_maxdate));
302
303 // set min/max date for both widget
304 gtk_date_entry_set_maxdate(GTK_DATE_ENTRY(data->PO_mindate), data->filter->maxdate);
305 gtk_date_entry_set_mindate(GTK_DATE_ENTRY(data->PO_maxdate), data->filter->mindate);
306
307 g_signal_handler_block(data->CY_range, data->handler_id[HID_REPTIME_RANGE]);
308 gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_range), FLT_RANGE_OTHER);
309 g_signal_handler_unblock(data->CY_range, data->handler_id[HID_REPTIME_RANGE]);
310
311 ui_reptime_compute(widget, NULL);
312 ui_reptime_update_daterange(widget, NULL);
313
314 }
315
316
317 static void ui_reptime_update_quickdate(GtkWidget *widget, gpointer user_data)
318 {
319 struct ui_reptime_data *data;
320
321 DB( g_print("\n[reptime] update quickdate\n") );
322
323 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
324
325 g_signal_handler_block(data->PO_mindate, data->handler_id[HID_REPTIME_MINDATE]);
326 g_signal_handler_block(data->PO_maxdate, data->handler_id[HID_REPTIME_MAXDATE]);
327
328 gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_mindate), data->filter->mindate);
329 gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_maxdate), data->filter->maxdate);
330
331 g_signal_handler_unblock(data->PO_mindate, data->handler_id[HID_REPTIME_MINDATE]);
332 g_signal_handler_unblock(data->PO_maxdate, data->handler_id[HID_REPTIME_MAXDATE]);
333
334 }
335
336
337 static void ui_reptime_range_change(GtkWidget *widget, gpointer user_data)
338 {
339 struct ui_reptime_data *data;
340 gint range;
341
342 DB( g_print("\n[reptime] range change\n") );
343
344 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
345
346 range = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_range));
347
348 if(range != FLT_RANGE_OTHER)
349 {
350 filter_preset_daterange_set(data->filter, range, data->accnum);
351
352 ui_reptime_update_quickdate(widget, NULL);
353
354 ui_reptime_compute(widget, NULL);
355 ui_reptime_update_daterange(widget, NULL);
356 }
357
358 }
359
360 static void ui_reptime_update_daterange(GtkWidget *widget, gpointer user_data)
361 {
362 struct ui_reptime_data *data;
363 gchar *daterange;
364
365 DB( g_print("\n[reptime] update daterange\n") );
366
367 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
368
369 daterange = filter_daterange_text_get(data->filter);
370 gtk_label_set_markup(GTK_LABEL(data->TX_daterange), daterange);
371 g_free(daterange);
372 }
373
374
375 static void ui_reptime_detail(GtkWidget *widget, gpointer user_data)
376 {
377 struct ui_reptime_data *data;
378 guint active = GPOINTER_TO_INT(user_data);
379 guint tmpfor, tmpslice;
380 gboolean showall;
381 guint32 from;
382 guint i;
383 GList *list;
384 GtkTreeModel *model;
385 GtkTreeIter iter;
386 guint32 selkey;
387
388 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
389
390 DB( g_print("\n[reptime] detail\n") );
391
392 tmpfor = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_for));
393 tmpslice = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_view));
394 showall = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_all));
395 selkey = 0;
396
397 switch(tmpfor)
398 {
399 case FOR_REPTIME_ACCOUNT:
400 selkey = ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(data->PO_acc));
401 break;
402 case FOR_REPTIME_CATEGORY:
403 selkey = ui_cat_comboboxentry_get_key(GTK_COMBO_BOX(data->PO_cat));
404 break;
405 case FOR_REPTIME_PAYEE:
406 selkey = ui_pay_comboboxentry_get_key(GTK_COMBO_BOX(data->PO_pay));
407 break;
408 }
409
410 //DB( g_print(" for=%d, view by=%d :: key=%d\n", tmpfor, tmpslice, selkey) );
411
412 //get our min max date
413 from = data->filter->mindate;
414 //to = data->filter->maxdate;
415
416 /* clear and detach our model */
417 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_detail));
418 gtk_list_store_clear (GTK_LIST_STORE(model));
419
420 if(data->detail)
421 {
422 g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
423 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_detail), NULL); /* Detach model from view */
424
425 /* fill in the model */
426 list = g_queue_peek_head_link(data->txn_queue);
427 while (list != NULL)
428 {
429 Transaction *ope = list->data;
430 guint32 pos = 0;
431 gboolean include = FALSE;
432
433 //DB( g_print(" get %s\n", ope->ope_Word) );
434
435 switch(tmpfor)
436 {
437 case FOR_REPTIME_ACCOUNT:
438 if( selkey == ope->kacc )
439 include = TRUE;
440 break;
441 case FOR_REPTIME_CATEGORY:
442 {
443 Category *catentry;
444
445 if( ope->flags & OF_SPLIT )
446 {
447 guint nbsplit = da_splits_count(ope->splits);
448 Split *split;
449
450 for(i=0;i<nbsplit;i++)
451 {
452 split = ope->splits[i];
453 catentry = da_cat_get(split->kcat);
454 if(catentry != NULL) //#1340142
455 {
456 if( selkey == catentry->parent || selkey == catentry->key )
457 include = TRUE;
458
459 }
460 }
461 }
462 else
463 {
464 catentry = da_cat_get(ope->kcat);
465 if(catentry != NULL) //#1340142
466 {
467 if( selkey == catentry->parent || selkey == catentry->key )
468 include = TRUE;
469
470 }
471 }
472 }
473 break;
474 case FOR_REPTIME_PAYEE:
475 if( selkey == ope->kpay )
476 include = TRUE;
477 break;
478 }
479
480 if( include == TRUE || showall == TRUE )
481 {
482
483 switch(tmpslice)
484 {
485 case GROUPBY_REPTIME_DAY:
486 pos = ope->date - from;
487 break;
488
489 case GROUPBY_REPTIME_WEEK:
490 pos = (ope->date - from)/7;
491 break;
492
493 case GROUPBY_REPTIME_MONTH:
494 pos = DateInMonth(from, ope->date);
495 break;
496
497 case GROUPBY_REPTIME_QUARTER:
498 pos = DateInQuarter(from, ope->date);
499 break;
500
501 case GROUPBY_REPTIME_YEAR:
502 pos = DateInYear(from, ope->date);
503 break;
504 }
505
506 DB( g_print("** pos=%d\n", pos) );
507
508 //insert
509 if( pos == active )
510 {
511
512 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
513 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
514 LST_DSPOPE_DATAS, ope,
515 -1);
516 }
517
518
519 }
520
521 list = g_list_next(list);
522 }
523
524 /* Re-attach model to view */
525 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_detail), model);
526 g_object_unref(model);
527
528 gtk_tree_view_columns_autosize( GTK_TREE_VIEW(data->LV_detail) );
529 }
530
531 }
532
533
534 static void ui_reptime_update(GtkWidget *widget, gpointer user_data)
535 {
536 struct ui_reptime_data *data;
537 GtkTreeModel *model;
538 gint page;
539 gint tmpfor;
540 gchar *title;
541 //gboolean xval;
542
543 DB( g_print("\n[reptime] update\n") );
544
545 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
546
547
548 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report));
549 //byamount = 0;
550 tmpfor = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_for));
551 //tmpslice = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_view));
552
553 // ensure not exp & inc for piechart
554 page = gtk_notebook_get_current_page(GTK_NOTEBOOK(data->GR_result));
555
556 DB( g_print(" page %d\n\n", page) );
557 //DB( g_print(" tmpslice %d\n\n", tmpslice) );
558
559
560 //column = LST_REPTIME_POS;
561 //DB( g_print(" sort on column %d\n\n", column) );
562 //gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model), column, GTK_SORT_DESCENDING);
563
564 gtk_chart_show_legend(GTK_CHART(data->RE_line), FALSE, FALSE);
565 gtk_chart_show_xval(GTK_CHART(data->RE_line), TRUE);
566
567 ////TRANSLATORS: example 'Expense by Category'
568 title = g_strdup_printf(_("%s Over Time"), _(CYA_TIMESELECT[tmpfor]) );
569 gtk_chart_set_datas(GTK_CHART(data->RE_line), model, LST_REPTIME_AMOUNT, title, NULL);
570 g_free(title);
571
572 if(page == 1)
573 {
574 DB( g_print(" change chart type to %d\n", data->charttype) );
575 gtk_chart_set_type (GTK_CHART(data->RE_line), data->charttype);
576 gtk_chart_set_showmono(GTK_CHART(data->RE_line), TRUE);
577 }
578
579 }
580
581 static void ui_reptime_export_csv(GtkWidget *widget, gpointer user_data)
582 {
583 struct ui_reptime_data *data;
584 GtkTreeModel *model;
585 GtkTreeIter iter;
586 gboolean valid;
587 gchar *filename = NULL;
588 GIOChannel *io;
589 gchar *outstr, *name;
590 gint tmpfor;
591
592 DB( g_print("\n[reptime] export csv\n") );
593
594 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
595
596 tmpfor = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_for));
597
598 name = g_strdup_printf("hb-reptime_%s.csv", CYA_TIMESELECT[tmpfor]);
599
600 if( ui_file_chooser_csv(GTK_WINDOW(data->window), GTK_FILE_CHOOSER_ACTION_SAVE, &filename, name) == TRUE )
601 {
602 DB( g_print(" + filename is %s\n", filename) );
603
604 io = g_io_channel_new_file(filename, "w", NULL);
605 if(io != NULL)
606 {
607 // header
608 outstr = g_strdup_printf("%s;%s;\n", _("Time slice"), _("Amount"));
609 g_io_channel_write_chars(io, outstr, -1, NULL, NULL);
610
611 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report));
612 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
613
614 while (valid)
615 {
616 gchar *name;
617 gdouble amount;
618
619 gtk_tree_model_get (model, &iter,
620 //LST_REPTIME_KEY, i,
621 LST_REPTIME_TITLE , &name,
622 LST_REPTIME_AMOUNT , &amount,
623
624 -1);
625
626 outstr = g_strdup_printf("%s;%.2f\n", name, amount);
627 g_io_channel_write_chars(io, outstr, -1, NULL, NULL);
628
629 DB( g_print("%s", outstr) );
630
631 g_free(outstr);
632
633 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
634 }
635
636 g_io_channel_unref (io);
637 }
638
639 g_free( filename );
640 }
641
642 g_free(name);
643
644
645 }
646
647
648 static void ui_reptime_update_for(GtkWidget *widget, gpointer user_data)
649 {
650 struct ui_reptime_data *data;
651 gint tmpfor;
652 gboolean visible;
653
654 DB( g_print("\n[reptime] update for\n") );
655
656 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
657
658 tmpfor = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_for));
659
660 visible = tmpfor == 0 ? TRUE : FALSE;
661 hb_widget_visible(data->LB_acc, visible);
662 hb_widget_visible(data->PO_acc, visible);
663
664 visible = tmpfor == 1 ? TRUE : FALSE;
665 hb_widget_visible(data->LB_cat, visible);
666 hb_widget_visible(data->PO_cat, visible);
667
668 visible = tmpfor == 2 ? TRUE : FALSE;
669 hb_widget_visible(data->LB_pay, visible);
670 hb_widget_visible(data->PO_pay, visible);
671
672 }
673
674
675
676 static void ui_reptime_for(GtkWidget *widget, gpointer user_data)
677 {
678 struct ui_reptime_data *data;
679
680 DB( g_print("\n[reptime] for\n") );
681
682 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
683
684 ui_reptime_update_for(widget, data);
685
686 ui_reptime_compute(widget, data);
687 }
688
689
690 static void ui_reptime_compute(GtkWidget *widget, gpointer user_data)
691 {
692 struct ui_reptime_data *data;
693 gint tmpfor, tmpslice;
694 guint32 from, to;
695 gboolean cumul;
696 gboolean showall;
697
698 gdouble cumulation, average;
699
700 GtkTreeModel *model;
701 GtkTreeIter iter;
702 GList *list;
703 gint id;
704 guint n_result, i;
705 GDate *date1, *date2;
706 gdouble *tmp_amount;
707 guint32 selkey;
708
709 DB( g_print("\n[reptime] compute\n") );
710
711 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
712
713 tmpfor = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_for));
714 tmpslice = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_view));
715 cumul = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_cumul));
716 showall = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_all));
717 selkey = 0;
718
719 data->accnum = 0;
720
721 switch(tmpfor)
722 {
723 case FOR_REPTIME_ACCOUNT:
724 selkey = ui_acc_comboboxentry_get_key(GTK_COMBO_BOX(data->PO_acc));
725 if(showall == FALSE)
726 data->accnum = selkey;
727 break;
728 case FOR_REPTIME_CATEGORY:
729 selkey = ui_cat_comboboxentry_get_key(GTK_COMBO_BOX(data->PO_cat));
730 break;
731 case FOR_REPTIME_PAYEE:
732 selkey = ui_pay_comboboxentry_get_key(GTK_COMBO_BOX(data->PO_pay));
733 break;
734 }
735
736 DB( g_print(" for=%d, view by=%d :: key=%d\n", tmpfor, tmpslice, selkey) );
737
738 //to remove > 5.0.2
739 //filter_preset_daterange_set(data->filter, data->filter->range, data->accnum);
740 //ui_reptime_update_quickdate(widget, NULL);
741
742 //get our min max date
743 from = data->filter->mindate;
744 to = data->filter->maxdate;
745 if(to < from) return;
746
747 g_queue_free (data->txn_queue);
748 data->txn_queue = hbfile_transaction_get_partial(data->filter->mindate, data->filter->maxdate);
749
750
751 /* count number or results */
752 switch(tmpslice)
753 {
754 case GROUPBY_REPTIME_DAY:
755 n_result = 1 + (to - from);
756 break;
757 case GROUPBY_REPTIME_WEEK:
758 n_result = 1 + ((to - from) / 7);
759 break;
760 case GROUPBY_REPTIME_MONTH:
761 date1 = g_date_new_julian(from);
762 date2 = g_date_new_julian(to);
763 n_result = 1 + ((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1);
764 g_date_free(date2);
765 g_date_free(date1);
766 break;
767 case GROUPBY_REPTIME_QUARTER:
768 date1 = g_date_new_julian(from);
769 date2 = g_date_new_julian(to);
770 n_result = 1 + (((g_date_get_year(date2) - g_date_get_year(date1)) * 12) + g_date_get_month(date2) - g_date_get_month(date1))/3;
771 g_date_free(date2);
772 g_date_free(date1);
773 break;
774 case GROUPBY_REPTIME_YEAR:
775 date1 = g_date_new_julian(from);
776 date2 = g_date_new_julian(to);
777 n_result = 1 + g_date_get_year(date2) - g_date_get_year(date1);
778 g_date_free(date2);
779 g_date_free(date1);
780 break;
781 default:
782 n_result = 0;
783 }
784
785 DB( g_print(" %s :: n_result=%d\n", CYA_TIMESELECT[tmpfor], n_result) );
786
787 /* allocate some memory */
788
789 tmp_amount = g_malloc0((n_result+2) * sizeof(gdouble));
790
791 if(tmp_amount)
792 {
793 guint32 kcur;
794
795 /* set currency */
796 kcur = GLOBALS->kcur;
797 if( (tmpfor == FOR_REPTIME_ACCOUNT) && (showall == FALSE) )
798 {
799 Account *acc = da_acc_get(selkey);
800
801 if( acc != NULL )
802 {
803 kcur = acc->kcur;
804 }
805 }
806
807 ui_reptime_list_set_cur(GTK_TREE_VIEW(data->LV_report), kcur);
808 gtk_chart_set_currency(GTK_CHART(data->RE_line), kcur);
809
810 /* compute the results */
811 list = g_queue_peek_head_link(data->txn_queue);
812 while (list != NULL)
813 {
814 Transaction *ope = list->data;
815 gboolean include = FALSE;
816
817 //debug
818 DB( g_print("** testing '%s', cat=%d==> %d\n", ope->wording, ope->kcat, filter_test(data->filter, ope)) );
819
820 // add usage of payee or category
821 switch(tmpfor)
822 {
823 case FOR_REPTIME_ACCOUNT:
824 if( selkey == ope->kacc )
825 include = TRUE;
826 break;
827 case FOR_REPTIME_CATEGORY:
828 {
829 Category *catentry;
830
831 if( ope->flags & OF_SPLIT )
832 {
833 guint nbsplit = da_splits_count(ope->splits);
834 Split *split;
835
836 for(i=0;i<nbsplit;i++)
837 {
838 split = ope->splits[i];
839 catentry = da_cat_get(split->kcat);
840 if(catentry != NULL) //#1340142
841 {
842 if( selkey == catentry->parent || selkey == catentry->key )
843 include = TRUE;
844 }
845 }
846 }
847 else
848 {
849 catentry = da_cat_get(ope->kcat);
850 if(catentry != NULL) //#1340142
851 {
852 if( selkey == catentry->parent || selkey == catentry->key )
853 include = TRUE;
854 }
855 }
856
857 }
858 break;
859 case FOR_REPTIME_PAYEE:
860 if( selkey == ope->kpay )
861 include = TRUE;
862 break;
863 }
864
865 if( include == TRUE || showall == TRUE)
866 {
867 guint32 pos = 0;
868 gdouble trn_amount;
869
870 switch(tmpslice)
871 {
872 case GROUPBY_REPTIME_DAY:
873 pos = ope->date - from;
874 break;
875
876 case GROUPBY_REPTIME_WEEK:
877 pos = (ope->date - from)/7;
878 break;
879
880 case GROUPBY_REPTIME_MONTH:
881 pos = DateInMonth(from, ope->date);
882 break;
883
884 case GROUPBY_REPTIME_QUARTER:
885 pos = DateInQuarter(from, ope->date);
886 break;
887
888 case GROUPBY_REPTIME_YEAR:
889 pos = DateInYear(from, ope->date);
890 break;
891 }
892
893 trn_amount = 0.0;
894
895 if( tmpfor == FOR_REPTIME_CATEGORY && ope->flags & OF_SPLIT )
896 {
897 guint nbsplit = da_splits_count(ope->splits);
898 Split *split;
899 Category *catentry;
900
901 for(i=0;i<nbsplit;i++)
902 {
903 split = ope->splits[i];
904 catentry = da_cat_get(split->kcat);
905 if(catentry != NULL) //#1340142
906 {
907 if( selkey == catentry->parent || selkey == catentry->key )
908 trn_amount += split->amount;
909 }
910 }
911 }
912 else
913 trn_amount = ope->amount;
914
915 trn_amount = hb_amount_base(trn_amount, ope->kcur);
916
917 DB( g_print("** pos=%d will add %.2f to \n", pos, trn_amount) );
918
919 tmp_amount[pos] += trn_amount;
920
921 }
922
923 list = g_list_next(list);
924 }
925
926 /* clear and detach our model */
927 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report));
928 gtk_list_store_clear (GTK_LIST_STORE(model));
929 g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
930 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report), NULL); /* Detach model from view */
931
932 cumulation = 0.0;
933
934 /* insert into the treeview */
935 for(i=0, id=0; i<n_result; i++)
936 {
937 gchar *name, *fullcatname;
938 gdouble value;
939 gchar buffer[64];
940 GDate *date;
941
942 name = NULL;
943 fullcatname = NULL;
944
945
946 DB( g_print("try to insert item %d\n", i) );
947
948 /* get the result name */
949 switch(tmpslice)
950 {
951 case GROUPBY_REPTIME_DAY:
952 date = g_date_new_julian (from + i);
953 g_date_strftime (buffer, 63, PREFS->date_format, date);
954 g_date_free(date);
955 name = buffer;
956 break;
957
958 case GROUPBY_REPTIME_WEEK:
959 date = g_date_new_julian(from);
960 g_date_add_days(date, i*7);
961 //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date));
962 g_snprintf(buffer, 63, "%d-%d", g_date_get_year(date), g_date_get_monday_week_of_year(date));
963 g_date_free(date);
964 name = buffer;
965 break;
966
967 case GROUPBY_REPTIME_MONTH:
968 date = g_date_new_julian(from);
969 g_date_add_months(date, i);
970 //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date));
971 g_snprintf(buffer, 63, "%d-%s", g_date_get_year(date), _(CYA_ABMONTHS[g_date_get_month(date)]));
972 g_date_free(date);
973 name = buffer;
974 break;
975
976 case GROUPBY_REPTIME_QUARTER:
977 date = g_date_new_julian(from);
978 g_date_add_months(date, i*3);
979 //g_snprintf(buffer, 63, "%d-%02d", g_date_get_year(date), g_date_get_month(date));
980 g_snprintf(buffer, 63, "%d-%d", g_date_get_year(date), ((g_date_get_month(date)-1)/3)+1);
981 g_date_free(date);
982 name = buffer;
983 break;
984
985 case GROUPBY_REPTIME_YEAR:
986 date = g_date_new_julian(from);
987 g_date_add_years(date, i);
988 g_snprintf(buffer, 63, "%d", g_date_get_year(date));
989 g_date_free(date);
990 name = buffer;
991 break;
992 }
993
994 cumulation += tmp_amount[i];
995 value = cumul == TRUE ? cumulation : tmp_amount[i];
996
997
998 //DB( g_print(" inserting %2d, '%s', %9.2f\n", i, name, value) );
999
1000 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
1001 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
1002 LST_REPTIME_POS, id++,
1003 LST_REPTIME_KEY, i,
1004 LST_REPTIME_TITLE, name,
1005 LST_REPTIME_AMOUNT, value,
1006 -1);
1007
1008 g_free(fullcatname);
1009 }
1010
1011 /* update column 0 title */
1012 GtkTreeViewColumn *column = gtk_tree_view_get_column( GTK_TREE_VIEW(data->LV_report), 0);
1013 gtk_tree_view_column_set_title(column, _(CYA_VIEWBY[tmpslice]));
1014
1015 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_report));
1016
1017 /* Re-attach model to view */
1018 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report), model);
1019 g_object_unref(model);
1020
1021 //update average
1022 {
1023 gchar *info;
1024 gchar buf[128];
1025
1026 average = cumulation / n_result;
1027
1028 hb_strfmon(buf, 127, average, kcur, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor)) );
1029
1030 ////TRANSLATORS: count of transaction in balancedrawn / count of total transaction under abalancedrawn amount threshold
1031 info = g_strdup_printf(_("Average: %s"), buf);
1032 gtk_label_set_text(GTK_LABEL(data->TX_info), info);
1033 g_free(info);
1034 }
1035 }
1036
1037 /* free our memory */
1038 g_free(tmp_amount);
1039
1040 ui_reptime_update(widget, user_data);
1041
1042 }
1043
1044
1045
1046
1047
1048 /*
1049 ** update sensitivity
1050 */
1051 static void ui_reptime_sensitive(GtkWidget *widget, gpointer user_data)
1052 {
1053 struct ui_reptime_data *data;
1054 gboolean active;
1055 gboolean sensitive;
1056 gint page;
1057
1058 DB( g_print("\n[reptime] sensitive\n") );
1059
1060 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1061
1062 active = gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_report)), NULL, NULL);
1063
1064 page = gtk_notebook_get_current_page(GTK_NOTEBOOK(data->GR_result));
1065
1066 sensitive = page == 0 ? active : FALSE;
1067 // gtk_widget_set_sensitive(data->TB_buttons[ACTION_REPBUDGET_DETAIL], sensitive);
1068 gtk_action_set_sensitive(gtk_ui_manager_get_action(data->ui, "/ToolBar/Detail"), sensitive);
1069
1070 sensitive = page == 0 ? FALSE : TRUE;
1071 gtk_widget_set_sensitive(data->LB_zoomx, sensitive);
1072 gtk_widget_set_sensitive(data->RG_zoomx, sensitive);
1073
1074 }
1075
1076
1077 static void ui_reptime_detail_onRowActivated (GtkTreeView *treeview,
1078 GtkTreePath *path,
1079 GtkTreeViewColumn *col,
1080 gpointer userdata)
1081 {
1082 struct ui_reptime_data *data;
1083 Transaction *active_txn;
1084 gboolean result;
1085
1086 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(treeview), GTK_TYPE_WINDOW)), "inst_data");
1087
1088 DB( g_print ("\n[reptime] A detail row has been double-clicked!\n") );
1089
1090 active_txn = list_txn_get_active_transaction(GTK_TREE_VIEW(data->LV_detail));
1091 if(active_txn)
1092 {
1093 Transaction *old_txn, *new_txn;
1094
1095 old_txn = da_transaction_clone (active_txn);
1096 new_txn = active_txn;
1097 result = deftransaction_external_edit(GTK_WINDOW(data->window), old_txn, new_txn);
1098
1099 if(result == GTK_RESPONSE_ACCEPT)
1100 {
1101 //#1640885
1102 GLOBALS->changes_count++;
1103 ui_reptime_compute(data->window, NULL);
1104 }
1105
1106 da_transaction_free (old_txn);
1107 }
1108 }
1109
1110
1111 static void ui_reptime_update_detail(GtkWidget *widget, gpointer user_data)
1112 {
1113 struct ui_reptime_data *data;
1114
1115 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1116
1117 if(data->detail)
1118 {
1119 GtkTreeSelection *treeselection;
1120 GtkTreeModel *model;
1121 GtkTreeIter iter;
1122 guint key;
1123
1124 treeselection = gtk_tree_view_get_selection (GTK_TREE_VIEW(data->LV_report));
1125
1126 if (gtk_tree_selection_get_selected(treeselection, &model, &iter))
1127 {
1128 gtk_tree_model_get(model, &iter, LST_REPTIME_KEY, &key, -1);
1129
1130 DB( g_print(" - active is %d\n", key) );
1131
1132 ui_reptime_detail(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), GINT_TO_POINTER(key));
1133 }
1134
1135
1136
1137 gtk_widget_show(data->GR_detail);
1138 }
1139 else
1140 gtk_widget_hide(data->GR_detail);
1141 }
1142
1143
1144
1145
1146 static void ui_reptime_toggle_detail(GtkWidget *widget, gpointer user_data)
1147 {
1148 struct ui_reptime_data *data;
1149
1150 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1151
1152 data->detail ^= 1;
1153
1154 DB( g_print("(stats) toggledetail to %d\n", data->detail) );
1155
1156 ui_reptime_update_detail(widget, user_data);
1157
1158 }
1159
1160 static void ui_reptime_zoomx_callback(GtkWidget *widget, gpointer user_data)
1161 {
1162 struct ui_reptime_data *data;
1163 gdouble value;
1164
1165 DB( g_print("\n[reptime] zoomx\n") );
1166
1167 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1168
1169 value = gtk_range_get_value(GTK_RANGE(data->RG_zoomx));
1170
1171 DB( g_print(" + scale is %.2f\n", value) );
1172
1173 gtk_chart_set_barw(GTK_CHART(data->RE_line), value);
1174
1175 }
1176
1177
1178
1179 static void ui_reptime_toggle_minor(GtkWidget *widget, gpointer user_data)
1180 {
1181 struct ui_reptime_data *data;
1182
1183 DB( g_print("\n[reptime] toggle\n") );
1184
1185 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1186
1187 GLOBALS->minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor));
1188
1189 //hbfile_update(data->LV_acc, (gpointer)4);
1190 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_report));
1191
1192 gtk_chart_show_minor(GTK_CHART(data->RE_line), GLOBALS->minor);
1193
1194 }
1195
1196
1197 static void ui_reptime_toggle_showall(GtkWidget *widget, gpointer user_data)
1198 {
1199 struct ui_reptime_data *data;
1200 gboolean showall;
1201
1202 DB( g_print("\n[reptime] toggle\n") );
1203
1204 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
1205
1206 showall = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_all));
1207
1208 gtk_widget_set_sensitive(GTK_WIDGET(data->PO_acc), showall^1);
1209 gtk_widget_set_sensitive(GTK_WIDGET(data->PO_cat), showall^1);
1210 gtk_widget_set_sensitive(GTK_WIDGET(data->PO_pay), showall^1);
1211
1212 ui_reptime_compute(widget, data);
1213
1214 }
1215
1216
1217
1218 /*
1219 **
1220 */
1221 static void ui_reptime_setup(struct ui_reptime_data *data, guint32 accnum)
1222 {
1223 DB( g_print("\n[reptime] setup\n") );
1224
1225 data->txn_queue = g_queue_new ();
1226
1227 data->filter = da_filter_malloc();
1228 filter_default_all_set(data->filter);
1229
1230 data->detail = 0;
1231
1232 /* 3.4 : make int transfer out of stats */
1233 data->filter->option[FILTER_PAYMODE] = 1;
1234 data->filter->paymode[PAYMODE_INTXFER] = FALSE;
1235
1236 filter_preset_daterange_set(data->filter, PREFS->date_range_rep, data->accnum);
1237
1238 g_signal_handler_block(data->PO_mindate, data->handler_id[HID_REPTIME_MINDATE]);
1239 g_signal_handler_block(data->PO_maxdate, data->handler_id[HID_REPTIME_MAXDATE]);
1240
1241 gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_mindate), data->filter->mindate);
1242 gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_maxdate), data->filter->maxdate);
1243
1244 g_signal_handler_unblock(data->PO_mindate, data->handler_id[HID_REPTIME_MINDATE]);
1245 g_signal_handler_unblock(data->PO_maxdate, data->handler_id[HID_REPTIME_MAXDATE]);
1246
1247
1248 DB( g_print(" populate\n") );
1249 ui_acc_comboboxentry_populate(GTK_COMBO_BOX(data->PO_acc), GLOBALS->h_acc, ACC_LST_INSERT_REPORT);
1250 if( accnum )
1251 ui_acc_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_acc), accnum);
1252 else
1253 gtk_combo_box_set_active(GTK_COMBO_BOX(data->PO_acc), 0);
1254
1255 ui_pay_comboboxentry_populate(GTK_COMBO_BOX(data->PO_pay), GLOBALS->h_pay);
1256 ui_pay_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_pay), 0);
1257
1258 ui_cat_comboboxentry_populate(GTK_COMBO_BOX(data->PO_cat), GLOBALS->h_cat);
1259 gtk_combo_box_set_active(GTK_COMBO_BOX(data->PO_cat), 0);
1260
1261 DB( g_print(" all ok\n") );
1262
1263 }
1264
1265
1266
1267 static void ui_reptime_selection(GtkTreeSelection *treeselection, gpointer user_data)
1268 {
1269 GtkTreeModel *model;
1270 GtkTreeIter iter;
1271 guint key = -1;
1272
1273 DB( g_print("\n[reptime] selection\n") );
1274
1275 if (gtk_tree_selection_get_selected(treeselection, &model, &iter))
1276 {
1277 gtk_tree_model_get(model, &iter, LST_REPTIME_KEY, &key, -1);
1278
1279 }
1280
1281 DB( g_print(" - active is %d\n", key) );
1282
1283 ui_reptime_detail(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), GINT_TO_POINTER(key));
1284 ui_reptime_sensitive(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), NULL);
1285 }
1286
1287
1288 /*
1289 **
1290 */
1291 static gboolean ui_reptime_dispose(GtkWidget *widget, GdkEvent *event, gpointer user_data)
1292 {
1293 struct ui_reptime_data *data = user_data;
1294 struct WinGeometry *wg;
1295
1296 DB( g_print("\n[reptime] dispose\n") );
1297
1298 g_queue_free (data->txn_queue);
1299
1300 da_filter_free(data->filter);
1301
1302 g_free(data);
1303
1304 //store position and size
1305 wg = &PREFS->tme_wg;
1306 gtk_window_get_position(GTK_WINDOW(widget), &wg->l, &wg->t);
1307 gtk_window_get_size(GTK_WINDOW(widget), &wg->w, &wg->h);
1308
1309 DB( g_print(" window: l=%d, t=%d, w=%d, h=%d\n", wg->l, wg->t, wg->w, wg->h) );
1310
1311
1312
1313 //enable define windows
1314 GLOBALS->define_off--;
1315 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE));
1316
1317 return FALSE;
1318 }
1319
1320 // the window creation
1321 GtkWidget *ui_reptime_window_new(guint32 accnum)
1322 {
1323 struct ui_reptime_data *data;
1324 struct WinGeometry *wg;
1325 GtkWidget *window, *mainvbox, *hbox, *vbox, *notebook, *treeview;
1326 GtkWidget *label, *widget, *table;
1327 gint row;
1328 GtkUIManager *ui;
1329 GtkActionGroup *actions;
1330 GtkAction *action;
1331 GError *error = NULL;
1332
1333 data = g_malloc0(sizeof(struct ui_reptime_data));
1334 if(!data) return NULL;
1335
1336 DB( g_print("\n[reptime] new\n") );
1337
1338
1339 //disable define windows
1340 GLOBALS->define_off++;
1341 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(2));
1342
1343 /* create window, etc */
1344 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1345 data->window = window;
1346
1347 //store our window private data
1348 g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)data);
1349
1350 gtk_window_set_title (GTK_WINDOW (window), _("Trend Time Report"));
1351
1352 //set the window icon
1353 gtk_window_set_icon_name(GTK_WINDOW (window), ICONNAME_HB_REP_TIME);
1354
1355
1356 //window contents
1357 mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1358 gtk_container_add (GTK_CONTAINER (window), mainvbox);
1359
1360 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
1361 gtk_box_pack_start (GTK_BOX (mainvbox), hbox, TRUE, TRUE, 0);
1362
1363 //control part
1364 table = gtk_grid_new ();
1365 gtk_widget_set_hexpand (GTK_WIDGET(table), FALSE);
1366 gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0);
1367
1368 gtk_container_set_border_width (GTK_CONTAINER (table), SPACING_SMALL);
1369 gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_SMALL);
1370 gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_MEDIUM);
1371
1372 row = 0;
1373 label = make_label_group(_("Display"));
1374 gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
1375
1376 row++;
1377 label = make_label_widget(_("_For:"));
1378 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1379 widget = make_cycle(label, CYA_TIMESELECT);
1380 data->CY_for = widget;
1381 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1382
1383 row++;
1384 label = make_label_widget(_("A_ccount:"));
1385 data->LB_acc = label;
1386 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1387 widget = ui_acc_comboboxentry_new(label);
1388 data->PO_acc = widget;
1389 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1390
1391 row++;
1392 label = make_label_widget(_("_Category:"));
1393 data->LB_cat = label;
1394 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1395 widget = ui_cat_comboboxentry_new(label);
1396 data->PO_cat = widget;
1397 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1398
1399 row++;
1400 label = make_label_widget(_("_Payee:"));
1401 data->LB_pay = label;
1402 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1403 widget = ui_pay_comboboxentry_new(label);
1404 data->PO_pay = widget;
1405 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1406
1407 row++;
1408 widget = gtk_check_button_new_with_mnemonic (_("Select _all"));
1409 data->CM_all = widget;
1410 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1411
1412 row++;
1413 widget = gtk_check_button_new_with_mnemonic (_("_Cumulate"));
1414 data->CM_cumul = widget;
1415 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1416
1417 row++;
1418 label = make_label_widget(_("_View by:"));
1419 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1420 widget = make_cycle(label, CYA_VIEWBY);
1421 data->CY_view = widget;
1422 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1423
1424 row++;
1425 widget = gtk_check_button_new_with_mnemonic (_("Euro _minor"));
1426 data->CM_minor = widget;
1427 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1428
1429 row++;
1430 label = make_label_widget(_("_Zoom X:"));
1431 data->LB_zoomx = label;
1432 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1433 widget = make_scale(label);
1434 data->RG_zoomx = widget;
1435 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
1436
1437
1438 row++;
1439 widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
1440 gtk_grid_attach (GTK_GRID (table), widget, 0, row, 3, 1);
1441
1442 row++;
1443 label = make_label_group(_("Date filter"));
1444 gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
1445
1446 row++;
1447 label = make_label_widget(_("_Range:"));
1448 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1449 data->CY_range = make_daterange(label, FALSE);
1450 gtk_grid_attach (GTK_GRID (table), data->CY_range, 2, row, 1, 1);
1451
1452 row++;
1453 label = make_label_widget(_("_From:"));
1454 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1455 data->PO_mindate = gtk_date_entry_new();
1456 gtk_grid_attach (GTK_GRID (table), data->PO_mindate, 2, row, 1, 1);
1457
1458 row++;
1459 label = make_label_widget(_("_To:"));
1460 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
1461 data->PO_maxdate = gtk_date_entry_new();
1462 gtk_grid_attach (GTK_GRID (table), data->PO_maxdate, 2, row, 1, 1);
1463
1464
1465 //part: info + report
1466 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1467 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1468
1469 //ui manager
1470 actions = gtk_action_group_new ("Account");
1471
1472 //as we use gettext
1473 gtk_action_group_set_translation_domain(actions, GETTEXT_PACKAGE);
1474
1475 // data to action callbacks is set here (data)
1476 gtk_action_group_add_actions (actions, entries, n_entries, data);
1477
1478 gtk_action_group_add_toggle_actions (actions,
1479 toggle_entries, n_toggle_entries,
1480 data);
1481
1482
1483 /* set which action should have priority in the toolbar */
1484 action = gtk_action_group_get_action(actions, "List");
1485 g_object_set(action, "is_important", TRUE, NULL);
1486
1487 action = gtk_action_group_get_action(actions, "Line");
1488 g_object_set(action, "is_important", TRUE, NULL);
1489
1490 /*action = gtk_action_group_get_action(actions, "Column");
1491 g_object_set(action, "is_important", TRUE, NULL);*/
1492
1493 action = gtk_action_group_get_action(actions, "Detail");
1494 g_object_set(action, "is_important", TRUE, NULL);
1495
1496 action = gtk_action_group_get_action(actions, "Refresh");
1497 g_object_set(action, "is_important", TRUE, NULL);
1498
1499
1500 ui = gtk_ui_manager_new ();
1501 gtk_ui_manager_insert_action_group (ui, actions, 0);
1502 gtk_window_add_accel_group (GTK_WINDOW (window), gtk_ui_manager_get_accel_group (ui));
1503
1504 if (!gtk_ui_manager_add_ui_from_string (ui, ui_info, -1, &error))
1505 {
1506 g_message ("building UI failed: %s", error->message);
1507 g_error_free (error);
1508 }
1509
1510 data->ui = ui;
1511 data->actions = actions;
1512
1513 //toolbar
1514 data->TB_bar = gtk_ui_manager_get_widget (ui, "/ToolBar");
1515 gtk_box_pack_start (GTK_BOX (vbox), data->TB_bar, FALSE, FALSE, 0);
1516
1517 //infos
1518 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
1519 gtk_container_set_border_width (GTK_CONTAINER(hbox), SPACING_SMALL);
1520 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1521
1522 label = gtk_label_new(NULL);
1523 data->TX_info = label;
1524 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
1525
1526 widget = make_label(NULL, 0.5, 0.5);
1527 gimp_label_set_attributes (GTK_LABEL (widget), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1);
1528 data->TX_daterange = widget;
1529 gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
1530
1531
1532
1533 notebook = gtk_notebook_new();
1534 data->GR_result = notebook;
1535 gtk_widget_show(notebook);
1536 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
1537 gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
1538
1539 gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
1540
1541 //page: list
1542 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1543 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, NULL);
1544
1545 widget = gtk_scrolled_window_new (NULL, NULL);
1546 //gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW (widget), GTK_CORNER_TOP_RIGHT);
1547 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_ETCHED_IN);
1548 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1549 treeview = ui_list_reptime_create();
1550 data->LV_report = treeview;
1551 gtk_container_add (GTK_CONTAINER(widget), treeview);
1552 gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
1553
1554 //detail
1555 widget = gtk_scrolled_window_new (NULL, NULL);
1556 data->GR_detail = widget;
1557 //gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW (widget), GTK_CORNER_TOP_RIGHT);
1558 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_ETCHED_IN);
1559 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1560 treeview = create_list_transaction(LIST_TXN_TYPE_DETAIL, PREFS->lst_ope_columns);
1561 data->LV_detail = treeview;
1562 gtk_container_add (GTK_CONTAINER(widget), treeview);
1563
1564 gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
1565
1566
1567 //page: lines
1568 widget = gtk_chart_new(CHART_TYPE_LINE);
1569 data->RE_line = widget;
1570 //gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.suffix_symbol);
1571 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), widget, NULL);
1572
1573 //todo:should move this
1574 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_minor), GLOBALS->minor);
1575
1576 gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_view), 1);
1577
1578 /* attach our minor to treeview */
1579 g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report))), "minor", (gpointer)data->CM_minor);
1580 g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_detail))), "minor", (gpointer)data->CM_minor);
1581
1582
1583
1584 /* signal connect */
1585 g_signal_connect (window, "delete-event", G_CALLBACK (ui_reptime_dispose), (gpointer)data);
1586
1587 g_signal_connect (data->CM_cumul, "toggled", G_CALLBACK (ui_reptime_compute), NULL);
1588
1589 g_signal_connect (data->CM_minor, "toggled", G_CALLBACK (ui_reptime_toggle_minor), NULL);
1590
1591 data->handler_id[HID_REPTIME_MINDATE] = g_signal_connect (data->PO_mindate, "changed", G_CALLBACK (ui_reptime_date_change), (gpointer)data);
1592 data->handler_id[HID_REPTIME_MAXDATE] = g_signal_connect (data->PO_maxdate, "changed", G_CALLBACK (ui_reptime_date_change), (gpointer)data);
1593
1594 data->handler_id[HID_REPTIME_RANGE] = g_signal_connect (data->CY_range, "changed", G_CALLBACK (ui_reptime_range_change), NULL);
1595
1596 g_signal_connect (data->CY_for, "changed", G_CALLBACK (ui_reptime_for), (gpointer)data);
1597 data->handler_id[HID_REPTIME_VIEW] = g_signal_connect (data->CY_view, "changed", G_CALLBACK (ui_reptime_compute), (gpointer)data);
1598
1599 //setup, init and show window
1600 ui_reptime_setup(data, accnum);
1601
1602 g_signal_connect (data->CM_all, "toggled", G_CALLBACK (ui_reptime_toggle_showall), NULL);
1603 g_signal_connect (data->PO_acc, "changed", G_CALLBACK (ui_reptime_compute), NULL);
1604 g_signal_connect (data->PO_cat, "changed", G_CALLBACK (ui_reptime_compute), NULL);
1605 g_signal_connect (data->PO_pay, "changed", G_CALLBACK (ui_reptime_compute), NULL);
1606
1607 g_signal_connect (data->RG_zoomx, "value-changed", G_CALLBACK (ui_reptime_zoomx_callback), NULL);
1608
1609
1610 g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_report)), "changed", G_CALLBACK (ui_reptime_selection), NULL);
1611
1612 g_signal_connect (GTK_TREE_VIEW(data->LV_detail), "row-activated", G_CALLBACK (ui_reptime_detail_onRowActivated), NULL);
1613
1614
1615 /* toolbar */
1616 if(PREFS->toolbar_style == 0)
1617 gtk_toolbar_unset_style(GTK_TOOLBAR(data->TB_bar));
1618 else
1619 gtk_toolbar_set_style(GTK_TOOLBAR(data->TB_bar), PREFS->toolbar_style-1);
1620
1621 //setup, init and show window
1622 wg = &PREFS->tme_wg;
1623 gtk_window_move(GTK_WINDOW(window), wg->l, wg->t);
1624 gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h);
1625
1626 gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_view), GROUPBY_REPTIME_MONTH);
1627
1628 gtk_widget_show_all (window);
1629
1630 //minor ?
1631 if( PREFS->euro_active )
1632 gtk_widget_show(data->CM_minor);
1633 else
1634 gtk_widget_hide(data->CM_minor);
1635
1636 ui_reptime_update_for(window, data);
1637 //gtk_widget_hide(data->GR_detail);
1638
1639
1640
1641 ui_reptime_sensitive(window, NULL);
1642 ui_reptime_update_detail(window, NULL);
1643
1644 DB( g_print("range: %d\n", PREFS->date_range_rep) );
1645
1646 if( PREFS->date_range_rep != 0)
1647 gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_range), PREFS->date_range_rep);
1648 else
1649 ui_reptime_compute(window, NULL);
1650
1651 return window;
1652 }
1653
1654 /*
1655 ** ============================================================================
1656 */
1657
1658
1659 static void ui_reptime_amount_cell_data_function (GtkTreeViewColumn *col,
1660 GtkCellRenderer *renderer,
1661 GtkTreeModel *model,
1662 GtkTreeIter *iter,
1663 gpointer user_data)
1664 {
1665 gdouble value;
1666 gchar *color;
1667 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
1668 guint32 kcur = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(gtk_tree_view_column_get_tree_view(col)), "kcur_data"));
1669
1670 gtk_tree_model_get(model, iter, GPOINTER_TO_INT(user_data), &value, -1);
1671
1672 if( value )
1673 {
1674 hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, value, kcur, GLOBALS->minor);
1675
1676 color = get_normal_color_amount(value);
1677
1678 g_object_set(renderer,
1679 "foreground", color,
1680 "text", buf,
1681 NULL); }
1682 else
1683 {
1684 g_object_set(renderer, "text", "", NULL);
1685 }
1686 }
1687
1688
1689 static GtkTreeViewColumn *amount_list_ui_reptime_column(gchar *name, gint id)
1690 {
1691 GtkTreeViewColumn *column;
1692 GtkCellRenderer *renderer;
1693
1694 column = gtk_tree_view_column_new();
1695 gtk_tree_view_column_set_title(column, name);
1696 renderer = gtk_cell_renderer_text_new ();
1697 g_object_set(renderer, "xalign", 1.0, NULL);
1698 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1699 gtk_tree_view_column_set_cell_data_func(column, renderer, ui_reptime_amount_cell_data_function, GINT_TO_POINTER(id), NULL);
1700 gtk_tree_view_column_set_alignment (column, 0.5);
1701 //gtk_tree_view_column_set_sort_column_id (column, id);
1702 return column;
1703 }
1704
1705
1706 static void ui_reptime_list_set_cur(GtkTreeView *treeview, guint32 kcur)
1707 {
1708 g_object_set_data(G_OBJECT(treeview), "kcur_data", GUINT_TO_POINTER(kcur));
1709 }
1710
1711
1712
1713 /*
1714 ** create our statistic list
1715 */
1716 static GtkWidget *ui_list_reptime_create(void)
1717 {
1718 GtkListStore *store;
1719 GtkWidget *view;
1720 GtkCellRenderer *renderer;
1721 GtkTreeViewColumn *column;
1722
1723 /* create list store */
1724 store = gtk_list_store_new(
1725 NUM_LST_REPTIME,
1726 G_TYPE_INT,
1727 G_TYPE_INT,
1728 G_TYPE_STRING,
1729 G_TYPE_DOUBLE
1730 );
1731
1732 //treeview
1733 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1734 g_object_unref(store);
1735
1736 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), PREFS->grid_lines);
1737
1738 /* column: Name */
1739 column = gtk_tree_view_column_new();
1740 gtk_tree_view_column_set_title(column, _("Time slice"));
1741 renderer = gtk_cell_renderer_text_new ();
1742 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1743 //gtk_tree_view_column_set_cell_data_func(column, renderer, ope_result_cell_data_function, NULL, NULL);
1744 gtk_tree_view_column_add_attribute(column, renderer, "text", LST_REPTIME_TITLE);
1745 //gtk_tree_view_column_set_sort_column_id (column, LST_REPTIME_NAME);
1746 gtk_tree_view_column_set_resizable(column, TRUE);
1747 gtk_tree_view_column_set_alignment (column, 0.5);
1748 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1749
1750 /* column: Amount */
1751 column = amount_list_ui_reptime_column(_("Amount"), LST_REPTIME_AMOUNT);
1752 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1753
1754 /* column last: empty */
1755 column = gtk_tree_view_column_new();
1756 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1757
1758 /* sort */
1759 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_REPTIME_POS , ui_list_reptime_compare_func, GINT_TO_POINTER(LST_REPTIME_POS), NULL);
1760 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);
1761
1762 return(view);
1763 }
1764
1765 static gint ui_list_reptime_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
1766 {
1767 gint sortcol = GPOINTER_TO_INT(userdata);
1768 gint retval = 0;
1769 gint pos1, pos2;
1770 gdouble val1, val2;
1771
1772 gtk_tree_model_get(model, a,
1773 LST_REPTIME_POS, &pos1,
1774 sortcol, &val1,
1775 -1);
1776 gtk_tree_model_get(model, b,
1777 LST_REPTIME_POS, &pos2,
1778 sortcol, &val2,
1779 -1);
1780 /*
1781 if(pos1 == -1) return(1);
1782 if(pos2 == -1) return(-1);
1783 */
1784
1785 if(sortcol == LST_REPTIME_POS)
1786 retval = pos2 - pos1;
1787 else
1788 retval = (ABS(val1) - ABS(val2)) > 0 ? 1 : -1;
1789
1790 //DB( g_print(" sort %d=%d or %.2f=%.2f :: %d\n", pos1,pos2, val1, val2, ret) );
1791
1792 return retval;
1793 }
1794
This page took 0.114914 seconds and 4 git commands to generate.