diff options
-rw-r--r-- | mail/ChangeLog | 20 | ||||
-rw-r--r-- | mail/em-folder-tree-model.c | 130 | ||||
-rw-r--r-- | mail/em-folder-tree-model.h | 10 | ||||
-rw-r--r-- | mail/em-folder-tree.c | 164 | ||||
-rw-r--r-- | mail/mail-component.c | 4 |
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? */ |