27 #include <glib/gi18n.h>
31 #include "dialog-fincalc.h"
32 #include "dialog-utils.h"
35 #include "gnc-amount-edit.h"
37 #include "gnc-component-manager.h"
38 #include "gnc-date-edit.h"
40 #include "gnc-gui-query.h"
41 #include "gnc-locale-utils.h"
44 #define DIALOG_FINCALC_CM_CLASS "dialog-fincalc"
45 #define GNC_PREFS_GROUP "dialogs.fincalc"
63 GtkWidget *amounts[NUM_FIN_CALC_VALUES];
65 GtkWidget *calc_button;
67 GtkWidget *compounding_combo;
68 GtkWidget *payment_combo;
70 GtkWidget *end_of_period_radio;
71 GtkWidget *discrete_compounding_radio;
73 GtkWidget *payment_total_label;
78 static unsigned int periods[] =
98 void fincalc_update_calc_button_cb(GtkWidget *unused,
FinCalcDialog *fcd);
99 void fincalc_calc_clicked_cb(GtkButton *button,
FinCalcDialog *fcd);
100 void fincalc_compounding_radio_toggled(GtkToggleButton *togglebutton, gpointer data);
101 void fincalc_amount_clear_clicked_cb(GtkButton *button,
FinCalcDialog *fcd);
102 void fincalc_response_cb (GtkDialog *dialog, gint response,
FinCalcDialog *fcd);
109 normalize_period(
unsigned int *period)
113 g_return_val_if_fail (period, 0);
115 for (i = (
sizeof(periods) /
sizeof(
unsigned int)) - 1; i >= 0; i--)
116 if (*period >= periods[i])
118 *period = periods[i];
122 *period = periods[0];
132 static char string[64];
141 npp = gnc_numeric_create (fcd->financial_info.npp, 1);
143 gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(fcd->amounts[PAYMENT_PERIODS]),
145 gnc_amount_edit_set_damount (GNC_AMOUNT_EDIT(fcd->amounts[INTEREST_RATE]),
146 fcd->financial_info.ir);
147 gnc_amount_edit_set_damount (GNC_AMOUNT_EDIT(fcd->amounts[PRESENT_VALUE]),
148 fcd->financial_info.pv);
149 gnc_amount_edit_set_damount (GNC_AMOUNT_EDIT(fcd->amounts[PERIODIC_PAYMENT]),
150 fcd->financial_info.pmt);
151 gnc_amount_edit_set_damount (GNC_AMOUNT_EDIT(fcd->amounts[FUTURE_VALUE]),
152 -fcd->financial_info.fv);
162 gtk_label_set_text (GTK_LABEL(fcd->payment_total_label),
string);
164 i = normalize_period(&fcd->financial_info.CF);
165 gtk_combo_box_set_active(GTK_COMBO_BOX(fcd->compounding_combo), i);
167 i = normalize_period(&fcd->financial_info.PF);
168 gtk_combo_box_set_active(GTK_COMBO_BOX(fcd->payment_combo), i);
170 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fcd->end_of_period_radio),
171 !fcd->financial_info.bep);
173 gtk_toggle_button_set_active
174 (GTK_TOGGLE_BUTTON(fcd->discrete_compounding_radio),
175 fcd->financial_info.disc);
182 GtkToggleButton *toggle;
190 gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(fcd->amounts[PAYMENT_PERIODS]));
191 fcd->financial_info.npp = npp.num;
193 fcd->financial_info.ir =
194 gnc_amount_edit_get_damount(GNC_AMOUNT_EDIT(fcd->amounts[INTEREST_RATE]));
196 fcd->financial_info.pv =
197 gnc_amount_edit_get_damount(GNC_AMOUNT_EDIT(fcd->amounts[PRESENT_VALUE]));
199 fcd->financial_info.pmt =
200 gnc_amount_edit_get_damount(GNC_AMOUNT_EDIT(fcd->amounts[PERIODIC_PAYMENT]));
202 fcd->financial_info.fv =
203 gnc_amount_edit_get_damount(GNC_AMOUNT_EDIT(fcd->amounts[FUTURE_VALUE]));
204 fcd->financial_info.fv = -fcd->financial_info.fv;
206 i = gtk_combo_box_get_active(GTK_COMBO_BOX(fcd->compounding_combo));
207 fcd->financial_info.CF = periods[i];
209 i = gtk_combo_box_get_active(GTK_COMBO_BOX(fcd->payment_combo));
210 fcd->financial_info.PF = periods[i];
212 toggle = GTK_TOGGLE_BUTTON(fcd->end_of_period_radio);
213 fcd->financial_info.bep = !gtk_toggle_button_get_active(toggle);
215 toggle = GTK_TOGGLE_BUTTON(fcd->discrete_compounding_radio);
216 fcd->financial_info.disc = gtk_toggle_button_get_active(toggle);
218 fcd->financial_info.prec = gnc_locale_decimal_places ();
223 fincalc_update_calc_button_cb(GtkWidget *unused,
FinCalcDialog *fcd)
231 for (i = 0; i < NUM_FIN_CALC_VALUES; i++)
233 text = gtk_entry_get_text(GTK_ENTRY(fcd->amounts[i]));
234 if ((text == NULL) || (*text ==
'\0'))
236 gtk_widget_set_sensitive(GTK_WIDGET(fcd->calc_button), TRUE);
241 gtk_widget_set_sensitive(GTK_WIDGET(fcd->calc_button), FALSE);
246 fincalc_dialog_destroy(GtkObject *
object, gpointer data)
253 gnc_unregister_gui_component_by_data (DIALOG_FINCALC_CM_CLASS, fcd);
259 fincalc_compounding_radio_toggled(GtkToggleButton *togglebutton, gpointer data)
267 fincalc_update_calc_button_cb(GTK_WIDGET(togglebutton), fcd);
269 sensitive = gtk_toggle_button_get_active (togglebutton);
271 gtk_widget_set_sensitive (fcd->compounding_combo, sensitive);
275 fincalc_amount_clear_clicked_cb(GtkButton *button,
FinCalcDialog *fcd)
277 GtkEntry * edit = GTK_ENTRY(g_object_get_data(G_OBJECT(button),
"edit"));
279 if (edit && GTK_IS_ENTRY(edit))
280 gtk_entry_set_text(edit,
"");
291 lc = gnc_localeconv();
293 fcd->financial_info.npp = 12;
294 fcd->financial_info.ir = 8.5;
295 fcd->financial_info.pv = 15000.0;
296 fcd->financial_info.pmt = -400.0;
297 fcd->financial_info.CF = 12;
298 fcd->financial_info.PF = 12;
299 fcd->financial_info.bep = FALSE;
300 fcd->financial_info.disc = TRUE;
301 fcd->financial_info.prec = lc->frac_digits;
303 fi_calc_future_value(&fcd->financial_info);
310 can_calc_value(
FinCalcDialog *fcd, FinCalcValue value,
int *error_item)
312 const char *missing = _(
"This program can only calculate one value at a time. "
313 "You must enter values for all but one quantity.");
314 const char *bad_exp = _(
"GnuCash cannot determine the value in one of the fields. "
315 "You must enter a valid expression.");
324 for (i = 0; i < NUM_FIN_CALC_VALUES; i++)
327 string = gtk_entry_get_text(GTK_ENTRY(fcd->amounts[i]));
328 if ((
string == NULL) || (*
string ==
'\0'))
334 if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (fcd->amounts[i])))
344 case PAYMENT_PERIODS:
346 case PERIODIC_PAYMENT:
348 nvalue = gnc_amount_edit_get_amount
349 (GNC_AMOUNT_EDIT (fcd->amounts[INTEREST_RATE]));
352 *error_item = INTEREST_RATE;
353 return _(
"The interest rate cannot be zero.");
365 case PERIODIC_PAYMENT:
367 nvalue = gnc_amount_edit_get_amount
368 (GNC_AMOUNT_EDIT(fcd->amounts[PAYMENT_PERIODS]));
371 *error_item = PAYMENT_PERIODS;
372 return _(
"The number of payments cannot be zero.");
376 *error_item = PAYMENT_PERIODS;
377 return _(
"The number of payments cannot be negative.");
396 string = can_calc_value(fcd, value, &error_item);
401 gnc_error_dialog(fcd->dialog,
"%s",
string);
403 entry = fcd->amounts[0];
405 entry = fcd->amounts[error_item];
406 gtk_widget_grab_focus (entry);
414 case PAYMENT_PERIODS:
415 fi_calc_num_payments(&fcd->financial_info);
418 fi_calc_interest(&fcd->financial_info);
421 fi_calc_present_value(&fcd->financial_info);
423 case PERIODIC_PAYMENT:
424 fi_calc_payment(&fcd->financial_info);
427 fi_calc_future_value(&fcd->financial_info);
430 PERR(
"Unknown financial variable");
436 gtk_widget_set_sensitive(GTK_WIDGET(fcd->calc_button), FALSE);
440 fincalc_calc_clicked_cb(GtkButton *button,
FinCalcDialog *fcd)
445 for (i = 0; i < NUM_FIN_CALC_VALUES; i++)
447 text = gtk_entry_get_text(GTK_ENTRY(fcd->amounts[i]));
448 if ((text != NULL) && (*text !=
'\0'))
455 void fincalc_response_cb (GtkDialog *dialog,
461 case GTK_RESPONSE_OK:
465 case GTK_RESPONSE_CLOSE:
466 gnc_save_window_size(GNC_PREFS_GROUP, GTK_WINDOW(dialog));
474 gnc_close_gui_component_by_data (DIALOG_FINCALC_CM_CLASS, fcd);
479 close_handler (gpointer user_data)
483 gtk_widget_destroy (fcd->dialog);
487 show_handler (
const char *klass, gint component_id,
488 gpointer user_data, gpointer iter_data)
494 gtk_window_present (GTK_WINDOW(fcd->dialog));
519 print_info = gnc_integral_print_info ();
520 print_info.min_decimal_places = min_places;
521 print_info.max_decimal_places = max_places;
523 gnc_amount_edit_set_print_info (edit, print_info);
524 gnc_amount_edit_set_fraction (edit, fraction);
525 gnc_amount_edit_set_evaluate_on_enter (edit, TRUE);
526 gtk_entry_set_alignment (GTK_ENTRY(edit), 1.0);
543 print_info = gnc_commodity_print_info (commodity, FALSE);
545 gnc_amount_edit_set_print_info (edit, print_info);
546 gnc_amount_edit_set_fraction (edit, fraction);
547 gnc_amount_edit_set_evaluate_on_enter (edit, TRUE);
548 gtk_entry_set_alignment (GTK_ENTRY(edit), 1.0);
552 gnc_ui_fincalc_dialog_create(
void)
561 if (gnc_forall_gui_components (DIALOG_FINCALC_CM_CLASS,
568 builder = gtk_builder_new();
569 gnc_builder_add_from_file (builder,
"dialog-fincalc.glade",
"liststore1");
570 gnc_builder_add_from_file (builder,
"dialog-fincalc.glade",
"liststore2");
571 gnc_builder_add_from_file (builder,
"dialog-fincalc.glade",
"Financial Calculator Dialog");
573 fcd->dialog = GTK_WIDGET(gtk_builder_get_object (builder,
"Financial Calculator Dialog"));
575 gnc_register_gui_component (DIALOG_FINCALC_CM_CLASS,
576 NULL, close_handler, fcd);
578 g_signal_connect (G_OBJECT (fcd->dialog),
"destroy",
579 G_CALLBACK (fincalc_dialog_destroy), fcd);
582 hbox = GTK_WIDGET(gtk_builder_get_object (builder,
"payment_periods_hbox"));
583 edit = gnc_amount_edit_new();
584 fincalc_init_gae (GNC_AMOUNT_EDIT (edit), 0, 0, 1);
585 fcd->amounts[PAYMENT_PERIODS] = edit;
586 gtk_box_pack_end(GTK_BOX(hbox), edit, FALSE, FALSE, 0);
587 g_signal_connect (G_OBJECT(edit),
"changed",
588 G_CALLBACK (fincalc_update_calc_button_cb), fcd);
590 button = GTK_WIDGET(gtk_builder_get_object (builder,
"payment_periods_clear_button"));
591 g_object_set_data(G_OBJECT(button),
"edit", edit);
593 hbox = GTK_WIDGET(gtk_builder_get_object (builder,
"interest_rate_hbox"));
594 edit = gnc_amount_edit_new();
595 fincalc_init_gae (GNC_AMOUNT_EDIT (edit), 2, 5, 100000);
596 fcd->amounts[INTEREST_RATE] = edit;
597 gtk_box_pack_end(GTK_BOX(hbox), edit, FALSE, FALSE, 0);
598 g_signal_connect (G_OBJECT(edit),
"changed",
599 G_CALLBACK (fincalc_update_calc_button_cb), fcd);
601 button = GTK_WIDGET(gtk_builder_get_object (builder,
"interest_rate_clear_button"));
602 g_object_set_data(G_OBJECT(button),
"edit", edit);
604 hbox = GTK_WIDGET(gtk_builder_get_object (builder,
"present_value_hbox"));
605 edit = gnc_amount_edit_new();
606 fincalc_init_commodity_gae (GNC_AMOUNT_EDIT (edit));
607 fcd->amounts[PRESENT_VALUE] = edit;
608 gtk_box_pack_end(GTK_BOX(hbox), edit, FALSE, FALSE, 0);
609 g_signal_connect (G_OBJECT(edit),
"changed",
610 G_CALLBACK (fincalc_update_calc_button_cb), fcd);
612 button = GTK_WIDGET(gtk_builder_get_object (builder,
"present_value_clear_button"));
613 g_object_set_data(G_OBJECT(button),
"edit", edit);
615 hbox = GTK_WIDGET(gtk_builder_get_object (builder,
"periodic_payment_hbox"));
616 edit = gnc_amount_edit_new();
617 fincalc_init_commodity_gae (GNC_AMOUNT_EDIT (edit));
618 fcd->amounts[PERIODIC_PAYMENT] = edit;
619 gtk_box_pack_end(GTK_BOX(hbox), edit, FALSE, FALSE, 0);
620 g_signal_connect (G_OBJECT(edit),
"changed",
621 G_CALLBACK (fincalc_update_calc_button_cb), fcd);
623 button = GTK_WIDGET(gtk_builder_get_object (builder,
"periodic_payment_clear_button"));
624 g_object_set_data(G_OBJECT(button),
"edit", edit);
626 hbox = GTK_WIDGET(gtk_builder_get_object (builder,
"future_value_hbox"));
627 edit = gnc_amount_edit_new();
628 fincalc_init_commodity_gae (GNC_AMOUNT_EDIT (edit));
629 fcd->amounts[FUTURE_VALUE] = edit;
630 gtk_box_pack_end(GTK_BOX(hbox), edit, FALSE, FALSE, 0);
631 g_signal_connect (G_OBJECT(edit),
"changed",
632 G_CALLBACK (fincalc_update_calc_button_cb), fcd);
634 button = GTK_WIDGET(gtk_builder_get_object (builder,
"future_value_clear_button"));
635 g_object_set_data(G_OBJECT(button),
"edit", edit);
638 fcd->calc_button = GTK_WIDGET(gtk_builder_get_object (builder,
"calc_button"));
641 combo = GTK_WIDGET(gtk_builder_get_object (builder,
"compounding_combo"));
642 fcd->compounding_combo = combo;
643 g_signal_connect(fcd->compounding_combo,
"changed",
644 G_CALLBACK (fincalc_update_calc_button_cb), fcd);
646 combo = GTK_WIDGET(gtk_builder_get_object (builder,
"payment_combo"));
647 fcd->payment_combo = combo;
648 g_signal_connect(fcd->compounding_combo,
"changed",
649 G_CALLBACK (fincalc_update_calc_button_cb), fcd);
651 button = GTK_WIDGET(gtk_builder_get_object (builder,
"period_payment_radio"));
652 fcd->end_of_period_radio = button;
654 button = GTK_WIDGET(gtk_builder_get_object (builder,
"discrete_compounding_radio"));
655 fcd->discrete_compounding_radio = button;
657 fcd->payment_total_label = GTK_WIDGET(gtk_builder_get_object (builder,
"payment_total_label"));
659 button = GTK_WIDGET(gtk_builder_get_object (builder,
"schedule_button"));
660 gtk_widget_hide (button);
666 gtk_widget_grab_focus(fcd->amounts[PAYMENT_PERIODS]);
669 gtk_builder_connect_signals(builder, fcd);
670 g_object_unref(G_OBJECT(builder));
672 gnc_restore_window_size(GNC_PREFS_GROUP, GTK_WINDOW(fcd->dialog));
673 gtk_widget_show(fcd->dialog);
682 gnc_close_gui_component_by_data (DIALOG_FINCALC_CM_CLASS, fcd);
int gnc_commodity_get_fraction(const gnc_commodity *cm)
gnc_numeric double_to_gnc_numeric(double n, gint64 denom, gint how)
gboolean gnc_numeric_zero_p(gnc_numeric a)
#define PERR(format, args...)
gboolean gnc_numeric_negative_p(gnc_numeric a)
gnc_commodity * gnc_default_currency(void)
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
All type declarations for the whole Gnucash engine.
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Commodity handling public routines.
const gchar * QofLogModule