aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog16
-rw-r--r--mail/message-list.c165
-rw-r--r--mail/message-list.h7
-rw-r--r--mail/message-thread.c2
4 files changed, 168 insertions, 22 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 8169830a2b..0df4e1ac6f 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,5 +1,21 @@
2000-07-06 Not Zed <NotZed@HelixCode.com>
+ * message-list.c (message_list_init_header): Setup the subject
+ renderer to a tree in tree mode.
+ (on_cursor_change_cmd): For a tree model, map the view row to the
+ data row.
+ (build_tree): Builds the tree data structure of all messages.
+ (message_list_set_search): For a tree model, build the tree here.
+ (ml_tree_icon_at): Icon callback, returns nothing.
+ (ml_tree_value_at):
+ (ml_tree_set_value_at):
+ (ml_tree_is_cell_editable): Maps tree node to data row, and calls
+ the equivalent table callback
+ (message_list_init_renderers): Setup the tree renderer if needed.
+
+ * message-list.h: Add a tree renderer to render list, and
+ tree_view indicator.
+
* message-thread.[ch]: Code for message threading.
2000-07-05 Dan Winship <danw@helixcode.com>
diff --git a/mail/message-list.c b/mail/message-list.c
index 9b34ba7ddc..799b2aeab5 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -16,6 +16,7 @@
#include "camel/camel-exception.h"
#include <camel/camel-folder.h>
#include "message-list.h"
+#include "message-thread.h"
#include "Mail.h"
#include "widgets/e-table/e-table-header-item.h"
#include "widgets/e-table/e-table-item.h"
@@ -25,6 +26,8 @@
#include "art/mail-replied.xpm"
#include "art/attachment.xpm"
#include "art/empty.xpm"
+#include "art/tree-expanded.xpm"
+#include "art/tree-unexpanded.xpm"
/*
* Default sizes for the ETable display
@@ -58,6 +61,19 @@ static void on_row_selection (ETable *table, int row, gboolean selected,
static void select_row (ETable *table, gpointer user_data);
static char *filter_date (const void *data);
+static struct {
+ char **image_base;
+ GdkPixbuf *pixbuf;
+} states_pixmaps [] = {
+ { mail_new_xpm, NULL },
+ { mail_read_xpm, NULL },
+ { mail_replied_xpm, NULL },
+ { empty_xpm, NULL },
+ { attachment_xpm, NULL },
+ { tree_expanded_xpm, NULL },
+ { tree_unexpanded_xpm, NULL },
+ { NULL, NULL }
+};
static CamelMessageInfo *
get_message_info(MessageList *message_list, gint row)
@@ -512,17 +528,40 @@ ml_value_to_string (ETableModel *etm, int col, const void *value, void *data)
}
}
-static struct {
- char **image_base;
- GdkPixbuf *pixbuf;
-} states_pixmaps [] = {
- { mail_new_xpm, NULL },
- { mail_read_xpm, NULL },
- { mail_replied_xpm, NULL },
- { empty_xpm, NULL },
- { attachment_xpm, NULL },
- { NULL, NULL }
-};
+/* the tree versions of same ... we just map the tree nodes to the rows
+ of data we have */
+
+static GdkPixbuf *
+ml_tree_icon_at (ETreeModel *etm, ETreePath *path, void *model_data)
+{
+ /* we dont really need an icon ... */
+ return NULL;
+}
+
+static void *
+ml_tree_value_at (ETreeModel *etm, ETreePath *path, int col, void *model_data)
+{
+ /* we just map the node to a row id, and reuse the other value_at */
+ int row = (int)e_tree_model_node_get_data (etm, path);
+
+ return ml_value_at((ETableModel *)etm, col, row, model_data);
+}
+
+static void
+ml_tree_set_value_at (ETreeModel *etm, ETreePath *path, int col, const void *val, void *model_data)
+{
+ int row = (int)e_tree_model_node_get_data (etm, path);
+
+ ml_set_value_at((ETableModel *)etm, col, row, val, model_data);
+}
+
+static gboolean
+ml_tree_is_cell_editable (ETreeModel *etm, ETreePath *path, int col, void *model_data)
+{
+ int row = (int)e_tree_model_node_get_data (etm, path);
+
+ return ml_is_cell_editable((ETableModel *)etm, col, row, model_data);
+}
static void
message_list_init_images (void)
@@ -619,6 +658,16 @@ message_list_init_renderers (MessageList *message_list)
* FIXME: We need a real renderer here
*/
message_list->render_priority = e_cell_checkbox_new ();
+
+ /*
+ * for tree view
+ */
+ if (message_list->is_tree_view) {
+ message_list->render_tree =
+ e_cell_tree_new(message_list->table_model,
+ states_pixmaps[5].pixbuf, states_pixmaps[6].pixbuf,
+ TRUE, message_list->render_text);
+ }
}
static void
@@ -675,7 +724,7 @@ message_list_init_header (MessageList *message_list)
e_table_col_new (
COL_SUBJECT, _("Subject"),
COL_SUBJECT_EXPANSION, COL_SUBJECT_WIDTH_MIN,
- message_list->render_text,
+ message_list->is_tree_view?message_list->render_tree:message_list->render_text,
g_str_compare, TRUE);
message_list->table_cols [COL_SENT] =
@@ -728,14 +777,27 @@ message_list_init (GtkObject *object)
{
MessageList *message_list = MESSAGE_LIST (object);
char *spec;
-
- message_list->table_model = e_table_simple_new (
- ml_col_count, ml_row_count, ml_value_at,
- ml_set_value_at, ml_is_cell_editable,
- ml_duplicate_value, ml_free_value,
- ml_initialize_value, ml_value_is_empty,
- ml_value_to_string,
- message_list);
+
+ message_list->is_tree_view = TRUE;
+
+ if (message_list->is_tree_view) {
+ message_list->table_model = (ETableModel *)
+ e_tree_simple_new(ml_tree_icon_at,
+ ml_tree_value_at,
+ ml_tree_set_value_at,
+ ml_tree_is_cell_editable,
+ message_list);
+ /* setting this seems to upset the display, not sure. It should be set though */
+ /*e_tree_model_root_node_set_visible((ETableModel *)message_list->table_model, FALSE); */
+ } else {
+ message_list->table_model = e_table_simple_new (
+ ml_col_count, ml_row_count, ml_value_at,
+ ml_set_value_at, ml_is_cell_editable,
+ ml_duplicate_value, ml_free_value,
+ ml_initialize_value, ml_value_is_empty,
+ ml_value_to_string,
+ message_list);
+ }
message_list_init_renderers (message_list);
message_list_init_header (message_list);
@@ -799,6 +861,9 @@ message_list_destroy (GtkObject *object)
gtk_object_unref (GTK_OBJECT (message_list->render_message_status));
gtk_object_unref (GTK_OBJECT (message_list->render_priority));
gtk_object_unref (GTK_OBJECT (message_list->render_attachment));
+ if (message_list->is_tree_view) {
+ gtk_object_unref (GTK_OBJECT (message_list->render_tree));
+ }
gtk_object_unref (GTK_OBJECT (message_list->etable));
@@ -929,6 +994,40 @@ message_list_new (FolderBrowser *parent_folder_browser)
return BONOBO_OBJECT (message_list);
}
+/* only call if we have a tree model */
+/* builds the tree structure */
+static void
+build_tree(MessageList *ml, ETreePath *parent, struct _container *c)
+{
+ ETreePath *node;
+
+ while (c) {
+ int index=-1;
+
+ node = e_tree_model_node_insert((ETreeModel *)ml->table_model, parent, 0, ml);
+ if (c->message) {
+ /* FIXME: this ugly SLOW stuff maps a message to a message index in
+ the message index array
+ probably add the array index into the container ... */
+ int i;
+
+ for (i=0;i<ml->summary_table->len;i++) {
+ if (c->message == ml->summary_table->pdata[i]) {
+ index = i;
+ break;
+ }
+ }
+ }
+ e_tree_model_node_set_data ((ETreeModel *)ml->table_model, node, (void *)index);
+ if (c->child) {
+ /* by default, open all tree's */
+ e_tree_model_node_set_expanded((ETreeModel *)ml->table_model, node, TRUE);
+ build_tree(ml, node, c->child);
+ }
+ c = c->next;
+ }
+}
+
void
message_list_set_search (MessageList *message_list, const char *search)
{
@@ -954,6 +1053,20 @@ message_list_set_search (MessageList *message_list, const char *search)
memset(message_list->summary_search_cache->pdata, 0, sizeof(message_list->summary_search_cache->pdata[0]) * message_list->match_count);
}
+ /* ok, if its a tree, build the tree here */
+ /* FIXME: first free the old tree? */
+ /* FIXME: what about searches? */
+ if (message_list->is_tree_view) {
+ struct _container *head;
+
+ head = thread_messages((CamelMessageInfo **)message_list->summary_table->pdata, message_list->summary_table->len);
+ message_list->tree_root = e_tree_model_node_insert((ETreeModel *)message_list->table_model, NULL, 0, message_list);
+ e_tree_model_node_set_expanded((ETreeModel *)message_list->table_model, message_list->tree_root, TRUE);
+ build_tree(message_list, message_list->tree_root, head);
+ /* no longer need the thread structure */
+ thread_messages_free(head);
+ }
+
e_table_model_changed (message_list->table_model);
message_list->rows_selected = 0;
select_msg (message_list, 0);
@@ -1046,13 +1159,21 @@ on_cursor_change_cmd (ETable *table,
message_list = MESSAGE_LIST (user_data);
+ /* must map the tree view row to the real message index first */
+ if (message_list->is_tree_view) {
+ ETreePath *node;
+
+ node = e_tree_model_node_at_row ((ETreeModel *)message_list->table_model, row);
+ row = (int)e_tree_model_node_get_data ((ETreeModel *)message_list->table_model, node);
+ }
+
info = get_message_info (message_list, row);
if (!info)
return;
-
+
message_list->cursor_row = row;
message_list->cursor_uid = info->uid;
-
+
if (!message_list->idle_id)
message_list->idle_id = g_idle_add_full (G_PRIORITY_LOW, on_cursor_change_idle, message_list, NULL);
}
diff --git a/mail/message-list.h b/mail/message-list.h
index 8e43888663..0e21e69998 100644
--- a/mail/message-list.h
+++ b/mail/message-list.h
@@ -8,9 +8,11 @@
#include "camel/camel-folder.h"
#include "e-table/e-table.h"
#include "e-table/e-table-simple.h"
+#include "e-table/e-tree-simple.h"
#include "e-table/e-cell-text.h"
#include "e-table/e-cell-toggle.h"
#include "e-table/e-cell-checkbox.h"
+#include "e-table/e-cell-tree.h"
#include "folder-browser.h"
@@ -59,6 +61,9 @@ struct _MessageList {
ECell *render_message_status;
ECell *render_priority;
ECell *render_attachment;
+ ECell *render_tree;
+
+ ETreePath *tree_root; /* for tree view */
GtkWidget *etable;
@@ -78,6 +83,8 @@ struct _MessageList {
/* row-selection and seen-marking timers */
guint idle_id, seen_id;
+
+ gboolean is_tree_view; /* if we're doing tree view */
};
typedef struct {
diff --git a/mail/message-thread.c b/mail/message-thread.c
index 153cc75015..008982e8db 100644
--- a/mail/message-thread.c
+++ b/mail/message-thread.c
@@ -405,9 +405,11 @@ thread_messages(CamelMessageInfo **messages, int count)
/* find any siblings which missed out */
group_root_set(&head);
+#if 0
printf("finished\n");
i = dump_tree(head, 0);
printf("%d count, %d msgs initially, %d items in tree\n", count, msgs, i);
+#endif
return head;
}