Some fixes in datetime formatter
[modest] / src / modest-datetime-formatter.c
1 /* Copyright (c) 2008, 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 <config.h>
31 #include <modest-datetime-formatter.h>
32 #ifdef MODEST_TOOLKIT_HILDON2
33 #include <gconf/gconf-client.h>
34 #include <glib/gi18n.h>
35 #include <modest-text-utils.h>
36 #include <gtk/gtkmarshal.h>
37 #endif
38
39 typedef enum {
40         DATETIME_FORMAT_12H,
41         DATETIME_FORMAT_24H,
42         DATETIME_FORMAT_LOCALE,
43 } DatetimeFormat;
44
45 #define HILDON2_GCONF_FORMAT_KEY "/apps/clock/time-format"
46
47 /* 'private'/'protected' functions */
48 static void   modest_datetime_formatter_class_init (ModestDatetimeFormatterClass *klass);
49 static void   modest_datetime_formatter_finalize   (GObject *obj);
50 static void   modest_datetime_formatter_instance_init (ModestDatetimeFormatter *obj);
51
52 typedef struct _ModestDatetimeFormatterPrivate ModestDatetimeFormatterPrivate;
53 struct _ModestDatetimeFormatterPrivate {
54         DatetimeFormat current_format;
55 #ifdef MODEST_TOOLKIT_HILDON2
56         guint gconf_handler;
57 #endif
58 };
59
60 #define MODEST_DATETIME_FORMATTER_GET_PRIVATE(o)     (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
61                                                                                    MODEST_TYPE_DATETIME_FORMATTER, \
62                                                                                    ModestDatetimeFormatterPrivate))
63
64 enum {
65         FORMAT_CHANGED_SIGNAL,
66         LAST_SIGNAL
67 };
68
69 /* globals */
70 static GObjectClass *parent_class = NULL;
71
72 static guint signals[LAST_SIGNAL] = {0};
73
74 GType
75 modest_datetime_formatter_get_type (void)
76 {
77         static GType my_type = 0;
78
79         if (!my_type) {
80                 static const GTypeInfo my_info = {
81                         sizeof(ModestDatetimeFormatterClass),
82                         NULL,   /* base init */
83                         NULL,   /* base finalize */
84                         (GClassInitFunc) modest_datetime_formatter_class_init,
85                         NULL,   /* class finalize */
86                         NULL,   /* class data */
87                         sizeof(ModestDatetimeFormatter),
88                         0,      /* n_preallocs */
89                         (GInstanceInitFunc) modest_datetime_formatter_instance_init,
90                         NULL
91                 };
92
93                 my_type = g_type_register_static (G_TYPE_OBJECT,
94                                                   "ModestDatetimeFormatter",
95                                                   &my_info, 0);
96         }
97         return my_type;
98 }
99
100 static void
101 modest_datetime_formatter_class_init (ModestDatetimeFormatterClass *klass)
102 {
103         GObjectClass *gobject_class;
104         gobject_class = (GObjectClass *) klass;
105
106         parent_class = g_type_class_peek_parent (klass);
107         gobject_class->finalize = modest_datetime_formatter_finalize;
108
109         g_type_class_add_private (gobject_class,
110                                   sizeof(ModestDatetimeFormatterPrivate));
111
112         signals[FORMAT_CHANGED_SIGNAL] =
113                 g_signal_new ("format_changed",
114                               G_TYPE_FROM_CLASS (gobject_class),
115                               G_SIGNAL_RUN_FIRST,
116                               G_STRUCT_OFFSET (ModestDatetimeFormatterClass, format_changed),
117                               NULL, NULL,
118                               gtk_marshal_VOID__VOID,
119                               G_TYPE_NONE, 0);
120 }
121
122 #ifdef MODEST_TOOLKIT_HILDON2
123 static void
124 update_format (ModestDatetimeFormatter *obj)
125 {
126         GConfClient *gconf;
127         GError *err = NULL;
128         gboolean gconf_value;
129         ModestDatetimeFormatterPrivate *priv;
130
131         priv = MODEST_DATETIME_FORMATTER_GET_PRIVATE (obj);
132
133         gconf = gconf_client_get_default ();
134         gconf_value = gconf_client_get_bool (gconf, HILDON2_GCONF_FORMAT_KEY,
135                                              &err);
136
137         if (err != NULL) {
138                 g_warning ("Error reading time format in gconf %s", err->message);
139                 g_error_free (err);
140         } else {
141                 priv->current_format = gconf_value?DATETIME_FORMAT_24H:DATETIME_FORMAT_12H;
142         }
143 }
144
145 static void
146 clock_format_changed (GConfClient *gconf,
147                       guint cnxn_id,
148                       GConfEntry *entry,
149                       gpointer userdata)
150 {
151         ModestDatetimeFormatter *self = (ModestDatetimeFormatter *) userdata;
152
153         update_format (self);
154         g_signal_emit (G_OBJECT (self), signals[FORMAT_CHANGED_SIGNAL], 0);
155 }
156 #endif
157
158 static void
159 init_format (ModestDatetimeFormatter *obj)
160 {
161         ModestDatetimeFormatterPrivate *priv;
162
163         priv = MODEST_DATETIME_FORMATTER_GET_PRIVATE (obj);
164
165         priv->current_format = DATETIME_FORMAT_LOCALE;
166
167 #ifdef MODEST_TOOLKIT_HILDON2
168         GConfClient *gconf;
169         GError *err = NULL;
170
171         gconf = gconf_client_get_default ();
172         priv->gconf_handler = gconf_client_notify_add (gconf, HILDON2_GCONF_FORMAT_KEY,
173                                                        clock_format_changed, (gpointer) obj,
174                                                        NULL, &err);
175
176         if (err != NULL) {
177                 g_warning ("Error listening to time format in gconf %s", err->message);
178                 g_error_free (err);
179         }
180         update_format (obj);
181 #endif
182 }
183
184 static void
185 modest_datetime_formatter_instance_init (ModestDatetimeFormatter *obj)
186 {
187         ModestDatetimeFormatterPrivate *priv;
188
189         priv = MODEST_DATETIME_FORMATTER_GET_PRIVATE (obj);
190
191         init_format (obj);
192 }
193
194 static void   
195 modest_datetime_formatter_finalize   (GObject *obj)
196 {
197 #ifdef MODEST_TOOLKIT_HILDON2
198         ModestDatetimeFormatterPrivate *priv;
199
200         priv = MODEST_DATETIME_FORMATTER_GET_PRIVATE (obj);
201         gconf_client_notify_remove (gconf_client_get_default (),
202                                     priv->gconf_handler);
203         priv->gconf_handler = 0;
204 #endif
205         G_OBJECT_CLASS (parent_class)->finalize (obj);
206 }
207
208 ModestDatetimeFormatter*
209 modest_datetime_formatter_new (void)
210 {
211         return g_object_new (MODEST_TYPE_DATETIME_FORMATTER, NULL);
212 }
213
214 const gchar *
215 modest_datetime_formatter_format_date (ModestDatetimeFormatter *self,
216                                        time_t date)
217 {
218 #define DATE_BUF_SIZE 64 
219
220         static gchar date_buf[DATE_BUF_SIZE];
221         ModestDatetimeFormatterPrivate *priv;
222         const gchar *format_string = NULL;
223
224         g_return_val_if_fail (MODEST_IS_DATETIME_FORMATTER (self), NULL);
225         priv = MODEST_DATETIME_FORMATTER_GET_PRIVATE (self);
226
227         switch (priv->current_format) {
228         case DATETIME_FORMAT_12H:
229         case DATETIME_FORMAT_24H:
230                 format_string = _HL("wdgt_va_date");
231                 break;
232         case DATETIME_FORMAT_LOCALE:
233                 format_string = "%x";
234                 break;
235         }
236         modest_text_utils_strftime (date_buf, DATE_BUF_SIZE, format_string, date);
237
238         return date_buf;
239 }
240
241 const gchar *
242 modest_datetime_formatter_format_time (ModestDatetimeFormatter *self,
243                                        time_t date)
244 {
245 #define DATE_BUF_SIZE 64 
246
247         static gchar date_buf[DATE_BUF_SIZE];
248         ModestDatetimeFormatterPrivate *priv;
249         const gchar *format_string = NULL;
250         gboolean is_pm;
251
252         g_return_val_if_fail (MODEST_IS_DATETIME_FORMATTER (self), NULL);
253         priv = MODEST_DATETIME_FORMATTER_GET_PRIVATE (self);
254
255         is_pm = (date / (60 * 60 * 12)) % 2;
256
257         switch (priv->current_format) {
258         case DATETIME_FORMAT_12H:
259                 format_string = is_pm?_HL("wdgt_12h_time_pm"):_HL("wdgt_12h_time_am");
260                 break;
261         case DATETIME_FORMAT_24H:
262                 format_string = _HL("wdgt_va_24h_time");
263                 break;
264         case DATETIME_FORMAT_LOCALE:
265                 format_string = "%X";
266                 break;
267         }
268         modest_text_utils_strftime (date_buf, DATE_BUF_SIZE, format_string, date);
269
270         return date_buf;
271 }
272
273 const gchar *
274 modest_datetime_formatter_display_datetime (ModestDatetimeFormatter *self,
275                                             time_t date)
276 {
277
278         int day = time (NULL) / (24*60*60);
279         int date_day = date / (24*60*60);
280
281         if (day == date_day)
282                 return modest_datetime_formatter_format_time (self, date);
283         else
284                 return modest_datetime_formatter_format_date (self, date);
285 }