From f665251bcf9820840d406d096358034178e1ab40 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 2 Nov 2000 03:56:41 +0000 Subject: Make "Get Mail" even more functional on IMAP (scans all folders), and do a first cut at folder tree highlighting (for IMAP/news only). * mail-ops.c (do_fetch_mail): For imap (sigh, we *still* shouldn't be hardcoding that), rescan the store's folder tree, rescan each changed folder for new messages, and update the shell folder tree. (do_scan_subfolders): Update for component-factory.c changes, and set folder display names and highlights appropriately when building the storage. * component-factory.c (add_storage): Make this static (was mail_add_new_storage). Use camel_service_get_name for the name rather than url->host. (Among other things, this lets you use a single machine as both an IMAP server and a news server.) (mail_lookup_storage): Hash storages based on their CamelStore rather than the URL. (factory_destroy): Disconnect each of the CamelStores in the storages_hash. * subscribe-dialog.c (cleanup_subscribe_folder): * mail-vfolder.c (vfolder_refresh): Pass "highlighted" flag to evolution_storage_new_folder svn path=/trunk/; revision=6342 --- mail/ChangeLog | 26 +++++++++ mail/component-factory.c | 133 +++++++++++++++++++++++------------------------ mail/mail-ops.c | 125 ++++++++++++++++++++++++++++++++------------ mail/mail-ops.h | 2 +- mail/mail-vfolder.c | 4 +- mail/mail.h | 3 +- mail/subscribe-dialog.c | 5 +- 7 files changed, 190 insertions(+), 108 deletions(-) diff --git a/mail/ChangeLog b/mail/ChangeLog index 874cd6ddf4..c1beb752d4 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,29 @@ +2000-11-01 Dan Winship + + Make "Get Mail" even more functional on IMAP (scans all folders), + and do a first cut at folder tree highlighting (for IMAP/news + only). + + * mail-ops.c (do_fetch_mail): For imap (sigh, we *still* shouldn't + be hardcoding that), rescan the store's folder tree, rescan each + changed folder for new messages, and update the shell folder tree. + (do_scan_subfolders): Update for component-factory.c changes, and + set folder display names and highlights appropriately when + building the storage. + + * component-factory.c (add_storage): Make this static (was + mail_add_new_storage). Use camel_service_get_name for the name + rather than url->host. (Among other things, this lets you use a + single machine as both an IMAP server and a news server.) + (mail_lookup_storage): Hash storages based on their CamelStore + rather than the URL. + (factory_destroy): Disconnect each of the CamelStores in the + storages_hash. + + * subscribe-dialog.c (cleanup_subscribe_folder): + * mail-vfolder.c (vfolder_refresh): Pass "highlighted" flag to + evolution_storage_new_folder + 2000-11-01 Jeffrey Stedfast * mail-ops.c (mail_op_report_status): Don't call the default diff --git a/mail/component-factory.c b/mail/component-factory.c index c1b09fed5e..dbff4b8c5c 100644 --- a/mail/component-factory.c +++ b/mail/component-factory.c @@ -151,12 +151,11 @@ owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data) } static void -hash_foreach (gpointer key, - gpointer value, - gpointer data) +free_storage (gpointer service, gpointer storage, gpointer data) { - g_free (key); - gtk_object_unref (GTK_OBJECT (value)); + camel_service_disconnect (service, TRUE, NULL); + camel_object_unref (service); + gtk_object_unref (storage); } static void @@ -173,7 +172,7 @@ factory_destroy (BonoboEmbeddable *embeddable, g_warning ("Serious ref counting error"); factory = NULL; - g_hash_table_foreach (storages_hash, hash_foreach, NULL); + g_hash_table_foreach (storages_hash, free_storage, NULL); g_hash_table_destroy (storages_hash); storages_hash = NULL; @@ -223,7 +222,7 @@ component_factory_init (void) factory = bonobo_generic_factory_new (COMPONENT_FACTORY_ID, factory_fn, NULL); summary_factory = bonobo_generic_factory_new (SUMMARY_FACTORY_ID, summary_fn, NULL); - storages_hash = g_hash_table_new (g_str_hash, g_str_equal); + storages_hash = g_hash_table_new (NULL, NULL); if (factory == NULL) { e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, @@ -251,7 +250,37 @@ create_vfolder_storage (EvolutionShellComponent *shell_component) vfolder_create_storage(shell_component); } -void +static void +add_storage (const char *uri, CamelService *store, + Evolution_Shell corba_shell, CamelException *ex) +{ + EvolutionStorage *storage; + EvolutionStorageResult res; + char *name; + + name = camel_service_get_name (store, TRUE); + storage = evolution_storage_new (name); + g_free (name); + + res = evolution_storage_register_on_shell (storage, corba_shell); + + switch (res) { + case EVOLUTION_STORAGE_OK: + g_hash_table_insert (storages_hash, store, storage); + camel_object_ref (CAMEL_OBJECT (store)); + mail_do_scan_subfolders (CAMEL_STORE (store), storage); + /* falllll */ + case EVOLUTION_STORAGE_ERROR_ALREADYREGISTERED: + case EVOLUTION_STORAGE_ERROR_EXISTS: + return; + default: + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, + _("Cannot register storage with shell")); + break; + } +} + +void mail_load_storages (Evolution_Shell corba_shell, GSList *sources) { CamelException ex; @@ -266,91 +295,57 @@ mail_load_storages (Evolution_Shell corba_shell, GSList *sources) */ for (iter = sources; iter; iter = iter->next) { - CamelService *temp; - CamelProvider *prov = NULL; + CamelService *store; + CamelProvider *prov; svc = (MailConfigService *) iter->data; if (svc->url == NULL || svc->url[0] == '\0') continue; - temp = camel_session_get_service (session, svc->url, - CAMEL_PROVIDER_STORE, &ex); - if (temp == NULL) { + store = camel_session_get_service (session, svc->url, + CAMEL_PROVIDER_STORE, &ex); + if (store == NULL) { /* FIXME: real error dialog */ - - g_warning ("couldn't get service %s: %s\n", - svc->url, camel_exception_get_description (&ex)); + g_warning ("couldn't get service %s: %s\n", svc->url, + camel_exception_get_description (&ex)); + camel_exception_clear (&ex); continue; } - prov = camel_service_get_provider (temp); + prov = camel_service_get_provider (store); - /* FIXME: this case is ambiguous for things like the mbox provider, - * which can really be a spool (/var/spool/mail/user) or a storage - * (~/mail/, eg). That issue can't be resolved on the provider - * level -- it's a per-URL problem. + /* FIXME: this case is ambiguous for things like the + * mbox provider, which can really be a spool + * (/var/spool/mail/user) or a storage (~/mail/, eg). + * That issue can't be resolved on the provider level + * -- it's a per-URL problem. */ - - if (prov->flags & CAMEL_PROVIDER_IS_STORAGE && prov->flags & CAMEL_PROVIDER_IS_REMOTE) { - mail_add_new_storage (svc->url, corba_shell, &ex); - + if (prov->flags & CAMEL_PROVIDER_IS_STORAGE && + prov->flags & CAMEL_PROVIDER_IS_REMOTE) { + add_storage (svc->url, store, corba_shell, &ex); if (camel_exception_is_set (&ex)) { /* FIXME: real error dialog */ g_warning ("Cannot load storage: %s", camel_exception_get_description (&ex)); + camel_exception_clear (&ex); } + camel_object_unref (CAMEL_OBJECT (store)); } - - camel_object_unref (CAMEL_OBJECT (temp)); } } -void -mail_add_new_storage (const char *uri, Evolution_Shell corba_shell, CamelException *ex) +EvolutionStorage* +mail_lookup_storage (CamelStore *store) { EvolutionStorage *storage; - EvolutionStorageResult res; - CamelURL *url; - - g_return_if_fail (uri && uri[0] != '\0'); - - url = camel_url_new (uri, ex); - if (url == NULL) - return; - - if (url->host == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Bad storage URL (no server): %s"), - uri); - return; - } - storage = evolution_storage_new (url->host); - - res = evolution_storage_register_on_shell (storage, corba_shell); - - switch (res) { - case EVOLUTION_STORAGE_OK: - g_hash_table_insert (storages_hash, g_strdup(url->host), storage); - mail_do_scan_subfolders (uri, storage); - /* falllll */ - case EVOLUTION_STORAGE_ERROR_ALREADYREGISTERED: - case EVOLUTION_STORAGE_ERROR_EXISTS: - return; - default: - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot register storage with shell")); - break; - } - - camel_url_free (url); -} - -EvolutionStorage* -mail_lookup_storage (CamelService *service) -{ - EvolutionStorage *storage = g_hash_table_lookup (storages_hash, service->url->host); + /* Because the storages_hash holds a reference to each store + * used as a key in it, none of them will ever be gc'ed, meaning + * any call to camel_session_get_{service,store} with the same + * URL will always return the same object. So this works. + */ + storage = g_hash_table_lookup (storages_hash, store); if (storage) gtk_object_ref (GTK_OBJECT (storage)); diff --git a/mail/mail-ops.c b/mail/mail-ops.c index fcc9a7e5ae..e5c9140a15 100644 --- a/mail/mail-ops.c +++ b/mail/mail-ops.c @@ -115,6 +115,51 @@ mail_op_report_status (FilterDriver *driver, enum filter_status_t status, const } } +static void +update_changed_folders (CamelStore *store, CamelFolderInfo *info, + EvolutionStorage *storage, const char *path, + CamelException *ex) +{ + CamelFolder *folder; + char *name, *display; + + name = g_strdup_printf ("%s/%s", path, info->name); + if (info->url) { + if (info->unread_message_count > 0) { + display = g_strdup_printf ("%s (%d)", info->name, + info->unread_message_count); + evolution_storage_update_folder (storage, name, + display, TRUE); + g_free (display); + } else { + evolution_storage_update_folder (storage, name, + info->name, FALSE); + } + + /* This is a bit of a hack... if the store is already + * caching the folder, then we update it. Otherwise + * we don't. + */ + folder = CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS (store))-> + lookup_folder (store, info->full_name); + if (folder) { + camel_folder_sync (folder, FALSE, ex); + if (!camel_exception_is_set (ex)) + camel_folder_refresh_info (folder, ex); + camel_object_unref (CAMEL_OBJECT (folder)); + } + } + if (!camel_exception_is_set (ex) && info->sibling) { + update_changed_folders (store, info->sibling, storage, + path, ex); + } + if (!camel_exception_is_set (ex) && info->child) { + update_changed_folders (store, info->child, storage, + name, ex); + } + g_free (name); +} + static void do_fetch_mail (gpointer in_data, gpointer op_data, CamelException *ex) { @@ -127,14 +172,29 @@ do_fetch_mail (gpointer in_data, gpointer op_data, CamelException *ex) /* FIXME: This shouldn't be checking for "imap" specifically. */ if (!strncmp (input->source_url, "imap:", 5)) { - folder = mail_tool_get_inbox (input->source_url, ex); - if (folder) { - camel_folder_sync (folder, FALSE, ex); - if (!camel_exception_is_set (ex)) - camel_folder_refresh_info (folder, ex); - camel_object_unref (CAMEL_OBJECT (folder)); + CamelStore *store; + CamelFolderInfo *info; + EvolutionStorage *storage; + + store = camel_session_get_store (session, input->source_url, ex); + if (!store) + return; + storage = mail_lookup_storage (store); + g_return_if_fail (storage != NULL); + + info = camel_store_get_folder_info (store, NULL, FALSE, + TRUE, TRUE, ex); + if (!info) { + camel_object_unref (CAMEL_OBJECT (store)); + gtk_object_unref (GTK_OBJECT (storage)); + return; } - + + update_changed_folders (store, info, storage, "", ex); + camel_store_free_folder_info (store, info); + camel_object_unref (CAMEL_OBJECT (store)); + gtk_object_unref (GTK_OBJECT (storage)); + data->empty = FALSE; return; } @@ -1168,7 +1228,7 @@ mail_do_flag_all_messages (CamelFolder *source, gboolean invert, typedef struct scan_subfolders_input_s { - gchar *source_uri; + CamelStore *store; EvolutionStorage *storage; } scan_subfolders_input_t; @@ -1178,6 +1238,7 @@ typedef struct scan_subfolders_folderinfo_s char *path; char *name; char *uri; + gboolean highlighted; } scan_subfolders_folderinfo_t; @@ -1191,13 +1252,14 @@ static gchar * describe_scan_subfolders (gpointer in_data, gboolean gerund) { scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data; + char *name; + name = camel_service_get_name (CAMEL_SERVICE (input->store), TRUE); if (gerund) - return g_strdup_printf (_("Scanning folders in \"%s\""), - input->source_uri); + return g_strdup_printf (_("Scanning folders in \"%s\""), name); else - return g_strdup_printf (_("Scan folders in \"%s\""), - input->source_uri); + return g_strdup_printf (_("Scan folders in \"%s\""), name); + g_free (name); } static void @@ -1207,10 +1269,10 @@ setup_scan_subfolders (gpointer in_data, gpointer op_data, scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data; scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data; + camel_object_ref (CAMEL_OBJECT (input->store)); gtk_object_ref (GTK_OBJECT (input->storage)); - data->new_folders = g_ptr_array_new (); - gtk_object_ref (GTK_OBJECT(input->storage)); + data->new_folders = g_ptr_array_new (); } static void @@ -1220,7 +1282,14 @@ add_folders (GPtrArray *folders, const char *prefix, CamelFolderInfo *fi) info = g_new (scan_subfolders_folderinfo_t, 1); info->path = g_strdup_printf ("%s/%s", prefix, fi->name); - info->name = g_strdup (fi->name); + if (fi->unread_message_count > 0) { + info->name = g_strdup_printf ("%s (%d)", fi->name, + fi->unread_message_count); + info->highlighted = TRUE; + } else { + info->name = g_strdup (fi->name); + info->highlighted = FALSE; + } info->uri = g_strdup (fi->url); g_ptr_array_add (folders, info); if (fi->child) @@ -1234,23 +1303,14 @@ do_scan_subfolders (gpointer in_data, gpointer op_data, CamelException *ex) { scan_subfolders_input_t *input = (scan_subfolders_input_t *) in_data; scan_subfolders_op_t *data = (scan_subfolders_op_t *) op_data; - CamelStore *store; CamelFolderInfo *tree; - store = camel_session_get_store (session, input->source_uri, ex); - if (!store) - return; - - tree = camel_store_get_folder_info (store, NULL, TRUE, TRUE, TRUE, ex); + tree = camel_store_get_folder_info (input->store, NULL, FALSE, + TRUE, TRUE, ex); if (tree) { add_folders (data->new_folders, "", tree); - camel_store_free_folder_info (store, tree); + camel_store_free_folder_info (input->store, tree); } - - /* FIXME: We intentionally lose a reference to the store here - * for the benefit of the IMAP provider. Undo this when the - * namespace situation is fixed. - */ } static void @@ -1267,7 +1327,8 @@ cleanup_scan_subfolders (gpointer in_data, gpointer op_data, evolution_storage_new_folder (input->storage, info->path, info->name, "mail", info->uri ? info->uri : "", - _("(No description)")); + _("(No description)"), + info->highlighted); g_free (info->uri); g_free (info->name); @@ -1277,7 +1338,7 @@ cleanup_scan_subfolders (gpointer in_data, gpointer op_data, g_ptr_array_free (data->new_folders, TRUE); gtk_object_unref (GTK_OBJECT (input->storage)); - g_free (input->source_uri); + camel_object_unref (CAMEL_OBJECT (input->store)); } static const mail_operation_spec op_scan_subfolders = { @@ -1289,15 +1350,15 @@ static const mail_operation_spec op_scan_subfolders = { }; void -mail_do_scan_subfolders (const gchar *source_uri, EvolutionStorage *storage) +mail_do_scan_subfolders (CamelStore *store, EvolutionStorage *storage) { scan_subfolders_input_t *input; - g_return_if_fail (source_uri != NULL); + g_return_if_fail (CAMEL_IS_STORE (store)); g_return_if_fail (EVOLUTION_IS_STORAGE (storage)); input = g_new (scan_subfolders_input_t, 1); - input->source_uri = g_strdup (source_uri); + input->store = store; input->storage = storage; mail_operation_queue (&op_scan_subfolders, input, TRUE); diff --git a/mail/mail-ops.h b/mail/mail-ops.h index e61f5f87ce..e136465cff 100644 --- a/mail/mail-ops.h +++ b/mail/mail-ops.h @@ -54,7 +54,7 @@ void mail_do_flag_messages (CamelFolder *source, GPtrArray *uids, guint32 mask, guint32 set); void mail_do_flag_all_messages (CamelFolder *source, gboolean invert, guint32 mask, guint32 set); -void mail_do_scan_subfolders (const gchar *source_uri, EvolutionStorage *storage); +void mail_do_scan_subfolders (CamelStore *store, EvolutionStorage *storage); void mail_do_attach_message (CamelFolder *folder, const char *uid, EMsgComposer *composer); void mail_do_forward_message (CamelMimeMessage *basis, CamelFolder *source, diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c index a0c3289806..5bdac810cc 100644 --- a/mail/mail-vfolder.c +++ b/mail/mail-vfolder.c @@ -91,7 +91,7 @@ vfolder_refresh(void) path = g_strdup_printf("/%s", info->name); evolution_storage_removed_folder(vfolder_storage, path); evolution_storage_new_folder(vfolder_storage, path, g_basename(path), - "mail", uri, info->name); + "mail", uri, info->name, FALSE); g_free(uri); g_free(path); } @@ -104,7 +104,7 @@ vfolder_refresh(void) uri = g_strdup_printf("vfolder:%s", info->name); path = g_strdup_printf("/%s", info->name); evolution_storage_new_folder(vfolder_storage, path, g_basename(path), - "mail", uri, info->name); + "mail", uri, info->name, FALSE); g_free(uri); g_free(path); } diff --git a/mail/mail.h b/mail/mail.h index 54d1c6b123..5623297dc2 100644 --- a/mail/mail.h +++ b/mail/mail.h @@ -115,9 +115,8 @@ GtkWidget *mail_view_create (CamelFolder *source, const char *uid, CamelMimeMess /* component factory for lack of a better place */ /*takes a GSList of MailConfigServices */ void mail_load_storages (Evolution_Shell corba_shell, GSList *sources); -void mail_add_new_storage (const char *uri, Evolution_Shell corba_shell, CamelException *ex); /* used in the subscribe dialog code */ -EvolutionStorage* mail_lookup_storage (CamelService *service); +EvolutionStorage *mail_lookup_storage (CamelStore *store); /* session */ void session_init (void); diff --git a/mail/subscribe-dialog.c b/mail/subscribe-dialog.c index 30327b0fef..e74ab4f1bd 100644 --- a/mail/subscribe-dialog.c +++ b/mail/subscribe-dialog.c @@ -319,7 +319,8 @@ cleanup_subscribe_folder (gpointer in_data, gpointer op_data, data->path, data->name, "mail", data->url, - _("(No description)") /* XXX */); + _("(No description)") /* XXX */, + FALSE); if (input->cb) input->cb (input->sc, !camel_exception_is_set(ex), input->cb_data); @@ -838,7 +839,7 @@ build_tree (SubscribeDialog *sc, CamelStore *store) gtk_object_unref (GTK_OBJECT (sc->storage)); sc->store = store; - sc->storage = mail_lookup_storage (CAMEL_SERVICE (sc->store)); + sc->storage = mail_lookup_storage (sc->store); sc->folder_info = camel_store_get_folder_info (sc->store, sc->search_top, TRUE, TRUE, FALSE, ex); if (camel_exception_is_set (ex)) { -- cgit v1.2.3