Hello community, here is the log from the commit of package gnome-calendar for openSUSE:Factory checked in at 2018-05-03 12:33:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gnome-calendar (Old) and /work/SRC/openSUSE:Factory/.gnome-calendar.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gnome-calendar" Thu May 3 12:33:04 2018 rev:24 rq:602999 version:3.28.2 Changes: -------- --- /work/SRC/openSUSE:Factory/gnome-calendar/gnome-calendar.changes 2018-04-17 11:16:30.953228880 +0200 +++ /work/SRC/openSUSE:Factory/.gnome-calendar.new/gnome-calendar.changes 2018-05-03 12:33:05.410767369 +0200 @@ -1,0 +2,12 @@ +Wed May 2 04:47:20 UTC 2018 - [email protected] + +- Update to version 3.28.2: + + Don't show time labels on full day events. + + Fix Week grid collapsing non-overlapping events. + + Force timed events square box to be squared. + + Use the correct end date on tooltips. + + Minor improvements to the Month view paddings. + + Fix a crash when deleting tasks. + + Updates translations. + +------------------------------------------------------------------- Old: ---- gnome-calendar-3.28.1.tar.xz New: ---- gnome-calendar-3.28.2.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gnome-calendar.spec ++++++ --- /var/tmp/diff_new_pack.YtYGWu/_old 2018-05-03 12:33:06.286736172 +0200 +++ /var/tmp/diff_new_pack.YtYGWu/_new 2018-05-03 12:33:06.290736029 +0200 @@ -17,7 +17,7 @@ Name: gnome-calendar -Version: 3.28.1 +Version: 3.28.2 Release: 0 Summary: A calendar application for GNOME License: GPL-3.0-or-later ++++++ gnome-calendar-3.28.1.tar.xz -> gnome-calendar-3.28.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/NEWS new/gnome-calendar-3.28.2/NEWS --- old/gnome-calendar-3.28.1/NEWS 2018-04-10 16:52:05.000000000 +0200 +++ new/gnome-calendar-3.28.2/NEWS 2018-05-02 02:26:44.000000000 +0200 @@ -1,3 +1,12 @@ +Major changes in 3.28.2: +* Don't show time labels on full day events (Abdullahi Usman) +* Fix Week grid collapsing non-overlapping events +* Force timed events square box to be squared +* Use the correct end date on tooltips +* Minor improvements to the Month view paddings +* Fix a crash when deleting tasks +* Updates translations + Major changes in 3.28.1: * Updated translations diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/data/appdata/org.gnome.Calendar.appdata.xml.in new/gnome-calendar-3.28.2/data/appdata/org.gnome.Calendar.appdata.xml.in --- old/gnome-calendar-3.28.1/data/appdata/org.gnome.Calendar.appdata.xml.in 2018-04-10 16:52:05.000000000 +0200 +++ new/gnome-calendar-3.28.2/data/appdata/org.gnome.Calendar.appdata.xml.in 2018-05-02 02:26:44.000000000 +0200 @@ -49,6 +49,15 @@ <project_group>GNOME</project_group> <releases> + <release date="2018-05-01" version="3.28.2"> + <description> + <p> + The 3.28.2 release brings polish to the Month and Week views, and fixes a crash + when removing tasks. It also updates many translations. + </p> + </description> + </release> + <release date="2018-04-10" version="3.28.1"> <description> <p>This release updates many translations.</p> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/data/theme/Adwaita.css new/gnome-calendar-3.28.2/data/theme/Adwaita.css --- old/gnome-calendar-3.28.1/data/theme/Adwaita.css 2018-04-10 16:52:05.000000000 +0200 +++ new/gnome-calendar-3.28.2/data/theme/Adwaita.css 2018-05-02 02:26:44.000000000 +0200 @@ -424,7 +424,7 @@ border: solid 1px alpha(@borders, 0.3); border-width: 1px 0 0 1px; background: transparent; - padding: 1px 0 1px 0; + padding: 1px 3px 0 3px; transition: background-color 200ms; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/data/ui/event-widget.ui new/gnome-calendar-3.28.2/data/ui/event-widget.ui --- old/gnome-calendar-3.28.1/data/ui/event-widget.ui 2018-04-10 16:52:05.000000000 +0200 +++ new/gnome-calendar-3.28.2/data/ui/event-widget.ui 2018-05-02 02:26:44.000000000 +0200 @@ -22,6 +22,10 @@ <object class="GtkBox" id="color_box"> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="width-request">16</property> + <property name="height-request">16</property> <style> <class name="icon-box" /> </style> @@ -48,6 +52,7 @@ <object class="GtkLabel" id="hour_label"> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="no-show-all">True</property> <style> <class name="dim-label" /> </style> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/data/ui/month-popover.ui new/gnome-calendar-3.28.2/data/ui/month-popover.ui --- old/gnome-calendar-3.28.1/data/ui/month-popover.ui 2018-04-10 16:52:05.000000000 +0200 +++ new/gnome-calendar-3.28.2/data/ui/month-popover.ui 2018-05-02 02:26:44.000000000 +0200 @@ -89,7 +89,7 @@ <property name="visible">true</property> <property name="relief">none</property> <property name="label" translatable="yes">New Event…</property> - <signal name="clicked" handler="new_event_button_clicked_cb" object="GcalMonthPopover" /> + <signal name="clicked" handler="new_event_button_clicked_cb" object="GcalMonthPopover" swapped="no" /> </object> </child> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/meson.build new/gnome-calendar-3.28.2/meson.build --- old/gnome-calendar-3.28.1/meson.build 2018-04-10 16:52:05.000000000 +0200 +++ new/gnome-calendar-3.28.2/meson.build 2018-05-02 02:26:44.000000000 +0200 @@ -1,7 +1,7 @@ project( 'gnome-calendar', 'c', - version: '3.28.1', + version: '3.28.2', license: 'GPL3+', meson_version: '>= 0.42.0' ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/src/gcal-event-widget.c new/gnome-calendar-3.28.2/src/gcal-event-widget.c --- old/gnome-calendar-3.28.1/src/gcal-event-widget.c 2018-04-10 16:52:05.000000000 +0200 +++ new/gnome-calendar-3.28.2/src/gcal-event-widget.c 2018-05-02 02:26:44.000000000 +0200 @@ -310,9 +310,6 @@ escaped_summary = g_markup_escape_text (gcal_event_get_summary (event), -1); g_string_append_printf (tooltip_mesg, "<b>%s</b>", escaped_summary); - tooltip_start = g_date_time_to_local (gcal_event_get_date_start (event)); - tooltip_end = g_date_time_to_local (gcal_event_get_date_end (event)); - allday = gcal_event_get_all_day (event); multiday = gcal_event_is_multiday (event); @@ -320,6 +317,10 @@ if (allday) { + /* All day events span from [ start, end - 1 day ] */ + tooltip_start = g_date_time_ref (gcal_event_get_date_start (event)); + tooltip_end = g_date_time_add_days (gcal_event_get_date_end (event), -1); + if (multiday) { start = g_date_time_format (tooltip_start, "%x"); @@ -333,6 +334,9 @@ } else { + tooltip_start = g_date_time_to_local (gcal_event_get_date_start (event)); + tooltip_end = g_date_time_to_local (gcal_event_get_date_end (event)); + if (multiday) { if (self->clock_format_24h) @@ -395,9 +399,7 @@ if (allday && !multiday) { - g_string_append_printf (tooltip_mesg, - "\n%s", - start); + g_string_append_printf (tooltip_mesg, "\n%s", start); } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/src/gcal-event.c new/gnome-calendar-3.28.2/src/gcal-event.c --- old/gnome-calendar-3.28.1/src/gcal-event.c 2018-04-10 16:52:05.000000000 +0200 +++ new/gnome-calendar-3.28.2/src/gcal-event.c 2018-05-02 02:26:44.000000000 +0200 @@ -1492,43 +1492,50 @@ * gcal_event_is_multiday: * @self: a #GcalEvent * - * Whether the event spans more than 1 day. + * Whether the event visibly spans more than one day in the + * calendar. + * + * This function can return different values for the same event + * depending on your timezone. For example, an event that spans + * [ 02:00, 22:00 ) +0000 would assume the following values: + * + * |[ + * D-1 D D+1 + * -0600 [ ---][------- ][ ] (multiday) + * +0000 [ ][ ---------- ][ ] (single day) + * +0800 [ ][ -------][--- ] (multiday) + * ]| * * Returns: %TRUE if @self spans more than 1 day, %FALSE otherwise. */ gboolean gcal_event_is_multiday (GcalEvent *self) { - g_autoptr (GDateTime) real_end_date = NULL; - gboolean is_multiday; - gint n_days; + g_autoptr (GDateTime) inclusive_end_date = NULL; + g_autoptr (GDateTime) local_start_date = NULL; + g_autoptr (GDateTime) local_end_date = NULL; + GDate start_dt; + GDate end_dt; g_return_val_if_fail (GCAL_IS_EVENT (self), FALSE); - real_end_date = g_date_time_add_seconds (gcal_event_get_date_end (self), -1); - n_days = g_date_time_difference (real_end_date, self->dt_start) / G_TIME_SPAN_DAY; - is_multiday = FALSE; - - /* - * An all-day event with only 1 day of time span is treated as a - * single-day event. - */ - if (self->all_day && n_days == 1) - is_multiday = FALSE; - - /* - * If any of the following fields are different, we're certain that - * it's a multiday event. Otherwise, we're certain it's NOT a multiday - * event. - */ - if (g_date_time_get_year (self->dt_start) != g_date_time_get_year (real_end_date) || - g_date_time_get_month (self->dt_start) != g_date_time_get_month (real_end_date) || - g_date_time_get_day_of_month (self->dt_start) != g_date_time_get_day_of_month (real_end_date)) - { - is_multiday = TRUE; - } + inclusive_end_date = g_date_time_add_seconds (gcal_event_get_date_end (self), -1); + local_start_date = g_date_time_to_local (self->dt_start); + local_end_date = g_date_time_to_local (inclusive_end_date); + + g_date_clear (&start_dt, 1); + g_date_set_dmy (&start_dt, + g_date_time_get_day_of_month (local_start_date), + g_date_time_get_month (local_start_date), + g_date_time_get_year (local_start_date)); + + g_date_clear (&end_dt, 1); + g_date_set_dmy (&end_dt, + g_date_time_get_day_of_month (local_end_date), + g_date_time_get_month (local_end_date), + g_date_time_get_year (local_end_date)); - return is_multiday; + return g_date_days_between (&start_dt, &end_dt) > 1; } /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/src/gcal-manager.c new/gnome-calendar-3.28.2/src/gcal-manager.c --- old/gnome-calendar-3.28.1/src/gcal-manager.c 2018-04-10 16:52:05.000000000 +0200 +++ new/gnome-calendar-3.28.2/src/gcal-manager.c 2018-05-02 02:26:44.000000000 +0200 @@ -1715,7 +1715,7 @@ (ECalObjModType) mod, self->async_ops, on_event_removed, - event); + g_object_ref (event)); g_free (rid); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/src/views/gcal-month-popover.c new/gnome-calendar-3.28.2/src/views/gcal-month-popover.c --- old/gnome-calendar-3.28.1/src/views/gcal-month-popover.c 2018-04-10 16:52:06.000000000 +0200 +++ new/gnome-calendar-3.28.2/src/views/gcal-month-popover.c 2018-05-02 02:26:44.000000000 +0200 @@ -18,6 +18,7 @@ #define G_LOG_DOMAIN "GcalMonthPopover" +#include "gcal-debug.h" #include "gcal-event-widget.h" #include "gcal-month-popover.h" #include "gcal-utils.h" @@ -25,6 +26,7 @@ #include <dazzle.h> #define RATIO_TO_RELATIVE 1.25 +#define MIN_WIDTH 250 struct _GcalMonthPopover { @@ -274,6 +276,8 @@ gtk_window_move (GTK_WINDOW (self), alloc.x - diff_w / 2, alloc.y - diff_h / 2); + alloc.width = MAX (MIN_WIDTH, alloc.width); + if (animate) { gtk_widget_set_size_request (GTK_WIDGET (self), alloc.width, alloc.height); @@ -399,10 +403,16 @@ GActionMap *map; GAction *action; + GCAL_ENTRY; + map = G_ACTION_MAP (g_application_get_default ()); action = g_action_map_lookup_action (map, "new"); + gcal_month_popover_popdown (self); + g_action_activate (action, NULL); + + GCAL_EXIT; } static void @@ -846,6 +856,8 @@ gtk_widget_get_toplevel (self->relative_to), 0, 0, &alloc.x, &alloc.y); adjust_margin (self, &alloc); + alloc.width = MAX (MIN_WIDTH, alloc.width); + animate_opacity (self, 0.0); animate_position (self, 0.0, 0.0); animate_size (self, alloc.width, alloc.height); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/src/views/gcal-month-view.c new/gnome-calendar-3.28.2/src/views/gcal-month-view.c --- old/gnome-calendar-3.28.1/src/views/gcal-month-view.c 2018-04-10 16:52:06.000000000 +0200 +++ new/gnome-calendar-3.28.2/src/views/gcal-month-view.c 2018-05-02 02:26:44.000000000 +0200 @@ -124,14 +124,24 @@ gboolean pending_event_allocation; }; + static void gcal_view_interface_init (GcalViewInterface *iface); static void gtk_buildable_interface_init (GtkBuildableIface *iface); static void e_data_model_subscriber_interface_init (ECalDataModelSubscriberInterface *iface); -static void update_weather (GcalMonthView *self, - gboolean clear_old); +static void on_event_activated_cb (GcalEventWidget *widget, + GcalMonthView *self); + +static void on_event_widget_visibility_changed_cb (GtkWidget *event_widget, + GParamSpec *pspec, + GcalMonthView *self); + +static void on_month_cell_show_overflow_popover_cb (GcalMonthCell *cell, + GtkWidget *button, + GcalMonthView *self); + G_DEFINE_TYPE_WITH_CODE (GcalMonthView, gcal_month_view, GTK_TYPE_CONTAINER, G_IMPLEMENT_INTERFACE (GCAL_TYPE_VIEW, gcal_view_interface_init) @@ -162,28 +172,13 @@ } static void -event_activated (GcalMonthView *self, - GcalEventWidget *widget, - gpointer unused) +activate_event (GcalMonthView *self, + GcalEventWidget *event_widget) { cancel_selection (self); gcal_month_popover_popdown (self->overflow_popover); - g_signal_emit_by_name (self, "event-activated", widget); -} - -static void -event_widget_visibility_changed_cb (GcalMonthView *self) -{ - self->pending_event_allocation = TRUE; - gtk_widget_queue_resize (GTK_WIDGET (self)); -} - -static void -weather_changed_cb (GcalWeatherService *weather_service, - GcalMonthView *self) -{ - update_weather (self, TRUE); + g_signal_emit_by_name (self, "event-activated", event_widget); } static void @@ -193,8 +188,8 @@ if (!gtk_widget_get_parent (widget)) gtk_widget_set_parent (widget, GTK_WIDGET (self)); - g_signal_connect_swapped (widget, "activate", G_CALLBACK (event_activated), self); - g_signal_connect_swapped (widget, "notify::visible", G_CALLBACK (event_widget_visibility_changed_cb), self); + g_signal_connect (widget, "activate", G_CALLBACK (on_event_activated_cb), self); + g_signal_connect (widget, "notify::visible", G_CALLBACK (on_event_widget_visibility_changed_cb), self); } static gboolean @@ -836,22 +831,6 @@ } static void -show_overflow_popover_cb (GcalMonthCell *cell, - GtkWidget *button, - GcalMonthView *self) -{ - GcalMonthPopover *popover; - - popover = GCAL_MONTH_POPOVER (self->overflow_popover); - - cancel_selection (self); - - gcal_month_popover_set_relative_to (popover, GTK_WIDGET (cell)); - gcal_month_popover_set_date (popover, gcal_month_cell_get_date (cell)); - gcal_month_popover_popup (popover); -} - -static void setup_header_widget (GcalMonthView *self, GtkWidget *widget) { @@ -876,10 +855,7 @@ cell = gcal_month_cell_new (); - g_signal_connect (cell, - "show-overflow", - G_CALLBACK (show_overflow_popover_cb), - self); + g_signal_connect (cell, "show-overflow", G_CALLBACK (on_month_cell_show_overflow_popover_cb), self); self->month_cell[row][col] = cell; @@ -1040,7 +1016,7 @@ queue_update_month_cells (GcalMonthView *self) { if (self->update_grid_id > 0) - g_source_remove (self->update_grid_id); + return; self->update_grid_id = g_idle_add ((GSourceFunc) update_month_cells, self); } @@ -1071,185 +1047,83 @@ } } + /* - * GtkWidget overrides + * Callbacks */ -static gboolean -gcal_month_view_key_press (GtkWidget *widget, - GdkEventKey *event) +static void +add_new_event_button_cb (GtkWidget *button, + gpointer user_data) { GcalMonthView *self; - gboolean create_event; - gboolean selection; - gboolean valid_key; - gboolean is_ltr; - gint min, max, diff, month_change, current_day; - gint row, col; - - g_return_val_if_fail (GCAL_IS_MONTH_VIEW (widget), FALSE); - - self = GCAL_MONTH_VIEW (widget); - selection = event->state & GDK_SHIFT_MASK; - create_event = FALSE; - valid_key = FALSE; - diff = 0; - month_change = 0; - current_day = self->keyboard_cell - self->days_delay + 1; - min = self->days_delay; - max = self->days_delay + icaltime_days_in_month (self->date->month, self->date->year) - 1; - is_ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL; - - /* - * If it's starting the selection right now, it should mark the current keyboard - * focused cell as the start, and then update the end mark after updating the - * focused cell. - */ - if (selection && self->start_mark_cell == NULL) - self->start_mark_cell = g_date_time_new_local (self->date->year, self->date->month, current_day, 0, 0, 0); - - switch (event->keyval) - { - case GDK_KEY_Up: - valid_key = TRUE; - diff = -7; - break; - - case GDK_KEY_Down: - valid_key = TRUE; - diff = 7; - break; - - case GDK_KEY_Left: - valid_key = TRUE; - diff = is_ltr ? -1 : 1; - break; - - case GDK_KEY_Right: - valid_key = TRUE; - diff = is_ltr ? 1 : -1; - break; - - case GDK_KEY_Return: - /* - * If it's not on the selection mode (i.e. shift is not pressed), we should - * simulate it by changing the start & end selected cells = keyboard cell. - */ - if (!selection && !self->start_mark_cell && !self->end_mark_cell) - self->start_mark_cell = self->end_mark_cell = g_date_time_new_local (self->date->year, self->date->month, current_day, 0, 0, 0); - - create_event = TRUE; - break; - - case GDK_KEY_Escape: - cancel_selection (GCAL_MONTH_VIEW (widget)); - break; - - default: - return GDK_EVENT_PROPAGATE; - } - - if (self->keyboard_cell + diff <= max && self->keyboard_cell + diff >= min) - { - self->keyboard_cell += diff; - } - else - { - month_change = self->keyboard_cell + diff > max ? 1 : -1; - self->date->month += month_change; - *self->date = icaltime_normalize (*self->date); - - self->days_delay = (time_day_of_week (1, self->date->month - 1, self->date->year) - self->first_weekday + 7) % 7; - - /* - * Set keyboard cell value to the sum or difference of days delay of successive - * month or last day of preceeding month and overload value depending on - * month_change. Overload value is the equal to the deviation of the value - * of keboard_cell from the min or max value of the current month depending - * on the overload point. - */ - if (month_change == 1) - self->keyboard_cell = self->days_delay + self->keyboard_cell + diff - max - 1; - else - self->keyboard_cell = self->days_delay + icaltime_days_in_month (self->date->month, self->date->year) - min + self->keyboard_cell + diff; - } - - /* Focus the selected month cell */ - row = self->keyboard_cell / 7; - col = self->keyboard_cell % 7; + GDateTime *start_date; + gint day; - gtk_widget_grab_focus (self->month_cell[row][col]); + self = GCAL_MONTH_VIEW (user_data); - current_day = self->keyboard_cell - self->days_delay + 1; - self->date->day = current_day; + gcal_month_popover_popdown (self->overflow_popover); - /* - * We can only emit the :create-event signal ~after~ grabbing the focus, otherwise - * the popover is instantly hidden. - */ - if (create_event) - emit_create_event (self); + day = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (self->overflow_popover), "selected-day")); + start_date = g_date_time_new_local (self->date->year, self->date->month, day, 0, 0, 0); - g_object_notify (G_OBJECT (widget), "active-date"); + g_signal_emit_by_name (GCAL_VIEW (user_data), "create-event-detailed", start_date, NULL); - if (selection) - { - self->end_mark_cell = g_date_time_new_local (self->date->year, self->date->month, current_day, 0, 0, 0); - } - else if (!selection && valid_key) - { - /* Cancel selection if SHIFT is not pressed */ - cancel_selection (GCAL_MONTH_VIEW (widget)); - } + g_date_time_unref (start_date); +} - return GDK_EVENT_STOP; +static void +on_event_activated_cb (GcalEventWidget *widget, + GcalMonthView *self) +{ + activate_event (self, widget); } -static gboolean -gcal_month_view_scroll_event (GtkWidget *widget, - GdkEventScroll *scroll_event) +static void +on_event_widget_visibility_changed_cb (GtkWidget *event_widget, + GParamSpec *pspec, + GcalMonthView *self) { - GcalMonthView *self = GCAL_MONTH_VIEW (widget); + self->pending_event_allocation = TRUE; + gtk_widget_queue_resize (GTK_WIDGET (self)); +} - /* - * If we accumulated enough scrolling, change the month. Otherwise, we'd scroll - * waaay too fast. - */ - if (should_change_date_for_scroll (&self->scroll_value, scroll_event)) - { - self->date->month += self->scroll_value > 0 ? 1 : -1; - *self->date = icaltime_normalize (*self->date); - self->scroll_value = 0; +static void +on_month_cell_show_overflow_popover_cb (GcalMonthCell *cell, + GtkWidget *button, + GcalMonthView *self) +{ + GcalMonthPopover *popover; - gtk_widget_queue_draw (widget); + popover = GCAL_MONTH_POPOVER (self->overflow_popover); - g_object_notify (G_OBJECT (widget), "active-date"); - } + cancel_selection (self); - return GDK_EVENT_STOP; + gcal_month_popover_set_relative_to (popover, GTK_WIDGET (cell)); + gcal_month_popover_set_date (popover, gcal_month_cell_get_date (cell)); + gcal_month_popover_popup (popover); } static void -add_new_event_button_cb (GtkWidget *button, - gpointer user_data) +on_month_popover_event_activated_cb (GcalMonthPopover *month_popover, + GcalEventWidget *event_widget, + GcalMonthView *self) { - GcalMonthView *self; - GDateTime *start_date; - gint day; - - self = GCAL_MONTH_VIEW (user_data); - - gcal_month_popover_popdown (self->overflow_popover); + activate_event (self, event_widget); +} - day = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (self->overflow_popover), "selected-day")); - start_date = g_date_time_new_local (self->date->year, self->date->month, day, 0, 0, 0); +static void +on_weather_service_weather_changed_cb (GcalWeatherService *weather_service, + GcalMonthView *self) +{ + update_weather (self, TRUE); +} - g_signal_emit_by_name (GCAL_VIEW (user_data), "create-event-detailed", start_date, NULL); - g_date_time_unref (start_date); -} +/* + * GcalView interface + */ -/* GcalView Interface API */ static icaltimetype* gcal_month_view_get_date (GcalView *view) { @@ -1348,6 +1222,7 @@ iface->add_child = gcal_month_view_add_child; } + /* * ECalDataModelSubscriber interface */ @@ -1494,6 +1369,7 @@ iface->thaw = gcal_month_view_thaw; } + /* * GtkContainer overrides */ @@ -1690,7 +1566,7 @@ if (self->header) (*callback) (self->header, callback_data); - /* Header */ + /* Grid */ if (self->grid) (*callback) (self->grid, callback_data); @@ -1716,123 +1592,25 @@ /* - * GObject overrides + * GtkWidget overrides */ static void -gcal_month_view_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) +gcal_month_view_realize (GtkWidget *widget) { - GcalMonthView *self = (GcalMonthView *) object; - gint i; - - switch (property_id) - { - case PROP_DATE: - gcal_view_set_date (GCAL_VIEW (object), g_value_get_boxed (value)); - break; - - case PROP_MANAGER: - self->manager = g_value_dup_object (value); + GcalMonthView *self; + GdkWindow *parent_window; + GdkWindowAttr attributes; + gint attributes_mask; + GtkAllocation allocation; - g_signal_connect_swapped (gcal_manager_get_clock (self->manager), - "day-changed", - G_CALLBACK (update_month_cells), - self); + self = GCAL_MONTH_VIEW (widget); + gtk_widget_set_realized (widget, TRUE); - for (i = 0; i < 42; i++) - gcal_month_cell_set_manager (GCAL_MONTH_CELL (self->month_cell[i / 7][i % 7]), self->manager); + parent_window = gtk_widget_get_parent_window (widget); + gtk_widget_set_window (widget, g_object_ref (parent_window)); - g_object_notify (object, "manager"); - break; - - case PROP_WEATHER_SERVICE: - gcal_view_set_weather_service_impl_helper (&self->weather_service, - g_value_get_object (value), - (GcalWeatherUpdateFunc) update_weather, - (GCallback) weather_changed_cb, - GTK_WIDGET (self)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gcal_month_view_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GcalMonthView *self = GCAL_MONTH_VIEW (object); - - switch (property_id) - { - case PROP_DATE: - g_value_set_boxed (value, self->date); - break; - - case PROP_MANAGER: - g_value_set_object (value, self->manager); - break; - - case PROP_WEATHER_SERVICE: - g_value_set_boxed (value, self->weather_service); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gcal_month_view_finalize (GObject *object) -{ - GcalMonthView *self = GCAL_MONTH_VIEW (object); - - if (self->weather_service) - g_signal_handlers_disconnect_by_func (self->weather_service, weather_changed_cb, self); - - g_clear_pointer (&self->date, g_free); - g_clear_pointer (&self->children, g_hash_table_destroy); - g_clear_pointer (&self->single_cell_children, g_hash_table_destroy); - g_clear_pointer (&self->overflow_cells, g_hash_table_destroy); - g_clear_pointer (&self->multi_cell_children, g_list_free); - - g_clear_object (&self->manager); - g_clear_object (&self->weather_service); - - if (self->update_grid_id > 0) - { - g_source_remove (self->update_grid_id); - self->update_grid_id = 0; - } - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (gcal_month_view_parent_class)->finalize (object); -} - -static void -gcal_month_view_realize (GtkWidget *widget) -{ - GcalMonthView *self; - GdkWindow *parent_window; - GdkWindowAttr attributes; - gint attributes_mask; - GtkAllocation allocation; - - self = GCAL_MONTH_VIEW (widget); - gtk_widget_set_realized (widget, TRUE); - - parent_window = gtk_widget_get_parent_window (widget); - gtk_widget_set_window (widget, g_object_ref (parent_window)); - - gtk_widget_get_allocation (widget, &allocation); + gtk_widget_get_allocation (widget, &allocation); attributes.window_type = GDK_WINDOW_CHILD; attributes.wclass = GDK_INPUT_ONLY; @@ -2132,6 +1910,260 @@ gtk_widget_queue_resize (widget); } +static gboolean +gcal_month_view_key_press (GtkWidget *widget, + GdkEventKey *event) +{ + GcalMonthView *self; + gboolean create_event; + gboolean selection; + gboolean valid_key; + gboolean is_ltr; + gint min, max, diff, month_change, current_day; + gint row, col; + + g_return_val_if_fail (GCAL_IS_MONTH_VIEW (widget), FALSE); + + self = GCAL_MONTH_VIEW (widget); + selection = event->state & GDK_SHIFT_MASK; + create_event = FALSE; + valid_key = FALSE; + diff = 0; + month_change = 0; + current_day = self->keyboard_cell - self->days_delay + 1; + min = self->days_delay; + max = self->days_delay + icaltime_days_in_month (self->date->month, self->date->year) - 1; + is_ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL; + + /* + * If it's starting the selection right now, it should mark the current keyboard + * focused cell as the start, and then update the end mark after updating the + * focused cell. + */ + if (selection && self->start_mark_cell == NULL) + self->start_mark_cell = g_date_time_new_local (self->date->year, self->date->month, current_day, 0, 0, 0); + + switch (event->keyval) + { + case GDK_KEY_Up: + valid_key = TRUE; + diff = -7; + break; + + case GDK_KEY_Down: + valid_key = TRUE; + diff = 7; + break; + + case GDK_KEY_Left: + valid_key = TRUE; + diff = is_ltr ? -1 : 1; + break; + + case GDK_KEY_Right: + valid_key = TRUE; + diff = is_ltr ? 1 : -1; + break; + + case GDK_KEY_Return: + /* + * If it's not on the selection mode (i.e. shift is not pressed), we should + * simulate it by changing the start & end selected cells = keyboard cell. + */ + if (!selection && !self->start_mark_cell && !self->end_mark_cell) + self->start_mark_cell = self->end_mark_cell = g_date_time_new_local (self->date->year, self->date->month, current_day, 0, 0, 0); + + create_event = TRUE; + break; + + case GDK_KEY_Escape: + cancel_selection (GCAL_MONTH_VIEW (widget)); + break; + + default: + return GDK_EVENT_PROPAGATE; + } + + if (self->keyboard_cell + diff <= max && self->keyboard_cell + diff >= min) + { + self->keyboard_cell += diff; + } + else + { + month_change = self->keyboard_cell + diff > max ? 1 : -1; + self->date->month += month_change; + *self->date = icaltime_normalize (*self->date); + + self->days_delay = (time_day_of_week (1, self->date->month - 1, self->date->year) - self->first_weekday + 7) % 7; + + /* + * Set keyboard cell value to the sum or difference of days delay of successive + * month or last day of preceeding month and overload value depending on + * month_change. Overload value is the equal to the deviation of the value + * of keboard_cell from the min or max value of the current month depending + * on the overload point. + */ + if (month_change == 1) + self->keyboard_cell = self->days_delay + self->keyboard_cell + diff - max - 1; + else + self->keyboard_cell = self->days_delay + icaltime_days_in_month (self->date->month, self->date->year) - min + self->keyboard_cell + diff; + } + + /* Focus the selected month cell */ + row = self->keyboard_cell / 7; + col = self->keyboard_cell % 7; + + gtk_widget_grab_focus (self->month_cell[row][col]); + + current_day = self->keyboard_cell - self->days_delay + 1; + self->date->day = current_day; + + /* + * We can only emit the :create-event signal ~after~ grabbing the focus, otherwise + * the popover is instantly hidden. + */ + if (create_event) + emit_create_event (self); + + g_object_notify (G_OBJECT (widget), "active-date"); + + if (selection) + { + self->end_mark_cell = g_date_time_new_local (self->date->year, self->date->month, current_day, 0, 0, 0); + } + else if (!selection && valid_key) + { + /* Cancel selection if SHIFT is not pressed */ + cancel_selection (GCAL_MONTH_VIEW (widget)); + } + + return GDK_EVENT_STOP; +} + +static gboolean +gcal_month_view_scroll_event (GtkWidget *widget, + GdkEventScroll *scroll_event) +{ + GcalMonthView *self = GCAL_MONTH_VIEW (widget); + + /* + * If we accumulated enough scrolling, change the month. Otherwise, we'd scroll + * waaay too fast. + */ + if (should_change_date_for_scroll (&self->scroll_value, scroll_event)) + { + self->date->month += self->scroll_value > 0 ? 1 : -1; + *self->date = icaltime_normalize (*self->date); + self->scroll_value = 0; + + gtk_widget_queue_draw (widget); + + g_object_notify (G_OBJECT (widget), "active-date"); + } + + return GDK_EVENT_STOP; +} + + +/* + * GObject overrides + */ + +static void +gcal_month_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GcalMonthView *self = (GcalMonthView *) object; + gint i; + + switch (property_id) + { + case PROP_DATE: + gcal_view_set_date (GCAL_VIEW (object), g_value_get_boxed (value)); + break; + + case PROP_MANAGER: + self->manager = g_value_dup_object (value); + + g_signal_connect_swapped (gcal_manager_get_clock (self->manager), + "day-changed", + G_CALLBACK (update_month_cells), + self); + + for (i = 0; i < 42; i++) + gcal_month_cell_set_manager (GCAL_MONTH_CELL (self->month_cell[i / 7][i % 7]), self->manager); + + g_object_notify (object, "manager"); + break; + + case PROP_WEATHER_SERVICE: + gcal_view_set_weather_service_impl_helper (&self->weather_service, + g_value_get_object (value), + (GcalWeatherUpdateFunc) update_weather, + G_CALLBACK (on_weather_service_weather_changed_cb), + GTK_WIDGET (self)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gcal_month_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GcalMonthView *self = GCAL_MONTH_VIEW (object); + + switch (property_id) + { + case PROP_DATE: + g_value_set_boxed (value, self->date); + break; + + case PROP_MANAGER: + g_value_set_object (value, self->manager); + break; + + case PROP_WEATHER_SERVICE: + g_value_set_boxed (value, self->weather_service); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gcal_month_view_finalize (GObject *object) +{ + GcalMonthView *self = GCAL_MONTH_VIEW (object); + + g_clear_pointer (&self->date, g_free); + g_clear_pointer (&self->children, g_hash_table_destroy); + g_clear_pointer (&self->single_cell_children, g_hash_table_destroy); + g_clear_pointer (&self->overflow_cells, g_hash_table_destroy); + g_clear_pointer (&self->multi_cell_children, g_list_free); + + g_clear_object (&self->manager); + g_clear_object (&self->weather_service); + + if (self->update_grid_id > 0) + { + g_source_remove (self->update_grid_id); + self->update_grid_id = 0; + } + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (gcal_month_view_parent_class)->finalize (object); +} + static void gcal_month_view_class_init (GcalMonthViewClass *klass) { @@ -2221,9 +2253,6 @@ "manager", G_BINDING_DEFAULT); - g_signal_connect_swapped (self->overflow_popover, - "event-activated", - G_CALLBACK (event_activated), - self); + g_signal_connect (self->overflow_popover, "event-activated", G_CALLBACK (on_month_popover_event_activated_cb), self); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/src/views/gcal-view.c new/gnome-calendar-3.28.2/src/views/gcal-view.c --- old/gnome-calendar-3.28.1/src/views/gcal-view.c 2018-04-10 16:52:06.000000000 +0200 +++ new/gnome-calendar-3.28.2/src/views/gcal-view.c 2018-05-02 02:26:44.000000000 +0200 @@ -218,7 +218,7 @@ g_set_object (old_service, new_service); if (*old_service) - g_signal_connect (*old_service, "weather-changed", weather_changed_cb, data); + g_signal_connect_object (*old_service, "weather-changed", weather_changed_cb, data, 0); update_func (data); g_object_notify (G_OBJECT (data), "weather-service"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/src/views/gcal-week-grid.c new/gnome-calendar-3.28.2/src/views/gcal-week-grid.c --- old/gnome-calendar-3.28.1/src/views/gcal-week-grid.c 2018-04-10 16:52:06.000000000 +0200 +++ new/gnome-calendar-3.28.2/src/views/gcal-week-grid.c 2018-05-02 02:26:44.000000000 +0200 @@ -152,11 +152,12 @@ if (end) { - - GDateTime *event_end; + g_autoptr (GDateTime) inclusive_end_date = NULL; + g_autoptr (GDateTime) event_end = NULL; gboolean event_end_dst; - event_end = g_date_time_to_local (gcal_event_get_date_end (event)); + inclusive_end_date = g_date_time_add_seconds (gcal_event_get_date_end (event), -1); + event_end = g_date_time_to_local (inclusive_end_date); event_end_dst = g_date_time_is_daylight_savings (event_end); diff = g_date_time_difference (event_end, week_start); @@ -171,8 +172,6 @@ */ if (start && *start == *end) *end = *end + 1; - - g_clear_pointer (&event_end, g_date_time_unref); } g_clear_pointer (&week_start, g_date_time_unref); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/src/views/gcal-week-header.c new/gnome-calendar-3.28.2/src/views/gcal-week-header.c --- old/gnome-calendar-3.28.1/src/views/gcal-week-header.c 2018-04-10 16:52:06.000000000 +0200 +++ new/gnome-calendar-3.28.2/src/views/gcal-week-header.c 2018-05-02 02:26:44.000000000 +0200 @@ -1095,13 +1095,7 @@ for (i = 0; i < 7; i++) g_list_free (self->events[i]); - if (self->weather_service != NULL) - { - g_signal_handlers_disconnect_by_func (self->weather_service, - (GCallback) on_weather_update, - self); - g_clear_object (&self->weather_service); - } + g_clear_object (&self->weather_service); for (i = 0; i < G_N_ELEMENTS (self->weather_infos); i++) wid_clear (&self->weather_infos[i]); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gnome-calendar-3.28.1/tests/test-event.c new/gnome-calendar-3.28.2/tests/test-event.c --- old/gnome-calendar-3.28.1/tests/test-event.c 2018-04-10 16:52:06.000000000 +0200 +++ new/gnome-calendar-3.28.2/tests/test-event.c 2018-05-02 02:26:44.000000000 +0200 @@ -197,7 +197,7 @@ event_date_multiday (void) { const gchar * const events[] = { - EVENT_STRING_FOR_DATE ("20160229T000000Z", "20160301T000001Z"), + EVENT_STRING_FOR_DATE ("20160229T000000Z", "20160302T000001Z"), EVENT_STRING_FOR_DATE ("20160229T020000Z", "20160310T004500Z"), };
