From d79c65cdd57322db9e73296a2acbf2721f69b5ed Mon Sep 17 00:00:00 2001 From: mygrexit <33792951+mygrexit@users.noreply.github.com> Date: Fri, 10 Nov 2023 13:39:08 +0100 Subject: [PATCH 1/3] Add localized formatting for multi-day event durations This commit introduces a feature to format the names of multi-day events using Arrow's localization. Event titles now include the event duration in days. --- inkycal/modules/inkycal_calendar.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/inkycal/modules/inkycal_calendar.py b/inkycal/modules/inkycal_calendar.py index 65012a1..68ccb26 100755 --- a/inkycal/modules/inkycal_calendar.py +++ b/inkycal/modules/inkycal_calendar.py @@ -355,7 +355,13 @@ class Calendar(inkycal_module): cursor = 0 for event in upcoming_events: if cursor < len(event_lines): - the_name = event['title'] + event_duration = (event['end'] - event['begin']).days + if event_duration > 1: + # Format the duration using Arrow's localization + days_translation = arrow.get().shift(days=event_duration).humanize(only_distance=True, locale=lang) + the_name = f"{event['title']} ({days_translation})" + else: + the_name = event['title'] the_date = event['begin'].format(self.date_format, locale=lang) the_time = event['begin'].format(self.time_format, locale=lang) # logger.debug(f"name:{the_name} date:{the_date} time:{the_time}") From 2dc945ebee3b92208b4ac79aa5968f6462235a23 Mon Sep 17 00:00:00 2001 From: mygrexit <33792951+mygrexit@users.noreply.github.com> Date: Fri, 10 Nov 2023 14:57:47 +0100 Subject: [PATCH 2/3] Added support for multi-day events Improved event handling in calendar: Enhanced the calendar module to handle events spanning multiple days. --- inkycal/modules/inkycal_calendar.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/inkycal/modules/inkycal_calendar.py b/inkycal/modules/inkycal_calendar.py index 68ccb26..a6d3154 100755 --- a/inkycal/modules/inkycal_calendar.py +++ b/inkycal/modules/inkycal_calendar.py @@ -296,14 +296,27 @@ class Calendar(inkycal_module): month_events = parser.get_events(month_start, month_end, self.timezone) parser.sort() self.month_events = month_events + + # Initialize days_with_events as an empty list + days_with_events = [] - # find out on which days of this month events are taking place - days_with_events = [ - int(events['begin'].format('D')) for events in month_events - ] + # Handle multi-day events by adding all days between start and end + for event in month_events: + start_date = event['begin'].date() + end_date = event['end'].date() + + # Convert start and end dates to arrow objects with timezone + start = arrow.get(event['begin'].date(), tzinfo=self.timezone) + end = arrow.get(event['end'].date(), tzinfo=self.timezone) + + # Use arrow's range function for generating dates + for day in arrow.Arrow.range('day', start, end): + day_num = int(day.format('D')) # get day number using arrow's format method + if day_num not in days_with_events: + days_with_events.append(day_num) # remove duplicates (more than one event in a single day) - list(set(days_with_events)).sort() + days_with_events = sorted(set(days_with_events)) self._days_with_events = days_with_events # Draw a border with specified parameters around days with events From 126b3826e6b2892d6ae638ce5ef59191baa7b5a8 Mon Sep 17 00:00:00 2001 From: mygrexit <33792951+mygrexit@users.noreply.github.com> Date: Fri, 10 Nov 2023 21:53:36 +0100 Subject: [PATCH 3/3] Add dotted and dashed lines (draw_boarder function) First version of adding dotted and dashed line in order to be able to have more distinguishon between multi event, single event and mixed event days. This version is using the "arcs" from PIL ImageDraw which isn't pretty. --- inkycal/custom/functions.py | 94 ++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 33 deletions(-) diff --git a/inkycal/custom/functions.py b/inkycal/custom/functions.py index a092007..ff3f16e 100644 --- a/inkycal/custom/functions.py +++ b/inkycal/custom/functions.py @@ -277,60 +277,88 @@ def internet_available(): return False -def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1)): - """Draws a border at given coordinates. +from PIL import Image, ImageDraw + +def draw_dotted_line(draw, start, end, colour, thickness): + """Draws a dotted line between start and end points using dots.""" + delta_x = end[0] - start[0] + delta_y = end[1] - start[1] + distance = ((delta_x ** 2 + delta_y ** 2) ** 0.5) + dot_spacing = 6 # Distance between dots + + for i in range(0, int(distance / dot_spacing), 1): + dot_position = (start[0] + (i * dot_spacing * delta_x / distance), + start[1] + (i * dot_spacing * delta_y / distance)) + # Drawing a circle at each dot position to create a dotted effect + draw.ellipse([(dot_position[0] - thickness, dot_position[1] - thickness), + (dot_position[0] + thickness, dot_position[1] + thickness)], + fill=colour) + +def draw_dashed_line(draw, start, end, colour, thickness): + """Draws a dashed line between start and end points.""" + delta_x = end[0] - start[0] + delta_y = end[1] - start[1] + distance = ((delta_x ** 2 + delta_y ** 2) ** 0.5) + step_size = 10 + gap_size = 5 + + for i in range(0, int(distance / (step_size + gap_size)), 1): + segment_start = (start[0] + (i * (step_size + gap_size) * delta_x / distance), + start[1] + (i * (step_size + gap_size) * delta_y / distance)) + segment_end = (segment_start[0] + (step_size * delta_x / distance), + segment_start[1] + (step_size * delta_y / distance)) + draw.line((segment_start, segment_end), fill=colour, width=thickness) + +def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1), style='solid'): + """ + Draws a border at given coordinates with specified styles (solid, dotted, dashed). Args: - - image: The image on which the border should be drawn (usually im_black or - im_colour. - - - xy: Tuple representing the top-left corner of the border e.g. (32, 100) - where 32 is the x co-ordinate and 100 is the y-coordinate. - - - size: Size of the border as a tuple -> (width, height). - - - radius: Radius of the corners, where 0 = plain rectangle, 5 = round corners. - - - thickness: Thickness of the border in pixels. - - - shrinkage: A tuple containing decimals presenting a percentage of shrinking - -> (width_shrink_percentage, height_shrink_percentage). - e.g. (0.1, 0.2) ~ shrinks the width of border by 10%, shrinks height of - border by 20% + - image: Image on which the border should be drawn. + - xy: Tuple for the top-left corner of the border. + - size: Size of the border as a tuple (width, height). + - radius: Radius of the corners. + - thickness: Thickness of the border in pixels. + - shrinkage: Tuple for width and height shrinkage percentages. + - style: Style of the border ('solid', 'dotted', 'dashed'). """ colour = 'black' - - # size from function paramter width, height = int(size[0] * (1 - shrinkage[0])), int(size[1] * (1 - shrinkage[1])) - - # shift cursor to move rectangle to center offset_x, offset_y = int((size[0] - width) / 2), int((size[1] - height) / 2) x, y, diameter = xy[0] + offset_x, xy[1] + offset_y, radius * 2 - # lenght of rectangle size a, b = (width - diameter), (height - diameter) - # Set coordinates for staright lines p1, p2 = (x + radius, y), (x + radius + a, y) p3, p4 = (x + width, y + radius), (x + width, y + radius + b) p5, p6 = (p2[0], y + height), (p1[0], y + height) p7, p8 = (x, p4[1]), (x, p3[1]) + + draw = ImageDraw.Draw(image) + + # Choose the appropriate line drawing function based on style + if style == 'solid': + line_drawer = draw.line + elif style == 'dotted': + line_drawer = lambda coords, fill, width: draw_dotted_line(draw, coords[0], coords[1], fill, width) + elif style == 'dashed': + line_drawer = lambda coords, fill, width: draw_dashed_line(draw, coords[0], coords[1], fill, width) + else: + raise ValueError(f"Unknown style: {style}") + + # Draw lines according to the chosen style + line_drawer((p1, p2), fill=colour, width=thickness) + line_drawer((p3, p4), fill=colour, width=thickness) + line_drawer((p5, p6), fill=colour, width=thickness) + line_drawer((p7, p8), fill=colour, width=thickness) + if radius != 0: - # Set coordinates for arcs c1, c2 = (x, y), (x + diameter, y + diameter) c3, c4 = ((x + width) - diameter, y), (x + width, y + diameter) c5, c6 = ((x + width) - diameter, (y + height) - diameter), (x + width, y + height) c7, c8 = (x, (y + height) - diameter), (x + diameter, y + height) - # Draw lines and arcs, creating a square with round corners - draw = ImageDraw.Draw(image) - draw.line((p1, p2), fill=colour, width=thickness) - draw.line((p3, p4), fill=colour, width=thickness) - draw.line((p5, p6), fill=colour, width=thickness) - draw.line((p7, p8), fill=colour, width=thickness) - - if radius != 0: draw.arc((c1, c2), 180, 270, fill=colour, width=thickness) draw.arc((c3, c4), 270, 360, fill=colour, width=thickness) draw.arc((c5, c6), 0, 90, fill=colour, width=thickness)