112 lines
4.0 KiB
Python
Executable File
112 lines
4.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
import subprocess as sp
|
|
import datetime
|
|
import time
|
|
import gi
|
|
gi.require_version("Gtk","3.0")
|
|
from gi.repository import Gtk
|
|
|
|
calcurse_event_cmd = ["calcurse", "-Q",
|
|
"--input-datefmt","4",
|
|
"--output-datefmt","4",
|
|
"--filter-type", "cal",
|
|
"--format-recur-apt", '"apt;%S;%E;%m\n"',
|
|
"--format-apt", '"apt;%S;%E;%m\n"',
|
|
"--format-event", '"event;%m\n"',
|
|
"--from"]
|
|
|
|
def get_event_list(date): # Gets the clean event list output from calcurse.
|
|
date_str = date.isoformat()
|
|
cmd = calcurse_event_cmd.copy()
|
|
cmd.append(date_str)
|
|
calcurse_out = sp.run(cmd,capture_output=True).stdout
|
|
decoded = calcurse_out.decode().replace("\"","")
|
|
out = decoded.splitlines()[1:]
|
|
return out
|
|
|
|
def parse_event_list(event_list): # parses calcurse event list into dicts for future use
|
|
split_events = [event.split(';') for event in event_list]
|
|
out = []
|
|
for event in split_events:
|
|
if event[0] == "event":
|
|
out.append({
|
|
'type':'event',
|
|
'start': datetime.time(0),
|
|
'description': event[1],
|
|
})
|
|
elif event[0] == "apt":
|
|
out.append({
|
|
'type':'apt',
|
|
'start': parse_time(event[1]),
|
|
'end': parse_time(event[2]),
|
|
'description': event[3]
|
|
})
|
|
|
|
return out
|
|
|
|
def parse_time(time): # Takes a time as returned by calcurse, returns a datetime.time object
|
|
t = time.split(':')
|
|
return datetime.time(int(t[0]),int(t[1]))
|
|
|
|
class CalendarWindow(Gtk.ApplicationWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.header_bar = Gtk.HeaderBar()
|
|
self.header_bar.set_title("Calendar")
|
|
self.header_bar.props.show_close_button = True
|
|
self.set_titlebar(self.header_bar)
|
|
self.event_list = Gtk.ListBox()
|
|
self.event_list.fill = True
|
|
self.calendar_box = Gtk.Paned(orientation=Gtk.Orientation.VERTICAL)
|
|
self.calendar = Gtk.Calendar()
|
|
self.calendar.fill = True
|
|
self.calendar.expand = True
|
|
self.calendar.set_size_request(400,400)
|
|
self.calendar_box.add(self.calendar)
|
|
self.calendar_box.add(Gtk.Label(label="PlaceHolder"))
|
|
self.main_box = Gtk.Paned(orientation=Gtk.Orientation.HORIZONTAL) # Box containing the list view and cal/buttons
|
|
self.main_box.add(self.calendar_box)
|
|
self.main_box.add(self.event_list)
|
|
self.add(self.main_box)
|
|
self.connect("destroy",Gtk.main_quit)
|
|
self.calendar.connect("day_selected",self._on_day_selected)
|
|
|
|
def _on_day_selected(self,calendar):
|
|
calendar_date = calendar.get_date()
|
|
date = datetime.date(calendar_date.year,calendar_date.month+1,calendar_date.day)
|
|
self.header_bar.set_subtitle(date.isoformat())
|
|
self.populate_day(date)
|
|
|
|
|
|
def populate_day(self,date):
|
|
for c in self.event_list.get_children():
|
|
c.destroy()
|
|
events = parse_event_list(get_event_list(date))
|
|
sorted_events = sorted(events, key=lambda k: k['start'])
|
|
for event in sorted_events:
|
|
row = EventRow(event)
|
|
self.event_list.add(row)
|
|
self.event_list.show_all()
|
|
|
|
class EventRow(Gtk.ListBoxRow):
|
|
def __init__(self,event):
|
|
super().__init__()
|
|
self.description_label = Gtk.Label(label=event['description'])
|
|
self.box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
|
|
self.box.padding = 20
|
|
if event['type'] != 'event':
|
|
timespan = f"{event['start'].strftime('%H:%M')} - {event['end'].strftime('%H:%M')}"
|
|
self.timespan_label = Gtk.Label(label=timespan)
|
|
self.box.pack_start(self.timespan_label,0,0,0)
|
|
self.box.pack_end(self.description_label,0,0,0)
|
|
else:
|
|
self.box.pack_start(self.description_label,0,0,0)
|
|
self.add(self.box)
|
|
|
|
today = datetime.date.today()
|
|
c = CalendarWindow()
|
|
c.populate_day(today)
|
|
c.header_bar.set_subtitle(today.isoformat())
|
|
c.show_all()
|
|
Gtk.main()
|