aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog14
-rw-r--r--camel/camel-folder.c143
-rw-r--r--camel/camel-folder.h12
-rw-r--r--camel/providers/mbox/camel-mbox-folder.c18
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 <danw@helixcode.com>
+
+ * 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 <fejj@helixcode.com>
* 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: