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