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" 41 #include "gnc-gui-query.h" 42 #include "gnc-locale-utils.h" 45 #define DIALOG_FINCALC_CM_CLASS "dialog-fincalc" 46 #define GNC_PREFS_GROUP "dialogs.fincalc" 64 GtkWidget *amounts[NUM_FIN_CALC_VALUES];
66 GtkWidget *calc_button;
68 GtkWidget *compounding_combo;
69 GtkWidget *payment_combo;
71 GtkWidget *end_of_period_radio;
73 GtkWidget *discrete_compounding_radio;
75 GtkWidget *payment_total_label;
80 static unsigned int periods[] =
96 __attribute__((unused))
static QofLogModule log_module = GNC_MOD_GUI;
100 void fincalc_update_calc_button_cb (GtkWidget *unused, FinCalcDialog *fcd);
101 void fincalc_calc_clicked_cb (GtkButton *button, FinCalcDialog *fcd);
102 void fincalc_compounding_radio_toggled (GtkToggleButton *togglebutton, gpointer user_data);
103 void fincalc_amount_clear_clicked_cb (GtkButton *button, FinCalcDialog *fcd);
104 void fincalc_precision_spin_value_changed_cb (GtkButton *button, FinCalcDialog *fcd);
105 void fincalc_response_cb (GtkDialog *dialog, gint response, FinCalcDialog *fcd);
112 normalize_period (
unsigned int *period)
116 g_return_val_if_fail (period, 0);
118 for (i = (
sizeof (periods) /
sizeof (
unsigned int)) - 1; i >= 0; i--)
119 if (*period >= periods[i])
121 *period = periods[i];
125 *period = periods[0];
132 fi_to_gui (FinCalcDialog *fcd)
135 static char string[64];
144 npp = gnc_numeric_create (fcd->financial_info.npp, 1);
146 gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(fcd->amounts[PAYMENT_PERIODS]),
148 gnc_amount_edit_set_damount (GNC_AMOUNT_EDIT(fcd->amounts[INTEREST_RATE]),
149 fcd->financial_info.ir);
150 gnc_amount_edit_set_damount (GNC_AMOUNT_EDIT(fcd->amounts[PRESENT_VALUE]),
151 fcd->financial_info.pv);
152 gnc_amount_edit_set_damount (GNC_AMOUNT_EDIT(fcd->amounts[PERIODIC_PAYMENT]),
153 fcd->financial_info.pmt);
154 gnc_amount_edit_set_damount (GNC_AMOUNT_EDIT(fcd->amounts[FUTURE_VALUE]),
155 -fcd->financial_info.fv);
159 precision = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(fcd->precision));
164 gtk_label_set_text (GTK_LABEL(fcd->payment_total_label),
string);
166 i = normalize_period (&fcd->financial_info.CF);
167 gtk_combo_box_set_active (GTK_COMBO_BOX(fcd->compounding_combo), i);
169 i = normalize_period (&fcd->financial_info.PF);
170 gtk_combo_box_set_active (GTK_COMBO_BOX(fcd->payment_combo), i);
172 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(fcd->end_of_period_radio),
173 !fcd->financial_info.bep);
175 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(fcd->discrete_compounding_radio),
176 fcd->financial_info.disc);
181 gui_to_fi (FinCalcDialog *fcd)
183 GtkToggleButton *toggle;
193 entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT(fcd->amounts[PAYMENT_PERIODS]));
194 text = gtk_entry_get_text (GTK_ENTRY(entry));
201 npp = gnc_numeric_zero ();
204 npp = gnc_numeric_zero ();
205 fcd->financial_info.npp = npp.num;
207 fcd->financial_info.ir =
208 gnc_amount_edit_get_damount (GNC_AMOUNT_EDIT(fcd->amounts[INTEREST_RATE]));
210 fcd->financial_info.pv =
211 gnc_amount_edit_get_damount (GNC_AMOUNT_EDIT(fcd->amounts[PRESENT_VALUE]));
213 fcd->financial_info.pmt =
214 gnc_amount_edit_get_damount (GNC_AMOUNT_EDIT(fcd->amounts[PERIODIC_PAYMENT]));
216 fcd->financial_info.fv =
217 gnc_amount_edit_get_damount (GNC_AMOUNT_EDIT(fcd->amounts[FUTURE_VALUE]));
218 fcd->financial_info.fv = -fcd->financial_info.fv;
220 i = gtk_combo_box_get_active (GTK_COMBO_BOX(fcd->compounding_combo));
221 fcd->financial_info.CF = periods[i];
223 i = gtk_combo_box_get_active (GTK_COMBO_BOX(fcd->payment_combo));
224 fcd->financial_info.PF = periods[i];
226 toggle = GTK_TOGGLE_BUTTON(fcd->end_of_period_radio);
227 fcd->financial_info.bep = !gtk_toggle_button_get_active (toggle);
229 toggle = GTK_TOGGLE_BUTTON(fcd->discrete_compounding_radio);
230 fcd->financial_info.disc = gtk_toggle_button_get_active (toggle);
232 fcd->financial_info.prec = gnc_locale_decimal_places ();
237 fincalc_update_calc_button_cb (GtkWidget *unused, FinCalcDialog *fcd)
245 for (i = 0; i < NUM_FIN_CALC_VALUES; i++)
247 GtkWidget *entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT(fcd->amounts[i]));
248 text = gtk_entry_get_text (GTK_ENTRY(entry));
249 if ((text == NULL) || (*text ==
'\0'))
251 gtk_widget_set_sensitive (GTK_WIDGET(fcd->calc_button), TRUE);
256 gtk_widget_set_sensitive (GTK_WIDGET(fcd->calc_button), FALSE);
261 fincalc_dialog_destroy (GObject *
object, gpointer user_data)
263 FinCalcDialog *fcd = user_data;
268 gnc_unregister_gui_component_by_data (DIALOG_FINCALC_CM_CLASS, fcd);
274 fincalc_compounding_radio_toggled (GtkToggleButton *togglebutton, gpointer user_data)
276 FinCalcDialog *fcd = user_data;
282 fincalc_update_calc_button_cb (GTK_WIDGET(togglebutton), fcd);
284 sensitive = gtk_toggle_button_get_active (togglebutton);
286 gtk_widget_set_sensitive (fcd->compounding_combo, sensitive);
290 fincalc_amount_clear_clicked_cb (GtkButton *button, FinCalcDialog *fcd)
292 GNCAmountEdit * edit = GNC_AMOUNT_EDIT(g_object_get_data (G_OBJECT(button),
"edit"));
293 GtkWidget * entry = gnc_amount_edit_gtk_entry (edit);
296 if (entry && GTK_IS_ENTRY(entry))
297 gtk_entry_set_text (GTK_ENTRY(entry),
"");
299 gnc_amount_edit_expr_is_valid (edit, &value, TRUE, NULL);
303 fincalc_precision_spin_value_changed_cb (GtkButton *button, FinCalcDialog *fcd)
305 gtk_widget_set_sensitive (GTK_WIDGET(fcd->calc_button), TRUE);
309 init_fi (FinCalcDialog *fcd)
316 lc = gnc_localeconv ();
318 fcd->financial_info.npp = 12;
319 fcd->financial_info.ir = 8.5;
320 fcd->financial_info.pv = 15000.0;
321 fcd->financial_info.pmt = -400.0;
322 fcd->financial_info.CF = 12;
323 fcd->financial_info.PF = 12;
324 fcd->financial_info.bep = FALSE;
325 fcd->financial_info.disc = TRUE;
326 fcd->financial_info.prec = lc->frac_digits;
328 fi_calc_future_value (&fcd->financial_info);
335 can_calc_value (FinCalcDialog *fcd, FinCalcValue value,
int *error_item)
337 const char *missing = _(
"This program can only calculate one value at a time. " 338 "You must enter values for all but one quantity.");
339 const char *bad_exp = _(
"GnuCash cannot determine the value in one of the fields. " 340 "You must enter a valid expression.");
349 for (i = 0; i < NUM_FIN_CALC_VALUES; i++)
352 GtkWidget *entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT(fcd->amounts[i]));
353 string = gtk_entry_get_text (GTK_ENTRY(entry));
354 if ((
string == NULL) || (*
string ==
'\0'))
361 if (i != PAYMENT_PERIODS)
363 if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT(fcd->amounts[i]), NULL))
374 case PAYMENT_PERIODS:
376 case PERIODIC_PAYMENT:
378 nvalue = gnc_amount_edit_get_amount
379 (GNC_AMOUNT_EDIT(fcd->amounts[INTEREST_RATE]));
382 *error_item = INTEREST_RATE;
383 return _(
"The interest rate cannot be zero.");
395 case PERIODIC_PAYMENT:
399 GNCAmountEdit *edit = GNC_AMOUNT_EDIT(fcd->amounts[PAYMENT_PERIODS]);
400 gint result = gnc_amount_edit_expr_is_valid (edit, &nvalue, TRUE, NULL);
404 *error_item = PAYMENT_PERIODS;
409 *error_item = PAYMENT_PERIODS;
410 return _(
"The number of payments cannot be zero.");
414 *error_item = PAYMENT_PERIODS;
415 return _(
"The number of payments cannot be negative.");
427 calc_value (FinCalcDialog *fcd, FinCalcValue value)
435 string = can_calc_value (fcd, value, &error_item);
440 gnc_error_dialog (GTK_WINDOW (fcd->dialog),
"%s",
string);
442 entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT(fcd->amounts[0]));
444 entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT(fcd->amounts[error_item]));
445 gtk_widget_grab_focus (entry);
453 case PAYMENT_PERIODS:
454 fi_calc_num_payments (&fcd->financial_info);
457 fi_calc_interest (&fcd->financial_info);
460 fi_calc_present_value (&fcd->financial_info);
462 case PERIODIC_PAYMENT:
463 fi_calc_payment (&fcd->financial_info);
466 fi_calc_future_value (&fcd->financial_info);
474 gtk_widget_set_sensitive (GTK_WIDGET(fcd->calc_button), FALSE);
478 fincalc_calc_clicked_cb (GtkButton *button, FinCalcDialog *fcd)
483 for (i = 0; i < NUM_FIN_CALC_VALUES; i++)
485 GtkWidget *entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT(fcd->amounts[i]));
486 text = gtk_entry_get_text (GTK_ENTRY(entry));
487 if ((text != NULL) && (*text !=
'\0'))
492 calc_value (fcd, NUM_FIN_CALC_VALUES);
495 void fincalc_response_cb (GtkDialog *dialog,
501 case GTK_RESPONSE_HELP:
505 case GTK_RESPONSE_OK:
509 case GTK_RESPONSE_CLOSE:
510 gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(dialog));
518 gnc_close_gui_component_by_data (DIALOG_FINCALC_CM_CLASS, fcd);
523 close_handler (gpointer user_data)
525 FinCalcDialog *fcd = user_data;
527 gtk_widget_destroy (fcd->dialog);
531 show_handler (
const char *klass, gint component_id,
532 gpointer user_data, gpointer iter_data)
534 FinCalcDialog *fcd = user_data;
538 gtk_window_present (GTK_WINDOW(fcd->dialog));
556 fincalc_init_gae (GNCAmountEdit *edit,
564 print_info = gnc_integral_print_info ();
565 print_info.min_decimal_places = min_places;
566 print_info.max_decimal_places = max_places;
568 gnc_amount_edit_set_print_info (edit, print_info);
569 gnc_amount_edit_set_fraction (edit, fraction);
570 gnc_amount_edit_set_evaluate_on_enter (edit, TRUE);
571 entry = gnc_amount_edit_gtk_entry (edit);
572 gtk_entry_set_alignment (GTK_ENTRY(entry), 1.0);
581 fincalc_init_commodity_gae (GNCAmountEdit *edit)
584 gnc_commodity *commodity;
590 print_info = gnc_commodity_print_info (commodity, FALSE);
592 gnc_amount_edit_set_print_info (edit, print_info);
593 gnc_amount_edit_set_fraction (edit, fraction);
594 gnc_amount_edit_set_evaluate_on_enter (edit, TRUE);
595 entry = gnc_amount_edit_gtk_entry (edit);
596 gtk_entry_set_alignment (GTK_ENTRY(entry), 1.0);
600 gnc_ui_fincalc_dialog_create (GtkWindow *parent)
609 GtkAdjustment *adjustment;
611 if (gnc_forall_gui_components (DIALOG_FINCALC_CM_CLASS,
616 fcd = g_new0 (FinCalcDialog, 1);
618 builder = gtk_builder_new ();
619 gnc_builder_add_from_file (builder,
"dialog-fincalc.glade",
"liststore1");
620 gnc_builder_add_from_file (builder,
"dialog-fincalc.glade",
"liststore2");
621 gnc_builder_add_from_file (builder,
"dialog-fincalc.glade",
"financial_calculator_dialog");
623 fcd->dialog = GTK_WIDGET(gtk_builder_get_object (builder,
"financial_calculator_dialog"));
626 gtk_widget_set_name (GTK_WIDGET(fcd->dialog),
"gnc-id-financial-calc");
630 gtk_window_set_transient_for (GTK_WINDOW(fcd->dialog), GTK_WINDOW(parent));
632 gnc_register_gui_component (DIALOG_FINCALC_CM_CLASS,
633 NULL, close_handler, fcd);
635 g_signal_connect (G_OBJECT(fcd->dialog),
"destroy",
636 G_CALLBACK(fincalc_dialog_destroy), fcd);
638 hbox = GTK_WIDGET(gtk_builder_get_object (builder,
"payment_periods_hbox"));
639 edit = gnc_amount_edit_new ();
640 fincalc_init_gae (GNC_AMOUNT_EDIT(edit), 0, 0, 1);
641 fcd->amounts[PAYMENT_PERIODS] = edit;
642 gtk_box_pack_end (GTK_BOX(hbox), edit, TRUE, TRUE, 0);
643 g_signal_connect (G_OBJECT(edit),
"changed",
644 G_CALLBACK(fincalc_update_calc_button_cb), fcd);
646 button = GTK_WIDGET(gtk_builder_get_object (builder,
"payment_periods_clear_button"));
647 g_object_set_data (G_OBJECT(button),
"edit", edit);
649 hbox = GTK_WIDGET(gtk_builder_get_object (builder,
"interest_rate_hbox"));
650 edit = gnc_amount_edit_new ();
651 fincalc_init_gae (GNC_AMOUNT_EDIT(edit), 2, 5, 100000);
652 fcd->amounts[INTEREST_RATE] = edit;
653 gtk_box_pack_end (GTK_BOX(hbox), edit, TRUE, TRUE, 0);
654 g_signal_connect (G_OBJECT(edit),
"changed",
655 G_CALLBACK(fincalc_update_calc_button_cb), fcd);
657 button = GTK_WIDGET(gtk_builder_get_object (builder,
"interest_rate_clear_button"));
658 g_object_set_data (G_OBJECT(button),
"edit", edit);
660 hbox = GTK_WIDGET(gtk_builder_get_object (builder,
"present_value_hbox"));
661 edit = gnc_amount_edit_new ();
662 fincalc_init_commodity_gae (GNC_AMOUNT_EDIT(edit));
663 fcd->amounts[PRESENT_VALUE] = edit;
664 gtk_box_pack_end (GTK_BOX(hbox), edit, TRUE, TRUE, 0);
665 g_signal_connect (G_OBJECT(edit),
"changed",
666 G_CALLBACK(fincalc_update_calc_button_cb), fcd);
668 button = GTK_WIDGET(gtk_builder_get_object (builder,
"present_value_clear_button"));
669 g_object_set_data (G_OBJECT(button),
"edit", edit);
671 hbox = GTK_WIDGET(gtk_builder_get_object (builder,
"periodic_payment_hbox"));
672 edit = gnc_amount_edit_new ();
673 fincalc_init_commodity_gae (GNC_AMOUNT_EDIT(edit));
674 fcd->amounts[PERIODIC_PAYMENT] = edit;
675 gtk_box_pack_end (GTK_BOX(hbox), edit, TRUE, TRUE, 0);
676 g_signal_connect (G_OBJECT(edit),
"changed",
677 G_CALLBACK(fincalc_update_calc_button_cb), fcd);
679 button = GTK_WIDGET(gtk_builder_get_object (builder,
"periodic_payment_clear_button"));
680 g_object_set_data (G_OBJECT(button),
"edit", edit);
682 hbox = GTK_WIDGET(gtk_builder_get_object (builder,
"future_value_hbox"));
683 edit = gnc_amount_edit_new ();
684 fincalc_init_commodity_gae (GNC_AMOUNT_EDIT(edit));
685 fcd->amounts[FUTURE_VALUE] = edit;
686 gtk_box_pack_end (GTK_BOX(hbox), edit, TRUE, TRUE, 0);
687 g_signal_connect (G_OBJECT(edit),
"changed",
688 G_CALLBACK(fincalc_update_calc_button_cb), fcd);
690 button = GTK_WIDGET(gtk_builder_get_object (builder,
"future_value_clear_button"));
691 g_object_set_data (G_OBJECT(button),
"edit", edit);
693 fcd->calc_button = GTK_WIDGET(gtk_builder_get_object (builder,
"calc_button"));
695 combo = GTK_WIDGET(gtk_builder_get_object (builder,
"compounding_combo"));
696 fcd->compounding_combo = combo;
697 g_signal_connect(fcd->compounding_combo,
"changed",
698 G_CALLBACK (fincalc_update_calc_button_cb), fcd);
700 combo = GTK_WIDGET(gtk_builder_get_object (builder,
"payment_combo"));
701 fcd->payment_combo = combo;
702 g_signal_connect (fcd->compounding_combo,
"changed",
703 G_CALLBACK(fincalc_update_calc_button_cb), fcd);
705 spin = GTK_WIDGET(gtk_builder_get_object (builder,
"precision_spin"));
706 adjustment = gtk_adjustment_new (2, 0, 10, 1, 1, 1);
707 gtk_spin_button_set_adjustment (GTK_SPIN_BUTTON(spin), adjustment);
708 fcd->precision = spin;
710 button = GTK_WIDGET(gtk_builder_get_object (builder,
"period_payment_radio"));
711 fcd->end_of_period_radio = button;
713 button = GTK_WIDGET(gtk_builder_get_object (builder,
"discrete_compounding_radio"));
714 fcd->discrete_compounding_radio = button;
716 fcd->payment_total_label = GTK_WIDGET(gtk_builder_get_object (builder,
"payment_total_label"));
718 button = GTK_WIDGET(gtk_builder_get_object (builder,
"schedule_button"));
719 gtk_widget_hide (button);
725 gtk_widget_grab_focus (fcd->amounts[PAYMENT_PERIODS]);
728 gtk_builder_connect_signals (builder, fcd);
729 g_object_unref (G_OBJECT(builder));
731 gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(fcd->dialog), parent);
732 gtk_widget_show (fcd->dialog);
736 gnc_ui_fincalc_dialog_destroy (FinCalcDialog *fcd)
741 gnc_close_gui_component_by_data (DIALOG_FINCALC_CM_CLASS, fcd);
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
gnc_numeric double_to_gnc_numeric(double n, gint64 denom, gint how)
Convert a floating-point number to a gnc_numeric.
gboolean gnc_numeric_zero_p(gnc_numeric a)
Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
gboolean gnc_numeric_negative_p(gnc_numeric a)
Returns 1 if a < 0, otherwise returns 0.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
gnc_numeric gnc_numeric_convert(gnc_numeric n, gint64 denom, gint how)
Change the denominator of a gnc_numeric value to the specified denominator under standard arguments '...
void gnc_gnome_help(GtkWindow *parent, const char *file_name, const char *anchor)
Launch the systems default help browser, gnome's yelp for linux, and open to a given link within a gi...
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Multiply a times b, returning the product.
All type declarations for the whole Gnucash engine.
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
Truncate fractions (round toward zero)
gnc_numeric gnc_numeric_from_string(const gchar *str)
Read a gnc_numeric from str, skipping any leading whitespace.
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
Check for error signal in value.
Use unbiased ("banker's") rounding.
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.
Commodity handling public routines.