1
/* HomeBank -- Free easy personal accounting for all !
2
* Copyright (C) 1995-2006 Maxime DOYEN
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1
/* HomeBank -- Free, easy, personal accounting for everyone.
2
* Copyright (C) 1995-2008 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/>.
20
21
#include "homebank.h"
23
#include "dsp_wallet.h"
22
24
#include "rep_stats.h"
23
25
#include "list_operation.h"
24
26
#include "def_filter.h"
113
119
static void statistic_action_filter(GtkAction *action, gpointer user_data);
114
120
static void statistic_action_refresh(GtkAction *action, gpointer user_data);
122
static void statistic_busy(GtkWidget *widget, gboolean state);
116
125
static GtkActionEntry entries[] = {
117
126
{ "List" , "hb-stock-view-list" , N_("List") , NULL, N_("View results as list"), G_CALLBACK (statistic_action_viewlist) },
118
{ "Bar" , "hb-stock-view-bar" , N_("Bar") , NULL, N_("View results as 2d-bars"), G_CALLBACK (statistic_action_viewbar) },
119
{ "Pie" , "hb-stock-view-pie" , N_("Pie") , NULL, N_("View results as 2d-pies"), G_CALLBACK (statistic_action_viewpie) },
127
{ "Bar" , "hb-stock-view-bar" , N_("Bar") , NULL, N_("View results as bars"), G_CALLBACK (statistic_action_viewbar) },
128
{ "Pie" , "hb-stock-view-pie" , N_("Pie") , NULL, N_("View results as pies"), G_CALLBACK (statistic_action_viewpie) },
121
130
{ "Detail" , "hb-stock-ope-show" , N_("Detail") , NULL, N_("Toggle detail"), G_CALLBACK (statistic_action_detail) },
122
131
{ "Legend" , "hb-stock-legend" , N_("Legend") , NULL, N_("Toggle legend"), G_CALLBACK (statistic_action_legend) },
163
void statistic_date_change(GtkWidget *widget, gpointer user_data);
164
void statistic_period_change(GtkWidget *widget, gpointer user_data);
165
void statistic_range_change(GtkWidget *widget, gpointer user_data);
166
void statistic_action(GtkWidget *widget, gpointer user_data);
167
void statistic_detail(GtkWidget *widget, gpointer user_data);
168
void statistic_update(GtkWidget *widget, gpointer user_data);
169
void statistic_update_total(GtkWidget *widget, gpointer user_data);
170
void statistic_compute(GtkWidget *widget, gpointer user_data);
171
void statistic_sensitive(GtkWidget *widget, gpointer user_data);
172
void statistic_toggle_detail(GtkWidget *widget, gpointer user_data);
173
void statistic_toggle_legend(GtkWidget *widget, gpointer user_data);
174
void statistic_toggle_minor(GtkWidget *widget, gpointer user_data);
175
void statistic_toggle_rate(GtkWidget *widget, gpointer user_data);
176
GtkWidget *create_list_statistic(void);
172
static void statistic_date_change(GtkWidget *widget, gpointer user_data);
173
static void statistic_period_change(GtkWidget *widget, gpointer user_data);
174
static void statistic_range_change(GtkWidget *widget, gpointer user_data);
175
static void statistic_detail(GtkWidget *widget, gpointer user_data);
176
static void statistic_update(GtkWidget *widget, gpointer user_data);
177
static void statistic_update_total(GtkWidget *widget, gpointer user_data);
178
static void statistic_compute(GtkWidget *widget, gpointer user_data);
179
static void statistic_sensitive(GtkWidget *widget, gpointer user_data);
180
static void statistic_toggle_detail(GtkWidget *widget, gpointer user_data);
181
static void statistic_toggle_legend(GtkWidget *widget, gpointer user_data);
182
static void statistic_toggle_minor(GtkWidget *widget, gpointer user_data);
183
static void statistic_toggle_rate(GtkWidget *widget, gpointer user_data);
184
static GtkWidget *create_list_statistic(void);
178
gint stat_list_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata);
186
static gint stat_list_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata);
356
363
** return the year list position correponding to the passed date
358
gint DateInYear(guint32 from, guint32 opedate)
365
static gint DateInYear(guint32 from, guint32 opedate)
361
368
gint year_from, year_ope, pos;
510
517
DB( g_print("(statistic) detail\n") );
519
/* clear and detach our model */
520
model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_detail));
521
gtk_list_store_clear (GTK_LIST_STORE(model));
523
if(data->detail && active != -1)
514
525
tmpfor = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_for));
516
/* clear and detach our model */
517
model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_detail));
518
gtk_list_store_clear (GTK_LIST_STORE(model));
519
527
g_object_ref(model); /* Make sure the model stays with us after the tree view unrefs it */
520
528
gtk_tree_view_set_model(GTK_TREE_VIEW(data->LV_detail), NULL); /* Detach model from view */
585
void statistic_update(GtkWidget *widget, gpointer user_data)
592
static void statistic_update(GtkWidget *widget, gpointer user_data)
587
594
struct statistic_data *data;
588
595
gboolean byamount;
589
596
GtkTreeModel *model;
590
gint tmpkind, column;
597
gint page, tmpkind, column;
592
599
DB( g_print("(statistic) update\n") );
598
605
byamount = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_byamount));
599
606
tmpkind = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_view));
608
// ensure not exp & inc for piechart
609
page = gtk_notebook_get_current_page(GTK_NOTEBOOK(data->GR_result));
611
if( page == 2 && tmpkind == 0 )
613
g_signal_handler_block(data->CY_view, data->handler_id[HID_VIEW]);
614
gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_view), 1);
615
g_signal_handler_unblock(data->CY_view, data->handler_id[HID_VIEW]);
601
620
DB( g_print(" tmpkind %d\n\n", tmpkind) );
841
861
DB( g_print(" inserting %2d, %48s, %9.2f %9.2f %9.2f\n", i, name, tmp_expense[i], tmp_income[i], tmp_expense[i] + tmp_income[i]) );
868
if( data->total_expense )
869
exprate = (ABS(tmp_expense[i]) * 100 / data->total_expense);
871
if( data->total_income )
872
incrate = (tmp_income[i] * 100 / data->total_income);
874
if( (data->total_expense + data->total_income) )
875
balrate = (ABS(tmp_expense[i]) + tmp_income[i]) * 100 / (data->total_expense + data->total_income);
843
877
gtk_list_store_append (GTK_LIST_STORE(model), &iter);
844
878
gtk_list_store_set (GTK_LIST_STORE(model), &iter,
845
879
LST_STAT_POS, id++,
848
882
LST_STAT_EXPENSE, tmp_expense[i],
849
883
LST_STAT_INCOME, tmp_income[i],
850
884
LST_STAT_BALANCE, tmp_expense[i] + tmp_income[i],
851
LST_STAT_EXPRATE, (ABS(tmp_expense[i]) * 100 / data->total_expense),
852
LST_STAT_INCRATE, (tmp_income[i] * 100 / data->total_income),
853
LST_STAT_BALRATE, (ABS(tmp_expense[i]) + tmp_income[i]) * 100 / (data->total_expense + data->total_income) ,
885
LST_STAT_EXPRATE, exprate,
886
LST_STAT_INCRATE, incrate,
887
LST_STAT_BALRATE, balrate,
856
890
g_free(fullcatname);
919
953
// gtk_widget_set_sensitive(data->TB_buttons[ACTION_REPBUDGET_DETAIL], sensitive);
920
954
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->ui, "/ToolBar/Detail"), sensitive);
956
view = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_view));
922
958
sensitive = page == 0 ? FALSE : TRUE;
923
gtk_widget_set_sensitive(data->CY_view, sensitive);
959
// gtk_widget_set_sensitive(data->CY_view, sensitive);
924
960
// gtk_widget_set_sensitive(data->TB_buttons[ACTION_REPBUDGET_LEGEND], sensitive);
925
961
gtk_action_set_sensitive(gtk_ui_manager_get_action(data->ui, "/ToolBar/Legend"), sensitive);
930
void statistic_update_detail(GtkWidget *widget, gpointer user_data)
966
static void statistic_update_detail(GtkWidget *widget, gpointer user_data)
932
968
struct statistic_data *data;
1001
1037
** change the chart rate columns visibility
1003
void statistic_toggle_rate(GtkWidget *widget, gpointer user_data)
1039
static void statistic_toggle_rate(GtkWidget *widget, gpointer user_data)
1005
1041
struct statistic_data *data;
1006
1042
GtkTreeViewColumn *column;
1083
static void statistic_busy(GtkWidget *widget, gboolean state)
1085
struct statistic_data *data;
1089
DB( g_printf("(statistic) busy\n") );
1091
window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
1092
data = g_object_get_data(G_OBJECT(window), "inst_data");
1097
cursor = gdk_cursor_new(GDK_WATCH);
1098
gdk_window_set_cursor(GTK_WIDGET(window)->window, cursor);
1099
gdk_cursor_unref(cursor);
1101
//gtk_grab_add(data->busy_popup);
1103
gtk_widget_set_sensitive(window, FALSE);
1104
gtk_action_group_set_sensitive(data->actions, FALSE);
1106
/* make sure chnages is up */
1107
while (gtk_events_pending ())
1108
gtk_main_iteration ();
1113
gtk_widget_set_sensitive(window, TRUE);
1114
gtk_action_group_set_sensitive(data->actions, TRUE);
1116
gdk_window_set_cursor(GTK_WIDGET(window)->window, NULL);
1117
//gtk_grab_remove(data->busy_popup);
1050
void statistic_setup(struct statistic_data *data)
1124
static void statistic_setup(struct statistic_data *data)
1052
1126
DB( g_print("(statistic) setup\n") );
1062
1136
statistic_toggle_rate(data->window, NULL);
1064
1138
filter_reset(data->filter);
1140
/* 3.4 : make int transfert out of stats */
1141
data->filter->option[FILTER_PAYMODE] = 1;
1142
data->filter->paymode[PAYMODE_PERSTRANSFERT] = FALSE;
1066
1144
/* if ope get date bounds */
1067
1145
if(g_list_length(GLOBALS->ope_list) > 0)
1122
1200
gtk_tree_model_get(model, &iter, LST_STAT_KEY, &key, -1);
1124
DB( g_print(" - active is %d\n", key) );
1127
statistic_detail(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), (gpointer)key);
1204
DB( g_print(" - active is %d\n", key) );
1206
statistic_detail(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), (gpointer)key);
1130
1207
statistic_sensitive(GTK_WIDGET(gtk_tree_selection_get_tree_view (treeselection)), NULL);
1138
gboolean statistic_dispose(GtkWidget *widget, GdkEvent *event, gpointer user_data)
1214
static gboolean statistic_dispose(GtkWidget *widget, GdkEvent *event, gpointer user_data)
1140
1216
struct statistic_data *data = user_data;
1217
struct WinGeometry *wg;
1142
1219
DB( g_print("(statistic) dispose\n") );
1225
//store position and size
1226
wg = &PREFS->sta_wg;
1227
gtk_window_get_position(GTK_WINDOW(widget), &wg->l, &wg->t);
1228
gtk_window_get_size(GTK_WINDOW(widget), &wg->w, &wg->h);
1230
DB( g_printf(" window: l=%d, t=%d, w=%d, h=%d\n", wg->l, wg->t, wg->w, wg->h) );
1148
1234
//enable define windows
1149
1235
GLOBALS->define_off--;
1150
1236
wallet_update(GLOBALS->mainwindow, (gpointer)2);
1156
1242
GtkWidget *create_statistic_window(void)
1158
1244
struct statistic_data *data;
1245
struct WinGeometry *wg;
1159
1246
GtkWidget *window, *mainvbox, *hbox, *vbox, *notebook, *treeview;
1160
1247
GtkWidget *label, *widget, *table, *alignment, *vbar, *entry;
1369
1457
//gtk_scrolled_window_set_placement(GTK_SCROLLED_WINDOW (widget), GTK_CORNER_TOP_RIGHT);
1370
1458
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_ETCHED_IN);
1371
1459
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
1372
treeview = create_list_operation();
1460
treeview = create_list_operation(PREFS->lst_ope_columns);
1373
1461
data->LV_detail = treeview;
1374
1462
gtk_container_add (GTK_CONTAINER(widget), treeview);
1380
1468
widget = gtk_chart_new(CHART_BAR_TYPE);
1381
1469
data->RE_bar = widget;
1382
gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->euro_symbol);
1470
gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.suffix_symbol);
1383
1471
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), widget, NULL);
1386
1474
widget = gtk_chart_new(CHART_PIE_TYPE);
1387
1475
data->RE_pie = widget;
1388
gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->euro_symbol);
1476
gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.suffix_symbol);
1389
1477
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), widget, NULL);
1393
1481
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_minor), GLOBALS->minor);
1394
1482
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_byamount), PREFS->stat_byamount);
1484
gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_view), 1);
1397
1486
/* attach our minor to treeview */
1398
1487
g_object_set_data(G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_report))), "minor", (gpointer)data->CM_minor);
1422
1511
//setup, init and show window
1423
1512
statistic_setup(data);
1426
gtk_window_set_default_size (GTK_WINDOW (window), 640, 480);
1515
if(PREFS->toolbar_style == 0)
1516
gtk_toolbar_unset_style(GTK_TOOLBAR(data->TB_bar));
1518
gtk_toolbar_set_style(GTK_TOOLBAR(data->TB_bar), PREFS->toolbar_style-1);
1520
//setup, init and show window
1521
wg = &PREFS->sta_wg;
1522
gtk_window_move(GTK_WINDOW(window), wg->l, wg->t);
1523
gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h);
1428
1525
gtk_widget_show_all (window);
1527
statistic_busy(window, TRUE);
1432
1530
if( PREFS->euro_active )
1505
1605
gtk_tree_model_get(model, iter, user_data, &value, -1);
1507
widget = g_object_get_data(G_OBJECT(model), "minor");
1508
if(GTK_IS_TOGGLE_BUTTON(widget))
1510
minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1609
widget = g_object_get_data(G_OBJECT(model), "minor");
1610
if(GTK_IS_TOGGLE_BUTTON(widget))
1612
minor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
1617
mystrfmon(buf, 127, value, minor);
1619
color = (value > 0) ? PREFS->color_inc : PREFS->color_exp;
1621
markuptxt = g_strdup_printf("<span color='#%06x'>%s</span>", color, buf);
1622
g_object_set(renderer, "markup", markuptxt, NULL);
1515
hb_strfmon(buf, 127, value, minor);
1517
color = (value > 0) ? PREFS->color_inc : PREFS->color_exp;
1519
markuptxt = g_strdup_printf("<span color='#%06x'>%s</span>", color, buf);
1520
g_object_set(renderer, "markup", markuptxt, NULL);
1627
g_object_set(renderer, "text", "", NULL);
1526
GtkTreeViewColumn *amount_list_statistic_column(gchar *name, gint id)
1633
static GtkTreeViewColumn *amount_list_statistic_column(gchar *name, gint id)
1528
1635
GtkTreeViewColumn *column;
1529
1636
GtkCellRenderer *renderer;
1597
1704
//gtk_tree_view_column_set_cell_data_func(column, renderer, ope_result_cell_data_function, NULL, NULL);
1598
1705
gtk_tree_view_column_add_attribute(column, renderer, "text", LST_STAT_NAME);
1599
1706
//gtk_tree_view_column_set_sort_column_id (column, LST_STAT_NAME);
1707
gtk_tree_view_column_set_resizable(column, TRUE);
1600
1708
gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
1602
1710
/* column: Expense */
1634
gint stat_list_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
1742
static gint stat_list_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
1636
1744
gint sortcol = GPOINTER_TO_INT(userdata);