diff options
Diffstat (limited to 'mail/em-folder-tree.c')
-rw-r--r-- | mail/em-folder-tree.c | 2039 |
1 files changed, 863 insertions, 1176 deletions
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c index b13a47a0e0..7c9293ca19 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,12 +61,10 @@ #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" #include "em-utils.h" -#include "em-popup.h" #include "em-folder-tree.h" #include "em-folder-utils.h" #include "em-folder-selector.h" @@ -73,8 +72,14 @@ #include "em-folder-properties.h" #include "em-event.h" +#include "e-mail-local.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,9 +88,6 @@ struct _selected_uri { }; struct _EMFolderTreePrivate { - GtkTreeView *treeview; - EMFolderTreeModel *model; - GSList *select_uris; /* selected_uri structures of each path pending selection. */ GHashTable *select_uris_table; /*Removed as they're encountered, so use this to find uri's not presnet but selected */ @@ -93,14 +95,11 @@ struct _EMFolderTreePrivate { gboolean (*excluded_func)(EMFolderTree *emft, GtkTreeModel *model, GtkTreeIter *iter, gpointer data); gpointer excluded_data; - guint do_multiselect:1; /* multiple select mode */ guint cursor_set:1; /* set to TRUE means we or something * else has set the cursor, otherwise * we need to set it when we set the * selection */ - guint save_state_id; - guint autoscroll_id; guint autoexpand_id; GtkTreeRowReference *autoexpand_row; @@ -115,7 +114,7 @@ struct _EMFolderTreePrivate { enum { FOLDER_ACTIVATED, /* aka double-clicked or user hit enter */ FOLDER_SELECTED, - HIDDEN_KEY_EVENT, + POPUP_EVENT, LAST_SIGNAL }; @@ -154,101 +153,613 @@ 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); +struct _emft_selection_data { + GtkTreeModel *model; + GtkTreeIter *iter; + gboolean set; +}; -static gboolean emft_save_state (EMFolderTree *emft); -static void emft_queue_save_state (EMFolderTree *emft); +static gpointer parent_class = NULL; -static void emft_update_model_expanded_state (struct _EMFolderTreePrivate *priv, GtkTreeIter *iter, gboolean expanded); +struct _EMFolderTreeGetFolderInfo { + MailMsg base; -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); -static gboolean emft_tree_button_press (GtkTreeView *treeview, GdkEventButton *event, EMFolderTree *emft); -static void emft_tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft); -static gboolean emft_tree_user_event (GtkTreeView *treeview, GdkEvent *e, EMFolderTree *emft); -static gboolean emft_popup_menu (GtkWidget *widget); + /* input data */ + GtkTreeRowReference *root; + EMFolderTree *emft; + CamelStore *store; + guint32 flags; + gchar *top; -struct _emft_selection_data { + /* output data */ + CamelFolderInfo *fi; +}; + +static gchar * +emft_get_folder_info__desc (struct _EMFolderTreeGetFolderInfo *m) +{ + gchar *ret, *name; + + name = camel_service_get_name((CamelService *)m->store, TRUE); + ret = g_strdup_printf(_("Scanning folders in \"%s\""), name); + g_free(name); + return ret; +} + +static void +emft_get_folder_info__exec (struct _EMFolderTreeGetFolderInfo *m) +{ + guint32 flags = m->flags | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; + + m->fi = camel_store_get_folder_info (m->store, m->top, flags, &m->base.ex); +} + +static void +emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) +{ + struct _EMFolderTreeModelStoreInfo *si; + GtkTreeIter root, iter, titer; + CamelFolderInfo *fi; + GtkTreeView *tree_view; GtkTreeModel *model; - GtkTreeIter *iter; - gboolean set; + GtkTreePath *path; + gboolean is_store; + + /* check that we haven't been destroyed */ + 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; + + tree_view = GTK_TREE_VIEW (m->emft); + model = gtk_tree_view_get_model (tree_view); + + si = em_folder_tree_model_lookup_store_info ( + EM_FOLDER_TREE_MODEL (model), m->store); + if (si == NULL) { + /* store has been removed in the interim - do nothing */ + return; + } + + path = gtk_tree_row_reference_get_path (m->root); + gtk_tree_model_get_iter (model, &root, path); + + /* 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( + GTK_TREE_STORE (model), &root, + COL_BOOL_LOAD_SUBDIRS, TRUE, -1); + gtk_tree_view_collapse_row (tree_view, path); + gtk_tree_path_free (path); + return; + } + + gtk_tree_path_free (path); + + /* make sure we still need to load the tree subfolders... */ + gtk_tree_model_get (model, &root, COL_BOOL_IS_STORE, &is_store, -1); + + /* get the first child (which will be a dummy node) */ + gtk_tree_model_iter_children (model, &iter, &root); + + /* Traverse to the last valid iter */ + titer = iter; + while (gtk_tree_model_iter_next (model, &iter)) + titer = iter; /* Preserve the last valid iter */ + + iter = titer; + + /* FIXME: camel's IMAP code is totally on crack here, @top's + * folder info should be @fi and fi->child should be what we + * want to fill our tree with... *sigh* */ + if (m->top && m->fi && !strcmp (m->fi->full_name, m->top)) { + if (!(fi = m->fi->child)) + fi = m->fi->next; + } else + fi = m->fi; + + if (fi == NULL) { + /* no children afterall... remove the "Loading..." placeholder node */ + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter); + + if (is_store) { + path = gtk_tree_model_get_path (model, &root); + gtk_tree_view_collapse_row (tree_view, path); + gtk_tree_path_free (path); + return; + } + } else { + gint fully_loaded = (m->flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) ? TRUE : FALSE; + + do { + gboolean known = g_hash_table_lookup (si->full_hash, fi->full_name) != NULL; + + if (!known) + em_folder_tree_model_set_folder_info ( + EM_FOLDER_TREE_MODEL (model), + &iter, si, fi, fully_loaded); + + if ((fi = fi->next) != NULL && !known) + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &root); + } while (fi != NULL); + } + + gtk_tree_store_set ( + GTK_TREE_STORE (model), &root, + COL_BOOL_LOAD_SUBDIRS, FALSE, -1); +} + +static void +emft_get_folder_info__free (struct _EMFolderTreeGetFolderInfo *m) +{ + camel_store_free_folder_info (m->store, m->fi); + + gtk_tree_row_reference_free (m->root); + g_object_unref(m->emft); + camel_object_unref (m->store); + g_free (m->top); +} + +static MailMsgInfo get_folder_info_info = { + sizeof (struct _EMFolderTreeGetFolderInfo), + (MailMsgDescFunc) emft_get_folder_info__desc, + (MailMsgExecFunc) emft_get_folder_info__exec, + (MailMsgDoneFunc) emft_get_folder_info__done, + (MailMsgFreeFunc) emft_get_folder_info__free }; -static GtkVBoxClass *parent_class = NULL; +static void +folder_tree_emit_popup_event (EMFolderTree *emft, + GdkEvent *event) +{ + g_signal_emit (emft, signals[POPUP_EVENT], 0, event); +} -GType -em_folder_tree_get_type (void) +static void +emft_free_select_uri (struct _selected_uri *u) { - static GType type = 0; + g_free (u->uri); + if (u->store) + camel_object_unref (u->store); + g_free (u->key); + g_free (u->path); + g_free (u); +} - 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 gboolean +emft_select_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean selected) +{ + EMFolderTreePrivate *priv; + GtkTreeView *tree_view; + gboolean is_store; + guint32 flags; + GtkTreeIter iter; + + tree_view = gtk_tree_selection_get_tree_view (selection); + + priv = EM_FOLDER_TREE_GET_PRIVATE (tree_view); + + if (selected) + return TRUE; + + if (priv->excluded == 0 && priv->excluded_func == NULL) + return TRUE; + + if (!gtk_tree_model_get_iter (model, &iter, path)) + return TRUE; + + if (priv->excluded_func != NULL) + return priv->excluded_func( + EM_FOLDER_TREE (tree_view), model, + &iter, priv->excluded_data); + + gtk_tree_model_get ( + model, &iter, COL_UINT_FLAGS, &flags, + COL_BOOL_IS_STORE, &is_store, -1); + + if (is_store) + flags |= CAMEL_FOLDER_NOSELECT; + + return (flags & priv->excluded) == 0; +} + +static void +emft_clear_selected_list(EMFolderTree *emft) +{ + EMFolderTreePrivate *priv = emft->priv; + + 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; + priv->select_uris_table = g_hash_table_new(g_str_hash, g_str_equal); + priv->cursor_set = FALSE; +} + +static void +emft_selection_changed_cb (EMFolderTree *emft, + GtkTreeSelection *selection) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GList *list; + guint32 flags = 0; + guint unread = 0; + guint old_unread = 0; + gchar *full_name = NULL; + gchar *uri = NULL; - type = g_type_register_static (GTK_TYPE_VBOX, "EMFolderTree", &info, 0); + list = gtk_tree_selection_get_selected_rows (selection, &model); + + if (list == NULL) + goto exit; + + gtk_tree_model_get_iter (model, &iter, list->data); + + gtk_tree_model_get ( + model, &iter, + COL_STRING_FULL_NAME, &full_name, + COL_STRING_URI, &uri, COL_UINT_FLAGS, &flags, + COL_UINT_UNREAD, &unread, COL_UINT_UNREAD_LAST_SEL, + &old_unread, -1); + + /* Sync unread counts to distinguish new incoming mail. */ + if (unread != old_unread) + gtk_tree_store_set ( + GTK_TREE_STORE (model), &iter, + COL_UINT_UNREAD_LAST_SEL, unread, -1); + +exit: + g_signal_emit ( + emft, signals[FOLDER_SELECTED], 0, full_name, uri, flags); + + g_free (full_name); + g_free (uri); + + g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL); + g_list_free (list); +} + +static void +folder_tree_finalize (GObject *object) +{ + EMFolderTreePrivate *priv; + + priv = EM_FOLDER_TREE_GET_PRIVATE (object); + + 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_class_init (EMFolderTreeClass *klass) +em_folder_tree_destroy (GtkObject *object) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + EMFolderTreePrivate *priv; + GtkTreeModel *model; - parent_class = g_type_class_ref (GTK_TYPE_VBOX); + priv = EM_FOLDER_TREE_GET_PRIVATE (object); - object_class->finalize = em_folder_tree_finalize; + model = gtk_tree_view_get_model (GTK_TREE_VIEW (object)); + + if (priv->loaded_row_id != 0) { + g_signal_handler_disconnect (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; + } + + /* Chain up to parent's destroy() method. */ + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static gboolean +emft_button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + EMFolderTreePrivate *priv; + GtkWidgetClass *widget_class; + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreePath *path; + + priv = EM_FOLDER_TREE_GET_PRIVATE (widget); + + tree_view = GTK_TREE_VIEW (widget); + selection = gtk_tree_view_get_selection (tree_view); + + if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_SINGLE) + emft_clear_selected_list (EM_FOLDER_TREE (widget)); + + priv->cursor_set = TRUE; + + if (event->button != 3) + goto chainup; + + if (!gtk_tree_view_get_path_at_pos ( + tree_view, event->x, event->y, + &path, NULL, NULL, NULL)) + goto chainup; + + /* select/focus the row that was right-clicked */ + gtk_tree_selection_select_path (selection, path); + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); + + gtk_tree_path_free (path); + + folder_tree_emit_popup_event ( + EM_FOLDER_TREE (tree_view), (GdkEvent *) event); + +chainup: + + /* Chain up to parent's button_press_event() method. */ + widget_class = GTK_WIDGET_CLASS (parent_class); + return widget_class->button_press_event (widget, event); +} + +static gboolean +emft_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + EMFolderTreePrivate *priv; + GtkWidgetClass *widget_class; + GtkTreeSelection *selection; + GtkTreeView *tree_view; + + priv = EM_FOLDER_TREE_GET_PRIVATE (widget); + + tree_view = GTK_TREE_VIEW (widget); + selection = gtk_tree_view_get_selection (tree_view); + + if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_SINGLE) + emft_clear_selected_list (EM_FOLDER_TREE (widget)); + + priv->cursor_set = TRUE; + + /* Chain up to parent's key_press_event() method. */ + widget_class = GTK_WIDGET_CLASS (parent_class); + return widget_class->key_press_event (widget, event); +} + +static gboolean +emft_popup_menu (GtkWidget *widget) +{ + folder_tree_emit_popup_event (EM_FOLDER_TREE (widget), NULL); + + return TRUE; +} + +static void +emft_row_activated (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column) +{ + EMFolderTreePrivate *priv; + GtkTreeModel *model; + gchar *full_name, *uri; + GtkTreeIter iter; + guint32 flags; + + priv = EM_FOLDER_TREE_GET_PRIVATE (tree_view); + + model = gtk_tree_view_get_model (tree_view); + + if (priv->skip_double_click) + return; + + if (!gtk_tree_model_get_iter (model, &iter, path)) + return; + + gtk_tree_model_get ( + model, &iter, COL_STRING_FULL_NAME, &full_name, + COL_STRING_URI, &uri, COL_UINT_FLAGS, &flags, -1); + + emft_clear_selected_list (EM_FOLDER_TREE (tree_view)); + + g_signal_emit ( + tree_view, signals[FOLDER_SELECTED], 0, full_name, uri, flags); + + g_signal_emit ( + tree_view, signals[FOLDER_ACTIVATED], 0, full_name, uri); + + g_free (full_name); + g_free (uri); +} + +static gboolean +emft_test_collapse_row (GtkTreeView *tree_view, + GtkTreeIter *iter, + GtkTreePath *path) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter cursor; + + selection = gtk_tree_view_get_selection (tree_view); + + if (!gtk_tree_selection_get_selected (selection, &model, &cursor)) + goto exit; + + /* Select the collapsed node IFF it is a + * parent of the currently selected folder. */ + if (gtk_tree_store_is_ancestor (GTK_TREE_STORE (model), iter, &cursor)) + gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE); + +exit: + return FALSE; +} + +static void +emft_row_expanded (GtkTreeView *tree_view, + GtkTreeIter *iter, + GtkTreePath *path) +{ + struct _EMFolderTreeGetFolderInfo *msg; + GtkTreeModel *model; + CamelStore *store; + gchar *full_name; + gboolean load; + + model = gtk_tree_view_get_model (tree_view); + + gtk_tree_model_get ( + model, iter, + COL_STRING_FULL_NAME, &full_name, + COL_POINTER_CAMEL_STORE, &store, + COL_BOOL_LOAD_SUBDIRS, &load, -1); + + if (!load) { + g_free (full_name); + return; + } + + gtk_tree_store_set ( + GTK_TREE_STORE (model), iter, + COL_BOOL_LOAD_SUBDIRS, FALSE, -1); + + msg = mail_msg_new (&get_folder_info_info); + msg->root = gtk_tree_row_reference_new (model, path); + camel_object_ref (store); + msg->store = store; + msg->emft = g_object_ref (tree_view); + msg->top = full_name; + msg->flags = + CAMEL_STORE_FOLDER_INFO_RECURSIVE | + CAMEL_STORE_FOLDER_INFO_FAST; + + mail_msg_unordered_push (msg); +} + +static void +folder_tree_class_init (EMFolderTreeClass *class) +{ + GObjectClass *object_class; + GtkObjectClass *gtk_object_class; + GtkWidgetClass *widget_class; + GtkTreeViewClass *tree_view_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMFolderTreePrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = 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->button_press_event = emft_button_press_event; + widget_class->key_press_event = emft_key_press_event; 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[HIDDEN_KEY_EVENT] = - g_signal_new ("hidden-key-event", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EMFolderTreeClass, hidden_key_event), - NULL, NULL, - g_cclosure_marshal_VOID__BOXED, - G_TYPE_NONE, 1, GDK_TYPE_EVENT); + tree_view_class = GTK_TREE_VIEW_CLASS (class); + tree_view_class->row_activated = emft_row_activated; + tree_view_class->test_collapse_row = emft_test_collapse_row; + tree_view_class->row_expanded = emft_row_expanded; + + 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) +{ + GtkTreeSelection *selection; + GHashTable *select_uris_table; + EMFolderTreeModel *model; + + 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; + + model = em_folder_tree_model_get_default (); + gtk_tree_view_set_model (GTK_TREE_VIEW (emft), GTK_TREE_MODEL (model)); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (emft)); + + g_signal_connect_swapped ( + selection, "changed", + G_CALLBACK (emft_selection_changed_cb), emft); +} + +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 @@ -277,7 +788,7 @@ static void render_display_name (GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) { - gboolean is_store, bold, subdirs_unread = FALSE; + gboolean is_store, bold; guint unread; gchar *display; gchar *name; @@ -286,36 +797,28 @@ render_display_name (GtkTreeViewColumn *column, GtkCellRenderer *renderer, COL_BOOL_IS_STORE, &is_store, COL_UINT_UNREAD, &unread, -1); - bold = is_store || unread; - - if (gtk_tree_model_iter_has_child (model, iter)) { - gboolean expanded = TRUE; - - g_object_get (renderer, "is-expanded", &expanded, NULL); - - if (!bold || !expanded) - subdirs_unread = subdirs_contain_unread (model, iter); + if (!(bold = is_store || unread)) { + if (gtk_tree_model_iter_has_child (model, iter)) + bold = subdirs_contain_unread (model, iter); } - bold = bold || subdirs_unread; - if (!is_store && unread) { /* Translators: This is the string used for displaying the - * folder names in folder trees. The first "%s" will be - * replaced by the folder's name and "%u" will be replaced - * with the number of unread messages in the folder. The - * second %s will be replaced with a "+" letter for collapsed - * folders with unread messages in some subfolder too, - * or with an empty string for other cases. + * folder names in folder trees. "%s" will be replaced by + * the folder's name and "%u" will be replaced with the + * number of unread messages in the folder. * - * Most languages should translate this as "%s (%u%s)". The + * Most languages should translate this as "%s (%u)". The * languages that use localized digits (like Persian) may * need to replace "%u" with "%Iu". Right-to-left languages * (like Arabic and Hebrew) may need to add bidirectional * formatting codes to take care of the cases the folder * name appears in either direction. + * + * Do not translate the "folder-display|" part. Remove it + * from your translation. */ - display = g_strdup_printf (C_("folder-display", "%s (%u%s)"), name, unread, subdirs_unread ? "+" : ""); + display = g_strdup_printf (C_("folder-display", "%s (%u)"), name, unread); g_free (name); } else display = name; @@ -333,10 +836,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, @@ -349,8 +855,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; @@ -368,133 +878,21 @@ render_icon (GtkTreeViewColumn *column, g_object_set (renderer, "gicon", icon, NULL); g_object_unref (icon); - g_free (icon_name); -} - -static gboolean -emft_select_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean selected, gpointer data) -{ - EMFolderTree *emft = data; - gboolean is_store; - guint32 flags; - GtkTreeIter iter; - - /* NB: This will be called with selection==NULL from tree_row_activated */ - if (emft->priv->excluded == 0 && emft->priv->excluded_func == NULL) - return TRUE; - - if (!gtk_tree_model_get_iter(model, &iter, path)) - return TRUE; - - if (emft->priv->excluded_func != NULL) - return emft->priv->excluded_func(emft, model, &iter, emft->priv->excluded_data); - - gtk_tree_model_get(model, &iter, COL_UINT_FLAGS, &flags, COL_BOOL_IS_STORE, &is_store, -1); - if (is_store) - flags |= CAMEL_FOLDER_NOSELECT; - - 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) +folder_tree_new (EMFolderTree *emft) { GtkTreeSelection *selection; GtkTreeViewColumn *column; GtkCellRenderer *renderer; GtkWidget *tree; - gboolean side_bar_search; GConfClient *gconf; 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 Gross hack */ + tree = GTK_WIDGET (emft); GTK_WIDGET_SET_FLAGS(tree, GTK_CAN_FOCUS); column = gtk_tree_view_column_new (); @@ -516,84 +914,99 @@ folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model) selection = gtk_tree_view_get_selection ((GtkTreeView *) tree); gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - gtk_tree_selection_set_select_function(selection, emft_select_func, emft, NULL); + gtk_tree_selection_set_select_function ( + selection, (GtkTreeSelectionFunc) + emft_select_func, NULL, NULL); gtk_tree_view_set_headers_visible ((GtkTreeView *) tree, FALSE); gtk_tree_view_set_search_column((GtkTreeView *)tree, COL_STRING_DISPLAY_NAME); - gtk_tree_view_set_enable_search((GtkTreeView *)tree, side_bar_search); return (GtkTreeView *) tree; } 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); + + /* Center the tree view on the selected path. */ + gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.0); +} - priv->model = model; - priv->treeview = folder_tree_new (emft, model); - gtk_widget_show ((GtkWidget *) priv->treeview); +static void +folder_tree_copy_state (EMFolderTree *emft) +{ + GtkTreeSelection *selection; + GtkTreeView *tree_view; + GtkTreeModel *model; - 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); + tree_view = GTK_TREE_VIEW (emft); + model = gtk_tree_view_get_model (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 ( + EM_FOLDER_TREE_MODEL (model)); + if (selection == NULL) + return; - 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; - EMFolderTree *emft; - - model = em_folder_tree_model_new (e_get_user_data_dir ()); - emft = (EMFolderTree *) em_folder_tree_new_with_model (model); - g_object_unref (model); - - return (GtkWidget *) emft; + folder_tree_new (emft); + folder_tree_copy_state (emft); + gtk_widget_show (GTK_WIDGET (emft)); } /* NOTE: Removes and frees the selected uri structure */ static void emft_select_uri(EMFolderTree *emft, GtkTreePath *path, struct _selected_uri *u) { - struct _EMFolderTreePrivate *priv = emft->priv; + 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 -emft_expand_node (EMFolderTreeModel *model, const gchar *key, EMFolderTree *emft) +emft_expand_node (const gchar *key, EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; struct _EMFolderTreeModelStoreInfo *si; GtkTreeRowReference *row; + GtkTreeView *tree_view; + GtkTreeModel *model; GtkTreePath *path; EAccount *account; CamelStore *store; @@ -611,7 +1024,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); + model = gtk_tree_view_get_model (tree_view); + + if ((account = e_get_account_by_uid (uid)) && account->enabled) { CamelException ex; camel_exception_init (&ex); @@ -626,7 +1042,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_local_get_store ())) return; camel_object_ref (store); @@ -634,7 +1050,9 @@ 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 ( + EM_FOLDER_TREE_MODEL (model), store); + if (si == NULL) { camel_object_unref (store); return; } @@ -648,7 +1066,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) @@ -660,15 +1078,17 @@ emft_expand_node (EMFolderTreeModel *model, const gchar *key, EMFolderTree *emft static void emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTreeIter *iter, EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; + 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, @@ -676,8 +1096,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 */ @@ -687,21 +1107,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 (key, emft); - if (u) - emft_select_uri(emft, tree_path, u); + emft_select_uri(emft, tree_path, u); } g_free (full_name); @@ -709,21 +1122,25 @@ emft_maybe_expand_row (EMFolderTreeModel *model, GtkTreePath *tree_path, GtkTree } GtkWidget * -em_folder_tree_new_with_model (EMFolderTreeModel *model) +em_folder_tree_new (void) { EMFolderTree *emft; + GtkTreeModel *model; AtkObject *a11y; emft = g_object_new (EM_TYPE_FOLDER_TREE, NULL); - em_folder_tree_construct (emft, model); - g_object_ref (model); + em_folder_tree_construct (emft); - em_folder_tree_model_expand_foreach (model, (EMFTModelExpandFunc)emft_expand_node, emft); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (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); + 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; @@ -732,7 +1149,7 @@ em_folder_tree_new_with_model (EMFolderTreeModel *model) static void tree_drag_begin (GtkWidget *widget, GdkDragContext *context, EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; + EMFolderTreePrivate *priv = emft->priv; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreePath *path; @@ -752,8 +1169,9 @@ tree_drag_begin (GtkWidget *widget, GdkDragContext *context, EMFolderTree *emft) static void tree_drag_data_delete(GtkWidget *widget, GdkDragContext *context, EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; + EMFolderTreePrivate *priv = emft->priv; gchar *full_name = NULL; + GtkTreeModel *model; GtkTreePath *src_path; gboolean is_store; CamelStore *store; @@ -763,13 +1181,16 @@ tree_drag_data_delete(GtkWidget *widget, GdkDragContext *context, EMFolderTree * if (!priv->drag_row || (src_path = gtk_tree_row_reference_get_path (priv->drag_row))) return; - if (!gtk_tree_model_get_iter((GtkTreeModel *)priv->model, &iter, src_path)) + model = gtk_tree_view_get_model (GTK_TREE_VIEW (emft)); + + if (!gtk_tree_model_get_iter (model, &iter, src_path)) goto fail; - gtk_tree_model_get((GtkTreeModel *)priv->model, &iter, - COL_POINTER_CAMEL_STORE, &store, - COL_STRING_FULL_NAME, &full_name, - COL_BOOL_IS_STORE, &is_store, -1); + gtk_tree_model_get ( + model, &iter, + COL_POINTER_CAMEL_STORE, &store, + COL_STRING_FULL_NAME, &full_name, + COL_BOOL_IS_STORE, &is_store, -1); if (is_store) goto fail; @@ -786,8 +1207,9 @@ fail: static void tree_drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection, guint info, guint time, EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; + EMFolderTreePrivate *priv = emft->priv; gchar *full_name = NULL, *uri = NULL; + GtkTreeModel *model; GtkTreePath *src_path; CamelFolder *folder; CamelStore *store; @@ -797,13 +1219,16 @@ tree_drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData if (!priv->drag_row || !(src_path = gtk_tree_row_reference_get_path(priv->drag_row))) return; - if (!gtk_tree_model_get_iter((GtkTreeModel *)priv->model, &iter, src_path)) + model = gtk_tree_view_get_model (GTK_TREE_VIEW (emft)); + + if (!gtk_tree_model_get_iter (model, &iter, src_path)) goto fail; - gtk_tree_model_get((GtkTreeModel *)priv->model, &iter, - COL_POINTER_CAMEL_STORE, &store, - COL_STRING_FULL_NAME, &full_name, - COL_STRING_URI, &uri, -1); + gtk_tree_model_get ( + model, &iter, + COL_POINTER_CAMEL_STORE, &store, + COL_STRING_FULL_NAME, &full_name, + COL_STRING_URI, &uri, -1); /* make sure user isn't trying to drag on a placeholder row */ if (full_name == NULL) @@ -959,61 +1384,22 @@ tree_drag_data_action(struct _DragDataReceivedAsync *m) } static void -emft_drop_popup_copy(EPopup *ep, EPopupItem *item, gpointer data) -{ - struct _DragDataReceivedAsync *m = data; - - m->action = GDK_ACTION_COPY; - tree_drag_data_action(m); -} - -static void -emft_drop_popup_move(EPopup *ep, EPopupItem *item, gpointer data) -{ - struct _DragDataReceivedAsync *m = data; - - m->action = GDK_ACTION_MOVE; - tree_drag_data_action(m); -} - -static void -emft_drop_popup_cancel(EPopup *ep, EPopupItem *item, gpointer data) -{ - struct _DragDataReceivedAsync *m = data; - - m->aborted = TRUE; - mail_msg_unref(m); -} - -static EPopupItem emft_drop_popup_menu[] = { - { E_POPUP_ITEM, (gchar *) "00.emc.00", (gchar *) N_("_Copy to Folder"), emft_drop_popup_copy, NULL, NULL, 1 }, - { E_POPUP_ITEM, (gchar *) "00.emc.01", (gchar *) N_("_Move to Folder"), emft_drop_popup_move, NULL, NULL, 1 }, - { E_POPUP_ITEM, (gchar *) "00.emc.02", (gchar *) N_("_Copy"), emft_drop_popup_copy, NULL, (gchar *) "folder-copy", 2 }, - { E_POPUP_ITEM, (gchar *) "00.emc.03", (gchar *) N_("_Move"), emft_drop_popup_move, NULL, (gchar *) "folder-move", 2 }, - { E_POPUP_BAR, (gchar *) "10.emc" }, - { E_POPUP_ITEM, (gchar *) "99.emc.00", (gchar *) N_("Cancel _Drag"), emft_drop_popup_cancel, NULL, (gchar *) "dialog-cancel", 0 }, -}; - -static void -emft_drop_popup_free(EPopup *ep, GSList *items, gpointer data) -{ - g_slist_free(items); -} - -static void tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *selection, guint info, guint time, EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; GtkTreeViewDropPosition pos; + GtkTreeModel *model; + GtkTreeView *tree_view; GtkTreePath *dest_path; struct _DragDataReceivedAsync *m; gboolean is_store; CamelStore *store; GtkTreeIter iter; 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); + model = gtk_tree_view_get_model (tree_view); + + if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &dest_path, &pos)) return; /* this means we are receiving no data */ @@ -1022,15 +1408,16 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint return; } - if (!gtk_tree_model_get_iter((GtkTreeModel *)priv->model, &iter, dest_path)) { + if (!gtk_tree_model_get_iter (model, &iter, dest_path)) { gtk_drag_finish(context, FALSE, FALSE, GDK_CURRENT_TIME); return; } - gtk_tree_model_get((GtkTreeModel *)priv->model, &iter, - COL_POINTER_CAMEL_STORE, &store, - COL_BOOL_IS_STORE, &is_store, - COL_STRING_FULL_NAME, &full_name, -1); + gtk_tree_model_get ( + model, &iter, + COL_POINTER_CAMEL_STORE, &store, + COL_BOOL_IS_STORE, &is_store, + COL_STRING_FULL_NAME, &full_name, -1); /* make sure user isn't try to drop on a placeholder row */ if (full_name == NULL && !is_store) { @@ -1053,30 +1440,7 @@ tree_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint memcpy(m->selection->data, selection->data, selection->length); m->selection->length = selection->length; - if (context->action == GDK_ACTION_ASK) { - EMPopup *emp; - gint mask; - GSList *menus = NULL; - GtkMenu *menu; - - emp = em_popup_new("org.gnome.mail.storageset.popup.drop"); - if (info != DND_DROP_TYPE_FOLDER) - mask = ~1; - else - mask = ~2; - - for (i=0;i<sizeof(emft_drop_popup_menu)/sizeof(emft_drop_popup_menu[0]);i++) { - EPopupItem *item = &emft_drop_popup_menu[i]; - - if ((item->visible & mask) == 0) - menus = g_slist_append(menus, item); - } - e_popup_add_items((EPopup *)emp, menus, NULL, emft_drop_popup_free, m); - menu = e_popup_create_menu_once((EPopup *)emp, NULL, mask); - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); - } else { - tree_drag_data_action(m); - } + tree_drag_data_action(m); } static gboolean @@ -1088,27 +1452,32 @@ is_special_local_folder (const gchar *name) static GdkAtom emft_drop_target(EMFolderTree *emft, GdkDragContext *context, GtkTreePath *path) { - struct _EMFolderTreePrivate *p = emft->priv; + EMFolderTreePrivate *p = emft->priv; gchar *full_name = NULL, *uri = NULL, *src_uri = NULL; CamelStore *local, *sstore, *dstore; GdkAtom atom = GDK_NONE; gboolean is_store; + GtkTreeModel *model; GtkTreeIter iter; GList *targets; guint32 flags = 0; + model = gtk_tree_view_get_model (GTK_TREE_VIEW (emft)); + /* This is a bit of a mess, but should handle all the cases properly */ - if (!gtk_tree_model_get_iter((GtkTreeModel *)p->model, &iter, path)) + if (!gtk_tree_model_get_iter (model, &iter, path)) return GDK_NONE; - gtk_tree_model_get((GtkTreeModel *)p->model, &iter, COL_BOOL_IS_STORE, &is_store, - COL_STRING_FULL_NAME, &full_name, - COL_UINT_FLAGS, &flags, - COL_POINTER_CAMEL_STORE, &dstore, - COL_STRING_URI, &uri, -1); + gtk_tree_model_get ( + model, &iter, + COL_BOOL_IS_STORE, &is_store, + COL_STRING_FULL_NAME, &full_name, + COL_UINT_FLAGS, &flags, + COL_POINTER_CAMEL_STORE, &dstore, + COL_STRING_URI, &uri, -1); - local = mail_component_peek_local_store (NULL); + local = e_mail_local_get_store (); targets = context->targets; @@ -1150,10 +1519,11 @@ emft_drop_target(EMFolderTree *emft, GdkDragContext *context, GtkTreePath *path) GtkTreePath *src_path = gtk_tree_row_reference_get_path(p->drag_row); if (src_path) { - if (gtk_tree_model_get_iter((GtkTreeModel *)p->model, &iter, src_path)) - gtk_tree_model_get((GtkTreeModel *)p->model, &iter, - COL_POINTER_CAMEL_STORE, &sstore, - COL_STRING_URI, &src_uri, -1); + if (gtk_tree_model_get_iter (model, &iter, src_path)) + gtk_tree_model_get ( + model, &iter, + COL_POINTER_CAMEL_STORE, &sstore, + COL_STRING_URI, &src_uri, -1); /* can't dnd onto itself or below itself - bad things happen, no point dragging to where we were either */ @@ -1284,12 +1654,15 @@ emft_drop_target(EMFolderTree *emft, GdkDragContext *context, GtkTreePath *path) static gboolean tree_drag_drop (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; + 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; @@ -1303,7 +1676,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); @@ -1317,7 +1690,7 @@ tree_drag_drop (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guin static void tree_drag_end (GtkWidget *widget, GdkDragContext *context, EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; + EMFolderTreePrivate *priv = emft->priv; if (priv->drag_row) { gtk_tree_row_reference_free (priv->drag_row); @@ -1330,7 +1703,10 @@ tree_drag_end (GtkWidget *widget, GdkDragContext *context, EMFolderTree *emft) static void tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; + EMFolderTreePrivate *priv = emft->priv; + GtkTreeView *tree_view; + + tree_view = GTK_TREE_VIEW (emft); if (priv->autoscroll_id != 0) { g_source_remove (priv->autoscroll_id); @@ -1345,7 +1721,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); } #define SCROLL_EDGE_SIZE 15 @@ -1353,19 +1729,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; @@ -1377,7 +1754,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); @@ -1388,11 +1765,13 @@ tree_autoscroll (EMFolderTree *emft) static gboolean tree_autoexpand (EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; + 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; @@ -1401,16 +1780,20 @@ tree_autoexpand (EMFolderTree *emft) static gboolean tree_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv = emft->priv; - GtkTreeModel *model = (GtkTreeModel *) priv->model; + EMFolderTreePrivate *priv = emft->priv; GtkTreeViewDropPosition pos; + GtkTreeView *tree_view; + GtkTreeModel *model; 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); + model = gtk_tree_view_get_model (tree_view); + + if (!gtk_tree_view_get_dest_row_at_pos(tree_view, x, y, &path, &pos)) return FALSE; if (priv->autoscroll_id == 0) @@ -1418,7 +1801,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; @@ -1454,10 +1837,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; } @@ -1476,12 +1859,15 @@ tree_drag_motion (GtkWidget *widget, GdkDragContext *context, gint x, gint y, gu void em_folder_tree_enable_drag_and_drop (EMFolderTree *emft) { - struct _EMFolderTreePrivate *priv; + 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++) @@ -1493,35 +1879,35 @@ 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); + gtk_drag_dest_set((GtkWidget *)tree_view, GTK_DEST_DEFAULT_ALL, drop_types, NUM_DROP_TYPES, GDK_ACTION_COPY | GDK_ACTION_MOVE); - 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_excluded (EMFolderTree *emft, guint32 flags) { - GtkTreeSelection *sel = gtk_tree_view_get_selection ((GtkTreeView *) tree->priv->treeview); - - tree->priv->do_multiselect = mode; - gtk_tree_selection_set_mode (sel, mode ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE); -} + g_return_if_fail (EM_IS_FOLDER_TREE (emft)); -void em_folder_tree_set_excluded(EMFolderTree *emft, guint32 flags) -{ 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; } @@ -1529,10 +1915,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)) @@ -1569,31 +1959,22 @@ 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; } -static void -emft_clear_selected_list(EMFolderTree *emft) -{ - struct _EMFolderTreePrivate *priv = emft->priv; - - g_slist_foreach(priv->select_uris, emft_free_select_uri, emft); - g_slist_free(priv->select_uris); - g_hash_table_destroy(priv->select_uris_table); - priv->select_uris = NULL; - priv->select_uris_table = g_hash_table_new(g_str_hash, g_str_equal); - priv->cursor_set = FALSE; -} - void em_folder_tree_set_selected_list (EMFolderTree *emft, GList *list, gboolean expand_only) { - struct _EMFolderTreePrivate *priv = emft->priv; + EMFolderTreePrivate *priv = emft->priv; gint id = 0; /* FIXME: need to remove any currently selected stuff? */ @@ -1646,8 +2027,7 @@ 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); + emft_expand_node(expand_key, emft); *end = 0; end = strrchr(expand_key, '/'); } while (end); @@ -1679,680 +2059,15 @@ dump_fi (CamelFolderInfo *fi, gint depth) } #endif -struct _EMFolderTreeGetFolderInfo { - MailMsg base; - - /* input data */ - GtkTreeRowReference *root; - EMFolderTree *emft; - CamelStore *store; - guint32 flags; - gchar *top; - - /* output data */ - CamelFolderInfo *fi; -}; - -static gchar * -emft_get_folder_info__desc (struct _EMFolderTreeGetFolderInfo *m) -{ - gchar *ret, *name; - - name = camel_service_get_name((CamelService *)m->store, TRUE); - ret = g_strdup_printf(_("Scanning folders in \"%s\""), name); - g_free(name); - return ret; -} - -static void -emft_get_folder_info__exec (struct _EMFolderTreeGetFolderInfo *m) -{ - guint32 flags = m->flags | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED; - - m->fi = camel_store_get_folder_info (m->store, m->top, flags, &m->base.ex); -} - -static void -emft_get_folder_info__done (struct _EMFolderTreeGetFolderInfo *m) -{ - struct _EMFolderTreePrivate *priv = m->emft->priv; - struct _EMFolderTreeModelStoreInfo *si; - GtkTreeIter root, iter, titer; - CamelFolderInfo *fi; - GtkTreeStore *model; - GtkTreePath *path; - gboolean is_store; - - /* check that we haven't been destroyed */ - if (priv->treeview == NULL) - return; - - /* 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))) { - /* store has been removed in the interim - do nothing */ - return; - } - - model = (GtkTreeStore *) gtk_tree_view_get_model (priv->treeview); - - path = gtk_tree_row_reference_get_path (m->root); - gtk_tree_model_get_iter ((GtkTreeModel *) model, &root, path); - - /* 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_path_free (path); - return; - } - - gtk_tree_path_free (path); - - /* make sure we still need to load the tree subfolders... */ - gtk_tree_model_get ((GtkTreeModel *) model, &root, - COL_BOOL_IS_STORE, &is_store, - -1); - - /* get the first child (which will be a dummy node) */ - gtk_tree_model_iter_children ((GtkTreeModel *) model, &iter, &root); - - /* Traverse to the last valid iter */ - titer = iter; - while (gtk_tree_model_iter_next((GtkTreeModel *) model, &iter)) - titer = iter; /* Preserve the last valid iter */ - - iter = titer; - - /* FIXME: camel's IMAP code is totally on crack here, @top's - * folder info should be @fi and fi->child should be what we - * want to fill our tree with... *sigh* */ - if (m->top && m->fi && !strcmp (m->fi->full_name, m->top)) { - if (!(fi = m->fi->child)) - fi = m->fi->next; - } else - fi = m->fi; - - 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_path_free (path); - return; - } - } else { - gint fully_loaded = (m->flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) ? TRUE : FALSE; - - do { - gboolean known = g_hash_table_lookup (si->full_hash, fi->full_name) != NULL; - - if (!known) - em_folder_tree_model_set_folder_info (priv->model, &iter, si, fi, fully_loaded); - - if ((fi = fi->next) != NULL && !known) - gtk_tree_store_append (model, &iter, &root); - } while (fi != NULL); - } - - gtk_tree_store_set (model, &root, COL_BOOL_LOAD_SUBDIRS, FALSE, -1); - emft_queue_save_state (m->emft); -} - -static void -emft_get_folder_info__free (struct _EMFolderTreeGetFolderInfo *m) -{ - camel_store_free_folder_info (m->store, m->fi); - - gtk_tree_row_reference_free (m->root); - g_object_unref(m->emft); - camel_object_unref (m->store); - g_free (m->top); -} - -static MailMsgInfo get_folder_info_info = { - sizeof (struct _EMFolderTreeGetFolderInfo), - (MailMsgDescFunc) emft_get_folder_info__desc, - (MailMsgExecFunc) emft_get_folder_info__exec, - (MailMsgDoneFunc) emft_get_folder_info__done, - (MailMsgFreeFunc) emft_get_folder_info__free -}; - -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; - gchar *full_name; - gboolean load; - - model = gtk_tree_view_get_model (treeview); - - gtk_tree_model_get (model, root, - COL_STRING_FULL_NAME, &full_name, - COL_POINTER_CAMEL_STORE, &store, - 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; - } - - gtk_tree_store_set ((GtkTreeStore *)model, root, COL_BOOL_LOAD_SUBDIRS, FALSE, -1); - - m = mail_msg_new (&get_folder_info_info); - m->root = gtk_tree_row_reference_new (model, tree_path); - camel_object_ref (store); - m->store = store; - m->emft = emft; - g_object_ref(emft); - m->top = full_name; - m->flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE|CAMEL_STORE_FOLDER_INFO_FAST; - - mail_msg_unordered_push (m); -} - -static gboolean -emft_tree_test_collapse_row (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_path, EMFolderTree *emft) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter cursor; - - selection = gtk_tree_view_get_selection (treeview); - if (gtk_tree_selection_get_selected (selection, &model, &cursor)) { - /* select the collapsed node IFF it is a parent of the currently selected folder */ - if (gtk_tree_store_is_ancestor ((GtkTreeStore *) model, root, &cursor)) - 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; -} - -static void -emft_tree_row_activated (GtkTreeView *treeview, GtkTreePath *tree_path, GtkTreeViewColumn *column, EMFolderTree *emft) -{ - struct _EMFolderTreePrivate *priv = emft->priv; - GtkTreeModel *model = (GtkTreeModel *) priv->model; - gchar *full_name, *uri; - GtkTreeIter iter; - guint32 flags; - - if (!emft_select_func(NULL, model, tree_path, FALSE, emft)) - return; - - if (!gtk_tree_model_get_iter (model, &iter, tree_path)) - return; - - gtk_tree_model_get (model, &iter, COL_STRING_FULL_NAME, &full_name, - COL_STRING_URI, &uri, COL_UINT_FLAGS, &flags, -1); - - emft_clear_selected_list(emft); - - g_signal_emit (emft, signals[FOLDER_SELECTED], 0, full_name, uri, flags); - g_signal_emit (emft, signals[FOLDER_ACTIVATED], 0, full_name, uri); - - g_free(full_name); - 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) -{ - struct _emft_selection_data *dat = (struct _emft_selection_data *) data; - - dat->model = model; - if (!dat->set) - *(dat->iter) = *iter; - dat->set = TRUE; -} - -static gboolean -emft_selection_get_selected (GtkTreeSelection *selection, GtkTreeModel **model, GtkTreeIter *iter) -{ - struct _emft_selection_data dat = { NULL, iter, FALSE }; - - if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_MULTIPLE) { - gtk_tree_selection_selected_foreach (selection, selfunc, &dat); - if (model) - *model = dat.model; - return dat.set; - } else { - return gtk_tree_selection_get_selected (selection, model, iter); - } -} - -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) -{ - 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); - - 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; - GtkTreePath *tree_path; - - /* this centralises working out when the user's done something */ - emft_tree_user_event(treeview, (GdkEvent *)event, emft); - - if (event->button != 3 && !(event->button == 1 && event->type == GDK_2BUTTON_PRESS)) - return FALSE; - - if (!gtk_tree_view_get_path_at_pos (treeview, (gint) event->x, (gint) event->y, &tree_path, NULL, NULL, NULL)) - return FALSE; - - /* select/focus the row that was right-clicked or double-clicked */ - selection = gtk_tree_view_get_selection (treeview); - gtk_tree_selection_select_path(selection, tree_path); - gtk_tree_view_set_cursor (treeview, tree_path, NULL, FALSE); - - if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { - if (emft->priv->skip_double_click) { - return FALSE; - } - emft_tree_row_activated (treeview, tree_path, NULL, emft); - gtk_tree_path_free (tree_path); - return TRUE; - } - - gtk_tree_path_free (tree_path); - - return emft_popup (emft, (GdkEvent *)event); -} - -/* This is called for keyboard and mouse events, it seems the only way - * we know the user has done something to the selection as opposed to - * code or initialisation processes */ -static gboolean -emft_tree_user_event (GtkTreeView *treeview, GdkEvent *e, EMFolderTree *emft) -{ - if (e && e->type == GDK_KEY_PRESS && (e->key.keyval == GDK_space || e->key.keyval == '.' || e->key.keyval == ',' || e->key.keyval == '[' || e->key.keyval == ']')) { - g_signal_emit (emft, signals [HIDDEN_KEY_EVENT], 0, e); - - return TRUE; - } - if (!emft->priv->do_multiselect) - emft_clear_selected_list(emft); - - emft->priv->cursor_set = TRUE; - - return FALSE; -} - -static void -emft_tree_selection_changed (GtkTreeSelection *selection, EMFolderTree *emft) -{ - gchar *full_name, *uri; - GtkTreeModel *model; - GtkTreeIter iter; - guint32 flags; - guint unread = 0; - 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; - } - - gtk_tree_model_get ( - model, &iter, - COL_STRING_FULL_NAME, &full_name, - COL_STRING_URI, &uri, COL_UINT_FLAGS, &flags, - COL_UINT_UNREAD, &unread, COL_UINT_UNREAD_LAST_SEL, - &old_unread, -1); - - /* Sync unread counts to distinguish new incoming mail. */ - if (unread != old_unread) - gtk_tree_store_set ( - GTK_TREE_STORE (model), &iter, - COL_UINT_UNREAD_LAST_SEL, unread, -1); - - g_signal_emit (emft, signals[FOLDER_SELECTED], 0, full_name, uri, flags); - g_free(uri); - g_free(full_name); -} - 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); @@ -2363,16 +2078,18 @@ 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; GtkTreePath *current_path, *path = NULL; guint unread = 0; - struct _EMFolderTreePrivate *priv = emft->priv; + EMFolderTreePrivate *priv = emft->priv; 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); @@ -2407,16 +2124,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; } @@ -2442,16 +2159,18 @@ 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; GtkTreePath *path = NULL, *current_path = NULL; guint unread = 0; - struct _EMFolderTreePrivate *priv = emft->priv; + EMFolderTreePrivate *priv = emft->priv; 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)) { @@ -2485,17 +2204,17 @@ 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; } @@ -2503,6 +2222,7 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders) gchar * em_folder_tree_get_selected_uri (EMFolderTree *emft) { + GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; @@ -2510,9 +2230,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; } @@ -2520,6 +2244,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; @@ -2527,9 +2252,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; } @@ -2537,6 +2266,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; @@ -2549,7 +2279,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); @@ -2565,6 +2297,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; @@ -2577,7 +2310,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, @@ -2606,54 +2341,6 @@ em_folder_tree_get_selected_folder_info (EMFolderTree *emft) return fi; } -EMFolderTreeModel * -em_folder_tree_get_model (EMFolderTree *emft) -{ - g_return_val_if_fail (EM_IS_FOLDER_TREE (emft), NULL); - - 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) { |