for i in range(IMAGE_SIZE-2):
img.putpixel((i+1,0), color)
img.putpixel((i+1,IMAGE_SIZE-1), color)
- _day(sheet, img, date, (2, IMAGE_SIZE-2), (2, IMAGE_SIZE-2), TARGET_HOURS, 255)
+ tt = _day(sheet, img, date, (2, IMAGE_SIZE-2), (2, IMAGE_SIZE-2), TARGET_HOURS, 255)
+ hr_ratio = floor(min(1, tt.total_seconds()/(TARGET_HOURS*60*60))*128)
+ grad_size = IMAGE_SIZE-2
+ for i in range(IMAGE_SIZE-2):
+ img.putpixel((1,1+i), (255,255,255, floor(hr_ratio*(grad_size-i)/grad_size)))
+ img.putpixel((IMAGE_SIZE-2,1+i), (255,255,255, floor(hr_ratio*(grad_size-i)/grad_size)))
+ for i in range(IMAGE_SIZE-4):
+ img.putpixel((2+i,1), (255,255,255, hr_ratio))
else:
_day(sheet, img, date, (0, IMAGE_SIZE), (0, IMAGE_SIZE), TARGET_HOURS, 255)
+ corner_alpha = 64
+ for px in (0, IMAGE_SIZE-1):
+ for py in (0, IMAGE_SIZE-1):
+ pxl = img.getpixel((px,py))
+ img.putpixel((px,py), pxl[:3] + (floor(corner_alpha*pxl[3]/255),))
img = img.resize((32,32), Image.NEAREST)
return img
def _day(sheet: TimeSheet, image: Image.Image, date: datetime.date,
x_range: Tuple[int,int], y_range: Tuple[int,int],
- target_hours: int = 0, alpha: int = 255) -> None:
+ target_hours: int = 0, alpha: int = 255) -> datetime.timedelta:
dt = datetime.datetime.combine(date, datetime.time(), datetime.datetime.now().astimezone().tzinfo)
de = dt + datetime.timedelta(days=1)
tt = datetime.timedelta(0)
segments = x_range[1] - x_range[0]
hours = y_range[1] - y_range[0]
+ size = max(floor(hours/target_hours), 1)
+ hours = floor(hours/size)
+ segments = floor(segments/size)
+
seg_time = _time_per_segment(segments)
# pre-fill taget range
for i in range(min(target_hours, hours)):
for j in range(segments):
- image.putpixel((x_range[0]+j, y_range[1]-1-i), (255,255,255,32))
+ for sx in range(size):
+ for sy in range(size):
+ image.putpixel((x_range[0]+j*size+sx,
+ y_range[1]-1-i*size-sy),
+ (255,255,255,32))
for entry in sheet.entries:
if entry is None:
time = entry.t_out - max(dt, entry.t_in) # type: ignore
tt += time
while ct < hours * segments and tt > datetime.timedelta(0):
- image.putpixel((x_range[0]+ct%segments, y_range[1]-1-floor(ct/segments)), color)
+ for sx in range(size):
+ for sy in range(size):
+ image.putpixel((x_range[0]+size*(ct%segments)+sx, y_range[1]-1-size*floor(ct/segments)-sy), color)
tt -= seg_time
ct += 1
+ return ct*seg_time + tt
+
def _time_per_segment(segments: int) -> datetime.timedelta:
seg_minutes = floor(60/segments)
# SPDX-License-Identifier: GPL-3.0-or-later
import datetime
+from math import floor
import pystray
from threading import Condition, Thread
from time import sleep
def _generate_menu_items(self):
active = self.sheet.get_open_entries()
+ in_text = ""
+ if len(active) == 1:
+ in_text = " " + self.sheet.categories[active[0].category].name
punch_in_menu = pystray.Menu(*self._generate_punch_in_items())
+ today_times = self._generate_todays_times()
return [
pystray.MenuItem("Punch in", punch_in_menu),
- pystray.MenuItem("Punch out",
+ pystray.MenuItem("Punch out" + in_text,
lambda: self.sheet.punch_out(),
enabled=len(active)==1,
default=True),
pystray.Menu.SEPARATOR,
+ pystray.MenuItem(today_times, None),
+ pystray.Menu.SEPARATOR,
pystray.MenuItem("Pop", lambda: self._pop_last()),
]
if i >= 5:
break
punch_in_items.append(
- pystray.MenuItem(entry.category,
+ pystray.MenuItem(self.sheet.categories[entry.category].name + " (" + entry.category + ")",
lambda _icon, item: self._punch_in(item)))
- return tuple(punch_in_items)
+ return punch_in_items
+
+
+ def _generate_todays_times(self) -> str:
+ today_times = ""
+ td = datetime.datetime.combine(datetime.date.today(), datetime.time(), tzinfo=datetime.datetime.now().astimezone().tzinfo)
+ for cat, times in self.sheet.cat_entries.items():
+ tt = datetime.timedelta(0)
+ for entry_i in reversed(times):
+ entry = self.sheet.entries[entry_i]
+ if entry is None:
+ break
+ if not entry.is_complete:
+ tt += datetime.datetime.now().astimezone() - max(td, entry.t_in)
+ elif entry.t_in < td and entry.t_out < td: # type: ignore
+ break
+ elif entry.t_in < td:
+ tt += entry.t_out - td # type: ignore
+ break
+ else:
+ tt += entry.duration # type: ignore
+
+ if tt > datetime.timedelta(0):
+ seconds = tt.total_seconds()
+ minutes = floor(seconds/60)
+ hours = floor(minutes/60)
+ today_times += f"{cat} {hours:02}:{minutes:02}\n"
+
+ return today_times.strip()
def _punch_in(self, item: pystray.MenuItem):
return
if len(active) == 1:
self.sheet.punch_out()
- self.sheet.punch_in(item.text)
+ self.sheet.punch_in(item.text[item.text.find("(")+1:-1])
def _pop_last(self):