From 30ff908fcddcf18107d8b0fd39e4504b2a69ef19 Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Tue, 25 Nov 2003 03:54:13 +0000 Subject: New function to save tree expanded state. 2003-11-24 Jeffrey Stedfast * em-folder-tree.c (em_folder_tree_save_state): New function to save tree expanded state. (em_folder_tree_queue_save_state): New function to queue saving of the expanded state. (em_folder_tree_construct): Connect to the row-collapsed signal. (tree_row_collapsed): Queue a save-state. (tree_row_expanded): Queue a save state. (em_folder_tree_get_folder_info__got): Queue a save-state. svn path=/trunk/; revision=23485 --- mail/ChangeLog | 11 ++++ mail/em-folder-selection.c | 2 + mail/em-folder-tree-model.h | 1 + mail/em-folder-tree.c | 140 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/mail/ChangeLog b/mail/ChangeLog index ba60d0ccd7..e2b69ace82 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,14 @@ +2003-11-24 Jeffrey Stedfast + + * em-folder-tree.c (em_folder_tree_save_state): New function to + save tree expanded state. + (em_folder_tree_queue_save_state): New function to queue saving of + the expanded state. + (em_folder_tree_construct): Connect to the row-collapsed signal. + (tree_row_collapsed): Queue a save-state. + (tree_row_expanded): Queue a save state. + (em_folder_tree_get_folder_info__got): Queue a save-state. + 2003-11-25 Not Zed * em-folder-view.c (em_folder_view_print): set session on print diff --git a/mail/em-folder-selection.c b/mail/em-folder-selection.c index fcb1054a5a..4a73623529 100644 --- a/mail/em-folder-selection.c +++ b/mail/em-folder-selection.c @@ -25,6 +25,8 @@ #include #endif +#include + #include #include diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h index 3d928a2ef5..f120c0dc62 100644 --- a/mail/em-folder-tree-model.h +++ b/mail/em-folder-tree-model.h @@ -64,6 +64,7 @@ struct _EMFolderTreeModel { GHashTable *store_hash; /* maps CamelStore's to store-info's */ GHashTable *uri_hash; /* maps URI's to GtkTreeRowReferences */ + GHashTable *expanded; }; struct _EMFolderTreeModelClass { diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index fce291c5e1..dbcbb50eaa 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "e-util/e-mktemp.h" #include "e-util/e-request.h" @@ -49,6 +50,8 @@ #include "mail-mt.h" #include "mail-ops.h" #include "mail-tools.h" +#include "mail-config.h" +#include "mail-component.h" #include "em-utils.h" #include "em-popup.h" @@ -92,6 +95,8 @@ struct _EMFolderTreePrivate { char *selected_uri; char *selected_path; + guint save_state_id; + /* dnd signal ids */ guint ddr, rdp, rd, ddg, ddd; }; @@ -141,6 +146,10 @@ static void em_folder_tree_init (EMFolderTree *emft); static void em_folder_tree_destroy (GtkObject *obj); static void em_folder_tree_finalize (GObject *obj); +static void em_folder_tree_save_state (EMFolderTree *emft); +static void em_folder_tree_queue_save_state (EMFolderTree *emft); + +static void tree_row_collapsed (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *path, EMFolderTree *emft); static void tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *path, EMFolderTree *emft); static gboolean tree_button_press (GtkWidget *treeview, GdkEventButton *event, EMFolderTree *emft); static void tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft); @@ -349,6 +358,11 @@ em_folder_tree_destroy (GtkObject *obj) priv->ddd = 0; } + if (priv->save_state_id != 0) { + em_folder_tree_save_state ((EMFolderTree *) obj); + priv->save_state_id = 0; + } + priv->treeview = NULL; priv->model = NULL; @@ -402,6 +416,7 @@ em_folder_tree_construct (EMFolderTree *emft, EMFolderTreeModel *model) gtk_widget_show ((GtkWidget *) priv->treeview); g_signal_connect (priv->treeview, "row-expanded", G_CALLBACK (tree_row_expanded), emft); + g_signal_connect (priv->treeview, "row-collapsed", G_CALLBACK (tree_row_collapsed), emft); g_signal_connect (priv->treeview, "button-press-event", G_CALLBACK (tree_button_press), emft); selection = gtk_tree_view_get_selection ((GtkTreeView *) priv->treeview); @@ -1023,6 +1038,8 @@ em_folder_tree_get_folder_info__got (struct _mail_msg *mm) if (m->select_uri) em_folder_tree_set_selected (m->emft, m->select_uri); + + em_folder_tree_queue_save_state (m->emft); } static void @@ -1063,8 +1080,10 @@ tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_p COL_POINTER_CAMEL_STORE, &store, COL_BOOL_LOAD_SUBDIRS, &load, -1); - if (!load) + if (!load) { + em_folder_tree_queue_save_state (emft); return; + } if (!path || !strcmp (path, "/")) top = NULL; @@ -1083,6 +1102,11 @@ tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_p e_thread_put (mail_thread_new, (EMsg *) m); } +static void +tree_row_collapsed (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_path, EMFolderTree *emft) +{ + em_folder_tree_queue_save_state (emft); +} #if 0 static void @@ -2320,3 +2344,117 @@ em_folder_tree_get_model (EMFolderTree *emft) return emft->priv->model; } + + +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); +} + + +static void +em_folder_tree_queue_save_state (EMFolderTree *emft) +{ + struct _EMFolderTreePrivate *priv = emft->priv; + + if (priv->save_state_id != 0) + return; + + priv->save_state_id = g_timeout_add (1000, (GSourceFunc) em_folder_tree_save_state, emft); +} -- cgit