New function, set the complete list of folders on a vfolder, all at once.
author4 <NotZed@Ximian.com>
Sat, 15 Sep 2001 08:12:58 +0000 (08:12 +0000)
committerMichael Zucci <zucchi@src.gnome.org>
Sat, 15 Sep 2001 08:12:58 +0000 (08:12 +0000)
2001-09-14    <NotZed@Ximian.com>

* camel-vee-folder.c (camel_vee_folder_set_folders): New function,
set the complete list of folders on a vfolder, all at once.
(camel_vee_folder_set_expression): If we set the query to be the
same thing, dont do anything.

* camel-vee-store.c (camel_vee_store_init): Turn off vtrash for
this store.

* camel-store.c (camel_store_init): Enable vtrash by default via
flags.
(camel_store_get_trash): REturn NULL if the store doesn't support
vtrash.
(init_trash): Dont init if store doesn't support vtrash.

* camel-store.h: Add a new flags CAMEL_STORE_VTRASH -> store
supports vtrash.

2001-09-13    <NotZed@Ximian.com>

* camel-vee-store.c (vee_get_folder_info): Implement.
(build_info): Used to build a folder record from the folders
hashtable.
(vee_delete_folder): Implemented, remove folder from hashtable.
(vee_rename_folder): Implemented, remove old folder from
hashtable, add new one and rename its guts too.

* camel-store.c (camel_store_rename_folder): Do nothing if we're
not asked to actually change names.  Also dont do the renamed
cache check till after we've called the subclass.
(camel_store_delete_folder): Call the subclass delete firs,t then
make sure the cache is right.

* camel-vee-folder.c (vee_folder_construct): Remove support for
name?query syntax to setup vfolder.  Abort if such syntax is used.
(camel_vee_folder_new): Removed code that handles ? syntax, etc.
(vee_folder_build_folder): Handle unset expression, treat it as an
empty search.
(camel_vee_folder_set_expression): Oops, actually set the
expression.

* camel-vtrash-folder.c (camel_vtrash_folder_new): Dont use
name?query syntax to setup vfolder, but set the expression
directly.  Also fixes a small memleak.

2001-09-12    <NotZed@Ximian.com>

* camel-store.c (camel_store_delete_folder): Fixed warnings with a cast.
(camel_store_rename_folder): "

camel/ChangeLog
camel/camel-store.c
camel/camel-store.h
camel/camel-vee-folder.c
camel/camel-vee-folder.h
camel/camel-vee-store.c
camel/camel-vtrash-folder.c

index e2cc98d..a62a593 100644 (file)
@@ -1,3 +1,54 @@
+2001-09-14    <NotZed@Ximian.com>
+
+       * camel-vee-folder.c (camel_vee_folder_set_folders): New function,
+       set the complete list of folders on a vfolder, all at once.
+       (camel_vee_folder_set_expression): If we set the query to be the
+       same thing, dont do anything.
+
+       * camel-vee-store.c (camel_vee_store_init): Turn off vtrash for
+       this store.
+
+       * camel-store.c (camel_store_init): Enable vtrash by default via
+       flags.
+       (camel_store_get_trash): REturn NULL if the store doesn't support
+       vtrash.
+       (init_trash): Dont init if store doesn't support vtrash.
+
+       * camel-store.h: Add a new flags CAMEL_STORE_VTRASH -> store
+       supports vtrash.
+
+2001-09-13    <NotZed@Ximian.com>
+
+       * camel-vee-store.c (vee_get_folder_info): Implement.
+       (build_info): Used to build a folder record from the folders
+       hashtable.
+       (vee_delete_folder): Implemented, remove folder from hashtable.
+       (vee_rename_folder): Implemented, remove old folder from
+       hashtable, add new one and rename its guts too.
+
+       * camel-store.c (camel_store_rename_folder): Do nothing if we're
+       not asked to actually change names.  Also dont do the renamed
+       cache check till after we've called the subclass.
+       (camel_store_delete_folder): Call the subclass delete firs,t then
+       make sure the cache is right.
+
+       * camel-vee-folder.c (vee_folder_construct): Remove support for
+       name?query syntax to setup vfolder.  Abort if such syntax is used.
+       (camel_vee_folder_new): Removed code that handles ? syntax, etc.
+       (vee_folder_build_folder): Handle unset expression, treat it as an
+       empty search.
+       (camel_vee_folder_set_expression): Oops, actually set the
+       expression.
+
+       * camel-vtrash-folder.c (camel_vtrash_folder_new): Dont use
+       name?query syntax to setup vfolder, but set the expression
+       directly.  Also fixes a small memleak.
+
+2001-09-12    <NotZed@Ximian.com>
+
+       * camel-store.c (camel_store_delete_folder): Fixed warnings with a cast.
+       (camel_store_rename_folder): "
+
 2001-09-14  Jeffrey Stedfast  <fejj@ximian.com>
 
        * camel-url.c (camel_url_set_param): Use g_datalist_set_data_full
index 470ada7..9722163 100644 (file)
@@ -111,7 +111,8 @@ camel_store_init (void *o)
        } else
                store->folders = NULL;
        
-       store->flags = 0;
+       /* set vtrash on by default */
+       store->flags = CAMEL_STORE_VTRASH;
        
        store->priv = g_malloc0 (sizeof (*store->priv));
 #ifdef ENABLE_THREADS
@@ -226,11 +227,15 @@ camel_store_get_folder (CamelStore *store, const char *folder_name, guint32 flag
                        if (store->folders) {
                                CAMEL_STORE_LOCK(store, cache_lock);
                                
+                               printf("adding folder '%s' to folders hashtable\n", folder_name);
                                g_hash_table_insert (store->folders, g_strdup (folder_name), folder);
                                
+                               printf("store folders size = %d\n", g_hash_table_size(store->folders));
+
                                camel_object_hook_event (CAMEL_OBJECT (folder), "finalize", folder_finalize, store);
                                CAMEL_STORE_UNLOCK(store, cache_lock);
-                       }
+                       } else
+                               printf("not adding folder '%s' to folders hashtable\n", folder_name);
                }
        }
        
@@ -296,13 +301,15 @@ camel_store_delete_folder (CamelStore *store, const char *folder_name, CamelExce
 
        CAMEL_STORE_LOCK(store, folder_lock);
 
+       CS_CLASS (store)->delete_folder (store, folder_name, ex);
+
        /* if we deleted a folder, force it out of the cache, and also out of the vtrash if setup */
        if (store->folders) {
                CamelFolder *folder;
                char *key;
 
                CAMEL_STORE_LOCK(store, cache_lock);
-               if (g_hash_table_lookup_extended(store->folders, folder_name, &key, (void **)&folder)) {
+               if (g_hash_table_lookup_extended(store->folders, folder_name, (void **)&key, (void **)&folder)) {
                        g_hash_table_remove(store->folders, key);
                        g_free(key);
                        CAMEL_STORE_UNLOCK(store, cache_lock);
@@ -313,7 +320,6 @@ camel_store_delete_folder (CamelStore *store, const char *folder_name, CamelExce
                }
        }
 
-       CS_CLASS (store)->delete_folder (store, folder_name, ex);
        CAMEL_STORE_UNLOCK(store, folder_lock);
 }
 
@@ -341,17 +347,20 @@ camel_store_rename_folder (CamelStore *store, const char *old_name, const char *
        char *key;
        CamelFolder *folder;
 
+       if (strcmp(old_name, new_name) == 0)
+               return;
+
        CAMEL_STORE_LOCK(store, folder_lock);
+       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, &key, (void **)&folder)) {
+       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_STORE_UNLOCK(store, cache_lock);
 
-       CS_CLASS (store)->rename_folder (store, old_name, new_name, ex);
        CAMEL_STORE_UNLOCK(store, folder_lock);
 }
 
@@ -406,6 +415,9 @@ trash_finalize (CamelObject *trash, gpointer event_data, gpointer user_data)
 static void
 init_trash (CamelStore *store)
 {
+       if ((store->flags & CAMEL_STORE_VTRASH) == 0)
+               return;
+
        store->vtrash = camel_vtrash_folder_new (store, CAMEL_VTRASH_NAME);
        
        if (store->vtrash) {
@@ -455,6 +467,9 @@ CamelFolder *
 camel_store_get_trash (CamelStore *store, CamelException *ex)
 {
        CamelFolder *folder;
+
+       if ((store->flags & CAMEL_STORE_VTRASH) == 0)
+               return NULL;
        
        CAMEL_STORE_LOCK(store, folder_lock);
        folder = CS_CLASS (store)->get_trash (store, ex);
index 02ceb57..6983524 100644 (file)
@@ -54,7 +54,8 @@ typedef struct _CamelFolderInfo {
 
 
 /* Flags for store flags */
-#define CAMEL_STORE_SUBSCRIPTIONS (1 << 0)
+#define CAMEL_STORE_SUBSCRIPTIONS      (1 << 0)
+#define CAMEL_STORE_VTRASH             (1 << 1)
 
 struct _CamelStore
 {
index fde38fa..e2e224d 100644 (file)
@@ -194,14 +194,10 @@ vee_folder_construct (CamelVeeFolder *vf, CamelStore *parent_store, const char *
        
        vf->flags = flags;
 
-       tmp = strchr(name, '?');
-       if (tmp) {
-               vf->vname = g_strndup(name, tmp-name);
-               vf->expression = g_strdup(tmp+1);
-       } else {
-               vf->vname = g_strdup(name);
-       }
+       /* We dont support ? syntax anymore */
+       g_assert(strchr(name, '?') == NULL);
 
+       vf->vname = g_strdup(name);
        tmp = strrchr(vf->vname, '/');
        if (tmp)
                tmp++;
@@ -247,7 +243,6 @@ CamelFolder *
 camel_vee_folder_new(CamelStore *parent_store, const char *name, guint32 flags)
 {
        CamelVeeFolder *vf;
-       char *path, *query;
 
        UNMATCHED_LOCK();
 
@@ -261,13 +256,7 @@ camel_vee_folder_new(CamelStore *parent_store, const char *name, guint32 flags)
 
        UNMATCHED_UNLOCK();
 
-       path = alloca(strlen(name)+1);
-       strcpy(path, name);
-       query = strchr(path, '?');
-       if (query)
-               *query++ = 0;
-
-       if (strcmp(path, "UNMATCHED") == 0) {
+       if (strcmp(name, "UNMATCHED") == 0) {
                camel_object_ref((CamelObject *)folder_unmatched);
                printf("returning unmatched %p, count = %d\n", folder_unmatched, camel_folder_get_message_count((CamelFolder *)folder_unmatched));
                return (CamelFolder *)folder_unmatched;
@@ -289,6 +278,17 @@ camel_vee_folder_set_expression(CamelVeeFolder *vf, const char *query)
 
        CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock);
 
+       /* no change, do nothing */
+       if ((vf->expression && query && strcmp(vf->expression, query) == 0)
+           || (vf->expression == NULL && query == NULL)) {
+               CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock);
+               return;
+       }
+
+       g_free(vf->expression);
+       if (query)
+               vf->expression = g_strdup(query);
+
        node = p->folders;
        while (node) {
                CamelFolder *f = node->data;
@@ -372,6 +372,54 @@ camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub)
        camel_object_unref((CamelObject *)sub);
 }
 
+static void
+remove_folders(CamelFolder *folder, CamelFolder *foldercopy, CamelVeeFolder *vf)
+{
+       camel_vee_folder_remove_folder(vf, folder);
+       camel_object_unref((CamelObject *)folder);
+}
+
+/**
+ * camel_vee_folder_set_folders:
+ * @vf: 
+ * @folders: 
+ * 
+ * Set the whole list of folder sources on a vee folder.
+ **/
+void
+camel_vee_folder_set_folders(CamelVeeFolder *vf, GList *folders)
+{
+       GHashTable *remove = g_hash_table_new(NULL, NULL);
+       GList *l;
+       CamelFolder *folder;
+
+       /* setup a table of all folders we have currently */
+       CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock);
+       l = vf->priv->folders;
+       while (l) {
+               g_hash_table_insert(remove, l->data, l->data);
+               camel_object_ref((CamelObject *)l->data);
+               l = l->next;
+       }
+       CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock);
+
+       /* if we already have the folder, ignore it, otherwise add it */
+       l = folders;
+       while (l) {
+               if ((folder = g_hash_table_lookup(remove, l->data))) {
+                       g_hash_table_remove(remove, folder);
+                       camel_object_unref((CamelObject *)folder);
+               } else {
+                       camel_vee_folder_add_folder(vf, l->data);
+               }
+               l = l->next;
+       }
+
+       /* then remove any we still have */
+       g_hash_table_foreach(remove, (GHFunc)remove_folders, vf);
+       g_hash_table_destroy(remove);
+}
+
 /**
  * camel_vee_folder_hash_folder:
  * @folder: 
@@ -750,9 +798,14 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException
        if (vf == folder_unmatched)
                return 0;
 
-       match = camel_folder_search_by_expression(f, vf->expression, ex);
-       if (match == NULL)
-               return -1;
+       /* if we have no expression, or its been cleared, then act as if no matches */
+       if (vf->expression == NULL) {
+               match = g_ptr_array_new();
+       } else {
+               match = camel_folder_search_by_expression(f, vf->expression, ex);
+               if (match == NULL)
+                       return -1;
+       }
 
        u.source = source;
        u.vf = vf;
@@ -847,7 +900,11 @@ vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException
 
        g_hash_table_destroy(matchhash);
        g_hash_table_destroy(allhash);
-       camel_folder_search_free(f, match);
+       /* if expression not set, we only had a null list */
+       if (vf->expression == NULL)
+               g_ptr_array_free(match, TRUE);
+       else
+               camel_folder_search_free(f, match);
        camel_folder_free_uids(f, all);
 
        if (unmatched_changes) {
index 8c7deb6..8370575 100644 (file)
@@ -62,6 +62,7 @@ void         camel_vee_folder_construct               (CamelVeeFolder *vf, CamelStore *parent
 
 void         camel_vee_folder_add_folder        (CamelVeeFolder *vf, CamelFolder *sub);
 void         camel_vee_folder_remove_folder     (CamelVeeFolder *vf, CamelFolder *sub);
+void        camel_vee_folder_set_folders       (CamelVeeFolder *vf, GList *folders);
 void        camel_vee_folder_set_expression    (CamelVeeFolder *vf, const char *expr);
 
 void        camel_vee_folder_hash_folder       (CamelFolder *folder, char buffer[8]);
index 2d44b45..f5de80f 100644 (file)
  *  USA
  */
 
+#include "camel-exception.h"
 #include "camel-vee-store.h"
 #include "camel-vee-folder.h"
 
+#include "camel-private.h"
+
 #include <string.h>
 
 static CamelFolder *vee_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex);
+static void vee_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex);
+static void vee_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex);
 static void vee_init_trash (CamelStore *store);
 static CamelFolder *vee_get_trash  (CamelStore *store, CamelException *ex);
 
+static CamelFolderInfo *vee_get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex);
+
 struct _CamelVeeStorePrivate {
        CamelFolderInfo *folder_info;
 };
@@ -67,6 +74,11 @@ camel_vee_store_class_init (CamelVeeStoreClass *klass)
 
        /* virtual method overload */
        store_class->get_folder = vee_get_folder;
+       store_class->rename_folder = vee_rename_folder;
+       store_class->delete_folder = vee_delete_folder;
+       store_class->get_folder_info = vee_get_folder_info;
+       store_class->free_folder_info = camel_store_free_folder_info_full;
+
        store_class->init_trash = vee_init_trash;
        store_class->get_trash = vee_get_trash;
 }
@@ -75,6 +87,10 @@ static void
 camel_vee_store_init (CamelVeeStore *obj)
 {
        struct _CamelVeeStorePrivate *p;
+       CamelStore *store = (CamelStore *)obj;
+
+       /* we dont want a vtrash on this one */
+       store->flags &= ~(CAMEL_STORE_VTRASH);  
 
        p = _PRIVATE(obj) = g_malloc0(sizeof(*p));
 }
@@ -138,3 +154,158 @@ vee_get_trash (CamelStore *store, CamelException *ex)
 {
        return NULL;
 }
+
+struct _build_info {
+       const char *top;
+       guint32 flags;
+       GPtrArray *infos;
+};
+
+static void
+build_info(char *name, CamelVeeFolder *folder, struct _build_info *data)
+{
+       CamelFolderInfo *info;
+
+       /* check we have to include this one */
+       if (data->top) {
+               if (data->flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) {
+                       if (strncmp(name, data->top, strlen(data->top) != 0))
+                               return;
+               } else {
+                       if (strcmp(name, data->top))
+                               return;
+               }
+       } else {
+               if ((data->flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) == 0) {
+                       if (strchr(name, '/'))
+                               return;
+               }
+       }
+
+       info = g_malloc0(sizeof(*info));
+       info->url = g_strdup_printf("vfolder:%s#%s", ((CamelService *)((CamelFolder *)folder)->parent_store)->url->path,
+                                   ((CamelFolder *)folder)->full_name);
+       info->full_name = g_strdup(((CamelFolder *)folder)->full_name);
+       info->name = g_strdup(((CamelFolder *)folder)->name);
+       info->unread_message_count = camel_folder_get_unread_message_count((CamelFolder *)folder);
+       g_ptr_array_add(data->infos, info);
+}
+
+static CamelFolderInfo *
+vee_get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex)
+{
+       struct _build_info data;
+       CamelFolderInfo *info;
+
+       /* first, build the info list */
+       data.top = top;
+       data.flags = flags;
+       data.infos = g_ptr_array_new();
+       CAMEL_STORE_LOCK(store, cache_lock);
+       g_hash_table_foreach(store->folders, (GHFunc)build_info, &data);
+       CAMEL_STORE_UNLOCK(store, cache_lock);
+
+       /* and always add UNMATCHED, if scanning from top/etc */
+       if (top == NULL || top[0] == 0 || strncmp(top, "UNMATCHED", strlen("UNMATCHED")) == 0) {
+               info = g_malloc0(sizeof(*info));
+               info->url = g_strdup_printf("vfolder:%s#UNMATCHED", ((CamelService *)store)->url->path);
+               info->full_name = g_strdup("UNMATCHED");
+               info->name = g_strdup("UNMATCHED");
+               info->unread_message_count = -1;
+               g_ptr_array_add(data.infos, info);
+       }
+               
+       /* convert it into a tree */
+       info = camel_folder_info_build(data.infos, (top&&top[0])?top:"", '/', TRUE);
+       g_ptr_array_free(data.infos, TRUE);
+
+       return info;
+}
+
+static void
+vee_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex)
+{
+       CamelFolder *folder;
+       char *key;
+
+       if (strcmp(folder_name, "UNMATCHED") == 0) {
+               camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
+                                    _("Cannot delete folder: %s: Invalid operation"), folder_name);
+               return;
+       }
+
+       CAMEL_STORE_LOCK(store, cache_lock);
+       if (g_hash_table_lookup_extended(store->folders, folder_name, (void **)&key, (void **)&folder)) {
+               int update;
+
+               update = (((CamelVeeFolder *)folder)->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0;
+               g_hash_table_remove(store->folders, key);
+               CAMEL_STORE_UNLOCK(store, cache_lock);
+               if (store->vtrash)
+                       camel_vee_folder_remove_folder((CamelVeeFolder *)store->vtrash, folder);
+
+               /* FIXME: deleted event shoudl just pass out the folder name, not all this shit?? */
+               if (update) {
+                       CamelFolderInfo *fi = g_malloc0(sizeof(*fi));
+
+                       fi->full_name = g_strdup(key);
+                       fi->name = strrchr(key, '/');
+                       if (fi->name == NULL)
+                               fi->name = g_strdup(key);
+                       else
+                               fi->name = g_strdup(fi->name);
+                       fi->url = g_strdup_printf("vfolder:%s#%s", ((CamelService *)store)->url->path, key);
+                       fi->unread_message_count = -1;
+       
+                       camel_object_trigger_event(CAMEL_OBJECT(store), "folder_deleted", fi);
+                       camel_folder_info_free(fi);
+               }
+               g_free(key);
+       } else {
+               CAMEL_STORE_UNLOCK(store, cache_lock);
+
+               camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
+                                    _("Cannot delete folder: %s: No such folder"), folder_name);
+       }
+}
+
+static void
+vee_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex)
+{
+       CamelFolder *folder;
+       char *key, *oldname, *full_oldname;
+
+       if (strcmp(old, "UNMATCHED") == 0) {
+               camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
+                                    _("Cannot rename folder: %s: Invalid operation"), old);
+               return;
+       }
+
+       CAMEL_STORE_LOCK(store, cache_lock);
+       if (g_hash_table_lookup_extended(store->folders, old, (void **)&key, (void **)&folder)) {
+               g_hash_table_remove(store->folders, key);
+               g_free(key);
+
+               /* this should really be atomic */
+               oldname = folder->name;
+               full_oldname = folder->full_name;
+               key = folder->name;
+               folder->full_name = g_strdup(new);
+               key = strrchr(new, '/');
+               key = key?key+1:(char *)new;
+               folder->name = g_strdup(key);
+               g_hash_table_insert(store->folders, g_strdup(new), folder);
+
+               g_free(oldname);
+               g_free(full_oldname);
+               CAMEL_STORE_UNLOCK(store, cache_lock);
+
+               
+       } else {
+               CAMEL_STORE_UNLOCK(store, cache_lock);
+
+               camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
+                                    _("Cannot rename folder: %s: No such folder"), new);
+       }
+}
+
index d76c9f8..be66202 100644 (file)
@@ -83,15 +83,12 @@ CamelFolder *
 camel_vtrash_folder_new (CamelStore *parent_store, const char *name)
 {
        CamelFolder *vtrash;
-       char *vtrash_name;
-       guint32 flags;
        
        vtrash = (CamelFolder *)camel_object_new (camel_vtrash_folder_get_type ());
-       vtrash_name = g_strdup_printf ("%s?(match-all (system-flag \"Deleted\"))", name);
-       flags = CAMEL_STORE_FOLDER_PRIVATE | CAMEL_STORE_FOLDER_CREATE | CAMEL_STORE_VEE_FOLDER_AUTO;
-       
-       camel_vee_folder_construct (CAMEL_VEE_FOLDER (vtrash), parent_store, vtrash_name, flags);
-       
+       camel_vee_folder_construct (CAMEL_VEE_FOLDER (vtrash), parent_store, name,
+                                   CAMEL_STORE_FOLDER_PRIVATE | CAMEL_STORE_FOLDER_CREATE | CAMEL_STORE_VEE_FOLDER_AUTO);
+       camel_vee_folder_set_expression((CamelVeeFolder *)vtrash, "(match-all (system-flag \"Deleted\"))");
+
        return vtrash;
 }