aboutsummaryrefslogtreecommitdiffstats
path: root/mail/em-folder-tree-model.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/em-folder-tree-model.c')
-rw-r--r--mail/em-folder-tree-model.c445
1 files changed, 8 insertions, 437 deletions
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
index f78405a7c7..f1a667b9f4 100644
--- a/mail/em-folder-tree-model.c
+++ b/mail/em-folder-tree-model.c
@@ -107,38 +107,6 @@ store_info_free (EMFolderTreeModelStoreInfo *si)
g_free (si);
}
-static void
-folder_tree_model_load_state (EMFolderTreeModel *model,
- const gchar *filename)
-{
- xmlNodePtr root, node;
-
- if (model->state)
- xmlFreeDoc (model->state);
-
- if ((model->state = e_xml_parse_file (filename)) != NULL) {
- node = xmlDocGetRootElement (model->state);
- if (!node || strcmp ((gchar *)node->name, "tree-state") != 0) {
- /* it is not expected XML file, thus free it and use the default */
- xmlFreeDoc (model->state);
- } else
- return;
- }
-
- /* setup some defaults - expand "Local Folders" and "Search Folders" */
- model->state = xmlNewDoc ((const guchar *)"1.0");
- root = xmlNewDocNode (model->state, NULL, (const guchar *)"tree-state", NULL);
- xmlDocSetRootElement (model->state, root);
-
- node = xmlNewChild (root, NULL, (const guchar *)"node", NULL);
- xmlSetProp (node, (const guchar *)"name", (const guchar *)"local");
- xmlSetProp (node, (const guchar *)"expand", (const guchar *)"true");
-
- node = xmlNewChild (root, NULL, (const guchar *)"node", NULL);
- xmlSetProp (node, (const guchar *)"name", (const guchar *)"vfolder");
- xmlSetProp (node, (const guchar *)"expand", (const guchar *)"true");
-}
-
static gint
folder_tree_model_sort (GtkTreeModel *model,
GtkTreeIter *a,
@@ -256,10 +224,6 @@ folder_tree_model_finalize (GObject *object)
{
EMFolderTreeModel *model = (EMFolderTreeModel *) object;
- g_free (model->filename);
- if (model->state)
- xmlFreeDoc (model->state);
-
g_hash_table_destroy (model->store_hash);
g_hash_table_destroy (model->uri_hash);
@@ -272,23 +236,6 @@ folder_tree_model_finalize (GObject *object)
}
static void
-folder_tree_model_constructed (GObject *object)
-{
- EMFolderTreeModel *model = EM_FOLDER_TREE_MODEL (object);
- EShellBackend *shell_backend;
- const gchar *config_dir;
- gchar *filename;
-
- shell_backend = model->priv->shell_backend;
- config_dir = e_shell_backend_get_config_dir (shell_backend);
-
- filename = g_build_filename (
- config_dir, "folder-tree-expand-state.xml", NULL);
- folder_tree_model_load_state (model, filename);
- model->filename = filename;
-}
-
-static void
folder_tree_model_class_init (EMFolderTreeModelClass *class)
{
GObjectClass *object_class;
@@ -300,7 +247,6 @@ folder_tree_model_class_init (EMFolderTreeModelClass *class)
object_class->set_property = folder_tree_model_set_property;
object_class->get_property = folder_tree_model_get_property;
object_class->finalize = folder_tree_model_finalize;
- object_class->constructed = folder_tree_model_constructed;
g_object_class_install_property (
object_class,
@@ -361,6 +307,7 @@ folder_tree_model_init (EMFolderTreeModel *model)
G_TYPE_STRING, /* uri */
G_TYPE_UINT, /* unread count */
G_TYPE_UINT, /* flags */
+ G_TYPE_BOOLEAN, /* is expanded in sidebar */
G_TYPE_BOOLEAN, /* is a store node */
G_TYPE_BOOLEAN, /* is a folder node */
G_TYPE_BOOLEAN, /* has not-yet-loaded subfolders */
@@ -399,19 +346,6 @@ folder_tree_model_init (EMFolderTreeModel *model)
model->account_removed_id = g_signal_connect (
model->accounts, "account-removed",
G_CALLBACK (account_removed), model);
- //g_signal_connect (
- // model, "row-changed",
- // G_CALLBACK (emft_model_unread_count_changed), NULL);
-}
-
-static void
-tree_model_iface_init (GtkTreeModelIface *iface)
-{
-}
-
-static void
-tree_sortable_iface_init (GtkTreeSortableIface *iface)
-{
}
GType
@@ -433,41 +367,20 @@ em_folder_tree_model_get_type (void)
NULL /* value_table */
};
- static const GInterfaceInfo tree_model_info = {
- (GInterfaceInitFunc) tree_model_iface_init,
- NULL,
- NULL
- };
-
- static const GInterfaceInfo sortable_info = {
- (GInterfaceInitFunc) tree_sortable_iface_init,
- NULL,
- NULL
- };
-
type = g_type_register_static (
GTK_TYPE_TREE_STORE, "EMFolderTreeModel",
&type_info, 0);
-
- g_type_add_interface_static (
- type, GTK_TYPE_TREE_MODEL, &tree_model_info);
- g_type_add_interface_static (
- type, GTK_TYPE_TREE_SORTABLE, &sortable_info);
}
return type;
}
-
static void
emft_model_unread_count_changed (GtkTreeModel *model, GtkTreeIter *iter)
{
GtkTreeIter parent_iter;
GtkTreeIter child_iter = *iter;
- g_signal_handlers_block_by_func (
- model, emft_model_unread_count_changed, NULL);
-
/* Folders are displayed with a bold weight to indicate that
they contain unread messages. We signal that parent rows
have changed here to update them. */
@@ -480,14 +393,8 @@ emft_model_unread_count_changed (GtkTreeModel *model, GtkTreeIter *iter)
gtk_tree_path_free (parent_path);
child_iter = parent_iter;
}
-
- g_signal_handlers_unblock_by_func (
- model, emft_model_unread_count_changed, NULL);
}
-
-
-
EMFolderTreeModel *
em_folder_tree_model_new (EMailShellBackend *mail_shell_backend)
{
@@ -1012,7 +919,7 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model, CamelStore *store, con
camel_object_ref (store);
si->store = store;
si->account = account;
- si->row = row;
+ si->row = gtk_tree_row_reference_copy (row);
si->full_hash = g_hash_table_new_full (
g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
@@ -1020,6 +927,9 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model, CamelStore *store, con
g_hash_table_insert (model->store_hash, store, si);
g_hash_table_insert (model->account_hash, account, si);
+ /* Transfer ownership of the URI and GtkTreeRowReference. */
+ g_hash_table_insert (model->uri_hash, uri, row);
+
/* 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);
@@ -1034,8 +944,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model, CamelStore *store, con
COL_UINT_UNREAD_LAST_SEL, 0,
-1);
- g_free (uri);
-
/* 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);
@@ -1133,275 +1041,6 @@ em_folder_tree_model_remove_store (EMFolderTreeModel *model, CamelStore *store)
em_folder_tree_model_remove_folders (model, si, &iter);
}
-
-static xmlNodePtr
-find_xml_node (xmlNodePtr root, const gchar *name)
-{
- xmlNodePtr node;
- gchar *nname;
-
- node = root->children;
- while (node != NULL) {
- if (!strcmp ((gchar *)node->name, "node")) {
- nname = (gchar *)xmlGetProp (node, (const guchar *)"name");
- if (nname && !strcmp (nname, name)) {
- xmlFree (nname);
- return node;
- }
-
- xmlFree (nname);
- }
-
- node = node->next;
- }
-
- return node;
-}
-
-gboolean
-em_folder_tree_model_get_expanded (EMFolderTreeModel *model, const gchar *key)
-{
- xmlNodePtr node;
- const gchar *name;
- gchar *buf, *p;
-
- /* This code needs to be rewritten.
- First it doesn't belong on the model
- Second, it shouldn't use an xml tree to store a bit table in memory! */
-
- node = model->state ? model->state->children : NULL;
- if (!node || strcmp ((gchar *)node->name, "tree-state") != 0)
- return FALSE;
-
- name = buf = g_alloca (strlen (key) + 1);
- p = g_stpcpy (buf, key);
- if (p[-1] == '/')
- p[-1] = '\0';
- p = NULL;
-
- do {
- if ((p = strchr (name, '/')))
- *p = '\0';
-
- if ((node = find_xml_node (node, name))) {
- gboolean expanded;
-
- buf = (gchar *)xmlGetProp (node, (const guchar *)"expand");
- expanded = buf && !strcmp ((gchar *)buf, "true");
- xmlFree (buf);
-
- if (!expanded || p == NULL)
- return expanded;
- }
-
- name = p ? p + 1 : NULL;
- } while (name && node);
-
- return FALSE;
-}
-
-
-void
-em_folder_tree_model_set_expanded (EMFolderTreeModel *model, const gchar *key, gboolean expanded)
-{
- xmlNodePtr node, parent;
- const gchar *name;
- gchar *buf, *p;
-
- if (model->state == NULL)
- model->state = xmlNewDoc ((const guchar *)"1.0");
-
- if (!model->state->children) {
- node = xmlNewDocNode (model->state, NULL, (const guchar *)"tree-state", NULL);
- xmlDocSetRootElement (model->state, node);
- } else {
- node = model->state->children;
- }
-
- name = buf = g_alloca (strlen (key) + 1);
- p = g_stpcpy (buf, key);
- if (p[-1] == '/')
- p[-1] = '\0';
- p = NULL;
-
- do {
- parent = node;
- if ((p = strchr (name, '/')))
- *p = '\0';
-
- if (!(node = find_xml_node (node, name))) {
- if (!expanded) {
- /* node doesn't exist, so we don't need to set expanded to FALSE */
- return;
- }
-
- /* node (or parent node) doesn't exist, need to add it */
- node = xmlNewChild (parent, NULL, (const guchar *)"node", NULL);
- xmlSetProp (node, (const guchar *)"name", (guchar *)name);
- }
-
- xmlSetProp (node, (const guchar *)"expand", (const guchar *)(expanded || p ? "true" : "false"));
-
- name = p ? p + 1 : NULL;
- } while (name);
-}
-
-/**
- * emftm_uri_to_key
- * Converts uri to key used in functions like em_folder_tree_model_[s/g]et_expanded.
- * @param uri Uri to be converted.
- * @return Key of the uri or NULL, if failed. Returned value should be clear by g_free.
- **/
-static gchar *
-emftm_uri_to_key (const gchar *uri)
-{
- CamelException ex = { 0 };
- CamelStore *store;
- CamelURL *url;
- gchar *key;
-
- if (!uri)
- return NULL;
-
- store = (CamelStore *)camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex);
- camel_exception_clear(&ex);
-
- url = camel_url_new (uri, NULL);
-
- if (store == NULL || url == NULL) {
- key = NULL;
- } else {
- const gchar *path;
- EAccount *account;
-
- if (((CamelService *)store)->provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH)
- path = url->fragment;
- else
- path = url->path && url->path[0]=='/' ? url->path+1:url->path;
-
- if (path == NULL)
- path = "";
-
- if ( (account = mail_config_get_account_by_source_url (uri)) )
- key = g_strdup_printf ("%s/%s", account->uid, path);
- else if (CAMEL_IS_VEE_STORE (store))
- key = g_strdup_printf ("vfolder/%s", path);
- else
- key = g_strdup_printf ("local/%s", path);
- }
-
- if (url)
- camel_url_free (url);
-
- if (store)
- camel_object_unref (store);
-
- return key;
-}
-
-/**
- * em_folder_tree_model_get_expanded_uri
- * Same as @ref em_folder_tree_model_get_expanded, but here we use uri, not key for node.
- **/
-gboolean
-em_folder_tree_model_get_expanded_uri (EMFolderTreeModel *model, const gchar *uri)
-{
- gchar *key;
- gboolean expanded;
-
- g_return_val_if_fail (model != NULL, FALSE);
- g_return_val_if_fail (uri != NULL, FALSE);
-
- key = emftm_uri_to_key (uri);
- expanded = key && em_folder_tree_model_get_expanded (model, key);
-
- g_free (key);
-
- return expanded;
-}
-
-/**
- * em_folder_tree_model_set_expanded_uri
- * Same as @ref em_folder_tree_model_set_expanded, but here we use uri, not key for node.
- **/
-void
-em_folder_tree_model_set_expanded_uri (EMFolderTreeModel *model, const gchar *uri, gboolean expanded)
-{
- gchar *key;
-
- g_return_if_fail (model != NULL);
- g_return_if_fail (uri != NULL);
-
- key = emftm_uri_to_key (uri);
- if (key)
- em_folder_tree_model_set_expanded (model, key, expanded);
-
- g_free (key);
-}
-
-void
-em_folder_tree_model_save_state (EMFolderTreeModel *model)
-{
- gchar *dirname;
-
- if (model->state == NULL)
- return;
-
- dirname = g_path_get_dirname (model->filename);
- if (g_mkdir_with_parents (dirname, 0777) == -1 && errno != EEXIST) {
- g_free (dirname);
- return;
- }
-
- g_free (dirname);
-
- e_xml_save_file (model->filename, model->state);
-}
-
-
-static void
-expand_foreach_r (EMFolderTreeModel *model, xmlNodePtr parent, const gchar *dirname, EMFTModelExpandFunc func, gpointer user_data)
-{
- xmlNodePtr node = parent->children;
- gchar *path, *name, *expand;
-
- while (node != NULL) {
- if (!strcmp ((gchar *)node->name, "node")) {
- name = (gchar *)xmlGetProp (node, (const guchar *)"name");
- expand = (gchar *)xmlGetProp (node, (const guchar *)"expand");
-
- if (expand && name && !strcmp ((gchar *)expand, "true")) {
- if (dirname)
- path = g_strdup_printf ("%s/%s", dirname, name);
- else
- path = g_strdup (name);
-
- func (model, path, user_data);
- if (node->children)
- expand_foreach_r (model, node, path, func, user_data);
- g_free (path);
- }
-
- xmlFree (expand);
- xmlFree (name);
- }
-
- node = node->next;
- }
-}
-
-void
-em_folder_tree_model_expand_foreach (EMFolderTreeModel *model, EMFTModelExpandFunc func, gpointer user_data)
-{
- xmlNodePtr root;
-
- root = model->state ? model->state->children : NULL;
- if (!root || !root->children || strcmp ((gchar *)root->name, "tree-state") != 0)
- return;
-
- expand_foreach_r (model, root, NULL, func, user_data);
-}
-
gboolean
em_folder_tree_model_is_type_inbox (EMFolderTreeModel *model, CamelStore *store, const gchar *full)
{
@@ -1487,7 +1126,6 @@ em_folder_tree_model_set_unread_count (EMFolderTreeModel *model, CamelStore *sto
GtkTreePath *tree_path;
GtkTreeIter iter;
guint old_unread = 0;
- gchar *uri, *sel_uri;
g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model));
g_return_if_fail (CAMEL_IS_STORE (store));
@@ -1516,82 +1154,15 @@ em_folder_tree_model_set_unread_count (EMFolderTreeModel *model, CamelStore *sto
gtk_tree_path_free (tree_path);
- sel_uri = em_folder_tree_model_get_selected (model);
gtk_tree_model_get (
GTK_TREE_MODEL (model), &iter,
- COL_UINT_UNREAD_LAST_SEL, &old_unread,
- COL_STRING_URI, &uri, -1);
- if (!(g_strcmp0 (sel_uri, uri) != 0 && unread > old_unread))
- old_unread = unread;
+ COL_UINT_UNREAD_LAST_SEL, &old_unread, -1);
+
gtk_tree_store_set (
GTK_TREE_STORE (model), &iter,
COL_UINT_UNREAD, unread,
- COL_UINT_UNREAD_LAST_SEL, old_unread, -1);
-
- g_free (uri);
- g_free (sel_uri);
+ COL_UINT_UNREAD_LAST_SEL, MIN (old_unread, unread), -1);
/* May be this is from where we should propagate unread count to parents etc. */
emft_model_unread_count_changed (GTK_TREE_MODEL (model), &iter);
}
-
-
-gchar *
-em_folder_tree_model_get_selected (EMFolderTreeModel *model)
-{
- xmlNodePtr node;
- gchar *buf, *uri;
-
- node = model->state ? model->state->children : NULL;
- if (!node || strcmp ((gchar *)node->name, "tree-state") != 0)
- return NULL;
-
- node = node->children;
- while (node != NULL) {
- if (!strcmp ((gchar *)node->name, "selected"))
- break;
- node = node->next;
- }
-
- if (node == NULL)
- return NULL;
-
- buf = (gchar *)xmlGetProp (node, (guchar *)"uri");
- uri = g_strdup (buf);
- xmlFree (buf);
-
- if (uri && !*uri) {
- g_free (uri);
- return NULL;
- }
- return uri;
-}
-
-
-void
-em_folder_tree_model_set_selected (EMFolderTreeModel *model, const gchar *uri)
-{
- xmlNodePtr root, node;
-
- if (model->state == NULL)
- model->state = xmlNewDoc ((guchar *)"1.0");
-
- if (!model->state->children) {
- root = xmlNewDocNode (model->state, NULL, (const guchar *)"tree-state", NULL);
- xmlDocSetRootElement (model->state, root);
- } else {
- root = model->state->children;
- }
-
- node = root->children;
- while (node != NULL) {
- if (!strcmp ((gchar *)node->name, "selected"))
- break;
- node = node->next;
- }
-
- if (node == NULL)
- node = xmlNewChild (root, NULL, (const guchar *)"selected", NULL);
-
- xmlSetProp (node, (const guchar *)"uri", (guchar *)uri);
-}