# HG changeset patch # User Paul Boddie # Date 1515790454 -3600 # Node ID 9286159dc46649635e95ad097d114c9677615198 # Parent 857aae8d5942678c7e1d23645d7d86360b33029c Added support for rule editing. Changed organiser-initiated event updates to redefine events under a narrower set of circumstances, making the emission of ADD method updates more likely. diff -r 857aae8d5942 -r 9286159dc466 imiptools/editing.py --- a/imiptools/editing.py Fri Jan 12 19:35:17 2018 +0100 +++ b/imiptools/editing.py Fri Jan 12 21:54:14 2018 +0100 @@ -3,7 +3,7 @@ """ User interface data abstractions. -Copyright (C) 2014, 2015, 2017 Paul Boddie +Copyright (C) 2014, 2015, 2017, 2018 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -30,6 +30,7 @@ to_date, to_utc_datetime, to_timezone from imiptools.period import get_overlapping_members, RecurringPeriod from itertools import chain +import vRecurrence # General editing abstractions. @@ -153,6 +154,7 @@ "attendees" : lambda: OrderedDict(self.obj.get_items("ATTENDEE") or []), "organiser" : lambda: self.obj.get_value("ORGANIZER"), "periods" : lambda: CopiableList(form_periods_from_periods(self.get_unedited_periods())), + "rule" : lambda: CopiableList(vRecurrence.get_selectors_for_rule(self.obj.get_value("RRULE"))), "suggested_attendees" : self.get_suggested_attendees, "suggested_periods" : self.get_suggested_periods, "summary" : lambda: self.obj.get_value("SUMMARY"), @@ -429,7 +431,7 @@ is_changed = [] - for name in ["summary"]: + for name in ["rule", "summary"]: if self.state.has_changed(name): is_changed.append(name) @@ -475,6 +477,10 @@ self.update_attendees(to_invite, to_cancel, to_modify) self.update_event_from_periods(to_set, to_exclude) + if self.state.has_changed("rule"): + rule = vRecurrence.to_property(self.state.get("rule")) + self.obj.set_rule((rule, {})) + # Classify the nature of any update. if is_changed: @@ -736,7 +742,7 @@ def remove_attendees(self, indexes): - "Remove attendee at 'index'." + "Remove attendee at 'indexes'." attendees = self.state.get("attendees") to_remove = [] @@ -767,7 +773,31 @@ return True + def can_edit_rule_selector(self, index): + "Return whether the recurrence rule selector at 'index' can be edited." + + try: + rule = self.state.get("rule") + return rule and rule[index] or None + except IndexError: + return None + + def remove_rule_selectors(self, indexes): + + "Remove rule selectors at 'indexes'." + + rule = self.state.get("rule") + to_remove = [] + removed = 0 + + for index in indexes: + if self.can_edit_rule_selector(index): + to_remove.append(index - removed) + removed += 1 + + for index in to_remove: + del rule[index] # Period-related abstractions. @@ -1457,12 +1487,13 @@ # All modifications redefine the event. # For shared events... - # New periods should cause the event to be redefined. - # Other changes should also cause event redefinition. - # Event redefinition should only occur if no replacement periods exist. + # Property changes should cause event redefinition. # Cancelled rule-originating periods must be excluded. + # NOTE: New periods where no replacement periods exist might also cause + # NOTE: complete redefinition, especially if ADD requests are not + # NOTE: desired. - if not is_shared or new and not replaced: + if not is_shared or is_changed: to_set = active_non_rule to_exclude = list(chain(cancelled_rule, obsolete_rule, cancelled_main)) to_unschedule = []