* Change headers list tree view rows layout (flags, header, date).
[modest] / src / widgets / modest-header-view-render.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <modest-header-view.h>
31 #include <modest-header-view-priv.h>
32 #include <modest-icon-names.h>
33 #include <modest-text-utils.h>
34 #include <modest-runtime.h>
35 #include <glib/gi18n.h>
36 #include <modest-platform.h>
37
38
39 static GdkPixbuf*
40 get_pixbuf_for_flag (TnyHeaderFlags flag)
41 {
42         /* optimization */
43         static GdkPixbuf *deleted_pixbuf          = NULL;
44         static GdkPixbuf *seen_pixbuf             = NULL;
45         static GdkPixbuf *unread_pixbuf           = NULL;
46         static GdkPixbuf *attachments_pixbuf      = NULL;
47         
48         switch (flag) {
49         case TNY_HEADER_FLAG_DELETED:
50                 if (G_UNLIKELY(!deleted_pixbuf))
51                         deleted_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_DELETED);
52                 return deleted_pixbuf;
53         case TNY_HEADER_FLAG_SEEN:
54                 if (G_UNLIKELY(!seen_pixbuf))
55                         seen_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_READ);
56                 return seen_pixbuf;
57         case TNY_HEADER_FLAG_ATTACHMENTS:
58                 if (G_UNLIKELY(!attachments_pixbuf))
59                         attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH);
60                 return attachments_pixbuf;
61         default:
62                 if (G_UNLIKELY(!unread_pixbuf))
63                         unread_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_UNREAD);
64                 return unread_pixbuf;
65         }
66 }
67
68 static GdkPixbuf*
69 get_pixbuf_for_compact_flag (TnyHeaderFlags flag)
70 {
71         /* optimization */
72         static GdkPixbuf *high_attachments_pixbuf   = NULL;
73         static GdkPixbuf *normal_attachments_pixbuf = NULL;
74         static GdkPixbuf *low_attachments_pixbuf    = NULL;
75         static GdkPixbuf *high_pixbuf               = NULL;
76         static GdkPixbuf *low_pixbuf                = NULL;
77         
78         if (flag & TNY_HEADER_FLAG_ATTACHMENTS) {
79                 if (flag & TNY_HEADER_FLAG_HIGH_PRIORITY) {
80                         if (G_UNLIKELY(!high_attachments_pixbuf))
81                                 high_attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH_HIGH_PRIORITY);
82                         return high_attachments_pixbuf;
83                 }
84                 else if (flag & TNY_HEADER_FLAG_LOW_PRIORITY) {
85                         if (G_UNLIKELY(!low_attachments_pixbuf))
86                                 low_attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH_LOW_PRIORITY);
87                         return low_attachments_pixbuf;
88                 }
89                 else {
90                         if (G_UNLIKELY(!normal_attachments_pixbuf))
91                                 normal_attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH_NORM_PRIORITY);
92                         return normal_attachments_pixbuf;
93                 }
94         }
95         else if (flag & TNY_HEADER_FLAG_HIGH_PRIORITY) {
96                 if (G_UNLIKELY(!high_pixbuf))
97                         high_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_HIGH_PRIORITY);
98                 return high_pixbuf;
99         }
100         else if (flag & TNY_HEADER_FLAG_LOW_PRIORITY) {
101                 if (G_UNLIKELY(!low_pixbuf))
102                         low_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_LOW_PRIORITY);
103                 return low_pixbuf;
104         }
105
106         
107         return NULL;
108 }
109
110 static void
111 set_common_flags (GtkCellRenderer *renderer, TnyHeaderFlags flags)
112 {
113         g_object_set (G_OBJECT(renderer),
114                       "weight", (flags & TNY_HEADER_FLAG_SEEN) ? 400: 800,
115                       "strikethrough",  (flags & TNY_HEADER_FLAG_DELETED) ?  TRUE:FALSE,
116                       NULL);    
117 }
118
119
120 void
121 _modest_header_view_msgtype_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
122                    GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data)
123 {
124         TnyHeaderFlags flags;
125                 
126         gtk_tree_model_get (tree_model, iter, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
127                             &flags, -1);
128
129         if (flags & TNY_HEADER_FLAG_DELETED)
130                 g_object_set (G_OBJECT (renderer), "pixbuf",
131                               get_pixbuf_for_flag (TNY_HEADER_FLAG_DELETED), NULL);           
132         else if (flags & TNY_HEADER_FLAG_SEEN)
133                 g_object_set (G_OBJECT (renderer), "pixbuf",
134                               get_pixbuf_for_flag (TNY_HEADER_FLAG_SEEN), NULL);              
135         else 
136                 g_object_set (G_OBJECT (renderer), "pixbuf",
137                               get_pixbuf_for_flag (0), NULL); /* ughh, FIXME */               
138 }
139
140 void
141 _modest_header_view_attach_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
142                                       GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data)
143 {
144         TnyHeaderFlags flags;
145
146         gtk_tree_model_get (tree_model, iter, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
147                             &flags, -1);
148
149         if (flags & TNY_HEADER_FLAG_ATTACHMENTS)
150                 g_object_set (G_OBJECT (renderer), "pixbuf",
151                               get_pixbuf_for_flag (TNY_HEADER_FLAG_ATTACHMENTS),
152                               NULL);
153 }
154
155 void
156 _modest_header_view_compact_flag_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
157                                             GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data)
158 {
159         TnyHeaderFlags flags;
160
161         gtk_tree_model_get (tree_model, iter, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
162                             &flags, -1);
163
164         flags = TNY_HEADER_FLAG_ATTACHMENTS;
165         if (flags & TNY_HEADER_FLAG_ATTACHMENTS) {
166                 if (flags & TNY_HEADER_FLAG_HIGH_PRIORITY) 
167                         g_object_set (G_OBJECT (renderer), "pixbuf",
168                                       get_pixbuf_for_compact_flag (flags),
169                                       NULL);
170                 else if (flags & TNY_HEADER_FLAG_LOW_PRIORITY) 
171                         g_object_set (G_OBJECT (renderer), "pixbuf",
172                                       get_pixbuf_for_compact_flag (flags),                                    
173                                       NULL);
174                 else  
175                         g_object_set (G_OBJECT (renderer), "pixbuf",
176                                       get_pixbuf_for_compact_flag (flags),    
177                                       NULL);
178         }
179         else {
180                 if (flags & TNY_HEADER_FLAG_HIGH_PRIORITY) 
181                         g_object_set (G_OBJECT (renderer), "pixbuf",
182                                       get_pixbuf_for_compact_flag (flags),
183                                       NULL);
184                 else if (flags & TNY_HEADER_FLAG_LOW_PRIORITY) 
185                         g_object_set (G_OBJECT (renderer), "pixbuf",
186                                       get_pixbuf_for_compact_flag (flags),
187                                       NULL);
188         }
189 }
190
191 void
192 _modest_header_view_header_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
193                   GtkTreeModel *tree_model,  GtkTreeIter *iter,  gpointer user_data)
194 {
195         TnyHeaderFlags flags;
196         
197         gtk_tree_model_get (tree_model, iter, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
198                             &flags, -1);
199         set_common_flags (renderer, flags);
200 }
201
202
203 void
204 _modest_header_view_date_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
205                                      GtkTreeModel *tree_model,  GtkTreeIter *iter,
206                                      gpointer user_data)
207 {
208         TnyHeaderFlags flags;
209         guint date, date_col;
210         gchar *display_date = NULL, *tmp_date = NULL;
211         gboolean received = GPOINTER_TO_INT(user_data);
212
213         if (received)
214                 date_col = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
215         else
216                 date_col = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
217
218         gtk_tree_model_get (tree_model, iter,
219                             TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
220                             date_col, &date,
221                             -1);
222
223         tmp_date = modest_text_utils_get_display_date (date);
224         display_date = g_strdup_printf ("\n<small>%s</small>", tmp_date);
225         g_object_set (G_OBJECT(renderer), "markup", display_date, NULL);        
226
227         set_common_flags (renderer, flags);
228         g_free (tmp_date);
229         g_free (display_date);
230 }
231
232
233 void
234 _modest_header_view_sender_receiver_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
235                             GtkTreeModel *tree_model,  GtkTreeIter *iter,  gboolean is_sender)
236 {
237         TnyHeaderFlags flags;
238         gchar *address;
239         gint sender_receiver_col;
240
241         if (is_sender)
242                 sender_receiver_col = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
243         else
244                 sender_receiver_col = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
245                 
246         gtk_tree_model_get (tree_model, iter,
247                             sender_receiver_col,  &address,
248                             TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
249                             -1);
250         
251         g_object_set (G_OBJECT(renderer),
252                       "text",
253                       modest_text_utils_get_display_address (address),
254                       NULL);
255         g_free (address);
256         set_common_flags (renderer, flags);
257 }
258 /*
259  * this for both incoming and outgoing mail, depending on the the user_data
260  * parameter. in the incoming case, show 'From' and 'Received date', in the
261  * outgoing case, show 'To' and 'Sent date'
262  */
263 void
264 _modest_header_view_compact_header_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
265                                                GtkTreeModel *tree_model,  GtkTreeIter *iter,  gpointer user_data)
266 {
267         GObject *rendobj;
268         TnyHeaderFlags flags;
269         gchar *address, *subject, *header;
270         time_t date;
271         gboolean is_incoming;
272
273         is_incoming = GPOINTER_TO_INT(user_data); /* GPOINTER_TO_BOOLEAN is not available
274                                                    * in older versions of glib...*/
275
276         if (is_incoming)
277                 gtk_tree_model_get (tree_model, iter,
278                                     TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
279                                     TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN,  &address,
280                                     TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN, &subject,
281                                     TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN, &date,   
282                                     -1);
283         else
284                 gtk_tree_model_get (tree_model, iter,
285                                     TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
286                                     TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN,  &address,
287                                     TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN, &subject,
288                                     TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &date,   
289                                     -1);
290         
291         rendobj = G_OBJECT(renderer);
292         if (flags & TNY_HEADER_FLAG_SEEN)
293                 header = g_strdup_printf ("<b>%s</b>\n<small>%s</small>",
294                                           subject,
295                                           modest_text_utils_get_display_address (address));
296         else
297                 header = g_strdup_printf ("<i>%s</i>\n<small>%s</small>",
298                                           subject,
299                                           modest_text_utils_get_display_address (address));
300         g_free (address);
301         g_free (subject);
302         
303         g_object_set (G_OBJECT(renderer), "markup", header, NULL);      
304 /*      set_common_flags (renderer, flags); */
305         
306         g_free (header);
307 }
308
309
310 void
311 _modest_header_view_size_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
312                                      GtkTreeModel *tree_model,  GtkTreeIter *iter,
313                                      gpointer user_data)
314 {
315         TnyHeaderFlags flags;
316         guint size;
317         gchar *size_str;
318         
319         gtk_tree_model_get (tree_model, iter,
320                            TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
321                            TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN, &size,
322                             -1);
323         
324         size_str = modest_text_utils_get_display_size (size);
325         
326         g_object_set (G_OBJECT(renderer), "text", size_str, NULL);
327         set_common_flags (renderer, flags);
328
329         g_free (size_str);
330  }
331
332 void
333 _modest_header_view_status_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
334                                      GtkTreeModel *tree_model,  GtkTreeIter *iter,
335                                      gpointer user_data)
336 {
337         TnyHeaderFlags flags;
338         guint status;
339         gchar *status_str;
340         
341         gtk_tree_model_get (tree_model, iter,
342                            TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
343                            TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN, &status,
344                             -1);
345         
346 /*      size_str = modest_text_utils_get_display_size (size); */
347         status_str = g_strdup(_("Wating ..."));
348         
349         g_object_set (G_OBJECT(renderer), "text", status_str, NULL);
350         set_common_flags (renderer, flags);
351
352         g_free (status_str);
353  }