aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-06-20 12:15:43 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-06-20 13:02:42 +0800
commit7d98f48c246dd3024f4f093ca4249c993286ee36 (patch)
treebc7cc11a1bd434852de2739bf8d17364efa3c145
parentcd29d53b07609ac39be3efa646baa59f9d1731ed (diff)
downloadgsoc2013-evolution-7d98f48c246dd3024f4f093ca4249c993286ee36.tar
gsoc2013-evolution-7d98f48c246dd3024f4f093ca4249c993286ee36.tar.gz
gsoc2013-evolution-7d98f48c246dd3024f4f093ca4249c993286ee36.tar.bz2
gsoc2013-evolution-7d98f48c246dd3024f4f093ca4249c993286ee36.tar.lz
gsoc2013-evolution-7d98f48c246dd3024f4f093ca4249c993286ee36.tar.xz
gsoc2013-evolution-7d98f48c246dd3024f4f093ca4249c993286ee36.tar.zst
gsoc2013-evolution-7d98f48c246dd3024f4f093ca4249c993286ee36.zip
EMFolderTree cleanups.
-rw-r--r--mail/em-composer-utils.c4
-rw-r--r--mail/em-folder-selection-button.c10
-rw-r--r--mail/em-folder-tree.c894
-rw-r--r--mail/em-folder-tree.h1
4 files changed, 469 insertions, 440 deletions
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index 4b1d9aedce..ebef6cf78b 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -2401,6 +2401,7 @@ post_header_clicked_cb (EComposerPostHeader *header,
EMailShellBackend *mail_shell_backend)
{
EMFolderTreeModel *model;
+ GtkTreeSelection *selection;
GtkWidget *folder_tree;
GtkWidget *dialog;
GList *list;
@@ -2408,7 +2409,8 @@ post_header_clicked_cb (EComposerPostHeader *header,
model = e_mail_shell_backend_get_folder_tree_model (mail_shell_backend);
folder_tree = em_folder_tree_new_with_model (model);
- em_folder_tree_set_multiselect (EM_FOLDER_TREE (folder_tree), TRUE);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_tree));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
em_folder_tree_set_excluded (
EM_FOLDER_TREE (folder_tree),
diff --git a/mail/em-folder-selection-button.c b/mail/em-folder-selection-button.c
index 933393ae80..cff76adcee 100644
--- a/mail/em-folder-selection-button.c
+++ b/mail/em-folder-selection-button.c
@@ -251,12 +251,20 @@ folder_selection_button_clicked (GtkButton *button)
EMFolderSelectionButtonPrivate *priv;
EMFolderTree *emft;
GtkWidget *dialog;
+ GtkTreeSelection *selection;
+ GtkSelectionMode mode;
priv = EM_FOLDER_SELECTION_BUTTON_GET_PRIVATE (button);
emft = (EMFolderTree *) em_folder_tree_new_with_model (priv->model);
- em_folder_tree_set_multiselect (emft, priv->multiple_select);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (emft));
+ if (priv->multiple_select)
+ mode = GTK_SELECTION_MULTIPLE;
+ else
+ mode = GTK_SELECTION_SINGLE;
+ gtk_tree_selection_set_mode (selection, mode);
+
em_folder_tree_set_excluded (
emft, EMFT_EXCLUDE_NOSELECT |
EMFT_EXCLUDE_VIRTUAL | EMFT_EXCLUDE_VTRASH);
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index b8ee5e354a..d5291e0c01 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -98,7 +98,6 @@ 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
@@ -157,14 +156,6 @@ static guint signals[LAST_SIGNAL] = { 0 };
extern CamelSession *session;
extern CamelStore *vfolder_store;
-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);
-
struct _emft_selection_data {
GtkTreeModel *model;
GtkTreeIter *iter;
@@ -173,6 +164,150 @@ struct _emft_selection_data {
static gpointer parent_class = NULL;
+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)
+{
+ EMFolderTreePrivate *priv = m->emft->priv;
+ 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 */
+ 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;
+
+ 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;
+ }
+
+ 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);
+
+ /* 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 (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 ((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 */
+ gtk_tree_store_remove (model, &iter);
+
+ if (is_store) {
+ path = gtk_tree_model_get_path ((GtkTreeModel *) model, &root);
+ gtk_tree_view_collapse_row (tree_view, path);
+ 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);
+}
+
+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
folder_tree_emit_popup_event (EMFolderTree *emft,
GdkEvent *event)
@@ -191,6 +326,103 @@ emft_free_select_uri (struct _selected_uri *u)
g_free (u);
}
+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;
+
+ 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)
{
@@ -242,12 +474,193 @@ em_folder_tree_destroy (GtkObject *object)
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 (event->keyval == GDK_space)
+ return TRUE;
+
+ 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));
@@ -259,8 +672,15 @@ folder_tree_class_init (EMFolderTreeClass *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;
+ 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),
@@ -298,12 +718,19 @@ folder_tree_class_init (EMFolderTreeClass *class)
static void
folder_tree_init (EMFolderTree *emft)
{
+ GtkTreeSelection *selection;
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;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (emft));
+
+ g_signal_connect_swapped (
+ selection, "changed",
+ G_CALLBACK (emft_selection_changed_cb), emft);
}
GType
@@ -450,31 +877,6 @@ render_icon (GtkTreeViewColumn *column,
g_object_unref (icon);
}
-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 GtkTreeView *
folder_tree_new (EMFolderTree *emft, EMFolderTreeModel *model)
{
@@ -513,7 +915,9 @@ 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);
@@ -570,29 +974,19 @@ folder_tree_copy_state (EMFolderTree *emft,
static void
em_folder_tree_construct (EMFolderTree *emft, EMFolderTreeModel *model)
{
- struct _EMFolderTreePrivate *priv = emft->priv;
- GtkTreeSelection *selection;
+ EMFolderTreePrivate *priv = emft->priv;
priv->model = model;
folder_tree_new (emft, model);
folder_tree_copy_state (emft, model);
gtk_widget_show (GTK_WIDGET (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 */
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;
@@ -612,7 +1006,7 @@ emft_select_uri(EMFolderTree *emft, GtkTreePath *path, struct _selected_uri *u)
static void
emft_expand_node (EMFolderTreeModel *model, const gchar *key, EMFolderTree *emft)
{
- struct _EMFolderTreePrivate *priv = emft->priv;
+ EMFolderTreePrivate *priv = emft->priv;
struct _EMFolderTreeModelStoreInfo *si;
EMailShellBackend *mail_shell_backend;
GtkTreeRowReference *row;
@@ -687,7 +1081,7 @@ 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;
@@ -752,7 +1146,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;
@@ -772,7 +1166,7 @@ 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;
GtkTreePath *src_path;
gboolean is_store;
@@ -806,7 +1200,7 @@ 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;
GtkTreePath *src_path;
CamelFolder *folder;
@@ -1023,7 +1417,7 @@ emft_drop_popup_free(EPopup *ep, GSList *items, gpointer data)
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;
+ EMFolderTreePrivate *priv = emft->priv;
GtkTreeViewDropPosition pos;
GtkTreeView *tree_view;
GtkTreePath *dest_path;
@@ -1111,7 +1505,7 @@ 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;
EMailShellBackend *mail_shell_backend;
@@ -1309,7 +1703,7 @@ 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;
@@ -1345,7 +1739,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);
@@ -1358,7 +1752,7 @@ 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);
@@ -1421,7 +1815,7 @@ tree_autoscroll (EMFolderTree *emft)
static gboolean
tree_autoexpand (EMFolderTree *emft)
{
- struct _EMFolderTreePrivate *priv = emft->priv;
+ EMFolderTreePrivate *priv = emft->priv;
GtkTreeView *tree_view;
GtkTreePath *path;
@@ -1436,7 +1830,7 @@ 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;
+ EMFolderTreePrivate *priv = emft->priv;
GtkTreeModel *model = (GtkTreeModel *) priv->model;
GtkTreeViewDropPosition pos;
GtkTreeView *tree_view;
@@ -1514,7 +1908,7 @@ 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;
@@ -1548,22 +1942,6 @@ em_folder_tree_enable_drag_and_drop (EMFolderTree *emft)
}
void
-em_folder_tree_set_multiselect (EMFolderTree *tree,
- gboolean mode)
-{
- GtkTreeSelection *sel;
- GtkTreeView *tree_view;
-
- g_return_if_fail (EM_IS_FOLDER_TREE (tree));
-
- tree_view = GTK_TREE_VIEW (tree);
- sel = gtk_tree_view_get_selection (tree_view);
-
- 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)
{
g_return_if_fail (EM_IS_FOLDER_TREE (emft));
@@ -1642,23 +2020,10 @@ em_folder_tree_get_selected_paths (EMFolderTree *emft)
return list;
}
-static void
-emft_clear_selected_list(EMFolderTree *emft)
-{
- struct _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;
-}
-
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? */
@@ -1744,351 +2109,6 @@ 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;
- GtkTreeView *tree_view;
- GtkTreeStore *model;
- 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;
-
- 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;
- }
-
- 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);
-
- /* 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 (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 ((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 */
- gtk_tree_store_remove (model, &iter);
-
- if (is_store) {
- path = gtk_tree_model_get_path ((GtkTreeModel *) model, &root);
- gtk_tree_view_collapse_row (tree_view, path);
- 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);
-}
-
-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_tree_row_expanded (GtkTreeView *treeview, GtkTreeIter *root, GtkTreePath *tree_path, EMFolderTree *emft)
-{
- 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);
-
- if (!load) {
- 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);
- }
-
- 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);
-}
-
-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 gboolean
-emft_popup_menu (GtkWidget *widget)
-{
- folder_tree_emit_popup_event (EM_FOLDER_TREE (widget), NULL);
-
- return TRUE;
-}
-
-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);
-
- folder_tree_emit_popup_event (emft, (GdkEvent *) event);
-
- return TRUE;
-}
-
-/* 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) {
- 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)) {
- g_signal_emit (emft, signals[FOLDER_SELECTED], 0, NULL, NULL, 0);
- 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,
@@ -2115,7 +2135,7 @@ em_folder_tree_select_next_path (EMFolderTree *emft, gboolean skip_read_folders)
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));
@@ -2196,7 +2216,7 @@ em_folder_tree_select_prev_path (EMFolderTree *emft, gboolean skip_read_folders)
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));
diff --git a/mail/em-folder-tree.h b/mail/em-folder-tree.h
index 132c9a0b5c..41e02a58aa 100644
--- a/mail/em-folder-tree.h
+++ b/mail/em-folder-tree.h
@@ -87,7 +87,6 @@ GtkWidget *em_folder_tree_new_with_model (EMFolderTreeModel *model);
void em_folder_tree_enable_drag_and_drop (EMFolderTree *emft);
-void em_folder_tree_set_multiselect (EMFolderTree *emft, gboolean mode);
void em_folder_tree_set_excluded(EMFolderTree *emft, guint32 flags);
void em_folder_tree_set_excluded_func(EMFolderTree *emft, EMFTExcludeFunc exclude, gpointer data);