1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2014 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.h"
27 #include "gtk-dateentry.h"
29 #include "dsp_mainwindow.h"
33 /****************************************************************************/
35 /****************************************************************************/
51 /* our global datas */
52 extern struct HomeBank
*GLOBALS
;
53 extern struct Preferences
*PREFS
;
64 GtkWidget
*TX_daterange
;
72 GtkWidget
*PO_mindate
, *PO_maxdate
;
77 GtkWidget
*TX_total
[3];
93 gulong handler_id
[MAX_HID
];
97 static void repbudget_action_viewlist(GtkAction
*action
, gpointer user_data
);
98 static void repbudget_action_viewbar(GtkAction
*action
, gpointer user_data
);
99 static void repbudget_action_detail(GtkAction
*action
, gpointer user_data
);
100 static void repbudget_action_legend(GtkAction
*action
, gpointer user_data
);
101 static void repbudget_action_refresh(GtkAction
*action
, gpointer user_data
);
109 gchar
*CYA_BUDGSELECT
[] = { N_("Category"), N_("Subcategory"), NULL
};
111 gchar
*CYA_KIND
[] = { N_("Exp. & Inc."), N_("Expense"), N_("Income"), NULL
};
113 gchar
*CYA_BUDGETSELECT
[] = { N_("Spent & Budget"), N_("Spent"), N_("Budget"), N_("Result"), NULL
};
116 //extern gchar *CYA_FLT_SELECT[];
118 static GtkActionEntry entries
[] = {
119 { "List" , "hb-view-list" , N_("List") , NULL
, N_("View results as list"), G_CALLBACK (repbudget_action_viewlist
) },
120 { "Bar" , "hb-view-bar" , N_("Bar") , NULL
, N_("View results as bars"), G_CALLBACK (repbudget_action_viewbar
) },
121 { "Refresh" , GTK_STOCK_REFRESH
, N_("Refresh"), NULL
, N_("Refresh results"), G_CALLBACK (repbudget_action_refresh
) },
123 static guint n_entries
= G_N_ELEMENTS (entries
);
126 static GtkToggleActionEntry toggle_entries
[] = {
127 { "Detail", "hb-ope-show", /* name, stock id */
128 N_("Detail"), NULL
, /* label, accelerator */
129 N_("Toggle detail"), /* tooltip */
130 G_CALLBACK (repbudget_action_detail
),
131 FALSE
}, /* is_active */
133 { "Legend", "hb-legend", /* name, stock id */
134 N_("Legend"), NULL
, /* label, accelerator */
135 N_("Toggle legend"), /* tooltip */
136 G_CALLBACK (repbudget_action_legend
),
137 TRUE
}, /* is_active */
140 static guint n_toggle_entries
= G_N_ELEMENTS (toggle_entries
);
143 static const gchar
*ui_info
=
145 " <toolbar name='ToolBar'>"
146 " <toolitem action='List'/>"
147 " <toolitem action='Bar'/>"
149 " <toolitem action='Detail'/>"
150 " <toolitem action='Legend'/>"
152 " <toolitem action='Refresh'/>"
170 static void repbudget_date_change(GtkWidget
*widget
, gpointer user_data
);
171 static void repbudget_range_change(GtkWidget
*widget
, gpointer user_data
);
172 static void repbudget_toggle_detail(GtkWidget
*widget
, gpointer user_data
);
173 static void repbudget_detail(GtkWidget
*widget
, gpointer user_data
);
174 static void repbudget_compute(GtkWidget
*widget
, gpointer user_data
);
175 static void repbudget_update_total(GtkWidget
*widget
, gpointer user_data
);
176 static void repbudget_sensitive(GtkWidget
*widget
, gpointer user_data
);
177 static void repbudget_toggle_legend(GtkWidget
*widget
, gpointer user_data
);
178 static void repbudget_toggle(GtkWidget
*widget
, gpointer user_data
);
179 static GtkWidget
*create_list_budget(void);
180 static void repbudget_update_detail(GtkWidget
*widget
, gpointer user_data
);
181 static void repbudget_update_daterange(GtkWidget
*widget
, gpointer user_data
);
183 /* action functions -------------------- */
184 static void repbudget_action_viewlist(GtkAction
*action
, gpointer user_data
)
186 struct repbudget_data
*data
= user_data
;
188 gtk_notebook_set_current_page(GTK_NOTEBOOK(data
->GR_result
), 0);
189 repbudget_sensitive(data
->window
, NULL
);
192 static void repbudget_action_viewbar(GtkAction
*action
, gpointer user_data
)
194 struct repbudget_data
*data
= user_data
;
196 gtk_notebook_set_current_page(GTK_NOTEBOOK(data
->GR_result
), 1);
197 repbudget_sensitive(data
->window
, NULL
);
200 static void repbudget_action_detail(GtkAction
*action
, gpointer user_data
)
202 struct repbudget_data
*data
= user_data
;
204 repbudget_toggle_detail(data
->window
, NULL
);
207 static void repbudget_action_legend(GtkAction
*action
, gpointer user_data
)
209 struct repbudget_data
*data
= user_data
;
211 repbudget_toggle_legend(data
->window
, NULL
);
214 static void repbudget_action_refresh(GtkAction
*action
, gpointer user_data
)
216 struct repbudget_data
*data
= user_data
;
218 repbudget_compute(data
->window
, NULL
);
223 /* ======================== */
226 static gint
getmonth(guint date
)
231 date1
= g_date_new_julian(date
);
232 month
= g_date_get_month(date1
);
236 g_date_strftime (buffer1
, 128-1, "%x", date1
);
237 g_print(" date is '%s'\n", buffer1
);
239 g_print(" month is %d\n", month
);
248 static gint
countmonth(guint32 mindate
, guint32 maxdate
)
250 GDate
*date1
, *date2
;
253 date1
= g_date_new_julian(mindate
);
254 date2
= g_date_new_julian(maxdate
);
257 while(g_date_compare(date1
, date2
) < 0)
260 g_date_add_months(date1
, 1);
269 static gdouble
budget_compute_result(gdouble budget
, gdouble spent
)
274 //result = ABS(budget) - ABS(spent);
276 retval
= spent
- budget
;
285 static void repbudget_date_change(GtkWidget
*widget
, gpointer user_data
)
287 struct repbudget_data
*data
;
289 DB( g_print("(repbudget) date change\n") );
291 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
293 data
->filter
->mindate
= gtk_dateentry_get_date(GTK_DATE_ENTRY(data
->PO_mindate
));
294 data
->filter
->maxdate
= gtk_dateentry_get_date(GTK_DATE_ENTRY(data
->PO_maxdate
));
296 // set min/max date for both widget
297 gtk_dateentry_set_maxdate(GTK_DATE_ENTRY(data
->PO_mindate
), data
->filter
->maxdate
);
298 gtk_dateentry_set_mindate(GTK_DATE_ENTRY(data
->PO_maxdate
), data
->filter
->mindate
);
300 g_signal_handler_block(data
->CY_range
, data
->handler_id
[HID_RANGE
]);
301 gtk_combo_box_set_active(GTK_COMBO_BOX(data
->CY_range
), FLT_RANGE_OTHER
);
302 g_signal_handler_unblock(data
->CY_range
, data
->handler_id
[HID_RANGE
]);
305 repbudget_compute(widget
, NULL
);
306 repbudget_update_daterange(widget
, NULL
);
311 static void repbudget_range_change(GtkWidget
*widget
, gpointer user_data
)
313 struct repbudget_data
*data
;
316 DB( g_print("(repbudget) range change\n") );
318 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
320 range
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->CY_range
));
323 if(range
!= FLT_RANGE_OTHER
)
325 filter_preset_daterange_set(data
->filter
, range
);
327 g_signal_handler_block(data
->PO_mindate
, data
->handler_id
[HID_MINDATE
]);
328 g_signal_handler_block(data
->PO_maxdate
, data
->handler_id
[HID_MAXDATE
]);
330 gtk_dateentry_set_date(GTK_DATE_ENTRY(data
->PO_mindate
), data
->filter
->mindate
);
331 gtk_dateentry_set_date(GTK_DATE_ENTRY(data
->PO_maxdate
), data
->filter
->maxdate
);
333 g_signal_handler_unblock(data
->PO_mindate
, data
->handler_id
[HID_MINDATE
]);
334 g_signal_handler_unblock(data
->PO_maxdate
, data
->handler_id
[HID_MAXDATE
]);
336 repbudget_compute(widget
, NULL
);
337 repbudget_update_daterange(widget
, NULL
);
342 static void repbudget_update_daterange(GtkWidget
*widget
, gpointer user_data
)
344 struct repbudget_data
*data
;
347 DB( g_print("(repbudget) update daterange\n") );
349 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
351 daterange
= filter_daterange_text_get(data
->filter
);
352 gtk_label_set_markup(GTK_LABEL(data
->TX_daterange
), daterange
);
357 static void repbudget_toggle_detail(GtkWidget
*widget
, gpointer user_data
)
359 struct repbudget_data
*data
;
361 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
363 DB( g_print("(repbudget) toggle detail\n") );
367 repbudget_update_detail(widget
, user_data
);
371 static void repbudget_update_detail(GtkWidget
*widget
, gpointer user_data
)
373 struct repbudget_data
*data
;
375 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
377 DB( g_print("(repbudget) update detail\n") );
379 if(GTK_IS_TREE_VIEW(data
->LV_report
))
383 GtkTreeSelection
*treeselection
;
388 treeselection
= gtk_tree_view_get_selection (GTK_TREE_VIEW(data
->LV_report
));
390 if (gtk_tree_selection_get_selected(treeselection
, &model
, &iter
))
392 gtk_tree_model_get(model
, &iter
, LST_BUDGET_KEY
, &key
, -1);
394 //DB( g_print(" - active is %d\n", pos) );
396 repbudget_detail(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection
)), GINT_TO_POINTER(key
));
400 gtk_widget_show(data
->GR_detail
);
403 gtk_widget_hide(data
->GR_detail
);
409 static void repbudget_detail(GtkWidget
*widget
, gpointer user_data
)
411 struct repbudget_data
*data
;
412 guint active
= GPOINTER_TO_INT(user_data
);
418 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
420 DB( g_print("(repbudget) detail\n") );
424 /* clear and detach our model */
425 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_detail
));
426 gtk_list_store_clear (GTK_LIST_STORE(model
));
427 g_object_ref(model
); /* Make sure the model stays with us after the tree view unrefs it */
428 gtk_tree_view_set_model(GTK_TREE_VIEW(data
->LV_detail
), NULL
); /* Detach model from view */
430 tmpfor
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->CY_for
));
432 /* fill in the model */
433 list
= g_list_first(GLOBALS
->ope_list
);
437 Transaction
*ope
= list
->data
;
439 //DB( g_print(" get %s\n", ope->ope_Word) );
441 acc
= da_acc_get(ope
->kacc
);
444 if((acc
->flags
& AF_CLOSED
)) goto next1
;
445 if((acc
->flags
& AF_NOBUDGET
)) goto next1
;
449 if( !(ope
->flags
& OF_REMIND
) && (ope
->date
>= data
->filter
->mindate
) && (ope
->date
<= data
->filter
->maxdate
))
452 gboolean insert
= FALSE
;
454 if( ope
->flags
& OF_SPLIT
)
456 guint nbsplit
= da_transaction_splits_count(ope
);
460 for(i
=0;i
<nbsplit
;i
++)
462 split
= ope
->splits
[i
];
467 Category
*catentry
= da_cat_get(split
->kcat
);
469 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
472 case BUDG_SUBCATEGORY
:
478 { insert
= TRUE
; break; }
487 Category
*catentry
= da_cat_get(ope
->kcat
);
489 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
492 case BUDG_SUBCATEGORY
:
505 gtk_list_store_append (GTK_LIST_STORE(model
), &iter
);
506 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
,
507 LST_DSPOPE_DATAS
, ope
,
513 list
= g_list_next(list
);
516 /* Re-attach model to view */
517 gtk_tree_view_set_model(GTK_TREE_VIEW(data
->LV_detail
), model
);
518 g_object_unref(model
);
525 static void repbudget_compute(GtkWidget
*widget
, gpointer user_data
)
527 struct repbudget_data
*data
;
529 gint tmpfor
, tmpkind
, tmpview
;
530 guint32 mindate
, maxdate
;
535 guint n_result
, id
, column
;
536 gdouble
*tmp_spent
, *tmp_budget
, *tmp_hasbudget
;
539 DB( g_print("(repbudget) compute\n") );
541 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
543 tmpfor
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->CY_for
));
544 tmpkind
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->CY_kind
));
545 tmpview
= gtk_combo_box_get_active(GTK_COMBO_BOX(data
->CY_view
));
547 mindate
= data
->filter
->mindate
;
548 maxdate
= data
->filter
->maxdate
;
549 if(maxdate
< mindate
) return;
551 DB( g_print(" kind=%d,view=%d\n", tmpkind
, tmpview
) );
554 /* do nothing if no transaction */
555 if(g_list_length(GLOBALS
->ope_list
) == 0) return;
557 nbmonth
= countmonth(mindate
, maxdate
);
558 DB( g_print(" date: min=%d max=%d nbmonth=%d\n", mindate
, maxdate
, nbmonth
) );
560 n_result
= da_cat_get_max_key();
561 DB( g_print(" nbcat=%d\n", n_result
) );
563 /* allocate some memory */
564 tmp_spent
= g_malloc0((n_result
+1) * sizeof(gdouble
));
565 tmp_budget
= g_malloc0((n_result
+1) * sizeof(gdouble
));
566 tmp_hasbudget
= g_malloc0((n_result
+1) * sizeof(gdouble
));
568 if(tmp_spent
&& tmp_budget
&& tmp_hasbudget
)
571 /* compute the results */
572 data
->total_spent
= 0.0;
573 data
->total_budget
= 0.0;
576 /* compute budget for each category */
577 //fixed #328034: here <=n_result
578 for(i
=0, id
=0; i
<=n_result
; i
++)
584 entry
= da_cat_get(i
);
593 g_print("--------\n");
595 g_print("+ %s", entry
->name
);
597 g_print( "%d[%.2f] ", k
, entry
->budget
[k
]);
607 Category
*catentry
= da_cat_get(i
);
609 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
612 case BUDG_SUBCATEGORY
:
617 DB( g_print(" ** budget for %d '%s'\n", entry
->key
, entry
->name
) );
619 // same value each month ?
620 if(!(entry
->flags
& GF_CUSTOM
))
622 //DB( g_print(" cat %s -> monthly %.2f\n", entry->name, entry->budget[0]) );
623 tmp_budget
[pos
] += entry
->budget
[0]*nbmonth
;
624 tmp_hasbudget
[i
] += entry
->budget
[0]*nbmonth
;
626 //otherwise sum each month from mindate month
629 gint month
= getmonth(mindate
);
632 for(j
=0;j
<nbmonth
;j
++)
634 DB( g_print(" %d, cat %s -> custom : month=%d budg=%.2f\n", j
, entry
->name
, month
, entry
->budget
[month
]) );
636 tmp_budget
[pos
] += entry
->budget
[month
];
637 tmp_hasbudget
[i
] += entry
->budget
[month
];
639 if(month
> 12) month
= 1;
645 if( tmp_budget
[pos
] )
647 g_print(" -> cat %d %s, budg[%d]=%.2f hasbudg[%d]=%.2f\n",
648 entry
->key
, entry
->name
, pos
, tmp_budget
[pos
], i
, tmp_hasbudget
[i
]);
658 // compute spent for each transaction */
659 DB( g_print(" ** compute spent for each categories\n") );
662 list
= g_list_first(GLOBALS
->ope_list
);
665 Transaction
*ope
= list
->data
;
668 //DB( g_print("%d, get ope: %s :: acc=%d, cat=%d, mnt=%.2f\n", i, ope->wording, ope->account, ope->category, ope->amount) );
670 acc
= da_acc_get(ope
->kacc
);
672 if(acc
== NULL
) goto next1
;
673 if((acc
->flags
& (AF_CLOSED
|AF_NOREPORT
))) goto next1
;
674 if((acc
->flags
& AF_NOBUDGET
)) goto next1
;
676 if( !(ope
->flags
& OF_REMIND
) && ope
->date
>= mindate
&& ope
->date
<= maxdate
)
681 if( ope
->flags
& OF_SPLIT
)
683 guint nbsplit
= da_transaction_splits_count(ope
);
686 for(i
=0;i
<nbsplit
;i
++)
688 split
= ope
->splits
[i
];
693 Category
*catentry
= da_cat_get(split
->kcat
);
695 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
698 case BUDG_SUBCATEGORY
:
703 //trn_amount = to_base_amount(split->amount, acc->kcur);
704 trn_amount
= split
->amount
;
707 DB( g_print(" -> affecting split %.2f to cat %d\n", trn_amount
, pos
) );
709 tmp_spent
[pos
] += trn_amount
;
719 Category
*catentry
= da_cat_get(ope
->kcat
);
721 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
724 case BUDG_SUBCATEGORY
:
729 //trn_amount = to_base_amount(ope->amount, acc->kcur);
730 trn_amount
= ope
->amount
;
732 DB( g_print(" -> affecting %.2f to cat %d\n", trn_amount
, pos
) );
734 tmp_spent
[pos
] += trn_amount
;
743 list
= g_list_next(list
);
751 DB( g_print("clear and detach model\n") );
753 /* clear and detach our model */
754 model
= gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_report
));
755 gtk_list_store_clear (GTK_LIST_STORE(model
));
756 g_object_ref(model
); /* Make sure the model stays with us after the tree view unrefs it */
757 gtk_tree_view_set_model(GTK_TREE_VIEW(data
->LV_report
), NULL
); /* Detach model from view */
760 /* insert into the treeview */
761 for(i
=0, id
=0; i
<=n_result
; i
++)
763 gchar
*name
, *fullcatname
;
769 entry
= da_cat_get(i
);
773 if(entry
->flags
& GF_SUB
)
775 Category
*parent
= da_cat_get( entry
->parent
);
777 fullcatname
= g_strdup_printf("%s:%s", parent
->name
, entry
->name
);
783 if(name
== NULL
) name
= "(None)";
785 if( (tmpfor
== BUDG_CATEGORY
&& !(entry
->flags
& GF_SUB
)) || (tmpfor
== BUDG_SUBCATEGORY
) )
796 Category
*catentry
= da_cat_get(i
);
798 pos
= (catentry
->flags
& GF_SUB
) ? catentry
->parent
: catentry
->key
;
801 case BUDG_SUBCATEGORY
:
806 // display expense or income (filter on amount and not category hupothetical flag
807 //if( tmpkind != (entry->flags & GF_INCOME)) continue;
808 if( tmpkind
== 1 && tmp_budget
[pos
] > 0)
811 if( tmpkind
== 2 && tmp_budget
[pos
] < 0)
815 if(tmp_budget
[pos
] || entry
->flags
& GF_FORCED
/*|| tmp_spent[pos]*/)
819 result
= budget_compute_result(tmp_budget
[pos
], tmp_spent
[pos
]);
821 DB( g_print(" inserting %i, %s, %.2f %.2f %.2f\n", i
, name
, tmp_spent
[pos
], tmp_budget
[pos
], result
) );
823 gtk_list_store_append (GTK_LIST_STORE(model
), &iter
);
824 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
,
825 LST_BUDGET_POS
, id
++,
827 LST_BUDGET_NAME
, name
,
828 LST_BUDGET_SPENT
, tmp_spent
[pos
],
829 LST_BUDGET_BUDGET
, tmp_budget
[pos
],
830 LST_BUDGET_RESULT
, result
,
833 data
->total_spent
+= tmp_spent
[pos
];
834 data
->total_budget
+= tmp_budget
[pos
];
844 /* Re-attach model to view */
845 gtk_tree_view_set_model(GTK_TREE_VIEW(data
->LV_report
), model
);
846 g_object_unref(model
);
850 repbudget_update_total(widget
, NULL
);
852 column
= LST_BUDGET_SPENT
+tmpview
-1;
854 /* update bar chart */
855 DB( g_print(" set bar to %d\n\n", column
) );
857 //gtk_chart_set_currency(GTK_CHART(data->RE_bar), GLOBALS->kcur);
859 /* set chart color scheme */
860 gtk_chart_set_color_scheme(GTK_CHART(data
->RE_bar
), PREFS
->report_color_scheme
);
863 gtk_chart_set_dualdatas(GTK_CHART(data
->RE_bar
), model
, LST_BUDGET_SPENT
, LST_BUDGET_BUDGET
, _(CYA_BUDGETSELECT
[tmpview
]));
865 gtk_chart_set_datas(GTK_CHART(data
->RE_bar
), model
, column
, _(CYA_BUDGETSELECT
[tmpview
]));
870 //DB( g_print(" inserting %i, %f %f\n", i, total_expense, total_income) );
872 /* free our memory */
875 g_free(tmp_hasbudget
);
881 static void repbudget_update_total(GtkWidget
*widget
, gpointer user_data
)
883 struct repbudget_data
*data
;
885 DB( g_print("(repbudget) update total\n") );
887 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
889 GLOBALS
->minor
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data
->CM_minor
));
892 hb_label_set_colvaluecurr(GTK_LABEL(data->TX_total[0]), data->total_spent, GLOBALS->kcur);
893 hb_label_set_colvaluecurr(GTK_LABEL(data->TX_total[1]), data->total_budget, GLOBALS->kcur);
894 hb_label_set_colvaluecurr(GTK_LABEL(data->TX_total[2]), budget_compute_result(data->total_budget, data->total_spent), GLOBALS->kcur);
896 hb_label_set_colvalue(GTK_LABEL(data
->TX_total
[0]), data
->total_spent
, GLOBALS
->minor
);
897 hb_label_set_colvalue(GTK_LABEL(data
->TX_total
[1]), data
->total_budget
, GLOBALS
->minor
);
898 hb_label_set_colvalue(GTK_LABEL(data
->TX_total
[2]), budget_compute_result(data
->total_budget
, data
->total_spent
), GLOBALS
->minor
);
905 ** update sensitivity
907 static void repbudget_sensitive(GtkWidget
*widget
, gpointer user_data
)
909 struct repbudget_data
*data
;
914 DB( g_print("(repbudget) sensitive\n") );
916 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
918 active
= gtk_tree_selection_get_selected(gtk_tree_view_get_selection(GTK_TREE_VIEW(data
->LV_report
)), NULL
, NULL
);
920 page
= gtk_notebook_get_current_page(GTK_NOTEBOOK(data
->GR_result
));
922 sensitive
= page
== 0 ? active
: FALSE
;
923 // gtk_widget_set_sensitive(data->TB_buttons[ACTION_REPBUDGET_DETAIL], sensitive);
924 gtk_action_set_sensitive(gtk_ui_manager_get_action(data
->ui
, "/ToolBar/Detail"), sensitive
);
926 sensitive
= page
== 0 ? FALSE
: TRUE
;
927 gtk_widget_set_sensitive(data
->CY_view
, sensitive
);
928 gtk_widget_set_sensitive(data
->RG_zoomx
, sensitive
);
929 // gtk_widget_set_sensitive(data->TB_buttons[ACTION_REPBUDGET_LEGEND], sensitive);
930 gtk_action_set_sensitive(gtk_ui_manager_get_action(data
->ui
, "/ToolBar/Legend"), sensitive
);
937 ** change the chart legend visibility
939 static void repbudget_toggle_legend(GtkWidget
*widget
, gpointer user_data
)
941 struct repbudget_data
*data
;
943 DB( g_print("(repbudget) legend\n") );
945 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
947 //active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_legend));
950 gtk_chart_show_legend(GTK_CHART(data
->RE_bar
), data
->legend
, FALSE
);
954 static void repbudget_zoomx_callback(GtkWidget
*widget
, gpointer user_data
)
956 struct repbudget_data
*data
;
959 DB( g_print("(repbudget) zoomx\n") );
961 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
963 value
= gtk_range_get_value(GTK_RANGE(data
->RG_zoomx
));
965 DB( g_print(" + scale is %.2f\n", value
) );
967 gtk_chart_set_barw(GTK_CHART(data
->RE_bar
), value
);
971 static void repbudget_toggle(GtkWidget
*widget
, gpointer user_data
)
973 struct repbudget_data
*data
;
976 DB( g_print("(repbudget) toggle\n") );
978 data
= g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget
, GTK_TYPE_WINDOW
)), "inst_data");
980 repbudget_update_total(widget
, NULL
);
982 //hbfile_update(data->LV_acc, (gpointer)4);
983 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data
->LV_report
));
985 minor
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data
->CM_minor
));
986 gtk_chart_show_minor(GTK_CHART(data
->RE_bar
), minor
);
990 static void repbudget_setup(struct repbudget_data
*data
)
992 DB( g_print("(repbudget) setup\n") );
994 data
->detail
= PREFS
->budg_showdetail
;
998 data
->filter
= da_filter_malloc();
999 filter_default_all_set(data
->filter
);
1001 /* 3.4 : make int transfer out of stats */
1002 data
->filter
->option
[FILTER_PAYMODE
] = 1;
1003 data
->filter
->paymode
[PAYMODE_INTXFER
] = FALSE
;
1005 filter_preset_daterange_set(data
->filter
, PREFS
->date_range_rep
);
1007 g_signal_handler_block(data
->PO_mindate
, data
->handler_id
[HID_MINDATE
]);
1008 g_signal_handler_block(data
->PO_maxdate
, data
->handler_id
[HID_MAXDATE
]);
1010 gtk_dateentry_set_date(GTK_DATE_ENTRY(data
->PO_mindate
), data
->filter
->mindate
);
1011 gtk_dateentry_set_date(GTK_DATE_ENTRY(data
->PO_maxdate
), data
->filter
->maxdate
);
1013 g_signal_handler_unblock(data
->PO_mindate
, data
->handler_id
[HID_MINDATE
]);
1014 g_signal_handler_unblock(data
->PO_maxdate
, data
->handler_id
[HID_MAXDATE
]);
1019 static void repbudget_selection(GtkTreeSelection
*treeselection
, gpointer user_data
)
1021 GtkTreeModel
*model
;
1025 DB( g_print("(repbudget) selection\n") );
1027 if (gtk_tree_selection_get_selected(treeselection
, &model
, &iter
))
1029 gtk_tree_model_get(model
, &iter
, LST_BUDGET_KEY
, &key
, -1);
1031 DB( g_print(" - active is %d\n", key
) );
1033 repbudget_detail(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection
)), GINT_TO_POINTER(key
));
1036 repbudget_sensitive(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection
)), NULL
);
1041 static gboolean
repbudget_window_dispose(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
)
1043 struct repbudget_data
*data
= user_data
;
1044 struct WinGeometry
*wg
;
1046 DB( g_print("(repbudget) start dispose\n") );
1048 da_filter_free(data
->filter
);
1052 //store position and size
1053 wg
= &PREFS
->bud_wg
;
1054 gtk_window_get_position(GTK_WINDOW(widget
), &wg
->l
, &wg
->t
);
1055 gtk_window_get_size(GTK_WINDOW(widget
), &wg
->w
, &wg
->h
);
1057 DB( g_print(" window: l=%d, t=%d, w=%d, h=%d\n", wg
->l
, wg
->t
, wg
->w
, wg
->h
) );
1059 //enable define windows
1060 GLOBALS
->define_off
--;
1061 ui_mainwindow_update(GLOBALS
->mainwindow
, GINT_TO_POINTER(UF_SENSITIVE
));
1063 DB( g_print("(repbudget) end dispose\n") );
1069 // the window creation
1070 GtkWidget
*repbudget_window_new(void)
1072 struct repbudget_data
*data
;
1073 struct WinGeometry
*wg
;
1074 GtkWidget
*window
, *mainvbox
, *hbox
, *vbox
, *notebook
, *treeview
;
1075 GtkWidget
*label
, *widget
, *table
, *alignment
, *entry
;
1078 GtkActionGroup
*actions
;
1080 GError
*error
= NULL
;
1082 data
= g_malloc0(sizeof(struct repbudget_data
));
1083 if(!data
) return NULL
;
1085 DB( g_print("(repbudget) new\n") );
1087 //disable define windows
1088 GLOBALS
->define_off
++;
1089 ui_mainwindow_update(GLOBALS
->mainwindow
, GINT_TO_POINTER(2));
1091 /* create window, etc */
1092 window
= gtk_window_new (GTK_WINDOW_TOPLEVEL
);
1093 data
->window
= window
;
1095 //store our window private data
1096 g_object_set_data(G_OBJECT(window
), "inst_data", (gpointer
)data
);
1098 gtk_window_set_title (GTK_WINDOW (window
), _("Budget report"));
1100 //set the window icon
1101 //homebank_window_set_icon_from_file(GTK_WINDOW (window), "report_budget.svg");
1102 gtk_window_set_icon_name(GTK_WINDOW (window
), HB_STOCK_REP_BUDGET
);
1106 mainvbox
= gtk_vbox_new (FALSE
, 0);
1107 gtk_container_add (GTK_CONTAINER (window
), mainvbox
);
1109 hbox
= gtk_hbox_new(FALSE
, 0);
1110 gtk_box_pack_start (GTK_BOX (mainvbox
), hbox
, TRUE
, TRUE
, 0);
1113 table
= gtk_table_new (9, 3, FALSE
);
1114 // gtk_alignment_new(xalign, yalign, xscale, yscale)
1115 alignment
= gtk_alignment_new(0.0, 0.0, 0.0, 0.0);
1116 gtk_container_add(GTK_CONTAINER(alignment
), table
);
1117 gtk_box_pack_start (GTK_BOX (hbox
), alignment
, FALSE
, FALSE
, 0);
1119 gtk_container_set_border_width (GTK_CONTAINER (table
), HB_BOX_SPACING
);
1120 gtk_table_set_row_spacings (GTK_TABLE (table
), HB_TABROW_SPACING
);
1121 gtk_table_set_col_spacings (GTK_TABLE (table
), HB_TABCOL_SPACING
);
1124 label
= make_label(_("Display"), 0.0, 0.5);
1125 gimp_label_set_attributes(GTK_LABEL(label
), PANGO_ATTR_WEIGHT
, PANGO_WEIGHT_BOLD
, -1);
1126 gtk_table_attach_defaults (GTK_TABLE (table
), label
, 0, 3, row
, row
+1);
1129 label
= make_label(_("_For:"), 0, 0.5);
1130 gtk_table_attach (GTK_TABLE (table
), label
, 1, 2, row
, row
+1, (GtkAttachOptions
) (GTK_FILL
), (GtkAttachOptions
) (0), 0, 0);
1131 widget
= make_cycle(label
, CYA_BUDGSELECT
);
1132 data
->CY_for
= widget
;
1133 gtk_table_attach_defaults (GTK_TABLE (table
), data
->CY_for
, 2, 3, row
, row
+1);
1137 label
= make_label(_("_Kind:"), 0, 0.5);
1138 gtk_table_attach (GTK_TABLE (table
), label
, 1, 2, row
, row
+1, (GtkAttachOptions
) (GTK_FILL
), (GtkAttachOptions
) (0), 0, 0);
1139 widget
= make_cycle(label
, CYA_KIND
);
1140 data
->CY_kind
= widget
;
1141 gtk_table_attach_defaults (GTK_TABLE (table
), data
->CY_kind
, 2, 3, row
, row
+1);
1144 label
= make_label(_("_View:"), 0, 0.5);
1145 gtk_table_attach (GTK_TABLE (table
), label
, 1, 2, row
, row
+1, (GtkAttachOptions
) (GTK_FILL
), (GtkAttachOptions
) (0), 0, 0);
1146 widget
= make_cycle(label
, CYA_BUDGETSELECT
);
1147 data
->CY_view
= widget
;
1148 gtk_table_attach_defaults (GTK_TABLE (table
), data
->CY_view
, 2, 3, row
, row
+1);
1151 widget
= gtk_check_button_new_with_mnemonic (_("_Minor currency"));
1152 data
->CM_minor
= widget
;
1153 gtk_table_attach_defaults (GTK_TABLE (table
), widget
, 1, 3, row
, row
+1);
1156 label
= make_label(_("_Zoom X:"), 0, 0.5);
1157 gtk_table_attach (GTK_TABLE (table
), label
, 1, 2, row
, row
+1, (GtkAttachOptions
) (GTK_FILL
), (GtkAttachOptions
) (0), 0, 0);
1158 widget
= make_scale(label
);
1159 data
->RG_zoomx
= widget
;
1160 gtk_table_attach_defaults (GTK_TABLE (table
), widget
, 2, 3, row
, row
+1);
1163 widget
= gtk_hseparator_new();
1164 gtk_table_attach_defaults (GTK_TABLE (table
), widget
, 0, 3, row
, row
+1);
1167 label
= make_label(_("Date filter"), 0.0, 0.5);
1168 gimp_label_set_attributes(GTK_LABEL(label
), PANGO_ATTR_WEIGHT
, PANGO_WEIGHT_BOLD
, -1);
1169 gtk_table_attach_defaults (GTK_TABLE (table
), label
, 0, 3, row
, row
+1);
1172 label
= make_label(_("_Range:"), 0, 0.5);
1173 gtk_table_attach (GTK_TABLE (table
), label
, 1, 2, row
, row
+1, (GtkAttachOptions
) (GTK_FILL
), (GtkAttachOptions
) (0), 0, 0);
1174 data
->CY_range
= make_daterange(label
, FALSE
);
1175 gtk_table_attach_defaults (GTK_TABLE (table
), data
->CY_range
, 2, 3, row
, row
+1);
1178 label
= make_label(_("_From:"), 0, 0.5);
1179 gtk_table_attach (GTK_TABLE (table
), label
, 1, 2, row
, row
+1, (GtkAttachOptions
) (GTK_FILL
), (GtkAttachOptions
) (0), 0, 0);
1180 data
->PO_mindate
= gtk_dateentry_new();
1181 gtk_table_attach_defaults (GTK_TABLE (table
), data
->PO_mindate
, 2, 3, row
, row
+1);
1184 label
= make_label(_("_To:"), 0, 0.5);
1185 gtk_table_attach (GTK_TABLE (table
), label
, 1, 2, row
, row
+1, (GtkAttachOptions
) (GTK_FILL
), (GtkAttachOptions
) (0), 0, 0);
1186 data
->PO_maxdate
= gtk_dateentry_new();
1187 gtk_table_attach_defaults (GTK_TABLE (table
), data
->PO_maxdate
, 2, 3, row
, row
+1);
1190 //part: info + report
1191 vbox
= gtk_vbox_new (FALSE
, 0);
1192 gtk_box_pack_start (GTK_BOX (hbox
), vbox
, TRUE
, TRUE
, 0);
1195 actions
= gtk_action_group_new ("Account");
1198 gtk_action_group_set_translation_domain(actions
, GETTEXT_PACKAGE
);
1200 // data to action callbacks is set here (data)
1201 gtk_action_group_add_actions (actions
, entries
, n_entries
, data
);
1203 gtk_action_group_add_toggle_actions (actions
,
1204 toggle_entries
, n_toggle_entries
,
1208 /* set which action should have priority in the toolbar */
1209 action
= gtk_action_group_get_action(actions
, "List");
1210 g_object_set(action
, "is_important", TRUE
, NULL
);
1212 action
= gtk_action_group_get_action(actions
, "Bar");
1213 g_object_set(action
, "is_important", TRUE
, NULL
);
1215 action
= gtk_action_group_get_action(actions
, "Detail");
1216 g_object_set(action
, "is_important", TRUE
, NULL
);
1217 g_object_set(action
, "active", PREFS
->budg_showdetail
, NULL
);
1219 action
= gtk_action_group_get_action(actions
, "Refresh");
1220 g_object_set(action
, "is_important", TRUE
, NULL
);
1223 ui
= gtk_ui_manager_new ();
1224 gtk_ui_manager_insert_action_group (ui
, actions
, 0);
1225 gtk_window_add_accel_group (GTK_WINDOW (window
), gtk_ui_manager_get_accel_group (ui
));
1227 if (!gtk_ui_manager_add_ui_from_string (ui
, ui_info
, -1, &error
))
1229 g_message ("building UI failed: %s", error
->message
);
1230 g_error_free (error
);
1236 data
->TB_bar
= gtk_ui_manager_get_widget (ui
, "/ToolBar");
1237 gtk_box_pack_start (GTK_BOX (vbox
), data
->TB_bar
, FALSE
, FALSE
, 0);
1240 hbox
= gtk_hbox_new (FALSE
, HB_BOX_SPACING
);
1241 gtk_container_set_border_width (GTK_CONTAINER(hbox
), HB_BOX_SPACING
);
1242 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1244 widget
= make_label(NULL
, 0.5, 0.5);
1245 gimp_label_set_attributes (GTK_LABEL (widget
), PANGO_ATTR_SCALE
, PANGO_SCALE_SMALL
, -1);
1246 data
->TX_daterange
= widget
;
1247 gtk_box_pack_start (GTK_BOX (hbox
), widget
, TRUE
, TRUE
, 0);
1250 entry
= gtk_label_new(NULL
);
1251 data
->TX_total
[2] = entry
;
1252 gtk_box_pack_end (GTK_BOX (hbox
), entry
, FALSE
, FALSE
, 0);
1253 label
= gtk_label_new(_("Result:"));
1254 gtk_box_pack_end (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
1256 entry
= gtk_label_new(NULL
);
1257 data
->TX_total
[1] = entry
;
1258 gtk_box_pack_end (GTK_BOX (hbox
), entry
, FALSE
, FALSE
, 0);
1259 label
= gtk_label_new(_("Budget:"));
1260 gtk_box_pack_end (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
1262 entry
= gtk_label_new(NULL
);
1263 data
->TX_total
[0] = entry
;
1264 gtk_box_pack_end (GTK_BOX (hbox
), entry
, FALSE
, FALSE
, 0);
1265 label
= gtk_label_new(_("Spent:"));
1266 gtk_box_pack_end (GTK_BOX (hbox
), label
, FALSE
, FALSE
, 0);
1269 notebook
= gtk_notebook_new();
1270 data
->GR_result
= notebook
;
1271 gtk_widget_show(notebook
);
1272 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook
), FALSE
);
1273 gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook
), FALSE
);
1275 gtk_box_pack_start (GTK_BOX (vbox
), notebook
, TRUE
, TRUE
, 0);
1279 vbox
= gtk_vbox_new (FALSE
, 0);
1280 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
), vbox
, NULL
);
1282 widget
= gtk_scrolled_window_new (NULL
, NULL
);
1283 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget
), GTK_SHADOW_ETCHED_IN
);
1284 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget
), GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1285 treeview
= create_list_budget();
1286 data
->LV_report
= treeview
;
1287 gtk_container_add (GTK_CONTAINER(widget
), treeview
);
1288 gtk_box_pack_start (GTK_BOX (vbox
), widget
, TRUE
, TRUE
, 0);
1291 widget
= gtk_scrolled_window_new (NULL
, NULL
);
1292 data
->GR_detail
= widget
;
1293 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget
), GTK_SHADOW_ETCHED_IN
);
1294 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget
), GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1295 treeview
= create_list_transaction(TRN_LIST_TYPE_DETAIL
, PREFS
->lst_ope_columns
);
1296 data
->LV_detail
= treeview
;
1297 gtk_container_add (GTK_CONTAINER(widget
), treeview
);
1299 gtk_box_pack_start (GTK_BOX (vbox
), widget
, TRUE
, TRUE
, 0);
1302 widget
= gtk_chart_new(CHART_TYPE_COL
);
1303 data
->RE_bar
= widget
;
1304 //gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.suffix_symbol);
1305 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
), widget
, NULL
);
1307 //todo:should move this
1308 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data
->CM_minor
),GLOBALS
->minor
);
1311 /* attach our minor to treeview */
1312 g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_report
))), "minor", (gpointer
)data
->CM_minor
);
1313 g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data
->LV_detail
))), "minor", (gpointer
)data
->CM_minor
);
1315 /* signal connect */
1316 g_signal_connect (window
, "delete-event", G_CALLBACK (repbudget_window_dispose
), (gpointer
)data
);
1318 g_signal_connect (data
->CM_minor
, "toggled", G_CALLBACK (repbudget_toggle
), NULL
);
1321 data
->handler_id
[HID_RANGE
] = g_signal_connect (data
->CY_range
, "changed", G_CALLBACK (repbudget_range_change
), NULL
);
1323 g_signal_connect (data
->CY_for
, "changed", G_CALLBACK (repbudget_compute
), (gpointer
)data
);
1324 g_signal_connect (data
->CY_kind
, "changed", G_CALLBACK (repbudget_compute
), (gpointer
)data
);
1325 g_signal_connect (data
->CY_view
, "changed", G_CALLBACK (repbudget_compute
), (gpointer
)data
);
1327 g_signal_connect (data
->RG_zoomx
, "value-changed", G_CALLBACK (repbudget_zoomx_callback
), NULL
);
1329 data
->handler_id
[HID_MINDATE
] = g_signal_connect (data
->PO_mindate
, "changed", G_CALLBACK (repbudget_date_change
), (gpointer
)data
);
1330 data
->handler_id
[HID_MAXDATE
] = g_signal_connect (data
->PO_maxdate
, "changed", G_CALLBACK (repbudget_date_change
), (gpointer
)data
);
1332 g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data
->LV_report
)), "changed", G_CALLBACK (repbudget_selection
), NULL
);
1334 //setup, init and show window
1335 repbudget_setup(data
);
1339 if(PREFS
->toolbar_style
== 0)
1340 gtk_toolbar_unset_style(GTK_TOOLBAR(data
->TB_bar
));
1342 gtk_toolbar_set_style(GTK_TOOLBAR(data
->TB_bar
), PREFS
->toolbar_style
-1);
1345 //setup, init and show window
1346 wg
= &PREFS
->bud_wg
;
1347 gtk_window_move(GTK_WINDOW(window
), wg
->l
, wg
->t
);
1348 gtk_window_resize(GTK_WINDOW(window
), wg
->w
, wg
->h
);
1352 gtk_widget_show_all (window
);
1356 if( PREFS
->euro_active
)
1357 gtk_widget_show(data
->CM_minor
);
1359 gtk_widget_hide(data
->CM_minor
);
1361 //check for any account included into the budget or warn
1366 lacc
= list
= g_hash_table_get_values(GLOBALS
->h_acc
);
1368 while (list
!= NULL
)
1372 if((acc
->flags
& (AF_CLOSED
|AF_NOREPORT
))) goto next1
;
1373 if(!(acc
->flags
& AF_NOBUDGET
))
1376 list
= g_list_next(list
);
1382 ui_dialog_msg_infoerror(GTK_WINDOW(data
->window
), GTK_MESSAGE_WARNING
,
1383 _("No account is defined to be part of the budget."),
1384 _("You should include some accounts from the account dialog.")
1394 //gtk_widget_hide(data->GR_detail);
1396 repbudget_sensitive(window
, NULL
);
1397 repbudget_update_detail(window
, NULL
);
1399 if( PREFS
->date_range_rep
!= 0)
1400 gtk_combo_box_set_active(GTK_COMBO_BOX(data
->CY_range
), PREFS
->date_range_rep
);
1402 repbudget_compute(window
, NULL
);
1408 ** ============================================================================
1410 static void budget_amount_cell_data_function (GtkTreeViewColumn
*col
,
1411 GtkCellRenderer
*renderer
,
1412 GtkTreeModel
*model
,
1418 gchar buf
[G_ASCII_DTOSTR_BUF_SIZE
];
1419 gint column_id
= GPOINTER_TO_INT(user_data
);
1421 gtk_tree_model_get(model
, iter
, column_id
, &value
, -1);
1425 mystrfmon(buf
, G_ASCII_DTOSTR_BUF_SIZE
-1, value
, GLOBALS
->minor
);
1426 //hb_strfmon(buf, G_ASCII_DTOSTR_BUF_SIZE-1, value, GLOBALS->kcur);
1428 if( column_id
== LST_BUDGET_RESULT
)
1429 color
= get_minimum_color_amount (value
, 0.0);
1431 color
= get_normal_color_amount(value
);
1433 g_object_set(renderer
,
1434 "foreground", color
,
1440 g_object_set(renderer
, "text", "", NULL
);
1445 static GtkTreeViewColumn
*amount_list_budget_column(gchar
*name
, gint id
)
1447 GtkTreeViewColumn
*column
;
1448 GtkCellRenderer
*renderer
;
1450 column
= gtk_tree_view_column_new();
1451 gtk_tree_view_column_set_title(column
, name
);
1452 renderer
= gtk_cell_renderer_text_new ();
1453 g_object_set(renderer
, "xalign", 1.0, NULL
);
1454 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1455 gtk_tree_view_column_set_cell_data_func(column
, renderer
, budget_amount_cell_data_function
, GINT_TO_POINTER(id
), NULL
);
1456 gtk_tree_view_column_set_alignment (column
, 0.5);
1457 //gtk_tree_view_column_set_sort_column_id (column, id);
1462 ** create our statistic list
1464 static GtkWidget
*create_list_budget(void)
1466 GtkListStore
*store
;
1468 GtkCellRenderer
*renderer
;
1469 GtkTreeViewColumn
*column
;
1471 /* create list store */
1472 store
= gtk_list_store_new(
1483 view
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(store
));
1484 g_object_unref(store
);
1486 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view
), PREFS
->rules_hint
);
1489 column
= gtk_tree_view_column_new();
1490 gtk_tree_view_column_set_title(column
, _("Category"));
1491 renderer
= gtk_cell_renderer_text_new ();
1492 gtk_tree_view_column_pack_start(column
, renderer
, TRUE
);
1493 //gtk_tree_view_column_set_cell_data_func(column, renderer, ope_result_cell_data_function, NULL, NULL);
1494 gtk_tree_view_column_add_attribute(column
, renderer
, "text", LST_BUDGET_NAME
);
1495 //gtk_tree_view_column_set_sort_column_id (column, LST_STAT_NAME);
1496 gtk_tree_view_column_set_resizable(column
, TRUE
);
1497 gtk_tree_view_column_set_alignment (column
, 0.5);
1498 gtk_tree_view_append_column (GTK_TREE_VIEW(view
), column
);
1500 /* column: Expense */
1501 column
= amount_list_budget_column(_("Spent"), LST_BUDGET_SPENT
);
1502 gtk_tree_view_append_column (GTK_TREE_VIEW(view
), column
);
1504 /* column: Income */
1505 column
= amount_list_budget_column(_("Budget"), LST_BUDGET_BUDGET
);
1506 gtk_tree_view_append_column (GTK_TREE_VIEW(view
), column
);
1508 /* column: Result */
1509 column
= amount_list_budget_column(_("Result"), LST_BUDGET_RESULT
);
1510 gtk_tree_view_append_column (GTK_TREE_VIEW(view
), column
);
1512 /* column last: empty */
1513 column
= gtk_tree_view_column_new();
1514 gtk_tree_view_append_column (GTK_TREE_VIEW(view
), column
);
1518 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_BUDGET_POS , stat_list_compare_func, GINT_TO_POINTER(LST_BUDGET_POS), NULL);
1519 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_BUDGET_SPENT , stat_list_compare_func, GINT_TO_POINTER(LST_BUDGET_SPENT), NULL);
1520 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_BUDGET_BUDGET, stat_list_compare_func, GINT_TO_POINTER(LST_BUDGET_BUDGET), NULL);
1521 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), LST_BUDGET_RESULT , stat_list_compare_func, GINT_TO_POINTER(LST_BUDGET_RESULT), NULL);