Add section timing
This commit is contained in:
parent
ca385dcf54
commit
0fb1536055
@ -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.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user