Merge branch 'main' into feature/#311
This commit is contained in:
commit
b409cfe544
@ -232,14 +232,14 @@ which the given font should be scaled to.</p></li>
|
|||||||
|
|
||||||
<dl class="py function">
|
<dl class="py function">
|
||||||
<dt class="sig sig-object py" id="inkycal.custom.functions.draw_border">
|
<dt class="sig sig-object py" id="inkycal.custom.functions.draw_border">
|
||||||
<span class="sig-prename descclassname"><span class="pre">inkycal.custom.functions.</span></span><span class="sig-name descname"><span class="pre">draw_border</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">image</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">xy</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">size</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">radius</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">5</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">thickness</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">1</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">shrinkage</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">(0.1,</span> <span class="pre">0.1)</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#inkycal.custom.functions.draw_border" title="Link to this definition"></a></dt>
|
<span class="sig-prename descclassname"><span class="pre">inkycal.custom.functions.</span></span><span class="sig-name descname"><span class="pre">draw_border</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="pre">image:</span> <span class="pre"><module</span> <span class="pre">'PIL.Image'</span> <span class="pre">from</span> <span class="pre">'/home/runner/work/Inkycal/Inkycal/venv/lib/python3.11/site-packages/PIL/Image.py'>,</span> <span class="pre">xy:</span> <span class="pre">~typing.Tuple[int,</span> <span class="pre">int],</span> <span class="pre">size:</span> <span class="pre">~typing.Tuple[int,</span> <span class="pre">int],</span> <span class="pre">radius:</span> <span class="pre">int</span> <span class="pre">=</span> <span class="pre">5,</span> <span class="pre">thickness:</span> <span class="pre">int</span> <span class="pre">=</span> <span class="pre">1,</span> <span class="pre">shrinkage:</span> <span class="pre">~typing.Tuple[int,</span> <span class="pre">int]</span> <span class="pre">=</span> <span class="pre">(0.1,</span> <span class="pre">0.1)</span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">→</span> <span class="sig-return-typehint"><span class="pre">None</span></span></span><a class="headerlink" href="#inkycal.custom.functions.draw_border" title="Link to this definition"></a></dt>
|
||||||
<dd><p>Draws a border at given coordinates.</p>
|
<dd><p>Draws a border at given coordinates.</p>
|
||||||
<dl class="simple">
|
<dl class="simple">
|
||||||
<dt>Args:</dt><dd><ul class="simple">
|
<dt>Args:</dt><dd><ul class="simple">
|
||||||
<li><p>image: The image on which the border should be drawn (usually im_black or
|
<li><p>image: The image on which the border should be drawn (usually im_black or
|
||||||
im_colour.</p></li>
|
im_colour).</p></li>
|
||||||
<li><p>xy: Tuple representing the top-left corner of the border e.g. (32, 100)
|
<li><p>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.</p></li>
|
where 32 is the x-coordinate and 100 is the y-coordinate.</p></li>
|
||||||
<li><p>size: Size of the border as a tuple -> (width, height).</p></li>
|
<li><p>size: Size of the border as a tuple -> (width, height).</p></li>
|
||||||
<li><p>radius: Radius of the corners, where 0 = plain rectangle, 5 = round corners.</p></li>
|
<li><p>radius: Radius of the corners, where 0 = plain rectangle, 5 = round corners.</p></li>
|
||||||
<li><p>thickness: Thickness of the border in pixels.</p></li>
|
<li><p>thickness: Thickness of the border in pixels.</p></li>
|
||||||
@ -288,14 +288,14 @@ printed fonts of this function:</p>
|
|||||||
<p>The extracted timezone can be used to show the local time instead of UTC. e.g.</p>
|
<p>The extracted timezone can be used to show the local time instead of UTC. e.g.</p>
|
||||||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">arrow</span>
|
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">arrow</span>
|
||||||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">arrow</span><span class="o">.</span><span class="n">now</span><span class="p">())</span> <span class="c1"># returns non-timezone-aware time</span>
|
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">arrow</span><span class="o">.</span><span class="n">now</span><span class="p">())</span> <span class="c1"># returns non-timezone-aware time</span>
|
||||||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">arrow</span><span class="o">.</span><span class="n">now</span><span class="p">(</span><span class="n">tz</span><span class="o">=</span><span class="n">get_system_tz</span><span class="p">())</span> <span class="c1"># prints timezone aware time.</span>
|
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">arrow</span><span class="o">.</span><span class="n">now</span><span class="p">(</span><span class="n">tz</span><span class="o">=</span><span class="n">get_system_tz</span><span class="p">()))</span> <span class="c1"># prints timezone aware time.</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<dl class="py function">
|
<dl class="py function">
|
||||||
<dt class="sig sig-object py" id="inkycal.custom.functions.internet_available">
|
<dt class="sig sig-object py" id="inkycal.custom.functions.internet_available">
|
||||||
<span class="sig-prename descclassname"><span class="pre">inkycal.custom.functions.</span></span><span class="sig-name descname"><span class="pre">internet_available</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#inkycal.custom.functions.internet_available" title="Link to this definition"></a></dt>
|
<span class="sig-prename descclassname"><span class="pre">inkycal.custom.functions.</span></span><span class="sig-name descname"><span class="pre">internet_available</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">→</span> <span class="sig-return-typehint"><span class="pre">bool</span></span></span><a class="headerlink" href="#inkycal.custom.functions.internet_available" title="Link to this definition"></a></dt>
|
||||||
<dd><p>checks if the internet is available.</p>
|
<dd><p>checks if the internet is available.</p>
|
||||||
<p>Attempts to connect to google.com with a timeout of 5 seconds to check
|
<p>Attempts to connect to google.com with a timeout of 5 seconds to check
|
||||||
if the network can be reached.</p>
|
if the network can be reached.</p>
|
||||||
@ -315,7 +315,7 @@ if the network can be reached.</p>
|
|||||||
|
|
||||||
<dl class="py function">
|
<dl class="py function">
|
||||||
<dt class="sig sig-object py" id="inkycal.custom.functions.text_wrap">
|
<dt class="sig sig-object py" id="inkycal.custom.functions.text_wrap">
|
||||||
<span class="sig-prename descclassname"><span class="pre">inkycal.custom.functions.</span></span><span class="sig-name descname"><span class="pre">text_wrap</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">text</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">font</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">max_width</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#inkycal.custom.functions.text_wrap" title="Link to this definition"></a></dt>
|
<span class="sig-prename descclassname"><span class="pre">inkycal.custom.functions.</span></span><span class="sig-name descname"><span class="pre">text_wrap</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">text</span></span><span class="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><span class="pre">str</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">font</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">max_width</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#inkycal.custom.functions.text_wrap" title="Link to this definition"></a></dt>
|
||||||
<dd><p>Splits a very long text into smaller parts</p>
|
<dd><p>Splits a very long text into smaller parts</p>
|
||||||
<p>Splits a long text to smaller lines which can fit in a line with max_width.
|
<p>Splits a long text to smaller lines which can fit in a line with max_width.
|
||||||
Uses a Font object for more accurate calculations.</p>
|
Uses a Font object for more accurate calculations.</p>
|
||||||
@ -334,7 +334,7 @@ splitting the text into the next chunk.</p></li>
|
|||||||
|
|
||||||
<dl class="py function">
|
<dl class="py function">
|
||||||
<dt class="sig sig-object py" id="inkycal.custom.functions.write">
|
<dt class="sig sig-object py" id="inkycal.custom.functions.write">
|
||||||
<span class="sig-prename descclassname"><span class="pre">inkycal.custom.functions.</span></span><span class="sig-name descname"><span class="pre">write</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">image</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">xy</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">box_size</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">text</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">font</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kwargs</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#inkycal.custom.functions.write" title="Link to this definition"></a></dt>
|
<span class="sig-prename descclassname"><span class="pre">inkycal.custom.functions.</span></span><span class="sig-name descname"><span class="pre">write</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="pre">image:</span> <span class="pre"><module</span> <span class="pre">'PIL.Image'</span> <span class="pre">from</span> <span class="pre">'/home/runner/work/Inkycal/Inkycal/venv/lib/python3.11/site-packages/PIL/Image.py'>,</span> <span class="pre">xy:</span> <span class="pre">~typing.Tuple[int,</span> <span class="pre">int],</span> <span class="pre">box_size:</span> <span class="pre">~typing.Tuple[int,</span> <span class="pre">int],</span> <span class="pre">text:</span> <span class="pre">str,</span> <span class="pre">font=None,</span> <span class="pre">**kwargs</span></em><span class="sig-paren">)</span><a class="headerlink" href="#inkycal.custom.functions.write" title="Link to this definition"></a></dt>
|
||||||
<dd><p>Writes text on an image.</p>
|
<dd><p>Writes text on an image.</p>
|
||||||
<p>Writes given text at given position on the specified image.</p>
|
<p>Writes given text at given position on the specified image.</p>
|
||||||
<dl class="simple">
|
<dl class="simple">
|
||||||
|
BIN
fonts/MaterialIcons/MaterialIcons.ttf
Normal file
BIN
fonts/MaterialIcons/MaterialIcons.ttf
Normal file
Binary file not shown.
@ -8,9 +8,9 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
import PIL
|
|
||||||
import requests
|
import requests
|
||||||
import tzlocal
|
import tzlocal
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
@ -73,7 +73,7 @@ def get_system_tz() -> str:
|
|||||||
|
|
||||||
>>> import arrow
|
>>> import arrow
|
||||||
>>> print(arrow.now()) # returns non-timezone-aware time
|
>>> print(arrow.now()) # returns non-timezone-aware time
|
||||||
>>> print(arrow.now(tz=get_system_tz()) # prints timezone aware time.
|
>>> print(arrow.now(tz=get_system_tz())) # prints timezone aware time.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
local_tz = tzlocal.get_localzone().key
|
local_tz = tzlocal.get_localzone().key
|
||||||
@ -111,7 +111,7 @@ def auto_fontsize(font, max_height):
|
|||||||
return font
|
return font
|
||||||
|
|
||||||
|
|
||||||
def write(image, xy, box_size, text, font=None, **kwargs):
|
def write(image: Image, xy: Tuple[int, int], box_size: Tuple[int, int], text: str, font=None, **kwargs):
|
||||||
"""Writes text on an image.
|
"""Writes text on an image.
|
||||||
|
|
||||||
Writes given text at given position on the specified image.
|
Writes given text at given position on the specified image.
|
||||||
@ -161,7 +161,7 @@ def write(image, xy, box_size, text, font=None, **kwargs):
|
|||||||
text_bbox = font.getbbox(text)
|
text_bbox = font.getbbox(text)
|
||||||
text_width = text_bbox[2] - text_bbox[0]
|
text_width = text_bbox[2] - text_bbox[0]
|
||||||
text_bbox_height = font.getbbox("hg")
|
text_bbox_height = font.getbbox("hg")
|
||||||
text_height = text_bbox_height[3] - text_bbox_height[1]
|
text_height = abs(text_bbox_height[3]) # - abs(text_bbox_height[1])
|
||||||
|
|
||||||
while text_width < int(box_width * fill_width) and text_height < int(box_height * fill_height):
|
while text_width < int(box_width * fill_width) and text_height < int(box_height * fill_height):
|
||||||
size += 1
|
size += 1
|
||||||
@ -169,12 +169,12 @@ def write(image, xy, box_size, text, font=None, **kwargs):
|
|||||||
text_bbox = font.getbbox(text)
|
text_bbox = font.getbbox(text)
|
||||||
text_width = text_bbox[2] - text_bbox[0]
|
text_width = text_bbox[2] - text_bbox[0]
|
||||||
text_bbox_height = font.getbbox("hg")
|
text_bbox_height = font.getbbox("hg")
|
||||||
text_height = text_bbox_height[3] - text_bbox_height[1]
|
text_height = abs(text_bbox_height[3]) # - abs(text_bbox_height[1])
|
||||||
|
|
||||||
text_bbox = font.getbbox(text)
|
text_bbox = font.getbbox(text)
|
||||||
text_width = text_bbox[2] - text_bbox[0]
|
text_width = text_bbox[2] - text_bbox[0]
|
||||||
text_bbox_height = font.getbbox("hg")
|
text_bbox_height = font.getbbox("hg")
|
||||||
text_height = text_bbox_height[3] - text_bbox_height[1]
|
text_height = abs(text_bbox_height[3]) # - abs(text_bbox_height[1])
|
||||||
|
|
||||||
# Truncate text if text is too long, so it can fit inside the box
|
# Truncate text if text is too long, so it can fit inside the box
|
||||||
if (text_width, text_height) > (box_width, box_height):
|
if (text_width, text_height) > (box_width, box_height):
|
||||||
@ -184,7 +184,7 @@ def write(image, xy, box_size, text, font=None, **kwargs):
|
|||||||
text_bbox = font.getbbox(text)
|
text_bbox = font.getbbox(text)
|
||||||
text_width = text_bbox[2] - text_bbox[0]
|
text_width = text_bbox[2] - text_bbox[0]
|
||||||
text_bbox_height = font.getbbox("hg")
|
text_bbox_height = font.getbbox("hg")
|
||||||
text_height = text_bbox_height[3] - text_bbox_height[1]
|
text_height = abs(text_bbox_height[3]) # - abs(text_bbox_height[1])
|
||||||
logger.debug(text)
|
logger.debug(text)
|
||||||
|
|
||||||
# Align text to desired position
|
# Align text to desired position
|
||||||
@ -195,10 +195,13 @@ def write(image, xy, box_size, text, font=None, **kwargs):
|
|||||||
elif alignment == "right":
|
elif alignment == "right":
|
||||||
x = int(box_width - text_width)
|
x = int(box_width - text_width)
|
||||||
|
|
||||||
|
# Vertical centering
|
||||||
|
y = int((box_height / 2) - (text_height / 2))
|
||||||
|
|
||||||
# Draw the text in the text-box
|
# Draw the text in the text-box
|
||||||
draw = ImageDraw.Draw(image)
|
draw = ImageDraw.Draw(image)
|
||||||
space = Image.new('RGBA', (box_width, box_height))
|
space = Image.new('RGBA', (box_width, box_height))
|
||||||
ImageDraw.Draw(space).text((x, 0), text, fill=colour, font=font)
|
ImageDraw.Draw(space).text((x, y), text, fill=colour, font=font)
|
||||||
|
|
||||||
# Uncomment following two lines, comment out above two lines to show
|
# Uncomment following two lines, comment out above two lines to show
|
||||||
# red text-box with white text (debugging purposes)
|
# red text-box with white text (debugging purposes)
|
||||||
@ -213,7 +216,7 @@ def write(image, xy, box_size, text, font=None, **kwargs):
|
|||||||
image.paste(space, xy, space)
|
image.paste(space, xy, space)
|
||||||
|
|
||||||
|
|
||||||
def text_wrap(text, font=None, max_width=None):
|
def text_wrap(text: str, font=None, max_width=None):
|
||||||
"""Splits a very long text into smaller parts
|
"""Splits a very long text into smaller parts
|
||||||
|
|
||||||
Splits a long text to smaller lines which can fit in a line with max_width.
|
Splits a long text to smaller lines which can fit in a line with max_width.
|
||||||
@ -249,7 +252,7 @@ def text_wrap(text, font=None, max_width=None):
|
|||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
def internet_available():
|
def internet_available() -> bool:
|
||||||
"""checks if the internet is available.
|
"""checks if the internet is available.
|
||||||
|
|
||||||
Attempts to connect to google.com with a timeout of 5 seconds to check
|
Attempts to connect to google.com with a timeout of 5 seconds to check
|
||||||
@ -274,15 +277,16 @@ def internet_available():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1)):
|
def draw_border(image: Image, xy: Tuple[int, int], size: Tuple[int, int], radius: int = 5, thickness: int = 1,
|
||||||
|
shrinkage: Tuple[int, int] = (0.1, 0.1)) -> None:
|
||||||
"""Draws a border at given coordinates.
|
"""Draws a border at given coordinates.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
- image: The image on which the border should be drawn (usually im_black or
|
- image: The image on which the border should be drawn (usually im_black or
|
||||||
im_colour.
|
im_colour).
|
||||||
|
|
||||||
- xy: Tuple representing the top-left corner of the border e.g. (32, 100)
|
- 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.
|
where 32 is the x-coordinate and 100 is the y-coordinate.
|
||||||
|
|
||||||
- size: Size of the border as a tuple -> (width, height).
|
- size: Size of the border as a tuple -> (width, height).
|
||||||
|
|
||||||
@ -320,6 +324,7 @@ def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1)):
|
|||||||
c5, c6 = ((x + width) - diameter, (y + height) - diameter), (x + width, y + height)
|
c5, c6 = ((x + width) - diameter, (y + height) - diameter), (x + width, y + height)
|
||||||
c7, c8 = (x, (y + height) - diameter), (x + diameter, y + height)
|
c7, c8 = (x, (y + height) - diameter), (x + diameter, y + height)
|
||||||
|
|
||||||
|
|
||||||
# Draw lines and arcs, creating a square with round corners
|
# Draw lines and arcs, creating a square with round corners
|
||||||
draw = ImageDraw.Draw(image)
|
draw = ImageDraw.Draw(image)
|
||||||
draw.line((p1, p2), fill=colour, width=thickness)
|
draw.line((p1, p2), fill=colour, width=thickness)
|
||||||
@ -334,7 +339,7 @@ def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1)):
|
|||||||
draw.arc((c7, c8), 90, 180, fill=colour, width=thickness)
|
draw.arc((c7, c8), 90, 180, fill=colour, width=thickness)
|
||||||
|
|
||||||
|
|
||||||
def draw_border_2(im: PIL.Image, xy: tuple, size: tuple, radius: int):
|
def draw_border_2(im: Image, xy: Tuple[int, int], size: Tuple[int, int], radius: int):
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
x, y = xy
|
x, y = xy
|
||||||
|
@ -41,18 +41,9 @@ def get_json_from_url(request_url):
|
|||||||
|
|
||||||
|
|
||||||
class OpenWeatherMap:
|
class OpenWeatherMap:
|
||||||
def __init__(
|
def __init__(self, api_key: str, city_id: int = None, lat: float = None, lon: float = None,
|
||||||
self,
|
api_version: API_VERSIONS = "2.5", temp_unit: TEMP_UNITS = "celsius",
|
||||||
api_key: str,
|
wind_unit: WIND_UNITS = "meters_sec", language: str = "en", tz_name: str = "UTC") -> None:
|
||||||
city_id: int = None,
|
|
||||||
lat: float = None,
|
|
||||||
lon: float = None,
|
|
||||||
api_version: API_VERSIONS = "2.5",
|
|
||||||
temp_unit: TEMP_UNITS = "celsius",
|
|
||||||
wind_unit: WIND_UNITS = "meters_sec",
|
|
||||||
language: str = "en",
|
|
||||||
tz_name: str = "UTC",
|
|
||||||
) -> None:
|
|
||||||
self.api_key = api_key
|
self.api_key = api_key
|
||||||
self.temp_unit = temp_unit
|
self.temp_unit = temp_unit
|
||||||
self.wind_unit = wind_unit
|
self.wind_unit = wind_unit
|
||||||
@ -187,7 +178,7 @@ class OpenWeatherMap:
|
|||||||
:return:
|
:return:
|
||||||
Forecast dictionary
|
Forecast dictionary
|
||||||
"""
|
"""
|
||||||
# Make sure hourly forecasts are up to date
|
# Make sure hourly forecasts are up-to-date
|
||||||
_ = self.get_weather_forecast()
|
_ = self.get_weather_forecast()
|
||||||
|
|
||||||
# Calculate the start and end times for the specified number of days from now
|
# Calculate the start and end times for the specified number of days from now
|
||||||
@ -207,7 +198,7 @@ class OpenWeatherMap:
|
|||||||
]
|
]
|
||||||
|
|
||||||
# In case the next available forecast is already for the next day, use that one for the less than 3 remaining hours of today
|
# In case the next available forecast is already for the next day, use that one for the less than 3 remaining hours of today
|
||||||
if forecasts == []:
|
if not forecasts:
|
||||||
forecasts.append(self.hourly_forecasts[0])
|
forecasts.append(self.hourly_forecasts[0])
|
||||||
|
|
||||||
# Get rain and temperatures for that day
|
# Get rain and temperatures for that day
|
||||||
|
@ -75,6 +75,8 @@ class Agenda(inkycal_module):
|
|||||||
# Additional config
|
# Additional config
|
||||||
self.timezone = get_system_tz()
|
self.timezone = get_system_tz()
|
||||||
|
|
||||||
|
self.icon_font = ImageFont.truetype(fonts['MaterialIcons'], size=self.fontsize)
|
||||||
|
|
||||||
# give an OK message
|
# give an OK message
|
||||||
logger.debug(f'{__name__} loaded')
|
logger.debug(f'{__name__} loaded')
|
||||||
|
|
||||||
@ -201,10 +203,10 @@ class Agenda(inkycal_module):
|
|||||||
write(im_black, (x_time, line_pos[cursor][1]),
|
write(im_black, (x_time, line_pos[cursor][1]),
|
||||||
(time_width, line_height), time,
|
(time_width, line_height), time,
|
||||||
font=self.font, alignment='right')
|
font=self.font, alignment='right')
|
||||||
if parser.all_day(_):
|
else:
|
||||||
write(im_black, (x_time, line_pos[cursor][1]),
|
write(im_black, (x_time, line_pos[cursor][1]),
|
||||||
(time_width, line_height), "all day",
|
(time_width, line_height), "\ue878",
|
||||||
font=self.font, alignment='right')
|
font=self.icon_font, alignment='right')
|
||||||
|
|
||||||
write(im_black, (x_event, line_pos[cursor][1]),
|
write(im_black, (x_event, line_pos[cursor][1]),
|
||||||
(event_width, line_height),
|
(event_width, line_height),
|
||||||
|
@ -6,16 +6,16 @@ Copyright by aceinnolab
|
|||||||
# pylint: disable=logging-fstring-interpolation
|
# pylint: disable=logging-fstring-interpolation
|
||||||
|
|
||||||
import calendar as cal
|
import calendar as cal
|
||||||
import arrow
|
|
||||||
from inkycal.modules.template import inkycal_module
|
|
||||||
from inkycal.custom import *
|
from inkycal.custom import *
|
||||||
|
from inkycal.modules.template import inkycal_module
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Calendar(inkycal_module):
|
class Calendar(inkycal_module):
|
||||||
"""Calendar class
|
"""Calendar class
|
||||||
Create monthly calendar and show events from given icalendars
|
Create monthly calendar and show events from given iCalendars
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = "Calendar - Show monthly calendar with events from iCalendars"
|
name = "Calendar - Show monthly calendar with events from iCalendars"
|
||||||
@ -61,7 +61,7 @@ class Calendar(inkycal_module):
|
|||||||
self._days_with_events = None
|
self._days_with_events = None
|
||||||
|
|
||||||
# optional parameters
|
# optional parameters
|
||||||
self.weekstart = config['week_starts_on']
|
self.week_start = config['week_starts_on']
|
||||||
self.show_events = config['show_events']
|
self.show_events = config['show_events']
|
||||||
self.date_format = config["date_format"]
|
self.date_format = config["date_format"]
|
||||||
self.time_format = config['time_format']
|
self.time_format = config['time_format']
|
||||||
@ -109,7 +109,7 @@ class Calendar(inkycal_module):
|
|||||||
# Allocate space for month-names, weekdays etc.
|
# Allocate space for month-names, weekdays etc.
|
||||||
month_name_height = int(im_height * 0.10)
|
month_name_height = int(im_height * 0.10)
|
||||||
text_bbox_height = self.font.getbbox("hg")
|
text_bbox_height = self.font.getbbox("hg")
|
||||||
weekdays_height = int((text_bbox_height[3] - text_bbox_height[1]) * 1.25)
|
weekdays_height = int((abs(text_bbox_height[3]) + abs(text_bbox_height[1])) * 1.25)
|
||||||
logger.debug(f"month_name_height: {month_name_height}")
|
logger.debug(f"month_name_height: {month_name_height}")
|
||||||
logger.debug(f"weekdays_height: {weekdays_height}")
|
logger.debug(f"weekdays_height: {weekdays_height}")
|
||||||
|
|
||||||
@ -156,13 +156,13 @@ class Calendar(inkycal_module):
|
|||||||
|
|
||||||
now = arrow.now(tz=self.timezone)
|
now = arrow.now(tz=self.timezone)
|
||||||
|
|
||||||
# Set weekstart of calendar to specified weekstart
|
# Set week-start of calendar to specified week-start
|
||||||
if self.weekstart == "Monday":
|
if self.week_start == "Monday":
|
||||||
cal.setfirstweekday(cal.MONDAY)
|
cal.setfirstweekday(cal.MONDAY)
|
||||||
weekstart = now.shift(days=-now.weekday())
|
week_start = now.shift(days=-now.weekday())
|
||||||
else:
|
else:
|
||||||
cal.setfirstweekday(cal.SUNDAY)
|
cal.setfirstweekday(cal.SUNDAY)
|
||||||
weekstart = now.shift(days=-now.isoweekday())
|
week_start = now.shift(days=-now.isoweekday())
|
||||||
|
|
||||||
# Write the name of current month
|
# Write the name of current month
|
||||||
write(
|
write(
|
||||||
@ -174,9 +174,9 @@ class Calendar(inkycal_module):
|
|||||||
autofit=True,
|
autofit=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set up weeknames in local language and add to main section
|
# Set up week-names in local language and add to main section
|
||||||
weekday_names = [
|
weekday_names = [
|
||||||
weekstart.shift(days=+_).format('ddd', locale=self.language)
|
week_start.shift(days=+_).format('ddd', locale=self.language)
|
||||||
for _ in range(7)
|
for _ in range(7)
|
||||||
]
|
]
|
||||||
logger.debug(f'weekday names: {weekday_names}')
|
logger.debug(f'weekday names: {weekday_names}')
|
||||||
@ -192,7 +192,7 @@ class Calendar(inkycal_module):
|
|||||||
fill_height=0.9,
|
fill_height=0.9,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create a calendar template and flatten (remove nestings)
|
# Create a calendar template and flatten (remove nesting)
|
||||||
calendar_flat = self.flatten(cal.monthcalendar(now.year, now.month))
|
calendar_flat = self.flatten(cal.monthcalendar(now.year, now.month))
|
||||||
# logger.debug(f" calendar_flat: {calendar_flat}")
|
# logger.debug(f" calendar_flat: {calendar_flat}")
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ class Calendar(inkycal_module):
|
|||||||
month_start = arrow.get(now.floor('month'))
|
month_start = arrow.get(now.floor('month'))
|
||||||
month_end = arrow.get(now.ceil('month'))
|
month_end = arrow.get(now.ceil('month'))
|
||||||
|
|
||||||
# fetch events from given icalendars
|
# fetch events from given iCalendars
|
||||||
self.ical = iCalendar()
|
self.ical = iCalendar()
|
||||||
parser = self.ical
|
parser = self.ical
|
||||||
|
|
||||||
@ -300,8 +300,6 @@ class Calendar(inkycal_module):
|
|||||||
|
|
||||||
# Handle multi-day events by adding all days between start and end
|
# Handle multi-day events by adding all days between start and end
|
||||||
for event in month_events:
|
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
|
# Convert start and end dates to arrow objects with timezone
|
||||||
start = arrow.get(event['begin'].date(), tzinfo=self.timezone)
|
start = arrow.get(event['begin'].date(), tzinfo=self.timezone)
|
||||||
@ -324,9 +322,7 @@ class Calendar(inkycal_module):
|
|||||||
im_colour,
|
im_colour,
|
||||||
grid[days],
|
grid[days],
|
||||||
(icon_width, icon_height),
|
(icon_width, icon_height),
|
||||||
radius=6,
|
radius=6
|
||||||
thickness=1,
|
|
||||||
shrinkage=(0, 0),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Filter upcoming events until 4 weeks in the future
|
# Filter upcoming events until 4 weeks in the future
|
||||||
@ -369,7 +365,8 @@ class Calendar(inkycal_module):
|
|||||||
event_duration = (event['end'] - event['begin']).days
|
event_duration = (event['end'] - event['begin']).days
|
||||||
if event_duration > 1:
|
if event_duration > 1:
|
||||||
# Format the duration using Arrow's localization
|
# Format the duration using Arrow's localization
|
||||||
days_translation = arrow.get().shift(days=event_duration).humanize(only_distance=True, locale=lang)
|
days_translation = arrow.get().shift(days=event_duration).humanize(only_distance=True,
|
||||||
|
locale=lang)
|
||||||
the_name = f"{event['title']} ({days_translation})"
|
the_name = f"{event['title']} ({days_translation})"
|
||||||
else:
|
else:
|
||||||
the_name = event['title']
|
the_name = event['title']
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
Inkycal weather module
|
Inkycal weather module
|
||||||
Copyright by aceinnolab
|
Copyright by aceinnolab
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import arrow
|
|
||||||
import decimal
|
import decimal
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
import arrow
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from PIL import ImageDraw
|
from PIL import ImageDraw
|
||||||
from PIL import ImageFont
|
from PIL import ImageFont
|
||||||
@ -51,7 +51,7 @@ class Weather(inkycal_module):
|
|||||||
"options": [True, False],
|
"options": [True, False],
|
||||||
},
|
},
|
||||||
|
|
||||||
"round_windspeed": {
|
"round_wind_speed": {
|
||||||
"label": "Round windspeed?",
|
"label": "Round windspeed?",
|
||||||
"options": [True, False],
|
"options": [True, False],
|
||||||
},
|
},
|
||||||
@ -89,7 +89,7 @@ class Weather(inkycal_module):
|
|||||||
|
|
||||||
# Check if all required parameters are present
|
# Check if all required parameters are present
|
||||||
for param in self.requires:
|
for param in self.requires:
|
||||||
if not param in config:
|
if param not in config:
|
||||||
raise Exception(f'config is missing {param}')
|
raise Exception(f'config is missing {param}')
|
||||||
|
|
||||||
# required parameters
|
# required parameters
|
||||||
@ -98,7 +98,7 @@ class Weather(inkycal_module):
|
|||||||
|
|
||||||
# optional parameters
|
# optional parameters
|
||||||
self.round_temperature = config['round_temperature']
|
self.round_temperature = config['round_temperature']
|
||||||
self.round_windspeed = config['round_windspeed']
|
self.round_wind_speed = config['round_windspeed']
|
||||||
self.forecast_interval = config['forecast_interval']
|
self.forecast_interval = config['forecast_interval']
|
||||||
self.hour_format = int(config['hour_format'])
|
self.hour_format = int(config['hour_format'])
|
||||||
if config['units'] == "imperial":
|
if config['units'] == "imperial":
|
||||||
@ -106,7 +106,7 @@ class Weather(inkycal_module):
|
|||||||
else:
|
else:
|
||||||
self.temp_unit = "celsius"
|
self.temp_unit = "celsius"
|
||||||
|
|
||||||
if config['use_beaufort'] == True:
|
if config['use_beaufort']:
|
||||||
self.wind_unit = "beaufort"
|
self.wind_unit = "beaufort"
|
||||||
elif config['units'] == "imperial":
|
elif config['units'] == "imperial":
|
||||||
self.wind_unit = "miles_hour"
|
self.wind_unit = "miles_hour"
|
||||||
@ -145,8 +145,6 @@ class Weather(inkycal_module):
|
|||||||
# give an OK message
|
# give an OK message
|
||||||
logger.debug(f"{__name__} loaded")
|
logger.debug(f"{__name__} loaded")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def generate_image(self):
|
def generate_image(self):
|
||||||
"""Generate image for this module"""
|
"""Generate image for this module"""
|
||||||
|
|
||||||
@ -224,12 +222,19 @@ class Weather(inkycal_module):
|
|||||||
'50n': '\uf023'
|
'50n': '\uf023'
|
||||||
}
|
}
|
||||||
|
|
||||||
def draw_icon(image, xy, box_size, icon, rotation=None):
|
def draw_icon(image: Image, xy: Tuple[int, int], box_size: Tuple[int, int], icon: str, rotation=None):
|
||||||
"""Custom function to add icons of weather font on image
|
"""Custom function to add icons of weather font on the image.
|
||||||
image = on which image should the text be added?
|
|
||||||
xy = xy-coordinates as tuple -> (x,y)
|
Args:
|
||||||
box_size = size of text-box -> (width,height)
|
- image:
|
||||||
icon = icon-unicode, looks this up in weathericons dictionary
|
the image on which image should the text be added
|
||||||
|
- xy:
|
||||||
|
coordinates as tuple -> (x,y)
|
||||||
|
- box_size:
|
||||||
|
size of text-box -> (width,height)
|
||||||
|
- icon:
|
||||||
|
icon-unicode, looks this up in weather-icons dictionary
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
icon_size_correction = {
|
icon_size_correction = {
|
||||||
@ -264,7 +269,6 @@ class Weather(inkycal_module):
|
|||||||
'\uf0a0': 0,
|
'\uf0a0': 0,
|
||||||
'\uf0a3': 0,
|
'\uf0a3': 0,
|
||||||
'\uf0a7': 0,
|
'\uf0a7': 0,
|
||||||
'\uf0aa': 0,
|
|
||||||
'\uf0ae': 0
|
'\uf0ae': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,8 +282,7 @@ class Weather(inkycal_module):
|
|||||||
font = ImageFont.truetype(font.path, size)
|
font = ImageFont.truetype(font.path, size)
|
||||||
text_width, text_height = font.getbbox(text)[2:]
|
text_width, text_height = font.getbbox(text)[2:]
|
||||||
|
|
||||||
while (text_width < int(box_width * 0.9) and
|
while text_width < int(box_width * 0.9) and text_height < int(box_height * 0.9):
|
||||||
text_height < int(box_height * 0.9)):
|
|
||||||
size += 1
|
size += 1
|
||||||
font = ImageFont.truetype(font.path, size)
|
font = ImageFont.truetype(font.path, size)
|
||||||
text_width, text_height = font.getbbox(text)[2:]
|
text_width, text_height = font.getbbox(text)[2:]
|
||||||
@ -290,8 +293,6 @@ class Weather(inkycal_module):
|
|||||||
x = int((box_width / 2) - (text_width / 2))
|
x = int((box_width / 2) - (text_width / 2))
|
||||||
y = int((box_height / 2) - (text_height / 2))
|
y = int((box_height / 2) - (text_height / 2))
|
||||||
|
|
||||||
# Draw the text in the text-box
|
|
||||||
draw = ImageDraw.Draw(image)
|
|
||||||
space = Image.new('RGBA', (box_width, box_height))
|
space = Image.new('RGBA', (box_width, box_height))
|
||||||
ImageDraw.Draw(space).text((x, y), text, fill='black', font=font)
|
ImageDraw.Draw(space).text((x, y), text, fill='black', font=font)
|
||||||
|
|
||||||
@ -350,17 +351,17 @@ class Weather(inkycal_module):
|
|||||||
row3 = row2 + line_gap + row_height
|
row3 = row2 + line_gap + row_height
|
||||||
|
|
||||||
# Draw lines on each row and border
|
# Draw lines on each row and border
|
||||||
############################################################################
|
###########################################################################
|
||||||
## draw = ImageDraw.Draw(im_black)
|
# draw = ImageDraw.Draw(im_black)
|
||||||
## draw.line((0, 0, im_width, 0), fill='red')
|
# draw.line((0, 0, im_width, 0), fill='red')
|
||||||
## draw.line((0, im_height-1, im_width, im_height-1), fill='red')
|
# draw.line((0, im_height-1, im_width, im_height-1), fill='red')
|
||||||
## draw.line((0, row1, im_width, row1), fill='black')
|
# draw.line((0, row1, im_width, row1), fill='black')
|
||||||
## draw.line((0, row1+row_height, im_width, row1+row_height), fill='black')
|
# draw.line((0, row1+row_height, im_width, row1+row_height), fill='black')
|
||||||
## draw.line((0, row2, im_width, row2), fill='black')
|
# draw.line((0, row2, im_width, row2), fill='black')
|
||||||
## draw.line((0, row2+row_height, im_width, row2+row_height), fill='black')
|
# draw.line((0, row2+row_height, im_width, row2+row_height), fill='black')
|
||||||
## draw.line((0, row3, im_width, row3), fill='black')
|
# draw.line((0, row3, im_width, row3), fill='black')
|
||||||
## draw.line((0, row3+row_height, im_width, row3+row_height), fill='black')
|
# draw.line((0, row3+row_height, im_width, row3+row_height), fill='black')
|
||||||
############################################################################
|
###########################################################################
|
||||||
|
|
||||||
# Positions for current weather details
|
# Positions for current weather details
|
||||||
weather_icon_pos = (col1, 0)
|
weather_icon_pos = (col1, 0)
|
||||||
@ -379,24 +380,24 @@ class Weather(inkycal_module):
|
|||||||
sunset_time_pos = (col3 + icon_small, row3)
|
sunset_time_pos = (col3 + icon_small, row3)
|
||||||
|
|
||||||
# Positions for forecast 1
|
# Positions for forecast 1
|
||||||
stamp_fc1 = (col4, row1)
|
stamp_fc1 = (col4, row1) # noqa
|
||||||
icon_fc1 = (col4, row1 + row_height)
|
icon_fc1 = (col4, row1 + row_height) # noqa
|
||||||
temp_fc1 = (col4, row3)
|
temp_fc1 = (col4, row3) # noqa
|
||||||
|
|
||||||
# Positions for forecast 2
|
# Positions for forecast 2
|
||||||
stamp_fc2 = (col5, row1)
|
stamp_fc2 = (col5, row1) # noqa
|
||||||
icon_fc2 = (col5, row1 + row_height)
|
icon_fc2 = (col5, row1 + row_height) # noqa
|
||||||
temp_fc2 = (col5, row3)
|
temp_fc2 = (col5, row3) # noqa
|
||||||
|
|
||||||
# Positions for forecast 3
|
# Positions for forecast 3
|
||||||
stamp_fc3 = (col6, row1)
|
stamp_fc3 = (col6, row1) # noqa
|
||||||
icon_fc3 = (col6, row1 + row_height)
|
icon_fc3 = (col6, row1 + row_height) # noqa
|
||||||
temp_fc3 = (col6, row3)
|
temp_fc3 = (col6, row3) # noqa
|
||||||
|
|
||||||
# Positions for forecast 4
|
# Positions for forecast 4
|
||||||
stamp_fc4 = (col7, row1)
|
stamp_fc4 = (col7, row1) # noqa
|
||||||
icon_fc4 = (col7, row1 + row_height)
|
icon_fc4 = (col7, row1 + row_height) # noqa
|
||||||
temp_fc4 = (col7, row3)
|
temp_fc4 = (col7, row3) # noqa
|
||||||
|
|
||||||
# Create current-weather and weather-forecast objects
|
# Create current-weather and weather-forecast objects
|
||||||
logging.debug('looking up location by ID')
|
logging.debug('looking up location by ID')
|
||||||
@ -405,7 +406,7 @@ class Weather(inkycal_module):
|
|||||||
|
|
||||||
# Set decimals
|
# Set decimals
|
||||||
dec_temp = 0 if self.round_temperature == True else 1
|
dec_temp = 0 if self.round_temperature == True else 1
|
||||||
dec_wind = 0 if self.round_windspeed == True else 1
|
dec_wind = 0 if self.round_wind_speed == True else 1
|
||||||
|
|
||||||
logging.debug(f'temperature unit: {self.temp_unit}')
|
logging.debug(f'temperature unit: {self.temp_unit}')
|
||||||
logging.debug(f'decimals temperature: {dec_temp} | decimals wind: {dec_wind}')
|
logging.debug(f'decimals temperature: {dec_temp} | decimals wind: {dec_wind}')
|
||||||
@ -425,7 +426,8 @@ class Weather(inkycal_module):
|
|||||||
fc_data['fc' + str(index + 1)] = {
|
fc_data['fc' + str(index + 1)] = {
|
||||||
'temp': f"{forecast['temp']:.{dec_temp}f}{self.tempDispUnit}",
|
'temp': f"{forecast['temp']:.{dec_temp}f}{self.tempDispUnit}",
|
||||||
'icon': forecast["icon"],
|
'icon': forecast["icon"],
|
||||||
'stamp': forecast["datetime"].strftime("%I %p" if self.hour_format == 12 else "%H:%M")}
|
'stamp': forecast["datetime"].strftime("%I %p" if self.hour_format == 12 else "%H:%M")
|
||||||
|
}
|
||||||
|
|
||||||
elif self.forecast_interval == 'daily':
|
elif self.forecast_interval == 'daily':
|
||||||
|
|
||||||
@ -514,6 +516,9 @@ class Weather(inkycal_module):
|
|||||||
# Add the forecast data to the correct places
|
# Add the forecast data to the correct places
|
||||||
for pos in range(1, len(fc_data) + 1):
|
for pos in range(1, len(fc_data) + 1):
|
||||||
stamp = fc_data[f'fc{pos}']['stamp']
|
stamp = fc_data[f'fc{pos}']['stamp']
|
||||||
|
# check if we're using daily forecasts
|
||||||
|
if "day" in stamp:
|
||||||
|
stamp = arrow.get(fc_data[f'fc{pos}']['stamp'], "dddd").format("dddd", locale="de")
|
||||||
|
|
||||||
icon = weather_icons[fc_data[f'fc{pos}']['icon']]
|
icon = weather_icons[fc_data[f'fc{pos}']['icon']]
|
||||||
temp = fc_data[f'fc{pos}']['temp']
|
temp = fc_data[f'fc{pos}']['temp']
|
||||||
|
@ -41,7 +41,10 @@ class Webshot(inkycal_module):
|
|||||||
},
|
},
|
||||||
"crop_h": {
|
"crop_h": {
|
||||||
"label": "Please enter the crop height",
|
"label": "Please enter the crop height",
|
||||||
}
|
},
|
||||||
|
"rotation": {
|
||||||
|
"label": "Please enter the rotation. Must be either 0, 90, 180 or 270",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
@ -73,6 +76,12 @@ class Webshot(inkycal_module):
|
|||||||
else:
|
else:
|
||||||
self.crop_y = 0
|
self.crop_y = 0
|
||||||
|
|
||||||
|
self.rotation = 0
|
||||||
|
if "rotation" in config:
|
||||||
|
self.rotation = int(config["rotation"])
|
||||||
|
if self.rotation not in [0, 90, 180, 270]:
|
||||||
|
raise Exception("Rotation must be either 0, 90, 180 or 270")
|
||||||
|
|
||||||
# give an OK message
|
# give an OK message
|
||||||
logger.debug(f'Inkycal webshot loaded')
|
logger.debug(f'Inkycal webshot loaded')
|
||||||
|
|
||||||
@ -106,7 +115,7 @@ class Webshot(inkycal_module):
|
|||||||
logger.info(
|
logger.info(
|
||||||
f'preparing webshot from {self.url}... cropH{self.crop_h} cropW{self.crop_w} cropX{self.crop_x} cropY{self.crop_y}')
|
f'preparing webshot from {self.url}... cropH{self.crop_h} cropW{self.crop_w} cropX{self.crop_x} cropY{self.crop_y}')
|
||||||
|
|
||||||
shot = WebShot()
|
shot = WebShot(size=(im_height, im_width))
|
||||||
|
|
||||||
shot.params = {
|
shot.params = {
|
||||||
"--crop-x": self.crop_x,
|
"--crop-x": self.crop_x,
|
||||||
@ -152,6 +161,16 @@ class Webshot(inkycal_module):
|
|||||||
|
|
||||||
centerPosX = int((im_width / 2) - (im.image.width / 2))
|
centerPosX = int((im_width / 2) - (im.image.width / 2))
|
||||||
|
|
||||||
|
|
||||||
|
if self.rotation != 0:
|
||||||
|
webshotSpaceBlack.paste(im_webshot_black, (centerPosX, webshotCenterPosY))
|
||||||
|
im_black.paste(webshotSpaceBlack)
|
||||||
|
im_black = im_black.rotate(self.rotation, expand=True)
|
||||||
|
|
||||||
|
webshotSpaceColour.paste(im_webshot_colour, (centerPosX, webshotCenterPosY))
|
||||||
|
im_colour.paste(webshotSpaceColour)
|
||||||
|
im_colour = im_colour.rotate(self.rotation, expand=True)
|
||||||
|
else:
|
||||||
webshotSpaceBlack.paste(im_webshot_black, (centerPosX, webshotCenterPosY))
|
webshotSpaceBlack.paste(im_webshot_black, (centerPosX, webshotCenterPosY))
|
||||||
im_black.paste(webshotSpaceBlack)
|
im_black.paste(webshotSpaceBlack)
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ python-dotenv==1.0.1
|
|||||||
pytz==2024.1
|
pytz==2024.1
|
||||||
PyYAML==6.0.1
|
PyYAML==6.0.1
|
||||||
recurring-ical-events==2.1.2
|
recurring-ical-events==2.1.2
|
||||||
requests==2.31.0
|
requests==2.32.0
|
||||||
sgmllib3k==1.0.0
|
sgmllib3k==1.0.0
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
soupsieve==2.5
|
soupsieve==2.5
|
||||||
@ -46,7 +46,7 @@ types-python-dateutil==2.8.19.20240106
|
|||||||
typing_extensions==4.9.0
|
typing_extensions==4.9.0
|
||||||
tzdata==2024.1
|
tzdata==2024.1
|
||||||
tzlocal==5.2
|
tzlocal==5.2
|
||||||
urllib3==2.2.0
|
urllib3==2.2.2
|
||||||
virtualenv==20.25.0
|
virtualenv==20.25.0
|
||||||
webencodings==0.5.1
|
webencodings==0.5.1
|
||||||
x-wr-timezone==0.0.6
|
x-wr-timezone==0.0.6
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
"""
|
"""
|
||||||
Test the functions in the functions module.
|
Test the functions in the functions module.
|
||||||
"""
|
"""
|
||||||
|
import unittest
|
||||||
|
|
||||||
from PIL import Image, ImageFont
|
from PIL import Image, ImageFont
|
||||||
from inkycal.custom import write, fonts
|
|
||||||
|
from inkycal.custom import write, fonts, get_system_tz
|
||||||
|
|
||||||
|
|
||||||
def test_write():
|
class TestIcalendar(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_write(self):
|
||||||
im = Image.new("RGB", (500, 200), "white")
|
im = Image.new("RGB", (500, 200), "white")
|
||||||
font = ImageFont.truetype(fonts['NotoSans-SemiCondensed'], size=40)
|
font = ImageFont.truetype(fonts['NotoSans-SemiCondensed'], size=40)
|
||||||
write(im, (125, 75), (250, 50), "Hello World", font)
|
write(im, (125, 75), (250, 50), "Hello World", font)
|
||||||
# im.show()
|
# im.show()
|
||||||
|
|
||||||
|
def test_get_system_tz(self):
|
||||||
|
tz = get_system_tz()
|
||||||
|
assert isinstance(tz, str)
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ tests = [
|
|||||||
"size": [500, 800],
|
"size": [500, 800],
|
||||||
"ical_urls": sample_url,
|
"ical_urls": sample_url,
|
||||||
"ical_files": None,
|
"ical_files": None,
|
||||||
"date_format": "ddd D MMM",
|
"date_format": "DD.MMMM YYYY",
|
||||||
"time_format": "HH:mm",
|
"time_format": "HH:mm",
|
||||||
"padding_x": 10,
|
"padding_x": 10,
|
||||||
"padding_y": 10,
|
"padding_y": 10,
|
||||||
|
@ -20,7 +20,7 @@ tests = [
|
|||||||
{
|
{
|
||||||
"name": "Calendar",
|
"name": "Calendar",
|
||||||
"config": {
|
"config": {
|
||||||
"size": [500, 500],
|
"size": [500, 600],
|
||||||
"week_starts_on": "Monday",
|
"week_starts_on": "Monday",
|
||||||
"show_events": True,
|
"show_events": True,
|
||||||
"ical_urls": sample_url,
|
"ical_urls": sample_url,
|
||||||
|
@ -34,7 +34,7 @@ tests = [
|
|||||||
"padding_x": 10,
|
"padding_x": 10,
|
||||||
"padding_y": 10,
|
"padding_y": 10,
|
||||||
"fontsize": 12,
|
"fontsize": 12,
|
||||||
"language": "en"
|
"language": "de"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -16,33 +16,13 @@ preview = Inkyimage.preview
|
|||||||
merge = Inkyimage.merge
|
merge = Inkyimage.merge
|
||||||
|
|
||||||
tests = [
|
tests = [
|
||||||
{
|
|
||||||
"position": 1,
|
|
||||||
"name": "Webshot",
|
|
||||||
"config": {
|
|
||||||
"size": [400, 100],
|
|
||||||
"url": "https://github.com",
|
|
||||||
"palette": "bwr",
|
|
||||||
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"position": 1,
|
"position": 1,
|
||||||
"name": "Webshot",
|
"name": "Webshot",
|
||||||
"config": {
|
"config": {
|
||||||
"size": [400, 200],
|
"size": [400, 200],
|
||||||
"url": "https://github.com",
|
"url": "https://aceinnolab.com",
|
||||||
"palette": "bwy",
|
"palette": "bwr",
|
||||||
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"position": 1,
|
|
||||||
"name": "Webshot",
|
|
||||||
"config": {
|
|
||||||
"size": [400, 300],
|
|
||||||
"url": "https://github.com",
|
|
||||||
"palette": "bw",
|
|
||||||
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
|
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -51,8 +31,31 @@ tests = [
|
|||||||
"name": "Webshot",
|
"name": "Webshot",
|
||||||
"config": {
|
"config": {
|
||||||
"size": [400, 400],
|
"size": [400, 400],
|
||||||
"url": "https://github.com",
|
"url": "https://aceinnolab.com",
|
||||||
|
"palette": "bwy",
|
||||||
|
"rotation": 0,
|
||||||
|
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": 1,
|
||||||
|
"name": "Webshot",
|
||||||
|
"config": {
|
||||||
|
"size": [400, 600],
|
||||||
|
"url": "https://aceinnolab.com",
|
||||||
|
"palette": "bw",
|
||||||
|
"rotation": 90,
|
||||||
|
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": 1,
|
||||||
|
"name": "Webshot",
|
||||||
|
"config": {
|
||||||
|
"size": [400, 800],
|
||||||
|
"url": "https://aceinnolab.com",
|
||||||
"palette": "bwr",
|
"palette": "bwr",
|
||||||
|
"rotation": 180,
|
||||||
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
|
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user