From d7ce67bb66a78ba64aa1b9927687e20305ca0d62 Mon Sep 17 00:00:00 2001 From: Robert Graham Merkel Date: Wed, 1 Aug 2001 06:45:20 +0000 Subject: [PATCH] Add support for detecting "changes after last save". Format cleanup. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@5062 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 20 ++++ src/doc/TODO-schedxactions | 4 +- src/engine/SchedXaction.c | 131 ++++++++++++++++++--------- src/engine/SchedXaction.h | 87 +++++++++++++----- src/engine/gnc-book-p.h | 13 +++ src/engine/gnc-book.c | 58 +++++++++++- src/engine/gnc-schedxaction-xml-v2.c | 3 +- src/gnome/dialog-scheduledxaction.c | 2 +- 8 files changed, 247 insertions(+), 71 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0a99d72263..1b05b73033 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2001-08-01 Robert Graham Merkel + + * src/engine/SchedXaction.{ch}: modified indenting to 2 spaces. + + * src/engine/SchedXaction.{ch}: Added member for recording if + SX has changed since last save. + (xaccSchedXactionSetDirtyness) provide API for modifying that field. + All setter functions changed to set member appropriately. + (xaccSchedXactionSetSlot, XaccSchedXactionGetSlot): New functions + + * src/engine/gnc-book-p.h (struct gnc_book_struct): Added field + for recording whether sx list had changed. + + * src/engine/gnc-book.c: (gnc_book_marked_save): mark the SX-related + stuff as saved. + (gnc_book_not_saved): look up the SX-related stuff as well. + + * src/engine/gnc-schedxaction-v2.c: once a scheduled transaction is + loaded by the backend, mark it as not saved. + 2001-07-30 Christian Stimming * src/scm/html-utilities.scm: Fixed bug with sub-balances in diff --git a/src/doc/TODO-schedxactions b/src/doc/TODO-schedxactions index 93453288d2..cdc95fca10 100644 --- a/src/doc/TODO-schedxactions +++ b/src/doc/TODO-schedxactions @@ -13,6 +13,7 @@ X XMLv2 I/O X need policy for start-dates in GNCFrequency X fix GetNextInstance and GetInstanceAfter, mostly for composite FreqSpecs X also needs to deal with >28-mday values WRT last-occur date + multipliers +X Engine ...Init() functions should be private. X would like "don't even tell me you instantiated it, just fscking do it!" option for non-manual-conf SXes @@ -21,7 +22,6 @@ X would like "don't even tell me you instantiated it, just fscking do ### '.' = to-do, 'X' = done ################################################## -. Engine ...Init() functions should be private. . FreqSpec.c . xaccFreqSpecGetFreqStr [display] needs to go away [?] @@ -33,7 +33,7 @@ X create a template register . this is going to be: a tabbed notebook in which the tabs contain the number of transactions the GL they hold contain. -. Hook into 'book data changed' save-on-exit decision. +. Hook into 'book data changed' save-on-exit decision . add a big calendar [gnome-pim? evo?] to SXaction List/overview diff --git a/src/engine/SchedXaction.c b/src/engine/SchedXaction.c index e14f285348..30a2c7fddb 100644 --- a/src/engine/SchedXaction.c +++ b/src/engine/SchedXaction.c @@ -50,7 +50,7 @@ void sxprivtransactionListMapDelete( gpointer data, gpointer user_data ); static void -xaccSchedXactionInit( SchedXaction *sx, GNCBook *book ) +xaccSchedXactionInit( SchedXaction *sx, GNCBook *book) { AccountGroup *ag; char *name; @@ -68,6 +68,7 @@ xaccSchedXactionInit( SchedXaction *sx, GNCBook *book ) sx->autoCreateNotify = FALSE; sx->advanceCreateDays = 0; sx->advanceRemindDays = 0; + sx->dirty = TRUE; /* sx->templateSplits = NULL; */ /* create a new template account for our splits */ @@ -124,20 +125,6 @@ xaccSchedXactionFree( SchedXaction *sx ) gnc_engine_generate_event( &sx->guid, GNC_EVENT_DESTROY ); xaccRemoveEntity( &sx->guid ); - /* - * FIXME: commented out at this stage because I haven't figured - * out exactly how to get rid of sx->templateSplits yet - * but I don't want to be deleting these transactions twice . . . - */ - -#if 0 - g_list_foreach( sx->templateSplits, - sxprivtransactionListMapDelete, - NULL ); - - g_list_free( sx->templateSplits ); - -#endif if ( sx->name ) g_free( sx->name ); @@ -185,6 +172,7 @@ xaccSchedXactionSetFreqSpec( SchedXaction *sx, FreqSpec *fs ) xaccFreqSpecFree( sx->freq ); sx->freq = fs; + sx->dirty = TRUE; } gchar * @@ -201,6 +189,7 @@ xaccSchedXactionSetName( SchedXaction *sx, const gchar *newName ) g_free( sx->name ); sx->name = NULL; } + sx->dirty = TRUE; sx->name = g_strdup( newName ); } @@ -214,6 +203,7 @@ void xaccSchedXactionSetStartDate( SchedXaction *sx, GDate* newStart ) { sx->start_date = *newStart; + sx->dirty = TRUE; } gboolean @@ -231,13 +221,15 @@ xaccSchedXactionGetEndDate( SchedXaction *sx ) void xaccSchedXactionSetEndDate( SchedXaction *sx, GDate *newEnd ) { - if ( g_date_valid( newEnd ) ) { - if ( g_date_compare( newEnd, &sx->start_date ) < 0 ) { - /* FIXME:error - error( "New end date before start date" ); */ - } - } - sx->end_date = *newEnd; + if ( g_date_valid( newEnd ) ) { + if ( g_date_compare( newEnd, &sx->start_date ) < 0 ) { + /* FIXME:error + error( "New end date before start date" ); */ + } + } + + sx->end_date = *newEnd; + sx->dirty = TRUE; } GDate* @@ -249,44 +241,76 @@ xaccSchedXactionGetLastOccurDate( SchedXaction *sx ) void xaccSchedXactionSetLastOccurDate( SchedXaction *sx, GDate* newLastOccur ) { - sx->last_date = *newLastOccur; + sx->last_date = *newLastOccur; + sx->dirty = TRUE; + return; } gboolean xaccSchedXactionHasOccurDef( SchedXaction *sx ) { - return ( xaccSchedXactionGetNumOccur( sx ) != 0 ); + return ( xaccSchedXactionGetNumOccur( sx ) != 0 ); } gint xaccSchedXactionGetNumOccur( SchedXaction *sx ) { - return sx->num_occurances_total; + return sx->num_occurances_total; } void xaccSchedXactionSetNumOccur( SchedXaction *sx, gint newNum ) { - sx->num_occurances_remain = sx->num_occurances_total = newNum; + sx->num_occurances_remain = sx->num_occurances_total = newNum; + sx->dirty = TRUE; } gint xaccSchedXactionGetRemOccur( SchedXaction *sx ) { - return sx->num_occurances_remain; + return sx->num_occurances_remain; } void xaccSchedXactionSetRemOccur( SchedXaction *sx, gint numRemain ) { - /* FIXME This condition can be tightened up */ - if ( numRemain > sx->num_occurances_total ) { - /* FIXME:error - error( "more remaining occurances than total" ); */ - } - sx->num_occurances_remain = numRemain; + /* FIXME This condition can be tightened up */ + if ( numRemain > sx->num_occurances_total ) { + /* FIXME:error + error( "more remaining occurances than total" ); */ + } + sx->num_occurances_remain = numRemain; + sx->dirty = TRUE; + return; +} + + +kvp_value * +xaccSchedXactionGetSlot( SchedXaction *sx, const char *slot ) +{ + if (!sx) + { + return NULL; + } + + return kvp_frame_get_slot(sx->kvp_data, slot); +} + +void +xaccSchedXactionSetSlot( SchedXaction *sx, + const char *slot, + const kvp_value *value ) +{ + if (!sx) + { + return; + } + + kvp_frame_set_slot( sx->kvp_data, slot, value ); + sx->dirty = TRUE; + return; } kvp_frame* @@ -298,7 +322,8 @@ xaccSchedXactionGetSlots( SchedXaction *sx ) void xaccSchedXactionSetSlots( SchedXaction *sx, kvp_frame *frm ) { - sx->kvp_data = frm; + sx->kvp_data = frm; + sx->dirty = TRUE; } const GUID* @@ -310,7 +335,8 @@ xaccSchedXactionGetGUID( SchedXaction *sx ) void xaccSchedXactionSetGUID( SchedXaction *sx, GUID g ) { - sx->guid = g; + sx->guid = g; + sx->dirty = TRUE; } void @@ -318,8 +344,9 @@ xaccSchedXactionGetAutoCreate( SchedXaction *sx, gboolean *outAutoCreate, gboolean *outNotify ) { - *outAutoCreate = sx->autoCreateOption; - *outNotify = sx->autoCreateNotify; + *outAutoCreate = sx->autoCreateOption; + *outNotify = sx->autoCreateNotify; + return; } void @@ -327,20 +354,24 @@ xaccSchedXactionSetAutoCreate( SchedXaction *sx, gboolean newAutoCreate, gboolean newNotify ) { - sx->autoCreateOption = newAutoCreate; - sx->autoCreateNotify = newNotify; + + sx->autoCreateOption = newAutoCreate; + sx->autoCreateNotify = newNotify; + sx->dirty = TRUE; + return; } gint xaccSchedXactionGetAdvanceCreation( SchedXaction *sx ) { - return sx->advanceCreateDays; + return sx->advanceCreateDays; } void xaccSchedXactionSetAdvanceCreation( SchedXaction *sx, gint createDays ) { - sx->advanceCreateDays = createDays; + sx->advanceCreateDays = createDays; + sx->dirty = TRUE; } gint @@ -352,7 +383,8 @@ xaccSchedXactionGetAdvanceReminder( SchedXaction *sx ) void xaccSchedXactionSetAdvanceReminder( SchedXaction *sx, gint reminderDays ) { - sx->advanceRemindDays = reminderDays; + sx->dirty = TRUE; + sx->advanceRemindDays = reminderDays; } GDate @@ -436,6 +468,21 @@ xaccSchedXactionSetSplits( SchedXaction *sx, GList *newSplits ) { g_return_if_fail( sx ); sx->templateSplits = newSplits; + return; } #endif + + +void +xaccSchedXactionSetDirtyness( SchedXaction *sx, gboolean dirty_p) +{ + sx->dirty = dirty_p; + return; +} + +gboolean +xaccSchedXactionIsDirty(SchedXaction *sx) +{ + return sx->dirty; +} diff --git a/src/engine/SchedXaction.h b/src/engine/SchedXaction.h index 5cae033b2e..c4845521fb 100644 --- a/src/engine/SchedXaction.h +++ b/src/engine/SchedXaction.h @@ -56,29 +56,33 @@ * of the internal ledger] for this editing. **/ typedef struct gncp_SchedXaction { - gchar *name; - - FreqSpec *freq; - - GDate last_date; - - GDate start_date; - /* if end_date is invalid, then no end. */ - GDate end_date; - - /* if num_occurances_total == 0, then no limit */ - gint num_occurances_total; - /* reminaing occurances are as-of the 'last_date'. */ - gint num_occurances_remain; - - gboolean autoCreateOption; - gboolean autoCreateNotify; - gint advanceCreateDays; - gint advanceRemindDays; + gchar *name; + + FreqSpec *freq; + + GDate last_date; + + GDate start_date; + /* if end_date is invalid, then no end. */ + GDate end_date; + /* if num_occurances_total == 0, then no limit */ + gint num_occurances_total; + /* reminaing occurances are as-of the 'last_date'. */ + gint num_occurances_remain; + + gboolean autoCreateOption; + gboolean autoCreateNotify; + gint advanceCreateDays; + gint advanceRemindDays; + Account *template_acct; - GUID guid; - kvp_frame *kvp_data; + GUID guid; + + /* Changed since last save? */ + gboolean dirty; + + kvp_frame *kvp_data; } SchedXaction; @@ -86,7 +90,24 @@ typedef struct gncp_SchedXaction { /** * Creates and initializes a scheduled transaction. **/ -SchedXaction *xaccSchedXactionMalloc( GNCBook *book ); +SchedXaction *xaccSchedXactionMalloc( GNCBook *book); + +/* + * returns true if the scheduled transaction is dirty and needs to + * be saved + */ + +gboolean xaccSchedXactionIsDirty(SchedXaction *sx); + +/* + * Set dirtyness state. Only save/load code should modify this outside + * SX engine CODE . . . + * (set it to FALSE after backend completes reading in data + * + * FIXME: put this into a private header . . . . + */ + +void xaccSchedXactionSetDirtyness(SchedXaction *sx, gboolean dirty_p); /* * Cleans up and frees a SchedXaction and it's associated data. **/ @@ -149,6 +170,12 @@ void xaccSchedXactionAddXaction( SchedXaction *sx, #error ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #endif /* 0 */ + +/* + * The following function is slightly risky. If you change + * the retrieved kvp_frame you must mark the SchedXaction + * dirty with xaccSchedXactionSetDirtyness + */ kvp_frame *xaccSchedXactionGetSlots( SchedXaction *sx ); /** * Sets the SX kvp data to the given kvp_frame. @@ -157,6 +184,22 @@ kvp_frame *xaccSchedXactionGetSlots( SchedXaction *sx ); void xaccSchedXactionSetSlots( SchedXaction *sx, kvp_frame *frm ); + +/** + * Use the following two functions in preference to + * the above two . . . + */ +kvp_value *xaccSchedXactionGetSlot( SchedXaction *sx, + const char *slot ); + +/* + * This function copies value, so you don't have to + */ + +void xaccSchedXactionSetSlot( SchedXaction *sx, + const char *slot, + const kvp_value *value ); + const GUID *xaccSchedXactionGetGUID( SchedXaction *sx ); void xaccSchedXactionSetGUID( SchedXaction *sx, GUID g ); diff --git a/src/engine/gnc-book-p.h b/src/engine/gnc-book-p.h index 9bbbaf52b0..1ecd9717ad 100644 --- a/src/engine/gnc-book-p.h +++ b/src/engine/gnc-book-p.h @@ -54,6 +54,13 @@ struct gnc_book_struct GList *sched_xactions; AccountGroup *template_group; + /* + * should be set true if sched_xactions is changed + * before saving + */ + + gboolean sx_notsaved; + /* the requested book id, in the form or a URI, such as * file:/some/where, or sql:server.host.com:555 */ @@ -81,6 +88,12 @@ struct gnc_book_struct void gnc_book_set_group(GNCBook *book, AccountGroup *grp); void gnc_book_set_pricedb(GNCBook *book, GNCPriceDB *db); +/* + * used by backends to mark the notsaved as FALSE just after + * loading. Do not use otherwise! + */ + + void gnc_book_mark_saved(GNCBook *book); void gnc_book_push_error (GNCBook *book, GNCBackendError err, char *message); diff --git a/src/engine/gnc-book.c b/src/engine/gnc-book.c index c4240b69c8..8f46cd949e 100644 --- a/src/engine/gnc-book.c +++ b/src/engine/gnc-book.c @@ -129,6 +129,7 @@ gnc_book_init (GNCBook *book) book->pricedb = gnc_pricedb_create(); book->sched_xactions = NULL; + book->sx_notsaved = FALSE; book->template_group = xaccMallocAccountGroup(); book->book_id = NULL; @@ -217,8 +218,10 @@ gnc_book_get_schedxactions( GNCBook *book ) void gnc_book_set_schedxactions( GNCBook *book, GList *newList ) { - if ( book == NULL ) return; - book->sched_xactions = newList; + if ( book == NULL ) return; + book->sched_xactions = newList; + book->sx_notsaved = TRUE; + return; } AccountGroup * @@ -264,11 +267,35 @@ gnc_book_get_url (GNCBook *book) /* ---------------------------------------------------------------------- */ +static void +mark_sx_clean(gpointer data, gpointer user_data) +{ + SchedXaction *sx = (SchedXaction *) data; + xaccSchedXactionSetDirtyness(sx, FALSE); + return; +} + +static void +book_sxns_mark_saved(GNCBook *book) +{ + book->sx_notsaved = FALSE; + g_list_foreach(gnc_book_get_schedxactions(book), + mark_sx_clean, + NULL); + return; +} void gnc_book_mark_saved(GNCBook *book) { + /* FIXME: is this the right behaviour if book == NULL? */ + g_return_if_fail(book); xaccGroupMarkSaved(gnc_book_get_group(book)); gnc_pricedb_mark_clean(gnc_book_get_pricedb(book)); + + xaccGroupMarkSaved(gnc_book_get_template_group(book)); + book_sxns_mark_saved(book); + + return; } @@ -502,6 +529,29 @@ gnc_book_load (GNCBook *book) return TRUE; } + + +static gboolean +book_sxlist_notsaved(GNCBook *book) +{ + GList *sxlist; + SchedXaction *sx; + if(book->sx_notsaved + || + xaccGroupNotSaved(book->template_group)) return TRUE; + + for(sxlist = book->sched_xactions; + sxlist != NULL; + sxlist = g_list_next(sxlist)) + { + sx = (SchedXaction *) (sxlist->data); + if (xaccSchedXactionIsDirty( sx )) + return TRUE; + } + + return FALSE; +} + /* ---------------------------------------------------------------------- */ gboolean @@ -511,7 +561,9 @@ gnc_book_not_saved(GNCBook *book) return(xaccGroupNotSaved(book->topgroup) || - gnc_pricedb_dirty(book->pricedb)); + gnc_pricedb_dirty(book->pricedb) + || + book_sxlist_notsaved(book)); } /* ---------------------------------------------------------------------- */ diff --git a/src/engine/gnc-schedxaction-xml-v2.c b/src/engine/gnc-schedxaction-xml-v2.c index b234b891d4..575b3f024c 100644 --- a/src/engine/gnc-schedxaction-xml-v2.c +++ b/src/engine/gnc-schedxaction-xml-v2.c @@ -416,7 +416,7 @@ gnc_schedXaction_end_handler(gpointer data_for_children, g_return_val_if_fail( tree, FALSE ); - sx = xaccSchedXactionMalloc( NULL ); + sx = xaccSchedXactionMalloc( NULL); /* FIXME: this should be removed somewhere near 1.8 release time. */ { @@ -470,6 +470,7 @@ gnc_schedXaction_end_handler(gpointer data_for_children, sx->template_acct = acct; } + xaccSchedXactionSetDirtyness(sx, FALSE); xmlFreeNode( tree ); return successful; diff --git a/src/gnome/dialog-scheduledxaction.c b/src/gnome/dialog-scheduledxaction.c index f69cf9e3c3..4db79046df 100644 --- a/src/gnome/dialog-scheduledxaction.c +++ b/src/gnome/dialog-scheduledxaction.c @@ -838,7 +838,7 @@ new_button_clicked( GtkButton *b, gpointer d ) { SchedXactionDialog *sxd; SchedXaction *tmpSX = - xaccSchedXactionMalloc( gncGetCurrentBook() ); + xaccSchedXactionMalloc( gncGetCurrentBook()); SchedXactionEditorDialog *sxed; sxd = (SchedXactionDialog*)d;