diff --git a/projects/khora/khora/khal_adapter.py b/projects/khora/khora/khal_adapter.py index 56a7a128..902bc86e 100644 --- a/projects/khora/khora/khal_adapter.py +++ b/projects/khora/khora/khal_adapter.py @@ -23,6 +23,7 @@ class KhalRepository: name=name, color=settings.get("color") or None, readonly=settings.get("readonly", False), + account=Path(settings["path"]).expanduser().parent.name or "Calendars", ) for name, settings in self._config["calendars"].items() if settings.get("type", "calendar") == "calendar" diff --git a/projects/khora/khora/model.py b/projects/khora/khora/model.py index 51ac63f3..0faa90d1 100644 --- a/projects/khora/khora/model.py +++ b/projects/khora/khora/model.py @@ -59,6 +59,7 @@ class Calendar: name: str color: str | None = None readonly: bool = False + account: str = "Calendars" @dataclass(frozen=True) diff --git a/projects/khora/khora/window.py b/projects/khora/khora/window.py index d01131ee..c869ee3a 100644 --- a/projects/khora/khora/window.py +++ b/projects/khora/khora/window.py @@ -10,7 +10,7 @@ from gi.repository import Adw, Gio, GLib, Gtk, Pango from .colors import display_color from .khal_adapter import KhalRepository -from .model import Event, event_slot_range, period_label, shifted_date, week_dates +from .model import Calendar, Event, event_slot_range, period_label, shifted_date, week_dates SIDEBAR_WIDTH = 280 @@ -130,20 +130,41 @@ class KhoraWindow(Adw.ApplicationWindow): box.append(self._calendar) box.append(Gtk.Label(label="Calendars", xalign=0, css_classes=["heading"])) - calendars = Gtk.ListBox(selection_mode=Gtk.SelectionMode.NONE) - calendars.add_css_class("boxed-list") + groups = Gtk.Box( + orientation=Gtk.Orientation.VERTICAL, + spacing=18, + margin_bottom=6, + ) assert self._repository is not None + calendars_by_account: dict[str, list[Calendar]] = {} for calendar in self._repository.calendars: - toggle = Gtk.Switch(active=True, valign=Gtk.Align.CENTER) - toggle.connect("notify::active", self._on_calendar_toggled, calendar.name) - row = Adw.ActionRow(title=calendar.name, activatable=True) - row.add_prefix(self._color_dot(calendar.color)) - row.add_suffix(toggle) - row.set_activatable_widget(toggle) - calendars.append(row) - box.append(calendars) + calendars_by_account.setdefault(calendar.account, []).append(calendar) + + for account, calendars in calendars_by_account.items(): + group = Adw.PreferencesGroup(title=self._account_label(account)) + for calendar in calendars: + toggle = Gtk.Switch(active=True, valign=Gtk.Align.CENTER) + toggle.connect("notify::active", self._on_calendar_toggled, calendar.name) + row = Adw.ActionRow(title=calendar.name, activatable=True) + row.add_prefix(self._color_dot(calendar.color)) + row.add_suffix(toggle) + row.set_activatable_widget(toggle) + group.add(row) + groups.append(group) + + box.append( + Gtk.ScrolledWindow( + child=groups, + hscrollbar_policy=Gtk.PolicyType.NEVER, + vexpand=True, + ) + ) return box + @staticmethod + def _account_label(account: str) -> str: + return account.replace("-", " ").replace("_", " ").title() + def _build_calendar_view(self) -> Gtk.Widget: overlay = Gtk.Overlay() scroller = Gtk.ScrolledWindow( diff --git a/projects/khora/tests/test_khal_adapter.py b/projects/khora/tests/test_khal_adapter.py new file mode 100644 index 00000000..ba5d0b88 --- /dev/null +++ b/projects/khora/tests/test_khal_adapter.py @@ -0,0 +1,24 @@ +from khora.khal_adapter import KhalRepository + + +def test_calendar_accounts_come_from_their_parent_directory() -> None: + repository = KhalRepository.__new__(KhalRepository) + repository._config = { + "calendars": { + "Personal": { + "path": "/home/example/Calendars/personal/default", + "type": "calendar", + "color": "dark blue", + "readonly": False, + }, + "University": { + "path": "/home/example/Calendars/university/classes", + "type": "calendar", + "readonly": True, + }, + } + } + + calendars = repository.calendars + + assert tuple(calendar.account for calendar in calendars) == ("personal", "university")