00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027
00028 #include <gtk/gtk.h>
00029 #include <glib/gi18n.h>
00030
00031 #include "Account.h"
00032 #include "gnc-accounting-period.h"
00033 #include "gnc-component-manager.h"
00034 #include "gnc-euro.h"
00035 #include "gnc-event.h"
00036 #include "gnc-gconf-utils.h"
00037 #include "gnc-ui-util.h"
00038 #include "window-main-summarybar.h"
00039
00040 typedef struct {
00041 GtkWidget * hbox;
00042 GtkWidget * totals_combo;
00043 GtkListStore *datamodel;
00044 int component_id;
00045 int cnxn_id;
00046 } GNCMainSummary;
00047
00048 #define WINDOW_SUMMARYBAR_CM_CLASS "summary-bar"
00049
00050 #define GCONF_SECTION "window/pages/account_tree/summary"
00051 #define KEY_GRAND_TOTAL "grand_total"
00052 #define KEY_NON_CURRENCY "non_currency"
00053
00065 typedef struct {
00066 gnc_commodity * currency;
00067 gnc_numeric assets;
00068 gnc_numeric profits;
00069 gint total_mode;
00070 } GNCCurrencyAcc;
00071
00072
00073
00074 #define TOTAL_SINGLE 0
00075 #define TOTAL_CURR_TOTAL 1
00076 #define TOTAL_NON_CURR_TOTAL 2
00077 #define TOTAL_GRAND_TOTAL 3
00078
00079
00081 typedef struct {
00082 gnc_commodity *default_currency;
00083 gboolean euro;
00084 gboolean grand_total;
00085 gboolean non_currency;
00086 time_t start_date;
00087 time_t end_date;
00088 } GNCSummarybarOptions;
00089
00094 static GNCCurrencyAcc *
00095 gnc_ui_get_currency_accumulator(GList **list, gnc_commodity * currency, gint total_mode)
00096 {
00097 GList *current;
00098 GNCCurrencyAcc *found;
00099
00100 for (current = g_list_first(*list); current; current = g_list_next(current)) {
00101 found = current->data;
00102 if ((gnc_commodity_equiv(currency, found->currency))
00103 && (found->total_mode == total_mode)) {
00104 return found;
00105 }
00106 }
00107
00108 found = g_new0 (GNCCurrencyAcc, 1);
00109 found->currency = currency;
00110 found->assets = gnc_numeric_zero ();
00111 found->profits = gnc_numeric_zero ();
00112 found->total_mode = total_mode;
00113 *list = g_list_append (*list, found);
00114
00115 return found;
00116 }
00117
00121 static void
00122 gnc_ui_accounts_recurse (Account *parent, GList **currency_list,
00123 GNCSummarybarOptions options)
00124 {
00125 gnc_numeric start_amount;
00126 gnc_numeric start_amount_default_currency;
00127 gnc_numeric end_amount;
00128 gnc_numeric end_amount_default_currency;
00129 GNCAccountType account_type;
00130 gnc_commodity * account_currency;
00131 gnc_commodity * euro_commodity;
00132 GNCCurrencyAcc *currency_accum = NULL;
00133 GNCCurrencyAcc *euro_accum = NULL;
00134 GNCCurrencyAcc *grand_total_accum = NULL;
00135 GNCCurrencyAcc *non_curr_accum = NULL;
00136 GList *children, *node;
00137 gboolean non_currency = FALSE;
00138 Timespec end_timespec;
00139 Timespec start_timespec;
00140
00141 if (parent == NULL) return;
00142
00143 children = gnc_account_get_children(parent);
00144 for (node = children; node; node = g_list_next(node))
00145 {
00146 Account *account = node->data;
00147
00148 account_type = xaccAccountGetType(account);
00149 account_currency = xaccAccountGetCommodity(account);
00150
00151 if(options.grand_total)
00152 grand_total_accum = gnc_ui_get_currency_accumulator(currency_list,
00153 options.default_currency,
00154 TOTAL_GRAND_TOTAL);
00155
00156 if (options.euro)
00157 {
00158 euro_commodity = gnc_get_euro ();
00159 euro_accum = gnc_ui_get_currency_accumulator(currency_list,
00160 euro_commodity,
00161 TOTAL_CURR_TOTAL);
00162 }
00163 else
00164 euro_commodity = NULL;
00165
00166 if(!gnc_commodity_is_currency(account_currency)) {
00167 non_currency = TRUE;
00168 non_curr_accum = gnc_ui_get_currency_accumulator(currency_list,
00169 options.default_currency,
00170 TOTAL_NON_CURR_TOTAL);
00171 }
00172
00173 if(!non_currency || options.non_currency) {
00174 currency_accum = gnc_ui_get_currency_accumulator(currency_list,
00175 account_currency,
00176 TOTAL_SINGLE);
00177 }
00178
00179 switch (account_type)
00180 {
00181 case ACCT_TYPE_BANK:
00182 case ACCT_TYPE_CASH:
00183 case ACCT_TYPE_ASSET:
00184 case ACCT_TYPE_STOCK:
00185 case ACCT_TYPE_MUTUAL:
00186 case ACCT_TYPE_CREDIT:
00187 case ACCT_TYPE_LIABILITY:
00188 case ACCT_TYPE_PAYABLE:
00189 case ACCT_TYPE_RECEIVABLE:
00190 end_amount = xaccAccountGetBalanceAsOfDate(account, options.end_date);
00191 timespecFromTime_t(&end_timespec, options.end_date);
00192 end_amount_default_currency =
00193 xaccAccountConvertBalanceToCurrencyAsOfDate
00194 (account, end_amount, account_currency, options.default_currency,
00195 timespecToTime_t(timespecCanonicalDayTime(end_timespec)));
00196
00197 if(!non_currency || options.non_currency) {
00198 currency_accum->assets =
00199 gnc_numeric_add (currency_accum->assets, end_amount,
00200 gnc_commodity_get_fraction (account_currency),
00201 GNC_RND_ROUND);
00202 }
00203
00204 if(non_currency) {
00205 non_curr_accum->assets =
00206 gnc_numeric_add (non_curr_accum->assets, end_amount_default_currency,
00207 gnc_commodity_get_fraction (options.default_currency),
00208 GNC_RND_ROUND);
00209 }
00210
00211 if(options.grand_total) {
00212 grand_total_accum->assets =
00213 gnc_numeric_add (grand_total_accum->assets, end_amount_default_currency,
00214 gnc_commodity_get_fraction (options.default_currency),
00215 GNC_RND_ROUND);
00216 }
00217
00218 if (options.euro && (currency_accum != euro_accum)) {
00219 euro_accum->assets =
00220 gnc_numeric_add (euro_accum->assets,
00221 gnc_convert_to_euro(account_currency, end_amount),
00222 gnc_commodity_get_fraction (euro_commodity),
00223 GNC_RND_ROUND);
00224 }
00225
00226 gnc_ui_accounts_recurse(account, currency_list, options);
00227 break;
00228 case ACCT_TYPE_INCOME:
00229 case ACCT_TYPE_EXPENSE:
00230 start_amount = xaccAccountGetBalanceAsOfDate(account, options.start_date);
00231 timespecFromTime_t(&start_timespec, options.start_date);
00232 start_amount_default_currency =
00233 xaccAccountConvertBalanceToCurrencyAsOfDate
00234 (account, start_amount, account_currency, options.default_currency,
00235 timespecToTime_t(timespecCanonicalDayTime(start_timespec)));
00236 end_amount = xaccAccountGetBalanceAsOfDate(account, options.end_date);
00237 timespecFromTime_t(&end_timespec, options.end_date);
00238 end_amount_default_currency =
00239 xaccAccountConvertBalanceToCurrencyAsOfDate
00240 (account, end_amount, account_currency, options.default_currency,
00241 timespecToTime_t(timespecCanonicalDayTime(end_timespec)));
00242
00243 if(!non_currency || options.non_currency) {
00244 currency_accum->profits =
00245 gnc_numeric_add (currency_accum->profits, start_amount,
00246 gnc_commodity_get_fraction (account_currency),
00247 GNC_RND_ROUND);
00248 currency_accum->profits =
00249 gnc_numeric_sub (currency_accum->profits, end_amount,
00250 gnc_commodity_get_fraction (account_currency),
00251 GNC_RND_ROUND);
00252 }
00253
00254 if(non_currency) {
00255 non_curr_accum->profits =
00256 gnc_numeric_add (non_curr_accum->profits, start_amount_default_currency,
00257 gnc_commodity_get_fraction (options.default_currency),
00258 GNC_RND_ROUND);
00259 non_curr_accum->profits =
00260 gnc_numeric_sub (non_curr_accum->profits, end_amount_default_currency,
00261 gnc_commodity_get_fraction (options.default_currency),
00262 GNC_RND_ROUND);
00263 }
00264
00265 if(options.grand_total) {
00266 grand_total_accum->profits =
00267 gnc_numeric_add (grand_total_accum->profits,
00268 start_amount_default_currency,
00269 gnc_commodity_get_fraction (options.default_currency),
00270 GNC_RND_ROUND);
00271 grand_total_accum->profits =
00272 gnc_numeric_sub (grand_total_accum->profits,
00273 end_amount_default_currency,
00274 gnc_commodity_get_fraction (options.default_currency),
00275 GNC_RND_ROUND);
00276 }
00277
00278 if (options.euro && (currency_accum != euro_accum)) {
00279 euro_accum->profits =
00280 gnc_numeric_add (euro_accum->profits,
00281 gnc_convert_to_euro(account_currency, start_amount),
00282 gnc_commodity_get_fraction (euro_commodity),
00283 GNC_RND_ROUND);
00284 euro_accum->profits =
00285 gnc_numeric_sub (euro_accum->profits,
00286 gnc_convert_to_euro(account_currency, end_amount),
00287 gnc_commodity_get_fraction (euro_commodity),
00288 GNC_RND_ROUND);
00289 }
00290
00291 gnc_ui_accounts_recurse(account, currency_list, options);
00292 break;
00293 case ACCT_TYPE_EQUITY:
00294
00295 break;
00296 case ACCT_TYPE_CURRENCY:
00297 default:
00298 break;
00299 }
00300 }
00301 g_list_free(children);
00302 }
00303
00304 static char*
00305 get_total_mode_label(const char *mnemonic, int total_mode)
00306 {
00307 char *label_str;
00308
00309 switch(total_mode)
00310 {
00311 case TOTAL_CURR_TOTAL:
00312 label_str = g_strdup_printf( _("%s, Total:"), mnemonic );
00313 break;
00314 case TOTAL_NON_CURR_TOTAL:
00315 label_str = g_strdup_printf( _("%s, Non Currency Commodities Total:"), mnemonic );
00316 break;
00317 case TOTAL_GRAND_TOTAL:
00318 label_str = g_strdup_printf( _("%s, Grand Total:"), mnemonic );
00319 break;
00320 case TOTAL_SINGLE:
00321 default:
00322 label_str = g_strdup_printf( _("%s:"), mnemonic );
00323 break;
00324 }
00325 return label_str;
00326 }
00327
00328 enum {
00329 COLUMN_MNEMONIC_TYPE,
00330 COLUMN_ASSETS,
00331 COLUMN_ASSETS_VALUE,
00332 COLUMN_PROFITS,
00333 COLUMN_PROFITS_VALUE,
00334 N_COLUMNS,
00335 };
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 static void
00355 gnc_main_window_summary_refresh (GNCMainSummary * summary)
00356 {
00357 Account *root;
00358 char asset_string[256];
00359 char profit_string[256];
00360 GNCCurrencyAcc *currency_accum;
00361 GList *currency_list;
00362 GList *current;
00363 GNCSummarybarOptions options;
00364
00365 options.default_currency = gnc_default_report_currency ();
00366
00367 options.euro = gnc_gconf_get_bool(GCONF_GENERAL, KEY_ENABLE_EURO, NULL);
00368 options.grand_total =
00369 gnc_gconf_get_bool(GCONF_SECTION, KEY_GRAND_TOTAL, NULL);
00370 options.non_currency =
00371 gnc_gconf_get_bool(GCONF_SECTION, KEY_NON_CURRENCY, NULL);
00372 options.start_date = gnc_accounting_period_fiscal_start();
00373 options.end_date = gnc_accounting_period_fiscal_end();
00374
00375 currency_list = NULL;
00376
00377
00378 if(options.grand_total) {
00379 gnc_ui_get_currency_accumulator (¤cy_list, options.default_currency,
00380 TOTAL_GRAND_TOTAL);
00381 }
00382
00383 gnc_ui_get_currency_accumulator (¤cy_list, options.default_currency,
00384 TOTAL_SINGLE);
00385
00386 root = gnc_get_current_root_account ();
00387 gnc_ui_accounts_recurse(root, ¤cy_list, options);
00388
00389 {
00390 GtkTreeIter iter;
00391 char asset_amount_string[256], profit_amount_string[256];
00392 struct lconv *lc;
00393
00394 lc = gnc_localeconv();
00395
00396 g_object_ref(summary->datamodel);
00397 gtk_combo_box_set_model(GTK_COMBO_BOX(summary->totals_combo), NULL);
00398 gtk_list_store_clear(summary->datamodel);
00399 for (current = g_list_first(currency_list); current; current = g_list_next(current)) {
00400 const char *mnemonic;
00401 gchar *total_mode_label;
00402
00403 currency_accum = current->data;
00404
00405 if (gnc_commodity_equiv (currency_accum->currency, gnc_locale_default_currency ()))
00406 mnemonic = lc->currency_symbol;
00407 else
00408 mnemonic = gnc_commodity_get_mnemonic (currency_accum->currency);
00409
00410 if (mnemonic == NULL)
00411 mnemonic = "";
00412
00413 *asset_string= '\0';
00414 xaccSPrintAmount(asset_amount_string,
00415 currency_accum->assets,
00416 gnc_commodity_print_info(currency_accum->currency, TRUE));
00417
00418 *profit_string= '\0';
00419 xaccSPrintAmount(profit_amount_string,
00420 currency_accum->profits,
00421 gnc_commodity_print_info(currency_accum->currency, TRUE));
00422
00423 gtk_list_store_append(summary->datamodel, &iter);
00424 total_mode_label = get_total_mode_label(mnemonic, currency_accum->total_mode);
00425 gtk_list_store_set(summary->datamodel, &iter,
00426 COLUMN_MNEMONIC_TYPE, total_mode_label,
00427 COLUMN_ASSETS, _("Assets:"),
00428 COLUMN_ASSETS_VALUE, asset_amount_string,
00429 COLUMN_PROFITS, _("Profits:"),
00430 COLUMN_PROFITS_VALUE, profit_amount_string,
00431 -1);
00432 g_free(total_mode_label);
00433 }
00434 gtk_combo_box_set_model(GTK_COMBO_BOX(summary->totals_combo),
00435 GTK_TREE_MODEL(summary->datamodel));
00436 g_object_unref(summary->datamodel);
00437
00438 gtk_combo_box_set_active(GTK_COMBO_BOX(summary->totals_combo), 0);
00439 }
00440
00441
00442 for (current = g_list_first(currency_list);
00443 current;
00444 current = g_list_next(current)) {
00445 g_free(current->data);
00446 }
00447 g_list_free(currency_list);
00448 }
00449
00450 static void
00451 gnc_main_window_summary_destroy_cb(GNCMainSummary *summary, gpointer data)
00452 {
00453 gnc_gconf_remove_anon_notification(GCONF_SECTION, summary->cnxn_id);
00454 gnc_unregister_gui_component(summary->component_id);
00455 g_free(summary);
00456 }
00457
00458 static void
00459 summarybar_refresh_handler(GHashTable * changes, gpointer user_data)
00460 {
00461 GNCMainSummary * summary = user_data;
00462 gnc_main_window_summary_refresh(summary);
00463 }
00464
00465 static void
00466 gconf_client_notify_cb (GConfClient *client,
00467 guint cnxn_id,
00468 GConfEntry *entry,
00469 gpointer user_data)
00470 {
00471 GNCMainSummary * summary = user_data;
00472 gnc_main_window_summary_refresh(summary);
00473 }
00474
00475 GtkWidget *
00476 gnc_main_window_summary_new (void)
00477 {
00478 GNCMainSummary * retval = g_new0(GNCMainSummary, 1);
00479 GtkCellRenderer *textRenderer;
00480 int i;
00481
00482
00483
00484 gboolean expandOptions[] = { TRUE, FALSE, TRUE, FALSE, TRUE };
00485
00486 retval->datamodel = gtk_list_store_new( N_COLUMNS,
00487 G_TYPE_STRING,
00488 G_TYPE_STRING,
00489 G_TYPE_STRING,
00490 G_TYPE_STRING,
00491 G_TYPE_STRING );
00492
00493 retval->hbox = gtk_hbox_new (FALSE, 5);
00494 retval->totals_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (retval->datamodel));
00495 g_object_unref (retval->datamodel);
00496
00497 retval->component_id = gnc_register_gui_component (WINDOW_SUMMARYBAR_CM_CLASS,
00498 summarybar_refresh_handler,
00499 NULL, retval);
00500 gnc_gui_component_watch_entity_type (retval->component_id,
00501 GNC_ID_ACCOUNT,
00502 QOF_EVENT_DESTROY
00503 | GNC_EVENT_ITEM_CHANGED);
00504
00505 for ( i = 0; i < N_COLUMNS; i++ )
00506 {
00507 textRenderer = GTK_CELL_RENDERER(gtk_cell_renderer_text_new());
00508 gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(retval->totals_combo), textRenderer, expandOptions[i] );
00509 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(retval->totals_combo), textRenderer, "text", i );
00510 }
00511
00512 gtk_container_set_border_width (GTK_CONTAINER (retval->hbox), 2);
00513 gtk_box_pack_start (GTK_BOX(retval->hbox), retval->totals_combo, TRUE, TRUE, 5);
00514 gtk_widget_show (retval->totals_combo);
00515 gtk_widget_show (retval->hbox);
00516
00517 g_signal_connect_swapped (G_OBJECT (retval->hbox), "destroy",
00518 G_CALLBACK (gnc_main_window_summary_destroy_cb),
00519 retval);
00520
00521 gnc_main_window_summary_refresh(retval);
00522
00523 retval->cnxn_id = gnc_gconf_add_anon_notification(GCONF_SECTION,
00524 gconf_client_notify_cb,
00525 retval);
00526
00527 return retval->hbox;
00528 }
00529