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:
parent
4bff1a8b59
commit
712c965095
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -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()
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user