2004-03-07 Joshua Sled <jsled@asynchronous.org>

* HACKING: Added instructions about running under valgrind.

	* lib/gnucash_valgrind.supp: Added a large set of valgrind
	suppressions for both guile and gnucash.

	* src/register/ledger-core/gnc-ledger-display.c
	(gnc_ledger_display_template_gl): Change the reg_type to
	SEARCH_LEDGER so all the 'action' types appear. Bug#108833.

	* src/gnome/glade/sched-xact.glade: Remove unused 'ledger_status'
	widget. Bug#102269.

	* src/gnome-utils/gnc-dense-cal.c (gnc_dense_cal_draw_to_buffer):
	At least be consistent about the background coloring of the month
	labels, even if we're still not using GTK themeage correctly.

	* src/gnome-utils/gnc-dense-cal.c (gnc_dense_cal_destroy): Destroy
	the transient window when the widget is destroyed. Bug#103910.

	* src/gnome/dialog-scheduledxaction.c
	(gnc_ui_scheduled_xaction_editor_dialog_create): Make the advance
	and remind spin-buttons editable [Bug#94963].

	* src/gnome/glade/sched-xact.glade: Change the upper bound on the
	advance and remind spins to 365 [days], with a page-size of 30
	[days].

	* src/gnome/dialog-sx-from-trans.c (gnc_sx_create_from_trans):
	Disallow the Scheduling of being-editing transactions in the
	Register, preventing a class of unbalacned SX template
	transactions from being entered and propogated through the
	system. See Bug#130330.

	* src/engine/FreqSpec.c (xaccFreqSpecGetFreqStr): Fix nasty
	memory-corruption issue; insufficent bounds checking on array
	index. Bug#125600.

	* src/gnome/dialog-sxsincelast.c (create_each_transaction_helper):
	Better handling of various error cases in
        transaction-creation. Bug#120311; Bug#130330.

2004-03-01  Joshua Sled  <jsled@asynchronous.org>

	* src/gnome/dialog-scheduledxaction.c (gnc_sxed_check_consistent):
	Fix for part of Bug#121740 -- only allow auto-create SXes which
	have splits to be created.

2004-02-07  Joshua Sled  <jsled@asynchronous.org>

	* src/gnome/dialog-scheduledxaction.c (editor_ok_button_clicked):
	* src/gnome-utils/gnc-frequency.c (gnc_frequency_save_state):
	* src/backend/file/gnc-freqspec-xml-v2.c (fs_none_handler):
	* src/engine/FreqSpec.c (xaccFreqSpecGetFreqStr):
	Adding "NONE" as an allowable FreqSpec [Bug#103968].


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@9858 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Joshua Sled 2004-03-11 01:17:14 +00:00
parent c967d17c4e
commit e19df01f5f
12 changed files with 321 additions and 69 deletions

View File

@ -4,6 +4,49 @@
glade/hbci.glade, gnc-hbci-transfer.c: Transfer template management
GUI added by Bernd Wagner <F.J.Bernd.Wagner@t-online.de>
2004-03-07 Joshua Sled <jsled@asynchronous.org>
* HACKING: Added instructions about running under valgrind.
* lib/gnucash_valgrind.supp: Added a large set of valgrind
suppressions for both guile and gnucash.
* src/register/ledger-core/gnc-ledger-display.c
(gnc_ledger_display_template_gl): Change the reg_type to
SEARCH_LEDGER so all the 'action' types appear. Bug#108833.
* src/gnome/glade/sched-xact.glade: Remove unused 'ledger_status'
widget. Bug#102269.
* src/gnome-utils/gnc-dense-cal.c (gnc_dense_cal_draw_to_buffer):
At least be consistent about the background coloring of the month
labels, even if we're still not using GTK themeage correctly.
* src/gnome-utils/gnc-dense-cal.c (gnc_dense_cal_destroy): Destroy
the transient window when the widget is destroyed. Bug#103910.
* src/gnome/dialog-scheduledxaction.c
(gnc_ui_scheduled_xaction_editor_dialog_create): Make the advance
and remind spin-buttons editable [Bug#94963].
* src/gnome/glade/sched-xact.glade: Change the upper bound on the
advance and remind spins to 365 [days], with a page-size of 30
[days].
* src/gnome/dialog-sx-from-trans.c (gnc_sx_create_from_trans):
Disallow the Scheduling of being-editing transactions in the
Register, preventing a class of unbalacned SX template
transactions from being entered and propogated through the
system. See Bug#130330.
* src/engine/FreqSpec.c (xaccFreqSpecGetFreqStr): Fix nasty
memory-corruption issue; insufficent bounds checking on array
index. Bug#125600.
* src/gnome/dialog-sxsincelast.c (create_each_transaction_helper):
Better handling of various error cases in
transaction-creation. Bug#120311; Bug#130330.
2004-03-03 Derek Atkins <derek@ihtfp.com>
* src/register/ledger-core/split-register-load.c: make the code a
@ -12,6 +55,20 @@
existing variable. Unlikely to actually fix anything, but
you never know what a compiler might do.
2004-03-01 Joshua Sled <jsled@asynchronous.org>
* src/gnome/dialog-scheduledxaction.c (gnc_sxed_check_consistent):
Fix for part of Bug#121740 -- only allow auto-create SXes which
have splits to be created.
2004-02-07 Joshua Sled <jsled@asynchronous.org>
* src/gnome/dialog-scheduledxaction.c (editor_ok_button_clicked):
* src/gnome-utils/gnc-frequency.c (gnc_frequency_save_state):
* src/backend/file/gnc-freqspec-xml-v2.c (fs_none_handler):
* src/engine/FreqSpec.c (xaccFreqSpecGetFreqStr):
Adding "NONE" as an allowable FreqSpec [Bug#103968].
2004-02-14 Christian Stimming <stimming@tuhh.de>
* configure.in: Require the correct openhbci2 version. Add verbose

12
HACKING
View File

@ -129,4 +129,14 @@ However, I did not find valgrind to be useful. It reported a bunch of
guile bugs, some g_has_table bugs, and then the program exited prematurely
for no appearenet reason. :-(
If you know how to fix this, please update tehse instructions.
For the moment, use the supressions in lib/gnucash_valgrind.supp.
This file needs to be cleaned up in two ways:
1/ There are a bunch of duplicate supressions in the file.
* The supressions in place were auto-generated by valgrind itself
[--gen-suppressions=yes], and it makes no effort to output the
suppression only once.
2/ There are a bunch of suppressions which need to not be supressions, but
instead just not be generated by valgrind.

View File

@ -33,7 +33,7 @@ m4data_DATA = gnucash.m4
# Don't list any directories or you'll get *everything*, including the
# CVS dirs.
EXTRA_DIST = config.rpath \
EXTRA_DIST = config.rpath config.rpath \
.cvsignore \
ChangeLog.1 \
HACKING \

View File

@ -86,6 +86,7 @@ struct freqTypeTuple {
};
struct freqTypeTuple freqTypeStrs[] = {
{ "none", INVALID },
{ "once", ONCE },
{ "daily", DAILY },
{ "weekly", WEEKLY },
@ -163,6 +164,11 @@ gnc_freqSpec_dom_tree_create( FreqSpec *fs )
xmlAddChild( ret, xmlSub );
switch( fs->type ) {
case INVALID: {
xmlSub = xmlNewNode( NULL, "fs:none" );
} break;
case ONCE: {
xmlSub = xmlNewNode( NULL, "fs:once" );
xmlAddChild( xmlSub,
@ -260,7 +266,6 @@ gnc_freqSpec_dom_tree_create( FreqSpec *fs )
xmlAddChild( ret, xmlComposites );
} break;
case INVALID:
default:
g_return_val_if_fail( FALSE, NULL );
}
@ -412,6 +417,21 @@ struct dom_tree_handler fs_union_dom_handlers[] = {
{ NULL, NULL, 0, 0 },
};
static
gboolean
fs_none_handler( xmlNodePtr node, gpointer data )
{
fsParseData *fspd = data;
gboolean successful;
successful = dom_tree_generic_parse( node,
fs_union_dom_handlers,
fspd );
if ( !successful )
return FALSE;
fspd->fs->type = INVALID;
return TRUE;
}
static
gboolean
fs_once_handler( xmlNodePtr node, gpointer data )
@ -531,6 +551,7 @@ static struct dom_tree_handler fs_dom_handlers[] = {
{ "gnc:freqspec", gnc_fs_handler, 0, 0 },
{ "fs:ui_type", fs_uift_handler, 1, 0 },
{ "fs:id", fs_guid_handler, 1, 0 },
{ "fs:none", fs_none_handler, 0, 0 },
{ "fs:once", fs_once_handler, 0, 0 },
{ "fs:daily", fs_daily_handler, 0, 0 },
{ "fs:weekly", fs_weekly_handler, 0, 0 },

View File

@ -3,6 +3,15 @@ Author: jsled@asynchronous.org
Main Scheduled Transaction todo list
------------------------------------
. Bug#102311...
. As per comment 2004-01-05T16:31, there is an issue when other pieces of
the system change accounts that SXes depend on. We have two options:
1: handle change at account-deletion time ["remove this acocunt will
affect this scheduled transaction ... what to do?"]
2: break out of SX since-last-run processing ["this account was removed;
{edit,delete} SX?"].
##################################################
### To-Do
###

View File

@ -138,6 +138,7 @@ get_wday_name(guint day)
{
static gchar wday_name[WDAY_BUF_WIDTH];
struct tm t;
memset( &t, 0, sizeof( t ) );
t.tm_wday = day;
strftime(wday_name, WDAY_NAME_WIDTH, "%A", &t);
return wday_name;
@ -160,6 +161,7 @@ get_abbrev_month_name(guint month)
{
static gchar month_name[WDAY_BUF_WIDTH];
struct tm t;
memset( &t, 0, sizeof( t ) );
t.tm_mon = month;
strftime(month_name, WDAY_NAME_WIDTH, "%b", &t);
return month_name;
@ -240,7 +242,7 @@ xaccFreqSpecGetType( FreqSpec *fs )
{
g_return_val_if_fail( fs, INVALID );
/* Is this really a fail? */
g_return_val_if_fail( fs->type != INVALID, INVALID );
//g_return_val_if_fail( fs->type != INVALID, INVALID );
return fs->type;
}
@ -451,6 +453,14 @@ xaccFreqSpecIsValidDateRelaxed( FreqSpec *fs, time_t query )
}
*/
void
xaccFreqSpecSetNone( FreqSpec *fs )
{
g_return_if_fail( fs );
xaccFreqSpecCleanUp( fs );
fs->type = INVALID;
}
void
xaccFreqSpecSetOnceDate( FreqSpec *fs, const GDate* when )
{
@ -709,6 +719,10 @@ xaccFreqSpecGetFreqStr( FreqSpec *fs, GString *str )
memset( freqStrBuf, 0, MAX_FREQ_STR_SIZE + 1 );
switch( xaccFreqSpecGetUIType( fs ) ) {
case UIFREQ_NONE:
snprintf( freqStrBuf, MAX_FREQ_STR_SIZE, _("None") );
break;
case UIFREQ_ONCE:
tmpStr = g_new0( char, GDATE_STRING_BUF_SIZE );
/* this is now a GDate. */
@ -778,6 +792,7 @@ xaccFreqSpecGetFreqStr( FreqSpec *fs, GString *str )
if ( xaccFreqSpecGetType(tmpFS) != WEEKLY ) {
snprintf( freqStrBuf, MAX_FREQ_STR_SIZE,
"error: UIFREQ_WEEKLY doesn't contain weekly children" );
g_free( tmpStr );
return;
}
if ( tmpInt == -1 ) {
@ -785,7 +800,7 @@ xaccFreqSpecGetFreqStr( FreqSpec *fs, GString *str )
}
/* put the first letter of the weekday name in
the appropriate position. */
dowIdx = tmpFS->s.weekly.offset_from_epoch;
dowIdx = tmpFS->s.weekly.offset_from_epoch % 7;
tmpStr[dowIdx] = *(get_wday_name(dowIdx));
}

View File

@ -126,6 +126,8 @@ void xaccFreqSpecSetUIType( FreqSpec *fs, UIFreqType newUIFreqType );
UIFreqType xaccFreqSpecGetUIType( FreqSpec *fs );
void xaccFreqSpecSetNone( FreqSpec *fs );
/**
* Sets the type to once-off, and initialises the
* date it occurs on.

View File

@ -171,6 +171,8 @@ static const gchar *month_name(int mon)
struct tm my_tm;
int i;
memset( buf, 0, MONTH_NAME_BUFSIZE );
memset( &my_tm, 0, sizeof( struct tm ) );
my_tm.tm_mon = mon;
i = strftime (buf, MONTH_NAME_BUFSIZE-1, "%b", &my_tm);
return buf;
@ -187,6 +189,8 @@ static const gchar *day_label(int wday)
struct tm my_tm;
int i;
memset( buf, 0, MONTH_NAME_BUFSIZE );
memset( &my_tm, 0, sizeof( struct tm ) );
my_tm.tm_wday = wday;
i = strftime (buf, MONTH_NAME_BUFSIZE-1, "%a", &my_tm);
/* Wild hack to use only the first two letters */
@ -467,6 +471,13 @@ gnc_dense_cal_destroy (GtkObject *object)
g_return_if_fail (GNC_IS_DENSE_CAL (object));
dcal = GNC_DENSE_CAL(object);
if ( GTK_WIDGET_REALIZED( dcal->transPopup ) ) {
gtk_widget_hide( GTK_WIDGET(dcal->transPopup) );
gtk_widget_destroy( GTK_WIDGET(dcal->transPopup) );
dcal->transPopup = NULL;
}
if ( dcal->drawbuf )
gdk_pixmap_unref( dcal->drawbuf );
@ -762,13 +773,13 @@ gnc_dense_cal_draw_to_buffer( GncDenseCal *dcal )
dcal->label_width,
dcal->label_height, -1 );
gdk_draw_rectangle( dcal->monthLabels[i],
widget->style->bg_gc[widget->state],
widget->style->white_gc,
TRUE, 0, 0,
dcal->label_width,
dcal->label_height );
gdk_draw_rectangle( tmpPix,
widget->style->bg_gc[widget->state],
widget->style->white_gc,
TRUE, 0, 0,
dcal->label_height,
dcal->label_width );
@ -783,7 +794,7 @@ gnc_dense_cal_draw_to_buffer( GncDenseCal *dcal )
dcal->label_width );
/* now, (transpose the pixel matrix)==(do a 90-degree
* counter-clocwise rotation) */
* counter-clockwise rotation) */
for ( x=0; x < dcal->label_height; x++ ) {
for ( y=0; y < dcal->label_width; y++ ) {
if ( gdk_image_get_pixel( tmpImg, x, y )
@ -955,7 +966,7 @@ gnc_dense_cal_draw_to_buffer( GncDenseCal *dcal )
g_date_add_days( &d, 1 ), doc++ ) {
doc_coords( dcal, doc, &x1, &y1, &x2, &y2 );
memset( dayNumBuf, 0, 3 );
sprintf( dayNumBuf, "%d", g_date_day( &d ) );
snprintf( dayNumBuf, 3, "%d", g_date_day( &d ) );
numW = gdk_string_width( dcal->dayLabelFont, dayNumBuf );
numH = gdk_string_height( dcal->dayLabelFont, dayNumBuf );
w = (x2 - x1)+1;
@ -1018,6 +1029,8 @@ populate_hover_window( GncDenseCal *dcal, gint doc )
rowText[1] = gdcmd->info;
gtk_clist_insert( cl, row++, rowText );
}
// FIXME: free 'date'?
}
}
@ -1221,6 +1234,7 @@ month_coords( GncDenseCal *dcal, int monthOfCal, GList **outList )
startD = g_date_new();
endD = g_date_new();
// FIXME: clean these up?
/* Calculate the number of weeks in the column before the month we're
* interested in. */
@ -1549,6 +1563,7 @@ gnc_dense_cal_mark_remove( GncDenseCal *dcal, guint markToRemove )
/* Ignore non-realistic marks */
if ( (gint)markToRemove == -1 ) {
DEBUG( "markToRemove = -1" );
return;
}
@ -1560,6 +1575,7 @@ gnc_dense_cal_mark_remove( GncDenseCal *dcal, guint markToRemove )
}
g_assert( l != NULL );
if ( l == NULL ) {
DEBUG( "l == null" );
return;
}
g_assert( gdcmd != NULL );

View File

@ -102,6 +102,16 @@ typedef enum _EndTypeEnum {
END_OCCUR,
} EndType;
/* Runtime/dialog information about a particular SX. */
typedef struct _SxRuntimeInfo
{
SchedXaction *sx;
// the gnc-dense-cal mark-tag
gint markTag;
// which row in the GTK CList this SX is.
gint row;
} SxRuntimeInfo;
struct _SchedXactionDialog
{
GtkWidget *dialog;
@ -212,6 +222,10 @@ static gboolean sxed_confirmed_cancel( SchedXactionEditorDialog *sxed );
static gboolean editor_component_sx_equality( gpointer find_data,
gpointer user_data );
static SxRuntimeInfo* _new_sx_runtime_info( SchedXaction *sx );
static void _clear_runtime_info_row( gpointer key, gpointer value, gpointer user_data );
/** Implementations *****************************************************/
static
@ -224,6 +238,15 @@ sxd_close_handler ( gpointer user_data )
gnome_dialog_close( GNOME_DIALOG( sxd->dialog ) );
}
static
void
_clear_runtime_info_row( gpointer key, gpointer value, gpointer user_data )
{
SxRuntimeInfo *sxri;
sxri = (SxRuntimeInfo*)value;
sxri->row = -1;
}
void
gnc_sxd_list_refresh( SchedXactionDialog *sxd )
{
@ -233,9 +256,13 @@ gnc_sxd_list_refresh( SchedXactionDialog *sxd )
/* Update the clist. */
cl = GTK_CLIST( glade_xml_get_widget( sxd->gxml, SX_LIST ) );
gtk_clist_freeze( cl );
gtk_clist_clear( cl );
// Also, flush the row-numbers from storage
g_hash_table_foreach( sxd->sxData, _clear_runtime_info_row, NULL );
sxList = gnc_book_get_schedxactions( gnc_get_current_book() );
g_list_foreach( sxList, putSchedXactionInDialog, sxd );
gtk_clist_thaw( cl );
}
@ -342,9 +369,10 @@ editor_ok_button_clicked( GtkButton *b, SchedXactionEditorDialog *sxed )
sxList = gnc_book_get_schedxactions( book );
sxList = g_list_append( sxList, sxed->sx );
gnc_book_set_schedxactions( book, sxList );
sxed->sx = NULL;
sxed->newsxP = FALSE;
}
// regardless, do this so the close handler won't complain.
sxed->sx = NULL;
/* update lists */
/* We now do this by getting the list of SX Lists and updating them
@ -607,7 +635,7 @@ static
gboolean
gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
{
gint ttVarCount;
gint ttVarCount, splitCount;
FreqSpec *fs;
/* Do checks on validity and such, interrupting the user if
@ -630,6 +658,7 @@ gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
*/
ttVarCount = 0;
splitCount = 0;
{
static const int NUM_ITERS_WITH_VARS = 5;
static const int NUM_ITERS_NO_VARS = 1;
@ -685,8 +714,11 @@ gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
(gpointer)vars );
g_hash_table_foreach( txns, set_sums_to_zero, NULL );
tmp = gnc_numeric_zero();
for ( splitList = xaccSchedXactionGetSplits( sxed->sx );
splitList; splitList = splitList->next )
splitList = xaccSchedXactionGetSplits( sxed->sx );
splitCount += g_list_length( splitList );
for ( ; splitList; splitList = splitList->next )
{
txnCreditDebitSums *tcds;
s = (Split*)splitList->data;
@ -835,6 +867,15 @@ gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
"cannot be automatically created.") );
return FALSE;
}
/* Fix for part of Bug#121740 -- auto-create transactions are
* only valid if there's actually a transaction to create. */
if ( autocreateState && splitCount == 0 ) {
gnc_warning_dialog( sxed->dialog,
_("Scheduled Transactions without a template\n"
"transaction cannot be automatically created.") );
return FALSE;
}
}
/* deal with time. */
@ -1004,6 +1045,10 @@ gnc_sxed_save_sx( SchedXactionEditorDialog *sxed )
fs = xaccSchedXactionGetFreqSpec( sxed->sx );
gnc_frequency_save_state( sxed->gncfreq, fs, &gdate );
GString *str = g_string_new( "" );
xaccFreqSpecGetFreqStr( fs, str );
DEBUG( "fs: %s", str->str );
/* now that we have it, set the start date */
xaccSchedXactionSetStartDate( sxed->sx, &gdate );
}
@ -1049,6 +1094,8 @@ scheduledxaction_dialog_destroy(GtkObject *object, gpointer data)
gnc_unregister_gui_component_by_data
(DIALOG_SCHEDXACTION_CM_CLASS, sxd);
// FIXME: um. We should free memory and stuff, here.
g_free( sxd );
}
@ -1144,6 +1191,8 @@ gnc_ui_scheduled_xaction_dialog_create(void)
gtk_signal_connect( GTK_OBJECT(w), "click-column",
GTK_SIGNAL_FUNC(gnc_sxd_row_click_handler), sxd );
// gtk_clist_column_titles_active( GTK_CLIST( w ) );
/* Default to sorting by ascending next-instance date. */
sxd->currentSortCol = 2;
sxd->currentSortType = GTK_SORT_ASCENDING;
@ -1400,6 +1449,10 @@ gnc_ui_scheduled_xaction_editor_dialog_create( SchedXactionDialog *sxd,
gtk_widget_set_sensitive( GTK_WIDGET(sxed->remindSpin), FALSE );
gtk_widget_set_sensitive( GTK_WIDGET(sxed->endCountEntry), FALSE );
gtk_widget_set_sensitive( GTK_WIDGET(sxed->endRemainEntry), FALSE );
gtk_editable_set_editable( GTK_EDITABLE(sxed->advanceSpin), TRUE );
gtk_editable_set_editable( GTK_EDITABLE(sxed->remindSpin), TRUE );
/* Allow grow, allow shrink, auto-shrink */
gtk_window_set_policy (GTK_WINDOW(sxed->dialog), TRUE, TRUE, FALSE);
@ -1795,18 +1848,19 @@ delete_button_clicked( GtkButton *b, gpointer d )
book = gnc_get_current_book ();
sxList = gnc_book_get_schedxactions( book );
for ( sel = cl->selection; sel; sel = sel->next ) {
gint tag;
gint *p_tag = &tag;
SxRuntimeInfo *sxri;
SxRuntimeInfo **p_sxri = &sxri;
gpointer unused;
gboolean foundP;
sx = (SchedXaction*)gtk_clist_get_row_data( cl, (int)sel->data );
sxList = g_list_remove( sxList, (gpointer)sx );
foundP = g_hash_table_lookup_extended( sxd->sxData, sx,
&unused, (gpointer*)p_tag );
&unused,
(gpointer*)p_sxri );
g_assert( foundP );
if ( tag != -1 ) {
gnc_dense_cal_mark_remove( sxd->gdcal, tag );
if ( sxri->markTag != -1 ) {
gnc_dense_cal_mark_remove( sxd->gdcal, sxri->markTag );
}
g_hash_table_remove( sxd->sxData, sx );
xaccSchedXactionFree( sx );
@ -1898,6 +1952,19 @@ _gnc_sxd_free_dates( gpointer data, gpointer user_data )
g_date_free( (GDate*)data );
}
static
SxRuntimeInfo*
_new_sx_runtime_info( SchedXaction *sx )
{
SxRuntimeInfo *sxri;
sxri = g_new0( SxRuntimeInfo, 1 );
sxri->sx = sx;
sxri->row = -1;
sxri->markTag = -1;
return sxri;
}
static
void
putSchedXactionInDialog( gpointer data, gpointer user_data )
@ -1908,14 +1975,17 @@ putSchedXactionInDialog( gpointer data, gpointer user_data )
char *text[3];
GString *freqStr;
GString *nextDate;
gint row;
int i;
GDate *nextInstDate = NULL, *calEndDate;
int instArraySize;
GDate **instArray;
GList *instList;
gint gdcMarkTag, oldMarkTag;
gint *p_oldMarkTag = &oldMarkTag;
gpointer unused;
SxRuntimeInfo *sxri = NULL;
SxRuntimeInfo **p_sxri = &sxri;
gboolean foundP;
gint gdcMarkTag;
gint row;
sx = (SchedXaction*)data;
sxd = (SchedXactionDialog*)user_data;
@ -1986,38 +2056,47 @@ putSchedXactionInDialog( gpointer data, gpointer user_data )
nextInstDate = NULL;
}
foundP = g_hash_table_lookup_extended( sxd->sxData,
(gpointer)sx,
&unused,
(gpointer*)p_sxri );
if ( ! foundP )
{
// new SX -- create runtime storage for it
sxri = _new_sx_runtime_info( sx );
sxri->markTag = gdcMarkTag;
}
else
{
// existing SX; remove it's
if ( sxri->markTag != -1 ) {
gnc_dense_cal_mark_remove( sxd->gdcal, sxri->markTag );
sxri->markTag = gdcMarkTag;
}
}
text[0] = xaccSchedXactionGetName( sx );
text[1] = freqStr->str;
text[2] = nextDate->str;
clist = GTK_CLIST( glade_xml_get_widget( sxd->gxml, SX_LIST ) );
gtk_clist_freeze( clist );
row = gtk_clist_find_row_from_data( clist, sx );
if ( row != -1 ) {
gpointer unused;
gboolean foundP =
g_hash_table_lookup_extended( sxd->sxData,
(gpointer)sx,
&unused,
(gpointer*)p_oldMarkTag );
g_assert( foundP );
}
if ( row == -1 ) {
row = gtk_clist_find_row_from_data( clist, (gpointer)sx );
if ( sxri->row == -1 ) {
/* new item to be inserted */
row = gtk_clist_append( clist, text );
gtk_clist_set_row_data( clist, row, sx );
sxri->row = gtk_clist_append( clist, text );
gtk_clist_set_row_data( clist, sxri->row, sx );
} else {
/* old item being replaced. */
if ( oldMarkTag != -1 ) {
gnc_dense_cal_mark_remove( sxd->gdcal, oldMarkTag );
}
for ( i=0; i<3; i++ ) {
gtk_clist_set_text( clist, row, i, text[i] );
gtk_clist_set_text( clist, sxri->row, i, text[i] );
}
}
gtk_clist_sort( clist );
gtk_clist_thaw( clist );
g_hash_table_insert( sxd->sxData, (gpointer)sx, (gpointer)gdcMarkTag );
g_hash_table_insert( sxd->sxData, (gpointer)sx, (gpointer)sxri );
sxri = NULL;
g_string_free( freqStr, TRUE );
g_string_free( nextDate, TRUE );
@ -2272,10 +2351,8 @@ gnc_sxed_update_cal( SchedXactionEditorDialog *sxed )
}
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 ) );
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 */
@ -2307,8 +2384,12 @@ gnc_sxed_update_cal( SchedXactionEditorDialog *sxed )
sxed->cal_marks,
name, info->str );
gtk_widget_queue_draw( GTK_WIDGET( sxed->example_cal ) );
g_free( name );
g_string_free( info, TRUE );
if ( name != NULL )
{
g_free( name );
}
}
xaccFreqSpecFree( fs );

View File

@ -38,6 +38,7 @@
#include "gnc-book.h"
#include "gnc-date-edit.h"
#include "gnc-engine-util.h"
#include "gnc-ui.h"
#include "gnc-ui-util.h"
#include "gnc-dense-cal.h"
@ -60,6 +61,9 @@
#define SX_OPT_STR "Scheduled Transactions"
#define SXFTD_ERRNO_UNBALANCED_XACTION 3
#define SXFTD_ERRNO_OPEN_XACTION -3
#define SXFTD_EXCAL_NUM_MONTHS 4
#define SXFTD_EXCAL_MONTHS_PER_COL 4
@ -212,14 +216,17 @@ sxftd_add_template_trans(SXFromTransInfo *sxfti)
{
Transaction *tr = sxfti->trans;
GList *tt_list= NULL;
GList *tt_list = NULL;
GList *splits, *template_splits = NULL;
TTInfo *tti = gnc_ttinfo_malloc();
TTSplitInfo *ttsi;
Split *sp;
gnc_numeric runningBalance;
gnc_numeric split_value;
const char *tmpStr;
runningBalance = gnc_numeric_zero();
gnc_ttinfo_set_description(tti, xaccTransGetDescription(tr));
gnc_ttinfo_set_num(tti, xaccTransGetNum(tr));
gnc_ttinfo_set_currency(tti, xaccTransGetCurrency(tr));
@ -232,6 +239,9 @@ sxftd_add_template_trans(SXFromTransInfo *sxfti)
split_value = xaccSplitGetValue(sp);
gnc_ttsplitinfo_set_memo(ttsi, xaccSplitGetMemo(sp));
runningBalance = gnc_numeric_add( runningBalance, split_value,
100, (GNC_DENOM_AUTO | GNC_DENOM_LCD) );
if(gnc_numeric_positive_p(split_value))
{
tmpStr = xaccPrintAmount( split_value,
@ -252,6 +262,17 @@ sxftd_add_template_trans(SXFromTransInfo *sxfti)
template_splits = g_list_append(template_splits, ttsi);
}
if ( ! gnc_numeric_zero_p( runningBalance )
&& !gnc_verify_dialog( (gncUIWidget)sxfti->dialog,
FALSE, "%s",
_("The Scheduled Transaction Editor "
"cannot automatically\nbalance "
"this transaction. "
"Should it still be "
"entered?") ) ) {
return SXFTD_ERRNO_UNBALANCED_XACTION;
}
gnc_ttinfo_set_template_splits(tti, template_splits);
tt_list = g_list_append(tt_list, tti);
@ -338,7 +359,10 @@ sxftd_init( SXFromTransInfo *sxfti )
if ( ! sxfti->trans ) {
return -2;
}
if ( xaccTransIsOpen( sxfti->trans ) ) {
return SXFTD_ERRNO_OPEN_XACTION;
}
sxfti_attach_callbacks(sxfti);
/* Setup the example calendar and related data structures. */
@ -512,7 +536,10 @@ sxftd_compute_sx(SXFromTransInfo *sxfti)
xaccSchedXactionSetAdvanceReminder( sx, daysInAdvance );
}
sxftd_add_template_trans( sxfti );
if ( sxftd_add_template_trans( sxfti ) != 0 )
{
sxftd_errno = SXFTD_ERRNO_UNBALANCED_XACTION;
}
return sxftd_errno;
}
@ -540,13 +567,20 @@ sxftd_ok_clicked(GtkWidget *w, gpointer user_data)
GList *sx_list;
guint sx_error = sxftd_compute_sx(sxfti);
if (sx_error != 0)
if (sx_error != 0
&& sx_error != SXFTD_ERRNO_UNBALANCED_XACTION)
{
PERR( "Error in sxftd_compute_sx after ok_clicked [%d]", sx_error );
}
else
{
SchedXactionDialog *sxd;
if ( sx_error == SXFTD_ERRNO_UNBALANCED_XACTION ) {
gnc_error_dialog( gnc_ui_get_toplevel(),
_( "The Scheduled Transaction is unbalanced.\n"
"You are strongly encouraged to correct this situation." ) );
}
book = gnc_get_current_book ();
sx_list = gnc_book_get_schedxactions(book);
sx_list = g_list_append(sx_list, sxfti->sx);
@ -609,10 +643,13 @@ sxftd_advanced_clicked(GtkWidget *w, gpointer user_data)
SchedXactionDialog *adv_dlg;
SchedXactionEditorDialog *adv_edit_dlg;
if (sx_error != 0)
if ( sx_error != 0
&& sx_error != SXFTD_ERRNO_UNBALANCED_XACTION )
{
PWARN( "something bad happened in sxftd_compute_sx [%d]", sx_error );
return;
// unbalanced-xaction is "okay", since this is also checked for by
// the advanced editor.
PWARN( "something bad happened in sxftd_compute_sx [%d]", sx_error );
return;
}
gtk_widget_hide( sxfti->dialog );
/* force a gui update. */
@ -645,7 +682,20 @@ gnc_sx_create_from_trans( Transaction *trans )
sxfti->sx = xaccSchedXactionMalloc(gnc_get_current_book ());
if ( (errno = sxftd_init( sxfti )) < 0 ) {
PERR( "Error in sxftd_init: %d", errno );
if ( errno == SXFTD_ERRNO_OPEN_XACTION )
{
gnc_error_dialog( gnc_ui_get_toplevel(),
_( "Cannot create a Scheduled Transaction "
"from a Transaction currently\n"
"being edited. Please Enter the "
"Transaction before Scheduling." ) );
sxftd_close( sxfti, TRUE );
return;
}
else
{
PERR( "Error in sxftd_init: %d", errno );
}
}
gtk_widget_show_all(sxfti->dialog);

View File

@ -313,10 +313,10 @@
<wrap>False</wrap>
<value>0</value>
<lower>0</lower>
<upper>100</upper>
<upper>365</upper>
<step>1</step>
<page>10</page>
<page_size>10</page_size>
<page>30</page>
<page_size>30</page_size>
<child>
<padding>0</padding>
<expand>False</expand>
@ -390,10 +390,10 @@
<wrap>False</wrap>
<value>0</value>
<lower>0</lower>
<upper>100</upper>
<upper>365</upper>
<step>1</step>
<page>10</page>
<page_size>10</page_size>
<page>30</page>
<page_size>30</page_size>
<child>
<padding>0</padding>
<expand>False</expand>
@ -696,15 +696,6 @@
</widget>
</widget>
<widget>
<class>GtkStatusbar</class>
<name>ledger_status</name>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
</widget>
</widget>

View File

@ -488,7 +488,7 @@ gnc_ledger_display_template_gl (char *id)
}
ld = gnc_ledger_display_internal (NULL, q, LD_GL,
GENERAL_LEDGER,
SEARCH_LEDGER,
REG_STYLE_JOURNAL,
FALSE, TRUE); /* TRUE : template mode */