Added new design and minor improvements
This commit is contained in:
parent
d3f46c820e
commit
30eb1e4cdd
10 changed files with 181 additions and 28 deletions
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
151
Calendar/DayFocusListPanel.py
Normal file
151
Calendar/DayFocusListPanel.py
Normal file
|
@ -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()
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
"image-folder" : "",
|
||||
"overlay-image" : "" # Size must be 384x640px with default display
|
||||
"overlay-image" : "", # Size must be 384x640px with default display
|
||||
"extra-excluded-urls" : []
|
||||
}
|
||||
|
||||
|
||||
|
|
BIN
Gallery/day-focus-list_example.png
Normal file
BIN
Gallery/day-focus-list_example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
|
@ -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)
|
||||
|
||||
<img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/day-list_example.png" width="270"><img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/month-overview_example.png" width="270"><img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/agenda-list_example.png" width="270"><img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/day-view_example.png" width="270"><img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/image-frame_example.png" width="270">
|
||||
<img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/day-list_example.png" width="270"><img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/month-overview_example.png" width="270"><img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/agenda-list_example.png" width="270"><img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/day-view_example.png" width="270"><img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/day-focus-list_example.png" width="270"><img src="https://github.com/mgfcf/E-Paper-Calendar/blob/master/Gallery/image-frame_example.png" width="270">
|
||||
|
||||
1.: Day-List Panel 
|
||||
2.: Month-Overview Panel 
|
||||
3.: Agenda-List Panel<br>
|
||||
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 |
|
||||
|
|
Loading…
Reference in a new issue