GnuCash  5.6-150-g038405b370+
dialog-fincalc.c
1 /********************************************************************\
2  * dialog-fincalc.c : dialog for a financial calculator *
3  * Copyright (C) 2000 Dave Peticolas <dave@krondo.com> *
4  * Copyright (c) 2006 David Hampton <hampton@employees.org> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
11  * This program 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. *
15  * *
16  * You should have received a copy of the GNU General Public License*
17  * along with this program; if not, contact: *
18  * *
19  * Free Software Foundation Voice: +1-617-542-5942 *
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21  * Boston, MA 02110-1301, USA gnu@gnu.org *
22 \********************************************************************/
23 
24 #include <config.h>
25 
26 #include <gtk/gtk.h>
27 #include <glib/gi18n.h>
28 #include <locale.h>
29 #include <time.h>
30 
31 #include "dialog-fincalc.h"
32 #include "dialog-utils.h"
33 #include "finproto.h"
34 #include "finvar.h"
35 #include "gnc-amount-edit.h"
36 #include "gnc-commodity.h"
37 #include "gnc-component-manager.h"
38 #include "gnc-date-edit.h"
39 #include "gnc-engine.h"
40 #include "gnc-ui.h"
41 #include "gnc-gui-query.h"
42 #include "gnc-locale-utils.h"
43 
44 
45 #define DIALOG_FINCALC_CM_CLASS "dialog-fincalc"
46 #define GNC_PREFS_GROUP "dialogs.fincalc"
47 
48 typedef enum
49 {
50  PAYMENT_PERIODS = 0,
51  INTEREST_RATE,
52  PRESENT_VALUE,
53  PERIODIC_PAYMENT,
54  FUTURE_VALUE,
55  NUM_FIN_CALC_VALUES
56 } FinCalcValue;
57 
58 
61 {
62  GtkWidget *dialog;
63 
64  GtkWidget *amounts[NUM_FIN_CALC_VALUES];
65 
66  GtkWidget *calc_button;
67 
68  GtkWidget *compounding_combo;
69  GtkWidget *payment_combo;
70 
71  GtkWidget *end_of_period_radio;
72  GtkWidget *precision;
73  GtkWidget *discrete_compounding_radio;
74 
75  GtkWidget *payment_total_label;
76 
78 };
79 
80 static unsigned int periods[] =
81 {
82  1, /* annual */
83  2, /* semi-annual */
84  3, /* tri-annual */
85  4, /* quarterly */
86  6, /* bi-monthly */
87  12, /* monthly */
88  24, /* semi-monthly */
89  26, /* bi-weekly */
90  52, /* weekly */
91  360, /* daily (360) */
92  365, /* daily (365) */
93 };
94 
95 /* This static indicates the debugging module that this .o belongs to. */
96 __attribute__((unused)) static QofLogModule log_module = GNC_MOD_GUI;
97 
98 
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);
106 
109 /* Ensure the given argument is one of the values in the periods array
110  * above and return the index of the value. */
111 static int
112 normalize_period (unsigned int *period)
113 {
114  int i;
115 
116  g_return_val_if_fail (period, 0);
117 
118  for (i = (sizeof (periods) / sizeof (unsigned int)) - 1; i >= 0; i--)
119  if (*period >= periods[i])
120  {
121  *period = periods[i];
122  return i;
123  }
124 
125  *period = periods[0];
126 
127  return 0;
128 }
129 
130 /* Copy the values in the financial_info structure to the GUI */
131 static void
132 fi_to_gui (FinCalcDialog *fcd)
133 {
134  int precision;
135  static char string[64];
136  gnc_numeric total;
137  gnc_numeric npp;
138  gnc_numeric pmt;
139  int i;
140 
141  if (fcd == NULL)
142  return;
143 
144  npp = gnc_numeric_create (fcd->financial_info.npp, 1);
145 
146  gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT(fcd->amounts[PAYMENT_PERIODS]),
147  npp);
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);
156 
157  pmt = double_to_gnc_numeric (fcd->financial_info.pmt, 100000, GNC_HOW_RND_ROUND_HALF_UP);
158 
159  precision = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(fcd->precision));
160 
161  total = gnc_numeric_mul (npp, pmt, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND);
162 
163  xaccSPrintAmount (string, total, gnc_share_print_info_places (precision));
164  gtk_label_set_text (GTK_LABEL(fcd->payment_total_label), string);
165 
166  i = normalize_period (&fcd->financial_info.CF);
167  gtk_combo_box_set_active (GTK_COMBO_BOX(fcd->compounding_combo), i);
168 
169  i = normalize_period (&fcd->financial_info.PF);
170  gtk_combo_box_set_active (GTK_COMBO_BOX(fcd->payment_combo), i);
171 
172  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(fcd->end_of_period_radio),
173  !fcd->financial_info.bep);
174 
175  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(fcd->discrete_compounding_radio),
176  fcd->financial_info.disc);
177 }
178 
179 /* Copy the values in the GUI to the financial_info structure */
180 static void
181 gui_to_fi (FinCalcDialog *fcd)
182 {
183  GtkToggleButton *toggle;
184  GtkWidget *entry;
185  gnc_numeric npp;
186  int i;
187  const gchar *text;
188 
189  if (fcd == NULL)
190  return;
191 
192  /* treat PAYMENT_PERIODS as a plain GtkEntry */
193  entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT(fcd->amounts[PAYMENT_PERIODS]));
194  text = gtk_entry_get_text (GTK_ENTRY(entry));
195  if (text && *text)
196  {
197  gnc_numeric out = gnc_numeric_from_string (text);
198  if (!gnc_numeric_check (out))
199  npp = gnc_numeric_convert (out, 1, GNC_HOW_RND_TRUNC);
200  else
201  npp = gnc_numeric_zero ();
202  }
203  else
204  npp = gnc_numeric_zero ();
205  fcd->financial_info.npp = npp.num;
206 
207  fcd->financial_info.ir =
208  gnc_amount_edit_get_damount (GNC_AMOUNT_EDIT(fcd->amounts[INTEREST_RATE]));
209 
210  fcd->financial_info.pv =
211  gnc_amount_edit_get_damount (GNC_AMOUNT_EDIT(fcd->amounts[PRESENT_VALUE]));
212 
213  fcd->financial_info.pmt =
214  gnc_amount_edit_get_damount (GNC_AMOUNT_EDIT(fcd->amounts[PERIODIC_PAYMENT]));
215 
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;
219 
220  i = gtk_combo_box_get_active (GTK_COMBO_BOX(fcd->compounding_combo));
221  fcd->financial_info.CF = periods[i];
222 
223  i = gtk_combo_box_get_active (GTK_COMBO_BOX(fcd->payment_combo));
224  fcd->financial_info.PF = periods[i];
225 
226  toggle = GTK_TOGGLE_BUTTON(fcd->end_of_period_radio);
227  fcd->financial_info.bep = !gtk_toggle_button_get_active (toggle);
228 
229  toggle = GTK_TOGGLE_BUTTON(fcd->discrete_compounding_radio);
230  fcd->financial_info.disc = gtk_toggle_button_get_active (toggle);
231 
232  fcd->financial_info.prec = gnc_locale_decimal_places ();
233 }
234 
235 /* Set the sensitivity of the calculation buttons based on the argument. */
236 void
237 fincalc_update_calc_button_cb (GtkWidget *unused, FinCalcDialog *fcd)
238 {
239  const gchar *text;
240  gint i;
241 
242  if (fcd == NULL)
243  return;
244 
245  for (i = 0; i < NUM_FIN_CALC_VALUES; i++)
246  {
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'))
250  {
251  gtk_widget_set_sensitive (GTK_WIDGET(fcd->calc_button), TRUE);
252  return;
253  }
254  }
255 
256  gtk_widget_set_sensitive (GTK_WIDGET(fcd->calc_button), FALSE);
257 }
258 
259 /* Free the calc button list and free the FinCalcDialog structure. */
260 static void
261 fincalc_dialog_destroy (GObject *object, gpointer user_data)
262 {
263  FinCalcDialog *fcd = user_data;
264 
265  if (fcd == NULL)
266  return;
267 
268  gnc_unregister_gui_component_by_data (DIALOG_FINCALC_CM_CLASS, fcd);
269 
270  g_free (fcd);
271 }
272 
273 void
274 fincalc_compounding_radio_toggled (GtkToggleButton *togglebutton, gpointer user_data)
275 {
276  FinCalcDialog *fcd = user_data;
277  gboolean sensitive;
278 
279  if (fcd == NULL)
280  return;
281 
282  fincalc_update_calc_button_cb (GTK_WIDGET(togglebutton), fcd);
283 
284  sensitive = gtk_toggle_button_get_active (togglebutton);
285 
286  gtk_widget_set_sensitive (fcd->compounding_combo, sensitive);
287 }
288 
289 void
290 fincalc_amount_clear_clicked_cb (GtkButton *button, FinCalcDialog *fcd)
291 {
292  GNCAmountEdit * edit = GNC_AMOUNT_EDIT(g_object_get_data (G_OBJECT(button), "edit"));
293  GtkWidget * entry = gnc_amount_edit_gtk_entry (edit);
294  gnc_numeric value;
295 
296  if (entry && GTK_IS_ENTRY(entry))
297  gtk_entry_set_text (GTK_ENTRY(entry), "");
298 
299  gnc_amount_edit_expr_is_valid (edit, &value, TRUE, NULL);
300 }
301 
302 void
303 fincalc_precision_spin_value_changed_cb (GtkButton *button, FinCalcDialog *fcd)
304 {
305  gtk_widget_set_sensitive (GTK_WIDGET(fcd->calc_button), TRUE);
306 }
307 
308 static void
309 init_fi (FinCalcDialog *fcd)
310 {
311  struct lconv *lc;
312 
313  if (fcd == NULL)
314  return;
315 
316  lc = gnc_localeconv ();
317 
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;
327 
328  fi_calc_future_value (&fcd->financial_info);
329 }
330 
331 /* Determine whether the value can be calculated. If it can, return
332  * NULL. Otherwise, return a string describing the reason and the offending
333  * entry in error_item. */
334 static const char *
335 can_calc_value (FinCalcDialog *fcd, FinCalcValue value, int *error_item)
336 {
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.");
341  const char *string;
342  gnc_numeric nvalue;
343  unsigned int i;
344 
345  if (fcd == NULL)
346  return NULL;
347 
348  /* Check for missing values */
349  for (i = 0; i < NUM_FIN_CALC_VALUES; i++)
350  if (i != value)
351  {
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'))
355  {
356  *error_item = i;
357  return missing;
358  }
359 
360  /* treat PAYMENT_PERIODS as a plain GtkEntry */
361  if (i != PAYMENT_PERIODS)
362  {
363  if (!gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT(fcd->amounts[i]), NULL))
364  {
365  *error_item = i;
366  return bad_exp;
367  }
368  }
369  }
370 
371  /* Check for zero interest */
372  switch (value)
373  {
374  case PAYMENT_PERIODS:
375  case PRESENT_VALUE:
376  case PERIODIC_PAYMENT:
377  case FUTURE_VALUE:
378  nvalue = gnc_amount_edit_get_amount
379  (GNC_AMOUNT_EDIT(fcd->amounts[INTEREST_RATE]));
380  if (gnc_numeric_zero_p (nvalue))
381  {
382  *error_item = INTEREST_RATE;
383  return _("The interest rate cannot be zero.");
384  }
385  break;
386  default:
387  break;
388  }
389 
390  /* Check for zero payment periods */
391  switch (value)
392  {
393  case INTEREST_RATE:
394  case PRESENT_VALUE:
395  case PERIODIC_PAYMENT:
396  case FUTURE_VALUE:
397  {
398  /* treat PAYMENT_PERIODS as a plain GtkEntry */
399  GNCAmountEdit *edit = GNC_AMOUNT_EDIT(fcd->amounts[PAYMENT_PERIODS]);
400  gint result = gnc_amount_edit_expr_is_valid (edit, &nvalue, TRUE, NULL);
401 
402  if (result == 1)
403  {
404  *error_item = PAYMENT_PERIODS;
405  return bad_exp;
406  }
407  if (gnc_numeric_zero_p (nvalue))
408  {
409  *error_item = PAYMENT_PERIODS;
410  return _("The number of payments cannot be zero.");
411  }
412  if (gnc_numeric_negative_p (nvalue))
413  {
414  *error_item = PAYMENT_PERIODS;
415  return _("The number of payments cannot be negative.");
416  }
417  }
418  break;
419  default:
420  break;
421  }
422 
423  return NULL;
424 }
425 
426 static void
427 calc_value (FinCalcDialog *fcd, FinCalcValue value)
428 {
429  const char *string;
430  int error_item = 0;
431 
432  if (fcd == NULL)
433  return;
434 
435  string = can_calc_value (fcd, value, &error_item);
436  if (string != NULL)
437  {
438  GtkWidget *entry;
439 
440  gnc_error_dialog (GTK_WINDOW (fcd->dialog), "%s", string);
441  if (error_item == 0)
442  entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT(fcd->amounts[0]));
443  else
444  entry = gnc_amount_edit_gtk_entry (GNC_AMOUNT_EDIT(fcd->amounts[error_item]));
445  gtk_widget_grab_focus (entry);
446  return;
447  }
448 
449  gui_to_fi (fcd);
450 
451  switch (value)
452  {
453  case PAYMENT_PERIODS:
454  fi_calc_num_payments (&fcd->financial_info);
455  break;
456  case INTEREST_RATE:
457  fi_calc_interest (&fcd->financial_info);
458  break;
459  case PRESENT_VALUE:
460  fi_calc_present_value (&fcd->financial_info);
461  break;
462  case PERIODIC_PAYMENT:
463  fi_calc_payment (&fcd->financial_info);
464  break;
465  case FUTURE_VALUE:
466  fi_calc_future_value (&fcd->financial_info);
467  break;
468  default:
469  break;
470  }
471 
472  fi_to_gui (fcd);
473 
474  gtk_widget_set_sensitive (GTK_WIDGET(fcd->calc_button), FALSE);
475 }
476 
477 void
478 fincalc_calc_clicked_cb (GtkButton *button, FinCalcDialog *fcd)
479 {
480  const gchar *text;
481  gint i;
482 
483  for (i = 0; i < NUM_FIN_CALC_VALUES; i++)
484  {
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'))
488  continue;
489  calc_value (fcd, i);
490  return;
491  }
492  calc_value (fcd, NUM_FIN_CALC_VALUES);
493 }
494 
495 void fincalc_response_cb (GtkDialog *dialog,
496  gint response,
497  FinCalcDialog *fcd)
498 {
499  switch (response)
500  {
501  case GTK_RESPONSE_HELP:
502  gnc_gnome_help (GTK_WINDOW(dialog), DF_MANUAL, DL_FIN_CALC);
503  return;
504 
505  case GTK_RESPONSE_OK:
506  /* Do something here whenever the hidden schedule button is clicked. */
507  /* Fall through */
508 
509  case GTK_RESPONSE_CLOSE:
510  gnc_save_window_size (GNC_PREFS_GROUP, GTK_WINDOW(dialog));
511  break;
512 
513  default:
514  /* Cancel, destroy, etc. Do nothing. */
515  break;
516  }
517 
518  gnc_close_gui_component_by_data (DIALOG_FINCALC_CM_CLASS, fcd);
519 }
520 
521 
522 static void
523 close_handler (gpointer user_data)
524 {
525  FinCalcDialog *fcd = user_data;
526 
527  gtk_widget_destroy (fcd->dialog);
528 }
529 
530 static gboolean
531 show_handler (const char *klass, gint component_id,
532  gpointer user_data, gpointer iter_data)
533 {
534  FinCalcDialog *fcd = user_data;
535 
536  if (!fcd)
537  return FALSE;
538  gtk_window_present (GTK_WINDOW(fcd->dialog));
539  return TRUE;
540 }
541 
542 
555 static void
556 fincalc_init_gae (GNCAmountEdit *edit,
557  gint min_places,
558  gint max_places,
559  gint fraction)
560 {
561  GNCPrintAmountInfo print_info;
562  GtkWidget *entry;
563 
564  print_info = gnc_integral_print_info ();
565  print_info.min_decimal_places = min_places;
566  print_info.max_decimal_places = max_places;
567 
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);
573 }
574 
580 static void
581 fincalc_init_commodity_gae (GNCAmountEdit *edit)
582 {
583  GNCPrintAmountInfo print_info;
584  gnc_commodity *commodity;
585  gint fraction;
586  GtkWidget *entry;
587 
588  commodity = gnc_default_currency ();
589  fraction = gnc_commodity_get_fraction (commodity);
590  print_info = gnc_commodity_print_info (commodity, FALSE);
591 
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);
597 }
598 
599 void
600 gnc_ui_fincalc_dialog_create (GtkWindow *parent)
601 {
602  FinCalcDialog *fcd;
603  GtkWidget *button;
604  GtkWidget *combo;
605  GtkWidget *edit;
606  GtkWidget *spin;
607  GtkWidget *hbox;
608  GtkBuilder *builder;
609  GtkAdjustment *adjustment;
610 
611  if (gnc_forall_gui_components (DIALOG_FINCALC_CM_CLASS,
612  show_handler, NULL))
613  return;
614 
615 
616  fcd = g_new0 (FinCalcDialog, 1);
617 
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");
622 
623  fcd->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "financial_calculator_dialog"));
624 
625  // Set the name for this dialog so it can be easily manipulated with css
626  gtk_widget_set_name (GTK_WIDGET(fcd->dialog), "gnc-id-financial-calc");
627 
628  /* parent */
629  if (parent != NULL)
630  gtk_window_set_transient_for (GTK_WINDOW(fcd->dialog), GTK_WINDOW(parent));
631 
632  gnc_register_gui_component (DIALOG_FINCALC_CM_CLASS,
633  NULL, close_handler, fcd);
634 
635  g_signal_connect (G_OBJECT(fcd->dialog), "destroy",
636  G_CALLBACK(fincalc_dialog_destroy), fcd);
637 
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);
645 
646  button = GTK_WIDGET(gtk_builder_get_object (builder, "payment_periods_clear_button"));
647  g_object_set_data (G_OBJECT(button), "edit", edit);
648 
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);
656 
657  button = GTK_WIDGET(gtk_builder_get_object (builder, "interest_rate_clear_button"));
658  g_object_set_data (G_OBJECT(button), "edit", edit);
659 
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);
667 
668  button = GTK_WIDGET(gtk_builder_get_object (builder, "present_value_clear_button"));
669  g_object_set_data (G_OBJECT(button), "edit", edit);
670 
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);
678 
679  button = GTK_WIDGET(gtk_builder_get_object (builder, "periodic_payment_clear_button"));
680  g_object_set_data (G_OBJECT(button), "edit", edit);
681 
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);
689 
690  button = GTK_WIDGET(gtk_builder_get_object (builder, "future_value_clear_button"));
691  g_object_set_data (G_OBJECT(button), "edit", edit);
692 
693  fcd->calc_button = GTK_WIDGET(gtk_builder_get_object (builder, "calc_button"));
694 
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);
699 
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);
704 
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;
709 
710  button = GTK_WIDGET(gtk_builder_get_object (builder, "period_payment_radio"));
711  fcd->end_of_period_radio = button;
712 
713  button = GTK_WIDGET(gtk_builder_get_object (builder, "discrete_compounding_radio"));
714  fcd->discrete_compounding_radio = button;
715 
716  fcd->payment_total_label = GTK_WIDGET(gtk_builder_get_object (builder, "payment_total_label"));
717 
718  button = GTK_WIDGET(gtk_builder_get_object (builder, "schedule_button"));
719  gtk_widget_hide (button);
720 
721  init_fi (fcd);
722 
723  fi_to_gui (fcd);
724 
725  gtk_widget_grab_focus (fcd->amounts[PAYMENT_PERIODS]);
726 
727  /* Connect all signals specified in glade. */
728  gtk_builder_connect_signals (builder, fcd);
729  g_object_unref (G_OBJECT(builder));
730 
731  gnc_restore_window_size (GNC_PREFS_GROUP, GTK_WINDOW(fcd->dialog), parent);
732  gtk_widget_show (fcd->dialog);
733 }
734 
735 void
736 gnc_ui_fincalc_dialog_destroy (FinCalcDialog *fcd)
737 {
738  if (fcd == NULL)
739  return;
740 
741  gnc_close_gui_component_by_data (DIALOG_FINCALC_CM_CLASS, fcd);
742 }
Datatypes.
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 &#39;...
void gnc_gnome_help(GtkWindow *parent, const char *file_name, const char *anchor)
Launch the systems default help browser, gnome&#39;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)
Definition: gnc-numeric.h:152
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...
Definition: gnc-numeric.h:165
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
Check for error signal in value.
Use unbiased ("banker&#39;s") rounding.
Definition: gnc-numeric.h:172
#define GNC_DENOM_AUTO
Values that can be passed as the &#39;denom&#39; argument.
Definition: gnc-numeric.h:245
Commodity handling public routines.