aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog20
-rw-r--r--mail/em-folder-tree-model.c130
-rw-r--r--mail/em-folder-tree-model.h10
-rw-r--r--mail/em-folder-tree.c164
-rw-r--r--mail/mail-component.c4
5 files changed, 192 insertions, 136 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index bec65cd287..8cdf28dcb1 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,23 @@
+2003-12-02 Jeffrey Stedfast <fejj@ximian.com>
+
+ * em-folder-tree.c (em_folder_tree_new): Fixed to pass the
+ evolution dir into em_folder_tree_model_new().
+ (model_save_state): Removed.
+ (em_folder_tree_save_state): Moved all the saving logic into
+ em_folder_tree_model_save_expanded().
+
+ * em-folder-tree-model.c (em_folder_tree_model_new): Load the
+ expanded state off disk.
+ (em_folder_tree_model_save_expanded): New function to save
+ expanded state.
+ (em_folder_tree_model_get_expanded): new function to get if a node
+ should be expanded.
+ (em_folder_tree_model_set_expanded): new function to set the
+ expanded state of a node.
+
+ * mail-component.c (mail_component_init): Pass the evo dir to
+ em_folder_tree_model_new() which now requires it.
+
2003-12-02 Rodney Dawes <dobey@ximian.com>
* Makefile.am: Version the schemas
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
index 677ab8d0fe..e9819346be 100644
--- a/mail/em-folder-tree-model.c
+++ b/mail/em-folder-tree-model.c
@@ -25,7 +25,14 @@
#include <config.h>
#endif
+#include <stdio.h>
#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <camel/camel-file-utils.h>
#include "mail-config.h"
@@ -201,6 +208,7 @@ em_folder_tree_model_init (EMFolderTreeModel *model)
{
model->store_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
model->uri_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ model->expanded = g_hash_table_new (g_str_hash, g_str_equal);
}
static void
@@ -241,6 +249,12 @@ uri_hash_free (gpointer key, gpointer value, gpointer user_data)
gtk_tree_row_reference_free (value);
}
+static gboolean
+expanded_free (gpointer key, gpointer value, gpointer user_data)
+{
+ g_free (key);
+ return TRUE;
+}
static void
em_folder_tree_model_finalize (GObject *obj)
@@ -253,6 +267,11 @@ em_folder_tree_model_finalize (GObject *obj)
g_hash_table_foreach (model->uri_hash, uri_hash_free, NULL);
g_hash_table_destroy (model->uri_hash);
+ g_hash_table_foreach (model->expanded, (GHFunc) expanded_free, NULL);
+ g_hash_table_destroy (model->expanded);
+
+ g_free (model->filename);
+
G_OBJECT_CLASS (parent_class)->finalize (obj);
}
@@ -335,14 +354,37 @@ model_drag_data_delete (GtkTreeDragSource *drag_source, GtkTreePath *src_path)
}
+static void
+em_folder_tree_model_load_state (EMFolderTreeModel *model, const char *filename)
+{
+ char *node;
+ FILE *fp;
+
+ g_hash_table_foreach_remove (model->expanded, expanded_free, NULL);
+
+ if ((fp = fopen (filename, "r")) == NULL)
+ return;
+
+ while (camel_file_util_decode_string (fp, &node) != -1)
+ g_hash_table_insert (model->expanded, node, GINT_TO_POINTER (TRUE));
+
+ fclose (fp);
+}
+
+
EMFolderTreeModel *
-em_folder_tree_model_new (void)
+em_folder_tree_model_new (const char *evolution_dir)
{
EMFolderTreeModel *model;
+ char *filename;
model = g_object_new (EM_TYPE_FOLDER_TREE_MODEL, NULL);
gtk_tree_store_set_column_types ((GtkTreeStore *) model, NUM_COLUMNS, col_types);
+ filename = g_build_filename (evolution_dir, "mail", "config", "folder-tree.state", NULL);
+ em_folder_tree_model_load_state (model, filename);
+ model->filename = filename;
+
return model;
}
@@ -767,3 +809,89 @@ em_folder_tree_model_remove_store (EMFolderTreeModel *model, CamelStore *store)
/* recursively remove subfolders and finally the toplevel store */
em_folder_tree_model_remove_folders (model, si, &iter);
}
+
+
+gboolean
+em_folder_tree_model_get_expanded (EMFolderTreeModel *model, const char *key)
+{
+ if (g_hash_table_lookup (model->expanded, key))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+void
+em_folder_tree_model_set_expanded (EMFolderTreeModel *model, const char *key, gboolean expanded)
+{
+ gpointer okey, oval;
+
+ if (g_hash_table_lookup_extended (model->expanded, key, &okey, &oval)) {
+ g_hash_table_remove (model->expanded, okey);
+ g_free (okey);
+ }
+
+ if (expanded)
+ g_hash_table_insert (model->expanded, g_strdup (key), GINT_TO_POINTER (TRUE));
+}
+
+
+static void
+expanded_save (gpointer key, gpointer value, FILE *fp)
+{
+ if (!GPOINTER_TO_INT (value))
+ return;
+
+ camel_file_util_encode_string (fp, key);
+}
+
+void
+em_folder_tree_model_save_expanded (EMFolderTreeModel *model)
+{
+ char *dirname, *tmpname;
+ FILE *fp;
+ int fd;
+
+ dirname = g_path_get_dirname (model->filename);
+ if (camel_mkdir (dirname, 0777) == -1 && errno != EEXIST) {
+ g_free (dirname);
+ return;
+ }
+
+ g_free (dirname);
+ tmpname = g_strdup_printf ("%s~", model->filename);
+
+ if (!(fp = fopen (tmpname, "w+"))) {
+ g_free (tmpname);
+ return;
+ }
+
+ g_hash_table_foreach (model->expanded, (GHFunc) expanded_save, fp);
+
+ if (fflush (fp) != 0)
+ goto exception;
+
+ if ((fd = fileno (fp)) == -1)
+ goto exception;
+
+ if (fsync (fd) == -1)
+ goto exception;
+
+ fclose (fp);
+ fp = NULL;
+
+ if (rename (tmpname, model->filename) == -1)
+ goto exception;
+
+ g_free (tmpname);
+
+ return;
+
+ exception:
+
+ if (fp != NULL)
+ fclose (fp);
+
+ unlink (tmpname);
+ g_free (tmpname);
+}
diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h
index e8755f0578..f06591bfbd 100644
--- a/mail/em-folder-tree-model.h
+++ b/mail/em-folder-tree-model.h
@@ -78,9 +78,11 @@ struct _EMFolderTreeModelStoreInfo {
struct _EMFolderTreeModel {
GtkTreeStore parent_object;
+ char *filename; /* state filename */
+
GHashTable *store_hash; /* maps CamelStore's to store-info's */
GHashTable *uri_hash; /* maps URI's to GtkTreeRowReferences */
- GHashTable *expanded;
+ GHashTable *expanded; /* saved expanded state from previous session */
};
struct _EMFolderTreeModelClass {
@@ -107,7 +109,7 @@ struct _EMFolderTreeModelClass {
GType em_folder_tree_model_get_type (void);
-EMFolderTreeModel *em_folder_tree_model_new (void);
+EMFolderTreeModel *em_folder_tree_model_new (const char *evolution_dir);
void em_folder_tree_model_set_folder_info (EMFolderTreeModel *model, GtkTreeIter *iter,
@@ -119,6 +121,10 @@ void em_folder_tree_model_remove_store (EMFolderTreeModel *model, CamelStore *st
void em_folder_tree_model_remove_folders (EMFolderTreeModel *model, struct _EMFolderTreeModelStoreInfo *si,
GtkTreeIter *toplevel);
+gboolean em_folder_tree_model_get_expanded (EMFolderTreeModel *model, const char *key);
+void em_folder_tree_model_set_expanded (EMFolderTreeModel *model, const char *key, gboolean expanded);
+void em_folder_tree_model_save_expanded (EMFolderTreeModel *model);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index 7aad5a8260..32c1828765 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -69,8 +69,6 @@ struct _EMFolderTreePrivate {
GtkTreeView *treeview;
EMFolderTreeModel *model;
- GHashTable *expanded;
-
char *selected_uri;
char *selected_path;
@@ -287,52 +285,17 @@ render_display_name (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
g_free (display);
}
-
-static gboolean
-expanded_free (gpointer key, gpointer value, gpointer user_data)
-{
- g_free (key);
- return TRUE;
-}
-
-static void
-em_folder_tree_load_state (EMFolderTree *emft)
-{
- struct _EMFolderTreePrivate *priv = emft->priv;
- char *filename, *node;
- const char *dirname;
- FILE *fp;
-
- g_hash_table_foreach_remove (priv->expanded, expanded_free, NULL);
-
- /*dirname = mail_component_peek_base_directory (mail_component_peek ());*/
- dirname = "/home/null/.evolution";
- filename = g_build_filename (dirname, "mail", "config", "folder-tree.state", NULL);
- if ((fp = fopen (filename, "r")) == NULL) {
- g_free (filename);
- return;
- }
-
- while (camel_file_util_decode_string (fp, &node) != -1)
- g_hash_table_insert (priv->expanded, node, GINT_TO_POINTER (TRUE));
-
- fclose (fp);
-}
-
static void
em_folder_tree_init (EMFolderTree *emft)
{
struct _EMFolderTreePrivate *priv;
priv = g_new0 (struct _EMFolderTreePrivate, 1);
- priv->expanded = g_hash_table_new (g_str_hash, g_str_equal);
priv->selected_uri = NULL;
priv->selected_path = NULL;
priv->treeview = NULL;
priv->model = NULL;
emft->priv = priv;
-
- em_folder_tree_load_state (emft);
}
static void
@@ -340,9 +303,6 @@ em_folder_tree_finalize (GObject *obj)
{
EMFolderTree *emft = (EMFolderTree *) obj;
- g_hash_table_foreach (emft->priv->expanded, (GHFunc) g_free, NULL);
- g_hash_table_destroy (emft->priv->expanded);
-
g_free (emft->priv->selected_uri);
g_free (emft->priv->selected_path);
g_free (emft->priv);
@@ -860,7 +820,7 @@ em_folder_tree_new (void)
EMFolderTreeModel *model;
EMFolderTree *emft;
- model = em_folder_tree_model_new ();
+ model = em_folder_tree_model_new (mail_component_peek_base_directory (mail_component_peek ()));
emft = (EMFolderTree *) em_folder_tree_new_with_model (model);
priv = emft->priv;
@@ -954,7 +914,8 @@ em_folder_tree_new_with_model (EMFolderTreeModel *model)
em_folder_tree_construct (emft, model);
g_object_ref (model);
- g_hash_table_foreach (emft->priv->expanded, (GHFunc) expand_node, emft);
+ /* FIXME: this sucks... */
+ g_hash_table_foreach (model->expanded, (GHFunc) expand_node, emft);
return (GtkWidget *) emft;
}
@@ -1101,8 +1062,33 @@ static struct _mail_msg_op get_folder_info_op = {
};
static void
+update_model_expanded_state (struct _EMFolderTreePrivate *priv, GtkTreeIter *iter, gboolean expanded)
+{
+ struct _EMFolderTreeModelStoreInfo *si;
+ CamelStore *store;
+ EAccount *account;
+ char *path, *key;
+
+ gtk_tree_model_get ((GtkTreeModel *) priv->model, iter,
+ COL_STRING_FOLDER_PATH, &path,
+ COL_POINTER_CAMEL_STORE, &store,
+ -1);
+
+ si = g_hash_table_lookup (priv->model->store_hash, store);
+ if ((account = mail_config_get_account_by_name (si->display_name))) {
+ key = g_strdup_printf ("%s:%s", account->uid, path);
+ } else {
+ key = g_strdup_printf ("%s:%s", si->display_name, path);
+ }
+
+ em_folder_tree_model_set_expanded (priv->model, key, expanded);
+ g_free (key);
+}
+
+static void
tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_path, EMFolderTree *emft)
{
+ struct _EMFolderTreePrivate *priv = emft->priv;
struct _EMFolderTreeGetFolderInfo *m;
GtkTreeModel *model;
CamelStore *store;
@@ -1117,6 +1103,9 @@ tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_p
COL_POINTER_CAMEL_STORE, &store,
COL_BOOL_LOAD_SUBDIRS, &load,
-1);
+
+ update_model_expanded_state (priv, root, TRUE);
+
if (!load) {
em_folder_tree_queue_save_state (emft);
return;
@@ -1142,6 +1131,7 @@ tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_p
static void
tree_row_collapsed (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_path, EMFolderTree *emft)
{
+ update_model_expanded_state (emft->priv, root, FALSE);
em_folder_tree_queue_save_state (emft);
}
@@ -2069,104 +2059,16 @@ em_folder_tree_get_model (EMFolderTree *emft)
static void
-model_save_state (FILE *fp, struct _EMFolderTreePrivate *priv, GtkTreeModel *model, GtkTreeIter *node)
-{
- struct _EMFolderTreeModelStoreInfo *si;
- GtkTreePath *tree_path;
- char *alias, *path;
- EAccount *account;
- CamelStore *store;
- GtkTreeIter iter;
-
- do {
- tree_path = gtk_tree_model_get_path (model, node);
- if (gtk_tree_view_row_expanded (priv->treeview, tree_path)) {
- gtk_tree_model_get (model, node, COL_POINTER_CAMEL_STORE, &store, COL_STRING_FOLDER_PATH, &path, -1);
- si = g_hash_table_lookup (priv->model->store_hash, store);
- if ((account = mail_config_get_account_by_name (si->display_name))) {
- alias = g_strdup_printf ("%s:%s", account->uid, path);
- } else {
- alias = g_strdup_printf ("%s:%s", si->display_name, path);
- }
- camel_file_util_encode_string (fp, alias);
- g_free (alias);
-
- if (gtk_tree_model_iter_children (model, &iter, node))
- model_save_state (fp, priv, model, &iter);
- }
- gtk_tree_path_free (tree_path);
- } while (gtk_tree_model_iter_next (model, node));
-}
-
-
-static void
em_folder_tree_save_state (EMFolderTree *emft)
{
struct _EMFolderTreePrivate *priv = emft->priv;
- char *dirname, *filename, *tmpname;
- GtkTreeModel *model;
- GtkTreeIter iter;
- FILE *fp;
- int fd;
if (priv->save_state_id != 0) {
g_source_remove (priv->save_state_id);
priv->save_state_id = 0;
}
- model = gtk_tree_view_get_model (priv->treeview);
-
- if (!gtk_tree_model_get_iter_first (model, &iter))
- return;
-
- dirname = (char *) mail_component_peek_base_directory (mail_component_peek ());
- dirname = g_build_filename (dirname, "mail", "config", NULL);
-
- if (camel_mkdir (dirname, 0777) == -1 && errno != EEXIST) {
- g_free (dirname);
- return;
- }
-
- tmpname = g_build_filename (dirname, "folder-tree.state~", NULL);
- filename = g_build_filename (dirname, "folder-tree.state", NULL);
- g_free (dirname);
-
- if (!(fp = fopen (tmpname, "w+"))) {
- g_free (filename);
- g_free (tmpname);
- return;
- }
-
- model_save_state (fp, priv, model, &iter);
-
- if (fflush (fp) != 0)
- goto exception;
-
- if ((fd = fileno (fp)) == -1)
- goto exception;
-
- if (fsync (fd) == -1)
- goto exception;
-
- fclose (fp);
- fp = NULL;
-
- if (rename (tmpname, filename) == -1)
- goto exception;
-
- g_free (filename);
- g_free (tmpname);
-
- return;
-
- exception:
-
- if (fp != NULL)
- fclose (fp);
-
- unlink (tmpname);
- g_free (tmpname);
- g_free (filename);
+ em_folder_tree_model_save_expanded (priv->model);
}
diff --git a/mail/mail-component.c b/mail/mail-component.c
index fd22ad4524..0e3318acf9 100644
--- a/mail/mail-component.c
+++ b/mail/mail-component.c
@@ -448,8 +448,8 @@ mail_component_init (MailComponent *component)
if (camel_mkdir (priv->base_directory, 0777) == -1 && errno != EEXIST)
abort ();
- priv->model = em_folder_tree_model_new ();
-
+ priv->model = em_folder_tree_model_new (priv->base_directory);
+
priv->activity_handler = e_activity_handler_new ();
/* EPFIXME: Turn into an object? */