]> Dogcows Code - chaz/homebank/blob - src/rep_vehicle.c
550fd6c478852d2d82aab05b0e5d18fdb024dcd6
[chaz/homebank] / src / rep_vehicle.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2016 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->wording = ope->wording;
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->wording);
323 data->vehicle_list = g_list_append(data->vehicle_list, item);
324 DB( g_print(" -> store acc=%d '%s' %.2f\n", ope->kacc, ope->wording, 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->wording = 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_WORDING , item->wording,
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(2));
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
699 gtk_window_set_title (GTK_WINDOW (window), _("Vehicle cost report"));
700
701 //set the window icon
702 gtk_window_set_icon_name(GTK_WINDOW (window), ICONNAME_HB_REP_CAR);
703
704
705
706 //window contents
707 mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
708 gtk_container_add (GTK_CONTAINER (window), mainvbox);
709
710 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
711 gtk_box_pack_start (GTK_BOX (mainvbox), hbox, TRUE, TRUE, 0);
712
713 //control part
714 table = gtk_grid_new ();
715 gtk_widget_set_hexpand (GTK_WIDGET(table), FALSE);
716 gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0);
717
718 gtk_container_set_border_width (GTK_CONTAINER (table), SPACING_SMALL);
719 gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_SMALL);
720 gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_MEDIUM);
721
722 row = 0;
723 label = make_label_group(_("Display"));
724 gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
725
726 row++;
727 label = make_label_widget(_("Vehi_cle:"));
728 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
729
730 widget = ui_cat_comboboxentry_new(label);
731 data->PO_cat = widget;
732 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
733
734 row++;
735 widget = gtk_check_button_new_with_mnemonic (_("Euro _minor"));
736 data->CM_minor = widget;
737 gtk_grid_attach (GTK_GRID (table), widget, 2, row, 1, 1);
738
739 row++;
740 widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
741 gtk_grid_attach (GTK_GRID (table), widget, 0, row, 3, 1);
742
743 row++;
744 label = make_label_group(_("Date filter"));
745 gtk_grid_attach (GTK_GRID (table), label, 0, row, 3, 1);
746
747 row++;
748 label = make_label_widget(_("_Range:"));
749 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
750 data->CY_range = make_daterange(label, FALSE);
751 gtk_grid_attach (GTK_GRID (table), data->CY_range, 2, row, 1, 1);
752
753 row++;
754 label = make_label_widget(_("_From:"));
755 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
756 data->PO_mindate = gtk_date_entry_new();
757 gtk_grid_attach (GTK_GRID (table), data->PO_mindate, 2, row, 1, 1);
758
759 row++;
760 label = make_label_widget(_("_To:"));
761 gtk_grid_attach (GTK_GRID (table), label, 1, row, 1, 1);
762 data->PO_maxdate = gtk_date_entry_new();
763 gtk_grid_attach (GTK_GRID (table), data->PO_maxdate, 2, row, 1, 1);
764
765
766 //part: info + report
767 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
768 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
769
770 //ui manager
771 actions = gtk_action_group_new ("Account");
772
773 //as we use gettext
774 gtk_action_group_set_translation_domain(actions, GETTEXT_PACKAGE);
775
776 // data to action callbacks is set here (data)
777 gtk_action_group_add_actions (actions, entries, n_entries, data);
778
779 /* set which action should have priority in the toolbar */
780 action = gtk_action_group_get_action(actions, "Refresh");
781 g_object_set(action, "is_important", TRUE, NULL);
782
783
784 ui = gtk_ui_manager_new ();
785 gtk_ui_manager_insert_action_group (ui, actions, 0);
786 gtk_window_add_accel_group (GTK_WINDOW (window), gtk_ui_manager_get_accel_group (ui));
787
788 if (!gtk_ui_manager_add_ui_from_string (ui, ui_info, -1, &error))
789 {
790 g_message ("building UI failed: %s", error->message);
791 g_error_free (error);
792 }
793
794 data->ui = ui;
795 data->actions = actions;
796
797 //toolbar
798 data->TB_bar = gtk_ui_manager_get_widget (ui, "/ToolBar");
799 gtk_box_pack_start (GTK_BOX (vbox), data->TB_bar, FALSE, FALSE, 0);
800
801
802 // total
803 table = gtk_grid_new ();
804 gtk_widget_set_hexpand (GTK_WIDGET(table), FALSE);
805 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
806
807 gtk_container_set_border_width (GTK_CONTAINER (table), SPACING_SMALL);
808 gtk_grid_set_row_spacing (GTK_GRID (table), SPACING_SMALL);
809 gtk_grid_set_column_spacing (GTK_GRID (table), SPACING_MEDIUM);
810
811 row = 0; col = 1;
812
813 label = make_label_widget(_("Meter:"));
814 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
815
816 col++;
817 label = make_label_widget(_("Consumption:"));
818 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
819
820 col++;
821 label = make_label_widget(_("Fuel cost:"));
822 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
823
824 col++;
825 label = make_label_widget(_("Other cost:"));
826 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
827
828 col++;
829 label = make_label_widget(_("Total cost:"));
830 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
831
832 row++;
833 col = 0;
834 label = make_label_widget(PREFS->vehicle_unit_100);
835 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
836
837 for(col = 1;col<MAX_CAR_RES;col++)
838 {
839 label = make_label(NULL, 1.0, 0.5);
840 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
841 data->LA_avera[col] = label;
842 }
843
844 row++;
845 col = 0;
846 label = make_label_widget(_("Total"));
847 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
848
849 for(col = 1;col<MAX_CAR_RES;col++)
850 {
851 label = make_label(NULL, 1.0, 0.5);
852 gtk_grid_attach (GTK_GRID (table), label, col, row, 1, 1);
853 data->LA_total[col] = label;
854 }
855
856
857 //detail
858 widget = gtk_scrolled_window_new (NULL, NULL);
859 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_ETCHED_IN);
860 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
861
862 treeview = create_list_repvehicle();
863 data->LV_report = treeview;
864 gtk_container_add (GTK_CONTAINER(widget), treeview);
865 gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
866
867
868 //todo:should move this
869 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_minor),GLOBALS->minor);
870
871
872
873 /* attach our minor to treeview */
874 g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report))), "minor", (gpointer)data->CM_minor);
875
876
877
878 /* signal connect */
879 g_signal_connect (window, "delete-event", G_CALLBACK (repvehicle_window_dispose), (gpointer)data);
880
881 g_signal_connect (data->CM_minor, "toggled", G_CALLBACK (repvehicle_toggle_minor), NULL);
882
883 data->handler_id[HID_REPVEHICLE_MINDATE] = g_signal_connect (data->PO_mindate, "changed", G_CALLBACK (repvehicle_date_change), (gpointer)data);
884 data->handler_id[HID_REPVEHICLE_MAXDATE] = g_signal_connect (data->PO_maxdate, "changed", G_CALLBACK (repvehicle_date_change), (gpointer)data);
885
886 data->handler_id[HID_REPVEHICLE_RANGE] = g_signal_connect (data->CY_range, "changed", G_CALLBACK (repvehicle_range_change), NULL);
887
888 data->handler_id[HID_REPVEHICLE_VEHICLE] = g_signal_connect (data->PO_cat, "changed", G_CALLBACK (repvehicle_compute), NULL);
889
890
891 //setup, init and show window
892 repvehicle_setup(data);
893
894 /* toolbar */
895 /*
896 if(PREFS->toolbar_style == 0)
897 gtk_toolbar_unset_style(GTK_TOOLBAR(data->TB_bar));
898 else
899 gtk_toolbar_set_style(GTK_TOOLBAR(data->TB_bar), PREFS->toolbar_style-1);
900 */
901
902 //setup, init and show window
903 wg = &PREFS->cst_wg;
904 gtk_window_move(GTK_WINDOW(window), wg->l, wg->t);
905 gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h);
906
907 gtk_widget_show_all (window);
908
909 //minor ?
910 if( PREFS->euro_active )
911 gtk_widget_show(data->CM_minor);
912 else
913 gtk_widget_hide(data->CM_minor);
914
915
916
917 if( PREFS->date_range_rep )
918 gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_range), PREFS->date_range_rep);
919 else
920 repvehicle_compute(window, NULL);
921
922 return(window);
923 }
924
925 /*
926 ** ============================================================================
927 */
928
929 static void repvehicle_date_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
930 {
931 GDate *date;
932 guint32 julian;
933 gchar buf[256];
934
935 gtk_tree_model_get(model, iter,
936 LST_CAR_DATE, &julian,
937 -1);
938
939 date = g_date_new_julian (julian);
940 g_date_strftime (buf, 256-1, PREFS->date_format, date);
941 g_date_free(date);
942
943 g_object_set(renderer, "text", buf, NULL);
944 }
945
946 static void repvehicle_distance_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
947 {
948 guint distance;
949 gchar *text;
950
951 gtk_tree_model_get(model, iter, user_data, &distance, -1);
952
953 if(distance != 0)
954 {
955 text = g_strdup_printf(PREFS->vehicle_unit_dist, distance);
956 g_object_set(renderer, "text", text, NULL);
957 g_free(text);
958 }
959 else
960 g_object_set(renderer, "text", "-", NULL);
961 }
962
963 static void repvehicle_volume_cell_data_function (GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
964 {
965 gdouble volume;
966 gboolean partial;
967 gchar *text;
968
969 gtk_tree_model_get(model, iter, user_data, &volume, LST_CAR_PARTIAL, &partial, -1);
970
971 if(volume != 0)
972 {
973 text = g_strdup_printf(PREFS->vehicle_unit_vol, volume);
974 g_object_set(renderer,
975 "text", text,
976 "style-set", TRUE,
977 "style", partial ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL,
978 NULL);
979
980 g_free(text);
981 }
982 else
983 g_object_set(renderer, "text", "-", NULL);
984 }
985
986 static void repvehicle_amount_cell_data_function (GtkTreeViewColumn *col,
987 GtkCellRenderer *renderer,
988 GtkTreeModel *model,
989 GtkTreeIter *iter,
990 gpointer user_data)
991 {
992 gdouble value;
993 gchar *color;
994 gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
995
996 gtk_tree_model_get(model, iter,
997 user_data, &value,
998 -1);
999
1000 if( value )
1001 {
1002 hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, value, GLOBALS->kcur, GLOBALS->minor);
1003
1004 color = get_normal_color_amount(value);
1005
1006 g_object_set(renderer,
1007 "foreground", color,
1008 "text", buf,
1009 NULL); }
1010 else
1011 {
1012 g_object_set(renderer, "text", "", NULL);
1013 }
1014 }
1015
1016 static GtkTreeViewColumn *volume_list_repvehicle_column(gchar *name, gint id)
1017 {
1018 GtkTreeViewColumn *column;
1019 GtkCellRenderer *renderer;
1020
1021 column = gtk_tree_view_column_new();
1022 gtk_tree_view_column_set_title(column, name);
1023 renderer = gtk_cell_renderer_text_new ();
1024 g_object_set(renderer, "xalign", 1.0, NULL);
1025 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1026 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_volume_cell_data_function, GINT_TO_POINTER(id), NULL);
1027 gtk_tree_view_column_set_alignment (column, 0.5);
1028 //gtk_tree_view_column_set_sort_column_id (column, id);
1029 return column;
1030 }
1031
1032 static GtkTreeViewColumn *distance_list_repvehicle_column(gchar *name, gint id)
1033 {
1034 GtkTreeViewColumn *column;
1035 GtkCellRenderer *renderer;
1036
1037 column = gtk_tree_view_column_new();
1038 gtk_tree_view_column_set_title(column, name);
1039 renderer = gtk_cell_renderer_text_new ();
1040 g_object_set(renderer, "xalign", 1.0, NULL);
1041 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1042 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_distance_cell_data_function, GINT_TO_POINTER(id), NULL);
1043 gtk_tree_view_column_set_alignment (column, 0.5);
1044 //gtk_tree_view_column_set_sort_column_id (column, id);
1045 return column;
1046 }
1047
1048 static GtkTreeViewColumn *amount_list_repvehicle_column(gchar *name, gint id)
1049 {
1050 GtkTreeViewColumn *column;
1051 GtkCellRenderer *renderer;
1052
1053 column = gtk_tree_view_column_new();
1054 gtk_tree_view_column_set_title(column, name);
1055 renderer = gtk_cell_renderer_text_new ();
1056 g_object_set(renderer, "xalign", 1.0, NULL);
1057 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1058 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_amount_cell_data_function, GINT_TO_POINTER(id), NULL);
1059 gtk_tree_view_column_set_alignment (column, 0.5);
1060 //gtk_tree_view_column_set_sort_column_id (column, id);
1061 return column;
1062 }
1063
1064
1065 /*
1066 ** create our statistic list
1067 */
1068 static GtkWidget *create_list_repvehicle(void)
1069 {
1070 GtkListStore *store;
1071 GtkWidget *view;
1072 GtkCellRenderer *renderer;
1073 GtkTreeViewColumn *column;
1074
1075 /* create list store */
1076 store = gtk_list_store_new(
1077 NUM_LST_CAR,
1078 G_TYPE_UINT,
1079 G_TYPE_STRING,
1080 G_TYPE_UINT,
1081 G_TYPE_DOUBLE,
1082 G_TYPE_DOUBLE,
1083 G_TYPE_DOUBLE,
1084 G_TYPE_UINT,
1085 G_TYPE_DOUBLE,
1086 G_TYPE_UINT,
1087 G_TYPE_BOOLEAN );
1088
1089 //treeview
1090 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
1091 g_object_unref(store);
1092
1093 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), PREFS->grid_lines);
1094
1095 /* column date */
1096 column = gtk_tree_view_column_new();
1097 gtk_tree_view_column_set_title(column, _("Date"));
1098 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1099 renderer = gtk_cell_renderer_text_new();
1100 g_object_set(renderer, "xalign", 1.0, NULL);
1101 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1102 //gtk_tree_view_column_add_attribute(column, renderer, "text", LST_CAR_DATE);
1103 gtk_tree_view_column_set_alignment (column, 0.5);
1104 gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_date_cell_data_function, NULL, NULL);
1105
1106 /*
1107 LST_CAR_DATE,
1108 LST_CAR_WORDING,
1109 LST_CAR_METER,
1110 LST_CAR_FUEL,
1111 LST_CAR_PRICE,
1112 LST_CAR_AMOUNT,
1113 LST_CAR_DIST,
1114 LST_CAR_100KM
1115
1116 */
1117
1118 /* column: Wording */
1119 /*
1120 column = gtk_tree_view_column_new();
1121 gtk_tree_view_column_set_title(column, _("Wording"));
1122 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1123 renderer = gtk_cell_renderer_text_new();
1124 gtk_tree_view_column_pack_start(column, renderer, TRUE);
1125 gtk_tree_view_column_add_attribute(column, renderer, "text", LST_CAR_WORDING);
1126 //gtk_tree_view_column_set_cell_data_func(column, renderer, repvehicle_text_cell_data_function, NULL, NULL);
1127 */
1128
1129 /* column: Meter */
1130 column = distance_list_repvehicle_column(_("Meter"), LST_CAR_METER);
1131 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1132
1133 /* column: Fuel load */
1134 column = volume_list_repvehicle_column(_("Fuel"), LST_CAR_FUEL);
1135 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1136
1137 /* column: Price by unit */
1138 column = amount_list_repvehicle_column(_("Price"), LST_CAR_PRICE);
1139 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1140
1141 /* column: Amount */
1142 column = amount_list_repvehicle_column(_("Amount"), LST_CAR_AMOUNT);
1143 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1144
1145 /* column: Distance done */
1146 column = distance_list_repvehicle_column(_("Dist."), LST_CAR_DIST);
1147 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1148
1149 /* column: consumption for 100Km */
1150 column = volume_list_repvehicle_column(PREFS->vehicle_unit_100, LST_CAR_100KM);
1151 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1152
1153 /* column: km by liter (distance by volume */
1154 column = distance_list_repvehicle_column(PREFS->vehicle_unit_distbyvol, LST_CAR_DISTBYVOL);
1155 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1156
1157
1158 /* column last: empty */
1159 column = gtk_tree_view_column_new();
1160 gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1161
1162 return(view);
1163 }
This page took 0.082838 seconds and 4 git commands to generate.