- booking_lines += [dat_line]
- elif booking_lines:
- booking = Booking(
- len(self.bookings), booking_lines,
- self.bookings[-1] if self.bookings else None)
- if last_date > booking.intro.date:
- booking.intro.errors += ['date < previous valid date']
- else:
- last_date = booking.intro.date
- self.bookings += [booking]
- booking_lines = []
-
- def save(self) -> None:
- """Save current state to ._path_dat."""
- self._path_dat.write_text(
- '\n'.join([line.raw for line in self.dat_lines]), encoding='utf8')
- self.load()
-
- def _margin_indices(self, booking: Booking) -> tuple[int, int]:
- start_idx = self.dat_lines.index(booking.dat_lines[0])
- end_idx = self.dat_lines.index(booking.dat_lines[-1])
- return start_idx, end_idx
-
- def _replace_from_to(self,
- start_idx: int,
- end_idx: int,
- new_lines: list[DatLine]
- ) -> None:
- self.dat_lines = (self.dat_lines[:start_idx]
- + new_lines
- + self.dat_lines[end_idx+1:])
- self._load_bookings()
-
- def move_booking(self, id_: int, up: bool) -> None:
- """Move Booking of id_ one step up or downwards"""
- id_other = id_ + (-1 if up else 1)
- agent = self.bookings[id_]
- other = self.bookings[id_other]
- start_agent, end_agent = self._margin_indices(agent)
- start_other, end_other = self._margin_indices(other)
- gap_lines = self.dat_lines[(end_other if up else end_agent) + 1:
- start_agent if up else start_other]
- self._replace_from_to(start_other if up else start_agent,
- end_agent if up else end_other,
- (agent.dat_lines if up else other.dat_lines)
- + gap_lines
- + (other.dat_lines if up else agent.dat_lines))
-
- def rewrite_booking(self, id_: int, new_dat_lines: list[DatLine]) -> None:
- """Rewrite .dat_lines for Booking of .id_ with new_dat_lines."""
- self._replace_from_to(*self._margin_indices(self.bookings[id_]),
- new_dat_lines)
+ if gap_lines:
+ if booking:
+ booking.gap_lines = gap_lines[:]
+ else:
+ self.initial_gap_lines = gap_lines[:]
+ gap_lines.clear()
+ booked_lines += [dat_line]
+ else:
+ if booked_lines:
+ booking = Booking(len(self.bookings), booked_lines[:])
+ if last_date > booking.date:
+ booking.intro_line.errors += [
+ 'date < previous valid date']
+ else:
+ last_date = booking.date
+ self.bookings += [booking]
+ booked_lines.clear()
+ gap_lines += [dat_line]
+ for booking in self.bookings:
+ booking.recalc_prev_next(self.bookings)
+ if booking:
+ booking.gap_lines = gap_lines[:-1]
+
+ def _recalc_dat_lines(self) -> None:
+ self.dat_lines = self.initial_gap_lines[:]
+ for booking in self.bookings:
+ self.dat_lines += booking.booked_lines
+ self.dat_lines += booking.gap_lines
+
+ def _move_booking(self, idx_from, idx_to) -> None:
+ moving = self.bookings[idx_from]
+ if idx_from >= idx_to: # moving upward, deletion must
+ del self.bookings[idx_from] # precede insertion to keep
+ self.bookings[idx_to:idx_to] = [moving] # deletion index, downwards
+ if idx_from < idx_to: # the other way around keeps
+ del self.bookings[idx_from] # insertion index
+ min_idx, max_idx = min(idx_from, idx_to), max(idx_from, idx_to)
+ for idx, booking in enumerate(self.bookings[min_idx:max_idx + 1]):
+ booking.id_ = min_idx + idx
+ booking.recalc_prev_next(self.bookings)
+
+ def move_booking(self, old_id: int, up: bool) -> int:
+ """Move Booking of old_id one step up or downwards"""
+ new_id = old_id + (-1 if up else 1)
+ self._move_booking(old_id, # moving down implies
+ new_id + (0 if up else 1)) # jumping over next item
+ self._recalc_dat_lines()
+ return new_id
+
+ def rewrite_booking(self, old_id: int, new_booked_lines: list[DatLine]
+ ) -> int:
+ """Rewrite Booking with new_booked_lines, move if changed date."""
+ old_booking = self.bookings[old_id]
+ new_date = new_booked_lines[0].code.lstrip().split(maxsplit=1)[0]
+ if new_date == old_booking.date:
+ new_booking = Booking(
+ old_id, new_booked_lines, old_booking.gap_lines_copied)
+ self.bookings[old_id] = new_booking
+ new_booking.recalc_prev_next(self.bookings)
+ else:
+ i_booking = self.bookings[0]
+ new_idx = None
+ while i_booking.next:
+ if not i_booking.prev and i_booking.date > new_date:
+ new_idx = i_booking.id_
+ break
+ if i_booking.next.date > new_date:
+ break
+ i_booking = i_booking.next
+ if new_idx is None:
+ new_idx = i_booking.id_ + 1
+ # ensure that, if we land in group of like-dated Bookings, we land
+ # on the edge closest to our last position
+ if i_booking.date == new_date and old_id < i_booking.id_:
+ new_idx = [b for b in self.bookings
+ if b.date == new_date][0].id_
+ new_booking = Booking(
+ new_idx, new_booked_lines, old_booking.gap_lines_copied)
+ self.bookings[old_id] = new_booking
+ self._move_booking(old_id, new_idx)
+ self._recalc_dat_lines()
+ return new_booking.id_