* Move tree column creation from UI implementations to modest-tny-header-tree-view.c.
[modest] / src / modest-tny-header-tree-view.c
1 /* modest-tny-header-tree-view.c 
2  *
3  * This file is part of modest.
4  *
5  * Copyright (C) 2006 Nokia Corporation
6  * 
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.
11  *
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.
16  *
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.
20  *
21  */
22 #include <glib/gi18n.h>
23 #include "modest-tny-header-tree-view.h"
24
25 /* 'private'/'protected' functions */
26 static void modest_tny_header_tree_view_class_init  (ModestTnyHeaderTreeViewClass *klass);
27 static void modest_tny_header_tree_view_init        (ModestTnyHeaderTreeView *obj);
28 static void modest_tny_header_tree_view_finalize    (GObject *obj);
29
30 static void selection_changed (GtkTreeSelection *sel, gpointer user_data);
31         
32 /* list my signals */
33 enum {
34         /* MY_SIGNAL_1, */
35         MESSAGE_SELECTED_SIGNAL,
36         LAST_SIGNAL
37 };
38
39 typedef struct _ModestTnyHeaderTreeViewPrivate ModestTnyHeaderTreeViewPrivate;
40 struct _ModestTnyHeaderTreeViewPrivate {
41         TnyMsgFolderIface *tny_msg_folder;
42         GtkTreeModel *header_tree_model;
43 };
44 #define MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
45                                                          MODEST_TYPE_TNY_HEADER_TREE_VIEW, \
46                                                          ModestTnyHeaderTreeViewPrivate))
47 /* globals */
48 static GObjectClass *parent_class = NULL;
49
50 /* uncomment the following if you have defined any signals */
51 static guint signals[LAST_SIGNAL] = {0};
52
53 GType
54 modest_tny_header_tree_view_get_type (void)
55 {
56         static GType my_type = 0;
57         if (!my_type) {
58                 static const GTypeInfo my_info = {
59                         sizeof(ModestTnyHeaderTreeViewClass),
60                         NULL,           /* base init */
61                         NULL,           /* base finalize */
62                         (GClassInitFunc) modest_tny_header_tree_view_class_init,
63                         NULL,           /* class finalize */
64                         NULL,           /* class data */
65                         sizeof(ModestTnyHeaderTreeView),
66                         1,              /* n_preallocs */
67                         (GInstanceInitFunc) modest_tny_header_tree_view_init,
68                 };
69                 my_type = g_type_register_static (GTK_TYPE_TREE_VIEW,
70                                                   "ModestTnyHeaderTreeView",
71                                                   &my_info, 0);
72         }
73         return my_type;
74 }
75
76 static void
77 modest_tny_header_tree_view_class_init (ModestTnyHeaderTreeViewClass *klass)
78 {
79         GObjectClass *gobject_class;
80         gobject_class = (GObjectClass*) klass;
81
82         parent_class            = g_type_class_peek_parent (klass);
83         gobject_class->finalize = modest_tny_header_tree_view_finalize;
84
85         g_type_class_add_private (gobject_class, sizeof(ModestTnyHeaderTreeViewPrivate));
86
87         signals[MESSAGE_SELECTED_SIGNAL] = 
88                 g_signal_new ("message_selected",
89                               G_TYPE_FROM_CLASS (gobject_class),
90                               G_SIGNAL_RUN_FIRST,
91                               G_STRUCT_OFFSET (ModestTnyHeaderTreeViewClass,message_selected),
92                               NULL, NULL,
93                               g_cclosure_marshal_VOID__POINTER,
94                               G_TYPE_NONE, 1, G_TYPE_POINTER);  
95 }
96
97 static void
98 modest_tny_header_tree_view_init (ModestTnyHeaderTreeView *obj)
99 {
100         GtkTreeViewColumn *column;
101         GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
102         ModestTnyHeaderTreeViewPrivate *priv;
103         
104         priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(obj); 
105
106         priv->tny_msg_folder = NULL;
107         priv->header_tree_model = NULL;
108         
109         column =  gtk_tree_view_column_new_with_attributes(_("Date"), renderer,
110                                                            "text",
111                                                            TNY_MSG_HEADER_LIST_MODEL_DATE_RECEIVED_COLUMN,
112                                                            NULL);
113         gtk_tree_view_column_set_resizable (column, TRUE);
114         gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column);
115
116
117
118         column =  gtk_tree_view_column_new_with_attributes(_("From"), renderer,
119                                                            "text",
120                                                            TNY_MSG_HEADER_LIST_MODEL_FROM_COLUMN,
121                                                            NULL);
122         gtk_tree_view_column_set_resizable (column, TRUE);
123         gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column);
124
125
126         column =  gtk_tree_view_column_new_with_attributes(_("Subject"), renderer,
127                                                            "text",
128                                                            TNY_MSG_HEADER_LIST_MODEL_SUBJECT_COLUMN,
129                                                            NULL);
130         gtk_tree_view_column_set_resizable (column, TRUE);
131         gtk_tree_view_append_column (GTK_TREE_VIEW(obj), column);
132
133         gtk_tree_view_set_headers_visible   (GTK_TREE_VIEW(obj), TRUE);
134         gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW(obj), TRUE);
135         
136 }
137
138 static void
139 modest_tny_header_tree_view_finalize (GObject *obj)
140 {
141         ModestTnyHeaderTreeView        *self;
142         ModestTnyHeaderTreeViewPrivate *priv;
143
144         self = MODEST_TNY_HEADER_TREE_VIEW(obj);
145         priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self);
146
147         if (priv->header_tree_model)    
148                 g_object_unref (G_OBJECT(priv->header_tree_model));
149
150         priv->header_tree_model = NULL;
151         priv->tny_msg_folder    = NULL;
152 }
153
154 GtkWidget*
155 modest_tny_header_tree_view_new (TnyMsgFolderIface *folder)
156 {
157         GObject *obj;
158         GtkTreeSelection *sel;
159         ModestTnyHeaderTreeView *self;
160                 
161         obj  = G_OBJECT(g_object_new(MODEST_TYPE_TNY_HEADER_TREE_VIEW, NULL));
162         self = MODEST_TNY_HEADER_TREE_VIEW(obj);
163
164         if (!modest_tny_header_tree_view_set_folder (self, NULL)) {
165                 g_warning ("could not set the folder");
166                 g_object_unref (obj);
167                 return NULL;
168         }
169                 
170         sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self));
171         g_signal_connect (sel, "changed",
172                           G_CALLBACK(selection_changed), self);
173
174         return GTK_WIDGET(self);
175 }
176
177
178 gboolean
179 modest_tny_header_tree_view_set_folder (ModestTnyHeaderTreeView *self,
180                                         TnyMsgFolderIface *folder)
181 {
182         GtkTreeModel *sortable;
183         ModestTnyHeaderTreeViewPrivate *priv;
184
185         g_return_val_if_fail (self, FALSE);
186
187         priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self);
188
189         /* clean up old stuff */
190         if (priv->header_tree_model)
191                 g_object_unref (G_OBJECT(priv->header_tree_model));
192         priv->header_tree_model = NULL;
193
194         priv->header_tree_model = GTK_TREE_MODEL (tny_msg_header_list_model_new());
195         if (folder) {
196                 tny_msg_header_list_model_set_folder (
197                         TNY_MSG_HEADER_LIST_MODEL(priv->header_tree_model),
198                         folder, TRUE); /* FIXME: refresh?*/
199                 
200                 sortable = gtk_tree_model_sort_new_with_model (priv->header_tree_model);
201                 
202         } else {
203                 static GtkTreeModel *empty_model = NULL;
204                 if (!empty_model)
205                         empty_model = GTK_TREE_MODEL(gtk_list_store_new(1,G_TYPE_STRING));
206
207                 sortable = empty_model;
208         }
209
210         gtk_tree_view_set_model (GTK_TREE_VIEW (self), sortable);
211
212         if (sortable)
213                 g_object_unref (G_OBJECT(sortable));
214         
215         return TRUE;
216 }
217
218
219 void
220 selection_changed (GtkTreeSelection *sel, gpointer user_data)
221 {
222         GtkTreeModel            *model;
223         TnyMsgHeaderIface       *header;
224         GtkTreeIter             iter;
225         ModestTnyHeaderTreeView *tree_view;
226
227         g_return_if_fail (sel);
228         g_return_if_fail (user_data);
229         
230         if (!gtk_tree_selection_get_selected (sel, &model, &iter))
231                 return; /* msg was _un_selected */
232         
233         tree_view = MODEST_TNY_HEADER_TREE_VIEW (user_data);
234         
235         gtk_tree_model_get (model, &iter,
236                             TNY_MSG_HEADER_LIST_MODEL_INSTANCE_COLUMN,
237                             &header, -1);
238         
239         if (header) {
240                 const TnyMsgIface *msg;
241                 const TnyMsgFolderIface *folder;
242                 
243                 folder = tny_msg_header_iface_get_folder (TNY_MSG_HEADER_IFACE(header));
244                 if (!folder) {
245                         g_warning ("cannot find folder");
246                         return;
247                 }
248                 
249                 msg = tny_msg_folder_iface_get_message (TNY_MSG_FOLDER_IFACE(folder), header);
250                 if (!msg) {
251                         g_warning ("cannot find msg");
252                         return;
253                 }
254                 
255                 g_signal_emit (G_OBJECT(tree_view), signals[MESSAGE_SELECTED_SIGNAL], 0,
256                                msg); 
257         }
258 }