diff --git a/app/classes.py b/app/classes.py index ffaae87..713eb86 100644 --- a/app/classes.py +++ b/app/classes.py @@ -93,13 +93,6 @@ class MusicMusterSignals(QObject): super().__init__() -@singleton -@dataclass -class Selection: - playlist_id: int = 0 - rows: list[int] = field(default_factory=list) - - class Tags(NamedTuple): artist: str title: str diff --git a/app/musicmuster.py b/app/musicmuster.py index 043d46f..760abae 100755 --- a/app/musicmuster.py +++ b/app/musicmuster.py @@ -49,7 +49,6 @@ import stackprinter # type: ignore # App imports from classes import ( MusicMusterSignals, - Selection, TrackInfo, ) from config import Config @@ -81,13 +80,17 @@ class DownloadCSV(QDialog): self.ui.buttonBox.rejected.connect(self.reject) -@dataclass -class PlaylistData: +class Current: base_model: PlaylistModel proxy_model: PlaylistProxyModel + playlist_id: int = 0 + selected_rows: list[int] = field(default_factory=list) - def __post_init__(self): - self.proxy_model.setSourceModel(self.base_model) + def __repr__(self): + return ( + f"" + ) class PreviewManager: @@ -286,8 +289,7 @@ class Window(QMainWindow, Ui_MainWindow): self.connect_signals_slots() self.catch_return_key = False self.importer: Optional[FileImporter] = None - self.selection = Selection() - self.playlists: dict[int, PlaylistData] = {} + self.current = Current() if not Config.USE_INTERNAL_BROWSER: webbrowser.register( @@ -325,7 +327,7 @@ class Window(QMainWindow, Ui_MainWindow): ) 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: return self.tabPlaylist.currentWidget() @@ -551,24 +553,21 @@ class Window(QMainWindow, Ui_MainWindow): log.debug(f"create_playlist_tab({playlist=})") # Create model and proxy model - self.playlists[playlist.id] = PlaylistData( - base_model=PlaylistModel(playlist.id), proxy_model=PlaylistProxyModel() - ) + base_model = PlaylistModel(playlist.id) + proxy_model = PlaylistProxyModel() + proxy_model.setSourceModel(base_model) # Create tab - playlist_tab = PlaylistTab( - musicmuster=self, model=self.playlists[playlist.id].proxy_model - ) + playlist_tab = PlaylistTab(musicmuster=self, model=proxy_model) idx = self.tabPlaylist.addTab(playlist_tab, playlist.name) log.debug(f"create_playlist_tab() returned: {idx=}") + return idx def debug(self): """Invoke debugger""" - visible_playlist_id = self.selection.playlist_id - print(f"Active playlist id={visible_playlist_id}") import ipdb # type: ignore ipdb.set_trace() @@ -579,7 +578,7 @@ class Window(QMainWindow, Ui_MainWindow): """ with db.Session() as session: - playlist_id = self.selection.playlist_id + playlist_id = self.current.playlist_id playlist = session.get(Playlists, playlist_id) if playlist: if helpers.ask_yes_no( @@ -655,7 +654,7 @@ class Window(QMainWindow, Ui_MainWindow): track_sequence.current = None # Tell playlist previous track has finished - self.active_base_model().previous_track_ended() + self.current.base_model.previous_track_ended() # Reset clocks self.frame_fade.setStyleSheet("") @@ -677,7 +676,7 @@ class Window(QMainWindow, Ui_MainWindow): def export_playlist_tab(self) -> None: """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: # Get output filename @@ -726,7 +725,7 @@ class Window(QMainWindow, Ui_MainWindow): if self.hide_played_tracks: 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") else: self.hide_played_tracks = True @@ -734,7 +733,7 @@ class Window(QMainWindow, Ui_MainWindow): if Config.HIDE_PLAYED_MODE == Config.HIDE_PLAYED_MODE_SECTIONS: self.active_tab().hide_played_sections() else: - self.active_base_model().hide_played_tracks(True) + self.current.base_model.hide_played_tracks(True) # Reset row heights 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 # garbage collected while import threads are still running self.importer = FileImporter( - self.active_base_model(), - self.selection.rows[0], + self.current.base_model, + self.current.selected_rows[0], ) self.importer.do_import() @@ -762,24 +761,24 @@ class Window(QMainWindow, Ui_MainWindow): dlg.resize(500, 100) ok = dlg.exec() if ok: - self.active_base_model().insert_row( - proposed_row_number=self.selection.rows[0], + self.current.base_model.insert_row( + proposed_row_number=self.current.selected_rows[0], note=dlg.textValue(), ) def insert_track(self) -> None: """Show dialog box to select and add track from database""" - if self.selection.rows: - new_row_number = self.selection.rows[0] + if self.current.selected_rows: + new_row_number = self.current.selected_rows[0] else: - new_row_number = self.active_base_model().rowCount() + new_row_number = self.current.base_model.rowCount() with db.Session() as session: dlg = TrackSelectDialog( parent=self, session=session, new_row_number=new_row_number, - base_model=self.active_base_model(), + base_model=self.current.base_model, ) dlg.exec() session.commit() @@ -836,8 +835,8 @@ class Window(QMainWindow, Ui_MainWindow): # Save the selected PlaylistRows items ready for a later # paste - self.move_source_rows = self.selection.rows - self.move_source_model = self.active_base_model() + self.move_source_rows = self.current.selected_rows + self.move_source_model = self.current.base_model log.debug( 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 playlists = [] - source_playlist_id = self.selection.playlist_id + source_playlist_id = self.current.playlist_id with db.Session() as session: for playlist in Playlists.get_all(session): @@ -873,7 +872,7 @@ class Window(QMainWindow, Ui_MainWindow): to_row = 0 # 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 ) @@ -892,7 +891,7 @@ class Window(QMainWindow, Ui_MainWindow): Move selected rows to another playlist """ - selected_rows = self.selection.rows + selected_rows = self.current.selected_rows if not selected_rows: return @@ -903,7 +902,7 @@ class Window(QMainWindow, Ui_MainWindow): 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: return # 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: return - to_playlist_model = self.active_base_model() - selected_rows = self.selection.rows + to_playlist_model = self.current.base_model + selected_rows = self.current.selected_rows if selected_rows: destination_row = selected_rows[0] 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 # that moved row the next track @@ -1176,8 +1175,8 @@ class Window(QMainWindow, Ui_MainWindow): track.intro = intro session.commit() self.preview_manager.set_intro(intro) - self.active_base_model().refresh_row(session, row_number) - self.active_base_model().invalidate_row(row_number) + self.current.base_model.refresh_row(session, row_number) + self.current.base_model.invalidate_row(row_number) def preview_start(self) -> None: """Restart preview""" @@ -1206,7 +1205,7 @@ class Window(QMainWindow, Ui_MainWindow): """ with db.Session() as session: - playlist_id = self.selection.playlist_id + playlist_id = self.current.playlist_id playlist = session.get(Playlists, playlist_id) if playlist: 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" ) Playlists.save_as_template( - session, self.selection.playlist_id, template_name + session, self.current.playlist_id, template_name ) session.commit() helpers.show_OK(self, "Template", "Template saved") @@ -1348,9 +1347,7 @@ class Window(QMainWindow, Ui_MainWindow): Incremental search of playlist """ - active_proxy_model = self.playlists[self.selection.playlist_id].proxy_model - - active_proxy_model.set_incremental_search(self.txtSearch.text()) + self.current.proxy_model.set_incremental_search(self.txtSearch.text()) 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. """ - row_number = self.selection.rows[0] + row_number = self.current.selected_rows[0] if row_number is None: if track_sequence.next: if track_sequence.next.track_id: @@ -1366,7 +1363,7 @@ class Window(QMainWindow, Ui_MainWindow): if row_number is 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: return None @@ -1449,7 +1446,7 @@ class Window(QMainWindow, Ui_MainWindow): return # 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()): if self.tabPlaylist.widget(idx).playlist_id == playlist_id: self.tabPlaylist.setCurrentIndex(idx) diff --git a/app/playlistmodel.py b/app/playlistmodel.py index 20e8747..5cc74e6 100644 --- a/app/playlistmodel.py +++ b/app/playlistmodel.py @@ -1671,7 +1671,7 @@ class PlaylistProxyModel(QSortFilterProxyModel): self.setFilterKeyColumn(-1) def __repr__(self) -> str: - return f"" + return f"" def filterAcceptsRow(self, source_row: int, source_parent: QModelIndex) -> bool: """ diff --git a/app/playlists.py b/app/playlists.py index 2b71e67..5daec74 100644 --- a/app/playlists.py +++ b/app/playlists.py @@ -37,7 +37,7 @@ import line_profiler # App imports 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 dialogs import TrackSelectDialog from helpers import ( @@ -295,9 +295,8 @@ class PlaylistTab(QTableView): super().__init__() # Save passed settings - self.musicmuster = ( - musicmuster # TODO: do we need to keep a reference to musicmuster? - ) + self.musicmuster = musicmuster + self.playlist_id = model.sourceModel().playlist_id # Set up widget @@ -329,9 +328,6 @@ class PlaylistTab(QTableView): self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) - # Singleton object to store selection - self.selection = Selection() - # Set up for Audacity try: self.ac: Optional[AudacityController] = AudacityController() @@ -487,7 +483,7 @@ class PlaylistTab(QTableView): """ 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 len(selected_rows) == 0: @@ -1115,8 +1111,11 @@ class PlaylistTab(QTableView): Called when tab gets focus """ - self.selection.playlist_id = self.playlist_id - self.selection.rows = self.get_selected_rows() + # Update musicmuster + 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()