diff --git a/Calendar/CalendarEvent.py b/Calendar/CalendarEvent.py
index d3a058b..0f97f2f 100644
--- a/Calendar/CalendarEvent.py
+++ b/Calendar/CalendarEvent.py
@@ -15,6 +15,7 @@ class CalendarEvent (object):
self.highlight = None
self.calendar_name = None
+ self.calendar_url = None
self.location = None
self.fetch_datetime = None
diff --git a/Calendar/CalendarInterface.py b/Calendar/CalendarInterface.py
index 740a5cc..4efbad3 100644
--- a/Calendar/CalendarInterface.py
+++ b/Calendar/CalendarInterface.py
@@ -10,6 +10,7 @@ class CalendarInterface (DataSourceInterface):
def __init__(self):
self.events = []
+ self.excluded_urls = []
def reload(self):
if self.is_available() == False:
@@ -17,6 +18,9 @@ class CalendarInterface (DataSourceInterface):
self.events = self.__get_events__()
self.events = self.__sort_events__(self.events)
+ def exclude_calendars(self, urls=[]):
+ self.excluded_urls = urls
+
def __sort_events__(self, events):
events.sort(key=lambda x: x.begin_datetime)
return events
@@ -72,6 +76,10 @@ class CalendarInterface (DataSourceInterface):
events_in_range = []
for event in self.events:
+ # Is excluded?
+ if event.calendar_url in self.excluded_urls:
+ continue
+
event_occurrence = self.__get_if_event_in_range__(
event, start, duration)
if event_occurrence:
diff --git a/Calendar/DayFocusListPanel.py b/Calendar/DayFocusListPanel.py
new file mode 100644
index 0000000..751e0d9
--- /dev/null
+++ b/Calendar/DayFocusListPanel.py
@@ -0,0 +1,151 @@
+from datetime import date, datetime, timedelta, timezone
+from settings import line_thickness, general_settings
+from DayHeaderDesign import DayHeaderDesign
+from HourListDesign import HourListDesign
+from DayRowDesign import DayRowDesign
+from PanelDesign import PanelDesign
+from Assets import colors
+from PIL import ImageDraw
+
+HEADER_SIZE = (1, 0.2)
+HOURLIST_HEIGHT = 0.3
+HOURLIST_SIZE = (1, HOURLIST_HEIGHT)
+DAYLIST_YPOS = HEADER_SIZE[1] + HOURLIST_SIZE[1]
+DAYLIST_HEIGHT = 1 - HEADER_SIZE[1] - HOURLIST_SIZE[1]
+DAYLIST_SIZE = (1, DAYLIST_HEIGHT)
+HOURS_COUNT = 6
+DAYROW_MIN_FORMAT = 40 / 384
+DAYROW_MAX_FORMAT = 60 / 384
+PANEL_LINE_THICKNESS = line_thickness
+
+
+class DayFocusListPanel (PanelDesign):
+ """Shows Day-View for today and a short Day-List for
+ the upcoming days."""
+
+ def __init__(self, size):
+ super(DayFocusListPanel, self).__init__(size)
+ self.hours_count = HOURS_COUNT
+ self.__init_modules__()
+
+ def __abs_co__(self, coordinates):
+ return (int(coordinates[0] * self.size[0]), int(coordinates[1] * self.size[1]))
+
+ def __init_modules__(self):
+ self.__init_header__()
+ self.__init_hourlist__()
+ self.__init_daylist__()
+
+ def __init_header__(self):
+ self.__header__ = DayHeaderDesign(
+ self.__abs_co__(HEADER_SIZE), date.today())
+ self.__header__.pos = (0, 0)
+
+ def __init_hourlist__(self):
+ start, end = self.__get_current_hour_range__()
+ size = self.__abs_co__(HOURLIST_SIZE)
+
+ self.__hourlist__ = HourListDesign(size, start, end)
+ self.__hourlist__.pos = (0, self.__header__.size[1])
+
+ def __init_daylist__(self):
+ self.__daylist_rows__ = []
+ self.__calc_dayrow_size__()
+ self.__create_day_rows__()
+
+ def __calc_dayrow_size__(self):
+ max_area_height = DAYLIST_HEIGHT * self.size[1]
+ max_row_number = max_area_height / (DAYROW_MIN_FORMAT * self.size[0])
+ min_row_number = max_area_height / (DAYROW_MAX_FORMAT * self.size[0])
+ average_row_number = (max_row_number + min_row_number) / 2
+ self.dayrow_count = round(average_row_number)
+ row_height = max_area_height / self.dayrow_count
+ self.dayrow_size = (1, row_height / self.size[1])
+
+ def __create_day_rows__(self):
+ following_days = self.__get_following_days__()
+ for i, date in enumerate(following_days):
+ row = DayRowDesign(self.__abs_co__(self.dayrow_size), date)
+ row.pos = self.__get_day_row_pos__(i)
+ self.__daylist_rows__.append(row)
+
+ def __get_following_days__(self):
+ following_days = []
+ for i in range(self.dayrow_count):
+ following_days.append(date.today() + timedelta(days=i + 1))
+ return following_days
+
+ def __get_day_row_pos__(self, i):
+ ypos = self.size[1] * DAYLIST_YPOS
+ down_shift = i * self.dayrow_size[1] * self.size[1]
+ return (0, int(ypos + down_shift))
+
+ def __finish_panel__(self):
+ self.draw_design(self.__header__)
+ self.draw_design(self.__hourlist__)
+
+ for row in self.__daylist_rows__:
+ self.draw_design(row)
+ self.__draw_daylist_lines__()
+
+ def __draw_daylist_lines__(self):
+ positions = []
+ for i in range(len(self.__daylist_rows__)):
+ positions.append(self.__get_day_row_pos__(i)[1])
+ for ypos in positions:
+ line_start = (0, ypos)
+ line_end = (self.size[0], ypos)
+ ImageDraw.Draw(self.__image__).line(
+ [line_start, line_end], fill=colors["fg"], width=PANEL_LINE_THICKNESS)
+
+ def __get_current_hour_range__(self):
+ start_hour = datetime.now().hour
+ additional_hours = self.hours_count - 1
+
+ if start_hour + additional_hours > 23:
+ start_hour = 23 - additional_hours
+
+ return start_hour, start_hour + additional_hours
+
+ def add_weather(self, weather):
+ self.__header__.add_weather(weather)
+
+ def add_calendar(self, calendar):
+ allday_ev, timed_ev = self.__split_events__(
+ calendar.get_today_events())
+ self.__header__.add_events(allday_ev)
+ self.__hourlist__.add_events(timed_ev)
+
+ self.__add_calendar_daylist__(calendar)
+
+ def __split_events__(self, events):
+ allday_ev = []
+ timed_ev = []
+
+ for event in events:
+ if event.allday:
+ allday_ev.append(event)
+ elif event.multiday:
+ if self.__is_today__(event.begin_datetime):
+ timed_ev.append(event)
+ elif self.__is_today__(event.end_datetime):
+ timed_ev.append(event)
+ else:
+ allday_ev.append(event)
+ else:
+ timed_ev.append(event)
+ return allday_ev, timed_ev
+
+ def __is_today__(self, dt):
+ today = date.today()
+ return dt.day == today.day and \
+ dt.month == today.month and \
+ dt.year == today.year
+
+ def __add_calendar_daylist__(self, calendar):
+ calendar.exclude_calendars(general_settings["extra-excluded-urls"])
+
+ for row in self.__daylist_rows__:
+ row.add_calendar(calendar)
+
+ calendar.exclude_calendars()
diff --git a/Calendar/E-Paper.py b/Calendar/E-Paper.py
index 6fd51af..1360310 100644
--- a/Calendar/E-Paper.py
+++ b/Calendar/E-Paper.py
@@ -17,6 +17,7 @@ from settings import datetime_encoding, language, render_to_display, render_to_f
from MonthOvPanel import MonthOvPanel
from DayListPanel import DayListPanel
from DayViewPanel import DayViewPanel
+from DayFocusListPanel import DayFocusListPanel
from MonthViewPanel import MonthViewPanel
from AgendaListPanel import AgendaListPanel
from ImageFramePanel import ImageFramePanel
@@ -54,12 +55,14 @@ available_panels = {
"day-list": DayListPanel,
"month-overview": MonthOvPanel,
"day-view": DayViewPanel,
+ "day-focus-list": DayFocusListPanel,
"agenda-list": AgendaListPanel,
"month-view": MonthViewPanel,
- "image-frame": ImageFramePanel
+ "image-frame": ImageFramePanel,
}
-loop_timer = LoopTimer(update_interval, run_on_hour=run_on_hour, max_loop_count=max_loop_count)
+loop_timer = LoopTimer(
+ update_interval, run_on_hour=run_on_hour, max_loop_count=max_loop_count)
"""Main loop starts from here"""
@@ -117,7 +120,8 @@ def main():
loop_timer.end_loop()
if loop_timer.was_last_loop():
- debug.print_line("Maximum loop count " + str(loop_timer.loop_count) + " reached, exiting.")
+ debug.print_line("Maximum loop count " +
+ str(loop_timer.loop_count) + " reached, exiting.")
return
sleep_time = loop_timer.time_until_next()
diff --git a/Calendar/IcalEvents.py b/Calendar/IcalEvents.py
index ef5068e..7ec6d22 100644
--- a/Calendar/IcalEvents.py
+++ b/Calendar/IcalEvents.py
@@ -51,6 +51,7 @@ class IcalEvents(CalendarInterface):
ical = Calendar(decode)
for event in ical.events:
cal_event = CalendarEvent()
+ cal_event.calendar_url = calendar
cal_event.fetch_datetime = datetime.now(timezone.utc)
cal_event.begin_datetime = event.begin.datetime
diff --git a/Calendar/ImageFramePanel.py b/Calendar/ImageFramePanel.py
index 37dd2c5..3cb4e4d 100644
--- a/Calendar/ImageFramePanel.py
+++ b/Calendar/ImageFramePanel.py
@@ -44,18 +44,3 @@ class ImageFramePanel (PanelDesign):
overlay = ImageDesign(self.size, self.overlay_path)
overlay.__finish_image__()
self.__image__.alpha_composite(overlay.__image__)
-
- def add_weather(self, weather):
- pass
-
- def add_calendar(self, calendar):
- pass
-
- def add_rssfeed(self, rss):
- pass
-
- def add_crypto(self, crypto):
- pass
-
- def add_tasks(self, tasks):
- pass
diff --git a/Calendar/PanelDesign.py b/Calendar/PanelDesign.py
index e1fc60b..a360ef8 100644
--- a/Calendar/PanelDesign.py
+++ b/Calendar/PanelDesign.py
@@ -12,19 +12,19 @@ class PanelDesign (DesignEntity):
self.start_timestamp = datetime.now()
def add_weather(self, weather):
- raise NotImplementedError("Function needs to be implemented")
+ pass
def add_calendar(self, calendar):
- raise NotImplementedError("Function needs to be implemented")
+ pass
def add_rssfeed(self, rss):
- raise NotImplementedError("Function needs to be implemented")
+ pass
def add_tasks(self, tasks):
- raise NotImplementedError("Function needs to be implemented")
+ pass
def add_crypto(self, crypto):
- raise NotImplementedError("Function needs to be implemented")
+ pass
def __finish_panel__(self):
pass
diff --git a/Calendar/settings.py.sample b/Calendar/settings.py.sample
index 52f6c9f..a683a38 100644
--- a/Calendar/settings.py.sample
+++ b/Calendar/settings.py.sample
@@ -30,13 +30,14 @@ run_on_hour = True # If True, updates calendar every full hour, ignoring differ
font_size = 14 # does not affect every text
font_boldness = "semibold" # extralight, light, regular, semibold, bold, extrabold
line_thickness = 1 # 1-3 Thickness advised
-choosen_design = "month-overview" # month-overview, day-list, day-view, agenda-list, month-view, image-frame
+choosen_design = "month-overview" # month-overview, day-list, day-view, day-focus-list, agenda-list, month-view, image-frame
general_settings = { # General settings that designs may use
"info-area" : "rss", # empty, events, rss, crypto
"highlight-event-days" : True,
- "weather-info" : True,
+ "weather-info" : True,
"image-folder" : "",
- "overlay-image" : "" # Size must be 384x640px with default display
+ "overlay-image" : "", # Size must be 384x640px with default display
+ "extra-excluded-urls" : []
}
diff --git a/Gallery/day-focus-list_example.png b/Gallery/day-focus-list_example.png
new file mode 100644
index 0000000..9d3686a
Binary files /dev/null and b/Gallery/day-focus-list_example.png differ
diff --git a/README.md b/README.md
index f261eb1..7ced017 100644
--- a/README.md
+++ b/README.md
@@ -15,13 +15,14 @@ This software fully supports the 3-Colour **and** 2-Colour version of the 7.5" E
* **Added Support for the 2-Colour E-Paper Display as well!** (Late September 2018)
* **Added Support for Raspbian Stretch lite.** (Late September 2018)
-
+
1.: Day-List Panel
2.: Month-Overview Panel
3.: Agenda-List Panel
4.: Day-View Panel
-5.: Image-Frame Panel
+5.: Day-Focus-List Panel
+6.: Image-Frame Panel
## Main features
* Display a calendar with one of multiple designes
@@ -98,6 +99,7 @@ Once the packages are installed, navigate to the home directory, open 'E-Paper-M
| `"weather-info"` | If set to `False`, weather info areas disappear and make room for events/rss/etc. (depends on the design). |
| `"image-folder"` | Set a relative or absolute path to a folder containing images that you want to see fullscreen with the `"image-frame"` design activated. |
| `"overlay-image"` | Set a relative or absolute path to an image with the same size as the screen (default: 384x640px) to show some static information over every image shown in the `"image-frame"` design. If the overlay image is contained within the `"image-folder"`, it will not be included into the slideshow. |
+| `"extra-excluded-urls"` | A list of calendar urls that may be excluded in some panels in certain areas. |
### Debug
| Parameter | Description |