* Use strftime function instead of GDate to build string
[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 gchar *
40 _pango_parse_string (const gchar *string) {
41         gchar **tmp = NULL;     
42         gchar *parsed_string = NULL;
43         gchar *tmp_string = NULL;
44         guint i = 0;
45
46         tmp = g_strsplit(string, "&", 0);
47         parsed_string = g_strdup(tmp[i]);
48         for (i = 1; tmp[i] != NULL; i++) {
49                 tmp_string = g_strconcat (parsed_string, "&amp;", tmp[i], NULL);
50                 g_free(parsed_string);
51                 parsed_string = g_strdup(tmp_string);
52         } 
53
54         return parsed_string;
55 }
56
57
58 static GdkPixbuf*
59 get_pixbuf_for_flag (TnyHeaderFlags flag)
60 {
61         /* optimization */
62         static GdkPixbuf *deleted_pixbuf          = NULL;
63         static GdkPixbuf *seen_pixbuf             = NULL;
64         static GdkPixbuf *unread_pixbuf           = NULL;
65         static GdkPixbuf *attachments_pixbuf      = NULL;
66         
67         switch (flag) {
68         case TNY_HEADER_FLAG_DELETED:
69                 if (G_UNLIKELY(!deleted_pixbuf))
70                         deleted_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_DELETED);
71                 return deleted_pixbuf;
72         case TNY_HEADER_FLAG_SEEN:
73                 if (G_UNLIKELY(!seen_pixbuf))
74                         seen_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_READ);
75                 return seen_pixbuf;
76         case TNY_HEADER_FLAG_ATTACHMENTS:
77                 if (G_UNLIKELY(!attachments_pixbuf))
78                         attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH);
79                 return attachments_pixbuf;
80         default:
81                 if (G_UNLIKELY(!unread_pixbuf))
82                         unread_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_UNREAD);
83                 return unread_pixbuf;
84         }
85 }
86
87 static GdkPixbuf*
88 get_pixbuf_for_compact_flag (TnyHeaderFlags flags)
89 {
90         /* optimization */
91         static GdkPixbuf *high_attachments_pixbuf   = NULL;
92         static GdkPixbuf *normal_attachments_pixbuf = NULL;
93         static GdkPixbuf *low_attachments_pixbuf    = NULL;
94         static GdkPixbuf *high_pixbuf               = NULL;
95         static GdkPixbuf *low_pixbuf                = NULL;
96         
97         if (flags & TNY_HEADER_FLAG_ATTACHMENTS) {
98                 if (flags & TNY_HEADER_FLAG_HIGH_PRIORITY) {
99                         if (G_UNLIKELY(!high_attachments_pixbuf))
100                                 high_attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH_HIGH_PRIORITY);
101                         return high_attachments_pixbuf;
102                 }
103                 else if (flags & TNY_HEADER_FLAG_LOW_PRIORITY) {
104                         if (G_UNLIKELY(!low_attachments_pixbuf))
105                                 low_attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH_LOW_PRIORITY);
106                         return low_attachments_pixbuf;
107                 }
108                 else {
109                         if (G_UNLIKELY(!normal_attachments_pixbuf))
110                                 normal_attachments_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_ATTACH_NORM_PRIORITY);
111                         return normal_attachments_pixbuf;
112                 }
113         }
114         else if (flags & TNY_HEADER_FLAG_HIGH_PRIORITY) {
115                 if (G_UNLIKELY(!high_pixbuf))
116                         high_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_HIGH_PRIORITY);
117                 return high_pixbuf;
118         }
119         else if (flags & TNY_HEADER_FLAG_LOW_PRIORITY) {
120                 if (G_UNLIKELY(!low_pixbuf))
121                         low_pixbuf = modest_platform_get_icon (MODEST_HEADER_ICON_LOW_PRIORITY);
122                 return low_pixbuf;
123         }
124
125         
126         return NULL;
127 }
128
129 static void
130 set_common_flags (GtkCellRenderer *renderer, TnyHeaderFlags flags)
131 {
132         g_object_set (G_OBJECT(renderer),
133                       "weight", (flags & TNY_HEADER_FLAG_SEEN) ? PANGO_WEIGHT_NORMAL: PANGO_WEIGHT_ULTRABOLD,
134                       "strikethrough",  (flags & TNY_HEADER_FLAG_DELETED) ?  TRUE:FALSE,
135                       NULL);    
136 }
137
138
139 void
140 _modest_header_view_msgtype_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
141                    GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data)
142 {
143         TnyHeaderFlags flags;
144                 
145         gtk_tree_model_get (tree_model, iter, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
146                             &flags, -1);
147
148         if (flags & TNY_HEADER_FLAG_DELETED)
149                 g_object_set (G_OBJECT (renderer), "pixbuf",
150                               get_pixbuf_for_flag (TNY_HEADER_FLAG_DELETED), NULL);           
151         else if (flags & TNY_HEADER_FLAG_SEEN)
152                 g_object_set (G_OBJECT (renderer), "pixbuf",
153                               get_pixbuf_for_flag (TNY_HEADER_FLAG_SEEN), NULL);              
154         else 
155                 g_object_set (G_OBJECT (renderer), "pixbuf",
156                               get_pixbuf_for_flag (0), NULL); /* ughh, FIXME */               
157 }
158
159 void
160 _modest_header_view_attach_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
161                                       GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data)
162 {
163         TnyHeaderFlags flags;
164
165         gtk_tree_model_get (tree_model, iter, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
166                             &flags, -1);
167
168         if (flags & TNY_HEADER_FLAG_ATTACHMENTS)
169                 g_object_set (G_OBJECT (renderer), "pixbuf",
170                               get_pixbuf_for_flag (TNY_HEADER_FLAG_ATTACHMENTS),
171                               NULL);
172 }
173
174 void
175 _modest_header_view_compact_flag_cell_data (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
176                                             GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer user_data)
177 {
178         TnyHeaderFlags flags;
179
180         gtk_tree_model_get (tree_model, iter, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
181                             &flags, -1);
182
183         if (flags & TNY_HEADER_FLAG_ATTACHMENTS) {
184                 if (flags & TNY_HEADER_FLAG_HIGH_PRIORITY) 
185                         g_object_set (G_OBJECT (renderer), "pixbuf",
186                                       get_pixbuf_for_compact_flag (flags),
187                                       NULL);
188                 else if (flags & TNY_HEADER_FLAG_LOW_PRIORITY) 
189                         g_object_set (G_OBJECT (renderer), "pixbuf",
190                                       get_pixbuf_for_compact_flag (flags),                                    
191                                       NULL);
192                 else  
193                         g_object_set (G_OBJECT (renderer), "pixbuf",
194                                       get_pixbuf_for_compact_flag (flags),    
195                                       NULL);
196         }
197         else {
198                 if (flags & TNY_HEADER_FLAG_HIGH_PRIORITY) 
199                         g_object_set (G_OBJECT (renderer), "pixbuf",
200                                       get_pixbuf_for_compact_flag (flags),
201                                       NULL);
202                 else if (flags & TNY_HEADER_FLAG_LOW_PRIORITY) 
203                         g_object_set (G_OBJECT (renderer), "pixbuf",
204                                       get_pixbuf_for_compact_flag (flags),
205                                       NULL);
206         }
207 }
208
209 void
210 _modest_header_view_header_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
211                   GtkTreeModel *tree_model,  GtkTreeIter *iter,  gpointer user_data)
212 {
213         TnyHeaderFlags flags;
214         
215         gtk_tree_model_get (tree_model, iter, TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN,
216                             &flags, -1);
217         set_common_flags (renderer, flags);
218 }
219
220
221 void
222 _modest_header_view_date_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
223                                      GtkTreeModel *tree_model,  GtkTreeIter *iter,
224                                      gpointer user_data)
225 {
226         TnyHeaderFlags flags;
227         guint date, date_col;
228         gchar *display_date = NULL, *tmp_date = NULL;
229         gboolean received = GPOINTER_TO_INT(user_data);
230
231         if (received)
232                 date_col = TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN;
233         else
234                 date_col = TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN;
235
236         gtk_tree_model_get (tree_model, iter,
237                             TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
238                             date_col, &date,
239                             -1);
240
241         tmp_date = modest_text_utils_get_display_date (date);
242         display_date = g_strdup_printf ("\n<small>%s</small>", tmp_date);
243         g_object_set (G_OBJECT(renderer), "markup", display_date, NULL);        
244
245         set_common_flags (renderer, flags);
246         g_free (tmp_date);
247         g_free (display_date);
248 }
249
250
251 void
252 _modest_header_view_sender_receiver_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
253                             GtkTreeModel *tree_model,  GtkTreeIter *iter,  gboolean is_sender)
254 {
255         TnyHeaderFlags flags;
256         gchar *address;
257         gint sender_receiver_col;
258
259         if (is_sender)
260                 sender_receiver_col = TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN;
261         else
262                 sender_receiver_col = TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN;
263                 
264         gtk_tree_model_get (tree_model, iter,
265                             sender_receiver_col,  &address,
266                             TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
267                             -1);
268         
269         g_object_set (G_OBJECT(renderer),
270                       "text",
271                       modest_text_utils_get_display_address (address),
272                       NULL);
273         g_free (address);
274         set_common_flags (renderer, flags);
275 }
276 /*
277  * this for both incoming and outgoing mail, depending on the the user_data
278  * parameter. in the incoming case, show 'From' and 'Received date', in the
279  * outgoing case, show 'To' and 'Sent date'
280  */
281 void
282 _modest_header_view_compact_header_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
283                                                GtkTreeModel *tree_model,  GtkTreeIter *iter,  gpointer user_data)
284 {
285         GObject *rendobj;
286         TnyHeaderFlags flags;
287         gchar *address, *subject, *header, *display_address;
288         gchar *parsed_address, *parsed_subject;
289         time_t date;
290         gboolean is_incoming;
291
292         is_incoming = GPOINTER_TO_INT(user_data); /* GPOINTER_TO_BOOLEAN is not available
293                                                    * in older versions of glib...*/
294
295         if (is_incoming)
296                 gtk_tree_model_get (tree_model, iter,
297                                     TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
298                                     TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN,  &address,
299                                     TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN, &subject,
300                                     TNY_GTK_HEADER_LIST_MODEL_DATE_RECEIVED_TIME_T_COLUMN, &date,   
301                                     -1);
302         else
303                 gtk_tree_model_get (tree_model, iter,
304                                     TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
305                                     TNY_GTK_HEADER_LIST_MODEL_TO_COLUMN,  &address,
306                                     TNY_GTK_HEADER_LIST_MODEL_SUBJECT_COLUMN, &subject,
307                                     TNY_GTK_HEADER_LIST_MODEL_DATE_SENT_TIME_T_COLUMN, &date,   
308                                     -1);
309         
310         rendobj = G_OBJECT(renderer);
311         
312         /* Escape special characteres to allow pango makup`*/
313         display_address = modest_text_utils_get_display_address (address);
314         parsed_address = _pango_parse_string (display_address);
315         parsed_subject = _pango_parse_string (subject);
316
317         header = g_strdup_printf ("%s\n<small>%s</small>",
318                                   parsed_subject,
319                                   parsed_address);
320         g_free (address);
321         g_free (subject);
322         g_free(parsed_subject);
323         g_free(parsed_address);
324
325         g_object_set (rendobj, "markup", header, NULL); 
326         set_common_flags (renderer, flags);
327         
328         g_free (header);
329 }
330
331
332 void
333 _modest_header_view_size_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
334                                      GtkTreeModel *tree_model,  GtkTreeIter *iter,
335                                      gpointer user_data)
336 {
337         TnyHeaderFlags flags;
338         guint size;
339         gchar *size_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, &size,
344                             -1);
345         
346         size_str = modest_text_utils_get_display_size (size);
347         
348         g_object_set (G_OBJECT(renderer), "text", size_str, NULL);
349         set_common_flags (renderer, flags);
350
351         g_free (size_str);
352  }
353
354 void
355 _modest_header_view_status_cell_data  (GtkTreeViewColumn *column,  GtkCellRenderer *renderer,
356                                      GtkTreeModel *tree_model,  GtkTreeIter *iter,
357                                      gpointer user_data)
358 {
359         TnyHeaderFlags flags;
360         guint status;
361         gchar *status_str;
362         
363         gtk_tree_model_get (tree_model, iter,
364                            TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
365                            TNY_GTK_HEADER_LIST_MODEL_MESSAGE_SIZE_COLUMN, &status,
366                             -1);
367         
368 /*      size_str = modest_text_utils_get_display_size (size); */
369         status_str = g_strdup(_("Wating ..."));
370         
371         g_object_set (G_OBJECT(renderer), "text", status_str, NULL);
372         set_common_flags (renderer, flags);
373
374         g_free (status_str);
375  }
376