diff options
-rw-r--r-- | mail/ChangeLog | 38 | ||||
-rw-r--r-- | mail/em-folder-tree-model.c | 412 | ||||
-rw-r--r-- | mail/em-folder-tree-model.h | 28 | ||||
-rw-r--r-- | mail/em-folder-tree.c | 449 | ||||
-rw-r--r-- | mail/em-folder-tree.h | 3 | ||||
-rw-r--r-- | mail/mail-component.c | 18 |
6 files changed, 482 insertions, 466 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index 8d1e933446..be75dee5d6 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -16,6 +16,44 @@ 2003-12-01 Jeffrey Stedfast <fejj@ximian.com> + * em-folder-tree.c (em_folder_tree_get_folder_info__got): Updated + to call em_folder_tree_model_set_folder_info(). + (folder_subscribed_cb): Removed. + (folder_unsubscribed_cb): Removed. + (folder_created_cb): Removed. + (folder_deleted_cb): Removed. + (folder_renamed_cb): Removed. + + * em-folder-tree-model.c (em_folder_tree_store_set_folder_info): + New function to replace tree_store_set_folder_info() which had + been in em-folder-tree.c + (em_folder_tree_model_remove_uri): Made private. + (em_folder_tree_model_remove_store_info): Made private. + (em_folder_tree_model_remove_folders): New function to replace + remove_folders() from em-folder-tree.c + (em_folder_tree_model_new): No longer takes any args. + + * em-folder-tree.c (em_folder_tree_new): Updated. + + * mail-component.c (add_store): Add the store to the model rather + than the treeview. + (impl_createControls): create a new treeview based on the + already-instantiated model. + (mail_component_init): Create a new tree model. + (mail_component_remove_store): Remove the store from the model + directly. + (mail_component_get_tree_model): Updated. + + * em-folder-tree.c (folder_unsubscribed_cb): Call + em_folder_tree_model_remove_folders() rather than the deprecated + internal remove_folders() function. + (folder_renamed_cb): Same. + (em_folder_tree_remove_store): Removed. + (em_folder_tree_add_store): Removed. + (remove_folders): Removed. + +2003-12-01 Jeffrey Stedfast <fejj@ximian.com> + * em-composer-utils.c (composer_get_message): rfc2047 encode the Organization header value. diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c index f6f7d6cc27..677ab8d0fe 100644 --- a/mail/em-folder-tree-model.c +++ b/mail/em-folder-tree-model.c @@ -25,10 +25,25 @@ #include <config.h> #endif +#include <string.h> + +#include "mail-config.h" + #include "em-marshal.h" #include "em-folder-tree-model.h" +static GType col_types[] = { + G_TYPE_STRING, /* display name */ + G_TYPE_POINTER, /* store object */ + G_TYPE_STRING, /* path */ + G_TYPE_STRING, /* uri */ + G_TYPE_UINT, /* unread count */ + G_TYPE_BOOLEAN, /* is a store node */ + G_TYPE_BOOLEAN, /* has not-yet-loaded subfolders */ +}; + + /* GObject virtual method overrides */ static void em_folder_tree_model_class_init (EMFolderTreeModelClass *klass); static void em_folder_tree_model_init (EMFolderTreeModel *model); @@ -321,18 +336,348 @@ model_drag_data_delete (GtkTreeDragSource *drag_source, GtkTreePath *src_path) EMFolderTreeModel * -em_folder_tree_model_new (int n_columns, GType *types) +em_folder_tree_model_new (void) { EMFolderTreeModel *model; model = g_object_new (EM_TYPE_FOLDER_TREE_MODEL, NULL); - gtk_tree_store_set_column_types ((GtkTreeStore *) model, n_columns, types); + gtk_tree_store_set_column_types ((GtkTreeStore *) model, NUM_COLUMNS, col_types); return model; } void +em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *iter, + struct _EMFolderTreeModelStoreInfo *si, + CamelFolderInfo *fi) +{ + GtkTreeRowReference *uri_row, *path_row; + unsigned int unread; + EAccount *account; + GtkTreePath *path; + GtkTreeIter sub; + gboolean load; + char *node; + + load = !fi->child && (fi->flags & CAMEL_FOLDER_CHILDREN) && !(fi->flags & CAMEL_FOLDER_NOINFERIORS); + + path = gtk_tree_model_get_path ((GtkTreeModel *) model, iter); + uri_row = gtk_tree_row_reference_new ((GtkTreeModel *) model, path); + path_row = gtk_tree_row_reference_copy (uri_row); + /*gtk_tree_path_free (path);*/ + + g_hash_table_insert (model->uri_hash, g_strdup (fi->url), uri_row); + g_hash_table_insert (si->path_hash, g_strdup (fi->path), path_row); + + unread = fi->unread_message_count == -1 ? 0 : fi->unread_message_count; + + gtk_tree_store_set ((GtkTreeStore *) model, iter, + COL_STRING_DISPLAY_NAME, fi->name, + COL_POINTER_CAMEL_STORE, si->store, + COL_STRING_FOLDER_PATH, fi->path, + COL_STRING_URI, fi->url, + COL_UINT_UNREAD, unread, + COL_BOOL_IS_STORE, FALSE, + COL_BOOL_LOAD_SUBDIRS, load, + -1); + + node = fi->path; + + if (fi->child) { + fi = fi->child; + + do { + gtk_tree_store_append ((GtkTreeStore *) model, &sub, iter); + em_folder_tree_model_set_folder_info (model, &sub, si, fi); + fi = fi->sibling; + } while (fi); + } else if (load) { + /* create a placeholder node for our subfolders... */ + gtk_tree_store_append ((GtkTreeStore *) model, &sub, iter); + gtk_tree_store_set ((GtkTreeStore *) model, &sub, + COL_STRING_DISPLAY_NAME, _("Loading..."), + COL_POINTER_CAMEL_STORE, si->store, + COL_STRING_FOLDER_PATH, fi->path, + COL_BOOL_LOAD_SUBDIRS, TRUE, + COL_BOOL_IS_STORE, FALSE, + COL_STRING_URI, fi->url, + COL_UINT_UNREAD, 0, + -1); + } +#if 0 + /* FIXME: need to somehow get access to the appropriate treeview widget... */ + if ((account = mail_config_get_account_by_name (si->display_name))) + node = g_strdup_printf ("%s:%s", account->uid, node); + else + node = g_strdup_printf ("%s:%s", si->display_name, node); + + if (g_hash_table_lookup (priv->expanded, node)) { + printf ("expanding node '%s'\n", node); + gtk_tree_view_expand_to_path (priv->treeview, path); + } + + gtk_tree_path_free (path); + g_free (node); +#endif +} + + +static void +folder_subscribed_cb (CamelStore *store, void *event_data, EMFolderTreeModel *model) +{ + struct _EMFolderTreeModelStoreInfo *si; + CamelFolderInfo *fi = event_data; + GtkTreeRowReference *row; + GtkTreeIter parent, iter; + GtkTreePath *path; + gboolean load; + char *dirname; + + if (!(si = g_hash_table_lookup (model->store_hash, store))) + return; + + /* make sure we don't already know about it? */ + if (g_hash_table_lookup (si->path_hash, fi->path)) + return; + + /* get our parent folder's path */ + if (!(dirname = g_path_get_dirname (fi->path))) + return; + + if (!strcmp (dirname, "/")) { + /* user subscribed to a toplevel folder */ + row = si->row; + g_free (dirname); + } else { + row = g_hash_table_lookup (si->path_hash, dirname); + g_free (dirname); + + /* if row is NULL, don't bother adding to the tree, + * when the user expands enough nodes - it will be + * added auto-magically */ + if (row == NULL) + return; + } + + path = gtk_tree_row_reference_get_path (row); + if (!(gtk_tree_model_get_iter ((GtkTreeModel *) model, &parent, path))) { + gtk_tree_path_free (path); + return; + } + + gtk_tree_path_free (path); + + /* make sure parent's subfolders have already been loaded */ + gtk_tree_model_get ((GtkTreeModel *) model, &parent, COL_BOOL_LOAD_SUBDIRS, &load, -1); + if (load) + return; + + /* append a new node */ + gtk_tree_store_append ((GtkTreeStore *) model, &iter, &parent); + + em_folder_tree_model_set_folder_info (model, &iter, si, fi); +} + +static void +folder_unsubscribed_cb (CamelStore *store, void *event_data, EMFolderTreeModel *model) +{ + struct _EMFolderTreeModelStoreInfo *si; + CamelFolderInfo *fi = event_data; + GtkTreeRowReference *row; + GtkTreePath *path; + GtkTreeIter iter; + + if (!(si = g_hash_table_lookup (model->store_hash, store))) + return; + + if (!(row = g_hash_table_lookup (si->path_hash, fi->path))) + return; + + path = gtk_tree_row_reference_get_path (row); + if (!(gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, path))) { + gtk_tree_path_free (path); + return; + } + + em_folder_tree_model_remove_folders (model, si, &iter); +} + +static void +folder_created_cb (CamelStore *store, void *event_data, EMFolderTreeModel *model) +{ + /* we only want created events to do more work if we don't support subscriptions */ + if (!camel_store_supports_subscriptions (store)) + folder_subscribed_cb (store, event_data, model); +} + +static void +folder_deleted_cb (CamelStore *store, void *event_data, EMFolderTreeModel *model) +{ + /* we only want deleted events to do more work if we don't support subscriptions */ + if (!camel_store_supports_subscriptions (store)) + folder_unsubscribed_cb (store, event_data, model); +} + +static void +folder_renamed_cb (CamelStore *store, void *event_data, EMFolderTreeModel *model) +{ + struct _EMFolderTreeModelStoreInfo *si; + CamelRenameInfo *info = event_data; + GtkTreeRowReference *row; + GtkTreeIter root, iter; + GtkTreePath *path; + char *parent, *p; + + if (!(si = g_hash_table_lookup (model->store_hash, store))) + return; + + parent = g_strdup_printf ("/%s", info->old_base); + if (!(row = g_hash_table_lookup (si->path_hash, parent))) { + g_free (parent); + return; + } + g_free (parent); + + path = gtk_tree_row_reference_get_path (row); + if (!(gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, path))) { + gtk_tree_path_free (path); + return; + } + + em_folder_tree_model_remove_folders (model, si, &iter); + + parent = g_strdup (info->new->path); + if ((p = strrchr (parent + 1, '/'))) + *p = '\0'; + + if (!strcmp (parent, "/")) { + /* renamed to a toplevel folder on the store */ + path = gtk_tree_row_reference_get_path (si->row); + } else { + if (!(row = g_hash_table_lookup (si->path_hash, parent))) { + /* NOTE: this should never happen, but I + * suppose if it does in reality, we can add + * code here to add the missing nodes to the + * tree */ + g_assert_not_reached (); + g_free (parent); + return; + } + + path = gtk_tree_row_reference_get_path (row); + } + + g_free (parent); + + if (!gtk_tree_model_get_iter ((GtkTreeModel *) model, &root, path)) { + gtk_tree_path_free (path); + g_assert_not_reached (); + return; + } + + gtk_tree_store_append ((GtkTreeStore *) model, &iter, &root); + em_folder_tree_model_set_folder_info (model, &iter, si, info->new); +} + + +void +em_folder_tree_model_add_store (EMFolderTreeModel *model, CamelStore *store, const char *display_name) +{ + struct _EMFolderTreeModelStoreInfo *si; + GtkTreeRowReference *row; + GtkTreeIter root, iter; + GtkTreePath *path; + EAccount *account; + char *node, *uri; + + g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model)); + g_return_if_fail (CAMEL_IS_STORE (store)); + g_return_if_fail (display_name != NULL); + + if ((si = g_hash_table_lookup (model->store_hash, store))) { + const char *name; + + path = gtk_tree_row_reference_get_path (si->row); + gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, path); + gtk_tree_path_free (path); + + gtk_tree_model_get ((GtkTreeModel *) model, &iter, COL_STRING_DISPLAY_NAME, (char **) &name, -1); + + g_warning ("the store `%s' is already in the folder tree as `%s'", + display_name, name); + + return; + } + + uri = camel_url_to_string (((CamelService *) store)->url, CAMEL_URL_HIDE_ALL); + + /* add the store to the tree */ + gtk_tree_store_append ((GtkTreeStore *) model, &iter, NULL); + gtk_tree_store_set ((GtkTreeStore *) model, &iter, + COL_STRING_DISPLAY_NAME, display_name, + COL_POINTER_CAMEL_STORE, store, + COL_STRING_FOLDER_PATH, "/", + COL_BOOL_LOAD_SUBDIRS, TRUE, + COL_BOOL_IS_STORE, TRUE, + COL_STRING_URI, uri, -1); + + path = gtk_tree_model_get_path ((GtkTreeModel *) model, &iter); + row = gtk_tree_row_reference_new ((GtkTreeModel *) model, path); + gtk_tree_path_free (path); + + si = g_new (struct _EMFolderTreeModelStoreInfo, 1); + si->display_name = g_strdup (display_name); + camel_object_ref (store); + si->store = store; + si->row = row; + si->path_hash = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (model->store_hash, store, si); + + /* each store has folders... but we don't load them until the user demands them */ + root = iter; + gtk_tree_store_append ((GtkTreeStore *) model, &iter, &root); + gtk_tree_store_set ((GtkTreeStore *) model, &iter, + COL_STRING_DISPLAY_NAME, _("Loading..."), + COL_POINTER_CAMEL_STORE, store, + COL_STRING_FOLDER_PATH, "/", + COL_BOOL_LOAD_SUBDIRS, TRUE, + COL_BOOL_IS_STORE, FALSE, + COL_STRING_URI, uri, + COL_UINT_UNREAD, 0, + -1); + + g_free (uri); + +#if 0 + /* FIXME: how to do this now that it is being done in the + * model instead of the tree widget code??? need to somehow + * get access to the appropriate treeview widget... */ + if ((account = mail_config_get_account_by_name (display_name))) + node = g_strdup_printf ("%s:/", account->uid); + else + node = g_strdup_printf ("%s:/", display_name); + + if (g_hash_table_lookup (priv->expanded, node)) { + path = gtk_tree_model_get_path ((GtkTreeModel *) model, &iter); + gtk_tree_view_expand_to_path (priv->treeview, path); + gtk_tree_path_free (path); + } + + g_free (node); +#endif + + /* listen to store events */ +#define CAMEL_CALLBACK(func) ((CamelObjectEventHookFunc) func) + si->created_id = camel_object_hook_event (store, "folder_created", CAMEL_CALLBACK (folder_created_cb), model); + si->deleted_id = camel_object_hook_event (store, "folder_deleted", CAMEL_CALLBACK (folder_deleted_cb), model); + si->renamed_id = camel_object_hook_event (store, "folder_renamed", CAMEL_CALLBACK (folder_renamed_cb), model); + si->subscribed_id = camel_object_hook_event (store, "folder_subscribed", CAMEL_CALLBACK (folder_subscribed_cb), model); + si->unsubscribed_id = camel_object_hook_event (store, "folder_unsubscribed", CAMEL_CALLBACK (folder_unsubscribed_cb), model); +} + + +static void em_folder_tree_model_remove_uri (EMFolderTreeModel *model, const char *uri) { GtkTreeRowReference *row; @@ -347,7 +692,7 @@ em_folder_tree_model_remove_uri (EMFolderTreeModel *model, const char *uri) } -void +static void em_folder_tree_model_remove_store_info (EMFolderTreeModel *model, CamelStore *store) { struct _EMFolderTreeModelStoreInfo *si; @@ -361,3 +706,64 @@ em_folder_tree_model_remove_store_info (EMFolderTreeModel *model, CamelStore *st g_hash_table_remove (model->store_hash, si->store); store_info_free (si); } + + +void +em_folder_tree_model_remove_folders (EMFolderTreeModel *model, struct _EMFolderTreeModelStoreInfo *si, GtkTreeIter *toplevel) +{ + GtkTreeRowReference *row; + char *uri, *folder_path; + gboolean is_store, go; + GtkTreeIter iter; + + if (gtk_tree_model_iter_children ((GtkTreeModel *) model, &iter, toplevel)) { + do { + GtkTreeIter next = iter; + + go = gtk_tree_model_iter_next ((GtkTreeModel *) model, &next); + em_folder_tree_model_remove_folders (model, si, &iter); + iter = next; + } while (go); + } + + gtk_tree_model_get ((GtkTreeModel *) model, toplevel, COL_STRING_URI, &uri, + COL_STRING_FOLDER_PATH, &folder_path, + COL_BOOL_IS_STORE, &is_store, -1); + + if ((row = g_hash_table_lookup (si->path_hash, folder_path))) { + g_hash_table_remove (si->path_hash, folder_path); + gtk_tree_row_reference_free (row); + } + + em_folder_tree_model_remove_uri (model, uri); + + gtk_tree_store_remove ((GtkTreeStore *) model, toplevel); + + if (is_store) + em_folder_tree_model_remove_store_info (model, si->store); +} + + +void +em_folder_tree_model_remove_store (EMFolderTreeModel *model, CamelStore *store) +{ + struct _EMFolderTreeModelStoreInfo *si; + GtkTreePath *path; + GtkTreeIter iter; + + g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model)); + g_return_if_fail (CAMEL_IS_STORE (store)); + + if (!(si = g_hash_table_lookup (model->store_hash, store))) { + g_warning ("the store `%s' is not in the folder tree", si->display_name); + + return; + } + + path = gtk_tree_row_reference_get_path (si->row); + gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, path); + gtk_tree_path_free (path); + + /* recursively remove subfolders and finally the toplevel store */ + em_folder_tree_model_remove_folders (model, si, &iter); +} diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h index f120c0dc62..e8755f0578 100644 --- a/mail/em-folder-tree-model.h +++ b/mail/em-folder-tree-model.h @@ -45,6 +45,22 @@ typedef struct _EMFolderTreeModel EMFolderTreeModel; typedef struct _EMFolderTreeModelClass EMFolderTreeModelClass; typedef struct _EMFolderTreeModelStoreInfo EMFolderTreeModelStoreInfo; +enum { + COL_STRING_DISPLAY_NAME, /* string that appears in the tree */ + COL_POINTER_CAMEL_STORE, /* CamelStore object */ + COL_STRING_FOLDER_PATH, /* if node is a folder, the full path of the folder */ + COL_STRING_URI, /* the uri to get the store or + * folder object */ + COL_UINT_UNREAD, /* unread count */ + + COL_BOOL_IS_STORE, /* toplevel store node? */ + COL_BOOL_LOAD_SUBDIRS, /* %TRUE only if the store/folder + * has subfolders which have not yet + * been added to the tree */ + NUM_COLUMNS +}; + + struct _EMFolderTreeModelStoreInfo { CamelStore *store; GtkTreeRowReference *row; @@ -91,11 +107,17 @@ struct _EMFolderTreeModelClass { GType em_folder_tree_model_get_type (void); -EMFolderTreeModel *em_folder_tree_model_new (int n_columns, GType *types); +EMFolderTreeModel *em_folder_tree_model_new (void); + +void em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *iter, + struct _EMFolderTreeModelStoreInfo *si, + CamelFolderInfo *fi); -void em_folder_tree_model_remove_uri (EMFolderTreeModel *model, const char *uri); -void em_folder_tree_model_remove_store_info (EMFolderTreeModel *model, CamelStore *store); +void em_folder_tree_model_add_store (EMFolderTreeModel *model, CamelStore *store, const char *display_name); +void em_folder_tree_model_remove_store (EMFolderTreeModel *model, CamelStore *store); +void em_folder_tree_model_remove_folders (EMFolderTreeModel *model, struct _EMFolderTreeModelStoreInfo *si, + GtkTreeIter *toplevel); #ifdef __cplusplus } diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index 48c71f164d..7aad5a8260 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -64,30 +64,6 @@ #define d(x) x -enum { - COL_STRING_DISPLAY_NAME, /* string that appears in the tree */ - COL_POINTER_CAMEL_STORE, /* CamelStore object */ - COL_STRING_FOLDER_PATH, /* if node is a folder, the full path of the folder */ - COL_STRING_URI, /* the uri to get the store or - * folder object */ - COL_UINT_UNREAD, /* unread count */ - - COL_BOOL_IS_STORE, /* toplevel store node? */ - COL_BOOL_LOAD_SUBDIRS, /* %TRUE only if the store/folder - * has subfolders which have not yet - * been added to the tree */ - NUM_COLUMNS -}; - -static GType col_types[] = { - G_TYPE_STRING, /* display name */ - G_TYPE_POINTER, /* store object */ - G_TYPE_STRING, /* path */ - G_TYPE_STRING, /* uri */ - G_TYPE_UINT, /* unread count */ - G_TYPE_BOOLEAN, /* is a store node */ - G_TYPE_BOOLEAN, /* has not-yet-loaded subfolders */ -}; struct _EMFolderTreePrivate { GtkTreeView *treeview; @@ -884,7 +860,7 @@ em_folder_tree_new (void) EMFolderTreeModel *model; EMFolderTree *emft; - model = em_folder_tree_model_new (NUM_COLUMNS, col_types); + model = em_folder_tree_model_new (); emft = (EMFolderTree *) em_folder_tree_new_with_model (model); priv = emft->priv; @@ -984,96 +960,6 @@ em_folder_tree_new_with_model (EMFolderTreeModel *model) } -static void -tree_store_set_folder_info (GtkTreeStore *model, GtkTreeIter *iter, - struct _EMFolderTreePrivate *priv, - struct _EMFolderTreeModelStoreInfo *si, - CamelFolderInfo *fi) -{ - GtkTreeRowReference *uri_row, *path_row; - unsigned int unread; - EAccount *account; - GtkTreePath *path; - GtkTreeIter sub; - gboolean load; - char *node; - - load = !fi->child && (fi->flags & CAMEL_FOLDER_CHILDREN) && !(fi->flags & CAMEL_FOLDER_NOINFERIORS); - - path = gtk_tree_model_get_path ((GtkTreeModel *) model, iter); - uri_row = gtk_tree_row_reference_new ((GtkTreeModel *) model, path); - path_row = gtk_tree_row_reference_copy (uri_row); - /*gtk_tree_path_free (path);*/ - - g_hash_table_insert (priv->model->uri_hash, g_strdup (fi->url), uri_row); - g_hash_table_insert (si->path_hash, g_strdup (fi->path), path_row); - - unread = fi->unread_message_count == -1 ? 0 : fi->unread_message_count; - - gtk_tree_store_set (model, iter, - COL_STRING_DISPLAY_NAME, fi->name, - COL_POINTER_CAMEL_STORE, si->store, - COL_STRING_FOLDER_PATH, fi->path, - COL_STRING_URI, fi->url, - COL_UINT_UNREAD, unread, - COL_BOOL_IS_STORE, FALSE, - COL_BOOL_LOAD_SUBDIRS, load, - -1); - - node = fi->path; - - if (fi->child) { - fi = fi->child; - - do { - gtk_tree_store_append (model, &sub, iter); - tree_store_set_folder_info ((GtkTreeStore *) model, &sub, priv, si, fi); - fi = fi->sibling; - } while (fi); - } else if (load) { - /* create a placeholder node for our subfolders... */ - gtk_tree_store_append (model, &sub, iter); - gtk_tree_store_set (model, &sub, - COL_STRING_DISPLAY_NAME, _("Loading..."), - COL_POINTER_CAMEL_STORE, si->store, - COL_STRING_FOLDER_PATH, fi->path, - COL_BOOL_LOAD_SUBDIRS, TRUE, - COL_BOOL_IS_STORE, FALSE, - COL_STRING_URI, fi->url, - COL_UINT_UNREAD, 0, - -1); -#if 0 - if ((account = mail_config_get_account_by_name (si->display_name))) - node = g_strdup_printf ("%s:%s", account->uid, fi->path); - else - node = g_strdup_printf ("%s:%s", si->display_name, fi->path); - - if (g_hash_table_lookup (priv->expanded, node)) { - printf ("expanding node '%s'\n", node); - path = gtk_tree_model_get_path ((GtkTreeModel *) model, &sub); - gtk_tree_view_expand_to_path (priv->treeview, path); - gtk_tree_path_free (path); - } - - g_free (node); -#endif - } -#if 1 - if ((account = mail_config_get_account_by_name (si->display_name))) - node = g_strdup_printf ("%s:%s", account->uid, node); - else - node = g_strdup_printf ("%s:%s", si->display_name, node); - - if (g_hash_table_lookup (priv->expanded, node)) { - printf ("expanding node '%s'\n", node); - gtk_tree_view_expand_to_path (priv->treeview, path); - } - - gtk_tree_path_free (path); - g_free (node); -#endif -} - #if 0 static void dump_fi (CamelFolderInfo *fi, int depth) @@ -1140,7 +1026,7 @@ em_folder_tree_get_folder_info__got (struct _mail_msg *mm) return; /* check that our parent folder hasn't been deleted/unsubscribed */ - if (!gtk_tree_row_reference_is_valid (m->root)) + if (!gtk_tree_row_reference_valid (m->root)) return; if (!(si = g_hash_table_lookup (priv->model->store_hash, m->store))) { @@ -1178,7 +1064,7 @@ em_folder_tree_get_folder_info__got (struct _mail_msg *mm) gtk_tree_store_remove (model, &iter); } else { do { - tree_store_set_folder_info (model, &iter, priv, si, fi); + em_folder_tree_model_set_folder_info (priv->model, &iter, si, fi); if ((fi = fi->sibling) != NULL) gtk_tree_store_append (model, &iter, &root); @@ -2069,335 +1955,6 @@ tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft) } -static void -folder_subscribed_cb (CamelStore *store, void *event_data, EMFolderTree *emft) -{ - struct _EMFolderTreePrivate *priv = emft->priv; - struct _EMFolderTreeModelStoreInfo *si; - CamelFolderInfo *fi = event_data; - GtkTreeRowReference *row; - GtkTreeIter parent, iter; - GtkTreeModel *model; - GtkTreePath *path; - gboolean load; - char *dirname; - - if (!(si = g_hash_table_lookup (priv->model->store_hash, store))) - return; - - /* make sure we don't already know about it? */ - if (g_hash_table_lookup (si->path_hash, fi->path)) - return; - - /* get our parent folder's path */ - if (!(dirname = g_path_get_dirname (fi->path))) - return; - - if (!strcmp (dirname, "/")) { - /* user subscribed to a toplevel folder */ - row = si->row; - g_free (dirname); - } else { - row = g_hash_table_lookup (si->path_hash, dirname); - g_free (dirname); - - /* if row is NULL, don't bother adding to the tree, - * when the user expands enough nodes - it will be - * added auto-magically */ - if (row == NULL) - return; - } - - path = gtk_tree_row_reference_get_path (row); - model = gtk_tree_view_get_model (priv->treeview); - if (!(gtk_tree_model_get_iter (model, &parent, path))) { - gtk_tree_path_free (path); - return; - } - - gtk_tree_path_free (path); - - /* make sure parent's subfolders have already been loaded */ - gtk_tree_model_get (model, &parent, COL_BOOL_LOAD_SUBDIRS, &load, -1); - if (load) - return; - - /* append a new node */ - gtk_tree_store_append ((GtkTreeStore *) model, &iter, &parent); - - tree_store_set_folder_info ((GtkTreeStore *) model, &iter, priv, si, fi); -} - -static void -remove_folders (EMFolderTree *emft, GtkTreeModel *model, struct _EMFolderTreeModelStoreInfo *si, GtkTreeIter *toplevel) -{ - struct _EMFolderTreePrivate *priv = emft->priv; - GtkTreeRowReference *row; - char *uri, *folder_path; - gboolean is_store, go; - GtkTreeIter iter; - - if (gtk_tree_model_iter_children (model, &iter, toplevel)) { - do { - GtkTreeIter next = iter; - - go = gtk_tree_model_iter_next (model, &next); - remove_folders (emft, model, si, &iter); - iter = next; - } while (go); - } - - gtk_tree_model_get (model, toplevel, COL_STRING_URI, &uri, - COL_STRING_FOLDER_PATH, &folder_path, - COL_BOOL_IS_STORE, &is_store, -1); - - if ((row = g_hash_table_lookup (si->path_hash, folder_path))) { - g_hash_table_remove (si->path_hash, folder_path); - gtk_tree_row_reference_free (row); - } - - em_folder_tree_model_remove_uri (priv->model, uri); - - gtk_tree_store_remove ((GtkTreeStore *) model, toplevel); - - if (is_store) - em_folder_tree_model_remove_store_info (priv->model, si->store); -} - -static void -folder_unsubscribed_cb (CamelStore *store, void *event_data, EMFolderTree *emft) -{ - struct _EMFolderTreePrivate *priv = emft->priv; - struct _EMFolderTreeModelStoreInfo *si; - CamelFolderInfo *fi = event_data; - GtkTreeRowReference *row; - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - - if (!(si = g_hash_table_lookup (priv->model->store_hash, store))) - return; - - if (!(row = g_hash_table_lookup (si->path_hash, fi->path))) - return; - - path = gtk_tree_row_reference_get_path (row); - model = gtk_tree_view_get_model (emft->priv->treeview); - if (!(gtk_tree_model_get_iter (model, &iter, path))) { - gtk_tree_path_free (path); - return; - } - - remove_folders (emft, model, si, &iter); -} - -static void -folder_created_cb (CamelStore *store, void *event_data, EMFolderTree *emft) -{ - /* we only want created events to do more work if we don't support subscriptions */ - if (!camel_store_supports_subscriptions (store)) - folder_subscribed_cb (store, event_data, emft); -} - -static void -folder_deleted_cb (CamelStore *store, void *event_data, EMFolderTree *emft) -{ - /* we only want deleted events to do more work if we don't support subscriptions */ - if (!camel_store_supports_subscriptions (store)) - folder_unsubscribed_cb (store, event_data, emft); -} - -static void -folder_renamed_cb (CamelStore *store, void *event_data, EMFolderTree *emft) -{ - struct _EMFolderTreePrivate *priv = emft->priv; - struct _EMFolderTreeModelStoreInfo *si; - CamelRenameInfo *info = event_data; - GtkTreeRowReference *row; - GtkTreeIter root, iter; - GtkTreeModel *model; - GtkTreePath *path; - char *parent, *p; - - if (!(si = g_hash_table_lookup (priv->model->store_hash, store))) - return; - - parent = g_strdup_printf ("/%s", info->old_base); - if (!(row = g_hash_table_lookup (si->path_hash, parent))) { - g_free (parent); - return; - } - g_free (parent); - - path = gtk_tree_row_reference_get_path (row); - model = gtk_tree_view_get_model (emft->priv->treeview); - if (!(gtk_tree_model_get_iter (model, &iter, path))) { - gtk_tree_path_free (path); - return; - } - - remove_folders (emft, model, si, &iter); - - parent = g_strdup (info->new->path); - if ((p = strrchr (parent + 1, '/'))) - *p = '\0'; - - if (!strcmp (parent, "/")) { - /* renamed to a toplevel folder on the store */ - path = gtk_tree_row_reference_get_path (si->row); - } else { - if (!(row = g_hash_table_lookup (si->path_hash, parent))) { - /* NOTE: this should never happen, but I - * suppose if it does in reality, we can add - * code here to add the missing nodes to the - * tree */ - g_assert_not_reached (); - g_free (parent); - return; - } - - path = gtk_tree_row_reference_get_path (row); - } - - g_free (parent); - - if (!gtk_tree_model_get_iter (model, &root, path)) { - gtk_tree_path_free (path); - g_assert_not_reached (); - return; - } - - gtk_tree_store_append ((GtkTreeStore *) model, &iter, &root); - tree_store_set_folder_info ((GtkTreeStore *) model, &iter, priv, si, info->new); -} - - -void -em_folder_tree_add_store (EMFolderTree *emft, CamelStore *store, const char *display_name) -{ - struct _EMFolderTreeModelStoreInfo *si; - struct _EMFolderTreePrivate *priv; - GtkTreeRowReference *row; - GtkTreeIter root, iter; - GtkTreeStore *model; - GtkTreePath *path; - EAccount *account; - char *node, *uri; - - g_return_if_fail (EM_IS_FOLDER_TREE (emft)); - g_return_if_fail (CAMEL_IS_STORE (store)); - g_return_if_fail (display_name != NULL); - - priv = emft->priv; - model = (GtkTreeStore *) gtk_tree_view_get_model (priv->treeview); - - if ((si = g_hash_table_lookup (priv->model->store_hash, store))) { - const char *name; - - path = gtk_tree_row_reference_get_path (si->row); - gtk_tree_model_get_iter ((GtkTreeModel *) model, &iter, path); - gtk_tree_path_free (path); - - gtk_tree_model_get ((GtkTreeModel *) model, &iter, COL_STRING_DISPLAY_NAME, (char **) &name, -1); - - g_warning ("the store `%s' is already in the folder tree as `%s'", - display_name, name); - - return; - } - - uri = camel_url_to_string (((CamelService *) store)->url, CAMEL_URL_HIDE_ALL); - - /* add the store to the tree */ - gtk_tree_store_append (model, &iter, NULL); - gtk_tree_store_set (model, &iter, - COL_STRING_DISPLAY_NAME, display_name, - COL_POINTER_CAMEL_STORE, store, - COL_STRING_FOLDER_PATH, "/", - COL_BOOL_LOAD_SUBDIRS, TRUE, - COL_BOOL_IS_STORE, TRUE, - COL_STRING_URI, uri, -1); - - path = gtk_tree_model_get_path ((GtkTreeModel *) model, &iter); - row = gtk_tree_row_reference_new ((GtkTreeModel *) model, path); - gtk_tree_path_free (path); - - si = g_new (struct _EMFolderTreeModelStoreInfo, 1); - si->display_name = g_strdup (display_name); - camel_object_ref (store); - si->store = store; - si->row = row; - si->path_hash = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_insert (priv->model->store_hash, store, si); - - /* each store has folders... but we don't load them until the user demands them */ - root = iter; - gtk_tree_store_append (model, &iter, &root); - gtk_tree_store_set (model, &iter, - COL_STRING_DISPLAY_NAME, _("Loading..."), - COL_POINTER_CAMEL_STORE, store, - COL_STRING_FOLDER_PATH, "/", - COL_BOOL_LOAD_SUBDIRS, TRUE, - COL_BOOL_IS_STORE, FALSE, - COL_STRING_URI, uri, - COL_UINT_UNREAD, 0, - -1); - - g_free (uri); - - if ((account = mail_config_get_account_by_name (display_name))) - node = g_strdup_printf ("%s:/", account->uid); - else - node = g_strdup_printf ("%s:/", display_name); - - if (g_hash_table_lookup (priv->expanded, node)) { - path = gtk_tree_model_get_path ((GtkTreeModel *) model, &iter); - gtk_tree_view_expand_to_path (priv->treeview, path); - gtk_tree_path_free (path); - } - - g_free (node); - - /* listen to store events */ -#define CAMEL_CALLBACK(func) ((CamelObjectEventHookFunc) func) - si->created_id = camel_object_hook_event (store, "folder_created", CAMEL_CALLBACK (folder_created_cb), emft); - si->deleted_id = camel_object_hook_event (store, "folder_deleted", CAMEL_CALLBACK (folder_deleted_cb), emft); - si->renamed_id = camel_object_hook_event (store, "folder_renamed", CAMEL_CALLBACK (folder_renamed_cb), emft); - si->subscribed_id = camel_object_hook_event (store, "folder_subscribed", CAMEL_CALLBACK (folder_subscribed_cb), emft); - si->unsubscribed_id = camel_object_hook_event (store, "folder_unsubscribed", CAMEL_CALLBACK (folder_unsubscribed_cb), emft); -} - - -void -em_folder_tree_remove_store (EMFolderTree *emft, CamelStore *store) -{ - struct _EMFolderTreeModelStoreInfo *si; - struct _EMFolderTreePrivate *priv; - GtkTreeModel *model; - GtkTreePath *path; - GtkTreeIter iter; - - g_return_if_fail (EM_IS_FOLDER_TREE (emft)); - g_return_if_fail (CAMEL_IS_STORE (store)); - - priv = emft->priv; - model = gtk_tree_view_get_model (priv->treeview); - - if (!(si = g_hash_table_lookup (priv->model->store_hash, store))) { - g_warning ("the store `%s' is not in the folder tree", si->display_name); - - return; - } - - path = gtk_tree_row_reference_get_path (si->row); - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_path_free (path); - - /* recursively remove subfolders and finally the toplevel store */ - remove_folders (emft, model, si, &iter); -} - - void em_folder_tree_set_selected (EMFolderTree *emft, const char *uri) { diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h index b4b845afac..71971b6585 100644 --- a/mail/em-folder-tree.h +++ b/mail/em-folder-tree.h @@ -63,9 +63,6 @@ GType em_folder_tree_get_type (void); GtkWidget *em_folder_tree_new (void); GtkWidget *em_folder_tree_new_with_model (EMFolderTreeModel *model); -void em_folder_tree_add_store (EMFolderTree *emft, CamelStore *store, const char *display_name); -void em_folder_tree_remove_store (EMFolderTree *emft, CamelStore *store); - void em_folder_tree_set_selected (EMFolderTree *emft, const char *uri); const char *em_folder_tree_get_selected_uri (EMFolderTree *emft); const char *em_folder_tree_get_selected_path (EMFolderTree *emft); diff --git a/mail/mail-component.c b/mail/mail-component.c index c278e6217b..6f06889e81 100644 --- a/mail/mail-component.c +++ b/mail/mail-component.c @@ -77,7 +77,7 @@ static BonoboObjectClass *parent_class = NULL; struct _MailComponentPrivate { char *base_directory; - EMFolderTree *emft; + EMFolderTreeModel *model; MailAsyncEvent *async_event; GHashTable *store_hash; /* display_name by store */ @@ -96,7 +96,7 @@ add_store (MailComponent *component, const char *name, CamelStore *store, CamelE { camel_object_ref (store); g_hash_table_insert (component->priv->store_hash, store, g_strdup (name)); - em_folder_tree_add_store (component->priv->emft, store, name); + em_folder_tree_model_add_store (component->priv->model, store, name); mail_note_store (store, NULL, NULL, NULL); } @@ -327,8 +327,8 @@ impl_createControls (PortableServer_Servant servant, GtkWidget *tree_widget; GtkWidget *view_widget; - tree_widget = (GtkWidget *) priv->emft; view_widget = em_folder_browser_new (); + tree_widget = (GtkWidget *) em_folder_tree_new_with_model (priv->model); em_format_set_session ((EMFormat *) ((EMFolderView *) view_widget)->preview, session); gtk_widget_show (tree_widget); @@ -431,7 +431,7 @@ mail_component_init (MailComponent *component) if (camel_mkdir (priv->base_directory, 0777) == -1 && errno != EEXIST) abort (); - priv->emft = (EMFolderTree *) em_folder_tree_new (); + priv->model = em_folder_tree_model_new (); /* EPFIXME: Turn into an object? */ mail_session_init (priv->base_directory); @@ -624,7 +624,7 @@ mail_component_remove_store (MailComponent *component, CamelStore *store) being removed. ?? */ mail_note_store_remove (store); - em_folder_tree_remove_store (priv->emft, store); + em_folder_tree_model_remove_store (priv->model, store); mail_async_event_emit (priv->async_event, MAIL_ASYNC_THREAD, (MailAsyncFunc) store_disconnect, store, NULL, NULL); } @@ -675,12 +675,8 @@ mail_component_remove_folder (MailComponent *component, CamelStore *store, const EMFolderTreeModel * mail_component_get_tree_model (MailComponent *component) { - EMFolderTreeModel *model; - - model = em_folder_tree_get_model (component->priv->emft); - g_object_ref (model); - - return model; + g_object_ref (component->priv->model); + return component->priv->model; } struct _CamelFolder * |