]> Dogcows Code - chaz/homebank/blob - src/rep-vehicle.c
import homebank-5.2.7
[chaz/homebank] / src / rep-vehicle.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2019 Maxime DOYEN
3 *
4 * This file is part of HomeBank.
5 *
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 #include "homebank.h"
22
23 #include "rep-vehicle.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-category.h"
31
32
33 /****************************************************************************/
34 /* Debug macros */
35 /****************************************************************************/
36 #define MYDEBUG 0
37
38 #if MYDEBUG
39 #define DB(x) (x);
40 #else
41 #define DB(x);
42 #endif
43
44 /* our global datas */
45 extern struct HomeBank *GLOBALS;
46 extern struct Preferences *PREFS;
47
48
49 /* prototypes */
50 static void repvehicle_action_refresh(GtkAction *action, gpointer user_data);
51 static void repvehicle_action_export(GtkAction *action, gpointer user_data);
52
53 static void repvehicle_export_csv(GtkWidget *widget, gpointer user_data);
54 static void repvehicle_date_change(GtkWidget *widget, gpointer user_data);
55 static void repvehicle_range_change(GtkWidget *widget, gpointer user_data);
56 static void repvehicle_compute(GtkWidget *widget, gpointer user_data);
57 static void repvehicle_update(GtkWidget *widget, gpointer user_data);
58 static void repvehicle_toggle_minor(GtkWidget *widget, gpointer user_data);
59 static void repvehicle_setup(struct repvehicle_data *data);
60 static gboolean repvehicle_window_dispose(GtkWidget *widget, GdkEvent *event, gpointer user_data);
61 static GtkWidget *create_list_repvehicle(void);
62
63
64 static GtkActionEntry entries[] = {
65 { "Refresh" , ICONNAME_HB_REFRESH , N_("Refresh"), NULL, N_("Refresh results"), G_CALLBACK (repvehicle_action_refresh) },
66
67 { "Export" , ICONNAME_HB_FILE_EXPORT, N_("Export") , NULL, N_("Export as CSV"), G_CALLBACK (repvehicle_action_export) },
68 };
69 static guint n_entries = G_N_ELEMENTS (entries);
70
71 static const gchar *ui_info =
72 "<ui>"
73 " <toolbar name='ToolBar'>"
74 " <toolitem action='Refresh'/>"
75 " <separator/>"
76 " <toolitem action='Export'/>"
77 " </toolbar>"
78 "</ui>";
79
80 static void repvehicle_date_change(GtkWidget *widget, gpointer user_data)
81 {
82 struct repvehicle_data *data;
83
84 DB( g_print("\n[vehiclecost] date change\n") );
85
86 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
87
88 data->filter->mindate = gtk_date_entry_get_date(GTK_DATE_ENTRY(data->PO_mindate));
89 data->filter->maxdate = gtk_date_entry_get_date(GTK_DATE_ENTRY(data->PO_maxdate));
90
91 // set min/max date for both widget
92 gtk_date_entry_set_maxdate(GTK_DATE_ENTRY(data->PO_mindate), data->filter->maxdate);
93 gtk_date_entry_set_mindate(GTK_DATE_ENTRY(data->PO_maxdate), data->filter->mindate);
94
95 g_signal_handler_block(data->CY_range, data->handler_id[HID_REPVEHICLE_RANGE]);
96 hbtk_combo_box_set_active_id(GTK_COMBO_BOX_TEXT(data->CY_range), FLT_RANGE_OTHER);
97 g_signal_handler_unblock(data->CY_range, data->handler_id[HID_REPVEHICLE_RANGE]);
98
99
100 repvehicle_compute(widget, NULL);
101
102 }
103
104
105 static void repvehicle_action_refresh(GtkAction *action, gpointer user_data)
106 {
107 struct repvehicle_data *data = user_data;
108
109 repvehicle_compute(data->window, NULL);
110 }
111
112 static void repvehicle_action_export(GtkAction *action, gpointer user_data)
113 {
114 struct repvehicle_data *data = user_data;
115
116 repvehicle_export_csv(data->window, NULL);
117 }
118
119
120
121 static void repvehicle_range_change(GtkWidget *widget, gpointer user_data)
122 {
123 struct repvehicle_data *data;
124 gint range;
125
126 DB( g_print("\n[vehiclecost] range change\n") );
127
128 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
129
130 range = hbtk_combo_box_get_active_id(GTK_COMBO_BOX_TEXT(data->CY_range));
131
132 if(range != FLT_RANGE_OTHER)
133 {
134 filter_preset_daterange_set(data->filter, range, 0);
135
136 g_signal_handler_block(data->PO_mindate, data->handler_id[HID_REPVEHICLE_MINDATE]);
137 g_signal_handler_block(data->PO_maxdate, data->handler_id[HID_REPVEHICLE_MAXDATE]);
138
139 gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_mindate), data->filter->mindate);
140 gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_maxdate), data->filter->maxdate);
141
142 g_signal_handler_unblock(data->PO_mindate, data->handler_id[HID_REPVEHICLE_MINDATE]);
143 g_signal_handler_unblock(data->PO_maxdate, data->handler_id[HID_REPVEHICLE_MAXDATE]);
144
145 repvehicle_compute(widget, NULL);
146 }
147 }
148
149 static gint repvehicle_transaction_compare_func(CarCost *a, CarCost *b)
150 {
151 gint retval;
152
153 //retval = (gint)(a->ope->date - b->ope->date);
154 //if( retval == 0 )
155 retval = a->meter - b->meter;
156
157 return retval;
158 }
159
160
161 //#1277622
162 static CarCost *repvehicle_eval_memofield(CarCost *item, gchar *text)
163 {
164 gchar *d, *v1, *v2;
165 gint len;
166
167 if( text != NULL)
168 {
169 len = strlen(text);
170 d = g_strstr_len(text, len, "d=");
171 v1 = g_strstr_len(text, len, "v=");
172 v2 = g_strstr_len(text, len, "v~");
173 if(d && (v1 || v2))
174 {
175 item->meter = atol(d+2);
176 if(v1)
177 {
178 item->fuel = g_strtod(v1+2, NULL);
179 item->partial = FALSE;
180 }
181 else
182 {
183 item->fuel = g_strtod(v2+2, NULL);
184 item->partial = TRUE;
185 }
186 }
187 }
188
189 return item;
190 }
191
192
193 static void repvehicle_export_csv(GtkWidget *widget, gpointer user_data)
194 {
195 struct repvehicle_data *data;
196 GtkTreeModel *model;
197 GtkTreeIter iter;
198 gboolean valid;
199 gchar *filename = NULL;
200 GIOChannel *io;
201 gchar *outstr, *name;
202
203 DB( g_print("\n[repvehicle] export csv\n") );
204
205 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
206
207 name = "hb-vehicle.csv";
208
209 if( ui_file_chooser_csv(GTK_WINDOW(data->window), GTK_FILE_CHOOSER_ACTION_SAVE, &filename, name) == TRUE )
210 {
211 DB( g_print(" + filename is %s\n", filename) );
212
213 io = g_io_channel_new_file(filename, "w", NULL);
214 if(io != NULL)
215 {
216 // header
217 outstr = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s;%s\n",
218 _("Date"),
219 _("Meter"),
220 _("Fuel"),
221 _("Price"),
222 _("Amount"),
223 _("Dist."),
224 PREFS->vehicle_unit_100,
225 PREFS->vehicle_unit_distbyvol
226 );
227 g_io_channel_write_chars(io, outstr, -1, NULL, NULL);
228
229
230 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report));
231 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
232 while (valid)
233 {
234 guint32 julian;
235 gint meter, dist, distbyvol;
236 gdouble fuel, price, amount, centkm;
237 gboolean partial;
238 gchar datebuf[16];
239
240 gtk_tree_model_get (model, &iter,
241 LST_CAR_DATE , &julian,
242 LST_CAR_METER , &meter,
243 LST_CAR_FUEL , &fuel,
244 LST_CAR_PRICE , &price,
245 LST_CAR_AMOUNT , &amount,
246 LST_CAR_DIST , &dist,
247 LST_CAR_100KM , &centkm,
248 LST_CAR_DISTBYVOL, &distbyvol,
249 LST_CAR_PARTIAL, &partial,
250 -1);
251
252 hb_sprint_date(datebuf, julian);
253
254 outstr = g_strdup_printf("%s;%d;%.2f;%.2f;%.2f;%d;%.2f;%d;%d\n",
255 datebuf, meter, fuel, price, amount, dist, centkm, distbyvol, partial);
256 g_io_channel_write_chars(io, outstr, -1, NULL, NULL);
257
258 DB( g_print("%s", outstr) );
259
260 g_free(outstr);
261
262 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
263 }
264
265 g_io_channel_unref (io);
266 }
267
268 g_free( filename );
269 }
270 }
271
272
273 static void repvehicle_compute(GtkWidget *widget, gpointer user_data)
274 {
275 struct repvehicle_data *data;
276 GList *list;
277 guint32 catkey;
278
279 DB( g_print("\n[vehiclecost] compute\n") );
280
281 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
282
283 // clear the glist
284 da_vehiclecost_destroy(data->vehicle_list);
285 data->vehicle_list = NULL;
286
287 // get the category key
288 catkey = ui_cat_comboboxentry_get_key(GTK_COMBO_BOX(data->PO_cat));
289
290 /* do nothing if cat is 0 */
291 if( catkey == 0 )
292 goto end1;
293
294 DB( g_print(" -> active cat is %d\n", catkey) );
295
296 g_queue_free (data->txn_queue);
297 data->txn_queue = hbfile_transaction_get_partial(data->filter->mindate, data->filter->maxdate);
298
299 // collect transactions
300 // the purpose here is to collect all cat transaction
301 // and precompute item-> meter/fuel/partial
302 list = g_queue_peek_head_link(data->txn_queue);
303 while (list != NULL)
304 {
305 Transaction *ope = list->data;
306 Category *cat;
307 CarCost *item;
308
309 // eval normal transaction
310 if(!(ope->flags & OF_SPLIT))
311 {
312 cat = da_cat_get(ope->kcat);
313 if( cat && (cat->key == catkey || cat->parent == catkey) )
314 {
315 item = da_vehiclecost_malloc();
316 item->date = ope->date;
317 item->memo = ope->memo;
318 // get amount in base currency
319 //item->amount = ope->amount;
320 item->amount = hb_amount_base(ope->amount, ope->kcur);
321
322 item = repvehicle_eval_memofield(item, ope->memo);
323 data->vehicle_list = g_list_append(data->vehicle_list, item);
324 DB( g_print(" -> store acc=%d '%s' %.2f\n", ope->kacc, ope->memo, ope->amount) );
325 }
326 }
327 // eval split transaction
328 else
329 {
330 guint i, nbsplit = da_splits_length(ope->splits);
331 Split *split;
332
333 DB( g_print(" -> nb split %d\n", nbsplit) );
334
335 for(i=0;i<nbsplit;i++)
336 {
337 split = da_splits_get(ope->splits, i);
338 cat = da_cat_get(split->kcat);
339
340 DB( g_print(" -> eval split '%s'\n", split->memo) );
341
342 if( cat && (cat->key == catkey || cat->parent == catkey) )
343 {
344 item = da_vehiclecost_malloc();
345 item->date = ope->date;
346 item->memo = split->memo;
347 // get amount in base currency
348 //item->amount = split->amount;
349 item->amount = hb_amount_base(split->amount, ope->kcur);
350
351 item = repvehicle_eval_memofield(item, split->memo);
352 data->vehicle_list = g_list_append(data->vehicle_list, item);
353 DB( g_print(" -> store split part acc=%d '%s' %.2f\n", ope->kacc, split->memo, split->amount) );
354 }
355 }
356 }
357
358 list = g_list_next(list);
359 }
360
361 // sort by meter #399170
362 data->vehicle_list = g_list_sort(data->vehicle_list, (GCompareFunc)repvehicle_transaction_compare_func);
363
364 end1:
365 repvehicle_update(widget, NULL);
366 }
367
368
369 static void repvehicle_update(GtkWidget *widget, gpointer user_data)
370 {
371 struct repvehicle_data *data;
372 GtkTreeModel *model;
373 GtkTreeIter iter;
374 GList *list;
375 gchar *buf;
376 gint nb_refuel = 0;
377 int nb_fullrefuel = 0;
378 guint lastmeter = 0;
379
380 DB( g_print("\n[vehiclecost] update\n") );
381
382 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
383
384 // clear and detach our model
385 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report));
386 gtk_list_store_clear (GTK_LIST_STORE(model));
387 g_object_ref(model);
388 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report), NULL);
389
390 data->total_misccost = 0;
391 data->total_fuelcost = 0;
392 data->total_fuel = 0;
393 data->total_dist = 0;
394
395 gdouble partial_fuel = 0;
396 guint partial_dist = 0;
397
398
399 list = g_list_first(data->vehicle_list);
400 while (list != NULL)
401 {
402 CarCost *item = list->data;
403 gint dist;
404 gdouble centkm;
405 guint distbyvol;
406 gdouble trn_amount;
407
408 if( (item->date >= data->filter->mindate) && (item->date <= data->filter->maxdate) )
409 {
410 trn_amount = item->amount;
411
412 if( item->meter == 0 )
413 {
414 data->total_misccost += trn_amount;
415 }
416 else
417 {
418 if(nb_refuel > 0 )
419 {
420 //previtem = g_list_nth_data(data->vehicle_list, nb_refuel-1);
421 //if(previtem != NULL) previtem->dist = item->meter - previtem->meter;
422 //DB( g_print(" + previous item dist = %d\n", item->meter - previtem->meter) );
423 item->dist = item->meter - lastmeter;
424
425 //DB( g_print(" + last meter = %d\n", lastmeter) );
426
427 }
428
429 lastmeter = item->meter;
430 nb_refuel++;
431
432 DB( g_print("\n eval %02d :: d=%d v=%.2f $%.2f dist=%d\n", nb_refuel, item->meter, item->fuel, trn_amount, item->dist) );
433 DB( g_print(" + %s :: pf=%.2f pd=%d\n", item->partial ? "partial" : "full", partial_fuel, partial_dist) );
434
435 centkm = 0;
436 dist = 0;
437
438 //bugfix #159066 partial/full
439 if(item->partial == FALSE)
440 {
441 //#1836380 if we don't have a full already, the computing will be wrong
442 if( nb_fullrefuel > 0 )
443 {
444 // full refuel after partial
445 if(partial_fuel && partial_dist)
446 {
447 partial_fuel += item->fuel;
448 partial_dist += item->dist;
449 dist = item->dist;
450 centkm = partial_dist != 0 ? partial_fuel * 100 / partial_dist : 0;
451 DB( g_print(" + centkm=%.2f %.2f * 100 / %d (full after partial)\n", centkm, partial_fuel, partial_dist) );
452 }
453 else
454 {
455 dist = item->dist;
456 centkm = item->dist != 0 ? item->fuel * 100 / item->dist : 0;
457 DB( g_print(" + centkm=%.2f :: %.2f * 100 / %d (full after full)\n", centkm, item->fuel, item->dist) );
458 }
459 }
460 partial_fuel = 0;
461 partial_dist = 0;
462 nb_fullrefuel++;
463 }
464 // partial refuel
465 else
466 {
467 partial_fuel += item->fuel;
468 partial_dist += item->dist;
469 dist = item->dist;
470 DB( g_print(" + centkm= not computable\n") );
471 }
472
473 distbyvol = 0;
474 if(centkm != 0)
475 distbyvol = hb_amount_round((1/centkm)*100, 0);
476
477
478 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
479
480 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
481 LST_CAR_DATE , item->date,
482 LST_CAR_MEMO , item->memo,
483 LST_CAR_METER , item->meter,
484 LST_CAR_FUEL , item->fuel,
485 LST_CAR_PRICE , ABS(trn_amount) / item->fuel,
486 LST_CAR_AMOUNT , trn_amount,
487 LST_CAR_DIST , dist,
488 LST_CAR_100KM , centkm,
489 LST_CAR_DISTBYVOL, distbyvol,
490 LST_CAR_PARTIAL, item->partial,
491 -1);
492
493 //DB( g_print("\n insert d=%d v=%4.2f $%8.2f %d %5.2f\n", item->meter, item->fuel, trn_amount, dist, centkm) );
494
495 if(item->dist)
496 {
497 data->total_fuelcost += trn_amount;
498 data->total_fuel += item->fuel;
499 data->total_dist += item->dist;
500 }
501
502
503 }
504 }
505 list = g_list_next(list);
506 }
507
508 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report), model);
509 g_object_unref(model);
510
511
512 gdouble coef = data->total_dist ? 100 / (gdouble)data->total_dist : 0;
513
514 GLOBALS->minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor));
515
516
517 DB( g_print(" coef = 100 / %.2f = %.2f\n", (gdouble)data->total_dist, coef) );
518
519 // row 1 is for 100km
520 /*
521 gtk_label_set_text(GTK_LABEL(data->LA_total[1][1]), "1:1"); //Consumption
522 gtk_label_set_text(GTK_LABEL(data->LA_total[2][1]), "2:1"); //Fuel cost
523 gtk_label_set_text(GTK_LABEL(data->LA_total[3][1]), "3:1"); //Other cost
524 gtk_label_set_text(GTK_LABEL(data->LA_total[4][1]), "4:1"); //Total cost
525 */
526
527 // 100km fuel
528 buf = g_strdup_printf(PREFS->vehicle_unit_vol, data->total_fuel * coef);
529 gtk_label_set_text(GTK_LABEL(data->LA_avera[CAR_RES_FUEL]), buf);
530 g_free(buf);
531
532 // 100km fuelcost
533 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_avera[CAR_RES_FUELCOST]), data->total_fuelcost * coef, GLOBALS->kcur);
534 hb_label_set_colvalue(GTK_LABEL(data->LA_avera[CAR_RES_FUELCOST]), data->total_fuelcost * coef, GLOBALS->kcur, GLOBALS->minor);
535
536 // 100km other cost
537 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_avera[CAR_RES_OTHERCOST]), data->total_misccost * coef, GLOBALS->kcur);
538 hb_label_set_colvalue(GTK_LABEL(data->LA_avera[CAR_RES_OTHERCOST]), data->total_misccost * coef, GLOBALS->kcur, GLOBALS->minor);
539
540 // 100km cost
541 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_avera[CAR_RES_TOTALCOST]), (data->total_fuelcost + data->total_misccost) * coef, GLOBALS->kcur);
542 hb_label_set_colvalue(GTK_LABEL(data->LA_avera[CAR_RES_TOTALCOST]), (data->total_fuelcost + data->total_misccost) * coef, GLOBALS->kcur, GLOBALS->minor);
543
544
545 // row 2 is for total
546 /*
547 gtk_label_set_text(GTK_LABEL(data->LA_total[1][2]), "1:2"); //Consumption
548 gtk_label_set_text(GTK_LABEL(data->LA_total[2][2]), "2:2"); //Fuel cost
549 gtk_label_set_text(GTK_LABEL(data->LA_total[3][2]), "3:2"); //Other cost
550 gtk_label_set_text(GTK_LABEL(data->LA_total[4][2]), "4:2"); //Total
551 */
552
553 // total distance
554 buf = g_strdup_printf(PREFS->vehicle_unit_dist, data->total_dist);
555 gtk_label_set_text(GTK_LABEL(data->LA_total[CAR_RES_METER]), buf);
556 g_free(buf);
557
558 // total fuel
559 buf = g_strdup_printf(PREFS->vehicle_unit_vol, data->total_fuel);
560 gtk_label_set_text(GTK_LABEL(data->LA_total[CAR_RES_FUEL]), buf);
561 g_free(buf);
562
563 // total fuelcost
564 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_total[CAR_RES_FUELCOST]), data->total_fuelcost, GLOBALS->kcur);
565 hb_label_set_colvalue(GTK_LABEL(data->LA_total[CAR_RES_FUELCOST]), data->total_fuelcost, GLOBALS->kcur, GLOBALS->minor);
566
567 // total other cost
568 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_total[CAR_RES_OTHERCOST]), data->total_misccost, GLOBALS->kcur);
569 hb_label_set_colvalue(GTK_LABEL(data->LA_total[CAR_RES_OTHERCOST]), data->total_misccost, GLOBALS->kcur, GLOBALS->minor);
570
571 // total cost
572 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_total[CAR_RES_TOTALCOST]), data->total_fuelcost + data->total_misccost, GLOBALS->kcur);
573 hb_label_set_colvalue(GTK_LABEL(data->LA_total[CAR_RES_TOTALCOST]), data->total_fuelcost + data->total_misccost, GLOBALS->kcur, GLOBALS->minor);
574
575
576 }
577
578 static void repvehicle_toggle_minor(GtkWidget *widget, gpointer user_data)
579 {
580 struct repvehicle_data *data;
581
582 DB( g_print("\n[vehiclecost] toggle\n") );
583
584 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
585
586 repvehicle_update(widget, NULL);
587 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_report));
588
589
590 /*
591 statistic_update_total(widget,NULL);
592
593 //hbfile_update(data->LV_acc, (gpointer)4);
594 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_report));
595
596 minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor));
597 gtk_chart_show_minor(GTK_CHART(data->RE_bar), minor);
598 gtk_chart_show_minor(GTK_CHART(data->RE_pie), minor);
599 */
600
601 }
602
603 /*
604 **
605 */
606 static void repvehicle_setup(struct repvehicle_data *data)
607 {
608 DB( g_print("\n[vehiclecost] setup\n") );
609
610 data->txn_queue = g_queue_new ();
611 data->vehicle_list = NULL;
612
613 data->filter = da_flt_malloc();
614 filter_reset(data->filter);
615
616 /* 3.4 : make int transfer out of stats */
617 data->filter->option[FILTER_PAYMODE] = 1;
618 data->filter->paymode[PAYMODE_INTXFER] = FALSE;
619
620 filter_preset_daterange_set(data->filter, PREFS->date_range_rep, 0);
621
622 g_signal_handler_block(data->PO_mindate, data->handler_id[HID_REPVEHICLE_MINDATE]);
623 g_signal_handler_block(data->PO_maxdate, data->handler_id[HID_REPVEHICLE_MAXDATE]);
624
625 gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_mindate), data->filter->mindate);
626 gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_maxdate), data->filter->maxdate);
627
628 g_signal_handler_unblock(data->PO_mindate, data->handler_id[HID_REPVEHICLE_MINDATE]);
629 g_signal_handler_unblock(data->PO_maxdate, data->handler_id[HID_REPVEHICLE_MAXDATE]);
630
631
632 ui_cat_comboboxentry_populate(GTK_COMBO_BOX(data->PO_cat), GLOBALS->h_cat);
633
634 g_signal_handler_block(data->PO_cat, data->handler_id[HID_REPVEHICLE_VEHICLE]);
635 ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_cat), GLOBALS->vehicle_category);
636 g_signal_handler_unblock(data->PO_cat, data->handler_id[HID_REPVEHICLE_VEHICLE]);
637
638
639
640 }
641
642
643 /*
644 **
645 */
646 static gboolean repvehicle_window_dispose(GtkWidget *widget, GdkEvent *event, gpointer user_data)
647 {
648 struct repvehicle_data *data = user_data;
649 struct WinGeometry *wg;
650
651 DB( g_print("\n[vehiclecost] dispose\n") );
652
653 g_queue_free (data->txn_queue);
654
655 da_vehiclecost_destroy(data->vehicle_list);
656
657 da_flt_free(data->filter);
658
659 g_free(data);
660
661 //store position and size
662 wg = &PREFS->cst_wg;
663 gtk_window_get_position(GTK_WINDOW(widget), &wg->l, &wg->t);
664 gtk_window_get_size(GTK_WINDOW(widget), &wg->w, &wg->h);
665
666 DB( g_print(" window: l=%d, t=%d, w=%d, h=%d\n", wg->l, wg->t, wg->w, wg->h) );
667
668 //enable define windows
669 GLOBALS->define_off--;
670 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE));
671
672 return FALSE;
673 }
674
675
676 // the window creation
677 GtkWidget *repcost_window_new(void)
678 {
679 struct repvehicle_data *data;
680 struct WinGeometry *wg;
681 GtkWidget *window, *mainvbox, *hbox, *vbox, *treeview;
682 GtkWidget *label, *widget, *table;
683 gint row, col;
684 GtkUIManager *ui;
685 GtkActionGroup *actions;
686 //GtkAction *action;
687 GError *error = NULL;
688
689 data = g_malloc0(sizeof(struct repvehicle_data));
690 if(!data) return NULL;
691
692 DB( g_print("\n[vehiclecost] new\n") );
693
694 //disable define windows
695 GLOBALS->define_off++;
696 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE));
697
698 /* create window, etc */
699 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
700 data->window = window;
701
702 //store our window private data
703 g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)data);
704 DB( g_print(" - new window=%p, inst_data=%p\n", window, data) );
705
706 gtk_window_set_title (GTK_WINDOW (window), _("Vehicle cost report"));
707
708 //set the window icon
709 gtk_window_set_icon_name(GTK_WINDOW (window), ICONNAME_HB_REP_CAR);
710
711
712
713 //window contents
714 mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
715 gtk_container_add (GTK_CONTAINER (window), mainvbox);
716
717 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
718 gtk_box_pack_start (GTK_BOX (mainvbox), hbox, TRUE, TRUE, 0);
719
720 //control part
721 table = gtk_grid_new ();
722 gtk_widget_set_hexpand (GTK_WIDGET(table), FALSE);
723 gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0);
724
725 gtk_container_set_border_width (GTK_CONTAINER (table), SPACING_SMALL);
726 gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_SMALL);
727 gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_MEDIUM);
728
729 row = 0;
730 label = make_label_group(_("Display"));
731 gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
732
733 row++;
734 label = make_label_widget(_("Vehi_cle:"));
735 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
736
737 widget = ui_cat_comboboxentry_new(label);
738 data->PO_cat = widget;
739 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
740
741 row++;
742 widget = gtk_check_button_new_with_mnemonic (_("Euro _minor"));
743 data->CM_minor = widget;
744 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
745
746 row++;
747 widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
748 gtk_grid_attach (GTK_GRID (table), widget, 0, row, 3, 1);
749
750 row++;
751 label = make_label_group(_("Date filter"));
752 gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
753
754 row++;
755 label = make_label_widget(_("_Range:"));
756 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
757 data->CY_range = make_daterange(label, DATE_RANGE_CUSTOM_DISABLE);
758 gtk_grid_attach (GTK_GRID (table), data->CY_range, 2, row, 1, 1);
759
760 row++;
761 label = make_label_widget(_("_From:"));
762 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
763 data->PO_mindate = gtk_date_entry_new();
764 gtk_grid_attach (GTK_GRID (table), data->PO_mindate, 2, row, 1, 1);
765
766 row++;
767 label = make_label_widget(_("_To:"));
768 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
769 data->PO_maxdate = gtk_date_entry_new();
770 gtk_grid_attach (GTK_GRID (table), data->PO_maxdate, 2, row, 1, 1);
771
772
773 //part: info + report
774 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
775 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
776
777 //ui manager
778 actions = gtk_action_group_new ("default");
779
780 //as we use gettext
781 gtk_action_group_set_translation_domain(actions, GETTEXT_PACKAGE);
782
783 // data to action callbacks is set here (data)
784 gtk_action_group_add_actions (actions, entries, n_entries, data);
785
786 /* set which action should have priority in the toolbar */
787 //action = gtk_action_group_get_action(actions, "Refresh");
788 //g_object_set(action, "is_important", TRUE, NULL);
789
790
791 ui = gtk_ui_manager_new ();
792 gtk_ui_manager_insert_action_group (ui, actions, 0);
793 gtk_window_add_accel_group (GTK_WINDOW (window), gtk_ui_manager_get_accel_group (ui));
794
795 if (!gtk_ui_manager_add_ui_from_string (ui, ui_info, -1, &error))
796 {
797 g_message ("building UI failed: %s", error->message);
798 g_error_free (error);
799 }
800
801 data->ui = ui;
802 data->actions = actions;
803
804 //toolbar
805 data->TB_bar = gtk_ui_manager_get_widget (ui, "/ToolBar");
806 gtk_box_pack_start (GTK_BOX (vbox), data->TB_bar, FALSE, FALSE, 0);
807
808
809 // total
810 table = gtk_grid_new ();
811 gtk_widget_set_hexpand (GTK_WIDGET(table), FALSE);
812 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
813
814 gtk_container_set_border_width (GTK_CONTAINER (table), SPACING_SMALL);
815 gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_SMALL);
816 gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_MEDIUM);
817
818 row = 0; col = 1;
819
820 label = make_label_widget(_("Meter:"));
821 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
822
823 col++;
824 label = make_label_widget(_("Consumption:"));
825 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
826
827 col++;
828 label = make_label_widget(_("Fuel cost:"));
829 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
830
831 col++;
832 label = make_label_widget(_("Other cost:"));
833 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
834
835 col++;
836 label = make_label_widget(_("Total cost:"));
837 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
838
839 row++;
840 col = 0;
841 label = make_label_widget(PREFS->vehicle_unit_100);
842 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
843
844 for(col = 1;col<MAX_CAR_RES;col++)
845 {
846 label = make_label(NULL, 1.0, 0.5);
847 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
848 data->LA_avera[col] = label;
849 }
850
851 row++;
852 col = 0;
853 label = make_label_widget(_("Total"));
854 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
855
856 for(col = 1;col<MAX_CAR_RES;col++)
857 {
858 label = make_label(NULL, 1.0, 0.5);
859 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
860 data->LA_total[col] = label;
861 }
862
863
864 //detail
865 widget = gtk_scrolled_window_new (NULL, NULL);
866 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_ETCHED_IN);
867 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
868
869 treeview = create_list_repvehicle();
870 data->LV_report = treeview;
871 gtk_container_add (GTK_CONTAINER(widget), treeview);
872 gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
873
874
875 //todo:should move this
876 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_minor),GLOBALS->minor);
877
878
879
880 /* attach our minor to treeview */
881 g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report))), "minor", (gpointer)data->CM_minor);
882
883
884
885 /* signal connect */
886 g_signal_connect (window, "delete-event", G_CALLBACK (repvehicle_window_dispose), (gpointer)data);
887
888 g_signal_connect (data->CM_minor, "toggled", G_CALLBACK (repvehicle_toggle_minor), NULL);
889
890 data->handler_id[HID_REPVEHICLE_MINDATE] = g_signal_connect (data->PO_mindate, "changed", G_CALLBACK (repvehicle_date_change), (gpointer)data);
891 data->handler_id[HID_REPVEHICLE_MAXDATE] = g_signal_connect (data->PO_maxdate, "changed", G_CALLBACK (repvehicle_date_change), (gpointer)data);
892
893 data->handler_id[HID_REPVEHICLE_RANGE] = g_signal_connect (data->CY_range, "changed", G_CALLBACK (repvehicle_range_change), NULL);
894
895 data->handler_id[HID_REPVEHICLE_VEHICLE] = g_signal_connect (data->PO_cat, "changed", G_CALLBACK (repvehicle_compute), NULL);
896
897
898 //setup, init and show window
899 repvehicle_setup(data);
900
901 /* toolbar */
902 /*
903 if(PREFS->toolbar_style == 0)
904 gtk_toolbar_unset_style(GTK_TOOLBAR(data->TB_bar));
905 else
906 gtk_toolbar_set_style(GTK_TOOLBAR(data->TB_bar), PREFS->toolbar_style-1);
907 */
908
909 //setup, init and show window
910 wg = &PREFS->cst_wg;
911 gtk_window_move(GTK_WINDOW(window), wg->l, wg->t);
912 gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h);
913
914 gtk_widget_show_all (window);
915
916 //minor ?
917 if( PREFS->euro_active )
918 gtk_widget_show(data->CM_minor);
919 else
920 gtk_widget_hide(data->CM_minor);
921
922
923
924 if( PREFS->date_range_rep )
925 hbtk_combo_box_set_active_id(GTK_COMBO_BOX_TEXT(data->CY_range), PREFS->date_range_rep);
926 else
927 repvehicle_compute(window, NULL);
928
929 return(window);
930 }
931
932 /*
933 ** ============================================================================
934 */
935
936 static void repvehicle_date_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
937 {
938 GDate *date;
939 guint32 julian;
940 gchar buf[256];
941
942 gtk_tree_model_get(model, iter,
943 LST_CAR_DATE, &julian,
944 -1);
945
946 date = g_date_new_julian (julian);
947 g_date_strftime (buf, 256-1, PREFS->date_format, date);
948 g_date_free(date);
949
950 g_object_set(renderer, "text", buf, NULL);
951 }
952
953 static void repvehicle_distance_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
954 {
955 guint distance;
956 gchar *text;
957
958 gtk_tree_model_get(model, iter, user_data, &distance, -1);
959
960 if(distance != 0)
961 {
962 text = g_strdup_printf(PREFS->vehicle_unit_dist, distance);
963 g_object_set(renderer, "text", text, NULL);
964 g_free(text);
965 }
966 else
967 g_object_set(renderer, "text", "-", NULL);
968 }
969
970 static void repvehicle_volume_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
971 {
972 gdouble volume;
973 gboolean partial;
974 gchar *text;
975
976 gtk_tree_model_get(model, iter, user_data, &volume, LST_CAR_PARTIAL, &partial, -1);
977
978 if(volume != 0)
979 {
980 text = g_strdup_printf(PREFS->vehicle_unit_vol, volume);
981 g_object_set(renderer,
982 "text", text,
983 "style-set", TRUE,
984 "style", partial ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL,
985 NULL);
986
987 g_free(text);
988 }
989 else
990 g_object_set(renderer, "text", "-", NULL);
991 }
992
993 static void repvehicle_amount_cell_data_function (GtkTreeViewColumn *col,
994 GtkCellRenderer *renderer,
995 GtkTreeModel *model,
996 GtkTreeIter *iter,
997 gpointer user_data)
998 {
999 gdouble value;
1000 gchar *color;
1001 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
1002
1003 gtk_tree_model_get(model, iter,
1004 user_data, &value,
1005 -1);
1006
1007 if( value )
1008 {
1009 hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, value, GLOBALS->kcur, GLOBALS->minor);
1010
1011 color = get_normal_color_amount(value);
1012
1013 g_object_set(renderer,
1014 "foreground", color,
1015 "text", buf,
1016 NULL); }
1017 else
1018 {
1019 g_object_set(renderer, "text", "", NULL);
1020 }
1021 }
1022
1023 static GtkTreeViewColumn *volume_list_repvehicle_column(gchar *name, gint id)
1024 {
1025 GtkTreeViewColumn *column;
1026 GtkCellRenderer *renderer;
1027
1028 column = gtk_tree_view_column_new();
1029 gtk_tree_view_column_set_title(column, name);
1030 renderer = gtk_cell_renderer_text_new ();
1031 g_object_set(renderer, "xalign", 1.0, NULL);
1032 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1033 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_volume_cell_data_function, GINT_TO_POINTER(id), NULL);
1034 gtk_tree_view_column_set_alignment (column, 0.5);
1035 //gtk_tree_view_column_set_sort_column_id (column, id);
1036 return column;
1037 }
1038
1039 static GtkTreeViewColumn *distance_list_repvehicle_column(gchar *name, gint id)
1040 {
1041 GtkTreeViewColumn *column;
1042 GtkCellRenderer *renderer;
1043
1044 column = gtk_tree_view_column_new();
1045 gtk_tree_view_column_set_title(column, name);
1046 renderer = gtk_cell_renderer_text_new ();
1047 g_object_set(renderer, "xalign", 1.0, NULL);
1048 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1049 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_distance_cell_data_function, GINT_TO_POINTER(id), NULL);
1050 gtk_tree_view_column_set_alignment (column, 0.5);
1051 //gtk_tree_view_column_set_sort_column_id (column, id);
1052 return column;
1053 }
1054
1055 static GtkTreeViewColumn *amount_list_repvehicle_column(gchar *name, gint id)
1056 {
1057 GtkTreeViewColumn *column;
1058 GtkCellRenderer *renderer;
1059
1060 column = gtk_tree_view_column_new();
1061 gtk_tree_view_column_set_title(column, name);
1062 renderer = gtk_cell_renderer_text_new ();
1063 g_object_set(renderer, "xalign", 1.0, NULL);
1064 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1065 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_amount_cell_data_function, GINT_TO_POINTER(id), NULL);
1066 gtk_tree_view_column_set_alignment (column, 0.5);
1067 //gtk_tree_view_column_set_sort_column_id (column, id);
1068 return column;
1069 }
1070
1071
1072 /*
1073 ** create our statistic list
1074 */
1075 static GtkWidget *create_list_repvehicle(void)
1076 {
1077 GtkListStore *store;
1078 GtkWidget *view;
1079 GtkCellRenderer *renderer;
1080 GtkTreeViewColumn *column;
1081
1082 /* create list store */
1083 store = gtk_list_store_new(
1084 NUM_LST_CAR,
1085 G_TYPE_UINT,
1086 G_TYPE_STRING,
1087 G_TYPE_UINT,
1088 G_TYPE_DOUBLE,
1089 G_TYPE_DOUBLE,
1090 G_TYPE_DOUBLE,
1091 G_TYPE_UINT,
1092 G_TYPE_DOUBLE,
1093 G_TYPE_UINT,
1094 G_TYPE_BOOLEAN );
1095
1096 //treeview
1097 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1098 g_object_unref(store);
1099
1100 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), PREFS->grid_lines);
1101
1102 /* column date */
1103 column = gtk_tree_view_column_new();
1104 gtk_tree_view_column_set_title(column, _("Date"));
1105 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1106 renderer = gtk_cell_renderer_text_new();
1107 g_object_set(renderer, "xalign", 1.0, NULL);
1108 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1109 //gtk_tree_view_column_add_attribute(column, renderer, "text", LST_CAR_DATE);
1110 gtk_tree_view_column_set_alignment (column, 0.5);
1111 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_date_cell_data_function, NULL, NULL);
1112
1113 /*
1114 LST_CAR_DATE,
1115 LST_CAR_MEMO,
1116 LST_CAR_METER,
1117 LST_CAR_FUEL,
1118 LST_CAR_PRICE,
1119 LST_CAR_AMOUNT,
1120 LST_CAR_DIST,
1121 LST_CAR_100KM
1122
1123 */
1124
1125 /* column: Memo */
1126 /*
1127 column = gtk_tree_view_column_new();
1128 gtk_tree_view_column_set_title(column, _("Memo"));
1129 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1130 renderer = gtk_cell_renderer_text_new();
1131 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1132 gtk_tree_view_column_add_attribute(column, renderer, "text", LST_CAR_MEMO);
1133 //gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_text_cell_data_function, NULL, NULL);
1134 */
1135
1136 /* column: Meter */
1137 column = distance_list_repvehicle_column(_("Meter"), LST_CAR_METER);
1138 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1139
1140 /* column: Fuel load */
1141 column = volume_list_repvehicle_column(_("Fuel"), LST_CAR_FUEL);
1142 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1143
1144 /* column: Price by unit */
1145 column = amount_list_repvehicle_column(_("Price"), LST_CAR_PRICE);
1146 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1147
1148 /* column: Amount */
1149 column = amount_list_repvehicle_column(_("Amount"), LST_CAR_AMOUNT);
1150 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1151
1152 /* column: Distance done */
1153 column = distance_list_repvehicle_column(_("Dist."), LST_CAR_DIST);
1154 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1155
1156 /* column: consumption for 100Km */
1157 column = volume_list_repvehicle_column(PREFS->vehicle_unit_100, LST_CAR_100KM);
1158 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1159
1160 /* column: km by liter (distance by volume */
1161 column = distance_list_repvehicle_column(PREFS->vehicle_unit_distbyvol, LST_CAR_DISTBYVOL);
1162 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1163
1164
1165 /* column last: empty */
1166 column = gtk_tree_view_column_new();
1167 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1168
1169 return(view);
1170 }
This page took 0.082158 seconds and 4 git commands to generate.