r21118 - gnucash/trunk/src - Bug #653109 Change Loan Druid to an Assistant
Geert Janssens
gjanssens at code.gnucash.org
Sun Aug 7 05:14:37 EDT 2011
Author: gjanssens
Date: 2011-08-07 05:14:36 -0400 (Sun, 07 Aug 2011)
New Revision: 21118
Trac: http://svn.gnucash.org/trac/changeset/21118
Added:
gnucash/trunk/src/gnome/assistant-loan.c
gnucash/trunk/src/gnome/assistant-loan.h
gnucash/trunk/src/gnome/gtkbuilder/assistant-loan.glade
Removed:
gnucash/trunk/src/gnome/druid-loan.c
gnucash/trunk/src/gnome/druid-loan.h
Modified:
gnucash/trunk/src/gnome-utils/gnc-account-sel.c
gnucash/trunk/src/gnome/Makefile.am
gnucash/trunk/src/gnome/glade/sched-xact.glade
gnucash/trunk/src/gnome/gnc-plugin-basic-commands.c
gnucash/trunk/src/gnome/gtkbuilder/Makefile.am
gnucash/trunk/src/gnome/gtkbuilder/sched-xact.glade
Log:
Bug #653109 Change Loan Druid to an Assistant
Patch by Bob
Modified: gnucash/trunk/src/gnome/Makefile.am
===================================================================
--- gnucash/trunk/src/gnome/Makefile.am 2011-08-07 09:14:22 UTC (rev 21117)
+++ gnucash/trunk/src/gnome/Makefile.am 2011-08-07 09:14:36 UTC (rev 21118)
@@ -26,6 +26,7 @@
swig-gnome.c \
assistant-acct-period.c \
assistant-hierarchy.c \
+ assistant-loan.c \
assistant-stock-split.c \
dialog-commodities.c \
dialog-fincalc.c \
@@ -39,7 +40,6 @@
dialog-sx-from-trans.c \
dialog-sx-since-last-run.c \
dialog-tax-info.c \
- druid-loan.c \
gnc-plugin-account-tree.c \
gnc-plugin-basic-commands.c \
gnc-plugin-budget.c \
@@ -66,6 +66,7 @@
noinst_HEADERS = \
assistant-acct-period.h \
assistant-hierarchy.h \
+ assistant-loan.h \
assistant-stock-split.h \
dialog-fincalc.h \
dialog-find-transactions.h \
@@ -75,7 +76,6 @@
dialog-sx-editor.h \
dialog-sx-from-trans.h \
dialog-sx-since-last-run.h \
- druid-loan.h \
gnc-plugin-account-tree.h \
gnc-plugin-basic-commands.h \
gnc-plugin-budget.h \
Copied: gnucash/trunk/src/gnome/assistant-loan.c (from rev 21117, gnucash/trunk/src/gnome/druid-loan.c)
===================================================================
--- gnucash/trunk/src/gnome/assistant-loan.c (rev 0)
+++ gnucash/trunk/src/gnome/assistant-loan.c 2011-08-07 09:14:36 UTC (rev 21118)
@@ -0,0 +1,3199 @@
+/********************************************************************\
+ * assistant-loan.c : An Assistant for setting up loan-repayment *
+ * scheduled transactions. *
+ * Copyright (C) 2002,2007 Joshua Sled <jsled at asynchronous.org> *
+ * Copyright (C) 2006 David Hampton <hampton at employees.org> *
+ * Copyright (C) 2011 Robert Fewell *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+
+#include "config.h"
+#include <gnome.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <glade/glade.h>
+#include <math.h>
+#include "assistant-loan.h"
+#include "SchedXaction.h"
+#include "SX-book.h"
+#include "SX-ttinfo.h"
+#include "assistant-utils.h"
+#include "gnc-amount-edit.h"
+#include "gnc-account-sel.h"
+#include "gnc-date.h"
+#include "gnc-exp-parser.h"
+#include "gnc-component-manager.h"
+#include "dialog-utils.h"
+#include "Account.h"
+#include "gnc-ui.h"
+#include "gnc-gdate-utils.h"
+#include "gnc-gui-query.h"
+#include "gnc-ui-util.h"
+#include "gnc-frequency.h"
+#include "gnc-engine.h"
+
+#define DIALOG_LOAN_ASSISTANT_CM_CLASS "assistant-loan-setup"
+
+static QofLogModule log_module = GNC_MOD_ASSISTANT;
+
+enum loan_cols
+{
+ LOAN_COL_DATE = 0,
+ LOAN_COL_PAYMENT,
+ LOAN_COL_PRINCIPAL,
+ LOAN_COL_INTEREST,
+ NUM_LOAN_COLS
+};
+
+typedef enum
+{
+ CURRENT_YEAR,
+ NOW_PLUS_ONE,
+ WHOLE_LOAN,
+ CUSTOM
+} REV_RANGE_OPTS;
+
+struct LoanAssistantData_;
+
+/**
+ * The data relating to a single "repayment option" -- a potential
+ * [sub-]transaction in the repayment.
+ **/
+typedef struct RepayOptData_
+{
+ gboolean enabled;
+ gboolean optValid;
+ gboolean FreqUniq;
+ char *name; /* { "insurance", "pmi", "taxes", ... } */
+ char *txnMemo;
+ float amount;
+ gboolean throughEscrowP;
+ gboolean specSrcAcctP;
+ Account *to;
+ Account *from; /* If NULL { If throughEscrowP, then through escrowAcct };
+ * else: undefined. */
+ GList *schedule;
+ /* If NULL, part of repayment; otherwise: defined
+ * here. */
+ GDate *startDate;
+} RepayOptData;
+
+/**
+ * The default repayment options data.
+ **/
+typedef struct RepayOptDataDefault_
+{
+ char *name;
+ char *defaultTxnMemo;
+ gboolean escrowDefault;
+ gboolean specSrcAcctDefault;
+} RepayOptDataDefault;
+
+static RepayOptDataDefault REPAY_DEFAULTS[] =
+{
+ /* { name, default txn memo, throughEscrowP, specSrcAcctP } */
+ { N_("Taxes"), N_("Tax Payment"), TRUE, FALSE },
+ { N_("Insurance"), N_("Insurance Payment"), TRUE, FALSE },
+ /* Translators: PMI stands for Private Mortgage Insurance. */
+ { N_("PMI"), N_("PMI Payment"), TRUE, FALSE },
+ { N_("Other Expense"), N_("Miscellaneous Payment"), FALSE, FALSE },
+ { NULL }
+};
+
+/**
+ * The UI-side storage of the repayment options.
+ **/
+typedef struct RepayOptUI_
+{
+ /* must be stated this way [instead of 'LoanAssistantData*'] because of
+ * forward decl. */
+ struct LoanAssistantData_ *ldd;
+ GtkCheckButton *optCb;
+ GtkCheckButton *escrowCb;
+ RepayOptData *optData;
+} RepayOptUIData;
+
+typedef enum
+{
+ GNC_FIXED = 0,
+ GNC_VARIABLE,
+ GNC_VARIABLE_3_1 = GNC_VARIABLE,
+ GNC_VARIABLE_5_1,
+ GNC_VARIABLE_7_1,
+ GNC_VARIABLE_10_1,
+ /* ... FIXME */
+} LoanType;
+
+typedef enum
+{
+ GNC_MONTHS = 0,
+ GNC_YEARS
+} PeriodSize;
+
+/*type of interest rate entered*/
+typedef enum
+{
+ GNC_IRATE_SIMPLE,
+ GNC_IRATE_APR_DAILY,
+ GNC_IRATE_APR_WEEKLY,
+ GNC_IRATE_APR_MONTHLY,
+ GNC_IRATE_APR_QUARTERLY,
+ GNC_IRATE_APR_ANNUALLY
+} IRateType;
+
+/**
+ * A transient struct used to collate the GDate and the gnc_numeric row-data
+ * for the repayment review schedule. numCells is an array of gnc_numerics,
+ * with a length of the LoanData.revNumPmts.
+ **/
+typedef struct rev_repayment_row
+{
+ GDate date;
+ gnc_numeric *numCells;
+} RevRepaymentRow;
+
+/**
+ * Data about a loan repayment.
+ **/
+typedef struct LoanData_
+{
+ Account *primaryAcct;
+ gnc_numeric principal;
+ float interestRate;
+ IRateType rateType;
+ LoanType type;
+ GList *loan_schedule;
+ GDate *startDate;
+ GDate *varStartDate;
+ int numPer;
+ PeriodSize perSize;
+ int numMonRemain;
+
+ char *repMemo;
+ char *repAmount;
+ Account *repFromAcct;
+ Account *repPriAcct;
+ Account *repIntAcct;
+ Account *escrowAcct;
+ GList *repayment_schedule;
+ GDate *repStartDate;
+
+ int repayOptCount;
+ RepayOptData **repayOpts;
+
+ /* Data concerning the review of repayments. */
+ int revNumPmts;
+ int revRepayOptToColMap[ (sizeof(REPAY_DEFAULTS)
+ / sizeof(RepayOptDataDefault))
+ - 1 ];
+ GList *revSchedule;
+} LoanData;
+
+/**
+ * The UI-side storage of the loan druid data.
+ **/
+typedef struct LoanAssistantData_
+{
+ GtkWidget *window;
+ GtkWidget *assistant;
+
+ LoanData ld;
+ /* The UI-side storage of repayment data; this is 1:1 with the array
+ * in LoanData */
+ RepayOptUIData **repayOptsUI;
+
+ /* Current index of the payment opt for multiplexing the 'payment'
+ * page. */
+ int currentIdx;
+
+ /* widgets */
+ /* prm = params */
+ GtkTable *prmTable;
+ GNCAccountSel *prmAccountGAS;
+ GNCAmountEdit *prmOrigPrincGAE;
+ GtkSpinButton *prmIrateSpin;
+ GtkComboBox *prmType;
+ GtkFrame *prmVarFrame;
+ GncFrequency *prmVarGncFreq;
+ GNCDateEdit *prmStartDateGDE;
+ GtkSpinButton *prmLengthSpin;
+ GtkComboBox *prmLengthType;
+ GtkSpinButton *prmRemainSpin;
+ GtkComboBox *prmIrateType;
+
+ /* opt = options */
+ GtkVBox *optVBox;
+ GtkCheckButton *optEscrowCb;
+ GtkHBox *optEscrowHBox;
+ GNCAccountSel *optEscrowGAS;
+
+ /* rep = repayment */
+ GtkEntry *repTxnName;
+ GtkTable *repTable;
+ GtkEntry *repAmtEntry;
+ GNCAccountSel *repAssetsFromGAS;
+ GNCAccountSel *repPrincToGAS;
+ GNCAccountSel *repIntToGAS;
+ GtkFrame *repFreqFrame;
+ GncFrequency *repGncFreq;
+
+ /* pay = payment[s] */
+ GtkEntry *payTxnName;
+ GtkEntry *payAmtEntry;
+ GNCAccountSel *payAcctFromGAS;
+ GNCAccountSel *payAcctEscToGAS;
+ GNCAccountSel *payAcctEscFromGAS;
+ GNCAccountSel *payAcctToGAS;
+ GtkTable *payTable;
+ GtkCheckButton *payUseEscrow;
+ GtkCheckButton *paySpecSrcAcct;
+ GtkLabel *payAcctFromLabel;
+ GtkLabel *payEscToLabel;
+ GtkLabel *payEscFromLabel;
+ GtkRadioButton *payTxnFreqPartRb;
+ GtkRadioButton *payTxnFreqUniqRb;
+ GtkAlignment *payFreqAlign;
+ GncFrequency *payGncFreq;
+
+ /* rev = review */
+ GtkComboBox *revRangeOpt;
+ GtkFrame *revDateFrame;
+ GtkTable *revTable;
+ GNCDateEdit *revStartDate;
+ GNCDateEdit *revEndDate;
+ GtkScrolledWindow *revScrollWin;
+ GtkTreeView *revView;
+} LoanAssistantData;
+
+/**
+ * A transient structure to contain SX details during the creation process.
+ **/
+typedef struct toCreateSX_
+{
+ /** The name of the SX */
+ gchar *name;
+ /** The start, last-occurred and end dates. */
+ GDate start, last, end;
+ /** The SX schedule */
+ GList *schedule;
+ /** The current 'instance-num' count. */
+ gint instNum;
+ /** The main/source transaction being created. */
+ TTInfo *mainTxn;
+ /** The optional escrow transaction being created. */
+ TTInfo *escrowTxn;
+} toCreateSX;
+
+/**************************************************************************/
+
+static void loan_assistant_window_destroy_cb( GtkObject *object, gpointer user_data );
+static void loan_assistant_close_handler( gpointer user_data );
+static void loan_assistant_data_init( LoanAssistantData *ldd );
+
+static void loan_info_prep( GtkAssistant *assistant, gpointer user_data );
+static void loan_info_prm_type_cb( GtkWidget *w, gpointer user_data );
+static void loan_info_calc_update_cb( GtkWidget *widget, gpointer user_data );
+void loan_info_page_valid_cb( GtkWidget *widget, gpointer user_data );
+static gboolean loan_info_page_complete( GtkAssistant *assistant, gpointer user_data );
+static void loan_info_page_save( GtkAssistant *assistant, gpointer user_data );
+
+static void loan_opt_prep( GtkAssistant *assistant, gpointer user_data );
+static void loan_opt_toggled_cb( GtkToggleButton *tb, gpointer user_data );
+static void loan_opt_consistency_cb( GtkToggleButton *tb, gpointer user_data );
+static void loan_opt_escrow_toggle_cb( GtkToggleButton *tb, gpointer user_data );
+static void loan_opt_escrow_toggled_cb( GtkToggleButton *tb, gpointer user_data );
+void loan_opt_page_valid_cb (GtkWidget *widget, gpointer user_data );
+static gboolean loan_opt_page_complete( GtkAssistant *assistant, gpointer user_data );
+
+static void loan_rep_prep ( GtkAssistant *assistant, gpointer user_data );
+void loan_rep_page_valid_cb (GtkWidget *widget, gpointer user_data );
+static gboolean loan_rep_page_complete( GtkAssistant *assistant, gpointer user_data );
+static void loan_rep_page_save( GtkAssistant *assistant, gpointer user_data );
+
+static void loan_pay_prep ( GtkAssistant *assistant, gpointer user_data );
+static void loan_pay_use_esc_setup( LoanAssistantData *ldd, gboolean newState );
+static void loan_pay_use_esc_toggle_cb( GtkToggleButton *tb, gpointer user_data );
+static void loan_pay_spec_src_setup( LoanAssistantData *ldd, gboolean newState );
+static void loan_pay_spec_src_toggle_cb( GtkToggleButton *tb, gpointer user_data );
+static void loan_pay_freq_toggle_cb( GtkToggleButton *tb, gpointer user_data );
+static void loan_pay_page_valid_cb (GtkWidget *widget, gpointer user_data );
+static gboolean loan_pay_complete( GtkAssistant *assistant, gpointer user_data );
+static gboolean loan_pay_all_opt_valid ( GtkAssistant *assistant, gpointer user_data );
+static void loan_pay_back_button_cb( GtkButton *button, gpointer user_data );
+static void loan_pay_next_button_cb( GtkButton *button, gpointer user_data );
+
+static void loan_rev_prep ( GtkAssistant *assistant, gpointer user_data );
+static void loan_rev_recalc_schedule( LoanAssistantData *ldd );
+static void loan_rev_range_opt_changed_cb( GtkComboBox *combo, gpointer user_data );
+static void loan_rev_range_changed_cb( GNCDateEdit *gde, gpointer user_data );
+static void loan_rev_get_loan_range( LoanAssistantData *ldd, GDate *start, GDate *end );
+static void loan_rev_get_dates( LoanAssistantData *ldd, GDate *start, GDate *end );
+static void loan_rev_update_view( LoanAssistantData *ldd, GDate *start, GDate *end );
+static void loan_rev_sched_list_free( gpointer data, gpointer user_data );
+static void loan_rev_hash_to_list( gpointer key, gpointer val, gpointer user_data );
+static void loan_rev_hash_free_date_keys( gpointer key, gpointer val, gpointer user_data );
+
+static void loan_get_pmt_formula( LoanAssistantData *ldd, GString *gstr );
+static void loan_get_ppmt_formula( LoanAssistantData *ldd, GString *gstr );
+static void loan_get_ipmt_formula( LoanAssistantData *ldd, GString *gstr );
+static float loan_apr_to_simple_formula (float rate, float compounding_periods);
+
+static void loan_create_sxes( LoanAssistantData *ldd );
+static gint loan_find_ttsplit_with_acct( gconstpointer elt, gconstpointer crit );
+static void loan_create_sx_from_tcSX( LoanAssistantData *ldd, toCreateSX *tcSX );
+static void loan_tcSX_free( gpointer data, gpointer user_data );
+
+void loan_assistant_prepare( GtkAssistant *assistant, GtkWidget *page, gpointer user_data );
+void loan_assistant_finish( GtkAssistant *gtkassistant, gpointer user_data );
+void loan_assistant_cancel( GtkAssistant *gtkassistant, gpointer user_data );
+void loan_assistant_close( GtkAssistant *gtkassistant, gpointer user_data );
+
+/*****************************************************************************/
+
+
+static
+void
+loan_assistant_close_handler( gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ gtk_widget_destroy( ldd->window );
+}
+
+
+static
+void
+loan_assistant_window_destroy_cb( GtkObject *object, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+
+ g_assert( ldd );
+
+ gnc_unregister_gui_component_by_data (DIALOG_LOAN_ASSISTANT_CM_CLASS, ldd);
+
+ /* free alloc'd mem; cleanup */
+
+ /* repay opts */
+ {
+ int i;
+
+ g_date_free( ldd->ld.startDate );
+ g_date_free( ldd->ld.varStartDate );
+ recurrenceListFree(&ldd->ld.loan_schedule);
+
+ if ( ldd->ld.repMemo )
+ g_free( ldd->ld.repMemo );
+
+ for ( i = 0; i < ldd->ld.repayOptCount; i++ )
+ {
+ RepayOptData *rod = ldd->ld.repayOpts[i];
+ if ( rod->name )
+ g_free( rod->name );
+ if ( rod->txnMemo )
+ g_free( rod->txnMemo );
+
+ if ( rod->startDate )
+ g_date_free( rod->startDate );
+
+ if (rod->schedule != NULL)
+ recurrenceListFree(&rod->schedule);
+
+ g_free( ldd->ld.repayOpts[i] );
+ g_free( ldd->repayOptsUI[i] );
+ }
+ g_free( ldd->ld.repayOpts );
+ g_free( ldd->repayOptsUI );
+
+ if ( ldd->ld.repAmount )
+ g_free( ldd->ld.repAmount );
+
+ g_date_free( ldd->ld.repStartDate );
+ }
+
+ /* review */
+ {
+ if ( ldd->ld.revSchedule )
+ {
+ g_list_foreach( ldd->ld.revSchedule,
+ loan_rev_sched_list_free,
+ NULL );
+ g_list_free( ldd->ld.revSchedule );
+ ldd->ld.revSchedule = NULL;
+ }
+ }
+
+ g_free( ldd );
+}
+
+
+static GtkWidget *
+gnc_loan_assistant_create( LoanAssistantData *ldd )
+{
+ GtkBuilder *builder;
+ GtkWidget *window;
+
+ loan_assistant_data_init( ldd );
+
+ builder = gtk_builder_new();
+
+ gnc_builder_add_from_file (builder ,"assistant-loan.glade", "len_liststore");
+ gnc_builder_add_from_file (builder ,"assistant-loan.glade", "range_liststore");
+ gnc_builder_add_from_file (builder ,"assistant-loan.glade", "type_liststore");
+ gnc_builder_add_from_file (builder ,"assistant-loan.glade", "rate_liststore");
+
+ gnc_builder_add_from_file (builder ,"assistant-loan.glade", "Loan-Mortgage Assistant");
+ window = GTK_WIDGET(gtk_builder_get_object (builder, "Loan-Mortgage Assistant"));
+ ldd->window = window;
+
+
+ /* Set the assistant colors */
+ gnc_assistant_set_colors (GTK_ASSISTANT (ldd->window));
+
+ /* Enable buttons on complete pages. */
+ gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
+ GTK_WIDGET(gtk_builder_get_object(builder, "loan_intro_page")),
+ TRUE);
+ gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
+ GTK_WIDGET(gtk_builder_get_object(builder, "loan_options_page")),
+ TRUE);
+ gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
+ GTK_WIDGET(gtk_builder_get_object(builder, "loan_review_page")),
+ TRUE);
+
+ /* Information Page */
+ {
+ ldd->prmTable = GTK_TABLE(gtk_builder_get_object(builder, "param_table"));
+ ldd->prmVarFrame = GTK_FRAME(gtk_builder_get_object(builder, "type_freq_frame"));
+ ldd->prmIrateSpin = GTK_SPIN_BUTTON (gtk_builder_get_object(builder, "irate_spin"));
+ ldd->prmType = GTK_COMBO_BOX (gtk_builder_get_object(builder, "type_combobox"));
+ gtk_combo_box_set_active( GTK_COMBO_BOX( ldd->prmType), 0 );
+ ldd->prmLengthSpin = GTK_SPIN_BUTTON (gtk_builder_get_object(builder, "len_spin"));
+ ldd->prmLengthType = GTK_COMBO_BOX (gtk_builder_get_object(builder, "len_opt"));
+ gtk_combo_box_set_active( GTK_COMBO_BOX( ldd->prmLengthType), 0 );
+ ldd->prmRemainSpin = GTK_SPIN_BUTTON (gtk_builder_get_object(builder, "rem_spin"));
+ ldd->prmIrateType = GTK_COMBO_BOX (gtk_builder_get_object(builder, "irate_type_combobox"));
+ gtk_combo_box_set_active( GTK_COMBO_BOX( ldd->prmIrateType), 0 );
+ /* ldd->prmStartDateGDE */
+ }
+ /* Repayment Page */
+ {
+ ldd->repTable = GTK_TABLE(gtk_builder_get_object(builder, "repay_table"));
+ ldd->repTxnName = GTK_ENTRY(gtk_builder_get_object(builder, "txn_title"));
+ ldd->repAmtEntry = GTK_ENTRY(gtk_builder_get_object(builder, "amount_ent"));
+ ldd->repFreqFrame = GTK_FRAME(gtk_builder_get_object(builder, "freq_frame"));
+ }
+ /* Options Page */
+ {
+ ldd->optVBox = GTK_VBOX(gtk_builder_get_object(builder, "loan_options_page"));
+ ldd->optEscrowCb = GTK_CHECK_BUTTON(gtk_builder_get_object(builder, "opt_escrow_cb"));
+ ldd->optEscrowHBox = GTK_HBOX(gtk_builder_get_object(builder, "opt_escrow_hbox"));
+ }
+ /* Payment Page */
+ {
+ ldd->payTable = GTK_TABLE(gtk_builder_get_object(builder, "pay_table"));
+ ldd->payTxnName = GTK_ENTRY(gtk_builder_get_object(builder, "pay_txn_title"));
+ ldd->payAmtEntry = GTK_ENTRY(gtk_builder_get_object(builder, "pay_amt_ent"));
+ ldd->payUseEscrow = GTK_CHECK_BUTTON(gtk_builder_get_object(builder, "pay_use_escrow"));
+ ldd->paySpecSrcAcct = GTK_CHECK_BUTTON(gtk_builder_get_object(builder, "pay_specify_source"));
+ ldd->payAcctFromLabel = GTK_LABEL(gtk_builder_get_object(builder, "pay_from_account_label"));
+ ldd->payEscToLabel = GTK_LABEL(gtk_builder_get_object(builder, "pay_escrow_to_label"));
+ ldd->payEscFromLabel = GTK_LABEL(gtk_builder_get_object(builder, "pay_escrow_from_label"));
+ ldd->payTxnFreqPartRb = GTK_RADIO_BUTTON(gtk_builder_get_object(builder, "pay_txn_part_rb"));
+ ldd->payTxnFreqUniqRb = GTK_RADIO_BUTTON(gtk_builder_get_object(builder, "pay_uniq_freq_rb"));
+ ldd->payFreqAlign = GTK_ALIGNMENT(gtk_builder_get_object(builder, "pay_freq_align"));
+ }
+ /* Review Page */
+ {
+ ldd->revTable = GTK_TABLE(gtk_builder_get_object(builder, "rev_date_range_table"));
+ ldd->revRangeOpt = GTK_COMBO_BOX(gtk_builder_get_object(builder, "rev_range_opt"));
+ ldd->revDateFrame = GTK_FRAME(gtk_builder_get_object(builder, "rev_date_frame"));
+ ldd->revScrollWin = GTK_SCROLLED_WINDOW(gtk_builder_get_object(builder, "rev_scrollwin"));
+ /* GNCDateEdit *revStartDate */
+ /* GNCDateEdit *revEndDate */
+ }
+
+ /* non-buildable widget setup */
+ {
+ GtkWidget *butt;
+ int i;
+ // ACCT_TYPE_LIABILITY
+ GList *liabilityAcct;
+ // ACCT_TYPE_BANK, ACCT_TYPE_CASH, ACCT_TYPE_CREDIT,
+ // ACCT_TYPE_ASSET + ACCT_TYPE_LIABILITY
+ GList *paymentFromAccts;
+ // ACCT_TYPE_EXPENSE, ACCT_TYPE_LIABILITY, + payment-froms.
+ GList *paymentToAccts;
+ int fromLen = 5;
+ GNCAccountType paymentFroms[] = { ACCT_TYPE_BANK, ACCT_TYPE_CASH,
+ ACCT_TYPE_CREDIT, ACCT_TYPE_ASSET,
+ ACCT_TYPE_LIABILITY
+ };
+ int toLen = 1;
+ GNCAccountType paymentTos[] = { ACCT_TYPE_EXPENSE };
+
+ liabilityAcct = NULL;
+ paymentFromAccts = NULL;
+ paymentToAccts = NULL;
+
+ liabilityAcct = g_list_append( liabilityAcct,
+ GINT_TO_POINTER( ACCT_TYPE_LIABILITY ) );
+ for ( i = 0; i < fromLen; i++ )
+ {
+ paymentFromAccts
+ = g_list_append( paymentFromAccts,
+ GINT_TO_POINTER( paymentFroms[i] ) );
+ paymentToAccts
+ = g_list_append( paymentToAccts,
+ GINT_TO_POINTER( paymentFroms[i] ) );
+ }
+
+ for ( i = 0; i < toLen; i++ )
+ {
+ paymentToAccts = g_list_append( paymentToAccts,
+ GINT_TO_POINTER( paymentTos[i] ) );
+ }
+
+ /* All of the GncAccountSel[ectors]... */
+ {
+ int i;
+ GtkAlignment *a;
+ /* "gas" == GncAccountSel */
+ struct gas_in_tables_data
+ {
+ GNCAccountSel **loc;
+ GtkTable *table;
+ gboolean newAcctAbility;
+ int left, right, top, bottom;
+ GList *allowableAccounts;
+ } gas_data[] =
+ {
+ /* These ints are the GtkTable boundries */
+ { &ldd->prmAccountGAS, ldd->prmTable, TRUE, 1, 4, 0, 1, liabilityAcct },
+ { &ldd->repAssetsFromGAS, ldd->repTable, TRUE, 1, 4, 2, 3, paymentFromAccts },
+ { &ldd->repPrincToGAS, ldd->repTable, TRUE, 1, 2, 3, 4, paymentToAccts },
+ { &ldd->repIntToGAS, ldd->repTable, TRUE, 3, 4, 3, 4, paymentToAccts },
+ { &ldd->payAcctFromGAS, ldd->payTable, TRUE, 1, 2, 4, 5, paymentFromAccts },
+ { &ldd->payAcctEscToGAS, ldd->payTable, FALSE, 3, 4, 4, 5, paymentToAccts },
+ { &ldd->payAcctEscFromGAS, ldd->payTable, FALSE, 1, 2, 5, 6, paymentFromAccts },
+ { &ldd->payAcctToGAS, ldd->payTable, TRUE, 3, 4, 5, 6, paymentToAccts },
+ { NULL }
+ };
+
+ /* left-aligned, 25%-width */
+ a = GTK_ALIGNMENT(gtk_alignment_new( 0.0, 0.5, 0.25, 1.0 ));
+ ldd->prmOrigPrincGAE = GNC_AMOUNT_EDIT(gnc_amount_edit_new());
+ gtk_container_add( GTK_CONTAINER(a), GTK_WIDGET(ldd->prmOrigPrincGAE) );
+ gtk_table_attach( ldd->prmTable, GTK_WIDGET(a),
+ 1, 4, 1, 2,
+ GTK_EXPAND | GTK_FILL,
+ GTK_EXPAND | GTK_FILL, 2, 2 );
+
+ for ( i = 0; gas_data[i].loc != NULL; i++ )
+ {
+ GNCAccountSel *gas;
+
+ a = GTK_ALIGNMENT(gtk_alignment_new( 0.0, 0.5, 0.25, 1.0 ));
+ gas = GNC_ACCOUNT_SEL(gnc_account_sel_new());
+ gnc_account_sel_set_new_account_ability(
+ gas, gas_data[i].newAcctAbility );
+ if ( gas_data[i].allowableAccounts != NULL )
+ {
+ gnc_account_sel_set_acct_filters(
+ gas, gas_data[i].allowableAccounts, NULL );
+ }
+ gtk_container_add( GTK_CONTAINER(a),
+ GTK_WIDGET(gas) );
+ gtk_table_attach( gas_data[i].table,
+ GTK_WIDGET(a),
+ gas_data[i].left,
+ gas_data[i].right,
+ gas_data[i].top,
+ gas_data[i].bottom,
+ GTK_EXPAND | GTK_FILL,
+ GTK_EXPAND | GTK_FILL, 2, 2 );
+ *(gas_data[i].loc) = gas;
+ }
+ }
+
+ /* Setup the payment page always-insensitive GASes */
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctEscToGAS), FALSE );
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctEscFromGAS), FALSE );
+
+ /* The GNCDateEdit[s] */
+ {
+ /* "gde" == GNCDateEdit */
+ struct gde_in_tables_data
+ {
+ GNCDateEdit **loc;
+ GtkTable *table;
+ int left, right, top, bottom;
+ } gde_data[] =
+ {
+ /* These ints are the GtkTable boundries */
+ { &ldd->prmStartDateGDE, ldd->prmTable, 1, 2, 4, 5 },
+ { &ldd->revStartDate, ldd->revTable, 1, 2, 0, 1 },
+ { &ldd->revEndDate, ldd->revTable, 1, 2, 1, 2 },
+ { NULL }
+ };
+
+ for ( i = 0; gde_data[i].loc != NULL; i++ )
+ {
+ *gde_data[i].loc =
+ GNC_DATE_EDIT(
+ gnc_date_edit_new( time(NULL),
+ FALSE, FALSE ) );
+ gtk_table_attach( gde_data[i].table,
+ GTK_WIDGET( *gde_data[i].loc ),
+ gde_data[i].left,
+ gde_data[i].right,
+ gde_data[i].top,
+ gde_data[i].bottom,
+ (GTK_EXPAND | GTK_FILL),
+ GTK_FILL, 0, 0 );
+ }
+
+ }
+
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->prmVarFrame), FALSE );
+ {
+ g_signal_connect( ldd->prmType, "changed",
+ G_CALLBACK( loan_info_prm_type_cb ),
+ ldd );
+ }
+
+ {
+ GtkAdjustment *a;
+
+ /* 8.0 [%], range of 0.005..100.0 with ticks at 0.001[%]. */
+ a = GTK_ADJUSTMENT(gtk_adjustment_new( 8.0, 0.001,
+ 100.0, 0.001,
+ 1.0, 0.0 ));
+ gtk_spin_button_set_adjustment( ldd->prmIrateSpin, a );
+ gtk_spin_button_set_value( ldd->prmIrateSpin, 8.00 );
+ gtk_spin_button_set_snap_to_ticks( ldd->prmIrateSpin, TRUE );
+
+ a = GTK_ADJUSTMENT(gtk_adjustment_new( 360, 1,
+ 9999, 1,
+ 12, 0.0 ));
+ gtk_spin_button_set_adjustment( ldd->prmLengthSpin, a );
+ g_signal_connect( ldd->prmLengthSpin, "changed",
+ G_CALLBACK( loan_info_calc_update_cb ),
+ ldd );
+ g_signal_connect( ldd->prmStartDateGDE, "date-changed",
+ G_CALLBACK( loan_info_calc_update_cb ),
+ ldd );
+ g_signal_connect( ldd->prmLengthSpin, "value-changed",
+ G_CALLBACK( loan_info_calc_update_cb ),
+ ldd );
+ g_signal_connect( ldd->prmLengthType, "changed",
+ G_CALLBACK( loan_info_calc_update_cb ),
+ ldd );
+
+ a = GTK_ADJUSTMENT(gtk_adjustment_new( 360, 1,
+ 9999, 1,
+ 12, 0.0 ));
+ gtk_spin_button_set_adjustment( ldd->prmRemainSpin, a );
+ }
+
+ g_signal_connect( ldd->optEscrowCb, "toggled",
+ G_CALLBACK(loan_opt_escrow_toggle_cb), ldd );
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->optEscrowHBox), FALSE );
+ ldd->optEscrowGAS = GNC_ACCOUNT_SEL(gnc_account_sel_new());
+ gnc_account_sel_set_new_account_ability( ldd->optEscrowGAS, TRUE );
+ gtk_container_add( GTK_CONTAINER(ldd->optEscrowHBox),
+ GTK_WIDGET(ldd->optEscrowGAS) );
+
+ {
+ /* . Each RepayOpt gets an "entry" in the optContainer.
+ * . Each "entry" is a 2-line vbox containing:
+ * . The checkbox for the option itself
+ * . an alignment-contained sub-checkbox for "through the
+ * escrow account".
+ * . Hook up each to bit-twiddling the appropriate line.
+ */
+
+ RepayOptUIData *rouid;
+ GtkVBox *vb;
+ GtkAlignment *optAlign, *subOptAlign;
+ GString *str;
+
+ str = g_string_sized_new( 32 );
+
+ for ( i = 0; i < ldd->ld.repayOptCount; i++ )
+ {
+ rouid = ldd->repayOptsUI[i];
+ vb = GTK_VBOX(gtk_vbox_new( FALSE, 2 ));
+
+ /* Add payment checkbox. */
+
+ /* Translators: %s is "Taxes",
+ * "Insurance", or similar. */
+ g_string_printf( str, _("... pay \"%s\"?"),
+ rouid->optData->name );
+ rouid->optCb =
+ GTK_CHECK_BUTTON(
+ gtk_check_button_new_with_label(
+ str->str ));
+ gtk_box_pack_start( GTK_BOX(vb),
+ GTK_WIDGET(rouid->optCb),
+ FALSE, FALSE, 2 );
+ rouid->escrowCb =
+ GTK_CHECK_BUTTON(
+ gtk_check_button_new_with_label(
+ _("via Escrow account?") ));
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(rouid->escrowCb),
+ FALSE );
+ subOptAlign =
+ GTK_ALIGNMENT(
+ gtk_alignment_new(
+ 0.5, 0.5, 0.75, 1.0 ));
+ gtk_container_add( GTK_CONTAINER(subOptAlign),
+ GTK_WIDGET(rouid->escrowCb) );
+ gtk_box_pack_start( GTK_BOX(vb), GTK_WIDGET(subOptAlign),
+ FALSE, FALSE, 2 );
+
+ g_signal_connect( rouid->optCb, "toggled",
+ G_CALLBACK(loan_opt_toggled_cb),
+ rouid );
+ g_signal_connect( rouid->optCb, "toggled",
+ G_CALLBACK(loan_opt_consistency_cb),
+ rouid );
+ g_signal_connect( rouid->escrowCb, "toggled",
+ G_CALLBACK(loan_opt_escrow_toggled_cb),
+ rouid );
+
+ optAlign = GTK_ALIGNMENT(gtk_alignment_new( 0.5, 0.5, 0.75, 1.0 ));
+ gtk_container_add( GTK_CONTAINER(optAlign),
+ GTK_WIDGET(vb) );
+ gtk_box_pack_start( GTK_BOX(ldd->optVBox), GTK_WIDGET(optAlign),
+ FALSE, FALSE, 2 );
+ gtk_widget_show_all( GTK_WIDGET(optAlign) );
+ }
+ g_string_free( str, TRUE );
+ }
+
+ g_signal_connect( ldd->payUseEscrow, "toggled",
+ G_CALLBACK(loan_pay_use_esc_toggle_cb), ldd );
+ g_signal_connect( ldd->paySpecSrcAcct, "toggled",
+ G_CALLBACK(loan_pay_spec_src_toggle_cb), ldd );
+ g_signal_connect( ldd->payTxnFreqUniqRb, "toggled",
+ G_CALLBACK(loan_pay_freq_toggle_cb), ldd );
+
+ {
+ GtkHBox *hbox;
+ hbox = GTK_HBOX(gtk_builder_get_object(builder, "type_freq_hbox"));
+ ldd->prmVarGncFreq = GNC_FREQUENCY(gnc_frequency_new( NULL, NULL ));
+ gtk_box_pack_start( GTK_BOX(hbox) , GTK_WIDGET(ldd->prmVarGncFreq), TRUE, FALSE, 0 );
+ g_signal_connect (ldd->prmVarGncFreq, "changed",
+ G_CALLBACK (loan_info_page_valid_cb), ldd);
+ }
+ {
+ GtkHBox *hbox;
+ hbox = GTK_HBOX(gtk_builder_get_object(builder, "freq_frame_hbox"));
+ ldd->repGncFreq = GNC_FREQUENCY(gnc_frequency_new( NULL, NULL ));
+ gtk_box_pack_start( GTK_BOX(hbox) , GTK_WIDGET(ldd->repGncFreq), TRUE, FALSE, 0 );
+ g_signal_connect (ldd->repGncFreq, "changed",
+ G_CALLBACK (loan_rep_page_valid_cb), ldd);
+ }
+
+ ldd->payGncFreq = GNC_FREQUENCY(gnc_frequency_new( NULL, NULL ));
+ gtk_container_add( GTK_CONTAINER(ldd->payFreqAlign), GTK_WIDGET(ldd->payGncFreq) );
+ g_signal_connect (ldd->payGncFreq, "changed",
+ G_CALLBACK (loan_pay_page_valid_cb), ldd);
+
+ butt = GTK_WIDGET(gtk_builder_get_object(builder, "pay_back_button"));
+ g_signal_connect (butt, "clicked",
+ G_CALLBACK (loan_pay_back_button_cb), ldd);
+
+ butt = GTK_WIDGET(gtk_builder_get_object(builder, "pay_next_button"));
+ g_signal_connect (butt, "clicked",
+ G_CALLBACK (loan_pay_next_button_cb), ldd);
+
+ }
+
+ /* Info page Call Back */
+ {
+ g_signal_connect (ldd->prmAccountGAS, "account_sel_changed",
+ G_CALLBACK (loan_info_page_valid_cb), ldd);
+ g_signal_connect( ldd->prmIrateType, "changed",
+ G_CALLBACK( loan_info_page_valid_cb ), ldd );
+ }
+ /* Opts page Call Back */
+ {
+ g_signal_connect (ldd->optEscrowGAS, "account_sel_changed",
+ G_CALLBACK (loan_opt_page_valid_cb), ldd);
+ }
+ /* Rep page Call Back */
+ {
+ g_signal_connect (ldd->repAssetsFromGAS, "account_sel_changed",
+ G_CALLBACK (loan_rep_page_valid_cb), ldd);
+ g_signal_connect (ldd->repIntToGAS, "account_sel_changed",
+ G_CALLBACK (loan_rep_page_valid_cb), ldd);
+ g_signal_connect (ldd->repPrincToGAS, "account_sel_changed",
+ G_CALLBACK (loan_rep_page_valid_cb), ldd);
+ }
+ /* Pay page Call Back */
+ {
+ g_signal_connect (ldd->payAcctFromGAS, "account_sel_changed",
+ G_CALLBACK (loan_pay_page_valid_cb), ldd);
+ g_signal_connect (ldd->payAcctToGAS, "account_sel_changed",
+ G_CALLBACK (loan_pay_page_valid_cb), ldd);
+ g_signal_connect (ldd->payAcctEscFromGAS, "account_sel_changed",
+ G_CALLBACK (loan_pay_page_valid_cb), ldd);
+ g_signal_connect (ldd->payAcctEscToGAS, "account_sel_changed",
+ G_CALLBACK (loan_pay_page_valid_cb), ldd);
+ }
+ /* Review page Call Back */
+ {
+ gtk_combo_box_set_active( ldd->revRangeOpt, 0 );
+ g_signal_connect( ldd->revRangeOpt, "changed",
+ G_CALLBACK( loan_rev_range_opt_changed_cb ),
+ ldd );
+ g_signal_connect( ldd->revStartDate, "date-changed",
+ G_CALLBACK( loan_rev_range_changed_cb ),
+ ldd );
+ g_signal_connect( ldd->revEndDate, "date-changed",
+ G_CALLBACK( loan_rev_range_changed_cb ),
+ ldd );
+ }
+
+ g_signal_connect( ldd->window, "destroy",
+ G_CALLBACK(loan_assistant_window_destroy_cb),
+ ldd );
+
+ gtk_builder_connect_signals(builder, ldd);
+ g_object_unref(G_OBJECT(builder));
+
+ gtk_widget_show_all( ldd->window );
+ return window;
+}
+
+
+static
+void
+loan_assistant_data_init( LoanAssistantData *ldd )
+{
+ int i, optCount;
+ RepayOptData *optData;
+
+ /* get the count of repayment defaults. */
+ for ( optCount = 0; REPAY_DEFAULTS[optCount].name != NULL; optCount++ )
+ ;
+
+ ldd->currentIdx = -1;
+
+ ldd->ld.principal = gnc_numeric_zero();
+ ldd->ld.startDate = g_date_new();
+ ldd->ld.varStartDate = g_date_new();
+ g_date_set_time_t( ldd->ld.startDate, time(NULL) );
+ ldd->ld.loan_schedule = NULL;
+ ldd->ld.repayment_schedule = NULL;
+ {
+ Recurrence *r = g_new0(Recurrence, 1);
+ recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate, WEEKEND_ADJ_NONE);
+ ldd->ld.repayment_schedule = g_list_append(ldd->ld.repayment_schedule, r);
+ }
+
+ ldd->ld.repMemo = g_strdup( _("Loan") );
+ ldd->ld.repAmount = NULL;
+ ldd->ld.repStartDate = g_date_new();
+ ldd->ld.repayOptCount = optCount;
+ ldd->ld.repayOpts = g_new0( RepayOptData*, optCount );
+ /* copy all the default lines into the LDD */
+ ldd->repayOptsUI = g_new0( RepayOptUIData*, optCount );
+ for ( i = 0; i < optCount; i++ )
+ {
+ g_assert( REPAY_DEFAULTS[i].name != NULL );
+
+ ldd->repayOptsUI[i] = g_new0( RepayOptUIData, 1 );
+ ldd->repayOptsUI[i]->ldd = ldd;
+
+ optData = ldd->ld.repayOpts[i]
+ = ldd->repayOptsUI[i]->optData
+ = g_new0( RepayOptData, 1 );
+
+ optData->enabled = FALSE;
+ optData->optValid = FALSE;
+ optData->FreqUniq = FALSE;
+ optData->name = g_strdup( _(REPAY_DEFAULTS[i].name) );
+ optData->txnMemo = g_strdup( _(REPAY_DEFAULTS[i].
+ defaultTxnMemo) );
+ optData->amount = 0.0;
+ optData->throughEscrowP = REPAY_DEFAULTS[i].escrowDefault;
+ optData->specSrcAcctP = REPAY_DEFAULTS[i].specSrcAcctDefault;
+ optData->schedule = NULL;
+ optData->startDate = NULL;
+ }
+}
+
+/************************ Page functions in order ***********************/
+
+static
+void
+loan_info_prep( GtkAssistant *assistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+
+ gnc_amount_edit_set_amount( ldd->prmOrigPrincGAE, ldd->ld.principal );
+ gtk_spin_button_set_value( ldd->prmIrateSpin, ldd->ld.interestRate );
+ gtk_combo_box_set_active( ldd->prmIrateType, ldd->ld.rateType );
+ gtk_combo_box_set_active( ldd->prmType, ldd->ld.type );
+ if ( ldd->ld.type != GNC_FIXED )
+ {
+ g_signal_handlers_block_by_func( GNC_FREQUENCY( ldd->prmVarGncFreq), loan_info_page_valid_cb , ldd );
+ gnc_frequency_setup_recurrence(ldd->prmVarGncFreq, ldd->ld.loan_schedule, ldd->ld.varStartDate);
+ g_signal_handlers_unblock_by_func( GNC_FREQUENCY( ldd->prmVarGncFreq), loan_info_page_valid_cb , ldd );
+ }
+
+ /* start date */
+ {
+ struct tm *tmpTm;
+
+ tmpTm = g_new0( struct tm, 1 );
+
+ g_date_to_struct_tm( ldd->ld.startDate, tmpTm );
+ gnc_date_edit_set_time( ldd->prmStartDateGDE,
+ mktime(tmpTm) );
+ g_free( tmpTm );
+ }
+
+ /* length: total and remaining */
+ {
+ gtk_spin_button_set_value( ldd->prmLengthSpin, ldd->ld.numPer );
+ gtk_combo_box_set_active( ldd->prmLengthType, ldd->ld.perSize );
+ gtk_spin_button_set_value( ldd->prmRemainSpin, ldd->ld.numMonRemain );
+ }
+}
+
+
+static
+void
+loan_info_prm_type_cb( GtkWidget *w, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ gint index;
+
+ index = gtk_combo_box_get_active( ldd->prmType );
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->prmVarFrame),
+ index != GNC_FIXED );
+}
+
+
+static
+void
+loan_info_calc_update_cb( GtkWidget *w, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ GDate start, now;
+ int i, totalVal, total, remain;
+
+ g_date_clear( &start, 1 );
+ g_date_clear( &now, 1 );
+ g_date_set_time_t( &start, gnc_date_edit_get_date( ldd->prmStartDateGDE ) );
+ g_date_set_time_t( &now, time(NULL) );
+ for ( i = 0; g_date_compare( &start, &now ) < 0; i++ )
+ {
+ g_date_add_months( &start, 1 );
+ }
+
+ /* Get the correct, current value of the length spin. */
+ {
+ gchar *valueStr = gtk_editable_get_chars( GTK_EDITABLE(ldd->prmLengthSpin),
+ 0, -1 );
+ totalVal = strtol( valueStr, NULL, 10 );
+ g_free( valueStr );
+ }
+ total = totalVal
+ * ( gtk_combo_box_get_active( ldd->prmLengthType )
+ == 1 ? 12 : 1 );
+ remain = total - i;
+ gtk_spin_button_set_value( ldd->prmRemainSpin, remain );
+ gtk_widget_show( GTK_WIDGET(ldd->prmRemainSpin) );
+}
+
+
+void
+loan_info_page_valid_cb (GtkWidget *widget, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
+ gint num = gtk_assistant_get_current_page (assistant);
+ GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+ gtk_assistant_set_page_complete (assistant, page,
+ loan_info_page_complete (assistant, ldd));
+}
+
+
+static
+gboolean
+loan_info_page_complete( GtkAssistant *assistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+
+ ldd->ld.primaryAcct = gnc_account_sel_get_account( ldd->prmAccountGAS );
+ /* Test for valid Account */
+ if ( ldd->ld.primaryAcct == NULL )
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static
+void
+loan_info_page_save( GtkAssistant *assistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+
+ ldd->ld.primaryAcct = gnc_account_sel_get_account( ldd->prmAccountGAS );
+
+ if ( ! ldd->ld.repPriAcct )
+ {
+ ldd->ld.repPriAcct = ldd->ld.primaryAcct;
+ }
+ ldd->ld.principal = gnc_amount_edit_get_amount( ldd->prmOrigPrincGAE );
+ ldd->ld.interestRate = gtk_spin_button_get_value( ldd->prmIrateSpin );
+ ldd->ld.rateType = gtk_combo_box_get_active (ldd->prmIrateType );
+ ldd->ld.type = gtk_combo_box_get_active( ldd->prmType );
+
+ if ( ldd->ld.type != GNC_FIXED )
+ {
+ recurrenceListFree(&ldd->ld.loan_schedule);
+ gnc_frequency_save_to_recurrence(ldd->prmVarGncFreq,
+ &ldd->ld.loan_schedule,
+ ldd->ld.varStartDate);
+ }
+
+ /* start date */
+ {
+ time_t tmpTT;
+ struct tm *tmpTm;
+
+ tmpTT = gnc_date_edit_get_date( ldd->prmStartDateGDE );
+ tmpTm = localtime( &tmpTT );
+ g_date_set_dmy( ldd->ld.startDate,
+ tmpTm->tm_mday,
+ (tmpTm->tm_mon + 1),
+ (1900 + tmpTm->tm_year) );
+ }
+
+ /* len / periods */
+ {
+ ldd->ld.perSize =
+ (gtk_combo_box_get_active( ldd->prmLengthType )
+ == GNC_MONTHS) ? GNC_MONTHS : GNC_YEARS;
+ ldd->ld.numPer =
+ gtk_spin_button_get_value_as_int( ldd->prmLengthSpin );
+ ldd->ld.numMonRemain =
+ gtk_spin_button_get_value_as_int( ldd->prmRemainSpin );
+ }
+}
+
+/************************************************************************/
+
+static
+void
+loan_opt_prep( GtkAssistant *assistant, gpointer user_data )
+{
+ int i;
+ RepayOptUIData *rouid;
+ LoanAssistantData *ldd = user_data;
+
+ /* Save Previous Page ( Information ) */
+ loan_info_page_save(assistant, ldd);
+
+ if ( ldd->ld.escrowAcct )
+ {
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->optEscrowCb), TRUE );
+ gnc_account_sel_set_account( ldd->optEscrowGAS, ldd->ld.escrowAcct, FALSE );
+ }
+ for ( i = 0; i < ldd->ld.repayOptCount; i++ )
+ {
+ rouid = ldd->repayOptsUI[i];
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rouid->optCb),
+ rouid->optData->enabled );
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rouid->escrowCb),
+ rouid->optData->throughEscrowP
+ && rouid->optData->enabled
+ && ldd->ld.escrowAcct );
+ gtk_widget_set_sensitive( GTK_WIDGET(rouid->escrowCb),
+ rouid->optData->enabled
+ && ldd->ld.escrowAcct );
+ }
+}
+
+
+static
+void
+loan_opt_toggled_cb( GtkToggleButton *tb, gpointer user_data )
+{
+ RepayOptUIData *rouid;
+
+ rouid = (RepayOptUIData*)user_data;
+ rouid->optData->enabled = gtk_toggle_button_get_active(tb);
+}
+
+
+static
+void
+loan_opt_consistency_cb( GtkToggleButton *tb, gpointer user_data )
+{
+ GtkToggleButton *escrowCb;
+ RepayOptUIData *rouid;
+
+ rouid = (RepayOptUIData*)user_data;
+ escrowCb = GTK_TOGGLE_BUTTON(rouid->escrowCb);
+ /* make sure the escrow option is only selected if we're active. */
+ gtk_toggle_button_set_active( escrowCb,
+ gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(
+ rouid->ldd->optEscrowCb) )
+ && rouid->optData->throughEscrowP
+ && gtk_toggle_button_get_active(tb) );
+ /* make sure the escrow option is only sensitive if we're active, and
+ * the escrow account is enabled */
+ gtk_widget_set_sensitive( GTK_WIDGET(escrowCb),
+ gtk_toggle_button_get_active(tb)
+ && gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(rouid->ldd->optEscrowCb)) );
+}
+
+
+static
+void
+loan_opt_escrow_toggle_cb( GtkToggleButton *tb, gpointer user_data )
+{
+ int i;
+ gboolean newState;
+ RepayOptUIData *rouid;
+ LoanAssistantData *ldd = user_data;
+ GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
+ gint num = gtk_assistant_get_current_page (assistant);
+ GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+ newState = gtk_toggle_button_get_active(tb);
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->optEscrowHBox), newState );
+ /* Check for Valid Account if enabled */
+ if (newState)
+ {
+ if (GNC_ACCOUNT_SEL( ldd->ld.escrowAcct) == NULL)
+ gtk_assistant_set_page_complete (assistant, page, FALSE);
+ }
+ else
+ {
+ ldd->ld.escrowAcct = NULL;
+ gnc_account_sel_set_account( GNC_ACCOUNT_SEL( ldd->optEscrowGAS), NULL , FALSE );
+ gtk_assistant_set_page_complete (assistant, page, TRUE);
+ }
+
+
+ /* deal with escrow options. */
+ for ( i = 0; i < ldd->ld.repayOptCount; i++ )
+ {
+ rouid = ldd->repayOptsUI[i];
+ /* If we're going off, then uncheck and desensitize all escrow opts. */
+ /* If we're going on, then sensitize all escrow opts. */
+
+ /* prevent the toggle handler from running and "trashing" the
+ * state of the throughEscrowP selection */
+ g_signal_handlers_block_by_func( rouid->escrowCb,
+ loan_opt_escrow_toggled_cb,
+ rouid );
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(rouid->escrowCb),
+ ( newState
+ && gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(rouid->optCb) )
+ && rouid->optData->throughEscrowP ) );
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(rouid->escrowCb),
+ newState
+ && gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(rouid->optCb) ) );
+ g_signal_handlers_unblock_by_func( rouid->escrowCb,
+ loan_opt_escrow_toggled_cb,
+ rouid );
+ if ( newState )
+ {
+ rouid->optData->from = ldd->ld.escrowAcct;
+ }
+ else
+ {
+ rouid->optData->from = NULL;
+ }
+ }
+}
+
+
+static
+void
+loan_opt_escrow_toggled_cb( GtkToggleButton *tb, gpointer user_data )
+{
+ RepayOptUIData *rouid;
+
+ rouid = (RepayOptUIData*)user_data;
+ rouid->optData->throughEscrowP = gtk_toggle_button_get_active( tb );
+}
+
+
+void
+loan_opt_page_valid_cb (GtkWidget *widget, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+
+ GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
+ gint num = gtk_assistant_get_current_page (assistant);
+ GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+ gtk_assistant_set_page_complete (assistant, page,
+ loan_opt_page_complete (assistant, ldd));
+}
+
+
+static
+gboolean
+loan_opt_page_complete( GtkAssistant *assistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+
+ if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ldd->optEscrowCb) ) )
+ {
+ ldd->ld.escrowAcct =
+ gnc_account_sel_get_account( ldd->optEscrowGAS );
+ /* Test for valid Account */
+ if ( ldd->ld.escrowAcct == NULL )
+ return FALSE;
+ }
+ else
+ {
+ ldd->ld.escrowAcct = NULL;
+ }
+ return TRUE;
+}
+
+/************************************************************************/
+
+static
+void
+loan_rep_prep( GtkAssistant *assistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ GString *str;
+
+ if ( ldd->ld.repAmount )
+ {
+ g_free( ldd->ld.repAmount );
+ }
+
+ str = g_string_sized_new( 64 );
+ loan_get_pmt_formula( ldd, str);
+ ldd->ld.repAmount = str->str;
+ g_string_free( str, FALSE );
+
+ if ( ldd->ld.repMemo )
+ gtk_entry_set_text( ldd->repTxnName, ldd->ld.repMemo );
+
+ if ( ldd->ld.repAmount )
+ gtk_entry_set_text( ldd->repAmtEntry, ldd->ld.repAmount );
+
+ gnc_account_sel_set_account( ldd->repAssetsFromGAS, ldd->ld.repFromAcct, FALSE );
+ gnc_account_sel_set_account( ldd->repPrincToGAS, ldd->ld.repPriAcct, FALSE );
+ gnc_account_sel_set_account( ldd->repIntToGAS, ldd->ld.repIntAcct, FALSE );
+
+ g_signal_handlers_block_by_func( ldd->repGncFreq, loan_rep_page_valid_cb , ldd );
+ gnc_frequency_setup_recurrence(ldd->repGncFreq, ldd->ld.repayment_schedule, ldd->ld.repStartDate);
+ g_signal_handlers_unblock_by_func( ldd->repGncFreq, loan_rep_page_valid_cb , ldd );
+
+ /* Find the first enabled option */
+ {
+ int i;
+ for ( i = 0; // we can always start at 0, here.
+ (i < ldd->ld.repayOptCount)
+ && !ldd->ld.repayOpts[i]->enabled;
+ i++ )
+ ;
+ if ( i < ldd->ld.repayOptCount )
+ ldd->currentIdx = i;
+ else
+ ldd->currentIdx = -1;
+ }
+}
+
+
+void
+loan_rep_page_valid_cb (GtkWidget *widget, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
+ gint num = gtk_assistant_get_current_page (assistant);
+ GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+ gtk_assistant_set_page_complete (assistant, page,
+ loan_rep_page_complete (assistant, ldd));
+}
+
+
+static
+gboolean
+loan_rep_page_complete( GtkAssistant *assistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ int i;
+
+ ldd->ld.repFromAcct =
+ gnc_account_sel_get_account( ldd->repAssetsFromGAS );
+ /* Test for valid Account */
+ if ( ldd->ld.repFromAcct == NULL )
+ return FALSE;
+
+ ldd->ld.repPriAcct =
+ gnc_account_sel_get_account( ldd->repPrincToGAS );
+ /* Test for valid Account */
+ if ( ldd->ld.repPriAcct == NULL )
+ return FALSE;
+
+ ldd->ld.repIntAcct =
+ gnc_account_sel_get_account( ldd->repIntToGAS );
+ /* Test for valid Account */
+ if ( ldd->ld.repIntAcct == NULL )
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static
+void
+loan_rep_page_save( GtkAssistant *assistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ int i;
+
+ if ( ldd->ld.repMemo )
+ g_free( ldd->ld.repMemo );
+ ldd->ld.repMemo =
+ gtk_editable_get_chars( GTK_EDITABLE(ldd->repTxnName), 0, -1 );
+
+ if ( ldd->ld.repAmount )
+ g_free( ldd->ld.repAmount );
+ ldd->ld.repAmount =
+ gtk_editable_get_chars( GTK_EDITABLE(ldd->repAmtEntry), 0, -1 );
+
+ ldd->ld.repFromAcct =
+ gnc_account_sel_get_account( ldd->repAssetsFromGAS );
+
+ ldd->ld.repPriAcct =
+ gnc_account_sel_get_account( ldd->repPrincToGAS );
+
+ ldd->ld.repIntAcct =
+ gnc_account_sel_get_account( ldd->repIntToGAS );
+
+ recurrenceListFree(&ldd->ld.repayment_schedule);
+ gnc_frequency_save_to_recurrence(ldd->repGncFreq,
+ &ldd->ld.repayment_schedule,
+ ldd->ld.repStartDate);
+}
+
+/************************************************************************/
+
+static
+void
+loan_pay_prep( GtkAssistant *assistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ RepayOptData *rod;
+ GString *str;
+
+
+ gint num = gtk_assistant_get_current_page (assistant);
+ GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+ /* Save Previous Page (Repayment) */
+ loan_rep_page_save(assistant, ldd);
+
+ /* Step over page if no options enabled */
+ if (ldd->currentIdx == -1 )
+ {
+ gtk_assistant_set_current_page (assistant, num + 1);
+ }
+ else
+ {
+ g_assert( ldd->currentIdx >= 0 );
+ g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
+
+ rod = ldd->ld.repayOpts[ldd->currentIdx];
+ str = g_string_sized_new( 32 );
+ /* Translators: %s is "Taxes", or "Insurance", or similar */
+ g_string_printf( str, _("Loan Repayment Option: \"%s\""), rod->name );
+ gtk_assistant_set_page_title (assistant, page, str->str );
+
+ /* copy in the relevant data from the currently-indexed option. */
+ gtk_entry_set_text( ldd->payTxnName, rod->txnMemo );
+ g_string_printf( str, "%0.2f", rod->amount );
+ gtk_entry_set_text( ldd->payAmtEntry, str->str );
+
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->payUseEscrow),
+ (ldd->ld.escrowAcct != NULL) );
+
+ {
+ g_signal_handlers_block_by_func( ldd->payUseEscrow,
+ loan_pay_use_esc_toggle_cb,
+ ldd );
+
+ loan_pay_use_esc_setup( ldd,
+ (ldd->ld.escrowAcct != NULL)
+ && rod->throughEscrowP );
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payUseEscrow),
+ (rod->throughEscrowP
+ && ldd->ld.escrowAcct != NULL) );
+
+ g_signal_handlers_unblock_by_func( ldd->payUseEscrow,
+ loan_pay_use_esc_toggle_cb,
+ ldd );
+ }
+
+ {
+ g_signal_handlers_block_by_func( ldd->paySpecSrcAcct,
+ loan_pay_spec_src_toggle_cb,
+ ldd );
+ loan_pay_spec_src_setup( ldd, rod->specSrcAcctP );
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->paySpecSrcAcct),
+ rod->specSrcAcctP );
+
+ g_signal_handlers_unblock_by_func( ldd->paySpecSrcAcct,
+ loan_pay_spec_src_toggle_cb,
+ ldd );
+ }
+
+ g_signal_handlers_block_by_func(ldd->payAcctToGAS, loan_pay_page_valid_cb, ldd );
+ gnc_account_sel_set_account( ldd->payAcctToGAS, rod->to, FALSE );
+ g_signal_handlers_unblock_by_func(ldd->payAcctToGAS, loan_pay_page_valid_cb, ldd );
+
+
+ g_signal_handlers_block_by_func(ldd->payTxnFreqUniqRb, loan_pay_freq_toggle_cb, ldd );
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqPartRb), !rod->FreqUniq );
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb), rod->FreqUniq );
+ g_signal_handlers_unblock_by_func(ldd->payTxnFreqUniqRb, loan_pay_freq_toggle_cb, ldd );
+
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->payFreqAlign), rod->FreqUniq );
+
+ if ( rod->FreqUniq )
+ {
+ g_signal_handlers_disconnect_by_func( ldd->payGncFreq, loan_pay_page_valid_cb, ldd );
+ gtk_container_remove( GTK_CONTAINER(ldd->payFreqAlign), GTK_WIDGET(ldd->payGncFreq) );
+ ldd->payGncFreq = NULL;
+ ldd->payGncFreq = GNC_FREQUENCY(gnc_frequency_new_from_recurrence( rod->schedule, rod->startDate ));
+ gtk_container_add( GTK_CONTAINER(ldd->payFreqAlign), GTK_WIDGET(ldd->payGncFreq) );
+ g_signal_connect (ldd->payGncFreq, "changed",
+ G_CALLBACK (loan_pay_page_valid_cb), ldd);
+ }
+ g_string_free( str, TRUE );
+ loan_pay_page_valid_cb(GTK_WIDGET(ldd->window), ldd);
+ }
+}
+
+
+void
+loan_pay_page_valid_cb (GtkWidget *widget, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
+ gint num = gtk_assistant_get_current_page (assistant);
+ GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
+
+ gtk_assistant_set_page_complete (assistant, page,
+ ( loan_pay_complete (assistant, ldd) &&
+ loan_pay_all_opt_valid (assistant, ldd )));
+}
+
+
+static
+void
+loan_pay_use_esc_setup( LoanAssistantData *ldd, gboolean newState )
+{
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->payEscToLabel), newState );
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->payEscFromLabel), newState );
+ if ( newState )
+ {
+ g_signal_handlers_block_by_func( ldd->payAcctEscToGAS, loan_pay_page_valid_cb, ldd );
+ g_signal_handlers_block_by_func( ldd->payAcctEscFromGAS, loan_pay_page_valid_cb, ldd );
+ gnc_account_sel_set_account( ldd->payAcctEscToGAS, ldd->ld.escrowAcct, FALSE );
+ gnc_account_sel_set_account( ldd->payAcctEscFromGAS, ldd->ld.escrowAcct, FALSE );
+ g_signal_handlers_unblock_by_func( ldd->payAcctEscToGAS, loan_pay_page_valid_cb, ldd );
+ g_signal_handlers_unblock_by_func( ldd->payAcctEscFromGAS, loan_pay_page_valid_cb, ldd );
+ }
+}
+
+
+static
+void
+loan_pay_use_esc_toggle_cb( GtkToggleButton *tb, gpointer user_data )
+{
+ gboolean newState;
+ LoanAssistantData *ldd = user_data;
+
+ newState = gtk_toggle_button_get_active( tb );
+ loan_pay_use_esc_setup( ldd, newState );
+}
+
+
+static
+void
+loan_pay_spec_src_setup( LoanAssistantData *ldd, gboolean newState )
+{
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctFromLabel), newState );
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctFromGAS), newState );
+ if ( newState )
+ {
+ g_signal_handlers_block_by_func( ldd->payAcctFromGAS, loan_pay_page_valid_cb, ldd );
+ gnc_account_sel_set_account( ldd->payAcctFromGAS, ldd->ld.repayOpts[ldd->currentIdx]->from, FALSE );
+ g_signal_handlers_unblock_by_func( ldd->payAcctFromGAS, loan_pay_page_valid_cb, ldd );
+ }
+ else
+ {
+ g_signal_handlers_block_by_func( ldd->payAcctFromGAS, loan_pay_page_valid_cb, ldd );
+ gnc_account_sel_set_account( ldd->payAcctFromGAS, NULL, FALSE );
+ ldd->ld.repayOpts[ldd->currentIdx]->from = NULL;
+ g_signal_handlers_unblock_by_func( ldd->payAcctFromGAS, loan_pay_page_valid_cb, ldd );
+ }
+}
+
+
+static
+void
+loan_pay_spec_src_toggle_cb( GtkToggleButton *tb, gpointer user_data )
+{
+ gboolean newState;
+ LoanAssistantData *ldd = user_data;
+
+ newState = gtk_toggle_button_get_active( tb );
+ loan_pay_spec_src_setup( ldd, newState );
+}
+
+
+static
+void
+loan_pay_freq_toggle_cb( GtkToggleButton *tb, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ RepayOptData *rod;
+
+ g_assert( ldd->currentIdx >= 0 );
+ g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
+
+ rod = ldd->ld.repayOpts[ldd->currentIdx];
+
+ rod->FreqUniq = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb) );
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->payFreqAlign), rod->FreqUniq );
+
+ if ( rod->FreqUniq )
+ {
+ if ( rod->schedule == NULL )
+ {
+ Recurrence *r = g_new0(Recurrence, 1);
+
+ recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate, WEEKEND_ADJ_NONE);
+ rod->schedule = g_list_append(rod->schedule, r);
+ }
+ if ( rod->startDate == NULL )
+ {
+ rod->startDate = g_date_new();
+ *rod->startDate = *ldd->ld.startDate;
+ }
+ g_signal_handlers_block_by_func( ldd->payGncFreq, loan_pay_page_valid_cb, ldd );
+ gnc_frequency_setup_recurrence(ldd->payGncFreq, rod->schedule, rod->startDate);
+ g_signal_handlers_unblock_by_func( ldd->payGncFreq, loan_pay_page_valid_cb, ldd );
+ }
+ else
+ {
+ if (rod->schedule)
+ {
+ recurrenceListFree(&rod->schedule);
+ }
+ if ( rod->startDate )
+ {
+ g_date_free( rod->startDate );
+ rod->startDate = NULL;
+ }
+ }
+}
+
+
+static
+void
+loan_pay_next_button_cb( GtkButton *button, gpointer user_data )
+{
+ int i;
+ LoanAssistantData *ldd = user_data;
+
+ /* save current data */
+ if ( loan_pay_complete ( GTK_ASSISTANT(ldd->window), user_data ) != FALSE )
+ {
+ /* Go through opts list and select next enabled option. */
+ for ( i = ldd->currentIdx + 1;
+ (i < ldd->ld.repayOptCount)
+ && !ldd->ld.repayOpts[i]->enabled; i++ )
+ ;
+ if ( i < ldd->ld.repayOptCount )
+ {
+ ldd->currentIdx = i;
+ loan_pay_prep( GTK_ASSISTANT(ldd->window), user_data );
+ }
+ }
+}
+
+
+static
+void
+loan_pay_back_button_cb( GtkButton *button, gpointer user_data )
+{
+ int i;
+ LoanAssistantData *ldd = user_data;
+
+ /* save current data */
+ if ( loan_pay_complete ( GTK_ASSISTANT(ldd->window), user_data ) != FALSE)
+ {
+ /* go back through opts list and select next enabled options. */
+ for ( i = ldd->currentIdx - 1;
+ (i > -1) && !ldd->ld.repayOpts[i]->enabled;
+ i-- )
+ ;
+ if ( i >= 0 )
+ {
+ ldd->currentIdx = i;
+ loan_pay_prep( GTK_ASSISTANT(ldd->window), user_data );
+ }
+ }
+}
+
+
+static
+gboolean
+loan_pay_all_opt_valid ( GtkAssistant *assistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ int i;
+ gboolean all_valid;
+ all_valid = FALSE;
+
+ /* Go through all option pages checking for valid enabled pages */
+ for ( i = 0; (i < ldd->ld.repayOptCount); i++ )
+ {
+ if (ldd->ld.repayOpts[i]->enabled)
+ {
+ if (ldd->ld.repayOpts[i]->optValid)
+ all_valid = TRUE;
+ else
+ all_valid = FALSE;
+ }
+ }
+ return all_valid;
+}
+
+
+static
+gboolean
+loan_pay_complete( GtkAssistant *assistant, gpointer user_data )
+{
+ gchar *tmpStr;
+ LoanAssistantData *ldd = user_data;
+ RepayOptData *rod;
+
+ g_assert( ldd->currentIdx >= 0 );
+ g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
+ rod = ldd->ld.repayOpts[ ldd->currentIdx ];
+
+ tmpStr = gtk_editable_get_chars( GTK_EDITABLE(ldd->payTxnName),
+ 0, -1 );
+ if ( rod->txnMemo != NULL )
+ {
+ g_free( rod->txnMemo );
+ }
+ rod->txnMemo = tmpStr;
+ tmpStr = NULL;
+
+ tmpStr = gtk_editable_get_chars( GTK_EDITABLE(ldd->payAmtEntry),
+ 0, -1 );
+ rod->amount = (float)strtod( tmpStr, NULL );
+ g_free( tmpStr );
+
+ rod->specSrcAcctP =
+ gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(ldd->paySpecSrcAcct) );
+
+ /* Test for Valid From Account */
+ if ( rod->specSrcAcctP )
+ {
+ rod->from = gnc_account_sel_get_account( ldd->payAcctFromGAS );
+ if ( rod->from == NULL )
+ return FALSE;
+ }
+
+ /* Test for Valid To Account */
+ rod->to = gnc_account_sel_get_account( ldd->payAcctToGAS );
+ if ( rod->to == NULL )
+ return FALSE;
+
+ /* Set Page Valid */
+ rod->optValid = TRUE;
+
+ /* If Uniq Freq, then save to recurrence */
+ if ( rod->FreqUniq )
+ {
+ if ( rod->startDate == NULL )
+ {
+ rod->startDate = g_date_new();
+ }
+ recurrenceListFree(&rod->schedule);
+ gnc_frequency_save_to_recurrence(ldd->payGncFreq, &rod->schedule, rod->startDate);
+
+ if(! rod->schedule )
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/************************************************************************/
+
+static
+void
+loan_rev_prep( GtkAssistant *assistant, gpointer user_data )
+{
+ /* 3, here, does not include the Date column. */
+ const static int BASE_COLS = 3;
+ LoanAssistantData *ldd = user_data;
+ GtkListStore *store;
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+ GType *types;
+ int i;
+ int col=1;
+
+ /* Make sure we saved last Payment Option */
+ if (ldd->currentIdx != -1)
+ loan_pay_complete(assistant, ldd);
+
+ /* Cleanup old view */
+ if ( ldd->revView != NULL )
+ {
+ gtk_widget_destroy( GTK_WIDGET(ldd->revView) );
+ ldd->revView = NULL;
+ }
+
+ ldd->ld.revNumPmts = BASE_COLS;
+ /* Get the correct number of repayment columns. */
+ for ( i = 0; i < ldd->ld.repayOptCount; i++ )
+ {
+ ldd->ld.revRepayOptToColMap[i] = -1;
+ if ( ! ldd->ld.repayOpts[i]->enabled )
+ {
+ continue;
+ }
+ /* not '+1' = there is no date column to be accounted for in
+ * the mapping. */
+ ldd->ld.revRepayOptToColMap[i] = ldd->ld.revNumPmts;
+ ldd->ld.revNumPmts += 1;
+ }
+ /* '+1' for leading date col */
+ types = g_new( GType, ldd->ld.revNumPmts + 1 );
+ for ( i = 0; i < ldd->ld.revNumPmts + 1; i++ )
+ types[i] = G_TYPE_STRING;
+ store = gtk_list_store_newv(ldd->ld.revNumPmts + 1, types);
+ g_free(types);
+
+ ldd->revView = GTK_TREE_VIEW(
+ gtk_tree_view_new_with_model( GTK_TREE_MODEL(store) ));
+ g_object_unref(store);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Date"), renderer,
+ "text", LOAN_COL_DATE,
+ NULL);
+ gtk_tree_view_append_column(ldd->revView, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Payment"), renderer,
+ "text", LOAN_COL_PAYMENT,
+ NULL);
+ gtk_tree_view_append_column(ldd->revView, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Principal"), renderer,
+ "text", LOAN_COL_PRINCIPAL,
+ NULL);
+ gtk_tree_view_append_column(ldd->revView, column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Interest"), renderer,
+ "text", LOAN_COL_INTEREST,
+ NULL);
+ gtk_tree_view_append_column(ldd->revView, column);
+
+ /* move the appropriate names over into the title array */
+ {
+ for ( i = 0; i < ldd->ld.repayOptCount; i++ )
+ {
+ if ( ldd->ld.revRepayOptToColMap[i] == -1 )
+ {
+ continue;
+ }
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes
+ (ldd->ld.repayOpts[i]->name, renderer,
+ "text", LOAN_COL_INTEREST + col,
+ NULL);
+ gtk_tree_view_append_column(ldd->revView, column);
+ col++;
+ }
+ }
+
+ gtk_container_add( GTK_CONTAINER(ldd->revScrollWin),
+ GTK_WIDGET(ldd->revView) );
+ gtk_widget_show( GTK_WIDGET(ldd->revView) );
+
+ loan_rev_recalc_schedule( ldd );
+
+ {
+ GDate start, end;
+ g_date_clear( &start, 1 );
+ g_date_clear( &end, 1 );
+ loan_rev_get_dates( ldd, &start, &end );
+ loan_rev_update_view( ldd, &start, &end );
+ }
+}
+
+
+static
+void
+loan_rev_range_opt_changed_cb( GtkComboBox *combo, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ int opt;
+
+ opt = gtk_combo_box_get_active( ldd->revRangeOpt );
+ gtk_widget_set_sensitive( GTK_WIDGET(ldd->revDateFrame),
+ (opt == CUSTOM) );
+ {
+ GDate start, end;
+ g_date_clear( &start, 1 );
+ g_date_clear( &end, 1 );
+ loan_rev_get_dates( ldd, &start, &end );
+ loan_rev_update_view( ldd, &start, &end );
+ }
+}
+
+
+static
+void
+loan_rev_range_changed_cb( GNCDateEdit *gde, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ {
+ GDate start, end;
+ g_date_clear( &start, 1 );
+ g_date_clear( &end, 1 );
+ loan_rev_get_dates( ldd, &start, &end );
+ loan_rev_update_view( ldd, &start, &end );
+ }
+}
+
+
+static
+void
+loan_rev_get_loan_range( LoanAssistantData *ldd, GDate *start, GDate *end )
+{
+ int monthsTotal;
+ struct tm *endDateMath;
+
+ *start = *ldd->ld.startDate;
+
+ endDateMath = g_new0( struct tm, 1 );
+ g_date_to_struct_tm( ldd->ld.startDate, endDateMath );
+ monthsTotal = ( (ldd->ld.numPer - 1)
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) );
+ endDateMath->tm_mon += monthsTotal;
+ g_date_set_time_t( end, mktime( endDateMath ) );
+ g_free( endDateMath );
+}
+
+
+static
+void
+loan_rev_get_dates( LoanAssistantData *ldd, GDate *start, GDate *end )
+{
+ int range = gtk_combo_box_get_active( ldd->revRangeOpt );
+ switch ( range )
+ {
+ case CURRENT_YEAR:
+ g_date_set_time_t( start, time(NULL) );
+ g_date_set_dmy( start, 1, G_DATE_JANUARY, g_date_get_year( start ) );
+ g_date_set_dmy( end, 31, G_DATE_DECEMBER, g_date_get_year( start ) );
+ break;
+ case NOW_PLUS_ONE:
+ g_date_set_time_t( start, time(NULL) );
+ *end = *start;
+ g_date_add_years( end, 1 );
+ break;
+ case WHOLE_LOAN:
+ loan_rev_get_loan_range( ldd, start, end );
+ break;
+ case CUSTOM:
+ g_date_set_time_t( start,
+ gnc_date_edit_get_date( ldd->revStartDate ) );
+ g_date_set_time_t( end,
+ gnc_date_edit_get_date( ldd->revEndDate ) );
+ break;
+ default:
+ PERR( "Unknown review date range option %d", range );
+ break;
+ }
+
+}
+
+
+static
+void
+loan_rev_sched_list_free( gpointer data, gpointer user_data )
+{
+ RevRepaymentRow *rrr = (RevRepaymentRow*)data;
+ g_free( rrr->numCells );
+ g_free( rrr );
+}
+
+
+static
+void
+loan_rev_hash_to_list( gpointer key, gpointer val, gpointer user_data )
+{
+ GList **l = (GList**)user_data;
+ RevRepaymentRow *rrr = g_new0( RevRepaymentRow, 1 );
+ if ( !key || !val )
+ {
+ DEBUG( "%.8x, %.8x",
+ GPOINTER_TO_UINT(key),
+ GPOINTER_TO_UINT(val));
+ return;
+ }
+ rrr->date = *(GDate*)key;
+ rrr->numCells = (gnc_numeric*)val;
+ *l = g_list_append( *l, (gpointer)rrr );
+}
+
+
+static
+void
+loan_rev_hash_free_date_keys( gpointer key, gpointer val, gpointer user_data )
+{
+ g_free( (GDate*)key );
+}
+
+
+static
+void
+loan_rev_recalc_schedule( LoanAssistantData *ldd )
+{
+ GDate start, end;
+ gnc_numeric *rowNumData;
+ GHashTable *repayment_schedule;
+
+ g_date_clear( &start, 1 );
+ g_date_clear( &end, 1 );
+ loan_rev_get_loan_range( ldd, &start, &end );
+
+ /* The repayment_schedule is a hash of GDates to
+ * row-of-gnc_numeric[N] data, where N is the number of columns as
+ * determined by the _prep function, and stored in
+ * LoanData::revNumPmts. */
+ repayment_schedule = g_hash_table_new(gnc_gdate_hash, gnc_gdate_equal);
+
+ /* Do the master repayment */
+ {
+ GDate curDate, nextDate;
+ GString *pmtFormula, *ppmtFormula, *ipmtFormula;
+ int i;
+ GHashTable *ivar;
+
+ pmtFormula = g_string_sized_new( 64 );
+ loan_get_pmt_formula( ldd, pmtFormula );
+ ppmtFormula = g_string_sized_new( 64 );
+ loan_get_ppmt_formula( ldd, ppmtFormula );
+ ipmtFormula = g_string_sized_new( 64 );
+ loan_get_ipmt_formula( ldd, ipmtFormula );
+
+ ivar = g_hash_table_new( g_str_hash, g_str_equal );
+ g_date_clear( &curDate, 1 );
+ curDate = start;
+ g_date_subtract_days( &curDate, 1 );
+ g_date_clear(&nextDate, 1);
+ recurrenceListNextInstance(ldd->ld.repayment_schedule, &curDate, &nextDate);
+ for ( i = 1;
+ g_date_valid( &nextDate )
+ && g_date_compare( &nextDate, &end ) <= 0 ;
+ i++,
+ curDate = nextDate,
+ recurrenceListNextInstance(ldd->ld.repayment_schedule,
+ &curDate, &nextDate))
+ {
+ gnc_numeric ival;
+ gnc_numeric val;
+ char *eloc;
+ rowNumData =
+ (gnc_numeric*)g_hash_table_lookup( repayment_schedule,
+ &curDate );
+ if ( rowNumData == NULL)
+ {
+ int j;
+ GDate *dateKeyCopy = g_date_new();
+
+ *dateKeyCopy = curDate;
+ rowNumData = g_new0( gnc_numeric, ldd->ld.revNumPmts );
+ g_assert( rowNumData != NULL );
+ for ( j = 0; j < ldd->ld.revNumPmts; j++ )
+ {
+ rowNumData[j] = gnc_numeric_error( GNC_ERROR_ARG );
+ }
+ g_hash_table_insert( repayment_schedule,
+ (gpointer)dateKeyCopy,
+ (gpointer)rowNumData );
+ }
+
+ /* evaluate the expressions given the correct
+ * sequence number i */
+ ival = gnc_numeric_create( i, 1 );
+ g_hash_table_insert( ivar, "i", &ival );
+
+ if ( ! gnc_exp_parser_parse_separate_vars(
+ pmtFormula->str, &val, &eloc, ivar ) )
+ {
+ PERR( "pmt Parsing error at %s", eloc );
+ continue;
+ }
+ val = gnc_numeric_convert( val, 100, GNC_HOW_RND_ROUND_HALF_UP );
+ rowNumData[0] = val;
+
+ if ( ! gnc_exp_parser_parse_separate_vars(
+ ppmtFormula->str, &val, &eloc, ivar ) )
+ {
+ PERR( "ppmt Parsing error at %s", eloc );
+ continue;
+ }
+ val = gnc_numeric_convert( val, 100, GNC_HOW_RND_ROUND_HALF_UP );
+ rowNumData[1] = val;
+
+ if ( ! gnc_exp_parser_parse_separate_vars(
+ ipmtFormula->str, &val, &eloc, ivar ) )
+ {
+ PERR( "ipmt Parsing error at %s", eloc );
+ continue;
+ }
+ val = gnc_numeric_convert( val, 100, GNC_HOW_RND_ROUND_HALF_UP );
+ rowNumData[2] = val;
+ }
+
+ g_string_free( ipmtFormula, TRUE );
+ g_string_free( ppmtFormula, TRUE );
+ g_string_free( pmtFormula, TRUE );
+
+ g_hash_table_destroy( ivar );
+ }
+
+ /* Process any other enabled payments. */
+ {
+ int i;
+ GDate curDate, nextDate;
+ GList *schedule;
+
+ for ( i = 0; i < ldd->ld.repayOptCount; i++ )
+ {
+ if ( ! ldd->ld.repayOpts[i]->enabled )
+ continue;
+
+ schedule
+ = ( ldd->ld.repayOpts[i]->schedule != NULL
+ ? ldd->ld.repayOpts[i]->schedule
+ : ldd->ld.repayment_schedule );
+
+ g_date_clear( &curDate, 1 );
+ curDate = start;
+ g_date_subtract_days( &curDate, 1 );
+ g_date_clear(&nextDate, 1);
+ recurrenceListNextInstance(schedule, &curDate, &nextDate );
+ for ( ; g_date_valid( &nextDate )
+ && g_date_compare( &nextDate, &end ) <= 0;
+ curDate = nextDate,
+ recurrenceListNextInstance(
+ schedule, &curDate, &nextDate ) )
+ {
+ gint gncn_how =
+ GNC_HOW_DENOM_SIGFIGS(2)
+ | GNC_HOW_RND_ROUND_HALF_UP;
+ gnc_numeric val;
+ rowNumData = (gnc_numeric*)g_hash_table_lookup( repayment_schedule,
+ &curDate );
+ if ( rowNumData == NULL )
+ {
+ int j;
+ GDate *dateKeyCopy = g_date_new();
+
+ *dateKeyCopy = curDate;
+ rowNumData = g_new0( gnc_numeric, ldd->ld.revNumPmts );
+ g_assert( rowNumData != NULL );
+ for ( j = 0; j < ldd->ld.revNumPmts; j++ )
+ {
+ rowNumData[j] = gnc_numeric_error( GNC_ERROR_ARG );
+ }
+ g_hash_table_insert( repayment_schedule,
+ (gpointer)dateKeyCopy,
+ (gpointer)rowNumData );
+ }
+
+ val = double_to_gnc_numeric( (double)ldd->ld
+ .repayOpts[i]
+ ->amount,
+ 100, gncn_how );
+ rowNumData[ ldd->ld.revRepayOptToColMap[i] ]
+ = val;
+ }
+ }
+ }
+
+ /* Convert the GHashTable into a sorted GList in the LoanData */
+ {
+ if ( ldd->ld.revSchedule != NULL )
+ {
+ g_list_foreach( ldd->ld.revSchedule,
+ loan_rev_sched_list_free,
+ NULL );
+ g_list_free( ldd->ld.revSchedule );
+ ldd->ld.revSchedule = NULL;
+ }
+ g_hash_table_foreach( repayment_schedule, loan_rev_hash_to_list,
+ &ldd->ld.revSchedule );
+ g_hash_table_foreach( repayment_schedule, loan_rev_hash_free_date_keys,
+ NULL );
+ g_hash_table_destroy( repayment_schedule );
+ ldd->ld.revSchedule =
+ g_list_sort( ldd->ld.revSchedule, (GCompareFunc)g_date_compare );
+ }
+}
+
+
+static
+void
+loan_rev_update_view( LoanAssistantData *ldd, GDate *start, GDate *end )
+{
+ static gchar *NO_AMT_CELL_TEXT = " ";
+ GList *l;
+ GNCPrintAmountInfo pai;
+ GtkListStore *store;
+ GtkTreeIter iter;
+
+ pai = gnc_default_price_print_info();
+ pai.min_decimal_places = 2;
+
+ store = GTK_LIST_STORE(gtk_tree_view_get_model( ldd->revView ));
+
+ gtk_list_store_clear( store );
+
+ for ( l = ldd->ld.revSchedule; l != NULL; l = l->next )
+ {
+ int i;
+ gchar tmpBuf[50];
+ RevRepaymentRow *rrr = (RevRepaymentRow*)l->data;
+
+ if ( g_date_compare( &rrr->date, start ) < 0 )
+ continue;
+ if ( g_date_compare( &rrr->date, end ) > 0 )
+ continue; /* though we can probably return, too. */
+
+ gtk_list_store_append(store, &iter);
+
+ qof_print_gdate( tmpBuf, MAX_DATE_LENGTH, &rrr->date );
+ gtk_list_store_set( store, &iter, LOAN_COL_DATE, tmpBuf, -1 );
+
+ for ( i = 0; i < ldd->ld.revNumPmts; i++ )
+ {
+ int numPrinted;
+ if ( gnc_numeric_check( rrr->numCells[i] )
+ == GNC_ERROR_ARG )
+ {
+ /* '+1' for the date cell */
+ gtk_list_store_set( store, &iter,
+ i + 1, NO_AMT_CELL_TEXT,
+ -1);
+ continue;
+ }
+
+ numPrinted = xaccSPrintAmount( tmpBuf, rrr->numCells[i], pai );
+ g_assert( numPrinted < 50 );
+ /* '+1' for the date cell */
+ gtk_list_store_set( store, &iter,
+ i + 1, tmpBuf,
+ -1);
+ }
+
+ }
+}
+
+/************************* Worker functions *****************************/
+
+/* convert APR rate to simple rate based on formula r=q((1+i)^(1/q)-1) (r=interest rate, i=apr, q=compounding periods) */
+
+gfloat loan_apr_to_simple_formula (gfloat rate, gfloat compounding_periods)
+{
+ /* float percent_to_frac; - redundant */
+ gfloat simple_rate;
+ /* percent_to_frac= compounding_periods/100; - redundant */
+ simple_rate = compounding_periods * ((pow((1 + rate), (1 / compounding_periods))) - 1);
+ return (simple_rate);
+}
+
+
+static
+void
+loan_get_pmt_formula( LoanAssistantData *ldd, GString *gstr )
+{
+ gint rate_case;
+ gfloat pass_thru_rate;
+ g_assert( ldd != NULL );
+ g_assert( gstr != NULL );
+ rate_case = ldd->ld.rateType;
+ pass_thru_rate = ldd->ld.interestRate / 100;
+ switch (rate_case)
+ {
+ case GNC_IRATE_SIMPLE:
+ {
+ g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
+ pass_thru_rate, 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal) );
+ }
+ break;
+ case GNC_IRATE_APR_DAILY:
+ {
+ g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 365),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal) );
+ }
+ break;
+ case GNC_IRATE_APR_WEEKLY:
+ {
+ g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 52),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal) );
+ }
+ break;
+ case GNC_IRATE_APR_MONTHLY:
+ {
+ g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 12),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal) );
+ }
+ break;
+ case GNC_IRATE_APR_QUARTERLY:
+ {
+ g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 4),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal) );
+ }
+ break;
+ case GNC_IRATE_APR_ANNUALLY:
+ {
+ g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 1),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal) );
+ }
+ break;
+ default:
+ g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
+ (ldd->ld.interestRate / 100),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal) );
+ break;
+ }
+}
+
+
+static
+void
+loan_get_ppmt_formula( LoanAssistantData *ldd, GString *gstr )
+{
+ gint rate_case;
+ gfloat pass_thru_rate;
+ g_assert( ldd != NULL );
+ g_assert( gstr != NULL );
+ rate_case = ldd->ld.rateType;
+ pass_thru_rate = ldd->ld.interestRate / 100;
+ switch (rate_case)
+ {
+ case GNC_IRATE_SIMPLE:
+ {
+ g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ pass_thru_rate,
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ case GNC_IRATE_APR_DAILY:
+ {
+ g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 365),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ case GNC_IRATE_APR_WEEKLY:
+ {
+ g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 52),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ case GNC_IRATE_APR_MONTHLY:
+ {
+ g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 12),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ case GNC_IRATE_APR_QUARTERLY:
+ {
+ g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 4),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ case GNC_IRATE_APR_ANNUALLY:
+ {
+ g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 1),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ default:
+ g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ (ldd->ld.interestRate / 100),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ break;
+ }
+}
+
+
+static
+void
+loan_get_ipmt_formula( LoanAssistantData *ldd, GString *gstr )
+{
+ gint rate_case;
+ gfloat pass_thru_rate;
+ g_assert( ldd != NULL );
+ g_assert( gstr != NULL );
+ rate_case = ldd->ld.rateType;
+ pass_thru_rate = ldd->ld.interestRate / 100;
+ switch (rate_case)
+ {
+ case GNC_IRATE_SIMPLE:
+ {
+ g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ pass_thru_rate,
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ case GNC_IRATE_APR_DAILY:
+ {
+ g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 365),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ case GNC_IRATE_APR_WEEKLY:
+ {
+ g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 52),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ case GNC_IRATE_APR_MONTHLY:
+ {
+ g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 12),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ case GNC_IRATE_APR_QUARTERLY:
+ {
+ g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 4),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ case GNC_IRATE_APR_ANNUALLY:
+ {
+ g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ loan_apr_to_simple_formula(pass_thru_rate, 1),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ }
+ break;
+ default:
+ g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
+ (ldd->ld.interestRate / 100),
+ 12.0,
+ ( ldd->ld.numPer
+ * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
+ gnc_numeric_to_double(ldd->ld.principal));
+ break;
+ }
+}
+
+/******************* Scheduled Transaction Functions ********************/
+
+static int
+ld_calc_sx_instance_num(GDate *start_date, GList *schedule)
+{
+ int instance_count;
+ GDate next_date, today;
+
+ g_date_clear(&next_date, 1);
+ g_date_clear(&today, 1);
+ g_date_set_time_t(&today, time(NULL));
+
+ if (g_date_compare(start_date, &today) > 0)
+ return 0;
+
+ instance_count = -1;
+ do
+ {
+ instance_count++;
+ recurrenceListNextInstance(schedule, start_date, &next_date);
+ }
+ while (g_date_compare(&next_date, &today) < 0);
+
+ return instance_count;
+}
+
+
+static
+void
+loan_tcSX_free( gpointer data, gpointer user_data )
+{
+ toCreateSX *tcSX = (toCreateSX*)data;
+ g_free( tcSX->name );
+ if ( tcSX->mainTxn )
+ gnc_ttinfo_free( tcSX->mainTxn );
+ if ( tcSX->escrowTxn )
+ gnc_ttinfo_free( tcSX->escrowTxn );
+ g_free( tcSX );
+}
+
+
+/**
+ * Custom GCompareFunc to find the element of a GList of TTSplitInfo's which
+ * has the given [Account*] criteria.
+ * @return 0 if match, as per GCompareFunc in the g_list_find_custom context.
+ **/
+static
+gint
+loan_find_ttsplit_with_acct( gconstpointer elt,
+ gconstpointer crit )
+{
+ TTSplitInfo *ttsi = (TTSplitInfo*)elt;
+ return ( (gnc_ttsplitinfo_get_account( ttsi )
+ == (Account*)crit) ? 0 : 1 );
+}
+
+
+/**
+ * Enters into the books a Scheduled Transaction from the given toCreateSX.
+ **/
+static
+void
+loan_create_sx_from_tcSX( LoanAssistantData *ldd, toCreateSX *tcSX )
+{
+ SchedXaction *sx;
+ SchedXactions *sxes;
+ GList *ttxnList;
+
+ sx = xaccSchedXactionMalloc( gnc_get_current_book() );
+ xaccSchedXactionSetName( sx, tcSX->name );
+ gnc_sx_set_schedule(sx, tcSX->schedule);
+ xaccSchedXactionSetStartDate( sx, &tcSX->start );
+ xaccSchedXactionSetLastOccurDate( sx, &tcSX->last );
+ xaccSchedXactionSetEndDate( sx, &tcSX->end );
+ gnc_sx_set_instance_count( sx, tcSX->instNum );
+
+ ttxnList = NULL;
+ if ( tcSX->mainTxn )
+ ttxnList = g_list_append( ttxnList, tcSX->mainTxn );
+ if ( tcSX->escrowTxn )
+ ttxnList = g_list_append( ttxnList, tcSX->escrowTxn );
+
+ g_assert( ttxnList != NULL );
+
+ xaccSchedXactionSetTemplateTrans( sx, ttxnList,
+ gnc_get_current_book() );
+
+ sxes = gnc_book_get_schedxactions(gnc_get_current_book());
+ gnc_sxes_add_sx(sxes, sx);
+ g_list_free( ttxnList );
+ ttxnList = NULL;
+}
+
+
+/**
+ * Does the work to setup the given toCreateSX structure for a specific
+ * repayment. Note that if the RepayOptData doesn't specify a unique
+ * schedule, the paymentSX and the tcSX parameters will be the same.
+ **/
+static
+void
+ld_setup_repayment_sx( LoanAssistantData *ldd,
+ RepayOptData *rod,
+ toCreateSX *paymentSX,
+ toCreateSX *tcSX )
+{
+ /* In DoubleEntryAccounting-ease, this is what we're going to do,
+ * below...
+ *
+ * if ( rep->escrow ) {
+ * if ( rep->from ) {
+ * a: paymentSX.main.splits += split( rep->fromAcct, repAmt )
+ * b: paymentSX.main.split( ldd->ld.escrowAcct ).debCred += repAmt
+ * tcSX.escrow.split( rep->escrow ).debCred += repAmt
+ * c1: tcSX.escrow.splits += split( rep->toAcct, +repAmt )
+ * } else {
+ * d: paymentSX.main.split( ldd->ld.repFromAcct ).debcred += -repAmt
+ * b: paymentSX.main.split( ldd->ld.escrowAcct ).debCred += repAmt
+ * tcSX.escrow.splits += split( rep->escrow, -repAmt )
+ * c1: tcSX.escrow.splits += split( rep->toAcct, +repAmt )
+ * }
+ * } else {
+ * if ( rep->from ) {
+ * a: paymentSX.main.splits += split( rep->fromAcct, -repAmt )
+ * c2: paymentSX.main.splits += split( rep->toAcct, +repAmt )
+ * } else {
+ * d: paymentSX.main.split( ldd->ld.payFromAcct ).debcred += -repAmt
+ * c2: paymentSX.main.splits += split( rep->toAcct, +repAmt )
+ * }
+ * }
+ */
+
+ /* Now, we refactor the common operations from the above out...
+ *
+ * fromSplit = NULL;
+ * if ( rep->escrow ) {
+ * b: paymentSX.main.split( ldd->ld.escrowAcct ).debCred += repAmt
+ * c1: ( toTTI = tcSX.escrow )
+ * if ( rep->from ) {
+ * a1: (fromSplit = NULL) paymentSX.main.splits += split( rep->fromAcct, repAmt )
+ * b:
+ * tcSX.escrow.split( rep->escrow ).debCred += repAmt
+ * c1:
+ * } else {
+ * a2: (fromSplit = paymentSX.main.split( ldd->ld.repFromAcct )) .debcred += -repAmt
+ * b:
+ * tcSX.escrow.splits += split( rep->escrow, -repAmt )
+ * c1:
+ * }
+ * } else {
+ * c2: ( toTTI = paymentSX.main )
+ * if ( rep->from ) {
+ * a1: (fromSplit = NULL) paymentSX.main.splits += split( rep->fromAcct, -repAmt )
+ * c2:
+ * } else {
+ * a2: (fromSplit = paymentSX.main.split( ldd->ld.payFromAcct )).debcred += -repAmt
+ * c2:
+ * }
+ * }
+ * if ( fromSplit ) {
+ * fromSplit.debCred += (-repAmt);
+ * } else {
+ * fromSplit = split( rep->fromAcct, -repAmt )
+ * paymentSX.main.splits += fromSplit
+ * }
+ * toTTI.splits += split( rep->toAcct, +repAmt );
+ */
+
+ /** Now, the actual implementation... */
+
+ GString *gstr;
+ GList *elt;
+ TTSplitInfo *fromSplit = NULL;
+ TTSplitInfo *ttsi;
+ TTInfo *toTxn = NULL;
+ GNCPrintAmountInfo pricePAI = gnc_default_price_print_info();
+#define AMTBUF_LEN 64
+ gchar amtBuf[AMTBUF_LEN];
+ gint GNCN_HOW = (GNC_HOW_DENOM_SIGFIGS(2) | GNC_HOW_RND_ROUND_HALF_UP);
+
+ /* We're going to use this a lot, below, so just create it once. */
+ xaccSPrintAmount( amtBuf,
+ double_to_gnc_numeric( rod->amount, 100,
+ GNCN_HOW ),
+ pricePAI );
+
+ if ( rod->throughEscrowP && ldd->ld.escrowAcct )
+ {
+ toTxn = tcSX->escrowTxn;
+
+ /* Add the repayment amount into the string of the existing
+ * ttsplit. */
+ {
+ elt = g_list_find_custom(
+ gnc_ttinfo_get_template_splits( paymentSX->mainTxn ),
+ ldd->ld.escrowAcct,
+ loan_find_ttsplit_with_acct );
+ g_assert( elt );
+ ttsi = (TTSplitInfo*)elt->data;
+ g_assert( ttsi );
+ gstr = g_string_new( gnc_ttsplitinfo_get_debit_formula( ttsi ) );
+ g_string_append_printf( gstr, " + %s", amtBuf );
+ gnc_ttsplitinfo_set_debit_formula( ttsi, gstr->str );
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+ ttsi = NULL;
+ }
+
+ if ( rod->from != NULL )
+ {
+ gchar *str;
+
+ fromSplit = NULL;
+
+ /* tcSX.escrow.split( rep->escrow ).debCred += repAmt */
+ elt = g_list_find_custom(
+ gnc_ttinfo_get_template_splits( tcSX->escrowTxn ),
+ ldd->ld.escrowAcct,
+ loan_find_ttsplit_with_acct );
+ ttsi = NULL;
+ if ( elt )
+ {
+ ttsi = (TTSplitInfo*)elt->data;
+ }
+ if ( !ttsi )
+ {
+ /* create split */
+ ttsi = gnc_ttsplitinfo_malloc();
+ gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
+ gnc_ttsplitinfo_set_account( ttsi, ldd->ld.escrowAcct );
+ gnc_ttinfo_append_template_split( tcSX->escrowTxn, ttsi );
+ }
+ if ( (str = (gchar*)gnc_ttsplitinfo_get_credit_formula( ttsi ))
+ == NULL )
+ {
+ gstr = g_string_sized_new( 16 );
+ }
+ else
+ {
+ /* If we did get a split/didn't have to
+ * create a split, then we need to add our
+ * amount in rather than replace. */
+ gstr = g_string_new( str );
+ g_string_append_printf( gstr, " + " );
+ }
+ g_string_append_printf( gstr, "%s", amtBuf );
+ gnc_ttsplitinfo_set_credit_formula( ttsi, gstr->str );
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+ ttsi = NULL;
+ }
+ else
+ {
+ /* (fromSplit = paymentSX.main.split( ldd->ld.repFromAcct )) */
+ elt = g_list_find_custom(
+ gnc_ttinfo_get_template_splits( paymentSX->mainTxn ),
+ ldd->ld.repFromAcct,
+ loan_find_ttsplit_with_acct );
+ g_assert( elt );
+ fromSplit = (TTSplitInfo*)elt->data;
+
+ /* tcSX.escrow.splits += split( rep->escrow, -repAmt ) */
+ ttsi = gnc_ttsplitinfo_malloc();
+ gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
+ gnc_ttsplitinfo_set_account( ttsi, ldd->ld.escrowAcct );
+ gnc_ttsplitinfo_set_credit_formula( ttsi, amtBuf );
+ gnc_ttinfo_append_template_split( tcSX->escrowTxn, ttsi );
+ ttsi = NULL;
+ }
+ }
+ else
+ {
+ toTxn = tcSX->mainTxn;
+
+ if ( rod->from != NULL )
+ {
+ fromSplit = NULL;
+ }
+ else
+ {
+ /* (fromSplit = paymentSX.main.split( ldd->ld.repFromAcct )) */
+ elt = g_list_find_custom(
+ gnc_ttinfo_get_template_splits( tcSX->mainTxn ),
+ ldd->ld.repFromAcct,
+ loan_find_ttsplit_with_acct );
+ fromSplit = NULL;
+ if ( elt )
+ {
+ /* This is conditionally true in the case of
+ * a repayment on it's own schedule. */
+ fromSplit = (TTSplitInfo*)elt->data;
+ }
+ }
+ }
+
+ if ( fromSplit != NULL )
+ {
+ /* Update the existing from-split. */
+ gstr = g_string_new( gnc_ttsplitinfo_get_credit_formula( fromSplit ) );
+ g_string_append_printf( gstr, " + %s", amtBuf );
+ gnc_ttsplitinfo_set_credit_formula( fromSplit, gstr->str );
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+
+ }
+ else
+ {
+ TTInfo *tti;
+ /* Create a new from-split. */
+ ttsi = gnc_ttsplitinfo_malloc();
+ gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
+ if ( rod->from )
+ {
+ gnc_ttsplitinfo_set_account( ttsi, rod->from );
+ }
+ else
+ {
+ gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repFromAcct );
+ }
+ gnc_ttsplitinfo_set_credit_formula( ttsi, amtBuf );
+ tti = tcSX->mainTxn;
+ if ( rod->throughEscrowP )
+ {
+ tti = paymentSX->mainTxn;
+ }
+ gnc_ttinfo_append_template_split( tti, ttsi );
+ ttsi = NULL;
+ tti = NULL;
+ }
+
+ /* Add to-account split. */
+ {
+ ttsi = gnc_ttsplitinfo_malloc();
+ gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
+ gnc_ttsplitinfo_set_account( ttsi, rod->to );
+ gnc_ttsplitinfo_set_debit_formula( ttsi, amtBuf );
+ gnc_ttinfo_append_template_split( toTxn, ttsi );
+ ttsi = NULL;
+ }
+}
+
+
+/**
+ * Actually does the heavy-lifting of creating the SXes from the
+ * LoanAssistantData.
+ *
+ * Rules:
+ * - There is at least one SX created, with at least one txn, for the loan
+ * payment itself.
+ * - A new SX is created for each repayment with a different frequency.
+ * - Non-unique repayment From-accounts cause a "summed (src-)split", unique
+ * repayment From-accounts cause new (src-)splits.
+ * - Each repayment causes a new (dst-)split [the To-account].
+ * - Escrow-diverted repayments cause new Txns w/in their
+ * SX. [Assets->Escrow, Escrow->(Expense|Liability)]
+ **/
+static
+void
+loan_create_sxes( LoanAssistantData *ldd )
+{
+ /* The main loan-payment SX.*/
+ toCreateSX *paymentSX = NULL;
+ /* A GList of any other repayment SXes with different schedule. */
+ GList *repaySXes = NULL;
+ /* The currently-being-referenced toCreateSX. */
+ toCreateSX *tcSX;
+ int i;
+ TTInfo *ttxn;
+ TTSplitInfo *ttsi;
+ GString *gstr;
+
+ paymentSX = g_new0( toCreateSX, 1 );
+ paymentSX->name = g_strdup(ldd->ld.repMemo);
+ paymentSX->start = *ldd->ld.startDate;
+ paymentSX->last = *ldd->ld.repStartDate;
+ g_date_subtract_months( &paymentSX->last, 1 );
+ {
+ paymentSX->end = *ldd->ld.repStartDate;
+ g_date_add_months( &paymentSX->end, ldd->ld.numMonRemain - 1);
+ }
+
+ paymentSX->schedule = ldd->ld.repayment_schedule;
+ /* Figure out the correct current instance-count for the txns in the
+ * SX. */
+ paymentSX->instNum =
+ (ldd->ld.numPer * ( ldd->ld.perSize == GNC_YEARS ? 12 : 1 ))
+ - ldd->ld.numMonRemain + 1;
+
+ paymentSX->mainTxn = gnc_ttinfo_malloc();
+ gnc_ttinfo_set_currency( paymentSX->mainTxn,
+ gnc_default_currency() );
+
+ {
+ GString *payMainTxnDesc = g_string_sized_new( 32 );
+ g_string_printf( payMainTxnDesc,
+ "%s - %s",
+ ldd->ld.repMemo,
+ ( ldd->ld.escrowAcct == NULL
+ ? _("Payment")
+ : _("Escrow Payment") )
+ );
+
+ gnc_ttinfo_set_description( paymentSX->mainTxn,
+ payMainTxnDesc->str );
+ g_string_free( payMainTxnDesc, TRUE );
+ }
+
+ /* Create the basic txns and splits...
+ *
+ * ttxn <- mainTxn
+ * srcAcct <- assets
+ * if ( escrow ) {
+ * realSrcAcct <- srcAcct
+ * srcAcct <- escrow;
+ * ttxn <- escrowTxn
+ * main.splits += split( realSrcAcct, -pmt )
+ * main.splits += split( escrow, pmt )
+ * }
+ * ttxn.splits += split( escrow, -pmt)
+ * ttxn.splits += split( liability, ppmt )
+ * ttxn.splits += split( expenses:interest, ipmt ) */
+
+ {
+ Account *srcAcct;
+
+ ttxn = paymentSX->mainTxn;
+ srcAcct = ldd->ld.repFromAcct;
+ if ( ldd->ld.escrowAcct != NULL )
+ {
+ Account *realSrcAcct = srcAcct;
+ srcAcct = ldd->ld.escrowAcct;
+ gstr = g_string_sized_new( 32 );
+ loan_get_pmt_formula( ldd, gstr );
+ /* ttxn.splits += split( realSrcAcct, -pmt ); */
+ {
+ ttsi = gnc_ttsplitinfo_malloc();
+ gnc_ttsplitinfo_set_memo( ttsi, ldd->ld.repMemo );
+ gnc_ttsplitinfo_set_account( ttsi, realSrcAcct );
+ gnc_ttsplitinfo_set_credit_formula( ttsi, gstr->str );
+ gnc_ttinfo_append_template_split( ttxn, ttsi );
+ ttsi = NULL;
+ }
+ /* ttxn.splits += split( escrowAcct, +pmt ); */
+ {
+ ttsi = gnc_ttsplitinfo_malloc();
+ gnc_ttsplitinfo_set_memo( ttsi, ldd->ld.repMemo );
+ gnc_ttsplitinfo_set_account( ttsi, ldd->ld.escrowAcct );
+ gnc_ttsplitinfo_set_debit_formula( ttsi, gstr->str );
+ gnc_ttinfo_append_template_split( ttxn, ttsi );
+ ttsi = NULL;
+ }
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+ paymentSX->escrowTxn = gnc_ttinfo_malloc();
+ gnc_ttinfo_set_currency( paymentSX->escrowTxn,
+ gnc_default_currency() );
+
+ {
+ GString *escrowTxnDesc;
+ escrowTxnDesc = g_string_new( ldd->ld.repMemo );
+ g_string_append_printf( escrowTxnDesc, " - %s", _("Payment") );
+ gnc_ttinfo_set_description( paymentSX->escrowTxn,
+ escrowTxnDesc->str );
+ g_string_free( escrowTxnDesc, TRUE );
+ }
+ ttxn = paymentSX->escrowTxn;
+ }
+ /* ttxn.splits += split( srcAcct, -pmt ); */
+ {
+ ttsi = gnc_ttsplitinfo_malloc();
+ {
+ gstr = g_string_new( ldd->ld.repMemo );
+ g_string_append_printf( gstr, " - %s",
+ _("Payment") );
+ gnc_ttsplitinfo_set_memo( ttsi, gstr->str );
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+ }
+ gnc_ttsplitinfo_set_account( ttsi, srcAcct );
+ gstr = g_string_sized_new( 32 );
+ loan_get_pmt_formula( ldd, gstr );
+ gnc_ttsplitinfo_set_credit_formula( ttsi, gstr->str );
+ gnc_ttinfo_append_template_split( ttxn, ttsi );
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+ ttsi = NULL;
+ }
+ /* ttxn.splits += split( ldd->ld.repPriAcct, +ppmt ); */
+ {
+ ttsi = gnc_ttsplitinfo_malloc();
+ {
+ gstr = g_string_new( ldd->ld.repMemo );
+ g_string_append_printf( gstr, " - %s",
+ _("Principal") );
+ gnc_ttsplitinfo_set_memo( ttsi, gstr->str );
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+ }
+ gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repPriAcct );
+ gstr = g_string_sized_new( 32 );
+ loan_get_ppmt_formula( ldd, gstr );
+ gnc_ttsplitinfo_set_debit_formula( ttsi, gstr->str );
+ gnc_ttinfo_append_template_split( ttxn, ttsi );
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+ ttsi = NULL;
+ }
+ /* ttxn.splits += split( ldd->ld.repIntAcct, +ipmt ); */
+ {
+ ttsi = gnc_ttsplitinfo_malloc();
+ {
+ gstr = g_string_new( ldd->ld.repMemo );
+ g_string_append_printf( gstr, " - %s",
+ _("Interest") );
+ gnc_ttsplitinfo_set_memo( ttsi, gstr->str );
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+ }
+ gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repIntAcct );
+ gstr = g_string_sized_new( 32 );
+ loan_get_ipmt_formula( ldd, gstr );
+ gnc_ttsplitinfo_set_debit_formula( ttsi, gstr->str );
+ gnc_ttinfo_append_template_split( ttxn, ttsi );
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+ ttsi = NULL;
+ }
+ }
+ for ( i = 0; i < ldd->ld.repayOptCount; i++ )
+ {
+ RepayOptData *rod = ldd->ld.repayOpts[i];
+ if ( ! rod->enabled )
+ continue;
+
+ tcSX = paymentSX;
+ if ( rod->schedule != NULL )
+ {
+ tcSX = g_new0( toCreateSX, 1 );
+ gstr = g_string_new( ldd->ld.repMemo );
+ g_string_append_printf( gstr, " - %s",
+ rod->name );
+ tcSX->name = g_strdup(gstr->str);
+ tcSX->start = *ldd->ld.startDate;
+ tcSX->last = *ldd->ld.repStartDate;
+ {
+ tcSX->end = tcSX->last;
+ g_date_add_months( &tcSX->end, ldd->ld.numMonRemain );
+ }
+ tcSX->schedule = rod->schedule;
+ /* So it won't get destroyed when the close the
+ * Druid. */
+ tcSX->instNum =
+ ld_calc_sx_instance_num(&tcSX->start, rod->schedule);
+ rod->schedule = NULL;
+ tcSX->mainTxn = gnc_ttinfo_malloc();
+ gnc_ttinfo_set_currency( tcSX->mainTxn,
+ gnc_default_currency() );
+ gnc_ttinfo_set_description( tcSX->mainTxn,
+ gstr->str );
+ tcSX->escrowTxn = gnc_ttinfo_malloc();
+ gnc_ttinfo_set_currency( tcSX->escrowTxn,
+ gnc_default_currency() );
+ gnc_ttinfo_set_description( tcSX->escrowTxn,
+ gstr->str );
+
+ g_string_free( gstr, TRUE );
+ gstr = NULL;
+
+ repaySXes = g_list_append( repaySXes, tcSX );
+
+ }
+
+ /* repayment */
+ ld_setup_repayment_sx( ldd, rod, paymentSX, tcSX );
+ }
+ /* Create the SXes */
+ {
+ GList *l;
+
+ loan_create_sx_from_tcSX( ldd, paymentSX );
+
+ for ( l = repaySXes; l; l = l->next )
+ {
+ loan_create_sx_from_tcSX( ldd, (toCreateSX*)l->data );
+ }
+ }
+ /* Clean up. */
+ loan_tcSX_free( paymentSX, NULL );
+ g_list_foreach( repaySXes, loan_tcSX_free, NULL );
+ g_list_free( repaySXes );
+}
+
+/************************ Assistant Functions ***************************/
+
+void
+loan_assistant_finish ( GtkAssistant *gtkassistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ loan_create_sxes( ldd );
+
+}
+
+
+void
+loan_assistant_cancel( GtkAssistant *gtkassistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ gnc_close_gui_component_by_data( DIALOG_LOAN_ASSISTANT_CM_CLASS,ldd );
+}
+
+
+void
+loan_assistant_close( GtkAssistant *gtkassistant, gpointer user_data )
+{
+ LoanAssistantData *ldd = user_data;
+ gnc_close_gui_component_by_data( DIALOG_LOAN_ASSISTANT_CM_CLASS,ldd );
+}
+
+
+void
+loan_assistant_prepare (GtkAssistant *assistant, GtkWidget *page,
+ gpointer user_data)
+{
+ LoanAssistantData *ldd = user_data;
+ gint currentpage = gtk_assistant_get_current_page(assistant);
+
+ switch (currentpage)
+ {
+ case 1:
+ /* Current page is info page */
+ loan_info_prep (assistant, user_data);
+ break;
+ case 2:
+ /* Current page is Options page */
+ loan_opt_prep (assistant, user_data);
+ break;
+ case 3:
+ /* Current page is Repayments page */
+ loan_rep_prep (assistant, user_data);
+ break;
+ case 4:
+ /* Current page is Repayments Options page */
+ loan_pay_prep (assistant, user_data);
+ break;
+ case 5:
+ /* Current page is Review page */
+ loan_rev_prep (assistant, user_data);
+ break;
+ }
+}
+
+
+/********************************************************************\
+ * gnc_ui_sx_loan_assistant_create *
+ * opens up a window to start the loan Assistant *
+ * *
+\********************************************************************/
+void
+gnc_ui_sx_loan_assistant_create (void)
+{
+ LoanAssistantData *ldd;
+ gint component_id;
+
+ ldd = g_new0 (LoanAssistantData, 1);
+
+ gnc_loan_assistant_create (ldd);
+
+ component_id = gnc_register_gui_component (DIALOG_LOAN_ASSISTANT_CM_CLASS,
+ NULL, loan_assistant_close_handler,
+ ldd);
+
+ gnc_gui_component_watch_entity_type (component_id,
+ GNC_ID_ACCOUNT,
+ QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
+
+ gtk_widget_show_all (ldd->window);
+
+ gnc_window_adjust_for_screen (GTK_WINDOW(ldd->window));
+}
+
Copied: gnucash/trunk/src/gnome/assistant-loan.h (from rev 21117, gnucash/trunk/src/gnome/druid-loan.h)
===================================================================
--- gnucash/trunk/src/gnome/assistant-loan.h (rev 0)
+++ gnucash/trunk/src/gnome/assistant-loan.h 2011-08-07 09:14:36 UTC (rev 21118)
@@ -0,0 +1,25 @@
+/********************************************************************\
+ * assistant-loan.h : An Assistant for setting up loan-repayment *
+ * scheduled transactions. *
+ * Copyright (C) 2002 Joshua Sled <jsled at asynchronous.org> *
+ * Copyright (C) 2011 Robert Fewell *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact: *
+ * *
+ * Free Software Foundation Voice: +1-617-542-5942 *
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
+ * Boston, MA 02110-1301, USA gnu at gnu.org *
+\********************************************************************/
+
+void gnc_ui_sx_loan_assistant_create(void);
Deleted: gnucash/trunk/src/gnome/druid-loan.c
===================================================================
--- gnucash/trunk/src/gnome/druid-loan.c 2011-08-07 09:14:22 UTC (rev 21117)
+++ gnucash/trunk/src/gnome/druid-loan.c 2011-08-07 09:14:36 UTC (rev 21118)
@@ -1,3207 +0,0 @@
-/********************************************************************\
- * druid-loan.c : A Gnome Druid for setting up loan-repayment *
- * scheduled transactions. *
- * Copyright (C) 2002,2007 Joshua Sled <jsled at asynchronous.org> *
- * Copyright (C) 2006 David Hampton <hampton at employees.org> *
- * *
- * This program is free software; you can redistribute it and/or *
- * modify it under the terms of the GNU General Public License as *
- * published by the Free Software Foundation; either version 2 of *
- * the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact: *
- * *
- * Free Software Foundation Voice: +1-617-542-5942 *
- * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
- * Boston, MA 02110-1301, USA gnu at gnu.org *
-\********************************************************************/
-
-#include "config.h"
-
-#include <gnome.h>
-#include <glib/gi18n.h>
-#include <string.h>
-#include <glade/glade.h>
-#include <math.h>
-
-#include "druid-loan.h"
-
-#include "SchedXaction.h"
-#include "SX-book.h"
-#include "SX-ttinfo.h"
-#include "druid-utils.h"
-#include "gnc-amount-edit.h"
-#include "gnc-account-sel.h"
-#include "gnc-date.h"
-#include "gnc-exp-parser.h"
-#include "gnc-component-manager.h"
-#include "dialog-utils.h"
-#include "Account.h"
-#include "gnc-ui.h"
-#include "gnc-gdate-utils.h"
-#include "gnc-gui-query.h"
-#include "gnc-ui-util.h"
-#include "gnc-frequency.h"
-#include "gnc-engine.h"
-
-#define DIALOG_LOAN_DRUID_CM_CLASS "druid-loan-setup"
-
-#define SX_GLADE_FILE "sched-xact.glade"
-#define LOAN_DRUID_WIN_GLADE_NAME "loan_druid_win"
-#define LOAN_DRUID_GLADE_NAME "loan_druid"
-
-#define PG_INTRO "loan_intro_pg"
-#define PG_INFO "loan_info_pg"
-# define PARAM_TABLE "param_table"
-# define ORIG_PRINC_ENTRY "orig_princ_ent"
-# define IRATE_SPIN "irate_spin"
-# define IRATE_TYPE_COMBOBOX "irate_type_combobox"
-# define TYPE_COMBOBOX "type_combobox"
-# define VAR_CONTAINER "type_freq_frame"
-# define LENGTH_SPIN "len_spin"
-# define LENGTH_OPT "len_opt"
-# define REMAIN_SPIN "rem_spin"
-#define PG_OPTS "loan_opts_pg"
-# define OPT_CONTAINER "opt_vbox"
-# define OPT_ESCROW "opt_escrow_cb"
-# define OPT_ESCROW_CONTAINER "opt_escrow_hbox"
-#define PG_REPAYMENT "repayment_pg"
-# define TXN_NAME "txn_title"
-# define REPAY_TABLE "repay_table"
-# define AMOUNT_ENTRY "amount_ent"
-# define FREQ_CONTAINER "freq_frame"
-#define PG_PAYMENT "payment_pg"
-# define PAY_TXN_TITLE "pay_txn_title"
-# define PAY_AMT_ENTRY "pay_amt_ent"
-# define PAY_TABLE "pay_table"
-# define PAY_USE_ESCROW "pay_use_escrow"
-# define PAY_SPEC_SRC_ACCT "pay_specify_source"
-# define PAY_FROM_ACCT_LBL "pay_from_account_label"
-# define PAY_ESC_TO_LBL "pay_escrow_to_label"
-# define PAY_ESC_FROM_LBL "pay_escrow_from_label"
-# define PAY_TXN_PART_RB "pay_txn_part_rb"
-# define PAY_UNIQ_FREQ_RB "pay_uniq_freq_rb"
-# define PAY_FREQ_CONTAINER "pay_freq_align"
-#define PG_REVIEW "review_pg"
-# define REV_SCROLLWIN "rev_scrollwin"
-# define REV_DATE_FRAME "rev_date_frame"
-# define REV_RANGE_OPT "rev_range_opt"
-# define REV_RANGE_TABLE "rev_date_range_table"
-#define PG_COMMIT "commit_pg"
-
-#define OPT_VBOX_SPACING 2
-
-enum loan_cols
-{
- LOAN_COL_DATE = 0,
- LOAN_COL_PAYMENT,
- LOAN_COL_PRINCIPAL,
- LOAN_COL_INTEREST,
- NUM_LOAN_COLS
-};
-
-typedef enum
-{
- CURRENT_YEAR,
- NOW_PLUS_ONE,
- WHOLE_LOAN,
- CUSTOM
-} REV_RANGE_OPTS;
-
-static QofLogModule log_module = GNC_MOD_SX;
-
-/**
- * TODO/fixme:
- * . param account selection should fill in orig/cur principal amounts from
- * the books.
- * . initialize type freq to monthly.
- * . if LoanType <- !GNC_FIXED
- * . Frequency <- sensitive
- **/
-
-struct LoanDruidData_;
-
-/**
- * The data relating to a single "repayment option" -- a potential
- * [sub-]transaction in the repayment.
- **/
-typedef struct RepayOptData_
-{
- gboolean enabled;
- char *name; /* { "insurance", "pmi", "taxes", ... } */
- char *txnMemo;
- float amount;
- gboolean throughEscrowP;
- gboolean specSrcAcctP;
- Account *to;
- Account *from; /* If NULL { If throughEscrowP, then through escrowAcct };
- * else: undefined. */
- GList *schedule;
- /* If NULL, part of repayment; otherwise: defined
- * here. */
- GDate *startDate;
-} RepayOptData;
-
-/**
- * The default repayment options data.
- **/
-typedef struct RepayOptDataDefault_
-{
- char *name;
- char *defaultTxnMemo;
- gboolean escrowDefault;
- gboolean specSrcAcctDefault;
-} RepayOptDataDefault;
-
-static RepayOptDataDefault REPAY_DEFAULTS[] =
-{
- /* { name, default txn memo, throughEscrowP, specSrcAcctP } */
- { N_("Taxes"), N_("Tax Payment"), TRUE, FALSE },
- { N_("Insurance"), N_("Insurance Payment"), TRUE, FALSE },
- /* Translators: PMI stands for Private Mortgage Insurance. */
- { N_("PMI"), N_("PMI Payment"), TRUE, FALSE },
- { N_("Other Expense"), N_("Miscellaneous Payment"), FALSE, FALSE },
- { NULL }
-};
-
-/**
- * The UI-side storage of the repayment options.
- **/
-typedef struct RepayOptUI_
-{
- /* must be stated this way [instead of 'LoanDruidData*'] because of
- * forward decl. */
- struct LoanDruidData_ *ldd;
- GtkCheckButton *optCb;
- GtkCheckButton *escrowCb;
- RepayOptData *optData;
-} RepayOptUIData;
-
-typedef enum
-{
- GNC_FIXED = 0,
- GNC_VARIABLE,
- GNC_VARIABLE_3_1 = GNC_VARIABLE,
- GNC_VARIABLE_5_1,
- GNC_VARIABLE_7_1,
- GNC_VARIABLE_10_1,
- /* ... FIXME */
-} LoanType;
-
-typedef enum
-{
- GNC_MONTHS = 0,
- GNC_YEARS
-} PeriodSize;
-/*type of interest rate entered*/
-typedef enum
-{
- GNC_IRATE_SIMPLE,
- GNC_IRATE_APR_DAILY,
- GNC_IRATE_APR_WEEKLY,
- GNC_IRATE_APR_MONTHLY,
- GNC_IRATE_APR_QUARTERLY,
- GNC_IRATE_APR_ANNUALLY
-} IRateType;
-
-/**
- * A transient struct used to collate the GDate and the gnc_numeric row-data
- * for the repayment review schedule. numCells is an array of gnc_numerics,
- * with a length of the LoanData.revNumPmts.
- **/
-typedef struct rev_repayment_row
-{
- GDate date;
- gnc_numeric *numCells;
-} RevRepaymentRow;
-
-/**
- * Data about a loan repayment.
- **/
-typedef struct LoanData_
-{
- Account *primaryAcct;
- gnc_numeric principal;
- float interestRate;
- IRateType rateType;
- LoanType type;
- GList *loan_schedule;
- GDate *startDate;
- GDate *varStartDate;
- int numPer;
- PeriodSize perSize;
- int numMonRemain;
-
- char *repMemo;
- char *repAmount;
- Account *repFromAcct;
- Account *repPriAcct;
- Account *repIntAcct;
- Account *escrowAcct;
- GList *repayment_schedule;
- GDate *repStartDate;
-
- int repayOptCount;
- RepayOptData **repayOpts;
-
- /* Data concerning the review of repayments. */
- int revNumPmts;
- int revRepayOptToColMap[ (sizeof(REPAY_DEFAULTS)
- / sizeof(RepayOptDataDefault))
- - 1 ];
- GList *revSchedule;
-} LoanData;
-
-/**
- * The UI-side storage of the loan druid data.
- **/
-typedef struct LoanDruidData_
-{
- GladeXML *gxml;
- GtkWidget *dialog;
- GnomeDruid *druid;
-
- LoanData ld;
- /* The UI-side storage of repayment data; this is 1:1 with the array
- * in LoanData */
- RepayOptUIData **repayOptsUI;
-
- /* Current index of the payment opt for multiplexing the 'payment'
- * page. */
- int currentIdx;
-
- /* widgets */
- /* prm = params */
- GtkTable *prmTable;
- GNCAccountSel *prmAccountGAS;
- GNCAmountEdit *prmOrigPrincGAE;
- GtkSpinButton *prmIrateSpin;
- GtkComboBox *prmType;
- GtkFrame *prmVarFrame;
- GncFrequency *prmVarGncFreq;
- GNCDateEdit *prmStartDateGDE;
- GtkSpinButton *prmLengthSpin;
- GtkComboBox *prmLengthType;
- GtkSpinButton *prmRemainSpin;
- GtkComboBox *prmIrateType;
-
- /* opt = options */
- GtkVBox *optVBox;
- GtkCheckButton *optEscrowCb;
- GtkHBox *optEscrowHBox;
- GNCAccountSel *optEscrowGAS;
-
- /* rep = repayment */
- GtkEntry *repTxnName;
- GtkTable *repTable;
- GtkEntry *repAmtEntry;
- GNCAccountSel *repAssetsFromGAS;
- GNCAccountSel *repPrincToGAS;
- GNCAccountSel *repIntToGAS;
- GtkFrame *repFreqFrame;
- GncFrequency *repGncFreq;
-
- /* pay = payment[s] */
- GtkEntry *payTxnName;
- GtkEntry *payAmtEntry;
- GNCAccountSel *payAcctFromGAS;
- GNCAccountSel *payAcctEscToGAS;
- GNCAccountSel *payAcctEscFromGAS;
- GNCAccountSel *payAcctToGAS;
- GtkTable *payTable;
- GtkCheckButton *payUseEscrow;
- GtkCheckButton *paySpecSrcAcct;
- GtkLabel *payAcctFromLabel;
- GtkLabel *payEscToLabel;
- GtkLabel *payEscFromLabel;
- GtkRadioButton *payTxnFreqPartRb;
- GtkRadioButton *payTxnFreqUniqRb;
- GtkAlignment *payFreqAlign;
- GncFrequency *payGncFreq;
-
- /* rev = review */
- GtkComboBox *revRangeOpt;
- GtkFrame *revDateFrame;
- GtkTable *revTable;
- GNCDateEdit *revStartDate;
- GNCDateEdit *revEndDate;
- GtkScrolledWindow *revScrollWin;
- GtkTreeView *revView;
-} LoanDruidData;
-
-/**
- * A transient structure to contain SX details during the creation process.
- **/
-typedef struct toCreateSX_
-{
- /** The name of the SX */
- gchar *name;
- /** The start, last-occurred and end dates. */
- GDate start, last, end;
- /** The SX schedule */
- GList *schedule;
- /** The current 'instance-num' count. */
- gint instNum;
- /** The main/source transaction being created. */
- TTInfo *mainTxn;
- /** The optional escrow transaction being created. */
- TTInfo *escrowTxn;
-} toCreateSX;
-
-static void gnc_loan_druid_data_init( LoanDruidData *ldd );
-static void gnc_loan_druid_get_widgets( LoanDruidData *ldd );
-
-static void ld_close_handler( LoanDruidData *ldd );
-static void ld_destroy( GtkObject *o, gpointer ud );
-
-static void ld_cancel_check( GnomeDruid *gd, LoanDruidData *ldd );
-static void ld_prm_type_changed( GtkWidget *w, gpointer ud );
-static void ld_calc_upd_rem_payments( GtkWidget *w, gpointer ud );
-
-static void ld_escrow_toggle( GtkToggleButton *tb, gpointer ud );
-static void ld_opt_toggled( GtkToggleButton *tb, gpointer ud );
-static void ld_opt_consistency( GtkToggleButton *tb, gpointer ud );
-static void ld_escrow_toggled( GtkToggleButton *tb, gpointer ud );
-
-static void ld_pay_freq_toggle( GtkToggleButton *tb, gpointer ud );
-
-static void ld_pay_use_esc_setup( LoanDruidData *ldd, gboolean newState );
-static void ld_pay_use_esc_toggle( GtkToggleButton *tb, gpointer ud );
-static void ld_pay_spec_src_setup( LoanDruidData *ldd, gboolean newState );
-static void ld_pay_spec_src_toggle( GtkToggleButton *tb, gpointer ud );
-
-static void ld_get_loan_range( LoanDruidData *ldd,
- GDate *start,
- GDate *end );
-
-static void ld_rev_recalc_schedule( LoanDruidData *ldd );
-static void ld_rev_range_opt_changed( GtkComboBox *combo, gpointer ud );
-static void ld_rev_range_changed( GNCDateEdit *gde, gpointer ud );
-static void ld_rev_get_dates( LoanDruidData *ldd,
- GDate *start,
- GDate *end );
-static void ld_rev_update_view( LoanDruidData *ldd,
- GDate *start,
- GDate *end );
-static void ld_rev_sched_list_free( gpointer data, gpointer user_data );
-static void ld_rev_hash_to_list( gpointer key,
- gpointer val,
- gpointer user_data );
-static void ld_rev_hash_free_date_keys( gpointer key,
- gpointer val,
- gpointer user_data );
-
-static void ld_get_pmt_formula( LoanDruidData *ldd, GString *gstr );
-static void ld_get_ppmt_formula( LoanDruidData *ldd, GString *gstr );
-static void ld_get_ipmt_formula( LoanDruidData *ldd, GString *gstr );
-
-static gboolean ld_info_save( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static void ld_info_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static gboolean ld_opts_tran( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static void ld_opts_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static gboolean ld_rep_next ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static void ld_rep_prep ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static gboolean ld_rep_back ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static gboolean ld_pay_next ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static void ld_pay_prep ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static gboolean ld_pay_back ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static gboolean ld_rev_next ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static void ld_rev_prep ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static gboolean ld_rev_back ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static gboolean ld_com_next ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static void ld_com_prep ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static gboolean ld_com_back ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-static void ld_com_fin ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
-
-static void ld_create_sxes( LoanDruidData *ldd );
-static gint ld_find_ttsplit_with_acct( gconstpointer elt,
- gconstpointer crit );
-static void ld_create_sx_from_tcSX( LoanDruidData *ldd, toCreateSX *tcSX );
-static void ld_tcSX_free( gpointer data, gpointer user_data );
-static float ld_apr_to_simple_formula (float rate, float compounding_periods);
-
-struct LoanDruidData_*
-gnc_ui_sx_loan_druid_create(void)
-{
- int i;
- LoanDruidData *ldd;
-
- ldd = g_new0( LoanDruidData, 1 );
-
- gnc_loan_druid_data_init( ldd );
-
- ldd->gxml = gnc_glade_xml_new( SX_GLADE_FILE, LOAN_DRUID_WIN_GLADE_NAME );
- ldd->dialog = glade_xml_get_widget( ldd->gxml, LOAN_DRUID_WIN_GLADE_NAME );
- ldd->druid = GNOME_DRUID(glade_xml_get_widget( ldd->gxml,
- LOAN_DRUID_GLADE_NAME ));
- gnc_druid_set_colors (ldd->druid);
-
- /* get pointers to the various widgets */
- gnc_loan_druid_get_widgets( ldd );
-
- /* non-gladeable widget setup */
- {
- int i;
- // ACCT_TYPE_LIABILITY
- GList *liabilityAcct;
- // ACCT_TYPE_BANK, ACCT_TYPE_CASH, ACCT_TYPE_CREDIT,
- // ACCT_TYPE_ASSET + ACCT_TYPE_LIABILITY
- GList *paymentFromAccts;
- // ACCT_TYPE_EXPENSE, ACCT_TYPE_LIABILITY, + payment-froms.
- GList *paymentToAccts;
- int fromLen = 5;
- GNCAccountType paymentFroms[] = { ACCT_TYPE_BANK, ACCT_TYPE_CASH,
- ACCT_TYPE_CREDIT, ACCT_TYPE_ASSET,
- ACCT_TYPE_LIABILITY
- };
- int toLen = 1;
- GNCAccountType paymentTos[] = { ACCT_TYPE_EXPENSE };
-
- liabilityAcct = NULL;
- paymentFromAccts = NULL;
- paymentToAccts = NULL;
-
- liabilityAcct = g_list_append( liabilityAcct,
- GINT_TO_POINTER( ACCT_TYPE_LIABILITY ) );
- for ( i = 0; i < fromLen; i++ )
- {
- paymentFromAccts
- = g_list_append( paymentFromAccts,
- GINT_TO_POINTER( paymentFroms[i] ) );
- paymentToAccts
- = g_list_append( paymentToAccts,
- GINT_TO_POINTER( paymentFroms[i] ) );
- }
-
- for ( i = 0; i < toLen; i++ )
- {
- paymentToAccts = g_list_append( paymentToAccts,
- GINT_TO_POINTER( paymentTos[i] ) );
- }
-
- /* All of the GncAccountSel[ectors]... */
- {
- int i;
- GtkAlignment *a;
- /* "gas" == GncAccountSel */
- struct gas_in_tables_data
- {
- GNCAccountSel **loc;
- GtkTable *table;
- gboolean newAcctAbility;
- int left, right, top, bottom;
- GList *allowableAccounts;
- } gas_data[] =
- {
- /* These ints are the GtkTable boundries */
- { &ldd->prmAccountGAS, ldd->prmTable, TRUE, 1, 4, 0, 1, liabilityAcct },
- { &ldd->repAssetsFromGAS, ldd->repTable, TRUE, 1, 4, 2, 3, paymentFromAccts },
- { &ldd->repPrincToGAS, ldd->repTable, TRUE, 1, 2, 3, 4, paymentToAccts },
- { &ldd->repIntToGAS, ldd->repTable, TRUE, 3, 4, 3, 4, paymentToAccts },
- { &ldd->payAcctFromGAS, ldd->payTable, TRUE, 1, 2, 4, 5, paymentFromAccts },
- { &ldd->payAcctEscToGAS, ldd->payTable, FALSE, 3, 4, 4, 5, paymentToAccts },
- { &ldd->payAcctEscFromGAS, ldd->payTable, FALSE, 1, 2, 5, 6, paymentFromAccts },
- { &ldd->payAcctToGAS, ldd->payTable, TRUE, 3, 4, 5, 6, paymentToAccts },
- { NULL }
- };
-
- /* left-aligned, 25%-width */
- a = GTK_ALIGNMENT(gtk_alignment_new( 0.0, 0.5, 0.25, 1.0 ));
- ldd->prmOrigPrincGAE = GNC_AMOUNT_EDIT(gnc_amount_edit_new());
- gtk_container_add( GTK_CONTAINER(a), GTK_WIDGET(ldd->prmOrigPrincGAE) );
- gtk_table_attach( ldd->prmTable, GTK_WIDGET(a),
- 1, 4, 1, 2,
- GTK_EXPAND | GTK_FILL,
- GTK_EXPAND | GTK_FILL, 2, 2 );
-
- for ( i = 0; gas_data[i].loc != NULL; i++ )
- {
- GNCAccountSel *gas;
-
- a = GTK_ALIGNMENT(gtk_alignment_new( 0.0, 0.5, 0.25, 1.0 ));
- gas = GNC_ACCOUNT_SEL(gnc_account_sel_new());
- gnc_account_sel_set_new_account_ability(
- gas, gas_data[i].newAcctAbility );
- if ( gas_data[i].allowableAccounts != NULL )
- {
- gnc_account_sel_set_acct_filters(
- gas, gas_data[i].allowableAccounts, NULL );
- }
- gtk_container_add( GTK_CONTAINER(a),
- GTK_WIDGET(gas) );
- gtk_table_attach( gas_data[i].table,
- GTK_WIDGET(a),
- gas_data[i].left,
- gas_data[i].right,
- gas_data[i].top,
- gas_data[i].bottom,
- GTK_EXPAND | GTK_FILL,
- GTK_EXPAND | GTK_FILL, 2, 2 );
- *(gas_data[i].loc) = gas;
- }
- }
-
- /* Setup the payment page always-insensitive GASes */
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctEscToGAS), FALSE );
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctEscFromGAS), FALSE );
-
- /* The GNCDateEdit[s] */
- {
- /* "gde" == GNCDateEdit */
- struct gde_in_tables_data
- {
- GNCDateEdit **loc;
- GtkTable *table;
- int left, right, top, bottom;
- } gde_data[] =
- {
- /* These ints are the GtkTable boundries */
- { &ldd->prmStartDateGDE, ldd->prmTable, 1, 2, 4, 5 },
- { &ldd->revStartDate, ldd->revTable, 1, 2, 0, 1 },
- { &ldd->revEndDate, ldd->revTable, 1, 2, 1, 2 },
- { NULL }
- };
-
- for ( i = 0; gde_data[i].loc != NULL; i++ )
- {
- *gde_data[i].loc =
- GNC_DATE_EDIT(
- gnc_date_edit_new( time(NULL),
- FALSE, FALSE ) );
- gtk_table_attach( gde_data[i].table,
- GTK_WIDGET( *gde_data[i].loc ),
- gde_data[i].left,
- gde_data[i].right,
- gde_data[i].top,
- gde_data[i].bottom,
- (GTK_EXPAND | GTK_FILL),
- GTK_FILL, 0, 0 );
- }
-
- }
-
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->prmVarFrame), FALSE );
- {
- g_signal_connect( ldd->prmType, "changed",
- G_CALLBACK( ld_prm_type_changed ),
- ldd );
- }
-
- {
- GtkAdjustment *a;
-
- /* 8.0 [%], range of 0.005..100.0 with ticks at 0.001[%]. */
- a = GTK_ADJUSTMENT(gtk_adjustment_new( 8.0, 0.001,
- 100.0, 0.001,
- 1.0, 1.0 ));
- gtk_spin_button_set_adjustment( ldd->prmIrateSpin, a );
- gtk_spin_button_set_value( ldd->prmIrateSpin, 8.00 );
- gtk_spin_button_set_snap_to_ticks( ldd->prmIrateSpin,
- TRUE );
-
- a = GTK_ADJUSTMENT(gtk_adjustment_new( 360, 1,
- 9999, 1,
- 12, 12 ));
- gtk_spin_button_set_adjustment( ldd->prmLengthSpin, a );
- g_signal_connect( ldd->prmLengthSpin, "changed",
- G_CALLBACK( ld_calc_upd_rem_payments ),
- ldd );
- g_signal_connect( ldd->prmStartDateGDE, "date-changed",
- G_CALLBACK( ld_calc_upd_rem_payments ),
- ldd );
- g_signal_connect( ldd->prmLengthSpin, "changed",
- G_CALLBACK( ld_calc_upd_rem_payments ),
- ldd );
- g_signal_connect( ldd->prmLengthType, "changed",
- G_CALLBACK( ld_calc_upd_rem_payments ),
- ldd );
-
- a = GTK_ADJUSTMENT(gtk_adjustment_new( 360, 1,
- 9999, 1,
- 12, 12 ));
- gtk_spin_button_set_adjustment( ldd->prmRemainSpin, a );
- }
-
- g_signal_connect( ldd->optEscrowCb, "toggled",
- G_CALLBACK(ld_escrow_toggle), ldd );
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->optEscrowHBox), FALSE );
- ldd->optEscrowGAS = GNC_ACCOUNT_SEL(gnc_account_sel_new());
- gnc_account_sel_set_new_account_ability( ldd->optEscrowGAS, TRUE );
- gtk_container_add( GTK_CONTAINER(ldd->optEscrowHBox),
- GTK_WIDGET(ldd->optEscrowGAS) );
-
- {
- /* . Each RepayOpt gets an "entry" in the optContainer.
- * . Each "entry" is a 2-line vbox containing:
- * . The checkbox for the option itself
- * . an alignment-contained sub-checkbox for "through the
- * escrow account".
- * . Hook up each to bit-twiddling the appropriate line.
- */
-
- RepayOptUIData *rouid;
- GtkVBox *vb;
- GtkAlignment *optAlign, *subOptAlign;
- GString *str;
-
- str = g_string_sized_new( 32 );
-
- for ( i = 0; i < ldd->ld.repayOptCount; i++ )
- {
- rouid = ldd->repayOptsUI[i];
- vb = GTK_VBOX(gtk_vbox_new( FALSE, OPT_VBOX_SPACING ));
-
- /* Add payment checkbox. */
-
- /* Translators: %s is "Taxes",
- * "Insurance", or similar. */
- g_string_printf( str, _("... pay \"%s\"?"),
- rouid->optData->name );
- rouid->optCb =
- GTK_CHECK_BUTTON(
- gtk_check_button_new_with_label(
- str->str ));
- gtk_box_pack_start( GTK_BOX(vb),
- GTK_WIDGET(rouid->optCb),
- FALSE, FALSE, 2 );
- rouid->escrowCb =
- GTK_CHECK_BUTTON(
- gtk_check_button_new_with_label(
- _("via Escrow account?") ));
- gtk_widget_set_sensitive(
- GTK_WIDGET(rouid->escrowCb),
- FALSE );
- subOptAlign =
- GTK_ALIGNMENT(
- gtk_alignment_new(
- 0.5, 0.5, 0.75, 1.0 ));
- gtk_container_add( GTK_CONTAINER(subOptAlign),
- GTK_WIDGET(rouid->escrowCb) );
- gtk_box_pack_start( GTK_BOX(vb), GTK_WIDGET(subOptAlign),
- FALSE, FALSE, 2 );
-
- g_signal_connect( rouid->optCb, "toggled",
- G_CALLBACK(ld_opt_toggled),
- rouid );
- g_signal_connect( rouid->optCb, "toggled",
- G_CALLBACK(ld_opt_consistency),
- rouid );
- g_signal_connect( rouid->escrowCb, "toggled",
- G_CALLBACK(ld_escrow_toggled),
- rouid );
-
- optAlign = GTK_ALIGNMENT(gtk_alignment_new( 0.5, 0.5, 0.75, 1.0 ));
- gtk_container_add( GTK_CONTAINER(optAlign),
- GTK_WIDGET(vb) );
- gtk_box_pack_start( GTK_BOX(ldd->optVBox), GTK_WIDGET(optAlign),
- FALSE, FALSE, 2 );
- gtk_widget_show_all( GTK_WIDGET(optAlign) );
- }
- g_string_free( str, TRUE );
- }
-
- g_signal_connect( ldd->payUseEscrow, "toggled",
- G_CALLBACK(ld_pay_use_esc_toggle), ldd );
- g_signal_connect( ldd->paySpecSrcAcct, "toggled",
- G_CALLBACK(ld_pay_spec_src_toggle), ldd );
- g_signal_connect( ldd->payTxnFreqPartRb, "toggled",
- G_CALLBACK(ld_pay_freq_toggle), ldd );
- g_signal_connect( ldd->payTxnFreqUniqRb, "toggled",
- G_CALLBACK(ld_pay_freq_toggle), ldd );
-
- ldd->prmVarGncFreq =
- GNC_FREQUENCY(gnc_frequency_new( NULL, NULL ));
- gtk_container_add( GTK_CONTAINER(ldd->prmVarFrame),
- GTK_WIDGET(ldd->prmVarGncFreq) );
-
- ldd->repGncFreq =
- GNC_FREQUENCY(gnc_frequency_new( NULL, NULL ));
- gtk_container_add( GTK_CONTAINER(ldd->repFreqFrame),
- GTK_WIDGET(ldd->repGncFreq) );
-
- ldd->payGncFreq =
- GNC_FREQUENCY(gnc_frequency_new( NULL, NULL ));
- gtk_container_add( GTK_CONTAINER(ldd->payFreqAlign),
- GTK_WIDGET(ldd->payGncFreq) );
- }
-
- /* Review page widget setup. */
- {
- gtk_combo_box_set_active( ldd->revRangeOpt, 0 );
- g_signal_connect( ldd->revRangeOpt, "changed",
- G_CALLBACK( ld_rev_range_opt_changed ),
- ldd );
- g_signal_connect( ldd->revStartDate, "date-changed",
- G_CALLBACK( ld_rev_range_changed ),
- ldd );
- g_signal_connect( ldd->revEndDate, "date-changed",
- G_CALLBACK( ld_rev_range_changed ),
- ldd );
- }
-
- {
- static struct
- {
- char *pageName;
- gboolean (*nextFn)();
- void (*prepFn)();
- gboolean (*backFn)();
- void (*finishFn)();
- /* cancel is handled by the druid itself. */
- } DRUID_HANDLERS[] =
- {
- { PG_INFO, ld_info_save, ld_info_prep, ld_info_save, NULL },
- { PG_OPTS, ld_opts_tran, ld_opts_prep, ld_opts_tran, NULL },
- { PG_REPAYMENT, ld_rep_next, ld_rep_prep, ld_rep_back, NULL },
- { PG_PAYMENT, ld_pay_next, ld_pay_prep, ld_pay_back, NULL },
- { PG_REVIEW, ld_rev_next, ld_rev_prep, ld_rev_back, NULL },
- { PG_COMMIT, ld_com_next, ld_com_prep, ld_com_back, ld_com_fin },
- { NULL }
- };
-
- /* setup page-transition handlers */
- /* setup druid-global handler for cancel */
- g_signal_connect( ldd->druid, "cancel",
- G_CALLBACK(ld_cancel_check), ldd );
- /* FIXME: this is substantially similar to the code in
- * dialog-sxsincelast.c ... it should probably be factored out
- * somewhere. */
- for ( i = 0; DRUID_HANDLERS[i].pageName != NULL; i++ )
- {
- GtkWidget *pg;
-
- pg = glade_xml_get_widget( ldd->gxml,
- DRUID_HANDLERS[i].pageName );
- if ( DRUID_HANDLERS[i].prepFn )
- {
- g_signal_connect( pg, "prepare",
- G_CALLBACK(DRUID_HANDLERS[i].
- prepFn),
- ldd);
- }
- if ( DRUID_HANDLERS[i].backFn )
- {
- g_signal_connect( pg, "back",
- G_CALLBACK(DRUID_HANDLERS[i].
- backFn),
- ldd);
- }
- if ( DRUID_HANDLERS[i].nextFn )
- {
- g_signal_connect( pg, "next",
- G_CALLBACK(DRUID_HANDLERS[i].
- nextFn),
- ldd);
- }
- if ( DRUID_HANDLERS[i].finishFn )
- {
- g_signal_connect( pg, "finish",
- G_CALLBACK(DRUID_HANDLERS[i].
- finishFn),
- ldd);
- }
- }
- }
-
- gnc_register_gui_component( DIALOG_LOAN_DRUID_CM_CLASS,
- NULL, /* no refresh handler */
- (GNCComponentCloseHandler)ld_close_handler,
- ldd );
-
- g_signal_connect( ldd->dialog, "destroy",
- G_CALLBACK(ld_destroy),
- ldd );
-
- gtk_widget_show_all( ldd->dialog );
- return ldd;
-}
-
-static
-void
-gnc_loan_druid_data_init( LoanDruidData *ldd )
-{
- int i, optCount;
- RepayOptData *optData;
-
- /* get the count of repayment defaults. */
- for ( optCount = 0; REPAY_DEFAULTS[optCount].name != NULL; optCount++ )
- ;
-
- ldd->currentIdx = -1;
-
- ldd->ld.principal = gnc_numeric_zero();
- ldd->ld.startDate = g_date_new();
- ldd->ld.varStartDate = g_date_new();
- g_date_set_time_t( ldd->ld.startDate, time(NULL) );
- ldd->ld.loan_schedule = NULL;
- ldd->ld.repayment_schedule = NULL;
- {
- Recurrence *r = g_new0(Recurrence, 1);
- recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate, WEEKEND_ADJ_NONE);
- ldd->ld.repayment_schedule = g_list_append(ldd->ld.repayment_schedule, r);
- }
-
- ldd->ld.repMemo = g_strdup( _("Loan") );
- ldd->ld.repAmount = NULL;
- ldd->ld.repStartDate = g_date_new();
- ldd->ld.repayOptCount = optCount;
- ldd->ld.repayOpts = g_new0( RepayOptData*, optCount );
- /* copy all the default lines into the LDD */
- ldd->repayOptsUI = g_new0( RepayOptUIData*, optCount );
- for ( i = 0; i < optCount; i++ )
- {
- g_assert( REPAY_DEFAULTS[i].name != NULL );
-
- ldd->repayOptsUI[i] = g_new0( RepayOptUIData, 1 );
- ldd->repayOptsUI[i]->ldd = ldd;
-
- optData = ldd->ld.repayOpts[i]
- = ldd->repayOptsUI[i]->optData
- = g_new0( RepayOptData, 1 );
-
- optData->enabled = FALSE;
- optData->name = g_strdup( _(REPAY_DEFAULTS[i].name) );
- optData->txnMemo = g_strdup( _(REPAY_DEFAULTS[i].
- defaultTxnMemo) );
- optData->amount = 0.0;
- optData->throughEscrowP = REPAY_DEFAULTS[i].escrowDefault;
- optData->specSrcAcctP = REPAY_DEFAULTS[i].specSrcAcctDefault;
- optData->schedule = NULL;
- optData->startDate = NULL;
- }
-}
-
-static
-void
-gnc_loan_druid_get_widgets( LoanDruidData *ldd )
-{
- g_assert( ldd != NULL );
- g_assert( ldd->gxml != NULL );
-
- /* Get all widgets */
-#define GET_CASTED_WIDGET( cast, name ) \
- (cast( glade_xml_get_widget( ldd->gxml, name ) ))
-
- /* prm = params */
- ldd->prmTable =
- GET_CASTED_WIDGET( GTK_TABLE, PARAM_TABLE );
- ldd->prmIrateSpin =
- GET_CASTED_WIDGET( GTK_SPIN_BUTTON, IRATE_SPIN );
- ldd->prmType =
- GET_CASTED_WIDGET( GTK_COMBO_BOX, TYPE_COMBOBOX );
- ldd->prmVarFrame =
- GET_CASTED_WIDGET( GTK_FRAME, VAR_CONTAINER );
- /* ldd->prmStartDateGDE */
- ldd->prmLengthSpin =
- GET_CASTED_WIDGET( GTK_SPIN_BUTTON, LENGTH_SPIN );
- ldd->prmLengthType =
- GET_CASTED_WIDGET( GTK_COMBO_BOX, LENGTH_OPT );
- ldd->prmRemainSpin =
- GET_CASTED_WIDGET( GTK_SPIN_BUTTON, REMAIN_SPIN );
- ldd->prmIrateType =
- GET_CASTED_WIDGET( GTK_COMBO_BOX, IRATE_TYPE_COMBOBOX );
-
- /* opt = options */
- ldd->optVBox =
- GET_CASTED_WIDGET( GTK_VBOX, OPT_CONTAINER );
- ldd->optEscrowCb =
- GET_CASTED_WIDGET( GTK_CHECK_BUTTON, OPT_ESCROW );
- ldd->optEscrowHBox =
- GET_CASTED_WIDGET( GTK_HBOX, OPT_ESCROW_CONTAINER );
-
- /* rep = repayment */
- ldd->repTxnName =
- GET_CASTED_WIDGET( GTK_ENTRY, TXN_NAME );
- ldd->repTable =
- GET_CASTED_WIDGET( GTK_TABLE, REPAY_TABLE );
- ldd->repAmtEntry =
- GET_CASTED_WIDGET( GTK_ENTRY, AMOUNT_ENTRY );
- ldd->repFreqFrame =
- GET_CASTED_WIDGET( GTK_FRAME, FREQ_CONTAINER );
-
- /* pay = payment[s] */
- ldd->payTxnName =
- GET_CASTED_WIDGET( GTK_ENTRY, PAY_TXN_TITLE );
- ldd->payAmtEntry =
- GET_CASTED_WIDGET( GTK_ENTRY, PAY_AMT_ENTRY );
- ldd->payTable =
- GET_CASTED_WIDGET( GTK_TABLE, PAY_TABLE );
- ldd->payUseEscrow =
- GET_CASTED_WIDGET( GTK_CHECK_BUTTON, PAY_USE_ESCROW );
- ldd->paySpecSrcAcct =
- GET_CASTED_WIDGET( GTK_CHECK_BUTTON, PAY_SPEC_SRC_ACCT );
- ldd->payAcctFromLabel =
- GET_CASTED_WIDGET( GTK_LABEL, PAY_FROM_ACCT_LBL );
- ldd->payEscToLabel =
- GET_CASTED_WIDGET( GTK_LABEL, PAY_ESC_TO_LBL );
- ldd->payEscFromLabel =
- GET_CASTED_WIDGET( GTK_LABEL, PAY_ESC_FROM_LBL );
- ldd->payTxnFreqPartRb =
- GET_CASTED_WIDGET( GTK_RADIO_BUTTON, PAY_TXN_PART_RB );
- ldd->payTxnFreqUniqRb =
- GET_CASTED_WIDGET( GTK_RADIO_BUTTON, PAY_UNIQ_FREQ_RB );
- ldd->payFreqAlign =
- GET_CASTED_WIDGET( GTK_ALIGNMENT, PAY_FREQ_CONTAINER );
-
- /* rev = review */
- ldd->revRangeOpt =
- GET_CASTED_WIDGET( GTK_COMBO_BOX, REV_RANGE_OPT );
- ldd->revDateFrame =
- GET_CASTED_WIDGET( GTK_FRAME, REV_DATE_FRAME );
- ldd->revTable =
- GET_CASTED_WIDGET( GTK_TABLE, REV_RANGE_TABLE );
- /* GNCDateEdit *revStartDate */
- /* GNCDateEdit *revEndDate */
- ldd->revScrollWin =
- GET_CASTED_WIDGET( GTK_SCROLLED_WINDOW, REV_SCROLLWIN );
-
-}
-
-/* convert APR rate to simple rate based on formula r=q((1+i)^(1/q)-1) (r=interest rate, i=apr, q=compounding periods) */
-
-gfloat ld_apr_to_simple_formula (gfloat rate, gfloat compounding_periods)
-{
- /* float percent_to_frac; - redundant */
- gfloat simple_rate;
- /* percent_to_frac= compounding_periods/100; - redundant */
- simple_rate = compounding_periods * ((pow((1 + rate), (1 / compounding_periods))) - 1);
- return (simple_rate);
-}
-
-
-static
-void
-ld_get_pmt_formula( LoanDruidData *ldd, GString *gstr )
-{
- gint rate_case;
- gfloat pass_thru_rate;
- g_assert( ldd != NULL );
- g_assert( gstr != NULL );
- rate_case = ldd->ld.rateType;
- pass_thru_rate = ldd->ld.interestRate / 100;
- switch (rate_case)
- {
- case GNC_IRATE_SIMPLE:
- {
- g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
- pass_thru_rate, 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal) );
- }
- break;
- case GNC_IRATE_APR_DAILY:
- {
- g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 365),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal) );
- }
- break;
- case GNC_IRATE_APR_WEEKLY:
- {
- g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 52),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal) );
- }
- break;
- case GNC_IRATE_APR_MONTHLY:
- {
- g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 12),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal) );
- }
- break;
- case GNC_IRATE_APR_QUARTERLY:
- {
- g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 4),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal) );
- }
- break;
- case GNC_IRATE_APR_ANNUALLY:
- {
- g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 1),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal) );
- }
- break;
- default:
- g_string_append_printf( gstr, "pmt( %.5f / %0.2f : %0.2f : %0.2f : 0 : 0 )",
- (ldd->ld.interestRate / 100),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal) );
- break;
- }
-}
-
-static
-void
-ld_get_ppmt_formula( LoanDruidData *ldd, GString *gstr )
-{
- gint rate_case;
- gfloat pass_thru_rate;
- g_assert( ldd != NULL );
- g_assert( gstr != NULL );
- rate_case = ldd->ld.rateType;
- pass_thru_rate = ldd->ld.interestRate / 100;
- switch (rate_case)
- {
- case GNC_IRATE_SIMPLE:
- {
- g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- pass_thru_rate,
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- case GNC_IRATE_APR_DAILY:
- {
- g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 365),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- case GNC_IRATE_APR_WEEKLY:
- {
- g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 52),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- case GNC_IRATE_APR_MONTHLY:
- {
- g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 12),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- case GNC_IRATE_APR_QUARTERLY:
- {
- g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 4),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- case GNC_IRATE_APR_ANNUALLY:
- {
- g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 1),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- default:
- g_string_printf( gstr, "ppmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- (ldd->ld.interestRate / 100),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- break;
- }
-}
-
-static
-void
-ld_get_ipmt_formula( LoanDruidData *ldd, GString *gstr )
-{
- gint rate_case;
- gfloat pass_thru_rate;
- g_assert( ldd != NULL );
- g_assert( gstr != NULL );
- rate_case = ldd->ld.rateType;
- pass_thru_rate = ldd->ld.interestRate / 100;
- switch (rate_case)
- {
- case GNC_IRATE_SIMPLE:
- {
- g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- pass_thru_rate,
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- case GNC_IRATE_APR_DAILY:
- {
- g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 365),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- case GNC_IRATE_APR_WEEKLY:
- {
- g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 52),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- case GNC_IRATE_APR_MONTHLY:
- {
- g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 12),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- case GNC_IRATE_APR_QUARTERLY:
- {
- g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 4),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- case GNC_IRATE_APR_ANNUALLY:
- {
- g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- ld_apr_to_simple_formula(pass_thru_rate, 1),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- }
- break;
- default:
- g_string_printf( gstr, "ipmt( %.5f / %0.2f : i : %0.2f : %0.2f : 0 : 0 )",
- (ldd->ld.interestRate / 100),
- 12.0,
- ( ldd->ld.numPer
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) ) * 1.,
- gnc_numeric_to_double(ldd->ld.principal));
- break;
- }
-}
-
-static
-void
-ld_close_handler( LoanDruidData *ldd )
-{
- gtk_widget_hide( ldd->dialog );
- gtk_widget_destroy( ldd->dialog );
-}
-
-static
-void
-ld_destroy( GtkObject *o, gpointer ud )
-{
- LoanDruidData *ldd;
-
- ldd = (LoanDruidData*)ud;
-
- g_assert( ldd );
-
- gnc_unregister_gui_component_by_data
- (DIALOG_LOAN_DRUID_CM_CLASS, ldd);
-
- /* free alloc'd mem; cleanup */
-
- /* repay opts */
- {
- int i;
-
- g_date_free( ldd->ld.startDate );
- g_date_free( ldd->ld.varStartDate );
- recurrenceListFree(&ldd->ld.loan_schedule);
-
- if ( ldd->ld.repMemo )
- g_free( ldd->ld.repMemo );
-
- for ( i = 0; i < ldd->ld.repayOptCount; i++ )
- {
- RepayOptData *rod = ldd->ld.repayOpts[i];
- if ( rod->name )
- g_free( rod->name );
- if ( rod->txnMemo )
- g_free( rod->txnMemo );
-
- if ( rod->startDate )
- g_date_free( rod->startDate );
-
- if (rod->schedule != NULL)
- recurrenceListFree(&rod->schedule);
-
- g_free( ldd->ld.repayOpts[i] );
- g_free( ldd->repayOptsUI[i] );
- }
- g_free( ldd->ld.repayOpts );
- g_free( ldd->repayOptsUI );
-
- if ( ldd->ld.repAmount )
- g_free( ldd->ld.repAmount );
-
- g_date_free( ldd->ld.repStartDate );
- }
-
- /* review */
- {
- if ( ldd->ld.revSchedule )
- {
- g_list_foreach( ldd->ld.revSchedule,
- ld_rev_sched_list_free,
- NULL );
- g_list_free( ldd->ld.revSchedule );
- ldd->ld.revSchedule = NULL;
- }
- }
-
- g_free( ldd );
-}
-
-
-static
-void
-ld_cancel_check( GnomeDruid *gd, LoanDruidData *ldd )
-{
- const char *cancelMsg = _( "Are you sure you want to cancel "
- "the Mortgage/Loan Setup Assistant?" );
- if ( gnc_verify_dialog( ldd->dialog, FALSE, "%s", cancelMsg ) )
- {
- gnc_close_gui_component_by_data( DIALOG_LOAN_DRUID_CM_CLASS,
- ldd );
- }
-}
-
-static
-void
-ld_prm_type_changed( GtkWidget *w, gpointer ud )
-{
- LoanDruidData *ldd;
- gint index;
-
- ldd = (LoanDruidData*)ud;
- index = gtk_combo_box_get_active( ldd->prmType );
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->prmVarFrame),
- index != GNC_FIXED );
-}
-
-static
-void
-ld_escrow_toggle( GtkToggleButton *tb, gpointer ud )
-{
- int i;
- gboolean newState;
- RepayOptUIData *rouid;
- LoanDruidData *ldd;
-
- ldd = (LoanDruidData*)ud;
- newState = gtk_toggle_button_get_active(tb);
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->optEscrowHBox), newState );
- /* deal with escrow options. */
- for ( i = 0; i < ldd->ld.repayOptCount; i++ )
- {
- rouid = ldd->repayOptsUI[i];
- /* If we're going off, then uncheck and desensitize all escrow opts. */
- /* If we're going on, then sensitize all escrow opts. */
-
- /* prevent the toggle handler from running and "trashing" the
- * state of the throughEscrowP selection */
- g_signal_handlers_block_by_func( rouid->escrowCb,
- ld_escrow_toggled,
- rouid );
- gtk_toggle_button_set_active(
- GTK_TOGGLE_BUTTON(rouid->escrowCb),
- ( newState
- && gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(rouid->optCb) )
- && rouid->optData->throughEscrowP ) );
- gtk_widget_set_sensitive(
- GTK_WIDGET(rouid->escrowCb),
- newState
- && gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(rouid->optCb) ) );
- g_signal_handlers_unblock_by_func( rouid->escrowCb,
- ld_escrow_toggled,
- rouid );
- if ( newState )
- {
- rouid->optData->from = ldd->ld.escrowAcct;
- }
- else
- {
- rouid->optData->from = NULL;
- }
- }
-}
-
-static
-void
-ld_opt_toggled( GtkToggleButton *tb, gpointer ud )
-{
- RepayOptUIData *rouid;
-
- rouid = (RepayOptUIData*)ud;
- rouid->optData->enabled = gtk_toggle_button_get_active(tb);
-}
-
-static
-void
-ld_opt_consistency( GtkToggleButton *tb, gpointer ud )
-{
- GtkToggleButton *escrowCb;
- RepayOptUIData *rouid;
-
- rouid = (RepayOptUIData*)ud;
- escrowCb = GTK_TOGGLE_BUTTON(rouid->escrowCb);
- /* make sure the escrow option is only selected if we're active. */
- gtk_toggle_button_set_active( escrowCb,
- gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(
- rouid->ldd->optEscrowCb) )
- && rouid->optData->throughEscrowP
- && gtk_toggle_button_get_active(tb) );
- /* make sure the escrow option is only sensitive if we're active, and
- * the escrow account is enabled */
- gtk_widget_set_sensitive( GTK_WIDGET(escrowCb),
- gtk_toggle_button_get_active(tb)
- && gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(rouid->ldd->optEscrowCb)) );
-}
-
-static
-void
-ld_escrow_toggled( GtkToggleButton *tb, gpointer ud )
-{
- RepayOptUIData *rouid;
-
- rouid = (RepayOptUIData*)ud;
- rouid->optData->throughEscrowP = gtk_toggle_button_get_active( tb );
-}
-
-static
-gboolean
-ld_info_save( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- LoanDruidData *ldd;
-
- ldd = (LoanDruidData*)ud;
-
- ldd->ld.primaryAcct = gnc_account_sel_get_account( ldd->prmAccountGAS );
- if ( ldd->ld.primaryAcct == NULL )
- {
- gnc_info_dialog( ldd->dialog, "%s",
- _("Please select a valid loan account.") );
- return TRUE;
- }
- if ( ! ldd->ld.repPriAcct )
- {
- ldd->ld.repPriAcct = ldd->ld.primaryAcct;
- }
- ldd->ld.principal = gnc_amount_edit_get_amount( ldd->prmOrigPrincGAE );
- ldd->ld.interestRate = gtk_spin_button_get_value( ldd->prmIrateSpin );
- ldd->ld.rateType = gtk_combo_box_get_active (ldd->prmIrateType );
- ldd->ld.type = gtk_combo_box_get_active( ldd->prmType );
- if ( ldd->ld.type != GNC_FIXED )
- {
- recurrenceListFree(&ldd->ld.loan_schedule);
- gnc_frequency_save_to_recurrence(ldd->prmVarGncFreq,
- &ldd->ld.loan_schedule,
- ldd->ld.varStartDate);
- }
-
- /* start date */
- {
- time_t tmpTT;
- struct tm *tmpTm;
-
- tmpTT = gnc_date_edit_get_date( ldd->prmStartDateGDE );
- tmpTm = localtime( &tmpTT );
- g_date_set_dmy( ldd->ld.startDate,
- tmpTm->tm_mday,
- (tmpTm->tm_mon + 1),
- (1900 + tmpTm->tm_year) );
- }
-
- /* len / periods */
- {
- ldd->ld.perSize =
- (gtk_combo_box_get_active( ldd->prmLengthType )
- == GNC_MONTHS) ? GNC_MONTHS : GNC_YEARS;
- ldd->ld.numPer =
- gtk_spin_button_get_value_as_int( ldd->prmLengthSpin );
- ldd->ld.numMonRemain =
- gtk_spin_button_get_value_as_int( ldd->prmRemainSpin );
- }
- return FALSE;
-}
-
-static
-void
-ld_info_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- LoanDruidData *ldd;
-
- ldd = (LoanDruidData*)ud;
- gnc_amount_edit_set_amount( ldd->prmOrigPrincGAE, ldd->ld.principal );
- gtk_spin_button_set_value( ldd->prmIrateSpin, ldd->ld.interestRate );
- gtk_combo_box_set_active( ldd->prmIrateType, ldd ->ld.rateType );
- gtk_combo_box_set_active( ldd->prmType, ldd->ld.type );
- if ( ldd->ld.type != GNC_FIXED )
- {
- gnc_frequency_setup_recurrence(ldd->prmVarGncFreq,
- ldd->ld.loan_schedule,
- ldd->ld.varStartDate);
- }
-
- /* start date */
- {
- struct tm *tmpTm;
-
- tmpTm = g_new0( struct tm, 1 );
-
- g_date_to_struct_tm( ldd->ld.startDate, tmpTm );
- gnc_date_edit_set_time( ldd->prmStartDateGDE,
- mktime(tmpTm) );
- g_free( tmpTm );
- }
-
- /* length: total and remaining */
- {
- gtk_spin_button_set_value( ldd->prmLengthSpin, ldd->ld.numPer );
- gtk_combo_box_set_active( ldd->prmLengthType, ldd->ld.perSize );
- gtk_spin_button_set_value( ldd->prmRemainSpin, ldd->ld.numMonRemain );
- }
-}
-
-static
-gboolean
-ld_opts_save_state( LoanDruidData *ldd )
-{
- if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ldd->optEscrowCb) ) )
- {
- ldd->ld.escrowAcct =
- gnc_account_sel_get_account( ldd->optEscrowGAS );
- if ( ldd->ld.escrowAcct == NULL )
- {
- gnc_info_dialog( ldd->dialog, "%s",
- _("Please select a valid "
- "Escrow Account.") );
- return TRUE;
- }
-
- }
- else
- {
- ldd->ld.escrowAcct = NULL;
- }
- return FALSE;
-}
-
-static
-gboolean
-ld_opts_tran( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- return ld_opts_save_state( (LoanDruidData*)ud );
-}
-
-static
-void
-ld_opts_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- int i;
- RepayOptUIData *rouid;
- LoanDruidData *ldd;
-
- ldd = (LoanDruidData*)ud;
- if ( ldd->ld.escrowAcct )
- {
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->optEscrowCb),
- TRUE );
- gnc_account_sel_set_account( ldd->optEscrowGAS, ldd->ld.escrowAcct, FALSE );
- }
- for ( i = 0; i < ldd->ld.repayOptCount; i++ )
- {
- rouid = ldd->repayOptsUI[i];
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rouid->optCb),
- rouid->optData->enabled );
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rouid->escrowCb),
- rouid->optData->throughEscrowP
- && rouid->optData->enabled
- && ldd->ld.escrowAcct );
- gtk_widget_set_sensitive( GTK_WIDGET(rouid->escrowCb),
- rouid->optData->enabled
- && ldd->ld.escrowAcct );
- }
-}
-
-static
-gboolean
-ld_rep_save( LoanDruidData *ldd )
-{
- int i;
-
- if ( ldd->ld.repMemo )
- g_free( ldd->ld.repMemo );
- ldd->ld.repMemo =
- gtk_editable_get_chars( GTK_EDITABLE(ldd->repTxnName), 0, -1 );
-
- if ( ldd->ld.repAmount )
- g_free( ldd->ld.repAmount );
- ldd->ld.repAmount =
- gtk_editable_get_chars( GTK_EDITABLE(ldd->repAmtEntry), 0, -1 );
-
- ldd->ld.repFromAcct =
- gnc_account_sel_get_account( ldd->repAssetsFromGAS );
- if ( ldd->ld.repFromAcct == NULL )
- {
- gnc_info_dialog( ldd->dialog, "%s",
- _("Please select a valid \"from\" account."));
- return TRUE;
- }
- ldd->ld.repPriAcct =
- gnc_account_sel_get_account( ldd->repPrincToGAS );
- if ( ldd->ld.repPriAcct == NULL )
- {
- gnc_info_dialog( ldd->dialog, "%s",
- _("Please select a valid \"to\" account.") );
- return TRUE;
- }
- ldd->ld.repIntAcct =
- gnc_account_sel_get_account( ldd->repIntToGAS );
- if ( ldd->ld.repIntAcct == NULL )
- {
- gnc_info_dialog( ldd->dialog, "%s",
- _("Please select a valid "
- "\"interest\" account.") );
- return TRUE;
- }
- recurrenceListFree(&ldd->ld.repayment_schedule);
- gnc_frequency_save_to_recurrence(ldd->repGncFreq,
- &ldd->ld.repayment_schedule,
- ldd->ld.repStartDate);
-
- /* Set the 'from' accounts of the various options to be the
- * Assets-From account, if they're not already something else. */
- for ( i = 0; i < ldd->ld.repayOptCount; i++ )
- {
- RepayOptData *rod = ldd->ld.repayOpts[i];
- if ( ! rod->from )
- {
- rod->from = ldd->ld.repFromAcct;
- }
- }
- return FALSE;
-}
-
-static
-gboolean
-ld_rep_next( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- LoanDruidData *ldd;
-
- ldd = (LoanDruidData*)ud;
-
- if ( ld_rep_save( ldd ) != FALSE )
- {
- DEBUG( "Couldn't save, stopping here." );
- return TRUE;
- }
-
- {
- int i;
- for ( i = 0; // we can always start at 0, here.
- (i < ldd->ld.repayOptCount)
- && !ldd->ld.repayOpts[i]->enabled;
- i++ )
- ;
- if ( i < ldd->ld.repayOptCount )
- {
- ldd->currentIdx = i;
- return FALSE;
- }
- }
- gnome_druid_set_page( ldd->druid,
- GNOME_DRUID_PAGE(
- glade_xml_get_widget( ldd->gxml,
- PG_REVIEW ) ) );
- return TRUE;
-}
-
-static
-gboolean
-ld_rep_back( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- LoanDruidData *ldd;
-
- ldd = (LoanDruidData*)ud;
- return ld_rep_save(ldd);
-}
-
-static
-void
-ld_rep_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- LoanDruidData *ldd;
- GString *str;
-
-
- ldd = (LoanDruidData*)ud;
-
- if ( ldd->ld.repAmount )
- {
- g_free( ldd->ld.repAmount );
- }
-
- str = g_string_sized_new( 64 );
- ld_get_pmt_formula( ldd, str);
- ldd->ld.repAmount = str->str;
- g_string_free( str, FALSE );
-
- if ( ldd->ld.repMemo )
- gtk_entry_set_text( ldd->repTxnName, ldd->ld.repMemo );
-
- if ( ldd->ld.repAmount )
- gtk_entry_set_text( ldd->repAmtEntry, ldd->ld.repAmount );
-
- gnc_account_sel_set_account( ldd->repAssetsFromGAS,
- ldd->ld.repFromAcct, FALSE );
- gnc_account_sel_set_account( ldd->repPrincToGAS,
- ldd->ld.repPriAcct, FALSE );
- gnc_account_sel_set_account( ldd->repIntToGAS,
- ldd->ld.repIntAcct, FALSE );
- gnc_frequency_setup_recurrence(ldd->repGncFreq,
- ldd->ld.repayment_schedule,
- ldd->ld.repStartDate);
-}
-
-static
-void
-ld_pay_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- LoanDruidData *ldd;
- RepayOptData *rod;
- GString *str;
- gboolean uniq;
-
- ldd = (LoanDruidData*)ud;
- g_assert( ldd->currentIdx >= 0 );
- g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
-
- rod = ldd->ld.repayOpts[ldd->currentIdx];
- str = g_string_sized_new( 32 );
- /* Translators: %s is "Taxes", or "Insurance", or similar */
- g_string_printf( str, _("Payment: \"%s\""), rod->name );
- gnome_druid_page_standard_set_title( GNOME_DRUID_PAGE_STANDARD(gdp),
- str->str );
- /* copy in the relevant data from the currently-indexed
- * option. */
- gtk_entry_set_text( ldd->payTxnName, rod->txnMemo );
- g_string_printf( str, "%0.2f", rod->amount );
- gtk_entry_set_text( ldd->payAmtEntry, str->str );
-
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->payUseEscrow),
- (ldd->ld.escrowAcct != NULL) );
-
- {
- g_signal_handlers_block_by_func( ldd->payUseEscrow,
- ld_pay_use_esc_toggle,
- ldd );
-
- ld_pay_use_esc_setup( ldd,
- (ldd->ld.escrowAcct != NULL)
- && rod->throughEscrowP );
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payUseEscrow),
- (rod->throughEscrowP
- && ldd->ld.escrowAcct != NULL) );
-
- g_signal_handlers_unblock_by_func( ldd->payUseEscrow,
- ld_pay_use_esc_toggle,
- ldd );
- }
-
- {
- g_signal_handlers_block_by_func( ldd->paySpecSrcAcct,
- ld_pay_spec_src_toggle,
- ldd );
-
- ld_pay_spec_src_setup( ldd, rod->specSrcAcctP );
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->paySpecSrcAcct),
- rod->specSrcAcctP );
-
- g_signal_handlers_unblock_by_func( ldd->paySpecSrcAcct,
- ld_pay_spec_src_toggle,
- ldd );
- }
-
- gnc_account_sel_set_account( ldd->payAcctToGAS, rod->to, FALSE );
-
- uniq = (rod->schedule != NULL);
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqPartRb),
- !uniq );
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb),
- uniq );
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->payFreqAlign),
- uniq );
- if ( uniq )
- {
- gnc_frequency_setup_recurrence( ldd->payGncFreq, rod->schedule, rod->startDate );
- }
-
- g_string_free( str, TRUE );
-}
-
-static
-gboolean
-ld_pay_save_current( LoanDruidData *ldd )
-{
- gchar *tmpStr;
- RepayOptData *rod;
-
- g_assert( ldd->currentIdx >= 0 );
- g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
- rod = ldd->ld.repayOpts[ ldd->currentIdx ];
-
- tmpStr = gtk_editable_get_chars( GTK_EDITABLE(ldd->payTxnName),
- 0, -1 );
- if ( rod->txnMemo != NULL )
- {
- g_free( rod->txnMemo );
- }
- rod->txnMemo = tmpStr;
- tmpStr = NULL;
-
- tmpStr = gtk_editable_get_chars( GTK_EDITABLE(ldd->payAmtEntry),
- 0, -1 );
- rod->amount = (float)strtod( tmpStr, NULL );
- g_free( tmpStr );
-
- rod->specSrcAcctP =
- gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(ldd->paySpecSrcAcct) );
-
- rod->from = NULL;
- if ( rod->specSrcAcctP )
- {
- rod->from = gnc_account_sel_get_account( ldd->payAcctFromGAS );
- if ( rod->from == NULL )
- {
- gnc_info_dialog( ldd->dialog, "%s",
- _("Please select a valid "
- "\"from\" account.") );
- return TRUE;
- }
- }
-
- rod->to = gnc_account_sel_get_account( ldd->payAcctToGAS );
- if ( rod->to == NULL )
- {
- gnc_info_dialog( ldd->dialog, "%s",
- _("Please select a valid "
- "\"to\" account.") );
- return TRUE;
- }
-
- /* if ( rb toggled )
- * ensure schedule/startdate setup
- * save
- * else
- * if (freqspec setup)
- * remove schedule/startdate
- */
-
- /* neither of these should happen. */
- g_assert( ! (rod->schedule && !rod->startDate) );
- g_assert( ! (!rod->schedule && rod->startDate) );
-
- if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb)) )
- {
- if ( rod->startDate == NULL )
- {
- rod->startDate = g_date_new();
- }
- recurrenceListFree(&rod->schedule);
- gnc_frequency_save_to_recurrence(ldd->payGncFreq,
- &rod->schedule,
- rod->startDate);
- }
- else
- {
- if (rod->schedule)
- {
- recurrenceListFree(&rod->schedule);
- }
- if ( rod->startDate )
- {
- g_date_free( rod->startDate );
- rod->startDate = NULL;
- }
- }
- return FALSE;
-}
-
-static
-gboolean
-ld_pay_next( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- int i;
- LoanDruidData *ldd;
-
- ldd = (LoanDruidData*)ud;
- /* save current data */
- if ( ld_pay_save_current( ldd ) != FALSE )
- {
- return TRUE;
- }
-
- /* Go through opts list and select next enabled option. */
- for ( i = ldd->currentIdx + 1;
- (i < ldd->ld.repayOptCount)
- && !ldd->ld.repayOpts[i]->enabled; i++ )
- ;
-
- if ( i < ldd->ld.repayOptCount )
- {
- ldd->currentIdx = i;
- ld_pay_prep( gdp, arg1, ud );
- return TRUE;
- }
-
- /* If there's no repayment options enabled, then go immediately to
- * the review page. */
- gnome_druid_set_page( ldd->druid,
- GNOME_DRUID_PAGE(
- glade_xml_get_widget( ldd->gxml,
- PG_REVIEW ) ) );
- return TRUE;
-}
-
-static
-gboolean
-ld_pay_back( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- int i;
- LoanDruidData *ldd;
-
- ldd = (LoanDruidData*)ud;
-
- /* save current data */
- if ( ld_pay_save_current( ldd ) != FALSE )
- {
- return TRUE;
- }
-
- /* go back through opts list and select next enabled options. */
- for ( i = ldd->currentIdx - 1;
- (i > -1) && !ldd->ld.repayOpts[i]->enabled;
- i-- )
- ;
- if ( i >= 0 )
- {
- ldd->currentIdx = i;
- ld_pay_prep( gdp, arg1, ud );
- return TRUE;
- }
- ldd->currentIdx = -1;
- return FALSE;
-}
-
-static
-void
-ld_pay_freq_toggle( GtkToggleButton *tb, gpointer ud )
-{
- LoanDruidData *ldd;
- gboolean uniq;
-
- ldd = (LoanDruidData*)ud;
-
- g_assert( ldd->currentIdx >= 0 );
- g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
-
- uniq = gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb) );
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->payFreqAlign), uniq );
-
- if ( uniq )
- {
- RepayOptData *rod;
- rod = ldd->ld.repayOpts[ ldd->currentIdx ];
-
- if ( rod->schedule == NULL )
- {
- Recurrence *r = g_new0(Recurrence, 1);
- recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate, WEEKEND_ADJ_NONE);
- rod->schedule = g_list_append(rod->schedule, r);
- }
- if ( rod->startDate == NULL )
- {
- rod->startDate = g_date_new();
- *rod->startDate = *ldd->ld.startDate;
- }
- gnc_frequency_setup_recurrence(ldd->payGncFreq,
- rod->schedule,
- rod->startDate);
- }
-}
-
-static
-void
-ld_pay_use_esc_setup( LoanDruidData *ldd, gboolean newState )
-{
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->payEscToLabel), newState );
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->payEscFromLabel), newState );
- if ( newState )
- {
- gnc_account_sel_set_account( ldd->payAcctEscToGAS,
- ldd->ld.escrowAcct, FALSE );
- gnc_account_sel_set_account( ldd->payAcctEscFromGAS,
- ldd->ld.escrowAcct, FALSE );
- }
-}
-
-static
-void
-ld_pay_use_esc_toggle( GtkToggleButton *tb, gpointer ud )
-{
- gboolean newState;
- LoanDruidData *ldd = (LoanDruidData*)ud;
-
- newState = gtk_toggle_button_get_active( tb );
- ld_pay_use_esc_setup( ldd, newState );
-}
-
-static
-void
-ld_pay_spec_src_setup( LoanDruidData *ldd, gboolean newState )
-{
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctFromLabel), newState );
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctFromGAS), newState );
- if ( newState )
- {
- gnc_account_sel_set_account( ldd->payAcctFromGAS,
- ldd->ld.repayOpts[ldd->currentIdx]
- ->from, FALSE );
- }
-}
-
-static
-void
-ld_pay_spec_src_toggle( GtkToggleButton *tb, gpointer ud )
-{
- gboolean newState;
- LoanDruidData *ldd = (LoanDruidData*)ud;
-
- newState = gtk_toggle_button_get_active( tb );
- ld_pay_spec_src_setup( ldd, newState );
-}
-
-static
-gboolean
-ld_rev_next( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- LoanDruidData *ldd;
-
- ldd = (LoanDruidData*)ud;
- gnome_druid_set_page( ldd->druid,
- GNOME_DRUID_PAGE(
- glade_xml_get_widget( ldd->gxml,
- PG_COMMIT ) ) );
- return TRUE;
-}
-
-static
-void
-ld_rev_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- /* 3, here, does not include the Date column. */
- const static int BASE_COLS = 3;
- LoanDruidData *ldd;
- GtkListStore *store;
- GtkCellRenderer *renderer;
- GtkTreeViewColumn *column;
- GType *types;
- int i;
-
- ldd = (LoanDruidData*)ud;
-
- /* Cleanup old view */
- if ( ldd->revView != NULL )
- {
- gtk_widget_destroy( GTK_WIDGET(ldd->revView) );
- ldd->revView = NULL;
- }
-
- ldd->ld.revNumPmts = BASE_COLS;
- /* Get the correct number of repayment columns. */
- for ( i = 0; i < ldd->ld.repayOptCount; i++ )
- {
- ldd->ld.revRepayOptToColMap[i] = -1;
- if ( ! ldd->ld.repayOpts[i]->enabled )
- {
- continue;
- }
- /* not '+1' = there is no date column to be accounted for in
- * the mapping. */
- ldd->ld.revRepayOptToColMap[i] = ldd->ld.revNumPmts;
- ldd->ld.revNumPmts += 1;
- }
-
- /* '+1' for leading date col */
- types = g_new( GType, ldd->ld.revNumPmts + 1 );
- for ( i = 0; i < ldd->ld.revNumPmts + 1; i++ )
- types[i] = G_TYPE_STRING;
- store = gtk_list_store_newv(ldd->ld.revNumPmts + 1, types);
- g_free(types);
-
- ldd->revView = GTK_TREE_VIEW(
- gtk_tree_view_new_with_model( GTK_TREE_MODEL(store) ));
- g_object_unref(store);
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Date"), renderer,
- "text", LOAN_COL_DATE,
- NULL);
- gtk_tree_view_append_column(ldd->revView, column);
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Payment"), renderer,
- "text", LOAN_COL_PAYMENT,
- NULL);
- gtk_tree_view_append_column(ldd->revView, column);
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Principal"), renderer,
- "text", LOAN_COL_PRINCIPAL,
- NULL);
- gtk_tree_view_append_column(ldd->revView, column);
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes(_("Interest"), renderer,
- "text", LOAN_COL_INTEREST,
- NULL);
- gtk_tree_view_append_column(ldd->revView, column);
-
- /* move the appropriate names over into the title array */
- {
- for ( i = 0; i < ldd->ld.repayOptCount; i++ )
- {
- if ( ldd->ld.revRepayOptToColMap[i] == -1 )
- {
- continue;
- }
-
- renderer = gtk_cell_renderer_text_new();
- column = gtk_tree_view_column_new_with_attributes
- (ldd->ld.repayOpts[i]->name, renderer,
- "text", LOAN_COL_INTEREST + i,
- NULL);
- gtk_tree_view_append_column(ldd->revView, column);
- }
- }
-
- gtk_container_add( GTK_CONTAINER(ldd->revScrollWin),
- GTK_WIDGET(ldd->revView) );
- gtk_widget_show( GTK_WIDGET(ldd->revView) );
-
- ld_rev_recalc_schedule( ldd );
-
- {
- GDate start, end;
- g_date_clear( &start, 1 );
- g_date_clear( &end, 1 );
- ld_rev_get_dates( ldd, &start, &end );
- ld_rev_update_view( ldd, &start, &end );
- }
-}
-
-static
-gboolean
-ld_rev_back( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- LoanDruidData *ldd = (LoanDruidData*)ud;
- int i;
-
- /* Get the correct page based on the repayment state. */
- /* go back through opts list and select next enabled options. */
- for ( i = ldd->currentIdx;
- (i > -1) && !ldd->ld.repayOpts[i]->enabled;
- i-- )
- ;
- if ( i >= 0 )
- {
- ldd->currentIdx = i;
- /* natural transition to the payments page */
- return FALSE;
- }
-
- /* If there are no payment options, then go directly to the main
- * repayment page. */
- gnome_druid_set_page( ldd->druid,
- GNOME_DRUID_PAGE(
- glade_xml_get_widget( ldd->gxml,
- PG_REPAYMENT ) ) );
- return TRUE;
-}
-
-static
-gboolean
-ld_com_next( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- g_assert( FALSE );
- return TRUE;
-}
-
-static
-void
-ld_com_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
-}
-
-static
-gboolean
-ld_com_back( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- LoanDruidData *ldd = (LoanDruidData*)ud;
- gnome_druid_set_page( ldd->druid,
- GNOME_DRUID_PAGE(
- glade_xml_get_widget( ldd->gxml,
- PG_REVIEW ) ) );
- return TRUE;
-}
-
-static
-void
-ld_com_fin( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
-{
- LoanDruidData *ldd = (LoanDruidData*)ud;
- ld_create_sxes( ldd );
- ld_close_handler( ldd );
-
-}
-
-static int
-ld_calc_sx_instance_num(GDate *start_date, GList *schedule)
-{
- int instance_count;
- GDate next_date, today;
-
- g_date_clear(&next_date, 1);
- g_date_clear(&today, 1);
- g_date_set_time_t(&today, time(NULL));
-
- if (g_date_compare(start_date, &today) > 0)
- return 0;
-
- instance_count = -1;
- do
- {
- instance_count++;
- recurrenceListNextInstance(schedule, start_date, &next_date);
- }
- while (g_date_compare(&next_date, &today) < 0);
-
- return instance_count;
-}
-
-static
-void
-ld_tcSX_free( gpointer data, gpointer user_data )
-{
- toCreateSX *tcSX = (toCreateSX*)data;
- g_free( tcSX->name );
- if ( tcSX->mainTxn )
- gnc_ttinfo_free( tcSX->mainTxn );
- if ( tcSX->escrowTxn )
- gnc_ttinfo_free( tcSX->escrowTxn );
- g_free( tcSX );
-}
-
-/**
- * Custom GCompareFunc to find the element of a GList of TTSplitInfo's which
- * has the given [Account*] criteria.
- * @return 0 if match, as per GCompareFunc in the g_list_find_custom context.
- **/
-static
-gint
-ld_find_ttsplit_with_acct( gconstpointer elt,
- gconstpointer crit )
-{
- TTSplitInfo *ttsi = (TTSplitInfo*)elt;
- return ( (gnc_ttsplitinfo_get_account( ttsi )
- == (Account*)crit) ? 0 : 1 );
-}
-
-/**
- * Enters into the books a Scheduled Transaction from the given toCreateSX.
- **/
-static
-void
-ld_create_sx_from_tcSX( LoanDruidData *ldd, toCreateSX *tcSX )
-{
- SchedXaction *sx;
- SchedXactions *sxes;
- GList *ttxnList;
-
- sx = xaccSchedXactionMalloc( gnc_get_current_book() );
- xaccSchedXactionSetName( sx, tcSX->name );
- gnc_sx_set_schedule(sx, tcSX->schedule);
- xaccSchedXactionSetStartDate( sx, &tcSX->start );
- xaccSchedXactionSetLastOccurDate( sx, &tcSX->last );
- xaccSchedXactionSetEndDate( sx, &tcSX->end );
- gnc_sx_set_instance_count( sx, tcSX->instNum );
-
- ttxnList = NULL;
- if ( tcSX->mainTxn )
- ttxnList = g_list_append( ttxnList, tcSX->mainTxn );
- if ( tcSX->escrowTxn )
- ttxnList = g_list_append( ttxnList, tcSX->escrowTxn );
-
- g_assert( ttxnList != NULL );
-
- xaccSchedXactionSetTemplateTrans( sx, ttxnList,
- gnc_get_current_book() );
-
- sxes = gnc_book_get_schedxactions(gnc_get_current_book());
- gnc_sxes_add_sx(sxes, sx);
-
- g_list_free( ttxnList );
- ttxnList = NULL;
-}
-
-/**
- * Does the work to setup the given toCreateSX structure for a specific
- * repayment. Note that if the RepayOptData doesn't specify a unique
- * schedule, the paymentSX and the tcSX parameters will be the same.
- **/
-static
-void
-ld_setup_repayment_sx( LoanDruidData *ldd,
- RepayOptData *rod,
- toCreateSX *paymentSX,
- toCreateSX *tcSX )
-{
- /* In DoubleEntryAccounting-ease, this is what we're going to do,
- * below...
- *
- * if ( rep->escrow ) {
- * if ( rep->from ) {
- * a: paymentSX.main.splits += split( rep->fromAcct, repAmt )
- * b: paymentSX.main.split( ldd->ld.escrowAcct ).debCred += repAmt
- * tcSX.escrow.split( rep->escrow ).debCred += repAmt
- * c1: tcSX.escrow.splits += split( rep->toAcct, +repAmt )
- * } else {
- * d: paymentSX.main.split( ldd->ld.repFromAcct ).debcred += -repAmt
- * b: paymentSX.main.split( ldd->ld.escrowAcct ).debCred += repAmt
- * tcSX.escrow.splits += split( rep->escrow, -repAmt )
- * c1: tcSX.escrow.splits += split( rep->toAcct, +repAmt )
- * }
- * } else {
- * if ( rep->from ) {
- * a: paymentSX.main.splits += split( rep->fromAcct, -repAmt )
- * c2: paymentSX.main.splits += split( rep->toAcct, +repAmt )
- * } else {
- * d: paymentSX.main.split( ldd->ld.payFromAcct ).debcred += -repAmt
- * c2: paymentSX.main.splits += split( rep->toAcct, +repAmt )
- * }
- * }
- */
-
- /* Now, we refactor the common operations from the above out...
- *
- * fromSplit = NULL;
- * if ( rep->escrow ) {
- * b: paymentSX.main.split( ldd->ld.escrowAcct ).debCred += repAmt
- * c1: ( toTTI = tcSX.escrow )
- * if ( rep->from ) {
- * a1: (fromSplit = NULL) paymentSX.main.splits += split( rep->fromAcct, repAmt )
- * b:
- * tcSX.escrow.split( rep->escrow ).debCred += repAmt
- * c1:
- * } else {
- * a2: (fromSplit = paymentSX.main.split( ldd->ld.repFromAcct )) .debcred += -repAmt
- * b:
- * tcSX.escrow.splits += split( rep->escrow, -repAmt )
- * c1:
- * }
- * } else {
- * c2: ( toTTI = paymentSX.main )
- * if ( rep->from ) {
- * a1: (fromSplit = NULL) paymentSX.main.splits += split( rep->fromAcct, -repAmt )
- * c2:
- * } else {
- * a2: (fromSplit = paymentSX.main.split( ldd->ld.payFromAcct )).debcred += -repAmt
- * c2:
- * }
- * }
- * if ( fromSplit ) {
- * fromSplit.debCred += (-repAmt);
- * } else {
- * fromSplit = split( rep->fromAcct, -repAmt )
- * paymentSX.main.splits += fromSplit
- * }
- * toTTI.splits += split( rep->toAcct, +repAmt );
- */
-
- /** Now, the actual implementation... */
-
- GString *gstr;
- GList *elt;
- TTSplitInfo *fromSplit = NULL;
- TTSplitInfo *ttsi;
- TTInfo *toTxn = NULL;
- GNCPrintAmountInfo pricePAI = gnc_default_price_print_info();
-#define AMTBUF_LEN 64
- gchar amtBuf[AMTBUF_LEN];
- gint GNCN_HOW = (GNC_HOW_DENOM_SIGFIGS(2) | GNC_HOW_RND_ROUND_HALF_UP);
-
- /* We're going to use this a lot, below, so just create it once. */
- xaccSPrintAmount( amtBuf,
- double_to_gnc_numeric( rod->amount, 100,
- GNCN_HOW ),
- pricePAI );
-
- if ( rod->throughEscrowP && ldd->ld.escrowAcct )
- {
- toTxn = tcSX->escrowTxn;
-
- /* Add the repayment amount into the string of the existing
- * ttsplit. */
- {
- elt = g_list_find_custom(
- gnc_ttinfo_get_template_splits( paymentSX->mainTxn ),
- ldd->ld.escrowAcct,
- ld_find_ttsplit_with_acct );
- g_assert( elt );
- ttsi = (TTSplitInfo*)elt->data;
- g_assert( ttsi );
- gstr = g_string_new( gnc_ttsplitinfo_get_debit_formula( ttsi ) );
- g_string_append_printf( gstr, " + %s", amtBuf );
- gnc_ttsplitinfo_set_debit_formula( ttsi, gstr->str );
- g_string_free( gstr, TRUE );
- gstr = NULL;
- ttsi = NULL;
- }
-
- if ( rod->from != NULL )
- {
- gchar *str;
-
- fromSplit = NULL;
-
- /* tcSX.escrow.split( rep->escrow ).debCred += repAmt */
- elt = g_list_find_custom(
- gnc_ttinfo_get_template_splits( tcSX->escrowTxn ),
- ldd->ld.escrowAcct,
- ld_find_ttsplit_with_acct );
- ttsi = NULL;
- if ( elt )
- {
- ttsi = (TTSplitInfo*)elt->data;
- }
- if ( !ttsi )
- {
- /* create split */
- ttsi = gnc_ttsplitinfo_malloc();
- gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
- gnc_ttsplitinfo_set_account( ttsi, ldd->ld.escrowAcct );
- gnc_ttinfo_append_template_split( tcSX->escrowTxn, ttsi );
- }
- if ( (str = (gchar*)gnc_ttsplitinfo_get_credit_formula( ttsi ))
- == NULL )
- {
- gstr = g_string_sized_new( 16 );
- }
- else
- {
- /* If we did get a split/didn't have to
- * create a split, then we need to add our
- * amount in rather than replace. */
- gstr = g_string_new( str );
- g_string_append_printf( gstr, " + " );
- }
- g_string_append_printf( gstr, "%s", amtBuf );
- gnc_ttsplitinfo_set_credit_formula( ttsi, gstr->str );
- g_string_free( gstr, TRUE );
- gstr = NULL;
- ttsi = NULL;
- }
- else
- {
- /* (fromSplit = paymentSX.main.split( ldd->ld.repFromAcct )) */
- elt = g_list_find_custom(
- gnc_ttinfo_get_template_splits( paymentSX->mainTxn ),
- ldd->ld.repFromAcct,
- ld_find_ttsplit_with_acct );
- g_assert( elt );
- fromSplit = (TTSplitInfo*)elt->data;
-
- /* tcSX.escrow.splits += split( rep->escrow, -repAmt ) */
- ttsi = gnc_ttsplitinfo_malloc();
- gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
- gnc_ttsplitinfo_set_account( ttsi, ldd->ld.escrowAcct );
- gnc_ttsplitinfo_set_credit_formula( ttsi, amtBuf );
- gnc_ttinfo_append_template_split( tcSX->escrowTxn, ttsi );
- ttsi = NULL;
- }
- }
- else
- {
- toTxn = tcSX->mainTxn;
-
- if ( rod->from != NULL )
- {
- fromSplit = NULL;
- }
- else
- {
- /* (fromSplit = paymentSX.main.split( ldd->ld.repFromAcct )) */
- elt = g_list_find_custom(
- gnc_ttinfo_get_template_splits( tcSX->mainTxn ),
- ldd->ld.repFromAcct,
- ld_find_ttsplit_with_acct );
- fromSplit = NULL;
- if ( elt )
- {
- /* This is conditionally true in the case of
- * a repayment on it's own schedule. */
- fromSplit = (TTSplitInfo*)elt->data;
- }
- }
- }
-
- if ( fromSplit != NULL )
- {
- /* Update the existing from-split. */
- gstr = g_string_new( gnc_ttsplitinfo_get_credit_formula( fromSplit ) );
- g_string_append_printf( gstr, " + %s", amtBuf );
- gnc_ttsplitinfo_set_credit_formula( fromSplit, gstr->str );
- g_string_free( gstr, TRUE );
- gstr = NULL;
-
- }
- else
- {
- TTInfo *tti;
- /* Create a new from-split. */
- ttsi = gnc_ttsplitinfo_malloc();
- gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
- if ( rod->from )
- {
- gnc_ttsplitinfo_set_account( ttsi, rod->from );
- }
- else
- {
- gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repFromAcct );
- }
- gnc_ttsplitinfo_set_credit_formula( ttsi, amtBuf );
- tti = tcSX->mainTxn;
- if ( rod->throughEscrowP )
- {
- tti = paymentSX->mainTxn;
- }
- gnc_ttinfo_append_template_split( tti, ttsi );
- ttsi = NULL;
- tti = NULL;
- }
-
- /* Add to-account split. */
- {
- ttsi = gnc_ttsplitinfo_malloc();
- gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
- gnc_ttsplitinfo_set_account( ttsi, rod->to );
- gnc_ttsplitinfo_set_debit_formula( ttsi, amtBuf );
- gnc_ttinfo_append_template_split( toTxn, ttsi );
- ttsi = NULL;
- }
-}
-
-/**
- * Actually does the heavy-lifting of creating the SXes from the
- * LoanDruidData.
- *
- * Rules:
- * - There is at least one SX created, with at least one txn, for the loan
- * payment itself.
- * - A new SX is created for each repayment with a different frequency.
- * - Non-unique repayment From-accounts cause a "summed (src-)split", unique
- * repayment From-accounts cause new (src-)splits.
- * - Each repayment causes a new (dst-)split [the To-account].
- * - Escrow-diverted repayments cause new Txns w/in their
- * SX. [Assets->Escrow, Escrow->(Expense|Liability)]
- **/
-static
-void
-ld_create_sxes( LoanDruidData *ldd )
-{
- /* The main loan-payment SX.*/
- toCreateSX *paymentSX = NULL;
- /* A GList of any other repayment SXes with different schedule. */
- GList *repaySXes = NULL;
- /* The currently-being-referenced toCreateSX. */
- toCreateSX *tcSX;
- int i;
- TTInfo *ttxn;
- TTSplitInfo *ttsi;
- GString *gstr;
-
- paymentSX = g_new0( toCreateSX, 1 );
- paymentSX->name = g_strdup(ldd->ld.repMemo);
- paymentSX->start = *ldd->ld.startDate;
- paymentSX->last = *ldd->ld.repStartDate;
- g_date_subtract_months( &paymentSX->last, 1 );
- {
- paymentSX->end = *ldd->ld.repStartDate;
- g_date_add_months( &paymentSX->end, ldd->ld.numMonRemain - 1);
- }
- paymentSX->schedule = ldd->ld.repayment_schedule;
- /* Figure out the correct current instance-count for the txns in the
- * SX. */
- paymentSX->instNum =
- (ldd->ld.numPer * ( ldd->ld.perSize == GNC_YEARS ? 12 : 1 ))
- - ldd->ld.numMonRemain + 1;
-
- paymentSX->mainTxn = gnc_ttinfo_malloc();
- gnc_ttinfo_set_currency( paymentSX->mainTxn,
- gnc_default_currency() );
- {
- GString *payMainTxnDesc = g_string_sized_new( 32 );
- g_string_printf( payMainTxnDesc,
- "%s - %s",
- ldd->ld.repMemo,
- ( ldd->ld.escrowAcct == NULL
- ? _("Payment")
- : _("Escrow Payment") )
- );
-
- gnc_ttinfo_set_description( paymentSX->mainTxn,
- payMainTxnDesc->str );
- g_string_free( payMainTxnDesc, TRUE );
- }
-
- /* Create the basic txns and splits...
- *
- * ttxn <- mainTxn
- * srcAcct <- assets
- * if ( escrow ) {
- * realSrcAcct <- srcAcct
- * srcAcct <- escrow;
- * ttxn <- escrowTxn
- * main.splits += split( realSrcAcct, -pmt )
- * main.splits += split( escrow, pmt )
- * }
- * ttxn.splits += split( escrow, -pmt)
- * ttxn.splits += split( liability, ppmt )
- * ttxn.splits += split( expenses:interest, ipmt ) */
-
- {
- Account *srcAcct;
-
- ttxn = paymentSX->mainTxn;
- srcAcct = ldd->ld.repFromAcct;
-
- if ( ldd->ld.escrowAcct != NULL )
- {
- Account *realSrcAcct = srcAcct;
- srcAcct = ldd->ld.escrowAcct;
-
- gstr = g_string_sized_new( 32 );
- ld_get_pmt_formula( ldd, gstr );
- /* ttxn.splits += split( realSrcAcct, -pmt ); */
- {
- ttsi = gnc_ttsplitinfo_malloc();
- gnc_ttsplitinfo_set_memo( ttsi, ldd->ld.repMemo );
- gnc_ttsplitinfo_set_account( ttsi, realSrcAcct );
- gnc_ttsplitinfo_set_credit_formula( ttsi, gstr->str );
- gnc_ttinfo_append_template_split( ttxn, ttsi );
- ttsi = NULL;
- }
-
- /* ttxn.splits += split( escrowAcct, +pmt ); */
- {
- ttsi = gnc_ttsplitinfo_malloc();
- gnc_ttsplitinfo_set_memo( ttsi, ldd->ld.repMemo );
- gnc_ttsplitinfo_set_account( ttsi, ldd->ld.escrowAcct );
- gnc_ttsplitinfo_set_debit_formula( ttsi, gstr->str );
- gnc_ttinfo_append_template_split( ttxn, ttsi );
- ttsi = NULL;
- }
- g_string_free( gstr, TRUE );
- gstr = NULL;
-
- paymentSX->escrowTxn = gnc_ttinfo_malloc();
- gnc_ttinfo_set_currency( paymentSX->escrowTxn,
- gnc_default_currency() );
-
- {
- GString *escrowTxnDesc;
- escrowTxnDesc = g_string_new( ldd->ld.repMemo );
- g_string_append_printf( escrowTxnDesc, " - %s", _("Payment") );
- gnc_ttinfo_set_description( paymentSX->escrowTxn,
- escrowTxnDesc->str );
- g_string_free( escrowTxnDesc, TRUE );
- }
- ttxn = paymentSX->escrowTxn;
- }
-
- /* ttxn.splits += split( srcAcct, -pmt ); */
- {
- ttsi = gnc_ttsplitinfo_malloc();
- {
- gstr = g_string_new( ldd->ld.repMemo );
- g_string_append_printf( gstr, " - %s",
- _("Payment") );
- gnc_ttsplitinfo_set_memo( ttsi, gstr->str );
- g_string_free( gstr, TRUE );
- gstr = NULL;
- }
- gnc_ttsplitinfo_set_account( ttsi, srcAcct );
- gstr = g_string_sized_new( 32 );
- ld_get_pmt_formula( ldd, gstr );
- gnc_ttsplitinfo_set_credit_formula( ttsi, gstr->str );
- gnc_ttinfo_append_template_split( ttxn, ttsi );
- g_string_free( gstr, TRUE );
- gstr = NULL;
- ttsi = NULL;
- }
-
- /* ttxn.splits += split( ldd->ld.repPriAcct, +ppmt ); */
- {
- ttsi = gnc_ttsplitinfo_malloc();
- {
- gstr = g_string_new( ldd->ld.repMemo );
- g_string_append_printf( gstr, " - %s",
- _("Principal") );
- gnc_ttsplitinfo_set_memo( ttsi, gstr->str );
- g_string_free( gstr, TRUE );
- gstr = NULL;
- }
- gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repPriAcct );
- gstr = g_string_sized_new( 32 );
- ld_get_ppmt_formula( ldd, gstr );
- gnc_ttsplitinfo_set_debit_formula( ttsi, gstr->str );
- gnc_ttinfo_append_template_split( ttxn, ttsi );
- g_string_free( gstr, TRUE );
- gstr = NULL;
- ttsi = NULL;
- }
-
- /* ttxn.splits += split( ldd->ld.repIntAcct, +ipmt ); */
- {
- ttsi = gnc_ttsplitinfo_malloc();
- {
- gstr = g_string_new( ldd->ld.repMemo );
- g_string_append_printf( gstr, " - %s",
- _("Interest") );
- gnc_ttsplitinfo_set_memo( ttsi, gstr->str );
- g_string_free( gstr, TRUE );
- gstr = NULL;
- }
- gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repIntAcct );
- gstr = g_string_sized_new( 32 );
- ld_get_ipmt_formula( ldd, gstr );
- gnc_ttsplitinfo_set_debit_formula( ttsi, gstr->str );
- gnc_ttinfo_append_template_split( ttxn, ttsi );
- g_string_free( gstr, TRUE );
- gstr = NULL;
- ttsi = NULL;
- }
- }
-
- for ( i = 0; i < ldd->ld.repayOptCount; i++ )
- {
- RepayOptData *rod = ldd->ld.repayOpts[i];
- if ( ! rod->enabled )
- continue;
-
- tcSX = paymentSX;
- if ( rod->schedule != NULL )
- {
- tcSX = g_new0( toCreateSX, 1 );
- gstr = g_string_new( ldd->ld.repMemo );
- g_string_append_printf( gstr, " - %s",
- rod->name );
- tcSX->name = g_strdup(gstr->str);
- tcSX->start = *ldd->ld.startDate;
- tcSX->last = *ldd->ld.repStartDate;
- {
- tcSX->end = tcSX->last;
- g_date_add_months( &tcSX->end, ldd->ld.numMonRemain );
- }
- tcSX->schedule = rod->schedule;
- /* So it won't get destroyed when the close the
- * Druid. */
- tcSX->instNum =
- ld_calc_sx_instance_num(&tcSX->start, rod->schedule);
- rod->schedule = NULL;
- tcSX->mainTxn = gnc_ttinfo_malloc();
- gnc_ttinfo_set_currency( tcSX->mainTxn,
- gnc_default_currency() );
- gnc_ttinfo_set_description( tcSX->mainTxn,
- gstr->str );
- tcSX->escrowTxn = gnc_ttinfo_malloc();
- gnc_ttinfo_set_currency( tcSX->escrowTxn,
- gnc_default_currency() );
- gnc_ttinfo_set_description( tcSX->escrowTxn,
- gstr->str );
-
- g_string_free( gstr, TRUE );
- gstr = NULL;
-
- repaySXes = g_list_append( repaySXes, tcSX );
-
- }
-
- /* repayment */
- ld_setup_repayment_sx( ldd, rod, paymentSX, tcSX );
- }
-
- /* Create the SXes */
- {
- GList *l;
-
- ld_create_sx_from_tcSX( ldd, paymentSX );
-
- for ( l = repaySXes; l; l = l->next )
- {
- ld_create_sx_from_tcSX( ldd, (toCreateSX*)l->data );
- }
- }
-
- /* Clean up. */
- ld_tcSX_free( paymentSX, NULL );
- g_list_foreach( repaySXes, ld_tcSX_free, NULL );
- g_list_free( repaySXes );
-}
-
-static
-void
-ld_calc_upd_rem_payments( GtkWidget *w, gpointer ud )
-{
- LoanDruidData *ldd = (LoanDruidData*)ud;
- GDate start, now;
- int i, totalVal, total, remain;
-
- g_date_clear( &start, 1 );
- g_date_clear( &now, 1 );
- g_date_set_time_t( &start, gnc_date_edit_get_date( ldd->prmStartDateGDE ) );
- g_date_set_time_t( &now, time(NULL) );
- for ( i = 0; g_date_compare( &start, &now ) < 0; i++ )
- {
- g_date_add_months( &start, 1 );
- }
-
- /* Get the correct, current value of the length spin. */
- {
- gchar *valueStr = gtk_editable_get_chars( GTK_EDITABLE(ldd->prmLengthSpin),
- 0, -1 );
- totalVal = strtol( valueStr, NULL, 10 );
- g_free( valueStr );
- }
- total = totalVal
- * ( gtk_combo_box_get_active( ldd->prmLengthType )
- == 1 ? 12 : 1 );
- remain = total - i;
- gtk_spin_button_set_value( ldd->prmRemainSpin, remain );
- gtk_widget_show( GTK_WIDGET(ldd->prmRemainSpin) );
-}
-
-static
-void
-ld_rev_range_opt_changed( GtkComboBox *combo, gpointer ud )
-{
- LoanDruidData *ldd = (LoanDruidData*)ud;
- int opt;
-
- opt = gtk_combo_box_get_active( ldd->revRangeOpt );
- gtk_widget_set_sensitive( GTK_WIDGET(ldd->revDateFrame),
- (opt == CUSTOM) );
- {
- GDate start, end;
- g_date_clear( &start, 1 );
- g_date_clear( &end, 1 );
- ld_rev_get_dates( ldd, &start, &end );
- ld_rev_update_view( ldd, &start, &end );
- }
-}
-
-static
-void
-ld_rev_range_changed( GNCDateEdit *gde, gpointer ud )
-{
- LoanDruidData *ldd = (LoanDruidData*)ud;
- {
- GDate start, end;
- g_date_clear( &start, 1 );
- g_date_clear( &end, 1 );
- ld_rev_get_dates( ldd, &start, &end );
- ld_rev_update_view( ldd, &start, &end );
- }
-}
-
-static
-void
-ld_get_loan_range( LoanDruidData *ldd, GDate *start, GDate *end )
-{
- int monthsTotal;
- struct tm *endDateMath;
-
- *start = *ldd->ld.startDate;
-
- endDateMath = g_new0( struct tm, 1 );
- g_date_to_struct_tm( ldd->ld.startDate, endDateMath );
- monthsTotal = ( (ldd->ld.numPer - 1)
- * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) );
- endDateMath->tm_mon += monthsTotal;
- g_date_set_time_t( end, mktime( endDateMath ) );
- g_free( endDateMath );
-}
-
-static
-void
-ld_rev_get_dates( LoanDruidData *ldd, GDate *start, GDate *end )
-{
- int range = gtk_combo_box_get_active( ldd->revRangeOpt );
- switch ( range )
- {
- case CURRENT_YEAR:
- g_date_set_time_t( start, time(NULL) );
- g_date_set_dmy( start, 1, G_DATE_JANUARY, g_date_get_year( start ) );
- g_date_set_dmy( end, 31, G_DATE_DECEMBER, g_date_get_year( start ) );
- break;
- case NOW_PLUS_ONE:
- g_date_set_time_t( start, time(NULL) );
- *end = *start;
- g_date_add_years( end, 1 );
- break;
- case WHOLE_LOAN:
- ld_get_loan_range( ldd, start, end );
- break;
- case CUSTOM:
- g_date_set_time_t( start,
- gnc_date_edit_get_date( ldd->revStartDate ) );
- g_date_set_time_t( end,
- gnc_date_edit_get_date( ldd->revEndDate ) );
- break;
- default:
- PERR( "Unknown review date range option %d", range );
- break;
- }
-
-}
-
-static
-void
-ld_rev_sched_list_free( gpointer data, gpointer user_data )
-{
- RevRepaymentRow *rrr = (RevRepaymentRow*)data;
- g_free( rrr->numCells );
- g_free( rrr );
-}
-
-static
-void
-ld_rev_hash_to_list( gpointer key, gpointer val, gpointer user_data )
-{
- GList **l = (GList**)user_data;
- RevRepaymentRow *rrr = g_new0( RevRepaymentRow, 1 );
- if ( !key || !val )
- {
- DEBUG( "%.8x, %.8x",
- GPOINTER_TO_UINT(key),
- GPOINTER_TO_UINT(val));
- return;
- }
- rrr->date = *(GDate*)key;
- rrr->numCells = (gnc_numeric*)val;
- *l = g_list_append( *l, (gpointer)rrr );
-}
-
-static
-void
-ld_rev_hash_free_date_keys( gpointer key, gpointer val, gpointer user_data )
-{
- g_free( (GDate*)key );
-}
-
-static
-void
-ld_rev_recalc_schedule( LoanDruidData *ldd )
-{
- GDate start, end;
- gnc_numeric *rowNumData;
- GHashTable *repayment_schedule;
-
- g_date_clear( &start, 1 );
- g_date_clear( &end, 1 );
- ld_get_loan_range( ldd, &start, &end );
-
- /* The repayment_schedule is a hash of GDates to
- * row-of-gnc_numeric[N] data, where N is the number of columns as
- * determined by the _prep function, and stored in
- * LoanData::revNumPmts. */
- repayment_schedule = g_hash_table_new(gnc_gdate_hash, gnc_gdate_equal);
-
- /* Do the master repayment */
- {
- GDate curDate, nextDate;
- GString *pmtFormula, *ppmtFormula, *ipmtFormula;
- int i;
- GHashTable *ivar;
-
- pmtFormula = g_string_sized_new( 64 );
- ld_get_pmt_formula( ldd, pmtFormula );
- ppmtFormula = g_string_sized_new( 64 );
- ld_get_ppmt_formula( ldd, ppmtFormula );
- ipmtFormula = g_string_sized_new( 64 );
- ld_get_ipmt_formula( ldd, ipmtFormula );
-
- ivar = g_hash_table_new( g_str_hash, g_str_equal );
- g_date_clear( &curDate, 1 );
- curDate = start;
- g_date_subtract_days( &curDate, 1 );
- g_date_clear(&nextDate, 1);
- recurrenceListNextInstance(ldd->ld.repayment_schedule, &curDate, &nextDate);
- for ( i = 1;
- g_date_valid( &nextDate )
- && g_date_compare( &nextDate, &end ) <= 0 ;
- i++,
- curDate = nextDate,
- recurrenceListNextInstance(ldd->ld.repayment_schedule,
- &curDate, &nextDate))
- {
- gnc_numeric ival;
- gnc_numeric val;
- char *eloc;
- rowNumData =
- (gnc_numeric*)g_hash_table_lookup( repayment_schedule,
- &curDate );
- if ( rowNumData == NULL)
- {
- int j;
- GDate *dateKeyCopy = g_date_new();
-
- *dateKeyCopy = curDate;
- rowNumData = g_new0( gnc_numeric, ldd->ld.revNumPmts );
- g_assert( rowNumData != NULL );
- for ( j = 0; j < ldd->ld.revNumPmts; j++ )
- {
- rowNumData[j] = gnc_numeric_error( GNC_ERROR_ARG );
- }
- g_hash_table_insert( repayment_schedule,
- (gpointer)dateKeyCopy,
- (gpointer)rowNumData );
- }
-
- /* evaluate the expressions given the correct
- * sequence number i */
- ival = gnc_numeric_create( i, 1 );
- g_hash_table_insert( ivar, "i", &ival );
-
- if ( ! gnc_exp_parser_parse_separate_vars(
- pmtFormula->str, &val, &eloc, ivar ) )
- {
- PERR( "pmt Parsing error at %s", eloc );
- continue;
- }
- val = gnc_numeric_convert( val, 100, GNC_HOW_RND_ROUND_HALF_UP );
- rowNumData[0] = val;
-
- if ( ! gnc_exp_parser_parse_separate_vars(
- ppmtFormula->str, &val, &eloc, ivar ) )
- {
- PERR( "ppmt Parsing error at %s", eloc );
- continue;
- }
- val = gnc_numeric_convert( val, 100, GNC_HOW_RND_ROUND_HALF_UP );
- rowNumData[1] = val;
-
- if ( ! gnc_exp_parser_parse_separate_vars(
- ipmtFormula->str, &val, &eloc, ivar ) )
- {
- PERR( "ipmt Parsing error at %s", eloc );
- continue;
- }
- val = gnc_numeric_convert( val, 100, GNC_HOW_RND_ROUND_HALF_UP );
- rowNumData[2] = val;
- }
-
- g_string_free( ipmtFormula, TRUE );
- g_string_free( ppmtFormula, TRUE );
- g_string_free( pmtFormula, TRUE );
-
- g_hash_table_destroy( ivar );
- }
-
- /* Process any other enabled payments. */
- {
- int i;
- GDate curDate, nextDate;
- GList *schedule;
-
- for ( i = 0; i < ldd->ld.repayOptCount; i++ )
- {
- if ( ! ldd->ld.repayOpts[i]->enabled )
- continue;
-
- schedule
- = ( ldd->ld.repayOpts[i]->schedule != NULL
- ? ldd->ld.repayOpts[i]->schedule
- : ldd->ld.repayment_schedule );
-
- g_date_clear( &curDate, 1 );
- curDate = start;
- g_date_subtract_days( &curDate, 1 );
- g_date_clear(&nextDate, 1);
- recurrenceListNextInstance(schedule, &curDate, &nextDate );
- for ( ; g_date_valid( &nextDate )
- && g_date_compare( &nextDate, &end ) <= 0;
- curDate = nextDate,
- recurrenceListNextInstance(
- schedule, &curDate, &nextDate ) )
- {
- gint gncn_how =
- GNC_HOW_DENOM_SIGFIGS(2)
- | GNC_HOW_RND_ROUND_HALF_UP;
- gnc_numeric val;
- rowNumData = (gnc_numeric*)g_hash_table_lookup( repayment_schedule,
- &curDate );
- if ( rowNumData == NULL )
- {
- int j;
- GDate *dateKeyCopy = g_date_new();
-
- *dateKeyCopy = curDate;
- rowNumData = g_new0( gnc_numeric, ldd->ld.revNumPmts );
- g_assert( rowNumData != NULL );
- for ( j = 0; j < ldd->ld.revNumPmts; j++ )
- {
- rowNumData[j] = gnc_numeric_error( GNC_ERROR_ARG );
- }
- g_hash_table_insert( repayment_schedule,
- (gpointer)dateKeyCopy,
- (gpointer)rowNumData );
- }
-
- val = double_to_gnc_numeric( (double)ldd->ld
- .repayOpts[i]
- ->amount,
- 100, gncn_how );
- rowNumData[ ldd->ld.revRepayOptToColMap[i] ]
- = val;
- }
- }
- }
-
- /* Convert the GHashTable into a sorted GList in the LoanData */
- {
- if ( ldd->ld.revSchedule != NULL )
- {
- g_list_foreach( ldd->ld.revSchedule,
- ld_rev_sched_list_free,
- NULL );
- g_list_free( ldd->ld.revSchedule );
- ldd->ld.revSchedule = NULL;
- }
- g_hash_table_foreach( repayment_schedule, ld_rev_hash_to_list,
- &ldd->ld.revSchedule );
- g_hash_table_foreach( repayment_schedule, ld_rev_hash_free_date_keys,
- NULL );
- g_hash_table_destroy( repayment_schedule );
- ldd->ld.revSchedule =
- g_list_sort( ldd->ld.revSchedule, (GCompareFunc)g_date_compare );
- }
-}
-
-static
-void
-ld_rev_update_view( LoanDruidData *ldd, GDate *start, GDate *end )
-{
- static gchar *NO_AMT_CELL_TEXT = " ";
- GList *l;
- GNCPrintAmountInfo pai;
- GtkListStore *store;
- GtkTreeIter iter;
-
- pai = gnc_default_price_print_info();
- pai.min_decimal_places = 2;
-
- store = GTK_LIST_STORE(gtk_tree_view_get_model( ldd->revView ));
-
- gtk_list_store_clear( store );
-
- for ( l = ldd->ld.revSchedule; l != NULL; l = l->next )
- {
- int i;
- gchar tmpBuf[50];
- RevRepaymentRow *rrr = (RevRepaymentRow*)l->data;
-
- if ( g_date_compare( &rrr->date, start ) < 0 )
- continue;
- if ( g_date_compare( &rrr->date, end ) > 0 )
- continue; /* though we can probably return, too. */
-
- gtk_list_store_append(store, &iter);
-
- qof_print_gdate( tmpBuf, MAX_DATE_LENGTH, &rrr->date );
- gtk_list_store_set( store, &iter, LOAN_COL_DATE, tmpBuf, -1 );
-
- for ( i = 0; i < ldd->ld.revNumPmts; i++ )
- {
- int numPrinted;
- if ( gnc_numeric_check( rrr->numCells[i] )
- == GNC_ERROR_ARG )
- {
- /* '+1' for the date cell */
- gtk_list_store_set( store, &iter,
- i + 1, NO_AMT_CELL_TEXT,
- -1);
- continue;
- }
-
- numPrinted = xaccSPrintAmount( tmpBuf, rrr->numCells[i], pai );
- g_assert( numPrinted < 50 );
- /* '+1' for the date cell */
- gtk_list_store_set( store, &iter,
- i + 1, tmpBuf,
- -1);
- }
-
- }
-}
Deleted: gnucash/trunk/src/gnome/druid-loan.h
===================================================================
--- gnucash/trunk/src/gnome/druid-loan.h 2011-08-07 09:14:22 UTC (rev 21117)
+++ gnucash/trunk/src/gnome/druid-loan.h 2011-08-07 09:14:36 UTC (rev 21118)
@@ -1,24 +0,0 @@
-/********************************************************************\
- * druid-loan.h : A Gnome Druid for setting up loan-repayment *
- * scheduled transactions. *
- * Copyright (C) 2002 Joshua Sled <jsled at asynchronous.org> *
- * *
- * This program is free software; you can redistribute it and/or *
- * modify it under the terms of the GNU General Public License as *
- * published by the Free Software Foundation; either version 2 of *
- * the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License*
- * along with this program; if not, contact: *
- * *
- * Free Software Foundation Voice: +1-617-542-5942 *
- * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
- * Boston, MA 02110-1301, USA gnu at gnu.org *
-\********************************************************************/
-
-struct LoanDruidData_* gnc_ui_sx_loan_druid_create(void);
Modified: gnucash/trunk/src/gnome/glade/sched-xact.glade
===================================================================
--- gnucash/trunk/src/gnome/glade/sched-xact.glade 2011-08-07 09:14:22 UTC (rev 21117)
+++ gnucash/trunk/src/gnome/glade/sched-xact.glade 2011-08-07 09:14:36 UTC (rev 21118)
@@ -1898,1104 +1898,6 @@
</widget>
</child>
</widget>
- <widget class="GtkWindow" id="loan_druid_win">
- <property name="visible">True</property>
- <property name="title" translatable="yes">Mortgage/Loan Assistant</property>
- <child>
- <widget class="GnomeDruid" id="loan_druid">
- <property name="visible">True</property>
- <property name="border_width">4</property>
- <child>
- <widget class="GnomeDruidPageEdge" id="loan_intro_pg">
- <property name="visible">True</property>
- <property name="position">Edge Start</property>
- <property name="title" translatable="yes">Mortgage/Loan Repayment Setup</property>
- <property name="text" translatable="yes">This is a step-by-step method of creating a loan repayment setup within GnuCash. In this assistant, you can input the parameters of your loan and its repayment and give the details of its payback. Using that information, the appropriate Scheduled Transactions will be created.
-
-If you make a mistake or want to make changes later, you can edit the created Scheduled Transactions directly.</property>
- </widget>
- </child>
- <child>
- <widget class="GnomeDruidPageStandard" id="loan_info_pg">
- <property name="visible">True</property>
- <property name="title" translatable="yes">Loan Information</property>
- <property name="title_foreground_gdk">#ffffffffffff</property>
- <property name="background_gdk">#666666669998</property>
- <property name="logo_background_gdk">#666666669998</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="druid-vbox10">
- <property name="visible">True</property>
- <property name="border_width">5</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkTable" id="param_table">
- <property name="visible">True</property>
- <property name="border_width">5</property>
- <property name="n_rows">6</property>
- <property name="n_columns">4</property>
- <property name="column_spacing">5</property>
- <property name="row_spacing">5</property>
- <child>
- <widget class="GtkLabel" id="label847897">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Interest Rate:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847899">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Start Date:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847900">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Length:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847895">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Amount:</property>
- <property name="justify">right</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847920">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Loan Account:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkSpinButton" id="rem_spin">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="adjustment">1 0 100 1 10 0</property>
- <property name="climb_rate">1</property>
- </widget>
- <packing>
- <property name="left_attach">3</property>
- <property name="right_attach">4</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkHBox" id="hbox167">
- <property name="visible">True</property>
- <child>
- <widget class="GtkSpinButton" id="len_spin">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="adjustment">1 0 100 1 10 0</property>
- <property name="climb_rate">1</property>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkComboBox" id="len_opt">
- <property name="visible">True</property>
- <property name="items" translatable="yes">months
-years</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment11">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xscale">0.25</property>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">4</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment12">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xscale">0.5</property>
- <child>
- <widget class="GtkHBox" id="hbox170">
- <property name="visible">True</property>
- <child>
- <widget class="GtkSpinButton" id="irate_spin">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="adjustment">1 0 100 1 10 0</property>
- <property name="climb_rate">1</property>
- <property name="digits">3</property>
- <property name="snap_to_ticks">True</property>
- <property name="numeric">True</property>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847921">
- <property name="visible">True</property>
- <property name="label" translatable="yes">%</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847898">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="yalign">0</property>
- <property name="label" translatable="yes">Type:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847901">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Months Remaining:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment23">
- <property name="visible">True</property>
- <property name="xscale">0.5</property>
- <property name="yscale">0.75</property>
- <child>
- <widget class="GtkFrame" id="type_freq_frame">
- <property name="visible">True</property>
- <property name="border_width">3</property>
- <property name="label_xalign">0.5</property>
- <child>
- <placeholder/>
- </child>
- <child>
- <widget class="GtkLabel" id="label847976">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Interest Rate Change Frequency</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">4</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
- <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkComboBox" id="type_combobox">
- <property name="visible">True</property>
- <property name="items" translatable="yes">Fixed Rate
-3/1 Year ARM
-5/1 Year ARM
-7/1 Year ARM
-10/1 Year ARM</property>
- </widget>
- <packing>
- <property name="left_attach">3</property>
- <property name="right_attach">4</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GnomeDruidPageStandard" id="loan_opts_pg">
- <property name="visible">True</property>
- <property name="title" translatable="yes">Options</property>
- <property name="title_foreground_gdk">#ffffffffffff</property>
- <property name="background_gdk">#666666669998</property>
- <property name="logo_background_gdk">#666666669998</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="opt_vbox">
- <property name="visible">True</property>
- <property name="border_width">16</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkLabel" id="label847903">
- <property name="visible">True</property>
- <property name="ypad">10</property>
- <property name="label" translatable="yes">Do you...</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment18">
- <property name="visible">True</property>
- <property name="xscale">0.75</property>
- <child>
- <widget class="GtkVBox" id="vbox174">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkCheckButton" id="opt_escrow_cb">
- <property name="label" translatable="yes">... utilize an escrow account for payments?</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment19">
- <property name="visible">True</property>
- <property name="xscale">0.75</property>
- <child>
- <widget class="GtkHBox" id="opt_escrow_hbox">
- <property name="visible">True</property>
- <child>
- <widget class="GtkLabel" id="label847963">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Escrow Account:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment20">
- <property name="visible">True</property>
- <property name="xscale">0.89999997615814209</property>
- <child>
- <widget class="GtkHSeparator" id="hseparator1">
- <property name="visible">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">5</property>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GnomeDruidPageStandard" id="repayment_pg">
- <property name="visible">True</property>
- <property name="title" translatable="yes">Repayment</property>
- <property name="title_foreground_gdk">#ffffffffffff</property>
- <property name="background_gdk">#666666669998</property>
- <property name="logo_background_gdk">#666666669998</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="druid-vbox12">
- <property name="visible">True</property>
- <property name="border_width">16</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkTable" id="repay_table">
- <property name="visible">True</property>
- <property name="border_width">5</property>
- <property name="n_rows">5</property>
- <property name="n_columns">4</property>
- <property name="column_spacing">5</property>
- <property name="row_spacing">5</property>
- <child>
- <widget class="GtkLabel" id="label847910">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Payment From:</property>
- <property name="justify">right</property>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847911">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Principal To:</property>
- <property name="justify">right</property>
- </widget>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847918">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Name:</property>
- <property name="justify">right</property>
- </widget>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847909">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Amount:</property>
- <property name="justify">right</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847912">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Interest To:</property>
- <property name="justify">right</property>
- </widget>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment13">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <child>
- <widget class="GtkEntry" id="txn_title">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">4</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment14">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <child>
- <widget class="GtkEntry" id="amount_ent">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">4</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment21">
- <property name="visible">True</property>
- <property name="xscale">0.5</property>
- <property name="yscale">0.89999997615814209</property>
- <child>
- <widget class="GtkFrame" id="freq_frame">
- <property name="visible">True</property>
- <property name="border_width">3</property>
- <property name="label_xalign">0.5</property>
- <child>
- <placeholder/>
- </child>
- <child>
- <widget class="GtkLabel" id="label847977">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Repayment Frequency</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="right_attach">4</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">GTK_SHRINK | GTK_FILL</property>
- <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="padding">5</property>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GnomeDruidPageStandard" id="payment_pg">
- <property name="visible">True</property>
- <property name="title" translatable="yes">Repayment Type</property>
- <property name="title_foreground_gdk">#ffffffffffff</property>
- <property name="background_gdk">#666666669998</property>
- <property name="logo_background_gdk">#666666669998</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="druid-vbox13">
- <property name="visible">True</property>
- <property name="border_width">16</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkEventBox" id="eventbox1">
- <property name="visible">True</property>
- <child>
- <widget class="GtkVBox" id="vbox158">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkTable" id="pay_table">
- <property name="visible">True</property>
- <property name="border_width">5</property>
- <property name="n_rows">6</property>
- <property name="n_columns">4</property>
- <property name="column_spacing">5</property>
- <property name="row_spacing">5</property>
- <child>
- <widget class="GtkLabel" id="label847916">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Amount:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="pay_from_account_label">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Payment From:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847919">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Name:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="pay_escrow_to_label">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Payment To (Escrow):</property>
- <property name="justify">right</property>
- </widget>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment16">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <child>
- <widget class="GtkEntry" id="pay_txn_title">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">4</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment17">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <child>
- <widget class="GtkEntry" id="pay_amt_ent">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">4</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="pay_escrow_from_label">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Payment From (Escrow):</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847975">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Payment To:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="pay_specify_source">
- <property name="label" translatable="yes">Specify Source Account</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">4</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="pay_use_escrow">
- <property name="label" translatable="yes">Use Escrow Account</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">4</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="alignment22">
- <property name="visible">True</property>
- <property name="xscale">0.5</property>
- <property name="yscale">0.75</property>
- <child>
- <widget class="GtkFrame" id="frame92">
- <property name="visible">True</property>
- <property name="border_width">5</property>
- <property name="label_xalign">0.5</property>
- <child>
- <widget class="GtkVBox" id="vbox159">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkRadioButton" id="pay_txn_part_rb">
- <property name="label" translatable="yes">Part of Payment Transaction</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox160">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkRadioButton" id="pay_uniq_freq_rb">
- <property name="label" translatable="yes">Other</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- <property name="group">pay_txn_part_rb</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkAlignment" id="pay_freq_align">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="xscale">0.94999998807907104</property>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="label847978">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Payment Frequency</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GnomeDruidPageStandard" id="review_pg">
- <property name="visible">True</property>
- <property name="title" translatable="yes">Review</property>
- <property name="title_foreground_gdk">#ffffffffffff</property>
- <property name="background_gdk">#666666669998</property>
- <property name="logo_background_gdk">#666666669998</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="druid-vbox14">
- <property name="visible">True</property>
- <property name="border_width">16</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkVBox" id="vbox177">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkHBox" id="hbox176">
- <property name="visible">True</property>
- <child>
- <widget class="GtkHBox" id="hbox178">
- <property name="visible">True</property>
- <child>
- <widget class="GtkLabel" id="label847973">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="xpad">5</property>
- <property name="ypad">5</property>
- <property name="label" translatable="yes">Range: </property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox178">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkComboBox" id="rev_range_opt">
- <property name="visible">True</property>
- <property name="items" translatable="yes">Current Year
-Now + 1 Year
-Whole Loan
-Custom</property>
- </widget>
- <packing>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkFrame" id="rev_date_frame">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="border_width">2</property>
- <property name="label_xalign">0.5</property>
- <child>
- <widget class="GtkTable" id="rev_date_range_table">
- <property name="visible">True</property>
- <property name="n_rows">2</property>
- <child>
- <widget class="GtkLabel" id="label847971">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="xpad">5</property>
- <property name="ypad">5</property>
- <property name="label" translatable="yes">Start Date:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label847972">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="xpad">5</property>
- <property name="ypad">5</property>
- <property name="label" translatable="yes">End Date:</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="label847979">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Date Range</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="padding">2</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkScrolledWindow" id="rev_scrollwin">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GnomeDruidPageEdge" id="commit_pg">
- <property name="visible">True</property>
- <property name="position">GNOME_EDGE_FINISH</property>
- <property name="text" translatable="yes">Press apply to commit these changes.</property>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
<widget class="GtkMenu" id="Since Last Run popup">
<property name="visible">True</property>
<child>
Modified: gnucash/trunk/src/gnome/gnc-plugin-basic-commands.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-basic-commands.c 2011-08-07 09:14:22 UTC (rev 21117)
+++ gnucash/trunk/src/gnome/gnc-plugin-basic-commands.c 2011-08-07 09:14:36 UTC (rev 21118)
@@ -46,7 +46,7 @@
#include "dialog-sx-since-last-run.h"
#include "dialog-totd.h"
#include "assistant-acct-period.h"
-#include "druid-loan.h"
+#include "assistant-loan.h"
#include "gnc-engine.h"
#include "gnc-file.h"
#include "gnc-gui-query.h"
@@ -501,7 +501,7 @@
static void
gnc_main_window_cmd_actions_mortgage_loan (GtkAction *action, GncMainWindowActionData *data)
{
- gnc_ui_sx_loan_druid_create ();
+ gnc_ui_sx_loan_assistant_create ();
}
static void
Modified: gnucash/trunk/src/gnome/gtkbuilder/Makefile.am
===================================================================
--- gnucash/trunk/src/gnome/gtkbuilder/Makefile.am 2011-08-07 09:14:22 UTC (rev 21117)
+++ gnucash/trunk/src/gnome/gtkbuilder/Makefile.am 2011-08-07 09:14:36 UTC (rev 21118)
@@ -2,6 +2,7 @@
gtkbuilder_DATA = \
account.glade \
acctperiod.glade \
+ assistant-loan.glade \
autoclear.glade \
budget.glade \
commodities.glade \
Added: gnucash/trunk/src/gnome/gtkbuilder/assistant-loan.glade
===================================================================
--- gnucash/trunk/src/gnome/gtkbuilder/assistant-loan.glade (rev 0)
+++ gnucash/trunk/src/gnome/gtkbuilder/assistant-loan.glade 2011-08-07 09:14:36 UTC (rev 21118)
@@ -0,0 +1,1417 @@
+<?xml version="1.0"?>
+<interface>
+ <requires lib="gtk+" version="2.16"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkAssistant" id="Loan-Mortgage Assistant">
+ <property name="can_focus">False</property>
+ <property name="border_width">12</property>
+ <signal name="close" handler="loan_assistant_close"/>
+ <signal name="apply" handler="loan_assistant_finish"/>
+ <signal name="cancel" handler="loan_assistant_cancel"/>
+ <signal name="prepare" handler="loan_assistant_prepare"/>
+ <child>
+ <object class="GtkLabel" id="loan_intro_page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">This is a step-by-step method for creating a loan repayment within GnuCash. In this assistant, you can input the details of your loan and its repayment along with the details of its payback. Using that information, the appropriate Scheduled Transactions will be created.
+
+If you make a mistake or want to make changes later, you can edit the created Scheduled Transactions directly.</property>
+ <property name="justify">center</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="page_type">intro</property>
+ <property name="title" translatable="yes">Loan / Mortgage Repayment Setup</property>
+ <property name="complete">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="loan_info_page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Enter the Loan Details, as a minimum enter a valid Loan Account and Amount.
+</property>
+ <property name="justify">center</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTable" id="param_table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="n_rows">6</property>
+ <property name="n_columns">4</property>
+ <property name="column_spacing">5</property>
+ <property name="row_spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="label847897">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Interest Rate:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847899">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Start Date:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847900">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Length:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847895">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Amount:</property>
+ <property name="justify">right</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847920">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Loan Account:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="rem_spin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ <property name="climb_rate">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox167">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkSpinButton" id="len_spin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ <property name="climb_rate">1</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="len_opt">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">len_liststore</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment11">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="xscale">0.25</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment12">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="xscale">0.5</property>
+ <child>
+ <object class="GtkHBox" id="hbox170">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkComboBox" id="irate_type_combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">rate_liststore</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="irate_spin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ <property name="climb_rate">1</property>
+ <property name="digits">3</property>
+ <property name="snap_to_ticks">True</property>
+ <property name="numeric">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847921">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">%</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847898">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">Type:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847901">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Months Remaining:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment23">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xscale">0.5</property>
+ <property name="yscale">0.75</property>
+ <child>
+ <object class="GtkFrame" id="type_freq_frame">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0.5</property>
+ <child>
+ <object class="GtkHBox" id="type_freq_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">10</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label847976">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Interest Rate Change Frequency</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="right_attach">4</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
+ <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="type_combobox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">type_liststore</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext3"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="title" translatable="yes">Loan Details</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="loan_options_page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label847903">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="ypad">10</property>
+ <property name="label" translatable="yes">
+Do you utilise an escrow account, if so an account must be specified...</property>
+ <property name="justify">center</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment18">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xscale">0.75</property>
+ <child>
+ <object class="GtkVBox" id="vbox174">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="opt_escrow_cb">
+ <property name="label" translatable="yes">... utilize an escrow account for payments?</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment19">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xscale">0.75</property>
+ <child>
+ <object class="GtkHBox" id="opt_escrow_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label847963">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Escrow Account:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment20">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xscale">0.89999997615814209</property>
+ <child>
+ <object class="GtkHSeparator" id="hseparator1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">5</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="title" translatable="yes">Loan Repayment Options</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="loan_repayment_page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">
+All accounts must have valid entries to continue.
+</property>
+ <property name="justify">center</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTable" id="repay_table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="n_rows">5</property>
+ <property name="n_columns">4</property>
+ <property name="column_spacing">5</property>
+ <property name="row_spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="label847910">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Payment From:</property>
+ <property name="justify">right</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847911">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Principal To:</property>
+ <property name="justify">right</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847918">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Name:</property>
+ <property name="justify">right</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847909">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Amount:</property>
+ <property name="justify">right</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847912">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Interest To:</property>
+ <property name="justify">right</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment13">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <child>
+ <object class="GtkEntry" id="txn_title">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment14">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <child>
+ <object class="GtkEntry" id="amount_ent">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment21">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xscale">0.5</property>
+ <property name="yscale">0.89999997615814209</property>
+ <child>
+ <object class="GtkFrame" id="freq_frame">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0.5</property>
+ <child>
+ <object class="GtkHBox" id="freq_frame_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">10</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label847977">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Repayment Frequency</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="right_attach">4</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_SHRINK | GTK_FILL</property>
+ <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="title" translatable="yes">Loan Repayment</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="loan_payment_page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">
+All enabled option pages must contain valid entries to continue.
+</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEventBox" id="eventbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkVBox" id="vbox158">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkTable" id="pay_table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="n_rows">6</property>
+ <property name="n_columns">4</property>
+ <property name="column_spacing">5</property>
+ <property name="row_spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="label847916">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Amount:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="pay_from_account_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Payment From:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847919">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Name:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="pay_escrow_to_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Payment To (Escrow):</property>
+ <property name="justify">right</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment16">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <child>
+ <object class="GtkEntry" id="pay_txn_title">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment17">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <child>
+ <object class="GtkEntry" id="pay_amt_ent">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="pay_escrow_from_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Payment From (Escrow):</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847975">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Payment To:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="pay_specify_source">
+ <property name="label" translatable="yes">Specify Source Account</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="pay_use_escrow">
+ <property name="label" translatable="yes">Use Escrow Account</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment22">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xscale">0.5</property>
+ <property name="yscale">0.75</property>
+ <child>
+ <object class="GtkFrame" id="frame92">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0.5</property>
+ <child>
+ <object class="GtkVBox" id="vbox159">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkRadioButton" id="pay_txn_part_rb">
+ <property name="label" translatable="yes">Part of Payment Transaction</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox160">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">10</property>
+ <child>
+ <object class="GtkRadioButton" id="pay_uniq_freq_rb">
+ <property name="label" translatable="yes">Other</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">pay_txn_part_rb</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="pay_freq_align">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="xscale">0.94999998807907104</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label847978">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Payment Frequency</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="pay_back_button">
+ <property name="label" translatable="yes">Previous Option</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="pay_next_button">
+ <property name="label" translatable="yes">Next Option</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="page_type">progress</property>
+ <property name="title" translatable="yes">Loan Payment</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="loan_review_page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">
+Review the details below and if correct press Apply to create the schedule.</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox177">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">10</property>
+ <child>
+ <object class="GtkHBox" id="hbox176">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkHBox" id="hbox178">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label847973">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="xpad">5</property>
+ <property name="ypad">5</property>
+ <property name="label" translatable="yes">Range: </property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox178">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">10</property>
+ <child>
+ <object class="GtkComboBox" id="rev_range_opt">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="model">range_liststore</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext4"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="rev_date_frame">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="label_xalign">0.5</property>
+ <child>
+ <object class="GtkTable" id="rev_date_range_table">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">10</property>
+ <property name="n_rows">2</property>
+ <child>
+ <object class="GtkLabel" id="label847971">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="xpad">5</property>
+ <property name="ypad">5</property>
+ <property name="label" translatable="yes">Start Date:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label847972">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="xpad">5</property>
+ <property name="ypad">5</property>
+ <property name="label" translatable="yes">End Date:</property>
+ <property name="justify">center</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label847979">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Date Range</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="padding">2</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="rev_scrollwin">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="page_type">confirm</property>
+ <property name="title" translatable="yes">Loan Review</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="loan_summary_page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Schedule added successfully.</property>
+ <property name="justify">center</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="page_type">summary</property>
+ <property name="title" translatable="yes">Loan Summary</property>
+ <property name="complete">True</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkListStore" id="len_liststore">
+ <columns>
+ <!-- column-name period -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Months</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Years</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="range_liststore">
+ <columns>
+ <!-- column-name range -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Current Year</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Now + 1 Year</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Whole Loan</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">Custome</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="rate_liststore">
+ <columns>
+ <!-- column-name rate -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Interest Rate</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">APR (Compounded Daily)</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">APR (Compounded Weekly)</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">APR (Compounded Monthly)</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">APR (Compounded Quarterly)</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">APR (Compounded Annually)</col>
+ </row>
+ </data>
+ </object>
+ <object class="GtkListStore" id="type_liststore">
+ <columns>
+ <!-- column-name type -->
+ <column type="gchararray"/>
+ </columns>
+ <data>
+ <row>
+ <col id="0" translatable="yes">Fixed Rate</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">3/1 Year ARM</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">5/1 Year ARM</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">7/1 Year ARM</col>
+ </row>
+ <row>
+ <col id="0" translatable="yes">10/1 Year ARM</col>
+ </row>
+ </data>
+ </object>
+</interface>
Modified: gnucash/trunk/src/gnome/gtkbuilder/sched-xact.glade
===================================================================
--- gnucash/trunk/src/gnome/gtkbuilder/sched-xact.glade 2011-08-07 09:14:22 UTC (rev 21117)
+++ gnucash/trunk/src/gnome/gtkbuilder/sched-xact.glade 2011-08-07 09:14:36 UTC (rev 21118)
@@ -1764,13 +1764,6 @@
<action-widget response="-5">ok_button</action-widget>
</action-widgets>
</object>
- <object class="GtkWindow" id="loan_druid_win">
- <property name="visible">True</property>
- <property name="title" translatable="yes">Mortgage/Loan Assistant</property>
- <child>
- <placeholder/>
- </child>
- </object>
<object class="GtkMenu" id="Since Last Run popup">
<property name="visible">True</property>
<child>
Modified: gnucash/trunk/src/gnome-utils/gnc-account-sel.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-account-sel.c 2011-08-07 09:14:22 UTC (rev 21117)
+++ gnucash/trunk/src/gnome-utils/gnc-account-sel.c 2011-08-07 09:14:36 UTC (rev 21118)
@@ -200,6 +200,8 @@
currentSel = gtk_editable_get_chars(
GTK_EDITABLE(entry), 0, -1 );
+ g_signal_handlers_block_by_func( gas->combo, combo_changed_cb , gas );
+
root = gnc_book_get_root_account( gnc_get_current_book() );
accts = gnc_account_get_descendants_sorted( root );
@@ -232,6 +234,8 @@
if (active != -1)
gtk_combo_box_set_active(GTK_COMBO_BOX(gas->combo), active);
+ g_signal_handlers_unblock_by_func( gas->combo, combo_changed_cb , gas );
+
g_list_free( filteredAccts );
if ( currentSel )
{
@@ -313,6 +317,7 @@
void
gnc_account_sel_set_account( GNCAccountSel *gas, Account *acct, gboolean set_default_acct )
{
+ GtkEntry *entry;
gas_find_data data;
if (set_default_acct)
@@ -324,8 +329,11 @@
gtk_combo_box_set_active( GTK_COMBO_BOX(gas->combo), -1 );
}
if ( acct == NULL )
+ {
+ entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(gas->combo)));
+ gtk_editable_delete_text(GTK_EDITABLE(entry),0,-1);
return;
-
+ }
data.gas = gas;
data.acct = acct;
gtk_tree_model_foreach(GTK_TREE_MODEL(gas->store),
More information about the gnucash-changes
mailing list