1 /* modest-tny-header-tree-view.c
3 * This file is part of modest.
5 * Copyright (C) 2006 Nokia Corporation
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <glib/gi18n.h>
23 #include "modest-tny-header-tree-view.h"
24 #include <tny-list-iface.h>
27 /* 'private'/'protected' functions */
28 static void modest_tny_header_tree_view_class_init (ModestTnyHeaderTreeViewClass *klass);
29 static void modest_tny_header_tree_view_init (ModestTnyHeaderTreeView *obj);
30 static void modest_tny_header_tree_view_finalize (GObject *obj);
32 static void selection_changed (GtkTreeSelection *sel, gpointer user_data);
33 static void column_clicked (GtkTreeViewColumn *treeviewcolumn, gpointer user_data);
35 #define PIXMAP_PREFIX PREFIX "/share/modest/pixmaps/"
38 MESSAGE_SELECTED_SIGNAL,
52 typedef struct _ModestTnyHeaderTreeViewPrivate ModestTnyHeaderTreeViewPrivate;
53 struct _ModestTnyHeaderTreeViewPrivate {
54 TnyMsgFolderIface *tny_msg_folder;
55 TnyListIface *headers;
57 GdkPixbuf *icons[HEADER_ICON_NUM];
59 #define MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
60 MODEST_TYPE_TNY_HEADER_TREE_VIEW, \
61 ModestTnyHeaderTreeViewPrivate))
63 static GObjectClass *parent_class = NULL;
65 /* uncomment the following if you have defined any signals */
66 static guint signals[LAST_SIGNAL] = {0};
69 modest_tny_header_tree_view_get_type (void)
71 static GType my_type = 0;
73 static const GTypeInfo my_info = {
74 sizeof(ModestTnyHeaderTreeViewClass),
76 NULL, /* base finalize */
77 (GClassInitFunc) modest_tny_header_tree_view_class_init,
78 NULL, /* class finalize */
79 NULL, /* class data */
80 sizeof(ModestTnyHeaderTreeView),
82 (GInstanceInitFunc) modest_tny_header_tree_view_init,
84 my_type = g_type_register_static (GTK_TYPE_TREE_VIEW,
85 "ModestTnyHeaderTreeView",
92 modest_tny_header_tree_view_class_init (ModestTnyHeaderTreeViewClass *klass)
94 GObjectClass *gobject_class;
95 gobject_class = (GObjectClass*) klass;
97 parent_class = g_type_class_peek_parent (klass);
98 gobject_class->finalize = modest_tny_header_tree_view_finalize;
100 g_type_class_add_private (gobject_class, sizeof(ModestTnyHeaderTreeViewPrivate));
102 signals[MESSAGE_SELECTED_SIGNAL] =
103 g_signal_new ("message_selected",
104 G_TYPE_FROM_CLASS (gobject_class),
106 G_STRUCT_OFFSET (ModestTnyHeaderTreeViewClass,message_selected),
108 g_cclosure_marshal_VOID__POINTER,
109 G_TYPE_NONE, 1, G_TYPE_POINTER);
115 flags_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
116 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
118 TnyMsgHeaderFlags flags;
119 static gchar txt[10];
121 gtk_tree_model_get (tree_model, iter, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags, -1);
122 g_snprintf (txt, 10, "%d", flags);
123 g_object_set (G_OBJECT (renderer), "text", txt, NULL);
129 msgtype_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
130 GtkTreeModel *tree_model, GtkTreeIter *iter,
131 GdkPixbuf *icons[HEADER_ICON_NUM])
133 TnyMsgHeaderFlags flags;
136 gtk_tree_model_get (tree_model, iter, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN,
139 if (flags & TNY_MSG_HEADER_FLAG_SEEN)
140 pixbuf = icons[HEADER_ICON_READ];
142 pixbuf = icons[HEADER_ICON_UNREAD];
144 g_object_set (G_OBJECT (renderer), "pixbuf", pixbuf,
149 attach_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
150 GtkTreeModel *tree_model, GtkTreeIter *iter, GdkPixbuf *icons[HEADER_ICON_NUM])
152 TnyMsgHeaderFlags flags;
155 gtk_tree_model_get (tree_model, iter, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN,
157 if (flags & TNY_MSG_HEADER_FLAG_ATTACHMENTS)
158 pixbuf = icons[HEADER_ICON_ATTACH];
162 g_object_set (G_OBJECT (renderer), "pixbuf", pixbuf, NULL);
168 header_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
169 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data)
172 TnyMsgHeaderFlags flags;
174 gtk_tree_model_get (tree_model, iter, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN,
176 rendobj = G_OBJECT(renderer);
178 if (!(flags & TNY_MSG_HEADER_FLAG_SEEN))
179 g_object_set (rendobj, "weight", 800, NULL);
181 g_object_set (rendobj, "weight", 400, NULL); /* default, non-bold */
186 init_icons (GdkPixbuf *icons[HEADER_ICON_NUM])
188 icons[HEADER_ICON_READ] =
189 gdk_pixbuf_new_from_file (PIXMAP_PREFIX "read.xpm",NULL);
190 icons[HEADER_ICON_UNREAD] =
191 gdk_pixbuf_new_from_file (PIXMAP_PREFIX "unread.xpm",NULL);
192 icons[HEADER_ICON_ATTACH] =
193 gdk_pixbuf_new_from_file (PIXMAP_PREFIX "clip.xpm",NULL);
198 modest_tny_header_tree_view_init (ModestTnyHeaderTreeView *obj)
200 GtkTreeViewColumn *column;
201 GtkCellRenderer *renderer_msgtype,
205 ModestTnyHeaderTreeViewPrivate *priv;
207 priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(obj);
209 init_icons (priv->icons);
211 renderer_msgtype = gtk_cell_renderer_pixbuf_new ();
212 renderer_attach = gtk_cell_renderer_pixbuf_new ();
213 renderer_header = gtk_cell_renderer_text_new ();
215 priv->tny_msg_folder = NULL;
216 priv->headers = NULL;
219 column = gtk_tree_view_column_new_with_attributes(_("M"), renderer_msgtype, NULL);
220 gtk_tree_view_column_set_resizable (column, TRUE);
221 gtk_tree_view_column_set_sort_column_id (column, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN);
222 gtk_tree_view_column_set_sort_indicator (column, FALSE);
223 gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column);
224 gtk_tree_view_column_set_cell_data_func(column, renderer_msgtype,
225 (GtkTreeCellDataFunc)msgtype_cell_data,
230 column = gtk_tree_view_column_new_with_attributes(_("A"), renderer_attach, NULL);
231 gtk_tree_view_column_set_resizable (column, TRUE);
232 gtk_tree_view_column_set_sort_column_id (column, TNY_MSG_HEADER_LIST_MODEL_FLAGS_COLUMN);
233 gtk_tree_view_column_set_sort_indicator (column, FALSE);
234 gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column);
235 gtk_tree_view_column_set_cell_data_func(column, renderer_attach,
236 (GtkTreeCellDataFunc)attach_cell_data,
240 column = gtk_tree_view_column_new_with_attributes(_("Date"), renderer_header,
242 TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_COLUMN,
244 gtk_tree_view_column_set_resizable (column, TRUE);
245 gtk_tree_view_column_set_sort_column_id (column, TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_COLUMN);
246 gtk_tree_view_column_set_sort_indicator (column, TRUE);
247 gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column);
248 gtk_tree_view_column_set_cell_data_func(column, renderer_header,
249 (GtkTreeCellDataFunc)header_cell_data,
251 g_signal_connect (G_OBJECT (column), "clicked", G_CALLBACK (column_clicked), obj);
255 column = gtk_tree_view_column_new_with_attributes(_("From"), renderer_header,
257 TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN,
259 gtk_tree_view_column_set_resizable (column, TRUE);
260 gtk_tree_view_column_set_sort_column_id (column, TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN);
261 gtk_tree_view_column_set_sort_indicator (column, TRUE);
262 gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column);
263 gtk_tree_view_column_set_cell_data_func(column, renderer_header,
264 (GtkTreeCellDataFunc)header_cell_data,
266 g_signal_connect (G_OBJECT (column), "clicked", G_CALLBACK (column_clicked), obj);
270 column = gtk_tree_view_column_new_with_attributes(_("Subject"), renderer_header,
272 TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN,
274 gtk_tree_view_column_set_resizable (column, TRUE);
275 gtk_tree_view_column_set_sort_column_id (column, TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN);
276 gtk_tree_view_column_set_sort_indicator (column, TRUE);
277 gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column);
278 g_signal_connect (G_OBJECT (column), "clicked", G_CALLBACK (column_clicked), obj);
282 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(obj), TRUE);
283 gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(obj), TRUE);
284 gtk_tree_view_column_set_cell_data_func(column, renderer_header,
285 (GtkTreeCellDataFunc)header_cell_data,
288 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW(obj), TRUE); /* alternating row colors */
293 modest_tny_header_tree_view_finalize (GObject *obj)
295 ModestTnyHeaderTreeView *self;
296 ModestTnyHeaderTreeViewPrivate *priv;
299 self = MODEST_TNY_HEADER_TREE_VIEW(obj);
300 priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self);
303 g_object_unref (G_OBJECT(priv->headers));
305 priv->headers = NULL;
306 priv->tny_msg_folder = NULL;
308 /* cleanup our icons */
309 for (i = 0; i != HEADER_ICON_NUM; ++i) {
310 if (priv->icons[i]) {
311 g_object_unref (G_OBJECT(priv->icons[i]));
312 priv->icons[i] = NULL;
318 modest_tny_header_tree_view_new (TnyMsgFolderIface *folder)
321 GtkTreeSelection *sel;
322 ModestTnyHeaderTreeView *self;
324 obj = G_OBJECT(g_object_new(MODEST_TYPE_TNY_HEADER_TREE_VIEW, NULL));
325 self = MODEST_TNY_HEADER_TREE_VIEW(obj);
327 if (!modest_tny_header_tree_view_set_folder (self, NULL)) {
328 g_warning ("could not set the folder");
329 g_object_unref (obj);
333 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self));
334 g_signal_connect (sel, "changed",
335 G_CALLBACK(selection_changed), self);
337 return GTK_WIDGET(self);
342 modest_tny_header_tree_view_set_folder (ModestTnyHeaderTreeView *self,
343 TnyMsgFolderIface *folder)
345 GtkTreeModel *oldsortable, *sortable, *oldmodel;
346 ModestTnyHeaderTreeViewPrivate *priv;
347 static GtkTreeModel *empty_model = NULL;
349 g_return_val_if_fail (self, FALSE);
351 priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self);
354 priv->headers = TNY_LIST_IFACE(tny_msg_header_list_model_new ());
355 tny_msg_folder_iface_get_headers (folder, priv->headers,
357 tny_msg_header_list_model_set_folder (TNY_MSG_HEADER_LIST_MODEL(priv->headers),
361 empty_model = GTK_TREE_MODEL(gtk_list_store_new(1, G_TYPE_STRING));
364 oldsortable = gtk_tree_view_get_model(GTK_TREE_VIEW (self));
365 if (oldsortable && GTK_IS_TREE_MODEL_SORT(oldsortable)) {
366 GtkTreeModel *oldmodel = gtk_tree_model_sort_get_model
367 (GTK_TREE_MODEL_SORT(oldsortable));
369 g_object_unref (G_OBJECT(oldmodel));
370 g_object_unref (oldsortable);
374 sortable = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(priv->headers));
376 sortable = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(empty_model));
378 gtk_tree_view_set_model (GTK_TREE_VIEW (self), sortable);
385 selection_changed (GtkTreeSelection *sel, gpointer user_data)
388 TnyMsgHeaderIface *header;
390 ModestTnyHeaderTreeView *tree_view;
392 g_return_if_fail (sel);
393 g_return_if_fail (user_data);
395 if (!gtk_tree_selection_get_selected (sel, &model, &iter))
396 return; /* msg was _un_selected */
398 tree_view = MODEST_TNY_HEADER_TREE_VIEW (user_data);
400 gtk_tree_model_get (model, &iter,
401 TNY_MSG_HEADER_LIST_MODEL_INSTANCE_COLUMN,
405 TnyMsgHeaderFlags flags;
406 const TnyMsgIface *msg;
407 const TnyMsgFolderIface *folder;
409 folder = tny_msg_header_iface_get_folder (TNY_MSG_HEADER_IFACE(header));
411 g_message ("cannot find folder");
413 msg = tny_msg_folder_iface_get_message (TNY_MSG_FOLDER_IFACE(folder),
416 g_message ("cannot find msg");
419 g_signal_emit (G_OBJECT(tree_view), signals[MESSAGE_SELECTED_SIGNAL], 0,
422 /* mark message as seen; _set_flags crashes, bug in tinymail? */
423 flags = tny_msg_header_iface_get_flags (TNY_MSG_HEADER_IFACE(header));
424 //tny_msg_header_iface_set_flags (header, flags | TNY_MSG_HEADER_FLAG_SEEN);
430 column_clicked (GtkTreeViewColumn *col, gpointer user_data)
432 GtkTreeView *treeview;
435 treeview = GTK_TREE_VIEW (user_data);
436 id = gtk_tree_view_column_get_sort_column_id (col);
438 gtk_tree_view_set_search_column (treeview, id);