From 55f2f43fcd9f047ce2e8ef2cd46c738bf572d4aa Mon Sep 17 00:00:00 2001 From: David Hampton Date: Tue, 17 Sep 2002 07:47:15 +0000 Subject: [PATCH] Add a progress bar to main window. Use this progress bar to show the progress of read, write and export functions. Internally this adds a callback pointer for the various backends to pass a percentage done number out to the session code. It also adds a callback pointer for the session code to pass this percentage on out to the routine that initiated the file read/write. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@7225 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 74 ++++++ src/app-file/gnc-file.c | 99 +++++++- src/app-file/gnc-file.h | 9 + src/backend/file/gnc-backend-file.c | 14 +- src/backend/file/io-example-account.c | 2 +- src/backend/file/io-gncxml-v2.c | 232 +++++++++++++----- src/backend/file/io-gncxml-v2.h | 22 +- src/backend/file/io-utils.c | 10 +- src/backend/file/io-utils.h | 7 +- src/backend/file/test/test-load-xml2.c | 2 +- src/backend/file/test/test-save-in-lang.c | 4 +- src/backend/postgres/PostgresBackend.c | 14 ++ src/backend/rpc/RpcBackend.c | 8 + src/engine/Backend.c | 2 + src/engine/Backend.h | 2 + src/engine/BackendP.h | 4 + src/engine/Makefile.am | 2 + src/engine/engine-utilities.scm | 2 +- src/engine/gnc-book.c | 7 + src/engine/gnc-book.h | 2 + src/engine/gnc-session-scm.c | 104 ++++++++ src/engine/gnc-session-scm.h | 50 ++++ src/engine/gnc-session.c | 47 +++- src/engine/gnc-session.h | 10 +- src/engine/gw-engine-spec.scm | 23 +- src/gnome-utils/Makefile.am | 2 + src/gnome-utils/gnc-mdi-utils.c | 31 +++ src/gnome/gw-gnc-spec.scm | 8 + src/gnome/top-level.c | 1 - src/gnome/window-main.c | 70 +----- .../qif-io-core/test/test-import-phase-1.scm | 2 +- src/scm/main.scm | 19 +- src/scm/price-quotes.scm | 2 +- 33 files changed, 723 insertions(+), 164 deletions(-) create mode 100644 src/engine/gnc-session-scm.c create mode 100644 src/engine/gnc-session-scm.h diff --git a/ChangeLog b/ChangeLog index 0b1aee80f4..d38bb454f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,77 @@ +2002-09-17 David Hampton + + Add progress bar to main window. Shows progress of read, write + and export functions. Adds a callback for the backend to pass a + percentage done number out to the session code, and a callback for + the session code to pass this percentage out to the caller's gui + display funtion. + + * src/app-file/gnc-file-p.h: + * src/app-file/gnc-file.c (gnc_file_set_pct_handler): Add a file + handler "percent done" routine that can be installed. + + * src/app-file/gnc-file.c (gnc_post_file_open) (gnc_file_save): + Call the file handler routine pre/post file read/write, and pass + the handler into the backend so that it can report percentage + complete. + + * src/app-file/gnc-file.c (gnc_file_export_file): + New export function. This is the upper half of the exporting + function. This is designed similar to the read/write routines. + + * src/backend/file/gnc-backend-file.c + (gnc_file_be_write_accounts_to_file): New export function. This + is part of the lower half of the exporting function. This is + designed similar to the read/write routines. + + * src/backend/file/io-example-account.c + (gnc_write_example_account):New calling arguments. Add counters. + Invoke the percentage done callback where appropriate. + + * src/backend/file/io-gncxml-v2.c (add_schedXaction_local) + (run_callback) (write_xxx): New calling arguments. Add counters. + Invoke the percentage done callback where appropriate. + (file_rw_feedback): New function for XML read/write. Computed + percentage done then calls the callback function handed in from + outside of the backend code. (gnc_sixtp_gdv2_new): New auxiliary + function. (gnc_book_write_to_xml_filehandle_v2) + (gnc_book_write_accounts_to_xml_filehandle_v2): Remember count of + items to process. (gnc_book_write_accounts_to_xml_file_v2): Other + part of the lower half of the exporting function. + + * src/backend/file/io-utils.c (write_account_group) + (write_accounts):New calling arguments. Add counters. Invoke the + percentage done callback where appropriate. + + * src/backend/postgres/PostgresBackend.c: + * src/backend/rpc/RpcBackend.c: + * src/enfine/Backend.c: + Initialize the new pointers in the backend data structure. + + * src/gnome/window-main.c (gnc_main_window_file_export_cb): + The file export function was moved into gnc-file.c. + + * src/engine/Makefile.am: + * src/engine/gnc-session-scm.[ch]: New files. Moved the scheme + session read/write hooks here because of the new callback. Keeps + scheme out of the main session sources. + + * src/engine/gnc-session.c (gnc_session_load): + (gnc_session_save): Added a callback for percentage done. + (gnc_session_export): New export function. This is the middle of + the exporting function. This is designed similar to the + load/save routines. + + * src/engine/gw-engine-spec.scm: New arguments to session + load/save. New session export function. + + * src/gnome/gw-gnc-spec.scm: New function to destroy the splash screen. + + * src/gnome/top-level.c: No longer destroys splash screen. + + * src/scm/main.scm: I18n new splash screen strings. Destroy splash + screen after loading data file. + 2002-09-16 Derek Atkins Fix bug #91413 -- Add TaxTable defaults to Customers and Vendors diff --git a/src/app-file/gnc-file.c b/src/app-file/gnc-file.c index 4e8c9408b9..c72e90bbb3 100644 --- a/src/app-file/gnc-file.c +++ b/src/app-file/gnc-file.c @@ -56,6 +56,7 @@ static GNCHistoryAddFileFunc history_add_file_func = NULL; static GNCHistoryGetLastFunc history_get_last_func = NULL; static GNCFileDialogFunc file_dialog_func = NULL; +static GNCFilePercentageFunc file_percentage_func = NULL; void @@ -68,6 +69,12 @@ gnc_file_set_handlers (GNCHistoryAddFileFunc history_add_file_func_in, file_dialog_func = file_dialog_func_in; } +void +gnc_file_set_pct_handler (GNCFilePercentageFunc file_percentage_func_in) +{ + file_percentage_func = file_percentage_func_in; +} + static GNCSession * gnc_get_current_session_internal (void) { @@ -427,7 +434,13 @@ gnc_post_file_open (const char * filename) { AccountGroup *new_group; - gnc_session_load (new_session); + if (file_percentage_func) { + file_percentage_func(_("Reading file..."), 0.0); + gnc_session_load (new_session, file_percentage_func); + file_percentage_func(NULL, -1.0); + } else { + gnc_session_load (new_session, NULL); + } /* check for i/o error, put up appropriate error dialog */ io_err = gnc_session_get_error (new_session); @@ -528,6 +541,82 @@ gnc_file_open_file (const char * newfile) return gnc_post_file_open (newfile); } +void +gnc_file_export_file(const char * newfile) +{ + GNCSession *new_session; + gboolean ok; + GNCBackendError io_err = ERR_BACKEND_NO_ERR; + + if (!newfile) { + if (!file_dialog_func) { + PWARN ("no file dialog function"); + return; + } + + newfile = file_dialog_func (_("Export"), NULL, NULL); + if (!newfile) + return; + } + + gnc_engine_suspend_events(); + + /* -- this session code is NOT identical in FileOpen and FileSaveAs -- */ + + new_session = gnc_session_new (); + gnc_session_begin (new_session, newfile, FALSE, FALSE); + + io_err = gnc_session_get_error (new_session); + + /* if file appears to be locked, ask the user ... */ + if (ERR_BACKEND_LOCKED == io_err) + { + if (FALSE == show_session_error (io_err, newfile)) + { + /* user told us to ignore locks. So ignore them. */ + gnc_session_begin (new_session, newfile, TRUE, FALSE); + } + } + + /* --------------- END CORE SESSION CODE -------------- */ + + /* oops ... file already exists ... ask user what to do... */ + if (gnc_session_save_may_clobber_data (new_session)) + { + const char *format = _("The file \n %s\n already exists.\n" + "Are you sure you want to overwrite it?"); + + /* if user says cancel, we should break out */ + if (!gnc_verify_dialog (FALSE, format, newfile)) + { + return; + } + + /* Whoa-ok. Blow away the previous file. */ + } + + /* use the current session to save to file */ + gnc_set_busy_cursor (NULL, TRUE); + if (file_percentage_func) { + file_percentage_func(_("Exporting file..."), 0.0); + ok = gnc_session_export (new_session, current_session, + file_percentage_func); + file_percentage_func(NULL, -1.0); + } else { + ok = gnc_session_export (new_session, current_session, NULL); + } + gnc_unset_busy_cursor (NULL); + gnc_session_destroy (new_session); + gnc_engine_resume_events(); + + if (!ok) + { + const char *format = _("There was an error saving the file.\n\n%s"); + + gnc_error_dialog_parented (NULL, format, strerror(errno)); + return; + } +} static gboolean been_here_before = FALSE; @@ -552,7 +641,13 @@ gnc_file_save (void) /* use the current session to save to file */ gnc_set_busy_cursor (NULL, TRUE); - gnc_session_save (session); + if (file_percentage_func) { + file_percentage_func(_("Writing file..."), 0.0); + gnc_session_save (session, file_percentage_func); + file_percentage_func(NULL, -1.0); + } else { + gnc_session_save (session, NULL); + } gnc_unset_busy_cursor (NULL); /* Make sure everything's OK - disk could be full, file could have diff --git a/src/app-file/gnc-file.h b/src/app-file/gnc-file.h index bbc5b0c79c..6c8e2a97ae 100644 --- a/src/app-file/gnc-file.h +++ b/src/app-file/gnc-file.h @@ -97,6 +97,11 @@ * routine, except that the new file to open is passed as a char * * argument. * + * The gnc_file_export_file() routine will check for an existing edit + * session, and if one exists, it will save just the commodities + * and accounts to a file. If an error occurs, a popup dialogue + * will inform the user of the error. + * * The gnc_file_quit() routine will close out and destroy the current session. * The user WILL NOT BE PROMPTED to confirm this action, or do do * any kind of saving beforehand. @@ -120,6 +125,7 @@ void gnc_file_save (void); void gnc_file_save_as (void); gboolean gnc_file_open_file (const char *filename); +void gnc_file_export_file(const char * filename); gboolean gnc_file_query_save (void); @@ -128,4 +134,7 @@ void gnc_file_quit (void); typedef gboolean (*GNCCanCancelSaveCB) (void); void gnc_file_set_can_cancel_callback (GNCCanCancelSaveCB cb); +typedef void (*GNCFilePercentageFunc) (const char *message, int percent); +void gnc_file_set_pct_handler (GNCFilePercentageFunc file_percentage_func); + #endif /* GNC_FILE_H */ diff --git a/src/backend/file/gnc-backend-file.c b/src/backend/file/gnc-backend-file.c index b13d5b665a..b93620d44f 100644 --- a/src/backend/file/gnc-backend-file.c +++ b/src/backend/file/gnc-backend-file.c @@ -66,6 +66,8 @@ static void gnc_file_be_load_from_file(Backend *, GNCBook *); static gboolean gnc_file_be_get_file_lock (FileBackend *be); static gboolean gnc_file_be_write_to_file(FileBackend *be, gboolean make_backup); +static void gnc_file_be_write_accounts_to_file(Backend *be, + GNCBook *book); static void gnc_file_be_remove_old_files(FileBackend *be); void @@ -213,6 +215,7 @@ gnc_backend_new(void) be->process_events = NULL; be->sync_all = file_sync_all; + be->export = gnc_file_be_write_accounts_to_file; fbe->dirname = NULL; fbe->fullpath = NULL; @@ -371,7 +374,7 @@ gnc_file_be_load_from_file (Backend *bend, GNCBook *book) switch (gnc_file_be_determine_file_type(be->fullpath)) { case GNC_BOOK_XML2_FILE: - rc = gnc_session_load_from_xml_file_v2 (be->session, NULL); + rc = gnc_session_load_from_xml_file_v2 (be->session); if (FALSE == rc) error = ERR_FILEIO_PARSE_ERROR; break; @@ -708,3 +711,12 @@ gnc_file_be_write_to_file(FileBackend *be, gboolean make_backup) } } +static void +gnc_file_be_write_accounts_to_file(Backend *be, GNCBook *book) +{ + const gchar *datafile; + + datafile = ((FileBackend *)be)->fullpath; + gnc_book_write_accounts_to_xml_file_v2(be, book, datafile); +} + diff --git a/src/backend/file/io-example-account.c b/src/backend/file/io-example-account.c index 8da8904b25..7144c6d8aa 100644 --- a/src/backend/file/io-example-account.c +++ b/src/backend/file/io-example-account.c @@ -375,7 +375,7 @@ gnc_write_example_account(GncExampleAccount *gea, const gchar *filename) write_string_part(out, GNC_ACCOUNT_LONG, gea->long_description); - write_account_group(out, gea->group); + write_account_group(out, gea->group, NULL); fprintf(out, "\n\n"); diff --git a/src/backend/file/io-gncxml-v2.c b/src/backend/file/io-gncxml-v2.c index 439caa795d..b52491805f 100644 --- a/src/backend/file/io-gncxml-v2.c +++ b/src/backend/file/io-gncxml-v2.c @@ -64,12 +64,12 @@ struct file_backend { #define GNC_V2_STRING "gnc-v2" static const gchar *book_version_string; -static void +void run_callback(sixtp_gdv2 *data, const char *type) { if(data->countCallback) { - data->countCallback(type, data->counter); + data->countCallback(data, type); } } @@ -298,6 +298,8 @@ add_schedXaction_local(sixtp_gdv2 *data, SchedXaction *sx) list = g_list_append(list, sx); gnc_book_set_schedxactions(data->book, list); + data->counter.schedXactions_loaded++; + run_callback(data, "schedXactions"); return TRUE; } @@ -473,21 +475,56 @@ gnc_counter_sixtp_parser_create(void) #if 0 static void -print_counter_data(load_counter data) +print_counter_data(load_counter *data) { PINFO("Transactions: Total: %d, Loaded: %d\n", - data.transactions_total, data.transactions_loaded); + data->transactions_total, data->transactions_loaded); PINFO("Accounts: Total: %d, Loaded: %d\n", - data.accounts_total, data.accounts_loaded); + data->accounts_total, data->accounts_loaded); PINFO("Books: Total: %d, Loaded: %d\n", - data.books_total, data.books_loaded); + data->books_total, data->books_loaded); PINFO("Commodities: Total: %d, Loaded: %d\n", - data.commodities_total, data.commodities_loaded); + data->commodities_total, data->commodities_loaded); PINFO("Scheduled Tansactions: Total: %d, Loaded: %d\n", - data.schedXactions_total, data.schedXactions_loaded); + data->schedXactions_total, data->schedXactions_loaded); } #endif +static void +file_rw_feedback (sixtp_gdv2 *gd, const char *type) +{ + load_counter *counter; + int loaded, total, percentage; + + g_assert(gd != NULL); + if (!gd->gui_display_fn) + return; + + counter = &gd->counter; + loaded = counter->transactions_loaded + counter->accounts_loaded + + counter->books_loaded + counter->commodities_loaded + + counter->schedXactions_loaded; + total = counter->transactions_total + counter->accounts_total + + counter->books_total + counter->commodities_total + + counter->schedXactions_total; + + percentage = (loaded * 100)/total; + if (percentage > 100) { + printf("Transactions: Total: %d, Loaded: %d\n", + counter->transactions_total, counter->transactions_loaded); + printf("Accounts: Total: %d, Loaded: %d\n", + counter->accounts_total, counter->accounts_loaded); + printf("Books: Total: %d, Loaded: %d\n", + counter->books_total, counter->books_loaded); + printf("Commodities: Total: %d, Loaded: %d\n", + counter->commodities_total, counter->commodities_loaded); + printf("Scheduled Tansactions: Total: %d, Loaded: %d\n", + counter->schedXactions_total, counter->schedXactions_loaded); + } + percentage = MIN(percentage, 100); + gd->gui_display_fn(NULL, percentage); +} + static const char *BOOK_TAG = "gnc:book"; static const char *BOOK_ID_TAG = "book:id"; static const char *BOOK_SLOTS_TAG = "book:slots"; @@ -605,21 +642,15 @@ add_parser_cb (const char *type, gpointer data_p, gpointer be_data_p) be_data->ok = FALSE; } -gboolean -gnc_session_load_from_xml_file_v2( - GNCSession *session, - void (*countcallback)(const char *type, load_counter count)) +static sixtp_gdv2 * +gnc_sixtp_gdv2_new ( + GNCBook *book, + countCallbackFn countcallback, + GNCBePercentageFunc gui_display_fn) { - GNCBook *book; - sixtp_gdv2 *gd; - sixtp *top_parser; - sixtp *main_parser; - sixtp *book_parser; - struct file_backend be_data; + sixtp_gdv2 *gd = g_new0(sixtp_gdv2, 1); - gd = g_new0(sixtp_gdv2, 1); - - book = gnc_session_get_book (session); + if (gd == NULL) return NULL; gd->book = book; gd->counter.accounts_loaded = 0; @@ -636,6 +667,24 @@ gnc_session_load_from_xml_file_v2( gd->counter.schedXactions_total = 0; gd->countCallback = countcallback; + gd->gui_display_fn = gui_display_fn; + return gd; +} + +gboolean +gnc_session_load_from_xml_file_v2(GNCSession *session) +{ + GNCBook *book; + Backend *be; + sixtp_gdv2 *gd; + sixtp *top_parser; + sixtp *main_parser; + sixtp *book_parser; + struct file_backend be_data; + + book = gnc_session_get_book (session); + be = (Backend *)gnc_book_get_backend(book); + gd = gnc_sixtp_gdv2_new(book, file_rw_feedback, be->percentage); top_parser = sixtp_new(); main_parser = sixtp_new(); @@ -646,7 +695,7 @@ gnc_session_load_from_xml_file_v2( GNC_V2_STRING, main_parser, NULL, NULL)) { - return FALSE; + goto bail; } if(!sixtp_add_some_sub_parsers( @@ -665,7 +714,7 @@ gnc_session_load_from_xml_file_v2( TEMPLATE_TRANSACTION_TAG, gnc_template_transaction_sixtp_parser_create(), NULL, NULL)) { - return FALSE; + goto bail; } if(!sixtp_add_some_sub_parsers( @@ -681,14 +730,14 @@ gnc_session_load_from_xml_file_v2( TEMPLATE_TRANSACTION_TAG, gnc_template_transaction_sixtp_parser_create(), NULL, NULL)) { - return FALSE; + goto bail; } be_data.ok = TRUE; be_data.parser = book_parser; gncObjectForeachBackend (GNC_FILE_BACKEND, add_parser_cb, &be_data); if (be_data.ok == FALSE) - return FALSE; + goto bail; /* stop logging while we load */ xaccLogDisable (); @@ -698,7 +747,7 @@ gnc_session_load_from_xml_file_v2( { sixtp_destroy(top_parser); xaccLogEnable (); - return FALSE; + goto bail; } /* If the parse succeeded, but there is no pricedb, @@ -729,9 +778,13 @@ gnc_session_load_from_xml_file_v2( g_free(gd); /* DEBUG */ - /* print_counter_data(gd.counter); */ + /* print_counter_data(&gd->counter); */ return TRUE; + + bail: + g_free(gd); + return FALSE; } /***********************************************************************/ @@ -790,10 +843,10 @@ compare_commodity_ids(gconstpointer a, gconstpointer b) gnc_commodity_get_mnemonic(cb))); } -static void write_pricedb (FILE *out, GNCBook *book); -static void write_transactions (FILE *out, GNCBook *book); -static void write_template_transaction_data (FILE *out, GNCBook *book); -static void write_schedXactions(FILE *out, GNCBook *book); +static void write_pricedb (FILE *out, GNCBook *book, sixtp_gdv2 *gd); +static void write_transactions (FILE *out, GNCBook *book, sixtp_gdv2 *gd); +static void write_template_transaction_data (FILE *out, GNCBook *book, sixtp_gdv2 *gd); +static void write_schedXactions(FILE *out, GNCBook *book, sixtp_gdv2 *gd); static void write_counts_cb (const char *type, gpointer data_p, gpointer be_data_p) @@ -824,7 +877,7 @@ write_data_cb (const char *type, gpointer data_p, gpointer be_data_p) } static void -write_book(FILE *out, GNCBook *book) +write_book(FILE *out, GNCBook *book, sixtp_gdv2 *gd) { struct file_backend be_data; @@ -860,7 +913,7 @@ write_book(FILE *out, GNCBook *book) gnc_commodity_table_get_size( gnc_book_get_commodity_table(book)), "account", - xaccGroupGetNumSubAccounts(gnc_book_get_group(book)), + 1 + xaccGroupGetNumSubAccounts(gnc_book_get_group(book)), "transaction", gnc_book_count_transactions(book), "schedxaction", @@ -869,12 +922,12 @@ write_book(FILE *out, GNCBook *book) gncObjectForeachBackend (GNC_FILE_BACKEND, write_counts_cb, &be_data); - write_commodities(out, book); - write_pricedb(out, book); - write_accounts(out, book); - write_transactions(out, book); - write_template_transaction_data(out, book); - write_schedXactions(out, book); + write_commodities(out, book, gd); + write_pricedb(out, book, gd); + write_accounts(out, book, gd); + write_transactions(out, book, gd); + write_template_transaction_data(out, book, gd); + write_schedXactions(out, book, gd); gncObjectForeachBackend (GNC_FILE_BACKEND, write_data_cb, &be_data); @@ -882,7 +935,7 @@ write_book(FILE *out, GNCBook *book) } void -write_commodities(FILE *out, GNCBook *book) +write_commodities(FILE *out, GNCBook *book, sixtp_gdv2 *gd) { gnc_commodity_table *tbl; GList *namespaces; @@ -916,6 +969,8 @@ write_commodities(FILE *out, GNCBook *book) fprintf(out, "\n"); xmlFreeNode(comnode); + gd->counter.commodities_loaded++; + run_callback(gd, "commodities"); } g_list_free (comms); @@ -926,7 +981,7 @@ write_commodities(FILE *out, GNCBook *book) } static void -write_pricedb(FILE *out, GNCBook *book) +write_pricedb(FILE *out, GNCBook *book, sixtp_gdv2 *gd) { xmlNodePtr node; @@ -946,27 +1001,34 @@ write_pricedb(FILE *out, GNCBook *book) static gboolean xml_add_trn_data(Transaction *t, gpointer data) { + struct file_backend *be_data = data; xmlNodePtr node; node = gnc_transaction_dom_tree_create(t); - xmlElemDump((FILE*)data, NULL, node); - fprintf((FILE*)data, "\n"); + xmlElemDump(be_data->out, NULL, node); + fprintf(be_data->out, "\n"); xmlFreeNode(node); + be_data->gd->counter.transactions_loaded++; + run_callback(be_data->gd, "transaction"); return TRUE; } static void -write_transactions(FILE *out, GNCBook *book) +write_transactions(FILE *out, GNCBook *book, sixtp_gdv2 *gd) { + struct file_backend be_data; + + be_data.out = out; + be_data.gd = gd; xaccGroupForEachTransaction(gnc_book_get_group(book), xml_add_trn_data, - (gpointer) out); + (gpointer) &be_data); } static void -write_template_transaction_data( FILE *out, GNCBook *book ) +write_template_transaction_data( FILE *out, GNCBook *book, sixtp_gdv2 *gd ) { AccountGroup *ag; @@ -974,14 +1036,14 @@ write_template_transaction_data( FILE *out, GNCBook *book ) if ( xaccGroupGetNumSubAccounts(ag) > 0 ) { fprintf( out, "<%s>\n", TEMPLATE_TRANSACTION_TAG ); - write_account_group( out, ag ); + write_account_group( out, ag, gd ); xaccGroupForEachTransaction( ag, xml_add_trn_data, (gpointer)out ); fprintf( out, "\n", TEMPLATE_TRANSACTION_TAG ); } } static void -write_schedXactions( FILE *out, GNCBook *book ) +write_schedXactions( FILE *out, GNCBook *book, sixtp_gdv2 *gd) { GList *schedXactions; SchedXaction *tmpSX; @@ -999,6 +1061,8 @@ write_schedXactions( FILE *out, GNCBook *book ) xmlElemDump( out, NULL, node ); fprintf( out, "\n" ); xmlFreeNode( node ); + gd->counter.schedXactions_loaded++; + run_callback(gd, "schedXactions"); } while ( (schedXactions = schedXactions->next) ); } @@ -1032,6 +1096,9 @@ write_v2_header (FILE *out) gboolean gnc_book_write_to_xml_filehandle_v2(GNCBook *book, FILE *out) { + Backend *be; + sixtp_gdv2 *gd; + if (!out) return FALSE; write_v2_header (out); @@ -1040,19 +1107,34 @@ gnc_book_write_to_xml_filehandle_v2(GNCBook *book, FILE *out) "book", 1, NULL); - write_book(out, book); + be = (Backend *)gnc_book_get_backend(book); + gd = gnc_sixtp_gdv2_new(book, file_rw_feedback, be->percentage); + gd->counter.commodities_total = + gnc_commodity_table_get_size(gnc_book_get_commodity_table(book)); + gd->counter.accounts_total = 1 + + xaccGroupGetNumSubAccounts(gnc_book_get_group(book)); + gd->counter.transactions_total = gnc_book_count_transactions(book); + gd->counter.schedXactions_total = + g_list_length( gnc_book_get_schedxactions(book)); + + write_book(out, book, gd); fprintf(out, "\n\n"); + g_free(gd); return TRUE; } +/* + * This function is called by the "export" code. + */ gboolean -gnc_book_write_accounts_to_xml_filehandle_v2(GNCBook *book, FILE *out) +gnc_book_write_accounts_to_xml_filehandle_v2(Backend *be, GNCBook *book, FILE *out) { + sixtp_gdv2 *gd; + if (!out) return FALSE; -PWARN ("huhhhh ???? Who is using this thing ??? \n"); write_v2_header (out); write_counts(out, @@ -1060,20 +1142,29 @@ PWARN ("huhhhh ???? Who is using this thing ??? \n"); gnc_commodity_table_get_size( gnc_book_get_commodity_table(book)), "account", - xaccGroupGetNumSubAccounts(gnc_book_get_group(book)), + 1 + xaccGroupGetNumSubAccounts(gnc_book_get_group(book)), NULL); - write_commodities(out, book); + gd = gnc_sixtp_gdv2_new(book, file_rw_feedback, be->percentage); + gd->counter.commodities_total = + gnc_commodity_table_get_size(gnc_book_get_commodity_table(book)); + gd->counter.accounts_total = 1 + + xaccGroupGetNumSubAccounts(gnc_book_get_group(book)); - write_accounts(out, book); + write_commodities(out, book, gd); + + write_accounts(out, book, gd); fprintf(out, "\n\n"); + g_free(gd); return TRUE; } gboolean -gnc_book_write_to_xml_file_v2(GNCBook *book, const char *filename) +gnc_book_write_to_xml_file_v2( + GNCBook *book, + const char *filename) { FILE *out; @@ -1095,6 +1186,37 @@ gnc_book_write_to_xml_file_v2(GNCBook *book, const char *filename) return TRUE; } +/* + * Have to pass in the backend as this routine needs the temporary + * backend for file export, not the real backend which could be + * postgress or anything else. + */ +gboolean +gnc_book_write_accounts_to_xml_file_v2( + Backend *be, + GNCBook *book, + const char *filename) +{ + FILE *out; + + out = fopen(filename, "w"); + if (out == NULL) + { + return FALSE; + } + + gnc_book_write_accounts_to_xml_filehandle_v2 (be, book, out); + + write_emacs_trailer(out); + + if (fclose(out) != 0) + { + return FALSE; + } + + return TRUE; +} + /***********************************************************************/ gboolean gnc_is_xml_data_file_v2(const gchar *name) diff --git a/src/backend/file/io-gncxml-v2.h b/src/backend/file/io-gncxml-v2.h index 933aac4210..4387706f93 100644 --- a/src/backend/file/io-gncxml-v2.h +++ b/src/backend/file/io-gncxml-v2.h @@ -34,6 +34,7 @@ #include #include "Account.h" +#include "Backend.h" #include "Transaction.h" #include "gnc-book.h" #include "gnc-commodity.h" @@ -64,12 +65,15 @@ typedef struct int schedXactions_loaded; } load_counter; -typedef struct +typedef struct sixtp_gdv2 sixtp_gdv2; +typedef void (*countCallbackFn)(sixtp_gdv2 *gd, const char *type); +struct sixtp_gdv2 { GNCBook *book; load_counter counter; - void (*countCallback)(const char *type, load_counter counter); -} sixtp_gdv2; + countCallbackFn countCallback; + GNCBePercentageFunc gui_display_fn; +}; /** * Struct used to pass in a new data type for XML storage. This contains @@ -114,18 +118,20 @@ typedef struct GNCBook *book; } gnc_template_xaction_data; +/* Call after loading each record */ +void run_callback(sixtp_gdv2 *data, const char *type); + /* read in an account group from a file */ -gboolean gnc_session_load_from_xml_file_v2( - GNCSession *session, - void (*countcallback)(const char *type, load_counter count)); +gboolean gnc_session_load_from_xml_file_v2(GNCSession *session); /* write all book info to a file */ gboolean gnc_book_write_to_xml_filehandle_v2(GNCBook *book, FILE *fh); gboolean gnc_book_write_to_xml_file_v2(GNCBook *book, const char *filename); /* write just the commodities and accounts to a file */ -gboolean gnc_book_write_accounts_to_xml_filehandle_v2(GNCBook *book, - FILE *out); +gboolean gnc_book_write_accounts_to_xml_filehandle_v2(Backend *be, GNCBook *book, FILE *fh); +gboolean gnc_book_write_accounts_to_xml_file_v2(Backend * be, GNCBook *book, + const char *filename); /* The is_gncxml_file() routine checks to see if the first few * chars of the file look like gnc-xml data. diff --git a/src/backend/file/io-utils.c b/src/backend/file/io-utils.c index 75bf5ea362..9ede61745c 100644 --- a/src/backend/file/io-utils.c +++ b/src/backend/file/io-utils.c @@ -53,7 +53,7 @@ write_emacs_trailer(FILE *out) } void -write_account_group(FILE *out, AccountGroup *grp) +write_account_group(FILE *out, AccountGroup *grp, sixtp_gdv2 *gd) { GList *list; GList *node; @@ -71,18 +71,20 @@ write_account_group(FILE *out, AccountGroup *grp) fprintf(out, "\n"); xmlFreeNode(accnode); + gd->counter.accounts_loaded++; + run_callback(gd, "account"); newgrp = xaccAccountGetChildren((Account*)(node->data)); if (newgrp) { - write_account_group(out, newgrp); + write_account_group(out, newgrp, gd); } } } void -write_accounts(FILE *out, GNCBook *book) +write_accounts(FILE *out, GNCBook *book, sixtp_gdv2 *gd) { - write_account_group(out, gnc_book_get_group(book)); + write_account_group(out, gnc_book_get_group(book), gd); } diff --git a/src/backend/file/io-utils.h b/src/backend/file/io-utils.h index b9f61365b1..fa32b32022 100644 --- a/src/backend/file/io-utils.h +++ b/src/backend/file/io-utils.h @@ -29,11 +29,12 @@ #include "gnc-book.h" #include "Group.h" +#include "io-gncxml-v2.h" -void write_account_group(FILE *out, AccountGroup *grp); -void write_accounts(FILE *out, GNCBook *book); +void write_account_group(FILE *out, AccountGroup *grp, sixtp_gdv2 *gd); +void write_accounts(FILE *out, GNCBook *book, sixtp_gdv2 *gd); void write_book_parts(FILE *out, GNCBook *book); -void write_commodities(FILE *out, GNCBook *book); +void write_commodities(FILE *out, GNCBook *book, sixtp_gdv2 *gd); void write_emacs_trailer(FILE *out); diff --git a/src/backend/file/test/test-load-xml2.c b/src/backend/file/test/test-load-xml2.c index 2c01a14c9c..2dca625891 100644 --- a/src/backend/file/test/test-load-xml2.c +++ b/src/backend/file/test/test-load-xml2.c @@ -57,7 +57,7 @@ test_load_file(const char *filename) ignore_lock = (strcmp(getenv("SRCDIR"), ".") != 0); gnc_session_begin(session, filename, ignore_lock, FALSE); - gnc_session_load_from_xml_file_v2(session, NULL); + gnc_session_load_from_xml_file_v2(session); book = gnc_session_get_book (session); diff --git a/src/backend/file/test/test-save-in-lang.c b/src/backend/file/test/test-save-in-lang.c index 11afde1f39..64f5047301 100644 --- a/src/backend/file/test/test-save-in-lang.c +++ b/src/backend/file/test/test-save-in-lang.c @@ -85,7 +85,7 @@ test_file(const char *filename) return g_strdup_printf("gnc_session_begin errorid %d", err); } - gnc_session_load(session); + gnc_session_load(session, NULL); err = gnc_session_pop_error (session); if(err) { @@ -109,7 +109,7 @@ test_file(const char *filename) possible_envs[i]); } - gnc_session_save(new_session); + gnc_session_save(new_session, NULL); cmd = g_strdup_printf(diff_command, filename, new_file); diff --git a/src/backend/postgres/PostgresBackend.c b/src/backend/postgres/PostgresBackend.c index 4bfe62d448..9c789d5d8e 100644 --- a/src/backend/postgres/PostgresBackend.c +++ b/src/backend/postgres/PostgresBackend.c @@ -2108,6 +2108,8 @@ pgend_session_begin (Backend *backend, be->be.sync_all = pgendSyncSingleFile; be->be.sync_group = NULL; be->be.sync_price = pgendSyncPriceDBSingleFile; + be->be.export = NULL; + be->be.percentage = NULL; be->be.events_pending = NULL; be->be.process_events = NULL; PWARN ("mode=single-file is final beta -- \n" @@ -2133,6 +2135,8 @@ pgend_session_begin (Backend *backend, be->be.sync_all = pgendSync; be->be.sync_group = NULL; be->be.sync_price = pgendSyncPriceDB; + be->be.export = NULL; + be->be.percentage = NULL; be->be.events_pending = NULL; be->be.process_events = NULL; PWARN ("mode=single-update is final beta -- \n" @@ -2158,6 +2162,8 @@ pgend_session_begin (Backend *backend, be->be.sync_all = pgendSync; be->be.sync_group = NULL; be->be.sync_price = pgendSyncPriceDB; + be->be.export = NULL; + be->be.percentage = NULL; be->be.events_pending = NULL; be->be.process_events = NULL; @@ -2188,6 +2194,8 @@ pgend_session_begin (Backend *backend, be->be.sync_all = pgendSync; be->be.sync_group = NULL; be->be.sync_price = pgendSyncPriceDB; + be->be.export = NULL; + be->be.percentage = NULL; be->be.events_pending = pgendEventsPending; be->be.process_events = pgendProcessEvents; @@ -2239,6 +2247,8 @@ pgendDisable (PGBackend *be) be->snr.sync_all = be->be.sync_all; be->snr.sync_group = be->be.sync_group; be->snr.sync_price = be->be.sync_price; + be->snr.export = be->be.export; + be->snr.percentage = be->be.percentage; be->snr.events_pending = be->be.events_pending; be->snr.process_events = be->be.process_events; @@ -2260,6 +2270,8 @@ pgendDisable (PGBackend *be) be->be.sync_all = NULL; be->be.sync_group = NULL; be->be.sync_price = NULL; + be->be.export = NULL; + be->be.percentage = NULL; be->be.events_pending = NULL; be->be.process_events = NULL; } @@ -2296,6 +2308,8 @@ pgendEnable (PGBackend *be) be->be.sync_all = be->snr.sync_all; be->be.sync_group = be->snr.sync_group; be->be.sync_price = be->snr.sync_price; + be->be.export = be->snr.export; + be->be.percentage = be->snr.percentage; be->be.events_pending = be->snr.events_pending; be->be.process_events = be->snr.process_events; } diff --git a/src/backend/rpc/RpcBackend.c b/src/backend/rpc/RpcBackend.c index 04340f4e17..00e65081ba 100644 --- a/src/backend/rpc/RpcBackend.c +++ b/src/backend/rpc/RpcBackend.c @@ -104,6 +104,8 @@ static void rpcendEnable (RPCBackend *be) be->be.price_lookup = be->snr.price_lookup; be->be.sync_all = be->snr.sync_all; be->be.sync_price = be->snr.sync_price; + be->be.export = be->snr.export; + be->be.percentage = be->snr.percentage; } static void rpcendDisable (RPCBackend *be) @@ -127,6 +129,8 @@ static void rpcendDisable (RPCBackend *be) be->snr.price_lookup = be->be.price_lookup; be->snr.sync_all = be->be.sync_all; be->snr.sync_price = be->be.sync_price; + be->snr.export = be->be.export; + be->snr.percentage = be->be.percentage; /* And turn off future calls */ be->be.account_begin_edit = NULL; @@ -140,6 +144,8 @@ static void rpcendDisable (RPCBackend *be) be->be.price_lookup = NULL; be->be.sync_all = NULL; be->be.sync_price = NULL; + be->be.export = NULL; + be->be.percentage = NULL; } static void myClose (void *arg) @@ -977,6 +983,8 @@ rpcend_session_begin (Backend *backend, be->be.price_lookup = rpcend_price_lookup; be->be.sync_all = rpcend_sync_all; be->be.sync_price = rpcend_sync_price; + be->be.export = NULL; + be->be.percentage = NULL; be->be.events_pending = rpcend_events_pending; be->be.process_events = rpcend_process_events; diff --git a/src/engine/Backend.c b/src/engine/Backend.c index 261274d373..d91aa91308 100644 --- a/src/engine/Backend.c +++ b/src/engine/Backend.c @@ -121,6 +121,8 @@ xaccInitBackend(Backend *be) be->sync_all = NULL; be->sync_group = NULL; be->sync_price = NULL; + be->export = NULL; + be->percentage = NULL; be->events_pending = NULL; be->process_events = NULL; diff --git a/src/engine/Backend.h b/src/engine/Backend.h index 8c8a9bbbb2..9ae8f5d7f9 100644 --- a/src/engine/Backend.h +++ b/src/engine/Backend.h @@ -95,4 +95,6 @@ typedef enum { typedef struct backend_s Backend; +typedef void (*GNCBePercentageFunc) (const char *message, int percent); + #endif /* XACC_BACKEND_H */ diff --git a/src/engine/BackendP.h b/src/engine/BackendP.h index 977a4c5189..651e8ecec3 100644 --- a/src/engine/BackendP.h +++ b/src/engine/BackendP.h @@ -245,6 +245,10 @@ struct backend_s void (*sync_group) (Backend *, GNCBook *); void (*sync_price) (Backend *, GNCBook *); + void (*export) (Backend *, GNCBook *); + + GNCBePercentageFunc percentage; + gint64 (*counter) (Backend *, const char *counter_name); gboolean (*events_pending) (Backend *be); diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am index 939ba856da..938a8d6e95 100644 --- a/src/engine/Makefile.am +++ b/src/engine/Makefile.am @@ -35,6 +35,7 @@ libgncmod_engine_la_SOURCES = \ gnc-numeric.c \ gnc-pricedb.c \ gnc-session.c \ + gnc-session-scm.c \ gncmod-engine.c \ guid.c \ gncObject.c \ @@ -73,6 +74,7 @@ gncinclude_HEADERS = \ gnc-numeric.h \ gnc-pricedb.h \ gnc-session.h \ + gnc-session-scm.h \ guid.h \ gncObject.h \ kvp_frame.h \ diff --git a/src/engine/engine-utilities.scm b/src/engine/engine-utilities.scm index ead0ede8c9..e05724a551 100644 --- a/src/engine/engine-utilities.scm +++ b/src/engine/engine-utilities.scm @@ -32,7 +32,7 @@ (gnc:session-begin session url ignore-lock? create-if-needed?) - (gnc:session-load session) + (gnc:session-load session #f) session))) (or result (begin (gnc:session-destroy session) #f)))) diff --git a/src/engine/gnc-book.c b/src/engine/gnc-book.c index 8e56ae2395..8adb79daa7 100644 --- a/src/engine/gnc-book.c +++ b/src/engine/gnc-book.c @@ -269,6 +269,13 @@ gnc_book_set_backend (GNCBook *book, Backend *be) book->backend = be; } +gpointer gnc_book_get_backend (GNCBook *book) +{ + if (!book) return NULL; + return (gpointer)book->backend; +} + + void gnc_book_set_pricedb(GNCBook *book, GNCPriceDB *db) { diff --git a/src/engine/gnc-book.h b/src/engine/gnc-book.h index 52f5caa74c..df22822e54 100644 --- a/src/engine/gnc-book.h +++ b/src/engine/gnc-book.h @@ -73,6 +73,8 @@ AccountGroup * gnc_book_get_template_group( GNCBook *book ); void gnc_book_set_data (GNCBook *book, const char *key, gpointer data); gpointer gnc_book_get_data (GNCBook *book, const char *key); +gpointer gnc_book_get_backend (GNCBook *book); + /* * The gnc_book_not_saved() subroutine will return TRUE if any * data in the book hasn't been saved to long-term storage. diff --git a/src/engine/gnc-session-scm.c b/src/engine/gnc-session-scm.c new file mode 100644 index 0000000000..9459e49c51 --- /dev/null +++ b/src/engine/gnc-session-scm.c @@ -0,0 +1,104 @@ +/********************************************************************\ + * gnc-sesssion.c -- session access (connection to backend) * + * Scheme specific code. * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * +\********************************************************************/ + +/* + * FILE: + * gnc-session-scm.c + * + * FUNCTION: + * Encapsulate a connection to a GnuCash backend. + * + * HISTORY: + * Created by David Hampton, September 2002 + * Copyright (c) 2002 Linas Vepstas + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "BackendP.h" +#include "TransLog.h" +#include "gnc-engine-util.h" +#include "DateUtils.h" +#include "gnc-book-p.h" +#include "gnc-engine.h" +#include "gnc-engine-util.h" +#include "gnc-module.h" +#include "gnc-session-p.h" +#include "gnc-session-scm.h" + +//static short module = MOD_IO; + +static SCM gnc_session_scm_gui_cb = SCM_BOOL_F; + +static void +gnc_session_scm_gui_cb_helper (const char *message, int percent) +{ + if (gnc_session_scm_gui_cb != SCM_BOOL_F) { + SCM string = gh_str02scm(message); + SCM scm_percent = gh_long2scm(percent); + gh_call2 (gnc_session_scm_gui_cb, string, scm_percent); + } +} + +void +gnc_session_scm_load (GNCSession *session) +{ + gnc_session_load (session, gnc_session_scm_gui_cb_helper); +} + +void +gnc_session_scm_save (GNCSession *session) +{ + gnc_session_save (session, gnc_session_scm_gui_cb_helper); +} + +gboolean +gnc_session_scm_export (GNCSession *tmp_session, GNCSession *real_session) +{ + return gnc_session_export(tmp_session, real_session, + gnc_session_scm_gui_cb_helper); +} + +/* + * Set the callback that will be used for any calls to the session + * load/save functions from the scheme side of the code. + */ +void +gnc_session_scm_set_callback (SCM percentage_cb) +{ + if (gnc_session_scm_gui_cb != SCM_BOOL_F) + scm_unprotect_object(gnc_session_scm_gui_cb); + + gnc_session_scm_gui_cb = percentage_cb; + if (gnc_session_scm_gui_cb != SCM_BOOL_F) + scm_protect_object(gnc_session_scm_gui_cb); +} + diff --git a/src/engine/gnc-session-scm.h b/src/engine/gnc-session-scm.h new file mode 100644 index 0000000000..940e131f67 --- /dev/null +++ b/src/engine/gnc-session-scm.h @@ -0,0 +1,50 @@ +/********************************************************************\ + * gnc-session-scm.h -- session access (connection to backend) * + * Scheme specific code. * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * + * * +\********************************************************************/ + +/* + * FILE: + * gnc-session-scm.h + * + * FUNCTION: + * Encapsulates a connection to a GnuCash backend. That is, it + * manages the connection to a persistant data store; whereas + * the backend is the thing that performs the actual datastore + * access. + * + * HISTORY: + * Created by David Hampton, September 2002 + * Copyright (c) 2002 Linas Vepstas + */ + +#ifndef GNC_SESSION_SCM_H +#define GNC_SESSION_SCM_H + +#include + +void gnc_session_scm_load (GNCSession *session); +gboolean gnc_session_scm_export (GNCSession *tmp_session, + GNCSession *real_session); +void gnc_session_scm_save (GNCSession *session); +void gnc_session_scm_set_callback (SCM percentage_cb); + +#endif /* GNC_SESSION_SCM_H */ diff --git a/src/engine/gnc-session.c b/src/engine/gnc-session.c index 3ce3a16f29..889d544df4 100644 --- a/src/engine/gnc-session.c +++ b/src/engine/gnc-session.c @@ -415,7 +415,8 @@ gnc_session_begin (GNCSession *session, const char * book_id, /* ====================================================================== */ void -gnc_session_load (GNCSession *session) +gnc_session_load (GNCSession *session, + GNCPercentageFunc percentage_func) { GNCBook *newbook; BookList *oldbooks, *node; @@ -448,6 +449,7 @@ gnc_session_load (GNCSession *session) * generic, backend-independent operation. */ be = session->backend; + gnc_book_set_backend(newbook, be); /* Starting the session should result in a bunch of accounts * and currencies being downloaded, but probably no transactions; @@ -456,6 +458,7 @@ gnc_session_load (GNCSession *session) if (be) { xaccLogDisable(); + be->percentage = percentage_func; if (be->book_load) { @@ -471,8 +474,6 @@ gnc_session_load (GNCSession *session) gnc_session_push_error(session, xaccBackendGetError(be), NULL); } - gnc_book_set_backend (newbook, be); - /* we just got done loading, it can't possibly be dirty !! */ gnc_book_mark_saved (newbook); @@ -566,7 +567,8 @@ save_error_handler(Backend *be, GNCSession *session) } void -gnc_session_save (GNCSession *session) +gnc_session_save (GNCSession *session, + GNCPercentageFunc percentage_func) { GList *node; Backend *be; @@ -596,6 +598,7 @@ gnc_session_save (GNCSession *session) /* if invoked as SaveAs(), then backend not yet set */ gnc_book_set_backend (abook, be); + be->percentage = percentage_func; if (be->sync_all) { @@ -636,6 +639,42 @@ gnc_session_save (GNCSession *session) /* ====================================================================== */ +gboolean +gnc_session_export (GNCSession *tmp_session, + GNCSession *real_session, + GNCPercentageFunc percentage_func) +{ + GNCBook *book; + Backend *be; + + if ((!tmp_session) || (!real_session)) return FALSE; + + book = gnc_session_get_book (real_session); + ENTER ("tmp_session=%p real_session=%p book=%p book_id=%s", + tmp_session, real_session, book, + gnc_session_get_url(tmp_session) + ? gnc_session_get_url(tmp_session) : "(null)"); + + /* There must be a backend or else. (It should always be the file + * backend too.) + */ + be = tmp_session->backend; + if (!be) + return FALSE; + + be->percentage = percentage_func; + if (be->export) + { + + (be->export)(be, book); + if (save_error_handler(be, tmp_session)) return FALSE; + } + + return TRUE; +} + +/* ====================================================================== */ + void gnc_session_end (GNCSession *session) { diff --git a/src/engine/gnc-session.h b/src/engine/gnc-session.h index 4a0004804b..e3bb77f1ed 100644 --- a/src/engine/gnc-session.h +++ b/src/engine/gnc-session.h @@ -148,7 +148,12 @@ void gnc_session_begin (GNCSession *session, const char * book_id, * to make the book actually usable; it would not cause *all* of the * data to be loaded. */ -void gnc_session_load (GNCSession *session); +typedef void (*GNCPercentageFunc) (const char *message, int percent); +void gnc_session_load (GNCSession *session, + GNCPercentageFunc percentage_func); +gboolean gnc_session_export (GNCSession *tmp_session, + GNCSession *real_session, + GNCPercentageFunc percentage_func); /* The gnc_session_get_error() routine can be used to obtain the reason * for any failure. Calling this routine returns the current error. @@ -208,7 +213,8 @@ gboolean gnc_session_save_may_clobber_data (GNCSession *session); * been written out before this, and so this routines wouldn't * roll-back anything; it would just shut the connection. */ -void gnc_session_save (GNCSession *session); +void gnc_session_save (GNCSession *session, + GNCPercentageFunc percentage_func); void gnc_session_end (GNCSession *session); /* The gnc_session_events_pending() method will return TRUE if the backend diff --git a/src/engine/gw-engine-spec.scm b/src/engine/gw-engine-spec.scm index ea34bd41bd..304b83e3da 100644 --- a/src/engine/gw-engine-spec.scm +++ b/src/engine/gw-engine-spec.scm @@ -28,6 +28,7 @@ "#include \n" "#include \n" "#include \n" + "#include \n" "#include \n" "#include \n" "#include \n" @@ -1362,7 +1363,7 @@ when no longer needed.") ws 'gnc:session-load ' - "gnc_session_load" + "gnc_session_scm_load" '(( session)) "Load the data associated with the given session.") @@ -1370,10 +1371,28 @@ when no longer needed.") ws 'gnc:session-save ' - "gnc_session_save" + "gnc_session_scm_save" '(( session)) "Save the data in the session.") +(gw:wrap-function + ws + 'gnc:session-export + ' + "gnc_session_scm_export" + '(( tmp_session) ( real_session)) + "Export the accounts in the session.") + +(gw:wrap-function + ws + 'gnc:session-set-callback + ' + "gnc_session_scm_set_callback" + '(( callback)) + "Setup a callback for the load/save functions to provide progress +reports. This function will be called with a string and an integer +argument between 0 and 100 (inclusive).") + (gw:wrap-function ws 'gnc:session-end diff --git a/src/gnome-utils/Makefile.am b/src/gnome-utils/Makefile.am index a7a305dcc1..8591ab4067 100644 --- a/src/gnome-utils/Makefile.am +++ b/src/gnome-utils/Makefile.am @@ -6,6 +6,7 @@ AM_CFLAGS = \ -I${top_srcdir}/src/gnc-module \ -I${top_srcdir}/src/engine \ -I${top_srcdir}/src/network-utils \ + -I${top_srcdir}/src/app-file \ -I${top_srcdir}/src/app-utils \ -I${top_srcdir}/src \ ${GUILE_INCS} \ @@ -85,6 +86,7 @@ libgncmod_gnome_utils_la_LIBADD = \ ${top_builddir}/src/engine/libgncmod-engine.la \ ${top_builddir}/src/calculation/libgncmod-calculation.la \ ${top_builddir}/src/network-utils/libgncmod-network-utils.la \ + ${top_builddir}/src/app-file/libgncmod-app-file.la \ ${top_builddir}/src/app-utils/libgncmod-app-utils.la \ ${GUILE_LIBS} \ ${GUPPI_LIBS} \ diff --git a/src/gnome-utils/gnc-mdi-utils.c b/src/gnome-utils/gnc-mdi-utils.c index ffc7f616e0..030d60ea9f 100644 --- a/src/gnome-utils/gnc-mdi-utils.c +++ b/src/gnome-utils/gnc-mdi-utils.c @@ -28,6 +28,7 @@ #include "dialog-utils.h" #include "global-options.h" #include "gnc-component-manager.h" +#include "gnc-file.h" #include "gnc-html.h" #include "gnc-mdi-utils.h" #include "gnc-ui-util.h" @@ -96,6 +97,34 @@ gnc_mdi_set_toolbar_visibility (gboolean visible) gnc_toolbar_visible = visible; } +static void +gnc_mdi_file_percentage (const char *message, int percentage) +{ + GtkWidget *app; + GnomeAppBar *appbar; + + app = gnc_ui_get_toplevel(); + if (app == NULL) + return; + if (GNOME_APP(app)->statusbar == NULL) + return; + + appbar = GNOME_APPBAR(GNOME_APP(app)->statusbar); + + if (percentage < 0) { + gnome_appbar_refresh(appbar); + gnome_appbar_set_progress(appbar, 0.0); + } else { + if (message) + gnome_appbar_set_status(appbar, message); + gnome_appbar_set_progress(appbar, ((gfloat)percentage)/100); + } + + /* make sure new text is up */ + while (gtk_events_pending ()) + gtk_main_iteration (); +} + /** * gnc_mdi_widget_show * @@ -490,6 +519,8 @@ gnc_mdi_app_created_cb (GnomeMDI * mdi, GnomeApp * app, gpointer data) /* enable save and restore of menubar positions */ gnome_app_enable_layout_config (app, TRUE); + gnc_file_set_pct_handler (gnc_mdi_file_percentage); + /* flag the app as gnc mdi created */ gtk_object_set_data (GTK_OBJECT (app), "gnc_mdi", mainwin); diff --git a/src/gnome/gw-gnc-spec.scm b/src/gnome/gw-gnc-spec.scm index 226a3d98e4..ce20c053fb 100644 --- a/src/gnome/gw-gnc-spec.scm +++ b/src/gnome/gw-gnc-spec.scm @@ -115,6 +115,14 @@ '((( caller-owned const) string)) "Update the progress box on the splash screen dialog.") + (gw:wrap-function + ws + 'gnc:destroy-splash-screen + ' + "gnc_destroy_splash_screen" + '() + "Destroy the splash screen dialog.") + (gw:wrap-function ws 'gnc:gui-shutdown diff --git a/src/gnome/top-level.c b/src/gnome/top-level.c index ce846c8607..091151ca76 100644 --- a/src/gnome/top-level.c +++ b/src/gnome/top-level.c @@ -405,7 +405,6 @@ gnc_gui_init (SCM command_line) /* initialize gnome MDI and set up application window defaults */ if (!gnc_mdi_get_current ()) gnc_main_window_new (); - gnc_destroy_splash_screen(); /* Run the ui startup hooks. */ { diff --git a/src/gnome/window-main.c b/src/gnome/window-main.c index 8ba5ad39c5..1912bc51e7 100644 --- a/src/gnome/window-main.c +++ b/src/gnome/window-main.c @@ -55,7 +55,6 @@ #include "gnc-menu-extensions.h" #include "gnc-ui.h" #include "guile-util.h" -#include "io-gncxml-v2.h" #include "mainwindow-account-tree.h" #include "option-util.h" #include "top-level.h" @@ -173,7 +172,7 @@ gnc_main_window_app_created_cb(GnomeMDI * mdi, GnomeApp * app, } /* add the statusbar */ - statusbar = gnome_appbar_new(FALSE, TRUE, GNOME_PREFERENCES_USER); + statusbar = gnome_appbar_new(TRUE, TRUE, GNOME_PREFERENCES_USER); gnome_app_set_statusbar(app, statusbar); /* set up extensions menu and hints */ @@ -519,71 +518,8 @@ gnc_main_window_file_save_as_cb(GtkWidget * widget, gpointer data) static void gnc_main_window_file_export_cb(GtkWidget * widget, gpointer data) { - const char *filename; - struct stat statbuf; - gboolean ok; - FILE *file; - int rc; - - filename = gnc_file_dialog (_("Export"), NULL, NULL); - if (!filename) - return; - - rc = stat (filename, &statbuf); - - /* Check for an error that isn't a non-existent file. */ - if (rc != 0 && errno != ENOENT) - { - const char *format = _("You cannot save to that filename.\n\n%s"); - - gnc_error_dialog_parented (GTK_WINDOW (gtk_widget_get_toplevel (widget)), - format, strerror(errno)); - return; - } - - /* Check for a file that isn't a regular file. */ - if (rc == 0 && !S_ISREG (statbuf.st_mode)) - { - const char *message = _("You cannot save to that file."); - - gnc_error_dialog_parented (GTK_WINDOW (gtk_widget_get_toplevel (widget)), - message); - return; - } - - if (rc == 0) - { - const char *format = _("The file \n %s\n already exists.\n" - "Are you sure you want to overwrite it?"); - if (!gnc_verify_dialog_parented (gtk_widget_get_toplevel (widget), - FALSE, format, filename)) - return; - } - - file = fopen (filename, "w"); - if (!file) - { - const char *format = _("You cannot save to that file.\n\n%s"); - - gnc_error_dialog_parented (GTK_WINDOW (gtk_widget_get_toplevel (widget)), - format, strerror(errno)); - return; - } - - ok = gnc_book_write_accounts_to_xml_filehandle_v2 (gnc_get_current_book (), - file); - - if (fclose (file) != 0) - ok = FALSE; - - if (!ok) - { - const char *format = _("There was an error saving the file.\n\n%s"); - - gnc_error_dialog_parented (GTK_WINDOW (gtk_widget_get_toplevel (widget)), - format, strerror(errno)); - return; - } + gnc_file_export_file(NULL); + gnc_refresh_main_window_info (); } static void diff --git a/src/import-export/qif-io-core/test/test-import-phase-1.scm b/src/import-export/qif-io-core/test/test-import-phase-1.scm index 4c6f0268fb..fc7c068e88 100644 --- a/src/import-export/qif-io-core/test/test-import-phase-1.scm +++ b/src/import-export/qif-io-core/test/test-import-phase-1.scm @@ -63,7 +63,7 @@ (simple-format #t "using book name='~A'\n" name) (gnc:book-set-group book group) (gnc:session-begin session name #t #t) - (gnc:session-save book) + (gnc:session-save book #f) (gnc:session-end book))))) 0) diff --git a/src/scm/main.scm b/src/scm/main.scm index 70618178c8..8946d06bfa 100644 --- a/src/scm/main.scm +++ b/src/scm/main.scm @@ -394,7 +394,7 @@ string and 'directories' must be a list of strings." (bootstrap (resolve-module '(gnucash main)))) (define (load-module name vers optional?) - (let ((str (string-append "Loading modules... " name))) + (let ((str (string-append (_ "Loading modules... ") name))) (gnc:update-splash-screen str) (if optional? (gnc:module-load-optional name vers) @@ -404,7 +404,6 @@ string and 'directories' must be a list of strings." ;; right now we have to statically load all these at startup time. ;; Hopefully we can gradually make them autoloading. - (gnc:update-splash-screen "Loading modules...") (load-module "gnucash/engine" 0 #f) (load-module "gnucash/app-file" 0 #f) @@ -432,7 +431,7 @@ string and 'directories' must be a list of strings." ;; +jsled - 2002.07.08 (load-from-path "fin.scm") - (gnc:update-splash-screen "Loading tip-of-the-day...") + (gnc:update-splash-screen (_ "Loading tip-of-the-day...")) (gnc:initialize-tip-of-the-day) (gnc:use-guile-module-here! '(gnucash price-quotes)) @@ -456,7 +455,7 @@ string and 'directories' must be a list of strings." (gnc:ui-hierarchy-druid))))) ;; Load the system configs - (gnc:update-splash-screen "Loading configs...") + (gnc:update-splash-screen (_ "Loading configs...")) (if (not (gnc:load-system-config-if-needed)) (gnc:shutdown 1)) @@ -520,9 +519,11 @@ string and 'directories' must be a list of strings." (define (gnc:load-account-file) (let ((file (gnc:account-file-to-load))) - (if file - (and (not (gnc:file-open-file file)) - (gnc:hook-run-danglers gnc:*book-opened-hook* #f)) + (if file + (begin + (gnc:update-splash-screen (_ "Loading data...")) + (and (not (gnc:file-open-file file)) + (gnc:hook-run-danglers gnc:*book-opened-hook* #f))) (gnc:hook-run-danglers gnc:*book-opened-hook* #f)))) (define (gnc:main) @@ -570,7 +571,9 @@ string and 'directories' must be a list of strings." (gnc:option-value (gnc:lookup-global-option "__new_user" "first_startup"))) (gnc:new-user-dialog) - (gnc:load-account-file)) + (begin + (gnc:load-account-file) + (gnc:destroy-splash-screen))) (gnc:start-ui-event-loop) (gnc:hook-remove-dangler gnc:*ui-shutdown-hook* gnc:gui-finish)) diff --git a/src/scm/price-quotes.scm b/src/scm/price-quotes.scm index 230aa845f4..7339eb5c33 100644 --- a/src/scm/price-quotes.scm +++ b/src/scm/price-quotes.scm @@ -709,7 +709,7 @@ Run 'update-finance-quote' as root to install them.") "\n"))) (gnc:session-get-book session))))) (if (not quote-ok?) (gnc:msg "book-add-quotes failed")) - (and session (gnc:session-save session)) + (and session (gnc:session-save session #f)) (if (not (eq? 'no-err (gw:enum--val->sym (gnc:session-get-error session) #f)))