Name source and proxy models consistently
This commit is contained in:
parent
45243759b8
commit
b74007119d
@ -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"""
|
||||||
|
|||||||
@ -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("")
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
101
app/playlists.py
101
app/playlists.py
@ -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()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user