diff --git a/src/gnc-component-manager.c b/src/gnc-component-manager.c index 0e6e9557e9..f91b91b3ee 100644 --- a/src/gnc-component-manager.c +++ b/src/gnc-component-manager.c @@ -19,12 +19,16 @@ #include "config.h" +#include + #include "gnc-component-manager.h" #include "gnc-engine-util.h" /** Declarations ****************************************************/ +#define CM_DEBUG 0 + typedef struct { GNCIdType entity_type; @@ -72,6 +76,26 @@ static void gnc_gui_refresh_internal (void); /** Implementations *************************************************/ +#if CM_DEBUG +static void +dump_components (void) +{ + GList *node; + + fprintf (stderr, "Components:\n"); + + for (node = components; node; node = node->next) + { + ComponentInfo *ci = node->data; + + fprintf (stderr, " %s:\t%d\n", + ci->component_class, ci->component_id); + } + + fprintf (stderr, "\n"); +} +#endif + static gboolean destroy_helper (gpointer key, gpointer value, gpointer user_data) { @@ -296,6 +320,12 @@ gnc_register_gui_component (const char *component_class, /* update id for next registration */ next_component_id = component_id + 1; +#if CM_DEBUG + fprintf (stderr, "Register component %d in class %s\n", + component_id, component_class); + dump_components (); +#endif + return component_id; } @@ -370,6 +400,11 @@ gnc_unregister_gui_component (gint component_id) return; } +#if CM_DEBUG + fprintf (stderr, "Unregister component %d in class %s\n", + ci->component_id, ci->component_class); +#endif + gnc_gui_component_clear_watches (component_id); components = g_list_remove (components, ci); @@ -381,6 +416,10 @@ gnc_unregister_gui_component (gint component_id) ci->component_class = NULL; g_free (ci); + +#if CM_DEBUG + dump_components (); +#endif } void @@ -528,10 +567,7 @@ gnc_close_gui_component (gint component_id) } if (!ci->close_handler) - { - PERR ("no close handler"); return; - } ci->close_handler (ci->user_data); } @@ -586,16 +622,12 @@ gnc_find_gui_components (const char *component_class, return list; } -void -gnc_forall_gui_components (const char *component_class, - GNCComponentHandler handler, - gpointer iter_data) +static GList * +find_component_ids_by_class (const char *component_class) { + GList *list = NULL; GList *node; - if (!handler) - return; - for (node = components; node; node = node->next) { ComponentInfo *ci = node->data; @@ -604,6 +636,35 @@ gnc_forall_gui_components (const char *component_class, safe_strcmp (component_class, ci->component_class) != 0) continue; + list = g_list_prepend (list, GINT_TO_POINTER (ci->component_id)); + } + + return list; +} + +void +gnc_forall_gui_components (const char *component_class, + GNCComponentHandler handler, + gpointer iter_data) +{ + GList *list; + GList *node; + + if (!handler) + return; + + /* so components can be destroyed during the forall */ + list = find_component_ids_by_class (component_class); + + for (node = list; node; node = node->next) + { + ComponentInfo *ci = find_component (GPOINTER_TO_INT (node->data)); + + if (!ci) + continue; + handler (ci->component_class, ci->component_id, iter_data); } + + g_list_free (list); } diff --git a/src/gnc-component-manager.h b/src/gnc-component-manager.h index 3cb621ba50..76a6e24319 100644 --- a/src/gnc-component-manager.h +++ b/src/gnc-component-manager.h @@ -246,6 +246,9 @@ void gnc_close_gui_component_by_data (const char *component_class, * * Returns: GList of user_data of found components, or NULL if none found * The list should be freed with g_list_free(). + * + * Notes on finding: components should not be registered or unregistered + * by the find callback. */ GList * gnc_find_gui_components (const char *component_class, GNCComponentFindHandler find_handler, @@ -258,6 +261,9 @@ GList * gnc_find_gui_components (const char *component_class, * all classes are iterated over * handler: handler to invoke * iter_data: data passed to handler + * + * Notes on forall: components may be unregistered by the handler, + * but no components should be registered. */ void gnc_forall_gui_components (const char *component_class, GNCComponentHandler handler, diff --git a/src/gnome/dialog-transfer.c b/src/gnome/dialog-transfer.c index 4f582d9fd6..8323db1541 100644 --- a/src/gnome/dialog-transfer.c +++ b/src/gnome/dialog-transfer.c @@ -26,24 +26,27 @@ #include +#include "FileDialog.h" +#include "MultiLedger.h" +#include "Refresh.h" +#include "account-tree.h" #include "dialog-transfer.h" #include "dialog-utils.h" -#include "MultiLedger.h" -#include "FileDialog.h" -#include "Refresh.h" -#include "window-reconcile.h" -#include "query-user.h" -#include "account-tree.h" #include "glade-gnc-dialogs.h" -#include "gnc-amount-edit.h" -#include "gnc-dateedit.h" -#include "gnc-exp-parser.h" -#include "messages.h" -#include "gnc-ui.h" #include "global-options.h" +#include "gnc-amount-edit.h" +#include "gnc-component-manager.h" +#include "gnc-dateedit.h" #include "gnc-engine-util.h" +#include "gnc-exp-parser.h" +#include "gnc-ui.h" +#include "messages.h" +#include "query-user.h" +#include "window-reconcile.h" +#define DIALOG_TRANSFER_CM_CLASS "dialog-transfer" + typedef enum { XFER_DIALOG_FROM, @@ -54,8 +57,6 @@ typedef enum /* This static indicates the debugging module that this .o belongs to. */ static short module = MOD_GUI; -static GList *xfer_dialogs = NULL; - struct _xferDialog { GtkWidget * dialog; @@ -278,6 +279,7 @@ gnc_xfer_dialog_curr_acct_activate(XferDialog *xferData) (GNC_AMOUNT_EDIT(xferData->to_amount_edit))); gtk_entry_set_text(entry, ""); } + g_list_free(curr_accts_name_list); } @@ -853,7 +855,7 @@ gnc_xfer_dialog_ok_cb(GtkWidget * widget, gpointer data) gnc_refresh_main_window(); - gnome_dialog_close(GNOME_DIALOG(xferData->dialog)); + gnc_close_gui_component_by_data (DIALOG_TRANSFER_CM_CLASS, xferData); } @@ -862,7 +864,7 @@ gnc_xfer_dialog_cancel_cb(GtkWidget * widget, gpointer data) { XferDialog *xferData = data; - gnome_dialog_close(GNOME_DIALOG(xferData->dialog)); + gnc_close_gui_component_by_data (DIALOG_TRANSFER_CM_CLASS, xferData); } @@ -889,7 +891,7 @@ gnc_xfer_dialog_close_cb(GnomeDialog *dialog, gpointer data) xferData->curr_accts_list = NULL; } - xfer_dialogs = g_list_remove(xfer_dialogs, dialog); + gnc_unregister_gui_component_by_data (DIALOG_TRANSFER_CM_CLASS, xferData); g_free(xferData); @@ -1050,6 +1052,13 @@ gnc_xfer_dialog_create(GtkWidget * parent, XferDialog *xferData) } } +static void +close_handler (gpointer user_data) +{ + XferDialog *xferData = user_data; + + gnome_dialog_close (GNOME_DIALOG (xferData->dialog)); +} /********************************************************************\ * gnc_xfer_dialog * @@ -1060,17 +1069,18 @@ gnc_xfer_dialog_create(GtkWidget * parent, XferDialog *xferData) * Return: XferDialog structure * \********************************************************************/ XferDialog * -gnc_xfer_dialog(GtkWidget * parent, Account * initial) +gnc_xfer_dialog (GtkWidget * parent, Account * initial) { XferDialog *xferData; GNCAmountEdit *gae; GtkWidget *amount_entry; - xferData = g_new0(XferDialog, 1); + xferData = g_new0 (XferDialog, 1); gnc_xfer_dialog_create(parent, xferData); - xfer_dialogs = g_list_prepend(xfer_dialogs, xferData->dialog); + gnc_register_gui_component (DIALOG_TRANSFER_CM_CLASS, + NULL, close_handler, xferData); gae = GNC_AMOUNT_EDIT(xferData->amount_edit); amount_entry = gnc_amount_edit_gtk_entry (gae); @@ -1091,6 +1101,14 @@ gnc_xfer_dialog(GtkWidget * parent, Account * initial) } +static void +destroy_helper (const char *component_class, + gint component_id, + gpointer iter_data) +{ + gnc_close_gui_component (component_id); +} + /********************************************************************\ * gnc_ui_destroy_xfer_windows * * destroy all open transfer dialogs * @@ -1099,14 +1117,8 @@ gnc_xfer_dialog(GtkWidget * parent, Account * initial) * Return: none * \********************************************************************/ void -gnc_ui_destroy_xfer_windows(void) +gnc_ui_destroy_xfer_windows (void) { - GnomeDialog *dialog; - - while (xfer_dialogs != NULL) - { - dialog = GNOME_DIALOG(xfer_dialogs->data); - - gnome_dialog_close(dialog); - } + gnc_forall_gui_components (DIALOG_TRANSFER_CM_CLASS, + destroy_helper, NULL); }