e64d3752e726a8d89b411f904774544773371811
[hildon] / hildon / hildon-time-selector.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2005, 2008 Nokia Corporation.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version. or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 /**
22  * SECTION:hildon-time-selector
23  * @short_description: A widget to select the current time.
24  *
25  * #HildonTimeSelector allows users to choose a time by selecting hour
26  * and minute. It also allows choosing between AM or PM format.
27  *
28  * The currently selected time can be altered with
29  * hildon_time_selector_set_time(), and retrieved using
30  * hildon_time_selector_get_time().
31  *
32  * Use this widget instead of deprecated HildonTimeEditor widget.
33  */
34
35 #define _GNU_SOURCE     /* needed for GNU nl_langinfo_l */
36 #define __USE_GNU       /* needed for locale */
37
38 #ifdef HAVE_SYS_TIME_H
39 #include <sys/time.h>
40 #endif
41
42 #include <string.h>
43 #include <stdlib.h>
44 #include <libintl.h>
45 #include <time.h>
46 #include <langinfo.h>
47 #include <locale.h>
48 #include <gconf/gconf-client.h>
49
50 #include "hildon-enum-types.h"
51 #include "hildon-time-selector.h"
52 #include "hildon-touch-selector-private.h"
53
54 #define HILDON_TIME_SELECTOR_GET_PRIVATE(obj)                           \
55   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TIME_SELECTOR, HildonTimeSelectorPrivate))
56
57 G_DEFINE_TYPE (HildonTimeSelector, hildon_time_selector, HILDON_TYPE_TOUCH_SELECTOR)
58
59 #define INIT_YEAR 100
60 #define LAST_YEAR 50    /* since current year */
61
62 #define _(String)  dgettext("hildon-libs", String)
63 #define N_(String) String
64
65
66 /* FIXME: we should get this two props from the clock ui headers */
67 #define CLOCK_GCONF_PATH "/apps/clock"
68 #define CLOCK_GCONF_IS_24H_FORMAT CLOCK_GCONF_PATH  "/time-format"
69
70 enum {
71   COLUMN_STRING,
72   COLUMN_INT,
73   TOTAL_MODEL_COLUMNS
74 };
75
76 enum {
77   COLUMN_HOURS = 0,
78   COLUMN_MINUTES,
79   COLUMN_AMPM,
80   TOTAL_TIME_COLUMNS
81 };
82
83 enum
84 {
85   PROP_0,
86   PROP_MINUTES_STEP,
87   PROP_TIME_FORMAT_POLICY
88 };
89
90 struct _HildonTimeSelectorPrivate
91 {
92   GtkTreeModel *hours_model;
93   GtkTreeModel *minutes_model;
94   GtkTreeModel *ampm_model;
95
96   guint minutes_step;
97   HildonTimeSelectorFormatPolicy format_policy;
98   gboolean ampm_format;         /* if using am/pm format or 24 h one */
99
100   gboolean pm;                  /* if we are on pm (only useful if ampm_format == TRUE) */
101
102   gint creation_hours;
103   gint creation_minutes;
104 };
105
106 static void hildon_time_selector_finalize (GObject * object);
107 static GObject* hildon_time_selector_constructor (GType type,
108                                                   guint n_construct_properties,
109                                                   GObjectConstructParam *construct_params);
110 static void hildon_time_selector_get_property (GObject *object,
111                                                guint param_id,
112                                                GValue *value,
113                                                GParamSpec *pspec);
114 static void hildon_time_selector_set_property (GObject *object,
115                                                guint param_id,
116                                                const GValue *value,
117                                                GParamSpec *pspec);
118
119 /* private functions */
120 static GtkTreeModel *_create_hours_model (HildonTimeSelector * selector);
121 static GtkTreeModel *_create_minutes_model (guint minutes_step);
122 static GtkTreeModel *_create_ampm_model (HildonTimeSelector * selector);
123
124 static void _get_real_time (gint * hours, gint * minutes);
125 static void _manage_ampm_selection_cb (HildonTouchSelector * selector,
126                                        gint num_column, gpointer data);
127 static void _set_pm (HildonTimeSelector * selector, gboolean pm);
128
129 static gchar *_custom_print_func (HildonTouchSelector * selector,
130                                   gpointer user_data);
131
132 static void
133 check_automatic_ampm_format                     (HildonTimeSelector * selector);
134
135 static void
136 update_format_policy                            (HildonTimeSelector *selector,
137                                                  HildonTimeSelectorFormatPolicy new_policy);
138 static void
139 update_format_dependant_columns                 (HildonTimeSelector *selector,
140                                                  guint hours,
141                                                  guint minutes);
142
143 static void
144 hildon_time_selector_class_init (HildonTimeSelectorClass * class)
145 {
146   GObjectClass *gobject_class;
147   GtkObjectClass *object_class;
148   GtkWidgetClass *widget_class;
149   GtkContainerClass *container_class;
150
151   gobject_class = (GObjectClass *) class;
152   object_class = (GtkObjectClass *) class;
153   widget_class = (GtkWidgetClass *) class;
154   container_class = (GtkContainerClass *) class;
155
156   /* GObject */
157   gobject_class->get_property = hildon_time_selector_get_property;
158   gobject_class->set_property = hildon_time_selector_set_property;
159   gobject_class->constructor = hildon_time_selector_constructor;
160   gobject_class->finalize = hildon_time_selector_finalize;
161
162   g_object_class_install_property (gobject_class,
163                                    PROP_MINUTES_STEP,
164                                    g_param_spec_uint ("minutes-step",
165                                                       "Step between minutes in the model",
166                                                       "Step between the minutes in the list of"
167                                                       " options of the widget ",
168                                                       1, 30, 1,
169                                                       G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
170
171   /**
172    * HildonTimeSelector:time-format-policy:
173    *
174    * The visual policy of the time format
175    *
176    * Since: 2.2
177    */
178   g_object_class_install_property (gobject_class,
179                                    PROP_TIME_FORMAT_POLICY,
180                                    g_param_spec_enum ("time_format_policy",
181                                                       "time format policy",
182                                                       "Visual policy of the time format",
183                                                       HILDON_TYPE_TIME_SELECTOR_FORMAT_POLICY,
184                                                       HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC,
185                                                       G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
186
187   /* GtkWidget */
188
189   /* GtkContainer */
190
191   /* signals */
192
193   g_type_class_add_private (object_class, sizeof (HildonTimeSelectorPrivate));
194 }
195
196 /* FIXME: the constructor was required because as we need the initial values
197    of the properties passed on g_object_new. But, probably use the method
198    constructed could be easier */
199 static GObject*
200 hildon_time_selector_constructor (GType type,
201                                   guint n_construct_properties,
202                                   GObjectConstructParam *construct_params)
203 {
204   GObject *object;
205   HildonTimeSelector *selector;
206   HildonTouchSelectorColumn *column;
207
208   object = (* G_OBJECT_CLASS (hildon_time_selector_parent_class)->constructor)
209     (type, n_construct_properties, construct_params);
210
211   selector = HILDON_TIME_SELECTOR (object);
212
213   selector->priv->hours_model = _create_hours_model (selector);
214
215   column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
216                                                      selector->priv->hours_model, TRUE);
217   hildon_touch_selector_column_set_text_column (column, 0);
218
219   /* we need initialization parameters in order to create minute models*/
220   selector->priv->minutes_step = selector->priv->minutes_step ? selector->priv->minutes_step : 1;
221
222   selector->priv->minutes_model = _create_minutes_model (selector->priv->minutes_step);
223
224   column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
225                                                      selector->priv->minutes_model, TRUE);
226   hildon_touch_selector_column_set_text_column (column, 0);
227
228   if (selector->priv->ampm_format) {
229     selector->priv->ampm_model = _create_ampm_model (selector);
230
231     hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
232                                               selector->priv->ampm_model, TRUE);
233
234     g_signal_connect (G_OBJECT (selector),
235                       "changed", G_CALLBACK (_manage_ampm_selection_cb),
236                       NULL);
237   }
238
239
240   /* By default we should select the current day */
241   hildon_time_selector_set_time (selector,
242                                  selector->priv->creation_hours,
243                                  selector->priv->creation_minutes);
244
245   return object;
246
247 }
248
249 static void
250 hildon_time_selector_init (HildonTimeSelector * selector)
251 {
252   selector->priv = HILDON_TIME_SELECTOR_GET_PRIVATE (selector);
253
254   GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW);
255   gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE);
256
257   hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (selector),
258                                         _custom_print_func);
259
260   /* By default we use the automatic ampm format */
261   selector->priv->pm = TRUE;
262   check_automatic_ampm_format (selector);
263
264   _get_real_time (&selector->priv->creation_hours,
265                   &selector->priv->creation_minutes);
266 }
267
268 static void
269 hildon_time_selector_get_property (GObject *object,
270                                    guint param_id,
271                                    GValue *value,
272                                    GParamSpec *pspec)
273 {
274   HildonTimeSelectorPrivate *priv = HILDON_TIME_SELECTOR_GET_PRIVATE (object);
275
276   switch (param_id)
277     {
278     case PROP_MINUTES_STEP:
279       g_value_set_uint (value, priv->minutes_step);
280       break;
281     case PROP_TIME_FORMAT_POLICY:
282       g_value_set_enum (value, priv->format_policy);
283       break;
284     default:
285       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
286       break;
287     }
288 }
289
290 static void
291 hildon_time_selector_set_property (GObject *object,
292                                    guint param_id,
293                                    const GValue *value,
294                                    GParamSpec *pspec)
295 {
296   HildonTimeSelectorPrivate *priv = HILDON_TIME_SELECTOR_GET_PRIVATE (object);
297
298   switch (param_id)
299     {
300     case PROP_MINUTES_STEP:
301       priv->minutes_step = g_value_get_uint (value);
302       break;
303     case PROP_TIME_FORMAT_POLICY:
304       update_format_policy (HILDON_TIME_SELECTOR (object),
305                             g_value_get_enum (value));
306       break;
307     default:
308       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
309       break;
310     }
311 }
312
313 static void
314 hildon_time_selector_finalize (GObject * object)
315 {
316   /* Note: we don't require to free the models. We don't manage it using own
317      references, so will be freed on the hildon-touch-selector finalize code.
318      See the implementation notes related to that on the touch selector
319      code. */
320
321   (*G_OBJECT_CLASS (hildon_time_selector_parent_class)->finalize) (object);
322 }
323
324 /* ------------------------------ PRIVATE METHODS ---------------------------- */
325
326 static gchar *
327 _custom_print_func (HildonTouchSelector * touch_selector,
328                     gpointer user_data)
329 {
330   gchar *result = NULL;
331   struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
332   HildonTimeSelector *selector = NULL;
333   static gchar string[255];
334   guint hours = 0;
335   guint minutes = 0;
336
337   selector = HILDON_TIME_SELECTOR (touch_selector);
338
339   hildon_time_selector_get_time (selector, &hours, &minutes);
340
341   tm.tm_min = minutes;
342   tm.tm_hour = hours;
343
344   if (selector->priv->ampm_format) {
345     if (selector->priv->pm) {
346       strftime (string, 255, _("wdgt_va_12h_time_pm"), &tm);
347     } else {
348       strftime (string, 255, _("wdgt_va_12h_time_am"), &tm);
349     }
350   } else {
351     strftime (string, 255, _("wdgt_va_24h_time"), &tm);
352   }
353
354
355   result = g_strdup (string);
356
357   return result;
358 }
359
360 static GtkTreeModel *
361 _create_minutes_model (guint minutes_step)
362 {
363   GtkListStore *store_minutes = NULL;
364   gint i = 0;
365   static gchar label[255];
366   struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
367   GtkTreeIter iter;
368
369   store_minutes = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
370   for (i = 0; i <= 59; i=i+minutes_step) {
371     tm.tm_min = i;
372     strftime (label, 255, _("wdgt_va_minutes"), &tm);
373
374     gtk_list_store_append (store_minutes, &iter);
375     gtk_list_store_set (store_minutes, &iter,
376                         COLUMN_STRING, label, COLUMN_INT, i, -1);
377   }
378
379   return GTK_TREE_MODEL (store_minutes);
380 }
381
382 static GtkTreeModel *
383 _create_hours_model (HildonTimeSelector * selector)
384 {
385   GtkListStore *store_hours = NULL;
386   gint i = 0;
387   GtkTreeIter iter;
388   struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
389   static gchar label[255];
390   static gint range_12h[12] = {12, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11};
391   static gint range_24h[24] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,
392                                12,13,14,15,16,17,18,19,20,21,22,23};
393   gint *range = NULL;
394   gint num_elements = 0;
395   gchar *format_string = NULL;
396
397   if (selector->priv->ampm_format) {
398     range = range_12h;
399     num_elements = 12;
400     format_string = N_("wdgt_va_12h_hours");
401   } else {
402     range = range_24h;
403     num_elements = 24;
404     format_string = N_("wdgt_va_24h_hours");
405   }
406
407   store_hours = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
408   for (i = 0; i < num_elements; i++) {
409     tm.tm_hour = range[i];
410     strftime (label, 255, _(format_string), &tm);
411
412     gtk_list_store_append (store_hours, &iter);
413     gtk_list_store_set (store_hours, &iter,
414                         COLUMN_STRING, label, COLUMN_INT, range[i], -1);
415   }
416
417   return GTK_TREE_MODEL (store_hours);
418 }
419
420 static GtkTreeModel *
421 _create_ampm_model (HildonTimeSelector * selector)
422 {
423   GtkListStore *store_ampm = NULL;
424   GtkTreeIter iter;
425   static gchar label[255];
426
427   store_ampm = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
428
429   snprintf (label, 255, _("wdgt_va_am"));
430   gtk_list_store_append (store_ampm, &iter);
431   gtk_list_store_set (store_ampm, &iter,
432                       COLUMN_STRING, label,
433                       COLUMN_INT, 0, -1);
434
435   snprintf (label, 255, _("wdgt_va_pm"));
436   gtk_list_store_append (store_ampm, &iter);
437   gtk_list_store_set (store_ampm, &iter,
438                       COLUMN_STRING, label,
439                       COLUMN_INT, 1, -1);
440
441   return GTK_TREE_MODEL (store_ampm);
442 }
443
444 static void
445 _get_real_time (gint * hours, gint * minutes)
446 {
447   time_t secs;
448   struct tm *tm = NULL;
449
450   secs = time (NULL);
451   tm = localtime (&secs);
452
453   if (hours != NULL) {
454     *hours = tm->tm_hour;
455   }
456
457   if (minutes != NULL) {
458     *minutes = tm->tm_min;
459   }
460 }
461
462 static void
463 _manage_ampm_selection_cb (HildonTouchSelector * touch_selector,
464                            gint num_column, gpointer data)
465 {
466   HildonTimeSelector *selector = NULL;
467   gint pm;
468   GtkTreeIter iter;
469
470   g_return_if_fail (HILDON_IS_TIME_SELECTOR (touch_selector));
471   selector = HILDON_TIME_SELECTOR (touch_selector);
472
473   if (num_column == COLUMN_AMPM &&
474       hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector),
475                                           COLUMN_AMPM, &iter)) {
476      gtk_tree_model_get (selector->priv->ampm_model, &iter, COLUMN_INT, &pm, -1);
477
478     selector->priv->pm = pm;
479   }
480 }
481
482 static void
483 check_automatic_ampm_format (HildonTimeSelector * selector)
484 {
485   GConfClient *client = NULL;
486   gboolean value = TRUE;
487   GError *error = NULL;
488
489   client = gconf_client_get_default ();
490   value = gconf_client_get_bool (client, CLOCK_GCONF_IS_24H_FORMAT, &error);
491   if (error != NULL) {
492     g_warning
493       ("Error trying to get gconf variable %s, using 24h format by default",
494        CLOCK_GCONF_IS_24H_FORMAT);
495     g_error_free (error);
496   }
497
498   selector->priv->ampm_format = !value;
499 }
500
501 static void
502 _set_pm (HildonTimeSelector * selector, gboolean pm)
503 {
504   GtkTreeIter iter;
505
506   selector->priv->pm = pm;
507
508   if (selector->priv->ampm_model != NULL) {
509     gtk_tree_model_iter_nth_child (selector->priv->ampm_model, &iter, NULL, pm);
510
511     hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector),
512                                        COLUMN_AMPM, &iter, FALSE);
513   }
514 }
515
516 static void
517 update_format_policy                            (HildonTimeSelector *selector,
518                                                  HildonTimeSelectorFormatPolicy new_policy)
519 {
520   gboolean prev_ampm_format = FALSE;
521   gint num_columns = -1;
522
523   num_columns = hildon_touch_selector_get_num_columns (HILDON_TOUCH_SELECTOR (selector));
524   prev_ampm_format = selector->priv->ampm_format;
525
526   if (new_policy != selector->priv->format_policy) {
527     guint hours;
528     guint minutes;
529
530     selector->priv->format_policy = new_policy;
531
532     /* We get the hour previous all the changes, to avoid problems with the
533        changing widget structure */
534     if (num_columns >= 2) {/* we are on the object construction */
535       hildon_time_selector_get_time (selector, &hours, &minutes);
536     }
537
538     switch (new_policy)
539       {
540       case HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM:
541         selector->priv->ampm_format = TRUE;
542         break;
543       case HILDON_TIME_SELECTOR_FORMAT_POLICY_24H:
544         selector->priv->ampm_format = FALSE;
545         break;
546       case HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC:
547         check_automatic_ampm_format (selector);
548         break;
549       }
550
551     if (prev_ampm_format != selector->priv->ampm_format) {
552       update_format_dependant_columns (selector, hours, minutes);
553     }
554   }
555 }
556
557 static void
558 update_format_dependant_columns                 (HildonTimeSelector *selector,
559                                                  guint hours,
560                                                  guint minutes)
561 {
562   gint num_columns = -1;
563
564   num_columns = hildon_touch_selector_get_num_columns (HILDON_TOUCH_SELECTOR (selector));
565   if (num_columns < 2) {/* we are on the object construction */
566     return;
567   }
568
569   /* To avoid an extra and wrong VALUE_CHANGED signal on the model update */
570   hildon_touch_selector_block_changed (HILDON_TOUCH_SELECTOR(selector));
571
572   selector->priv->hours_model = _create_hours_model (selector);
573   hildon_touch_selector_set_model (HILDON_TOUCH_SELECTOR (selector),
574                                    0,
575                                    selector->priv->hours_model);
576
577   /* We need to set NOW the correct hour on the hours column, because the number of
578      columns will be updated too, so a signal COLUMNS_CHANGED will be emitted. Some
579      other widget could have connected to this signal and ask for the hour, so this
580      emission could have a wrong hour. We could use a custom func to only modify the
581      hours selection, but hildon_time_selector_time manage yet all the ampm issues
582      to select the correct one */
583   hildon_time_selector_set_time (selector, hours, minutes);
584
585   /* if we are at this function, we are sure that a change on the number of columns
586      will happen, so check the column number is not required */
587   if (selector->priv->ampm_format) {
588     selector->priv->ampm_model = _create_ampm_model (selector);
589
590     hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
591                                               selector->priv->ampm_model, TRUE);
592
593     g_signal_connect (G_OBJECT (selector),
594                       "changed", G_CALLBACK (_manage_ampm_selection_cb),
595                       NULL);
596   } else {
597     selector->priv->ampm_model = NULL;
598     hildon_touch_selector_remove_column (HILDON_TOUCH_SELECTOR (selector), 2);
599   }
600
601   _set_pm (selector, hours >= 12);
602
603   hildon_touch_selector_unblock_changed (HILDON_TOUCH_SELECTOR (selector));
604 }
605 /* ------------------------------ PUBLIC METHODS ---------------------------- */
606
607 /**
608  * hildon_time_selector_new:
609  *
610  * Creates a new #HildonTimeSelector
611  *
612  * Returns: a new #HildonTimeSelector
613  *
614  * Since: 2.2
615  **/
616 GtkWidget *
617 hildon_time_selector_new ()
618 {
619   return g_object_new (HILDON_TYPE_TIME_SELECTOR, NULL);
620 }
621
622
623 /**
624  * hildon_time_selector_new_step:
625  * @minutes_step: step between the minutes in the selector.
626
627  * Creates a new #HildonTimeSelector, with @minutes_step steps between
628  * the minutes in the minutes column.
629  *
630  * Returns: a new #HildonTimeSelector
631  *
632  * Since: 2.2
633  **/
634 GtkWidget *
635 hildon_time_selector_new_step (guint minutes_step)
636 {
637   return g_object_new (HILDON_TYPE_TIME_SELECTOR, "minutes-step",
638                        minutes_step, NULL);
639 }
640
641 /**
642  * hildon_time_selector_set_time
643  * @selector: the #HildonTimeSelector
644  * @hours:  the current hour (0-23)
645  * @minutes: the current minute (0-59)
646  *
647  * Sets the current active hour on the #HildonTimeSelector widget
648  *
649  * The format of the hours accepted is always 24h format, with a range
650  * (0-23):(0-59).
651  *
652  * Since: 2.2
653  *
654  * Returns: %TRUE on success, %FALSE otherwise
655  **/
656 gboolean
657 hildon_time_selector_set_time (HildonTimeSelector * selector,
658                                guint hours, guint minutes)
659 {
660   GtkTreeIter iter;
661   gint hours_item = 0;
662
663   g_return_val_if_fail (HILDON_IS_TIME_SELECTOR (selector), FALSE);
664   g_return_val_if_fail (hours <= 23, FALSE);
665   g_return_val_if_fail (minutes <= 59, FALSE);
666
667   _set_pm (selector, hours >= 12);
668
669   if (selector->priv->ampm_format) {
670     hours_item = hours - selector->priv->pm * 12;
671   } else {
672     hours_item = hours;
673   }
674
675   gtk_tree_model_iter_nth_child (selector->priv->hours_model, &iter, NULL,
676                                  hours_item);
677   hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector),
678                                      COLUMN_HOURS, &iter, FALSE);
679
680   g_assert (selector->priv->minutes_step>0);
681   minutes = minutes/selector->priv->minutes_step;
682   gtk_tree_model_iter_nth_child (selector->priv->minutes_model, &iter, NULL,
683                                  minutes);
684   hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector),
685                                      COLUMN_MINUTES, &iter, FALSE);
686
687   return TRUE;
688 }
689
690 /**
691  * hildon_time_selector_get_time
692  * @selector: the #HildonTimeSelector
693  * @hours:  to set the current hour (0-23)
694  * @minutes: to set the current minute (0-59)
695  *
696  * Gets the current active hour on the #HildonTimeSelector widget. Both @year
697  * and @minutes can be NULL.
698  *
699  * This method returns the date always in 24h format, with a range (0-23):(0-59)
700  *
701  * Since: 2.2
702  **/
703 void
704 hildon_time_selector_get_time (HildonTimeSelector * selector,
705                                guint * hours, guint * minutes)
706 {
707   GtkTreeIter iter;
708
709   g_return_if_fail (HILDON_IS_TIME_SELECTOR (selector));
710
711   if (hours != NULL) {
712     if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector),
713                                             COLUMN_HOURS, &iter)) {
714
715       gtk_tree_model_get (selector->priv->hours_model,
716                           &iter, COLUMN_INT, hours, -1);
717     }
718     if (selector->priv->ampm_format) {
719       *hours %= 12;
720       *hours += selector->priv->pm * 12;
721     }
722   }
723
724   if (minutes != NULL) {
725     if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector),
726                                             COLUMN_MINUTES, &iter)) {
727       gtk_tree_model_get (selector->priv->minutes_model,
728                           &iter, COLUMN_INT, minutes, -1);
729     }
730   }
731 }