1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2016 Maxime DOYEN
4 * This file is part of HomeBank.
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.
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.
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/>.
23 #include "rep_budget.h"
25 #include "list_operation.h"
26 #include "gtk-chart-stack.h"
27 #include "gtk-dateentry.h"
29 #include "dsp_mainwindow.h"
30 #include "ui-transaction.h"
33 /****************************************************************************/
35 /****************************************************************************/
46 /* our global datas */
47 extern struct HomeBank
*GLOBALS
;
48 extern struct Preferences
*PREFS
;
51 static void repbudget_action_viewlist(GtkAction
*action
, gpointer user_data
);
52 static void repbudget_action_viewbar(GtkAction
*action
, gpointer user_data
);
53 static void repbudget_action_detail(GtkAction
*action
, gpointer user_data
);
54 static void repbudget_action_refresh(GtkAction
*action
, gpointer user_data
);
55 static void repbudget_action_export(GtkAction
*action
, gpointer user_data
);
57 static void repbudget_date_change(GtkWidget
*widget
, gpointer user_data
);
58 static void repbudget_range_change(GtkWidget
*widget
, gpointer user_data
);
59 static void repbudget_toggle_detail(GtkWidget
*widget
, gpointer user_data
);
60 static void repbudget_detail(GtkWidget
*widget
, gpointer user_data
);
61 static void repbudget_compute(GtkWidget
*widget
, gpointer user_data
);
62 static void repbudget_update_total(GtkWidget
*widget
, gpointer user_data
);
63 static void repbudget_sensitive(GtkWidget
*widget
, gpointer user_data
);
64 static void repbudget_toggle(GtkWidget
*widget
, gpointer user_data
);
65 static GtkWidget
*create_list_budget(void);
66 static void repbudget_update_detail(GtkWidget
*widget
, gpointer user_data
);
67 static void repbudget_update_daterange(GtkWidget
*widget
, gpointer user_data
);
68 static void repbudget_export_csv(GtkWidget
*widget
, gpointer user_data
);
70 gchar
*CYA_BUDGSELECT
[] = { N_("Category"), N_("Subcategory"), NULL
};
72 gchar
*CYA_KIND
[] = { N_("Exp. & Inc."), N_("Expense"), N_("Income"), NULL
};
74 gchar
*CYA_BUDGETSELECT
[] = { N_("Spent & Budget"), N_("Spent"), N_("Budget"), N_("Result"), NULL
};
77 //extern gchar *CYA_FLT_SELECT[];
79 static GtkActionEntry entries
[] = {
80 { "List" , ICONNAME_HB_VIEW_LIST
, N_("List") , NULL
, N_("View results as list"), G_CALLBACK (repbudget_action_viewlist
) },
81 { "Stack" , ICONNAME_HB_VIEW_STACK
, N_("Stack") , NULL
, N_("View results as stack bars"), G_CALLBACK (repbudget_action_viewbar
) },
82 { "Refresh" , ICONNAME_REFRESH
, N_("Refresh"), NULL
, N_("Refresh results"), G_CALLBACK (repbudget_action_refresh
) },
84 { "Export" , ICONNAME_HB_FILE_EXPORT
, N_("Export") , NULL
, N_("Export as CSV"), G_CALLBACK (repbudget_action_export
) },
86 static guint n_entries
= G_N_ELEMENTS (entries
);
89 static GtkToggleActionEntry toggle_entries
[] = {
90 { "Detail", ICONNAME_HB_OPE_SHOW
, /* name, icon-name */
91 N_("Detail"), NULL
, /* label, accelerator */
92 N_("Toggle detail"), /* tooltip */
93 G_CALLBACK (repbudget_action_detail
),
94 FALSE
}, /* is_active */
97 static guint n_toggle_entries
= G_N_ELEMENTS (toggle_entries
);
100 static const gchar
*ui_info
=
102 " <toolbar name='ToolBar'>"
103 " <toolitem action='List'/>"
104 " <toolitem action='Stack'/>"
106 " <toolitem action='Detail'/>"
108 " <toolitem action='Refresh'/>"
110 " <toolitem action='Export'/>"
116 /* action functions -------------------- */
117 static void repbudget_action_viewlist(GtkAction
*action
, gpointer user_data
)
119 struct repbudget_data
*data
= user_data
;
121 gtk_notebook_set_current_page(GTK_NOTEBOOK(data
->GR_result
), 0);
122 repbudget_sensitive(data
->window
, NULL
);
125 static void repbudget_action_viewbar(GtkAction
*action
, gpointer user_data
)
127 struct repbudget_data
*data
= user_data
;
129 gtk_notebook_set_current_page(GTK_NOTEBOOK(data
->GR_result
), 1);
130 repbudget_sensitive(data
->window
, NULL
);
133 static void repbudget_action_detail(GtkAction
*action
, gpointer user_data
)
135 struct repbudget_data
*data
= user_data
;
137 repbudget_toggle_detail(data
->window
, NULL
);
141 static void repbudget_action_refresh(GtkAction
*action
, gpointer user_data
)
143 struct repbudget_data
*data
= user_data
;
145 repbudget_compute(data
->window
, NULL
);
148 static void repbudget_action_export(GtkAction
*action
, gpointer user_data
)
150 struct repbudget_data
*data
= user_data
;
152 repbudget_export_csv(data
->window
, NULL
);
155 /* ======================== */
158 static gint
getmonth(guint date
)
163 date1
= g_date_new_julian(date
);
164 month
= g_date_get_month(date1
);
167 g_print("\n[repbudget] getmonth\n");
169 g_date_strftime (buffer1, 128-1, "%x", date1);
170 g_print(" date is '%s', month=%d\n", buffer1, month);
178 static gint
countmonth(guint32 mindate
, guint32 maxdate
)
180 GDate
*date1
, *date2
;
183 date1
= g_date_new_julian(mindate
);
184 date2
= g_date_new_julian(maxdate
);
187 while(g_date_compare(date1
, date2
) < 0)
190 g_date_add_months(date1
, 1);
199 static gdouble
budget_compute_result(gdouble budget
, gdouble spent
)
204 //result = ABS(budget) - ABS(spent);
206 retval
= spent
- budget
;
215 static void repbudget_date_change(GtkWidget
*widget
, gpointer user_data
)
217 struct repbudget_data
*data
;
219 DB( g_print("\n[repbudget] date change\n") );
221 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
223 data
->filter
->mindate
= gtk_date_entry_get_date(GTK_DATE_ENTRY(data
->PO_mindate
));
224 data
->filter
->maxdate
= gtk_date_entry_get_date(GTK_DATE_ENTRY(data
->PO_maxdate
));
226 // set min/max date for both widget
227 gtk_date_entry_set_maxdate(GTK_DATE_ENTRY(data
->PO_mindate
), data
->filter
->maxdate
);
228 gtk_date_entry_set_mindate(GTK_DATE_ENTRY(data
->PO_maxdate
), data
->filter
->mindate
);
230 g_signal_handler_block(data
->CY_range
, data
->handler_id
[HID_REPBUDGET_RANGE
]);
231 gtk_combo_box_set_active(GTK_COMBO_BOX(data
->CY_range
), FLT_RANGE_OTHER
);
232 g_signal_handler_unblock(data
->CY_range
, data
->handler_id
[HID_REPBUDGET_RANGE
]);
235 repbudget_compute(widget
, NULL
);
236 repbudget_update_daterange(widget
, NULL
);
241 static void repbudget_range_change(GtkWidget
*widget
, gpointer user_data
)
243 struct repbudget_data
*data
;
246 DB( g_print("\n[repbudget] range change\n") );
248 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
250 range
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->CY_range
));
253 if(range
!= FLT_RANGE_OTHER
)
255 filter_preset_daterange_set(data
->filter
, range
, 0);
257 g_signal_handler_block(data
->PO_mindate
, data
->handler_id
[HID_REPBUDGET_MINDATE
]);
258 g_signal_handler_block(data
->PO_maxdate
, data
->handler_id
[HID_REPBUDGET_MAXDATE
]);
260 gtk_date_entry_set_date(GTK_DATE_ENTRY(data
->PO_mindate
), data
->filter
->mindate
);
261 gtk_date_entry_set_date(GTK_DATE_ENTRY(data
->PO_maxdate
), data
->filter
->maxdate
);
263 g_signal_handler_unblock(data
->PO_mindate
, data
->handler_id
[HID_REPBUDGET_MINDATE
]);
264 g_signal_handler_unblock(data
->PO_maxdate
, data
->handler_id
[HID_REPBUDGET_MAXDATE
]);
266 repbudget_compute(widget
, NULL
);
267 repbudget_update_daterange(widget
, NULL
);
272 static void repbudget_update_daterange(GtkWidget
*widget
, gpointer user_data
)
274 struct repbudget_data
*data
;
277 DB( g_print("\n[repbudget] update daterange\n") );
279 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
281 daterange
= filter_daterange_text_get(data
->filter
);
282 gtk_label_set_markup(GTK_LABEL(data
->TX_daterange
), daterange
);
287 static void repbudget_toggle_detail(GtkWidget
*widget
, gpointer user_data
)
289 struct repbudget_data
*data
;
291 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
293 DB( g_print("\n[repbudget] toggle detail\n") );
297 repbudget_update_detail(widget
, user_data
);
302 static void repbudget_detail_onRowActivated (GtkTreeView
*treeview
,
304 GtkTreeViewColumn
*col
,
307 struct repbudget_data
*data
;
308 Transaction
*active_txn
;
311 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GTK_WIDGET(treeview
), GTK_TYPE_WINDOW
)), "inst_data");
313 DB( g_print ("\n[repbudget] A detail row has been double-clicked!\n") );
315 active_txn
= list_txn_get_active_transaction(GTK_TREE_VIEW(data
->LV_detail
));
318 Transaction
*old_txn
, *new_txn
;
320 old_txn
= da_transaction_clone (active_txn
);
321 new_txn
= active_txn
;
322 result
= deftransaction_external_edit(GTK_WINDOW(data
->window
), old_txn
, new_txn
);
324 if(result
== GTK_RESPONSE_ACCEPT
)
327 GLOBALS
->changes_count
++;
328 repbudget_compute(data
->window
, NULL
);
331 da_transaction_free (old_txn
);
336 static void repbudget_update_detail(GtkWidget
*widget
, gpointer user_data
)
338 struct repbudget_data
*data
;
340 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
342 DB( g_print("\n[repbudget] update detail\n") );
344 if(GTK_IS_TREE_VIEW(data
->LV_report
))
348 GtkTreeSelection
*treeselection
;
353 treeselection
= gtk_tree_view_get_selection (GTK_TREE_VIEW(data
->LV_report
));
355 if (gtk_tree_selection_get_selected(treeselection
, &model
, &iter
))
357 gtk_tree_model_get(model
, &iter
, LST_BUDGET_KEY
, &key
, -1);
359 //DB( g_print(" - active is %d\n", pos) );
361 repbudget_detail(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection
)), GINT_TO_POINTER(key
));
365 gtk_widget_show(data
->GR_detail
);
368 gtk_widget_hide(data
->GR_detail
);
375 static void repbudget_export_csv(GtkWidget
*widget
, gpointer user_data
)
377 struct repbudget_data
*data
;
381 gchar
*filename
= NULL
;
383 gchar
*outstr
, *name
;
386 DB( g_print("\n[repbudget] export csv\n") );
388 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
390 tmpfor
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->CY_for
));
392 name
= g_strdup_printf("hb-budget_%s.csv", CYA_BUDGSELECT
[tmpfor
]);
394 if( ui_file_chooser_csv(GTK_WINDOW(data
->window
), GTK_FILE_CHOOSER_ACTION_SAVE
, &filename
, name
) == TRUE
)
396 DB( g_print(" + filename is %s\n", filename
) );
398 io
= g_io_channel_new_file(filename
, "w", NULL
);
402 outstr
= g_strdup_printf("%s;%s;%s;%s;\n", _("Category"), _("Spent"), _("Budget"), _("Result"));
403 g_io_channel_write_chars(io
, outstr
, -1, NULL
, NULL
);
405 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_report
));
406 valid
= gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model
), &iter
);
409 gchar
*name
, *status
;
410 gdouble spent
, budget
, result
;
412 gtk_tree_model_get (model
, &iter
,
413 //LST_REPDIST_KEY, i,
414 LST_BUDGET_NAME
, &name
,
415 LST_BUDGET_SPENT
, &spent
,
416 LST_BUDGET_BUDGET
, &budget
,
417 LST_BUDGET_RESULT
, &result
,
418 LST_BUDGET_STATUS
, &status
,
421 outstr
= g_strdup_printf("%s;%.2f;%.2f;%.2f;%s\n", name
, spent
, budget
, result
, status
);
422 g_io_channel_write_chars(io
, outstr
, -1, NULL
, NULL
);
424 DB( g_print("%s", outstr
) );
428 valid
= gtk_tree_model_iter_next(GTK_TREE_MODEL(model
), &iter
);
431 g_io_channel_unref (io
);
443 static void repbudget_detail(GtkWidget
*widget
, gpointer user_data
)
445 struct repbudget_data
*data
;
446 guint active
= GPOINTER_TO_INT(user_data
);
452 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
454 DB( g_print("\n[repbudget] detail\n") );
458 /* clear and detach our model */
459 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_detail
));
460 gtk_list_store_clear (GTK_LIST_STORE(model
));
461 g_object_ref(model
); /* Make sure the model stays with us after the tree view unrefs it */
462 gtk_tree_view_set_model(GTK_TREE_VIEW(data
->LV_detail
), NULL
); /* Detach model from view */
464 tmpfor
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->CY_for
));
466 /* fill in the model */
467 list
= g_queue_peek_head_link(data
->txn_queue
);
471 Transaction
*ope
= list
->data
;
473 gboolean insert
= FALSE
;
475 //DB( g_print(" get %s\n", ope->ope_Word) );
477 acc
= da_acc_get(ope
->kacc
);
480 if((acc
->flags
& AF_NOBUDGET
)) goto next1
;
484 if( ope
->flags
& OF_SPLIT
)
486 guint nbsplit
= da_splits_count(ope
->splits
);
490 for(i
=0;i
<nbsplit
;i
++)
492 split
= ope
->splits
[i
];
497 Category
*catentry
= da_cat_get(split
->kcat
);
499 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
502 case BUDG_SUBCATEGORY
:
508 { insert
= TRUE
; break; }
517 Category
*catentry
= da_cat_get(ope
->kcat
);
519 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
522 case BUDG_SUBCATEGORY
:
535 gtk_list_store_append (GTK_LIST_STORE(model
), &iter
);
536 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
,
537 LST_DSPOPE_DATAS
, ope
,
543 list
= g_list_next(list
);
546 /* Re-attach model to view */
547 gtk_tree_view_set_model(GTK_TREE_VIEW(data
->LV_detail
), model
);
548 g_object_unref(model
);
550 gtk_tree_view_columns_autosize( GTK_TREE_VIEW(data
->LV_detail
) );
557 static void repbudget_compute(GtkWidget
*widget
, gpointer user_data
)
559 struct repbudget_data
*data
;
561 gint tmpfor
, tmpkind
;
562 guint32 mindate
, maxdate
;
568 gdouble
*tmp_spent
, *tmp_budget
;
572 DB( g_print("\n[repbudget] compute\n") );
574 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
576 tmpfor
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->CY_for
));
577 tmpkind
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->CY_kind
));
579 mindate
= data
->filter
->mindate
;
580 maxdate
= data
->filter
->maxdate
;
581 if(maxdate
< mindate
) return;
583 g_queue_free (data
->txn_queue
);
584 data
->txn_queue
= hbfile_transaction_get_partial(data
->filter
->mindate
, data
->filter
->maxdate
);
587 DB( g_print(" for=%d, kind=%d\n", tmpfor
, tmpkind
) );
589 nbmonth
= countmonth(mindate
, maxdate
);
590 DB( g_print(" date: min=%d max=%d nbmonth=%d\n", mindate
, maxdate
, nbmonth
) );
592 n_result
= da_cat_get_max_key();
593 DB( g_print(" nbcat=%d\n", n_result
) );
595 /* allocate some memory */
596 tmp_spent
= g_malloc0((n_result
+1) * sizeof(gdouble
));
597 tmp_budget
= g_malloc0((n_result
+1) * sizeof(gdouble
));
599 if(tmp_spent
&& tmp_budget
)
602 /* compute the results */
603 data
->total_spent
= 0.0;
604 data
->total_budget
= 0.0;
606 /* compute budget for each category */
607 DB( g_print("\n+ compute budget\n") );
609 //fixed #328034: here <=n_result
610 for(i
=1; i
<=n_result
; i
++)
616 entry
= da_cat_get(i
);
620 DB( g_print(" category %d:'%s' issub=%d hasbudget=%d custom=%d\n",
621 entry
->key
, entry
->name
, (entry
->flags
& GF_SUB
), (entry
->flags
& GF_BUDGET
), (entry
->flags
& GF_CUSTOM
)) );
626 g_print(" budget vector: ");
628 g_print( " %d:[%.2f]", k
, entry
->budget
[k
]);
637 Category
*catentry
= da_cat_get(i
);
639 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
642 case BUDG_SUBCATEGORY
:
647 // same value each month ?
648 if(!(entry
->flags
& GF_CUSTOM
))
650 DB( g_print(" - monthly %.2f\n", entry
->budget
[0]) );
651 tmp_budget
[pos
] += entry
->budget
[0]*nbmonth
;
653 //otherwise sum each month from mindate month
656 gint month
= getmonth(mindate
);
659 DB( g_print(" - custom each month for %d months\n", nbmonth
) );
660 for(j
=0;j
<nbmonth
;j
++) {
661 DB( g_print(" j=%d month=%d budg=%.2f\n", j
, month
, entry
->budget
[month
]) );
662 tmp_budget
[pos
] += entry
->budget
[month
];
672 g_print(" final budget: %d:'%s' : budg[%d]=%.2f\n", entry
->key
, entry
->name
, pos
, tmp_budget
[pos
] );
677 // compute spent for each transaction */
678 DB( g_print("\n+ compute spent from transactions\n") );
681 list
= g_queue_peek_head_link(data
->txn_queue
);
684 Transaction
*ope
= list
->data
;
688 //DB( g_print("%d, get ope: %s :: acc=%d, cat=%d, mnt=%.2f\n", i, ope->wording, ope->account, ope->category, ope->amount) );
690 if( ope
->flags
& OF_SPLIT
)
692 guint nbsplit
= da_splits_count(ope
->splits
);
695 for(i
=0;i
<nbsplit
;i
++)
697 split
= ope
->splits
[i
];
702 Category
*catentry
= da_cat_get(split
->kcat
);
704 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
707 case BUDG_SUBCATEGORY
:
712 //trn_amount = split->amount;
713 trn_amount
= hb_amount_base(split
->amount
, ope
->kcur
);
715 DB( g_print(" -> affecting split %.2f to cat pos %d\n", trn_amount
, pos
) );
717 tmp_spent
[pos
] += trn_amount
;
727 Category
*catentry
= da_cat_get(ope
->kcat
);
729 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
732 case BUDG_SUBCATEGORY
:
737 //trn_amount = ope->amount;
738 trn_amount
= hb_amount_base(ope
->amount
, ope
->kcur
);
740 DB( g_print(" -> affecting %.2f to cat pos %d\n", trn_amount
, pos
) );
742 tmp_spent
[pos
] += trn_amount
;
746 list
= g_list_next(list
);
750 DB( g_print("\nclear and detach model\n") );
752 /* clear and detach our model */
753 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_report
));
754 gtk_list_store_clear (GTK_LIST_STORE(model
));
755 g_object_ref(model
); /* Make sure the model stays with us after the tree view unrefs it */
756 gtk_tree_view_set_model(GTK_TREE_VIEW(data
->LV_report
), NULL
); /* Detach model from view */
758 DB( g_print("\n+ insert into treeview\n") );
760 /* insert into the treeview */
761 for(i
=1, id
=0; i
<=n_result
; i
++)
763 gchar
*name
, *fullcatname
;
768 entry
= da_cat_get(i
);
772 if(entry
->flags
& GF_SUB
)
774 Category
*parent
= da_cat_get( entry
->parent
);
776 fullcatname
= g_strdup_printf("%s:%s", parent
->name
, entry
->name
);
782 if(name
== NULL
) name
= "(None)";
785 //if( (tmpfor == BUDG_CATEGORY && !(entry->flags & GF_SUB)) || (tmpfor == BUDG_SUBCATEGORY) )
786 if( (tmpfor
== BUDG_CATEGORY
&& !(entry
->flags
& GF_SUB
)) || (tmpfor
== BUDG_SUBCATEGORY
&& (entry
->flags
& GF_SUB
)) )
795 Category
*catentry
= da_cat_get(i
);
797 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
800 case BUDG_SUBCATEGORY
:
805 // display expense or income (filter on amount and not category hypothetical flag
806 //if( tmpkind != (entry->flags & GF_INCOME)) continue;
807 if( tmpkind
== 1 && tmp_budget
[pos
] > 0)
810 if( tmpkind
== 2 && tmp_budget
[pos
] < 0)
813 DB( g_print(" eval %d '%s' : spen=%.2f bud=%.2f \n", i
, name
, tmp_spent
[pos
], tmp_budget
[pos
] ) );
815 if((entry
->flags
& (GF_BUDGET
|GF_FORCED
)) || tmp_budget
[pos
] /*|| tmp_spent[pos]*/)
817 gdouble result
, rawrate
;
820 result
= budget_compute_result(tmp_budget
[pos
], tmp_spent
[pos
]);
822 if(ABS(tmp_budget
[pos
]) > 0)
824 rawrate
= tmp_spent
[pos
] / tmp_budget
[pos
];
826 else if(tmp_budget
[pos
] == 0.0)
827 rawrate
= ABS(tmp_spent
[pos
]);
836 if(tmp_budget
[pos
] < 0.0)
838 else if(tmp_budget
[pos
] > 0.0)
839 status
= _(" under");
842 DB( g_print(" => insert %.2f | %.2f = %.2f '%s'\n", tmp_spent
[pos
], tmp_budget
[pos
], result
, status
) );
844 gtk_list_store_append (GTK_LIST_STORE(model
), &iter
);
845 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
,
846 LST_BUDGET_POS
, id
++,
848 LST_BUDGET_NAME
, name
,
849 LST_BUDGET_SPENT
, tmp_spent
[pos
],
850 LST_BUDGET_BUDGET
, tmp_budget
[pos
],
851 LST_BUDGET_RESULT
, result
,
852 LST_BUDGET_STATUS
, status
,
855 data
->total_spent
+= tmp_spent
[pos
];
856 data
->total_budget
+= tmp_budget
[pos
];
864 /* update column 0 title */
865 GtkTreeViewColumn
*column
= gtk_tree_view_get_column( GTK_TREE_VIEW(data
->LV_report
), 0);
866 gtk_tree_view_column_set_title(column
, _(CYA_BUDGSELECT
[tmpfor
]));
868 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data
->LV_report
));
870 /* Re-attach model to view */
871 gtk_tree_view_set_model(GTK_TREE_VIEW(data
->LV_report
), model
);
872 g_object_unref(model
);
875 repbudget_update_total(widget
, NULL
);
877 /* update stack chart */
878 title
= g_strdup_printf(_("Budget for %s"), _(CYA_BUDGSELECT
[tmpfor
]) );
880 ui_chart_stack_set_currency(GTK_CHARTSTACK(data
->RE_stack
), GLOBALS
->kcur
);
882 /* set chart color scheme */
883 ui_chart_stack_set_color_scheme(GTK_CHARTSTACK(data
->RE_stack
), PREFS
->report_color_scheme
);
884 ui_chart_stack_set_dualdatas(GTK_CHARTSTACK(data
->RE_stack
), model
, _("Budget"), _("Result"), title
, NULL
);
889 //DB( g_print(" inserting %i, %f %f\n", i, total_expense, total_income) );
891 /* free our memory */
898 static void repbudget_update_total(GtkWidget
*widget
, gpointer user_data
)
900 struct repbudget_data
*data
;
902 DB( g_print("\n[repbudget] update total\n") );
904 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
906 GLOBALS
->minor
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data
->CM_minor
));
908 hb_label_set_colvalue(GTK_LABEL(data
->TX_total
[0]), data
->total_spent
, GLOBALS
->kcur
, GLOBALS
->minor
);
909 hb_label_set_colvalue(GTK_LABEL(data
->TX_total
[1]), data
->total_budget
, GLOBALS
->kcur
, GLOBALS
->minor
);
910 hb_label_set_colvalue(GTK_LABEL(data
->TX_total
[2]), budget_compute_result(data
->total_budget
, data
->total_spent
), GLOBALS
->kcur
, GLOBALS
->minor
);
917 ** update sensitivity
919 static void repbudget_sensitive(GtkWidget
*widget
, gpointer user_data
)
921 struct repbudget_data
*data
;
926 DB( g_print("\n[repbudget] sensitive\n") );
928 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
930 active
= gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data
->LV_report
)), NULL
, NULL
);
932 page
= gtk_notebook_get_current_page(GTK_NOTEBOOK(data
->GR_result
));
934 sensitive
= page
== 0 ? active
: FALSE
;
935 // gtk_widget_set_sensitive(data->TB_buttons[ACTION_REPBUDGET_DETAIL], sensitive);
936 gtk_action_set_sensitive(gtk_ui_manager_get_action(data
->ui
, "/ToolBar/Detail"), sensitive
);
941 static void repbudget_toggle(GtkWidget
*widget
, gpointer user_data
)
943 struct repbudget_data
*data
;
946 DB( g_print("\n[repbudget] toggle\n") );
948 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
950 repbudget_update_total(widget
, NULL
);
952 //hbfile_update(data->LV_acc, (gpointer)4);
953 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data
->LV_report
));
955 minor
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data
->CM_minor
));
956 ui_chart_stack_show_minor(GTK_CHARTSTACK(data
->RE_stack
), minor
);
960 static void repbudget_setup(struct repbudget_data
*data
)
962 DB( g_print("\n[repbudget] setup\n") );
964 data
->txn_queue
= g_queue_new ();
966 data
->filter
= da_filter_malloc();
967 filter_default_all_set(data
->filter
);
969 data
->detail
= PREFS
->budg_showdetail
;
972 /* 3.4 : make int transfer out of stats */
973 data
->filter
->option
[FILTER_PAYMODE
] = 1;
974 data
->filter
->paymode
[PAYMODE_INTXFER
] = FALSE
;
976 filter_preset_daterange_set(data
->filter
, PREFS
->date_range_rep
, 0);
978 g_signal_handler_block(data
->PO_mindate
, data
->handler_id
[HID_REPBUDGET_MINDATE
]);
979 g_signal_handler_block(data
->PO_maxdate
, data
->handler_id
[HID_REPBUDGET_MAXDATE
]);
981 gtk_date_entry_set_date(GTK_DATE_ENTRY(data
->PO_mindate
), data
->filter
->mindate
);
982 gtk_date_entry_set_date(GTK_DATE_ENTRY(data
->PO_maxdate
), data
->filter
->maxdate
);
984 g_signal_handler_unblock(data
->PO_mindate
, data
->handler_id
[HID_REPBUDGET_MINDATE
]);
985 g_signal_handler_unblock(data
->PO_maxdate
, data
->handler_id
[HID_REPBUDGET_MAXDATE
]);
990 static void repbudget_selection(GtkTreeSelection
*treeselection
, gpointer user_data
)
996 DB( g_print("\n[repbudget] selection\n") );
998 if (gtk_tree_selection_get_selected(treeselection
, &model
, &iter
))
1000 gtk_tree_model_get(model
, &iter
, LST_BUDGET_KEY
, &key
, -1);
1002 DB( g_print(" - active is %d\n", key
) );
1004 repbudget_detail(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection
)), GINT_TO_POINTER(key
));
1007 repbudget_sensitive(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection
)), NULL
);
1012 static gboolean
repbudget_window_dispose(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
)
1014 struct repbudget_data
*data
= user_data
;
1015 struct WinGeometry
*wg
;
1017 DB( g_print("\n[repbudget] start dispose\n") );
1019 g_queue_free (data
->txn_queue
);
1021 da_filter_free(data
->filter
);
1025 //store position and size
1026 wg
= &PREFS
->bud_wg
;
1027 gtk_window_get_position(GTK_WINDOW(widget
), &wg
->l
, &wg
->t
);
1028 gtk_window_get_size(GTK_WINDOW(widget
), &wg
->w
, &wg
->h
);
1030 DB( g_print(" window: l=%d, t=%d, w=%d, h=%d\n", wg
->l
, wg
->t
, wg
->w
, wg
->h
) );
1032 //enable define windows
1033 GLOBALS
->define_off
--;
1034 ui_mainwindow_update(GLOBALS
->mainwindow
, GINT_TO_POINTER(UF_SENSITIVE
));
1036 DB( g_print("\n[repbudget] end dispose\n") );
1042 // the window creation
1043 GtkWidget
*repbudget_window_new(void)
1045 struct repbudget_data
*data
;
1046 struct WinGeometry
*wg
;
1047 GtkWidget
*window
, *mainvbox
, *hbox
, *vbox
, *notebook
, *treeview
;
1048 GtkWidget
*label
, *widget
, *table
, *entry
;
1051 GtkActionGroup
*actions
;
1053 GError
*error
= NULL
;
1055 data
= g_malloc0(sizeof(struct repbudget_data
));
1056 if(!data
) return NULL
;
1058 DB( g_print("\n[repbudget] new\n") );
1060 //disable define windows
1061 GLOBALS
->define_off
++;
1062 ui_mainwindow_update(GLOBALS
->mainwindow
, GINT_TO_POINTER(2));
1064 /* create window, etc */
1065 window
= gtk_window_new (GTK_WINDOW_TOPLEVEL
);
1066 data
->window
= window
;
1068 //store our window private data
1069 g_object_set_data(G_OBJECT(window
), "inst_data", (gpointer
)data
);
1071 gtk_window_set_title (GTK_WINDOW (window
), _("Budget report"));
1073 //set the window icon
1074 gtk_window_set_icon_name(GTK_WINDOW (window
), ICONNAME_HB_REP_BUDGET
);
1078 mainvbox
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 0);
1079 gtk_container_add (GTK_CONTAINER (window
), mainvbox
);
1081 hbox
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
1082 gtk_box_pack_start (GTK_BOX (mainvbox
), hbox
, TRUE
, TRUE
, 0);
1085 table
= gtk_grid_new ();
1086 // gtk_alignment_new(xalign, yalign, xscale, yscale)
1087 //alignment = gtk_alignment_new(0.0, 0.0, 0.0, 0.0);
1088 //gtk_container_add(GTK_CONTAINER(alignment), table);
1089 gtk_box_pack_start (GTK_BOX (hbox
), table
, FALSE
, FALSE
, 0);
1091 gtk_container_set_border_width (GTK_CONTAINER (table
), SPACING_SMALL
);
1092 gtk_grid_set_row_spacing (GTK_GRID (table
), SPACING_SMALL
);
1093 gtk_grid_set_column_spacing (GTK_GRID (table
), SPACING_MEDIUM
);
1096 label
= make_label_group(_("Display"));
1097 gtk_grid_attach (GTK_GRID (table
), label
, 0, row
, 3, 1);
1100 label
= make_label_widget(_("_For:"));
1101 gtk_grid_attach (GTK_GRID (table
), label
, 1, row
, 1, 1);
1102 widget
= make_cycle(label
, CYA_BUDGSELECT
);
1103 data
->CY_for
= widget
;
1104 gtk_grid_attach (GTK_GRID (table
), data
->CY_for
, 2, row
, 1, 1);
1108 label
= make_label_widget(_("_Kind:"));
1109 gtk_grid_attach (GTK_GRID (table
), label
, 1, row
, 1, 1);
1110 widget
= make_cycle(label
, CYA_KIND
);
1111 data
->CY_kind
= widget
;
1112 gtk_grid_attach (GTK_GRID (table
), data
->CY_kind
, 2, row
, 1, 1);
1115 widget
= gtk_check_button_new_with_mnemonic (_("Euro _minor"));
1116 data
->CM_minor
= widget
;
1117 gtk_grid_attach (GTK_GRID (table
), widget
, 2, row
, 1, 1);
1120 widget
= gtk_separator_new(GTK_ORIENTATION_HORIZONTAL
);
1121 gtk_grid_attach (GTK_GRID (table
), widget
, 0, row
, 3, 1);
1124 label
= make_label_group(_("Date filter"));
1125 gtk_grid_attach (GTK_GRID (table
), label
, 0, row
, 3, 1);
1128 label
= make_label_widget(_("_Range:"));
1129 gtk_grid_attach (GTK_GRID (table
), label
, 1, row
, 1, 1);
1130 data
->CY_range
= make_daterange(label
, FALSE
);
1131 gtk_grid_attach (GTK_GRID (table
), data
->CY_range
, 2, row
, 1, 1);
1134 label
= make_label_widget(_("_From:"));
1135 gtk_grid_attach (GTK_GRID (table
), label
, 1, row
, 1, 1);
1136 data
->PO_mindate
= gtk_date_entry_new();
1137 gtk_grid_attach (GTK_GRID (table
), data
->PO_mindate
, 2, row
, 1, 1);
1140 label
= make_label_widget(_("_To:"));
1141 gtk_grid_attach (GTK_GRID (table
), label
, 1, row
, 1, 1);
1142 data
->PO_maxdate
= gtk_date_entry_new();
1143 gtk_grid_attach (GTK_GRID (table
), data
->PO_maxdate
, 2, row
, 1, 1);
1146 //part: info + report
1147 vbox
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 0);
1148 gtk_box_pack_start (GTK_BOX (hbox
), vbox
, TRUE
, TRUE
, 0);
1151 actions
= gtk_action_group_new ("Account");
1154 gtk_action_group_set_translation_domain(actions
, GETTEXT_PACKAGE
);
1156 // data to action callbacks is set here (data)
1157 gtk_action_group_add_actions (actions
, entries
, n_entries
, data
);
1159 gtk_action_group_add_toggle_actions (actions
,
1160 toggle_entries
, n_toggle_entries
,
1164 /* set which action should have priority in the toolbar */
1165 action
= gtk_action_group_get_action(actions
, "List");
1166 g_object_set(action
, "is_important", TRUE
, NULL
);
1168 action
= gtk_action_group_get_action(actions
, "Stack");
1169 g_object_set(action
, "is_important", TRUE
, NULL
);
1171 action
= gtk_action_group_get_action(actions
, "Detail");
1172 g_object_set(action
, "is_important", TRUE
, NULL
);
1173 g_object_set(action
, "active", PREFS
->budg_showdetail
, NULL
);
1175 action
= gtk_action_group_get_action(actions
, "Refresh");
1176 g_object_set(action
, "is_important", TRUE
, NULL
);
1179 ui
= gtk_ui_manager_new ();
1180 gtk_ui_manager_insert_action_group (ui
, actions
, 0);
1181 gtk_window_add_accel_group (GTK_WINDOW (window
), gtk_ui_manager_get_accel_group (ui
));
1183 if (!gtk_ui_manager_add_ui_from_string (ui
, ui_info
, -1, &error
))
1185 g_message ("building UI failed: %s", error
->message
);
1186 g_error_free (error
);
1192 data
->TB_bar
= gtk_ui_manager_get_widget (ui
, "/ToolBar");
1193 gtk_box_pack_start (GTK_BOX (vbox
), data
->TB_bar
, FALSE
, FALSE
, 0);
1196 hbox
= gtk_box_new (GTK_ORIENTATION_HORIZONTAL
, SPACING_SMALL
);
1197 gtk_container_set_border_width (GTK_CONTAINER(hbox
), SPACING_SMALL
);
1198 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1200 widget
= make_label(NULL
, 0.5, 0.5);
1201 gimp_label_set_attributes (GTK_LABEL (widget
), PANGO_ATTR_SCALE
, PANGO_SCALE_SMALL
, -1);
1202 data
->TX_daterange
= widget
;
1203 gtk_box_pack_start (GTK_BOX (hbox
), widget
, TRUE
, TRUE
, 0);
1206 entry
= gtk_label_new(NULL
);
1207 data
->TX_total
[2] = entry
;
1208 gtk_box_pack_end (GTK_BOX (hbox
), entry
, FALSE
, FALSE
, 0);
1209 label
= gtk_label_new(_("Result:"));
1210 gtk_box_pack_end (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
1212 entry
= gtk_label_new(NULL
);
1213 data
->TX_total
[1] = entry
;
1214 gtk_box_pack_end (GTK_BOX (hbox
), entry
, FALSE
, FALSE
, 0);
1215 label
= gtk_label_new(_("Budget:"));
1216 gtk_box_pack_end (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
1218 entry
= gtk_label_new(NULL
);
1219 data
->TX_total
[0] = entry
;
1220 gtk_box_pack_end (GTK_BOX (hbox
), entry
, FALSE
, FALSE
, 0);
1221 label
= gtk_label_new(_("Spent:"));
1222 gtk_box_pack_end (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
1225 notebook
= gtk_notebook_new();
1226 data
->GR_result
= notebook
;
1227 gtk_widget_show(notebook
);
1228 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook
), FALSE
);
1229 gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook
), FALSE
);
1231 gtk_box_pack_start (GTK_BOX (vbox
), notebook
, TRUE
, TRUE
, 0);
1235 vbox
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 0);
1236 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
), vbox
, NULL
);
1238 widget
= gtk_scrolled_window_new (NULL
, NULL
);
1239 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget
), GTK_SHADOW_ETCHED_IN
);
1240 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget
), GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1241 treeview
= create_list_budget();
1242 data
->LV_report
= treeview
;
1243 gtk_container_add (GTK_CONTAINER(widget
), treeview
);
1244 gtk_box_pack_start (GTK_BOX (vbox
), widget
, TRUE
, TRUE
, 0);
1247 widget
= gtk_scrolled_window_new (NULL
, NULL
);
1248 data
->GR_detail
= widget
;
1249 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget
), GTK_SHADOW_ETCHED_IN
);
1250 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget
), GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1251 treeview
= create_list_transaction(LIST_TXN_TYPE_DETAIL
, PREFS
->lst_ope_columns
);
1252 data
->LV_detail
= treeview
;
1253 gtk_container_add (GTK_CONTAINER(widget
), treeview
);
1255 gtk_box_pack_start (GTK_BOX (vbox
), widget
, TRUE
, TRUE
, 0);
1258 //widget = gtk_chart_new(CHART_TYPE_COL);
1259 widget
= ui_chart_stack_new();
1260 data
->RE_stack
= widget
;
1261 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
), widget
, NULL
);
1263 //todo:should move this
1264 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data
->CM_minor
),GLOBALS
->minor
);
1267 /* attach our minor to treeview */
1268 g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_report
))), "minor", (gpointer
)data
->CM_minor
);
1269 g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_detail
))), "minor", (gpointer
)data
->CM_minor
);
1271 /* signal connect */
1272 g_signal_connect (window
, "delete-event", G_CALLBACK (repbudget_window_dispose
), (gpointer
)data
);
1274 g_signal_connect (data
->CM_minor
, "toggled", G_CALLBACK (repbudget_toggle
), NULL
);
1277 data
->handler_id
[HID_REPBUDGET_RANGE
] = g_signal_connect (data
->CY_range
, "changed", G_CALLBACK (repbudget_range_change
), NULL
);
1279 g_signal_connect (data
->CY_for
, "changed", G_CALLBACK (repbudget_compute
), (gpointer
)data
);
1280 g_signal_connect (data
->CY_kind
, "changed", G_CALLBACK (repbudget_compute
), (gpointer
)data
);
1282 data
->handler_id
[HID_REPBUDGET_MINDATE
] = g_signal_connect (data
->PO_mindate
, "changed", G_CALLBACK (repbudget_date_change
), (gpointer
)data
);
1283 data
->handler_id
[HID_REPBUDGET_MAXDATE
] = g_signal_connect (data
->PO_maxdate
, "changed", G_CALLBACK (repbudget_date_change
), (gpointer
)data
);
1285 g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data
->LV_report
)), "changed", G_CALLBACK (repbudget_selection
), NULL
);
1287 g_signal_connect (GTK_TREE_VIEW(data
->LV_detail
), "row-activated", G_CALLBACK (repbudget_detail_onRowActivated
), NULL
);
1290 //setup, init and show window
1291 repbudget_setup(data
);
1295 if(PREFS
->toolbar_style
== 0)
1296 gtk_toolbar_unset_style(GTK_TOOLBAR(data
->TB_bar
));
1298 gtk_toolbar_set_style(GTK_TOOLBAR(data
->TB_bar
), PREFS
->toolbar_style
-1);
1301 //setup, init and show window
1302 wg
= &PREFS
->bud_wg
;
1303 gtk_window_move(GTK_WINDOW(window
), wg
->l
, wg
->t
);
1304 gtk_window_resize(GTK_WINDOW(window
), wg
->w
, wg
->h
);
1308 gtk_widget_show_all (window
);
1312 if( PREFS
->euro_active
)
1313 gtk_widget_show(data
->CM_minor
);
1315 gtk_widget_hide(data
->CM_minor
);
1317 //check for any account included into the budget or warn
1322 lacc
= list
= g_hash_table_get_values(GLOBALS
->h_acc
);
1324 while (list
!= NULL
)
1328 if((acc
->flags
& (AF_CLOSED
|AF_NOREPORT
))) goto next1
;
1329 if(!(acc
->flags
& AF_NOBUDGET
))
1332 list
= g_list_next(list
);
1338 ui_dialog_msg_infoerror(GTK_WINDOW(data
->window
), GTK_MESSAGE_WARNING
,
1339 _("No account is defined to be part of the budget."),
1340 _("You should include some accounts from the account dialog.")
1350 //gtk_widget_hide(data->GR_detail);
1352 repbudget_sensitive(window
, NULL
);
1353 repbudget_update_detail(window
, NULL
);
1355 if( PREFS
->date_range_rep
!= 0)
1356 gtk_combo_box_set_active(GTK_COMBO_BOX(data
->CY_range
), PREFS
->date_range_rep
);
1358 repbudget_compute(window
, NULL
);
1364 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
1369 ** The function should return:
1370 ** a negative integer if the first value comes before the second,
1371 ** 0 if they are equal,
1372 ** or a positive integer if the first value comes after the second.
1374 static gint
budget_listview_compare_funct (GtkTreeModel
*model
, GtkTreeIter
*a
, GtkTreeIter
*b
, gpointer userdata
)
1377 //Category *entry1, *entry2;
1378 gchar
*entry1
, *entry2
;
1380 gtk_tree_model_get(model
, a
, LST_BUDGET_NAME
, &entry1
, -1);
1381 gtk_tree_model_get(model
, b
, LST_BUDGET_NAME
, &entry2
, -1);
1383 retval
= hb_string_utf8_compare(entry1
, entry2
);
1384 //retval = (entry1->flags & GF_INCOME) - (entry2->flags & GF_INCOME);
1387 // retval = hb_string_utf8_compare(entry1->name, entry2->name);
1394 static void budget_amount_cell_data_function (GtkTreeViewColumn
*col
,
1395 GtkCellRenderer
*renderer
,
1396 GtkTreeModel
*model
,
1402 gchar buf
[G_ASCII_DTOSTR_BUF_SIZE
];
1403 gint column_id
= GPOINTER_TO_INT(user_data
);
1405 gtk_tree_model_get(model
, iter
, column_id
, &value
, -1);
1409 hb_strfmon(buf
, G_ASCII_DTOSTR_BUF_SIZE
-1, value
, GLOBALS
->kcur
, GLOBALS
->minor
);
1411 if( column_id
== LST_BUDGET_RESULT
)
1412 color
= get_minimum_color_amount (value
, 0.0);
1414 color
= get_normal_color_amount(value
);
1416 g_object_set(renderer
,
1417 "foreground", color
,
1423 g_object_set(renderer
, "text", "", NULL
);
1429 static void budget_result_cell_data_function (GtkTreeViewColumn
*col
,
1430 GtkCellRenderer
*renderer
,
1431 GtkTreeModel
*model
,
1438 gint column_id
= GPOINTER_TO_INT(user_data
);
1440 gtk_tree_model_get(model
, iter
,
1442 LST_BUDGET_STATUS
, &status
,
1447 color
= get_minimum_color_amount (value
, 0.0);
1448 g_object_set(renderer
,
1449 "foreground", color
,
1455 g_object_set(renderer
, "text", "", NULL
);
1461 static GtkTreeViewColumn
*amount_list_budget_column(gchar
*name
, gint id
)
1463 GtkTreeViewColumn
*column
;
1464 GtkCellRenderer
*renderer
;
1466 column
= gtk_tree_view_column_new();
1467 gtk_tree_view_column_set_title(column
, name
);
1468 renderer
= gtk_cell_renderer_text_new ();
1469 g_object_set(renderer
, "xalign", 1.0, NULL
);
1470 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1471 gtk_tree_view_column_set_cell_data_func(column
, renderer
, budget_amount_cell_data_function
, GINT_TO_POINTER(id
), NULL
);
1472 gtk_tree_view_column_set_alignment (column
, 0.5);
1473 //gtk_tree_view_column_set_sort_column_id (column, id);
1478 ** create our statistic list
1480 static GtkWidget
*create_list_budget(void)
1482 GtkListStore
*store
;
1484 GtkCellRenderer
*renderer
;
1485 GtkTreeViewColumn
*column
;
1487 DB( g_print("\n[repbudget] create list\n") );
1490 /* create list store */
1491 store
= gtk_list_store_new(
1496 G_TYPE_DOUBLE
, //spent
1497 G_TYPE_DOUBLE
, //budget
1498 G_TYPE_DOUBLE
, //result
1499 G_TYPE_STRING
//status
1503 view
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(store
));
1504 g_object_unref(store
);
1506 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view
), PREFS
->grid_lines
);
1509 column
= gtk_tree_view_column_new();
1510 gtk_tree_view_column_set_title(column
, _("Category"));
1511 renderer
= gtk_cell_renderer_text_new ();
1512 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1513 //gtk_tree_view_column_set_cell_data_func(column, renderer, ope_result_cell_data_function, NULL, NULL);
1514 gtk_tree_view_column_add_attribute(column
, renderer
, "text", LST_BUDGET_NAME
);
1515 //gtk_tree_view_column_set_sort_column_id (column, LST_STAT_NAME);
1516 gtk_tree_view_column_set_resizable(column
, TRUE
);
1517 gtk_tree_view_column_set_alignment (column
, 0.5);
1518 gtk_tree_view_append_column (GTK_TREE_VIEW(view
), column
);
1520 /* column: Expense */
1521 column
= amount_list_budget_column(_("Spent"), LST_BUDGET_SPENT
);
1522 gtk_tree_view_append_column (GTK_TREE_VIEW(view
), column
);
1524 /* column: Income */
1525 column
= amount_list_budget_column(_("Budget"), LST_BUDGET_BUDGET
);
1526 gtk_tree_view_append_column (GTK_TREE_VIEW(view
), column
);
1528 /* column: Result */
1529 column
= amount_list_budget_column(_("Result"), LST_BUDGET_RESULT
);
1530 renderer
= gtk_cell_renderer_text_new ();
1531 //g_object_set(renderer, "xalign", 0.0, NULL);
1532 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1533 gtk_tree_view_column_set_cell_data_func(column
, renderer
, budget_result_cell_data_function
, GINT_TO_POINTER(LST_BUDGET_RESULT
), NULL
);
1534 gtk_tree_view_append_column (GTK_TREE_VIEW(view
), column
);
1536 /* column last: empty */
1537 column
= gtk_tree_view_column_new();
1538 gtk_tree_view_append_column (GTK_TREE_VIEW(view
), column
);
1541 gtk_tree_sortable_set_default_sort_func(GTK_TREE_SORTABLE(store
), budget_listview_compare_funct
, NULL
, NULL
);
1542 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store
), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID
, GTK_SORT_ASCENDING
);
1545 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_BUDGET_POS , stat_list_compare_func, GINT_TO_POINTER(LST_BUDGET_POS), NULL);
1546 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_BUDGET_SPENT , stat_list_compare_func, GINT_TO_POINTER(LST_BUDGET_SPENT), NULL);
1547 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_BUDGET_BUDGET, stat_list_compare_func, GINT_TO_POINTER(LST_BUDGET_BUDGET), NULL);
1548 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_BUDGET_RESULT , stat_list_compare_func, GINT_TO_POINTER(LST_BUDGET_RESULT), NULL);