From 590324995f5be439da8ab17f0f65933a3c5c02ea Mon Sep 17 00:00:00 2001 From: shouya <526598+shouya@users.noreply.github.com> Date: Sun, 15 Feb 2026 00:01:05 +0900 Subject: [PATCH] use python script to load khal events --- Scripts/python/src/calendar/khal-events.py | 70 ++++++++++++++++++++++ Services/Location/Calendar/Khal.qml | 10 ++-- 2 files changed, 75 insertions(+), 5 deletions(-) create mode 100755 Scripts/python/src/calendar/khal-events.py diff --git a/Scripts/python/src/calendar/khal-events.py b/Scripts/python/src/calendar/khal-events.py new file mode 100755 index 000000000..fc5abca76 --- /dev/null +++ b/Scripts/python/src/calendar/khal-events.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +import json +import os +import re +import subprocess +import sys +from datetime import datetime +from pathlib import Path + +def get_khal_date_format(): + """Read the khal config and extract the longdatetimeformat.""" + xdg_config = os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')) + config_path = Path(xdg_config) / 'khal' / 'config' + + if not config_path.exists(): + return '%c' + + with open(config_path, 'r') as f: + for line in f: + if m := re.match(r'^longdatetimeformat\s?=\s?(.+?)\s*$', line): + date_format = m.group(1).strip() + return date_format + + return '%c' + + +def to_khal(date_str, khal_format): + dt = datetime.strptime(date_str, "%Y-%m-%d") + return dt.strftime(khal_format) + +def from_khal(date_str, khal_format): + if not date_str: + return '' + dt = datetime.strptime(date_str, khal_format) + return dt.isoformat() + +def convert_event(event, khal_format): + event['start-long-full'] = from_khal(event.get('start-long-full', ''), khal_format) + event['end-long-full'] = from_khal(event.get('end-long-full', ''), khal_format) + return event + +def main(): + start_date = sys.argv[1] + duration = sys.argv[2] + + khal_format = get_khal_date_format() + khal_start = to_khal(start_date, khal_format) + + cmd = [ + 'khal', 'list', + '--json', 'uid', + '--json', 'title', + '--json', 'start-long-full', + '--json', 'end-long-full', + '--json', 'calendar', + '--json', 'description', + '--json', 'location', + khal_start, + duration + ] + + result = subprocess.run(cmd, capture_output=True, text=True) + output = result.stdout.strip() + + for line in output.split('\n'): + day_events = json.loads(line) + print(json.dumps([convert_event(e, khal_format) for e in day_events])) + +if __name__ == '__main__': + main() diff --git a/Services/Location/Calendar/Khal.qml b/Services/Location/Calendar/Khal.qml index af0deff48..3addbf519 100644 --- a/Services/Location/Calendar/Khal.qml +++ b/Services/Location/Calendar/Khal.qml @@ -9,6 +9,8 @@ import qs.Services.Location Singleton { id: root + readonly property string khalEventsScript: Quickshell.shellDir + '/Scripts/python/src/calendar/khal-events.py' + function init() { availabilityCheckProcess.running = true; } @@ -33,7 +35,7 @@ Singleton { Process { id: availabilityCheckProcess running: false - command: ["sh", "-c", "command -v khal >/dev/null 2>&1"] + command: ["sh", "-c", "command -v khal >/dev/null 2>&1 && command -v python3 >/dev/null 2>&1"] onExited: function (exitCode) { if (exitCode === 0) { CalendarService.available = true; @@ -92,7 +94,7 @@ Singleton { property string startTime: "" property string duration: "" - command: ["khal", "list", "--json", "uid", "--json", "title", "--json", "start-long-full", "--json", "end-long-full", "--json", "calendar", "--json", "description", "--json", "location", startTime, duration] + command: ["python3", root.khalEventsScript, startTime, duration] stdout: StdioCollector { onStreamFinished: { @@ -151,9 +153,7 @@ Singleton { } function parseTimestamp(timeStr) { - // The actual timeStr format depends on user's khal configuration - // for longdatetimeformat. Here we assume it's a reasonable to be - // recognized by js Date parser. + // expects ISO8601 format return Math.floor((Date.parse(timeStr)).valueOf() / 1000); }