Fixes NB#139032, remove the colons in folder details dialog. Use secondary
[modest] / src / widgets / modest-details-dialog.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-details-dialog.h"
31
32 #include <glib/gi18n.h>
33 #include <gdk/gdkkeysyms.h>
34 #include <gtk/gtkscrolledwindow.h>
35 #include <gtk/gtktable.h>
36 #include <gtk/gtkstock.h>
37 #include <gtk/gtklabel.h>
38 #include <tny-msg.h>
39 #include <tny-header.h>
40 #include <tny-header-view.h>
41 #include <tny-folder-store.h>
42 #include <modest-tny-folder.h>
43 #include <modest-tny-account.h>
44 #include <modest-text-utils.h>
45 #include <modest-datetime-formatter.h>
46 #include <string.h> /* for strlen */
47 #ifdef MODEST_TOOLKIT_HILDON2
48 #include <hildon/hildon-helper.h>
49 #endif
50
51 static void    modest_details_dialog_set_header_default          (ModestDetailsDialog *self,
52                                                                   TnyHeader *header,
53                                                                   gboolean get_size);
54
55 static void    modest_details_dialog_set_folder_default          (ModestDetailsDialog *self,
56                                                                   TnyFolder *foler);
57
58 static void    modest_details_dialog_set_message_size_default    (ModestDetailsDialog *self, 
59                                                                   guint message_size);
60
61 static void    modest_details_dialog_create_container_default    (ModestDetailsDialog *self);
62
63 static void    modest_details_dialog_add_data_default            (ModestDetailsDialog *self,
64                                                                   const gchar *label,
65                                                                   const gchar *value);
66
67
68 G_DEFINE_TYPE (ModestDetailsDialog, 
69                modest_details_dialog, 
70                GTK_TYPE_DIALOG);
71
72 #define MODEST_DETAILS_DIALOG_GET_PRIVATE(o) \
73         (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_DETAILS_DIALOG, ModestDetailsDialogPrivate))
74
75
76 typedef struct _ModestDetailsDialogPrivate ModestDetailsDialogPrivate;
77
78 struct _ModestDetailsDialogPrivate
79 {
80         GtkWidget *props_table;
81 };
82
83 static void
84 modest_details_dialog_finalize (GObject *object)
85 {
86         G_OBJECT_CLASS (modest_details_dialog_parent_class)->finalize (object);
87 }
88
89 static void
90 modest_details_dialog_class_init (ModestDetailsDialogClass *klass)
91 {
92         GObjectClass *object_class = G_OBJECT_CLASS (klass);
93
94         g_type_class_add_private (klass, sizeof (ModestDetailsDialogPrivate));
95         object_class->finalize = modest_details_dialog_finalize;
96
97         klass->create_container_func = modest_details_dialog_create_container_default;
98         klass->add_data_func = modest_details_dialog_add_data_default;
99         klass->set_header_func = modest_details_dialog_set_header_default;
100         klass->set_message_size_func = modest_details_dialog_set_message_size_default;
101         klass->set_folder_func = modest_details_dialog_set_folder_default;
102 }
103
104 static void
105 modest_details_dialog_init (ModestDetailsDialog *self)
106 {
107 }
108
109 GtkWidget*
110 modest_details_dialog_new_with_header (GtkWindow *parent, 
111                                        TnyHeader *header,
112                                        gboolean get_size)
113 {
114         ModestDetailsDialog *dialog;
115
116         g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
117         g_return_val_if_fail (TNY_IS_HEADER (header), NULL);
118
119         dialog = (ModestDetailsDialog *) (g_object_new (MODEST_TYPE_DETAILS_DIALOG, 
120                                                         "transient-for", parent, 
121                                                         NULL));
122
123         MODEST_DETAILS_DIALOG_GET_CLASS (dialog)->create_container_func (dialog);
124         MODEST_DETAILS_DIALOG_GET_CLASS (dialog)->set_header_func (dialog, header, get_size);
125
126         /* Add close button */
127         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_close"), GTK_RESPONSE_CLOSE);
128
129         return GTK_WIDGET (dialog);
130 }
131
132 GtkWidget* 
133 modest_details_dialog_new_with_folder  (GtkWindow *parent, 
134                                         TnyFolder *folder)
135 {
136         ModestDetailsDialog *dialog;
137
138         g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
139         g_return_val_if_fail (TNY_IS_FOLDER (folder), NULL);
140
141         dialog = (ModestDetailsDialog *) (g_object_new (MODEST_TYPE_DETAILS_DIALOG, 
142                                                         "transient-for", parent, 
143                                                         NULL));
144
145         MODEST_DETAILS_DIALOG_GET_CLASS (dialog)->create_container_func (dialog);
146         MODEST_DETAILS_DIALOG_GET_CLASS (dialog)->set_folder_func (dialog, folder);
147
148         /* Add close button */
149         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_close"), GTK_RESPONSE_CLOSE);
150
151         return GTK_WIDGET (dialog);
152 }
153
154 void
155 modest_details_dialog_add_data (ModestDetailsDialog *self,
156                                 const gchar *label,
157                                 const gchar *value)
158 {
159         MODEST_DETAILS_DIALOG_GET_CLASS (self)->add_data_func (self, label, value);
160 }
161
162 void
163 modest_details_dialog_set_message_size (ModestDetailsDialog *self,
164                                         guint size)
165 {
166         MODEST_DETAILS_DIALOG_GET_CLASS (self)->set_message_size_func (self, size);
167 }
168
169 static void
170 modest_details_dialog_add_data_default (ModestDetailsDialog *self,
171                                         const gchar *label,
172                                         const gchar *value)
173 {
174         ModestDetailsDialogPrivate *priv;
175         guint n_rows = 0;
176         GtkWidget *label_w, *value_w;
177         gchar *secure_value;
178
179         priv = MODEST_DETAILS_DIALOG_GET_PRIVATE (self);
180
181         g_object_get (G_OBJECT (priv->props_table), "n-rows", &n_rows,NULL);
182
183         /* Create label */
184         label_w = gtk_label_new (label);
185         gtk_misc_set_alignment (GTK_MISC (label_w), 0.0, 0.0);
186         gtk_label_set_justify (GTK_LABEL (label_w), GTK_JUSTIFY_LEFT);
187
188 #ifdef MODEST_TOOLKIT_HILDON2
189         hildon_helper_set_logical_color (label_w,
190                         GTK_RC_FG, GTK_STATE_NORMAL, "SecondaryTextColor");
191 #endif
192
193         /* Create secure value */
194         secure_value = modest_text_utils_get_secure_header (value, "");
195
196         /* Create value */
197         value_w = gtk_label_new (secure_value);
198         gtk_label_set_line_wrap ((GtkLabel *) value_w, TRUE);
199         gtk_label_set_line_wrap_mode ((GtkLabel *) value_w, PANGO_WRAP_WORD_CHAR);
200         gtk_misc_set_alignment (GTK_MISC (value_w), 0.0, 0.0);
201         gtk_label_set_justify ((GtkLabel *) value_w, GTK_JUSTIFY_LEFT);
202
203         /* Attach label and value */
204         gtk_table_attach (GTK_TABLE (priv->props_table), 
205                           label_w, 0, 1, 
206                           n_rows, n_rows + 1, 
207                           GTK_SHRINK|GTK_FILL, 
208                           GTK_SHRINK|GTK_FILL, 
209                           0, 0);
210         gtk_table_attach (GTK_TABLE (priv->props_table), 
211                           value_w, 1, 2, 
212                           n_rows, n_rows + 1, 
213                           GTK_EXPAND|GTK_FILL, 
214                           GTK_SHRINK|GTK_FILL, 
215                           0, 0);
216
217         g_free (secure_value);
218 }
219
220 static void 
221 replace_recipients (gchar **recipients)
222 {
223
224         gchar *result;
225
226         result = modest_text_utils_simplify_recipients (*recipients);
227
228         g_free (*recipients);
229         *recipients = result;
230 }
231
232 static void
233 modest_details_dialog_set_header_default (ModestDetailsDialog *self,
234                                           TnyHeader *header,
235                                           gboolean get_size)
236 {
237         gchar *from = NULL, *subject = NULL, *to = NULL, *cc = NULL, *bcc = NULL;
238         time_t received, sent;
239         guint size;
240         gchar *size_s;
241         TnyFolder *folder;
242         TnyFolderType folder_type;
243         ModestDatetimeFormatter *datetime_formatter;
244         const gchar *date_time_str;
245
246         datetime_formatter = modest_datetime_formatter_new ();
247
248         /* Set window title */
249         gtk_window_set_title (GTK_WINDOW (self), _("mcen_ti_message_properties"));
250
251         folder = tny_header_get_folder (header);
252         if (folder) {
253                 folder_type = modest_tny_folder_guess_folder_type (folder);
254                 g_object_unref (folder);
255         } else {
256                 folder_type = TNY_FOLDER_TYPE_NORMAL;
257         }
258
259         g_return_if_fail (folder_type != TNY_FOLDER_TYPE_INVALID);
260
261         /* Get header data */
262         from = tny_header_dup_from (header);
263         to = tny_header_dup_to (header);
264         subject = tny_header_dup_subject (header);
265         cc = tny_header_dup_cc (header);
266         bcc = tny_header_dup_bcc (header);
267         received = tny_header_get_date_received (header);
268         sent = tny_header_get_date_sent (header);
269         if (get_size) {
270                 size = tny_header_get_message_size (header);
271         } else {
272                 size = -1;
273         }
274
275         replace_recipients (&from);
276         replace_recipients (&to);
277         replace_recipients (&cc);
278         if (subject == NULL)
279                 subject = g_strdup ("");
280
281         if (!strcmp (subject, "")) {
282                 g_free (subject);
283                 subject = g_strdup (_("mail_va_no_subject"));
284         }
285
286         /* Add from and subject for all folders */
287         modest_details_dialog_add_data (self, _("mcen_fi_message_properties_from"), from);
288         modest_details_dialog_add_data (self, _("mcen_fi_message_properties_subject"), subject);
289
290
291         /* for inbox, user-created folders and archive: Received */
292         if (received && (folder_type != TNY_FOLDER_TYPE_SENT) &&
293             (folder_type != TNY_FOLDER_TYPE_DRAFTS) &&
294             (folder_type != TNY_FOLDER_TYPE_OUTBOX)) {
295                 date_time_str = modest_datetime_formatter_display_long_datetime (datetime_formatter, 
296                                                                             received);
297
298                 modest_details_dialog_add_data (self, _("mcen_fi_message_properties_received"),
299                                                 date_time_str);
300         }
301
302         /* for drafts (created) */
303         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
304                 date_time_str = modest_datetime_formatter_display_long_datetime (datetime_formatter, 
305                                                                             received);
306                 modest_details_dialog_add_data (self, _("mcen_fi_message_properties_created"),
307                                                 date_time_str);
308         }
309
310         /* for everyting except outbox, drafts: Sent */
311         if (sent && (folder_type != TNY_FOLDER_TYPE_DRAFTS)&&
312             (folder_type != TNY_FOLDER_TYPE_OUTBOX)) {
313                 
314                 date_time_str = modest_datetime_formatter_display_long_datetime (datetime_formatter, 
315                                                                             sent);
316                 modest_details_dialog_add_data (self, _("mcen_fi_message_properties_sent"),
317                                                 date_time_str);
318         }
319
320         /* Set To and CC */
321         modest_details_dialog_add_data (self, _("mcen_fi_message_properties_to"), to);
322
323         /* only show cc when it's there */
324         if (cc && strlen(cc) > 0)
325                 modest_details_dialog_add_data (self, _("mcen_fi_message_properties_cc"), cc);
326
327         /* only show cc when it's there */
328         if (bcc && strlen(bcc) > 0) {
329                 replace_recipients (&bcc);
330                 modest_details_dialog_add_data (self, _("mcen_fi_message_properties_bcc"), bcc);
331         }
332
333         /* Set size */
334         if (get_size) {
335                 size_s = modest_text_utils_get_display_size (size);
336                 modest_details_dialog_add_data (self, _("mcen_fi_message_properties_size"), size_s);
337                 g_free (size_s);
338         }
339
340         /* Frees */
341         g_object_unref (datetime_formatter);
342         g_free (to);
343         g_free (from);
344         g_free (subject);
345         g_free (cc);
346         g_free (bcc);
347 }
348
349 static void
350 modest_details_dialog_set_message_size_default (ModestDetailsDialog *self,
351                                                 guint size)
352 {
353         gchar *size_s;
354         size_s = modest_text_utils_get_display_size (size);
355         modest_details_dialog_add_data (self, _("mcen_fi_message_properties_size"), size_s);
356         g_free (size_s);
357         gtk_widget_show_all (GTK_WIDGET (self));
358 }
359
360 static void
361 modest_details_dialog_set_folder_default (ModestDetailsDialog *self,
362                                           TnyFolder *folder)
363 {
364         gchar *count_s, *size_s, *name = NULL;
365         guint size, count;
366
367         g_return_if_fail (folder && TNY_IS_FOLDER (folder));
368         g_return_if_fail (modest_tny_folder_guess_folder_type (folder)
369                           != TNY_FOLDER_TYPE_INVALID);
370
371         /* Set window title */
372         gtk_window_set_title (GTK_WINDOW (self), _("mcen_ti_folder_properties"));
373
374         /* Get data. We use our function because it's recursive */
375         count = tny_folder_get_all_count (TNY_FOLDER (folder));
376         size = tny_folder_get_local_size (TNY_FOLDER (folder));
377
378         /* Format count and size */
379         count_s = g_strdup_printf ("%d", count);
380         size_s = modest_text_utils_get_display_size (size);
381
382         /* Different names for the local folders */
383         if (modest_tny_folder_is_local_folder (folder) ||
384             modest_tny_folder_is_memory_card_folder (folder)) {
385                 gint type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
386                 if (type != TNY_FOLDER_TYPE_UNKNOWN)
387                         name = g_strdup(modest_local_folder_info_get_type_display_name (type));
388         }
389
390         if (!name) {
391                 if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX)
392                         name = g_strdup (_("mcen_me_folder_inbox"));
393                 else
394                         name = g_strdup (tny_folder_get_name (folder));
395         }
396
397 #ifdef MODEST_TOOLKIT_HILDON2
398         modest_details_dialog_add_data (self, _("mcen_fi_folder_properties_foldername"), name);
399 #else
400         gchar *tmp = g_strconcat (_("mcen_fi_folder_properties_foldername"), ":", NULL);
401         modest_details_dialog_add_data (self, tmp, name);
402         g_free (tmp);
403 #endif
404
405 #ifdef MODEST_TOOLKIT_HILDON2
406         modest_details_dialog_add_data (self, _("mcen_fi_folder_properties_messages"), count_s);
407 #else
408         gchar *tmp = g_strconcat (_("mcen_fi_folder_properties_messages"), ":", NULL);
409         modest_details_dialog_add_data (self, tmp, count_s);
410         g_free (tmp);
411 #endif
412
413 #ifdef MODEST_TOOLKIT_HILDON2
414         modest_details_dialog_add_data (self, _("mcen_fi_folder_properties_size"), size_s);
415 #else
416         gchar *tmp = g_strconcat (_("mcen_fi_folder_properties_size"), ":", NULL);
417         modest_details_dialog_add_data (self, tmp, size_s);
418         g_free (tmp);
419 #endif
420
421         /* Frees */
422         g_free (name);
423         g_free (size_s);
424         g_free (count_s);
425 }
426
427 static gboolean
428 on_key_press_event (GtkWindow *window, GdkEventKey *event, gpointer userdata)
429 {
430         GtkWidget *focused;
431
432         focused = gtk_window_get_focus (window);
433         if (GTK_IS_SCROLLED_WINDOW (focused)) {
434                 GtkAdjustment *vadj;
435                 gboolean return_value;
436
437                 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (focused));
438                 switch (event->keyval) {
439                 case GDK_Up:
440                 case GDK_KP_Up:
441                         if (vadj->value > 0.0) {
442                                 g_signal_emit_by_name (G_OBJECT (focused), "scroll-child", GTK_SCROLL_STEP_UP, FALSE, 
443                                                        &return_value);
444                                 return TRUE;
445                         }
446                         break;
447                 case GDK_Down:
448                 case GDK_KP_Down:
449                         if (vadj->value < vadj->upper - vadj->page_size) {
450                                 g_signal_emit_by_name (G_OBJECT (focused), "scroll-child", GTK_SCROLL_STEP_DOWN, FALSE, 
451                                                        &return_value);
452                                 return TRUE;
453                         }
454                         break;
455                 }
456         }
457
458         return FALSE;
459 }
460
461 static void
462 modest_details_dialog_create_container_default (ModestDetailsDialog *self)
463 {
464         ModestDetailsDialogPrivate *priv;
465         GtkWidget *scrollbar;
466
467         priv = MODEST_DETAILS_DIALOG_GET_PRIVATE (self);
468         scrollbar = gtk_scrolled_window_new (NULL, NULL);
469
470         gtk_window_set_default_size (GTK_WINDOW (self), 400, 220);
471
472         priv->props_table = gtk_table_new (0, 2, FALSE);
473         gtk_table_set_col_spacings (GTK_TABLE (priv->props_table), 12);
474         gtk_table_set_row_spacings (GTK_TABLE (priv->props_table), 1);
475         gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrollbar), priv->props_table);
476         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
477         gtk_container_set_focus_vadjustment (GTK_CONTAINER (priv->props_table), 
478                                              gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrollbar)));
479         gtk_container_add (GTK_CONTAINER (GTK_DIALOG (self)->vbox), scrollbar);
480
481         gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE);
482
483         g_signal_connect (self, "key-press-event", G_CALLBACK (on_key_press_event), self);
484 }