static void on_selection_changed (GtkTreeSelection *sel, gpointer user_data);
+#define MODEST_HEADER_VIEW_PTR "modest-header-view"
+
enum {
MESSAGE_SELECTED_SIGNAL,
ITEM_NOT_FOUND_SIGNAL,
typedef struct _ModestHeaderViewPrivate ModestHeaderViewPrivate;
struct _ModestHeaderViewPrivate {
- TnyFolder *tny_folder;
+ TnyFolder *folder;
TnyList *headers;
GMutex *lock;
ModestHeaderViewStyle style;
-
- gulong sig1;
+ gulong sig1;
};
#define MODEST_HEADER_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
MODEST_TYPE_HEADER_VIEW, \
ModestHeaderViewPrivate))
+
+typedef struct _GetMsgAsyncHelper {
+ ModestHeaderView *self;
+ TnyHeader *header;
+} GetMsgAsyncHelper;
+
/* globals */
static GObjectClass *parent_class = NULL;
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ModestHeaderViewClass,message_selected),
NULL, NULL,
- modest_marshal_VOID__STRING_INT,
- G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
+ modest_marshal_VOID__STRING_INT_INT,
+ G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
}
static void
}
-
-/* try to make a shorter display address; changes its argument in-place */
-static gchar*
-display_address (gchar *address)
-{
- gchar *cursor;
-
- if (!address)
- return NULL;
-
- /* simplistic --> remove <email@address> from display name */
- cursor = g_strstr_len (address, strlen(address), "<");
- if (cursor)
- cursor[0]='\0';
-
- /* simplistic --> remove (bla bla) from display name */
- cursor = g_strstr_len (address, strlen(address), "(");
- if (cursor)
- cursor[0]='\0';
-
- /* FIXME */
- if (!g_utf8_validate (address, -1, NULL))
- g_printerr ("modest: invalid: '%s'", address);
-
- return address;
-}
-
-
-
static void
sender_receiver_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
GtkTreeModel *tree_model, GtkTreeIter *iter, gboolean is_sender)
g_object_set (G_OBJECT(renderer),
"text",
- display_address (address),
+ modest_text_utils_display_address (address),
"weight",
(flags & TNY_HEADER_FLAG_SEEN) ? 400 : 800,
"style",
rendobj = G_OBJECT(renderer);
header = g_strdup_printf ("%s %s\n%s",
- display_address (from),
+ modest_text_utils_display_address (from),
display_date(date),
subject);
gboolean
-modest_header_view_set_columns (ModestHeaderView *obj, const GList *columns)
+modest_header_view_set_columns (ModestHeaderView *self, const GList *columns)
{
GtkTreeViewColumn *column=NULL;
GtkCellRenderer *renderer_msgtype,
ModestHeaderViewPrivate *priv;
const GList *cursor;
- priv = MODEST_HEADER_VIEW_GET_PRIVATE(obj);
-
+ priv = MODEST_HEADER_VIEW_GET_PRIVATE(self);
+
+ /* FIXME: check whether these renderers need to be freed */
renderer_msgtype = gtk_cell_renderer_pixbuf_new ();
renderer_attach = gtk_cell_renderer_pixbuf_new ();
- renderer_header = gtk_cell_renderer_text_new ();
+ renderer_header = gtk_cell_renderer_text_new ();
- remove_all_columns (obj);
+ remove_all_columns (self);
for (cursor = columns; cursor; cursor = g_list_next(cursor)) {
ModestHeaderViewColumn col =
g_assert_not_reached ();
}
+ /* we keep the column id around */
g_object_set_data (G_OBJECT(column), MODEST_HEADER_VIEW_COLUMN,
GINT_TO_POINTER(col));
-
+
+ /* we need this ptr when sorting the rows */
+ g_object_set_data (G_OBJECT(column), MODEST_HEADER_VIEW_PTR,
+ self);
+
gtk_tree_view_column_set_visible (column, TRUE);
- gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(self), column);
}
return TRUE;
}
priv->lock = NULL;
}
- priv->headers = NULL;
- priv->tny_folder = NULL;
+ priv->headers = NULL;
+ priv->folder = NULL;
G_OBJECT_CLASS(parent_class)->finalize (obj);
}
priv->sig1 = g_signal_connect (sel, "changed",
G_CALLBACK(on_selection_changed), self);
-
return GTK_WIDGET(self);
}
cmp_rows (GtkTreeModel *tree_model, GtkTreeIter *iter1, GtkTreeIter *iter2,
gpointer user_data)
{
- gint col_id = GPOINTER_TO_INT (user_data);
+ gint col_id;
gint t1, t2;
gint val1, val2;
gchar *s1, *s2;
gint cmp;
-
+
static int counter = 0;
+ col_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(user_data), MODEST_HEADER_VIEW_COLUMN));
+
+ if (!(++counter % 100)) {
+ GObject *header_view = g_object_get_data(G_OBJECT(user_data),
+ MODEST_HEADER_VIEW_PTR);
+ g_signal_emit (header_view,
+ signals[STATUS_UPDATE_SIGNAL],
+ 0, _("Sorting..."), 0, 0);
+ }
- g_return_val_if_fail (GTK_IS_TREE_MODEL(tree_model), -1);
-
- if (!(++counter % 100))
- g_print ("==> %d\n", counter);
-
-
switch (col_id) {
/* first one, we decide based on the time */
self = MODEST_HEADER_VIEW(user_data);
priv = MODEST_HEADER_VIEW_GET_PRIVATE(self);
+ priv->folder = folder;
+
if (!folder) /* when there is no folder */
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(self), FALSE);
else { /* it's a new one or a refresh */
/* install our special sorting functions */
cursor = cols = gtk_tree_view_get_columns (GTK_TREE_VIEW(self));
while (cursor) {
- gint col_id =
- GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cursor->data),
- MODEST_HEADER_VIEW_COLUMN));
+ gint col_id = GPOINTER_TO_INT (g_object_get_data(G_OBJECT(cursor->data),
+ MODEST_HEADER_VIEW_COLUMN));
gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(sortable),
col_id,
(GtkTreeIterCompareFunc)cmp_rows,
- GINT_TO_POINTER(col_id), NULL);
+ cursor->data, NULL);
cursor = g_list_next(cursor);
}
g_list_free (cols);
static void
on_refresh_folder_status_update (TnyFolder *folder, const gchar *msg,
- gint status_id, gpointer user_data)
+ gint num, gint total, gpointer user_data)
{
ModestHeaderView *self;
ModestHeaderViewPrivate *priv;
priv = MODEST_HEADER_VIEW_GET_PRIVATE(self);
g_signal_emit (G_OBJECT(self), signals[STATUS_UPDATE_SIGNAL],
- 0, msg, status_id);
+ 0, msg, num, total);
}
+TnyFolder*
+modest_header_view_get_folder (ModestHeaderView *self)
+{
+ ModestHeaderViewPrivate *priv;
+ priv = MODEST_HEADER_VIEW_GET_PRIVATE(self);
+
+ return priv->folder;
+}
+
gboolean
modest_header_view_set_folder (ModestHeaderView *self, TnyFolder *folder)
ModestHeaderViewPrivate *priv;
priv = MODEST_HEADER_VIEW_GET_PRIVATE(self);
+ priv->folder = folder;
+
if (!folder) {/* when there is no folder */
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(self), FALSE);
gtk_tree_view_set_model (GTK_TREE_VIEW (self), NULL);
on_refresh_folder_status_update,
self);
}
-
+
/* no message selected */
g_signal_emit (G_OBJECT(self), signals[MESSAGE_SELECTED_SIGNAL], 0,
NULL);
-
- //g_mutex_unlock (priv->lock);
-
return TRUE;
}
+static void
+get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
+{
+ GetMsgAsyncHelper *helper;
+ TnyHeaderFlags header_flags;
+
+ helper = (GetMsgAsyncHelper *) user_data;
+
+ if (msg) {
+ g_signal_emit (G_OBJECT(helper->self), signals[MESSAGE_SELECTED_SIGNAL], 0,
+ msg);
+
+ /* mark message as seen; _set_flags crashes, bug in tinymail? */
+ header_flags = tny_header_get_flags (helper->header);
+ tny_header_set_flags (helper->header, header_flags | TNY_HEADER_FLAG_SEEN);
+ } else {
+ g_signal_emit (G_OBJECT(helper->self), signals[ITEM_NOT_FOUND_SIGNAL],
+ 0, MODEST_ITEM_TYPE_MESSAGE);
+ }
+ /* Frees */
+ g_slice_free (GetMsgAsyncHelper, helper);
+}
static void
on_selection_changed (GtkTreeSelection *sel, gpointer user_data)
{
- GtkTreeModel *model;
- TnyHeader *header;
- TnyHeaderFlags header_flags;
- GtkTreeIter iter;
- ModestHeaderView *self;
+ GtkTreeModel *model;
+ TnyHeader *header;
+ GtkTreeIter iter;
+ ModestHeaderView *self;
ModestHeaderViewPrivate *priv;
- const TnyMsg *msg = NULL;
- const TnyFolder *folder;
+ TnyFolder *folder;
+ GetMsgAsyncHelper *helper;
g_return_if_fail (sel);
g_return_if_fail (user_data);
MODEST_ITEM_TYPE_FOLDER);
return;
}
-
- msg = tny_folder_get_msg (TNY_FOLDER(folder),
- header, NULL); /* FIXME */
- if (!msg) {
- g_signal_emit (G_OBJECT(self), signals[ITEM_NOT_FOUND_SIGNAL], 0,
- MODEST_ITEM_TYPE_MESSAGE);
- return;
- }
-
- g_signal_emit (G_OBJECT(self), signals[MESSAGE_SELECTED_SIGNAL], 0,
- msg);
-
- /* mark message as seen; _set_flags crashes, bug in tinymail? */
- header_flags = tny_header_get_flags (TNY_HEADER(header));
- tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
- /* Free */
-/* g_free (folder); */
-}
+ helper = g_slice_new0 (GetMsgAsyncHelper);
+ helper->self = self;
+ helper->header = header;
+
+ /* Get message asynchronously. The callback will issue a
+ signal if the message was retrieved correctly and then will
+ set the header flags as read. */
+ tny_folder_get_msg_async (TNY_FOLDER(folder),
+ header, get_msg_cb, helper);
+
+ /* Frees */
+ g_object_unref (G_OBJECT (folder));
+}
+
+
+/* PROTECTED method. It's useful when we want to force a given
+ selection to reload a msg. For example if we have selected a header
+ in offline mode, when Modest become online, we want to reload the
+ message automatically without an user click over the header */
+void
+_modest_header_view_change_selection (GtkTreeSelection *selection,
+ gpointer user_data)
+{
+ g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
+ g_return_if_fail (MODEST_IS_HEADER_VIEW (user_data));
+ on_selection_changed (selection, user_data);
+}