From 20228e34bf97f67b1dd542a22e92cd90f0db5c72 Mon Sep 17 00:00:00 2001 From: Dirli Date: Thu, 9 Apr 2020 16:30:16 +0300 Subject: [PATCH 1/8] added a single namespace --- meson.build | 14 +- src/DateIterator.vala | 82 ----- src/DateRange.vala | 66 ---- src/Indicator.vala | 341 +++++++++--------- .../calendar => Models}/CalendarModel.vala | 4 +- src/Services/TimeManager.vala | 230 ++++++------ src/Util/DateIterator.vala | 84 +++++ src/Util/DateRange.vala | 68 ++++ src/{Widgets/calendar => Util}/Util.vala | 8 +- src/Widgets/CalendarView.vala | 185 ++++++++++ src/Widgets/EventRow.vala | 184 +++++----- src/Widgets/{calendar => }/Grid.vala | 12 +- src/Widgets/GridDay.vala | 180 +++++++++ src/Widgets/PanelLabel.vala | 80 ++-- src/Widgets/calendar/CalendarView.vala | 183 ---------- src/Widgets/calendar/GridDay.vala | 178 --------- 16 files changed, 957 insertions(+), 942 deletions(-) delete mode 100644 src/DateIterator.vala delete mode 100644 src/DateRange.vala rename src/{Widgets/calendar => Models}/CalendarModel.vala (99%) create mode 100644 src/Util/DateIterator.vala create mode 100644 src/Util/DateRange.vala rename src/{Widgets/calendar => Util}/Util.vala (96%) create mode 100644 src/Widgets/CalendarView.vala rename src/Widgets/{calendar => }/Grid.vala (95%) create mode 100644 src/Widgets/GridDay.vala delete mode 100644 src/Widgets/calendar/CalendarView.vala delete mode 100644 src/Widgets/calendar/GridDay.vala diff --git a/meson.build b/meson.build index 2555723..b44c5bd 100644 --- a/meson.build +++ b/meson.build @@ -39,16 +39,16 @@ endif shared_module( meson.project_name(), gresource, - 'src/DateIterator.vala', - 'src/DateRange.vala', 'src/Indicator.vala', + 'src/Util/DateIterator.vala', + 'src/Util/DateRange.vala', + 'src/Util/Util.vala', + 'src/Models/CalendarModel.vala', + 'src/Widgets/CalendarView.vala', 'src/Widgets/EventRow.vala', + 'src/Widgets/Grid.vala', + 'src/Widgets/GridDay.vala', 'src/Widgets/PanelLabel.vala', - 'src/Widgets/calendar/CalendarModel.vala', - 'src/Widgets/calendar/CalendarView.vala', - 'src/Widgets/calendar/Grid.vala', - 'src/Widgets/calendar/GridDay.vala', - 'src/Widgets/calendar/Util.vala', 'src/Services/TimeManager.vala', dependencies: [ dependency('glib-2.0'), diff --git a/src/DateIterator.vala b/src/DateIterator.vala deleted file mode 100644 index 961895b..0000000 --- a/src/DateIterator.vala +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2011-2018 elementary, Inc. (https://elementary.io) - * - * This program 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 2 of the License, or (at your option) any later version. - * - * This program 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, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Authored by: Corentin Noël - */ - -public class Util.DateIterator : Object, Gee.Traversable, Gee.Iterator { - public GLib.DateTime current { get; construct set; } - public Util.DateRange range { get; construct; } - - // Required by Gee.Iterator - public bool valid { - get { - return true; - } - } - - // Required by Gee.Iterator - public bool read_only { - get { - return false; - } - } - - public DateIterator (Util.DateRange range) { - Object ( - range: range, - current: range.first_dt.add_days (-1) - ); - } - - public bool @foreach (Gee.ForallFunc f) { - var element = range.first_dt; - - while (element.compare (range.last_dt) < 0) { - if (f (element) == false) { - return false; - } - - element = element.add_days (1); - } - - return true; - } - - public bool next () { - if (!has_next ()) { - return false; - } - - current = this.current.add_days (1); - - return true; - } - - public bool has_next () { - return current.compare (range.last_dt) < 0; - } - - public new GLib.DateTime get () { - return current; - } - - public void remove () { - assert_not_reached (); - } -} diff --git a/src/DateRange.vala b/src/DateRange.vala deleted file mode 100644 index 08e4c00..0000000 --- a/src/DateRange.vala +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2011-2019 elementary, Inc. (https://elementary.io) - * - * This program 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 2 of the License, or (at your option) any later version. - * - * This program 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, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * Authored by: Corentin Noël - */ - -/* Represents date range from 'first' to 'last' inclusive */ -public class Util.DateRange : Object, Gee.Traversable, Gee.Iterable { - public GLib.DateTime first_dt { get; construct; } - public GLib.DateTime last_dt { get; construct; } - - public bool @foreach (Gee.ForallFunc f) { - foreach (var date in this) { - if (f (date) == false) { - return false; - } - } - - return true; - } - - public DateRange (GLib.DateTime first, GLib.DateTime last) { - Object ( - first_dt: first, - last_dt: last - ); - } - - public bool equals (DateRange other) { - return (first_dt == other.first_dt && last_dt == other.last_dt); - } - - public Gee.Iterator iterator () { - return new DateIterator (this); - } - - public Gee.List to_list () { - var list = new Gee.ArrayList ((Gee.EqualDataFunc? )datetime_equal_func); - - foreach (var date in this) { - list.add (date); - } - - return list; - } - - /* Returns true if 'a' and 'b' are the same GLib.DateTime */ - private bool datetime_equal_func (GLib.DateTime a, GLib.DateTime b) { - return a.equal (b); - } -} diff --git a/src/Indicator.vala b/src/Indicator.vala index 77aa35c..b712c12 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -17,218 +17,219 @@ * Boston, MA 02110-1301 USA. */ -public class DateTime.Indicator : Wingpanel.Indicator { - public static GLib.Settings settings; - - private Widgets.PanelLabel panel_label; - private Gtk.Grid main_grid; - private Widgets.CalendarView calendar; - private Gtk.ListBox event_listbox; - private uint update_events_idle_source = 0; - - public Indicator () { - Object ( - code_name: Wingpanel.Indicator.DATETIME, - display_name: _("Date & Time"), - description: _("The date and time indicator") - ); - } - - static construct { - settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime"); - } +namespace DateTimeIndicator { + public class Indicator : Wingpanel.Indicator { + public static GLib.Settings settings; + + private Widgets.PanelLabel panel_label; + private Gtk.Grid main_grid; + private Widgets.CalendarView calendar; + private Gtk.ListBox event_listbox; + private uint update_events_idle_source = 0; + + public Indicator () { + Object ( + code_name: Wingpanel.Indicator.DATETIME, + display_name: _("Date & Time"), + description: _("The date and time indicator") + ); + } - construct { - visible = true; - } + static construct { + settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime"); + } - public override Gtk.Widget get_display_widget () { - if (panel_label == null) { - panel_label = new Widgets.PanelLabel (); + construct { + visible = true; } - return panel_label; - } + public override Gtk.Widget get_display_widget () { + if (panel_label == null) { + panel_label = new Widgets.PanelLabel (); + } - public override Gtk.Widget? get_widget () { - if (main_grid == null) { - calendar = new Widgets.CalendarView (); - calendar.margin_bottom = 6; - - var placeholder_label = new Gtk.Label (_("No Events on This Day")); - placeholder_label.wrap = true; - placeholder_label.wrap_mode = Pango.WrapMode.WORD; - placeholder_label.margin_start = 12; - placeholder_label.margin_end = 12; - placeholder_label.max_width_chars = 20; - placeholder_label.justify = Gtk.Justification.CENTER; - placeholder_label.show_all (); - - var placeholder_style_context = placeholder_label.get_style_context (); - placeholder_style_context.add_class (Gtk.STYLE_CLASS_DIM_LABEL); - placeholder_style_context.add_class (Granite.STYLE_CLASS_H3_LABEL); - - event_listbox = new Gtk.ListBox (); - event_listbox.selection_mode = Gtk.SelectionMode.NONE; - event_listbox.set_header_func (header_update_func); - event_listbox.set_placeholder (placeholder_label); - event_listbox.set_sort_func (sort_function); - - var scrolled_window = new Gtk.ScrolledWindow (null, null); - scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER; - scrolled_window.add (event_listbox); - - var settings_button = new Gtk.ModelButton (); - settings_button.text = _("Date & Time Settings…"); - - main_grid = new Gtk.Grid (); - main_grid.margin_top = 12; - main_grid.attach (calendar, 0, 0); - main_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0); - main_grid.attach (scrolled_window, 2, 0); - main_grid.attach (new Wingpanel.Widgets.Separator (), 0, 2, 3); - main_grid.attach (settings_button, 0, 3, 3); - - var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); - size_group.add_widget (calendar); - size_group.add_widget (event_listbox); - - calendar.day_double_click.connect (() => { - close (); - }); + return panel_label; + } - calendar.selection_changed.connect ((date) => { - idle_update_events (); - }); + public override Gtk.Widget? get_widget () { + if (main_grid == null) { + calendar = new Widgets.CalendarView (); + calendar.margin_bottom = 6; + + var placeholder_label = new Gtk.Label (_("No Events on This Day")); + placeholder_label.wrap = true; + placeholder_label.wrap_mode = Pango.WrapMode.WORD; + placeholder_label.margin_start = 12; + placeholder_label.margin_end = 12; + placeholder_label.max_width_chars = 20; + placeholder_label.justify = Gtk.Justification.CENTER; + placeholder_label.show_all (); + + var placeholder_style_context = placeholder_label.get_style_context (); + placeholder_style_context.add_class (Gtk.STYLE_CLASS_DIM_LABEL); + placeholder_style_context.add_class (Granite.STYLE_CLASS_H3_LABEL); + + event_listbox = new Gtk.ListBox (); + event_listbox.selection_mode = Gtk.SelectionMode.NONE; + event_listbox.set_header_func (header_update_func); + event_listbox.set_placeholder (placeholder_label); + event_listbox.set_sort_func (sort_function); + + var scrolled_window = new Gtk.ScrolledWindow (null, null); + scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER; + scrolled_window.add (event_listbox); + + var settings_button = new Gtk.ModelButton (); + settings_button.text = _("Date & Time Settings…"); + + main_grid = new Gtk.Grid (); + main_grid.margin_top = 12; + main_grid.attach (calendar, 0, 0); + main_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0); + main_grid.attach (scrolled_window, 2, 0); + main_grid.attach (new Wingpanel.Widgets.Separator (), 0, 2, 3); + main_grid.attach (settings_button, 0, 3, 3); + + var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); + size_group.add_widget (calendar); + size_group.add_widget (event_listbox); + + calendar.day_double_click.connect (() => { + close (); + }); + + calendar.selection_changed.connect ((date) => { + idle_update_events (); + }); + + event_listbox.row_activated.connect ((row) => { + calendar.show_date_in_maya (((EventRow) row).date); + close (); + }); + + settings_button.clicked.connect (() => { + try { + AppInfo.launch_default_for_uri ("settings://time", null); + } catch (Error e) { + warning ("Failed to open time and date settings: %s", e.message); + } + }); + } - event_listbox.row_activated.connect ((row) => { - calendar.show_date_in_maya (((DateTime.EventRow) row).date); - close (); - }); + return main_grid; + } - settings_button.clicked.connect (() => { - try { - AppInfo.launch_default_for_uri ("settings://time", null); - } catch (Error e) { - warning ("Failed to open time and date settings: %s", e.message); + private void header_update_func (Gtk.ListBoxRow lbrow, Gtk.ListBoxRow? lbbefore) { + var row = (EventRow) lbrow; + if (lbbefore != null) { + var before = (EventRow) lbbefore; + if (row.is_allday == before.is_allday) { + row.set_header (null); + return; } - }); - } - return main_grid; - } + if (row.is_allday != before.is_allday) { + var header_label = new Granite.HeaderLabel (_("During the Day")); + header_label.margin_start = header_label.margin_end = 6; - private void header_update_func (Gtk.ListBoxRow lbrow, Gtk.ListBoxRow? lbbefore) { - var row = (DateTime.EventRow) lbrow; - if (lbbefore != null) { - var before = (DateTime.EventRow) lbbefore; - if (row.is_allday == before.is_allday) { - row.set_header (null); + row.set_header (header_label); + return; + } + } else { + if (row.is_allday) { + var allday_header = new Granite.HeaderLabel (_("All Day")); + allday_header.margin_start = allday_header.margin_end = 6; + + row.set_header (allday_header); + } return; } + } - if (row.is_allday != before.is_allday) { - var header_label = new Granite.HeaderLabel (_("During the Day")); - header_label.margin_start = header_label.margin_end = 6; + [CCode (instance_pos = -1)] + private int sort_function (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) { + var e1 = (EventRow) child1; + var e2 = (EventRow) child2; - row.set_header (header_label); - return; + if (e1.start_time.compare (e2.start_time) != 0) { + return e1.start_time.compare (e2.start_time); } - } else { - if (row.is_allday) { - var allday_header = new Granite.HeaderLabel (_("All Day")); - allday_header.margin_start = allday_header.margin_end = 6; - row.set_header (allday_header); + // If they have the same date, sort them wholeday first + if (e1.is_allday) { + return -1; + } else if (e2.is_allday) { + return 1; } - return; - } - } - - [CCode (instance_pos = -1)] - private int sort_function (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) { - var e1 = (EventRow) child1; - var e2 = (EventRow) child2; - if (e1.start_time.compare (e2.start_time) != 0) { - return e1.start_time.compare (e2.start_time); + return 0; } - // If they have the same date, sort them wholeday first - if (e1.is_allday) { - return -1; - } else if (e2.is_allday) { - return 1; + private void update_events_model (E.Source source, Gee.Collection events) { + idle_update_events (); } - return 0; - } - - private void update_events_model (E.Source source, Gee.Collection events) { - idle_update_events (); - } + private void idle_update_events () { + if (update_events_idle_source > 0) { + GLib.Source.remove (update_events_idle_source); + } - private void idle_update_events () { - if (update_events_idle_source > 0) { - GLib.Source.remove (update_events_idle_source); + update_events_idle_source = GLib.Idle.add (update_events); } - update_events_idle_source = GLib.Idle.add (update_events); - } - - private bool update_events () { - foreach (unowned Gtk.Widget widget in event_listbox.get_children ()) { - widget.destroy (); - } + private bool update_events () { + foreach (unowned Gtk.Widget widget in event_listbox.get_children ()) { + widget.destroy (); + } - if (calendar.selected_date == null) { - update_events_idle_source = 0; - return GLib.Source.REMOVE; - } + if (calendar.selected_date == null) { + update_events_idle_source = 0; + return GLib.Source.REMOVE; + } - var date = calendar.selected_date; + var date = calendar.selected_date; - var model = Widgets.CalendarModel.get_default (); + var model = Models.CalendarModel.get_default (); - var events_on_day = new Gee.TreeMap (); + var events_on_day = new Gee.TreeMap (); - model.source_events.@foreach ((source, component_map) => { - foreach (var comp in component_map.get_values ()) { - if (Util.calcomp_is_on_day (comp, date)) { - unowned ICal.Component ical = comp.get_icalcomponent (); - var event_uid = ical.get_uid (); - if (!events_on_day.has_key (event_uid)) { - events_on_day[event_uid] = new DateTime.EventRow (date, ical, source); + model.source_events.@foreach ((source, component_map) => { + foreach (var comp in component_map.get_values ()) { + if (Util.calcomp_is_on_day (comp, date)) { + unowned ICal.Component ical = comp.get_icalcomponent (); + var event_uid = ical.get_uid (); + if (!events_on_day.has_key (event_uid)) { + events_on_day[event_uid] = new EventRow (date, ical, source); - event_listbox.add (events_on_day[event_uid]); + event_listbox.add (events_on_day[event_uid]); + } } } - } - }); + }); - event_listbox.show_all (); - update_events_idle_source = 0; - return GLib.Source.REMOVE; - } + event_listbox.show_all (); + update_events_idle_source = 0; + return GLib.Source.REMOVE; + } - public override void opened () { - calendar.show_today (); + public override void opened () { + calendar.show_today (); - Widgets.CalendarModel.get_default ().events_added.connect (update_events_model); - Widgets.CalendarModel.get_default ().events_updated.connect (update_events_model); - Widgets.CalendarModel.get_default ().events_removed.connect (update_events_model); - } + Models.CalendarModel.get_default ().events_added.connect (update_events_model); + Models.CalendarModel.get_default ().events_updated.connect (update_events_model); + Models.CalendarModel.get_default ().events_removed.connect (update_events_model); + } - public override void closed () { - Widgets.CalendarModel.get_default ().events_added.disconnect (update_events_model); - Widgets.CalendarModel.get_default ().events_updated.disconnect (update_events_model); - Widgets.CalendarModel.get_default ().events_removed.disconnect (update_events_model); + public override void closed () { + Models.CalendarModel.get_default ().events_added.disconnect (update_events_model); + Models.CalendarModel.get_default ().events_updated.disconnect (update_events_model); + Models.CalendarModel.get_default ().events_removed.disconnect (update_events_model); + } } } - public Wingpanel.Indicator get_indicator (Module module) { debug ("Activating DateTime Indicator"); - var indicator = new DateTime.Indicator (); + var indicator = new DateTimeIndicator.Indicator (); return indicator; } diff --git a/src/Widgets/calendar/CalendarModel.vala b/src/Models/CalendarModel.vala similarity index 99% rename from src/Widgets/calendar/CalendarModel.vala rename to src/Models/CalendarModel.vala index 7602303..965b93e 100644 --- a/src/Widgets/calendar/CalendarModel.vala +++ b/src/Models/CalendarModel.vala @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -namespace DateTime.Widgets { - public class CalendarModel : Object { +namespace DateTimeIndicator { + public class Models.CalendarModel : Object { /* The data_range is the range of dates for which this model is storing * data. * diff --git a/src/Services/TimeManager.vala b/src/Services/TimeManager.vala index b68f158..5baa136 100644 --- a/src/Services/TimeManager.vala +++ b/src/Services/TimeManager.vala @@ -32,153 +32,155 @@ interface FDO.Accounts : Object { public abstract string find_user_by_name (string username) throws GLib.Error; } -public class DateTime.Services.TimeManager : Gtk.Calendar { - private static TimeManager? instance = null; +namespace DateTimeIndicator { + public class Services.TimeManager : Gtk.Calendar { + private static TimeManager? instance = null; - public signal void minute_changed (); + public signal void minute_changed (); - private GLib.DateTime? current_time = null; - private uint timeout_id = 0; - private Manager? manager = null; + private GLib.DateTime? current_time = null; + private uint timeout_id = 0; + private Manager? manager = null; - public bool clock_show_seconds { get; set; } - public bool is_12h { get; set; } + public bool clock_show_seconds { get; set; } + public bool is_12h { get; set; } - public TimeManager () { - update_current_time (); - - if (current_time == null) { - return; - } + public TimeManager () { + update_current_time (); - add_timeout (); - try { - var clock_settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime"); - clock_settings.bind ("clock-show-seconds", this, "clock-show-seconds", SettingsBindFlags.DEFAULT); + if (current_time == null) { + return; + } - notify["clock-show-seconds"].connect (() => { - add_timeout (); - }); + add_timeout (); + try { + var clock_settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime"); + clock_settings.bind ("clock-show-seconds", this, "clock-show-seconds", SettingsBindFlags.DEFAULT); - // Listen for the D-BUS server that controls time settings - Bus.watch_name (BusType.SYSTEM, "org.freedesktop.timedate1", BusNameWatcherFlags.NONE, on_watch, on_unwatch); - // Listen for the signal that is fired when waking up from sleep, then update time - manager = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.login1", "/org/freedesktop/login1"); - manager.prepare_for_sleep.connect ((sleeping) => { - if (!sleeping) { - update_current_time (); - minute_changed (); + notify["clock-show-seconds"].connect (() => { add_timeout (); - } - }); - } catch (Error e) { - warning (e.message); + }); + + // Listen for the D-BUS server that controls time settings + Bus.watch_name (BusType.SYSTEM, "org.freedesktop.timedate1", BusNameWatcherFlags.NONE, on_watch, on_unwatch); + // Listen for the signal that is fired when waking up from sleep, then update time + manager = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.login1", "/org/freedesktop/login1"); + manager.prepare_for_sleep.connect ((sleeping) => { + if (!sleeping) { + update_current_time (); + minute_changed (); + add_timeout (); + } + }); + } catch (Error e) { + warning (e.message); + } } - } - - construct { - setup_time_format.begin (); - } - private async void setup_time_format () { - try { - var accounts_service = yield GLib.Bus.get_proxy (GLib.BusType.SYSTEM, - "org.freedesktop.Accounts", - "/org/freedesktop/Accounts"); - var user_path = accounts_service.find_user_by_name (GLib.Environment.get_user_name ()); - - var greeter_act = yield GLib.Bus.get_proxy (GLib.BusType.SYSTEM, - "org.freedesktop.Accounts", - user_path, - GLib.DBusProxyFlags.GET_INVALIDATED_PROPERTIES); - is_12h = ("12h" in greeter_act.time_format); - ((GLib.DBusProxy) greeter_act).g_properties_changed.connect ((changed_properties, invalidated_properties) => { - if (changed_properties.lookup_value ("TimeFormat", GLib.VariantType.STRING) != null) { - is_12h = ("12h" in greeter_act.time_format); - } - }); - } catch (Error e) { - critical (e.message); - // Connect to the GSettings instead - var clock_settings = new GLib.Settings ("org.gnome.desktop.interface"); - clock_settings.changed["clock-format"].connect (() => { - is_12h = ("12h" in clock_settings.get_string ("clock-format")); - }); - - is_12h = ("12h" in clock_settings.get_string ("clock-format")); + construct { + setup_time_format.begin (); } - } - private void on_watch (DBusConnection conn) { - // Start updating the time display quicker because someone is changing settings - add_timeout (true); - } + private async void setup_time_format () { + try { + var accounts_service = yield GLib.Bus.get_proxy (GLib.BusType.SYSTEM, + "org.freedesktop.Accounts", + "/org/freedesktop/Accounts"); + var user_path = accounts_service.find_user_by_name (GLib.Environment.get_user_name ()); + + var greeter_act = yield GLib.Bus.get_proxy (GLib.BusType.SYSTEM, + "org.freedesktop.Accounts", + user_path, + GLib.DBusProxyFlags.GET_INVALIDATED_PROPERTIES); + is_12h = ("12h" in greeter_act.time_format); + ((GLib.DBusProxy) greeter_act).g_properties_changed.connect ((changed_properties, invalidated_properties) => { + if (changed_properties.lookup_value ("TimeFormat", GLib.VariantType.STRING) != null) { + is_12h = ("12h" in greeter_act.time_format); + } + }); + } catch (Error e) { + critical (e.message); + // Connect to the GSettings instead + var clock_settings = new GLib.Settings ("org.gnome.desktop.interface"); + clock_settings.changed["clock-format"].connect (() => { + is_12h = ("12h" in clock_settings.get_string ("clock-format")); + }); - private void on_unwatch (DBusConnection conn) { - // Stop updating the time display quicker - add_timeout (false); - } + is_12h = ("12h" in clock_settings.get_string ("clock-format")); + } + } - private void add_timeout (bool update_fast = false) { - uint interval; - if (update_fast || clock_show_seconds) { - interval = 500; - } else { - interval = calculate_time_until_next_minute (); + private void on_watch (DBusConnection conn) { + // Start updating the time display quicker because someone is changing settings + add_timeout (true); } - if (timeout_id > 0) { - Source.remove (timeout_id); + private void on_unwatch (DBusConnection conn) { + // Stop updating the time display quicker + add_timeout (false); } - timeout_id = Timeout.add (interval, () => { - update_current_time (); - minute_changed (); - add_timeout (update_fast); + private void add_timeout (bool update_fast = false) { + uint interval; + if (update_fast || clock_show_seconds) { + interval = 500; + } else { + interval = calculate_time_until_next_minute (); + } - return false; - }); - } + if (timeout_id > 0) { + Source.remove (timeout_id); + } - public string format (string format) { - if (current_time == null) { - return "undef"; + timeout_id = Timeout.add (interval, () => { + update_current_time (); + minute_changed (); + add_timeout (update_fast); + + return false; + }); } - return current_time.format (format); - } + public string format (string format) { + if (current_time == null) { + return "undef"; + } - public GLib.DateTime get_current_time () { - return current_time; - } + return current_time.format (format); + } - private void update_current_time () { - var local_time = new GLib.DateTime.now_local (); + public GLib.DateTime get_current_time () { + return current_time; + } - if (local_time == null) { - critical ("Can't get the local time."); + private void update_current_time () { + var local_time = new GLib.DateTime.now_local (); - return; - } + if (local_time == null) { + critical ("Can't get the local time."); - current_time = local_time; - } + return; + } - private uint calculate_time_until_next_minute () { - if (current_time == null) { - return 60 * 1000; + current_time = local_time; } - var seconds_until_next_minute = 60 - (current_time.to_unix () % 60); + private uint calculate_time_until_next_minute () { + if (current_time == null) { + return 60 * 1000; + } - return (uint)seconds_until_next_minute * 1000; - } + var seconds_until_next_minute = 60 - (current_time.to_unix () % 60); - public static TimeManager get_default () { - if (instance == null) { - instance = new TimeManager (); + return (uint)seconds_until_next_minute * 1000; } - return instance; + public static TimeManager get_default () { + if (instance == null) { + instance = new TimeManager (); + } + + return instance; + } } } diff --git a/src/Util/DateIterator.vala b/src/Util/DateIterator.vala new file mode 100644 index 0000000..c2c771e --- /dev/null +++ b/src/Util/DateIterator.vala @@ -0,0 +1,84 @@ +/* + * Copyright 2011-2018 elementary, Inc. (https://elementary.io) + * + * This program 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 2 of the License, or (at your option) any later version. + * + * This program 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, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Authored by: Corentin Noël + */ + +namespace DateTimeIndicator { + public class Util.DateIterator : Object, Gee.Traversable, Gee.Iterator { + public GLib.DateTime current { get; construct set; } + public Util.DateRange range { get; construct; } + + // Required by Gee.Iterator + public bool valid { + get { + return true; + } + } + + // Required by Gee.Iterator + public bool read_only { + get { + return false; + } + } + + public DateIterator (Util.DateRange range) { + Object ( + range: range, + current: range.first_dt.add_days (-1) + ); + } + + public bool @foreach (Gee.ForallFunc f) { + var element = range.first_dt; + + while (element.compare (range.last_dt) < 0) { + if (f (element) == false) { + return false; + } + + element = element.add_days (1); + } + + return true; + } + + public bool next () { + if (!has_next ()) { + return false; + } + + current = this.current.add_days (1); + + return true; + } + + public bool has_next () { + return current.compare (range.last_dt) < 0; + } + + public new GLib.DateTime get () { + return current; + } + + public void remove () { + assert_not_reached (); + } + } +} diff --git a/src/Util/DateRange.vala b/src/Util/DateRange.vala new file mode 100644 index 0000000..82da7c8 --- /dev/null +++ b/src/Util/DateRange.vala @@ -0,0 +1,68 @@ +/* + * Copyright 2011-2019 elementary, Inc. (https://elementary.io) + * + * This program 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 2 of the License, or (at your option) any later version. + * + * This program 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, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Authored by: Corentin Noël + */ + +namespace DateTimeIndicator { +/* Represents date range from 'first' to 'last' inclusive */ + public class Util.DateRange : Object, Gee.Traversable, Gee.Iterable { + public GLib.DateTime first_dt { get; construct; } + public GLib.DateTime last_dt { get; construct; } + + public bool @foreach (Gee.ForallFunc f) { + foreach (var date in this) { + if (f (date) == false) { + return false; + } + } + + return true; + } + + public DateRange (GLib.DateTime first, GLib.DateTime last) { + Object ( + first_dt: first, + last_dt: last + ); + } + + public bool equals (DateRange other) { + return (first_dt == other.first_dt && last_dt == other.last_dt); + } + + public Gee.Iterator iterator () { + return new DateIterator (this); + } + + public Gee.List to_list () { + var list = new Gee.ArrayList ((Gee.EqualDataFunc? )datetime_equal_func); + + foreach (var date in this) { + list.add (date); + } + + return list; + } + + /* Returns true if 'a' and 'b' are the same GLib.DateTime */ + private bool datetime_equal_func (GLib.DateTime a, GLib.DateTime b) { + return a.equal (b); + } + } +} diff --git a/src/Widgets/calendar/Util.vala b/src/Util/Util.vala similarity index 96% rename from src/Widgets/calendar/Util.vala rename to src/Util/Util.vala index e51f784..c261f4b 100644 --- a/src/Widgets/calendar/Util.vala +++ b/src/Util/Util.vala @@ -19,7 +19,7 @@ * Authored by: Corentin Noël */ -namespace Util { +namespace DateTimeIndicator.Util { static bool has_scrolled = false; public bool on_scroll_event (Gdk.EventScroll event) { @@ -35,7 +35,7 @@ namespace Util { /* It's mouse scroll ! */ if (choice == 1 || choice == -1) { - DateTime.Widgets.CalendarModel.get_default ().change_month ((int)choice); + Models.CalendarModel.get_default ().change_month ((int)choice); return true; } @@ -46,14 +46,14 @@ namespace Util { if (choice > 0.3) { reset_timer.begin (); - DateTime.Widgets.CalendarModel.get_default ().change_month (1); + Models.CalendarModel.get_default ().change_month (1); return true; } if (choice < -0.3) { reset_timer.begin (); - DateTime.Widgets.CalendarModel.get_default ().change_month (-1); + Models.CalendarModel.get_default ().change_month (-1); return true; } diff --git a/src/Widgets/CalendarView.vala b/src/Widgets/CalendarView.vala new file mode 100644 index 0000000..65cee28 --- /dev/null +++ b/src/Widgets/CalendarView.vala @@ -0,0 +1,185 @@ +/*- + * Copyright (c) 2011–2018 elementary, Inc. (https://elementary.io) + * + * This program 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. + * + * This program 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 . + * + * Authored by: Maxwell Barvian + * Corentin Noël + */ + +namespace DateTimeIndicator { + public class Widgets.CalendarView : Gtk.Grid { + public signal void day_double_click (); + public signal void event_updates (); + public signal void selection_changed (GLib.DateTime? new_date); + + public GLib.DateTime? selected_date { get; private set; } + + private Widgets.Grid grid; + private Gtk.Stack stack; + private Gtk.Grid big_grid; + + construct { + var label = new Gtk.Label (new GLib.DateTime.now_local ().format (_("%OB, %Y"))); + label.hexpand = true; + label.margin_start = 6; + label.xalign = 0; + label.width_chars = 13; + + var provider = new Gtk.CssProvider (); + provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/ControlHeader.css"); + + var label_style_context = label.get_style_context (); + label_style_context.add_class ("header-label"); + label_style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + var left_button = new Gtk.Button.from_icon_name ("pan-start-symbolic"); + var center_button = new Gtk.Button.from_icon_name ("office-calendar-symbolic"); + center_button.tooltip_text = _("Go to today's date"); + var right_button = new Gtk.Button.from_icon_name ("pan-end-symbolic"); + + var box_buttons = new Gtk.Grid (); + box_buttons.margin_end = 6; + box_buttons.valign = Gtk.Align.CENTER; + box_buttons.get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED); + box_buttons.add (left_button); + box_buttons.add (center_button); + box_buttons.add (right_button); + + big_grid = create_big_grid (); + + stack = new Gtk.Stack (); + stack.add (big_grid); + stack.show_all (); + stack.expand = true; + + stack.notify["transition-running"].connect (() => { + if (stack.transition_running == false) { + stack.get_children ().foreach ((child) => { + if (child != stack.visible_child) { + child.destroy (); + } + }); + } + }); + + column_spacing = 6; + row_spacing = 6; + margin_start = margin_end = 10; + attach (label, 0, 0); + attach (box_buttons, 1, 0); + attach (stack, 0, 1, 2); + + var model = Models.CalendarModel.get_default (); + model.notify["data-range"].connect (() => { + label.label = model.month_start.format (_("%OB, %Y")); + + sync_with_model (); + + selected_date = null; + selection_changed (selected_date); + }); + + left_button.clicked.connect (() => { + model.change_month (-1); + }); + + right_button.clicked.connect (() => { + model.change_month (1); + }); + + center_button.clicked.connect (() => { + show_today (); + }); + } + + private Gtk.Grid create_big_grid () { + grid = new Widgets.Grid (); + grid.show_all (); + + grid.on_event_add.connect ((date) => { + show_date_in_maya (date); + day_double_click (); + }); + + grid.selection_changed.connect ((date) => { + selected_date = date; + selection_changed (date); + }); + + return grid; + } + + public void show_today () { + var calmodel = Models.CalendarModel.get_default (); + var today = Util.strip_time (new GLib.DateTime.now_local ()); + var start = Util.get_start_of_month (today); + selected_date = today; + if (!start.equal (calmodel.month_start)) { + calmodel.month_start = start; + } + sync_with_model (); + + grid.set_focus_to_today (); + } + + // TODO: As far as maya supports it use the Dbus Activation feature to run the calendar-app. + public void show_date_in_maya (GLib.DateTime date) { + var command = "io.elementary.calendar --show-day %s".printf (date.format ("%F")); + + try { + var appinfo = AppInfo.create_from_commandline (command, null, AppInfoCreateFlags.NONE); + appinfo.launch_uris (null, null); + } catch (GLib.Error e) { + var dialog = new Granite.MessageDialog.with_image_from_icon_name ( + _("Unable To Launch Calendar"), + _("The program \"io.elementary.calendar\" may not be installed"), + "dialog-error" + ); + dialog.show_error_details (e.message); + dialog.run (); + dialog.destroy (); + } + } + + /* Sets the calendar widgets to the date range of the model */ + private void sync_with_model () { + var model = Models.CalendarModel.get_default (); + if (grid.grid_range != null && (model.data_range.equals (grid.grid_range) || grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) { + grid.update_today (); + return; // nothing else to do + } + + GLib.DateTime previous_first = null; + if (grid.grid_range != null) + previous_first = grid.grid_range.first_dt; + + big_grid = create_big_grid (); + stack.add (big_grid); + + grid.set_range (model.data_range, model.month_start); + grid.update_weeks (model.data_range.first_dt, model.num_weeks); + + if (previous_first != null) { + if (previous_first.compare (grid.grid_range.first_dt) == -1) { + stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT; + } else { + stack.transition_type = Gtk.StackTransitionType.SLIDE_RIGHT; + } + } + + stack.set_visible_child (big_grid); + } + } +} diff --git a/src/Widgets/EventRow.vala b/src/Widgets/EventRow.vala index 8e0513e..1268311 100644 --- a/src/Widgets/EventRow.vala +++ b/src/Widgets/EventRow.vala @@ -17,104 +17,106 @@ * Boston, MA 02110-1301 USA. */ -public class DateTime.EventRow : Gtk.ListBoxRow { - public GLib.DateTime date { get; construct; } - public unowned ICal.Component component { get; construct; } - public unowned E.SourceCalendar cal { get; construct; } - - public GLib.DateTime start_time { get; private set; } - public GLib.DateTime? end_time { get; private set; } - public bool is_allday { get; private set; default = false; } - - private static Services.TimeManager time_manager; - private static Gtk.CssProvider css_provider; - - private Gtk.Grid grid; - private Gtk.Image event_image; - private Gtk.Label time_label; - - public EventRow (GLib.DateTime date, ICal.Component component, E.Source source) { - Object ( - component: component, - date: date, - cal: (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR) - ); - } - - static construct { - css_provider = new Gtk.CssProvider (); - css_provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/EventRow.css"); - - time_manager = Services.TimeManager.get_default (); - } +namespace DateTimeIndicator { + public class EventRow : Gtk.ListBoxRow { + public GLib.DateTime date { get; construct; } + public unowned ICal.Component component { get; construct; } + public unowned E.SourceCalendar cal { get; construct; } + + public GLib.DateTime start_time { get; private set; } + public GLib.DateTime? end_time { get; private set; } + public bool is_allday { get; private set; default = false; } + + private static Services.TimeManager time_manager; + private static Gtk.CssProvider css_provider; + + private Gtk.Grid grid; + private Gtk.Image event_image; + private Gtk.Label time_label; + + public EventRow (GLib.DateTime date, ICal.Component component, E.Source source) { + Object ( + component: component, + date: date, + cal: (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR) + ); + } - construct { - start_time = Util.ical_to_date_time (component.get_dtstart ()); - end_time = Util.ical_to_date_time (component.get_dtend ()); + static construct { + css_provider = new Gtk.CssProvider (); + css_provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/EventRow.css"); - if (end_time != null && Util.is_the_all_day (start_time, end_time)) { - is_allday = true; + time_manager = Services.TimeManager.get_default (); } - unowned string icon_name = "office-calendar-symbolic"; - if (end_time == null) { - icon_name = "alarm-symbolic"; + construct { + start_time = Util.ical_to_date_time (component.get_dtstart ()); + end_time = Util.ical_to_date_time (component.get_dtend ()); + + if (end_time != null && Util.is_the_all_day (start_time, end_time)) { + is_allday = true; + } + + unowned string icon_name = "office-calendar-symbolic"; + if (end_time == null) { + icon_name = "alarm-symbolic"; + } + + event_image = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.MENU); + event_image.valign = Gtk.Align.START; + + unowned Gtk.StyleContext event_image_context = event_image.get_style_context (); + event_image_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + var name_label = new Gtk.Label (component.get_summary ()); + name_label.hexpand = true; + name_label.ellipsize = Pango.EllipsizeMode.END; + name_label.lines = 3; + name_label.max_width_chars = 30; + name_label.wrap = true; + name_label.wrap_mode = Pango.WrapMode.WORD_CHAR; + name_label.xalign = 0; + + unowned Gtk.StyleContext name_label_context = name_label.get_style_context (); + name_label_context.add_class ("title"); + name_label_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + time_label = new Gtk.Label (null); + time_label.use_markup = true; + time_label.xalign = 0; + time_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); + + grid = new Gtk.Grid (); + grid.column_spacing = 6; + grid.margin = 3; + grid.margin_start = grid.margin_end = 6; + grid.attach (event_image, 0, 0); + grid.attach (name_label, 1, 0); + if (!is_allday) { + grid.attach (time_label, 1, 1); + } + + unowned Gtk.StyleContext grid_context = grid.get_style_context (); + grid_context.add_class ("event"); + grid_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + add (grid); + + set_color (); + cal.notify["color"].connect (set_color); + + update_timelabel (); + time_manager.notify["is-12h"].connect (update_timelabel); } - event_image = new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.MENU); - event_image.valign = Gtk.Align.START; - - unowned Gtk.StyleContext event_image_context = event_image.get_style_context (); - event_image_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - - var name_label = new Gtk.Label (component.get_summary ()); - name_label.hexpand = true; - name_label.ellipsize = Pango.EllipsizeMode.END; - name_label.lines = 3; - name_label.max_width_chars = 30; - name_label.wrap = true; - name_label.wrap_mode = Pango.WrapMode.WORD_CHAR; - name_label.xalign = 0; - - unowned Gtk.StyleContext name_label_context = name_label.get_style_context (); - name_label_context.add_class ("title"); - name_label_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - - time_label = new Gtk.Label (null); - time_label.use_markup = true; - time_label.xalign = 0; - time_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - - grid = new Gtk.Grid (); - grid.column_spacing = 6; - grid.margin = 3; - grid.margin_start = grid.margin_end = 6; - grid.attach (event_image, 0, 0); - grid.attach (name_label, 1, 0); - if (!is_allday) { - grid.attach (time_label, 1, 1); + private void update_timelabel () { + var time_format = Granite.DateTime.get_default_time_format (time_manager.is_12h); + time_label.label = "%s – %s".printf (start_time.format (time_format), end_time.format (time_format)); } - unowned Gtk.StyleContext grid_context = grid.get_style_context (); - grid_context.add_class ("event"); - grid_context.add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - - add (grid); - - set_color (); - cal.notify["color"].connect (set_color); - - update_timelabel (); - time_manager.notify["is-12h"].connect (update_timelabel); - } - - private void update_timelabel () { - var time_format = Granite.DateTime.get_default_time_format (time_manager.is_12h); - time_label.label = "%s – %s".printf (start_time.format (time_format), end_time.format (time_format)); - } - - private void set_color () { - Util.set_event_calendar_color (cal, grid); - Util.set_event_calendar_color (cal, event_image); + private void set_color () { + Util.set_event_calendar_color (cal, grid); + Util.set_event_calendar_color (cal, event_image); + } } } diff --git a/src/Widgets/calendar/Grid.vala b/src/Widgets/Grid.vala similarity index 95% rename from src/Widgets/calendar/Grid.vala rename to src/Widgets/Grid.vala index 2b48636..165d11d 100644 --- a/src/Widgets/calendar/Grid.vala +++ b/src/Widgets/Grid.vala @@ -20,11 +20,11 @@ * Corentin Noël */ -namespace DateTime.Widgets { +namespace DateTimeIndicator { /** * Represents the entire date grid as a table. */ - public class Grid : Gtk.Grid { + public class Widgets.Grid : Gtk.Grid { public Util.DateRange grid_range { get; private set; } /* @@ -59,7 +59,7 @@ namespace DateTime.Widgets { hexpand = true; attach (week_sep_revealer, 1, 1, 1, 6); - DateTime.Indicator.settings.bind ("show-weeks", week_sep_revealer, "reveal-child", GLib.SettingsBindFlags.DEFAULT); + Indicator.settings.bind ("show-weeks", week_sep_revealer, "reveal-child", GLib.SettingsBindFlags.DEFAULT); data = new Gee.HashMap (); events |= Gdk.EventMask.SCROLL_MASK; @@ -77,7 +77,7 @@ namespace DateTime.Widgets { day.set_selected (true); day.set_state_flags (Gtk.StateFlags.FOCUSED, false); selection_changed (selected_date); - var calmodel = CalendarModel.get_default (); + var calmodel = Models.CalendarModel.get_default (); var date_month = selected_date.get_month () - calmodel.month_start.get_month (); var date_year = selected_date.get_year () - calmodel.month_start.get_year (); @@ -127,7 +127,7 @@ namespace DateTime.Widgets { /* Create new widgets for the new range */ var date = Util.strip_time (today); - date = date.add_days (CalendarModel.get_default ().week_starts_on - date.get_day_of_week ()); + date = date.add_days (Models.CalendarModel.get_default ().week_starts_on - date.get_day_of_week ()); foreach (var label in header_labels) { label.label = date.format ("%a"); date = date.add_days (1); @@ -221,7 +221,7 @@ namespace DateTime.Widgets { week_labels[c].add (week_label); week_labels[c].show_all (); - DateTime.Indicator.settings.bind ("show-weeks", week_labels[c], "reveal-child", GLib.SettingsBindFlags.DEFAULT); + Indicator.settings.bind ("show-weeks", week_labels[c], "reveal-child", GLib.SettingsBindFlags.DEFAULT); attach (week_labels[c], 0, c + 1); diff --git a/src/Widgets/GridDay.vala b/src/Widgets/GridDay.vala new file mode 100644 index 0000000..8c44443 --- /dev/null +++ b/src/Widgets/GridDay.vala @@ -0,0 +1,180 @@ +// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- +/*- + * Copyright (c) 2011–2018 elementary, Inc. (https://elementary.io) + * + * This program 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. + * + * This program 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 . + * + * Authored by: Maxwell Barvian + * Corentin Noël + */ + +namespace DateTimeIndicator { +/** + * Represents a single day on the grid. + */ + public class Widgets.GridDay : Gtk.EventBox { + /* + * Event emitted when the day is double clicked or the ENTER key is pressed. + */ + public signal void on_event_add (GLib.DateTime date); + + public GLib.DateTime date { get; construct set; } + + private static Gtk.CssProvider provider; + private static Models.CalendarModel model; + + private Gee.HashMap event_dots; + private Gtk.Grid event_grid; + private Gtk.Label label; + private bool valid_grab = false; + + public GridDay (GLib.DateTime date) { + Object (date: date); + } + + static construct { + model = Models.CalendarModel.get_default (); + + provider = new Gtk.CssProvider (); + provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/GridDay.css"); + } + + construct { + unowned Gtk.StyleContext style_context = get_style_context (); + style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + style_context.add_class ("circular"); + + label = new Gtk.Label (null); + + event_grid = new Gtk.Grid (); + event_grid.halign = Gtk.Align.CENTER; + event_grid.height_request = 6; + + var grid = new Gtk.Grid (); + grid.halign = grid.valign = Gtk.Align.CENTER; + grid.attach (label, 0, 0); + grid.attach (event_grid, 0, 1); + + can_focus = true; + events |= Gdk.EventMask.BUTTON_PRESS_MASK; + events |= Gdk.EventMask.KEY_PRESS_MASK; + events |= Gdk.EventMask.SMOOTH_SCROLL_MASK; + set_size_request (35, 35); + halign = Gtk.Align.CENTER; + hexpand = true; + add (grid); + show_all (); + + // Signals and handlers + button_press_event.connect (on_button_press); + key_press_event.connect (on_key_press); + scroll_event.connect ((event) => {return Util.on_scroll_event (event);}); + + notify["date"].connect (() => { + label.label = date.get_day_of_month ().to_string (); + }); + + event_dots = new Gee.HashMap (); + + model.events_added.connect (add_event_dots); + model.events_removed.connect (remove_event_dots); + } + + private void add_event_dots (E.Source source, Gee.Collection events) { + foreach (var component in events) { + if (event_dots.size >= 3) { + return; + } + + if (Util.calcomp_is_on_day (component, date)) { + unowned ICal.Component ical = component.get_icalcomponent (); + + var event_uid = ical.get_uid (); + if (!event_dots.has_key (event_uid)) { + var event_dot = new Gtk.Image (); + event_dot.gicon = new ThemedIcon ("pager-checked-symbolic"); + event_dot.pixel_size = 6; + + unowned Gtk.StyleContext style_context = event_dot.get_style_context (); + style_context.add_class (Granite.STYLE_CLASS_ACCENT); + style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR); + Util.set_event_calendar_color (source_calendar, event_dot); + + event_dots[event_uid] = event_dot; + + event_grid.add (event_dot); + } + } + } + + event_grid.show_all (); + } + + private void remove_event_dots (E.Source source, Gee.Collection events) { + foreach (var component in events) { + unowned ICal.Component ical = component.get_icalcomponent (); + var event_uid = ical.get_uid (); + var dot = event_dots[event_uid]; + if (dot != null) { + dot.destroy (); + event_dots.remove (event_uid); + } + } + } + + public void set_selected (bool selected) { + if (selected) { + set_state_flags (Gtk.StateFlags.SELECTED, true); + } else { + set_state_flags (Gtk.StateFlags.NORMAL, true); + } + } + + public void grab_focus_force () { + valid_grab = true; + grab_focus (); + } + + public override void grab_focus () { + if (valid_grab) { + base.grab_focus (); + valid_grab = false; + } + } + + public void sensitive_container (bool sens) { + label.sensitive = sens; + event_grid.sensitive = sens; + } + + private bool on_button_press (Gdk.EventButton event) { + if (event.type == Gdk.EventType.2BUTTON_PRESS && event.button == Gdk.BUTTON_PRIMARY) + on_event_add (date); + valid_grab = true; + grab_focus (); + return false; + } + + private bool on_key_press (Gdk.EventKey event) { + if (event.keyval == Gdk.keyval_from_name ("Return") ) { + on_event_add (date); + return true; + } + + return false; + } + } +} diff --git a/src/Widgets/PanelLabel.vala b/src/Widgets/PanelLabel.vala index f253f9b..dff9a21 100644 --- a/src/Widgets/PanelLabel.vala +++ b/src/Widgets/PanelLabel.vala @@ -17,55 +17,57 @@ * Boston, MA 02110-1301 USA. */ -public class DateTime.Widgets.PanelLabel : Gtk.Grid { - private Gtk.Label date_label; - private Gtk.Label time_label; - private Services.TimeManager time_manager; +namespace DateTimeIndicator { + public class Widgets.PanelLabel : Gtk.Grid { + private Gtk.Label date_label; + private Gtk.Label time_label; + private Services.TimeManager time_manager; - public string clock_format { get; set; } - public bool clock_show_seconds { get; set; } - public bool clock_show_weekday { get; set; } + public string clock_format { get; set; } + public bool clock_show_seconds { get; set; } + public bool clock_show_weekday { get; set; } - construct { - date_label = new Gtk.Label (null); - date_label.margin_end = 12; + construct { + date_label = new Gtk.Label (null); + date_label.margin_end = 12; - var date_revealer = new Gtk.Revealer (); - date_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_LEFT; - date_revealer.add (date_label); + var date_revealer = new Gtk.Revealer (); + date_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_LEFT; + date_revealer.add (date_label); - time_label = new Gtk.Label (null); + time_label = new Gtk.Label (null); - valign = Gtk.Align.CENTER; - add (date_revealer); - add (time_label); + valign = Gtk.Align.CENTER; + add (date_revealer); + add (time_label); - var clock_settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime"); - clock_settings.bind ("clock-format", this, "clock-format", SettingsBindFlags.DEFAULT); - clock_settings.bind ("clock-show-seconds", this, "clock-show-seconds", SettingsBindFlags.DEFAULT); - clock_settings.bind ("clock-show-date", date_revealer, "reveal_child", SettingsBindFlags.DEFAULT); - clock_settings.bind ("clock-show-weekday", this, "clock-show-weekday", SettingsBindFlags.DEFAULT); + var clock_settings = new GLib.Settings ("io.elementary.desktop.wingpanel.datetime"); + clock_settings.bind ("clock-format", this, "clock-format", SettingsBindFlags.DEFAULT); + clock_settings.bind ("clock-show-seconds", this, "clock-show-seconds", SettingsBindFlags.DEFAULT); + clock_settings.bind ("clock-show-date", date_revealer, "reveal_child", SettingsBindFlags.DEFAULT); + clock_settings.bind ("clock-show-weekday", this, "clock-show-weekday", SettingsBindFlags.DEFAULT); - notify.connect (() => { - update_labels (); - }); + notify.connect (() => { + update_labels (); + }); - time_manager = Services.TimeManager.get_default (); - time_manager.minute_changed.connect (update_labels); - time_manager.notify["is-12h"].connect (update_labels); - } - - private void update_labels () { - string date_format; - if (clock_format == "ISO8601") { - date_format = "%F"; - } else { - date_format = Granite.DateTime.get_default_date_format (clock_show_weekday, true, false); + time_manager = Services.TimeManager.get_default (); + time_manager.minute_changed.connect (update_labels); + time_manager.notify["is-12h"].connect (update_labels); } - date_label.label = time_manager.format (date_format); + private void update_labels () { + string date_format; + if (clock_format == "ISO8601") { + date_format = "%F"; + } else { + date_format = Granite.DateTime.get_default_date_format (clock_show_weekday, true, false); + } - string time_format = Granite.DateTime.get_default_time_format (time_manager.is_12h, clock_show_seconds); - time_label.label = time_manager.format (time_format); + date_label.label = time_manager.format (date_format); + + string time_format = Granite.DateTime.get_default_time_format (time_manager.is_12h, clock_show_seconds); + time_label.label = time_manager.format (time_format); + } } } diff --git a/src/Widgets/calendar/CalendarView.vala b/src/Widgets/calendar/CalendarView.vala deleted file mode 100644 index ef3f8f9..0000000 --- a/src/Widgets/calendar/CalendarView.vala +++ /dev/null @@ -1,183 +0,0 @@ -/*- - * Copyright (c) 2011–2018 elementary, Inc. (https://elementary.io) - * - * This program 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. - * - * This program 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 . - * - * Authored by: Maxwell Barvian - * Corentin Noël - */ - -public class DateTime.Widgets.CalendarView : Gtk.Grid { - public signal void day_double_click (); - public signal void event_updates (); - public signal void selection_changed (GLib.DateTime? new_date); - - public GLib.DateTime? selected_date { get; private set; } - - private Grid grid; - private Gtk.Stack stack; - private Gtk.Grid big_grid; - - construct { - var label = new Gtk.Label (new GLib.DateTime.now_local ().format (_("%OB, %Y"))); - label.hexpand = true; - label.margin_start = 6; - label.xalign = 0; - label.width_chars = 13; - - var provider = new Gtk.CssProvider (); - provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/ControlHeader.css"); - - var label_style_context = label.get_style_context (); - label_style_context.add_class ("header-label"); - label_style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - - var left_button = new Gtk.Button.from_icon_name ("pan-start-symbolic"); - var center_button = new Gtk.Button.from_icon_name ("office-calendar-symbolic"); - center_button.tooltip_text = _("Go to today's date"); - var right_button = new Gtk.Button.from_icon_name ("pan-end-symbolic"); - - var box_buttons = new Gtk.Grid (); - box_buttons.margin_end = 6; - box_buttons.valign = Gtk.Align.CENTER; - box_buttons.get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED); - box_buttons.add (left_button); - box_buttons.add (center_button); - box_buttons.add (right_button); - - big_grid = create_big_grid (); - - stack = new Gtk.Stack (); - stack.add (big_grid); - stack.show_all (); - stack.expand = true; - - stack.notify["transition-running"].connect (() => { - if (stack.transition_running == false) { - stack.get_children ().foreach ((child) => { - if (child != stack.visible_child) { - child.destroy (); - } - }); - } - }); - - column_spacing = 6; - row_spacing = 6; - margin_start = margin_end = 10; - attach (label, 0, 0); - attach (box_buttons, 1, 0); - attach (stack, 0, 1, 2); - - var model = CalendarModel.get_default (); - model.notify["data-range"].connect (() => { - label.label = model.month_start.format (_("%OB, %Y")); - - sync_with_model (); - - selected_date = null; - selection_changed (selected_date); - }); - - left_button.clicked.connect (() => { - model.change_month (-1); - }); - - right_button.clicked.connect (() => { - model.change_month (1); - }); - - center_button.clicked.connect (() => { - show_today (); - }); - } - - private Gtk.Grid create_big_grid () { - grid = new DateTime.Widgets.Grid (); - grid.show_all (); - - grid.on_event_add.connect ((date) => { - show_date_in_maya (date); - day_double_click (); - }); - - grid.selection_changed.connect ((date) => { - selected_date = date; - selection_changed (date); - }); - - return grid; - } - - public void show_today () { - var calmodel = CalendarModel.get_default (); - var today = Util.strip_time (new GLib.DateTime.now_local ()); - var start = Util.get_start_of_month (today); - selected_date = today; - if (!start.equal (calmodel.month_start)) { - calmodel.month_start = start; - } - sync_with_model (); - - grid.set_focus_to_today (); - } - - // TODO: As far as maya supports it use the Dbus Activation feature to run the calendar-app. - public void show_date_in_maya (GLib.DateTime date) { - var command = "io.elementary.calendar --show-day %s".printf (date.format ("%F")); - - try { - var appinfo = AppInfo.create_from_commandline (command, null, AppInfoCreateFlags.NONE); - appinfo.launch_uris (null, null); - } catch (GLib.Error e) { - var dialog = new Granite.MessageDialog.with_image_from_icon_name ( - _("Unable To Launch Calendar"), - _("The program \"io.elementary.calendar\" may not be installed"), - "dialog-error" - ); - dialog.show_error_details (e.message); - dialog.run (); - dialog.destroy (); - } - } - - /* Sets the calendar widgets to the date range of the model */ - private void sync_with_model () { - var model = CalendarModel.get_default (); - if (grid.grid_range != null && (model.data_range.equals (grid.grid_range) || grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) { - grid.update_today (); - return; // nothing else to do - } - - GLib.DateTime previous_first = null; - if (grid.grid_range != null) - previous_first = grid.grid_range.first_dt; - - big_grid = create_big_grid (); - stack.add (big_grid); - - grid.set_range (model.data_range, model.month_start); - grid.update_weeks (model.data_range.first_dt, model.num_weeks); - - if (previous_first != null) { - if (previous_first.compare (grid.grid_range.first_dt) == -1) { - stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT; - } else { - stack.transition_type = Gtk.StackTransitionType.SLIDE_RIGHT; - } - } - - stack.set_visible_child (big_grid); - } -} diff --git a/src/Widgets/calendar/GridDay.vala b/src/Widgets/calendar/GridDay.vala deleted file mode 100644 index a9b5a28..0000000 --- a/src/Widgets/calendar/GridDay.vala +++ /dev/null @@ -1,178 +0,0 @@ -// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- -/*- - * Copyright (c) 2011–2018 elementary, Inc. (https://elementary.io) - * - * This program 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. - * - * This program 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 . - * - * Authored by: Maxwell Barvian - * Corentin Noël - */ - -/** - * Represents a single day on the grid. - */ -public class DateTime.Widgets.GridDay : Gtk.EventBox { - /* - * Event emitted when the day is double clicked or the ENTER key is pressed. - */ - public signal void on_event_add (GLib.DateTime date); - - public GLib.DateTime date { get; construct set; } - - private static Gtk.CssProvider provider; - private static Widgets.CalendarModel model; - - private Gee.HashMap event_dots; - private Gtk.Grid event_grid; - private Gtk.Label label; - private bool valid_grab = false; - - public GridDay (GLib.DateTime date) { - Object (date: date); - } - - static construct { - model = Widgets.CalendarModel.get_default (); - - provider = new Gtk.CssProvider (); - provider.load_from_resource ("/io/elementary/desktop/wingpanel/datetime/GridDay.css"); - } - - construct { - unowned Gtk.StyleContext style_context = get_style_context (); - style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - style_context.add_class ("circular"); - - label = new Gtk.Label (null); - - event_grid = new Gtk.Grid (); - event_grid.halign = Gtk.Align.CENTER; - event_grid.height_request = 6; - - var grid = new Gtk.Grid (); - grid.halign = grid.valign = Gtk.Align.CENTER; - grid.attach (label, 0, 0); - grid.attach (event_grid, 0, 1); - - can_focus = true; - events |= Gdk.EventMask.BUTTON_PRESS_MASK; - events |= Gdk.EventMask.KEY_PRESS_MASK; - events |= Gdk.EventMask.SMOOTH_SCROLL_MASK; - set_size_request (35, 35); - halign = Gtk.Align.CENTER; - hexpand = true; - add (grid); - show_all (); - - // Signals and handlers - button_press_event.connect (on_button_press); - key_press_event.connect (on_key_press); - scroll_event.connect ((event) => {return Util.on_scroll_event (event);}); - - notify["date"].connect (() => { - label.label = date.get_day_of_month ().to_string (); - }); - - event_dots = new Gee.HashMap (); - - model.events_added.connect (add_event_dots); - model.events_removed.connect (remove_event_dots); - } - - private void add_event_dots (E.Source source, Gee.Collection events) { - foreach (var component in events) { - if (event_dots.size >= 3) { - return; - } - - if (Util.calcomp_is_on_day (component, date)) { - unowned ICal.Component ical = component.get_icalcomponent (); - - var event_uid = ical.get_uid (); - if (!event_dots.has_key (event_uid)) { - var event_dot = new Gtk.Image (); - event_dot.gicon = new ThemedIcon ("pager-checked-symbolic"); - event_dot.pixel_size = 6; - - unowned Gtk.StyleContext style_context = event_dot.get_style_context (); - style_context.add_class (Granite.STYLE_CLASS_ACCENT); - style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - - var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR); - Util.set_event_calendar_color (source_calendar, event_dot); - - event_dots[event_uid] = event_dot; - - event_grid.add (event_dot); - } - } - } - - event_grid.show_all (); - } - - private void remove_event_dots (E.Source source, Gee.Collection events) { - foreach (var component in events) { - unowned ICal.Component ical = component.get_icalcomponent (); - var event_uid = ical.get_uid (); - var dot = event_dots[event_uid]; - if (dot != null) { - dot.destroy (); - event_dots.remove (event_uid); - } - } - } - - public void set_selected (bool selected) { - if (selected) { - set_state_flags (Gtk.StateFlags.SELECTED, true); - } else { - set_state_flags (Gtk.StateFlags.NORMAL, true); - } - } - - public void grab_focus_force () { - valid_grab = true; - grab_focus (); - } - - public override void grab_focus () { - if (valid_grab) { - base.grab_focus (); - valid_grab = false; - } - } - - public void sensitive_container (bool sens) { - label.sensitive = sens; - event_grid.sensitive = sens; - } - - private bool on_button_press (Gdk.EventButton event) { - if (event.type == Gdk.EventType.2BUTTON_PRESS && event.button == Gdk.BUTTON_PRIMARY) - on_event_add (date); - valid_grab = true; - grab_focus (); - return false; - } - - private bool on_key_press (Gdk.EventKey event) { - if (event.keyval == Gdk.keyval_from_name ("Return") ) { - on_event_add (date); - return true; - } - - return false; - } -} From 11f11073d74dac1d831560c3a92687531aaf846e Mon Sep 17 00:00:00 2001 From: Dirli Date: Thu, 9 Apr 2020 20:46:31 +0300 Subject: [PATCH 2/8] Events list moved to a separate file --- meson.build | 1 + src/Indicator.vala | 113 +++------------------------------ src/Widgets/EventsListBox.vala | 102 +++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 103 deletions(-) create mode 100644 src/Widgets/EventsListBox.vala diff --git a/meson.build b/meson.build index b44c5bd..1b52276 100644 --- a/meson.build +++ b/meson.build @@ -46,6 +46,7 @@ shared_module( 'src/Models/CalendarModel.vala', 'src/Widgets/CalendarView.vala', 'src/Widgets/EventRow.vala', + 'src/Widgets/EventsListBox.vala', 'src/Widgets/Grid.vala', 'src/Widgets/GridDay.vala', 'src/Widgets/PanelLabel.vala', diff --git a/src/Indicator.vala b/src/Indicator.vala index b712c12..6a8d001 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -22,9 +22,9 @@ namespace DateTimeIndicator { public static GLib.Settings settings; private Widgets.PanelLabel panel_label; - private Gtk.Grid main_grid; private Widgets.CalendarView calendar; - private Gtk.ListBox event_listbox; + private Widgets.EventsListBox event_listbox; + private Gtk.Grid main_grid; private uint update_events_idle_source = 0; public Indicator () { @@ -56,24 +56,7 @@ namespace DateTimeIndicator { calendar = new Widgets.CalendarView (); calendar.margin_bottom = 6; - var placeholder_label = new Gtk.Label (_("No Events on This Day")); - placeholder_label.wrap = true; - placeholder_label.wrap_mode = Pango.WrapMode.WORD; - placeholder_label.margin_start = 12; - placeholder_label.margin_end = 12; - placeholder_label.max_width_chars = 20; - placeholder_label.justify = Gtk.Justification.CENTER; - placeholder_label.show_all (); - - var placeholder_style_context = placeholder_label.get_style_context (); - placeholder_style_context.add_class (Gtk.STYLE_CLASS_DIM_LABEL); - placeholder_style_context.add_class (Granite.STYLE_CLASS_H3_LABEL); - - event_listbox = new Gtk.ListBox (); - event_listbox.selection_mode = Gtk.SelectionMode.NONE; - event_listbox.set_header_func (header_update_func); - event_listbox.set_placeholder (placeholder_label); - event_listbox.set_sort_func (sort_function); + event_listbox = new Widgets.EventsListBox (); var scrolled_window = new Gtk.ScrolledWindow (null, null); scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER; @@ -84,11 +67,11 @@ namespace DateTimeIndicator { main_grid = new Gtk.Grid (); main_grid.margin_top = 12; - main_grid.attach (calendar, 0, 0); - main_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0); - main_grid.attach (scrolled_window, 2, 0); - main_grid.attach (new Wingpanel.Widgets.Separator (), 0, 2, 3); - main_grid.attach (settings_button, 0, 3, 3); + main_grid.attach (calendar, 0, 0); + main_grid.attach (new Wingpanel.Widgets.Separator (), 0, 1); + main_grid.attach (settings_button, 0, 2); + main_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 3); + main_grid.attach (scrolled_window, 2, 0, 1, 3); var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); size_group.add_widget (calendar); @@ -119,52 +102,6 @@ namespace DateTimeIndicator { return main_grid; } - private void header_update_func (Gtk.ListBoxRow lbrow, Gtk.ListBoxRow? lbbefore) { - var row = (EventRow) lbrow; - if (lbbefore != null) { - var before = (EventRow) lbbefore; - if (row.is_allday == before.is_allday) { - row.set_header (null); - return; - } - - if (row.is_allday != before.is_allday) { - var header_label = new Granite.HeaderLabel (_("During the Day")); - header_label.margin_start = header_label.margin_end = 6; - - row.set_header (header_label); - return; - } - } else { - if (row.is_allday) { - var allday_header = new Granite.HeaderLabel (_("All Day")); - allday_header.margin_start = allday_header.margin_end = 6; - - row.set_header (allday_header); - } - return; - } - } - - [CCode (instance_pos = -1)] - private int sort_function (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) { - var e1 = (EventRow) child1; - var e2 = (EventRow) child2; - - if (e1.start_time.compare (e2.start_time) != 0) { - return e1.start_time.compare (e2.start_time); - } - - // If they have the same date, sort them wholeday first - if (e1.is_allday) { - return -1; - } else if (e2.is_allday) { - return 1; - } - - return 0; - } - private void update_events_model (E.Source source, Gee.Collection events) { idle_update_events (); } @@ -174,42 +111,12 @@ namespace DateTimeIndicator { GLib.Source.remove (update_events_idle_source); } - update_events_idle_source = GLib.Idle.add (update_events); - } - - private bool update_events () { - foreach (unowned Gtk.Widget widget in event_listbox.get_children ()) { - widget.destroy (); - } + update_events_idle_source = GLib.Idle.add (() => { + event_listbox.update_events (calendar.selected_date); - if (calendar.selected_date == null) { update_events_idle_source = 0; return GLib.Source.REMOVE; - } - - var date = calendar.selected_date; - - var model = Models.CalendarModel.get_default (); - - var events_on_day = new Gee.TreeMap (); - - model.source_events.@foreach ((source, component_map) => { - foreach (var comp in component_map.get_values ()) { - if (Util.calcomp_is_on_day (comp, date)) { - unowned ICal.Component ical = comp.get_icalcomponent (); - var event_uid = ical.get_uid (); - if (!events_on_day.has_key (event_uid)) { - events_on_day[event_uid] = new EventRow (date, ical, source); - - event_listbox.add (events_on_day[event_uid]); - } - } - } }); - - event_listbox.show_all (); - update_events_idle_source = 0; - return GLib.Source.REMOVE; } public override void opened () { diff --git a/src/Widgets/EventsListBox.vala b/src/Widgets/EventsListBox.vala new file mode 100644 index 0000000..547e4c5 --- /dev/null +++ b/src/Widgets/EventsListBox.vala @@ -0,0 +1,102 @@ +namespace DateTimeIndicator { + public class Widgets.EventsListBox : Gtk.ListBox { + + public EventsListBox () { + selection_mode = Gtk.SelectionMode.NONE; + + var placeholder_label = new Gtk.Label (_("No Events on This Day")); + placeholder_label.wrap = true; + placeholder_label.wrap_mode = Pango.WrapMode.WORD; + placeholder_label.margin_start = 12; + placeholder_label.margin_end = 12; + placeholder_label.max_width_chars = 20; + placeholder_label.justify = Gtk.Justification.CENTER; + placeholder_label.show_all (); + + var placeholder_style_context = placeholder_label.get_style_context (); + placeholder_style_context.add_class (Gtk.STYLE_CLASS_DIM_LABEL); + placeholder_style_context.add_class (Granite.STYLE_CLASS_H3_LABEL); + + set_header_func (header_update_func); + set_placeholder (placeholder_label); + set_sort_func (sort_function); + } + + public void update_events (GLib.DateTime? selected_date) { + foreach (unowned Gtk.Widget widget in get_children ()) { + widget.destroy (); + } + + if (selected_date == null) { + return; + } + + var model = Models.CalendarModel.get_default (); + + var events_on_day = new Gee.TreeMap (); + + model.source_events.@foreach ((source, component_map) => { + foreach (var comp in component_map.get_values ()) { + if (Util.calcomp_is_on_day (comp, selected_date)) { + unowned ICal.Component ical = comp.get_icalcomponent (); + var event_uid = ical.get_uid (); + if (!events_on_day.has_key (event_uid)) { + events_on_day[event_uid] = new EventRow (selected_date, ical, source); + + add (events_on_day[event_uid]); + } + } + } + }); + + show_all (); + return; + } + + private void header_update_func (Gtk.ListBoxRow lbrow, Gtk.ListBoxRow? lbbefore) { + var row = (EventRow) lbrow; + if (lbbefore != null) { + var before = (EventRow) lbbefore; + if (row.is_allday == before.is_allday) { + row.set_header (null); + return; + } + + if (row.is_allday != before.is_allday) { + var header_label = new Granite.HeaderLabel (_("During the Day")); + header_label.margin_start = header_label.margin_end = 6; + + row.set_header (header_label); + return; + } + } else { + if (row.is_allday) { + var allday_header = new Granite.HeaderLabel (_("All Day")); + allday_header.margin_start = allday_header.margin_end = 6; + + row.set_header (allday_header); + } + return; + } + } + + [CCode (instance_pos = -1)] + private int sort_function (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) { + var e1 = (EventRow) child1; + var e2 = (EventRow) child2; + + if (e1.start_time.compare (e2.start_time) != 0) { + return e1.start_time.compare (e2.start_time); + } + + // If they have the same date, sort them wholeday first + if (e1.is_allday) { + return -1; + } else if (e2.is_allday) { + return 1; + } + + return 0; + } + } +} From 262d91676f78f031bcfbff637344e52c63ab89bd Mon Sep 17 00:00:00 2001 From: Dirli Date: Sat, 11 Apr 2020 21:56:33 +0300 Subject: [PATCH 3/8] added event manager --- meson.build | 1 + src/Indicator.vala | 38 ++++-- src/Models/CalendarModel.vala | 224 +------------------------------ src/Services/EventsManager.vala | 226 ++++++++++++++++++++++++++++++++ src/Util/Util.vala | 57 ++------ src/Widgets/CalendarView.vala | 9 ++ src/Widgets/EventsListBox.vala | 7 +- src/Widgets/Grid.vala | 31 +++++ src/Widgets/GridDay.vala | 111 +++++++++++----- 9 files changed, 385 insertions(+), 319 deletions(-) create mode 100644 src/Services/EventsManager.vala diff --git a/meson.build b/meson.build index 1b52276..e348e3d 100644 --- a/meson.build +++ b/meson.build @@ -50,6 +50,7 @@ shared_module( 'src/Widgets/Grid.vala', 'src/Widgets/GridDay.vala', 'src/Widgets/PanelLabel.vala', + 'src/Services/EventsManager.vala', 'src/Services/TimeManager.vala', dependencies: [ dependency('glib-2.0'), diff --git a/src/Indicator.vala b/src/Indicator.vala index 6a8d001..bf4358f 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -24,9 +24,14 @@ namespace DateTimeIndicator { private Widgets.PanelLabel panel_label; private Widgets.CalendarView calendar; private Widgets.EventsListBox event_listbox; + + private Services.EventsManager event_manager; + private Gtk.Grid main_grid; private uint update_events_idle_source = 0; + private bool opened_widget = false; + public Indicator () { Object ( code_name: Wingpanel.Indicator.DATETIME, @@ -56,10 +61,22 @@ namespace DateTimeIndicator { calendar = new Widgets.CalendarView (); calendar.margin_bottom = 6; + event_manager = new Services.EventsManager (); + event_manager.events_updated.connect (update_events_model); + event_manager.events_added.connect ((source, events) => { + calendar.add_event_dots (source, events); + update_events_model (source, events); + }); + event_manager.events_removed.connect ((source, events) => { + calendar.remove_event_dots (source, events); + update_events_model (source, events); + }); + event_listbox = new Widgets.EventsListBox (); var scrolled_window = new Gtk.ScrolledWindow (null, null); scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER; + scrolled_window.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; scrolled_window.add (event_listbox); var settings_button = new Gtk.ModelButton (); @@ -90,6 +107,12 @@ namespace DateTimeIndicator { close (); }); + var model = Models.CalendarModel.get_default (); + model.notify["month-start"].connect (() => { + model.compute_ranges (); + event_manager.load_all_sources (); + }); + settings_button.clicked.connect (() => { try { AppInfo.launch_default_for_uri ("settings://time", null); @@ -103,7 +126,9 @@ namespace DateTimeIndicator { } private void update_events_model (E.Source source, Gee.Collection events) { - idle_update_events (); + if (opened_widget) { + idle_update_events (); + } } private void idle_update_events () { @@ -112,7 +137,7 @@ namespace DateTimeIndicator { } update_events_idle_source = GLib.Idle.add (() => { - event_listbox.update_events (calendar.selected_date); + event_listbox.update_events (calendar.selected_date, event_manager.source_events); update_events_idle_source = 0; return GLib.Source.REMOVE; @@ -122,18 +147,15 @@ namespace DateTimeIndicator { public override void opened () { calendar.show_today (); - Models.CalendarModel.get_default ().events_added.connect (update_events_model); - Models.CalendarModel.get_default ().events_updated.connect (update_events_model); - Models.CalendarModel.get_default ().events_removed.connect (update_events_model); + opened_widget = true; } public override void closed () { - Models.CalendarModel.get_default ().events_added.disconnect (update_events_model); - Models.CalendarModel.get_default ().events_updated.disconnect (update_events_model); - Models.CalendarModel.get_default ().events_removed.disconnect (update_events_model); + opened_widget = false; } } } + public Wingpanel.Indicator get_indicator (Module module) { debug ("Activating DateTime Indicator"); var indicator = new DateTimeIndicator.Indicator (); diff --git a/src/Models/CalendarModel.vala b/src/Models/CalendarModel.vala index 965b93e..d60a9ac 100644 --- a/src/Models/CalendarModel.vala +++ b/src/Models/CalendarModel.vala @@ -35,17 +35,6 @@ namespace DateTimeIndicator { /* The start of week, ie. Monday=1 or Sunday=7 */ public GLib.DateWeekday week_starts_on { get; set; } - public HashTable> source_events { get; private set; } - - /* Notifies when events are added, updated, or removed */ - public signal void events_added (E.Source source, Gee.Collection events); - public signal void events_updated (E.Source source, Gee.Collection events); - public signal void events_removed (E.Source source, Gee.Collection events); - - private E.SourceRegistry registry { get; private set; } - private HashTable source_client; - private HashTable source_view; - private static CalendarModel? calendar_model = null; public static CalendarModel get_default () { @@ -59,12 +48,6 @@ namespace DateTimeIndicator { } construct { - open.begin (); - - source_client = new HashTable (str_hash, str_equal); - source_events = new HashTable > (Util.source_hash_func, Util.source_equal_func); - source_view = new HashTable (str_hash, str_equal); - int week_start = Posix.NLTime.FIRST_WEEKDAY.to_string ().data[0]; if (week_start >= 1 && week_start <= 7) { week_starts_on = (GLib.DateWeekday) (week_start - 1); @@ -72,66 +55,6 @@ namespace DateTimeIndicator { month_start = Util.get_start_of_month (); compute_ranges (); - notify["month-start"].connect (on_parameter_changed); - } - - private async void open () { - try { - registry = yield new E.SourceRegistry (null); - registry.source_removed.connect (remove_source); - registry.source_added.connect ((source) => add_source_async.begin (source)); - - // Add sources - registry.list_sources (E.SOURCE_EXTENSION_CALENDAR).foreach ((source) => { - E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR); - if (cal.selected == true && source.enabled == true) { - add_source_async.begin (source); - } - }); - - load_all_sources (); - } catch (GLib.Error error) { - critical (error.message); - } - } - - private void load_all_sources () { - lock (source_client) { - foreach (var id in source_client.get_keys ()) { - var source = registry.ref_source (id); - E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR); - - if (cal.selected == true && source.enabled == true) { - load_source (source); - } - } - } - } - - private void remove_source (E.Source source) { - debug ("Removing source '%s'", source.dup_display_name ()); - /* Already out of the model, so do nothing */ - unowned string uid = source.get_uid (); - - if (!source_view.contains (uid)) { - return; - } - - var current_view = source_view.get (uid); - try { - current_view.stop (); - } catch (Error e) { - warning (e.message); - } - - source_view.remove (uid); - lock (source_client) { - source_client.remove (uid); - } - - var events = source_events.get (source).get_values ().read_only_view; - events_removed (source, events); - source_events.remove (source); } public void change_month (int relative) { @@ -144,7 +67,7 @@ namespace DateTimeIndicator { /* --- Helper Methods ---// */ - private void compute_ranges () { + public void compute_ranges () { var month_end = month_start.add_full (0, 1, -1); int dow = month_start.get_day_of_week (); @@ -182,150 +105,5 @@ namespace DateTimeIndicator { debug (@"Date ranges: ($data_range_first <= $month_start < $month_end <= $data_range_last)"); } - - private void load_source (E.Source source) { - /* create empty source-event map */ - var events = new Gee.TreeMultiMap ( - (GLib.CompareDataFunc?) GLib.strcmp, - (GLib.CompareDataFunc?) Util.calcomponent_compare_func - ); - source_events.set (source, events); - /* query client view */ - var iso_first = ECal.isodate_from_time_t ((time_t)data_range.first_dt.to_unix ()); - var iso_last = ECal.isodate_from_time_t ((time_t)data_range.last_dt.add_days (1).to_unix ()); - var query = @"(occur-in-time-range? (make-time \"$iso_first\") (make-time \"$iso_last\"))"; - - ECal.Client client; - lock (source_client) { - client = source_client.get (source.dup_uid ()); - } - - if (client == null) { - return; - } - - debug ("Getting client-view for source '%s'", source.dup_display_name ()); - client.get_view.begin (query, null, (obj, results) => { - var view = on_client_view_received (results, source, client); - view.objects_added.connect ((objects) => on_objects_added (source, client, objects)); - view.objects_removed.connect ((objects) => on_objects_removed (source, client, objects)); - view.objects_modified.connect ((objects) => on_objects_modified (source, client, objects)); - try { - view.start (); - } catch (Error e) { - critical (e.message); - } - - source_view.set (source.dup_uid (), view); - }); - } - - private async void add_source_async (E.Source source) { - debug ("Adding source '%s'", source.dup_display_name ()); - try { - var client = (ECal.Client) ECal.Client.connect_sync (source, ECal.ClientSourceType.EVENTS, -1, null); - source_client.insert (source.dup_uid (), client); - } catch (Error e) { - critical (e.message); - } - - Idle.add (() => { - load_source (source); - - return false; - }); - } - - private void debug_event (E.Source source, ECal.Component event) { - unowned ICal.Component comp = event.get_icalcomponent (); - debug (@"Event ['$(comp.get_summary())', $(source.dup_display_name()), $(comp.get_uid()))]"); - } - - /* --- Signal Handlers ---// */ - private void on_parameter_changed () { - compute_ranges (); - load_all_sources (); - } - - private ECal.ClientView on_client_view_received (AsyncResult results, E.Source source, ECal.Client client) { - ECal.ClientView view; - try { - debug ("Received client-view for source '%s'", source.dup_display_name ()); - bool status = client.get_view.end (results, out view); - assert (status == true); - } catch (Error e) { - critical ("Error loading client-view from source '%s': %s", source.dup_display_name (), e.message); - } - - return view; - } - -#if E_CAL_2_0 - private void on_objects_added (E.Source source, ECal.Client client, SList objects) { -#else - private void on_objects_added (E.Source source, ECal.Client client, SList objects) { -#endif - debug (@"Received $(objects.length()) added event(s) for source '%s'", source.dup_display_name ()); - var events = source_events.get (source); - var added_events = new Gee.ArrayList ((Gee.EqualDataFunc?) Util.calcomponent_equal_func); - objects.foreach ((comp) => { - unowned string uid = comp.get_uid (); -#if E_CAL_2_0 - client.generate_instances_for_object_sync (comp, (time_t) data_range.first_dt.to_unix (), (time_t) data_range.last_dt.to_unix (), null, (comp, start, end) => { - var event = new ECal.Component.from_icalcomponent (comp); -#else - client.generate_instances_for_object_sync (comp, (time_t) data_range.first_dt.to_unix (), (time_t) data_range.last_dt.to_unix (), (event, start, end) => { -#endif - debug_event (source, event); - events.set (uid, event); - added_events.add (event); - return true; - }); - }); - } - -#if E_CAL_2_0 - private void on_objects_modified (E.Source source, ECal.Client client, SList objects) { -#else - private void on_objects_modified (E.Source source, ECal.Client client, SList objects) { -#endif - debug (@"Received $(objects.length()) modified event(s) for source '%s'", source.dup_display_name ()); - var updated_events = new Gee.ArrayList ((Gee.EqualDataFunc?) Util.calcomponent_equal_func); - - objects.foreach ((comp) => { - unowned string uid = comp.get_uid (); - var events = source_events.get (source).get (uid); - updated_events.add_all (events); - foreach (var event in events) { - debug_event (source, event); - } - }); - - events_updated (source, updated_events.read_only_view); - } - -#if E_CAL_2_0 - private void on_objects_removed (E.Source source, ECal.Client client, SList cids) { -#else - private void on_objects_removed (E.Source source, ECal.Client client, SList cids) { -#endif - debug (@"Received $(cids.length()) removed event(s) for source '%s'", source.dup_display_name ()); - var events = source_events.get (source); - var removed_events = new Gee.ArrayList ((Gee.EqualDataFunc?) Util.calcomponent_equal_func); - - cids.foreach ((cid) => { - if (cid == null) { - return; - } - - var comps = events.get (cid.get_uid ()); - foreach (ECal.Component event in comps) { - removed_events.add (event); - debug_event (source, event); - } - }); - - events_removed (source, removed_events.read_only_view); - } } } diff --git a/src/Services/EventsManager.vala b/src/Services/EventsManager.vala new file mode 100644 index 0000000..d939777 --- /dev/null +++ b/src/Services/EventsManager.vala @@ -0,0 +1,226 @@ +namespace DateTimeIndicator { + public class Services.EventsManager : GLib.Object { + public signal void events_added (E.Source source, Gee.Collection events); + public signal void events_updated (E.Source source, Gee.Collection events); + public signal void events_removed (E.Source source, Gee.Collection events); + + public HashTable> source_events { get; private set; } + + private E.SourceRegistry registry { get; private set; } + private HashTable source_client; + private HashTable source_view; + + public EventsManager () { + + } + + construct { + source_client = new HashTable (str_hash, str_equal); + source_events = new HashTable > (Util.source_hash_func, Util.source_equal_func); + source_view = new HashTable (str_hash, str_equal); + + open.begin (); + } + + private async void open () { + try { + registry = yield new E.SourceRegistry (null); + registry.source_removed.connect (remove_source); + registry.source_added.connect ((source) => add_source_async.begin (source)); + + // Add sources + registry.list_sources (E.SOURCE_EXTENSION_CALENDAR).foreach ((source) => { + E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR); + if (cal.selected == true && source.enabled == true) { + add_source_async.begin (source); + } + }); + + load_all_sources (); + } catch (GLib.Error error) { + critical (error.message); + } + } + + public void load_all_sources () { + lock (source_client) { + foreach (var id in source_client.get_keys ()) { + var source = registry.ref_source (id); + E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR); + + if (cal.selected == true && source.enabled == true) { + load_source (source); + } + } + } + } + + private void remove_source (E.Source source) { + debug ("Removing source '%s'", source.dup_display_name ()); + /* Already out of the model, so do nothing */ + unowned string uid = source.get_uid (); + + if (!source_view.contains (uid)) { + return; + } + + var current_view = source_view.get (uid); + try { + current_view.stop (); + } catch (Error e) { + warning (e.message); + } + + source_view.remove (uid); + lock (source_client) { + source_client.remove (uid); + } + + var events = source_events.get (source).get_values ().read_only_view; + events_removed (source, events); + source_events.remove (source); + } + + private void load_source (E.Source source) { + var model = Models.CalendarModel.get_default (); + + /* create empty source-event map */ + var events = new Gee.TreeMultiMap ( + (GLib.CompareDataFunc?) GLib.strcmp, + (GLib.CompareDataFunc?) Util.calcomponent_compare_func + ); + source_events.set (source, events); + /* query client view */ + var iso_first = ECal.isodate_from_time_t ((time_t) model.data_range.first_dt.to_unix ()); + var iso_last = ECal.isodate_from_time_t ((time_t) model.data_range.last_dt.add_days (1).to_unix ()); + var query = @"(occur-in-time-range? (make-time \"$iso_first\") (make-time \"$iso_last\"))"; + + ECal.Client client; + lock (source_client) { + client = source_client.get (source.dup_uid ()); + } + + if (client == null) { + return; + } + + debug ("Getting client-view for source '%s'", source.dup_display_name ()); + client.get_view.begin (query, null, (obj, results) => { + var view = on_client_view_received (results, source, client); + view.objects_added.connect ((objects) => on_objects_added (source, client, objects)); + view.objects_removed.connect ((objects) => on_objects_removed (source, client, objects)); + view.objects_modified.connect ((objects) => on_objects_modified (source, client, objects)); + try { + view.start (); + } catch (Error e) { + critical (e.message); + } + + source_view.set (source.dup_uid (), view); + }); + } + + private async void add_source_async (E.Source source) { + debug ("Adding source '%s'", source.dup_display_name ()); + try { + var client = (ECal.Client) ECal.Client.connect_sync (source, ECal.ClientSourceType.EVENTS, -1, null); + source_client.insert (source.dup_uid (), client); + } catch (Error e) { + critical (e.message); + } + + Idle.add (() => { + load_source (source); + + return false; + }); + } + + private void debug_event (E.Source source, ECal.Component event) { + unowned ICal.Component comp = event.get_icalcomponent (); + debug (@"Event ['$(comp.get_summary())', $(source.dup_display_name()), $(comp.get_uid()))]"); + } + + private ECal.ClientView on_client_view_received (AsyncResult results, E.Source source, ECal.Client client) { + ECal.ClientView view; + try { + debug ("Received client-view for source '%s'", source.dup_display_name ()); + bool status = client.get_view.end (results, out view); + assert (status == true); + } catch (Error e) { + critical ("Error loading client-view from source '%s': %s", source.dup_display_name (), e.message); + } + + return view; + } + +#if E_CAL_2_0 + private void on_objects_added (E.Source source, ECal.Client client, SList objects) { +#else + private void on_objects_added (E.Source source, ECal.Client client, SList objects) { +#endif + debug (@"Received $(objects.length()) added event(s) for source '%s'", source.dup_display_name ()); + var events = source_events.get (source); + var added_events = new Gee.ArrayList ((Gee.EqualDataFunc?) Util.calcomponent_equal_func); + var model = Models.CalendarModel.get_default (); + objects.foreach ((comp) => { + unowned string uid = comp.get_uid (); +#if E_CAL_2_0 + client.generate_instances_for_object_sync (comp, (time_t) model.data_range.first_dt.to_unix (), (time_t) model.data_range.last_dt.to_unix (), null, (comp, start, end) => { + var event = new ECal.Component.from_icalcomponent (comp); +#else + client.generate_instances_for_object_sync (comp, (time_t) model.data_range.first_dt.to_unix (), (time_t) model.data_range.last_dt.to_unix (), (event, start, end) => { +#endif + debug_event (source, event); + events.set (uid, event); + added_events.add (event); + return true; + }); + }); + } + +#if E_CAL_2_0 + private void on_objects_modified (E.Source source, ECal.Client client, SList objects) { +#else + private void on_objects_modified (E.Source source, ECal.Client client, SList objects) { +#endif + debug (@"Received $(objects.length()) modified event(s) for source '%s'", source.dup_display_name ()); + var updated_events = new Gee.ArrayList ((Gee.EqualDataFunc?) Util.calcomponent_equal_func); + + objects.foreach ((comp) => { + unowned string uid = comp.get_uid (); + var events = source_events.get (source).get (uid); + updated_events.add_all (events); + foreach (var event in events) { + debug_event (source, event); + } + }); + + events_updated (source, updated_events.read_only_view); + } + +#if E_CAL_2_0 + private void on_objects_removed (E.Source source, ECal.Client client, SList cids) { +#else + private void on_objects_removed (E.Source source, ECal.Client client, SList cids) { +#endif + debug (@"Received $(cids.length()) removed event(s) for source '%s'", source.dup_display_name ()); + var events = source_events.get (source); + var removed_events = new Gee.ArrayList ((Gee.EqualDataFunc?) Util.calcomponent_equal_func); + + cids.foreach ((cid) => { + if (cid == null) { + return; + } + + var comps = events.get (cid.get_uid ()); + foreach (ECal.Component event in comps) { + removed_events.add (event); + debug_event (source, event); + } + }); + + events_removed (source, removed_events.read_only_view); + } + } +} diff --git a/src/Util/Util.vala b/src/Util/Util.vala index c261f4b..b0bdf98 100644 --- a/src/Util/Util.vala +++ b/src/Util/Util.vala @@ -20,47 +20,6 @@ */ namespace DateTimeIndicator.Util { - static bool has_scrolled = false; - - public bool on_scroll_event (Gdk.EventScroll event) { - double delta_x; - double delta_y; - event.get_scroll_deltas (out delta_x, out delta_y); - - double choice = delta_x; - - if (((int)delta_x).abs () < ((int)delta_y).abs ()) { - choice = delta_y; - } - - /* It's mouse scroll ! */ - if (choice == 1 || choice == -1) { - Models.CalendarModel.get_default ().change_month ((int)choice); - - return true; - } - - if (has_scrolled == true) { - return true; - } - - if (choice > 0.3) { - reset_timer.begin (); - Models.CalendarModel.get_default ().change_month (1); - - return true; - } - - if (choice < -0.3) { - reset_timer.begin (); - Models.CalendarModel.get_default ().change_month (-1); - - return true; - } - - return false; - } - public GLib.DateTime get_start_of_month (owned GLib.DateTime? date = null) { if (date == null) { date = new GLib.DateTime.now_local (); @@ -225,12 +184,12 @@ namespace DateTimeIndicator.Util { return a.dup_uid () == b.dup_uid (); } - public async void reset_timer () { - has_scrolled = true; - Timeout.add (500, () => { - has_scrolled = false; - - return false; - }); - } + // public async void reset_timer () { + // has_scrolled = true; + // Timeout.add (500, () => { + // has_scrolled = false; + // + // return false; + // }); + // } } diff --git a/src/Widgets/CalendarView.vala b/src/Widgets/CalendarView.vala index 65cee28..070580f 100644 --- a/src/Widgets/CalendarView.vala +++ b/src/Widgets/CalendarView.vala @@ -181,5 +181,14 @@ namespace DateTimeIndicator { stack.set_visible_child (big_grid); } + + public void add_event_dots (E.Source source, Gee.Collection events) { + grid.add_event_dots (source, events); + } + + + public void remove_event_dots (E.Source source, Gee.Collection events) { + grid.remove_event_dots (source, events); + } } } diff --git a/src/Widgets/EventsListBox.vala b/src/Widgets/EventsListBox.vala index 547e4c5..c25af2e 100644 --- a/src/Widgets/EventsListBox.vala +++ b/src/Widgets/EventsListBox.vala @@ -1,6 +1,5 @@ namespace DateTimeIndicator { public class Widgets.EventsListBox : Gtk.ListBox { - public EventsListBox () { selection_mode = Gtk.SelectionMode.NONE; @@ -22,7 +21,7 @@ namespace DateTimeIndicator { set_sort_func (sort_function); } - public void update_events (GLib.DateTime? selected_date) { + public void update_events (GLib.DateTime? selected_date, HashTable> source_events) { foreach (unowned Gtk.Widget widget in get_children ()) { widget.destroy (); } @@ -31,11 +30,9 @@ namespace DateTimeIndicator { return; } - var model = Models.CalendarModel.get_default (); - var events_on_day = new Gee.TreeMap (); - model.source_events.@foreach ((source, component_map) => { + source_events.@foreach ((source, component_map) => { foreach (var comp in component_map.get_values ()) { if (Util.calcomp_is_on_day (comp, selected_date)) { unowned ICal.Component ical = comp.get_icalcomponent (); diff --git a/src/Widgets/Grid.vala b/src/Widgets/Grid.vala index 165d11d..660f212 100644 --- a/src/Widgets/Grid.vala +++ b/src/Widgets/Grid.vala @@ -261,5 +261,36 @@ namespace DateTimeIndicator { return date.get_year () * 10000 + date.get_month () * 100 + date.get_day_of_month (); } + public void add_event_dots (E.Source source, Gee.Collection events) { + data.foreach ((entry) => { + + foreach (var component in events) { + if (entry.value.skip_day ()) { + return true; + } + + if (Util.calcomp_is_on_day (component, entry.value.date)) { + entry.value.add_dots (source, component.get_icalcomponent ()); + } + } + + entry.value.show_event_grid (); + + return true; + }); + } + + public void remove_event_dots (E.Source source, Gee.Collection events) { + foreach (var component in events) { + unowned ICal.Component ical = component.get_icalcomponent (); + var event_uid = ical.get_uid (); + data.foreach ((entry) => { + if (entry.value.exist_event (event_uid)) { + entry.value.remove_dots (event_uid); + } + return true; + }); + } + } } } diff --git a/src/Widgets/GridDay.vala b/src/Widgets/GridDay.vala index 8c44443..00f82ea 100644 --- a/src/Widgets/GridDay.vala +++ b/src/Widgets/GridDay.vala @@ -31,6 +31,8 @@ namespace DateTimeIndicator { public GLib.DateTime date { get; construct set; } + private bool has_scrolled = false; + private static Gtk.CssProvider provider; private static Models.CalendarModel model; @@ -79,59 +81,100 @@ namespace DateTimeIndicator { // Signals and handlers button_press_event.connect (on_button_press); key_press_event.connect (on_key_press); - scroll_event.connect ((event) => {return Util.on_scroll_event (event);}); + scroll_event.connect (on_scroll_event); notify["date"].connect (() => { label.label = date.get_day_of_month ().to_string (); }); event_dots = new Gee.HashMap (); - - model.events_added.connect (add_event_dots); - model.events_removed.connect (remove_event_dots); } - private void add_event_dots (E.Source source, Gee.Collection events) { - foreach (var component in events) { - if (event_dots.size >= 3) { - return; - } + public bool on_scroll_event (Gdk.EventScroll event) { + double delta_x; + double delta_y; + event.get_scroll_deltas (out delta_x, out delta_y); + + double choice = delta_x; + + if (((int)delta_x).abs () < ((int)delta_y).abs ()) { + choice = delta_y; + } + + /* It's mouse scroll ! */ + if (choice == 1 || choice == -1) { + Models.CalendarModel.get_default ().change_month ((int)choice); - if (Util.calcomp_is_on_day (component, date)) { - unowned ICal.Component ical = component.get_icalcomponent (); + return true; + } - var event_uid = ical.get_uid (); - if (!event_dots.has_key (event_uid)) { - var event_dot = new Gtk.Image (); - event_dot.gicon = new ThemedIcon ("pager-checked-symbolic"); - event_dot.pixel_size = 6; + if (has_scrolled == true) { + return true; + } - unowned Gtk.StyleContext style_context = event_dot.get_style_context (); - style_context.add_class (Granite.STYLE_CLASS_ACCENT); - style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + if (choice > 0.3) { + reset_timer.begin (); + Models.CalendarModel.get_default ().change_month (1); - var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR); - Util.set_event_calendar_color (source_calendar, event_dot); + return true; + } - event_dots[event_uid] = event_dot; + if (choice < -0.3) { + reset_timer.begin (); + Models.CalendarModel.get_default ().change_month (-1); - event_grid.add (event_dot); - } - } + return true; } + return false; + } + + public async void reset_timer () { + has_scrolled = true; + Timeout.add (500, () => { + has_scrolled = false; + + return false; + }); + } + + public bool skip_day () { + return event_dots.size >= 3 ? true : false; + } + + public void show_event_grid () { event_grid.show_all (); } - private void remove_event_dots (E.Source source, Gee.Collection events) { - foreach (var component in events) { - unowned ICal.Component ical = component.get_icalcomponent (); - var event_uid = ical.get_uid (); - var dot = event_dots[event_uid]; - if (dot != null) { - dot.destroy (); - event_dots.remove (event_uid); - } + public void add_dots (E.Source source, ICal.Component ical) { + var event_uid = ical.get_uid (); + if (!event_dots.has_key (event_uid)) { + var event_dot = new Gtk. Image (); + event_dot.gicon = new ThemedIcon ("pager-checked-symbolic"); + event_dot.pixel_size = 6; + + unowned Gtk.StyleContext style_context = event_dot.get_style_context (); + style_context.add_class (Granite.STYLE_CLASS_ACCENT); + style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR); + Util.set_event_calendar_color (source_calendar, event_dot); + + event_dots[event_uid] = event_dot; + + event_grid.add (event_dot); + } + } + + public bool exist_event (string ical_uid) { + return event_dots.has_key (ical_uid); + } + + public void remove_dots (string event_uid) { + var dot = event_dots[event_uid]; + if (dot != null) { + dot.destroy (); + event_dots.unset (event_uid); } } From c99db5e63b9c48aa1d069b97b98b0c07481de27d Mon Sep 17 00:00:00 2001 From: Dirli Date: Sat, 11 Apr 2020 23:44:14 +0300 Subject: [PATCH 4/8] rename calendar elements --- meson.build | 4 +-- .../{GridDay.vala => CalendarDay.vala} | 4 +-- src/Widgets/{Grid.vala => CalendarGrid.vala} | 26 +++++++-------- src/Widgets/CalendarView.vala | 33 +++++++++---------- 4 files changed, 33 insertions(+), 34 deletions(-) rename src/Widgets/{GridDay.vala => CalendarDay.vala} (98%) rename src/Widgets/{Grid.vala => CalendarGrid.vala} (91%) diff --git a/meson.build b/meson.build index e348e3d..dcdd9b2 100644 --- a/meson.build +++ b/meson.build @@ -44,11 +44,11 @@ shared_module( 'src/Util/DateRange.vala', 'src/Util/Util.vala', 'src/Models/CalendarModel.vala', + 'src/Widgets/CalendarDay.vala', + 'src/Widgets/CalendarGrid.vala', 'src/Widgets/CalendarView.vala', 'src/Widgets/EventRow.vala', 'src/Widgets/EventsListBox.vala', - 'src/Widgets/Grid.vala', - 'src/Widgets/GridDay.vala', 'src/Widgets/PanelLabel.vala', 'src/Services/EventsManager.vala', 'src/Services/TimeManager.vala', diff --git a/src/Widgets/GridDay.vala b/src/Widgets/CalendarDay.vala similarity index 98% rename from src/Widgets/GridDay.vala rename to src/Widgets/CalendarDay.vala index 00f82ea..a5ca920 100644 --- a/src/Widgets/GridDay.vala +++ b/src/Widgets/CalendarDay.vala @@ -23,7 +23,7 @@ namespace DateTimeIndicator { /** * Represents a single day on the grid. */ - public class Widgets.GridDay : Gtk.EventBox { + public class Widgets.CalendarDay : Gtk.EventBox { /* * Event emitted when the day is double clicked or the ENTER key is pressed. */ @@ -41,7 +41,7 @@ namespace DateTimeIndicator { private Gtk.Label label; private bool valid_grab = false; - public GridDay (GLib.DateTime date) { + public CalendarDay (GLib.DateTime date) { Object (date: date); } diff --git a/src/Widgets/Grid.vala b/src/Widgets/CalendarGrid.vala similarity index 91% rename from src/Widgets/Grid.vala rename to src/Widgets/CalendarGrid.vala index 660f212..66e2757 100644 --- a/src/Widgets/Grid.vala +++ b/src/Widgets/CalendarGrid.vala @@ -24,7 +24,7 @@ namespace DateTimeIndicator { /** * Represents the entire date grid as a table. */ - public class Widgets.Grid : Gtk.Grid { + public class Widgets.CalendarGrid : Gtk.Grid { public Util.DateRange grid_range { get; private set; } /* @@ -34,8 +34,8 @@ namespace DateTimeIndicator { public signal void selection_changed (GLib.DateTime new_date); - private Gee.HashMap data; - private GridDay selected_gridday; + private Gee.HashMap data; + private Widgets.CalendarDay selected_gridday; private Gtk.Label[] header_labels; private Gtk.Revealer[] week_labels; @@ -61,12 +61,12 @@ namespace DateTimeIndicator { Indicator.settings.bind ("show-weeks", week_sep_revealer, "reveal-child", GLib.SettingsBindFlags.DEFAULT); - data = new Gee.HashMap (); + data = new Gee.HashMap (); events |= Gdk.EventMask.SCROLL_MASK; events |= Gdk.EventMask.SMOOTH_SCROLL_MASK; } - private void on_day_focus_in (GridDay day) { + private void on_day_focus_in (Widgets.CalendarDay day) { debug ("on_day_focus_in %s", day.date.to_string ()); if (selected_gridday != null) { selected_gridday.set_selected (false); @@ -94,7 +94,7 @@ namespace DateTimeIndicator { Gee.List dates = grid_range.to_list (); for (int i = 0; i < dates.size; i++) { var date = dates[i]; - GridDay? day = data[day_hash (date)]; + Widgets.CalendarDay? day = data[day_hash (date)]; if (day != null && day.name == "today") { day.grab_focus_force (); return; @@ -119,7 +119,7 @@ namespace DateTimeIndicator { var new_dates = new_range.to_list (); - var data_new = new Gee.HashMap (); + var data_new = new Gee.HashMap (); /* Assert that a valid number of weeks should be displayed */ assert (new_dates.size % 7 == 0); @@ -138,7 +138,7 @@ namespace DateTimeIndicator { for (i = 0; i < new_dates.size; i++) { var new_date = new_dates[i]; - GridDay day; + Widgets.CalendarDay day; if (i < old_dates.size) { /* A widget already exists for this date, just change it */ @@ -147,7 +147,7 @@ namespace DateTimeIndicator { day = update_day (data[day_hash (old_date)], new_date, today, month_start); } else { /* Still update_day to get the color of etc. right */ - day = update_day (new GridDay (new_date), new_date, today, month_start); + day = update_day (new Widgets.CalendarDay (new_date), new_date, today, month_start); day.on_event_add.connect ((date) => on_event_add (date)); day.scroll_event.connect ((event) => { scroll_event (event); return false; }); day.focus_in_event.connect ((event) => { @@ -182,9 +182,9 @@ namespace DateTimeIndicator { } /** - * Updates the given GridDay so that it shows the given date. Changes to its style etc. + * Updates the given CalendarDay so that it shows the given date. Changes to its style etc. */ - private GridDay update_day (GridDay day, GLib.DateTime new_date, GLib.DateTime today, GLib.DateTime month_start) { + private Widgets.CalendarDay update_day (Widgets.CalendarDay day, GLib.DateTime new_date, GLib.DateTime today, GLib.DateTime month_start) { update_today_style (day, new_date, today); if (new_date.get_month () == month_start.get_month ()) { day.sensitive_container (true); @@ -237,13 +237,13 @@ namespace DateTimeIndicator { int i = 0; for (i = 0; i < dates.size; i++) { var date = dates[i]; - GridDay? day = data[day_hash (date)]; + Widgets.CalendarDay? day = data[day_hash (date)]; if (day == null) return; update_today_style (day, date, today); } } - private void update_today_style (GridDay day, GLib.DateTime date, GLib.DateTime today) { + private void update_today_style (Widgets.CalendarDay day, GLib.DateTime date, GLib.DateTime today) { if (date.get_day_of_year () == today.get_day_of_year () && date.get_year () == today.get_year ()) { day.name = "today"; day.get_style_context ().add_class (Granite.STYLE_CLASS_ACCENT); diff --git a/src/Widgets/CalendarView.vala b/src/Widgets/CalendarView.vala index 070580f..db2139c 100644 --- a/src/Widgets/CalendarView.vala +++ b/src/Widgets/CalendarView.vala @@ -26,7 +26,7 @@ namespace DateTimeIndicator { public GLib.DateTime? selected_date { get; private set; } - private Widgets.Grid grid; + private Widgets.CalendarGrid calendar_grid; private Gtk.Stack stack; private Gtk.Grid big_grid; @@ -105,20 +105,20 @@ namespace DateTimeIndicator { } private Gtk.Grid create_big_grid () { - grid = new Widgets.Grid (); - grid.show_all (); + calendar_grid = new Widgets.CalendarGrid (); + calendar_grid.show_all (); - grid.on_event_add.connect ((date) => { + calendar_grid.on_event_add.connect ((date) => { show_date_in_maya (date); day_double_click (); }); - grid.selection_changed.connect ((date) => { + calendar_grid.selection_changed.connect ((date) => { selected_date = date; selection_changed (date); }); - return grid; + return calendar_grid; } public void show_today () { @@ -131,7 +131,7 @@ namespace DateTimeIndicator { } sync_with_model (); - grid.set_focus_to_today (); + calendar_grid.set_focus_to_today (); } // TODO: As far as maya supports it use the Dbus Activation feature to run the calendar-app. @@ -156,23 +156,23 @@ namespace DateTimeIndicator { /* Sets the calendar widgets to the date range of the model */ private void sync_with_model () { var model = Models.CalendarModel.get_default (); - if (grid.grid_range != null && (model.data_range.equals (grid.grid_range) || grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) { - grid.update_today (); + if (calendar_grid.grid_range != null && (model.data_range.equals (calendar_grid.grid_range) || calendar_grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) { + calendar_grid.update_today (); return; // nothing else to do } GLib.DateTime previous_first = null; - if (grid.grid_range != null) - previous_first = grid.grid_range.first_dt; + if (calendar_grid.grid_range != null) + previous_first = calendar_grid.grid_range.first_dt; big_grid = create_big_grid (); stack.add (big_grid); - grid.set_range (model.data_range, model.month_start); - grid.update_weeks (model.data_range.first_dt, model.num_weeks); + calendar_grid.set_range (model.data_range, model.month_start); + calendar_grid.update_weeks (model.data_range.first_dt, model.num_weeks); if (previous_first != null) { - if (previous_first.compare (grid.grid_range.first_dt) == -1) { + if (previous_first.compare (calendar_grid.grid_range.first_dt) == -1) { stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT; } else { stack.transition_type = Gtk.StackTransitionType.SLIDE_RIGHT; @@ -183,12 +183,11 @@ namespace DateTimeIndicator { } public void add_event_dots (E.Source source, Gee.Collection events) { - grid.add_event_dots (source, events); + calendar_grid.add_event_dots (source, events); } - public void remove_event_dots (E.Source source, Gee.Collection events) { - grid.remove_event_dots (source, events); + calendar_grid.remove_event_dots (source, events); } } } From 6b1b15305a9c90ff8b7e7244727a225984d34a14 Mon Sep 17 00:00:00 2001 From: Dirli Date: Sun, 12 Apr 2020 03:10:24 +0300 Subject: [PATCH 5/8] evolution data server now optional --- meson.build | 55 ++++++++++++++--------- meson_options.txt | 1 + src/Indicator.vala | 43 ++++++++++-------- src/Util/Util.vala | 85 ++++++++++++++++------------------- src/Widgets/CalendarDay.vala | 2 + src/Widgets/CalendarGrid.vala | 2 + src/Widgets/CalendarView.vala | 2 + 7 files changed, 104 insertions(+), 86 deletions(-) create mode 100644 meson_options.txt diff --git a/meson.build b/meson.build index dcdd9b2..5fee9ab 100644 --- a/meson.build +++ b/meson.build @@ -24,18 +24,40 @@ gresource = gnome.compile_resources( wingpanel_dep = dependency('wingpanel-2.0') wingpanel_indicatorsdir = wingpanel_dep.get_pkgconfig_variable('indicatorsdir', define_variable: ['libdir', libdir]) +deps = [ + dependency('glib-2.0'), + dependency('gobject-2.0'), + dependency('granite'), + dependency('gtk+-3.0'), + wingpanel_dep, + meson.get_compiler('vala').find_library('posix') +] -libecal_dep = dependency('libecal-2.0', required: false) -if libecal_dep.found() - libical_dep = dependency('libical-glib') - add_project_arguments('--define=E_CAL_2_0', language: 'vala') - add_project_arguments('-DLIBICAL_GLIB_UNSTABLE_API=1', language: 'c') -else - libecal_dep = dependency('libecal-1.2', version: '>=3.8.0') - libical_dep = dependency('libical') - add_project_arguments('--vapidir', join_paths(meson.current_source_dir(), 'vapi'), language: 'vala') +opt_files = [] + +if get_option('evo') + libecal_dep = dependency ('libecal-2.0', required: false) + if libecal_dep.found() + deps += dependency('libical-glib') + deps += libecal_dep + add_project_arguments('--define=E_CAL_2_0', language: 'vala') + add_project_arguments('-DLIBICAL_GLIB_UNSTABLE_API=1', language: 'c') + else + deps += dependency('libecal-1.2', version: '>=3.8.0') + deps += dependency('libical') + add_project_arguments('--vapidir', join_paths(meson.current_source_dir(), 'vapi'), language: 'vala') + endif + + deps += dependency ('libedataserver-1.2') + opt_files += files ( + 'src/Widgets/EventRow.vala', + 'src/Widgets/EventsListBox.vala', + 'src/Services/EventsManager.vala', + ) + add_project_arguments('--define=USE_EVO', language: 'vala') endif + shared_module( meson.project_name(), gresource, @@ -47,21 +69,10 @@ shared_module( 'src/Widgets/CalendarDay.vala', 'src/Widgets/CalendarGrid.vala', 'src/Widgets/CalendarView.vala', - 'src/Widgets/EventRow.vala', - 'src/Widgets/EventsListBox.vala', 'src/Widgets/PanelLabel.vala', - 'src/Services/EventsManager.vala', 'src/Services/TimeManager.vala', - dependencies: [ - dependency('glib-2.0'), - dependency('gobject-2.0'), - dependency('granite'), - dependency('gtk+-3.0'), - libecal_dep, - dependency('libedataserver-1.2'), - libical_dep, - wingpanel_dep, - ], + opt_files, + dependencies: deps, install: true, install_dir : wingpanel_indicatorsdir, ) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..a1c9f0e --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +option ('evo', type : 'boolean', value : true) diff --git a/src/Indicator.vala b/src/Indicator.vala index bf4358f..31c7af5 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -23,9 +23,11 @@ namespace DateTimeIndicator { private Widgets.PanelLabel panel_label; private Widgets.CalendarView calendar; - private Widgets.EventsListBox event_listbox; +#if USE_EVO + private Widgets.EventsListBox event_listbox; private Services.EventsManager event_manager; +#endif private Gtk.Grid main_grid; private uint update_events_idle_source = 0; @@ -60,7 +62,20 @@ namespace DateTimeIndicator { if (main_grid == null) { calendar = new Widgets.CalendarView (); calendar.margin_bottom = 6; + calendar.day_double_click.connect (() => { + close (); + }); + + var settings_button = new Gtk.ModelButton (); + settings_button.text = _("Date & Time Settings…"); + main_grid = new Gtk.Grid (); + main_grid.margin_top = 12; + main_grid.attach (calendar, 0, 0); + main_grid.attach (new Wingpanel.Widgets.Separator (), 0, 1); + main_grid.attach (settings_button, 0, 2); + +#if USE_EVO event_manager = new Services.EventsManager (); event_manager.events_updated.connect (update_events_model); event_manager.events_added.connect ((source, events) => { @@ -73,20 +88,16 @@ namespace DateTimeIndicator { }); event_listbox = new Widgets.EventsListBox (); + event_listbox.row_activated.connect ((row) => { + calendar.show_date_in_maya (((EventRow) row).date); + close (); + }); var scrolled_window = new Gtk.ScrolledWindow (null, null); scrolled_window.hscrollbar_policy = Gtk.PolicyType.NEVER; scrolled_window.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC; scrolled_window.add (event_listbox); - var settings_button = new Gtk.ModelButton (); - settings_button.text = _("Date & Time Settings…"); - - main_grid = new Gtk.Grid (); - main_grid.margin_top = 12; - main_grid.attach (calendar, 0, 0); - main_grid.attach (new Wingpanel.Widgets.Separator (), 0, 1); - main_grid.attach (settings_button, 0, 2); main_grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 3); main_grid.attach (scrolled_window, 2, 0, 1, 3); @@ -94,23 +105,17 @@ namespace DateTimeIndicator { size_group.add_widget (calendar); size_group.add_widget (event_listbox); - calendar.day_double_click.connect (() => { - close (); - }); - calendar.selection_changed.connect ((date) => { idle_update_events (); }); - - event_listbox.row_activated.connect ((row) => { - calendar.show_date_in_maya (((EventRow) row).date); - close (); - }); +#endif var model = Models.CalendarModel.get_default (); model.notify["month-start"].connect (() => { model.compute_ranges (); +#if USE_EVO event_manager.load_all_sources (); +#endif }); settings_button.clicked.connect (() => { @@ -125,6 +130,7 @@ namespace DateTimeIndicator { return main_grid; } +#if USE_EVO private void update_events_model (E.Source source, Gee.Collection events) { if (opened_widget) { idle_update_events (); @@ -143,6 +149,7 @@ namespace DateTimeIndicator { return GLib.Source.REMOVE; }); } +#endif public override void opened () { calendar.show_today (); diff --git a/src/Util/Util.vala b/src/Util/Util.vala index b0bdf98..26b343a 100644 --- a/src/Util/Util.vala +++ b/src/Util/Util.vala @@ -32,38 +32,6 @@ namespace DateTimeIndicator.Util { return datetime.add_full (0, 0, 0, -datetime.get_hour (), -datetime.get_minute (), -datetime.get_second ()); } - /** - * Converts the given ICal.Time to a DateTime. - */ - public TimeZone timezone_from_ical (ICal.Time date) { - int is_daylight; - var interval = date.get_timezone ().get_utc_offset (null, out is_daylight); - bool is_positive = interval >= 0; - interval = interval.abs (); - var hours = (interval / 3600); - var minutes = (interval % 3600) / 60; - var hour_string = "%s%02d:%02d".printf (is_positive ? "+" : "-", hours, minutes); - - return new TimeZone (hour_string); - } - - /** - * Converts the given ICal.Time to a DateTime. - * XXX : Track next versions of evolution in order to convert ICal.Timezone to GLib.TimeZone with a dedicated function… - */ - public GLib.DateTime ical_to_date_time (ICal.Time date) { -#if E_CAL_2_0 - int year, month, day, hour, minute, second; - date.get_date (out year, out month, out day); - date.get_time (out hour, out minute, out second); - return new GLib.DateTime (timezone_from_ical (date), year, month, - day, hour, minute, second); -#else - return new GLib.DateTime (timezone_from_ical (date), date.year, date.month, - date.day, date.hour, date.minute, date.second); -#endif - } - /** * Say if an event lasts all day. */ @@ -78,6 +46,7 @@ namespace DateTimeIndicator.Util { } } +#if USE_EVO private Gee.HashMap? providers; public void set_event_calendar_color (E.SourceCalendar cal, Gtk.Widget widget) { if (providers == null) { @@ -104,6 +73,38 @@ namespace DateTimeIndicator.Util { style_context.add_provider (providers[color], Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); } + /** + * Converts the given ICal.Time to a DateTime. + */ + public TimeZone timezone_from_ical (ICal.Time date) { + int is_daylight; + var interval = date.get_timezone ().get_utc_offset (null, out is_daylight); + bool is_positive = interval >= 0; + interval = interval.abs (); + var hours = (interval / 3600); + var minutes = (interval % 3600) / 60; + var hour_string = "%s%02d:%02d".printf (is_positive ? "+" : "-", hours, minutes); + + return new TimeZone (hour_string); + } + + /** + * Converts the given ICal.Time to a DateTime. + * XXX : Track next versions of evolution in order to convert ICal.Timezone to GLib.TimeZone with a dedicated function… + */ + public GLib.DateTime ical_to_date_time (ICal.Time date) { +#if E_CAL_2_0 + int year, month, day, hour, minute, second; + date.get_date (out year, out month, out day); + date.get_time (out hour, out minute, out second); + return new GLib.DateTime (timezone_from_ical (date), year, month, + day, hour, minute, second); +#else + return new GLib.DateTime (timezone_from_ical (date), date.year, date.month, + date.day, date.hour, date.minute, date.second); +#endif + } + /* * Gee Utility Functions */ @@ -113,6 +114,11 @@ namespace DateTimeIndicator.Util { return key.dup_uid (). hash (); } + /* Returns true if 'a' and 'b' are the same E.Source */ + public bool source_equal_func (E.Source a, E.Source b) { + return a.dup_uid () == b.dup_uid (); + } + /* Returns true if 'a' and 'b' are the same ECal.Component */ public bool calcomponent_equal_func (ECal.Component a, ECal.Component b) { return a.get_id ().equal (b.get_id ()); @@ -178,18 +184,5 @@ namespace DateTimeIndicator.Util { return false; } - - /* Returns true if 'a' and 'b' are the same E.Source */ - public bool source_equal_func (E.Source a, E.Source b) { - return a.dup_uid () == b.dup_uid (); - } - - // public async void reset_timer () { - // has_scrolled = true; - // Timeout.add (500, () => { - // has_scrolled = false; - // - // return false; - // }); - // } +#endif } diff --git a/src/Widgets/CalendarDay.vala b/src/Widgets/CalendarDay.vala index a5ca920..f9c742a 100644 --- a/src/Widgets/CalendarDay.vala +++ b/src/Widgets/CalendarDay.vala @@ -146,6 +146,7 @@ namespace DateTimeIndicator { event_grid.show_all (); } +#if USE_EVO public void add_dots (E.Source source, ICal.Component ical) { var event_uid = ical.get_uid (); if (!event_dots.has_key (event_uid)) { @@ -177,6 +178,7 @@ namespace DateTimeIndicator { event_dots.unset (event_uid); } } +#endif public void set_selected (bool selected) { if (selected) { diff --git a/src/Widgets/CalendarGrid.vala b/src/Widgets/CalendarGrid.vala index 66e2757..1d1e06c 100644 --- a/src/Widgets/CalendarGrid.vala +++ b/src/Widgets/CalendarGrid.vala @@ -261,6 +261,7 @@ namespace DateTimeIndicator { return date.get_year () * 10000 + date.get_month () * 100 + date.get_day_of_month (); } +#if USE_EVO public void add_event_dots (E.Source source, Gee.Collection events) { data.foreach ((entry) => { @@ -292,5 +293,6 @@ namespace DateTimeIndicator { }); } } +#endif } } diff --git a/src/Widgets/CalendarView.vala b/src/Widgets/CalendarView.vala index db2139c..77c233c 100644 --- a/src/Widgets/CalendarView.vala +++ b/src/Widgets/CalendarView.vala @@ -182,6 +182,7 @@ namespace DateTimeIndicator { stack.set_visible_child (big_grid); } +#if USE_EVO public void add_event_dots (E.Source source, Gee.Collection events) { calendar_grid.add_event_dots (source, events); } @@ -189,5 +190,6 @@ namespace DateTimeIndicator { public void remove_event_dots (E.Source source, Gee.Collection events) { calendar_grid.remove_event_dots (source, events); } +#endif } } From 16715f5114c0597d6961880bf877f04414400334 Mon Sep 17 00:00:00 2001 From: Dirli Date: Mon, 13 Apr 2020 22:21:07 +0300 Subject: [PATCH 6/8] returned dots in the calendar --- src/Indicator.vala | 6 ++-- src/Services/EventsManager.vala | 28 +++++---------- src/Widgets/CalendarDay.vala | 62 ++++++++++++++++++--------------- src/Widgets/CalendarGrid.vala | 29 ++++++--------- 4 files changed, 57 insertions(+), 68 deletions(-) diff --git a/src/Indicator.vala b/src/Indicator.vala index 31c7af5..c7550aa 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -105,8 +105,10 @@ namespace DateTimeIndicator { size_group.add_widget (calendar); size_group.add_widget (event_listbox); - calendar.selection_changed.connect ((date) => { - idle_update_events (); + event_manager.open.begin ((obj, res) => { + calendar.selection_changed.connect ((date) => { + idle_update_events (); + }); }); #endif diff --git a/src/Services/EventsManager.vala b/src/Services/EventsManager.vala index d939777..ad0397d 100644 --- a/src/Services/EventsManager.vala +++ b/src/Services/EventsManager.vala @@ -10,33 +10,25 @@ namespace DateTimeIndicator { private HashTable source_client; private HashTable source_view; - public EventsManager () { - - } - construct { source_client = new HashTable (str_hash, str_equal); source_events = new HashTable > (Util.source_hash_func, Util.source_equal_func); source_view = new HashTable (str_hash, str_equal); - - open.begin (); } - private async void open () { + public async void open () { try { registry = yield new E.SourceRegistry (null); registry.source_removed.connect (remove_source); - registry.source_added.connect ((source) => add_source_async.begin (source)); + registry.source_added.connect (add_source); // Add sources registry.list_sources (E.SOURCE_EXTENSION_CALENDAR).foreach ((source) => { - E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR); + E.SourceCalendar cal = (E.SourceCalendar) source.get_extension (E.SOURCE_EXTENSION_CALENDAR); if (cal.selected == true && source.enabled == true) { - add_source_async.begin (source); + add_source (source); } }); - - load_all_sources (); } catch (GLib.Error error) { critical (error.message); } @@ -46,7 +38,7 @@ namespace DateTimeIndicator { lock (source_client) { foreach (var id in source_client.get_keys ()) { var source = registry.ref_source (id); - E.SourceCalendar cal = (E.SourceCalendar)source.get_extension (E.SOURCE_EXTENSION_CALENDAR); + E.SourceCalendar cal = (E.SourceCalendar) source.get_extension (E.SOURCE_EXTENSION_CALENDAR); if (cal.selected == true && source.enabled == true) { load_source (source); @@ -120,7 +112,7 @@ namespace DateTimeIndicator { }); } - private async void add_source_async (E.Source source) { + private void add_source (E.Source source) { debug ("Adding source '%s'", source.dup_display_name ()); try { var client = (ECal.Client) ECal.Client.connect_sync (source, ECal.ClientSourceType.EVENTS, -1, null); @@ -129,11 +121,7 @@ namespace DateTimeIndicator { critical (e.message); } - Idle.add (() => { - load_source (source); - - return false; - }); + load_source (source); } private void debug_event (E.Source source, ECal.Component event) { @@ -177,6 +165,8 @@ namespace DateTimeIndicator { return true; }); }); + + events_added (source, added_events.read_only_view); } #if E_CAL_2_0 diff --git a/src/Widgets/CalendarDay.vala b/src/Widgets/CalendarDay.vala index f9c742a..a2c4922 100644 --- a/src/Widgets/CalendarDay.vala +++ b/src/Widgets/CalendarDay.vala @@ -36,7 +36,8 @@ namespace DateTimeIndicator { private static Gtk.CssProvider provider; private static Models.CalendarModel model; - private Gee.HashMap event_dots; + // private Gee.HashMap event_dots; + private Gee.ArrayList event_dots; private Gtk.Grid event_grid; private Gtk.Label label; private bool valid_grab = false; @@ -87,7 +88,8 @@ namespace DateTimeIndicator { label.label = date.get_day_of_month ().to_string (); }); - event_dots = new Gee.HashMap (); + // event_dots = new Gee.HashMap (); + event_dots = new Gee.ArrayList (); } public bool on_scroll_event (Gdk.EventScroll event) { @@ -138,44 +140,46 @@ namespace DateTimeIndicator { }); } - public bool skip_day () { - return event_dots.size >= 3 ? true : false; - } - - public void show_event_grid () { - event_grid.show_all (); - } - #if USE_EVO public void add_dots (E.Source source, ICal.Component ical) { var event_uid = ical.get_uid (); - if (!event_dots.has_key (event_uid)) { - var event_dot = new Gtk. Image (); - event_dot.gicon = new ThemedIcon ("pager-checked-symbolic"); - event_dot.pixel_size = 6; + if (event_dots.contains (event_uid)) { + return; + } - unowned Gtk.StyleContext style_context = event_dot.get_style_context (); - style_context.add_class (Granite.STYLE_CLASS_ACCENT); - style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + event_dots.add (event_uid); + if (event_dots.size > 3) { + return; + } - var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR); - Util.set_event_calendar_color (source_calendar, event_dot); + var event_dot = new Gtk.Image (); + event_dot.gicon = new ThemedIcon ("pager-checked-symbolic"); + event_dot.pixel_size = 6; - event_dots[event_uid] = event_dot; + unowned Gtk.StyleContext style_context = event_dot.get_style_context (); + style_context.add_class (Granite.STYLE_CLASS_ACCENT); + style_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - event_grid.add (event_dot); - } - } + var source_calendar = (E.SourceCalendar?) source.get_extension (E.SOURCE_EXTENSION_CALENDAR); + Util.set_event_calendar_color (source_calendar, event_dot); - public bool exist_event (string ical_uid) { - return event_dots.has_key (ical_uid); + event_grid.add (event_dot); + event_dot.show (); } public void remove_dots (string event_uid) { - var dot = event_dots[event_uid]; - if (dot != null) { - dot.destroy (); - event_dots.unset (event_uid); + if (event_dots.contains (event_uid)) { + return; + } + + event_dots.remove (event_uid); + if (event_dots.size >= 3) { + return; + } + + var w = event_grid.get_children (); + if (w.length () > 0) { + w.nth_data (0).destroy (); } } #endif diff --git a/src/Widgets/CalendarGrid.vala b/src/Widgets/CalendarGrid.vala index 1d1e06c..c544404 100644 --- a/src/Widgets/CalendarGrid.vala +++ b/src/Widgets/CalendarGrid.vala @@ -263,22 +263,16 @@ namespace DateTimeIndicator { #if USE_EVO public void add_event_dots (E.Source source, Gee.Collection events) { - data.foreach ((entry) => { - - foreach (var component in events) { - if (entry.value.skip_day ()) { - return true; - } - - if (Util.calcomp_is_on_day (component, entry.value.date)) { - entry.value.add_dots (source, component.get_icalcomponent ()); - } + foreach (var component in events) { + unowned ICal.Component? icomp = component.get_icalcomponent (); + ICal.Time? start_time = icomp.get_dtstart (); + time_t start_unix = start_time.as_timet (); + var t = new DateTime.from_unix_utc (start_unix); + var d_hash = day_hash (t); + if (data.has_key (d_hash)) { + data[d_hash].add_dots (source, component.get_icalcomponent ()); } - - entry.value.show_event_grid (); - - return true; - }); + } } public void remove_event_dots (E.Source source, Gee.Collection events) { @@ -286,9 +280,8 @@ namespace DateTimeIndicator { unowned ICal.Component ical = component.get_icalcomponent (); var event_uid = ical.get_uid (); data.foreach ((entry) => { - if (entry.value.exist_event (event_uid)) { - entry.value.remove_dots (event_uid); - } + entry.value.remove_dots (event_uid); + return true; }); } From 149da28659883b01ceb0773b35c018d31aa1d912 Mon Sep 17 00:00:00 2001 From: Dirli Date: Tue, 14 Apr 2020 00:16:01 +0300 Subject: [PATCH 7/8] issue #55 --- src/Services/EventsManager.vala | 2 ++ src/Widgets/CalendarDay.vala | 2 +- src/Widgets/CalendarGrid.vala | 11 +++++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Services/EventsManager.vala b/src/Services/EventsManager.vala index ad0397d..959762f 100644 --- a/src/Services/EventsManager.vala +++ b/src/Services/EventsManager.vala @@ -208,6 +208,8 @@ namespace DateTimeIndicator { removed_events.add (event); debug_event (source, event); } + + events.remove_all (cid.get_uid ()); }); events_removed (source, removed_events.read_only_view); diff --git a/src/Widgets/CalendarDay.vala b/src/Widgets/CalendarDay.vala index a2c4922..10d088c 100644 --- a/src/Widgets/CalendarDay.vala +++ b/src/Widgets/CalendarDay.vala @@ -168,7 +168,7 @@ namespace DateTimeIndicator { } public void remove_dots (string event_uid) { - if (event_dots.contains (event_uid)) { + if (!event_dots.contains (event_uid)) { return; } diff --git a/src/Widgets/CalendarGrid.vala b/src/Widgets/CalendarGrid.vala index c544404..6e6cbdb 100644 --- a/src/Widgets/CalendarGrid.vala +++ b/src/Widgets/CalendarGrid.vala @@ -279,11 +279,14 @@ namespace DateTimeIndicator { foreach (var component in events) { unowned ICal.Component ical = component.get_icalcomponent (); var event_uid = ical.get_uid (); - data.foreach ((entry) => { - entry.value.remove_dots (event_uid); - return true; - }); + ICal.Time? start_time = ical.get_dtstart (); + time_t start_unix = start_time.as_timet (); + var t = new DateTime.from_unix_utc (start_unix); + var d_hash = day_hash (t); + if (data.has_key (d_hash)) { + data[d_hash].remove_dots (event_uid); + } } } #endif From a3910e2b8242b8c4837cc764da7f268a02d05d6e Mon Sep 17 00:00:00 2001 From: Dirli Date: Fri, 17 Apr 2020 00:52:53 +0300 Subject: [PATCH 8/8] issue #127 --- src/Indicator.vala | 1 + src/Models/CalendarModel.vala | 17 ++++++--- src/Services/EventsManager.vala | 17 +++++++++ src/Widgets/CalendarDay.vala | 3 +- src/Widgets/CalendarGrid.vala | 66 ++++++++++++++++++++++----------- src/Widgets/CalendarView.vala | 17 ++++----- src/Widgets/EventsListBox.vala | 6 ++- 7 files changed, 87 insertions(+), 40 deletions(-) diff --git a/src/Indicator.vala b/src/Indicator.vala index c7550aa..63614e0 100644 --- a/src/Indicator.vala +++ b/src/Indicator.vala @@ -116,6 +116,7 @@ namespace DateTimeIndicator { model.notify["month-start"].connect (() => { model.compute_ranges (); #if USE_EVO + event_listbox.clear_list (); event_manager.load_all_sources (); #endif }); diff --git a/src/Models/CalendarModel.vala b/src/Models/CalendarModel.vala index d60a9ac..48b6e78 100644 --- a/src/Models/CalendarModel.vala +++ b/src/Models/CalendarModel.vala @@ -57,12 +57,17 @@ namespace DateTimeIndicator { compute_ranges (); } - public void change_month (int relative) { - month_start = month_start.add_months (relative); - } - - public void change_year (int relative) { - month_start = month_start.add_years (relative); + public void change_month (int m_relative, int y_relative = 0) { + if (y_relative == 0) { + month_start = month_start.add_months (m_relative); + } else { + if (m_relative == 0) { + month_start = month_start.add_years (y_relative); + } else { + GLib.DateTime tmp_date = month_start.add_months (m_relative); + month_start = tmp_date.add_years (y_relative); + } + } } /* --- Helper Methods ---// */ diff --git a/src/Services/EventsManager.vala b/src/Services/EventsManager.vala index 959762f..6ece557 100644 --- a/src/Services/EventsManager.vala +++ b/src/Services/EventsManager.vala @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2011-2020 elementary, Inc. (https://elementary.io) + * + * This program 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. + * + * This program 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 . + */ + namespace DateTimeIndicator { public class Services.EventsManager : GLib.Object { public signal void events_added (E.Source source, Gee.Collection events); diff --git a/src/Widgets/CalendarDay.vala b/src/Widgets/CalendarDay.vala index 10d088c..735fdc1 100644 --- a/src/Widgets/CalendarDay.vala +++ b/src/Widgets/CalendarDay.vala @@ -36,7 +36,6 @@ namespace DateTimeIndicator { private static Gtk.CssProvider provider; private static Models.CalendarModel model; - // private Gee.HashMap event_dots; private Gee.ArrayList event_dots; private Gtk.Grid event_grid; private Gtk.Label label; @@ -105,7 +104,7 @@ namespace DateTimeIndicator { /* It's mouse scroll ! */ if (choice == 1 || choice == -1) { - Models.CalendarModel.get_default ().change_month ((int)choice); + Models.CalendarModel.get_default ().change_month ((int) choice); return true; } diff --git a/src/Widgets/CalendarGrid.vala b/src/Widgets/CalendarGrid.vala index 6e6cbdb..ef8edb6 100644 --- a/src/Widgets/CalendarGrid.vala +++ b/src/Widgets/CalendarGrid.vala @@ -32,7 +32,7 @@ namespace DateTimeIndicator { */ public signal void on_event_add (GLib.DateTime date); - public signal void selection_changed (GLib.DateTime new_date); + public signal void selection_changed (GLib.DateTime new_date, bool up); private Gee.HashMap data; private Widgets.CalendarDay selected_gridday; @@ -66,25 +66,32 @@ namespace DateTimeIndicator { events |= Gdk.EventMask.SMOOTH_SCROLL_MASK; } - private void on_day_focus_in (Widgets.CalendarDay day) { - debug ("on_day_focus_in %s", day.date.to_string ()); + private bool on_day_focus_in (Gdk.EventFocus event) { + var day = get_focus_child (); + if (day == null) { + return false; + } + if (selected_gridday != null) { selected_gridday.set_selected (false); } - var selected_date = day.date; - selected_gridday = day; - day.set_selected (true); + var selected_date = (day as Widgets.CalendarDay).date; + selected_gridday = day as Widgets.CalendarDay; + (day as Widgets.CalendarDay).set_selected (true); day.set_state_flags (Gtk.StateFlags.FOCUSED, false); - selection_changed (selected_date); var calmodel = Models.CalendarModel.get_default (); var date_month = selected_date.get_month () - calmodel.month_start.get_month (); var date_year = selected_date.get_year () - calmodel.month_start.get_year (); if (date_month != 0 || date_year != 0) { - calmodel.change_month (date_month); - calmodel.change_year (date_year); + selection_changed (selected_date, false); + calmodel.change_month (date_month, date_year); + } else { + selection_changed (selected_date, true); } + + return false; } public void set_focus_to_today () { @@ -106,7 +113,7 @@ namespace DateTimeIndicator { * Sets the given range to be displayed in the grid. Note that the number of days * must remain the same. */ - public void set_range (Util.DateRange new_range, GLib.DateTime month_start) { + public void set_range (Util.DateRange new_range, GLib.DateTime month_start, GLib.DateTime? selected_date) { var today = new GLib.DateTime.now_local (); Gee.List old_dates; @@ -138,28 +145,46 @@ namespace DateTimeIndicator { for (i = 0; i < new_dates.size; i++) { var new_date = new_dates[i]; - Widgets.CalendarDay day; + Widgets.CalendarDay? day = null; if (i < old_dates.size) { /* A widget already exists for this date, just change it */ var old_date = old_dates[i]; - day = update_day (data[day_hash (old_date)], new_date, today, month_start); - } else { + var d_hash = day_hash (old_date); + if (data.has_key (d_hash)) { + day = data[d_hash]; + } + } + + if (day == null) { /* Still update_day to get the color of etc. right */ - day = update_day (new Widgets.CalendarDay (new_date), new_date, today, month_start); + day = new Widgets.CalendarDay (new_date); day.on_event_add.connect ((date) => on_event_add (date)); - day.scroll_event.connect ((event) => { scroll_event (event); return false; }); - day.focus_in_event.connect ((event) => { - on_day_focus_in (day); - + day.scroll_event.connect ((event) => { + scroll_event (event); return false; }); + day.focus_in_event.connect (on_day_focus_in); attach (day, col + 2, row); day.show_all (); } + update_day (day, new_date, month_start); + update_today_style (day, new_date, today); + if (selected_date != null && day.date.equal (selected_date)) { + /* disabled the signal to avoid unnecessary signals and selected + * the specified day from the new period */ + debug (@"focus selected day $selected_date"); + day.focus_in_event.disconnect (on_day_focus_in); + day.grab_focus_force (); + day.set_selected (true); + day.set_state_flags (Gtk.StateFlags.FOCUSED, false); + selected_gridday = day; + day.focus_in_event.connect (on_day_focus_in); + } + col = (col + 1) % 7; row = (col == 0) ? row + 1 : row; data_new.set (day_hash (new_date), day); @@ -184,8 +209,7 @@ namespace DateTimeIndicator { /** * Updates the given CalendarDay so that it shows the given date. Changes to its style etc. */ - private Widgets.CalendarDay update_day (Widgets.CalendarDay day, GLib.DateTime new_date, GLib.DateTime today, GLib.DateTime month_start) { - update_today_style (day, new_date, today); + private void update_day (Widgets.CalendarDay day, GLib.DateTime new_date, GLib.DateTime month_start) { if (new_date.get_month () == month_start.get_month ()) { day.sensitive_container (true); } else { @@ -193,8 +217,6 @@ namespace DateTimeIndicator { } day.date = new_date; - - return day; } public void update_weeks (GLib.DateTime date, int nr_of_weeks) { diff --git a/src/Widgets/CalendarView.vala b/src/Widgets/CalendarView.vala index 77c233c..fe957ab 100644 --- a/src/Widgets/CalendarView.vala +++ b/src/Widgets/CalendarView.vala @@ -85,10 +85,7 @@ namespace DateTimeIndicator { model.notify["data-range"].connect (() => { label.label = model.month_start.format (_("%OB, %Y")); - sync_with_model (); - - selected_date = null; - selection_changed (selected_date); + sync_with_model (selected_date != null); }); left_button.clicked.connect (() => { @@ -113,9 +110,11 @@ namespace DateTimeIndicator { day_double_click (); }); - calendar_grid.selection_changed.connect ((date) => { + calendar_grid.selection_changed.connect ((date, up) => { selected_date = date; - selection_changed (date); + if (up) { + selection_changed (date); + } }); return calendar_grid; @@ -154,9 +153,9 @@ namespace DateTimeIndicator { } /* Sets the calendar widgets to the date range of the model */ - private void sync_with_model () { + private void sync_with_model (bool show_selected = false) { var model = Models.CalendarModel.get_default (); - if (calendar_grid.grid_range != null && (model.data_range.equals (calendar_grid.grid_range) || calendar_grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) { + if (!show_selected && calendar_grid.grid_range != null && (model.data_range.equals (calendar_grid.grid_range) || calendar_grid.grid_range.first_dt.compare (model.data_range.first_dt) == 0)) { calendar_grid.update_today (); return; // nothing else to do } @@ -168,7 +167,7 @@ namespace DateTimeIndicator { big_grid = create_big_grid (); stack.add (big_grid); - calendar_grid.set_range (model.data_range, model.month_start); + calendar_grid.set_range (model.data_range, model.month_start, show_selected ? selected_date : null); calendar_grid.update_weeks (model.data_range.first_dt, model.num_weeks); if (previous_first != null) { diff --git a/src/Widgets/EventsListBox.vala b/src/Widgets/EventsListBox.vala index c25af2e..9022072 100644 --- a/src/Widgets/EventsListBox.vala +++ b/src/Widgets/EventsListBox.vala @@ -21,10 +21,14 @@ namespace DateTimeIndicator { set_sort_func (sort_function); } - public void update_events (GLib.DateTime? selected_date, HashTable> source_events) { + public void clear_list () { foreach (unowned Gtk.Widget widget in get_children ()) { widget.destroy (); } + } + + public void update_events (GLib.DateTime? selected_date, HashTable> source_events) { + clear_list (); if (selected_date == null) { return;