8e859867b81168a50e06403f8c1c1eafe4245a00
[modest] / src / modest-tny-header-tree-view.c
1 /* modest-tny-header-tree-view.c */
2
3 /* insert (c)/licensing information) */
4
5 #include "modest-tny-header-tree-view.h"
6
7 /* 'private'/'protected' functions */
8 static void modest_tny_header_tree_view_class_init  (ModestTnyHeaderTreeViewClass *klass);
9 static void modest_tny_header_tree_view_init        (ModestTnyHeaderTreeView *obj);
10 static void modest_tny_header_tree_view_finalize    (GObject *obj);
11
12 static void selection_changed (GtkTreeSelection *sel, gpointer user_data);
13         
14 /* list my signals */
15 enum {
16         /* MY_SIGNAL_1, */
17         MESSAGE_SELECTED_SIGNAL,
18         LAST_SIGNAL
19 };
20
21 typedef struct _ModestTnyHeaderTreeViewPrivate ModestTnyHeaderTreeViewPrivate;
22 struct _ModestTnyHeaderTreeViewPrivate {
23         TnyMsgFolderIface *tny_msg_folder;
24         GtkTreeModel *header_tree_model;
25 };
26 #define MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
27                                                          MODEST_TYPE_TNY_HEADER_TREE_VIEW, \
28                                                          ModestTnyHeaderTreeViewPrivate))
29 /* globals */
30 static GObjectClass *parent_class = NULL;
31
32 /* uncomment the following if you have defined any signals */
33 static guint signals[LAST_SIGNAL] = {0};
34
35 GType
36 modest_tny_header_tree_view_get_type (void)
37 {
38         static GType my_type = 0;
39         if (!my_type) {
40                 static const GTypeInfo my_info = {
41                         sizeof(ModestTnyHeaderTreeViewClass),
42                         NULL,           /* base init */
43                         NULL,           /* base finalize */
44                         (GClassInitFunc) modest_tny_header_tree_view_class_init,
45                         NULL,           /* class finalize */
46                         NULL,           /* class data */
47                         sizeof(ModestTnyHeaderTreeView),
48                         1,              /* n_preallocs */
49                         (GInstanceInitFunc) modest_tny_header_tree_view_init,
50                 };
51                 my_type = g_type_register_static (GTK_TYPE_TREE_VIEW,
52                                                   "ModestTnyHeaderTreeView",
53                                                   &my_info, 0);
54         }
55         return my_type;
56 }
57
58 static void
59 modest_tny_header_tree_view_class_init (ModestTnyHeaderTreeViewClass *klass)
60 {
61         GObjectClass *gobject_class;
62         gobject_class = (GObjectClass*) klass;
63
64         parent_class            = g_type_class_peek_parent (klass);
65         gobject_class->finalize = modest_tny_header_tree_view_finalize;
66
67         g_type_class_add_private (gobject_class, sizeof(ModestTnyHeaderTreeViewPrivate));
68
69         signals[MESSAGE_SELECTED_SIGNAL] = 
70                 g_signal_new ("message_selected",
71                               G_TYPE_FROM_CLASS (gobject_class),
72                               G_SIGNAL_RUN_FIRST,
73                               G_STRUCT_OFFSET (ModestTnyHeaderTreeViewClass,message_selected),
74                               NULL, NULL,
75                               g_cclosure_marshal_VOID__POINTER,
76                               G_TYPE_NONE, 1, G_TYPE_POINTER);  
77 }
78
79 static void
80 modest_tny_header_tree_view_init (ModestTnyHeaderTreeView *obj)
81 {
82         ModestTnyHeaderTreeViewPrivate *priv;
83         priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(obj); 
84
85         priv->tny_msg_folder = NULL;
86         priv->header_tree_model = NULL;
87 }
88
89 static void
90 modest_tny_header_tree_view_finalize (GObject *obj)
91 {
92         ModestTnyHeaderTreeView        *self;
93         ModestTnyHeaderTreeViewPrivate *priv;
94
95         self = MODEST_TNY_HEADER_TREE_VIEW(obj);
96         priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self);
97
98         if (priv->header_tree_model)    
99                 g_object_unref (G_OBJECT(priv->header_tree_model));
100
101         priv->header_tree_model = NULL;
102         priv->tny_msg_folder    = NULL;
103 }
104
105 GtkWidget*
106 modest_tny_header_tree_view_new (TnyMsgFolderIface *folder)
107 {
108         GObject *obj;
109         GtkTreeSelection *sel;
110         ModestTnyHeaderTreeView *self;
111                 
112         obj  = G_OBJECT(g_object_new(MODEST_TYPE_TNY_HEADER_TREE_VIEW, NULL));
113         self = MODEST_TNY_HEADER_TREE_VIEW(obj);
114
115         if (!modest_tny_header_tree_view_set_folder (self, NULL)) {
116                 g_warning ("could not set the folder");
117                 g_object_unref (obj);
118                 return NULL;
119         }
120                 
121         sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(self));
122         g_signal_connect (sel, "changed",
123                           G_CALLBACK(selection_changed), self);
124
125         return GTK_WIDGET(self);
126 }
127
128
129 gboolean
130 modest_tny_header_tree_view_set_folder (ModestTnyHeaderTreeView *self,
131                                         TnyMsgFolderIface *folder)
132 {
133         GtkTreeModel *sortable;
134         ModestTnyHeaderTreeViewPrivate *priv;
135
136         g_return_val_if_fail (self, FALSE);
137
138         priv = MODEST_TNY_HEADER_TREE_VIEW_GET_PRIVATE(self);
139
140         /* clean up old stuff */
141         if (priv->header_tree_model)
142                 g_object_unref (G_OBJECT(priv->header_tree_model));
143         priv->header_tree_model = NULL;
144         priv->header_tree_model = GTK_TREE_MODEL (tny_msg_header_list_model_new());
145
146         if (folder) {
147                 tny_msg_header_list_model_set_folder (
148                         TNY_MSG_HEADER_LIST_MODEL(priv->header_tree_model),
149                         folder, FALSE); /* FIXME: refresh?*/
150
151                 sortable = gtk_tree_model_sort_new_with_model (priv->header_tree_model);
152                 
153         } else {
154                 static GtkTreeModel *empty_model = NULL;
155                 if (!empty_model)
156                         empty_model = GTK_TREE_MODEL(gtk_list_store_new(1,G_TYPE_STRING));
157
158                 sortable = empty_model;
159         }
160         
161         gtk_tree_view_set_model (GTK_TREE_VIEW (self), sortable);
162
163         if (sortable)
164                 g_object_unref (G_OBJECT(sortable));
165         
166         return TRUE;
167 }
168
169
170 void
171 selection_changed (GtkTreeSelection *sel, gpointer user_data)
172 {
173         GtkTreeModel            *model;
174         TnyMsgHeaderIface       *header;
175         GtkTreeIter             iter;
176         ModestTnyHeaderTreeView *tree_view;
177
178         g_return_if_fail (sel);
179         g_return_if_fail (user_data);
180         
181         if (!gtk_tree_selection_get_selected (sel, &model, &iter))
182                 return; /* msg was _un_selected */
183         
184         tree_view = MODEST_TNY_HEADER_TREE_VIEW (user_data);
185         
186         gtk_tree_model_get (model, &iter,
187                             TNY_MSG_HEADER_LIST_MODEL_INSTANCE_COLUMN,
188                             &header, -1);
189         
190         if (header) {
191                 const TnyMsgIface *msg;
192                 const TnyMsgFolderIface *folder;
193                 
194                 folder = tny_msg_header_iface_get_folder (TNY_MSG_HEADER_IFACE(header));
195                 if (!folder) {
196                         g_warning ("cannot find folder");
197                         return;
198                 }
199                 
200                 msg = tny_msg_folder_iface_get_message (TNY_MSG_FOLDER_IFACE(folder), header);
201                 if (!msg) {
202                         g_warning ("cannot find msg");
203                         return;
204                 }
205                 
206                 g_signal_emit (G_OBJECT(tree_view), signals[MESSAGE_SELECTED_SIGNAL], 0,
207                                msg); 
208         }
209 }