Name source and proxy models consistently

This commit is contained in:
Keith Edmunds 2023-12-16 02:36:16 +00:00
parent 45243759b8
commit b74007119d
4 changed files with 117 additions and 133 deletions

View File

@ -22,7 +22,7 @@ class TrackSelectDialog(QDialog):
self, self,
session: scoped_session, session: scoped_session,
new_row_number: int, new_row_number: int,
model: PlaylistModel, source_model: PlaylistModel,
add_to_header: Optional[bool] = False, add_to_header: Optional[bool] = False,
*args, *args,
**kwargs, **kwargs,
@ -34,7 +34,7 @@ class TrackSelectDialog(QDialog):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.session = session self.session = session
self.new_row_number = new_row_number self.new_row_number = new_row_number
self.model = model self.source_model = source_model
self.add_to_header = add_to_header self.add_to_header = add_to_header
self.ui = Ui_Dialog() self.ui = Ui_Dialog()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -75,7 +75,7 @@ class TrackSelectDialog(QDialog):
if not track_id: if not track_id:
if note: if note:
self.model.insert_row(self.new_row_number, track_id, note) self.source_model.insert_row(self.new_row_number, track_id, note)
self.ui.txtNote.clear() self.ui.txtNote.clear()
return return
else: else:
@ -87,7 +87,7 @@ class TrackSelectDialog(QDialog):
# Check whether track is already in playlist # Check whether track is already in playlist
move_existing = False move_existing = False
existing_prd = self.model.is_track_in_playlist(track_id) existing_prd = self.source_model.is_track_in_playlist(track_id)
if existing_prd is not None: if existing_prd is not None:
if ask_yes_no( if ask_yes_no(
"Duplicate row", "Duplicate row",
@ -98,17 +98,17 @@ class TrackSelectDialog(QDialog):
if self.add_to_header: if self.add_to_header:
if move_existing and existing_prd: # "and existing_prd" for mypy's benefit if move_existing and existing_prd: # "and existing_prd" for mypy's benefit
self.model.move_track_to_header(self.new_row_number, existing_prd, note) self.source_model.move_track_to_header(self.new_row_number, existing_prd, note)
else: else:
self.model.add_track_to_header(self.new_row_number, track_id) self.source_model.add_track_to_header(self.new_row_number, track_id)
# Close dialog - we can only add one track to a header # Close dialog - we can only add one track to a header
self.accept() self.accept()
else: else:
# Adding a new track row # Adding a new track row
if move_existing and existing_prd: # "and existing_prd" for mypy's benefit 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) self.source_model.move_track_add_note(self.new_row_number, existing_prd, note)
else: else:
self.model.insert_row(self.new_row_number, track_id, note) self.source_model.insert_row(self.new_row_number, track_id, note)
def add_selected_and_close(self) -> None: def add_selected_and_close(self) -> None:
"""Handle Add and Close button""" """Handle Add and Close button"""

View File

@ -148,11 +148,11 @@ class ImportTrack(QObject):
import_finished = pyqtSignal() import_finished = pyqtSignal()
def __init__( def __init__(
self, filenames: List[str], model: PlaylistModel, row_number: Optional[int] self, filenames: List[str], source_model: PlaylistModel, row_number: Optional[int]
) -> None: ) -> None:
super().__init__() super().__init__()
self.filenames = filenames self.filenames = filenames
self.model = model self.source_model = source_model
self.next_row_number = row_number self.next_row_number = row_number
self.signals = MusicMusterSignals() self.signals = MusicMusterSignals()
@ -179,7 +179,7 @@ class ImportTrack(QObject):
# previous additions in this loop. So, commit now to # previous additions in this loop. So, commit now to
# lock in what we've just done. # lock in what we've just done.
session.commit() session.commit()
self.model.insert_row(self.next_row_number, track.id, "") self.source_model.insert_row(self.next_row_number, track.id, "")
self.next_row_number += 1 self.next_row_number += 1
self.signals.status_message_signal.emit( self.signals.status_message_signal.emit(
f"{len(self.filenames)} tracks imported", 10000 f"{len(self.filenames)} tracks imported", 10000
@ -216,11 +216,10 @@ class Window(QMainWindow, Ui_MainWindow):
FadeCurve.GraphWidget = self.widgetFadeVolume FadeCurve.GraphWidget = self.widgetFadeVolume
self.active_tab = lambda: self.tabPlaylist.currentWidget() self.active_tab = lambda: self.tabPlaylist.currentWidget()
self.active_model = lambda: self.tabPlaylist.currentWidget().model() self.active_proxy_model = lambda: self.tabPlaylist.currentWidget().model()
self.move_source_rows: Optional[List[int]] = None self.move_source_rows: Optional[List[int]] = None
self.move_source_model: Optional[PlaylistProxyModel] = None self.move_source_model: Optional[PlaylistProxyModel] = None
self.load_last_playlists()
if Config.CARTS_HIDE: if Config.CARTS_HIDE:
self.cartsWidget.hide() self.cartsWidget.hide()
self.frame_6.hide() self.frame_6.hide()
@ -603,7 +602,7 @@ 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.active_tab().get_selected_rows() self.move_source_rows = self.active_tab().get_selected_rows()
self.move_source_model = self.active_model() self.move_source_model = self.active_proxy_model()
def debug(self): def debug(self):
"""Invoke debugger""" """Invoke debugger"""
@ -758,11 +757,11 @@ 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_model().hide_played_tracks(False) self.active_proxy_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
self.active_model().hide_played_tracks(True) self.active_proxy_model().hide_played_tracks(True)
self.btnHidePlayed.setText("Show played") self.btnHidePlayed.setText("Show played")
def import_track(self) -> None: def import_track(self) -> None:
@ -828,8 +827,8 @@ class Window(QMainWindow, Ui_MainWindow):
self.import_thread = QThread() self.import_thread = QThread()
self.worker = ImportTrack( self.worker = ImportTrack(
new_tracks, new_tracks,
self.active_model(), self.active_proxy_model(),
self.active_tab().selected_model_row_number(), self.active_tab().source_model_selected_row_number(),
) )
self.worker.moveToThread(self.import_thread) self.worker.moveToThread(self.import_thread)
self.import_thread.started.connect(self.worker.run) self.import_thread.started.connect(self.worker.run)
@ -841,12 +840,8 @@ class Window(QMainWindow, Ui_MainWindow):
def insert_header(self) -> None: def insert_header(self) -> None:
"""Show dialog box to enter header text and add to playlist""" """Show dialog box to enter header text and add to playlist"""
try: proxy_model = self.active_proxy_model()
model = cast(PlaylistModel, self.active_tab().model()) if proxy_model is None:
if model is None:
return
except AttributeError:
# Just return if there's no visible playlist tab model
return return
# Get header text # Get header text
@ -856,8 +851,8 @@ class Window(QMainWindow, Ui_MainWindow):
dlg.resize(500, 100) dlg.resize(500, 100)
ok = dlg.exec() ok = dlg.exec()
if ok: if ok:
model.insert_row( proxy_model.insert_row(
proposed_row_number=self.active_tab().selected_model_row_number(), proposed_row_number=self.active_tab().source_model_selected_row_number(),
note=dlg.textValue(), note=dlg.textValue(),
) )
@ -867,8 +862,8 @@ class Window(QMainWindow, Ui_MainWindow):
with Session() as session: with Session() as session:
dlg = TrackSelectDialog( dlg = TrackSelectDialog(
session=session, session=session,
new_row_number=self.active_tab().selected_model_row_number(), new_row_number=self.active_tab().source_model_selected_row_number(),
model=self.active_model(), source_model=self.active_proxy_model(),
) )
dlg.exec() dlg.exec()
@ -897,11 +892,11 @@ class Window(QMainWindow, Ui_MainWindow):
Display songfacts page for title in highlighted row Display songfacts page for title in highlighted row
""" """
row_number = self.active_tab().selected_model_row_number() row_number = self.active_tab().source_model_selected_row_number()
if row_number is None: if row_number is None:
return return
track_info = self.active_model().get_row_info(row_number) track_info = self.active_proxy_model().get_row_info(row_number)
if track_info is None: if track_info is None:
return return
@ -912,11 +907,11 @@ class Window(QMainWindow, Ui_MainWindow):
Display Wikipedia page for title in highlighted row Display Wikipedia page for title in highlighted row
""" """
row_number = self.active_tab().selected_model_row_number() row_number = self.active_tab().source_model_selected_row_number()
if row_number is None: if row_number is None:
return return
track_info = self.active_model().get_row_info(row_number) track_info = self.active_proxy_model().get_row_info(row_number)
if track_info is None: if track_info is None:
return return
@ -953,7 +948,7 @@ class Window(QMainWindow, Ui_MainWindow):
to_row = 0 to_row = 0
# Move rows # Move rows
self.active_model().move_rows_between_playlists( self.active_proxy_model().move_rows_between_playlists(
row_numbers, to_row, to_playlist_id row_numbers, to_row, to_playlist_id
) )
@ -973,7 +968,7 @@ class Window(QMainWindow, Ui_MainWindow):
Move unplayed rows to another playlist Move unplayed rows to another playlist
""" """
unplayed_rows = self.active_model().get_unplayed_rows() unplayed_rows = self.active_proxy_model().get_unplayed_rows()
if not unplayed_rows: if not unplayed_rows:
return return
self.move_playlist_rows(unplayed_rows) self.move_playlist_rows(unplayed_rows)
@ -1022,16 +1017,16 @@ class Window(QMainWindow, Ui_MainWindow):
if self.move_source_rows is None or self.move_source_model is None: if self.move_source_rows is None or self.move_source_model is None:
return return
to_playlist_model = self.active_tab().data_model to_playlist_model = self.active_tab().source_model
selected_rows = self.active_tab().get_selected_rows() selected_rows = self.active_tab().get_selected_rows()
if selected_rows: if selected_rows:
destination_row = selected_rows[0] destination_row = selected_rows[0]
else: else:
destination_row = self.active_model().rowCount() destination_row = self.active_proxy_model().rowCount()
if ( if (
to_playlist_model.playlist_id to_playlist_model.playlist_id
== self.move_source_model.data_model.playlist_id == self.move_source_model.source_model.playlist_id
): ):
self.move_source_model.move_rows(self.move_source_rows, destination_row) self.move_source_model.move_rows(self.move_source_rows, destination_row)
else: else:
@ -1109,7 +1104,7 @@ class Window(QMainWindow, Ui_MainWindow):
sleep(0.1) sleep(0.1)
# Notify model # Notify model
self.active_model().current_track_started() self.active_proxy_model().current_track_started()
# Note that track is now playing # Note that track is now playing
self.playing = True self.playing = True
@ -1240,7 +1235,7 @@ class Window(QMainWindow, Ui_MainWindow):
Incremental search of playlist Incremental search of playlist
""" """
self.active_model().set_incremental_search(self.txtSearch.text()) self.active_proxy_model().set_incremental_search(self.txtSearch.text())
def select_next_row(self) -> None: def select_next_row(self) -> None:
"""Select next or first row in playlist""" """Select next or first row in playlist"""
@ -1330,8 +1325,8 @@ class Window(QMainWindow, Ui_MainWindow):
self.tabPlaylist.setCurrentIndex(idx) self.tabPlaylist.setCurrentIndex(idx)
break break
display_row = self.active_model().mapFromSource( display_row = self.active_proxy_model().mapFromSource(
self.active_model().data_model.index(plt.plr_rownum, 0) self.active_proxy_model().source_model.index(plt.plr_rownum, 0)
).row() ).row()
self.tabPlaylist.currentWidget().scroll_to_top(display_row) self.tabPlaylist.currentWidget().scroll_to_top(display_row)
@ -1409,7 +1404,7 @@ class Window(QMainWindow, Ui_MainWindow):
track_sequence.now = PlaylistTrack() track_sequence.now = PlaylistTrack()
# Tell model previous track has finished # Tell model previous track has finished
self.active_model().previous_track_ended() self.active_proxy_model().previous_track_ended()
# Reset clocks # Reset clocks
self.frame_fade.setStyleSheet("") self.frame_fade.setStyleSheet("")

View File

@ -1353,14 +1353,14 @@ class PlaylistProxyModel(QSortFilterProxyModel):
def __init__( def __init__(
self, self,
data_model: PlaylistModel, source_model: PlaylistModel,
*args, *args,
**kwargs, **kwargs,
): ):
self.data_model = data_model self.source_model = source_model
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.setSourceModel(data_model) self.setSourceModel(source_model)
# Search all columns # Search all columns
self.setFilterKeyColumn(-1) self.setFilterKeyColumn(-1)
@ -1369,8 +1369,8 @@ class PlaylistProxyModel(QSortFilterProxyModel):
Subclass to filter by played status Subclass to filter by played status
""" """
if self.data_model.played_tracks_hidden: if self.source_model.played_tracks_hidden:
if self.data_model.is_played_row(source_row): if self.source_model.is_played_row(source_row):
# Don't hide current or next track # Don't hide current or next track
with Session() as session: with Session() as session:
if track_sequence.next.plr_id: if track_sequence.next.plr_id:
@ -1378,7 +1378,7 @@ class PlaylistProxyModel(QSortFilterProxyModel):
if ( if (
next_plr next_plr
and next_plr.plr_rownum == source_row and next_plr.plr_rownum == source_row
and next_plr.playlist_id == self.data_model.playlist_id and next_plr.playlist_id == self.source_model.playlist_id
): ):
return True return True
if track_sequence.now.plr_id: if track_sequence.now.plr_id:
@ -1386,7 +1386,7 @@ class PlaylistProxyModel(QSortFilterProxyModel):
if ( if (
now_plr now_plr
and now_plr.plr_rownum == source_row and now_plr.plr_rownum == source_row
and now_plr.playlist_id == self.data_model.playlist_id and now_plr.playlist_id == self.source_model.playlist_id
): ):
return True return True
# Don't hide previous track until # Don't hide previous track until
@ -1399,7 +1399,7 @@ class PlaylistProxyModel(QSortFilterProxyModel):
if ( if (
previous_plr previous_plr
and previous_plr.plr_rownum == source_row and previous_plr.plr_rownum == source_row
and previous_plr.playlist_id == self.data_model.playlist_id and previous_plr.playlist_id == self.source_model.playlist_id
): ):
if track_sequence.now.start_time: if track_sequence.now.start_time:
if datetime.now() > ( if datetime.now() > (
@ -1418,7 +1418,7 @@ class PlaylistProxyModel(QSortFilterProxyModel):
# true next time through. # true next time through.
QTimer.singleShot( QTimer.singleShot(
Config.HIDE_AFTER_PLAYING_OFFSET + 100, Config.HIDE_AFTER_PLAYING_OFFSET + 100,
lambda: self.data_model.invalidate_row( lambda: self.source_model.invalidate_row(
source_row source_row
), ),
) )
@ -1445,28 +1445,28 @@ class PlaylistProxyModel(QSortFilterProxyModel):
# ###################################### # ######################################
def current_track_started(self): def current_track_started(self):
return self.data_model.current_track_started() return self.source_model.current_track_started()
def delete_rows(self, row_numbers: List[int]) -> None: def delete_rows(self, row_numbers: List[int]) -> None:
return self.data_model.delete_rows(row_numbers) return self.source_model.delete_rows(row_numbers)
def get_duplicate_rows(self) -> List[int]: def get_duplicate_rows(self) -> List[int]:
return self.data_model.get_duplicate_rows() return self.source_model.get_duplicate_rows()
def get_rows_duration(self, row_numbers: List[int]) -> int: def get_rows_duration(self, row_numbers: List[int]) -> int:
return self.data_model.get_rows_duration(row_numbers) return self.source_model.get_rows_duration(row_numbers)
def get_row_info(self, row_number: int) -> PlaylistRowData: def get_row_info(self, row_number: int) -> PlaylistRowData:
return self.data_model.get_row_info(row_number) return self.source_model.get_row_info(row_number)
def get_row_track_path(self, row_number: int) -> str: def get_row_track_path(self, row_number: int) -> str:
return self.data_model.get_row_track_path(row_number) return self.source_model.get_row_track_path(row_number)
def get_unplayed_rows(self) -> List[int]: def get_unplayed_rows(self) -> List[int]:
return self.data_model.get_unplayed_rows() return self.source_model.get_unplayed_rows()
def hide_played_tracks(self, hide: bool) -> None: def hide_played_tracks(self, hide: bool) -> None:
return self.data_model.hide_played_tracks(hide) return self.source_model.hide_played_tracks(hide)
def insert_row( def insert_row(
self, self,
@ -1474,65 +1474,65 @@ class PlaylistProxyModel(QSortFilterProxyModel):
track_id: Optional[int] = None, track_id: Optional[int] = None,
note: Optional[str] = None, note: Optional[str] = None,
) -> None: ) -> None:
return self.data_model.insert_row(proposed_row_number, track_id, note) return self.source_model.insert_row(proposed_row_number, track_id, note)
def is_header_row(self, row_number: int) -> bool: def is_header_row(self, row_number: int) -> bool:
return self.data_model.is_header_row(row_number) return self.source_model.is_header_row(row_number)
def is_played_row(self, row_number: int) -> bool: def is_played_row(self, row_number: int) -> bool:
return self.data_model.is_played_row(row_number) return self.source_model.is_played_row(row_number)
def is_track_in_playlist(self, track_id: int) -> Optional[PlaylistRowData]: def is_track_in_playlist(self, track_id: int) -> Optional[PlaylistRowData]:
return self.data_model.is_track_in_playlist(track_id) return self.source_model.is_track_in_playlist(track_id)
def mark_unplayed(self, row_numbers: List[int]) -> None: def mark_unplayed(self, row_numbers: List[int]) -> None:
return self.data_model.mark_unplayed(row_numbers) return self.source_model.mark_unplayed(row_numbers)
def move_rows(self, from_rows: List[int], to_row_number: int) -> None: def move_rows(self, from_rows: List[int], to_row_number: int) -> None:
return self.data_model.move_rows(from_rows, to_row_number) return self.source_model.move_rows(from_rows, to_row_number)
def move_rows_between_playlists( def move_rows_between_playlists(
self, from_rows: List[int], to_row_number: int, to_playlist_id: int self, from_rows: List[int], to_row_number: int, to_playlist_id: int
) -> None: ) -> None:
return self.data_model.move_rows_between_playlists( return self.source_model.move_rows_between_playlists(
from_rows, to_row_number, to_playlist_id from_rows, to_row_number, to_playlist_id
) )
def move_track_add_note( def move_track_add_note(
self, new_row_number: int, existing_prd: PlaylistRowData, note: str self, new_row_number: int, existing_prd: PlaylistRowData, note: str
) -> None: ) -> None:
return self.data_model.move_track_add_note(new_row_number, existing_prd, note) return self.source_model.move_track_add_note(new_row_number, existing_prd, note)
def move_track_to_header( def move_track_to_header(
self, header_row_number: int, existing_prd: PlaylistRowData, note: Optional[str] self, header_row_number: int, existing_prd: PlaylistRowData, note: Optional[str]
) -> None: ) -> None:
return self.data_model.move_track_to_header( return self.source_model.move_track_to_header(
header_row_number, existing_prd, note header_row_number, existing_prd, note
) )
def previous_track_ended(self) -> None: def previous_track_ended(self) -> None:
return self.data_model.previous_track_ended() return self.source_model.previous_track_ended()
def remove_track(self, row_number: int) -> None: def remove_track(self, row_number: int) -> None:
return self.data_model.remove_track(row_number) return self.source_model.remove_track(row_number)
def rescan_track(self, row_number: int) -> None: def rescan_track(self, row_number: int) -> None:
return self.data_model.rescan_track(row_number) return self.source_model.rescan_track(row_number)
def set_next_row(self, row_number: Optional[int]) -> None: def set_next_row(self, row_number: Optional[int]) -> None:
return self.data_model.set_next_row(row_number) return self.source_model.set_next_row(row_number)
def sort_by_artist(self, row_numbers: List[int]) -> None: def sort_by_artist(self, row_numbers: List[int]) -> None:
return self.data_model.sort_by_artist(row_numbers) return self.source_model.sort_by_artist(row_numbers)
def sort_by_duration(self, row_numbers: List[int]) -> None: def sort_by_duration(self, row_numbers: List[int]) -> None:
return self.data_model.sort_by_duration(row_numbers) return self.source_model.sort_by_duration(row_numbers)
def sort_by_lastplayed(self, row_numbers: List[int]) -> None: def sort_by_lastplayed(self, row_numbers: List[int]) -> None:
return self.data_model.sort_by_lastplayed(row_numbers) return self.source_model.sort_by_lastplayed(row_numbers)
def sort_by_title(self, row_numbers: List[int]) -> None: def sort_by_title(self, row_numbers: List[int]) -> None:
return self.data_model.sort_by_title(row_numbers) return self.source_model.sort_by_title(row_numbers)
def update_track_times(self) -> None: def update_track_times(self) -> None:
return self.data_model.update_track_times() return self.source_model.update_track_times()

View File

@ -54,9 +54,9 @@ class EscapeDelegate(QStyledItemDelegate):
- checks with user before abandoning edit on Escape - checks with user before abandoning edit on Escape
""" """
def __init__(self, parent, data_model: PlaylistModel) -> None: def __init__(self, parent, source_model: PlaylistModel) -> None:
super().__init__(parent) super().__init__(parent)
self.data_model = data_model self.source_model = source_model
self.signals = MusicMusterSignals() self.signals = MusicMusterSignals()
def createEditor( def createEditor(
@ -116,24 +116,18 @@ class EscapeDelegate(QStyledItemDelegate):
return False return False
def setEditorData(self, editor, index): def setEditorData(self, editor, index):
model = index.model() proxy_model = index.model()
if hasattr(model, "mapToSource"): edit_index = proxy_model.mapToSource(index)
edit_index = model.mapToSource(index)
else:
edit_index = index
self.original_text = self.data_model.data(edit_index, Qt.ItemDataRole.EditRole) self.original_text = self.source_model.data(edit_index, Qt.ItemDataRole.EditRole)
editor.setPlainText(self.original_text.value()) editor.setPlainText(self.original_text.value())
def setModelData(self, editor, model, index): def setModelData(self, editor, model, index):
model = index.model() proxy_model = index.model()
if hasattr(model, "mapToSource"): edit_index = proxy_model.mapToSource(index)
edit_index = model.mapToSource(index)
else:
edit_index = index
value = editor.toPlainText().strip() value = editor.toPlainText().strip()
self.data_model.setData(edit_index, value, Qt.ItemDataRole.EditRole) self.source_model.setData(edit_index, value, Qt.ItemDataRole.EditRole)
def updateEditorGeometry(self, editor, option, index): def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect) editor.setGeometry(option.rect)
@ -174,9 +168,9 @@ class PlaylistTab(QTableView):
self.playlist_id = playlist_id self.playlist_id = playlist_id
# Set up widget # Set up widget
self.data_model = PlaylistModel(playlist_id) self.source_model = PlaylistModel(playlist_id)
self.proxy_model = PlaylistProxyModel(self.data_model) self.proxy_model = PlaylistProxyModel(self.source_model)
self.setItemDelegate(EscapeDelegate(self, self.data_model)) self.setItemDelegate(EscapeDelegate(self, self.source_model))
self.setAlternatingRowColors(True) self.setAlternatingRowColors(True)
self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel) self.setVerticalScrollMode(QAbstractItemView.ScrollMode.ScrollPerPixel)
self.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove) self.setDragDropMode(QAbstractItemView.DragDropMode.InternalMove)
@ -224,7 +218,7 @@ class PlaylistTab(QTableView):
# Update start times in case a start time in a note has been # Update start times in case a start time in a note has been
# edited # edited
self.data_model.update_track_times() self.source_model.update_track_times()
# Deselect edited line # Deselect edited line
self.clear_selection() self.clear_selection()
@ -241,11 +235,11 @@ class PlaylistTab(QTableView):
to_model_row = self.proxy_model.mapToSource(to_index).row() to_model_row = self.proxy_model.mapToSource(to_index).row()
if ( if (
0 <= min(from_rows) <= self.data_model.rowCount() 0 <= min(from_rows) <= self.source_model.rowCount()
and 0 <= max(from_rows) <= self.data_model.rowCount() and 0 <= max(from_rows) <= self.source_model.rowCount()
and 0 <= to_model_row <= self.data_model.rowCount() and 0 <= to_model_row <= self.source_model.rowCount()
): ):
self.data_model.move_rows(from_rows, to_model_row) self.source_model.move_rows(from_rows, to_model_row)
# Reset drag mode to allow row selection by dragging # Reset drag mode to allow row selection by dragging
self.setDragEnabled(False) self.setDragEnabled(False)
@ -282,7 +276,7 @@ class PlaylistTab(QTableView):
if len(selected_rows) == 0: if len(selected_rows) == 0:
self.musicmuster.lblSumPlaytime.setText("") self.musicmuster.lblSumPlaytime.setText("")
else: else:
selected_duration = self.data_model.get_rows_duration( selected_duration = self.source_model.get_rows_duration(
self.get_selected_rows() self.get_selected_rows()
) )
if selected_duration > 0: if selected_duration > 0:
@ -320,7 +314,7 @@ class PlaylistTab(QTableView):
def _add_track(self) -> None: def _add_track(self) -> None:
"""Add a track to a section header making it a normal track row""" """Add a track to a section header making it a normal track row"""
model_row_number = self.selected_model_row_number() model_row_number = self.source_model_selected_row_number()
if model_row_number is None: if model_row_number is None:
return return
@ -328,7 +322,7 @@ class PlaylistTab(QTableView):
dlg = TrackSelectDialog( dlg = TrackSelectDialog(
session=session, session=session,
new_row_number=model_row_number, new_row_number=model_row_number,
model=self.data_model, source_model=self.source_model,
add_to_header=True, add_to_header=True,
) )
dlg.exec() dlg.exec()
@ -337,16 +331,12 @@ class PlaylistTab(QTableView):
"""Used to process context (right-click) menu, which is defined here""" """Used to process context (right-click) menu, which is defined here"""
self.menu.clear() self.menu.clear()
model = self.proxy_model proxy_model = self.proxy_model
display_row_number = item.row() index = proxy_model.index(item.row(), item.column())
if hasattr(model, "mapToSource"): model_row_number = proxy_model.mapToSource(index).row()
index = model.index(item.row(), item.column())
model_row_number = model.mapToSource(index).row()
else:
model_row_number = display_row_number
header_row = model.is_header_row(model_row_number) header_row = proxy_model.is_header_row(model_row_number)
track_row = not header_row track_row = not header_row
current_row = model_row_number == track_sequence.now.plr_rownum current_row = model_row_number == track_sequence.now.plr_rownum
next_row = model_row_number == track_sequence.next.plr_rownum next_row = model_row_number == track_sequence.next.plr_rownum
@ -373,7 +363,7 @@ class PlaylistTab(QTableView):
# Remove track from row # Remove track from row
if track_row and not current_row and not next_row: if track_row and not current_row and not next_row:
self._add_context_menu( self._add_context_menu(
"Remove track from row", lambda: model.remove_track(model_row_number) "Remove track from row", lambda: proxy_model.remove_track(model_row_number)
) )
# Add track to section header (ie, make this a track row) # Add track to section header (ie, make this a track row)
@ -384,7 +374,7 @@ class PlaylistTab(QTableView):
self.menu.addSeparator() self.menu.addSeparator()
# Mark unplayed # Mark unplayed
if track_row and model.is_played_row(model_row_number): if track_row and proxy_model.is_played_row(model_row_number):
self._add_context_menu( self._add_context_menu(
"Mark unplayed", "Mark unplayed",
lambda: self._mark_as_unplayed(self.get_selected_rows()), lambda: self._mark_as_unplayed(self.get_selected_rows()),
@ -403,22 +393,22 @@ class PlaylistTab(QTableView):
sort_menu = self.menu.addMenu("Sort") sort_menu = self.menu.addMenu("Sort")
self._add_context_menu( self._add_context_menu(
"by title", "by title",
lambda: model.sort_by_title(self.get_selected_rows()), lambda: proxy_model.sort_by_title(self.get_selected_rows()),
parent_menu=sort_menu, parent_menu=sort_menu,
) )
self._add_context_menu( self._add_context_menu(
"by artist", "by artist",
lambda: model.sort_by_artist(self.get_selected_rows()), lambda: proxy_model.sort_by_artist(self.get_selected_rows()),
parent_menu=sort_menu, parent_menu=sort_menu,
) )
self._add_context_menu( self._add_context_menu(
"by duration", "by duration",
lambda: model.sort_by_duration(self.get_selected_rows()), lambda: proxy_model.sort_by_duration(self.get_selected_rows()),
parent_menu=sort_menu, parent_menu=sort_menu,
) )
self._add_context_menu( self._add_context_menu(
"by last played", "by last played",
lambda: model.sort_by_lastplayed(self.get_selected_rows()), lambda: proxy_model.sort_by_lastplayed(self.get_selected_rows()),
parent_menu=sort_menu, parent_menu=sort_menu,
) )
@ -473,7 +463,7 @@ class PlaylistTab(QTableView):
to the clipboard. Otherwise, return None. to the clipboard. Otherwise, return None.
""" """
track_path = self.data_model.get_row_info(row_number).path track_path = self.source_model.get_row_info(row_number).path
if not track_path: if not track_path:
return return
@ -510,7 +500,7 @@ class PlaylistTab(QTableView):
if not ask_yes_no("Delete rows", f"Really delete {row_count} row{plural}?"): if not ask_yes_no("Delete rows", f"Really delete {row_count} row{plural}?"):
return return
self.data_model.delete_rows(self.selected_model_row_numbers()) self.source_model.delete_rows(self.selected_model_row_numbers())
self.clear_selection() self.clear_selection()
def get_selected_row_track_path(self) -> str: def get_selected_row_track_path(self) -> str:
@ -519,10 +509,10 @@ class PlaylistTab(QTableView):
row does not have a track, return empty string. row does not have a track, return empty string.
""" """
model_row_number = self.selected_model_row_number() model_row_number = self.source_model_selected_row_number()
if model_row_number is None: if model_row_number is None:
return "" return ""
return self.data_model.get_row_track_path(model_row_number) return self.source_model.get_row_track_path(model_row_number)
def get_selected_rows(self) -> List[int]: def get_selected_rows(self) -> List[int]:
"""Return a list of model-selected row numbers sorted by row""" """Return a list of model-selected row numbers sorted by row"""
@ -543,7 +533,7 @@ class PlaylistTab(QTableView):
def _info_row(self, row_number: int) -> None: def _info_row(self, row_number: int) -> None:
"""Display popup with info re row""" """Display popup with info re row"""
prd = self.data_model.get_row_info(row_number) prd = self.source_model.get_row_info(row_number)
if prd: if prd:
txt = ( txt = (
f"Title: {prd.title}\n" f"Title: {prd.title}\n"
@ -562,7 +552,7 @@ class PlaylistTab(QTableView):
def _mark_as_unplayed(self, row_numbers: List[int]) -> None: def _mark_as_unplayed(self, row_numbers: List[int]) -> None:
"""Rescan track""" """Rescan track"""
self.data_model.mark_unplayed(row_numbers) self.source_model.mark_unplayed(row_numbers)
self.clear_selection() self.clear_selection()
def open_in_audacity(self, row_number: int) -> None: def open_in_audacity(self, row_number: int) -> None:
@ -575,7 +565,7 @@ class PlaylistTab(QTableView):
show_warning(self.musicmuster, "Audacity", "Audacity is not running") show_warning(self.musicmuster, "Audacity", "Audacity is not running")
return return
path = self.data_model.get_row_track_path(row_number) path = self.source_model.get_row_track_path(row_number)
if not path: if not path:
return return
@ -619,14 +609,14 @@ class PlaylistTab(QTableView):
# We need to be in MultiSelection mode # We need to be in MultiSelection mode
self.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection) self.setSelectionMode(QAbstractItemView.SelectionMode.MultiSelection)
# Get the duplicate rows # Get the duplicate rows
duplicate_rows = self.data_model.get_duplicate_rows() duplicate_rows = self.source_model.get_duplicate_rows()
# Select the rows # Select the rows
for duplicate_row in duplicate_rows: for duplicate_row in duplicate_rows:
self.selectRow(duplicate_row) self.selectRow(duplicate_row)
# Reset selection mode # Reset selection mode
self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
def selected_model_row_number(self) -> Optional[int]: def source_model_selected_row_number(self) -> Optional[int]:
""" """
Return the model row number corresponding to the selected row or None Return the model row number corresponding to the selected row or None
""" """
@ -706,10 +696,10 @@ class PlaylistTab(QTableView):
Set selected row as next track Set selected row as next track
""" """
model_row_number = self.selected_model_row_number() model_row_number = self.source_model_selected_row_number()
if model_row_number is None: if model_row_number is None:
return return
self.data_model.set_next_row(model_row_number) self.source_model.set_next_row(model_row_number)
self.clearSelection() self.clearSelection()
def _span_cells( def _span_cells(
@ -722,11 +712,10 @@ class PlaylistTab(QTableView):
if playlist_id != self.playlist_id: if playlist_id != self.playlist_id:
return return
model = self.proxy_model proxy_model = self.proxy_model
if hasattr(model, "mapToSource"): edit_index = proxy_model.mapFromSource(self.source_model.createIndex(row, column))
edit_index = model.mapFromSource(self.data_model.createIndex(row, column)) row = edit_index.row()
row = edit_index.row() column = edit_index.column()
column = edit_index.column()
# Don't set spanning if already in place because that is seen as # Don't set spanning if already in place because that is seen as
# a change to the view and thus it refreshes the data which # a change to the view and thus it refreshes the data which
@ -742,5 +731,5 @@ class PlaylistTab(QTableView):
def _unmark_as_next(self) -> None: def _unmark_as_next(self) -> None:
"""Rescan track""" """Rescan track"""
self.data_model.set_next_row(None) self.source_model.set_next_row(None)
self.clear_selection() self.clear_selection()