Add section timing

This commit is contained in:
Keith Edmunds 2022-03-20 11:42:05 +00:00
parent ca385dcf54
commit 0fb1536055

View File

@ -18,6 +18,7 @@ from PyQt5.QtWidgets import (
import helpers
import os
import re
from config import Config
from datetime import datetime, timedelta
@ -33,6 +34,8 @@ from models import (
)
from dbconfig import Session
start_time_re = re.compile(r"@\d\d:\d\d\:\d\d")
class RowMeta:
CLEAR = 0
@ -269,7 +272,7 @@ class PlaylistTab(QTableWidget):
"""
Create note
If a row is selected, set note row to be rows above. Otherwise,
If a row is selected, set note row to be row above. Otherwise,
set note row to be end of playlist.
"""
@ -679,6 +682,8 @@ class PlaylistTab(QTableWidget):
note_text: str
row: int
row_time: Optional[datetime]
section_start_row: Optional[int] = None
section_time: int = 0
start_time: Optional[datetime]
start_times_row: Optional[int]
track: Optional[Tracks]
@ -700,12 +705,22 @@ class PlaylistTab(QTableWidget):
# Render notes in correct colour
if row in notes:
# Extract note text
note_text = self.item(row, self.COL_TITLE).text()
# Extract note text from database to ignore section timings
note_text = self._get_row_notes_object(row, session).note
# Does the note have a start time?
row_time = self._get_note_text_time(note_text)
if row_time:
next_start_time = row_time
# Does it delimit a section?
if section_start_row is not None:
if note_text.endswith("-"):
self._set_timed_section(session, section_start_row,
section_time)
section_start_row = None
section_time = 0
elif note_text.endswith("+"):
section_start_row = row
section_time = 0
# Set colour
note_colour = NoteColours.get_colour(session, note_text)
if not note_colour:
@ -715,16 +730,23 @@ class PlaylistTab(QTableWidget):
)
# Notes are always bold
self._set_row_bold(row)
continue
# Render unplayable tracks in correct colour
elif row in unreadable:
if row in unreadable:
self._set_row_colour(
row, QColor(Config.COLOUR_UNREADABLE)
)
self._set_row_bold(row)
continue
# Current row is a track row
track = self._get_row_track_object(row, session)
# Add track time to section time if in timed section
if section_start_row is not None:
section_time += track.duration
# Render current track
elif row == current_row:
if row == current_row:
# Set start time
self._set_row_start_time(
row, self.current_track_start_time)
@ -736,7 +758,6 @@ class PlaylistTab(QTableWidget):
last_played_str)
# Calculate next_start_time
track = self._get_row_track_object(row, session)
next_start_time = self._calculate_track_end_time(
track, self.current_track_start_time)
@ -749,9 +770,10 @@ class PlaylistTab(QTableWidget):
# Make bold
self._set_row_bold(row)
continue
# Render next track
elif row == next_row:
if row == next_row:
# if there's a track playing, set start time from that
if current_row:
start_time = self.current_track_start_time
@ -764,7 +786,6 @@ class PlaylistTab(QTableWidget):
self._set_row_start_time(row, start_time)
# Set end time
track = self._get_row_track_object(row, session)
next_start_time = self._calculate_track_end_time(
track, start_time)
self._set_row_end_time(row, next_start_time)
@ -778,7 +799,6 @@ class PlaylistTab(QTableWidget):
else:
# This is a track row other than next or current
track = self._get_row_track_object(row, session)
if row in played:
# Played today, so update last played column
last_playedtime = Playdates.last_played(
@ -809,6 +829,11 @@ class PlaylistTab(QTableWidget):
self._set_row_colour(
row, QColor(Config.COLOUR_EVEN_PLAYLIST))
# Have we had a section start but not end?
if section_start_row is not None:
self._set_timed_section(
session, section_start_row, section_time, no_end=True)
# ########## Internally called functions ##########
def _audacity(self, row: int) -> None:
@ -874,7 +899,7 @@ class PlaylistTab(QTableWidget):
if row in self._get_notes_rows():
# Save change to database
DEBUG(f"Notes.update_note: saving new note text '{new_text=}'")
note: Notes = self._get_notes_row_object(row, session)
note: Notes = self._get_row_notes_object(row, session)
note.update_note(session, row, new_text)
# Set/clear row start time accordingly
start_time = self._get_note_text_time(new_text)
@ -892,7 +917,7 @@ class PlaylistTab(QTableWidget):
"start time"
)
else:
track: Tracks = self._get_track_row_object(row, session)
track: Tracks = self._get_row_track_object(row, session)
if column == self.COL_ARTIST:
track.update_artist(session, artist=new_text)
elif column == self.COL_TITLE:
@ -926,6 +951,19 @@ class PlaylistTab(QTableWidget):
# Disable play controls so that keyboard input doesn't disturb playing
self.musicmuster.disable_play_next_controls()
# If this is a note cell and it's a section start, we need to
# remove any existing section timing so user can't edit that.
# Section timing is only in display of item, not in note text in
# database. Keep it simple: if this is a note, pull text from
# database.
if self._is_note_row(row):
item = self.item(row, self.COL_TITLE)
with Session() as session:
note_object = self._get_row_notes_object(row, session)
if note_object:
item.setText(note_object.note)
def _clear_current_track_row(self) -> None:
"""
Clear current row if there is one.
@ -1066,14 +1104,15 @@ class PlaylistTab(QTableWidget):
@staticmethod
def _get_note_text_time(text: str) -> Optional[datetime]:
"""Return time specified at the end of text"""
"""Return time specified as @hh:mm:ss in text"""
match = start_time_re.search(text)
if not match:
return None
try:
time_length = len(Config.NOTE_TIME_FORMAT)
return datetime.strptime(
text[(-time_length):],
Config.NOTE_TIME_FORMAT
)
return datetime.strptime(match.group(0)[1:],
Config.NOTE_TIME_FORMAT)
except ValueError:
return None
@ -1231,6 +1270,16 @@ class PlaylistTab(QTableWidget):
and pos.y() >= rect.center().y() # noqa W503
)
def _is_note_row(self, row: int) -> bool:
"""
Return True if passed row is a note row, else False
"""
if self._meta_get(row):
if self._meta_get(row) & (1 << RowMeta.NOTE):
return True
return False
def _meta_clear_attribute(self, row: int, attribute: int) -> None:
"""Clear given metadata for row"""
@ -1502,6 +1551,21 @@ class PlaylistTab(QTableWidget):
item: QTableWidgetItem = QTableWidgetItem(time_str)
self.setItem(row, self.COL_START_TIME, item)
def _set_timed_section(self, session, start_row, ms, no_end=False):
"""Add duration to a marked section"""
duration = helpers.ms_to_mmss(ms)
note_object = self._get_row_notes_object(start_row, session)
if not note_object:
ERROR("Can't get note_object in playlists._set_timed_section")
note_text = note_object.note
caveat = ""
if no_end:
caveat = " (to end of playlist)"
display_text = note_text + ' [' + duration + caveat + ']'
item = self.item(start_row, self.COL_TITLE)
item.setText(display_text)
def _update_row(self, session, row: int, track: Tracks) -> None:
"""
Update the passed row with info from the passed track.