WIP V3: check track already present in playlist when adding
This commit is contained in:
parent
3cab9f737c
commit
b1442b2c7d
@ -79,8 +79,6 @@ class MusicMusterSignals(QObject):
|
||||
https://refactoring.guru/design-patterns/singleton/python/example#example-0
|
||||
"""
|
||||
|
||||
add_track_to_header_signal = pyqtSignal(int, int, int)
|
||||
add_track_to_playlist_signal = pyqtSignal(int, int, int, str)
|
||||
begin_reset_model_signal = pyqtSignal(int)
|
||||
enable_escape_signal = pyqtSignal(bool)
|
||||
end_reset_model_signal = pyqtSignal(int)
|
||||
|
||||
@ -6,10 +6,12 @@ from PyQt6.QtWidgets import QDialog, QListWidgetItem
|
||||
from classes import MusicMusterSignals
|
||||
from dbconfig import scoped_session
|
||||
from helpers import (
|
||||
ask_yes_no,
|
||||
get_relative_date,
|
||||
ms_to_mmss,
|
||||
)
|
||||
from models import Settings, Tracks
|
||||
from playlistmodel import PlaylistModel
|
||||
from ui.dlg_TrackSelect_ui import Ui_Dialog # type: ignore
|
||||
|
||||
|
||||
@ -20,7 +22,7 @@ class TrackSelectDialog(QDialog):
|
||||
self,
|
||||
session: scoped_session,
|
||||
new_row_number: int,
|
||||
playlist_id: int,
|
||||
model: PlaylistModel,
|
||||
add_to_header: Optional[bool] = False,
|
||||
*args,
|
||||
**kwargs,
|
||||
@ -32,7 +34,7 @@ class TrackSelectDialog(QDialog):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.session = session
|
||||
self.new_row_number = new_row_number
|
||||
self.playlist_id = playlist_id
|
||||
self.model = model
|
||||
self.add_to_header = add_to_header
|
||||
self.ui = Ui_Dialog()
|
||||
self.ui.setupUi(self)
|
||||
@ -73,14 +75,30 @@ class TrackSelectDialog(QDialog):
|
||||
track_id = None
|
||||
if track:
|
||||
track_id = track.id
|
||||
if self.add_to_header:
|
||||
self.signals.add_track_to_header_signal.emit(
|
||||
self.playlist_id, self.new_row_number, track_id
|
||||
)
|
||||
else:
|
||||
self.signals.add_track_to_playlist_signal.emit(
|
||||
self.playlist_id, self.new_row_number, track_id, note
|
||||
)
|
||||
return
|
||||
# Check whether track is already in playlist
|
||||
move_existing = False
|
||||
existing_prd = self.model.is_track_in_playlist(track_id)
|
||||
if existing_prd is not None:
|
||||
if ask_yes_no(
|
||||
"Duplicate row",
|
||||
"Track already in playlist. " "Move to new location?",
|
||||
default_yes=True,
|
||||
):
|
||||
move_existing = True
|
||||
if self.add_to_header and existing_prd: # and existing_prd for mypy's benefit
|
||||
if move_existing:
|
||||
self.model.move_track_to_header(self.new_row_number, existing_prd, note)
|
||||
else:
|
||||
self.model.add_track_to_header(self.new_row_number, track_id)
|
||||
# Close dialog - we can only add one track to a header
|
||||
self.accept()
|
||||
else:
|
||||
if move_existing and existing_prd: # and existing_prd for mypy's benefit
|
||||
self.model.move_track_add_note(self.new_row_number, existing_prd, note)
|
||||
else:
|
||||
self.model.insert_row(self.new_row_number, track_id, note)
|
||||
|
||||
def add_selected_and_close(self) -> None:
|
||||
"""Handle Add and Close button"""
|
||||
|
||||
@ -148,11 +148,11 @@ class ImportTrack(QObject):
|
||||
import_finished = pyqtSignal()
|
||||
|
||||
def __init__(
|
||||
self, filenames: List[str], playlist_id: int, row_number: Optional[int]
|
||||
self, filenames: List[str], model: PlaylistModel, row_number: Optional[int]
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.filenames = filenames
|
||||
self.playlist_id = playlist_id
|
||||
self.model = model
|
||||
self.next_row_number = row_number
|
||||
self.signals = MusicMusterSignals()
|
||||
|
||||
@ -179,9 +179,7 @@ class ImportTrack(QObject):
|
||||
# previous additions in this loop. So, commit now to
|
||||
# lock in what we've just done.
|
||||
session.commit()
|
||||
self.signals.add_track_to_playlist_signal.emit(
|
||||
self.playlist_id, self.next_row_number, track.id, ""
|
||||
)
|
||||
self.model.insert_row(self.next_row_number, track.id, "")
|
||||
self.next_row_number += 1
|
||||
self.signals.status_message_signal.emit(
|
||||
f"{len(self.filenames)} tracks imported", 10000
|
||||
@ -532,8 +530,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
self.actionSelect_duplicate_rows.triggered.connect(
|
||||
lambda: self.active_tab().select_duplicate_rows()
|
||||
)
|
||||
self.actionSelect_next_track.triggered.connect(self.select_next_row)
|
||||
self.actionSelect_previous_track.triggered.connect(self.select_previous_row)
|
||||
self.actionMoveUnplayed.triggered.connect(self.move_unplayed)
|
||||
self.actionSetNext.triggered.connect(self.set_selected_track_next)
|
||||
self.actionSkipToNext.triggered.connect(self.play_next)
|
||||
@ -832,8 +828,8 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
self.import_thread = QThread()
|
||||
self.worker = ImportTrack(
|
||||
new_tracks,
|
||||
self.active_tab().playlist_id,
|
||||
self.active_tab().get_selected_row_number(),
|
||||
self.active_model(),
|
||||
self.active_tab().selected_model_row_number(),
|
||||
)
|
||||
self.worker.moveToThread(self.import_thread)
|
||||
self.import_thread.started.connect(self.worker.run)
|
||||
@ -871,8 +867,8 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
with Session() as session:
|
||||
dlg = TrackSelectDialog(
|
||||
session=session,
|
||||
new_row_number=self.active_tab().get_selected_row_number(),
|
||||
playlist_id=self.active_tab().playlist_id,
|
||||
new_row_number=self.active_tab().selected_model_row_number(),
|
||||
model=self.active_model()
|
||||
)
|
||||
dlg.exec()
|
||||
|
||||
@ -893,7 +889,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
Display songfacts page for title in highlighted row
|
||||
"""
|
||||
|
||||
row_number = self.active_tab().get_selected_row_number()
|
||||
row_number = self.active_tab().selected_model_row_number()
|
||||
if row_number is None:
|
||||
return
|
||||
|
||||
@ -908,7 +904,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
Display Wikipedia page for title in highlighted row
|
||||
"""
|
||||
|
||||
row_number = self.active_tab().get_selected_row_number()
|
||||
row_number = self.active_tab().selected_model_row_number()
|
||||
if row_number is None:
|
||||
return
|
||||
|
||||
|
||||
@ -124,8 +124,6 @@ class PlaylistModel(QAbstractTableModel):
|
||||
self.signals = MusicMusterSignals()
|
||||
self.played_tracks_hidden = False
|
||||
|
||||
self.signals.add_track_to_header_signal.connect(self.add_track_to_header)
|
||||
self.signals.add_track_to_playlist_signal.connect(self.add_track)
|
||||
self.signals.begin_reset_model_signal.connect(self.begin_reset_model)
|
||||
self.signals.end_reset_model_signal.connect(self.end_reset_model)
|
||||
self.signals.row_order_changed_signal.connect(self.row_order_changed)
|
||||
@ -142,45 +140,22 @@ class PlaylistModel(QAbstractTableModel):
|
||||
f"<PlaylistModel: playlist_id={self.playlist_id}, {self.rowCount()} rows>"
|
||||
)
|
||||
|
||||
def add_track(
|
||||
self,
|
||||
playlist_id: int,
|
||||
new_row_number: int,
|
||||
track_id: Optional[int],
|
||||
note: Optional[str],
|
||||
) -> None:
|
||||
"""
|
||||
Add track if it's for our playlist
|
||||
"""
|
||||
|
||||
# Ignore if it's not for us
|
||||
if playlist_id != self.playlist_id:
|
||||
return
|
||||
|
||||
self.insert_row(
|
||||
proposed_row_number=new_row_number, track_id=track_id, note=note
|
||||
)
|
||||
|
||||
def add_track_to_header(
|
||||
self,
|
||||
playlist_id: int,
|
||||
row_number: int,
|
||||
track_id: int,
|
||||
note: Optional[str] = None
|
||||
) -> None:
|
||||
"""
|
||||
Add track to existing header row if it's for our playlist
|
||||
Add track to existing header row
|
||||
"""
|
||||
|
||||
# Ignore if it's not for us
|
||||
if playlist_id != self.playlist_id:
|
||||
return
|
||||
|
||||
# Get existing row
|
||||
try:
|
||||
prd = self.playlist_rows[row_number]
|
||||
except KeyError:
|
||||
log.error(
|
||||
f"KeyError in PlaylistModel:add_track_to_header ({playlist_id=}, "
|
||||
f"KeyError in PlaylistModel:add_track_to_header "
|
||||
f"{row_number=}, {track_id=}, {len(self.playlist_rows)=}"
|
||||
)
|
||||
return
|
||||
@ -195,6 +170,9 @@ class PlaylistModel(QAbstractTableModel):
|
||||
if plr:
|
||||
# Add track to PlaylistRows
|
||||
plr.track_id = track_id
|
||||
# Add any further note
|
||||
if note:
|
||||
plr.note += "\n" + note
|
||||
# Reset header row spanning
|
||||
self.signals.span_cells_signal.emit(
|
||||
row_number, HEADER_NOTES_COLUMN, 1, 1
|
||||
@ -723,7 +701,8 @@ class PlaylistModel(QAbstractTableModel):
|
||||
"""
|
||||
|
||||
self.dataChanged.emit(
|
||||
self.index(modified_row, 0), self.index(modified_row, self.columnCount() - 1)
|
||||
self.index(modified_row, 0),
|
||||
self.index(modified_row, self.columnCount() - 1),
|
||||
)
|
||||
|
||||
def invalidate_rows(self, modified_rows: List[int]) -> None:
|
||||
@ -734,6 +713,18 @@ class PlaylistModel(QAbstractTableModel):
|
||||
for modified_row in modified_rows:
|
||||
self.invalidate_row(modified_row)
|
||||
|
||||
def is_track_in_playlist(self, track_id: int) -> Optional[PlaylistRowData]:
|
||||
"""
|
||||
If this track_id is in the playlist, return the PlaylistRowData object
|
||||
else return None
|
||||
"""
|
||||
|
||||
for row_number in range(len(self.playlist_rows)):
|
||||
if self.playlist_rows[row_number].track_id == track_id:
|
||||
return self.playlist_rows[row_number]
|
||||
|
||||
return None
|
||||
|
||||
def mark_unplayed(self, row_numbers: List[int]) -> None:
|
||||
"""
|
||||
Mark row as unplayed
|
||||
@ -869,6 +860,39 @@ class PlaylistModel(QAbstractTableModel):
|
||||
self.signals.end_reset_model_signal.emit(to_playlist_id)
|
||||
self.update_track_times()
|
||||
|
||||
def move_track_add_note(
|
||||
self, new_row_number: int, existing_prd: PlaylistRowData, note: str
|
||||
) -> None:
|
||||
"""
|
||||
Move existing_prd track to new_row_number and append note to any existing note
|
||||
"""
|
||||
|
||||
if note:
|
||||
with Session() as session:
|
||||
plr = session.get(PlaylistRows, existing_prd.plrid)
|
||||
if plr:
|
||||
if plr.note:
|
||||
plr.note += "\n" + note
|
||||
else:
|
||||
plr.note = note
|
||||
|
||||
# Carry out the move outside of the session context to ensure
|
||||
# database updated with any note change
|
||||
self.move_rows([existing_prd.plr_rownum], new_row_number)
|
||||
|
||||
def move_track_to_header(
|
||||
self, header_row_number: int, existing_prd: PlaylistRowData, note: Optional[str]
|
||||
) -> None:
|
||||
"""
|
||||
Add the existing_prd track details to the existing header at header_row_number
|
||||
"""
|
||||
|
||||
if existing_prd.track_id:
|
||||
if note and existing_prd.note:
|
||||
note += "\n" + existing_prd.note
|
||||
self.add_track_to_header(header_row_number, existing_prd.track_id, note)
|
||||
self.delete_rows([existing_prd.plr_rownum])
|
||||
|
||||
def open_in_audacity(self, row_number: int) -> None:
|
||||
"""
|
||||
Open track at passed row number in Audacity
|
||||
@ -1338,6 +1362,9 @@ class PlaylistProxyModel(QSortFilterProxyModel):
|
||||
def is_played_row(self, row_number: int) -> bool:
|
||||
return self.playlist_model.is_played_row(row_number)
|
||||
|
||||
def is_track_in_playlist(self, track_id: int) -> Optional[PlaylistRowData]:
|
||||
return self.playlist_model.is_track_in_playlist(track_id)
|
||||
|
||||
def mark_unplayed(self, row_numbers: List[int]) -> None:
|
||||
return self.playlist_model.mark_unplayed(row_numbers)
|
||||
|
||||
@ -1351,6 +1378,16 @@ class PlaylistProxyModel(QSortFilterProxyModel):
|
||||
from_rows, to_row_number, to_playlist_id
|
||||
)
|
||||
|
||||
def move_track_add_note(
|
||||
self, new_row_number: int, existing_prd: PlaylistRowData, note: str
|
||||
) -> None:
|
||||
return self.playlist_model.move_track_add_note(new_row_number, existing_prd, note)
|
||||
|
||||
def move_track_to_header(
|
||||
self, header_row_number: int, existing_prd: PlaylistRowData, note: Optional[str]
|
||||
) -> None:
|
||||
return self.playlist_model.move_track_to_header(header_row_number, existing_prd)
|
||||
|
||||
def open_in_audacity(self, row_number: int) -> None:
|
||||
return self.playlist_model.open_in_audacity(row_number)
|
||||
|
||||
|
||||
@ -562,7 +562,7 @@ class PlaylistTab(QTableView):
|
||||
dlg = TrackSelectDialog(
|
||||
session=session,
|
||||
new_row_number=model_row_number,
|
||||
playlist_id=self.playlist_id,
|
||||
model=self.playlist_model,
|
||||
add_to_header=True,
|
||||
)
|
||||
dlg.exec()
|
||||
|
||||
@ -786,9 +786,6 @@ padding-left: 8px;</string>
|
||||
</property>
|
||||
<addaction name="actionSearch"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSelect_next_track"/>
|
||||
<addaction name="actionSelect_previous_track"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSearch_title_in_Wikipedia"/>
|
||||
<addaction name="actionSearch_title_in_Songfacts"/>
|
||||
</widget>
|
||||
|
||||
@ -493,9 +493,6 @@ class Ui_MainWindow(object):
|
||||
self.menuPlaylist.addAction(self.actionPaste)
|
||||
self.menuSearc_h.addAction(self.actionSearch)
|
||||
self.menuSearc_h.addSeparator()
|
||||
self.menuSearc_h.addAction(self.actionSelect_next_track)
|
||||
self.menuSearc_h.addAction(self.actionSelect_previous_track)
|
||||
self.menuSearc_h.addSeparator()
|
||||
self.menuSearc_h.addAction(self.actionSearch_title_in_Wikipedia)
|
||||
self.menuSearc_h.addAction(self.actionSearch_title_in_Songfacts)
|
||||
self.menuHelp.addAction(self.action_About)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user