2002-08-18 Joshua Sled <jsled@asynchronous.org>

* src/gnome-utils/gnc-frequency.c: Added support for a "changed"
	signal so callers can use their own calendar to show the effects
	of editing the FreqSpec.

	* src/gnome/dialog-sx-from-trans.c: Added support for using the
	dense-calendar for showing the effects of option changes.

	* src/gnome/dialog-scheduledxaction.c: Added editor support for
	using the dense-calendar for showing the effects of FreqSpec
	changes; re-arranged the editor layout to accomodate.  Added
	editor support for showing the last-occurred date of an SX.

	* src/gnome/glade/sched-xact.glade: Changes to sx-from-trans
	dialog, SX editor, GNCFrequency-widgets.

	* src/gnome/dialog-sxsincelast.c (sxsincelast_entry_changed):
	Added support for variable-entry parsing errors to go to an
	on-screen status bar instead of being printed to stderr
	[Bug#90354].

	* src/gnome/druid-loan.c (gnc_loan_druid_length_changed): Added
	change-handler to the total-loan-length spin; when it changes, the
	remaining-length spin changes the same [Bug#90785].
	(gnc_ui_sx_loan_druid_create): Adjusted the size/granularity of
	the interest-rate spin-button to 3 sig.digits. [Bug#90780].

	* src/gnome/glade/sched-xact.glade: Changed [back?] the
	shrink/auto-shrink flags on the since-last-run-druid, fixing
	Bug#90364 and strangely fixing Bug#90365.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@7183 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Joshua Sled
2002-08-20 03:19:25 +00:00
parent f6a2b6cafa
commit 0018937426
13 changed files with 2533 additions and 2182 deletions
+32
View File
@@ -1,3 +1,35 @@
2002-08-18 Joshua Sled <jsled@asynchronous.org>
* src/gnome-utils/gnc-frequency.c: Added support for a "changed"
signal so callers can use their own calendar to show the effects
of editing the FreqSpec.
* src/gnome/dialog-sx-from-trans.c: Added support for using the
dense-calendar for showing the effects of option changes.
* src/gnome/dialog-scheduledxaction.c: Added editor support for
using the dense-calendar for showing the effects of FreqSpec
changes; re-arranged the editor layout to accomodate. Added
editor support for showing the last-occurred date of an SX.
* src/gnome/glade/sched-xact.glade: Changes to sx-from-trans
dialog, SX editor, GNCFrequency-widgets.
* src/gnome/dialog-sxsincelast.c (sxsincelast_entry_changed):
Added support for variable-entry parsing errors to go to an
on-screen status bar instead of being printed to stderr
[Bug#90354].
* src/gnome/druid-loan.c (gnc_loan_druid_length_changed): Added
change-handler to the total-loan-length spin; when it changes, the
remaining-length spin changes the same [Bug#90785].
(gnc_ui_sx_loan_druid_create): Adjusted the size/granularity of
the interest-rate spin-button to 3 sig.digits. [Bug#90780].
* src/gnome/glade/sched-xact.glade: Changed [back?] the
shrink/auto-shrink flags on the since-last-run-druid, fixing
Bug#90364 and strangely fixing Bug#90365.
2002-08-15 Christian Stimming <stimming@tuhh.de>
* src/import-export/hbci/*: much more HBCI work. Ini-Letter of
+6 -2
View File
@@ -77,10 +77,14 @@ gboolean gnc_exp_parser_parse (const char * expression,
gnc_numeric *value_p,
char **error_loc_p );
/* Parses as per gnc_exp_parser_parse, but with an optional last argument
/**
* Parses as per gnc_exp_parser_parse, but with an optional last argument
* dealing with a non-shared variable list and state, local to the expression
* being parsed. This is a hashTable of variable names mapping to
* gnc_numeric pointers. */
* gnc_numeric pointers.
* @note It is the CALLER'S RESPONSIBILITY to g_free() both the keys and
* values of varHash when done.
**/
gboolean gnc_exp_parser_parse_separate_vars (const char * expression,
gnc_numeric *value_p,
char **error_loc_p,
+110 -127
View File
@@ -120,6 +120,8 @@ static short module = MOD_SX;
/** PROTOTYPES ******************************************************/
static int int_cmp( int a, int b );
/**
* Destroys all sub-FreqSpecs in a composite FreqSpec.
* Assertion error if it's not a COMPOSITE FreqSpec.
@@ -268,20 +270,22 @@ static inline guint32 min( guint32 a, guint32 b )
}
void
xaccFreqSpecGetNextInstance(
FreqSpec *fs,
const GDate* in_date,
GDate* out_date )
xaccFreqSpecGetNextInstance( FreqSpec *fs,
const GDate* in_date,
GDate* out_date )
{
GList *list;
GList *list;
g_return_if_fail( fs );
switch( fs->type ) {
case INVALID:
g_return_if_fail(FALSE);
/* this is okay, just lame. */
g_date_clear( out_date, 1 );
break;
case ONCE:
if ( g_date_compare( &(fs->s.once.date), CONST_HACK in_date ) > 0 ) {
if ( g_date_compare( &(fs->s.once.date),
CONST_HACK in_date ) > 0 ) {
*out_date = fs->s.once.date;
} else {
/* Date is past due. Return an invalid date. */
@@ -290,147 +294,125 @@ xaccFreqSpecGetNextInstance(
break;
case DAILY: {
guint32 julian_in_date, julian_next_repeat, complete_intervals;
guint32 julian_in_date, julian_next_repeat, complete_intervals;
julian_in_date = g_date_julian( CONST_HACK in_date );
complete_intervals =
(julian_in_date - fs->s.daily.offset_from_epoch) /
fs->s.daily.interval_days;
julian_next_repeat =
fs->s.daily.offset_from_epoch +
(complete_intervals + 1) * fs->s.daily.interval_days;
g_date_set_julian( out_date, julian_next_repeat );
} break;
julian_in_date = g_date_julian( CONST_HACK in_date );
complete_intervals =
(julian_in_date - fs->s.daily.offset_from_epoch) /
fs->s.daily.interval_days;
julian_next_repeat =
fs->s.daily.offset_from_epoch +
(complete_intervals + 1) * fs->s.daily.interval_days;
g_date_set_julian( out_date, julian_next_repeat );
} break;
case WEEKLY: {
/* This implementation stores the offset from epoch as the number
* of days, not week epoch offset and day in week offset.
* It is very similar to the daily repeat representation. */
guint32 julian_in_date, julian_next_repeat, complete_intervals;
/* This implementation stores the offset from epoch as the number
* of days, not week epoch offset and day in week offset.
* It is very similar to the daily repeat representation. */
guint32 julian_in_date, julian_next_repeat, complete_intervals;
julian_in_date = g_date_julian( CONST_HACK in_date );
complete_intervals =
(julian_in_date - fs->s.weekly.offset_from_epoch) /
(fs->s.weekly.interval_weeks * 7);
julian_next_repeat =
fs->s.weekly.offset_from_epoch +
(complete_intervals + 1) * fs->s.weekly.interval_weeks * 7;
g_date_set_julian( out_date, julian_next_repeat );
/* This code passes the test, but it seems large and complicated...
* it uses a separate week offset from epoch and day in week offset. */
/* guint32 julian_in_date, julian_next_repeat, complete_intervals,
in_weeks_from_epoch, after_repeat_in_week_interval;
julian_in_date = g_date_julian( CONST_HACK in_date );
in_weeks_from_epoch = (julian_in_date-1) / 7;
complete_intervals =
(in_weeks_from_epoch -
fs->s.weekly.offset_from_epoch) /
fs->s.weekly.interval_weeks;
after_repeat_in_week_interval =
((julian_in_date-1) % 7 >= fs->s.weekly.day_of_week ||
(in_weeks_from_epoch - fs->s.weekly.offset_from_epoch) %
fs->s.weekly.interval_weeks > 0 ) ? 1 : 0;
julian_next_repeat =
(fs->s.weekly.offset_from_epoch +
(complete_intervals + after_repeat_in_week_interval) *
fs->s.weekly.interval_weeks) * 7 +
fs->s.weekly.day_of_week + 1;
g_date_set_julian( out_date, julian_next_repeat );
*/
} break;
julian_in_date = g_date_julian( CONST_HACK in_date );
complete_intervals =
(julian_in_date - fs->s.weekly.offset_from_epoch) /
(fs->s.weekly.interval_weeks * 7);
julian_next_repeat =
fs->s.weekly.offset_from_epoch +
(complete_intervals + 1) * fs->s.weekly.interval_weeks * 7;
g_date_set_julian( out_date, julian_next_repeat );
} break;
case MONTHLY: {
guint32 in_months_from_epoch, after_repeat_in_month_interval,
complete_intervals, next_repeat_months_from_epoch, month, year;
guint32 in_months_from_epoch, after_repeat_in_month_interval,
complete_intervals, next_repeat_months_from_epoch, month, year;
in_months_from_epoch = (g_date_year( CONST_HACK in_date )-1) * 12 +
g_date_month( CONST_HACK in_date ) - 1;
complete_intervals =
(in_months_from_epoch - fs->s.monthly.offset_from_epoch) /
fs->s.monthly.interval_months;
after_repeat_in_month_interval =
(g_date_day( CONST_HACK in_date ) >= fs->s.monthly.day_of_month ||
(in_months_from_epoch - fs->s.monthly.offset_from_epoch) %
fs->s.monthly.interval_months > 0 ||
g_date_day( CONST_HACK in_date ) >=
g_date_days_in_month( g_date_month( CONST_HACK in_date ),
g_date_year( CONST_HACK in_date ) ) ) ? 1 : 0;
next_repeat_months_from_epoch =
fs->s.monthly.offset_from_epoch +
(complete_intervals + after_repeat_in_month_interval) *
fs->s.monthly.interval_months;
/* Hmmm... what happens if the day of the month is greater than the
* number of days in this month?
* Here I have constrained the day of the month by the number
* of days in the month. This is compensated for above by checking if
* the input day is the last day of that month, in which case it will
* move to the next month interval.
*/
month = next_repeat_months_from_epoch % 12 + 1;
year = next_repeat_months_from_epoch / 12 + 1;
g_date_set_dmy( out_date,
in_months_from_epoch = (g_date_year( CONST_HACK in_date )-1) * 12 +
g_date_month( CONST_HACK in_date ) - 1;
complete_intervals =
(in_months_from_epoch - fs->s.monthly.offset_from_epoch) /
fs->s.monthly.interval_months;
after_repeat_in_month_interval =
(g_date_day( CONST_HACK in_date ) >= fs->s.monthly.day_of_month ||
(in_months_from_epoch - fs->s.monthly.offset_from_epoch) %
fs->s.monthly.interval_months > 0 ||
g_date_day( CONST_HACK in_date ) >=
g_date_days_in_month( g_date_month( CONST_HACK in_date ),
g_date_year( CONST_HACK in_date ) ) ) ? 1 : 0;
next_repeat_months_from_epoch =
fs->s.monthly.offset_from_epoch +
(complete_intervals + after_repeat_in_month_interval) *
fs->s.monthly.interval_months;
/* Hmmm... what happens if the day of the month is greater than the
* number of days in this month?
* Here I have constrained the day of the month by the number
* of days in the month. This is compensated for above by checking if
* the input day is the last day of that month, in which case it will
* move to the next month interval.
*/
month = next_repeat_months_from_epoch % 12 + 1;
year = next_repeat_months_from_epoch / 12 + 1;
g_date_set_dmy( out_date,
min( fs->s.monthly.day_of_month,
g_date_days_in_month( month, year ) ),
g_date_days_in_month( month, year ) ),
month,
year );
} break;
} break;
case MONTH_RELATIVE: {
guint32 in_months_from_epoch, after_repeat_in_month_interval,
complete_intervals, next_repeat_months_from_epoch, month, year,
wday_of_1st, day_of_repeat;
guint32 in_months_from_epoch, after_repeat_in_month_interval,
complete_intervals, next_repeat_months_from_epoch, month, year,
wday_of_1st, day_of_repeat;
GDate date1;
in_months_from_epoch = (g_date_year( CONST_HACK in_date )-1) * 12 +
g_date_month( CONST_HACK in_date ) - 1;
complete_intervals =
(in_months_from_epoch - fs->s.month_relative.offset_from_epoch) /
fs->s.month_relative.interval_months;
month = g_date_month( CONST_HACK in_date );
year = g_date_year( CONST_HACK in_date );
g_date_set_dmy( &date1, 1, month, year );
wday_of_1st = g_date_weekday( &date1 );
day_of_repeat = (fs->s.month_relative.occurrence-1)*7 +
((fs->s.month_relative.weekday + 7 - wday_of_1st)%7 + 1);
after_repeat_in_month_interval =
(g_date_day( CONST_HACK in_date ) >= day_of_repeat ||
day_of_repeat > g_date_days_in_month( month, year ) ||
(in_months_from_epoch - fs->s.month_relative.offset_from_epoch) %
fs->s.month_relative.interval_months > 0 ) ? 1 : 0;
GDate date1;
in_months_from_epoch = (g_date_year( CONST_HACK in_date )-1) * 12 +
g_date_month( CONST_HACK in_date ) - 1;
complete_intervals =
(in_months_from_epoch - fs->s.month_relative.offset_from_epoch) /
fs->s.month_relative.interval_months;
month = g_date_month( CONST_HACK in_date );
year = g_date_year( CONST_HACK in_date );
g_date_set_dmy( &date1, 1, month, year );
wday_of_1st = g_date_weekday( &date1 );
day_of_repeat = (fs->s.month_relative.occurrence-1)*7 +
((fs->s.month_relative.weekday + 7 - wday_of_1st)%7 + 1);
after_repeat_in_month_interval =
(g_date_day( CONST_HACK in_date ) >= day_of_repeat ||
day_of_repeat > g_date_days_in_month( month, year ) ||
(in_months_from_epoch - fs->s.month_relative.offset_from_epoch) %
fs->s.month_relative.interval_months > 0 ) ? 1 : 0;
next_repeat_months_from_epoch =
fs->s.month_relative.offset_from_epoch +
(complete_intervals + after_repeat_in_month_interval) *
fs->s.month_relative.interval_months;
month = next_repeat_months_from_epoch % 12 + 1;
year = next_repeat_months_from_epoch / 12 + 1;
g_date_set_dmy( &date1, 1, month, year );
wday_of_1st = g_date_weekday( &date1 );
/* This calculates the day of the month in the month which forms
* the next month in the cycle after the given input date.
* However, this day may be larger than the number of days in that month... */
day_of_repeat = (fs->s.month_relative.occurrence-1)*7 +
((fs->s.month_relative.weekday + 7 - wday_of_1st)%7 + 1);
while( day_of_repeat > g_date_days_in_month( month, year ) ) {
/* If the repeat occurs after the end of the month, then
* find the next month containing a day which satisfies the request.
* Each candiate month separated by interval_months is considered
* by this loop.*/
++complete_intervals;
next_repeat_months_from_epoch =
fs->s.month_relative.offset_from_epoch +
(complete_intervals + after_repeat_in_month_interval) *
fs->s.month_relative.interval_months;
complete_intervals * fs->s.month_relative.interval_months;
month = next_repeat_months_from_epoch % 12 + 1;
year = next_repeat_months_from_epoch / 12 + 1;
g_date_set_dmy( &date1, 1, month, year );
wday_of_1st = g_date_weekday( &date1 );
/* This calculates the day of the month in the month which forms
* the next month in the cycle after the given input date.
* However, this day may be larger than the number of days in that month... */
day_of_repeat = (fs->s.month_relative.occurrence-1)*7 +
((fs->s.month_relative.weekday + 7 - wday_of_1st)%7 + 1);
while( day_of_repeat > g_date_days_in_month( month, year ) ) {
/* If the repeat occurs after the end of the month, then
* find the next month containing a day which satisfies the request.
* Each candiate month separated by interval_months is considered
* by this loop.*/
++complete_intervals;
next_repeat_months_from_epoch =
fs->s.month_relative.offset_from_epoch +
complete_intervals * fs->s.month_relative.interval_months;
month = next_repeat_months_from_epoch % 12 + 1;
year = next_repeat_months_from_epoch / 12 + 1;
g_date_set_dmy( &date1, 1, month, year );
wday_of_1st = g_date_weekday( &date1 );
day_of_repeat = (fs->s.month_relative.occurrence-1)*7 +
((fs->s.month_relative.weekday + 7 - wday_of_1st)%7 + 1);
/* Hmmm... It would be nice to know that this loop is
* guaranteed to terminate... CHECK ME! */
}
g_date_set_dmy( out_date, day_of_repeat, month, year );
} break;
/* Hmmm... It would be nice to know that this loop is
* guaranteed to terminate... CHECK ME! */
}
g_date_set_dmy( out_date, day_of_repeat, month, year );
} break;
case COMPOSITE:
list = fs->s.composites.subSpecs;
@@ -934,6 +916,7 @@ xaccFreqSpecGetFreqStr( FreqSpec *fs, GString *str )
}
}
static
int
int_cmp( int a, int b )
{
+1 -1
View File
@@ -282,7 +282,7 @@ gnc_account_sel_set_account( GNCAccountSel *gas, Account *acct )
}
acctStr = xaccAccountGetFullName( acct,
gnc_get_account_separator() );
gtk_entry_set_text( GTK_EDITABLE(gas->combo->entry), acctStr );
gtk_entry_set_text( GTK_ENTRY(gas->combo->entry), acctStr );
g_free( acctStr );
}
+38 -46
View File
@@ -29,12 +29,15 @@
#include <gtk/gtk.h>
#include "gnc-dense-cal.h"
/* For PERR, only... */
#include "gnc-engine-util.h"
/**
* Todo:
* . marking
* . color-per-marker (configurable)
* X all-or-nothing
* . handle errors properly
* \ handle errors properly
* X mouse-over -> "hottip"
* X rotated month labels
* X weeksPerCol -> monthsPerCol
@@ -99,6 +102,8 @@ enum gnc_dense_cal_signal_enum {
static gint gnc_dense_cal_signals[LAST_SIGNAL] = { 0 };
static short module = MOD_SX;
static void gnc_dense_cal_class_init (GncDenseCalClass *class);
static void gnc_dense_cal_init (GncDenseCal *dcal);
static void gnc_dense_cal_destroy (GtkObject *object);
@@ -264,8 +269,8 @@ gnc_dense_cal_init (GncDenseCal *dcal)
dcal->weekColors,
MAX_COLORS, TRUE, TRUE,
&colorAllocSuccess ) > 0 ) {
/* FIXME : handle properly */
printf( "Error allocating colors\n" );
/* FIXME : handle [more] properly */
PERR( "Error allocating colors\n" );
}
/* Deal with the various label sizes. */
@@ -275,16 +280,10 @@ gnc_dense_cal_init (GncDenseCal *dcal)
gint lbearing, rbearing, width, ascent, descent;
dcal->monthLabelFont = gdk_font_load( LABEL_FONT_NAME );
if ( dcal->monthLabelFont == NULL ) {
printf( "Couldn't load font \"%s\"\n", LABEL_FONT_NAME );
gtk_main_quit();
}
g_assert( dcal->monthLabelFont );
dcal->dayLabelFont = GTK_WIDGET(dcal)->style->font;
if ( dcal->dayLabelFont == NULL ) {
printf( "Couldn't get day-label font from widget->style\n" );
gtk_main_quit();
}
g_assert( dcal->dayLabelFont );
maxWidth = maxHeight = maxAscent = maxLBearing = 0;
for ( i=0; i<12; i++ ) {
@@ -370,8 +369,8 @@ gnc_dense_cal_set_month( GncDenseCal *dcal, GDateMonth mon )
recompute_extents( dcal );
if ( GTK_WIDGET_REALIZED( dcal ) ) {
recompute_x_y_scales( dcal );
gtk_widget_queue_draw( GTK_WIDGET(dcal) );
}
gtk_widget_queue_draw( GTK_WIDGET(dcal) );
}
void
@@ -475,7 +474,7 @@ gnc_dense_cal_size_request( GtkWidget *widget,
{
GncDenseCal *dcal = GNC_DENSE_CAL(widget);
if ( !dcal->initialized ) {
printf( "Uninitialized size request\n" );
PERR( "Uninitialized size request\n" );
requisition->width = DENSE_CAL_DEFAULT_WIDTH;
requisition->height = DENSE_CAL_DEFAULT_HEIGHT;
return;
@@ -546,10 +545,9 @@ recompute_mark_storage( GncDenseCal *dcal )
goto createNew;
}
dcal->markData = NULL;
for ( i=0; i<oldNumMarks; i++ ) {
/* Each of these just contains an elt of dcal->markData,
* which we're about to free... */
* which we're about to free, below... */
g_list_free( dcal->marks[i] );
}
g_free( dcal->marks );
@@ -559,6 +557,7 @@ recompute_mark_storage( GncDenseCal *dcal )
g_list_free( ((gdc_mark_data*)l->data)->ourMarks );
g_free( (gdc_mark_data*)l->data );
}
g_list_free( dcal->markData );
dcal->markData = NULL;
createNew:
@@ -748,9 +747,9 @@ gnc_dense_cal_expose( GtkWidget *widget,
/* FIXME: use a different GC for this */
gdk_gc_set_foreground( widget->style->fg_gc[widget->state], &markColor );
for ( i=0; i<num_weeks(dcal)*7; i++ ) {
l = dcal->marks[i];
for ( ; l ; l = l->next ) {
//for ( i=0; i<num_weeks(dcal)*7; i++ ) {
for ( i=0; i<dcal->numMarks; i++ ) {
for ( l = dcal->marks[i]; l ; l = l->next ) {
gdcmd = (gdc_mark_data*)l->data;
doc_coords( dcal, i, &x1, &y1, &x2, &y2 );
gdk_draw_rectangle( widget->window,
@@ -1264,27 +1263,27 @@ wheres_this( GncDenseCal *dcal, int x, int y )
y -= dcal->topPadding;
if ( (x < 0) || (y < 0) ) {
printf( "x(%d) or y(%d) < 0\n", x, y );
PERR( "x(%d) or y(%d) < 0\n", x, y );
return -1;
}
if ( (x >= GTK_WIDGET(dcal)->allocation.width)
|| (y >= GTK_WIDGET(dcal)->allocation.height) ) {
printf( "x(%d) > allocation.width(%d) or y(%d) > allocation->height(%d)\n",
x, y,
GTK_WIDGET(dcal)->allocation.width,
GTK_WIDGET(dcal)->allocation.height );
PERR( "x(%d) > allocation.width(%d) or y(%d) > allocation->height(%d)\n",
x, y,
GTK_WIDGET(dcal)->allocation.width,
GTK_WIDGET(dcal)->allocation.height );
return -1;
}
/* "outside of displayed table" check */
if ( x >= (num_cols(dcal) * (col_width(dcal) + COL_BORDER_SIZE)) ) {
printf( "x(%d) > ( col_width(%d) * num_cols(%d) )\n",
x, col_width(dcal), num_cols(dcal) );
PERR( "x(%d) > ( col_width(%d) * num_cols(%d) )\n",
x, col_width(dcal), num_cols(dcal) );
return -1;
}
if ( y >= col_height(dcal) ) {
printf( "y(%d) > col_height(%d)\n",
y, col_height(dcal) );
PERR( "y(%d) > col_height(%d)\n",
y, col_height(dcal) );
return -1;
}
@@ -1294,17 +1293,17 @@ wheres_this( GncDenseCal *dcal, int x, int y )
x %= (col_width(dcal)+COL_BORDER_SIZE);
x -= dcal->label_width;
if ( x < 0 ) {
printf( "X is over the label.\n" );
PERR( "X is over the label.\n" );
return -1;
}
if ( x >= day_width(dcal) * 7 ) {
printf( "X is in the col_border space.\n" );
PERR( "X is in the col_border space.\n" );
return -1;
}
y -= dcal->dayLabelHeight;
if ( y < 0 ) {
printf( "Y is over the label.\n" );
PERR( "Y is over the label.\n" );
return -1;
}
@@ -1317,7 +1316,7 @@ wheres_this( GncDenseCal *dcal, int x, int y )
dayCol -= (g_date_weekday(&d) % 7);
if ( weekRow == 0 ) {
if ( dayCol < 0 ) {
printf( "Before the beginning of the first month.\n" );
PERR( "Before the beginning of the first month.\n" );
return -1;
}
}
@@ -1329,8 +1328,8 @@ wheres_this( GncDenseCal *dcal, int x, int y )
g_date_set_dmy( &ccd, 1, dcal->month, dcal->year );
g_date_add_months( &ccd, (colNum+1) * dcal->monthsPerCol );
if ( g_date_julian(&d) >= g_date_julian(&ccd) ) {
printf( "%d outside of column range [%d]\n",
g_date_julian(&d), g_date_julian(&ccd) );
PERR( "%d outside of column range [%d]\n",
g_date_julian(&d), g_date_julian(&ccd) );
return -1;
}
}
@@ -1341,8 +1340,8 @@ wheres_this( GncDenseCal *dcal, int x, int y )
g_date_subtract_months( &d, dcal->numMonths );
if ( g_date_julian(&d) >= g_date_julian(&startD) ) {
/* we're past the end of the displayed calendar, thus -1 */
printf( "%d >= %d\n",
g_date_julian( &d ), g_date_julian( &startD ) );
PERR( "%d >= %d\n",
g_date_julian( &d ), g_date_julian( &startD ) );
return -1;
}
@@ -1384,16 +1383,15 @@ gnc_dense_cal_mark( GncDenseCal *dcal,
gint i, doc;
gdc_mark_data *newMark;
GDate *d;
GList *l;
if ( size == 0 ) {
printf( "0 size not allowed\n" );
PERR( "0 size not allowed\n" );
return -1;
}
if ( name == NULL
|| strlen(name) == 0 ) {
printf( "name must be reasonable\n" );
PERR( "name must be reasonable\n" );
return -1;
}
@@ -1410,16 +1408,10 @@ gnc_dense_cal_mark( GncDenseCal *dcal,
d = dateArray[i];
doc = gdc_get_doc_offset( dcal, d );
if ( doc < 0 ) {
#if 0 /* Silently ignore. */
printf( "This is TheErrorThatShouldBeAppropriately"
"Handeled @ %d for \"%s\" with %d\n",
i, name, doc );
#endif /* 0 */
continue;
}
l = g_list_alloc();
l->data = newMark;
dcal->marks[doc] = g_list_concat( dcal->marks[doc], l );
g_assert( doc < dcal->numMarks );
dcal->marks[doc] = g_list_append( dcal->marks[doc], newMark );
newMark->ourMarks = g_list_append( newMark->ourMarks,
GINT_TO_POINTER(doc) );
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -52,7 +52,7 @@ typedef struct _GNCFrequency {
typedef struct _GNCFrequencyClass {
GtkVBoxClass parent_class;
void (*value_changed) (GNCFrequency *gf);
void (*changed) (GNCFrequency *gf);
} GNCFrequencyClass;
struct pageDataTuple {
+257 -81
View File
@@ -53,6 +53,10 @@
/* FIXME: temp until variable-related-stuff settled. */
#include "dialog-sxsincelast.h"
#ifdef HAVE_LANGINFO_D_FMT
#include <langinfo.h>
#endif
static short module = MOD_SX;
#define SX_LIST_WIN_PREFIX "sx_list_win"
@@ -64,6 +68,7 @@ static short module = MOD_SX;
#define SXED_WIN_PREFIX "sx_editor_win"
#define SXED_NAME_ENTRY "sxe_name"
#define SXED_LAST_OCCUR_LABEL "last_occur_label"
#define AUTOCREATE_OPT "autocreate_opt"
#define NOTIFY_OPT "notify_opt"
#define ADVANCE_OPT "advance_opt"
@@ -73,6 +78,7 @@ static short module = MOD_SX;
#define END_DATE_DATEENTRY "sxe_end_date"
#define END_GNOME_NUMENTRY "end_gnome_nentry"
#define REMAIN_GNOME_NUMENTRY "remain_gnome_nentry"
#define REMAIN_ENTRY "remain_nentry"
#define END_NEVER_OPTION 0
#define END_DATE_OPTION 1
@@ -80,6 +86,18 @@ static short module = MOD_SX;
#define NUM_LEDGER_LINES_DEFAULT 6
#define EX_CAL_NUM_MONTHS 6
#define EX_CAL_MO_PER_COL 2
#ifdef HAVE_LANGINFO_D_FMT
# define GNC_D_FMT (nl_langinfo (D_FMT))
#else
# define GNC_D_FMT "%Y-%m-%d"
#endif
#define GNC_D_WIDTH 25
#define GNC_D_BUF_WIDTH 26
/** Datatypes ***********************************************************/
typedef enum _EndTypeEnum {
@@ -113,8 +131,14 @@ struct _SchedXactionEditorDialog
GnucashRegister *reg;
GNCFrequency *gncfreq;
GncDenseCal *example_cal;
GDate **cal_marks;
gint markId;
GtkEditable *nameEntry;
GtkLabel *lastOccurLabel;
GtkToggleButton *autocreateOpt;
GtkToggleButton *notifyOpt;
GtkToggleButton *advanceOpt;
@@ -174,8 +198,13 @@ static void set_endgroup_toggle_states( SchedXactionEditorDialog *sxed, EndType
static void advance_toggle( GtkButton *b, SchedXactionEditorDialog *sxed );
static gboolean gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed );
static gboolean gnc_sxed_check_changed( SchedXactionEditorDialog *sxed );
static void free_keys_and_numerics_ea( gpointer key,
gpointer value,
gpointer user_data );
static void gnc_sxed_save_sx( SchedXactionEditorDialog *sxed );
static void gnc_sxed_freq_changed( GNCFrequency *gf, gpointer ud );
static void sxed_excal_update_adapt( GtkObject *o, gpointer ud );
static void gnc_sxed_update_cal( SchedXactionEditorDialog *sxed );
/* ledger standard-handlers */
static gncUIWidget sxe_ledger_get_parent( GNCLedgerDisplay *ld );
@@ -218,7 +247,7 @@ static
void
sxed_close_handler ( gpointer user_data )
{
SchedXactionEditorDialog *sxed = user_data;
SchedXactionEditorDialog *sxed = user_data;
gnc_sxed_reg_check_close( sxed );
gnc_sxed_record_size( sxed );
@@ -270,22 +299,23 @@ editor_help_button_clicked(GtkButton *b, SchedXactionEditorDialog *sxed)
static void
set_var_to_random_value( gpointer key, gpointer value, gpointer ud )
{
gnc_numeric *val;
val = g_new0( gnc_numeric, 1 );
*val = double_to_gnc_numeric( rand() + 2, 1,
GNC_NUMERIC_RND_MASK
| GNC_RND_FLOOR );
if ( value != NULL ) {
g_free( value );
if ( !value ) {
value = g_new0( gnc_numeric, 1 );
}
g_hash_table_insert( ud, key, val );
*(gnc_numeric*)value =
double_to_gnc_numeric( rand() + 2, 1,
GNC_NUMERIC_RND_MASK
| GNC_RND_FLOOR );
g_hash_table_insert( ud, key, value );
}
static
void
free_var_numeric( gpointer key, gpointer val, gpointer ud )
free_keys_and_numerics_ea( gpointer key, gpointer val, gpointer ud )
{
g_assert( key );
g_assert( val );
g_free( (gchar*)key );
g_free( (gnc_numeric*)val );
}
@@ -312,8 +342,8 @@ editor_ok_button_clicked( GtkButton *b, SchedXactionEditorDialog *sxed )
}
/* cleanup */
gnc_close_gui_component_by_data (DIALOG_SCHEDXACTION_EDITOR_CM_CLASS,
sxed);
gnc_close_gui_component_by_data( DIALOG_SCHEDXACTION_EDITOR_CM_CLASS,
sxed );
}
/**
@@ -619,11 +649,14 @@ gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
/* Subtract out pre-defined vars */
if ( g_hash_table_lookup_extended( vars, "i",
&unusedKey, &unusedValue ) ) {
&unusedKey,
&unusedValue ) ) {
ttVarCount -= 1;
}
g_hash_table_foreach( vars, free_var_numeric, (gpointer)vars );
g_hash_table_foreach( vars,
free_keys_and_numerics_ea,
NULL );
g_hash_table_destroy( vars );
if ( unbalanceable
@@ -907,18 +940,19 @@ scheduledxaction_dialog_destroy(GtkObject *object, gpointer data)
{
SchedXactionDialog *sxd = data;
if (!sxd) return;
if ( !sxd ) return;
gnc_unregister_gui_component_by_data
(DIALOG_SCHEDXACTION_CM_CLASS, sxd);
(DIALOG_SCHEDXACTION_CM_CLASS, sxd);
g_free(sxd);
g_free( sxd );
}
/* Local destruction of dialog */
static void
scheduledxaction_editor_dialog_destroy(GtkObject *object, gpointer data)
{
int i;
SchedXactionEditorDialog *sxed = data;
if (sxed == NULL)
@@ -928,17 +962,21 @@ scheduledxaction_editor_dialog_destroy(GtkObject *object, gpointer data)
(DIALOG_SCHEDXACTION_EDITOR_CM_CLASS, sxed);
if ( sxed->newsxP ) {
/* FIXME: WTF??? */
xaccSchedXactionFree( sxed->sx );
}
sxed->sx = NULL;
/* FIXME:
* . what do we need to do to clean up the reg widget?
* . what about the rest of the dialog?
*/
/* We don't need to deal with the ledger, as the gncRegWidget will do
* so for us. */
g_free (sxed->sxGUIDstr);
sxed->sxGUIDstr = NULL;
for ( i=0; i<(EX_CAL_NUM_MONTHS*31); i++ ) {
g_free( sxed->cal_marks[i] );
}
g_free( sxed->cal_marks );
g_free (sxed);
}
@@ -1037,24 +1075,6 @@ gnc_sxl_record_size( SchedXactionDialog *sxd )
gnc_save_window_size( SX_LIST_WIN_PREFIX, w, h );
}
void
gnc_ui_scheduled_xaction_dialog_destroy(SchedXactionDialog *sxd)
{
if (sxd == NULL)
return;
gnc_close_gui_component_by_data (DIALOG_SCHEDXACTION_CM_CLASS, sxd);
}
void
gnc_ui_scheduled_xaction_editor_dialog_destroy(SchedXactionEditorDialog *sxed)
{
if (sxed == NULL)
return;
gnc_close_gui_component_by_data
(DIALOG_SCHEDXACTION_EDITOR_CM_CLASS, sxed);
}
void
row_select_handler( GtkCList *clist,
gint row,
@@ -1116,6 +1136,8 @@ gnc_sxed_get_widgets( SchedXactionEditorDialog *sxed )
w = glade_xml_get_widget( sxed->gxml, SXED_NAME_ENTRY );
sxed->nameEntry = GTK_EDITABLE(w);
w = glade_xml_get_widget( sxed->gxml, SXED_LAST_OCCUR_LABEL );
sxed->lastOccurLabel = GTK_LABEL(w);
w = glade_xml_get_widget( sxed->gxml, AUTOCREATE_OPT );
sxed->autocreateOpt = GTK_TOGGLE_BUTTON(w);
w = glade_xml_get_widget( sxed->gxml, NOTIFY_OPT );
@@ -1167,12 +1189,15 @@ gnc_ui_scheduled_xaction_editor_dialog_create( SchedXactionDialog *sxd,
} widgets[] = {
{ "ok_button", "clicked", editor_ok_button_clicked, NULL },
{ "cancel_button", "clicked", editor_cancel_button_clicked, NULL },
{ "help_button", "clicked", editor_help_button_clicked, NULL},
{ "help_button", "clicked", editor_help_button_clicked, NULL },
{ "rb_noend", "toggled", endgroup_rb_toggled, GINT_TO_POINTER(END_NEVER_OPTION) },
{ "rb_enddate", "toggled", endgroup_rb_toggled, GINT_TO_POINTER(END_DATE_OPTION) },
{ "rb_num_occur", "toggled", endgroup_rb_toggled, GINT_TO_POINTER(NUM_OCCUR_OPTION) },
{ END_DATE_DATEENTRY, "date-changed", sxed_excal_update_adapt, NULL },
{ REMAIN_ENTRY , "changed", sxed_excal_update_adapt, NULL },
{ "autocreate_opt", "toggled", autocreate_toggled, NULL },
{ "advance_opt", "toggled", advance_toggle, (gpointer)ADVANCE_DAYS_SPIN },
{ "remind_opt", "toggled", advance_toggle, (gpointer)REMIND_DAYS_SPIN },
@@ -1198,6 +1223,15 @@ gnc_ui_scheduled_xaction_editor_dialog_create( SchedXactionDialog *sxd,
sxed->sxd = sxd;
sxed->sx = sx;
sxed->newsxP = newSX;
/* Setup dense-cal local mark storage */
{
int i;
sxed->cal_marks = g_new0( GDate*, EX_CAL_NUM_MONTHS * 31 );
for( i=0; i<(EX_CAL_NUM_MONTHS * 31); i++ ) {
sxed->cal_marks[i] = g_date_new();
}
sxed->markId = -1;
}
/* NOTE: this must occur before processing the widget list, above, so
* the gpointers stored with the advance_ and remind_opts are
@@ -1216,8 +1250,6 @@ gnc_ui_scheduled_xaction_editor_dialog_create( SchedXactionDialog *sxd,
GTK_SIGNAL_FUNC(scheduledxaction_editor_dialog_destroy),
sxed);
/* FIXME: want delete-event, too. [?] */
for ( i=0; widgets[i].name != NULL; i++ ) {
button = glade_xml_get_widget( sxed->gxml, widgets[i].name );
if ( widgets[i].objectData != NULL ) {
@@ -1230,8 +1262,8 @@ gnc_ui_scheduled_xaction_editor_dialog_create( SchedXactionDialog *sxd,
GTK_SIGNAL_FUNC( widgets[i].fn ), sxed );
}
/* FIXME: For some reason the Glade-specified sensitivity settings
* are not being honored. */
/* For some reason the Glade-specified sensitivity settings are not
* being honored... ? */
gtk_widget_set_sensitive( GTK_WIDGET(sxed->notifyOpt), FALSE );
gtk_widget_set_sensitive( GTK_WIDGET(sxed->advanceSpin), FALSE );
gtk_widget_set_sensitive( GTK_WIDGET(sxed->remindSpin), FALSE );
@@ -1249,7 +1281,8 @@ gnc_ui_scheduled_xaction_editor_dialog_create( SchedXactionDialog *sxd,
}
}
/* create the frequency-selection macrowidget */
/* create the frequency-selection macrowidget and example
* [dense-]calendar. */
schedXact_editor_create_freq_sel( sxed );
/* create the template-transaction ledger window */
schedXact_editor_create_ledger( sxed );
@@ -1276,28 +1309,26 @@ void
schedXact_editor_create_freq_sel( SchedXactionEditorDialog *sxed )
{
GtkFrame *f;
GtkBox *b;
f = GTK_FRAME( glade_xml_get_widget( sxed->gxml,
"recur_frame" ) );
f = GTK_FRAME(glade_xml_get_widget( sxed->gxml, "gncfreq_frame" ));
b = GTK_BOX( glade_xml_get_widget( sxed->gxml,
"recur_box" ) );
sxed->gncfreq =
GNC_FREQUENCY( gnc_frequency_new( xaccSchedXactionGetFreqSpec(sxed->sx),
xaccSchedXactionGetStartDate(sxed->sx) ) );
if ( sxed->gncfreq == NULL ) {
PERR( "gnc_frequency_new returned 0\n" );
return;
}
g_assert( sxed->gncfreq );
gtk_signal_connect( GTK_OBJECT(sxed->gncfreq), "changed",
GTK_SIGNAL_FUNC(gnc_sxed_freq_changed),
sxed );
gtk_container_add( GTK_CONTAINER(f), GTK_WIDGET(sxed->gncfreq) );
}
static void
sxe_ledger_destroy( GNCLedgerDisplay *ld )
{
SchedXactionEditorDialog *sxed;
sxed =(SchedXactionEditorDialog*)
gnc_ledger_display_get_user_data( ld );
DEBUG( "ledger's being destroyed... we probably want "
"to clean up in some appropriate way." );
f = GTK_FRAME(glade_xml_get_widget( sxed->gxml, "example_cal_frame" ));
sxed->example_cal = GNC_DENSE_CAL(gnc_dense_cal_new());
g_assert( sxed->example_cal );
gnc_dense_cal_set_num_months( sxed->example_cal, EX_CAL_NUM_MONTHS );
gnc_dense_cal_set_months_per_col( sxed->example_cal, EX_CAL_MO_PER_COL );
gtk_container_add( GTK_CONTAINER(f), GTK_WIDGET(sxed->example_cal) );
}
static
@@ -1386,6 +1417,18 @@ schedXact_editor_populate( SchedXactionEditorDialog *sxed )
if ( name != NULL ) {
gtk_entry_set_text( GTK_ENTRY(sxed->nameEntry), name );
}
{
gd = xaccSchedXactionGetLastOccurDate( sxed->sx );
if ( g_date_valid( gd ) ) {
gchar dateBuf[ GNC_D_BUF_WIDTH ];
g_date_strftime( dateBuf, GNC_D_WIDTH, GNC_D_FMT, gd );
gtk_label_set_text( sxed->lastOccurLabel, dateBuf );
} else {
gtk_label_set_text( sxed->lastOccurLabel, _( "(never)" ) );
}
gd = NULL;
}
gd = xaccSchedXactionGetEndDate( sxed->sx );
if ( g_date_valid( gd ) ) {
gtk_toggle_button_set_active( sxed->optEndDate, TRUE );
@@ -1491,6 +1534,9 @@ schedXact_editor_populate( SchedXactionEditorDialog *sxed )
gnc_split_register_load(splitReg, splitList, NULL );
} /* otherwise, use the existing stuff. */
}
/* Update the example cal */
gnc_sxed_update_cal( sxed );
}
static
@@ -1667,7 +1713,7 @@ void
endgroup_rb_toggled( GtkButton *b, gpointer d )
{
/* figure out which one */
SchedXactionEditorDialog *sxed;
SchedXactionEditorDialog *sxed;
gint id;
sxed = (SchedXactionEditorDialog*)d;
@@ -1688,8 +1734,14 @@ endgroup_rb_toggled( GtkButton *b, gpointer d )
g_error( "Unknown id %d", id );
break;
}
gnc_sxed_update_cal( sxed );
}
/**
* This is a copy of more complex code from dialog-sxsincelast.c. They
* should probably be combined into a single useful function somewhere.
**/
static
void
generate_instances( SchedXaction *sx,
@@ -1758,14 +1810,13 @@ putSchedXactionInDialog( gpointer data, gpointer user_data )
generate_instances( sx, calEndDate, &instList );
g_date_free( calEndDate );
/* FIXME: cleanup the date memory, here... */
/* cleanup the date memory, here... */
if ( instList == NULL ) {
/* This was a bug [#90326]; while we do want to generate
* instances within the visible calendar range, we also want
* to generate the first, next SX instance regardless of the
* calendar range. Thus, if the generate_instances above
* returns nothing, double-check with the SX.
*/
* returns nothing, double-check with the SX. */
nextInstDate = g_date_new();
*nextInstDate = xaccSchedXactionGetNextInstance( sx, NULL );
if ( g_date_valid( nextInstDate ) ) {
@@ -1803,9 +1854,9 @@ putSchedXactionInDialog( gpointer data, gpointer user_data )
xaccSchedXactionGetName(sx),
freqDesc->str );
g_string_free( freqDesc, TRUE );
g_free( instArray );
g_list_foreach( instList, _gnc_sxd_free_dates, NULL );
g_list_free( instList );
g_free( instArray );
}
text[0] = xaccSchedXactionGetName( sx );
@@ -1859,9 +1910,9 @@ static
void
sxed_reg_recordCB( GtkWidget *w, gpointer d )
{
SchedXactionEditorDialog *sxed = (SchedXactionEditorDialog*)d;
SplitRegister *reg;
Transaction *trans;
SchedXactionEditorDialog *sxed = (SchedXactionEditorDialog*)d;
SplitRegister *reg;
Transaction *trans;
reg = gnc_ledger_display_get_split_register( sxed->ledger );
trans = gnc_split_register_get_current_trans( reg );
@@ -1910,7 +1961,8 @@ gnc_sxed_reg_check_close(SchedXactionEditorDialog *sxed)
pending_changes = gnc_split_register_changed (reg);
if (pending_changes) {
const char *message =
_("The current template transaction has been changed.\n"
_("The current template transaction "
"has been changed.\n"
"Would you like to record the changes?");
if (gnc_verify_dialog_parented(sxed->dialog, TRUE, message)) {
sxed_reg_recordCB(sxed->dialog, sxed);
@@ -1947,7 +1999,8 @@ gnc_sxd_row_click_handler( GtkCList *clist,
sxd->currentSortType = GTK_SORT_ASCENDING;
break;
default:
PERR( "Unknown current sort type %d", sxd->currentSortType );
PERR( "Unknown current sort type %d",
sxd->currentSortType );
}
/* By defn, the current sort_compare method is correct. */
gtk_clist_set_sort_column( clist, col );
@@ -1985,7 +2038,9 @@ gnc_sxd_clist_compare_sx_name( GtkCList *cl, gconstpointer a, gconstpointer b )
static
gint
gnc_sxd_clist_compare_sx_freq( GtkCList *cl, gconstpointer a, gconstpointer b )
gnc_sxd_clist_compare_sx_freq( GtkCList *cl,
gconstpointer a,
gconstpointer b )
{
SchedXaction *sxa, *sxb;
@@ -2042,22 +2097,143 @@ static
void
gnc_sxd_set_sort_compare( GtkCList *cl, gint col )
{
gint (*fn)( GtkCList *, gconstpointer, gconstpointer );
fn = NULL;
switch ( col ) {
case 0: /* SX name */
gtk_clist_set_compare_func( cl, NULL );
gtk_clist_set_compare_func( cl, gnc_sxd_clist_compare_sx_name );
fn = gnc_sxd_clist_compare_sx_name;
break;
case 1: /* SX frequency */
gtk_clist_set_compare_func( cl, NULL );
gtk_clist_set_compare_func( cl, gnc_sxd_clist_compare_sx_freq );
fn = gnc_sxd_clist_compare_sx_freq;
break;
case 2: /* next-occur date */
gtk_clist_set_compare_func( cl, NULL );
gtk_clist_set_compare_func(
cl, gnc_sxd_clist_compare_sx_next_occur );
fn = gnc_sxd_clist_compare_sx_next_occur;
break;
default: /* ?? */
DEBUG( "invalid column value %d", col );
g_assert( FALSE );
}
gtk_clist_set_compare_func( cl, NULL );
gtk_clist_set_compare_func( cl, fn );
}
typedef enum { NO_END, DATE_END, COUNT_END } END_TYPE;
static
void
gnc_sxed_update_cal( SchedXactionEditorDialog *sxed )
{
int i;
FreqSpec *fs;
GDate d;
END_TYPE endType;
GDate endDate;
int numRemain;
endType = NO_END;
numRemain = -1;
/* figure out the end restriction */
if ( gtk_toggle_button_get_active( sxed->optEndDate ) ) {
time_t tt;
struct tm *tmpTm;
endType = DATE_END;
tt = gnome_date_edit_get_date( sxed->endDateEntry );
tmpTm = g_new0( struct tm, 1 );
*tmpTm = *(localtime( &tt ));
g_date_set_day( &endDate, tmpTm->tm_mday );
g_date_set_month( &endDate, tmpTm->tm_mon+1 );
g_date_set_year( &endDate, tmpTm->tm_year + 1900 );
g_free( tmpTm );
} else if ( gtk_toggle_button_get_active( sxed->optEndNone ) ) {
endType = NO_END;
} else if ( gtk_toggle_button_get_active( sxed->optEndCount ) ) {
endType = COUNT_END;
numRemain =
(gint)gnome_number_entry_get_number(
sxed->endRemainEntry );
} else {
g_assert( FALSE );
}
if ( sxed->markId != -1 ) {
gnc_dense_cal_mark_remove( sxed->example_cal, sxed->markId );
sxed->markId = -1;
}
fs = xaccFreqSpecMalloc( gnc_get_current_book() );
gnc_frequency_save_state( sxed->gncfreq, fs, &d );
g_date_subtract_days( &d, 1 );
xaccFreqSpecGetNextInstance( fs, &d, &d );
/* Deal with the fact that this SX may have been run before [the
* calendar should only show upcoming instances]... */
{
GDate *lastInst;
lastInst = xaccSchedXactionGetLastOccurDate( sxed->sx );
if ( g_date_valid( lastInst )
&& g_date_compare( lastInst, &d ) <= 0 ) {
d = *lastInst;
}
xaccFreqSpecGetNextInstance( fs, &d, &d );
}
if ( !g_date_valid( &d ) ) {
/* Nothing to do. */
xaccFreqSpecFree( fs );
return;
}
i = 0;
gnc_dense_cal_set_month( sxed->example_cal,
g_date_month( &d ) );
gnc_dense_cal_set_year( sxed->example_cal,
g_date_year( &d ) );
while ( (i < EX_CAL_NUM_MONTHS * 31)
&& g_date_valid( &d )
/* Restrict based on end date */
&& ( endType == NO_END
|| ( endType == DATE_END
&& g_date_compare( &d, &endDate ) <= 0 )
|| ( endType == COUNT_END
&& i < numRemain ) ) ) {
*(sxed->cal_marks[i++]) = d;
xaccFreqSpecGetNextInstance( fs, &d, &d );
}
if ( i <= 0 ) {
xaccFreqSpecFree( fs );
return;
}
{
gchar *name;
GString *info;
name = gtk_editable_get_chars( sxed->nameEntry, 0, -1 );
info = g_string_sized_new( 16 );
xaccFreqSpecGetFreqStr( fs, info );
sxed->markId = gnc_dense_cal_mark( sxed->example_cal, i,
sxed->cal_marks,
name, info->str );
gtk_widget_queue_draw( GTK_WIDGET( sxed->example_cal ) );
g_free( name );
g_string_free( info, TRUE );
}
xaccFreqSpecFree( fs );
}
static
void
gnc_sxed_freq_changed( GNCFrequency *gf, gpointer ud )
{
gnc_sxed_update_cal( (SchedXactionEditorDialog*)ud );
}
static
void
sxed_excal_update_adapt( GtkObject *o, gpointer ud )
{
gnc_sxed_update_cal( (SchedXactionEditorDialog*)ud );
}
+187 -30
View File
@@ -36,6 +36,7 @@
#include "gnc-book-p.h"
#include "gnc-engine-util.h"
#include "gnc-ui-util.h"
#include "gnc-dense-cal.h"
#define SX_GLADE_FILE "sched-xact.glade"
#define SXFTD_DIALOG_GLADE_NAME "sx_from_real_trans"
@@ -50,6 +51,10 @@
#define SXFTD_FREQ_OPTION_MENU "freq_option_menu"
#define SXFTD_END_DATE_EDIT "end_date_edit"
#define SXFTD_START_DATE_EDIT "start_date_edit"
#define SXFTD_EX_CAL_FRAME "ex_cal_frame"
#define SXFTD_EXCAL_NUM_MONTHS 4
#define SXFTD_EXCAL_MONTHS_PER_COL 4
static short module = MOD_SX;
@@ -57,17 +62,19 @@ static void sxftd_ok_clicked(GtkWidget *w, gpointer user_data);
static void sxftd_freq_option_changed( GtkWidget *w, gpointer user_data );
static void sxftd_advanced_clicked(GtkWidget *w, gpointer user_data);
static void sxftd_cancel_clicked(GtkWidget *w, gpointer user_data);
static void sxftd_destroy( GtkWidget *w, gpointer user_data );
typedef enum {NEVER_END, END_ON_DATE, END_AFTER_N_OCCS, BAD_END} endType;
typedef enum { NEVER_END, END_ON_DATE, END_AFTER_N_OCCS, BAD_END } endType;
typedef enum {FREQ_DAILY = 0, /* I know the =0 is redundant, but I'm using
* the numeric equivalences explicitly here
*/
FREQ_WEEKLY,
FREQ_BIWEEKLY,
FREQ_MONTHLY,
FREQ_QUARTERLY,
FREQ_ANNUALLY } SxftiFreqType;
typedef enum { FREQ_DAILY = 0, /* I know the =0 is redundant, but I'm using
* the numeric equivalences explicitly here
*/
FREQ_WEEKLY,
FREQ_BIWEEKLY,
FREQ_MONTHLY,
FREQ_QUARTERLY,
FREQ_ANNUALLY
} SxftiFreqType;
typedef struct
{
@@ -75,8 +82,14 @@ typedef struct
GtkWidget *dialog;
Transaction *trans;
SchedXaction *sx;
} SXFromTransInfo;
GncDenseCal *example_cal;
/** Storage for the maximum possible number of marks we could put on the
* calendar. */
GDate **cal_marks;
gint mark_id;
} SXFromTransInfo;
typedef struct
{
@@ -85,6 +98,9 @@ typedef struct
guint n_occurrences;
} getEndTuple;
static void sxftd_update_example_cal( SXFromTransInfo *sxfti );
static void sxftd_update_excal_adapt( GtkObject *o, gpointer ud );
/* Stolen from jsled - nice and neat, actually (if a little light on
* for typechecking, but we'll be careful) . . .
*/
@@ -94,16 +110,26 @@ typedef struct
gchar *signal;
void (*handlerFn)();
} widgetSignalHandlerTuple;
static void
sxfti_attach_callbacks(SXFromTransInfo *sxfti)
{
widgetSignalHandlerTuple callbacks[] =
{
/* Whenever any of the controls change, we want to update the
* calendar. */
{ SXFTD_START_DATE_EDIT, "date-changed", sxftd_update_excal_adapt },
{ SXFTD_NEVER_END_BUTTON, "clicked", sxftd_update_excal_adapt },
{ SXFTD_END_ON_DATE_BUTTON, "clicked", sxftd_update_excal_adapt },
{ SXFTD_END_DATE_EDIT, "date-changed", sxftd_update_excal_adapt },
{ SXFTD_N_OCCURRENCES_BUTTON, "clicked", sxftd_update_excal_adapt },
{ SXFTD_N_OCCURRENCES_ENTRY, "changed", sxftd_update_excal_adapt },
{ SXFTD_OK_BUTTON, "clicked", sxftd_ok_clicked },
{ SXFTD_ADVANCED_BUTTON, "clicked", sxftd_advanced_clicked },
{ SXFTD_CANCEL_BUTTON, "clicked", sxftd_cancel_clicked },
{ NULL, NULL, NULL }
};
@@ -116,11 +142,8 @@ sxfti_attach_callbacks(SXFromTransInfo *sxfti)
gtk_signal_connect( GTK_OBJECT(w), callbacks[i].signal,
GTK_SIGNAL_FUNC(callbacks[i].handlerFn),
sxfti);
sxfti );
}
return;
}
@@ -285,6 +308,7 @@ sxftd_update_fs( SXFromTransInfo *sxfti, GDate *date, FreqSpec *fs )
default:
PERR("Nonexistent frequency selected. This is a bug.");
g_assert( FALSE );
break;
}
}
@@ -309,6 +333,24 @@ sxftd_init( SXFromTransInfo *sxfti )
sxfti_attach_callbacks(sxfti);
/* Setup the example calendar and related data structures. */
{
int i;
w = GTK_WIDGET(glade_xml_get_widget( sxfti->gxml, SXFTD_EX_CAL_FRAME ));
sxfti->example_cal = GNC_DENSE_CAL(gnc_dense_cal_new());
g_assert( sxfti->example_cal );
gnc_dense_cal_set_num_months( sxfti->example_cal, SXFTD_EXCAL_NUM_MONTHS );
gnc_dense_cal_set_months_per_col( sxfti->example_cal, SXFTD_EXCAL_MONTHS_PER_COL );
gtk_container_add( GTK_CONTAINER(w), GTK_WIDGET(sxfti->example_cal) );
sxfti->mark_id = -1;
sxfti->cal_marks = g_new0( GDate*, (SXFTD_EXCAL_NUM_MONTHS * 31) );
for ( i=0; i < SXFTD_EXCAL_NUM_MONTHS * 31; i++ ) {
sxfti->cal_marks[i] = g_date_new();
}
}
/* Get the name from the transaction, try that as the initial SX name. */
transName = xaccTransGetDescription( sxfti->trans );
xaccSchedXactionSetName( sxfti->sx, transName );
@@ -342,6 +384,11 @@ sxftd_init( SXFromTransInfo *sxfti )
gtk_signal_connect( GTK_OBJECT(w), "selection-done",
GTK_SIGNAL_FUNC(sxftd_freq_option_changed),
sxfti );
gtk_signal_connect( GTK_OBJECT(w), "destroy",
GTK_SIGNAL_FUNC(sxftd_destroy),
sxfti );
sxftd_update_example_cal( sxfti );
return 0;
}
@@ -404,19 +451,18 @@ sxftd_compute_sx(SXFromTransInfo *sxfti)
return sxftd_errno;
}
static void
sxftd_delete(SXFromTransInfo *sxfti, gboolean delete_sx)
static
void
sxftd_close(SXFromTransInfo *sxfti, gboolean delete_sx)
{
/* FIXME: do we need to clean up the GladeXML pointer ?*/
gnome_dialog_close( GNOME_DIALOG(sxfti->dialog));
if(sxfti->sx && delete_sx)
if ( sxfti->sx && delete_sx )
{
xaccSchedXactionFree(sxfti->sx);
}
sxfti->sx = NULL;
gnome_dialog_close( GNOME_DIALOG(sxfti->dialog));
g_free(sxfti);
return;
}
@@ -447,7 +493,7 @@ sxftd_ok_clicked(GtkWidget *w, gpointer user_data)
}
}
sxftd_delete(sxfti, FALSE);
sxftd_close(sxfti, FALSE);
return;
}
@@ -479,13 +525,16 @@ sxftd_freq_option_changed( GtkWidget *w, gpointer user_data )
tmp_tt = mktime( tmpTm );
g_free( tmpTm );
gnome_date_edit_set_time( GNOME_DATE_EDIT(start_date), tmp_tt );
xaccFreqSpecFree( fs );
sxftd_update_example_cal( sxfti );
}
static void
sxftd_cancel_clicked(GtkWidget *w, gpointer user_data)
{
SXFromTransInfo *sxfti = user_data;
sxftd_delete(sxfti, TRUE);
sxftd_close(sxfti, TRUE);
}
static void
@@ -506,16 +555,17 @@ sxftd_advanced_clicked(GtkWidget *w, gpointer user_data)
while (g_main_iteration(FALSE));
adv_dlg = gnc_ui_scheduled_xaction_dialog_create();
adv_edit_dlg = gnc_ui_scheduled_xaction_editor_dialog_create(adv_dlg,
sxfti->sx,
TRUE /* newSX */);
adv_edit_dlg =
gnc_ui_scheduled_xaction_editor_dialog_create(adv_dlg,
sxfti->sx,
TRUE /* newSX */);
/* close ourself, since advanced editing entails us, and there are sync
* issues otherwise. */
sxftd_delete(sxfti, FALSE);
sxftd_close(sxfti, FALSE);
}
void
gnc_sx_create_from_trans(Transaction *trans)
gnc_sx_create_from_trans( Transaction *trans )
{
int errno;
SXFromTransInfo *sxfti = g_new0( SXFromTransInfo, 1);
@@ -538,3 +588,110 @@ gnc_sx_create_from_trans(Transaction *trans)
return;
}
static
void
sxftd_destroy( GtkWidget *w, gpointer user_data )
{
int i;
SXFromTransInfo *sxfti = (SXFromTransInfo*)user_data;
for ( i=0; i<SXFTD_EXCAL_NUM_MONTHS*31; i++ ) {
g_date_free( sxfti->cal_marks[i] );
}
g_free( sxfti->cal_marks );
if ( sxfti->sx ) {
xaccSchedXactionFree(sxfti->sx);
sxfti->sx = NULL;
}
/* FIXME: do we need to clean up the GladeXML pointer? */
g_free(sxfti);
}
/**
* Update the example calendar; make sure to take into account the end
* specification.
**/
static
void
sxftd_update_example_cal( SXFromTransInfo *sxfti )
{
GtkWidget *start_date;
struct tm *tmpTm;
time_t tmp_tt;
GDate date, startDate;
int i;
FreqSpec *fs;
getEndTuple get;
gchar *name;
GString *info;
i = 0;
fs = xaccFreqSpecMalloc( gnc_get_current_book() );
get = sxftd_get_end_info( sxfti );
start_date = glade_xml_get_widget( sxfti->gxml, SXFTD_START_DATE_EDIT );
tmp_tt = gnome_date_edit_get_date( GNOME_DATE_EDIT(start_date) );
tmpTm = g_new0( struct tm, 1 );
*tmpTm = *localtime( &tmp_tt );
/* go one day before what's in the box so we can get the correct start
* date. */
g_date_set_day( &date, tmpTm->tm_mday-1 );
g_date_set_month( &date, tmpTm->tm_mon+1 );
g_date_set_year( &date, tmpTm->tm_year+1900 );
g_free( tmpTm );
sxftd_update_fs( sxfti, &date, fs );
xaccFreqSpecGetNextInstance( fs, &date, &date );
startDate = date;
while ( (i < (SXFTD_EXCAL_NUM_MONTHS * 31))
&& g_date_valid( &date )
/* Do checking against end restriction. */
&& ( ( get.type == NEVER_END )
|| ( get.type == END_ON_DATE
&& g_date_compare( &date, &(get.end_date) ) <= 0 )
|| ( get.type == END_AFTER_N_OCCS
&& i < get.n_occurrences ) ) ) {
*sxfti->cal_marks[i++] = date;
xaccFreqSpecGetNextInstance( fs, &date, &date );
}
/* remove old marks */
if ( sxfti->mark_id != -1 ) {
gnc_dense_cal_mark_remove( sxfti->example_cal, sxfti->mark_id );
sxfti->mark_id = -1;
}
if ( i > 0 ) {
GtkWidget *w;
gnc_dense_cal_set_month( sxfti->example_cal,
g_date_month( &startDate ) );
gnc_dense_cal_set_year( sxfti->example_cal,
g_date_year( &startDate ) );
w = glade_xml_get_widget( sxfti->gxml, SXFTD_NAME_ENTRY );
name = gtk_editable_get_chars( GTK_EDITABLE(w), 0, -1 );
info = g_string_sized_new( 16 );
xaccFreqSpecGetFreqStr( fs, info );
sxfti->mark_id =
gnc_dense_cal_mark( sxfti->example_cal,
i, sxfti->cal_marks,
name, info->str );
gtk_widget_queue_draw( GTK_WIDGET(sxfti->example_cal) );
g_free( name );
g_string_free( info, TRUE );
}
xaccFreqSpecFree( fs );
}
static
void
sxftd_update_excal_adapt( GtkObject *o, gpointer ud )
{
SXFromTransInfo *sxfti = (SXFromTransInfo*)ud;
sxftd_update_example_cal( sxfti );
}
+59 -22
View File
@@ -102,6 +102,8 @@
#define REMINDER_LIST "reminders_list"
#define SX_GLADE_FILE "sched-xact.glade"
#define TO_CREATE_STATUS "to_create_status"
#define SELECT_ALL_BUTTON "select_all_button"
#define UNSELECT_ALL_BUTTON "unselect_all_button"
#define OK_BUTTON "ok_button"
@@ -157,6 +159,8 @@ typedef struct _sxSinceLastData {
GladeXML *gxml;
GtkProgressBar *prog;
GtkStatusbar *toCreateStatus;
guint statusCtxId;
/* Multi-stage processing-related stuff... */
GList /* <toCreateTuple*> */ *autoCreateList;
@@ -1238,6 +1242,17 @@ sxsincelast_init( sxSinceLastData *sxsld )
sxsld->prog = GTK_PROGRESS_BAR(glade_xml_get_widget( sxsld->gxml,
WHAT_TO_DO_PROGRESS ));
sxsld->toCreateStatus =
GTK_STATUSBAR(
glade_xml_get_widget( sxsld->gxml, TO_CREATE_STATUS ) );
sxsld->statusCtxId =
gtk_statusbar_get_context_id( sxsld->toCreateStatus,
/* Sure, we're overusing this
* string, but I don't see why
* the Statusbar even
* cares... */
TO_CREATE_STATUS );
create_autoCreate_ledger( sxsld );
create_created_ledger( sxsld );
@@ -1356,8 +1371,8 @@ generate_instances( SchedXaction *sx,
static void
_free_varBindings_hash_elts( gpointer key, gpointer value, gpointer data )
{
if ( key )
g_free( key );
g_assert( key );
g_free( key );
if ( value )
g_free( value );
}
@@ -1791,9 +1806,10 @@ static void
andequal_numerics_set( gpointer key, gpointer value, gpointer data )
{
gboolean *allVarsBound = data;
if ( strcmp( (gchar*)key, "i" ) != 0 ) {
*allVarsBound &= (value != NULL);
if ( strcmp( (gchar*)key, "i" ) == 0 ) {
return;
}
*allVarsBound &= (value != NULL);
}
static void
@@ -1805,6 +1821,8 @@ sxsincelast_entry_changed( GtkEditable *e, gpointer ud )
gchar *entryText;
gnc_numeric *num, *ourNum;
GHashTable *dummyVarHash;
static const int MSG_BUF_LEN = 127;
char msgBuf[MSG_BUF_LEN+1];
sxsld = (sxSinceLastData*)ud;
tci = (toCreateInstance*)gtk_object_get_data( GTK_OBJECT(e), "tci" );
@@ -1812,27 +1830,48 @@ sxsincelast_entry_changed( GtkEditable *e, gpointer ud )
num = (gnc_numeric*)gtk_object_get_data( GTK_OBJECT(e), "numeric" );
entryText = gtk_editable_get_chars( e, 0, -1 );
dummyVarHash = g_hash_table_new( NULL, NULL );
/* FIXME: these debugs probably want to go into a staus bar... */
/* FIXME: Should be using xaccParseAmount instead of parser_parse_separate_vars? */
/* FIXME?: Should be using xaccParseAmount instead of
* parser_parse_separate_vars? */
gtk_statusbar_pop( sxsld->toCreateStatus, sxsld->statusCtxId );
if ( !gnc_exp_parser_parse_separate_vars( entryText, num,
NULL, dummyVarHash ) ) {
DEBUG( "error parsing entry \"%s\"", entryText );
num = NULL;
if ( entryText != NULL
&& strlen(entryText) > 0 ) {
snprintf( msgBuf, MSG_BUF_LEN,
"error parsing entry near \"%s\"", entryText );
gtk_statusbar_push( sxsld->toCreateStatus,
sxsld->statusCtxId,
msgBuf );
}
} else if ( g_hash_table_size( dummyVarHash ) != 0 ) {
DEBUG( "no new variables allowed in variable "
"bindings for expression \"%s\"", entryText );
num = NULL;
snprintf( msgBuf, MSG_BUF_LEN,
"No new variables allowed in "
"expression \"%s\"", entryText );
gtk_statusbar_push( sxsld->toCreateStatus,
sxsld->statusCtxId,
msgBuf );
} else if ( gnc_numeric_check( *num ) != GNC_ERROR_OK ) {
DEBUG( "entry \"%s\" is not "
"gnc_numeric-parseable", entryText );
snprintf( msgBuf, MSG_BUF_LEN,
"Entry \"%s\" is not "
"parseable", entryText );
gtk_statusbar_push( sxsld->toCreateStatus,
sxsld->statusCtxId,
msgBuf );
num = NULL;
} else {
#if 0 /* 0 -- this is fine. */
DEBUG( "\"%s\" parses as \"%f\"", entryText,
gnc_numeric_to_double( *num ) );
#endif /* 0 -- this is fine. */
snprintf( msgBuf, MSG_BUF_LEN,
"%f", gnc_numeric_to_double( *num ) );
gtk_statusbar_push( sxsld->toCreateStatus,
sxsld->statusCtxId,
msgBuf );
}
g_hash_table_foreach( dummyVarHash,
_free_varBindings_hash_elts,
NULL );
g_hash_table_destroy( dummyVarHash );
{
@@ -1875,9 +1914,8 @@ sxsincelast_destroy( GtkObject *o, gpointer ud )
/* appropriate place to destroy data structures */
clean_sincelast_data( sxsld );
/* FIXME: need more freeing for ledgers? why do these result in
* "gnc_close_gui_component: component not found" messages? */
/* We don't need to close the ledgers, as the gnc-reg-widget will do
* this for us. */
gnc_ledger_display_close( sxsld->ac_ledger );
sxsld->ac_ledger = NULL;
@@ -1925,7 +1963,6 @@ gnc_sxsl_del_vars_table_ea( gpointer key,
g_assert( key );
if ( key )
g_free( (gchar*)key );
if ( value )
g_free( (gnc_numeric*)value );
}
@@ -2376,10 +2413,10 @@ sxsincelast_tc_row_sel( GtkCTree *ct,
* variables if they're present in the expression. */
varHashSize = g_hash_table_size( tci->varBindings );
{
gpointer *foo, *bar;
gpointer *unusedKey, *unusedVal;
if ( g_hash_table_lookup_extended( tci->varBindings, "i",
(gpointer)&foo,
(gpointer)&bar ) ) {
(gpointer)&unusedKey,
(gpointer)&unusedVal ) ) {
varHashSize -= 1;
}
}
+36 -7
View File
@@ -257,6 +257,8 @@ static void ld_cancel_check( GnomeDruid *gd, LoanDruidData *ldd );
static void ld_prm_type_changed( GtkWidget *w, gint index, gpointer ud );
static void gnc_loan_druid_length_changed( GtkEditable *e, 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 );
@@ -302,11 +304,13 @@ gnc_ui_sx_loan_druid_create()
{
int i;
GtkAlignment *a;
/* "gas" == GncAccountSel */
struct gas_in_tables_data {
GNCAccountSel **loc;
GtkTable *table;
int left, right, top, bottom;
} gas_data[] = {
/* These ints are the GtkTable boundries */
{ &ldd->prmAccountGAS, ldd->prmTable, 1, 4, 0, 1 },
{ &ldd->repAssetsFromGAS, ldd->repTable, 1, 4, 2, 3 },
{ &ldd->repPrincToGAS, ldd->repTable, 1, 2, 3, 4 },
@@ -345,6 +349,7 @@ gnc_ui_sx_loan_druid_create()
}
gtk_widget_set_sensitive( GTK_WIDGET(ldd->prmVarFrame), FALSE );
{
GtkAlignment *a;
GNCOptionInfo typeOptInfo[] = {
@@ -366,9 +371,9 @@ gnc_ui_sx_loan_druid_create()
{
GtkAdjustment *a;
/* 8.0 [%], range of 0.05..100.0 with ticks at 0.05[%]. */
a = GTK_ADJUSTMENT(gtk_adjustment_new( 8.0, 0.05,
100.0, 0.05,
/* 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 );
@@ -379,6 +384,9 @@ gnc_ui_sx_loan_druid_create()
9999, 1,
12, 12 ));
gtk_spin_button_set_adjustment( ldd->prmLengthSpin, a );
gtk_signal_connect( GTK_OBJECT(ldd->prmLengthSpin), "changed",
GTK_SIGNAL_FUNC(gnc_loan_druid_length_changed),
ldd );
a = GTK_ADJUSTMENT(gtk_adjustment_new( 360, 1,
9999, 1,
@@ -700,7 +708,7 @@ static
void
ld_cancel_check( GnomeDruid *gd, LoanDruidData *ldd )
{
const char *cancelMsg = _( "Are you sure you want to close "
const char *cancelMsg = _( "Are you sure you want to cancel "
"the Mortgage/Loan Setup Druid?" );
if ( gnc_verify_dialog_parented( ldd->dialog, FALSE, cancelMsg ) ) {
gnc_close_gui_component_by_data( DIALOG_LOAN_DRUID_CM_CLASS,
@@ -1027,7 +1035,7 @@ ld_rep_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
GString *str;
str = g_string_sized_new( 64 );
g_string_sprintfa( str, "pmt( %.4f / 12 : %d : %0.2f : 0 : 0 )",
g_string_sprintfa( str, "pmt( %.5f / 12 : %d : %0.2f : 0 : 0 )",
(ldd->ld.interestRate / 100),
ldd->ld.numPer,
gnc_numeric_to_double(ldd->ld.principal) );
@@ -1330,7 +1338,7 @@ ld_fin_fin ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
g_free( tmpStr );
gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repPriAcct );
tmpGS = g_string_sized_new( 64 );
g_string_sprintf( tmpGS, "ppmt( %.4f / 12 : i : %d : %0.2f : 0 : 0 )",
g_string_sprintf( tmpGS, "ppmt( %.5f / 12 : i : %d : %0.2f : 0 : 0 )",
(ldd->ld.interestRate / 100),
ldd->ld.numPer,
gnc_numeric_to_double(ldd->ld.principal));
@@ -1346,7 +1354,7 @@ ld_fin_fin ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
g_free( tmpStr );
gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repIntAcct );
tmpGS = g_string_sized_new( 64 );
g_string_sprintf( tmpGS, "ipmt( %.4f / 12 : i : %d : %0.2f : 0 : 0 )",
g_string_sprintf( tmpGS, "ipmt( %.5f / 12 : i : %d : %0.2f : 0 : 0 )",
(ldd->ld.interestRate / 100),
ldd->ld.numPer,
gnc_numeric_to_double( ldd->ld.principal ) );
@@ -1500,3 +1508,24 @@ ld_fin_fin ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
ld_close_handler( ldd );
}
static
void
gnc_loan_druid_length_changed( GtkEditable *e, gpointer ud )
{
LoanDruidData *ldd;
gchar *txt;
gint pos;
ldd = (LoanDruidData*)ud;
txt = gtk_editable_get_chars( e, 0, -1 );
if ( !txt )
return;
gtk_editable_select_region( GTK_EDITABLE(ldd->prmRemainSpin), 0, -1 );
gtk_editable_delete_selection( GTK_EDITABLE(ldd->prmRemainSpin) );
pos = 0;
gtk_editable_insert_text( GTK_EDITABLE(ldd->prmRemainSpin),
txt, strlen(txt), &pos );
g_free( txt );
}
File diff suppressed because it is too large Load Diff
+18
View File
@@ -2523,6 +2523,24 @@ gnc_register_recur_cb(GtkWidget *w, gpointer data)
SplitRegister *reg = gnc_ledger_display_get_split_register (regData->ledger);
Transaction *pending_trans = gnc_split_register_get_current_trans (reg);
/* FIXME: If the transaction has a sched-xact KVP frame, then go to the
* editor for the existing SX; otherwise, do the sx-from-trans dialog. */
{
kvp_frame *txn_frame;
kvp_value *kvp_val;
/* set a kvp-frame element in the transaction indicating and
* pointing-to the SX this was created from. */
txn_frame = xaccTransGetSlots( pending_trans );
if ( txn_frame != NULL ) {
DEBUG( "Got frame, looking up key" );
kvp_val = kvp_frame_get_slot( txn_frame, "from-sched-xaction" );
if ( kvp_val ) {
DEBUG( "Find SX with GUID \"%s\"",
guid_to_string( kvp_value_get_guid( kvp_val ) ) );
}
}
}
gnc_sx_create_from_trans(pending_trans);
}