aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-06-10 11:15:20 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-06-13 22:49:05 +0800
commitbe8ee5393471a83b24aed4de1669afd723cb3168 (patch)
treef8a8e50d3830ec32f83fd2fa7e8815ebfc8316dc /mail
parented0cdbd79042a962ec229f739b4c3284b00a4dc0 (diff)
downloadgsoc2013-evolution-be8ee5393471a83b24aed4de1669afd723cb3168.tar
gsoc2013-evolution-be8ee5393471a83b24aed4de1669afd723cb3168.tar.gz
gsoc2013-evolution-be8ee5393471a83b24aed4de1669afd723cb3168.tar.bz2
gsoc2013-evolution-be8ee5393471a83b24aed4de1669afd723cb3168.tar.lz
gsoc2013-evolution-be8ee5393471a83b24aed4de1669afd723cb3168.tar.xz
gsoc2013-evolution-be8ee5393471a83b24aed4de1669afd723cb3168.tar.zst
gsoc2013-evolution-be8ee5393471a83b24aed4de1669afd723cb3168.zip
Use key files for tracking widget states.
Each EShellView now maintains a GKeyFile for recording disposable widget state such as tree view path expansion, scroll bar positions, combo box selections, etc. The EShellView records changes to the key file to ~/.evolution/<shell-backend>/config/state, and automatically restores the GKeyFile at startup. Currently only the mailer uses the key file, but it's intended to serve all shell views. It replaces the use of Camel "cmeta" files, as well as "et-expanded-*" and "folder-tree-expand-state.xml" files. Also, the mailer's folder tree model now includes a column for tracking which sidebar folders are expanded. Folder tree widgets appearing in dialog windows can copy the sidebar's expanded state using em_folder_tree_clone_expanded().
Diffstat (limited to 'mail')
-rw-r--r--mail/e-mail-reader.c4
-rw-r--r--mail/e-mail-shell-content.c176
-rw-r--r--mail/e-mail-shell-sidebar.c344
-rw-r--r--mail/e-mail-shell-view-actions.c129
-rw-r--r--mail/e-mail-shell-view-private.c73
-rw-r--r--mail/e-mail-shell-view-private.h2
-rw-r--r--mail/em-composer-utils.c9
-rw-r--r--mail/em-folder-selection-button.c1
-rw-r--r--mail/em-folder-selection.c67
-rw-r--r--mail/em-folder-selection.h24
-rw-r--r--mail/em-folder-tree-model.c445
-rw-r--r--mail/em-folder-tree-model.h22
-rw-r--r--mail/em-folder-tree.c176
-rw-r--r--mail/em-folder-tree.h3
-rw-r--r--mail/em-folder-utils.c16
-rw-r--r--mail/em-folder-utils.h7
16 files changed, 733 insertions, 765 deletions
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index edea7cfa6f..94855ee68b 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -167,6 +167,8 @@ action_mail_copy_cb (GtkAction *action,
folder = message_list->folder;
+ em_folder_tree_clone_expanded (folder_tree);
+
em_folder_tree_set_excluded (
EM_FOLDER_TREE (folder_tree),
EMFT_EXCLUDE_NOSELECT | EMFT_EXCLUDE_VIRTUAL |
@@ -577,6 +579,8 @@ action_mail_move_cb (GtkAction *action,
folder = message_list->folder;
+ em_folder_tree_clone_expanded (folder_tree);
+
em_folder_tree_set_excluded (
EM_FOLDER_TREE (folder_tree),
EMFT_EXCLUDE_NOSELECT | EMFT_EXCLUDE_VIRTUAL |
diff --git a/mail/e-mail-shell-content.c b/mail/e-mail-shell-content.c
index 203876fcc3..abb7e8fa26 100644
--- a/mail/e-mail-shell-content.c
+++ b/mail/e-mail-shell-content.c
@@ -44,6 +44,9 @@
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_MAIL_SHELL_CONTENT, EMailShellContentPrivate))
+#define STATE_KEY_SCROLLBAR_POSITION "ScrollbarPosition"
+#define STATE_KEY_SELECTED_MESSAGE "SelectedMessage"
+
struct _EMailShellContentPrivate {
GtkWidget *paned;
GtkWidget *message_list;
@@ -52,8 +55,6 @@ struct _EMailShellContentPrivate {
EMFormatHTMLDisplay *html_display;
GalViewInstance *view_instance;
- gchar *selected_uid;
-
/* ETable scrolling hack */
gdouble default_scrollbar_position;
@@ -97,52 +98,78 @@ static void
mail_shell_content_message_list_scrolled_cb (EMailShellContent *mail_shell_content,
MessageList *message_list)
{
+ EShellContent *shell_content;
+ EShellView *shell_view;
+ GKeyFile *key_file;
+ const gchar *folder_uri;
const gchar *key;
+ gchar *group_name;
gdouble position;
- gchar *value;
/* Save the scrollbar position for the current folder. */
- if (message_list->folder == NULL)
+ folder_uri = message_list->folder_uri;
+
+ if (folder_uri == NULL)
return;
- key = "evolution:list_scroll_position";
+ shell_content = E_SHELL_CONTENT (mail_shell_content);
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ key_file = e_shell_view_get_state_key_file (shell_view);
+
+ key = STATE_KEY_SCROLLBAR_POSITION;
+ group_name = g_strdup_printf ("Folder %s", folder_uri);
position = message_list_get_scrollbar_position (message_list);
- value = g_strdup_printf ("%f", position);
- if (camel_object_meta_set (message_list->folder, key, value))
- camel_object_state_write (message_list->folder);
+ g_key_file_set_double (key_file, group_name, key, position);
+ e_shell_view_set_state_dirty (shell_view);
- g_free (value);
+ g_free (group_name);
}
static gboolean
mail_shell_content_scroll_timeout_cb (EMailShellContent *mail_shell_content)
{
EMailShellContentPrivate *priv = mail_shell_content->priv;
+ EShellContent *shell_content;
+ EShellView *shell_view;
MessageList *message_list;
EMailReader *reader;
+ GKeyFile *key_file;
+ const gchar *folder_uri;
const gchar *key;
- gdouble position;
- gchar *value;
+ gchar *group_name;
/* Initialize the scrollbar position for the current folder
* and setup a callback to handle scrollbar position changes. */
+ shell_content = E_SHELL_CONTENT (mail_shell_content);
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ key_file = e_shell_view_get_state_key_file (shell_view);
+
reader = E_MAIL_READER (mail_shell_content);
message_list = e_mail_reader_get_message_list (reader);
- position = priv->default_scrollbar_position;
+ folder_uri = message_list->folder_uri;
+
+ if (folder_uri == NULL)
+ goto skip;
+
+ /* Restore the message list scrollbar position. */
- key = "evolution:list_scroll_position";
- value = camel_object_meta_get (message_list->folder, key);
+ key = STATE_KEY_SCROLLBAR_POSITION;
+ group_name = g_strdup_printf ("Folder %s", folder_uri);
- if (value != NULL) {
- position = strtod (value, NULL);
- g_free (value);
+ if (g_key_file_has_key (key_file, group_name, key, NULL)) {
+ gdouble position;
+
+ position = g_key_file_get_double (
+ key_file, group_name, key, NULL);
+ message_list_set_scrollbar_position (message_list, position);
}
- message_list_set_scrollbar_position (message_list, position);
+ g_free (group_name);
+skip:
priv->message_list_scrolled_id = g_signal_connect_swapped (
message_list, "message-list-scrolled",
G_CALLBACK (mail_shell_content_message_list_scrolled_cb),
@@ -158,37 +185,59 @@ mail_shell_content_message_list_built_cb (EMailShellContent *mail_shell_content,
MessageList *message_list)
{
EMailShellContentPrivate *priv = mail_shell_content->priv;
+ EShellContent *shell_content;
+ EShellView *shell_view;
GtkScrolledWindow *scrolled_window;
GtkWidget *vscrollbar;
- gdouble position = 0.0;
+ GKeyFile *key_file;
+ gchar *uid;
g_signal_handler_disconnect (
message_list, priv->message_list_built_id);
priv->message_list_built_id = 0;
- if (message_list->cursor_uid == NULL && priv->selected_uid != NULL) {
+ shell_content = E_SHELL_CONTENT (mail_shell_content);
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ key_file = e_shell_view_get_state_key_file (shell_view);
+
+ if (message_list->cursor_uid != NULL)
+ uid = NULL;
+
+ else if (message_list->folder_uri == NULL)
+ uid = NULL;
+
+ else if (mail_shell_content->priv->suppress_message_selection)
+ uid = NULL;
+
+ else {
+ const gchar *folder_uri;
+ const gchar *key;
+ gchar *group_name;
+
+ key = STATE_KEY_SELECTED_MESSAGE;
+ folder_uri = message_list->folder_uri;
+ group_name = g_strdup_printf ("Folder %s", folder_uri);
+ uid = g_key_file_get_string (key_file, group_name, key, NULL);
+ g_free (group_name);
+ }
+
+ if (uid != NULL) {
+ CamelFolder *folder;
CamelMessageInfo *info;
- /* If the message isn't in the folder yet, keep selected_uid
- * around, as it could be caught by a set_folder() at some
- * later date. */
- info = camel_folder_get_message_info (
- message_list->folder, priv->selected_uid);
+ folder = message_list->folder;
+ info = camel_folder_get_message_info (folder, uid);
if (info != NULL) {
- camel_folder_free_message_info (
- message_list->folder, info);
- e_mail_reader_set_message (
- E_MAIL_READER (mail_shell_content),
- priv->selected_uid, TRUE);
- g_free (priv->selected_uid);
- priv->selected_uid = NULL;
+ EMailReader *reader;
+
+ reader = E_MAIL_READER (mail_shell_content);
+ e_mail_reader_set_message (reader, uid, TRUE);
+ camel_folder_free_message_info (folder, info);
}
- position = message_list_get_scrollbar_position (message_list);
+ g_free (uid);
}
- priv->default_scrollbar_position = position;
-
/* FIXME This is a gross workaround for an ETable bug that I can't
* fix (Ximian bug #55303).
*
@@ -227,25 +276,38 @@ mail_shell_content_display_view_cb (EMailShellContent *mail_shell_content,
static void
mail_shell_content_message_selected_cb (EMailShellContent *mail_shell_content,
- const gchar *selected_uid,
+ const gchar *message_uid,
MessageList *message_list)
{
- const gchar *key = "evolution:selected_uid";
- CamelFolder *folder;
+ EShellContent *shell_content;
+ EShellView *shell_view;
+ GKeyFile *key_file;
+ const gchar *folder_uri;
+ const gchar *key;
+ gchar *group_name;
- folder = message_list->folder;
+ folder_uri = message_list->folder_uri;
/* This also gets triggered when selecting a store name on
* the sidebar such as "On This Computer", in which case
- * 'folder' will be NULL. */
- if (folder == NULL)
+ * 'folder_uri' will be NULL. */
+ if (folder_uri == NULL)
return;
- if (camel_object_meta_set (folder, key, selected_uid))
- camel_object_state_write (folder);
+ shell_content = E_SHELL_CONTENT (mail_shell_content);
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ key_file = e_shell_view_get_state_key_file (shell_view);
+
+ key = STATE_KEY_SELECTED_MESSAGE;
+ group_name = g_strdup_printf ("Folder %s", folder_uri);
+
+ if (message_uid != NULL)
+ g_key_file_set_string (key_file, group_name, key, message_uid);
+ else
+ g_key_file_remove_key (key_file, group_name, key, NULL);
+ e_shell_view_set_state_dirty (shell_view);
- g_free (mail_shell_content->priv->selected_uid);
- mail_shell_content->priv->selected_uid = NULL;
+ g_free (group_name);
}
static void
@@ -345,19 +407,6 @@ mail_shell_content_dispose (GObject *object)
}
static void
-mail_shell_content_finalize (GObject *object)
-{
- EMailShellContentPrivate *priv;
-
- priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (object);
-
- g_free (priv->selected_uid);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
mail_shell_content_constructed (GObject *object)
{
EMailShellContentPrivate *priv;
@@ -543,7 +592,6 @@ mail_shell_content_set_folder (EMailReader *reader,
EMailReaderIface *default_iface;
MessageList *message_list;
gboolean different_folder;
- gchar *meta_data;
priv = E_MAIL_SHELL_CONTENT_GET_PRIVATE (reader);
@@ -570,15 +618,6 @@ mail_shell_content_set_folder (EMailReader *reader,
if (different_folder)
priv->suppress_message_selection = FALSE;
- if (!priv->suppress_message_selection)
- meta_data = camel_object_meta_get (
- folder, "evolution:selected_uid");
- else
- meta_data = NULL;
-
- g_free (priv->selected_uid);
- priv->selected_uid = meta_data;
-
/* This is a one-time-only callback. */
if (message_list->cursor_uid == NULL && priv->message_list_built_id == 0)
priv->message_list_built_id = g_signal_connect_swapped (
@@ -613,7 +652,6 @@ mail_shell_content_class_init (EMailShellContentClass *class)
object_class->set_property = mail_shell_content_set_property;
object_class->get_property = mail_shell_content_get_property;
object_class->dispose = mail_shell_content_dispose;
- object_class->finalize = mail_shell_content_finalize;
object_class->constructed = mail_shell_content_constructed;
shell_content_class = E_SHELL_CONTENT_CLASS (class);
diff --git a/mail/e-mail-shell-sidebar.c b/mail/e-mail-shell-sidebar.c
index 1b090fa703..10f0062f26 100644
--- a/mail/e-mail-shell-sidebar.c
+++ b/mail/e-mail-shell-sidebar.c
@@ -33,6 +33,8 @@
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarPrivate))
+#define STATE_KEY_EXPANDED "Expanded"
+
struct _EMailShellSidebarPrivate {
GtkWidget *folder_tree;
};
@@ -46,6 +48,301 @@ static gpointer parent_class;
static GType mail_shell_sidebar_type;
static void
+mail_shell_sidebar_restore_state (EMailShellSidebar *mail_shell_sidebar)
+{
+ EShellView *shell_view;
+ EShellSidebar *shell_sidebar;
+ EMFolderTreeModel *folder_tree_model;
+ EMFolderTree *folder_tree;
+ GtkTreeModel *tree_model;
+ GtkTreeView *tree_view;
+ GtkTreeIter iter;
+ GHashTable *hash_table;
+ GKeyFile *key_file;
+ gboolean valid;
+ gchar *selected;
+ gchar **groups;
+ gint ii;
+
+ shell_sidebar = E_SHELL_SIDEBAR (mail_shell_sidebar);
+ shell_view = e_shell_sidebar_get_shell_view (shell_sidebar);
+ key_file = e_shell_view_get_state_key_file (shell_view);
+
+ folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
+ folder_tree_model = em_folder_tree_get_model (folder_tree);
+ hash_table = folder_tree_model->uri_hash;
+
+ tree_view = GTK_TREE_VIEW (folder_tree);
+ tree_model = GTK_TREE_MODEL (folder_tree_model);
+
+ /* Restore selected folder. */
+
+ selected = g_key_file_get_string (
+ key_file, "Folder Tree", "Selected", NULL);
+ if (selected != NULL) {
+ em_folder_tree_set_selected (folder_tree, selected, FALSE);
+ g_free (selected);
+ }
+
+ /* Set the initial folder tree expanded state in two stages:
+ *
+ * 1) Iterate over the "Store" and "Folder" state file groups
+ * and apply the "Expanded" keys where possible.
+ *
+ * 2) Iterate over the top-level nodes in the folder tree
+ * (these are all stores) and expand those that have no
+ * corresponding "Expanded" key in the state file. This
+ * ensures that new stores are expanded by default.
+ *
+ * The expanded state is recorded and maintained in the tree model
+ * so that folder trees in other contexts can duplicate it using
+ * em_folder_tree_clone_expanded().
+ */
+
+ /* Stage 1 */
+
+ groups = g_key_file_get_groups (key_file, NULL);
+
+ for (ii = 0; groups[ii] != NULL; ii++) {
+ GtkTreeRowReference *reference;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ const gchar *group_name = groups[ii];
+ const gchar *key = STATE_KEY_EXPANDED;
+ const gchar *uri;
+ gboolean expanded;
+
+ if (g_str_has_prefix (group_name, "Store ")) {
+ uri = group_name + 6;
+ expanded = TRUE;
+ } else if (g_str_has_prefix (group_name, "Folder ")) {
+ uri = group_name + 7;
+ expanded = FALSE;
+ } else
+ continue;
+
+ if (g_key_file_has_key (key_file, group_name, key, NULL))
+ expanded = g_key_file_get_boolean (
+ key_file, group_name, key, NULL);
+
+ if (!expanded)
+ continue;
+
+ reference = g_hash_table_lookup (hash_table, uri);
+ if (reference == NULL)
+ continue;
+
+ path = gtk_tree_row_reference_get_path (reference);
+ gtk_tree_model_get_iter (tree_model, &iter, path);
+ gtk_tree_view_expand_row (tree_view, path, FALSE);
+ gtk_tree_path_free (path);
+
+ /* The expanded column is used to clone the sidebar's
+ * expanded state in other EMFolderTree instances. */
+ gtk_tree_store_set (
+ GTK_TREE_STORE (tree_model), &iter,
+ COL_BOOL_EXPANDED, TRUE, -1);
+ }
+
+ g_strfreev (groups);
+
+ /* Stage 2 */
+
+ valid = gtk_tree_model_get_iter_first (tree_model, &iter);
+
+ while (valid) {
+ const gchar *key = STATE_KEY_EXPANDED;
+ gchar *group_name;
+ gchar *uri;
+
+ gtk_tree_model_get (
+ tree_model, &iter, COL_STRING_URI, &uri, -1);
+
+ if (uri == NULL)
+ goto next;
+
+ group_name = g_strdup_printf ("Store %s", uri);
+
+ if (!g_key_file_has_key (key_file, group_name, key, NULL)) {
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (tree_model, &iter);
+ gtk_tree_view_expand_row (tree_view, path, FALSE);
+ gtk_tree_path_free (path);
+
+ /* The expanded column is used to clone the sidebar's
+ * expanded state in other EMFolderTree instances. */
+ gtk_tree_store_set (
+ GTK_TREE_STORE (tree_model), &iter,
+ COL_BOOL_EXPANDED, TRUE, -1);
+ }
+
+ g_free (group_name);
+ g_free (uri);
+
+ next:
+ valid = gtk_tree_model_iter_next (tree_model, &iter);
+ }
+}
+
+static void
+mail_shell_sidebar_row_collapsed_cb (EShellSidebar *shell_sidebar,
+ GtkTreeIter *iter,
+ GtkTreePath *path,
+ GtkTreeView *tree_view)
+{
+ EShellView *shell_view;
+ GtkTreeModel *model;
+ GKeyFile *key_file;
+ const gchar *key;
+ gboolean is_folder;
+ gboolean is_store;
+ gchar *group_name;
+ gchar *uri;
+
+ shell_view = e_shell_sidebar_get_shell_view (shell_sidebar);
+ key_file = e_shell_view_get_state_key_file (shell_view);
+
+ model = gtk_tree_view_get_model (tree_view);
+
+ gtk_tree_model_get (
+ model, iter,
+ COL_STRING_URI, &uri,
+ COL_BOOL_IS_STORE, &is_store,
+ COL_BOOL_IS_FOLDER, &is_folder, -1);
+
+ g_return_if_fail (is_store || is_folder);
+
+ /* The expanded column is used to clone the sidebar's
+ * expanded state in other EMFolderTree instances. */
+ gtk_tree_store_set (
+ GTK_TREE_STORE (model), iter,
+ COL_BOOL_EXPANDED, FALSE, -1);
+
+ key = STATE_KEY_EXPANDED;
+ if (is_store)
+ group_name = g_strdup_printf ("Store %s", uri);
+ else
+ group_name = g_strdup_printf ("Folder %s", uri);
+
+ g_key_file_set_boolean (key_file, group_name, key, FALSE);
+ e_shell_view_set_state_dirty (shell_view);
+
+ g_free (group_name);
+ g_free (uri);
+}
+
+static void
+mail_shell_sidebar_row_expanded_cb (EShellSidebar *shell_sidebar,
+ GtkTreeIter *unused,
+ GtkTreePath *path,
+ GtkTreeView *tree_view)
+{
+ EShellView *shell_view;
+ GtkTreeModel *model;
+ GKeyFile *key_file;
+ const gchar *key;
+ gboolean is_folder;
+ gboolean is_store;
+ gchar *group_name;
+ gchar *uri;
+
+ shell_view = e_shell_sidebar_get_shell_view (shell_sidebar);
+ key_file = e_shell_view_get_state_key_file (shell_view);
+
+ path = gtk_tree_path_copy (path);
+ model = gtk_tree_view_get_model (tree_view);
+
+ /* Expand the node and all ancestors. */
+ while (gtk_tree_path_get_depth (path) > 0) {
+ GtkTreeIter iter;
+
+ gtk_tree_model_get_iter (model, &iter, path);
+
+ gtk_tree_model_get (
+ model, &iter,
+ COL_STRING_URI, &uri,
+ COL_BOOL_IS_STORE, &is_store,
+ COL_BOOL_IS_FOLDER, &is_folder, -1);
+
+ g_return_if_fail (is_store || is_folder);
+
+ /* The expanded column is used to clone the sidebar's
+ * expanded state in other EMFolderTree instances. */
+ gtk_tree_store_set (
+ GTK_TREE_STORE (model), &iter,
+ COL_BOOL_EXPANDED, TRUE, -1);
+
+ key = STATE_KEY_EXPANDED;
+ if (is_store)
+ group_name = g_strdup_printf ("Store %s", uri);
+ else
+ group_name = g_strdup_printf ("Folder %s", uri);
+
+ g_key_file_set_boolean (key_file, group_name, key, TRUE);
+ e_shell_view_set_state_dirty (shell_view);
+
+ g_free (group_name);
+ g_free (uri);
+
+ gtk_tree_path_up (path);
+ }
+
+ gtk_tree_path_free (path);
+}
+
+static void
+mail_shell_sidebar_model_loaded_row_cb (EMailShellSidebar *mail_shell_sidebar,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ GtkTreeModel *model)
+{
+ EShellSidebar *shell_sidebar;
+ EShellView *shell_view;
+ GtkTreeView *tree_view;
+ GKeyFile *key_file;
+ gboolean is_folder;
+ gboolean is_store;
+ const gchar *key;
+ gchar *group_name;
+ gchar *uri;
+ gboolean expanded;
+
+ shell_sidebar = E_SHELL_SIDEBAR (mail_shell_sidebar);
+ shell_view = e_shell_sidebar_get_shell_view (shell_sidebar);
+ key_file = e_shell_view_get_state_key_file (shell_view);
+
+ tree_view = GTK_TREE_VIEW (mail_shell_sidebar->priv->folder_tree);
+
+ gtk_tree_model_get (
+ model, iter,
+ COL_STRING_URI, &uri,
+ COL_BOOL_IS_STORE, &is_store,
+ COL_BOOL_IS_FOLDER, &is_folder, -1);
+
+ g_return_if_fail (is_store || is_folder);
+
+ key = STATE_KEY_EXPANDED;
+ if (is_store) {
+ group_name = g_strdup_printf ("Store %s", uri);
+ expanded = TRUE;
+ } else {
+ group_name = g_strdup_printf ("Folder %s", uri);
+ expanded = FALSE;
+ }
+
+ if (g_key_file_has_key (key_file, group_name, key, NULL))
+ expanded = g_key_file_get_boolean (
+ key_file, group_name, key, NULL);
+
+ if (expanded)
+ gtk_tree_view_expand_row (tree_view, path, FALSE);
+
+ g_free (group_name);
+ g_free (uri);
+}
+
+static void
mail_shell_sidebar_selection_changed_cb (EShellSidebar *shell_sidebar,
GtkTreeSelection *selection)
{
@@ -53,21 +350,34 @@ mail_shell_sidebar_selection_changed_cb (EShellSidebar *shell_sidebar,
EShellViewClass *shell_view_class;
GtkTreeModel *model;
GtkTreeIter iter;
+ GKeyFile *key_file;
const gchar *icon_name;
gchar *display_name = NULL;
+ gchar *uri = NULL;
gboolean is_folder = FALSE;
guint flags = 0;
shell_view = e_shell_sidebar_get_shell_view (shell_sidebar);
shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view);
+ key_file = e_shell_view_get_state_key_file (shell_view);
if (gtk_tree_selection_get_selected (selection, &model, &iter))
gtk_tree_model_get (
model, &iter,
COL_STRING_DISPLAY_NAME, &display_name,
+ COL_STRING_URI, &uri,
COL_BOOL_IS_FOLDER, &is_folder,
COL_UINT_FLAGS, &flags, -1);
+ if (uri != NULL)
+ g_key_file_set_string (
+ key_file, "Folder Tree", "Selected", uri);
+ else
+ g_key_file_remove_key (
+ key_file, "Folder Tree", "Selected", NULL);
+
+ e_shell_view_set_state_dirty (shell_view);
+
if (is_folder)
icon_name = em_folder_utils_get_icon_name (flags);
else {
@@ -79,6 +389,7 @@ mail_shell_sidebar_selection_changed_cb (EShellSidebar *shell_sidebar,
e_shell_sidebar_set_primary_text (shell_sidebar, display_name);
g_free (display_name);
+ g_free (uri);
}
static void
@@ -128,8 +439,9 @@ mail_shell_sidebar_finalize (GObject *object)
static void
mail_shell_sidebar_constructed (GObject *object)
{
- EMailShellSidebarPrivate *priv;
EMailShellBackend *mail_shell_backend;
+ EMailShellSidebar *mail_shell_sidebar;
+ EMFolderTreeModel *folder_tree_model;
EShellSidebar *shell_sidebar;
EShellBackend *shell_backend;
EShellView *shell_view;
@@ -138,15 +450,18 @@ mail_shell_sidebar_constructed (GObject *object)
GtkWidget *container;
GtkWidget *widget;
- priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object);
-
/* Chain up to parent's constructed method. */
G_OBJECT_CLASS (parent_class)->constructed (object);
shell_sidebar = E_SHELL_SIDEBAR (object);
shell_view = e_shell_sidebar_get_shell_view (shell_sidebar);
shell_backend = e_shell_view_get_shell_backend (shell_view);
+
mail_shell_backend = E_MAIL_SHELL_BACKEND (shell_backend);
+ mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (object);
+
+ folder_tree_model = e_mail_shell_backend_get_folder_tree_model (
+ mail_shell_backend);
/* Build sidebar widgets. */
@@ -163,16 +478,33 @@ mail_shell_sidebar_constructed (GObject *object)
container = widget;
- widget = em_folder_tree_new (mail_shell_backend);
+ widget = em_folder_tree_new_with_model (folder_tree_model);
em_folder_tree_set_excluded (EM_FOLDER_TREE (widget), 0);
em_folder_tree_enable_drag_and_drop (EM_FOLDER_TREE (widget));
gtk_container_add (GTK_CONTAINER (container), widget);
- priv->folder_tree = g_object_ref (widget);
+ mail_shell_sidebar->priv->folder_tree = g_object_ref (widget);
gtk_widget_show (widget);
- tree_view = GTK_TREE_VIEW (priv->folder_tree);
+ tree_view = GTK_TREE_VIEW (mail_shell_sidebar->priv->folder_tree);
selection = gtk_tree_view_get_selection (tree_view);
+ mail_shell_sidebar_restore_state (mail_shell_sidebar);
+
+ g_signal_connect_swapped (
+ tree_view, "row-collapsed",
+ G_CALLBACK (mail_shell_sidebar_row_collapsed_cb),
+ shell_sidebar);
+
+ g_signal_connect_swapped (
+ tree_view, "row-expanded",
+ G_CALLBACK (mail_shell_sidebar_row_expanded_cb),
+ shell_sidebar);
+
+ g_signal_connect_swapped (
+ folder_tree_model, "loaded-row",
+ G_CALLBACK (mail_shell_sidebar_model_loaded_row_cb),
+ shell_sidebar);
+
g_signal_connect_swapped (
selection, "changed",
G_CALLBACK (mail_shell_sidebar_selection_changed_cb),
diff --git a/mail/e-mail-shell-view-actions.c b/mail/e-mail-shell-view-actions.c
index 6e4e7fdc8c..e9cba33117 100644
--- a/mail/e-mail-shell-view-actions.c
+++ b/mail/e-mail-shell-view-actions.c
@@ -21,6 +21,10 @@
#include "e-mail-shell-view-private.h"
+#define STATE_KEY_SEARCH_FILTER "SearchFilter"
+#define STATE_KEY_SEARCH_SCOPE "SearchScope"
+#define STATE_KEY_SEARCH_TEXT "SearchText"
+
static void
action_gal_save_custom_view_cb (GtkAction *action,
EMailShellView *mail_shell_view)
@@ -135,6 +139,7 @@ action_mail_folder_copy_cb (GtkAction *action,
EMailShellSidebar *mail_shell_sidebar;
CamelFolderInfo *folder_info;
EMFolderTree *folder_tree;
+ EMFolderTreeModel *model;
mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
@@ -142,7 +147,8 @@ action_mail_folder_copy_cb (GtkAction *action,
g_return_if_fail (folder_info != NULL);
/* XXX Leaking folder_info? */
- em_folder_utils_copy_folder (folder_info, FALSE);
+ model = em_folder_tree_get_model (folder_tree);
+ em_folder_utils_copy_folder (model, folder_info, FALSE);
}
static void
@@ -230,6 +236,7 @@ action_mail_folder_move_cb (GtkAction *action,
EMailShellSidebar *mail_shell_sidebar;
CamelFolderInfo *folder_info;
EMFolderTree *folder_tree;
+ EMFolderTreeModel *model;
mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
@@ -237,7 +244,8 @@ action_mail_folder_move_cb (GtkAction *action,
g_return_if_fail (folder_info != NULL);
/* XXX Leaking folder_info? */
- em_folder_utils_copy_folder (folder_info, TRUE);
+ model = em_folder_tree_get_model (folder_tree);
+ em_folder_utils_copy_folder (model, folder_info, TRUE);
}
static void
@@ -600,19 +608,6 @@ action_mail_label_none_cb (GtkAction *action,
}
static void
-action_mail_preview_cb (GtkToggleAction *action,
- EMailShellView *mail_shell_view)
-{
- EMailShellContent *mail_shell_content;
- gboolean active;
-
- mail_shell_content = mail_shell_view->priv->mail_shell_content;
- active = gtk_toggle_action_get_active (action);
-
- e_mail_shell_content_set_preview_visible (mail_shell_content, active);
-}
-
-static void
action_mail_search_cb (GtkRadioAction *action,
GtkRadioAction *current,
EMailShellView *mail_shell_view)
@@ -883,14 +878,46 @@ action_search_execute_cb (GtkAction *action,
EMailShellView *mail_shell_view)
{
EShellView *shell_view;
+ EShellContent *shell_content;
+ EMailReader *reader;
+ MessageList *message_list;
+ GKeyFile *key_file;
+ const gchar *folder_uri;
+
+ shell_view = E_SHELL_VIEW (mail_shell_view);
+ shell_content = e_shell_view_get_shell_content (shell_view);
+ key_file = e_shell_view_get_state_key_file (shell_view);
/* All shell views respond to the activation of this action,
* which is defined by EShellWindow. But only the currently
* active shell view proceeds with executing the search. */
- shell_view = E_SHELL_VIEW (mail_shell_view);
if (!e_shell_view_is_active (shell_view))
return;
+ reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content);
+ message_list = e_mail_reader_get_message_list (reader);
+ folder_uri = message_list->folder_uri;
+
+ if (folder_uri != NULL) {
+ const gchar *key;
+ const gchar *string;
+ gchar *group_name;
+
+ key = STATE_KEY_SEARCH_TEXT;
+ string = e_shell_content_get_search_text (shell_content);
+ group_name = g_strdup_printf ("Folder %s", folder_uri);
+
+ if (string != NULL && *string != '\0')
+ g_key_file_set_string (
+ key_file, group_name, key, string);
+ else
+ g_key_file_remove_key (
+ key_file, group_name, key, NULL);
+ e_shell_view_set_state_dirty (shell_view);
+
+ g_free (group_name);
+ }
+
e_mail_shell_view_execute_search (mail_shell_view);
}
@@ -899,7 +926,37 @@ action_search_filter_cb (GtkRadioAction *action,
GtkRadioAction *current,
EMailShellView *mail_shell_view)
{
- e_mail_shell_view_execute_search (mail_shell_view);
+ EShellView *shell_view;
+ EShellWindow *shell_window;
+ EMailReader *reader;
+ MessageList *message_list;
+ GKeyFile *key_file;
+ const gchar *folder_uri;
+
+ shell_view = E_SHELL_VIEW (mail_shell_view);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+ key_file = e_shell_view_get_state_key_file (shell_view);
+
+ reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content);
+ message_list = e_mail_reader_get_message_list (reader);
+ folder_uri = message_list->folder_uri;
+
+ if (folder_uri != NULL) {
+ const gchar *key;
+ const gchar *string;
+ gchar *group_name;
+
+ key = STATE_KEY_SEARCH_FILTER;
+ string = gtk_action_get_name (GTK_ACTION (current));
+ group_name = g_strdup_printf ("Folder %s", folder_uri);
+
+ g_key_file_set_string (key_file, group_name, key, string);
+ e_shell_view_set_state_dirty (shell_view);
+
+ g_free (group_name);
+ }
+
+ gtk_action_activate (ACTION (SEARCH_EXECUTE));
}
static void
@@ -907,7 +964,37 @@ action_search_scope_cb (GtkRadioAction *action,
GtkRadioAction *current,
EMailShellView *mail_shell_view)
{
- e_mail_shell_view_execute_search (mail_shell_view);
+ EShellView *shell_view;
+ EShellWindow *shell_window;
+ EMailReader *reader;
+ MessageList *message_list;
+ GKeyFile *key_file;
+ const gchar *folder_uri;
+
+ shell_view = E_SHELL_VIEW (mail_shell_view);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+ key_file = e_shell_view_get_state_key_file (shell_view);
+
+ reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content);
+ message_list = e_mail_reader_get_message_list (reader);
+ folder_uri = message_list->folder_uri;
+
+ if (folder_uri != NULL) {
+ const gchar *key;
+ const gchar *string;
+ gchar *group_name;
+
+ key = STATE_KEY_SEARCH_SCOPE;
+ string = gtk_action_get_name (GTK_ACTION (current));
+ group_name = g_strdup_printf ("Folder %s", folder_uri);
+
+ g_key_file_set_string (key_file, group_name, key, string);
+ e_shell_view_set_state_dirty (shell_view);
+
+ g_free (group_name);
+ }
+
+ gtk_action_activate (ACTION (SEARCH_EXECUTE));
}
static GtkActionEntry mail_entries[] = {
@@ -1205,7 +1292,7 @@ static GtkToggleActionEntry mail_toggle_entries[] = {
N_("Show Message _Preview"),
"<Control>m",
N_("Show message preview pane"),
- G_CALLBACK (action_mail_preview_cb),
+ NULL, /* Handled by property bindings */
TRUE },
{ "mail-threads-group-by",
@@ -1468,6 +1555,10 @@ e_mail_shell_view_actions_init (EMailShellView *mail_shell_view)
dst_object = G_OBJECT (ACTION (MAIL_THREADS_EXPAND_ALL));
e_binding_new (src_object, "active", dst_object, "sensitive");
+ e_mutual_binding_new (
+ G_OBJECT (ACTION (MAIL_PREVIEW)), "active",
+ G_OBJECT (shell_content), "preview-visible");
+
/* XXX The boolean sense of the GConf key is the inverse of
* the menu item, so we have to maintain two properties. */
e_mutual_binding_new_with_negation (
diff --git a/mail/e-mail-shell-view-private.c b/mail/e-mail-shell-view-private.c
index 9026c8ed60..d4fd3c7564 100644
--- a/mail/e-mail-shell-view-private.c
+++ b/mail/e-mail-shell-view-private.c
@@ -30,27 +30,23 @@ mail_shell_view_folder_tree_selected_cb (EMailShellView *mail_shell_view,
guint32 flags,
EMFolderTree *folder_tree)
{
+ EShellView *shell_view;
EMailReader *reader;
gboolean folder_selected;
+ shell_view = E_SHELL_VIEW (mail_shell_view);
reader = E_MAIL_READER (mail_shell_view->priv->mail_shell_content);
folder_selected =
!(flags & CAMEL_FOLDER_NOSELECT) &&
full_name != NULL;
- if (folder_selected) {
- EMFolderTreeModel *model;
-
- model = em_folder_tree_get_model (folder_tree);
- em_folder_tree_model_set_selected (model, uri);
- em_folder_tree_model_save_state (model);
-
+ if (folder_selected)
e_mail_reader_set_folder_uri (reader, uri);
- } else
+ else
e_mail_reader_set_folder (reader, NULL, NULL);
- e_shell_view_update_actions (E_SHELL_VIEW (mail_shell_view));
+ e_shell_view_update_actions (shell_view);
}
static void
@@ -122,7 +118,8 @@ mail_shell_view_message_list_right_click_cb (EShellView *shell_view,
}
static void
-mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view)
+mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view,
+ EMailReader *reader)
{
EMailShellContent *mail_shell_content;
@@ -218,7 +215,6 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
EShellSidebar *shell_sidebar;
EShellWindow *shell_window;
EMFormatHTMLDisplay *html_display;
- EMFolderTreeModel *folder_tree_model;
EMFolderTree *folder_tree;
RuleContext *context;
FilterRule *rule = NULL;
@@ -229,7 +225,6 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
GtkHTML *html;
const gchar *source;
guint merge_id;
- gchar *uri;
gint ii = 0;
shell_view = E_SHELL_VIEW (mail_shell_view);
@@ -298,6 +293,11 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
mail_shell_view);
g_signal_connect_swapped (
+ reader, "folder-loaded",
+ G_CALLBACK (e_mail_shell_view_restore_state),
+ mail_shell_view);
+
+ g_signal_connect_swapped (
tree_model, "row-changed",
G_CALLBACK (e_mail_shell_view_update_search_filter),
mail_shell_view);
@@ -336,24 +336,6 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
priv->search_rules[ii++] = g_object_ref (rule);
}
g_assert (ii == MAIL_NUM_SEARCH_RULES);
-
- /* Restore the previously selected folder. */
- folder_tree_model = em_folder_tree_get_model (folder_tree);
- uri = em_folder_tree_model_get_selected (folder_tree_model);
- if (uri != NULL) {
- gboolean expanded;
-
- expanded = em_folder_tree_model_get_expanded_uri (
- folder_tree_model, uri);
- em_folder_tree_set_selected (folder_tree, uri, FALSE);
- e_mail_reader_set_folder_uri (reader, uri);
-
- if (!expanded)
- em_folder_tree_model_set_expanded_uri (
- folder_tree_model, uri, expanded);
-
- g_free (uri);
- }
}
void
@@ -377,6 +359,33 @@ e_mail_shell_view_private_finalize (EMailShellView *mail_shell_view)
}
void
+e_mail_shell_view_restore_state (EMailShellView *mail_shell_view)
+{
+ EShellView *shell_view;
+ EShellContent *shell_content;
+ EMailReader *reader;
+ MessageList *message_list;
+ const gchar *folder_uri;
+ gchar *group_name;
+
+ /* XXX Move this to EMailShellContent. */
+
+ g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view));
+
+ shell_view = E_SHELL_VIEW (mail_shell_view);
+ shell_content = e_shell_view_get_shell_content (shell_view);
+
+ reader = E_MAIL_READER (shell_content);
+ message_list = e_mail_reader_get_message_list (reader);
+ folder_uri = message_list->folder_uri;
+ g_return_if_fail (folder_uri != NULL);
+
+ group_name = g_strdup_printf ("Folder %s", folder_uri);
+ e_shell_content_restore_state (shell_content, group_name);
+ g_free (group_name);
+}
+
+void
e_mail_shell_view_execute_search (EMailShellView *mail_shell_view)
{
EShell *shell;
@@ -538,7 +547,7 @@ filter:
temp = g_strdup_printf (
"(and %s (match-all "
"(> (get-received-date) "
- "(- (get_current_date) 86400))))",
+ "(- (get-current-date) 86400))))",
query);
g_free (query);
query = temp;
@@ -555,7 +564,7 @@ filter:
temp = g_strdup_printf (
"(and %s (match-all "
"(> (get-received-date) "
- "(- (get_current_date) 432000))))",
+ "(- (get-current-date) 432000))))",
query);
g_free (query);
query = temp;
diff --git a/mail/e-mail-shell-view-private.h b/mail/e-mail-shell-view-private.h
index 13c76c7cfe..f6646cabc2 100644
--- a/mail/e-mail-shell-view-private.h
+++ b/mail/e-mail-shell-view-private.h
@@ -149,6 +149,8 @@ void e_mail_shell_view_private_finalize
void e_mail_shell_view_actions_init
(EMailShellView *mail_shell_view);
+void e_mail_shell_view_restore_state
+ (EMailShellView *mail_shell_view);
void e_mail_shell_view_execute_search
(EMailShellView *mail_shell_view);
void e_mail_shell_view_create_filter_from_selected
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index 74438b2043..6c35a4e7e8 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -117,8 +117,6 @@ emcs_set_drafts_info (struct emcs_t *emcs,
camel_object_ref (drafts_folder);
emcs->drafts_folder = drafts_folder;
emcs->drafts_uid = g_strdup (drafts_uid);
-
- g_debug ("%s", G_STRFUNC);
}
static void
@@ -141,8 +139,6 @@ emcs_set_folder_info (struct emcs_t *emcs,
emcs->uid = g_strdup (uid);
emcs->flags = flags;
emcs->set = set;
-
- g_debug ("%s", G_STRFUNC);
}
static void
@@ -2412,8 +2408,9 @@ post_header_clicked_cb (EComposerPostHeader *header,
model = e_mail_shell_backend_get_folder_tree_model (mail_shell_backend);
folder_tree = em_folder_tree_new_with_model (model);
- em_folder_tree_set_multiselect (
- EM_FOLDER_TREE (folder_tree), TRUE);
+ em_folder_tree_clone_expanded (EM_FOLDER_TREE (folder_tree));
+ em_folder_tree_set_multiselect (EM_FOLDER_TREE (folder_tree), TRUE);
+
em_folder_tree_set_excluded (
EM_FOLDER_TREE (folder_tree),
EMFT_EXCLUDE_NOSELECT |
diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c
index 933393ae80..ecdccc0af7 100644
--- a/mail/em-folder-selection-button.c
+++ b/mail/em-folder-selection-button.c
@@ -256,6 +256,7 @@ folder_selection_button_clicked (GtkButton *button)
emft = (EMFolderTree *) em_folder_tree_new_with_model (priv->model);
+ em_folder_tree_clone_expanded (emft);
em_folder_tree_set_multiselect (emft, priv->multiple_select);
em_folder_tree_set_excluded (
emft, EMFT_EXCLUDE_NOSELECT |
diff --git a/mail/em-folder-selection.c b/mail/em-folder-selection.c
index a0528554d6..56c11bcfdf 100644
--- a/mail/em-folder-selection.c
+++ b/mail/em-folder-selection.c
@@ -33,53 +33,48 @@
#include "em-folder-selector.h"
#include "em-folder-selection.h"
-#include "e-mail-shell-backend.h"
-
/* TODO: rmeove this file, it could just go on em-folder-selection or em-utils */
-struct _select_folder_data {
- void (*done) (const gchar *uri, gpointer data);
- gpointer data;
-};
-
-static void
-emfs_selector_response(EMFolderSelector *emfs, gint response, struct _select_folder_data *d)
-{
- if (response == GTK_RESPONSE_OK) {
- const gchar *uri = em_folder_selector_get_selected_uri(emfs);
-
- d->done(uri, d->data);
- }
-
- gtk_widget_destroy((GtkWidget *)emfs);
-}
-
void
-em_select_folder (GtkWindow *parent_window, const gchar *title, const gchar *oklabel, const gchar *default_uri,
- EMFTExcludeFunc exclude,
- void (*done) (const gchar *uri, gpointer user_data), gpointer user_data)
+em_select_folder (EMFolderTreeModel *model,
+ const gchar *title,
+ const gchar *oklabel,
+ const gchar *default_uri,
+ EMFTExcludeFunc exclude,
+ void (*done) (const gchar *uri, gpointer user_data),
+ gpointer user_data)
{
- struct _select_folder_data *d;
- EMFolderTreeModel *model;
GtkWidget *dialog;
EMFolderTree *emft;
- model = e_mail_shell_backend_get_folder_tree_model (global_mail_shell_backend);
+ g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model));
+ g_return_if_fail (done != NULL);
+
+ /* XXX Do we leak this reference? */
emft = (EMFolderTree *) em_folder_tree_new_with_model (model);
+ em_folder_tree_clone_expanded (emft);
+
if (exclude)
- em_folder_tree_set_excluded_func(emft, exclude, user_data);
+ em_folder_tree_set_excluded_func (emft, exclude, user_data);
else
- em_folder_tree_set_excluded (emft, EMFT_EXCLUDE_NOSELECT|EMFT_EXCLUDE_VIRTUAL|EMFT_EXCLUDE_VTRASH);
+ em_folder_tree_set_excluded (
+ emft, EMFT_EXCLUDE_NOSELECT |
+ EMFT_EXCLUDE_VIRTUAL | EMFT_EXCLUDE_VTRASH);
- dialog = em_folder_selector_new(emft, EM_FOLDER_SELECTOR_CAN_CREATE, title, NULL, oklabel);
+ dialog = em_folder_selector_new (
+ emft, EM_FOLDER_SELECTOR_CAN_CREATE, title, NULL, oklabel);
- d = g_malloc0(sizeof(*d));
- d->data = user_data;
- d->done = done;
- g_signal_connect(dialog, "response", G_CALLBACK (emfs_selector_response), d);
- g_object_set_data_full((GObject *)dialog, "e-select-data", d, (GDestroyNotify)g_free);
- gtk_widget_show(dialog);
+ if (default_uri != NULL)
+ em_folder_selector_set_selected (
+ EM_FOLDER_SELECTOR (dialog), default_uri);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
+ const gchar *uri;
+
+ uri = em_folder_selector_get_selected_uri (
+ EM_FOLDER_SELECTOR (dialog));
+ done (uri, user_data);
+ }
- if (default_uri)
- em_folder_selector_set_selected((EMFolderSelector *)dialog, default_uri);
+ gtk_widget_destroy (dialog);
}
diff --git a/mail/em-folder-selection.h b/mail/em-folder-selection.h
index 098fa2b227..96d14cbc19 100644
--- a/mail/em-folder-selection.h
+++ b/mail/em-folder-selection.h
@@ -24,22 +24,18 @@
#ifndef EM_FOLDER_SELECTION_H
#define EM_FOLDER_SELECTION_H
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
+#include <mail/em-folder-tree-model.h>
-#include "em-folder-tree.h"
+G_BEGIN_DECLS
-struct _GtkWindow;
+void em_select_folder (EMFolderTreeModel *model,
+ const gchar *title,
+ const gchar *oklabel,
+ const gchar *default_uri,
+ EMFTExcludeFunc exclude,
+ void (*done)(const gchar *uri, gpointer data),
+ gpointer data);
-void em_select_folder (struct _GtkWindow *parent_window, const gchar *title, const gchar *oklabel, const gchar *default_uri,
- EMFTExcludeFunc exclude,
- void (*done)(const gchar *uri, gpointer data),
- gpointer data);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
#endif /* EM_FOLDER_SELECTION_H */
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);
-}
diff --git a/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h
index 418248acd6..f8952d0982 100644
--- a/mail/em-folder-tree-model.h
+++ b/mail/em-folder-tree-model.h
@@ -24,7 +24,6 @@
#define EM_FOLDER_TREE_MODEL_H
#include <gtk/gtk.h>
-#include <libxml/tree.h>
#include <camel/camel-store.h>
#include <libedataserver/e-account-list.h>
#include <mail/e-mail-shell-backend.h>
@@ -64,6 +63,7 @@ enum {
COL_UINT_UNREAD, /* unread count */
COL_UINT_FLAGS, /* FolderInfo.flags */
+ COL_BOOL_EXPANDED, /* node is expanded in sidebar */
COL_BOOL_IS_STORE, /* toplevel store node? */
COL_BOOL_IS_FOLDER, /* folder (not a store) */
COL_BOOL_LOAD_SUBDIRS, /* %TRUE only if the store/folder
@@ -93,9 +93,6 @@ struct _EMFolderTreeModel {
GtkTreeStore parent;
EMFolderTreeModelPrivate *priv;
- gchar *filename; /* state filename */
- xmlDocPtr state; /* saved expanded state from previous session */
-
GHashTable *store_hash; /* maps CamelStore's to store-info's */
GHashTable *uri_hash; /* maps URI's to GtkTreeRowReferences */
@@ -120,9 +117,6 @@ struct _EMFolderTreeModelClass {
void (* folder_added) (EMFolderTreeModel *model,
const gchar *path,
const gchar *uri);
-
- void (* store_added) (EMFolderTreeModel *model,
- const gchar *uri);
};
@@ -142,20 +136,6 @@ 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);
-gchar *em_folder_tree_model_get_selected (EMFolderTreeModel *model);
-void em_folder_tree_model_set_selected (EMFolderTreeModel *model, const gchar *uri);
-
-gboolean em_folder_tree_model_get_expanded (EMFolderTreeModel *model, const gchar *key);
-void em_folder_tree_model_set_expanded (EMFolderTreeModel *model, const gchar *key, gboolean expanded);
-
-gboolean em_folder_tree_model_get_expanded_uri (EMFolderTreeModel *model, const gchar *uri);
-void em_folder_tree_model_set_expanded_uri (EMFolderTreeModel *model, const gchar *uri, gboolean expanded);
-
-void em_folder_tree_model_save_state (EMFolderTreeModel *model);
-
-typedef void (* EMFTModelExpandFunc) (EMFolderTreeModel *model, const gchar *path, gpointer user_data);
-void em_folder_tree_model_expand_foreach (EMFolderTreeModel *model, EMFTModelExpandFunc func, gpointer user_data);
-
void em_folder_tree_model_set_unread_count (EMFolderTreeModel *model, CamelStore *store, const gchar *path, gint unread);
gboolean em_folder_tree_model_is_type_inbox (EMFolderTreeModel *model, CamelStore *store, const gchar *full);
gchar * em_folder_tree_model_get_folder_name (EMFolderTreeModel *model, CamelStore *store, const gchar *full);
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index e6abb53c9a..de488c7258 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -104,8 +104,6 @@ struct _EMFolderTreePrivate {
* we need to set it when we set the
* selection */
- guint save_state_id;
-
guint autoscroll_id;
guint autoexpand_id;
GtkTreeRowReference *autoexpand_row;
@@ -159,11 +157,6 @@ static guint signals[LAST_SIGNAL] = { 0 };
extern CamelSession *session;
extern CamelStore *vfolder_store;
-static gboolean emft_save_state (EMFolderTree *emft);
-static void emft_queue_save_state (EMFolderTree *emft);
-
-static void emft_update_model_expanded_state (struct _EMFolderTreePrivate *priv, GtkTreeIter *iter, gboolean expanded);
-
static void emft_tree_row_activated (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, EMFolderTree *emft);
static gboolean emft_tree_test_collapse_row (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *path, EMFolderTree *emft);
static void emft_tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *path, EMFolderTree *emft);
@@ -230,11 +223,6 @@ em_folder_tree_destroy (GtkObject *object)
priv->loaded_row_id = 0;
}
- if (priv->save_state_id != 0) {
- g_source_remove (priv->save_state_id);
- emft_save_state (EM_FOLDER_TREE (object));
- }
-
if (priv->autoscroll_id != 0) {
g_source_remove (priv->autoscroll_id);
priv->autoscroll_id = 0;
@@ -418,10 +406,13 @@ render_icon (GtkTreeViewColumn *column,
GtkTreeModel *model,
GtkTreeIter *iter)
{
+ GtkTreeSelection *selection;
+ GtkWidget *tree_view;
GIcon *icon;
guint unread;
guint old_unread;
gchar *icon_name;
+ gboolean row_selected;
gtk_tree_model_get (
model, iter,
@@ -434,8 +425,12 @@ render_icon (GtkTreeViewColumn *column,
icon = g_themed_icon_new (icon_name);
+ tree_view = gtk_tree_view_column_get_tree_view (column);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+ row_selected = gtk_tree_selection_iter_is_selected (selection, iter);
+
/* Show an emblem if there's new mail. */
- if (unread > old_unread) {
+ if (!row_selected && unread > old_unread) {
GIcon *temp_icon;
GEmblem *emblem;
@@ -547,22 +542,6 @@ em_folder_tree_construct (EMFolderTree *emft, EMFolderTreeModel *model)
g_signal_connect (selection, "changed", G_CALLBACK (emft_tree_selection_changed), emft);
}
-GtkWidget *
-em_folder_tree_new (EMailShellBackend *mail_shell_backend)
-{
- EMFolderTreeModel *model;
- EMFolderTree *emft;
-
- g_return_val_if_fail (
- E_IS_MAIL_SHELL_BACKEND (mail_shell_backend), NULL);
-
- model = e_mail_shell_backend_get_folder_tree_model (mail_shell_backend);
- emft = (EMFolderTree *) em_folder_tree_new_with_model (model);
- g_object_unref (model);
-
- return (GtkWidget *) emft;
-}
-
/* NOTE: Removes and frees the selected uri structure */
static void
emft_select_uri(EMFolderTree *emft, GtkTreePath *path, struct _selected_uri *u)
@@ -670,7 +649,6 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree
gchar *full_name;
gchar *key;
struct _selected_uri *u;
- gboolean is_expanded;
tree_view = GTK_TREE_VIEW (emft);
@@ -691,21 +669,14 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree
key = g_strdup_printf ("local/%s", full_name ? full_name : "");
}
- is_expanded = em_folder_tree_model_get_expanded (model, key);
u = g_hash_table_lookup(priv->select_uris_table, key);
- if (is_expanded || u) {
- if (is_expanded) {
- gtk_tree_view_expand_to_path (tree_view, tree_path);
- gtk_tree_view_expand_row (tree_view, tree_path, FALSE);
- } else {
- gchar *c = strrchr (key, '/');
+ if (u) {
+ gchar *c = strrchr (key, '/');
- *c = '\0';
- emft_expand_node (model, key, emft);
- }
+ *c = '\0';
+ emft_expand_node (model, key, emft);
- if (u)
- emft_select_uri(emft, tree_path, u);
+ emft_select_uri(emft, tree_path, u);
}
g_free (full_name);
@@ -722,8 +693,6 @@ em_folder_tree_new_with_model (EMFolderTreeModel *model)
em_folder_tree_construct (emft, model);
g_object_ref (model);
- em_folder_tree_model_expand_foreach (model, (EMFTModelExpandFunc)emft_expand_node, emft);
-
emft->priv->loading_row_id = g_signal_connect (model, "loading-row", G_CALLBACK (emft_maybe_expand_row), emft);
emft->priv->loaded_row_id = g_signal_connect (model, "loaded-row", G_CALLBACK (emft_maybe_expand_row), emft);
@@ -733,6 +702,38 @@ em_folder_tree_new_with_model (EMFolderTreeModel *model)
return (GtkWidget *) emft;
}
+static gboolean
+folder_tree_clone_expanded (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ GtkTreeView *tree_view)
+{
+ gboolean expanded;
+
+ gtk_tree_model_get (model, iter, COL_BOOL_EXPANDED, &expanded, -1);
+
+ if (expanded)
+ gtk_tree_view_expand_row (tree_view, path, FALSE);
+ else
+ gtk_tree_view_collapse_row (tree_view, path);
+
+ return FALSE;
+}
+
+void
+em_folder_tree_clone_expanded (EMFolderTree *emft)
+{
+ GtkTreeModel *model;
+
+ g_return_if_fail (EM_IS_FOLDER_TREE (emft));
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (emft));
+
+ gtk_tree_model_foreach (
+ model, (GtkTreeModelForeachFunc)
+ folder_tree_clone_expanded, emft);
+}
+
static void
tree_drag_begin (GtkWidget *widget, GdkDragContext *context, EMFolderTree *emft)
{
@@ -1532,11 +1533,14 @@ em_folder_tree_enable_drag_and_drop (EMFolderTree *emft)
}
void
-em_folder_tree_set_multiselect (EMFolderTree *tree, gboolean mode)
+em_folder_tree_set_multiselect (EMFolderTree *tree,
+ gboolean mode)
{
GtkTreeSelection *sel;
GtkTreeView *tree_view;
+ g_return_if_fail (EM_IS_FOLDER_TREE (tree));
+
tree_view = GTK_TREE_VIEW (tree);
sel = gtk_tree_view_get_selection (tree_view);
@@ -1544,13 +1548,22 @@ em_folder_tree_set_multiselect (EMFolderTree *tree, gboolean mode)
gtk_tree_selection_set_mode (sel, mode ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE);
}
-void em_folder_tree_set_excluded(EMFolderTree *emft, guint32 flags)
+void
+em_folder_tree_set_excluded (EMFolderTree *emft, guint32 flags)
{
+ g_return_if_fail (EM_IS_FOLDER_TREE (emft));
+
emft->priv->excluded = flags;
}
-void em_folder_tree_set_excluded_func(EMFolderTree *emft, EMFTExcludeFunc exclude, gpointer data)
+void
+em_folder_tree_set_excluded_func (EMFolderTree *emft,
+ EMFTExcludeFunc exclude,
+ gpointer data)
{
+ g_return_if_fail (EM_IS_FOLDER_TREE (emft));
+ g_return_if_fail (exclude != NULL);
+
emft->priv->excluded_func = exclude;
emft->priv->excluded_data = data;
}
@@ -1684,7 +1697,6 @@ em_folder_tree_set_selected_list (EMFolderTree *emft, GList *list, gboolean expa
end = strrchr(expand_key, '/');
do {
emft_expand_node(priv->model, expand_key, emft);
- em_folder_tree_model_set_expanded(priv->model, expand_key, TRUE);
*end = 0;
end = strrchr(expand_key, '/');
} while (end);
@@ -1816,14 +1828,11 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m)
if (fi == NULL) {
/* no children afterall... remove the "Loading..." placeholder node */
- emft_update_model_expanded_state (priv, &root, FALSE);
-
gtk_tree_store_remove (model, &iter);
if (is_store) {
path = gtk_tree_model_get_path ((GtkTreeModel *) model, &root);
gtk_tree_view_collapse_row (tree_view, path);
- emft_queue_save_state (m->emft);
gtk_tree_path_free (path);
return;
}
@@ -1842,7 +1851,6 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m)
}
gtk_tree_store_set (model, &root, COL_BOOL_LOAD_SUBDIRS, FALSE, -1);
- emft_queue_save_state (m->emft);
}
static void
@@ -1865,41 +1873,8 @@ static MailMsgInfo get_folder_info_info = {
};
static void
-emft_update_model_expanded_state (struct _EMFolderTreePrivate *priv, GtkTreeIter *iter, gboolean expanded)
-{
- struct _EMFolderTreeModelStoreInfo *si;
- gboolean is_store;
- CamelStore *store;
- EAccount *account;
- gchar *full_name;
- gchar *key;
-
- gtk_tree_model_get ((GtkTreeModel *) priv->model, iter,
- COL_STRING_FULL_NAME, &full_name,
- COL_POINTER_CAMEL_STORE, &store,
- COL_BOOL_IS_STORE, &is_store,
- -1);
-
- si = g_hash_table_lookup (priv->model->store_hash, store);
- if ((account = e_get_account_by_name (si->display_name))) {
- key = g_strdup_printf ("%s/%s", account->uid, full_name ? full_name : "");
- } else if (CAMEL_IS_VEE_STORE (store)) {
- /* vfolder store */
- key = g_strdup_printf ("vfolder/%s", full_name ? full_name : "");
- } else {
- /* local store */
- key = g_strdup_printf ("local/%s", full_name ? full_name : "");
- }
-
- em_folder_tree_model_set_expanded (priv->model, key, expanded);
- g_free (full_name);
- g_free (key);
-}
-
-static void
emft_tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_path, EMFolderTree *emft)
{
- struct _EMFolderTreePrivate *priv = emft->priv;
struct _EMFolderTreeGetFolderInfo *m;
GtkTreeModel *model;
CamelStore *store;
@@ -1914,10 +1889,7 @@ emft_tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *t
COL_BOOL_LOAD_SUBDIRS, &load,
-1);
- emft_update_model_expanded_state (priv, root, TRUE);
-
if (!load) {
- emft_queue_save_state (emft);
g_free (full_name);
return;
}
@@ -1950,9 +1922,6 @@ emft_tree_test_collapse_row (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePa
gtk_tree_view_set_cursor (treeview, tree_path, NULL, FALSE);
}
- emft_update_model_expanded_state (emft->priv, root, FALSE);
- emft_queue_save_state (emft);
-
return FALSE;
}
@@ -2081,9 +2050,7 @@ emft_tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft)
guint old_unread = 0;
if (!emft_selection_get_selected (selection, &model, &iter)) {
- em_folder_tree_model_set_selected (emft->priv->model, NULL);
g_signal_emit (emft, signals[FOLDER_SELECTED], 0, NULL, NULL, 0);
- emft_queue_save_state (emft);
return;
}
@@ -2401,29 +2368,6 @@ em_folder_tree_get_model_storeinfo (EMFolderTree *emft, CamelStore *store)
return si;
}
-static gboolean
-emft_save_state (EMFolderTree *emft)
-{
- struct _EMFolderTreePrivate *priv = emft->priv;
-
- em_folder_tree_model_save_state (priv->model);
- priv->save_state_id = 0;
-
- return FALSE;
-}
-
-
-static void
-emft_queue_save_state (EMFolderTree *emft)
-{
- struct _EMFolderTreePrivate *priv = emft->priv;
-
- if (priv->save_state_id != 0)
- return;
-
- priv->save_state_id = g_timeout_add_seconds (1, (GSourceFunc) emft_save_state, emft);
-}
-
void
em_folder_tree_set_skip_double_click (EMFolderTree *emft, gboolean skip)
{
diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h
index bcbac54b8d..4d32f00787 100644
--- a/mail/em-folder-tree.h
+++ b/mail/em-folder-tree.h
@@ -83,9 +83,8 @@ struct _EMFolderTreeClass {
};
GType em_folder_tree_get_type (void);
-
-GtkWidget *em_folder_tree_new (EMailShellBackend *mail_shell_backend);
GtkWidget *em_folder_tree_new_with_model (EMFolderTreeModel *model);
+void em_folder_tree_clone_expanded (EMFolderTree *emft);
void em_folder_tree_enable_drag_and_drop (EMFolderTree *emft);
diff --git a/mail/em-folder-utils.c b/mail/em-folder-utils.c
index f92e8e3115..4ab00e237e 100644
--- a/mail/em-folder-utils.c
+++ b/mail/em-folder-utils.c
@@ -355,17 +355,24 @@ emfu_copy_folder_exclude(EMFolderTree *tree, GtkTreeModel *model, GtkTreeIter *i
/* FIXME: this interface references the folderinfo without copying it */
/* FIXME: these functions must be documented */
void
-em_folder_utils_copy_folder(CamelFolderInfo *folderinfo, gint delete)
+em_folder_utils_copy_folder (EMFolderTreeModel *model,
+ CamelFolderInfo *folderinfo,
+ gint delete)
{
struct _copy_folder_data *cfd;
+ g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model));
+ g_return_if_fail (folderinfo != NULL);
+
cfd = g_malloc (sizeof (*cfd));
cfd->fi = folderinfo;
cfd->delete = delete;
- em_select_folder (NULL, _("Select folder"), delete?_("_Move"):_("C_opy"),
- NULL, emfu_copy_folder_exclude,
- emfu_copy_folder_selected, cfd);
+ em_select_folder (
+ model, _("Select folder"),
+ delete ? _("_Move") : _("C_opy"),
+ NULL, emfu_copy_folder_exclude,
+ emfu_copy_folder_selected, cfd);
}
static void
@@ -696,6 +703,7 @@ em_folder_utils_create_folder (CamelFolderInfo *folderinfo, EMFolderTree *emft,
model = e_mail_shell_backend_get_folder_tree_model (global_mail_shell_backend);
folder_tree = (EMFolderTree *) em_folder_tree_new_with_model (model);
+ em_folder_tree_clone_expanded (folder_tree);
dialog = em_folder_selector_create_new (folder_tree, 0, _("Create Folder"), _("Specify where to create the folder:"));
if (folderinfo != NULL)
diff --git a/mail/em-folder-utils.h b/mail/em-folder-utils.h
index db7ddb82fd..5d1333e9d0 100644
--- a/mail/em-folder-utils.h
+++ b/mail/em-folder-utils.h
@@ -40,14 +40,15 @@ gint em_folder_utils_copy_folders (CamelStore *fromstore,
/* FIXME These API's are really busted. There is no consistency and
* most rely on the wrong data. */
-void em_folder_utils_copy_folder (CamelFolderInfo *folderinfo,
- gint delete);
+void em_folder_utils_copy_folder (EMFolderTreeModel *model,
+ CamelFolderInfo *folderinfo,
+ gboolean delete);
void em_folder_utils_delete_folder (CamelFolder *folder);
void em_folder_utils_rename_folder (CamelFolder *folder);
void em_folder_utils_create_folder (CamelFolderInfo *folderinfo,
- EMFolderTree * emft,
+ EMFolderTree *emft,
GtkWindow *parent);
const gchar * em_folder_utils_get_icon_name (guint32 flags);