Add a new per-page callback to tell the page to finish any pending

activities.  The page may return FALSE to abort whatever the caller's
normal function.  Add helper routines to iterate over all pages in a
window, or all pages in all windows.  Call these new functions before
Quit, Save, Close, and closing a window.  The register page now
implements this hook and uses it to save/discard any pending
transaction.  Closes 334090.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@13615 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
David Hampton 2006-03-13 04:37:58 +00:00
parent 18b1188dbb
commit b486969db6
7 changed files with 183 additions and 4 deletions

View File

@ -1,5 +1,17 @@
2006-03-12 David Hampton <hampton@employees.org>
* src/gnome-utils/gnc-main-window.[ch]:
* src/gnome-utils/gnc-plugin-page.[ch]:
* src/gnome/gnc-plugin-basic-commands.c:
* src/gnome/gnc-plugin-page-register.c: Add a new per-page
callback to tell the page to finish any pending activities. The
page may return FALSE to abort whatever the caller's normal
function. Add helper routines to iterate over all pages in a
window, or all pages in all windows. Call these new functions
before Quit, Save, Close, and closing a window. The register page
now implements this hook and uses it to save/discard any pending
transaction. Closes 334090.
* src/gnome-utils/glade/commodity.glade: Tweak a couple of
tooltips. Try and make it clear that the commodity mnemonic field
must exactly match that used by the quote source.

View File

@ -810,6 +810,40 @@ gnc_main_window_save_all_windows(GKeyFile *keyfile)
g_list_foreach(active_windows, (GFunc)gnc_main_window_save_window, &data);
}
gboolean
gnc_main_window_finish_pending (GncMainWindow *window)
{
GncMainWindowPrivate *priv;
GList *item;
g_return_val_if_fail(GNC_IS_MAIN_WINDOW(window), TRUE);
priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
for (item = priv->installed_pages; item; item = g_list_next(item)) {
if (!gnc_plugin_page_finish_pending(item->data)) {
return FALSE;
}
}
return TRUE;
}
gboolean
gnc_main_window_all_finish_pending (void)
{
const GList *windows, *item;
windows = gnc_gobject_tracking_get_list(GNC_MAIN_WINDOW_NAME);
for (item = windows; item; item = g_list_next(item)) {
if (!gnc_main_window_finish_pending(item->data)) {
return FALSE;
}
}
return TRUE;
}
/** See if the page already exists. For each open window, look
* through the list of pages installed in that window and see if the
* specified page is there.
@ -971,6 +1005,11 @@ gnc_main_window_delete_event (GtkWidget *window,
"application. Are you sure that this is "
"what you want to do?");
if (!gnc_main_window_finish_pending(GNC_MAIN_WINDOW(window))) {
/* Don't close the window. */
return TRUE;
}
if (g_list_length(active_windows) > 1)
return FALSE;
@ -1551,7 +1590,7 @@ gnc_main_window_get_type (void)
};
gnc_main_window_type = g_type_register_static (GTK_TYPE_WINDOW,
"GncMainWindow",
GNC_MAIN_WINDOW_NAME,
&our_info, 0);
g_type_add_interface_static (gnc_main_window_type,
GNC_TYPE_WINDOW,
@ -2771,13 +2810,15 @@ static void
gnc_main_window_cmd_file_close (GtkAction *action, GncMainWindow *window)
{
GncMainWindowPrivate *priv;
GncPluginPage *page;
g_return_if_fail(GNC_IS_MAIN_WINDOW(window));
priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
if (priv->current_page != NULL) {
gnc_main_window_close_page (priv->current_page);
}
page = priv->current_page;
if (!gnc_plugin_page_finish_pending(page))
return;
gnc_main_window_close_page(page);
}
static gboolean
@ -2800,6 +2841,9 @@ gnc_main_window_cmd_file_quit (GtkAction *action, GncMainWindow *window)
return;
}
if (!gnc_main_window_all_finish_pending())
return;
session = gnc_get_current_session();
if (qof_book_not_saved(qof_session_get_book(session))) {
if (gnc_main_window_prompt_for_save(GTK_WIDGET(window))) {

View File

@ -49,6 +49,8 @@ G_BEGIN_DECLS
#define GNC_IS_MAIN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_MAIN_WINDOW))
#define GNC_MAIN_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_MAIN_WINDOW, GncMainWindowClass))
#define GNC_MAIN_WINDOW_NAME "GncMainWindow"
/* typedefs & structures */
/** The instance data structure for a main window object. */
@ -313,6 +315,31 @@ void
gnc_gtk_action_group_set_translation_domain (GtkActionGroup *action_group,
const gchar *domain);
/** Tell a window to finish any outstanding activities. This function
* will call gnc_plugin_page_finish_pending for each installed page.
* If any page returns a failure indication, then the function stops
* walking pages and immediately returns a failure.
*
* @param window Whe window whose pages should be checked.
*
* @return FALSE if any page could not or would not comply, which
* should cancel the pending operation. TRUE otherwise */
gboolean gnc_main_window_finish_pending (GncMainWindow *window);
/** Tell all pages in all windows to finish any outstanding
* activities. This function will call
* gnc_plugin_page_finish_pending for each installed page. If any
* page returns a failure indication, then the function stops walking
* pages and immediately returns a failure.
*
* @param window Whe window whose pages should be checked.
*
* @return FALSE if any page could not or would not comply, which
* should cancel the pending operation. TRUE otherwise */
gboolean gnc_main_window_all_finish_pending (void);
G_END_DECLS
#endif /* __GNC_MAIN_WINDOW_H */

View File

@ -929,5 +929,18 @@ gnc_plugin_page_create_action_group (GncPluginPage *page, const gchar *group_nam
return group;
}
gboolean
gnc_plugin_page_finish_pending (GncPluginPage *page)
{
if (!page)
return TRUE;
if (!GNC_IS_PLUGIN_PAGE(page))
return TRUE;
if (!GNC_PLUGIN_PAGE_GET_CLASS(page)->finish_pending)
return TRUE;
return (GNC_PLUGIN_PAGE_GET_CLASS(page)->finish_pending)(page);
}
/** @} */
/** @} */

View File

@ -175,6 +175,17 @@ typedef struct {
* @param hide Whether the widgets should be shown or
* hidden. */
void (* update_edit_menu_actions) (GncPluginPage *plugin_page, gboolean hide);
/** This function vector is called to finish any outstanding
* activities. It will be called for such things as closing a
* page, saving the data file, etc.
*
* @param page The page in a main window.
*
* @return FALSE if the page could not or would not comply,
* which should cancel the pending operation. TRUE
* otherwise */
gboolean (* finish_pending) (GncPluginPage *plugin_page);
} GncPluginPageClass;
@ -477,6 +488,13 @@ void gnc_plugin_page_removed (GncPluginPage *plugin_page);
void gnc_plugin_page_selected (GncPluginPage *plugin_page);
void gnc_plugin_page_unselected (GncPluginPage *plugin_page);
/** Tell a page to finish any outstanding activities.
*
* @param page A page.
*
* @return FALSE if the page could not or would not comply, which
* should cancel the pending operation. TRUE otherwise */
gboolean gnc_plugin_page_finish_pending (GncPluginPage *plugin_page);
G_END_DECLS

View File

@ -50,6 +50,7 @@
#include "gnc-engine.h"
#include "gnc-file.h"
#include "gnc-gui-query.h"
#include "gnc-main-window.h"
#include "gnc-ui.h"
#include "gnc-window.h"
#include "gnc-session.h"
@ -316,6 +317,9 @@ gnc_main_window_cmd_file_save (GtkAction *action, GncMainWindowActionData *data)
{
g_return_if_fail (data != NULL);
if (!gnc_main_window_all_finish_pending())
return;
gnc_window_set_progressbar_window (GNC_WINDOW(data->window));
gnc_file_save ();
gnc_window_set_progressbar_window (NULL);
@ -327,6 +331,9 @@ gnc_main_window_cmd_file_save_as (GtkAction *action, GncMainWindowActionData *da
{
g_return_if_fail (data != NULL);
if (!gnc_main_window_all_finish_pending())
return;
gnc_window_set_progressbar_window (GNC_WINDOW(data->window));
gnc_file_save_as ();
gnc_window_set_progressbar_window (NULL);

View File

@ -95,6 +95,7 @@ static void gnc_plugin_page_register_window_changed (GncPluginPage *plugin_page,
static void gnc_plugin_page_register_save_page (GncPluginPage *plugin_page, GKeyFile *file, const gchar *group);
static GncPluginPage *gnc_plugin_page_register_recreate_page (GtkWidget *window, GKeyFile *file, const gchar *group);
static void gnc_plugin_page_register_update_edit_menu (GncPluginPage *page, gboolean hide);
static gboolean gnc_plugin_page_register_finish_pending (GncPluginPage *page);
static gchar *gnc_plugin_page_register_get_tab_name (GncPluginPage *plugin_page);
@ -518,6 +519,7 @@ gnc_plugin_page_register_class_init (GncPluginPageRegisterClass *klass)
gnc_plugin_class->save_page = gnc_plugin_page_register_save_page;
gnc_plugin_class->recreate_page = gnc_plugin_page_register_recreate_page;
gnc_plugin_class->update_edit_menu_actions = gnc_plugin_page_register_update_edit_menu;
gnc_plugin_class->finish_pending = gnc_plugin_page_register_finish_pending;
g_type_class_add_private(klass, sizeof(GncPluginPageRegisterPrivate));
@ -1052,6 +1054,62 @@ gnc_plugin_page_register_update_edit_menu (GncPluginPage *page, gboolean hide)
}
static gboolean
gnc_plugin_page_register_finish_pending (GncPluginPage *page)
{
GncPluginPageRegisterPrivate *priv;
GncPluginPageRegister *reg_page;
SplitRegister *reg;
GtkWidget *dialog, *window;
const gchar *name;
gint response;
reg_page = GNC_PLUGIN_PAGE_REGISTER(page);
priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE(reg_page);
reg = gnc_ledger_display_get_split_register(priv->ledger);
if (!reg)
return TRUE;
if (!reg || !gnc_split_register_changed(reg))
return TRUE;
name = gnc_plugin_page_register_get_tab_name(page);
window = gnc_plugin_page_get_window(page);
dialog = gtk_message_dialog_new(GTK_WINDOW(window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING,
GTK_BUTTONS_NONE,
"Save changes to %s?", name);
gtk_message_dialog_format_secondary_text
(GTK_MESSAGE_DIALOG(dialog),
"This register has pending changes. Would you like to save "
"these changes, discard the changes, or cancel the operation?");
gnc_gtk_dialog_add_button(dialog, _("_Discard Transaction"),
GTK_STOCK_DELETE, GTK_RESPONSE_REJECT);
gtk_dialog_add_button(GTK_DIALOG(dialog),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
gnc_gtk_dialog_add_button(dialog, _("_Save Transaction"),
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT);
response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
switch (response) {
case GTK_RESPONSE_ACCEPT:
gnc_split_register_save(reg, TRUE);
return TRUE;
case GTK_RESPONSE_REJECT:
gnc_split_register_cancel_cursor_trans_changes(reg);
gnc_split_register_save (reg, TRUE);
return TRUE;
default:
return FALSE;
}
}
static gchar *
gnc_plugin_page_register_get_tab_name (GncPluginPage *plugin_page)
{