diff options
Diffstat (limited to 'mail/em-folder-tree.c')
-rw-r--r-- | mail/em-folder-tree.c | 1005 |
1 files changed, 373 insertions, 632 deletions
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index d765c2de7b..b8ee5e354a 100644 --- a/mail/em-folder-tree.c +++ b/mail/em-folder-tree.c @@ -48,6 +48,7 @@ #include <camel/camel-file-utils.h> #include <camel/camel-stream-fs.h> +#include "e-util/e-account-utils.h" #include "e-util/e-mktemp.h" #include "e-util/e-request.h" #include "e-util/e-icon-factory.h" @@ -60,7 +61,6 @@ #include "mail-ops.h" #include "mail-tools.h" #include "mail-config.h" -#include "mail-component.h" #include "mail-send-recv.h" #include "mail-vfolder.h" @@ -73,8 +73,14 @@ #include "em-folder-properties.h" #include "em-event.h" +#include "e-mail-shell-backend.h" + #define d(x) +#define EM_FOLDER_TREE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), EM_TYPE_FOLDER_TREE, EMFolderTreePrivate)) + struct _selected_uri { gchar *key; /* store:path or account/path */ gchar *uri; @@ -83,7 +89,6 @@ struct _selected_uri { }; struct _EMFolderTreePrivate { - GtkTreeView *treeview; EMFolderTreeModel *model; GSList *select_uris; /* selected_uri structures of each path pending selection. */ @@ -99,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; @@ -115,6 +118,7 @@ struct _EMFolderTreePrivate { enum { FOLDER_ACTIVATED, /* aka double-clicked or user hit enter */ FOLDER_SELECTED, + POPUP_EVENT, LAST_SIGNAL }; @@ -153,16 +157,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; extern CamelSession *session; extern CamelStore *vfolder_store; -static void em_folder_tree_class_init (EMFolderTreeClass *klass); -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 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); @@ -177,68 +171,165 @@ struct _emft_selection_data { gboolean set; }; -static GtkVBoxClass *parent_class = NULL; +static gpointer parent_class = NULL; -GType -em_folder_tree_get_type (void) +static void +folder_tree_emit_popup_event (EMFolderTree *emft, + GdkEvent *event) { - static GType type = 0; + g_signal_emit (emft, signals[POPUP_EVENT], 0, event); +} - if (!type) { - static const GTypeInfo info = { - sizeof (EMFolderTreeClass), - NULL, /* base_class_init */ - NULL, /* base_class_finalize */ - (GClassInitFunc) em_folder_tree_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (EMFolderTree), - 0, /* n_preallocs */ - (GInstanceInitFunc) em_folder_tree_init, - }; +static void +emft_free_select_uri (struct _selected_uri *u) +{ + g_free (u->uri); + if (u->store) + camel_object_unref (u->store); + g_free (u->key); + g_free (u->path); + g_free (u); +} + +static void +folder_tree_finalize (GObject *object) +{ + EMFolderTreePrivate *priv; + + priv = EM_FOLDER_TREE_GET_PRIVATE (object); - type = g_type_register_static (GTK_TYPE_VBOX, "EMFolderTree", &info, 0); + if (priv->select_uris != NULL) { + g_slist_foreach ( + priv->select_uris, + (GFunc) emft_free_select_uri, NULL); + g_slist_free (priv->select_uris); + g_hash_table_destroy (priv->select_uris_table); + priv->select_uris = NULL; } - return type; + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +em_folder_tree_destroy (GtkObject *object) +{ + EMFolderTreePrivate *priv; + + priv = EM_FOLDER_TREE_GET_PRIVATE (object); + + if (priv->loaded_row_id != 0) { + g_signal_handler_disconnect (priv->model, priv->loaded_row_id); + priv->loaded_row_id = 0; + } + + if (priv->autoscroll_id != 0) { + g_source_remove (priv->autoscroll_id); + priv->autoscroll_id = 0; + } + + if (priv->autoexpand_id != 0) { + gtk_tree_row_reference_free (priv->autoexpand_row); + priv->autoexpand_row = NULL; + + g_source_remove (priv->autoexpand_id); + priv->autoexpand_id = 0; + } + + priv->model = NULL; + + /* Chain up to parent's destroy() method. */ + GTK_OBJECT_CLASS (parent_class)->destroy (object); } static void -em_folder_tree_class_init (EMFolderTreeClass *klass) +folder_tree_class_init (EMFolderTreeClass *class) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class; + GtkObjectClass *gtk_object_class; + GtkWidgetClass *widget_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFolderTreePrivate)); - parent_class = g_type_class_ref (GTK_TYPE_VBOX); + object_class = G_OBJECT_CLASS (class); + object_class->finalize = folder_tree_finalize; - object_class->finalize = em_folder_tree_finalize; + gtk_object_class = GTK_OBJECT_CLASS (class); gtk_object_class->destroy = em_folder_tree_destroy; + widget_class = GTK_WIDGET_CLASS (class); widget_class->popup_menu = emft_popup_menu; - signals[FOLDER_SELECTED] = - g_signal_new ("folder-selected", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeClass, folder_selected), - NULL, NULL, - e_marshal_VOID__STRING_STRING_UINT, - G_TYPE_NONE, 3, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_UINT); - - signals[FOLDER_ACTIVATED] = - g_signal_new ("folder-activated", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EMFolderTreeClass, folder_activated), - NULL, NULL, - e_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 2, - G_TYPE_STRING, - G_TYPE_STRING); + signals[FOLDER_SELECTED] = g_signal_new ( + "folder-selected", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeClass, folder_selected), + NULL, NULL, + e_marshal_VOID__STRING_STRING_UINT, + G_TYPE_NONE, 3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_UINT); + + signals[FOLDER_ACTIVATED] = g_signal_new ( + "folder-activated", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EMFolderTreeClass, folder_activated), + NULL, NULL, + e_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, + G_TYPE_STRING, + G_TYPE_STRING); + + signals[POPUP_EVENT] = g_signal_new ( + "popup-event", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EMFolderTreeClass, popup_event), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); +} + +static void +folder_tree_init (EMFolderTree *emft) +{ + GHashTable *select_uris_table; + + select_uris_table = g_hash_table_new (g_str_hash, g_str_equal); + + emft->priv = EM_FOLDER_TREE_GET_PRIVATE (emft); + emft->priv->select_uris_table = select_uris_table; +} + +GType +em_folder_tree_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMFolderTreeClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) folder_tree_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMFolderTree), + 0, /* n_preallocs */ + (GInstanceInitFunc) folder_tree_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_TREE_VIEW, "EMFolderTree", &type_info, 0); + } + + return type; } static gboolean @@ -315,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, @@ -331,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; @@ -377,91 +475,6 @@ emft_select_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath * return (flags & emft->priv->excluded) == 0; } -static void -emft_free_select_uri(gpointer v, gpointer data) -{ - struct _selected_uri *u = v; - - g_free(u->uri); - if (u->store) - camel_object_unref(u->store); - g_free(u->key); - g_free(u->path); - g_free(u); -} - -static void -em_folder_tree_init (EMFolderTree *emft) -{ - struct _EMFolderTreePrivate *priv; - - priv = g_new0 (struct _EMFolderTreePrivate, 1); - priv->select_uris_table = g_hash_table_new(g_str_hash, g_str_equal); - priv->treeview = NULL; - priv->model = NULL; - priv->drag_row = NULL; - priv->skip_double_click = FALSE; - - emft->priv = priv; -} - -static void -em_folder_tree_finalize (GObject *obj) -{ - EMFolderTree *emft = (EMFolderTree *) obj; - - if (emft->priv->select_uris) { - g_slist_foreach(emft->priv->select_uris, emft_free_select_uri, emft); - g_slist_free(emft->priv->select_uris); - g_hash_table_destroy(emft->priv->select_uris_table); - emft->priv->select_uris = NULL; - } - - g_free (emft->priv); - - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -static void -em_folder_tree_destroy (GtkObject *obj) -{ - EMFolderTree *emft = (EMFolderTree *) obj; - struct _EMFolderTreePrivate *priv = emft->priv; - - if (priv->loading_row_id != 0) { - g_signal_handler_disconnect (priv->model, priv->loading_row_id); - priv->loading_row_id = 0; - } - - if (priv->loaded_row_id != 0) { - g_signal_handler_disconnect (priv->model, priv->loaded_row_id); - priv->loaded_row_id = 0; - } - - if (priv->save_state_id != 0) { - g_source_remove (priv->save_state_id); - emft_save_state (emft); - } - - if (priv->autoscroll_id != 0) { - g_source_remove (priv->autoscroll_id); - priv->autoscroll_id = 0; - } - - if (priv->autoexpand_id != 0) { - gtk_tree_row_reference_free (priv->autoexpand_row); - priv->autoexpand_row = NULL; - - g_source_remove (priv->autoexpand_id); - priv->autoexpand_id = 0; - } - - priv->treeview = NULL; - priv->model = NULL; - - GTK_OBJECT_CLASS (parent_class)->destroy (obj); -} - static GtkTreeView * folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model) { @@ -475,7 +488,10 @@ folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model) gconf = mail_config_get_gconf_client (); side_bar_search = gconf_client_get_bool (gconf, "/apps/evolution/mail/display/side_bar_search", NULL); - tree = gtk_tree_view_new_with_model ((GtkTreeModel *) model); + /* FIXME[KILL-BONOBO] Gross hack */ + tree = GTK_WIDGET (emft); + gtk_tree_view_set_model ( + GTK_TREE_VIEW (tree), GTK_TREE_MODEL (model)); GTK_WIDGET_SET_FLAGS(tree, GTK_CAN_FOCUS); column = gtk_tree_view_column_new (); @@ -507,47 +523,69 @@ folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model) } static void -em_folder_tree_construct (EMFolderTree *emft, EMFolderTreeModel *model) +folder_tree_copy_expanded_cb (GtkTreeView *unused, + GtkTreePath *path, + GtkTreeView *tree_view) +{ + gtk_tree_view_expand_row (tree_view, path, FALSE); +} + +static void +folder_tree_copy_selection_cb (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + GtkTreeView *tree_view) { - struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeSelection *selection; - GtkWidget *scrolled; - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN); + selection = gtk_tree_view_get_selection (tree_view); + gtk_tree_selection_select_path (selection, path); - priv->model = model; - priv->treeview = folder_tree_new (emft, model); - gtk_widget_show ((GtkWidget *) priv->treeview); + /* Center the tree view on the selected path. */ + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.0); +} - g_signal_connect (priv->treeview, "row-expanded", G_CALLBACK (emft_tree_row_expanded), emft); - g_signal_connect (priv->treeview, "test-collapse-row", G_CALLBACK (emft_tree_test_collapse_row), emft); - g_signal_connect (priv->treeview, "row-activated", G_CALLBACK (emft_tree_row_activated), emft); - g_signal_connect (priv->treeview, "button-press-event", G_CALLBACK (emft_tree_button_press), emft); - g_signal_connect (priv->treeview, "key-press-event", G_CALLBACK (emft_tree_user_event), emft); +static void +folder_tree_copy_state (EMFolderTree *emft, + EMFolderTreeModel *model) +{ + GtkTreeSelection *selection; + GtkTreeView *tree_view; - selection = gtk_tree_view_get_selection ((GtkTreeView *) priv->treeview); - g_signal_connect (selection, "changed", G_CALLBACK (emft_tree_selection_changed), emft); + selection = em_folder_tree_model_get_selection (model); + if (selection == NULL) + return; + + tree_view = gtk_tree_selection_get_tree_view (selection); - gtk_container_add ((GtkContainer *) scrolled, (GtkWidget *) priv->treeview); - gtk_widget_show (scrolled); + gtk_tree_view_map_expanded_rows ( + tree_view, (GtkTreeViewMappingFunc) + folder_tree_copy_expanded_cb, emft); - gtk_box_pack_start ((GtkBox *) emft, scrolled, TRUE, TRUE, 0); + gtk_tree_selection_selected_foreach ( + selection, (GtkTreeSelectionForeachFunc) + folder_tree_copy_selection_cb, emft); } -GtkWidget * -em_folder_tree_new (void) +static void +em_folder_tree_construct (EMFolderTree *emft, EMFolderTreeModel *model) { - EMFolderTreeModel *model; - EMFolderTree *emft; + struct _EMFolderTreePrivate *priv = emft->priv; + GtkTreeSelection *selection; - model = em_folder_tree_model_new (e_get_user_data_dir ()); - emft = (EMFolderTree *) em_folder_tree_new_with_model (model); - g_object_unref (model); + priv->model = model; + folder_tree_new (emft, model); + folder_tree_copy_state (emft, model); + gtk_widget_show (GTK_WIDGET (emft)); - return (GtkWidget *) emft; + g_signal_connect (emft, "row-expanded", G_CALLBACK (emft_tree_row_expanded), emft); + g_signal_connect (emft, "test-collapse-row", G_CALLBACK (emft_tree_test_collapse_row), emft); + g_signal_connect (emft, "row-activated", G_CALLBACK (emft_tree_row_activated), emft); + g_signal_connect (emft, "button-press-event", G_CALLBACK (emft_tree_button_press), emft); + g_signal_connect (emft, "key-press-event", G_CALLBACK (emft_tree_user_event), emft); + + selection = gtk_tree_view_get_selection ((GtkTreeView *) emft); + g_signal_connect (selection, "changed", G_CALLBACK (emft_tree_selection_changed), emft); } /* NOTE: Removes and frees the selected uri structure */ @@ -555,18 +593,20 @@ static void emft_select_uri(EMFolderTree *emft, GtkTreePath *path, struct _selected_uri *u) { struct _EMFolderTreePrivate *priv = emft->priv; + GtkTreeView *tree_view; GtkTreeSelection *selection; - selection = gtk_tree_view_get_selection(priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); gtk_tree_selection_select_path(selection, path); if (!priv->cursor_set) { - gtk_tree_view_set_cursor (priv->treeview, path, NULL, FALSE); + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); priv->cursor_set = TRUE; } - gtk_tree_view_scroll_to_cell (priv->treeview, path, NULL, TRUE, 0.8f, 0.0f); + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.8f, 0.0f); g_hash_table_remove(priv->select_uris_table, u->key); priv->select_uris = g_slist_remove(priv->select_uris, u); - emft_free_select_uri((gpointer)u, NULL); + emft_free_select_uri(u); } static void @@ -574,7 +614,9 @@ emft_expand_node (EMFolderTreeModel *model, const gchar *key, EMFolderTree *emft { struct _EMFolderTreePrivate *priv = emft->priv; struct _EMFolderTreeModelStoreInfo *si; + EMailShellBackend *mail_shell_backend; GtkTreeRowReference *row; + GtkTreeView *tree_view; GtkTreePath *path; EAccount *account; CamelStore *store; @@ -592,7 +634,10 @@ emft_expand_node (EMFolderTreeModel *model, const gchar *key, EMFolderTree *emft memcpy (uid, key, n); uid[n] = '\0'; - if ((account = mail_config_get_account_by_uid (uid)) && account->enabled) { + tree_view = GTK_TREE_VIEW (emft); + mail_shell_backend = em_folder_tree_model_get_mail_shell_backend (model); + + if ((account = e_get_account_by_uid (uid)) && account->enabled) { CamelException ex; camel_exception_init (&ex); @@ -607,7 +652,7 @@ emft_expand_node (EMFolderTreeModel *model, const gchar *key, EMFolderTree *emft camel_object_ref (store); } else if (!strcmp (uid, "local")) { - if (!(store = mail_component_peek_local_store (NULL))) + if (!(store = e_mail_shell_backend_get_local_store (mail_shell_backend))) return; camel_object_ref (store); @@ -615,7 +660,8 @@ emft_expand_node (EMFolderTreeModel *model, const gchar *key, EMFolderTree *emft return; } - if (!(si = g_hash_table_lookup (priv->model->store_hash, store))) { + si = em_folder_tree_model_lookup_store_info (priv->model, store); + if (si == NULL) { camel_object_unref (store); return; } @@ -629,7 +675,7 @@ emft_expand_node (EMFolderTreeModel *model, const gchar *key, EMFolderTree *emft row = si->row; path = gtk_tree_row_reference_get_path (row); - gtk_tree_view_expand_to_path (priv->treeview, path); + gtk_tree_view_expand_to_path (tree_view, path); u = g_hash_table_lookup(emft->priv->select_uris_table, key); if (u) @@ -643,13 +689,15 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree { struct _EMFolderTreePrivate *priv = emft->priv; struct _EMFolderTreeModelStoreInfo *si; + GtkTreeView *tree_view; gboolean is_store; CamelStore *store; EAccount *account; gchar *full_name; gchar *key; struct _selected_uri *u; - gboolean is_expanded; + + tree_view = GTK_TREE_VIEW (emft); gtk_tree_model_get ((GtkTreeModel *) model, iter, COL_STRING_FULL_NAME, &full_name, @@ -657,8 +705,8 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree COL_BOOL_IS_STORE, &is_store, -1); - si = g_hash_table_lookup (model->store_hash, store); - if ((account = mail_config_get_account_by_name (si->display_name))) { + si = em_folder_tree_model_lookup_store_info (model, 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 */ @@ -668,21 +716,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 (priv->treeview, tree_path); - gtk_tree_view_expand_row (priv->treeview, 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); @@ -699,12 +740,10 @@ 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); - a11y = gtk_widget_get_accessible (GTK_WIDGET (emft->priv->treeview)); + a11y = gtk_widget_get_accessible (GTK_WIDGET (emft)); atk_object_set_name (a11y, _("Mail Folder Tree")); return (GtkWidget *) emft; @@ -986,6 +1025,7 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint { struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeViewDropPosition pos; + GtkTreeView *tree_view; GtkTreePath *dest_path; struct _DragDataReceivedAsync *m; gboolean is_store; @@ -994,7 +1034,9 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint gchar *full_name; gint i; - if (!gtk_tree_view_get_dest_row_at_pos (priv->treeview, x, y, &dest_path, &pos)) + tree_view = GTK_TREE_VIEW (emft); + + if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &dest_path, &pos)) return; /* this means we are receiving no data */ @@ -1072,6 +1114,7 @@ emft_drop_target(EMFolderTree *emft, GdkDragContext *context, GtkTreePath *path) struct _EMFolderTreePrivate *p = emft->priv; gchar *full_name = NULL, *uri = NULL, *src_uri = NULL; CamelStore *local, *sstore, *dstore; + EMailShellBackend *mail_shell_backend; GdkAtom atom = GDK_NONE; gboolean is_store; GtkTreeIter iter; @@ -1089,7 +1132,8 @@ emft_drop_target(EMFolderTree *emft, GdkDragContext *context, GtkTreePath *path) COL_POINTER_CAMEL_STORE, &dstore, COL_STRING_URI, &uri, -1); - local = mail_component_peek_local_store (NULL); + mail_shell_backend = em_folder_tree_model_get_mail_shell_backend (p->model); + local = e_mail_shell_backend_get_local_store (mail_shell_backend); targets = context->targets; @@ -1267,10 +1311,13 @@ tree_drag_drop (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guin { struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeViewColumn *column; + GtkTreeView *tree_view; gint cell_x, cell_y; GtkTreePath *path; GdkAtom target; + tree_view = GTK_TREE_VIEW (emft); + if (priv->autoscroll_id != 0) { g_source_remove (priv->autoscroll_id); priv->autoscroll_id = 0; @@ -1284,7 +1331,7 @@ tree_drag_drop (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guin priv->autoexpand_id = 0; } - if (!gtk_tree_view_get_path_at_pos (priv->treeview, x, y, &path, &column, &cell_x, &cell_y)) + if (!gtk_tree_view_get_path_at_pos (tree_view, x, y, &path, &column, &cell_x, &cell_y)) return FALSE; target = emft_drop_target(emft, context, path); @@ -1312,6 +1359,9 @@ static void tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, EMFolderTree *emft) { struct _EMFolderTreePrivate *priv = emft->priv; + GtkTreeView *tree_view; + + tree_view = GTK_TREE_VIEW (emft); if (priv->autoscroll_id != 0) { g_source_remove (priv->autoscroll_id); @@ -1326,7 +1376,7 @@ tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, EMFolde priv->autoexpand_id = 0; } - gtk_tree_view_set_drag_dest_row(emft->priv->treeview, NULL, GTK_TREE_VIEW_DROP_BEFORE); + gtk_tree_view_set_drag_dest_row(tree_view, NULL, GTK_TREE_VIEW_DROP_BEFORE); } @@ -1335,19 +1385,20 @@ tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, EMFolde static gboolean tree_autoscroll (EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; GtkAdjustment *vadjustment; + GtkTreeView *tree_view; GdkRectangle rect; GdkWindow *window; gint offset, y; gfloat value; /* get the y pointer position relative to the treeview */ - window = gtk_tree_view_get_bin_window (priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + window = gtk_tree_view_get_bin_window (tree_view); gdk_window_get_pointer (window, NULL, &y, NULL); /* rect is in coorinates relative to the scrolled window relative to the treeview */ - gtk_tree_view_get_visible_rect (priv->treeview, &rect); + gtk_tree_view_get_visible_rect (tree_view, &rect); /* move y into the same coordinate system as rect */ y += rect.y; @@ -1359,7 +1410,7 @@ tree_autoscroll (EMFolderTree *emft) return TRUE; } - vadjustment = gtk_tree_view_get_vadjustment (priv->treeview); + vadjustment = gtk_tree_view_get_vadjustment (tree_view); value = CLAMP (vadjustment->value + offset, 0.0, vadjustment->upper - vadjustment->page_size); gtk_adjustment_set_value (vadjustment, value); @@ -1371,10 +1422,12 @@ static gboolean tree_autoexpand (EMFolderTree *emft) { struct _EMFolderTreePrivate *priv = emft->priv; + GtkTreeView *tree_view; GtkTreePath *path; + tree_view = GTK_TREE_VIEW (emft); path = gtk_tree_row_reference_get_path (priv->autoexpand_row); - gtk_tree_view_expand_row (priv->treeview, path, FALSE); + gtk_tree_view_expand_row (tree_view, path, FALSE); gtk_tree_path_free (path); return TRUE; @@ -1386,13 +1439,16 @@ tree_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, gu struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeModel *model = (GtkTreeModel *) priv->model; GtkTreeViewDropPosition pos; + GtkTreeView *tree_view; GdkDragAction action = 0; GtkTreePath *path; GtkTreeIter iter; GdkAtom target; gint i; - if (!gtk_tree_view_get_dest_row_at_pos(priv->treeview, x, y, &path, &pos)) + tree_view = GTK_TREE_VIEW (emft); + + if (!gtk_tree_view_get_dest_row_at_pos(tree_view, x, y, &path, &pos)) return FALSE; if (priv->autoscroll_id == 0) @@ -1400,7 +1456,7 @@ tree_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, gu gtk_tree_model_get_iter (model, &iter, path); - if (gtk_tree_model_iter_has_child (model, &iter) && !gtk_tree_view_row_expanded (priv->treeview, path)) { + if (gtk_tree_model_iter_has_child (model, &iter) && !gtk_tree_view_row_expanded (tree_view, path)) { if (priv->autoexpand_id != 0) { GtkTreePath *autoexpand_path; @@ -1436,10 +1492,10 @@ tree_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, gu action = context->suggested_action; if (action == GDK_ACTION_COPY && (context->actions & GDK_ACTION_MOVE)) action = GDK_ACTION_MOVE; - gtk_tree_view_set_drag_dest_row(priv->treeview, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); + gtk_tree_view_set_drag_dest_row(tree_view, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); break; default: - gtk_tree_view_set_drag_dest_row(priv->treeview, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); + gtk_tree_view_set_drag_dest_row(tree_view, path, GTK_TREE_VIEW_DROP_INTO_OR_AFTER); action = context->suggested_action; break; } @@ -1459,11 +1515,14 @@ void em_folder_tree_enable_drag_and_drop (EMFolderTree *emft) { struct _EMFolderTreePrivate *priv; + GtkTreeView *tree_view; static gint setup = 0; gint i; g_return_if_fail (EM_IS_FOLDER_TREE (emft)); + tree_view = GTK_TREE_VIEW (emft); + priv = emft->priv; if (!setup) { for (i=0; i<NUM_DRAG_TYPES; i++) @@ -1475,35 +1534,51 @@ em_folder_tree_enable_drag_and_drop (EMFolderTree *emft) setup = 1; } - gtk_drag_source_set((GtkWidget *)priv->treeview, GDK_BUTTON1_MASK, drag_types, NUM_DRAG_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); - gtk_drag_dest_set((GtkWidget *)priv->treeview, GTK_DEST_DEFAULT_ALL, drop_types, NUM_DROP_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); + gtk_drag_source_set((GtkWidget *)tree_view, GDK_BUTTON1_MASK, drag_types, NUM_DRAG_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); + gtk_drag_dest_set((GtkWidget *)tree_view, GTK_DEST_DEFAULT_ALL, drop_types, NUM_DROP_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK); - g_signal_connect (priv->treeview, "drag-begin", G_CALLBACK (tree_drag_begin), emft); - g_signal_connect (priv->treeview, "drag-data-delete", G_CALLBACK (tree_drag_data_delete), emft); - g_signal_connect (priv->treeview, "drag-data-get", G_CALLBACK (tree_drag_data_get), emft); - g_signal_connect (priv->treeview, "drag-data-received", G_CALLBACK (tree_drag_data_received), emft); - g_signal_connect (priv->treeview, "drag-drop", G_CALLBACK (tree_drag_drop), emft); - g_signal_connect (priv->treeview, "drag-end", G_CALLBACK (tree_drag_end), emft); - g_signal_connect (priv->treeview, "drag-leave", G_CALLBACK (tree_drag_leave), emft); - g_signal_connect (priv->treeview, "drag-motion", G_CALLBACK (tree_drag_motion), emft); + g_signal_connect (tree_view, "drag-begin", G_CALLBACK (tree_drag_begin), emft); + g_signal_connect (tree_view, "drag-data-delete", G_CALLBACK (tree_drag_data_delete), emft); + g_signal_connect (tree_view, "drag-data-get", G_CALLBACK (tree_drag_data_get), emft); + g_signal_connect (tree_view, "drag-data-received", G_CALLBACK (tree_drag_data_received), emft); + g_signal_connect (tree_view, "drag-drop", G_CALLBACK (tree_drag_drop), emft); + g_signal_connect (tree_view, "drag-end", G_CALLBACK (tree_drag_end), emft); + g_signal_connect (tree_view, "drag-leave", G_CALLBACK (tree_drag_leave), emft); + g_signal_connect (tree_view, "drag-motion", G_CALLBACK (tree_drag_motion), emft); } void -em_folder_tree_set_multiselect (EMFolderTree *tree, gboolean mode) +em_folder_tree_set_multiselect (EMFolderTree *tree, + gboolean mode) { - GtkTreeSelection *sel = gtk_tree_view_get_selection ((GtkTreeView *) tree->priv->treeview); + 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); tree->priv->do_multiselect = 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; } @@ -1511,10 +1586,14 @@ void em_folder_tree_set_excluded_func(EMFolderTree *emft, EMFTExcludeFunc exclud GList * em_folder_tree_get_selected_uris (EMFolderTree *emft) { - GtkTreeSelection *selection = gtk_tree_view_get_selection (emft->priv->treeview); + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; GList *list = NULL, *rows, *l; GSList *sl; - GtkTreeModel *model; + + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); /* at first, add lost uris */ for (sl = emft->priv->select_uris; sl; sl = g_slist_next(sl)) @@ -1551,9 +1630,13 @@ get_selected_uris_path_iterate (GtkTreeModel *model, GtkTreePath *treepath, GtkT GList * em_folder_tree_get_selected_paths (EMFolderTree *emft) { - GtkTreeSelection *selection = gtk_tree_view_get_selection (emft->priv->treeview); + GtkTreeSelection *selection; + GtkTreeView *tree_view; GList *list = NULL; + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + gtk_tree_selection_selected_foreach (selection, get_selected_uris_path_iterate, &list); return list; @@ -1564,7 +1647,7 @@ emft_clear_selected_list(EMFolderTree *emft) { struct _EMFolderTreePrivate *priv = emft->priv; - g_slist_foreach(priv->select_uris, emft_free_select_uri, emft); + g_slist_foreach(priv->select_uris, (GFunc) emft_free_select_uri, NULL); g_slist_free(priv->select_uris); g_hash_table_destroy(priv->select_uris_table); priv->select_uris = NULL; @@ -1629,7 +1712,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); @@ -1702,24 +1784,26 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) struct _EMFolderTreeModelStoreInfo *si; GtkTreeIter root, iter, titer; CamelFolderInfo *fi; + GtkTreeView *tree_view; GtkTreeStore *model; GtkTreePath *path; gboolean is_store; /* check that we haven't been destroyed */ - if (priv->treeview == NULL) - return; + g_return_if_fail (GTK_IS_TREE_VIEW (m->emft)); /* check that our parent folder hasn't been deleted/unsubscribed */ if (!gtk_tree_row_reference_valid (m->root)) return; - if (!(si = g_hash_table_lookup (priv->model->store_hash, m->store))) { + si = em_folder_tree_model_lookup_store_info (priv->model, m->store); + if (si == NULL) { /* store has been removed in the interim - do nothing */ return; } - model = (GtkTreeStore *) gtk_tree_view_get_model (priv->treeview); + tree_view = GTK_TREE_VIEW (m->emft); + model = (GtkTreeStore *) gtk_tree_view_get_model (tree_view); path = gtk_tree_row_reference_get_path (m->root); gtk_tree_model_get_iter ((GtkTreeModel *) model, &root, path); @@ -1727,7 +1811,7 @@ emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) /* if we had an error, then we need to re-set the load subdirs state and collapse the node */ if (!m->fi && camel_exception_is_set(&m->base.ex)) { gtk_tree_store_set(model, &root, COL_BOOL_LOAD_SUBDIRS, TRUE, -1); - gtk_tree_view_collapse_row (priv->treeview, path); + gtk_tree_view_collapse_row (tree_view, path); gtk_tree_path_free (path); return; } @@ -1760,14 +1844,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 (priv->treeview, path); - emft_queue_save_state (m->emft); + gtk_tree_view_collapse_row (tree_view, path); gtk_tree_path_free (path); return; } @@ -1786,7 +1867,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 @@ -1809,41 +1889,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 = mail_config_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; @@ -1858,10 +1905,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; } @@ -1894,9 +1938,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; } @@ -1927,53 +1968,6 @@ emft_tree_row_activated (GtkTreeView *treeview, GtkTreePath *tree_path, GtkTreeV g_free(uri); } -#if 0 -static void -emft_popup_view (GtkWidget *item, EMFolderTree *emft) -{ - -} - -static void -emft_popup_open_new (GtkWidget *item, EMFolderTree *emft) -{ -} -#endif - -static void -emft_popup_copy(EPopup *ep, EPopupItem *item, gpointer data) -{ - EMFolderTree *emft = data; - CamelFolderInfo *fi = NULL; - - /* FIXME: use async apis */ - if ((fi = em_folder_tree_get_selected_folder_info (emft)) != NULL) - em_folder_utils_copy_folder(fi, FALSE); -} - -static void -emft_popup_move(EPopup *ep, EPopupItem *item, gpointer data) -{ - EMFolderTree *emft = data; - CamelFolderInfo *fi = NULL; - - /* FIXME: use async apis */ - if ((fi = em_folder_tree_get_selected_folder_info (emft)) != NULL) - em_folder_utils_copy_folder(fi, TRUE); -} - -static void -emft_popup_new_folder (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - EMFolderTree *emft = data; - CamelFolderInfo *fi; - - if ((fi = em_folder_tree_get_selected_folder_info (emft)) != NULL) { - em_folder_utils_create_folder (fi, emft, NULL); - camel_folder_info_free(fi); - } -} - static void selfunc (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { @@ -2000,251 +1994,15 @@ emft_selection_get_selected (GtkTreeSelection *selection, GtkTreeModel **model, } } -static void -emft_popup_delete_folder (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - EMFolderTree *emft = data; - CamelFolder *folder; - - if ((folder = em_folder_tree_get_selected_folder (emft)) != NULL) { - em_folder_utils_delete_folder(folder); - } -} - -static void -emft_popup_rename_folder (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - EMFolderTree *emft = data; - CamelFolder *folder; - - if ((folder = em_folder_tree_get_selected_folder (emft)) != NULL) { - em_folder_utils_rename_folder(folder); - } -} - -static void -emft_popup_refresh_folder (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - EMFolderTree *emft = data; - CamelFolder *folder; - - if ((folder = em_folder_tree_get_selected_folder (emft)) != NULL) { - EMEvent *e = em_event_peek(); - EMEventTargetFolder *t = em_event_target_new_folder(e, folder->full_name, 0); - e_event_emit((EEvent *)e, "folder.refresh", (EEventTarget *)t); - mail_refresh_folder(folder, NULL, NULL); - } -} - -static void -emft_popup_flush_outbox (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - mail_send (); -} - -static void -emft_popup_empty_trash (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - em_utils_empty_trash (data); -} - -static void -emft_popup_properties (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - EMFolderTree *emft = data; - struct _EMFolderTreePrivate *priv = emft->priv; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - gchar *uri; - - selection = gtk_tree_view_get_selection (priv->treeview); - if (!emft_selection_get_selected (selection, &model, &iter)) - return; - - gtk_tree_model_get (model, &iter, COL_STRING_URI, &uri, -1); - em_folder_properties_show (NULL, NULL, uri); - g_free (uri); -} - -static void -emft_popup_uvfolder (EPopup *ep, EPopupItem *pitem, gpointer data) -{ - EMFolderTree *emft = data; - CamelFolder *folder; - - if ((folder = em_folder_tree_get_selected_folder (emft)) != NULL) { - gchar *meta = camel_object_meta_get(folder, "vfolder:unread"); - if (!meta || strcmp(meta, "false") == 0) - camel_object_meta_set(folder, "vfolder:unread", "true"); - else - camel_object_meta_set(folder, "vfolder:unread", "false"); - camel_object_state_write (folder); - g_free (meta); - } -} - -static EPopupItem emft_popup_items[] = { -#if 0 - { E_POPUP_ITEM, "00.emc.00", N_("_View"), emft_popup_view, NULL, NULL, EM_POPUP_FOLDER_SELECT }, - { E_POPUP_ITEM, "00.emc.01", N_("Open in _New Window"), emft_popup_open_new, NULL, NULL, EM_POPUP_FOLDER_SELECT }, - - { E_POPUP_BAR, "10.emc" }, -#endif - /* FIXME: need to disable for nochildren folders */ - { E_POPUP_ITEM, (gchar *) "10.emc.00", (gchar *) N_("_New Folder..."), emft_popup_new_folder, NULL, (gchar *) "folder-new", 0, EM_POPUP_FOLDER_INFERIORS }, - - { E_POPUP_ITEM, (gchar *) "10.emc.05", (gchar *) N_("_Copy..."), emft_popup_copy, NULL, (gchar *) "folder-copy", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT }, - { E_POPUP_ITEM, (gchar *) "10.emc.06", (gchar *) N_("_Move..."), emft_popup_move, NULL, (gchar *) "folder-move", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, - - /* FIXME: need to disable for undeletable folders */ - { E_POPUP_BAR, (gchar *) "20.emc" }, - { E_POPUP_ITEM, (gchar *) "20.emc.01", (gchar *) N_("_Delete"), emft_popup_delete_folder, NULL, (gchar *) "edit-delete", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, - - { E_POPUP_BAR, (gchar *) "30.emc" }, - { E_POPUP_ITEM, (gchar *) "30.emc.02", (gchar *) N_("_Rename..."), emft_popup_rename_folder, NULL, NULL, 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_DELETE }, - { E_POPUP_ITEM, (gchar *) "30.emc.03", (gchar *) N_("Re_fresh"), emft_popup_refresh_folder, NULL, (gchar *) "view-refresh", EM_POPUP_FOLDER_NONSTATIC, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT}, - { E_POPUP_ITEM, (gchar *) "30.emc.04", (gchar *) N_("Fl_ush Outbox"), emft_popup_flush_outbox, NULL, (gchar *) "mail-send", EM_POPUP_FOLDER_OUTBOX, 0 }, - - - { E_POPUP_BAR, (gchar *) "99.emc" }, - { E_POPUP_ITEM, (gchar *) "99.emc.00", (gchar *) N_("_Properties"), emft_popup_properties, NULL, (gchar *) "document-properties", 0, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT } -}; -static EPopupItem trash_popup_item = {E_POPUP_ITEM, (gchar *) "30.emc.05", (gchar *) N_("_Empty Trash"), emft_popup_empty_trash,NULL,NULL, 1, EM_POPUP_FOLDER_FOLDER|EM_POPUP_FOLDER_SELECT}; - -static void -emft_popup_free(EPopup *ep, GSList *items, gpointer data) -{ - g_slist_free(items); -} - static gboolean -emft_popup (EMFolderTree *emft, GdkEvent *event) +emft_popup_menu (GtkWidget *widget) { - GtkTreeView *treeview; - GtkTreeSelection *selection; - CamelStore *local, *store; - EMPopupTargetFolder *target; - GtkTreeModel *model; - GtkTreeIter iter; - GSList *menus = NULL; - guint32 info_flags = 0; - guint32 flags = 0; - guint32 folder_type_flags = 0; - gboolean isstore; - gchar *uri, *full_name; - GtkMenu *menu; - EMPopup *emp; - CamelFolder *selfolder = NULL; - gint i; - - treeview = emft->priv->treeview; - - /* this centralises working out when the user's done something */ - emft_tree_user_event(treeview, (GdkEvent *)event, emft); - - /* FIXME: we really need the folderinfo to build a proper menu */ - selection = gtk_tree_view_get_selection (treeview); - if (!emft_selection_get_selected (selection, &model, &iter)) - return FALSE; - - gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, - COL_STRING_URI, &uri, COL_STRING_FULL_NAME, &full_name, - COL_BOOL_IS_STORE, &isstore, COL_UINT_FLAGS, &folder_type_flags, -1); - - /* Stores have full_name == NULL, otherwise its just a placeholder */ - /* NB: This is kind of messy */ - if (!isstore && full_name == NULL) { - g_free (uri); - return FALSE; - } - - /* TODO: em_popup_target_folder_new? */ - if (isstore) { - flags |= EM_POPUP_FOLDER_STORE; - } else { - flags |= EM_POPUP_FOLDER_FOLDER; - - local = mail_component_peek_local_store (NULL); - - /* don't allow deletion of special local folders */ - if (!(store == local && is_special_local_folder (full_name))) - flags |= EM_POPUP_FOLDER_DELETE; - - /* hack for vTrash/vJunk */ - if (!strcmp (full_name, CAMEL_VTRASH_NAME) || !strcmp (full_name, CAMEL_VJUNK_NAME)) - info_flags |= CAMEL_FOLDER_VIRTUAL | CAMEL_FOLDER_NOINFERIORS; - - selfolder = em_folder_tree_get_selected_folder (emft); - - if (folder_type_flags & CAMEL_FOLDER_SYSTEM) - flags &= ~EM_POPUP_FOLDER_DELETE; - - if (em_utils_folder_is_outbox (selfolder, NULL)) - info_flags |= CAMEL_FOLDER_TYPE_OUTBOX; - } - - /** @HookPoint-EMPopup: Folder Tree Context Menu - * @Id: org.gnome.evolution.mail.foldertree.popup - * @Class: org.gnome.evolution.mail.popup:1.0 - * @Target: EMPopupTargetFolder - * - * This is the context menu shown on the folder tree. - */ - emp = em_popup_new ("org.gnome.evolution.mail.foldertree.popup"); - - /* FIXME: pass valid fi->flags here */ - target = em_popup_target_new_folder (emp, uri, info_flags, flags); - - for (i = 0; i < sizeof (emft_popup_items) / sizeof (emft_popup_items[0]); i++) - menus = g_slist_prepend (menus, &emft_popup_items[i]); - - if ((folder_type_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_TRASH) - menus = g_slist_prepend (menus, &trash_popup_item); - if (!isstore && strstr(uri, "vfolder")) { - /* This is a vfolder, so lets add hacked up menu item. */ - static EPopupItem *item = NULL; - gchar *meta = camel_object_meta_get (selfolder, "vfolder:unread"); - - if (!item) - item = g_malloc0(sizeof(*item)); - if (meta && (strcmp (meta, "true") == 0)) - item->type = E_POPUP_TOGGLE | E_POPUP_ACTIVE; - else - item->type = E_POPUP_TOGGLE & ~E_POPUP_ACTIVE; - item->path = (gchar *) "99.emc.99"; - item->label = _("_Unread Search Folder"); - item->activate = emft_popup_uvfolder; - item->visible = EM_POPUP_FOLDER_SELECT; - item->user_data = NULL; - menus = g_slist_prepend (menus, item); - g_free (meta); - } - - e_popup_add_items ((EPopup *)emp, menus, NULL, emft_popup_free, emft); - - menu = e_popup_create_menu_once ((EPopup *)emp, (EPopupTarget *)target, 0); - - if (event == NULL || event->type == GDK_KEY_PRESS) { - /* FIXME: menu pos function */ - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); - } else { - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button.button, event->button.time); - } - - g_free (full_name); - g_free (uri); + folder_tree_emit_popup_event (EM_FOLDER_TREE (widget), NULL); return TRUE; } static gboolean -emft_popup_menu (GtkWidget *widget) -{ - return emft_popup (EM_FOLDER_TREE (widget), NULL); -} - -static gboolean emft_tree_button_press (GtkTreeView *treeview, GdkEventButton *event, EMFolderTree *emft) { GtkTreeSelection *selection; @@ -2275,7 +2033,9 @@ emft_tree_button_press (GtkTreeView *treeview, GdkEventButton *event, EMFolderTr gtk_tree_path_free (tree_path); - return emft_popup (emft, (GdkEvent *)event); + folder_tree_emit_popup_event (emft, (GdkEvent *) event); + + return TRUE; } /* This is called for keyboard and mouse events, it seems the only way @@ -2296,7 +2056,8 @@ emft_tree_user_event (GtkTreeView *treeview, GdkEvent *e, EMFolderTree *emft) } static void -emft_tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft) +emft_tree_selection_changed (GtkTreeSelection *selection, + EMFolderTree *emft) { gchar *full_name, *uri; GtkTreeModel *model; @@ -2306,9 +2067,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; } @@ -2331,10 +2090,14 @@ emft_tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft) } void -em_folder_tree_set_selected (EMFolderTree *emft, const gchar *uri, gboolean expand_only) +em_folder_tree_set_selected (EMFolderTree *emft, + const gchar *uri, + gboolean expand_only) { GList *l = NULL; + g_return_if_fail (EM_IS_FOLDER_TREE (emft)); + if (uri && uri[0]) l = g_list_append(l, (gpointer)uri); @@ -2346,6 +2109,7 @@ em_folder_tree_set_selected (EMFolderTree *emft, const gchar *uri, gboolean expa void em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter, parent, child; @@ -2355,7 +2119,8 @@ em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders) g_return_if_fail (EM_IS_FOLDER_TREE (emft)); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection(tree_view); if (gtk_tree_selection_get_selected(selection, &model, &iter)) { current_path = gtk_tree_model_get_path (model, &iter); @@ -2390,16 +2155,16 @@ em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders) } if (path) { - if (!gtk_tree_view_row_expanded (emft->priv->treeview, path)) - gtk_tree_view_expand_to_path (emft->priv->treeview, path); + if (!gtk_tree_view_row_expanded (tree_view, path)) + gtk_tree_view_expand_to_path (tree_view, path); gtk_tree_selection_select_path(selection, path); if (!priv->cursor_set) { - gtk_tree_view_set_cursor (priv->treeview, path, NULL, FALSE); + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); priv->cursor_set = TRUE; } - gtk_tree_view_scroll_to_cell (priv->treeview, path, NULL, TRUE, 0.5f, 0.0f); + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5f, 0.0f); } return; } @@ -2425,6 +2190,7 @@ get_last_child (GtkTreeModel *model, GtkTreeIter *iter) void em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter, child; @@ -2434,7 +2200,8 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) g_return_if_fail (EM_IS_FOLDER_TREE (emft)); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); if (gtk_tree_selection_get_selected(selection, &model, &iter)){ @@ -2468,25 +2235,25 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) } if (path) { - if (!gtk_tree_view_row_expanded (priv->treeview, path)) { - gtk_tree_view_expand_to_path (priv->treeview, path); + if (!gtk_tree_view_row_expanded (tree_view, path)) { + gtk_tree_view_expand_to_path (tree_view, path); } gtk_tree_selection_select_path(selection, path); if (!priv->cursor_set) { - gtk_tree_view_set_cursor (priv->treeview, path, NULL, FALSE); + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); priv->cursor_set = TRUE; } - gtk_tree_view_scroll_to_cell (priv->treeview, path, NULL, TRUE, 0.5f, 0.0f); + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5f, 0.0f); } return; } - gchar * em_folder_tree_get_selected_uri (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2494,9 +2261,13 @@ em_folder_tree_get_selected_uri (EMFolderTree *emft) g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL); - selection = gtk_tree_view_get_selection(emft->priv->treeview); - if (gtk_tree_selection_get_selected(selection, &model, &iter)) - gtk_tree_model_get(model, &iter, COL_STRING_URI, &uri, -1); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return NULL; + + gtk_tree_model_get (model, &iter, COL_STRING_URI, &uri, -1); return uri; } @@ -2504,6 +2275,7 @@ em_folder_tree_get_selected_uri (EMFolderTree *emft) gchar * em_folder_tree_get_selected_path (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2511,9 +2283,13 @@ em_folder_tree_get_selected_path (EMFolderTree *emft) g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL); - selection = gtk_tree_view_get_selection(emft->priv->treeview); - if (gtk_tree_selection_get_selected(selection, &model, &iter)) - gtk_tree_model_get(model, &iter, COL_STRING_FULL_NAME, &name, -1); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return NULL; + + gtk_tree_model_get (model, &iter, COL_STRING_FULL_NAME, &name, -1); return name; } @@ -2521,6 +2297,7 @@ em_folder_tree_get_selected_path (EMFolderTree *emft) CamelFolder * em_folder_tree_get_selected_folder (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2533,7 +2310,9 @@ em_folder_tree_get_selected_folder (EMFolderTree *emft) camel_exception_init (&ex); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, COL_STRING_FULL_NAME, &full_name, -1); @@ -2549,6 +2328,7 @@ em_folder_tree_get_selected_folder (EMFolderTree *emft) CamelFolderInfo * em_folder_tree_get_selected_folder_info (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2561,7 +2341,9 @@ em_folder_tree_get_selected_folder_info (EMFolderTree *emft) camel_exception_init (&ex); - selection = gtk_tree_view_get_selection(emft->priv->treeview); + tree_view = GTK_TREE_VIEW (emft); + selection = gtk_tree_view_get_selection (tree_view); + if (gtk_tree_selection_get_selected(selection, &model, &iter)) gtk_tree_model_get (model, &iter, COL_POINTER_CAMEL_STORE, &store, COL_STRING_FULL_NAME, &full_name, @@ -2598,47 +2380,6 @@ em_folder_tree_get_model (EMFolderTree *emft) return emft->priv->model; } -EMFolderTreeModelStoreInfo * -em_folder_tree_get_model_storeinfo (EMFolderTree *emft, CamelStore *store) -{ - struct _EMFolderTreePrivate *priv = emft->priv; - struct _EMFolderTreeModelStoreInfo *si; - - if (!(si = g_hash_table_lookup (priv->model->store_hash, store))) { - g_return_val_if_reached (NULL); - } - 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); -} - -GtkWidget * -em_folder_tree_get_tree_view (EMFolderTree *emft) -{ - return (GtkWidget *)emft->priv->treeview; -} - void em_folder_tree_set_skip_double_click (EMFolderTree *emft, gboolean skip) { |