There was a typo in function name, which was only setting the upper bound for 24 hour time format. As the default lower bound is 0, no issue was known so far. But in cases like the user switched from 12 hour to 24 hour format there is a chance for some issues to appear as the lower bound of 12 Hour format is 1, and it won't be reset to 0 when the user has switched to 24 hour format. https://bugzilla.gnome.org/show_bug.cgi?id=781448
346 lines
10 KiB
C
346 lines
10 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/*
|
|
* gcal-time-selector.c
|
|
* Copyright (C) 2015 Erick Pérez Castellanos <erickpc@gnome.org>
|
|
* 2014 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
|
*
|
|
* gnome-calendar is free software: you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* gnome-calendar is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#define G_LOG_DOMAIN "GcalTimeSelector"
|
|
|
|
#include "gcal-time-selector.h"
|
|
|
|
#include <glib/gi18n.h>
|
|
|
|
struct _GcalTimeSelector
|
|
{
|
|
GtkMenuButton parent;
|
|
|
|
GtkAdjustment *hour_adjustment;
|
|
GtkAdjustment *minute_adjustment;
|
|
|
|
GtkWidget *time_label;
|
|
GtkWidget *hour_spin;
|
|
GtkWidget *minute_spin;
|
|
GtkWidget *period_combo;
|
|
GtkWidget *grid;
|
|
|
|
GDateTime *time;
|
|
|
|
gboolean format_24h;
|
|
};
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_TIME,
|
|
LAST_PROP
|
|
};
|
|
|
|
enum
|
|
{
|
|
AM,
|
|
PM
|
|
};
|
|
|
|
static void gcal_time_selector_constructed (GObject *object);
|
|
|
|
G_DEFINE_TYPE (GcalTimeSelector, gcal_time_selector, GTK_TYPE_MENU_BUTTON);
|
|
|
|
static void
|
|
update_label (GcalTimeSelector *selector)
|
|
{
|
|
gchar *new_label;
|
|
|
|
if (selector->format_24h)
|
|
{
|
|
new_label = g_date_time_format (selector->time, "%H:%M");
|
|
}
|
|
else
|
|
{
|
|
gchar *time_str;
|
|
gint hour, minute, period;
|
|
|
|
hour = (gint) gtk_adjustment_get_value (selector->hour_adjustment);
|
|
minute = (gint) gtk_adjustment_get_value (selector->minute_adjustment);
|
|
|
|
|
|
period = gtk_combo_box_get_active (GTK_COMBO_BOX (selector->period_combo));
|
|
time_str = g_strdup_printf ("%.2d:%.2d", hour, minute);
|
|
|
|
if (period == AM)
|
|
new_label = g_strdup_printf (_("%s AM"), time_str);
|
|
else
|
|
new_label = g_strdup_printf (_("%s PM"), time_str);
|
|
|
|
g_free (time_str);
|
|
}
|
|
|
|
gtk_label_set_label (GTK_LABEL (selector->time_label), new_label);
|
|
|
|
g_clear_pointer (&new_label, g_free);
|
|
}
|
|
|
|
static void
|
|
update_time (GcalTimeSelector *selector)
|
|
{
|
|
GDateTime *now, *new_time;
|
|
gint hour, minute;
|
|
|
|
/* Retrieve current time */
|
|
hour = (gint) gtk_adjustment_get_value (selector->hour_adjustment);
|
|
minute = (gint) gtk_adjustment_get_value (selector->minute_adjustment);
|
|
|
|
if (!selector->format_24h)
|
|
{
|
|
hour = hour % 12;
|
|
|
|
if (gtk_combo_box_get_active (GTK_COMBO_BOX (selector->period_combo)) == PM)
|
|
{
|
|
g_signal_handlers_block_by_func (selector->period_combo, update_time, selector);
|
|
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (selector->period_combo), hour >= 12);
|
|
hour += 12;
|
|
|
|
g_signal_handlers_unblock_by_func (selector->period_combo, update_time, selector);
|
|
}
|
|
}
|
|
|
|
now = g_date_time_new_now_local ();
|
|
new_time = g_date_time_new_local (g_date_time_get_year (now),
|
|
g_date_time_get_month (now),
|
|
g_date_time_get_day_of_month (now),
|
|
hour, minute, 0);
|
|
|
|
/* Set the new time */
|
|
gcal_time_selector_set_time (selector, new_time);
|
|
|
|
g_clear_pointer (&new_time, g_date_time_unref);
|
|
g_clear_pointer (&now, g_date_time_unref);
|
|
}
|
|
|
|
static gboolean
|
|
on_output (GtkWidget *widget,
|
|
GcalTimeSelector *selector)
|
|
{
|
|
GtkAdjustment *adjustment;
|
|
gchar *text;
|
|
gint value;
|
|
|
|
adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget));
|
|
value = (gint) gtk_adjustment_get_value (adjustment);
|
|
text = g_strdup_printf ("%02d", value);
|
|
gtk_entry_set_text (GTK_ENTRY (widget), text);
|
|
|
|
g_free (text);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gcal_time_selector_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GcalTimeSelector *self = (GcalTimeSelector*) object;
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_TIME:
|
|
g_value_set_boxed (value, self->time);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gcal_time_selector_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GcalTimeSelector *self = (GcalTimeSelector*) object;
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_TIME:
|
|
gcal_time_selector_set_time (self, g_value_get_boxed (value));
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
}
|
|
}
|
|
|
|
void
|
|
gcal_time_selector_set_time_format (GcalTimeSelector *selector,
|
|
gboolean format_24h)
|
|
{
|
|
g_return_if_fail (GCAL_IS_TIME_SELECTOR (selector));
|
|
|
|
selector->format_24h = format_24h;
|
|
gtk_widget_set_visible (selector->period_combo, !format_24h);
|
|
|
|
if (format_24h)
|
|
{
|
|
gtk_adjustment_set_lower (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 0.0);
|
|
gtk_adjustment_set_upper (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 23.0);
|
|
}
|
|
else
|
|
{
|
|
gtk_adjustment_set_lower (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 1.0);
|
|
gtk_adjustment_set_upper (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (selector->hour_spin)), 12.0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gcal_time_selector_finalize (GObject *object)
|
|
{
|
|
GcalTimeSelector *self = GCAL_TIME_SELECTOR (object);
|
|
|
|
g_clear_pointer (&self->time, g_date_time_unref);
|
|
G_OBJECT_CLASS (gcal_time_selector_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gcal_time_selector_dispose (GObject *object)
|
|
{
|
|
G_OBJECT_CLASS (gcal_time_selector_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gcal_time_selector_class_init (GcalTimeSelectorClass *klass)
|
|
{
|
|
GObjectClass *object_class;
|
|
|
|
object_class = G_OBJECT_CLASS (klass);
|
|
object_class->constructed = gcal_time_selector_constructed;
|
|
object_class->dispose = gcal_time_selector_dispose;
|
|
object_class->finalize = gcal_time_selector_finalize;
|
|
object_class->get_property = gcal_time_selector_get_property;
|
|
object_class->set_property = gcal_time_selector_set_property;
|
|
|
|
/**
|
|
* GcalTimeSelector::time:
|
|
*
|
|
* The current time of the selector.
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_TIME,
|
|
g_param_spec_boxed ("time",
|
|
"Time of the selector",
|
|
"The current time of the selector",
|
|
G_TYPE_DATE_TIME,
|
|
G_PARAM_READWRITE));
|
|
|
|
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/calendar/time-selector.ui");
|
|
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, time_label);
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, hour_adjustment);
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, hour_spin);
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, minute_adjustment);
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, minute_spin);
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, period_combo);
|
|
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, grid);
|
|
|
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), on_output);
|
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), update_time);
|
|
}
|
|
|
|
static void
|
|
gcal_time_selector_init (GcalTimeSelector *self)
|
|
{
|
|
self->time = g_date_time_new_now_local ();
|
|
|
|
gtk_widget_init_template (GTK_WIDGET (self));
|
|
}
|
|
|
|
static void
|
|
gcal_time_selector_constructed (GObject *object)
|
|
{
|
|
GcalTimeSelector *selector = GCAL_TIME_SELECTOR (object);
|
|
|
|
/* chaining up */
|
|
G_OBJECT_CLASS (gcal_time_selector_parent_class)->constructed (object);
|
|
|
|
gtk_widget_set_direction (selector->grid, GTK_TEXT_DIR_LTR);
|
|
}
|
|
|
|
/* Public API */
|
|
GtkWidget*
|
|
gcal_time_selector_new (void)
|
|
{
|
|
return g_object_new (GCAL_TYPE_TIME_SELECTOR, NULL);
|
|
}
|
|
|
|
void
|
|
gcal_time_selector_set_time (GcalTimeSelector *selector,
|
|
GDateTime *time)
|
|
{
|
|
g_return_if_fail (GCAL_IS_TIME_SELECTOR (selector));
|
|
|
|
if (selector->time != time)
|
|
{
|
|
gint hour, minute;
|
|
|
|
g_clear_pointer (&selector->time, g_date_time_unref);
|
|
selector->time = g_date_time_new_local (g_date_time_get_year (time),
|
|
g_date_time_get_month (time),
|
|
g_date_time_get_day_of_month (time),
|
|
g_date_time_get_hour (time),
|
|
g_date_time_get_minute (time),
|
|
0);
|
|
|
|
/* Update the spinners */
|
|
g_signal_handlers_block_by_func (selector->hour_adjustment, update_time, selector);
|
|
g_signal_handlers_block_by_func (selector->minute_adjustment, update_time, selector);
|
|
|
|
hour = g_date_time_get_hour (time);
|
|
minute = g_date_time_get_minute (time);
|
|
|
|
if (!selector->format_24h)
|
|
{
|
|
g_signal_handlers_block_by_func (selector->period_combo, update_time, selector);
|
|
|
|
gtk_combo_box_set_active (GTK_COMBO_BOX (selector->period_combo), hour >= 12);
|
|
hour = hour % 12;
|
|
hour = (hour == 0)? 12 : hour;
|
|
|
|
g_signal_handlers_unblock_by_func (selector->period_combo, update_time, selector);
|
|
}
|
|
|
|
gtk_adjustment_set_value (selector->hour_adjustment, hour);
|
|
gtk_adjustment_set_value (selector->minute_adjustment, minute);
|
|
|
|
update_label (selector);
|
|
|
|
g_signal_handlers_unblock_by_func (selector->hour_adjustment, update_time, selector);
|
|
g_signal_handlers_unblock_by_func (selector->minute_adjustment, update_time, selector);
|
|
|
|
g_object_notify (G_OBJECT (selector), "time");
|
|
}
|
|
}
|
|
|
|
GDateTime*
|
|
gcal_time_selector_get_time (GcalTimeSelector *selector)
|
|
{
|
|
g_return_val_if_fail (GCAL_IS_TIME_SELECTOR (selector), NULL);
|
|
|
|
return selector->time;
|
|
}
|