Clean up data structures in musicmuster.py

Replace self.playlists and self.selection with self.current and a new
Current() class
This commit is contained in:
Keith Edmunds 2024-12-28 17:16:19 +00:00
parent 4bff1a8b59
commit 712c965095
4 changed files with 55 additions and 66 deletions

View File

@ -93,13 +93,6 @@ class MusicMusterSignals(QObject):
super().__init__() super().__init__()
@singleton
@dataclass
class Selection:
playlist_id: int = 0
rows: list[int] = field(default_factory=list)
class Tags(NamedTuple): class Tags(NamedTuple):
artist: str artist: str
title: str title: str

View File

@ -49,7 +49,6 @@ import stackprinter # type: ignore
# App imports # App imports
from classes import ( from classes import (
MusicMusterSignals, MusicMusterSignals,
Selection,
TrackInfo, TrackInfo,
) )
from config import Config from config import Config
@ -81,13 +80,17 @@ class DownloadCSV(QDialog):
self.ui.buttonBox.rejected.connect(self.reject) self.ui.buttonBox.rejected.connect(self.reject)
@dataclass class Current:
class PlaylistData:
base_model: PlaylistModel base_model: PlaylistModel
proxy_model: PlaylistProxyModel proxy_model: PlaylistProxyModel
playlist_id: int = 0
selected_rows: list[int] = field(default_factory=list)
def __post_init__(self): def __repr__(self):
self.proxy_model.setSourceModel(self.base_model) return (
f"<Current(base_model={self.base_model}, proxy_model={self.proxy_model}, "
f"playlist_id={self.playlist_id}, selected_rows={self.selected_rows}>"
)
class PreviewManager: class PreviewManager:
@ -286,8 +289,7 @@ class Window(QMainWindow, Ui_MainWindow):
self.connect_signals_slots() self.connect_signals_slots()
self.catch_return_key = False self.catch_return_key = False
self.importer: Optional[FileImporter] = None self.importer: Optional[FileImporter] = None
self.selection = Selection() self.current = Current()
self.playlists: dict[int, PlaylistData] = {}
if not Config.USE_INTERNAL_BROWSER: if not Config.USE_INTERNAL_BROWSER:
webbrowser.register( webbrowser.register(
@ -325,7 +327,7 @@ class Window(QMainWindow, Ui_MainWindow):
) )
def active_base_model(self) -> PlaylistModel: def active_base_model(self) -> PlaylistModel:
return self.playlists[self.selection.playlist_id].base_model return self.current.base_model
def active_tab(self) -> PlaylistTab: def active_tab(self) -> PlaylistTab:
return self.tabPlaylist.currentWidget() return self.tabPlaylist.currentWidget()
@ -551,24 +553,21 @@ class Window(QMainWindow, Ui_MainWindow):
log.debug(f"create_playlist_tab({playlist=})") log.debug(f"create_playlist_tab({playlist=})")
# Create model and proxy model # Create model and proxy model
self.playlists[playlist.id] = PlaylistData( base_model = PlaylistModel(playlist.id)
base_model=PlaylistModel(playlist.id), proxy_model=PlaylistProxyModel() proxy_model = PlaylistProxyModel()
) proxy_model.setSourceModel(base_model)
# Create tab # Create tab
playlist_tab = PlaylistTab( playlist_tab = PlaylistTab(musicmuster=self, model=proxy_model)
musicmuster=self, model=self.playlists[playlist.id].proxy_model
)
idx = self.tabPlaylist.addTab(playlist_tab, playlist.name) idx = self.tabPlaylist.addTab(playlist_tab, playlist.name)
log.debug(f"create_playlist_tab() returned: {idx=}") log.debug(f"create_playlist_tab() returned: {idx=}")
return idx return idx
def debug(self): def debug(self):
"""Invoke debugger""" """Invoke debugger"""
visible_playlist_id = self.selection.playlist_id
print(f"Active playlist id={visible_playlist_id}")
import ipdb # type: ignore import ipdb # type: ignore
ipdb.set_trace() ipdb.set_trace()
@ -579,7 +578,7 @@ class Window(QMainWindow, Ui_MainWindow):
""" """
with db.Session() as session: with db.Session() as session:
playlist_id = self.selection.playlist_id playlist_id = self.current.playlist_id
playlist = session.get(Playlists, playlist_id) playlist = session.get(Playlists, playlist_id)
if playlist: if playlist:
if helpers.ask_yes_no( if helpers.ask_yes_no(
@ -655,7 +654,7 @@ class Window(QMainWindow, Ui_MainWindow):
track_sequence.current = None track_sequence.current = None
# Tell playlist previous track has finished # Tell playlist previous track has finished
self.active_base_model().previous_track_ended() self.current.base_model.previous_track_ended()
# Reset clocks # Reset clocks
self.frame_fade.setStyleSheet("") self.frame_fade.setStyleSheet("")
@ -677,7 +676,7 @@ class Window(QMainWindow, Ui_MainWindow):
def export_playlist_tab(self) -> None: def export_playlist_tab(self) -> None:
"""Export the current playlist to an m3u file""" """Export the current playlist to an m3u file"""
playlist_id = self.selection.playlist_id playlist_id = self.current.playlist_id
with db.Session() as session: with db.Session() as session:
# Get output filename # Get output filename
@ -726,7 +725,7 @@ class Window(QMainWindow, Ui_MainWindow):
if self.hide_played_tracks: if self.hide_played_tracks:
self.hide_played_tracks = False self.hide_played_tracks = False
self.active_base_model().hide_played_tracks(False) self.current.base_model.hide_played_tracks(False)
self.btnHidePlayed.setText("Hide played") self.btnHidePlayed.setText("Hide played")
else: else:
self.hide_played_tracks = True self.hide_played_tracks = True
@ -734,7 +733,7 @@ class Window(QMainWindow, Ui_MainWindow):
if Config.HIDE_PLAYED_MODE == Config.HIDE_PLAYED_MODE_SECTIONS: if Config.HIDE_PLAYED_MODE == Config.HIDE_PLAYED_MODE_SECTIONS:
self.active_tab().hide_played_sections() self.active_tab().hide_played_sections()
else: else:
self.active_base_model().hide_played_tracks(True) self.current.base_model.hide_played_tracks(True)
# Reset row heights # Reset row heights
self.active_tab().resize_rows() self.active_tab().resize_rows()
@ -747,8 +746,8 @@ class Window(QMainWindow, Ui_MainWindow):
# We need to keep a reference to the FileImporter else it will be # We need to keep a reference to the FileImporter else it will be
# garbage collected while import threads are still running # garbage collected while import threads are still running
self.importer = FileImporter( self.importer = FileImporter(
self.active_base_model(), self.current.base_model,
self.selection.rows[0], self.current.selected_rows[0],
) )
self.importer.do_import() self.importer.do_import()
@ -762,24 +761,24 @@ class Window(QMainWindow, Ui_MainWindow):
dlg.resize(500, 100) dlg.resize(500, 100)
ok = dlg.exec() ok = dlg.exec()
if ok: if ok:
self.active_base_model().insert_row( self.current.base_model.insert_row(
proposed_row_number=self.selection.rows[0], proposed_row_number=self.current.selected_rows[0],
note=dlg.textValue(), note=dlg.textValue(),
) )
def insert_track(self) -> None: def insert_track(self) -> None:
"""Show dialog box to select and add track from database""" """Show dialog box to select and add track from database"""
if self.selection.rows: if self.current.selected_rows:
new_row_number = self.selection.rows[0] new_row_number = self.current.selected_rows[0]
else: else:
new_row_number = self.active_base_model().rowCount() new_row_number = self.current.base_model.rowCount()
with db.Session() as session: with db.Session() as session:
dlg = TrackSelectDialog( dlg = TrackSelectDialog(
parent=self, parent=self,
session=session, session=session,
new_row_number=new_row_number, new_row_number=new_row_number,
base_model=self.active_base_model(), base_model=self.current.base_model,
) )
dlg.exec() dlg.exec()
session.commit() session.commit()
@ -836,8 +835,8 @@ class Window(QMainWindow, Ui_MainWindow):
# Save the selected PlaylistRows items ready for a later # Save the selected PlaylistRows items ready for a later
# paste # paste
self.move_source_rows = self.selection.rows self.move_source_rows = self.current.selected_rows
self.move_source_model = self.active_base_model() self.move_source_model = self.current.base_model
log.debug( log.debug(
f"mark_rows_for_moving(): {self.move_source_rows=} {self.move_source_model=}" f"mark_rows_for_moving(): {self.move_source_rows=} {self.move_source_model=}"
@ -850,7 +849,7 @@ class Window(QMainWindow, Ui_MainWindow):
# Identify destination playlist # Identify destination playlist
playlists = [] playlists = []
source_playlist_id = self.selection.playlist_id source_playlist_id = self.current.playlist_id
with db.Session() as session: with db.Session() as session:
for playlist in Playlists.get_all(session): for playlist in Playlists.get_all(session):
@ -873,7 +872,7 @@ class Window(QMainWindow, Ui_MainWindow):
to_row = 0 to_row = 0
# Move rows # Move rows
self.active_base_model().move_rows_between_playlists( self.current.base_model.move_rows_between_playlists(
row_numbers, to_row, to_playlist_id row_numbers, to_row, to_playlist_id
) )
@ -892,7 +891,7 @@ class Window(QMainWindow, Ui_MainWindow):
Move selected rows to another playlist Move selected rows to another playlist
""" """
selected_rows = self.selection.rows selected_rows = self.current.selected_rows
if not selected_rows: if not selected_rows:
return return
@ -903,7 +902,7 @@ class Window(QMainWindow, Ui_MainWindow):
Move unplayed rows to another playlist Move unplayed rows to another playlist
""" """
unplayed_rows = self.active_base_model().get_unplayed_rows() unplayed_rows = self.current.base_model.get_unplayed_rows()
if not unplayed_rows: if not unplayed_rows:
return return
# We can get a race condition as selected rows change while # We can get a race condition as selected rows change while
@ -986,12 +985,12 @@ class Window(QMainWindow, Ui_MainWindow):
if not self.move_source_rows or not self.move_source_model: if not self.move_source_rows or not self.move_source_model:
return return
to_playlist_model = self.active_base_model() to_playlist_model = self.current.base_model
selected_rows = self.selection.rows selected_rows = self.current.selected_rows
if selected_rows: if selected_rows:
destination_row = selected_rows[0] destination_row = selected_rows[0]
else: else:
destination_row = self.active_base_model().rowCount() destination_row = self.current.base_model.rowCount()
# If we move a row to immediately under the current track, make # If we move a row to immediately under the current track, make
# that moved row the next track # that moved row the next track
@ -1176,8 +1175,8 @@ class Window(QMainWindow, Ui_MainWindow):
track.intro = intro track.intro = intro
session.commit() session.commit()
self.preview_manager.set_intro(intro) self.preview_manager.set_intro(intro)
self.active_base_model().refresh_row(session, row_number) self.current.base_model.refresh_row(session, row_number)
self.active_base_model().invalidate_row(row_number) self.current.base_model.invalidate_row(row_number)
def preview_start(self) -> None: def preview_start(self) -> None:
"""Restart preview""" """Restart preview"""
@ -1206,7 +1205,7 @@ class Window(QMainWindow, Ui_MainWindow):
""" """
with db.Session() as session: with db.Session() as session:
playlist_id = self.selection.playlist_id playlist_id = self.current.playlist_id
playlist = session.get(Playlists, playlist_id) playlist = session.get(Playlists, playlist_id)
if playlist: if playlist:
new_name = self.solicit_playlist_name(session, playlist.name) new_name = self.solicit_playlist_name(session, playlist.name)
@ -1320,7 +1319,7 @@ class Window(QMainWindow, Ui_MainWindow):
self, "Duplicate template", "Template name already in use" self, "Duplicate template", "Template name already in use"
) )
Playlists.save_as_template( Playlists.save_as_template(
session, self.selection.playlist_id, template_name session, self.current.playlist_id, template_name
) )
session.commit() session.commit()
helpers.show_OK(self, "Template", "Template saved") helpers.show_OK(self, "Template", "Template saved")
@ -1348,9 +1347,7 @@ class Window(QMainWindow, Ui_MainWindow):
Incremental search of playlist Incremental search of playlist
""" """
active_proxy_model = self.playlists[self.selection.playlist_id].proxy_model self.current.proxy_model.set_incremental_search(self.txtSearch.text())
active_proxy_model.set_incremental_search(self.txtSearch.text())
def selected_or_next_track_info(self) -> Optional[RowAndTrack]: def selected_or_next_track_info(self) -> Optional[RowAndTrack]:
""" """
@ -1358,7 +1355,7 @@ class Window(QMainWindow, Ui_MainWindow):
next track. If no next track, return None. next track. If no next track, return None.
""" """
row_number = self.selection.rows[0] row_number = self.current.selected_rows[0]
if row_number is None: if row_number is None:
if track_sequence.next: if track_sequence.next:
if track_sequence.next.track_id: if track_sequence.next.track_id:
@ -1366,7 +1363,7 @@ class Window(QMainWindow, Ui_MainWindow):
if row_number is None: if row_number is None:
return None return None
track_info = self.active_base_model().get_row_info(row_number) track_info = self.current.base_model.get_row_info(row_number)
if track_info is None: if track_info is None:
return None return None
@ -1449,7 +1446,7 @@ class Window(QMainWindow, Ui_MainWindow):
return return
# Switch to correct tab # Switch to correct tab
if playlist_id != self.selection.playlist_id: if playlist_id != self.current.playlist_id:
for idx in range(self.tabPlaylist.count()): for idx in range(self.tabPlaylist.count()):
if self.tabPlaylist.widget(idx).playlist_id == playlist_id: if self.tabPlaylist.widget(idx).playlist_id == playlist_id:
self.tabPlaylist.setCurrentIndex(idx) self.tabPlaylist.setCurrentIndex(idx)

View File

@ -1671,7 +1671,7 @@ class PlaylistProxyModel(QSortFilterProxyModel):
self.setFilterKeyColumn(-1) self.setFilterKeyColumn(-1)
def __repr__(self) -> str: def __repr__(self) -> str:
return f"<PlaylistProxyModel: sourceModel={self.sourceModel}>" return f"<PlaylistProxyModel: sourceModel={self.sourceModel()}>"
def filterAcceptsRow(self, source_row: int, source_parent: QModelIndex) -> bool: def filterAcceptsRow(self, source_row: int, source_parent: QModelIndex) -> bool:
""" """

View File

@ -37,7 +37,7 @@ import line_profiler
# App imports # App imports
from audacity_controller import AudacityController from audacity_controller import AudacityController
from classes import ApplicationError, Col, MusicMusterSignals, Selection, TrackInfo from classes import ApplicationError, Col, MusicMusterSignals, TrackInfo
from config import Config from config import Config
from dialogs import TrackSelectDialog from dialogs import TrackSelectDialog
from helpers import ( from helpers import (
@ -295,9 +295,8 @@ class PlaylistTab(QTableView):
super().__init__() super().__init__()
# Save passed settings # Save passed settings
self.musicmuster = ( self.musicmuster = musicmuster
musicmuster # TODO: do we need to keep a reference to musicmuster?
)
self.playlist_id = model.sourceModel().playlist_id self.playlist_id = model.sourceModel().playlist_id
# Set up widget # Set up widget
@ -329,9 +328,6 @@ class PlaylistTab(QTableView):
self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
# Singleton object to store selection
self.selection = Selection()
# Set up for Audacity # Set up for Audacity
try: try:
self.ac: Optional[AudacityController] = AudacityController() self.ac: Optional[AudacityController] = AudacityController()
@ -487,7 +483,7 @@ class PlaylistTab(QTableView):
""" """
selected_rows = self.get_selected_rows() selected_rows = self.get_selected_rows()
self.selection.rows = selected_rows self.musicmuster.current.selected_rows = selected_rows
# If no rows are selected, we have nothing to do # If no rows are selected, we have nothing to do
if len(selected_rows) == 0: if len(selected_rows) == 0:
@ -1115,8 +1111,11 @@ class PlaylistTab(QTableView):
Called when tab gets focus Called when tab gets focus
""" """
self.selection.playlist_id = self.playlist_id # Update musicmuster
self.selection.rows = self.get_selected_rows() self.musicmuster.current.playlist_id = self.playlist_id
self.musicmuster.current.selected_rows = self.get_selected_rows()
self.musicmuster.current.base_model = self.get_base_model()
self.musicmuster.current.proxy_model = self.model()
self.resize_rows() self.resize_rows()