Fixup section duration times
This commit is contained in:
parent
16ad7ae5aa
commit
39ec7f470b
@ -464,26 +464,32 @@ class PlaylistRows(Base):
|
|||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_section_header_rows(cls, session: scoped_session,
|
def get_from_id_list(cls, session: scoped_session, playlist_id: int,
|
||||||
playlist_id: int) -> List["PlaylistRows"]:
|
plr_ids: List[int]) -> List["PlaylistRows"]:
|
||||||
"""
|
"""
|
||||||
Return a list of PlaylistRows that are section headers for this
|
Take a list of PlaylistRows ids and return a list of corresponding
|
||||||
playlist
|
PlaylistRows objects
|
||||||
"""
|
"""
|
||||||
|
|
||||||
plrs = session.execute(
|
plrs = session.execute(
|
||||||
select(cls)
|
select(cls)
|
||||||
.where(
|
.where(
|
||||||
cls.playlist_id == playlist_id,
|
cls.playlist_id == playlist_id,
|
||||||
cls.track_id.is_(None),
|
cls.id.in_(plr_ids)
|
||||||
(
|
|
||||||
cls.note.endswith("-") |
|
|
||||||
cls.note.endswith("+")
|
|
||||||
)
|
|
||||||
).order_by(cls.row_number)).scalars().all()
|
).order_by(cls.row_number)).scalars().all()
|
||||||
|
|
||||||
return plrs
|
return plrs
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_last_used_row(session: scoped_session,
|
||||||
|
playlist_id: int) -> Optional[int]:
|
||||||
|
"""Return the last used row for playlist, or None if no rows"""
|
||||||
|
|
||||||
|
return session.execute(
|
||||||
|
select(func.max(PlaylistRows.row_number))
|
||||||
|
.where(PlaylistRows.playlist_id == playlist_id)
|
||||||
|
).scalar_one()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_track_plr(session: scoped_session, track_id: int,
|
def get_track_plr(session: scoped_session, track_id: int,
|
||||||
playlist_id: int) -> Optional["PlaylistRows"]:
|
playlist_id: int) -> Optional["PlaylistRows"]:
|
||||||
@ -498,16 +504,6 @@ class PlaylistRows(Base):
|
|||||||
.limit(1)
|
.limit(1)
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_last_used_row(session: scoped_session,
|
|
||||||
playlist_id: int) -> Optional[int]:
|
|
||||||
"""Return the last used row for playlist, or None if no rows"""
|
|
||||||
|
|
||||||
return session.execute(
|
|
||||||
select(func.max(PlaylistRows.row_number))
|
|
||||||
.where(PlaylistRows.playlist_id == playlist_id)
|
|
||||||
).scalar_one()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_played_rows(cls, session: scoped_session,
|
def get_played_rows(cls, session: scoped_session,
|
||||||
playlist_id: int) -> List["PlaylistRows"]:
|
playlist_id: int) -> List["PlaylistRows"]:
|
||||||
@ -572,27 +568,6 @@ class PlaylistRows(Base):
|
|||||||
|
|
||||||
return plrs
|
return plrs
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def indexed_by_id(session: scoped_session,
|
|
||||||
plr_ids: Union[Iterable[int], ValuesView]) -> dict:
|
|
||||||
"""
|
|
||||||
Return a dictionary of playlist_rows indexed by their plr id from
|
|
||||||
the passed plr_id list.
|
|
||||||
"""
|
|
||||||
|
|
||||||
plrs = session.execute(
|
|
||||||
select(PlaylistRows)
|
|
||||||
.where(
|
|
||||||
PlaylistRows.id.in_(plr_ids)
|
|
||||||
)
|
|
||||||
).scalars().all()
|
|
||||||
|
|
||||||
result = {}
|
|
||||||
for plr in plrs:
|
|
||||||
result[plr.id] = plr
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def move_rows_down(session: scoped_session, playlist_id: int,
|
def move_rows_down(session: scoped_session, playlist_id: int,
|
||||||
starting_row: int, move_by: int) -> None:
|
starting_row: int, move_by: int) -> None:
|
||||||
|
|||||||
@ -63,6 +63,7 @@ if TYPE_CHECKING:
|
|||||||
from musicmuster import Window, MusicMusterSignals
|
from musicmuster import Window, MusicMusterSignals
|
||||||
|
|
||||||
start_time_re = re.compile(r"@\d\d:\d\d:\d\d")
|
start_time_re = re.compile(r"@\d\d:\d\d:\d\d")
|
||||||
|
section_header_cleanup_re = re.compile(r"(@\d\d:\d\d:\d\d.*)?(\+)?")
|
||||||
HEADER_NOTES_COLUMN = 2
|
HEADER_NOTES_COLUMN = 2
|
||||||
|
|
||||||
# Columns
|
# Columns
|
||||||
@ -255,9 +256,6 @@ class PlaylistTab(QTableWidget):
|
|||||||
with Session() as session:
|
with Session() as session:
|
||||||
self.save_playlist(session)
|
self.save_playlist(session)
|
||||||
|
|
||||||
# Update track times
|
|
||||||
self._update_start_end_times()
|
|
||||||
|
|
||||||
def _add_context_menu(self, text: str, action: Callable,
|
def _add_context_menu(self, text: str, action: Callable,
|
||||||
disabled: bool = False) -> QAction:
|
disabled: bool = False) -> QAction:
|
||||||
"""
|
"""
|
||||||
@ -565,8 +563,7 @@ class PlaylistTab(QTableWidget):
|
|||||||
self._set_row_bold(row, bold)
|
self._set_row_bold(row, bold)
|
||||||
|
|
||||||
if update_track_times:
|
if update_track_times:
|
||||||
# Queue time updates so playlist updates first
|
self._update_start_end_times()
|
||||||
QTimer.singleShot(0, self._update_start_end_times)
|
|
||||||
|
|
||||||
def insert_track(self, session: scoped_session, track: Tracks,
|
def insert_track(self, session: scoped_session, track: Tracks,
|
||||||
note: str = "", repaint: bool = True) -> None:
|
note: str = "", repaint: bool = True) -> None:
|
||||||
@ -606,10 +603,6 @@ class PlaylistTab(QTableWidget):
|
|||||||
plr = PlaylistRows(session, self.playlist_id, track.id,
|
plr = PlaylistRows(session, self.playlist_id, track.id,
|
||||||
row_number, note)
|
row_number, note)
|
||||||
self.insert_row(session, plr)
|
self.insert_row(session, plr)
|
||||||
session.flush()
|
|
||||||
|
|
||||||
# Let display update, then save playlist
|
|
||||||
# TODO: QTimer.singleShot(0, lambda: self.save_playlist(session))
|
|
||||||
self.save_playlist(session)
|
self.save_playlist(session)
|
||||||
|
|
||||||
def play_ended(self) -> None:
|
def play_ended(self) -> None:
|
||||||
@ -686,8 +679,6 @@ class PlaylistTab(QTableWidget):
|
|||||||
self.insert_row(session, plr, update_track_times=False,
|
self.insert_row(session, plr, update_track_times=False,
|
||||||
played=plr.row_number in played_rows)
|
played=plr.row_number in played_rows)
|
||||||
|
|
||||||
self._update_start_end_times()
|
|
||||||
|
|
||||||
# Scroll to top
|
# Scroll to top
|
||||||
if scroll_to_top:
|
if scroll_to_top:
|
||||||
row0_item = self.item(0, 0)
|
row0_item = self.item(0, 0)
|
||||||
@ -1086,10 +1077,7 @@ class PlaylistTab(QTableWidget):
|
|||||||
# Reset drag mode
|
# Reset drag mode
|
||||||
self.setDragEnabled(False)
|
self.setDragEnabled(False)
|
||||||
|
|
||||||
self.save_playlist(session)
|
self._update_start_end_times()
|
||||||
|
|
||||||
# Queue time updates so playlist updates first
|
|
||||||
QTimer.singleShot(0, self._update_start_end_times)
|
|
||||||
|
|
||||||
def _drop_on(self, event):
|
def _drop_on(self, event):
|
||||||
"""
|
"""
|
||||||
@ -1520,7 +1508,6 @@ class PlaylistTab(QTableWidget):
|
|||||||
|
|
||||||
_ = self._set_row_note_colour(session, row, plr.note,
|
_ = self._set_row_note_colour(session, row, plr.note,
|
||||||
section_header=True)
|
section_header=True)
|
||||||
self._update_start_end_times()
|
|
||||||
self.clear_selection()
|
self.clear_selection()
|
||||||
|
|
||||||
# Set track start/end times after track list is populated
|
# Set track start/end times after track list is populated
|
||||||
@ -2127,42 +2114,47 @@ class PlaylistTab(QTableWidget):
|
|||||||
Update section headers with run time of section
|
Update section headers with run time of section
|
||||||
"""
|
"""
|
||||||
|
|
||||||
header_rows = []
|
section_start_rows: List[PlaylistRows] = []
|
||||||
|
|
||||||
|
header_rows = [self._get_row_plr_id(row_number) for row_number in
|
||||||
|
range(self.rowCount())
|
||||||
|
if not self._get_row_track_id(row_number)]
|
||||||
|
plrs = PlaylistRows.get_from_id_list(session, self.playlist_id,
|
||||||
|
header_rows)
|
||||||
|
|
||||||
# Get section header PlaylistRows. Flush session first in case
|
|
||||||
# there are pending playlist changes that affect which row
|
|
||||||
# numbers are headers.
|
|
||||||
session.flush()
|
|
||||||
plrs = PlaylistRows.get_section_header_rows(session, self.playlist_id)
|
|
||||||
for plr in plrs:
|
for plr in plrs:
|
||||||
# TODO: print(f"{plr.row_number=}")
|
|
||||||
if plr.note.endswith("+"):
|
if plr.note.endswith("+"):
|
||||||
header_rows.append(plr)
|
section_start_rows.append(plr)
|
||||||
continue
|
continue
|
||||||
assert plr.note.endswith("-")
|
elif plr.note.endswith("-"):
|
||||||
try:
|
try:
|
||||||
from_plr = header_rows.pop()
|
from_plr = section_start_rows.pop()
|
||||||
to_plr = plr
|
to_plr = plr
|
||||||
total_time = self._track_time_between_rows(session,
|
total_time = self._track_time_between_rows(
|
||||||
from_plr, to_plr)
|
session, from_plr, to_plr)
|
||||||
time_str = self._get_section_timing_string(total_time)
|
time_str = self._get_section_timing_string(total_time)
|
||||||
self._update_note_text(from_plr, from_plr.note + time_str)
|
self._update_note_text(from_plr, from_plr.note + time_str)
|
||||||
|
|
||||||
# Update section end
|
# Update section end
|
||||||
if to_plr.note.strip() == "-":
|
if to_plr.note.strip() == "-":
|
||||||
new_text = (
|
new_text = (
|
||||||
"[End " + from_plr.note.strip()[:-1].strip() + "]"
|
"[End " + re.sub(
|
||||||
)
|
section_header_cleanup_re, '', from_plr.note,
|
||||||
self._update_note_text(plr, new_text)
|
).strip() + "]"
|
||||||
except IndexError:
|
)
|
||||||
continue
|
self._update_note_text(plr, new_text)
|
||||||
|
except IndexError:
|
||||||
|
# This ending row may have a time left from before a
|
||||||
|
# starting row above was deleted, so replace content
|
||||||
|
self._update_note_text(plr, plr.note)
|
||||||
|
continue
|
||||||
|
|
||||||
# If we still have plrs in header_rows, there isn't an end
|
# If we still have plrs in section_start_rows, there isn't an end
|
||||||
# section row for them
|
# section row for them
|
||||||
possible_plr = self._get_row_plr(session, self.rowCount() - 1)
|
possible_plr = self._get_row_plr(session, self.rowCount() - 1)
|
||||||
if possible_plr:
|
if possible_plr:
|
||||||
to_plr = possible_plr
|
to_plr = possible_plr
|
||||||
for from_plr in header_rows:
|
for from_plr in section_start_rows:
|
||||||
total_time = self._track_time_between_rows(session,
|
total_time = self._track_time_between_rows(session,
|
||||||
from_plr, to_plr)
|
from_plr, to_plr)
|
||||||
time_str = self._get_section_timing_string(total_time,
|
time_str = self._get_section_timing_string(total_time,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user