From 2d151f9fcf28b0f962736afb29bbaa0b2cfc163e Mon Sep 17 00:00:00 2001 From: Phil Longstaff Date: Mon, 27 Oct 2008 23:42:01 +0000 Subject: [PATCH] Add a callback to gnc-engine which will be called when a qof commit fails. Most engine objects catch the qof commit but then just log the problem to the trace log. Now, the engine objects will invoke this callback. gnc-main-window registers a callback and opens a dialog box to inform the user. This is necessary because with an sql backend, commits happen whenever an object is created or modified, not just synchronously when the user selects to save the file. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@17667 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/engine/Account.c | 1 + src/engine/SchedXaction.c | 1 + src/engine/Split.c | 8 +++++++- src/engine/Transaction.c | 1 + src/engine/gnc-budget.c | 1 + src/engine/gnc-commodity.c | 1 + src/engine/gnc-engine.c | 18 ++++++++++++++++++ src/engine/gnc-engine.h | 7 +++++++ src/engine/gnc-lot.c | 1 + src/engine/gnc-pricedb.c | 1 + src/gnome-utils/gnc-main-window.c | 21 +++++++++++++++++++++ 11 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/engine/Account.c b/src/engine/Account.c index 3207baca79..bb1e9b6ed4 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -1063,6 +1063,7 @@ static void on_done(QofInstance *inst) static void on_err (QofInstance *inst, QofBackendError errcode) { PERR("commit error: %d", errcode); + gnc_engine_signal_commit_error( errcode ); } static void acc_free (QofInstance *inst) diff --git a/src/engine/SchedXaction.c b/src/engine/SchedXaction.c index 8da9465321..441cd7203d 100644 --- a/src/engine/SchedXaction.c +++ b/src/engine/SchedXaction.c @@ -219,6 +219,7 @@ gnc_sx_begin_edit (SchedXaction *sx) static void commit_err (QofInstance *inst, QofBackendError errcode) { g_critical("Failed to commit: %d", errcode); + gnc_engine_signal_commit_error( errcode ); } static void commit_done(QofInstance *inst) diff --git a/src/engine/Split.c b/src/engine/Split.c index 64b6a16c86..1cf42655da 100644 --- a/src/engine/Split.c +++ b/src/engine/Split.c @@ -498,6 +498,12 @@ xaccSplitSetAccount (Split *s, Account *acc) xaccTransCommitEdit(trans); } +static void commit_err (QofInstance *inst, QofBackendError errcode) +{ + PERR("commit error: %d", errcode); + gnc_engine_signal_commit_error( errcode ); +} + /* An engine-private helper for completing xaccTransCommitEdit(). */ void xaccSplitCommitEdit(Split *s) @@ -551,7 +557,7 @@ xaccSplitCommitEdit(Split *s) original and new transactions, for the _next_ begin/commit cycle. */ s->orig_acc = s->acc; s->orig_parent = s->parent; - qof_commit_edit_part2(QOF_INSTANCE(s), NULL, NULL, + qof_commit_edit_part2(QOF_INSTANCE(s), commit_err, NULL, (void (*) (QofInstance *)) xaccFreeSplit); if (acc) { diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c index 83f57cdda9..20293fa418 100644 --- a/src/engine/Transaction.c +++ b/src/engine/Transaction.c @@ -940,6 +940,7 @@ static void trans_on_error(Transaction *trans, QofBackendError errcode) } xaccTransRollbackEdit(trans); + gnc_engine_signal_commit_error( errcode ); } static void trans_cleanup_commit(Transaction *trans) diff --git a/src/engine/gnc-budget.c b/src/engine/gnc-budget.c index 5a610e02c2..9af51bc5b7 100644 --- a/src/engine/gnc-budget.c +++ b/src/engine/gnc-budget.c @@ -232,6 +232,7 @@ gnc_budget_class_init(GncBudgetClass* klass) static void commit_err (QofInstance *inst, QofBackendError errcode) { PERR ("Failed to commit: %d", errcode); + gnc_engine_signal_commit_error( errcode ); } static void diff --git a/src/engine/gnc-commodity.c b/src/engine/gnc-commodity.c index 8f7819398c..8a192d585e 100644 --- a/src/engine/gnc-commodity.c +++ b/src/engine/gnc-commodity.c @@ -519,6 +519,7 @@ gnc_commodity_begin_edit (gnc_commodity *cm) static void commit_err (QofInstance *inst, QofBackendError errcode) { PERR ("Failed to commit: %d", errcode); + gnc_engine_signal_commit_error( errcode ); } static void noop (QofInstance *inst) {} diff --git a/src/engine/gnc-engine.c b/src/engine/gnc-engine.c index 0f0f53a84a..f80c58d37d 100644 --- a/src/engine/gnc-engine.c +++ b/src/engine/gnc-engine.c @@ -43,6 +43,10 @@ static GList * engine_init_hooks = NULL; static int engine_is_initialized = 0; + +EngineCommitErrorCallback g_error_cb; +gpointer g_error_cb_data; + // static QofLogModule log_module = GNC_MOD_ENGINE; /* GnuCash version functions */ @@ -165,3 +169,17 @@ void gnc_log_default(void) qof_log_set_level(GNC_MOD_TEST, QOF_LOG_DEBUG); } +void +gnc_engine_add_commit_error_callback( EngineCommitErrorCallback cb, gpointer data ) +{ + g_error_cb = cb; + g_error_cb_data = data; +} + +void +gnc_engine_signal_commit_error( QofBackendError errcode ) +{ + if( g_error_cb != NULL ) { + (*g_error_cb)( g_error_cb_data, errcode ); + } +} diff --git a/src/engine/gnc-engine.h b/src/engine/gnc-engine.h index b9627f244c..bc22b200c1 100644 --- a/src/engine/gnc-engine.h +++ b/src/engine/gnc-engine.h @@ -208,6 +208,7 @@ typedef GList AccountGUIDList; /** GList of GUIDs of a GNCBook */ typedef GList BookGUIDList; +typedef void (*EngineCommitErrorCallback)( gpointer data, QofBackendError errcode ); typedef gint (*SplitCallback)(Split *s, gpointer data); typedef gint (*TransactionCallback)(Transaction *t, void *data); @@ -244,5 +245,11 @@ void gnc_log_default(void); * it will be called during the evaluation of gnc_engine_init */ void gnc_engine_add_init_hook(gnc_engine_init_hook_t hook); +/** Set a callback function to be called in case an engine commit + * fails */ +void gnc_engine_add_commit_error_callback( EngineCommitErrorCallback cb, gpointer data ); + +void gnc_engine_signal_commit_error( QofBackendError errcode ); + #endif /** @} */ diff --git a/src/engine/gnc-lot.c b/src/engine/gnc-lot.c index a5ae770a7e..9e92264c1f 100644 --- a/src/engine/gnc-lot.c +++ b/src/engine/gnc-lot.c @@ -143,6 +143,7 @@ gnc_lot_begin_edit (GNCLot *lot) static void commit_err (QofInstance *inst, QofBackendError errcode) { PERR ("Failed to commit: %d", errcode); + gnc_engine_signal_commit_error( errcode ); } static void lot_free(QofInstance* inst) diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c index 45062dce61..dc0f9bc4c0 100644 --- a/src/engine/gnc-pricedb.c +++ b/src/engine/gnc-pricedb.c @@ -160,6 +160,7 @@ gnc_price_begin_edit (GNCPrice *p) static void commit_err (QofInstance *inst, QofBackendError errcode) { PERR ("Failed to commit: %d", errcode); + gnc_engine_signal_commit_error( errcode ); } static void noop (QofInstance *inst) {} diff --git a/src/gnome-utils/gnc-main-window.c b/src/gnome-utils/gnc-main-window.c index 028fe0762e..8ff55b6e35 100644 --- a/src/gnome-utils/gnc-main-window.c +++ b/src/gnome-utils/gnc-main-window.c @@ -122,6 +122,7 @@ static void gnc_main_window_page_reordered (GtkNotebook *notebook, GtkWidget *ch #endif static void gnc_main_window_plugin_added (GncPlugin *manager, GncPlugin *plugin, GncMainWindow *window); static void gnc_main_window_plugin_removed (GncPlugin *manager, GncPlugin *plugin, GncMainWindow *window); +static void gnc_main_window_engine_commit_error_callback( gpointer data, QofBackendError errcode ); /* Command callbacks */ #ifdef HAVE_GTK_2_10 @@ -2039,6 +2040,9 @@ gnc_main_window_new (void) active_windows = g_list_append (active_windows, window); gnc_main_window_update_title(window); gnc_main_window_update_all_menu_items(); + + gnc_engine_add_commit_error_callback( gnc_main_window_engine_commit_error_callback, window ); + return window; } @@ -2046,6 +2050,23 @@ gnc_main_window_new (void) * Utility Functions * ************************************************************/ +static void +gnc_main_window_engine_commit_error_callback( gpointer data, + QofBackendError errcode ) +{ + GncMainWindow* window = GNC_MAIN_WINDOW(data); + GtkWidget* dialog; + + dialog = gtk_message_dialog_new( GTK_WINDOW(window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Unable to save to database" ); + gtk_dialog_run(GTK_DIALOG (dialog)); + gtk_widget_destroy(dialog); + +} + /** Connect a GncPluginPage to the window. This function will insert * the page in to the window's notebook and its list of active pages. * It will also emit the "inserted" signal on the page, and the