aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog27
-rw-r--r--mail/mail-callbacks.c3
-rw-r--r--mail/subscribe-dialog.c119
3 files changed, 117 insertions, 32 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index e0d1e3d11b..7d330fe07e 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,30 @@
+2003-04-09 Not Zed <NotZed@Ximian.com>
+
+ ** See bug #40921
+
+ * subscribe-dialog.c (subscribe_dialog_finalise): add a finalise
+ funciton which actually free's resources.
+ (get_short_folderinfo_got): dont call activity callback implicitly
+ here, do it from the callers callback.
+ (subscribe_get_short_folderinfo): dont call activity callback
+ here.
+ (fe_got_children): check implicitly if we were cancelled. also
+ add back the node sort, and also call the activity callback from
+ here instead of breaking layers of abstraction as above.
+ (folder_etree_cancel_all): new method, force a cancel of all ops,
+ but dont free anything.
+ (store_data_free): dont unref the widget anymore, not needed.
+ call cancel all on the ftree if its still active.
+ (sc_close_pressed): destroy the subscribe dialogue as well as the
+ app, it doesn't seem to get destroyed otherwise.
+ (sc_activity_cb): do nothing if we have been cancelled.
+ (subscribe_dialog_destroy): trigger a cancel of all outstanding
+ ops. only free most data in the finalise method.
+ (subscribe_dialog_class_init): hook onto finalise.
+ (store_data_get_widget): dont ref the widget.
+
+ * mail-callbacks.c (manage_subscriptions): sink the dialog.
+
2003-04-09 Larry Ewing <lewing@ximian.com>
* mail-preferences.c (font_share_changed): set sensitivity of
diff --git a/mail/mail-callbacks.c b/mail/mail-callbacks.c
index c51a73c27e..331fc9cf26 100644
--- a/mail/mail-callbacks.c
+++ b/mail/mail-callbacks.c
@@ -3068,7 +3068,8 @@ manage_subscriptions (BonoboUIComponent *uih, void *user_data, const char *path)
g_object_weak_ref ((GObject *) SUBSCRIBE_DIALOG (subscribe_dialog)->app,
(GWeakNotify) subscribe_dialog_destroy, subscribe_dialog);
-
+ g_object_ref(subscribe_dialog);
+ gtk_object_sink((GtkObject *)subscribe_dialog);
subscribe_dialog_show (subscribe_dialog);
} else {
gdk_window_raise (SUBSCRIBE_DIALOG (subscribe_dialog)->app->window);
diff --git a/mail/subscribe-dialog.c b/mail/subscribe-dialog.c
index f4b203ad77..f975ee5825 100644
--- a/mail/subscribe-dialog.c
+++ b/mail/subscribe-dialog.c
@@ -22,6 +22,8 @@
*
*/
+/* This doens't do what it's supposed to do ...
+ I think etree changed so it just fills out the whole tree always anyway */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -242,6 +244,8 @@ get_short_folderinfo_get (struct _mail_msg *mm)
struct _get_short_folderinfo_msg *m = (struct _get_short_folderinfo_msg *) mm;
m->info = camel_store_get_folder_info (m->ftree->store, m->prefix, CAMEL_STORE_FOLDER_INFO_FAST, &mm->ex);
+
+ d(printf("%d: getted folderinfo '%s'\n", mm->seq, m->prefix));
}
static void
@@ -249,15 +253,13 @@ get_short_folderinfo_got (struct _mail_msg *mm)
{
struct _get_short_folderinfo_msg *m = (struct _get_short_folderinfo_msg *) mm;
- if (camel_exception_is_set (&mm->ex))
+ d(printf("%d: got folderinfo '%s'\n", mm->seq, m->prefix));
+
+ if (camel_exception_is_set (&mm->ex) && camel_exception_get_id(&mm->ex) != CAMEL_EXCEPTION_USER_CANCEL) {
g_warning ("Error getting folder info from store at %s: %s",
camel_service_get_url (CAMEL_SERVICE (m->ftree->store)),
camel_exception_get_description (&mm->ex));
-
- m->ftree->activity_level--;
- (m->ftree->activity_cb) (m->ftree->activity_level, m->ftree->activity_data);
-
- /* 'done' is probably guaranteed to fail, but... */
+ }
if (m->func)
m->func (m->ftree->store, m->prefix, m->info, m->user_data);
@@ -298,8 +300,7 @@ subscribe_get_short_folderinfo (FolderETree *ftree,
m->func = func;
m->user_data = user_data;
- ftree->activity_level++;
- (ftree->activity_cb) (ftree->activity_level, ftree->activity_data);
+ d(printf("%d: get folderinfo '%s'\n", m->msg.seq, m->prefix));
id = m->msg.seq;
e_thread_put (mail_thread_queued, (EMsg *)m);
@@ -694,7 +695,11 @@ fe_got_children (CamelStore *store, char *prefix, CamelFolderInfo *info, gpointe
ftree_op_data *closure = (ftree_op_data *) data;
if (!info) /* cancelled */
- return;
+ goto done;
+
+ /* also cancelled, but camel returned data, might leak */
+ if (closure->handle == -1)
+ goto done;
if (!prefix)
prefix = "";
@@ -717,17 +722,24 @@ fe_got_children (CamelStore *store, char *prefix, CamelFolderInfo *info, gpointe
fe_check_for_children (closure->ftree, child_path);
}
-#if 0
/* FIXME: this needs to be added back to sort the tree */
e_tree_memory_sort_node (E_TREE_MEMORY (closure->ftree),
closure->path,
fe_sort_folder,
NULL);
-#endif
+
if (closure->data)
closure->data->flags |= FTREE_NODE_GOT_CHILDREN;
g_hash_table_remove (closure->ftree->scan_ops, closure->path);
+
+done:
+ /* finish off the activity of this task */
+ /* hack, we know activity_data is an object */
+ closure->ftree->activity_level--;
+ (closure->ftree->activity_cb) (closure->ftree->activity_level, closure->ftree->activity_data);
+ g_object_unref(closure->ftree->activity_data);
+
g_free (closure);
}
@@ -762,8 +774,12 @@ fe_check_for_children (FolderETree *ftree, ETreePath path)
g_hash_table_insert (ftree->scan_ops, path, closure);
- /* FIXME. Tiny race possiblity I guess. */
+ /* hack, we know this is an object ... infact the subscribe dialog */
+ g_object_ref(ftree->activity_data);
+ ftree->activity_level++;
+ (ftree->activity_cb) (ftree->activity_level, ftree->activity_data);
+ /* FIXME. Tiny race possiblity I guess. */
closure->handle = subscribe_get_short_folderinfo (ftree, prefix, fe_got_children, closure);
}
@@ -830,8 +846,10 @@ fe_cancel_op_foreach (gpointer key, gpointer value, gpointer user_data)
/*FolderETree *ftree = (FolderETree *) user_data;*/
ftree_op_data *closure = (ftree_op_data *) value;
- if (closure->handle != -1)
+ if (closure->handle != -1) {
+ d(printf("%d: cancel get messageinfo\n", closure->handle));
mail_msg_cancel (closure->handle);
+ }
closure->handle = -1;
@@ -850,6 +868,8 @@ fe_finalise (GObject *obj)
{
FolderETree *ftree = (FolderETree *) (obj);
+ d(printf("fe finalise!?\n"));
+
fe_kill_current_tree (ftree);
g_hash_table_foreach_remove (ftree->subscribe_ops, fe_cancel_op_foreach, ftree);
@@ -1011,6 +1031,13 @@ folder_etree_path_toggle_subscription (FolderETree *ftree, ETreePath path)
return folder_etree_path_set_subscription (ftree, path, TRUE);
}
+static void
+folder_etree_cancel_all(FolderETree *ftree)
+{
+ g_hash_table_foreach_remove (ftree->scan_ops, fe_cancel_op_foreach, ftree);
+ g_hash_table_foreach_remove (ftree->subscribe_ops, fe_cancel_op_foreach, ftree);
+}
+
/* ** StoreData ************************************************************ */
typedef struct _StoreData StoreData;
@@ -1020,7 +1047,7 @@ typedef void (*StoreDataStoreFunc) (StoreData *, CamelStore *, gpointer);
struct _StoreData {
int refcount;
char *uri;
-
+
FolderETree *ftree;
CamelStore *store;
@@ -1039,21 +1066,22 @@ store_data_new (const char *uri)
sd = g_new0 (StoreData, 1);
sd->refcount = 1;
sd->uri = g_strdup (uri);
-
+
return sd;
}
static void
store_data_free (StoreData *sd)
{
+ d(printf("store data free?\n"));
+
if (sd->request_id)
mail_msg_cancel (sd->request_id);
-
- if (sd->widget)
- g_object_unref(sd->widget);
-
- if (sd->ftree)
+
+ if (sd->ftree) {
+ folder_etree_cancel_all(sd->ftree);
g_object_unref(sd->ftree);
+ }
if (sd->store)
camel_object_unref (sd->store);
@@ -1169,7 +1197,6 @@ store_data_get_widget (StoreData *sd,
g_object_unref(global_extras);
sd->widget = tree;
- g_object_ref(sd->widget);
return sd->widget;
}
@@ -1264,6 +1291,7 @@ struct _SubscribeDialogPrivate {
GtkWidget *progress;
GtkWidget *appbar;
+ int cancel; /* have we been cancelled? */
guint activity_timeout_id;
};
@@ -1283,6 +1311,8 @@ sc_close_pressed (GtkWidget *widget, gpointer user_data)
{
SubscribeDialog *sc = SUBSCRIBE_DIALOG (user_data);
+ /* order important here */
+ gtk_object_destroy (GTK_OBJECT (sc));
gtk_widget_destroy (GTK_WIDGET (sc->app));
}
@@ -1348,6 +1378,9 @@ sc_activity_cb (int level, SubscribeDialog *sc)
{
g_assert (pthread_self() == mail_gui_thread);
+ if (sc->priv->cancel)
+ return;
+
if (level) {
if (sc->priv->activity_timeout_id)
return;
@@ -1479,14 +1512,42 @@ populate_store_list (SubscribeDialog *sc)
}
static void
+subscribe_dialog_finalise (GObject *object)
+{
+ SubscribeDialog *sc;
+ GList *iter;
+
+ sc = SUBSCRIBE_DIALOG (object);
+
+ if (sc->priv->store_list) {
+ for (iter = sc->priv->store_list; iter; iter = iter->next) {
+ StoreData *data = iter->data;
+ store_data_unref (data);
+ }
+
+ g_list_free (sc->priv->store_list);
+ sc->priv->store_list = NULL;
+ }
+
+ g_free (sc->priv);
+ sc->priv = NULL;
+
+ ((GObjectClass *)subscribe_dialog_parent_class)->finalize (object);
+}
+
+static void
subscribe_dialog_destroy (GtkObject *object)
{
SubscribeDialog *sc;
GList *iter;
-
+
sc = SUBSCRIBE_DIALOG (object);
- if (sc->priv) {
+ d(printf("subscribe_dialog_destroy\n"));
+
+ if (!sc->priv->cancel) {
+ sc->priv->cancel = 1;
+
if (sc->priv->activity_timeout_id) {
g_source_remove (sc->priv->activity_timeout_id);
sc->priv->activity_timeout_id = 0;
@@ -1498,23 +1559,18 @@ subscribe_dialog_destroy (GtkObject *object)
if (store_data_mid_request (data))
store_data_cancel_get_store (data);
+
+ if (data->ftree)
+ folder_etree_cancel_all(data->ftree);
data->store_func = NULL;
-
- store_data_unref (data);
}
-
- g_list_free (sc->priv->store_list);
- sc->priv->store_list = NULL;
}
if (sc->priv->xml) {
g_object_unref(sc->priv->xml);
sc->priv->xml = NULL;
}
-
- g_free (sc->priv);
- sc->priv = NULL;
}
subscribe_dialog_parent_class->destroy (object);
@@ -1524,6 +1580,7 @@ static void
subscribe_dialog_class_init (GtkObjectClass *object_class)
{
object_class->destroy = subscribe_dialog_destroy;
+ ((GObjectClass *)object_class)->finalize = subscribe_dialog_finalise;
subscribe_dialog_parent_class = g_type_class_ref (PARENT_TYPE);
}