diff --git a/khal/custom_types.py b/khal/custom_types.py index d0a2a8041..39701192c 100644 --- a/khal/custom_types.py +++ b/khal/custom_types.py @@ -13,6 +13,7 @@ class CalendarConfiguration(TypedDict): priority: int ctype: str addresses: str + organizer: str class LocaleConfiguration(TypedDict): diff --git a/khal/khalendar/event.py b/khal/khalendar/event.py index 6841f2915..57b544e35 100644 --- a/khal/khalendar/event.py +++ b/khal/khalendar/event.py @@ -355,6 +355,11 @@ def organizer(self) -> str: else: return email + def update_organizer(self, organizer: str) -> None: + if len(self.attendees) > 0: + email = organizer.lstrip("MAILTO:").lower() + self._vevents[self.ref]['ORGANIZER'] = f"MAILTO:{email}" + @property def url(self) -> str: if 'URL' not in self._vevents[self.ref]: diff --git a/khal/settings/khal.spec b/khal/settings/khal.spec index 6d994ec95..0456befb6 100644 --- a/khal/settings/khal.spec +++ b/khal/settings/khal.spec @@ -76,6 +76,10 @@ type = option('calendar', 'birthdays', 'discover', default='calendar') # belongs to the user. addresses = force_list(default='') +# The organizer email to use when inviting attendees. +# 'MAILTO:' is automatically prepended to the email address. +organizer = string(default=None) + [sqlite] # khal stores its internal caching database here, by default this will be in the *$XDG_DATA_HOME/khal/khal.db* (this will most likely be *~/.local/share/khal/khal.db*). path = expand_db_path(default=None) @@ -197,6 +201,10 @@ quit = force_list(default=list('q', 'Q')) # new event). If this is not set, such operations require an explicit value. default_calendar = string(default=None) +# The organizer email to use when inviting attendees. +# 'MAILTO:' is automatically prepended to the email address. +default_organizer = string(default=None) + # By default, khal displays only dates with events in `list` or `calendar` # view. Setting this to *True* will show all days, even when there is no event # scheduled on that day. diff --git a/khal/ui/editor.py b/khal/ui/editor.py index 60ef44abf..da9bfa802 100644 --- a/khal/ui/editor.py +++ b/khal/ui/editor.py @@ -377,6 +377,7 @@ def __init__( self.description = event.description self.location = event.location self.attendees = event.attendees + self.organizer = event.organizer self.categories = event.categories self.url = event.url self.startendeditor = StartEndEditor( @@ -429,6 +430,20 @@ def decorate_choice(c) -> tuple[str, str]: self.url = urwid.AttrMap(ExtendedEdit( caption=('caption', 'URL: '), edit_text=self.url), 'edit', 'edit focus', ) + if len(self.organizer) == 0: + default_calendar = self.event.calendar + account_organizer = self._conf["calendars"][default_calendar].get( + "organizer", default=None + ) + if account_organizer: + self.organizer = account_organizer + else: + default_organizer = self._conf["default"]["default_organizer"] + if default_organizer: + self.organizer = default_organizer + self.organizer = urwid.AttrMap(ExtendedEdit( + caption=("caption", "Organizer: "), edit_text=self.organizer), "edit", "edit focus", + ) self.alarmseditor: AlarmsEditor = AlarmsEditor(self.event) self.pile = NListBox(urwid.SimpleFocusListWalker([ self.summary, @@ -442,6 +457,7 @@ def decorate_choice(c) -> tuple[str, str]: self.url, divider, self.attendees, + self.organizer, divider, self.startendeditor, self.recurrenceeditor, @@ -513,6 +529,8 @@ def changed(self): return True if get_wrapped_text(self.attendees) != self.event.attendees: return True + if get_wrapped_text(self.organizer) != self.event.organizer: + return True if self.startendeditor.changed or self.calendar_chooser.changed: return True if self.recurrenceeditor.changed: @@ -527,6 +545,7 @@ def update_vevent(self): self.event.update_location(get_wrapped_text(self.location)) self.event.update_attendees(get_wrapped_text(self.attendees).split(',')) self.event.update_categories(get_wrapped_text(self.categories).split(',')) + self.event.update_organizer(get_wrapped_text(self.organizer)) self.event.update_url(get_wrapped_text(self.url)) if self.startendeditor.changed: diff --git a/tests/settings_test.py b/tests/settings_test.py index a1d6799c7..bdac130e7 100644 --- a/tests/settings_test.py +++ b/tests/settings_test.py @@ -43,16 +43,19 @@ def test_simple_config(self): 'home': { 'path': os.path.expanduser('~/.calendars/home/'), 'readonly': False, 'color': None, 'priority': 10, 'type': 'calendar', 'addresses': [''], + 'organizer': None, }, 'work': { 'path': os.path.expanduser('~/.calendars/work/'), 'readonly': False, 'color': None, 'priority': 10, 'type': 'calendar', 'addresses': [''], + 'organizer': None, }, }, 'sqlite': {'path': os.path.expanduser('~/.local/share/khal/khal.db')}, 'locale': LOCALE_BERLIN, 'default': { 'default_calendar': None, + 'default_organizer': None, 'print_new': 'False', 'highlight_event_days': False, 'timedelta': dt.timedelta(days=2), @@ -85,10 +88,11 @@ def test_small(self): 'calendars': { 'home': {'path': os.path.expanduser('~/.calendars/home/'), 'color': 'dark green', 'readonly': False, 'priority': 20, - 'type': 'calendar', 'addresses': ['']}, + 'type': 'calendar', 'addresses': [''], 'organizer': None}, 'work': {'path': os.path.expanduser('~/.calendars/work/'), 'readonly': True, 'color': None, 'priority': 10, - 'type': 'calendar', 'addresses': ['user@example.com']}}, + 'type': 'calendar', 'addresses': ['user@example.com'], + 'organizer': None}}, 'sqlite': {'path': os.path.expanduser('~/.local/share/khal/khal.db')}, 'locale': { 'local_timezone': get_localzone(), @@ -104,6 +108,7 @@ def test_small(self): }, 'default': { 'default_calendar': None, + 'default_organizer': None, 'print_new': 'False', 'highlight_event_days': False, 'timedelta': dt.timedelta(days=2),