Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
34682ca
Started to work on WeekView based upon GNOME Calendar
marbetschar Apr 21, 2020
b505cd4
Sketching WeekView and WeekHeader based on GNOME Calendar
marbetschar Apr 21, 2020
550655c
Introducing new namespace Maya.Week
marbetschar Apr 21, 2020
b38beb8
Fixed compile errors
marbetschar Apr 21, 2020
ecfd214
Draw for Week.Grid
marbetschar Apr 21, 2020
46eef35
Fixed compile errors for Week.Grid.draw
marbetschar Apr 21, 2020
f3e6145
Added possibility to switch between month and week view
marbetschar Apr 21, 2020
bcc007f
First size allocation steps
marbetschar Apr 21, 2020
70493b5
Basic realization of Week.Grid
marbetschar Apr 21, 2020
bf17c77
Further steps towards week view...
marbetschar Apr 21, 2020
fb0260f
Further progress in adapting GNOME Calendar Codebase
marbetschar Apr 21, 2020
3407241
Week grid render does work
marbetschar Apr 22, 2020
081f511
Rendering Hour Sidebar
marbetschar Apr 22, 2020
7418da0
Moved drawing of hours into own class
marbetschar Apr 22, 2020
804e049
Added week header rendering
marbetschar Apr 22, 2020
f116f13
Use application accentColor for today
marbetschar Apr 22, 2020
5a6f3ff
Changed Icon to switch views
marbetschar Apr 22, 2020
37aa843
Made CalendarModel more generic and introducing new EventWidget
marbetschar Apr 22, 2020
a81dfb8
Distinguish where to put an event
marbetschar Apr 23, 2020
d01a919
Did some code cleanup
marbetschar Apr 23, 2020
e099f30
Removed all non essential code for rendering a week
marbetschar Apr 23, 2020
d13ce5a
giving up :(
marbetschar Apr 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions core/DisplayMode.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*-
* Copyright (c) 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 <http://www.gnu.org/licenses/>.
*
* Authored by: Marco Betschart<elementary@marco.betschart.name>
*/

namespace Maya {

public enum DisplayMode {
MONTH,
WEEK
}
}
62 changes: 41 additions & 21 deletions core/Model/CalendarModel.vala
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@
public class Maya.Model.CalendarModel : Object {

/* The data_range is the range of dates for which this model is storing
* data. The month_range is a subset of this range corresponding to the
* calendar month that is being focused on. In summary:
* data. The display_range is a subset of this range corresponding to the
* calendar view that is being focused on (either month or week). In summary:
*
* data_range.first_dt <= month_range.first_dt < month_range.last_dt <= data_range.last_dt
* data_range.first_dt <= display_range.first_dt < display_range.last_dt <= data_range.last_dt
*
* There is no way to set the ranges publicly. They can only be modified by
* changing one of the following properties: month_start, num_weeks, and
* changing one of the following properties: display_start, num_weeks, and
* week_starts_on.
*/
public Util.DateRange data_range { get; private set; }
public Util.DateRange month_range { get; private set; }
public Util.DateRange display_range { get; private set; }
public E.SourceRegistry registry { get; private set; }

/* The first day of the month */
public DateTime month_start { get; set; }
/* The first day to be displayed */
public DateTime display_start { get; set; }

/* The number of weeks to show in this model */
public int num_weeks { get; private set; default = 6; }
Expand All @@ -49,7 +49,7 @@ public class Maya.Model.CalendarModel : Object {
public signal void connected (E.Source source);
public signal void error_received (string error);

/* The month_start, num_weeks, or week_starts_on have been changed */
/* The display_start, num_weeks, or week_starts_on have been changed */
public signal void parameters_changed ();

HashTable<string, ECal.Client> source_client;
Expand All @@ -68,20 +68,30 @@ public class Maya.Model.CalendarModel : Object {
}

private CalendarModel () {
int week_start = Posix.NLTime.FIRST_WEEKDAY.to_string ().data[0];
int week_start = Util.get_first_weekday ();
if (week_start >= 1 && week_start <= 7) {
week_starts_on = (GLib.DateWeekday) (week_start - 1);
}

this.month_start = Util.get_start_of_month (Settings.SavedState.get_default ().get_page ());
var display_page = Settings.SavedState.get_default ().get_page ();
switch (Settings.SavedState.get_default ().get_mode ()) {
case Maya.DisplayMode.WEEK:
this.display_start = Util.get_start_of_week (display_page);
this.num_weeks = 1;
break;

case Maya.DisplayMode.MONTH:
this.display_start = Util.get_start_of_month (display_page);
break;
}
compute_ranges ();

source_client = new HashTable<string, ECal.Client> (str_hash, str_equal);
source_events = new HashTable<E.Source, Gee.TreeMultiMap<string, ECal.Component>> (Util.source_hash_func, Util.source_equal_func);
source_view = new HashTable<string, ECal.ClientView> (str_hash, str_equal);
calendar_trash = new GLib.Queue<E.Source> ();

notify["month-start"].connect (on_parameter_changed);
notify["display-start"].connect (on_parameter_changed);
open.begin ();
}

Expand Down Expand Up @@ -221,12 +231,16 @@ public class Maya.Model.CalendarModel : Object {
}
}

public void change_week (int relative) {
display_start = display_start.add_weeks (relative);
}

public void change_month (int relative) {
month_start = month_start.add_months (relative);
display_start = display_start.add_months (relative);
}

public void change_year (int relative) {
month_start = month_start.add_years (relative);
display_start = display_start.add_years (relative);
}

public void load_all_sources () {
Expand Down Expand Up @@ -284,11 +298,17 @@ public class Maya.Model.CalendarModel : Object {
//--- Helper Methods ---//

private void compute_ranges () {
Settings.SavedState.get_default ().month_page = month_start.format ("%Y-%m");
var month_end = month_start.add_full (0, 1, -1);
month_range = new Util.DateRange (month_start, month_end);
Settings.SavedState.get_default ().display_page = display_start.format ("%Y-%m-%d");

DateTime display_end;
if (num_weeks > 1) {
display_end = display_start.add_full (0, 1, -1);
} else {
display_end = display_start.add_full (0, 0, 6);
}
display_range = new Util.DateRange (display_start, display_end);

int dow = month_start.get_day_of_week ();
int dow = display_start.get_day_of_week ();
int wso = (int) week_starts_on;
int offset = 0;

Expand All @@ -298,9 +318,9 @@ public class Maya.Model.CalendarModel : Object {
offset = 7 + dow - wso;
}

var data_range_first = month_start.add_days (-offset);
var data_range_first = display_start.add_days (-offset);

dow = month_end.get_day_of_week ();
dow = display_end.get_day_of_week ();
wso = (int) (week_starts_on + 6);

// WSO must be between 1 and 7
Expand All @@ -314,12 +334,12 @@ public class Maya.Model.CalendarModel : Object {
else if (wso > dow)
offset = wso - dow;

var data_range_last = month_end.add_days (offset);
var data_range_last = display_end.add_days (offset);

data_range = new Util.DateRange (data_range_first, data_range_last);
num_weeks = data_range.to_list ().size / 7;

debug (@"Date ranges: ($data_range_first <= $month_start < $month_end <= $data_range_last)");
debug (@"Date ranges: ($data_range_first <= $display_start < $display_end <= $data_range_last)");
}

private void load_source (E.Source source) {
Expand Down
22 changes: 18 additions & 4 deletions core/Settings/SavedState.vala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
//

namespace Maya.Settings {

public class SavedState : Granite.Services.Settings {
private static Settings.SavedState? saved_state = null;

Expand All @@ -25,21 +26,34 @@ namespace Maya.Settings {
return saved_state;
}

public string month_page { get; set; }
public string display_mode { get; set; }
public string display_page { get; set; }
public string selected_day { get; set; }

private SavedState () {
base ("io.elementary.calendar.savedstate");
}

public Maya.DisplayMode get_mode () {
switch (display_mode) {
case "week":
return Maya.DisplayMode.WEEK;
default:
return Maya.DisplayMode.MONTH;
}
}

public DateTime get_page () {
if (month_page == null)
if (display_page == null)
return new DateTime.now_local ();
if (month_page == "")
if (display_page == "")
return new DateTime.now_local ();
var numbers = month_page.split ("-", 2);
var numbers = display_page.split ("-", 3);
var dt = new DateTime.local (int.parse (numbers[0]), 1, 1, 0, 0, 0);
dt = dt.add_months (int.parse (numbers[1]) - 1);
if (numbers.length > 2) {
dt = dt.add_days (int.parse (numbers[2]) - 1);
}
return dt;
}

Expand Down
103 changes: 103 additions & 0 deletions core/Utils.vala
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ namespace Maya.Util {
return false;
}

public bool is_all_day_event (ICal.Component comp) {
DateTime start, end;
get_local_datetimes_from_icalcomponent (comp, out start, out end);
return is_all_day (start, end);
}

/**
* Say if an event lasts all day.
*/
Expand All @@ -182,6 +188,103 @@ namespace Maya.Util {
return new DateTime.local (date.get_year (), date.get_month (), 1, 0, 0, 0);
}

/**
* TODO: This implementation needs some more work
*/
public int get_days_in_month (DateTime datetime) {
DateMonth month;

switch (datetime.get_month ()) {
case 1:
month = DateMonth.JANUARY;
break;
case 2:
month = DateMonth.FEBRUARY;
break;
case 3:
month = DateMonth.MARCH;
break;
case 4:
month = DateMonth.APRIL;
break;
case 5:
month = DateMonth.MAY;
break;
case 6:
month = DateMonth.JUNE;
break;
case 7:
month = DateMonth.JULY;
break;
case 8:
month = DateMonth.AUGUST;
break;
case 9:
month = DateMonth.SEPTEMBER;
break;
case 10:
month = DateMonth.OCTOBER;
break;
case 11:
month = DateMonth.NOVEMBER;
break;
case 12:
month = DateMonth.DECEMBER;
break;
default:
month = DateMonth.BAD_MONTH;
break;
}

// TODO: Make DateYear dynamic: datetime.get_year ()
// how do I convert int into ushort ...?!
DateYear year = 2020;

return month.get_days_in_month (year);
}

/**
* The implementation might not work on every platform. See GNOME Calendar's
* implementation for a more comprehensive approach if needed:
* https://gitlab.gnome.org/GNOME/gnome-calendar/-/blob/master/src/utils/gcal-utils.c#L301
*/
public int get_first_weekday () {
return Posix.NLTime.FIRST_WEEKDAY.to_string ().data[0];
}

/**
* Retrieves the first day of the week @date is in, at 00:00
* of the local timezone.
*
* This date is inclusive.
*/
public DateTime get_start_of_week (DateTime date) {
var first_weekday = get_first_weekday ();
var weekday = date.get_day_of_week () % 7;
var n_days_after_week_start = (weekday - first_weekday) % 7;

var start_of_week = date.add_days (-n_days_after_week_start);

return new DateTime.local (
start_of_week.get_year (),
start_of_week.get_month (),
start_of_week.get_day_of_month (),
0, 0, 0);
}


/**
* Retrieves the last day of the week @date is in, at 23:59:59
* of the local timezone.
*
* Because this date is exclusive, it actually is start of the
* next week.
*/
public DateTime get_end_of_week (DateTime date) {
var week_start = get_start_of_week (date);
return week_start.add_weeks (1);
}

public DateTime strip_time (DateTime datetime) {
return datetime.add_full (0, 0, 0, -datetime.get_hour (), -datetime.get_minute (), -datetime.get_second ());
}
Expand Down
1 change: 1 addition & 0 deletions core/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ core_files = files(
'Model/CalendarModel.vala',
'Settings/SavedState.vala',
'DateRange.vala',
'DisplayMode.vala',
'Utils.vala',
'GesturesUtils.vala'
)
Expand Down
2 changes: 1 addition & 1 deletion daemon/Daemon.vala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace Maya {
model.events_added.connect (on_events_added);
model.events_updated.connect (on_events_updated);
model.events_removed.connect (on_events_removed);
model.month_start = Maya.Util.get_start_of_month (new DateTime.now_local ());
model.display_start = Maya.Util.get_start_of_month (new DateTime.now_local ());
}

private void on_events_added (E.Source source, Gee.Collection<ECal.Component> events) {
Expand Down
11 changes: 8 additions & 3 deletions data/io.elementary.calendar.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,15 @@
<summary>Whether or not to show weeknumbers.</summary>
<description>Whether or not to show weeknumbers.</description>
</key>
<key name="month-page" type="s">
<key name="display-page" type="s">
<default>""</default>
<summary>The current year-month that is shown.</summary>
<description>The current year-month that is shown.</description>
<summary>The current year-month-day that is shown.</summary>
<description>The current year-month-day that is shown.</description>
</key>
<key name="display-mode" type="s">
<default>"month"</default>
<summary>The calendars display mode.</summary>
<description>In which display mode the calendar should be shown ("month", "week").</description>
</key>
<key name="selected-day" type="s">
<default>""</default>
Expand Down
1 change: 1 addition & 0 deletions data/maya.gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
<file alias="Grid.css" compressed="true">style/Grid.css</file>
<file alias="Header.css" compressed="true">style/Header.css</file>
<file alias="WeekLabels.css" compressed="true">style/WeekLabels.css</file>
<file alias="WeekView.css" compressed="true">style/WeekView.css</file>
</gresource>
</gresources>
Loading