From c4d87ba45ad016d5a6607df96ed27ba02910e2e6 Mon Sep 17 00:00:00 2001 From: 7 Date: Sat, 27 Oct 2001 06:00:34 +0000 Subject: Finished implementation. 2001-10-27 * providers/imap/camel-imap-store.c (rename_folder): Finished implementation. * providers/local/camel-local-folder.c (local_rename): Implement local rename of folder objects. 2001-10-26 * camel-vee-folder.c (camel_vee_folder_class_init): Hook into rename function. (vee_rename): Implement the veefolder rename function. (camel_vee_folder_class_init): (folder_changed_change): Kill a warning with a cast. * camel-vee-store.c (vee_rename_folder): Emit a folder_renamed event properly, also call parent to do some rename stuff. * camel-store.h: Added a CamelRenameInfo for the rename event. * camel-folder.c (camel_folder_rename): New function to rename a folder object. (camel_folder_class_init): Added a renamed event. (folder_rename): Default impl, set full_name, and set name assuming the dir separator is '/'. * camel-store.c (camel_store_class_init): Added folder_renamed event. (camel_store_rename_folder): Rename an active folder object if we have one, and update the folder table. (rename_folder): Make a default implementation that handles updating the folder tree. svn path=/trunk/; revision=14204 --- camel/camel-store.c | 100 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 18 deletions(-) (limited to 'camel/camel-store.c') diff --git a/camel/camel-store.c b/camel/camel-store.c index 85f618be5b..f4b15a045c 100644 --- a/camel/camel-store.c +++ b/camel/camel-store.c @@ -104,6 +104,7 @@ camel_store_class_init (CamelStoreClass *camel_store_class) camel_object_class_declare_event(camel_object_class, "folder_created", NULL); camel_object_class_declare_event(camel_object_class, "folder_deleted", NULL); + camel_object_class_declare_event(camel_object_class, "folder_renamed", NULL); camel_object_class_declare_event(camel_object_class, "folder_subscribed", NULL); camel_object_class_declare_event(camel_object_class, "folder_unsubscribed", NULL); } @@ -267,7 +268,6 @@ camel_store_get_folder (CamelStore *store, const char *folder_name, guint32 flag return folder; } - static CamelFolderInfo * create_folder (CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex) @@ -365,15 +365,32 @@ camel_store_delete_folder (CamelStore *store, const char *folder_name, CamelExce CAMEL_STORE_UNLOCK(store, folder_lock); } - static void -rename_folder (CamelStore *store, const char *old_name, - const char *new_name, CamelException *ex) +rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex) { w(g_warning ("CamelStore::rename_folder not implemented for `%s'", camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store)))); } +struct _get_info { + CamelStore *store; + GPtrArray *folders; + const char *old; + const char *new; +}; + +static void +get_subfolders(char *key, CamelFolder *folder, struct _get_info *info) +{ + /* If this is a subfolder of the one to be renamed, we need to get it, AND lock it */ + if (strncmp(folder->full_name, info->old, strlen(info->old)) == 0) { + d(printf("Found subfolder of '%s' == '%s'\n", info->old, folder->full_name)); + camel_object_ref((CamelObject *)folder); + g_ptr_array_add(info->folders, folder); + CAMEL_FOLDER_LOCK(folder, lock); + } +} + /** * camel_store_rename_folder: * @store: a CamelStore @@ -387,32 +404,79 @@ void camel_store_rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex) { char *key; - CamelFolder *folder; + CamelFolder *folder, *oldfolder; + struct _get_info info = { store, NULL, old_name, new_name }; + int i; + + printf("store rename folder '%s' '%s'\n", old_name, new_name); if (strcmp(old_name, new_name) == 0) return; + info.folders = g_ptr_array_new(); + CAMEL_STORE_LOCK(store, folder_lock); + + /* If the folder is open (or any subfolders of the open folder) + We need to rename them atomically with renaming the actual folder path */ + if (store->folders) { + CAMEL_STORE_LOCK(store, cache_lock); + /* Get all subfolders that are about to have their name changed */ + g_hash_table_foreach(store->folders, (GHFunc)get_subfolders, &info); + CAMEL_STORE_UNLOCK(store, cache_lock); + } + + /* Now try the real rename (will emit renamed event) */ CS_CLASS (store)->rename_folder (store, old_name, new_name, ex); - - /* remove the old name from the cache if it is there */ - CAMEL_STORE_LOCK(store, cache_lock); - if (g_hash_table_lookup_extended(store->folders, old_name, (void **)&key, (void **)&folder)) { - g_hash_table_remove(store->folders, key); - g_free(key); - - camel_object_ref (CAMEL_OBJECT (folder)); + + /* If it worked, update all open folders/unlock them */ + if (!camel_exception_is_set(ex)) { + guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE; + CamelRenameInfo reninfo; + + /* Emit changed signal */ + if (store->flags & CAMEL_STORE_SUBSCRIPTIONS) + flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; + reninfo.old_base = (char *)old_name; + reninfo.new = ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->get_folder_info(store, new_name, flags, ex); + if (info.new != NULL) { + camel_object_trigger_event(CAMEL_OBJECT(store), "folder_renamed", &reninfo); + ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->free_folder_info(store, reninfo.new); + } + + CAMEL_STORE_LOCK(store, cache_lock); + for (i=0;ilen;i++) { + char *new; + + folder = info.folders->pdata[i]; + + new = g_strdup_printf("%s%s", new_name, folder->full_name+strlen(old_name)); + + if (g_hash_table_lookup_extended(store->folders, folder->full_name, (void **)&key, (void **)&oldfolder)) { + g_hash_table_remove(store->folders, key); + g_free(key); + g_hash_table_insert(store->folders, new, oldfolder); + } + + camel_folder_rename(folder, new); + + CAMEL_FOLDER_UNLOCK(folder, lock); + camel_object_unref((CamelObject *)folder); + } CAMEL_STORE_UNLOCK(store, cache_lock); - - if (store->vtrash) - camel_vee_folder_remove_folder (CAMEL_VEE_FOLDER (store->vtrash), folder); - camel_object_unref (CAMEL_OBJECT (folder)); } else { - CAMEL_STORE_UNLOCK(store, cache_lock); + /* Failed, just unlock our folders for re-use */ + for (i=0;ilen;i++) { + folder = info.folders->pdata[i]; + CAMEL_FOLDER_UNLOCK(folder, lock); + camel_object_unref((CamelObject *)folder); + } } CAMEL_STORE_UNLOCK(store, folder_lock); + + g_ptr_array_free(info.folders, TRUE); } -- cgit