diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6245cf142e61601db42394f86fefd39fdfbef178..dfdec3a9d0e3442235ddf008cca2fcf6523f5d83 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -27,6 +27,8 @@ src/gui/event-editor/gcal-schedule-section.ui
src/gui/event-editor/gcal-summary-section.c
src/gui/event-editor/gcal-summary-section.ui
src/gui/event-editor/gcal-time-selector.ui
+src/gui/event-editor/gcal-time-zone-dialog.c
+src/gui/event-editor/gcal-time-zone-dialog.ui
src/gui/gcal-application.c
src/gui/gcal-calendar-button.ui
src/gui/gcal-calendar-combo-row.ui
diff --git a/src/core/gcal-event.c b/src/core/gcal-event.c
index 09c90b4ea532d5afede79984cec366fa1af336ca..7f675123cb1b05cc5935f35a55e343fe1ecca58c 100644
--- a/src/core/gcal-event.c
+++ b/src/core/gcal-event.c
@@ -234,7 +234,7 @@ build_component_from_datetime (GcalEvent *self,
g_autoptr (GTimeZone) zone = NULL;
ICalTimezone *tz;
- zone = gcal_util_get_app_timezone_or_local ();
+ zone = g_date_time_get_timezone (dt);
tz = gcal_timezone_to_icaltimezone (zone);
i_cal_time_set_timezone (itt, tz);
tzid = g_strdup (i_cal_timezone_get_tzid (tz));
diff --git a/src/gui/event-editor/event-editor.gresource.xml b/src/gui/event-editor/event-editor.gresource.xml
index 196b62db4a405ba095be229bfa82d79b998e1517..8ff039a73b3bb8a8603dac5e7ce847678d290bc8 100644
--- a/src/gui/event-editor/event-editor.gresource.xml
+++ b/src/gui/event-editor/event-editor.gresource.xml
@@ -5,6 +5,7 @@
gcal-date-chooser.ui
gcal-date-chooser-day.ui
gcal-date-chooser-row.ui
+ gcal-date-time-chooser.ui
gcal-date-selector.ui
gcal-event-editor-dialog.ui
gcal-multi-choice.ui
@@ -12,7 +13,7 @@
gcal-reminders-section.ui
gcal-schedule-section.ui
gcal-summary-section.ui
- gcal-time-chooser-row.ui
- gcal-time-selector.ui
+ gcal-time-zone-dialog.ui
+ gcal-time-zone-dialog-row.ui
diff --git a/src/gui/event-editor/gcal-date-chooser-row.c b/src/gui/event-editor/gcal-date-chooser-row.c
index 301a07fe20c66f1b94b193b0f6eb8d81f6963893..b64952eb4b8508e5af0599f74fda2c6f5419f89c 100644
--- a/src/gui/event-editor/gcal-date-chooser-row.c
+++ b/src/gui/event-editor/gcal-date-chooser-row.c
@@ -299,9 +299,16 @@ void
gcal_date_chooser_row_set_date (GcalDateChooserRow *self,
GDateTime *date)
{
+ g_autoptr (GDateTime) date_utc = NULL;
+
g_return_if_fail (GCAL_IS_DATE_CHOOSER_ROW (self));
- gcal_view_set_date (GCAL_VIEW (self->date_chooser), date);
+ date_utc = g_date_time_new_utc (g_date_time_get_year (date),
+ g_date_time_get_month (date),
+ g_date_time_get_day_of_month (date),
+ 0, 0, 0);
+
+ gcal_view_set_date (GCAL_VIEW (self->date_chooser), date_utc);
update_entry (self);
diff --git a/src/gui/event-editor/gcal-date-time-chooser.c b/src/gui/event-editor/gcal-date-time-chooser.c
new file mode 100644
index 0000000000000000000000000000000000000000..344cb5447e5a57e716915425bdc431c984d02967
--- /dev/null
+++ b/src/gui/event-editor/gcal-date-time-chooser.c
@@ -0,0 +1,829 @@
+/* gcal-date-time-chooser.c
+ *
+ * Copyright (C) 2024 Titouan Real
+ *
+ * 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 .
+ */
+
+#define G_LOG_DOMAIN "GcalDateTimeChooser"
+
+#include "gcal-date-chooser-row.h"
+#include "gcal-date-time-chooser.h"
+#include "gcal-date-time-utils.h"
+#include "gcal-debug.h"
+#include "gcal-time-zone-dialog.h"
+
+#include
+
+struct _GcalDateTimeChooser
+{
+ AdwPreferencesGroup parent;
+
+ GcalDateChooserRow *date_row;
+ AdwEntryRow *time_row;
+ GtkPopover *time_popover;
+ AdwButtonContent *time_zone_button_content;
+ AdwToggleGroup *period_toggle_group;
+
+ GtkAdjustment *hour_adjustment;
+ GtkAdjustment *minute_adjustment;
+
+ GDateTime *date_time;
+ GcalTimeFormat time_format;
+};
+
+G_DEFINE_TYPE (GcalDateTimeChooser, gcal_date_time_chooser, ADW_TYPE_PREFERENCES_GROUP);
+
+enum
+{
+ PROP_0,
+ PROP_DATE_TIME,
+ PROP_DATE_LABEL,
+ PROP_TIME_LABEL,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS] = {
+ NULL,
+};
+
+static void on_spin_buttons_value_changed_cb (GcalDateTimeChooser *self);
+
+static void on_period_toggle_group_active_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GcalDateTimeChooser *self);
+
+/*
+ * Auxiliary methods
+ */
+
+/*
+ * Use the stored date_time of the GcalDateTimeChooser to format the content of the time entry.
+ */
+static void
+normalize_time_entry (GcalDateTimeChooser *self)
+{
+ g_autoptr (GTimeZone) local_time_zone = g_time_zone_new_local ();
+ g_autoptr (GString) label = NULL;
+ const gchar *date_time_identifier;
+ const gchar *local_identifier;
+ gchar *date_time_str;
+
+ GCAL_ENTRY;
+
+ switch (self->time_format)
+ {
+ case GCAL_TIME_FORMAT_12H:
+ date_time_str = g_date_time_format (self->date_time, "%I:%M %p");
+ break;
+
+ case GCAL_TIME_FORMAT_24H:
+ date_time_str = g_date_time_format (self->date_time, "%R");
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ label = g_string_new_take (date_time_str);
+
+ date_time_identifier = g_time_zone_get_identifier (g_date_time_get_timezone (self->date_time));
+ local_identifier = g_time_zone_get_identifier (local_time_zone);
+
+ if (g_strcmp0 (date_time_identifier, local_identifier) != 0)
+ {
+ g_autofree gchar *time_zone_str = gcal_date_time_format_utc_offset (self->date_time);
+
+ g_string_append (label, " (");
+ g_string_append (label, time_zone_str);
+ g_string_append (label, ")");
+ }
+
+ gtk_editable_set_text (GTK_EDITABLE (self->time_row), label->str);
+
+ GCAL_EXIT;
+}
+
+/*
+ * Use the timezone of the stored date_time of the GcalDateTimeChooser to format the label of the timezone button.
+ */
+static void
+normalize_timezone_button_label (GcalDateTimeChooser *self)
+{
+ g_autofree gchar *formatted = NULL;
+ g_autofree gchar *utc_str = NULL;
+ const gchar *identifier;
+
+ identifier = g_time_zone_get_identifier (g_date_time_get_timezone (self->date_time));
+
+ if (g_strcmp0 (identifier, "UTC") == 0)
+ {
+ adw_button_content_set_label (self->time_zone_button_content, "UTC");
+ return;
+ }
+
+ utc_str = gcal_date_time_format_utc_offset (self->date_time);
+
+ /* Translators: "%1$s" is the timezone identifier (e.g. UTC, America/Sao_Paulo)
+ * and "%2$s" is the timezone offset (e.g. UTC-3).
+ */
+ formatted = g_strdup_printf (_("%1$s (%2$s)"), identifier, utc_str);
+
+ adw_button_content_set_label (self->time_zone_button_content, formatted);
+}
+
+/*
+ * Use the time of the stored date_time of the GcalDateTimeChooser to format the spinners and the am/pm toggle of the
+ * time popover.
+ */
+static void
+normalize_time_popover (GcalDateTimeChooser *self)
+{
+ gint new_hour, new_minute;
+
+ GCAL_ENTRY;
+
+ new_hour = g_date_time_get_hour (self->date_time);
+ new_minute = g_date_time_get_minute (self->date_time);
+
+ g_signal_handlers_block_by_func (self->hour_adjustment, on_spin_buttons_value_changed_cb, self);
+ g_signal_handlers_block_by_func (self->minute_adjustment, on_spin_buttons_value_changed_cb, self);
+ g_signal_handlers_block_by_func (self->period_toggle_group, on_period_toggle_group_active_changed_cb, self);
+
+ adw_toggle_group_set_active_name (self->period_toggle_group, new_hour < 12 ? "am" : "pm");
+
+ switch (self->time_format)
+ {
+ case GCAL_TIME_FORMAT_12H:
+ if (new_hour == 0)
+ gtk_adjustment_set_value (self->hour_adjustment, 12);
+ else if (new_hour <= 12)
+ gtk_adjustment_set_value (self->hour_adjustment, new_hour);
+ else
+ gtk_adjustment_set_value (self->hour_adjustment, new_hour - 12);
+ break;
+
+ case GCAL_TIME_FORMAT_24H:
+ gtk_adjustment_set_value (self->hour_adjustment, new_hour);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ gtk_adjustment_set_value (self->minute_adjustment, new_minute);
+
+ g_signal_handlers_unblock_by_func (self->hour_adjustment, on_spin_buttons_value_changed_cb, self);
+ g_signal_handlers_unblock_by_func (self->minute_adjustment, on_spin_buttons_value_changed_cb, self);
+ g_signal_handlers_unblock_by_func (self->period_toggle_group, on_period_toggle_group_active_changed_cb, self);
+
+ GCAL_EXIT;
+}
+
+static GRegex *
+get_12h_regex (void)
+{
+ static GRegex *regex = NULL;
+
+ if (g_once_init_enter_pointer (®ex))
+ {
+ g_autoptr (GError) error = NULL;
+ g_autofree gchar *str = NULL;
+
+ str = g_strdup_printf ("^(?[0-9]{1,2})([\\-:./_,'a-z](?[0-9]{1,2}))? ?(?%s|%s)",
+ _ ("AM"), _ ("PM"));
+
+ regex = g_regex_new (str, G_REGEX_CASELESS, 0, &error);
+
+ if (error)
+ g_error ("Failed to compile regex: %s. Aborting...", error->message);
+ }
+
+ return regex;
+}
+
+static GRegex *
+get_24h_regex (void)
+{
+ static GRegex *regex = NULL;
+
+ if (g_once_init_enter_pointer (®ex))
+ {
+ g_autoptr (GError) error = NULL;
+
+ regex = g_regex_new ("^(?[0-9]{1,2})([\\-:./_,'a-z](?[0-9]{1,2}))?", G_REGEX_CASELESS, 0, &error);
+
+ if (error)
+ g_error ("Failed to compile regex: %s. Aborting...", error->message);
+ }
+
+ return regex;
+}
+
+/*
+ * Parse the string of the time entry.
+ * If the string is not recognised as a time, it resets the entry to the formatted form of the last time.
+ * If it is recognised, the stored date_time is updated and the entry is formatted accordingly.
+ */
+static void
+validate_and_normalize_time_entry (GcalDateTimeChooser *self)
+{
+ const gchar *text;
+
+ text = gtk_editable_get_text (GTK_EDITABLE (self->time_row));
+
+ switch (self->time_format)
+ {
+ case GCAL_TIME_FORMAT_12H:
+ {
+ g_autoptr (GMatchInfo) match_info = NULL;
+ g_autoptr (GDateTime) date_time = NULL;
+ g_autofree gchar *minute_str = NULL;
+ g_autofree gchar *hour_str = NULL;
+ g_autofree gchar *ampm_str = NULL;
+ gboolean am;
+ gint64 hour, minute;
+
+ if (!g_regex_match (get_12h_regex (), text, 0, &match_info))
+ {
+ normalize_time_entry (self);
+ break;
+ }
+
+ hour_str = g_match_info_fetch_named (match_info, "hour");
+ minute_str = g_match_info_fetch_named (match_info, "minute");
+ ampm_str = g_match_info_fetch_named (match_info, "ampm");
+
+ hour = g_ascii_strtoll (hour_str, NULL, 10);
+ minute = g_ascii_strtoll (minute_str, NULL, 10);
+ am = (strcmp (g_ascii_strup (ampm_str, -1), _ ("AM")) == 0);
+
+ if (hour == 0 || hour > 12 || minute > 59)
+ normalize_time_entry (self);
+
+ if (hour == 12)
+ hour = 0;
+
+ if (!am)
+ hour += 12;
+
+ date_time = g_date_time_new (g_date_time_get_timezone (self->date_time),
+ g_date_time_get_year (self->date_time),
+ g_date_time_get_month (self->date_time),
+ g_date_time_get_day_of_month (self->date_time),
+ hour, minute, 0);
+
+ gcal_date_time_chooser_set_date_time (self, date_time);
+ }
+ break;
+
+ case GCAL_TIME_FORMAT_24H:
+ {
+ g_autoptr (GMatchInfo) match_info = NULL;
+ g_autoptr (GDateTime) date_time = NULL;
+ g_autofree gchar *minute_str = NULL;
+ g_autofree gchar *hour_str = NULL;
+ g_autofree gchar *ampm_str = NULL;
+ gint64 hour, minute;
+
+ if (!g_regex_match (get_24h_regex (), text, 0, &match_info))
+ {
+ normalize_time_entry (self);
+ break;
+ }
+
+ hour_str = g_match_info_fetch_named (match_info, "hour");
+ minute_str = g_match_info_fetch_named (match_info, "minute");
+
+ hour = g_ascii_strtoll (hour_str, NULL, 10);
+ minute = g_ascii_strtoll (minute_str, NULL, 10);
+
+ if (hour > 23 || minute > 59)
+ {
+ normalize_time_entry (self);
+ break;
+ }
+
+ date_time = g_date_time_new (g_date_time_get_timezone (self->date_time),
+ g_date_time_get_year (self->date_time),
+ g_date_time_get_month (self->date_time),
+ g_date_time_get_day_of_month (self->date_time),
+ hour, minute, 0);
+
+ gcal_date_time_chooser_set_date_time (self, date_time);
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+
+/*
+ * Callbacks
+ */
+
+static void
+on_date_changed_cb (GcalDateTimeChooser *self,
+ GParamSpec *pspec,
+ GtkWidget *widget)
+{
+ g_autoptr (GDateTime) new_date_time = NULL;
+ GDateTime *date_chooser_row_date;
+
+ GCAL_ENTRY;
+
+ date_chooser_row_date = gcal_date_chooser_row_get_date (self->date_row);
+ new_date_time = g_date_time_new (g_date_time_get_timezone (self->date_time),
+ g_date_time_get_year (date_chooser_row_date),
+ g_date_time_get_month (date_chooser_row_date),
+ g_date_time_get_day_of_month (date_chooser_row_date),
+ g_date_time_get_hour (self->date_time),
+ g_date_time_get_minute (self->date_time),
+ 0);
+
+ gcal_date_time_chooser_set_date_time (self, new_date_time);
+
+ GCAL_EXIT;
+}
+
+static void
+on_time_zone_selected_cb (GcalTimeZoneDialog *dialog,
+ GcalDateTimeChooser *self)
+{
+ GTimeZone *time_zone;
+ GDateTime *new;
+
+ GCAL_ENTRY;
+
+ time_zone = gcal_time_zone_dialog_get_time_zone (dialog);
+
+ new = g_date_time_new (time_zone,
+ g_date_time_get_year (self->date_time),
+ g_date_time_get_month (self->date_time),
+ g_date_time_get_day_of_month (self->date_time),
+ g_date_time_get_hour (self->date_time),
+ g_date_time_get_minute (self->date_time),
+ 0);
+
+ gcal_date_time_chooser_set_date_time (self, new);
+
+ GCAL_EXIT;
+}
+
+static void
+on_time_zone_button_clicked_cb (GtkButton *button,
+ GcalDateTimeChooser *self)
+{
+ AdwDialog *dialog;
+
+ validate_and_normalize_time_entry (self);
+
+ dialog = ADW_DIALOG (gcal_time_zone_dialog_new (self->date_time));
+ g_signal_connect (dialog, "timezone-selected", G_CALLBACK (on_time_zone_selected_cb), self);
+ gtk_popover_popdown (self->time_popover);
+ adw_dialog_present (dialog, GTK_WIDGET (self));
+}
+
+static void
+on_time_row_contains_focus_changed_cb (GtkEventControllerFocus *focus_controller,
+ GParamSpec *pspec,
+ GcalDateTimeChooser *self)
+{
+ validate_and_normalize_time_entry (self);
+}
+
+static void
+on_time_popover_shown_cb (GtkPopover *popover,
+ GcalDateTimeChooser *self)
+{
+ validate_and_normalize_time_entry (self);
+}
+
+static void
+on_spin_button_output_cb (GtkWidget *widget,
+ GcalDateTimeChooser *self)
+{
+ g_autofree gchar *text = NULL;
+ GtkAdjustment *adjustment;
+ gint hour;
+
+ adjustment = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget));
+ hour = gtk_adjustment_get_value (adjustment);
+
+ text = g_strdup_printf ("%02d", hour);
+ gtk_editable_set_text (GTK_EDITABLE (widget), text);
+}
+
+static void
+on_spin_buttons_value_changed_cb (GcalDateTimeChooser *self)
+{
+ g_autoptr (GDateTime) new_date_time = NULL;
+ gint hour, minute;
+
+ GCAL_ENTRY;
+
+ hour = gtk_adjustment_get_value (self->hour_adjustment);
+ minute = gtk_adjustment_get_value (self->minute_adjustment);
+
+ switch (self->time_format)
+ {
+ case GCAL_TIME_FORMAT_12H:
+ if (hour == 12)
+ hour = 0;
+ if (g_strcmp0 (adw_toggle_group_get_active_name (self->period_toggle_group), "pm") == 0)
+ hour += 12;
+ break;
+
+ case GCAL_TIME_FORMAT_24H:
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ new_date_time = g_date_time_new (g_date_time_get_timezone (self->date_time),
+ g_date_time_get_year (self->date_time),
+ g_date_time_get_month (self->date_time),
+ g_date_time_get_day_of_month (self->date_time),
+ hour, minute, 0);
+
+ gcal_date_time_chooser_set_date_time (self, new_date_time);
+
+ GCAL_EXIT;
+}
+
+static void
+on_hour_spin_button_wrapped_cb (GtkSpinButton *spin_button,
+ GcalDateTimeChooser *self)
+{
+ if (g_strcmp0 (adw_toggle_group_get_active_name (self->period_toggle_group), "am") == 0)
+ adw_toggle_group_set_active_name (self->period_toggle_group, "pm");
+ else
+ adw_toggle_group_set_active_name (self->period_toggle_group, "am");
+}
+
+static void
+on_period_toggle_group_active_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GcalDateTimeChooser *self)
+{
+ g_autoptr (GDateTime) new_date_time = NULL;
+
+ if (g_strcmp0 (adw_toggle_group_get_active_name (self->period_toggle_group), "am") == 0)
+ new_date_time = g_date_time_add_hours (self->date_time, -12);
+ else
+ new_date_time = g_date_time_add_hours (self->date_time, 12);
+
+ gcal_date_time_chooser_set_date_time (self, new_date_time);
+}
+
+/*
+ * GObject overrides
+ */
+
+static void
+gcal_date_time_chooser_dispose (GObject *object)
+{
+ GcalDateTimeChooser *self = GCAL_DATE_TIME_CHOOSER (object);
+
+ gcal_clear_date_time (&self->date_time);
+
+ G_OBJECT_CLASS (gcal_date_time_chooser_parent_class)->dispose (object);
+}
+
+static void
+gcal_date_time_chooser_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GcalDateTimeChooser *self = GCAL_DATE_TIME_CHOOSER (object);
+
+ switch (prop_id)
+ {
+ case PROP_DATE_TIME:
+ g_value_set_boxed (value, gcal_date_time_chooser_get_date_time (self));
+ break;
+
+ case PROP_DATE_LABEL:
+ g_value_set_string (value, gcal_date_time_chooser_get_date_label (self));
+ break;
+
+ case PROP_TIME_LABEL:
+ g_value_set_string (value, gcal_date_time_chooser_get_time_label (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gcal_date_time_chooser_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GcalDateTimeChooser *self = GCAL_DATE_TIME_CHOOSER (object);
+
+ switch (prop_id)
+ {
+ case PROP_DATE_TIME:
+ gcal_date_time_chooser_set_date_time (self, g_value_get_boxed (value));
+ break;
+
+ case PROP_DATE_LABEL:
+ gcal_date_time_chooser_set_date_label (self, g_value_get_string (value));
+ break;
+
+ case PROP_TIME_LABEL:
+ gcal_date_time_chooser_set_time_label (self, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gcal_date_time_chooser_class_init (GcalDateTimeChooserClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_ensure (GCAL_TYPE_DATE_CHOOSER_ROW);
+
+ object_class->dispose = gcal_date_time_chooser_dispose;
+ object_class->get_property = gcal_date_time_chooser_get_property;
+ object_class->set_property = gcal_date_time_chooser_set_property;
+
+ /**
+ * GcalDateTimeChooser::date-time:
+ *
+ * The current date-time of the chooser.
+ */
+ properties[PROP_DATE_TIME] = g_param_spec_boxed ("date-time",
+ "DateTime of the date-time chooser",
+ "The current date-time of the chooser",
+ G_TYPE_DATE_TIME,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GcalDateTimeChooser::date-label:
+ *
+ * The current date label of the date row.
+ */
+ properties[PROP_DATE_LABEL] = g_param_spec_string ("date-label",
+ NULL,
+ NULL,
+ "",
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GcalDateTimeChooser::time-label:
+ *
+ * The current time label of the time row.
+ */
+ properties[PROP_TIME_LABEL] = g_param_spec_string ("time-label",
+ NULL,
+ NULL,
+ "",
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/calendar/ui/event-editor/gcal-date-time-chooser.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GcalDateTimeChooser, date_row);
+ gtk_widget_class_bind_template_child (widget_class, GcalDateTimeChooser, time_row);
+ gtk_widget_class_bind_template_child (widget_class, GcalDateTimeChooser, time_popover);
+ gtk_widget_class_bind_template_child (widget_class, GcalDateTimeChooser, time_zone_button_content);
+ gtk_widget_class_bind_template_child (widget_class, GcalDateTimeChooser, period_toggle_group);
+ gtk_widget_class_bind_template_child (widget_class, GcalDateTimeChooser, hour_adjustment);
+ gtk_widget_class_bind_template_child (widget_class, GcalDateTimeChooser, minute_adjustment);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_date_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_time_zone_button_clicked_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_time_row_contains_focus_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_time_popover_shown_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_spin_button_output_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_spin_buttons_value_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_hour_spin_button_wrapped_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_period_toggle_group_active_changed_cb);
+}
+
+static void
+gcal_date_time_chooser_init (GcalDateTimeChooser *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->date_time = g_date_time_new_now_local ();
+}
+
+/* Public API */
+GtkWidget *
+gcal_date_time_chooser_new (void)
+{
+ return g_object_new (GCAL_TYPE_DATE_TIME_CHOOSER, NULL);
+}
+
+void
+gcal_date_time_chooser_set_time_format (GcalDateTimeChooser *self,
+ GcalTimeFormat time_format)
+{
+ g_return_if_fail (GCAL_IS_DATE_TIME_CHOOSER (self));
+
+ self->time_format = time_format;
+
+ gtk_widget_set_visible (GTK_WIDGET (self->period_toggle_group), time_format == GCAL_TIME_FORMAT_12H);
+
+ switch (self->time_format)
+ {
+ case GCAL_TIME_FORMAT_12H:
+ gtk_adjustment_set_lower (self->hour_adjustment, 1);
+ gtk_adjustment_set_upper (self->hour_adjustment, 12);
+ break;
+
+ case GCAL_TIME_FORMAT_24H:
+ gtk_adjustment_set_lower (self->hour_adjustment, 0);
+ gtk_adjustment_set_upper (self->hour_adjustment, 23);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ normalize_time_entry (self);
+}
+
+/**
+ * gcal_date_time_chooser_get_date_time:
+ * @self: a #GcalDateTimeChooser
+ *
+ * Get the value of the date-time shown
+ *
+ * Returns: (transfer none): the date-time of the chooser.
+ */
+GDateTime *
+gcal_date_time_chooser_get_date_time (GcalDateTimeChooser *self)
+{
+ g_assert (GCAL_IS_DATE_TIME_CHOOSER (self));
+
+ return g_date_time_ref (self->date_time);
+}
+
+/**
+ * gcal_date_time_chooser_set_date_time:
+ * @self: a #GcalDateTimeChooser
+ * @date_time: a valid #GDateTime
+ *
+ * Set the value of the shown date-time.
+ */
+void
+gcal_date_time_chooser_set_date_time (GcalDateTimeChooser *self,
+ GDateTime *date_time)
+{
+ GCAL_ENTRY;
+
+ gcal_set_date_time (&self->date_time, date_time);
+
+ g_signal_handlers_block_by_func (self->date_row, on_date_changed_cb, self);
+ gcal_date_chooser_row_set_date (self->date_row, date_time);
+ g_signal_handlers_unblock_by_func (self->date_row, on_date_changed_cb, self);
+
+ normalize_time_entry (self);
+ normalize_timezone_button_label (self);
+ normalize_time_popover (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DATE_TIME]);
+
+ GCAL_EXIT;
+}
+
+/**
+ * gcal_date_time_chooser_get_date:
+ * @self: a #GcalDateTimeChooser
+ *
+ * Get the value of the date shown.
+ * The timezone, hours, minutes and seconds are discarded and replaced with UTC, 0, 0 and 0 respectively.
+ *
+ * Returns: (transfer full): the date of the chooser.
+ */
+GDateTime *
+gcal_date_time_chooser_get_date (GcalDateTimeChooser *self)
+{
+ g_assert (GCAL_IS_DATE_TIME_CHOOSER (self));
+
+ return g_date_time_new_utc (g_date_time_get_year (self->date_time),
+ g_date_time_get_month (self->date_time),
+ g_date_time_get_day_of_month (self->date_time),
+ 0, 0, 0);
+}
+
+/**
+ * gcal_date_time_chooser_set_date:
+ * @self: a #GcalDateTimeChooser
+ * @date_time: a valid #GDateTime
+ *
+ * Set the value of the shown date.
+ * The timezone, hours, minutes and seconds are ignored.
+ */
+void
+gcal_date_time_chooser_set_date (GcalDateTimeChooser *self,
+ GDateTime *date_time)
+{
+ g_autoptr (GDateTime) new_date_time = NULL;
+
+ g_assert (GCAL_IS_DATE_TIME_CHOOSER (self));
+
+ GCAL_ENTRY;
+
+ new_date_time = g_date_time_new (g_date_time_get_timezone (self->date_time),
+ g_date_time_get_year (date_time),
+ g_date_time_get_month (date_time),
+ g_date_time_get_day_of_month (date_time),
+ g_date_time_get_hour (self->date_time),
+ g_date_time_get_minute (self->date_time),
+ 0);
+
+ gcal_date_time_chooser_set_date_time (self, new_date_time);
+
+ GCAL_EXIT;
+}
+
+/**
+ * gcal_date_time_chooser_get_date_label:
+ * @self: a #GcalDateTimeChooser
+ *
+ * Get the value of the date row label
+ *
+ * Returns: (transfer none): the label of the date row.
+ */
+const gchar*
+gcal_date_time_chooser_get_date_label (GcalDateTimeChooser *self)
+{
+ g_assert (GCAL_IS_DATE_TIME_CHOOSER (self));
+
+ return adw_preferences_row_get_title (ADW_PREFERENCES_ROW (self->date_row));
+}
+
+/**
+ * gcal_date_time_chooser_set_date_label:
+ * @self: a #GcalDateTimeChooser
+ * @date_label: The label
+ *
+ * Set the value of the date row label
+ */
+void
+gcal_date_time_chooser_set_date_label (GcalDateTimeChooser *self,
+ const gchar *date_label)
+{
+ g_assert (GCAL_IS_DATE_TIME_CHOOSER (self));
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->date_row), date_label);
+}
+
+/**
+ * gcal_date_time_chooser_get_time_label:
+ * @self: a #GcalDateTimeChooser
+ *
+ * Get the value of the time row label
+ *
+ * Returns: (transfer none): the label of the time row.
+ */
+const gchar*
+gcal_date_time_chooser_get_time_label (GcalDateTimeChooser *self)
+{
+ g_assert (GCAL_IS_DATE_TIME_CHOOSER (self));
+
+ return adw_preferences_row_get_title (ADW_PREFERENCES_ROW (self->time_row));
+}
+
+/**
+ * gcal_date_time_chooser_set_time_label:
+ * @self: a #GcalDateTimeChooser
+ * @time_label: The label
+ *
+ * Set the value of the time row label
+ */
+void
+gcal_date_time_chooser_set_time_label (GcalDateTimeChooser *self,
+ const gchar *time_label)
+{
+ g_assert (GCAL_IS_DATE_TIME_CHOOSER (self));
+
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->time_row), time_label);
+}
diff --git a/src/gui/event-editor/gcal-date-time-chooser.h b/src/gui/event-editor/gcal-date-time-chooser.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb78bd9ff9004d116fce8584a6f1778ca1829ad1
--- /dev/null
+++ b/src/gui/event-editor/gcal-date-time-chooser.h
@@ -0,0 +1,56 @@
+/* gcal-date-time-chooser.h
+ *
+ * Copyright (C) 2024 Titouan Real
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include
+
+#include "gcal-enums.h"
+
+G_BEGIN_DECLS
+
+#define GCAL_TYPE_DATE_TIME_CHOOSER (gcal_date_time_chooser_get_type ())
+
+G_DECLARE_FINAL_TYPE (GcalDateTimeChooser, gcal_date_time_chooser, GCAL, DATE_TIME_CHOOSER, AdwPreferencesGroup)
+
+GtkWidget* gcal_date_time_chooser_new (void);
+
+void gcal_date_time_chooser_set_time_format (GcalDateTimeChooser *chooser,
+ GcalTimeFormat time_format);
+
+GDateTime* gcal_date_time_chooser_get_date_time (GcalDateTimeChooser *chooser);
+
+void gcal_date_time_chooser_set_date_time (GcalDateTimeChooser *chooser,
+ GDateTime *date_time);
+
+GDateTime* gcal_date_time_chooser_get_date (GcalDateTimeChooser *chooser);
+
+void gcal_date_time_chooser_set_date (GcalDateTimeChooser *chooser,
+ GDateTime *date_time);
+
+const gchar* gcal_date_time_chooser_get_date_label (GcalDateTimeChooser *chooser);
+
+void gcal_date_time_chooser_set_date_label (GcalDateTimeChooser *chooser,
+ const gchar *date_label);
+
+const gchar* gcal_date_time_chooser_get_time_label (GcalDateTimeChooser *chooser);
+
+void gcal_date_time_chooser_set_time_label (GcalDateTimeChooser *chooser,
+ const gchar *time_label);
+
+G_END_DECLS
diff --git a/src/gui/event-editor/gcal-date-time-chooser.ui b/src/gui/event-editor/gcal-date-time-chooser.ui
new file mode 100644
index 0000000000000000000000000000000000000000..2a69948c820ada6623207c4709d30755bcca34d4
--- /dev/null
+++ b/src/gui/event-editor/gcal-date-time-chooser.ui
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 23
+ 1
+ 5
+
+
+
+ 59
+ 1
+ 10
+
+
+
+
diff --git a/src/gui/event-editor/gcal-schedule-section.c b/src/gui/event-editor/gcal-schedule-section.c
index afabfc550ac0b291ca8368341c01fd2c2b660f37..d5f33498a0e70dfab3d8a5528b33e7f0f2f24255 100644
--- a/src/gui/event-editor/gcal-schedule-section.c
+++ b/src/gui/event-editor/gcal-schedule-section.c
@@ -23,29 +23,31 @@
#include "gcal-context.h"
#include "gcal-date-selector.h"
#include "gcal-date-chooser-row.h"
+#include "gcal-date-time-chooser.h"
#include "gcal-debug.h"
#include "gcal-event.h"
#include "gcal-event-editor-section.h"
#include "gcal-recurrence.h"
#include "gcal-schedule-section.h"
-#include "gcal-time-chooser-row.h"
#include "gcal-utils.h"
#include
struct _GcalScheduleSection
{
- GtkBox parent;
-
- AdwToggleGroup *schedule_type_toggle_group;
- GcalDateChooserRow *start_date_row;
- GcalTimeChooserRow *start_time_row;
- GcalDateChooserRow *end_date_row;
- GcalTimeChooserRow *end_time_row;
- GtkWidget *number_of_occurrences_spin;
- GtkWidget *repeat_combo;
- GtkWidget *repeat_duration_combo;
- GtkWidget *until_date_selector;
+ GtkBox parent;
+
+ AdwToggleGroup *schedule_type_toggle_group;
+ AdwPreferencesGroup *start_date_group;
+ GcalDateChooserRow *start_date_row;
+ AdwPreferencesGroup *end_date_group;
+ GcalDateChooserRow *end_date_row;
+ GcalDateTimeChooser *start_date_time_chooser;
+ GcalDateTimeChooser *end_date_time_chooser;
+ GtkWidget *number_of_occurrences_spin;
+ GtkWidget *repeat_combo;
+ GtkWidget *repeat_duration_combo;
+ GtkWidget *until_date_selector;
GcalContext *context;
GcalEvent *event;
@@ -65,6 +67,22 @@ enum
N_PROPS
};
+static void on_start_date_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GcalScheduleSection *self);
+
+static void on_end_date_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GcalScheduleSection *self);
+
+static void on_start_date_time_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GcalScheduleSection *self);
+
+static void on_end_date_time_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GcalScheduleSection *self);
+
/*
* Auxiliary methods
@@ -77,225 +95,188 @@ all_day_selected (GcalScheduleSection *self)
return g_strcmp0 (active, "all-day") == 0;
}
+
static void
-find_best_timezones_for_event (GcalScheduleSection *self,
- GTimeZone **out_tz_start,
- GTimeZone **out_tz_end)
+block_date_signals (GcalScheduleSection *self)
{
- gboolean was_all_day;
- gboolean all_day;
- gboolean new_event;
+ g_signal_handlers_block_by_func (self->start_date_row, on_start_date_changed_cb, self);
+ g_signal_handlers_block_by_func (self->end_date_row, on_end_date_changed_cb, self);
- /* Update all day */
- all_day = all_day_selected (self);
- was_all_day = gcal_event_get_all_day (self->event);
- new_event = self->flags & GCAL_EVENT_EDITOR_FLAG_NEW_EVENT;
+ g_signal_handlers_block_by_func (self->start_date_time_chooser, on_start_date_time_changed_cb, self);
+ g_signal_handlers_block_by_func (self->end_date_time_chooser, on_end_date_time_changed_cb, self);
+}
- GCAL_TRACE_MSG ("Finding best timezone with all_day=%d, was_all_day=%d, event_is_new=%d",
- all_day,
- was_all_day,
- new_event);
+static void
+unblock_date_signals (GcalScheduleSection *self)
+{
+ g_signal_handlers_unblock_by_func (self->end_date_time_chooser, on_end_date_time_changed_cb, self);
+ g_signal_handlers_unblock_by_func (self->start_date_time_chooser, on_start_date_time_changed_cb, self);
- if (!new_event && was_all_day && !all_day)
- {
- GCAL_TRACE_MSG ("Using original event timezones");
+ g_signal_handlers_unblock_by_func (self->end_date_row, on_end_date_changed_cb, self);
+ g_signal_handlers_unblock_by_func (self->start_date_row, on_start_date_changed_cb, self);
+}
- gcal_event_get_original_timezones (self->event, out_tz_start, out_tz_end);
- return;
- }
+static void
+remove_recurrence_properties (GcalEvent *event)
+{
+ ECalComponent *comp;
- if (all_day)
- {
- GCAL_TRACE_MSG ("Using UTC timezones");
+ comp = gcal_event_get_component (event);
- if (out_tz_start)
- *out_tz_start = g_time_zone_new_utc ();
+ e_cal_component_set_recurid (comp, NULL);
+ e_cal_component_set_rrules (comp, NULL);
+ e_cal_component_commit_sequence (comp);
+}
- if (out_tz_end)
- *out_tz_end = g_time_zone_new_utc ();
- }
- else
- {
- g_autoptr (GTimeZone) tz_start = NULL;
- g_autoptr (GTimeZone) tz_end = NULL;
- if (new_event)
- {
- GCAL_TRACE_MSG ("Using the local timezone");
+/*
+ * Callbacks
+ */
- tz_start = g_time_zone_new_local ();
- tz_end = g_time_zone_new_local ();
- }
- else
- {
- GCAL_TRACE_MSG ("Using the current timezones");
+static void
+on_schedule_type_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GcalScheduleSection *self)
+{
+ gboolean all_day = all_day_selected (self);
- tz_start = g_time_zone_ref (g_date_time_get_timezone (gcal_event_get_date_start (self->event)));
- tz_end = g_time_zone_ref (g_date_time_get_timezone (gcal_event_get_date_end (self->event)));
- }
+ gtk_widget_set_visible (GTK_WIDGET (self->start_date_group), all_day);
+ gtk_widget_set_visible (GTK_WIDGET (self->end_date_group), all_day);
+ gtk_widget_set_visible (GTK_WIDGET (self->start_date_time_chooser), !all_day);
+ gtk_widget_set_visible (GTK_WIDGET (self->end_date_time_chooser), !all_day);
+
+ block_date_signals (self);
- if (out_tz_start)
- *out_tz_start = g_steal_pointer (&tz_start);
+ if (all_day)
+ {
+ g_autoptr (GDateTime) start_local = NULL;
+ g_autoptr (GDateTime) end_local = NULL;
+
+ GDateTime *start = gcal_date_time_chooser_get_date_time (self->start_date_time_chooser);
+ GDateTime *end = gcal_date_time_chooser_get_date_time (self->end_date_time_chooser);
- if (out_tz_end)
- *out_tz_end = g_steal_pointer (&tz_end);
+ start_local = g_date_time_to_local (start);
+ end_local = g_date_time_to_local (end);
+
+ gcal_date_chooser_row_set_date (self->start_date_row, start_local);
+ gcal_date_chooser_row_set_date (self->end_date_row, end_local);
+ gcal_date_time_chooser_set_date_time (self->start_date_time_chooser, start_local);
+ gcal_date_time_chooser_set_date_time (self->end_date_time_chooser, end_local);
}
+
+ unblock_date_signals (self);
}
-static GDateTime*
-return_datetime_for_widgets (GcalScheduleSection *self,
- GTimeZone *timezone,
- GcalDateChooserRow *date_chooser_row,
- GcalTimeChooserRow *time_chooser_row)
+static void
+on_start_date_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GcalScheduleSection *self)
{
- g_autoptr (GDateTime) date_in_local_tz = NULL;
- g_autoptr (GDateTime) date_in_best_tz = NULL;
- GDateTime *date;
- GDateTime *time;
- GDateTime *retval;
- gboolean all_day;
+ GDateTime *start, *end;
- all_day = all_day_selected (self);
- date = gcal_date_chooser_row_get_date (date_chooser_row);
- time = gcal_time_chooser_row_get_time (time_chooser_row);
+ GCAL_ENTRY;
- date_in_local_tz = g_date_time_new_local (g_date_time_get_year (date),
- g_date_time_get_month (date),
- g_date_time_get_day_of_month (date),
- all_day ? 0 : g_date_time_get_hour (time),
- all_day ? 0 : g_date_time_get_minute (time),
- 0);
+ block_date_signals (self);
- if (all_day)
- date_in_best_tz = g_date_time_ref (date_in_local_tz);
- else
- date_in_best_tz = g_date_time_to_timezone (date_in_local_tz, timezone);
-
- retval = g_date_time_new (timezone,
- g_date_time_get_year (date_in_best_tz),
- g_date_time_get_month (date_in_best_tz),
- g_date_time_get_day_of_month (date_in_best_tz),
- all_day ? 0 : g_date_time_get_hour (date_in_best_tz),
- all_day ? 0 : g_date_time_get_minute (date_in_best_tz),
- 0);
+ start = gcal_date_chooser_row_get_date (self->start_date_row);
+ end = gcal_date_chooser_row_get_date (self->end_date_row);
- return retval;
-}
+ if (g_date_time_compare (start, end) == 1)
+ {
+ gcal_date_chooser_row_set_date (self->end_date_row, start);
+ gcal_date_time_chooser_set_date (self->end_date_time_chooser, start);
+ }
-static GDateTime*
-get_date_start (GcalScheduleSection *self)
-{
- g_autoptr (GTimeZone) start_tz = NULL;
+ // Keep the date row and the date-time chooser in sync
+ gcal_date_time_chooser_set_date (self->start_date_time_chooser, start);
- find_best_timezones_for_event (self, &start_tz, NULL);
+ unblock_date_signals (self);
- return return_datetime_for_widgets (self,
- start_tz,
- self->start_date_row,
- self->start_time_row);
+ GCAL_EXIT;
}
-static GDateTime*
-get_date_end (GcalScheduleSection *self)
+static void
+on_end_date_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GcalScheduleSection *self)
{
- g_autoptr (GTimeZone) end_tz = NULL;
+ GDateTime *start, *end;
- find_best_timezones_for_event (self, NULL, &end_tz);
+ GCAL_ENTRY;
- return return_datetime_for_widgets (self,
- end_tz,
- self->end_date_row,
- self->end_time_row);
-}
+ block_date_signals (self);
-static void
-remove_recurrence_properties (GcalEvent *event)
-{
- ECalComponent *comp;
+ start = gcal_date_chooser_row_get_date (self->start_date_row);
+ end = gcal_date_chooser_row_get_date (self->end_date_row);
- comp = gcal_event_get_component (event);
+ if (g_date_time_compare (start, end) == 1)
+ {
+ gcal_date_chooser_row_set_date (self->start_date_row, end);
+ gcal_date_time_chooser_set_date (self->start_date_time_chooser, end);
+ }
- e_cal_component_set_recurid (comp, NULL);
- e_cal_component_set_rrules (comp, NULL);
- e_cal_component_commit_sequence (comp);
+ // Keep the date row and the date-time chooser in sync
+ gcal_date_time_chooser_set_date (self->end_date_time_chooser, end);
+
+ unblock_date_signals (self);
+
+ GCAL_EXIT;
}
static void
-sync_datetimes (GcalScheduleSection *self,
- GParamSpec *pspec,
- GtkWidget *widget)
+on_start_date_time_changed_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ GcalScheduleSection *self)
{
- GDateTime *start, *end, *start_local, *end_local, *new_date;
- GtkWidget *date_widget, *time_widget;
- gboolean is_start, is_all_day;
+ GDateTime *start, *end;
GCAL_ENTRY;
- is_start = (widget == GTK_WIDGET (self->start_time_row) || widget == GTK_WIDGET (self->start_date_row));
- is_all_day = all_day_selected (self);
- start = get_date_start (self);
- end = get_date_end (self);
-
- /* The date is valid, no need to update the fields */
- if (g_date_time_compare (end, start) >= 0)
- GCAL_GOTO (out);
+ block_date_signals (self);
- start_local = g_date_time_to_local (start);
- end_local = g_date_time_to_local (end);
-
- /*
- * If the user is changing the start date or time, we change the end
- * date or time (and vice versa).
- */
- if (is_start)
- {
- new_date = is_all_day ? g_date_time_add_hours (start, 0) : g_date_time_add_hours (start_local, 1);
+ start = gcal_date_time_chooser_get_date_time (self->start_date_time_chooser);
+ end = gcal_date_time_chooser_get_date_time (self->end_date_time_chooser);
- date_widget = GTK_WIDGET (self->end_date_row);
- time_widget = GTK_WIDGET (self->end_time_row);
- }
- else
+ if (g_date_time_compare (start, end) == 1)
{
- new_date = is_all_day ? g_date_time_add_hours (end, 0) : g_date_time_add_hours (end_local, -1);
+ GTimeZone *end_tz = g_date_time_get_timezone (end);
+ g_autoptr (GDateTime) new_end = g_date_time_add_hours (start, 1);
+ g_autoptr (GDateTime) new_end_in_end_tz = g_date_time_to_timezone (new_end, end_tz);
- date_widget = GTK_WIDGET (self->start_date_row);
- time_widget = GTK_WIDGET (self->start_time_row);
+ gcal_date_time_chooser_set_date_time (self->end_date_time_chooser, new_end_in_end_tz);
}
- g_signal_handlers_block_by_func (date_widget, sync_datetimes, self);
- g_signal_handlers_block_by_func (time_widget, sync_datetimes, self);
-
- gcal_date_chooser_row_set_date (GCAL_DATE_CHOOSER_ROW (date_widget), new_date);
- gcal_time_chooser_row_set_time (GCAL_TIME_CHOOSER_ROW (time_widget), new_date);
-
- g_signal_handlers_unblock_by_func (date_widget, sync_datetimes, self);
- g_signal_handlers_unblock_by_func (time_widget, sync_datetimes, self);
-
- g_clear_pointer (&start_local, g_date_time_unref);
- g_clear_pointer (&end_local, g_date_time_unref);
- g_clear_pointer (&new_date, g_date_time_unref);
-
-out:
- g_clear_pointer (&start, g_date_time_unref);
- g_clear_pointer (&end, g_date_time_unref);
+ unblock_date_signals (self);
GCAL_EXIT;
}
-
-/*
- * Callbacks
- */
-
static void
-on_schedule_type_changed_cb (GtkWidget *widget,
+on_end_date_time_changed_cb (GtkWidget *widget,
GParamSpec *pspec,
GcalScheduleSection *self)
{
- gboolean all_day = all_day_selected (self);
+ GDateTime *start, *end;
+
+ GCAL_ENTRY;
+
+ block_date_signals (self);
+
+ start = gcal_date_time_chooser_get_date_time (self->start_date_time_chooser);
+ end = gcal_date_time_chooser_get_date_time (self->end_date_time_chooser);
+
+ if (g_date_time_compare (start, end) == 1)
+ {
+ GTimeZone *start_tz = g_date_time_get_timezone (start);
+ g_autoptr (GDateTime) new_start = g_date_time_add_hours (end, -1);
+ g_autoptr (GDateTime) new_start_in_start_tz = g_date_time_to_timezone (new_start, start_tz);
+
+ gcal_date_time_chooser_set_date_time (self->start_date_time_chooser, new_start_in_start_tz);
+ }
+
+ unblock_date_signals (self);
- gtk_widget_set_visible (GTK_WIDGET (self->start_time_row), !all_day);
- gtk_widget_set_visible (GTK_WIDGET (self->end_time_row), !all_day);
+ GCAL_EXIT;
}
static void
@@ -329,8 +310,8 @@ on_time_format_changed_cb (GcalScheduleSection *self)
{
GcalTimeFormat time_format = gcal_context_get_time_format (self->context);
- gcal_time_chooser_row_set_time_format (self->start_time_row, time_format);
- gcal_time_chooser_row_set_time_format (self->end_time_row, time_format);
+ gcal_date_time_chooser_set_time_format (self->start_date_time_chooser, time_format);
+ gcal_date_time_chooser_set_time_format (self->end_date_time_chooser, time_format);
}
@@ -338,18 +319,33 @@ on_time_format_changed_cb (GcalScheduleSection *self)
* GcalEventEditorSection interface
*/
+/*
+ * Sets the event of the schedule section.
+ *
+ * If the event is not a new event, the event date start and date end timezones are kept and displayed to the user.
+ *
+ * If the event is a new event, the event date start and date end timezones are forgotten. The results of
+ * g_date_time_get_year, g_date_time_get_month, g_date_time_get_day_of_month, g_date_time_get_hour and
+ * g_date_time_get_minute are used for the date row and the date time chooser.
+ * The date row timezone is set to UTC (as all day events use the UTC timezone).
+ * The date time chooser timezone is set to local.
+ */
static void
gcal_schedule_section_set_event (GcalEventEditorSection *section,
GcalEvent *event,
GcalEventEditorFlags flags)
{
- g_autoptr (GDateTime) date_start = NULL;
- g_autoptr (GDateTime) date_end = NULL;
+ g_autoptr (GDateTime) date_time_start_utc = NULL;
+ g_autoptr (GDateTime) date_time_end_utc = NULL;
+ g_autoptr (GDateTime) date_time_start_local = NULL;
+ g_autoptr (GDateTime) date_time_end_local = NULL;
+ GcalScheduleSection *self;
+ GDateTime* date_time_start = NULL;
+ GDateTime* date_time_end = NULL;
GcalRecurrenceLimitType limit_type;
GcalRecurrenceFrequency frequency;
- GcalScheduleSection *self;
GcalRecurrence *recur;
- gboolean all_day;
+ gboolean all_day, new_event;
GCAL_ENTRY;
@@ -362,44 +358,69 @@ gcal_schedule_section_set_event (GcalEventEditorSection *section,
GCAL_RETURN ();
all_day = gcal_event_get_all_day (event);
+ new_event = flags & GCAL_EVENT_EDITOR_FLAG_NEW_EVENT;
/* schedule type */
adw_toggle_group_set_active_name (self->schedule_type_toggle_group,
all_day ? "all-day" : "time-slot");
- gtk_widget_set_visible (GTK_WIDGET (self->start_time_row), !all_day);
- gtk_widget_set_visible (GTK_WIDGET (self->end_time_row), !all_day);
-
- /* retrieve start and end dates */
- date_start = gcal_event_get_date_start (event);
- date_start = all_day ? g_date_time_ref (date_start) : g_date_time_to_local (date_start);
+ gtk_widget_set_visible (GTK_WIDGET (self->start_date_group), all_day);
+ gtk_widget_set_visible (GTK_WIDGET (self->end_date_group), all_day);
+ gtk_widget_set_visible (GTK_WIDGET (self->start_date_time_chooser), !all_day);
+ gtk_widget_set_visible (GTK_WIDGET (self->end_date_time_chooser), !all_day);
- date_end = gcal_event_get_date_end (event);
+ /* retrieve start and end date-times */
+ date_time_start = gcal_event_get_date_start (event);
+ date_time_end = gcal_event_get_date_end (event);
/*
* This is subtracting what has been added in action_button_clicked ().
* See bug 769300.
*/
- date_end = all_day ? g_date_time_add_days (date_end, -1) : g_date_time_to_local (date_end);
+ date_time_end = all_day ? g_date_time_add_days (date_time_end, -1) : date_time_end;
+
+ date_time_start_utc = g_date_time_new_utc (g_date_time_get_year (date_time_start),
+ g_date_time_get_month (date_time_start),
+ g_date_time_get_day_of_month (date_time_start),
+ 0, 0, 0);
+
+ date_time_end_utc = g_date_time_new_utc (g_date_time_get_year (date_time_end),
+ g_date_time_get_month (date_time_end),
+ g_date_time_get_day_of_month (date_time_end),
+ 0, 0, 0);
+
+ date_time_start_local = g_date_time_new_local (g_date_time_get_year (date_time_start),
+ g_date_time_get_month (date_time_start),
+ g_date_time_get_day_of_month (date_time_start),
+ g_date_time_get_hour (date_time_start),
+ g_date_time_get_minute (date_time_start),
+ 0);
+
+ date_time_end_local = g_date_time_new_local (g_date_time_get_year (date_time_end),
+ g_date_time_get_month (date_time_end),
+ g_date_time_get_day_of_month (date_time_end),
+ g_date_time_get_hour (date_time_end),
+ g_date_time_get_minute (date_time_end),
+ 0);
+
+ block_date_signals (self);
/* date */
- g_signal_handlers_block_by_func (self->end_date_row, sync_datetimes, self);
- g_signal_handlers_block_by_func (self->start_date_row, sync_datetimes, self);
+ gcal_date_chooser_row_set_date (self->start_date_row, date_time_start_utc);
+ gcal_date_chooser_row_set_date (self->end_date_row, date_time_end_utc);
- gcal_date_chooser_row_set_date (self->start_date_row, date_start);
- gcal_date_chooser_row_set_date (self->end_date_row, date_end);
-
- g_signal_handlers_unblock_by_func (self->start_date_row, sync_datetimes, self);
- g_signal_handlers_unblock_by_func (self->end_date_row, sync_datetimes, self);
-
- /* time */
- g_signal_handlers_block_by_func (self->end_time_row, sync_datetimes, self);
- g_signal_handlers_block_by_func (self->start_time_row, sync_datetimes, self);
-
- gcal_time_chooser_row_set_time (self->start_time_row, date_start);
- gcal_time_chooser_row_set_time (self->end_time_row, date_end);
+ /* date-time */
+ if (new_event || all_day)
+ {
+ gcal_date_time_chooser_set_date_time (self->start_date_time_chooser, date_time_start_local);
+ gcal_date_time_chooser_set_date_time (self->end_date_time_chooser, date_time_end_local);
+ }
+ else
+ {
+ gcal_date_time_chooser_set_date_time (self->start_date_time_chooser, date_time_start);
+ gcal_date_time_chooser_set_date_time (self->end_date_time_chooser, date_time_end);
+ }
- g_signal_handlers_unblock_by_func (self->start_time_row, sync_datetimes, self);
- g_signal_handlers_unblock_by_func (self->end_time_row, sync_datetimes, self);
+ unblock_date_signals (self);
/* Recurrences */
recur = gcal_event_get_recurrence (event);
@@ -440,29 +461,28 @@ gcal_schedule_section_set_event (GcalEventEditorSection *section,
static void
gcal_schedule_section_apply (GcalEventEditorSection *section)
{
- g_autoptr (GDateTime) start_date = NULL;
- g_autoptr (GDateTime) end_date = NULL;
+ GDateTime *start_date, *end_date;
GcalRecurrenceFrequency freq;
GcalScheduleSection *self;
GcalRecurrence *old_recur;
- gboolean was_all_day;
gboolean all_day;
GCAL_ENTRY;
self = GCAL_SCHEDULE_SECTION (section);
- all_day = all_day_selected (self);
- was_all_day = gcal_event_get_all_day (self->event);
- if (!was_all_day && all_day)
- gcal_event_save_original_timezones (self->event);
+ all_day = all_day_selected (self);
- /*
- * Update start & end dates. The dates are already translated to the current
- * timezone (unless the event used to be all day, but no longer is).
- */
- start_date = get_date_start (self);
- end_date = get_date_end (self);
+ if (!all_day)
+ {
+ start_date = gcal_date_time_chooser_get_date_time (self->start_date_time_chooser);
+ end_date = gcal_date_time_chooser_get_date_time (self->end_date_time_chooser);
+ }
+ else
+ {
+ start_date = gcal_date_chooser_row_get_date (self->start_date_row);
+ end_date = gcal_date_chooser_row_get_date (self->end_date_row);
+ }
#ifdef GCAL_ENABLE_TRACE
{
@@ -485,26 +505,8 @@ gcal_schedule_section_apply (GcalEventEditorSection *section)
{
GDateTime *fake_end_date = g_date_time_add_days (end_date, 1);
- g_clear_pointer (&end_date, g_date_time_unref);
end_date = fake_end_date;
}
- else if (!all_day && was_all_day)
- {
- /* When an all day event is changed to be not an all day event, we
- * need to correct for the fact that the event's timezone was until
- * now set to UTC. That means we need to change the timezone to
- * localtime now, or else it will be saved incorrectly.
- */
- GDateTime *localtime_date;
-
- localtime_date = g_date_time_to_local (start_date);
- g_clear_pointer (&start_date, g_date_time_unref);
- start_date = localtime_date;
-
- localtime_date = g_date_time_to_local (end_date);
- g_clear_pointer (&end_date, g_date_time_unref);
- end_date = localtime_date;
- }
gcal_event_set_date_start (self->event, start_date);
gcal_event_set_date_end (self->event, end_date);
@@ -548,9 +550,9 @@ gcal_schedule_section_apply (GcalEventEditorSection *section)
static gboolean
gcal_schedule_section_changed (GcalEventEditorSection *section)
{
- g_autoptr (GDateTime) start_date = NULL;
- g_autoptr (GDateTime) end_date = NULL;
GcalScheduleSection *self;
+ GDateTime *start_date, *end_date, *prev_start_date, *prev_end_date;
+ GTimeZone *start_tz, *end_tz, *prev_start_tz, *prev_end_tz;
gboolean was_all_day;
gboolean all_day;
@@ -564,38 +566,41 @@ gcal_schedule_section_changed (GcalEventEditorSection *section)
if (all_day != was_all_day)
GCAL_RETURN (TRUE);
+ if (!all_day)
+ {
+ start_date = gcal_date_time_chooser_get_date_time (self->start_date_time_chooser);
+ end_date = gcal_date_time_chooser_get_date_time (self->end_date_time_chooser);
+ }
+ else
+ {
+ start_date = gcal_date_chooser_row_get_date (self->start_date_row);
+ end_date = gcal_date_chooser_row_get_date (self->end_date_row);
+ }
+ prev_start_date = gcal_event_get_date_start (self->event);
+ prev_end_date = gcal_event_get_date_end (self->event);
+
+ start_tz = g_date_time_get_timezone (start_date);
+ end_tz = g_date_time_get_timezone (end_date);
+ prev_start_tz = g_date_time_get_timezone (prev_start_date);
+ prev_end_tz = g_date_time_get_timezone (prev_end_date);
+
/* Start date */
- start_date = get_date_start (self);
- if (!g_date_time_equal (start_date, gcal_event_get_date_start (self->event)))
+ if (!g_date_time_equal (start_date, prev_start_date))
+ GCAL_RETURN (TRUE);
+ if (g_strcmp0 (g_time_zone_get_identifier (start_tz), g_time_zone_get_identifier (prev_start_tz)) != 0)
GCAL_RETURN (TRUE);
/* End date */
- end_date = get_date_end (self);
if (all_day)
{
- g_autoptr (GDateTime) fake_end_date = g_date_time_add_days (end_date, 1);
- gcal_set_date_time (&end_date, fake_end_date);
- }
- else if (!all_day && was_all_day)
- {
- /* When an all day event is changed to be not an all day event, we
- * need to correct for the fact that the event's timezone was until
- * now set to UTC. That means we need to change the timezone to
- * localtime now, or else it will be saved incorrectly.
- */
- GDateTime *localtime_date;
-
- localtime_date = g_date_time_to_local (start_date);
- g_clear_pointer (&start_date, g_date_time_unref);
- start_date = localtime_date;
-
- localtime_date = g_date_time_to_local (end_date);
- g_clear_pointer (&end_date, g_date_time_unref);
- end_date = localtime_date;
+ GDateTime *fake_end_date = g_date_time_add_days (end_date, 1);
+ end_date = fake_end_date;
}
if (!g_date_time_equal (end_date, gcal_event_get_date_end (self->event)))
GCAL_RETURN (TRUE);
+ if (g_strcmp0 (g_time_zone_get_identifier (end_tz), g_time_zone_get_identifier (prev_end_tz)) != 0)
+ GCAL_RETURN (TRUE);
/* Recurrency */
GCAL_RETURN (gcal_schedule_section_recurrence_changed (self));
@@ -676,6 +681,8 @@ gcal_schedule_section_class_init (GcalScheduleSectionClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ g_type_ensure (GCAL_TYPE_DATE_TIME_CHOOSER);
+
object_class->finalize = gcal_schedule_section_finalize;
object_class->get_property = gcal_schedule_section_get_property;
object_class->set_property = gcal_schedule_section_set_property;
@@ -685,19 +692,23 @@ gcal_schedule_section_class_init (GcalScheduleSectionClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/calendar/ui/event-editor/gcal-schedule-section.ui");
gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, schedule_type_toggle_group);
+ gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, start_date_group);
gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, start_date_row);
- gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, start_time_row);
+ gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, end_date_group);
gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, end_date_row);
- gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, end_time_row);
+ gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, start_date_time_chooser);
+ gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, end_date_time_chooser);
gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, number_of_occurrences_spin);
gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, repeat_combo);
gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, repeat_duration_combo);
gtk_widget_class_bind_template_child (widget_class, GcalScheduleSection, until_date_selector);
- gtk_widget_class_bind_template_callback (widget_class, on_schedule_type_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_start_date_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_end_date_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_start_date_time_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_end_date_time_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, on_repeat_duration_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, on_repeat_type_changed_cb);
- gtk_widget_class_bind_template_callback (widget_class, sync_datetimes);
}
static void
@@ -705,7 +716,10 @@ gcal_schedule_section_init (GcalScheduleSection *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
- on_time_format_changed_cb (self);
+ g_signal_connect (self->schedule_type_toggle_group,
+ "notify::active",
+ G_CALLBACK (on_schedule_type_changed_cb),
+ self);
}
gboolean
@@ -734,15 +748,25 @@ gcal_schedule_section_recurrence_changed (GcalScheduleSection *self)
gboolean
gcal_schedule_section_day_changed (GcalScheduleSection *self)
{
- g_autoptr (GDateTime) start_date = NULL;
- g_autoptr (GDateTime) end_date = NULL;
+ GDateTime *start_date, *end_date;
+ gboolean all_day;
g_return_val_if_fail (GCAL_IS_SCHEDULE_SECTION (self), FALSE);
GCAL_ENTRY;
- start_date = get_date_start (self);
- end_date = get_date_end (self);
+ all_day = all_day_selected (self);
+
+ if (all_day)
+ {
+ start_date = gcal_date_time_chooser_get_date_time (self->start_date_time_chooser);
+ end_date = gcal_date_time_chooser_get_date_time (self->end_date_time_chooser);
+ }
+ else
+ {
+ start_date = gcal_date_chooser_row_get_date (self->start_date_row);
+ end_date = gcal_date_chooser_row_get_date (self->end_date_row);
+ }
GCAL_RETURN (gcal_date_time_compare_date (start_date, gcal_event_get_date_start (self->event)) < 0 ||
gcal_date_time_compare_date (end_date, gcal_event_get_date_end (self->event)) > 0);
diff --git a/src/gui/event-editor/gcal-schedule-section.ui b/src/gui/event-editor/gcal-schedule-section.ui
index dbc2fe1231e440ee89fc6b7715f8d7bcfc46b479..23e47e1eed4f12fe031eb36ef4a413732d7d6630 100644
--- a/src/gui/event-editor/gcal-schedule-section.ui
+++ b/src/gui/event-editor/gcal-schedule-section.ui
@@ -21,61 +21,46 @@
time-slot
-
+
-
- True
- 12
-
-
+
-
-
-
- Start Date
-
-
-
-
-
-
- Start Time
-
-
-
+
+ Start Date
+
-
+
-
- True
- 12
-
-
+
-
-
-
- End Date
-
-
-
-
-
-
- End Time
-
-
-
+
+ End Date
+
+
+
+
+
+
+ Start Date
+ Start Time
+
+
+
+
+
+ End Date
+ End Time
+
diff --git a/src/gui/event-editor/gcal-time-chooser-row.c b/src/gui/event-editor/gcal-time-chooser-row.c
deleted file mode 100644
index 0612d058ec108745923fc0891bdcff951adddb01..0000000000000000000000000000000000000000
--- a/src/gui/event-editor/gcal-time-chooser-row.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/* gcal-time-chooser-row.c
- *
- * Copyright (C) 2024 Titouan Real
- *
- * 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 .
- */
-
-#define G_LOG_DOMAIN "GcalTimeChooserRow"
-
-#include "gcal-time-chooser-row.h"
-#include "gcal-time-selector.h"
-
-#include
-#include
-#include
-#include
-
-struct _GcalTimeChooserRow
-{
- AdwEntryRow parent;
-
- /* widgets */
- GcalTimeSelector *time_selector;
-
- GcalTimeFormat time_format;
-};
-
-G_DEFINE_TYPE (GcalTimeChooserRow, gcal_time_chooser_row, ADW_TYPE_ENTRY_ROW);
-
-enum
-{
- PROP_0,
- PROP_TIME_FORMAT,
- PROP_TIME,
- N_PROPS
-};
-
-static GParamSpec* properties[N_PROPS] = { NULL, };
-
-
-/*
- * Auxiliary methods
- */
-
-static void
-update_entry (GcalTimeChooserRow *self)
-{
- g_autofree gchar *label = NULL;
- GDateTime *time;
-
- time = gcal_time_selector_get_time (self->time_selector);
-
- switch (self->time_format)
- {
- case GCAL_TIME_FORMAT_12H:
- label = g_date_time_format (time, "%I:%M %p");
- break;
-
- case GCAL_TIME_FORMAT_24H:
- label = g_date_time_format (time, "%R");
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- gtk_editable_set_text (GTK_EDITABLE (self), label);
-}
-
-static GRegex*
-get_12h_regex (void)
-{
- static GRegex *regex = NULL;
-
- if (g_once_init_enter_pointer (®ex))
- {
- g_autoptr (GError) error = NULL;
- g_autofree gchar *str = NULL;
-
- str = g_strdup_printf ("^(?[0-9]{1,2})([\\-:./_,'a-z](?[0-9]{1,2}))? ?(?%s|%s)",
- _("AM"), _("PM"));
-
- regex = g_regex_new (str, G_REGEX_CASELESS, 0, &error);
-
- if (error)
- g_error ("Failed to compile regex: %s. Aborting...", error->message);
- }
-
- return regex;
-}
-
-static GRegex*
-get_24h_regex (void)
-{
- static GRegex *regex = NULL;
-
- if (g_once_init_enter_pointer (®ex))
- {
- g_autoptr (GError) error = NULL;
-
- regex = g_regex_new ("^(?[0-9]{1,2})([\\-:./_,'a-z](?[0-9]{1,2}))?", G_REGEX_CASELESS, 0, &error);
-
- if (error)
- g_error ("Failed to compile regex: %s. Aborting...", error->message);
- }
-
- return regex;
-}
-
-static void
-parse_time (GcalTimeChooserRow *self)
-{
- g_autoptr (GDateTime) now = NULL;
- const gchar *text;
-
- text = gtk_editable_get_text (GTK_EDITABLE (self));
- now = g_date_time_new_now_local ();
-
- switch (self->time_format)
- {
- case GCAL_TIME_FORMAT_12H:
- {
- g_autoptr (GMatchInfo) match_info = NULL;
- g_autoptr (GDateTime) time = NULL;
- g_autofree gchar *minute_str = NULL;
- g_autofree gchar *hour_str = NULL;
- g_autofree gchar *ampm_str = NULL;
- gboolean am;
- gint64 hour, minute;
-
- if (!g_regex_match (get_12h_regex (), text, 0, &match_info))
- {
- update_entry (self);
- break;
- }
-
- hour_str = g_match_info_fetch_named (match_info, "hour");
- minute_str = g_match_info_fetch_named (match_info, "minute");
- ampm_str = g_match_info_fetch_named (match_info, "ampm");
-
- hour = g_ascii_strtoll (hour_str, NULL, 10);
- minute = g_ascii_strtoll (minute_str, NULL, 10);
- am = (strcmp (g_ascii_strup (ampm_str, -1), _("AM")) == 0);
-
- /* Allow 12AM and 12PM */
- if ((hour > 11 || minute > 59) && !(hour == 12 && minute == 0))
- {
- update_entry (self);
- break;
- }
-
- if (hour == 12)
- {
- g_assert (minute == 0);
- hour = 0;
- }
-
- if (!am)
- hour += 12;
-
- now = g_date_time_new_now_local ();
- 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);
-
- gcal_time_chooser_row_set_time (self, time);
-
- }
- break;
-
- case GCAL_TIME_FORMAT_24H:
- {
- g_autoptr (GMatchInfo) match_info = NULL;
- g_autoptr (GDateTime) time = NULL;
- g_autofree gchar *minute_str = NULL;
- g_autofree gchar *hour_str = NULL;
- g_autofree gchar *ampm_str = NULL;
- gint64 hour, minute;
-
- if (!g_regex_match (get_24h_regex (), text, 0, &match_info))
- {
- update_entry (self);
- break;
- }
-
- hour_str = g_match_info_fetch_named (match_info, "hour");
- minute_str = g_match_info_fetch_named (match_info, "minute");
-
- hour = g_ascii_strtoll (hour_str, NULL, 10);
- minute = g_ascii_strtoll (minute_str, NULL, 10);
-
- if (hour > 23 || minute > 59)
- {
- update_entry (self);
- break;
- }
-
- 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);
-
- gcal_time_chooser_row_set_time (self, time);
-
- }
- break;
-
- default:
- g_assert_not_reached ();
- }
-}
-
-
-/*
- * Callbacks
- */
-
-static void
-on_contains_focus_changed_cb (GtkEventControllerFocus *focus_controller,
- GParamSpec *pspec,
- GcalTimeChooserRow *self)
-{
- parse_time (self);
-}
-
-static void
-on_time_selected_changed_cb (GcalTimeSelector *selector,
- GParamSpec *pspec,
- GcalTimeChooserRow *self)
-{
- update_entry (self);
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TIME]);
-}
-
-static void
-on_time_popover_shown_cb (GtkPopover *popover,
- GcalTimeChooserRow *self)
-{
- parse_time (self);
-}
-
-
-/*
- * GObject overrides
- */
-
-static void
-gcal_time_chooser_row_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GcalTimeChooserRow *self = GCAL_TIME_CHOOSER_ROW (object);
-
- switch (prop_id)
- {
- case PROP_TIME_FORMAT:
- g_value_set_enum (value, self->time_format);
- break;
-
- case PROP_TIME:
- g_value_set_boxed (value, gcal_time_chooser_row_get_time (self));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-gcal_time_chooser_row_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GcalTimeChooserRow *self = GCAL_TIME_CHOOSER_ROW (object);
-
- switch (prop_id)
- {
- case PROP_TIME_FORMAT:
- gcal_time_chooser_row_set_time_format (self, g_value_get_enum (value));
- break;
-
- case PROP_TIME:
- gcal_time_chooser_row_set_time (self, g_value_get_boxed (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-gcal_time_chooser_row_class_init (GcalTimeChooserRowClass *klass)
-{
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->get_property = gcal_time_chooser_row_get_property;
- object_class->set_property = gcal_time_chooser_row_set_property;
-
- properties[PROP_TIME_FORMAT] = g_param_spec_enum ("time-format", NULL, NULL,
- GCAL_TYPE_TIME_FORMAT,
- GCAL_TIME_FORMAT_24H,
- G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
- properties[PROP_TIME] = g_param_spec_boxed ("time", NULL, NULL,
- G_TYPE_DATE_TIME,
- G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties (object_class, N_PROPS, properties);
-
- gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/calendar/ui/event-editor/gcal-time-chooser-row.ui");
-
- gtk_widget_class_bind_template_child (widget_class, GcalTimeChooserRow, time_selector);
-
- gtk_widget_class_bind_template_callback (widget_class, on_contains_focus_changed_cb);
- gtk_widget_class_bind_template_callback (widget_class, on_time_selected_changed_cb);
- gtk_widget_class_bind_template_callback (widget_class, on_time_popover_shown_cb);
-}
-
-static void
-gcal_time_chooser_row_init (GcalTimeChooserRow *self)
-{
- gtk_widget_init_template (GTK_WIDGET (self));
-
- self->time_format = GCAL_TIME_FORMAT_24H;
-}
-
-GcalTimeFormat
-gcal_time_chooser_row_get_time_format (GcalTimeChooserRow *self)
-{
- g_return_val_if_fail (GCAL_IS_TIME_CHOOSER_ROW (self), 0);
-
- return self->time_format;
-}
-
-void
-gcal_time_chooser_row_set_time_format (GcalTimeChooserRow *self,
- GcalTimeFormat time_format)
-{
- g_return_if_fail (GCAL_IS_TIME_CHOOSER_ROW (self));
-
- if (self->time_format == time_format)
- return;
-
- self->time_format = time_format;
-
- gcal_time_selector_set_time_format (self->time_selector, time_format);
- update_entry (self);
-}
-
-/**
- * gcal_time_chooser_row_set_time:
- * @selector: a #GcalTimeChooserRow
- * @date: a valid #GDateTime
- *
- * Set the value of the shown time.
- */
-void
-gcal_time_chooser_row_set_time (GcalTimeChooserRow *self,
- GDateTime *time)
-{
- g_return_if_fail (GCAL_IS_TIME_CHOOSER_ROW (self));
-
- gcal_time_selector_set_time (self->time_selector, time);
- update_entry (self);
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TIME]);
-}
-
-/**
- * gcal_time_chooser_row_get_time:
- * @selector: a #GcalTimeChooserRow
- *
- * Get the value of the time shown
- *
- * Returns: (transfer none): the time of the selector.
- */
-GDateTime*
-gcal_time_chooser_row_get_time (GcalTimeChooserRow *self)
-{
- g_return_val_if_fail (GCAL_IS_TIME_CHOOSER_ROW (self), NULL);
-
- return gcal_time_selector_get_time (self->time_selector);
-}
diff --git a/src/gui/event-editor/gcal-time-selector.c b/src/gui/event-editor/gcal-time-selector.c
deleted file mode 100644
index 2b466db34a540abebbd9108b93d561db70513b2e..0000000000000000000000000000000000000000
--- a/src/gui/event-editor/gcal-time-selector.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/* gcal-time-selector.c
- *
- * Copyright (C) 2015 Erick Pérez Castellanos
- * 2014 Georges Basile Stavracas Neto
- *
- * 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 .
- */
-
-#define G_LOG_DOMAIN "GcalTimeSelector"
-
-#include "gcal-date-time-utils.h"
-#include "gcal-time-selector.h"
-
-#include
-
-struct _GcalTimeSelector
-{
- GtkBox parent;
-
- GtkAdjustment *hour_adjustment;
- GtkAdjustment *minute_adjustment;
-
- GtkWidget *time_box;
- GtkWidget *hour_spin;
- GtkWidget *minute_spin;
- GtkWidget *period_toggle_group;
-
- GDateTime *time;
-
- GcalTimeFormat time_format;
-};
-
-enum
-{
- PROP_0,
- PROP_TIME,
- LAST_PROP
-};
-
-G_DEFINE_TYPE (GcalTimeSelector, gcal_time_selector, GTK_TYPE_BOX);
-
-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->time_format == GCAL_TIME_FORMAT_12H)
- {
- hour = hour % 12;
-
- if (g_strcmp0 (adw_toggle_group_get_active_name (ADW_TOGGLE_GROUP (selector->period_toggle_group)), "pm") == 0)
- hour += 12;
- }
-
- 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 void
-on_period_toggle_changed_cb (GtkWidget *widget,
- GParamSpec *pspec,
- GcalTimeSelector *selector)
-{
- update_time (selector);
-}
-
-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_editable_set_text (GTK_EDITABLE (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,
- GcalTimeFormat time_format)
-{
- g_return_if_fail (GCAL_IS_TIME_SELECTOR (selector));
-
- selector->time_format = time_format;
- gtk_widget_set_visible (selector->period_toggle_group, time_format == GCAL_TIME_FORMAT_12H);
-
- if (time_format == GCAL_TIME_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->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/ui/event-editor/gcal-time-selector.ui");
-
- gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GcalTimeSelector, time_box);
- 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_toggle_group);
-
- gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), on_output);
- gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), update_time);
- gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), on_period_toggle_changed_cb);
-}
-
-static void
-gcal_time_selector_init (GcalTimeSelector *self)
-{
- self->time = g_date_time_new_now_local ();
-
- gtk_widget_init_template (GTK_WIDGET (self));
-
- if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL)
- gtk_widget_set_direction (self->time_box, 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;
-
- if (selector->time &&
- time &&
- g_date_time_get_hour (selector->time) == g_date_time_get_hour (time) &&
- g_date_time_get_minute (selector->time) == g_date_time_get_minute (time) &&
- g_date_time_get_second (selector->time) == g_date_time_get_second (time))
- {
- return;
- }
-
- gcal_set_date_time (&selector->time, time);
-
- /* 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->time_format == GCAL_TIME_FORMAT_12H)
- {
- g_signal_handlers_block_by_func (selector->period_toggle_group, on_period_toggle_changed_cb, selector);
-
- adw_toggle_group_set_active_name (ADW_TOGGLE_GROUP (selector->period_toggle_group), hour >= 12 ? "pm" : "am");
- hour = hour % 12;
- hour = (hour == 0)? 12 : hour;
-
- g_signal_handlers_unblock_by_func (selector->period_toggle_group, on_period_toggle_changed_cb, selector);
- }
-
- gtk_adjustment_set_value (selector->hour_adjustment, hour);
- gtk_adjustment_set_value (selector->minute_adjustment, minute);
-
- 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;
-}
diff --git a/src/gui/event-editor/gcal-time-selector.h b/src/gui/event-editor/gcal-time-selector.h
deleted file mode 100644
index 84c2147c9f34860e1b42965045e9a6b02d4ad29f..0000000000000000000000000000000000000000
--- a/src/gui/event-editor/gcal-time-selector.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* gcal-time-selector.h
- *
- * Copyright (C) 2015 Erick Pérez Castellanos
- *
- * 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 .
- */
-
-#ifndef __GCAL_TIME_SELECTOR_H__
-#define __GCAL_TIME_SELECTOR_H__
-
-#include "gcal-enums.h"
-
-#include
-
-G_BEGIN_DECLS
-
-#define GCAL_TYPE_TIME_SELECTOR (gcal_time_selector_get_type ())
-G_DECLARE_FINAL_TYPE (GcalTimeSelector, gcal_time_selector, GCAL, TIME_SELECTOR, GtkBox)
-
-GtkWidget* gcal_time_selector_new (void);
-
-void gcal_time_selector_set_time_format (GcalTimeSelector *selector,
- GcalTimeFormat time_format);
-
-GDateTime* gcal_time_selector_get_time (GcalTimeSelector *selector);
-
-void gcal_time_selector_set_time (GcalTimeSelector *selector,
- GDateTime *time);
-
-G_END_DECLS
-
-#endif /* __GCAL_TIME_SELECTOR_H__ */
diff --git a/src/gui/event-editor/gcal-time-selector.ui b/src/gui/event-editor/gcal-time-selector.ui
deleted file mode 100644
index 6aa5540a6b8ba1238fcbe619150864c047540ccb..0000000000000000000000000000000000000000
--- a/src/gui/event-editor/gcal-time-selector.ui
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
- 6
-
-
-
- 6
-
-
-
-
- 0.5
- vertical
- hour_adjustment
-
-
-
-
-
-
- :
-
-
-
-
-
-
- 0.5
- vertical
- minute_adjustment
-
-
-
-
-
-
-
-
-
- False
- center
- am
- vertical
-
-
- AM
- am
-
-
-
-
- PM
- pm
-
-
-
-
-
-
-
-
- 23
- 1
- 5
-
-
-
- 59
- 1
- 10
-
-
-
diff --git a/src/gui/event-editor/gcal-time-zone-dialog-row.c b/src/gui/event-editor/gcal-time-zone-dialog-row.c
new file mode 100644
index 0000000000000000000000000000000000000000..2f0b00830bb1858849b85605e2d21012fa550503
--- /dev/null
+++ b/src/gui/event-editor/gcal-time-zone-dialog-row.c
@@ -0,0 +1,89 @@
+/* gcal-time-zone-dialog-row.c
+ *
+ * Copyright (C) 2024 Titouan Real
+ *
+ * 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 .
+ */
+#include "config.h"
+
+#define G_LOG_DOMAIN "GcalTimeZoneDialogRow"
+
+#include "gcal-time-zone-dialog-row.h"
+
+struct _GcalTimeZoneDialogRow
+{
+ AdwActionRow parent;
+
+ GWeatherLocation *location;
+};
+
+G_DEFINE_TYPE (GcalTimeZoneDialogRow, gcal_time_zone_dialog_row, ADW_TYPE_ACTION_ROW)
+
+
+/*
+ * Auxiliary methods
+ */
+
+
+/*
+ * Callbacks
+ */
+
+
+/*
+ * Gobject overrides
+ */
+
+static void
+gcal_time_zone_dialog_row_class_init (GcalTimeZoneDialogRowClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/calendar/ui/event-editor/gcal-time-zone-dialog-row.ui");
+}
+
+static void
+gcal_time_zone_dialog_row_init (GcalTimeZoneDialogRow *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+/**
+ * gcal_time_zone_dialog_row_new:
+ *
+ * Creates a new #GcalTimeZoneDialogRow
+ *
+ * Returns: (transfer full): a #GcalTimeZoneDialogRow
+ */
+GtkWidget*
+gcal_time_zone_dialog_row_new (GWeatherLocation *location)
+{
+ GtkWidget *widget = g_object_new (GCAL_TYPE_TIME_ZONE_DIALOG_ROW, NULL);
+
+ (GCAL_TIME_ZONE_DIALOG_ROW (widget))->location = g_object_ref (location);
+
+ return widget;
+}
+
+/**
+ * gcal_time_zone_dialog_row_get_location:
+ * @self: a #GcalTimeZoneDialogRow
+ *
+ * Returns: (transfer none): a #GWeatherLocation
+ */
+GWeatherLocation*
+gcal_time_zone_dialog_row_get_location (GcalTimeZoneDialogRow *self)
+{
+ return self->location;
+}
diff --git a/src/gui/event-editor/gcal-time-zone-dialog-row.h b/src/gui/event-editor/gcal-time-zone-dialog-row.h
new file mode 100644
index 0000000000000000000000000000000000000000..262596b42d4a0870c3578bd9d3bbadf713f4881a
--- /dev/null
+++ b/src/gui/event-editor/gcal-time-zone-dialog-row.h
@@ -0,0 +1,34 @@
+/* gcal-time-zone-dialog-row.h
+ *
+ * Copyright (C) 2024 Titouan Real
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include
+
+#include "libgweather/gweather.h"
+
+G_BEGIN_DECLS
+
+#define GCAL_TYPE_TIME_ZONE_DIALOG_ROW (gcal_time_zone_dialog_row_get_type ())
+G_DECLARE_FINAL_TYPE (GcalTimeZoneDialogRow, gcal_time_zone_dialog_row, GCAL, TIME_ZONE_DIALOG_ROW, AdwActionRow);
+
+GtkWidget* gcal_time_zone_dialog_row_new (GWeatherLocation *location);
+
+GWeatherLocation* gcal_time_zone_dialog_row_get_location (GcalTimeZoneDialogRow *self);
+
+G_END_DECLS
diff --git a/src/gui/event-editor/gcal-time-zone-dialog-row.ui b/src/gui/event-editor/gcal-time-zone-dialog-row.ui
new file mode 100644
index 0000000000000000000000000000000000000000..70fc7ccae39a5060572e24f6448906df9e558228
--- /dev/null
+++ b/src/gui/event-editor/gcal-time-zone-dialog-row.ui
@@ -0,0 +1,9 @@
+
+
+
+ true
+
+
+
diff --git a/src/gui/event-editor/gcal-time-zone-dialog.c b/src/gui/event-editor/gcal-time-zone-dialog.c
new file mode 100644
index 0000000000000000000000000000000000000000..0eb97069fc956f3de21c0a2b5eb09e7b10bf03f3
--- /dev/null
+++ b/src/gui/event-editor/gcal-time-zone-dialog.c
@@ -0,0 +1,313 @@
+/* gcal-time-zone-dialog.c
+ *
+ * Copyright (C) 2024 Titouan Real
+ *
+ * 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 .
+ */
+#include "config.h"
+
+#define G_LOG_DOMAIN "GcalTimeZoneDialog"
+
+#include "gcal-date-time-utils.h"
+#include "gcal-debug.h"
+#include "gcal-time-zone-dialog.h"
+#include "gcal-time-zone-dialog-row.h"
+
+#include
+
+#define RESULT_COUNT_LIMIT 12
+
+struct _GcalTimeZoneDialog
+{
+ AdwDialog parent;
+
+ GtkStack *stack;
+ AdwStatusPage *empty_search;
+ GtkScrolledWindow *search_results;
+ GtkSearchEntry *location_entry;
+ GtkListBox *listbox;
+
+ GListStore *locations;
+ GTimeZone *time_zone;
+ GDateTime *date_time;
+};
+
+G_DEFINE_TYPE (GcalTimeZoneDialog, gcal_time_zone_dialog, ADW_TYPE_DIALOG)
+
+enum
+{
+ TIME_ZONE_SELECTED,
+ N_SIGNALS,
+};
+
+static guint signals [N_SIGNALS] = { 0, };
+
+
+/*
+ * Auxiliary methods
+ */
+
+static GtkWidget*
+create_row (gpointer item,
+ gpointer user_data)
+{
+ GcalTimeZoneDialog *self = (GcalTimeZoneDialog *) user_data;
+ g_autoptr (GDateTime) date_time = NULL;
+ g_autofree gchar *country_name = NULL;
+ g_autofree gchar *utc_str = NULL;
+ g_autofree gchar *label = NULL;
+ GWeatherLocation *location;
+ AdwActionRow *row;
+
+ g_assert (GCAL_IS_TIME_ZONE_DIALOG (self));
+ g_assert (GWEATHER_IS_LOCATION (item));
+
+ location = GWEATHER_LOCATION (item);
+
+ country_name = gweather_location_get_country_name (location);
+ if (country_name)
+ {
+ /* Translators: "%1$s" is the city / region name, and
+ * "%2$s" is the country name (already localized).
+ */
+ label = g_strdup_printf (_("%1$s, %2$s"),
+ gweather_location_get_name (location),
+ country_name);
+ }
+ else
+ {
+ label = g_strdup (gweather_location_get_name (location));
+ }
+
+
+ date_time = g_date_time_new (gweather_location_get_timezone (location),
+ g_date_time_get_year (self->date_time),
+ g_date_time_get_month (self->date_time),
+ g_date_time_get_day_of_month (self->date_time),
+ g_date_time_get_hour (self->date_time),
+ g_date_time_get_minute (self->date_time),
+ 0);
+ utc_str = gcal_date_time_format_utc_offset (date_time);
+
+ row = ADW_ACTION_ROW (gcal_time_zone_dialog_row_new (location));
+ adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), utc_str);
+ adw_action_row_set_subtitle (row, label);
+
+ return GTK_WIDGET (row);
+}
+
+static void
+query_locations (GcalTimeZoneDialog *self,
+ GWeatherLocation *location,
+ gchar *search)
+{
+ gboolean contains_name;
+ GWeatherLocation *loc;
+ GTimeZone *timezone;
+ const gchar *name, *country_name;
+
+ timezone = gweather_location_get_timezone (location);
+
+ if (timezone)
+ {
+ name = gweather_location_get_name (location);
+ country_name = gweather_location_get_country_name (location);
+
+ contains_name = name != NULL && g_strrstr (g_utf8_casefold (g_utf8_normalize (name, -1, G_NORMALIZE_ALL), -1), search) != NULL;
+ contains_name = contains_name | (country_name != NULL && g_strrstr (g_utf8_casefold (g_utf8_normalize (country_name, -1, G_NORMALIZE_ALL), -1), search) != NULL);
+
+ if (g_list_model_get_n_items (G_LIST_MODEL (self->locations)) >= RESULT_COUNT_LIMIT)
+ return;
+
+ switch (gweather_location_get_level (location))
+ {
+ case GWEATHER_LOCATION_CITY:
+ if (contains_name)
+ g_list_store_append (self->locations, location);
+ return;
+
+ case GWEATHER_LOCATION_NAMED_TIMEZONE:
+ if (contains_name)
+ g_list_store_append (self->locations, location);
+ return;
+
+ default:
+ break;
+ }
+ }
+
+ loc = gweather_location_next_child (location, NULL);
+ while (loc)
+ {
+ query_locations (self, loc, search);
+ if (g_list_model_get_n_items (G_LIST_MODEL (self->locations)) >= RESULT_COUNT_LIMIT)
+ return;
+
+ loc = gweather_location_next_child (location, loc);
+ }
+}
+
+
+/*
+ * Callbacks
+ */
+
+static void
+on_search_changed (GtkSearchEntry *entry,
+ GcalTimeZoneDialog *self)
+{
+ gchar *temp, *search;
+ GWeatherLocation *world_location;
+
+ g_list_store_remove_all (self->locations);
+
+ if (g_strcmp0 (gtk_editable_get_text (GTK_EDITABLE (self->location_entry)), "") == 0)
+ {
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->empty_search));
+ return;
+ }
+
+ temp = g_utf8_normalize (gtk_editable_get_text (GTK_EDITABLE (self->location_entry)), -1, G_NORMALIZE_ALL);
+ search = g_utf8_casefold (temp, -1);
+ g_free(temp);
+
+ world_location = gweather_location_get_world ();
+ if (!world_location)
+ return;
+
+ query_locations (self, world_location, search);
+
+ if (g_list_model_get_n_items (G_LIST_MODEL (self->locations)) == 0)
+ {
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->empty_search));
+ return;
+ }
+
+ gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->search_results));
+}
+
+static void
+on_stop_search_cb (GtkSearchEntry *entry,
+ GcalTimeZoneDialog *self)
+{
+ adw_dialog_close (ADW_DIALOG (self));
+}
+
+static void
+on_row_activated_cb (GtkListBox *list_box,
+ GtkListBoxRow *list_box_row,
+ GcalTimeZoneDialog *self)
+{
+ GcalTimeZoneDialogRow *row;
+ GWeatherLocation *location;
+ GTimeZone *time_zone;
+
+ GCAL_ENTRY;
+
+ row = GCAL_TIME_ZONE_DIALOG_ROW (list_box_row);
+
+ location = gcal_time_zone_dialog_row_get_location (row);
+ time_zone = gweather_location_get_timezone (location);
+
+ // The dialog only shows locations that have a timezone.
+ g_assert (time_zone != NULL);
+
+ self->time_zone = g_time_zone_new_identifier (g_time_zone_get_identifier (time_zone));
+
+ g_signal_emit (self, signals[TIME_ZONE_SELECTED], 0);
+
+ adw_dialog_close (ADW_DIALOG (self));
+
+ GCAL_EXIT;
+}
+
+
+/*
+ * Gobject overrides
+ */
+
+static void
+gcal_time_zone_dialog_class_init (GcalTimeZoneDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ signals[TIME_ZONE_SELECTED] = g_signal_new ("timezone-selected",
+ GCAL_TYPE_TIME_ZONE_DIALOG,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/calendar/ui/event-editor/gcal-time-zone-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GcalTimeZoneDialog, stack);
+ gtk_widget_class_bind_template_child (widget_class, GcalTimeZoneDialog, empty_search);
+ gtk_widget_class_bind_template_child (widget_class, GcalTimeZoneDialog, search_results);
+ gtk_widget_class_bind_template_child (widget_class, GcalTimeZoneDialog, location_entry);
+ gtk_widget_class_bind_template_child (widget_class, GcalTimeZoneDialog, listbox);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_search_changed);
+ gtk_widget_class_bind_template_callback (widget_class, on_stop_search_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_row_activated_cb);
+}
+
+static void
+gcal_time_zone_dialog_init (GcalTimeZoneDialog *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_search_entry_set_key_capture_widget (self->location_entry, GTK_WIDGET (self));
+
+ self->locations = g_list_store_new (GWEATHER_TYPE_LOCATION);
+
+ gtk_list_box_bind_model (self->listbox,
+ G_LIST_MODEL (self->locations),
+ create_row,
+ self,
+ NULL);
+}
+
+/**
+ * gcal_time_zone_dialog_new:
+ * @date_time: a #GDateTime
+ *
+ * Creates a new #GcalTimeZoneDialog
+ *
+ * Returns: (transfer full): a #GcalTimeZoneDialog
+ */
+GtkWidget*
+gcal_time_zone_dialog_new (GDateTime *date_time)
+{
+ GcalTimeZoneDialog *dialog = g_object_new (GCAL_TYPE_TIME_ZONE_DIALOG, NULL);
+
+ dialog->date_time = g_date_time_ref (date_time);
+
+ return GTK_WIDGET (dialog);
+}
+
+/**
+ * gcal_time_zone_dialog_get_time_zone:
+ * @self: a #GcalTimeZoneDialog
+ *
+ * Get the value of the selected timezone
+ *
+ * Returns: (transfer none): the timezone selected in the dialog.
+ */
+GTimeZone*
+gcal_time_zone_dialog_get_time_zone (GcalTimeZoneDialog *self)
+{
+ return self->time_zone;
+}
diff --git a/src/gui/event-editor/gcal-time-zone-dialog.h b/src/gui/event-editor/gcal-time-zone-dialog.h
new file mode 100644
index 0000000000000000000000000000000000000000..276a0468029a5a23343d67e4a6c0212825209858
--- /dev/null
+++ b/src/gui/event-editor/gcal-time-zone-dialog.h
@@ -0,0 +1,34 @@
+/* gcal-time-zone-dialog.h
+ *
+ * Copyright (C) 2024 Titouan Real
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include
+
+#include "libgweather/gweather.h"
+
+G_BEGIN_DECLS
+
+#define GCAL_TYPE_TIME_ZONE_DIALOG (gcal_time_zone_dialog_get_type ())
+G_DECLARE_FINAL_TYPE (GcalTimeZoneDialog, gcal_time_zone_dialog, GCAL, TIME_ZONE_DIALOG, AdwDialog);
+
+GtkWidget* gcal_time_zone_dialog_new (GDateTime *date_time);
+
+GTimeZone* gcal_time_zone_dialog_get_time_zone (GcalTimeZoneDialog *self);
+
+G_END_DECLS
diff --git a/src/gui/event-editor/gcal-time-zone-dialog.ui b/src/gui/event-editor/gcal-time-zone-dialog.ui
new file mode 100644
index 0000000000000000000000000000000000000000..677538b1b87c6d0707162a442c3dc8fab3a11b9f
--- /dev/null
+++ b/src/gui/event-editor/gcal-time-zone-dialog.ui
@@ -0,0 +1,60 @@
+
+
+
+ Select Timezone
+ 400
+ 540
+
+
+
+
+
+
+
+
+
+ Search Locations
+
+
+
+
+
+
+
+
+
+
+
+ loupe-large-symbolic
+ Search for a Timezone
+
+
+
+
+
+
+
+
+
+ start
+ True
+ none
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/gui/event-editor/meson.build b/src/gui/event-editor/meson.build
index dcc40a13dc72b96487ee8d4ed6df1bd5c618139c..7e7abb2d9fcb797fe637e834ad8cc8f9870778f2 100644
--- a/src/gui/event-editor/meson.build
+++ b/src/gui/event-editor/meson.build
@@ -11,6 +11,7 @@ sources += files(
'gcal-date-chooser.c',
'gcal-date-chooser-day.c',
'gcal-date-chooser-row.c',
+ 'gcal-date-time-chooser.c',
'gcal-date-selector.c',
'gcal-event-editor-dialog.c',
'gcal-event-editor-section.c',
@@ -19,6 +20,6 @@ sources += files(
'gcal-reminders-section.c',
'gcal-schedule-section.c',
'gcal-summary-section.c',
- 'gcal-time-chooser-row.c',
- 'gcal-time-selector.c',
+ 'gcal-time-zone-dialog.c',
+ 'gcal-time-zone-dialog-row.c',
)
diff --git a/src/gui/gcal-window.c b/src/gui/gcal-window.c
index 2f88560b136c008272e5da3f396a79d08ab19dc5..f6446470c10125b2aaaf775910fae44a04cb6500 100644
--- a/src/gui/gcal-window.c
+++ b/src/gui/gcal-window.c
@@ -490,11 +490,10 @@ on_window_new_event_cb (GSimpleAction *action,
GcalEvent *event;
self = GCAL_WINDOW (user_data);
- start = g_date_time_new (gcal_context_get_timezone (self->context),
- g_date_time_get_year (self->active_date),
- g_date_time_get_month (self->active_date),
- g_date_time_get_day_of_month (self->active_date),
- 0, 0, 0);
+ start = g_date_time_new_utc (g_date_time_get_year (self->active_date),
+ g_date_time_get_month (self->active_date),
+ g_date_time_get_day_of_month (self->active_date),
+ 0, 0, 0);
end = g_date_time_add_days (start, 1);
manager = gcal_context_get_manager (self->context);
diff --git a/src/gui/icons/check-plain-symbolic.svg b/src/gui/icons/check-plain-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..096db07804da8ceefc25883013801347f6c18072
--- /dev/null
+++ b/src/gui/icons/check-plain-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/src/gui/icons/globe-symbolic.svg b/src/gui/icons/globe-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..40184d655c7cf0cdb1a2f7b686bfa72c630a9299
--- /dev/null
+++ b/src/gui/icons/globe-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/src/gui/icons/icons.gresource.xml b/src/gui/icons/icons.gresource.xml
index 2fe45bb1549ffd95fe7d77fc6ac0bb0ad5e3ae55..4ec18af5719e4ca0a85f513d102a55549b1a7907 100644
--- a/src/gui/icons/icons.gresource.xml
+++ b/src/gui/icons/icons.gresource.xml
@@ -5,11 +5,14 @@
calendar-month-symbolic.svg
calendar-week-symbolic.svg
calendar-today-symbolic.svg
+ check-plain-symbolic.svg
clock-alt-symbolic.svg
checkmark-small-symbolic.svg
external-link-symbolic.svg
edit-symbolic.svg
eye-not-looking-symbolic.svg
+ globe-symbolic.svg
info-outline-symbolic.svg
+ loupe-large-symbolic.svg
diff --git a/src/gui/icons/loupe-large-symbolic.svg b/src/gui/icons/loupe-large-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8472dea75b0cd4a796698ffa89568f850110d6af
--- /dev/null
+++ b/src/gui/icons/loupe-large-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/src/gui/views/gcal-week-view.c b/src/gui/views/gcal-week-view.c
index 4eb14a8a22584971af1e7b7e9d683a659fc29d76..4752cf8b2f56073b5a1b2d131c2cfe5928d7a156 100644
--- a/src/gui/views/gcal-week-view.c
+++ b/src/gui/views/gcal-week-view.c
@@ -178,7 +178,7 @@ begin_zoom (GcalWeekView *self,
center = gtk_adjustment_get_value (vadjustment) + view_center_y - gtk_adjustment_get_lower (vadjustment);
height = gtk_adjustment_get_upper (vadjustment) - gtk_adjustment_get_lower (vadjustment);
- self->gesture_zoom_center = center / height;
+ self->gesture_zoom_center = height != 0.f ? center / height : 1.0;
self->initial_zoom_level = self->zoom_level;
}
diff --git a/src/utils/gcal-date-time-utils.c b/src/utils/gcal-date-time-utils.c
index df3ebad4e4ee09e548af67bc334fbcb31f7d91fb..e9fec042388f0b60787cba817c20c7408e75937b 100644
--- a/src/utils/gcal-date-time-utils.c
+++ b/src/utils/gcal-date-time-utils.c
@@ -299,3 +299,48 @@ gcal_date_time_add_floating_minutes (GDateTime *initial,
offset = offset / 1000000;
return g_date_time_add_seconds (result, offset);
}
+
+/**
+ * gcal_date_time_add_floating_minutes:
+ * @date_time: #GDateTime for which to calculate the UTC difference
+ *
+ * Creates a string "UTC+-n" where n is the offset to UTC of date_time.
+ *
+ * Returns: (transfer full): A new string.
+ */
+gchar*
+gcal_date_time_format_utc_offset (GDateTime *date_time)
+{
+ g_autoptr (GTimeZone) local_time_zone = NULL;
+ g_autoptr (GString) utc_str = NULL;
+ gint64 utc_offset_seconds;
+
+ utc_str = g_string_new ("UTC");
+ utc_offset_seconds = g_date_time_get_utc_offset (date_time) / (1000 * 1000);
+
+ if (utc_offset_seconds != 0)
+ {
+ gboolean negative;
+ gint64 minutes;
+ gint64 hours;
+
+ negative = utc_offset_seconds < 0;
+
+ if (negative)
+ utc_offset_seconds = -utc_offset_seconds;
+
+ hours = utc_offset_seconds / 3600;
+ minutes = (utc_offset_seconds - hours*3600) / 60;
+
+ g_string_append (utc_str, negative ? "-" : "+");
+ g_string_append_printf (utc_str, "%ld", hours);
+
+ if (minutes != 0)
+ {
+ g_string_append (utc_str, ":");
+ g_string_append_printf (utc_str, "%02ld", minutes);
+ }
+ }
+
+ return g_string_free_and_steal (g_steal_pointer (&utc_str));
+}
diff --git a/src/utils/gcal-date-time-utils.h b/src/utils/gcal-date-time-utils.h
index 635338f8a1235770fce6d2cfc18672dab745624f..c61230d6e1a37a5987ac29bac09ffd0787226726 100644
--- a/src/utils/gcal-date-time-utils.h
+++ b/src/utils/gcal-date-time-utils.h
@@ -57,4 +57,7 @@ ICalTimezone* gcal_timezone_to_icaltimezone (GTimeZone
GDateTime* gcal_date_time_add_floating_minutes (GDateTime *initial,
gint minutes);
+gchar* gcal_date_time_format_utc_offset (GDateTime *date_time);
+
G_END_DECLS
+
diff --git a/tests/test-event.c b/tests/test-event.c
index 4df7c15213242aadaa499966fd83b42467901510..78a3ec3bb10fddbd58c5c106a07c00e3e7897579 100644
--- a/tests/test-event.c
+++ b/tests/test-event.c
@@ -334,55 +334,6 @@ event_date_create_tzid (void)
/*********************************************************************************************************************/
-static void
-event_date_edit_tzid (void)
-{
- struct {
- const gchar *string;
- const gchar *tz;
- } events[] = {
- {
- EVENT_STRING_FOR_DATE (";TZID=Europe/Madrid:20170818T130000", ";TZID=Europe/Madrid:20170818T140000"),
- "Europe/Madrid"
- },
- {
- // https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/170
- EVENT_STRING_FOR_DATE (";TZID=Europe/London:20170818T130000", ";TZID=Europe/London:20170818T140000"),
- "Europe/London"
- },
- {
- EVENT_STRING_FOR_DATE (";TZID=America/Costa_Rica:20170818T130000", ";TZID=America/Costa_Rica:20170818T140000"),
- "America/Costa_Rica"
- },
- };
-
- g_test_bug ("170");
-
- for (size_t i = 0; i < G_N_ELEMENTS (events); i++)
- {
- g_autoptr (GDateTime) datetime = NULL;
- g_autoptr (GTimeZone) timezone = NULL;
- g_autoptr (GcalEvent) event = NULL;
- g_autoptr (GError) error = NULL;
-
- ECalComponentDateTime *dt_end = NULL;
-
- event = create_event_for_string (events[i].string, &error);
- g_assert_no_error (error);
-
- // modify the event and check the tz in the result
- timezone = g_time_zone_new_identifier (events[i].tz);
- datetime = g_date_time_new (timezone, 2017, 8, 18, 15, 00, 00.);
- gcal_event_set_date_end (event, datetime);
-
- dt_end = e_cal_component_get_dtend (gcal_event_get_component (event));
- g_assert_cmpstr (e_cal_component_datetime_get_tzid (dt_end), ==, "UTC");
- e_cal_component_datetime_free (dt_end);
- }
-}
-
-/*********************************************************************************************************************/
-
static void
event_date_check_tz (void)
{
@@ -456,7 +407,6 @@ main (gint argc,
g_test_add_func ("/event/date/end", event_date_end);
g_test_add_func ("/event/date/singleday", event_date_singleday);
g_test_add_func ("/event/date/multiday", event_date_multiday);
- g_test_add_func ("/event/date/edit-tzid", event_date_edit_tzid);
g_test_add_func ("/event/date/create-tzid", event_date_create_tzid);
g_test_add_func ("/event/date/check-tz", event_date_check_tz);