]> Dogcows Code - chaz/homebank/blob - src/rep_vehicle.c
import homebank-5.1.7
[chaz/homebank] / src / rep_vehicle.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2018 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_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("(repvehicle) 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 gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_range), 11);
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("(repvehicle) 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 = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_range));
131
132 if(range != 11)
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("(repvehicle) 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 some datas
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_count(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 = 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 guint lastmeter = 0;
378
379 DB( g_print("(repvehicle) update\n") );
380
381 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
382
383 // clear and detach our model
384 model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report));
385 gtk_list_store_clear (GTK_LIST_STORE(model));
386 g_object_ref(model);
387 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report), NULL);
388
389 data->total_misccost = 0;
390 data->total_fuelcost = 0;
391 data->total_fuel = 0;
392 data->total_dist = 0;
393
394 gdouble partial_fuel = 0;
395 guint partial_dist = 0;
396
397
398 list = g_list_first(data->vehicle_list);
399 while (list != NULL)
400 {
401 CarCost *item = list->data;
402 gint dist;
403 gdouble centkm;
404 guint distbyvol;
405 gdouble trn_amount;
406
407 if( (item->date >= data->filter->mindate) && (item->date <= data->filter->maxdate) )
408 {
409 trn_amount = item->amount;
410
411 if( item->meter == 0 )
412 {
413 data->total_misccost += trn_amount;
414 }
415 else
416 {
417 if(nb_refuel > 0 )
418 {
419 //previtem = g_list_nth_data(data->vehicle_list, nb_refuel-1);
420 //if(previtem != NULL) previtem->dist = item->meter - previtem->meter;
421 //DB( g_print(" + previous item dist = %d\n", item->meter - previtem->meter) );
422 item->dist = item->meter - lastmeter;
423
424 //DB( g_print(" + last meter = %d\n", lastmeter) );
425
426 }
427
428 lastmeter = item->meter;
429 nb_refuel++;
430
431 DB( g_print(" eval : d=%d v=%4.2f $%8.2f dist=%d\n", item->meter, item->fuel, trn_amount, item->dist) );
432
433 //bugfix #159066
434 if(item->partial == FALSE)
435 {
436 // full refuel after partial
437 if(partial_fuel && partial_dist)
438 {
439 DB( g_print(" + full refuel after partial\n") );
440 partial_fuel += item->fuel;
441 partial_dist += item->dist;
442 dist = item->dist;
443 centkm = partial_dist != 0 ? partial_fuel * 100 / partial_dist : 0;
444 }
445 else
446 {
447 DB( g_print(" + real full refuel\n") );
448 dist = item->dist;
449 centkm = item->dist != 0 ? item->fuel * 100 / item->dist : 0;
450 }
451 partial_fuel = 0;
452 partial_dist = 0;
453 }
454 // partial refuel
455 else
456 {
457 DB( g_print(" + partial refuel\n") );
458 partial_fuel += item->fuel;
459 partial_dist += item->dist;
460 dist = item->dist;
461 centkm = 0;
462 }
463
464 distbyvol = 0;
465 if(centkm != 0)
466 distbyvol = hb_amount_round((1/centkm)*100, 0);
467
468 DB( g_print(" + pf=%.2f pd=%d :: dbv=%d\n", partial_fuel, partial_dist, distbyvol) );
469
470
471
472 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
473
474 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
475 LST_CAR_DATE , item->date,
476 LST_CAR_MEMO , item->memo,
477 LST_CAR_METER , item->meter,
478 LST_CAR_FUEL , item->fuel,
479 LST_CAR_PRICE , ABS(trn_amount) / item->fuel,
480 LST_CAR_AMOUNT , trn_amount,
481 LST_CAR_DIST , dist,
482 LST_CAR_100KM , centkm,
483 LST_CAR_DISTBYVOL, distbyvol,
484 LST_CAR_PARTIAL, item->partial,
485 -1);
486
487 DB( g_print(" + insert d=%d v=%4.2f $%8.2f %d %5.2f\n", item->meter, item->fuel, trn_amount, dist, centkm) );
488
489 if(item->dist)
490 {
491 data->total_fuelcost += trn_amount;
492 data->total_fuel += item->fuel;
493 data->total_dist += item->dist;
494 }
495
496
497 }
498 }
499 list = g_list_next(list);
500 }
501
502 gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_report), model);
503 g_object_unref(model);
504
505
506 gdouble coef = data->total_dist ? 100 / (gdouble)data->total_dist : 0;
507
508 GLOBALS->minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor));
509
510
511 DB( g_print(" coef = 100 / %.2f = %.2f\n", (gdouble)data->total_dist, coef) );
512
513 // row 1 is for 100km
514 /*
515 gtk_label_set_text(GTK_LABEL(data->LA_total[1][1]), "1:1"); //Consumption
516 gtk_label_set_text(GTK_LABEL(data->LA_total[2][1]), "2:1"); //Fuel cost
517 gtk_label_set_text(GTK_LABEL(data->LA_total[3][1]), "3:1"); //Other cost
518 gtk_label_set_text(GTK_LABEL(data->LA_total[4][1]), "4:1"); //Total cost
519 */
520
521 // 100km fuel
522 buf = g_strdup_printf(PREFS->vehicle_unit_vol, data->total_fuel * coef);
523 gtk_label_set_text(GTK_LABEL(data->LA_avera[CAR_RES_FUEL]), buf);
524 g_free(buf);
525
526 // 100km fuelcost
527 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_avera[CAR_RES_FUELCOST]), data->total_fuelcost * coef, GLOBALS->kcur);
528 hb_label_set_colvalue(GTK_LABEL(data->LA_avera[CAR_RES_FUELCOST]), data->total_fuelcost * coef, GLOBALS->kcur, GLOBALS->minor);
529
530 // 100km other cost
531 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_avera[CAR_RES_OTHERCOST]), data->total_misccost * coef, GLOBALS->kcur);
532 hb_label_set_colvalue(GTK_LABEL(data->LA_avera[CAR_RES_OTHERCOST]), data->total_misccost * coef, GLOBALS->kcur, GLOBALS->minor);
533
534 // 100km cost
535 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_avera[CAR_RES_TOTALCOST]), (data->total_fuelcost + data->total_misccost) * coef, GLOBALS->kcur);
536 hb_label_set_colvalue(GTK_LABEL(data->LA_avera[CAR_RES_TOTALCOST]), (data->total_fuelcost + data->total_misccost) * coef, GLOBALS->kcur, GLOBALS->minor);
537
538
539 // row 2 is for total
540 /*
541 gtk_label_set_text(GTK_LABEL(data->LA_total[1][2]), "1:2"); //Consumption
542 gtk_label_set_text(GTK_LABEL(data->LA_total[2][2]), "2:2"); //Fuel cost
543 gtk_label_set_text(GTK_LABEL(data->LA_total[3][2]), "3:2"); //Other cost
544 gtk_label_set_text(GTK_LABEL(data->LA_total[4][2]), "4:2"); //Total
545 */
546
547 // total distance
548 buf = g_strdup_printf(PREFS->vehicle_unit_dist, data->total_dist);
549 gtk_label_set_text(GTK_LABEL(data->LA_total[CAR_RES_METER]), buf);
550 g_free(buf);
551
552 // total fuel
553 buf = g_strdup_printf(PREFS->vehicle_unit_vol, data->total_fuel);
554 gtk_label_set_text(GTK_LABEL(data->LA_total[CAR_RES_FUEL]), buf);
555 g_free(buf);
556
557 // total fuelcost
558 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_total[CAR_RES_FUELCOST]), data->total_fuelcost, GLOBALS->kcur);
559 hb_label_set_colvalue(GTK_LABEL(data->LA_total[CAR_RES_FUELCOST]), data->total_fuelcost, GLOBALS->kcur, GLOBALS->minor);
560
561 // total other cost
562 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_total[CAR_RES_OTHERCOST]), data->total_misccost, GLOBALS->kcur);
563 hb_label_set_colvalue(GTK_LABEL(data->LA_total[CAR_RES_OTHERCOST]), data->total_misccost, GLOBALS->kcur, GLOBALS->minor);
564
565 // total cost
566 //hb_label_set_colvaluecurr(GTK_LABEL(data->LA_total[CAR_RES_TOTALCOST]), data->total_fuelcost + data->total_misccost, GLOBALS->kcur);
567 hb_label_set_colvalue(GTK_LABEL(data->LA_total[CAR_RES_TOTALCOST]), data->total_fuelcost + data->total_misccost, GLOBALS->kcur, GLOBALS->minor);
568
569
570 }
571
572 static void repvehicle_toggle_minor(GtkWidget *widget, gpointer user_data)
573 {
574 struct repvehicle_data *data;
575
576 DB( g_print("(repvehicle) toggle\n") );
577
578 data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
579
580 repvehicle_update(widget, NULL);
581 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_report));
582
583
584 /*
585 statistic_update_total(widget,NULL);
586
587 //hbfile_update(data->LV_acc, (gpointer)4);
588 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_report));
589
590 minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_minor));
591 gtk_chart_show_minor(GTK_CHART(data->RE_bar), minor);
592 gtk_chart_show_minor(GTK_CHART(data->RE_pie), minor);
593 */
594
595 }
596
597 /*
598 **
599 */
600 static void repvehicle_setup(struct repvehicle_data *data)
601 {
602 DB( g_print("(repvehicle) setup\n") );
603
604 data->txn_queue = g_queue_new ();
605 data->vehicle_list = NULL;
606
607 data->filter = da_filter_malloc();
608 filter_default_all_set(data->filter);
609
610 /* 3.4 : make int transfer out of stats */
611 data->filter->option[FILTER_PAYMODE] = 1;
612 data->filter->paymode[PAYMODE_INTXFER] = FALSE;
613
614 filter_preset_daterange_set(data->filter, PREFS->date_range_rep, 0);
615
616 g_signal_handler_block(data->PO_mindate, data->handler_id[HID_REPVEHICLE_MINDATE]);
617 g_signal_handler_block(data->PO_maxdate, data->handler_id[HID_REPVEHICLE_MAXDATE]);
618
619 gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_mindate), data->filter->mindate);
620 gtk_date_entry_set_date(GTK_DATE_ENTRY(data->PO_maxdate), data->filter->maxdate);
621
622 g_signal_handler_unblock(data->PO_mindate, data->handler_id[HID_REPVEHICLE_MINDATE]);
623 g_signal_handler_unblock(data->PO_maxdate, data->handler_id[HID_REPVEHICLE_MAXDATE]);
624
625
626 ui_cat_comboboxentry_populate(GTK_COMBO_BOX(data->PO_cat), GLOBALS->h_cat);
627
628 g_signal_handler_block(data->PO_cat, data->handler_id[HID_REPVEHICLE_VEHICLE]);
629 ui_cat_comboboxentry_set_active(GTK_COMBO_BOX(data->PO_cat), GLOBALS->vehicle_category);
630 g_signal_handler_unblock(data->PO_cat, data->handler_id[HID_REPVEHICLE_VEHICLE]);
631
632
633
634 }
635
636
637 /*
638 **
639 */
640 static gboolean repvehicle_window_dispose(GtkWidget *widget, GdkEvent *event, gpointer user_data)
641 {
642 struct repvehicle_data *data = user_data;
643 struct WinGeometry *wg;
644
645 DB( g_print("(repvehicle) dispose\n") );
646
647 g_queue_free (data->txn_queue);
648
649 da_vehiclecost_destroy(data->vehicle_list);
650
651 da_filter_free(data->filter);
652
653 g_free(data);
654
655 //store position and size
656 wg = &PREFS->cst_wg;
657 gtk_window_get_position(GTK_WINDOW(widget), &wg->l, &wg->t);
658 gtk_window_get_size(GTK_WINDOW(widget), &wg->w, &wg->h);
659
660 DB( g_print(" window: l=%d, t=%d, w=%d, h=%d\n", wg->l, wg->t, wg->w, wg->h) );
661
662 //enable define windows
663 GLOBALS->define_off--;
664 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE));
665
666 return FALSE;
667 }
668
669
670 // the window creation
671 GtkWidget *repcost_window_new(void)
672 {
673 struct repvehicle_data *data;
674 struct WinGeometry *wg;
675 GtkWidget *window, *mainvbox, *hbox, *vbox, *treeview;
676 GtkWidget *label, *widget, *table;
677 gint row, col;
678 GtkUIManager *ui;
679 GtkActionGroup *actions;
680 //GtkAction *action;
681 GError *error = NULL;
682
683 data = g_malloc0(sizeof(struct repvehicle_data));
684 if(!data) return NULL;
685
686 DB( g_print("(repvehicle) new\n") );
687
688 //disable define windows
689 GLOBALS->define_off++;
690 ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE));
691
692 /* create window, etc */
693 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
694 data->window = window;
695
696 //store our window private data
697 g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)data);
698 DB( g_print(" - new window=%p, inst_data=%p\n", window, data) );
699
700 gtk_window_set_title (GTK_WINDOW (window), _("Vehicle cost report"));
701
702 //set the window icon
703 gtk_window_set_icon_name(GTK_WINDOW (window), ICONNAME_HB_REP_CAR);
704
705
706
707 //window contents
708 mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
709 gtk_container_add (GTK_CONTAINER (window), mainvbox);
710
711 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
712 gtk_box_pack_start (GTK_BOX (mainvbox), hbox, TRUE, TRUE, 0);
713
714 //control part
715 table = gtk_grid_new ();
716 gtk_widget_set_hexpand (GTK_WIDGET(table), FALSE);
717 gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0);
718
719 gtk_container_set_border_width (GTK_CONTAINER (table), SPACING_SMALL);
720 gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_SMALL);
721 gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_MEDIUM);
722
723 row = 0;
724 label = make_label_group(_("Display"));
725 gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
726
727 row++;
728 label = make_label_widget(_("Vehi_cle:"));
729 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
730
731 widget = ui_cat_comboboxentry_new(label);
732 data->PO_cat = widget;
733 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
734
735 row++;
736 widget = gtk_check_button_new_with_mnemonic (_("Euro _minor"));
737 data->CM_minor = widget;
738 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
739
740 row++;
741 widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
742 gtk_grid_attach (GTK_GRID (table), widget, 0, row, 3, 1);
743
744 row++;
745 label = make_label_group(_("Date filter"));
746 gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
747
748 row++;
749 label = make_label_widget(_("_Range:"));
750 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
751 data->CY_range = make_daterange(label, FALSE);
752 gtk_grid_attach (GTK_GRID (table), data->CY_range, 2, row, 1, 1);
753
754 row++;
755 label = make_label_widget(_("_From:"));
756 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
757 data->PO_mindate = gtk_date_entry_new();
758 gtk_grid_attach (GTK_GRID (table), data->PO_mindate, 2, row, 1, 1);
759
760 row++;
761 label = make_label_widget(_("_To:"));
762 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
763 data->PO_maxdate = gtk_date_entry_new();
764 gtk_grid_attach (GTK_GRID (table), data->PO_maxdate, 2, row, 1, 1);
765
766
767 //part: info + report
768 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
769 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
770
771 //ui manager
772 actions = gtk_action_group_new ("default");
773
774 //as we use gettext
775 gtk_action_group_set_translation_domain(actions, GETTEXT_PACKAGE);
776
777 // data to action callbacks is set here (data)
778 gtk_action_group_add_actions (actions, entries, n_entries, data);
779
780 /* set which action should have priority in the toolbar */
781 //action = gtk_action_group_get_action(actions, "Refresh");
782 //g_object_set(action, "is_important", TRUE, NULL);
783
784
785 ui = gtk_ui_manager_new ();
786 gtk_ui_manager_insert_action_group (ui, actions, 0);
787 gtk_window_add_accel_group (GTK_WINDOW (window), gtk_ui_manager_get_accel_group (ui));
788
789 if (!gtk_ui_manager_add_ui_from_string (ui, ui_info, -1, &error))
790 {
791 g_message ("building UI failed: %s", error->message);
792 g_error_free (error);
793 }
794
795 data->ui = ui;
796 data->actions = actions;
797
798 //toolbar
799 data->TB_bar = gtk_ui_manager_get_widget (ui, "/ToolBar");
800 gtk_box_pack_start (GTK_BOX (vbox), data->TB_bar, FALSE, FALSE, 0);
801
802
803 // total
804 table = gtk_grid_new ();
805 gtk_widget_set_hexpand (GTK_WIDGET(table), FALSE);
806 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
807
808 gtk_container_set_border_width (GTK_CONTAINER (table), SPACING_SMALL);
809 gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_SMALL);
810 gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_MEDIUM);
811
812 row = 0; col = 1;
813
814 label = make_label_widget(_("Meter:"));
815 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
816
817 col++;
818 label = make_label_widget(_("Consumption:"));
819 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
820
821 col++;
822 label = make_label_widget(_("Fuel cost:"));
823 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
824
825 col++;
826 label = make_label_widget(_("Other cost:"));
827 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
828
829 col++;
830 label = make_label_widget(_("Total cost:"));
831 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
832
833 row++;
834 col = 0;
835 label = make_label_widget(PREFS->vehicle_unit_100);
836 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
837
838 for(col = 1;col<MAX_CAR_RES;col++)
839 {
840 label = make_label(NULL, 1.0, 0.5);
841 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
842 data->LA_avera[col] = label;
843 }
844
845 row++;
846 col = 0;
847 label = make_label_widget(_("Total"));
848 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
849
850 for(col = 1;col<MAX_CAR_RES;col++)
851 {
852 label = make_label(NULL, 1.0, 0.5);
853 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
854 data->LA_total[col] = label;
855 }
856
857
858 //detail
859 widget = gtk_scrolled_window_new (NULL, NULL);
860 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_ETCHED_IN);
861 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
862
863 treeview = create_list_repvehicle();
864 data->LV_report = treeview;
865 gtk_container_add (GTK_CONTAINER(widget), treeview);
866 gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
867
868
869 //todo:should move this
870 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_minor),GLOBALS->minor);
871
872
873
874 /* attach our minor to treeview */
875 g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report))), "minor", (gpointer)data->CM_minor);
876
877
878
879 /* signal connect */
880 g_signal_connect (window, "delete-event", G_CALLBACK (repvehicle_window_dispose), (gpointer)data);
881
882 g_signal_connect (data->CM_minor, "toggled", G_CALLBACK (repvehicle_toggle_minor), NULL);
883
884 data->handler_id[HID_REPVEHICLE_MINDATE] = g_signal_connect (data->PO_mindate, "changed", G_CALLBACK (repvehicle_date_change), (gpointer)data);
885 data->handler_id[HID_REPVEHICLE_MAXDATE] = g_signal_connect (data->PO_maxdate, "changed", G_CALLBACK (repvehicle_date_change), (gpointer)data);
886
887 data->handler_id[HID_REPVEHICLE_RANGE] = g_signal_connect (data->CY_range, "changed", G_CALLBACK (repvehicle_range_change), NULL);
888
889 data->handler_id[HID_REPVEHICLE_VEHICLE] = g_signal_connect (data->PO_cat, "changed", G_CALLBACK (repvehicle_compute), NULL);
890
891
892 //setup, init and show window
893 repvehicle_setup(data);
894
895 /* toolbar */
896 /*
897 if(PREFS->toolbar_style == 0)
898 gtk_toolbar_unset_style(GTK_TOOLBAR(data->TB_bar));
899 else
900 gtk_toolbar_set_style(GTK_TOOLBAR(data->TB_bar), PREFS->toolbar_style-1);
901 */
902
903 //setup, init and show window
904 wg = &PREFS->cst_wg;
905 gtk_window_move(GTK_WINDOW(window), wg->l, wg->t);
906 gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h);
907
908 gtk_widget_show_all (window);
909
910 //minor ?
911 if( PREFS->euro_active )
912 gtk_widget_show(data->CM_minor);
913 else
914 gtk_widget_hide(data->CM_minor);
915
916
917
918 if( PREFS->date_range_rep )
919 gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_range), PREFS->date_range_rep);
920 else
921 repvehicle_compute(window, NULL);
922
923 return(window);
924 }
925
926 /*
927 ** ============================================================================
928 */
929
930 static void repvehicle_date_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
931 {
932 GDate *date;
933 guint32 julian;
934 gchar buf[256];
935
936 gtk_tree_model_get(model, iter,
937 LST_CAR_DATE, &julian,
938 -1);
939
940 date = g_date_new_julian (julian);
941 g_date_strftime (buf, 256-1, PREFS->date_format, date);
942 g_date_free(date);
943
944 g_object_set(renderer, "text", buf, NULL);
945 }
946
947 static void repvehicle_distance_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
948 {
949 guint distance;
950 gchar *text;
951
952 gtk_tree_model_get(model, iter, user_data, &distance, -1);
953
954 if(distance != 0)
955 {
956 text = g_strdup_printf(PREFS->vehicle_unit_dist, distance);
957 g_object_set(renderer, "text", text, NULL);
958 g_free(text);
959 }
960 else
961 g_object_set(renderer, "text", "-", NULL);
962 }
963
964 static void repvehicle_volume_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
965 {
966 gdouble volume;
967 gboolean partial;
968 gchar *text;
969
970 gtk_tree_model_get(model, iter, user_data, &volume, LST_CAR_PARTIAL, &partial, -1);
971
972 if(volume != 0)
973 {
974 text = g_strdup_printf(PREFS->vehicle_unit_vol, volume);
975 g_object_set(renderer,
976 "text", text,
977 "style-set", TRUE,
978 "style", partial ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL,
979 NULL);
980
981 g_free(text);
982 }
983 else
984 g_object_set(renderer, "text", "-", NULL);
985 }
986
987 static void repvehicle_amount_cell_data_function (GtkTreeViewColumn *col,
988 GtkCellRenderer *renderer,
989 GtkTreeModel *model,
990 GtkTreeIter *iter,
991 gpointer user_data)
992 {
993 gdouble value;
994 gchar *color;
995 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
996
997 gtk_tree_model_get(model, iter,
998 user_data, &value,
999 -1);
1000
1001 if( value )
1002 {
1003 hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, value, GLOBALS->kcur, GLOBALS->minor);
1004
1005 color = get_normal_color_amount(value);
1006
1007 g_object_set(renderer,
1008 "foreground", color,
1009 "text", buf,
1010 NULL); }
1011 else
1012 {
1013 g_object_set(renderer, "text", "", NULL);
1014 }
1015 }
1016
1017 static GtkTreeViewColumn *volume_list_repvehicle_column(gchar *name, gint id)
1018 {
1019 GtkTreeViewColumn *column;
1020 GtkCellRenderer *renderer;
1021
1022 column = gtk_tree_view_column_new();
1023 gtk_tree_view_column_set_title(column, name);
1024 renderer = gtk_cell_renderer_text_new ();
1025 g_object_set(renderer, "xalign", 1.0, NULL);
1026 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1027 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_volume_cell_data_function, GINT_TO_POINTER(id), NULL);
1028 gtk_tree_view_column_set_alignment (column, 0.5);
1029 //gtk_tree_view_column_set_sort_column_id (column, id);
1030 return column;
1031 }
1032
1033 static GtkTreeViewColumn *distance_list_repvehicle_column(gchar *name, gint id)
1034 {
1035 GtkTreeViewColumn *column;
1036 GtkCellRenderer *renderer;
1037
1038 column = gtk_tree_view_column_new();
1039 gtk_tree_view_column_set_title(column, name);
1040 renderer = gtk_cell_renderer_text_new ();
1041 g_object_set(renderer, "xalign", 1.0, NULL);
1042 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1043 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_distance_cell_data_function, GINT_TO_POINTER(id), NULL);
1044 gtk_tree_view_column_set_alignment (column, 0.5);
1045 //gtk_tree_view_column_set_sort_column_id (column, id);
1046 return column;
1047 }
1048
1049 static GtkTreeViewColumn *amount_list_repvehicle_column(gchar *name, gint id)
1050 {
1051 GtkTreeViewColumn *column;
1052 GtkCellRenderer *renderer;
1053
1054 column = gtk_tree_view_column_new();
1055 gtk_tree_view_column_set_title(column, name);
1056 renderer = gtk_cell_renderer_text_new ();
1057 g_object_set(renderer, "xalign", 1.0, NULL);
1058 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1059 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_amount_cell_data_function, GINT_TO_POINTER(id), NULL);
1060 gtk_tree_view_column_set_alignment (column, 0.5);
1061 //gtk_tree_view_column_set_sort_column_id (column, id);
1062 return column;
1063 }
1064
1065
1066 /*
1067 ** create our statistic list
1068 */
1069 static GtkWidget *create_list_repvehicle(void)
1070 {
1071 GtkListStore *store;
1072 GtkWidget *view;
1073 GtkCellRenderer *renderer;
1074 GtkTreeViewColumn *column;
1075
1076 /* create list store */
1077 store = gtk_list_store_new(
1078 NUM_LST_CAR,
1079 G_TYPE_UINT,
1080 G_TYPE_STRING,
1081 G_TYPE_UINT,
1082 G_TYPE_DOUBLE,
1083 G_TYPE_DOUBLE,
1084 G_TYPE_DOUBLE,
1085 G_TYPE_UINT,
1086 G_TYPE_DOUBLE,
1087 G_TYPE_UINT,
1088 G_TYPE_BOOLEAN );
1089
1090 //treeview
1091 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1092 g_object_unref(store);
1093
1094 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), PREFS->grid_lines);
1095
1096 /* column date */
1097 column = gtk_tree_view_column_new();
1098 gtk_tree_view_column_set_title(column, _("Date"));
1099 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1100 renderer = gtk_cell_renderer_text_new();
1101 g_object_set(renderer, "xalign", 1.0, NULL);
1102 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1103 //gtk_tree_view_column_add_attribute(column, renderer, "text", LST_CAR_DATE);
1104 gtk_tree_view_column_set_alignment (column, 0.5);
1105 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_date_cell_data_function, NULL, NULL);
1106
1107 /*
1108 LST_CAR_DATE,
1109 LST_CAR_MEMO,
1110 LST_CAR_METER,
1111 LST_CAR_FUEL,
1112 LST_CAR_PRICE,
1113 LST_CAR_AMOUNT,
1114 LST_CAR_DIST,
1115 LST_CAR_100KM
1116
1117 */
1118
1119 /* column: Memo */
1120 /*
1121 column = gtk_tree_view_column_new();
1122 gtk_tree_view_column_set_title(column, _("Memo"));
1123 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1124 renderer = gtk_cell_renderer_text_new();
1125 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1126 gtk_tree_view_column_add_attribute(column, renderer, "text", LST_CAR_MEMO);
1127 //gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_text_cell_data_function, NULL, NULL);
1128 */
1129
1130 /* column: Meter */
1131 column = distance_list_repvehicle_column(_("Meter"), LST_CAR_METER);
1132 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1133
1134 /* column: Fuel load */
1135 column = volume_list_repvehicle_column(_("Fuel"), LST_CAR_FUEL);
1136 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1137
1138 /* column: Price by unit */
1139 column = amount_list_repvehicle_column(_("Price"), LST_CAR_PRICE);
1140 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1141
1142 /* column: Amount */
1143 column = amount_list_repvehicle_column(_("Amount"), LST_CAR_AMOUNT);
1144 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1145
1146 /* column: Distance done */
1147 column = distance_list_repvehicle_column(_("Dist."), LST_CAR_DIST);
1148 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1149
1150 /* column: consumption for 100Km */
1151 column = volume_list_repvehicle_column(PREFS->vehicle_unit_100, LST_CAR_100KM);
1152 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1153
1154 /* column: km by liter (distance by volume */
1155 column = distance_list_repvehicle_column(PREFS->vehicle_unit_distbyvol, LST_CAR_DISTBYVOL);
1156 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1157
1158
1159 /* column last: empty */
1160 column = gtk_tree_view_column_new();
1161 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1162
1163 return(view);
1164 }
This page took 0.085082 seconds and 4 git commands to generate.