aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog22
-rw-r--r--mail/em-folder-view.c30
-rw-r--r--mail/em-folder-view.h4
-rw-r--r--mail/message-list.c211
-rw-r--r--mail/message-list.h10
5 files changed, 178 insertions, 99 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index ba743cb80c..42eba10a99 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,25 @@
+2004-07-27 Not Zed <NotZed@Ximian.com>
+
+ ** See #57972.
+
+ * message-list.c (search_func): removed.
+ (ml_search_path): new function to just search, not actually change
+ the cursor like e_tree_find does.
+ (message_list_can_select): new function, returns true if the
+ selection specified is possible without changing the selection.
+ (message_list_select): rewritten.
+ (select_path): helper to select a path in a way that 'works
+ reliably'.
+ (message_list_select_next_thread): rewritten to use the
+ table-adapter, so it properly handles arbitrary sorting.
+
+ * em-folder-view.c (em_folder_view_get_popup_target): setup
+ next/prev flags as appropriate.
+ (emfv_enable_map[]): setup next/prev flags.
+
+ * em-folder-view.h: added last and first message status bits to
+ folder view select mask.
+
2004-07-23 Radek Doulik <rodo@ximian.com>
* added len parameter to em_utils_part_to_html and
diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c
index 51d5eee890..85c6cd9f92 100644
--- a/mail/em-folder-view.c
+++ b/mail/em-folder-view.c
@@ -724,7 +724,7 @@ emfv_popup_mark_junk (GtkWidget *w, EMFolderView *emfv)
CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN,
CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN);
if (uids->len == 1)
- message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0, FALSE);
+ message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0);
message_list_free_uids(emfv->list, uids);
}
@@ -739,7 +739,7 @@ emfv_popup_mark_nojunk (GtkWidget *w, EMFolderView *emfv)
CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN,
CAMEL_MESSAGE_JUNK_LEARN);
if (uids->len == 1)
- message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0, FALSE);
+ message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0);
message_list_free_uids(emfv->list, uids);
}
@@ -753,8 +753,8 @@ emfv_popup_delete(GtkWidget *w, EMFolderView *emfv)
em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED);
if (uids->len == 1) {
- if (!message_list_select (emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0, FALSE) && emfv->hide_deleted)
- message_list_select (emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0, FALSE);
+ if (!message_list_select (emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0) && emfv->hide_deleted)
+ message_list_select (emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0);
}
em_utils_uids_free(uids);
}
@@ -1110,7 +1110,7 @@ emfv_mail_next(BonoboUIComponent *uid, void *data, const char *path)
{
EMFolderView *emfv = data;
- message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0, FALSE);
+ message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0);
}
static void
@@ -1118,7 +1118,7 @@ emfv_mail_next_flagged(BonoboUIComponent *uid, void *data, const char *path)
{
EMFolderView *emfv = data;
- message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, CAMEL_MESSAGE_FLAGGED, CAMEL_MESSAGE_FLAGGED, TRUE);
+ message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT|MESSAGE_LIST_SELECT_WRAP, CAMEL_MESSAGE_FLAGGED, CAMEL_MESSAGE_FLAGGED);
}
static void
@@ -1126,7 +1126,7 @@ emfv_mail_next_unread(BonoboUIComponent *uid, void *data, const char *path)
{
EMFolderView *emfv = data;
- message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, CAMEL_MESSAGE_SEEN, TRUE);
+ message_list_select(emfv->list, MESSAGE_LIST_SELECT_NEXT|MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN);
}
static void
@@ -1142,7 +1142,7 @@ emfv_mail_previous(BonoboUIComponent *uid, void *data, const char *path)
{
EMFolderView *emfv = data;
- message_list_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0, FALSE);
+ message_list_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0);
}
static void
@@ -1150,7 +1150,7 @@ emfv_mail_previous_flagged(BonoboUIComponent *uid, void *data, const char *path)
{
EMFolderView *emfv = data;
- message_list_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, CAMEL_MESSAGE_FLAGGED, CAMEL_MESSAGE_FLAGGED, TRUE);
+ message_list_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS|MESSAGE_LIST_SELECT_WRAP, CAMEL_MESSAGE_FLAGGED, CAMEL_MESSAGE_FLAGGED);
}
static void
@@ -1158,7 +1158,7 @@ emfv_mail_previous_unread(BonoboUIComponent *uid, void *data, const char *path)
{
EMFolderView *emfv = data;
- message_list_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, CAMEL_MESSAGE_SEEN, TRUE);
+ message_list_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS|MESSAGE_LIST_SELECT_WRAP, 0, CAMEL_MESSAGE_SEEN);
}
static void
@@ -1549,11 +1549,11 @@ static const EMFolderViewEnable emfv_enable_map[] = {
{ "EditPaste", EM_POPUP_SELECT_FOLDER },
/* FIXME: should these be single-selection? */
- { "MailNext", EM_POPUP_SELECT_MANY },
+ { "MailNext", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_NEXT_MSG },
{ "MailNextFlagged", EM_POPUP_SELECT_MANY },
{ "MailNextUnread", EM_POPUP_SELECT_MANY },
{ "MailNextThread", EM_POPUP_SELECT_MANY },
- { "MailPrevious", EM_POPUP_SELECT_MANY },
+ { "MailPrevious", EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_PREV_MSG },
{ "MailPreviousFlagged", EM_POPUP_SELECT_MANY },
{ "MailPreviousUnread", EM_POPUP_SELECT_MANY },
@@ -1870,6 +1870,12 @@ em_folder_view_get_popup_target(EMFolderView *emfv)
if (message_list_hidden(emfv->list) != 0)
t->mask &= ~EM_FOLDER_VIEW_SELECT_HIDDEN;
+ if (message_list_can_select(emfv->list, MESSAGE_LIST_SELECT_NEXT, 0, 0))
+ t->mask &= ~EM_FOLDER_VIEW_SELECT_NEXT_MSG;
+
+ if (message_list_can_select(emfv->list, MESSAGE_LIST_SELECT_PREVIOUS, 0, 0))
+ t->mask &= ~EM_FOLDER_VIEW_SELECT_PREV_MSG;
+
/* See bug #54770 */
if (!emfv->hide_deleted)
t->mask &= ~EM_POPUP_SELECT_DELETE;
diff --git a/mail/em-folder-view.h b/mail/em-folder-view.h
index 279e9ab0ea..3cf9586bb4 100644
--- a/mail/em-folder-view.h
+++ b/mail/em-folder-view.h
@@ -47,7 +47,9 @@ typedef struct _EMFolderViewEnable EMFolderViewEnable;
enum {
EM_FOLDER_VIEW_SELECT_THREADED = EM_POPUP_SELECT_LAST,
EM_FOLDER_VIEW_SELECT_HIDDEN = EM_POPUP_SELECT_LAST<<1,
- EM_FOLDER_VIEW_SELECT_LAST = EM_POPUP_SELECT_LAST<<2,
+ EM_FOLDER_VIEW_SELECT_NEXT_MSG = EM_POPUP_SELECT_LAST<<2,
+ EM_FOLDER_VIEW_SELECT_PREV_MSG = EM_POPUP_SELECT_LAST<<3,
+ EM_FOLDER_VIEW_SELECT_LAST = EM_POPUP_SELECT_LAST<<4,
};
struct _EMFolderViewEnable {
diff --git a/mail/message-list.c b/mail/message-list.c
index 57047a857e..ab48b5e816 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -461,32 +461,6 @@ get_normalised_string (MessageList *message_list, CamelMessageInfo *info, int co
return e_poolv_get (poolv, index);
}
-struct search_func_data {
- MessageList *message_list;
- guint32 flags;
- guint32 mask;
- ETreePath path;
-};
-
-static gboolean
-search_func (ETreeModel *model, ETreePath path, struct search_func_data *data)
-{
- CamelMessageInfo *info;
-
- if (e_tree_model_node_is_root (data->message_list->model, path))
- return FALSE;
-
- info = get_message_info (data->message_list, path);
-
- if (info && (info->flags & data->mask) == data->flags) {
- g_free(data->message_list->cursor_uid);
- data->message_list->cursor_uid = NULL;
- data->path = path;
- return TRUE;
- }
- return FALSE;
-}
-
static void
clear_selection(MessageList *ml, struct _MLSelection *selection)
{
@@ -502,6 +476,88 @@ clear_selection(MessageList *ml, struct _MLSelection *selection)
selection->folder_uri = NULL;
}
+static ETreePath
+ml_search_forward(MessageList *ml, int start, int end, guint32 flags, guint32 mask)
+{
+ ETreePath path;
+ int row;
+ CamelMessageInfo *info;
+ ETreeTableAdapter *etta = e_tree_get_table_adapter(ml->tree);
+
+ for (row = start; row <= end; row ++) {
+ path = e_tree_table_adapter_node_at_row(etta, row);
+ if (path
+ && (info = get_message_info(ml, path))
+ && (info->flags & mask) == flags)
+ return path;
+ }
+
+ return NULL;
+}
+
+static ETreePath
+ml_search_backward(MessageList *ml, int start, int end, guint32 flags, guint32 mask)
+{
+ ETreePath path;
+ int row;
+ CamelMessageInfo *info;
+ ETreeTableAdapter *etta = e_tree_get_table_adapter(ml->tree);
+
+ for (row = start; row >= end; row --) {
+ path = e_tree_table_adapter_node_at_row(etta, row);
+ if (path
+ && (info = get_message_info(ml, path))
+ && (info->flags & mask) == flags)
+ return path;
+ }
+
+ return NULL;
+}
+
+static ETreePath
+ml_search_path(MessageList *ml, MessageListSelectDirection direction, guint32 flags, guint32 mask)
+{
+ ETreePath node;
+ int row, count;
+ ETreeTableAdapter *etta = e_tree_get_table_adapter(ml->tree);
+
+ if (ml->cursor_uid == NULL
+ || (node = g_hash_table_lookup(ml->uid_nodemap, ml->cursor_uid)) == NULL)
+ return NULL;
+
+ row = e_tree_table_adapter_row_of_node(etta, node);
+ if (row == -1)
+ return NULL;
+ count = e_table_model_row_count((ETableModel *)etta);
+
+ if ((direction & MESSAGE_LIST_SELECT_DIRECTION) == MESSAGE_LIST_SELECT_NEXT)
+ node = ml_search_forward(ml, row + 1, count - 1, flags, mask);
+ else
+ node = ml_search_backward(ml, row-1, 0, flags, mask);
+
+ if (node == NULL && (direction & MESSAGE_LIST_SELECT_WRAP)) {
+ if ((direction & MESSAGE_LIST_SELECT_DIRECTION) == MESSAGE_LIST_SELECT_NEXT)
+ node = ml_search_forward(ml, 0, row, flags, mask);
+ else
+ node = ml_search_backward(ml, count-1, row, flags, mask);
+ }
+
+ return node;
+}
+
+static void
+select_path(MessageList *ml, ETreePath path)
+{
+ ETreeSelectionModel *etsm = (ETreeSelectionModel *)e_tree_get_selection_model(ml->tree);
+
+ g_free(ml->cursor_uid);
+ ml->cursor_uid = NULL;
+
+ e_tree_table_adapter_show_node(e_tree_get_table_adapter(ml->tree), path);
+ e_tree_set_cursor(ml->tree, path);
+ e_tree_selection_model_select_single_path(etsm, path);
+}
+
/**
* message_list_select:
* @message_list: a MessageList
@@ -509,8 +565,6 @@ clear_selection(MessageList *ml, struct _MLSelection *selection)
* @direction: the direction to search in
* @flags: a set of flag values
* @mask: a mask for comparing against @flags
- * @wraparound: if %TRUE, go back to the beginning for
- * the next match if necessary.
*
* This moves the message list selection to a suitable row. @base_row
* lists the first (model) row to try, but as a special case, model
@@ -518,43 +572,43 @@ clear_selection(MessageList *ml, struct _MLSelection *selection)
* what constitutes a suitable row. @direction is
* %MESSAGE_LIST_SELECT_NEXT if it should find the next matching
* message, or %MESSAGE_LIST_SELECT_PREVIOUS if it should find the
- * previous. If no suitable row is found, the selection will be
+ * previous. %MESSAGE_LIST_SELECT_WRAP is an option bit which specifies the
+ * search should wrap.
+ *
+ * If no suitable row is found, the selection will be
* unchanged.
*
* Returns %TRUE if a new message has been selected or %FALSE otherwise.
**/
gboolean
-message_list_select (MessageList *message_list,
- MessageListSelectDirection direction,
- guint32 flags,
- guint32 mask,
- gboolean wraparound)
-{
- struct search_func_data data;
- ETreeFindNextParams params = 0;
-
- data.message_list = message_list;
- data.flags = flags;
- data.mask = mask;
- data.path = NULL;
-
- if (direction == MESSAGE_LIST_SELECT_NEXT)
- params |= E_TREE_FIND_NEXT_FORWARD;
- else
- params |= E_TREE_FIND_NEXT_BACKWARD;
-
- if (wraparound)
- params |= E_TREE_FIND_NEXT_WRAP;
-
- if (e_tree_find_next (message_list->tree, params, (ETreePathFunc) search_func, &data)) {
- ETreeSelectionModel *etsm = (ETreeSelectionModel *)e_tree_get_selection_model (message_list->tree);
+message_list_select(MessageList *ml, MessageListSelectDirection direction, guint32 flags, guint32 mask)
+{
+ ETreePath path;
- e_tree_selection_model_select_single_path(etsm, data.path);
+ path = ml_search_path(ml, direction, flags, mask);
+ if (path) {
+ select_path(ml, path);
return TRUE;
} else
return FALSE;
}
+/**
+ * message_list_can_select:
+ * @ml:
+ * @direction:
+ * @flags:
+ * @mask:
+ *
+ * Returns true if the selection specified is possible with the current view.
+ *
+ * Return value:
+ **/
+gboolean
+message_list_can_select(MessageList *ml, MessageListSelectDirection direction, guint32 flags, guint32 mask)
+{
+ return ml_search_path(ml, direction, flags, mask) != NULL;
+}
/**
* message_list_select_uid:
@@ -591,40 +645,33 @@ message_list_select_uid (MessageList *message_list, const char *uid)
}
}
-
void
-message_list_select_next_thread (MessageList *message_list)
+message_list_select_next_thread (MessageList *ml)
{
- ETreePath node, last;
-
- if (!message_list->cursor_uid)
+ ETreePath node;
+ ETreeTableAdapter *etta = e_tree_get_table_adapter(ml->tree);
+ int i, count, row;
+
+ if (!ml->cursor_uid
+ || (node = g_hash_table_lookup(ml->uid_nodemap, ml->cursor_uid)) == NULL)
return;
-
- /* get the thread parent node */
- last = node = g_hash_table_lookup (message_list->uid_nodemap, message_list->cursor_uid);
- while (!e_tree_model_node_is_root (message_list->model, node)) {
- last = node;
- node = e_tree_model_node_get_parent (message_list->model, node);
- }
-
- /* get the next toplevel node */
- node = e_tree_model_node_get_next (message_list->model, last);
-
- if (node) {
- CamelMessageInfo *info;
-
- info = get_message_info (message_list, node);
- e_tree_set_cursor (message_list->tree, node);
-
- g_free (message_list->cursor_uid);
- message_list->cursor_uid = g_strdup (camel_message_info_uid (info));
-
- g_signal_emit (GTK_OBJECT (message_list), message_list_signals[MESSAGE_SELECTED], 0,
- camel_message_info_uid (info));
+
+ row = e_tree_table_adapter_row_of_node(etta, node);
+ if (row == -1)
+ return;
+ count = e_table_model_row_count((ETableModel *)etta);
+
+ /* find the next node which has a root parent (i.e. toplevel node) */
+ for (i=row+1;i<count-1;i++) {
+ node = e_tree_table_adapter_node_at_row(etta, i);
+ if (node
+ && e_tree_model_node_is_root(ml->model, e_tree_model_node_get_parent(ml->model, node))) {
+ select_path(ml, node);
+ return;
+ }
}
}
-
/**
* message_list_select_all:
* @message_list: Message List widget
diff --git a/mail/message-list.h b/mail/message-list.h
index c8ec571ec5..1c09c2ce9f 100644
--- a/mail/message-list.h
+++ b/mail/message-list.h
@@ -165,8 +165,10 @@ typedef void (*MessageListForeachFunc) (MessageList *message_list,
gpointer user_data);
typedef enum {
- MESSAGE_LIST_SELECT_NEXT = 1,
- MESSAGE_LIST_SELECT_PREVIOUS = -1
+ MESSAGE_LIST_SELECT_NEXT = 0,
+ MESSAGE_LIST_SELECT_PREVIOUS = 1,
+ MESSAGE_LIST_SELECT_DIRECTION = 1, /* direction mask */
+ MESSAGE_LIST_SELECT_WRAP = 1<<1, /* option bit */
} MessageListSelectDirection;
GtkType message_list_get_type (void);
@@ -188,8 +190,8 @@ void message_list_free_uids(MessageList *ml, GPtrArray *uids);
gboolean message_list_select (MessageList *message_list,
MessageListSelectDirection direction,
guint32 flags,
- guint32 mask,
- gboolean wraparound);
+ guint32 mask);
+gboolean message_list_can_select(MessageList *ml, MessageListSelectDirection direction, guint32 flags, guint32 mask);
void message_list_select_uid (MessageList *message_list,
const char *uid);