From 03b3618408f037589882655e4b97e7b75787b756 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 3 Jul 2000 01:17:49 +0000 Subject: New functions to freeze and thaw a folder (to prevent message/folder * camel-folder.c (camel_folder_freeze, camel_folder_thaw): New functions to freeze and thaw a folder (to prevent message/folder changed signals in the middle of a long series of operations). (camel_folder_class_init): Change signals to GTK_RUN_FIRST. (message_changed, folder_changed): Add default implementations that stop the emission and record info for later if the folder is frozen. * providers/mbox/camel-mbox-folder.c (mbox_sync): leftover fixes from the close->sync change: don't destroy the ibex, summary, and search when syncing. svn path=/trunk/; revision=3863 --- camel/ChangeLog | 14 +++ camel/camel-folder.c | 143 ++++++++++++++++++++++++++++++- camel/camel-folder.h | 12 ++- camel/providers/mbox/camel-mbox-folder.c | 18 ++-- 4 files changed, 171 insertions(+), 16 deletions(-) diff --git a/camel/ChangeLog b/camel/ChangeLog index d5e0aee1a3..4123a4d397 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,17 @@ +2000-07-02 Dan Winship + + * camel-folder.c (camel_folder_freeze, camel_folder_thaw): New + functions to freeze and thaw a folder (to prevent message/folder + changed signals in the middle of a long series of operations). + (camel_folder_class_init): Change signals to GTK_RUN_FIRST. + (message_changed, folder_changed): Add default implementations + that stop the emission and record info for later if the folder is + frozen. + + * providers/mbox/camel-mbox-folder.c (mbox_sync): leftover fixes + from the close->sync change: don't destroy the ibex, summary, and + search when syncing. + 2000-07-02 Jeffrey Stedfast * camel-mime-utils.c (uudecode_step): A rather complex uudecoder diff --git a/camel/camel-folder.c b/camel/camel-folder.c index 095b0e8f36..aa5991b48b 100644 --- a/camel/camel-folder.c +++ b/camel/camel-folder.c @@ -132,6 +132,15 @@ static void move_message_to (CamelFolder *source, CamelFolder *dest, CamelException *ex); +static void freeze (CamelFolder *folder); +static void thaw (CamelFolder *folder); + +static void folder_changed (CamelFolder *folder, + int type); +static void message_changed (CamelFolder *folder, + const char *uid); + + static void camel_folder_class_init (CamelFolderClass *camel_folder_class) { @@ -171,13 +180,17 @@ camel_folder_class_init (CamelFolderClass *camel_folder_class) camel_folder_class->get_message_info = get_message_info; camel_folder_class->copy_message_to = copy_message_to; camel_folder_class->move_message_to = move_message_to; + camel_folder_class->freeze = freeze; + camel_folder_class->thaw = thaw; + camel_folder_class->folder_changed = folder_changed; + camel_folder_class->message_changed = message_changed; /* virtual method overload */ gtk_object_class->finalize = finalize; signals[FOLDER_CHANGED] = gtk_signal_new ("folder_changed", - GTK_RUN_LAST, + GTK_RUN_FIRST, gtk_object_class->type, GTK_SIGNAL_OFFSET (CamelFolderClass, folder_changed), @@ -186,7 +199,7 @@ camel_folder_class_init (CamelFolderClass *camel_folder_class) signals[MESSAGE_CHANGED] = gtk_signal_new ("message_changed", - GTK_RUN_LAST, + GTK_RUN_FIRST, gtk_object_class->type, GTK_SIGNAL_OFFSET (CamelFolderClass, message_changed), @@ -228,6 +241,7 @@ static void finalize (GtkObject *object) { CamelFolder *camel_folder = CAMEL_FOLDER (object); + GList *m; g_free (camel_folder->name); g_free (camel_folder->full_name); @@ -237,6 +251,10 @@ finalize (GtkObject *object) if (camel_folder->parent_folder) gtk_object_unref (GTK_OBJECT (camel_folder->parent_folder)); + for (m = camel_folder->messages_changed; m; m = m->next) + g_free (m->data); + g_list_free (camel_folder->messages_changed); + GTK_OBJECT_CLASS (parent_class)->finalize (object); } @@ -301,6 +319,10 @@ init (CamelFolder *folder, CamelStore *parent_store, folder->name = g_strdup (name); folder->full_name = full_name; + + folder->frozen = 0; + folder->folder_changed = FALSE; + folder->messages_changed = NULL; } @@ -1115,3 +1137,120 @@ camel_folder_move_message_to (CamelFolder *source, const char *uid, } else return move_message_to (source, uid, dest, ex); } + + +static void +freeze (CamelFolder *folder) +{ + folder->frozen++; +} + +/** + * camel_folder_freeze: + * @folder: a folder + * + * Freezes the folder so that a series of operation can be performed + * without "message_changed" and "folder_changed" signals being emitted. + * When the folder is later thawed with camel_folder_thaw(), the + * suppressed signals will be emitted. + **/ +void +camel_folder_freeze (CamelFolder *folder) +{ + g_return_if_fail (CAMEL_IS_FOLDER (folder)); + + CF_CLASS (folder)->freeze (folder); +} + + +static void +thaw (CamelFolder *folder) +{ + GList *messages, *m; + + folder->frozen--; + if (folder->frozen != 0) + return; + + /* Clear messages_changed now in case the signal handler ends + * up calling freeze and thaw itself. + */ + messages = folder->messages_changed; + folder->messages_changed = NULL; + + /* If the folder changed, emit that and ignore the individual + * messages (since the UIDs may no longer be valid). + */ + if (folder->folder_changed) { + folder->folder_changed = FALSE; + + gtk_signal_emit (GTK_OBJECT (folder), + signals[FOLDER_CHANGED], 0); + } else if (folder->messages_changed) { + /* FIXME: would be nice to not emit more than once for + * a given message + */ + for (m = messages; m; m = m->next) { + gtk_signal_emit_by_name (GTK_OBJECT (folder), + "message_changed", m->data); + g_free (m->data); + } + g_list_free (messages); + return; + } + + if (messages) { + for (m = messages; m; m = m->next) + g_free (m->data); + g_list_free (messages); + } +} + +/** + * camel_folder_thaw: + * @folder: a folder + * + * Thaws the folder and emits any pending folder_changed or + * message_changed signals. + **/ +void +camel_folder_thaw (CamelFolder *folder) +{ + g_return_if_fail (CAMEL_IS_FOLDER (folder)); + g_return_if_fail (folder->frozen != 0); + + CF_CLASS (folder)->thaw (folder); +} + + +/* Default signal implementations, which block emission when we're + * frozen. + */ +static void +folder_changed (CamelFolder *folder, int type) +{ + if (folder->frozen) { + gtk_signal_emit_stop (GTK_OBJECT (folder), + signals[FOLDER_CHANGED]); + folder->folder_changed = TRUE; + } +} + +static void +message_changed (CamelFolder *folder, const char *uid) +{ + if (folder->frozen) { + gtk_signal_emit_stop (GTK_OBJECT (folder), + signals[MESSAGE_CHANGED]); + + /* Only record the UID if it will be useful later. */ + if (!folder->folder_changed && + gtk_signal_handler_pending (GTK_OBJECT (folder), + signals[MESSAGE_CHANGED], + FALSE)) { + folder->messages_changed = + g_list_prepend (folder->messages_changed, + g_strdup (uid)); + } + } +} diff --git a/camel/camel-folder.h b/camel/camel-folder.h index 5ae8be25cc..d49a7f7650 100644 --- a/camel/camel-folder.h +++ b/camel/camel-folder.h @@ -44,7 +44,11 @@ extern "C" { struct _CamelFolder { CamelObject parent_object; - + + int frozen; + gboolean folder_changed; + GList *messages_changed; + gchar *name; gchar *full_name; gchar *separator; @@ -171,6 +175,9 @@ typedef struct { const char *uid, CamelFolder *destination, CamelException *ex); + + void (*freeze) (CamelFolder *folder); + void (*thaw) (CamelFolder *folder); } CamelFolderClass; @@ -294,6 +301,9 @@ void camel_folder_move_message_to (CamelFolder *source, CamelFolder *dest, CamelException *ex); +void camel_folder_freeze (CamelFolder *folder); +void camel_folder_thaw (CamelFolder *folder); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/camel/providers/mbox/camel-mbox-folder.c b/camel/providers/mbox/camel-mbox-folder.c index 09b718a1de..6efa93a42c 100644 --- a/camel/providers/mbox/camel-mbox-folder.c +++ b/camel/providers/mbox/camel-mbox-folder.c @@ -245,19 +245,10 @@ mbox_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) camel_mbox_summary_sync (mbox_folder->summary, FALSE, ex); /* save index */ - if (mbox_folder->index) { - ibex_close(mbox_folder->index); - mbox_folder->index = NULL; - } - if (mbox_folder->summary) { + if (mbox_folder->index) + ibex_save(mbox_folder->index); + if (mbox_folder->summary) camel_folder_summary_save (CAMEL_FOLDER_SUMMARY (mbox_folder->summary)); - gtk_object_unref (GTK_OBJECT (mbox_folder->summary)); - mbox_folder->summary = NULL; - } - if (mbox_folder->search) { - gtk_object_unref (GTK_OBJECT (mbox_folder->search)); - mbox_folder->search = NULL; - } } static void @@ -341,7 +332,8 @@ mbox_append_message (CamelFolder *folder, CamelMimeMessage *message, CamelExcept gtk_object_unref (GTK_OBJECT (output_stream)); /* force a summary update - will only update from the new position, if it can */ - camel_mbox_summary_update (mbox_folder->summary, seek); + if (camel_mbox_summary_update (mbox_folder->summary, seek) == 0) + gtk_signal_emit_by_name (GTK_OBJECT (folder), "folder_changed", 0); return; fail: -- cgit v1.2.3