Files
desktop-display/building.py

175 lines
4.8 KiB
Python

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from datetime import datetime, timedelta
from time import gmtime, strftime
import time
from itertools import groupby
from hasApi import get_calendar_events, get_todo_items
import dateutil.parser
from dotenv import load_dotenv
black = "#000000"
white = "#ffffff"
fontSymbols = ImageFont.truetype("SymbolsNerdFont-Regular.ttf", 18)
fontTitle = ImageFont.truetype("Nunito-Bold.ttf", 24)
fontLarge = ImageFont.truetype("Nunito-ExtraLight.ttf", 18)
fontLargeBold = ImageFont.truetype("Nunito-SemiBold.ttf", 18)
fontSmall = ImageFont.truetype("Nunito-ExtraLight.ttf", 16)
fontVerySmall = ImageFont.truetype("Nunito-ExtraLight.ttf", 10)
class Space(Exception):
pass
def getsize(font, text):
_, _, right, bottom = font.getbbox(text)
return (right, bottom)
def reflow_quote(quote, width, font):
words = quote.split(" ")
reflowed = ""
line_length = 0
for i in range(len(words)):
word = words[i] + " "
word_length = getsize(font, word)[0]
line_length += word_length
if line_length < width:
reflowed += word
else:
line_length = word_length
reflowed = reflowed[:-1] + "\n " + word
reflowed = reflowed.rstrip()
return reflowed
def draw_image():
image = Image.new("P", (400, 300))
draw = ImageDraw.Draw(image)
# Draw the top bar
topbar = 26
draw.rectangle((0, 0, 400, 300), fill=white)
draw.rectangle((0, 0, 400, topbar), fill=black)
# Add the clock
timeStr = strftime("%H:%M", time.localtime())
draw.text((10, 3), timeStr, white, fontSmall)
# Add indoor temperature
draw.text((350, 3), "19c", white, fontSmall)
# Add sections
ep = 3
margin = 5
draw.rounded_rectangle(
(margin, topbar + margin, (400 / 2) - margin, 300 - margin),
10,
outline=black,
width=2,
)
draw.rounded_rectangle(
((400 / 2) + margin, topbar + margin, 400 - margin, 300 - margin),
10,
outline=black,
width=2,
)
# Add tasks
draw.text((20, topbar + 7), "Tasks", black, fontTitle)
draw.line((margin, 62, 200 - margin, 62), fill=black, width=1)
tasks = get_todo_items()
taskStart = 70
for task in tasks:
if task["status"] == "completed":
continue
draw.text((15, taskStart - 2), "󰄵", black, fontSymbols)
else:
draw.text((15, taskStart), "󰄱", black, fontSymbols)
reflowedTitle = reflow_quote(task["summary"], 160, fontLarge)
titleSizeW, titleSizeH = getsize(fontLarge, reflowedTitle)
titleSizeH *= reflowedTitle.count("\n") + 1
draw.text((35, taskStart - 3), reflowedTitle, black, fontLarge)
taskStart += titleSizeH + (2 * ep)
# Add cal
draw.text((220, topbar + 7), "Calendar", black, fontTitle)
draw.line(((400 / 2) + margin, 62, 400 - margin, 62), fill=black, width=1)
events = get_calendar_events()
def get_start_date(x):
start = x["start"]
if "date" in start:
startDate = datetime.strptime(start["date"], "%Y-%m-%d").date()
elif "dateTime" in start:
startDate = datetime.strptime(start["dateTime"][:10], "%Y-%m-%d").date()
else:
print("Error")
print(start)
return None
if startDate < datetime.today().date():
return datetime.today().date()
else:
return startDate
itemStart = 70
for key, group in groupby(events, get_start_date):
dayStart = itemStart
# Calculate
if key == datetime.today().date():
dateStr = "Today"
elif key == (datetime.today() + timedelta(days=1)).date():
dateStr = "Tomorrow"
else:
dateStr = key.strftime("%d %b")
w, h = getsize(fontLarge, "Today")
dayStart += h + (ep)
dayTasks = list(group)
for thing in dayTasks:
reflowedItem = reflow_quote(thing["summary"], 170, fontSmall)
w, h = getsize(fontLarge, "Today")
h *= reflowedItem.count("\n") + 1
dayStart += h + (ep)
dayStart + ep
if dayStart > 280:
print()
break
# Commit if possible
draw.text((215, itemStart), dateStr, black, fontLargeBold)
w, h = getsize(fontLargeBold, dateStr)
itemStart += h + ep
for thing in dayTasks:
reflowedItem = reflow_quote(thing["summary"], 170, fontSmall)
w, h = getsize(fontSmall, thing["summary"])
h *= reflowedItem.count("\n") + 1
draw.text((230, itemStart), reflowedItem, black, fontSmall)
itemStart += h + ep
itemStart += ep
return image
if __name__ == "__main__":
load_dotenv()
img = draw_image()
img.save("built.bmp")