WIP V3: Add track to header row implemented
This commit is contained in:
parent
9554336860
commit
fedcfc3eea
@ -14,7 +14,8 @@ class MusicMusterSignals(QObject):
|
||||
https://refactoring.guru/design-patterns/singleton/python/example#example-0
|
||||
"""
|
||||
|
||||
add_track_to_header_signal = pyqtSignal(int, int, int)
|
||||
add_track_to_playlist_signal = pyqtSignal(int, int, int, str)
|
||||
enable_escape_signal = pyqtSignal(bool)
|
||||
set_next_track_signal = pyqtSignal(int, int)
|
||||
span_cells_signal = pyqtSignal(int, int, int, int)
|
||||
add_track_to_playlist_signal = pyqtSignal(int, int, int, str)
|
||||
|
||||
175
app/dialogs.py
Normal file
175
app/dialogs.py
Normal file
@ -0,0 +1,175 @@
|
||||
from PyQt6.QtCore import QEvent, Qt
|
||||
from PyQt6.QtWidgets import QDialog, QListWidgetItem
|
||||
from typing import Optional
|
||||
|
||||
import helpers
|
||||
|
||||
from datastructures import MusicMusterSignals
|
||||
from dbconfig import scoped_session
|
||||
from models import Settings, Tracks
|
||||
from ui.dlg_TrackSelect_ui import Ui_Dialog # type: ignore
|
||||
|
||||
|
||||
class TrackSelectDialog(QDialog):
|
||||
"""Select track from database"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
session: scoped_session,
|
||||
new_row_number: int,
|
||||
playlist_id: int,
|
||||
add_to_header: Optional[bool] = False,
|
||||
*args,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""
|
||||
Subclassed QDialog to manage track selection
|
||||
"""
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
self.session = session
|
||||
self.new_row_number = new_row_number
|
||||
self.playlist_id = playlist_id
|
||||
self.add_to_header = add_to_header
|
||||
self.ui = Ui_Dialog()
|
||||
self.ui.setupUi(self)
|
||||
self.ui.btnAdd.clicked.connect(self.add_selected)
|
||||
self.ui.btnAddClose.clicked.connect(self.add_selected_and_close)
|
||||
self.ui.btnClose.clicked.connect(self.close)
|
||||
self.ui.matchList.itemDoubleClicked.connect(self.add_selected)
|
||||
self.ui.matchList.itemSelectionChanged.connect(self.selection_changed)
|
||||
self.ui.radioTitle.toggled.connect(self.title_artist_toggle)
|
||||
self.ui.searchString.textEdited.connect(self.chars_typed)
|
||||
self.track: Optional[Tracks] = None
|
||||
self.signals = MusicMusterSignals()
|
||||
|
||||
record = Settings.get_int_settings(self.session, "dbdialog_width")
|
||||
width = record.f_int or 800
|
||||
record = Settings.get_int_settings(self.session, "dbdialog_height")
|
||||
height = record.f_int or 600
|
||||
self.resize(width, height)
|
||||
|
||||
def add_selected(self) -> None:
|
||||
"""Handle Add button"""
|
||||
|
||||
track = None
|
||||
|
||||
if self.ui.matchList.selectedItems():
|
||||
item = self.ui.matchList.currentItem()
|
||||
if item:
|
||||
track = item.data(Qt.ItemDataRole.UserRole)
|
||||
|
||||
note = self.ui.txtNote.text()
|
||||
|
||||
if not note and not track:
|
||||
return
|
||||
|
||||
self.ui.txtNote.clear()
|
||||
self.select_searchtext()
|
||||
|
||||
track_id = None
|
||||
if track:
|
||||
track_id = track.id
|
||||
if self.add_to_header:
|
||||
self.signals.add_track_to_header_signal.emit(
|
||||
self.playlist_id, self.new_row_number, track_id
|
||||
)
|
||||
else:
|
||||
self.signals.add_track_to_playlist_signal.emit(
|
||||
self.playlist_id, self.new_row_number, track_id, note
|
||||
)
|
||||
|
||||
def add_selected_and_close(self) -> None:
|
||||
"""Handle Add and Close button"""
|
||||
|
||||
self.add_selected()
|
||||
self.accept()
|
||||
|
||||
def chars_typed(self, s: str) -> None:
|
||||
"""Handle text typed in search box"""
|
||||
|
||||
self.ui.matchList.clear()
|
||||
if len(s) > 0:
|
||||
if self.ui.radioTitle.isChecked():
|
||||
matches = Tracks.search_titles(self.session, "%" + s)
|
||||
else:
|
||||
matches = Tracks.search_artists(self.session, "%" + s)
|
||||
if matches:
|
||||
for track in matches:
|
||||
last_played = None
|
||||
last_playdate = max(
|
||||
track.playdates, key=lambda p: p.lastplayed, default=None
|
||||
)
|
||||
if last_playdate:
|
||||
last_played = last_playdate.lastplayed
|
||||
t = QListWidgetItem()
|
||||
track_text = (
|
||||
f"{track.title} - {track.artist} "
|
||||
f"[{helpers.ms_to_mmss(track.duration)}] "
|
||||
f"({helpers.get_relative_date(last_played)})"
|
||||
)
|
||||
t.setText(track_text)
|
||||
t.setData(Qt.ItemDataRole.UserRole, track)
|
||||
self.ui.matchList.addItem(t)
|
||||
|
||||
def closeEvent(self, event: Optional[QEvent]) -> None:
|
||||
"""
|
||||
Override close and save dialog coordinates
|
||||
"""
|
||||
|
||||
if not event:
|
||||
return
|
||||
|
||||
record = Settings.get_int_settings(self.session, "dbdialog_height")
|
||||
if record.f_int != self.height():
|
||||
record.update(self.session, {"f_int": self.height()})
|
||||
|
||||
record = Settings.get_int_settings(self.session, "dbdialog_width")
|
||||
if record.f_int != self.width():
|
||||
record.update(self.session, {"f_int": self.width()})
|
||||
|
||||
event.accept()
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
"""
|
||||
Clear selection on ESC if there is one
|
||||
"""
|
||||
|
||||
if event.key() == Qt.Key.Key_Escape:
|
||||
if self.ui.matchList.selectedItems():
|
||||
self.ui.matchList.clearSelection()
|
||||
return
|
||||
|
||||
super(TrackSelectDialog, self).keyPressEvent(event)
|
||||
|
||||
def select_searchtext(self) -> None:
|
||||
"""Select the searchbox"""
|
||||
|
||||
self.ui.searchString.selectAll()
|
||||
self.ui.searchString.setFocus()
|
||||
|
||||
def selection_changed(self) -> None:
|
||||
"""Display selected track path in dialog box"""
|
||||
|
||||
if not self.ui.matchList.selectedItems():
|
||||
return
|
||||
|
||||
item = self.ui.matchList.currentItem()
|
||||
track = item.data(Qt.ItemDataRole.UserRole)
|
||||
last_playdate = max(track.playdates, key=lambda p: p.lastplayed, default=None)
|
||||
if last_playdate:
|
||||
last_played = last_playdate.lastplayed
|
||||
else:
|
||||
last_played = None
|
||||
path_text = f"{track.path} ({helpers.get_relative_date(last_played)})"
|
||||
|
||||
self.ui.dbPath.setText(path_text)
|
||||
|
||||
def title_artist_toggle(self) -> None:
|
||||
"""
|
||||
Handle switching between searching for artists and searching for
|
||||
titles
|
||||
"""
|
||||
|
||||
# Logic is handled already in chars_typed(), so just call that.
|
||||
self.chars_typed(self.ui.searchString.text())
|
||||
@ -66,12 +66,12 @@ from dbconfig import (
|
||||
import helpers
|
||||
import icons_rc # noqa F401
|
||||
import music
|
||||
from dialogs import TrackSelectDialog
|
||||
from models import Base, Carts, Playdates, PlaylistRows, Playlists, Settings, Tracks
|
||||
from config import Config
|
||||
from datastructures import MusicMusterSignals
|
||||
from playlists import PlaylistTab
|
||||
from ui.dlg_cart_ui import Ui_DialogCartEdit # type: ignore
|
||||
from ui.dlg_TrackSelect_ui import Ui_Dialog # type: ignore
|
||||
from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist # type: ignore
|
||||
from ui.downloadcsv_ui import Ui_DateSelect # type: ignore
|
||||
from ui.main_window_ui import Ui_MainWindow # type: ignore
|
||||
@ -1901,164 +1901,6 @@ class CartDialog(QDialog):
|
||||
self.ui.lblPath.setText(self.path)
|
||||
|
||||
|
||||
class TrackSelectDialog(QDialog):
|
||||
"""Select track from database"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
session: scoped_session,
|
||||
new_row_number: int,
|
||||
playlist_id: int,
|
||||
*args,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""
|
||||
Subclassed QDialog to manage track selection
|
||||
"""
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
self.session = session
|
||||
self.new_row_number = new_row_number
|
||||
self.playlist_id = playlist_id
|
||||
self.ui = Ui_Dialog()
|
||||
self.ui.setupUi(self)
|
||||
self.ui.btnAdd.clicked.connect(self.add_selected)
|
||||
self.ui.btnAddClose.clicked.connect(self.add_selected_and_close)
|
||||
self.ui.btnClose.clicked.connect(self.close)
|
||||
self.ui.matchList.itemDoubleClicked.connect(self.add_selected)
|
||||
self.ui.matchList.itemSelectionChanged.connect(self.selection_changed)
|
||||
self.ui.radioTitle.toggled.connect(self.title_artist_toggle)
|
||||
self.ui.searchString.textEdited.connect(self.chars_typed)
|
||||
self.track: Optional[Tracks] = None
|
||||
self.signals = MusicMusterSignals()
|
||||
|
||||
record = Settings.get_int_settings(self.session, "dbdialog_width")
|
||||
width = record.f_int or 800
|
||||
record = Settings.get_int_settings(self.session, "dbdialog_height")
|
||||
height = record.f_int or 600
|
||||
self.resize(width, height)
|
||||
|
||||
def add_selected(self) -> None:
|
||||
"""Handle Add button"""
|
||||
|
||||
track = None
|
||||
|
||||
if self.ui.matchList.selectedItems():
|
||||
item = self.ui.matchList.currentItem()
|
||||
if item:
|
||||
track = item.data(Qt.ItemDataRole.UserRole)
|
||||
|
||||
note = self.ui.txtNote.text()
|
||||
|
||||
if not note and not track:
|
||||
return
|
||||
|
||||
self.ui.txtNote.clear()
|
||||
self.select_searchtext()
|
||||
|
||||
track_id = None
|
||||
if track:
|
||||
track_id = track.id
|
||||
self.signals.add_track_to_playlist_signal.emit(
|
||||
self.playlist_id, self.new_row_number, track_id, note
|
||||
)
|
||||
|
||||
def add_selected_and_close(self) -> None:
|
||||
"""Handle Add and Close button"""
|
||||
|
||||
self.add_selected()
|
||||
self.accept()
|
||||
|
||||
def chars_typed(self, s: str) -> None:
|
||||
"""Handle text typed in search box"""
|
||||
|
||||
self.ui.matchList.clear()
|
||||
if len(s) > 0:
|
||||
if self.ui.radioTitle.isChecked():
|
||||
matches = Tracks.search_titles(self.session, "%" + s)
|
||||
else:
|
||||
matches = Tracks.search_artists(self.session, "%" + s)
|
||||
if matches:
|
||||
for track in matches:
|
||||
last_played = None
|
||||
last_playdate = max(
|
||||
track.playdates, key=lambda p: p.lastplayed, default=None
|
||||
)
|
||||
if last_playdate:
|
||||
last_played = last_playdate.lastplayed
|
||||
t = QListWidgetItem()
|
||||
track_text = (
|
||||
f"{track.title} - {track.artist} "
|
||||
f"[{helpers.ms_to_mmss(track.duration)}] "
|
||||
f"({helpers.get_relative_date(last_played)})"
|
||||
)
|
||||
t.setText(track_text)
|
||||
t.setData(Qt.ItemDataRole.UserRole, track)
|
||||
self.ui.matchList.addItem(t)
|
||||
|
||||
def closeEvent(self, event: Optional[QEvent]) -> None:
|
||||
"""
|
||||
Override close and save dialog coordinates
|
||||
"""
|
||||
|
||||
if not event:
|
||||
return
|
||||
|
||||
record = Settings.get_int_settings(self.session, "dbdialog_height")
|
||||
if record.f_int != self.height():
|
||||
record.update(self.session, {"f_int": self.height()})
|
||||
|
||||
record = Settings.get_int_settings(self.session, "dbdialog_width")
|
||||
if record.f_int != self.width():
|
||||
record.update(self.session, {"f_int": self.width()})
|
||||
|
||||
event.accept()
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
"""
|
||||
Clear selection on ESC if there is one
|
||||
"""
|
||||
|
||||
if event.key() == Qt.Key.Key_Escape:
|
||||
if self.ui.matchList.selectedItems():
|
||||
self.ui.matchList.clearSelection()
|
||||
return
|
||||
|
||||
super(TrackSelectDialog, self).keyPressEvent(event)
|
||||
|
||||
def select_searchtext(self) -> None:
|
||||
"""Select the searchbox"""
|
||||
|
||||
self.ui.searchString.selectAll()
|
||||
self.ui.searchString.setFocus()
|
||||
|
||||
def selection_changed(self) -> None:
|
||||
"""Display selected track path in dialog box"""
|
||||
|
||||
if not self.ui.matchList.selectedItems():
|
||||
return
|
||||
|
||||
item = self.ui.matchList.currentItem()
|
||||
track = item.data(Qt.ItemDataRole.UserRole)
|
||||
last_playdate = max(track.playdates, key=lambda p: p.lastplayed, default=None)
|
||||
if last_playdate:
|
||||
last_played = last_playdate.lastplayed
|
||||
else:
|
||||
last_played = None
|
||||
path_text = f"{track.path} ({helpers.get_relative_date(last_played)})"
|
||||
|
||||
self.ui.dbPath.setText(path_text)
|
||||
|
||||
def title_artist_toggle(self) -> None:
|
||||
"""
|
||||
Handle switching between searching for artists and searching for
|
||||
titles
|
||||
"""
|
||||
|
||||
# Logic is handled already in chars_typed(), so just call that.
|
||||
self.chars_typed(self.ui.searchString.text())
|
||||
|
||||
|
||||
class DownloadCSV(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__()
|
||||
|
||||
@ -21,6 +21,7 @@ from dbconfig import scoped_session, Session
|
||||
from helpers import (
|
||||
file_is_unreadable,
|
||||
)
|
||||
from log import log
|
||||
from models import PlaylistRows, Tracks
|
||||
|
||||
|
||||
@ -104,6 +105,7 @@ class PlaylistModel(QAbstractTableModel):
|
||||
self.signals = MusicMusterSignals()
|
||||
|
||||
self.signals.add_track_to_playlist_signal.connect(self.add_track)
|
||||
self.signals.add_track_to_header_signal.connect(self.add_track_to_header)
|
||||
|
||||
with Session() as session:
|
||||
self.refresh_data(session)
|
||||
@ -138,6 +140,49 @@ class PlaylistModel(QAbstractTableModel):
|
||||
# No track, no note, no point
|
||||
return
|
||||
|
||||
def add_track_to_header(
|
||||
self,
|
||||
playlist_id: int,
|
||||
row_number: int,
|
||||
track_id: int,
|
||||
) -> None:
|
||||
"""
|
||||
Add track to existing header row if it's for our playlist
|
||||
"""
|
||||
|
||||
# Ignore if it's not for us
|
||||
if playlist_id != self.playlist_id:
|
||||
return
|
||||
|
||||
# Get existing row
|
||||
try:
|
||||
prd = self.playlist_rows[row_number]
|
||||
except KeyError:
|
||||
log.error(
|
||||
f"KeyError in PlaylistModel:add_track_to_header ({playlist_id=}, "
|
||||
f"{row_number=}, {track_id=}, {len(self.playlist_rows)=}"
|
||||
)
|
||||
return
|
||||
if prd.path:
|
||||
log.error(
|
||||
f"Error in PlaylistModel:add_track_to_header ({prd=}, "
|
||||
"Header row already has track associated"
|
||||
)
|
||||
return
|
||||
with Session() as session:
|
||||
plr = session.get(PlaylistRows, prd.plrid)
|
||||
if plr:
|
||||
# Add track to PlaylistRows
|
||||
plr.track_id = track_id
|
||||
# Reset header row spanning
|
||||
self.signals.span_cells_signal.emit(
|
||||
row_number, HEADER_NOTES_COLUMN, 1, 1
|
||||
)
|
||||
# Update local copy
|
||||
self.refresh_row(session, row_number)
|
||||
# Repaint row
|
||||
self.invalidate_row(row_number)
|
||||
|
||||
def background_role(self, row: int, column: int, prd: PlaylistRowData) -> QBrush:
|
||||
"""Return background setting"""
|
||||
|
||||
@ -321,6 +366,13 @@ class PlaylistModel(QAbstractTableModel):
|
||||
|
||||
return QVariant()
|
||||
|
||||
def is_header_row(self, row_number: int) -> bool:
|
||||
"""
|
||||
Return True if row is a header row, else False
|
||||
"""
|
||||
|
||||
return self.playlist_rows[row_number].path == ""
|
||||
|
||||
def insert_header_row(self, row_number: Optional[int], text: str) -> None:
|
||||
"""
|
||||
Insert a header row.
|
||||
|
||||
223
app/playlists.py
223
app/playlists.py
@ -7,7 +7,7 @@ import threading
|
||||
import obsws_python as obs # type: ignore
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, cast, List, Optional, Tuple, TYPE_CHECKING
|
||||
from typing import Any, Callable, cast, List, Optional, Tuple, TYPE_CHECKING
|
||||
|
||||
from PyQt6.QtCore import (
|
||||
QEvent,
|
||||
@ -22,7 +22,7 @@ from PyQt6.QtWidgets import (
|
||||
QAbstractItemView,
|
||||
QApplication,
|
||||
QHeaderView,
|
||||
# QMenu,
|
||||
QMenu,
|
||||
QMessageBox,
|
||||
QPlainTextEdit,
|
||||
QStyledItemDelegate,
|
||||
@ -37,6 +37,7 @@ from PyQt6.QtWidgets import (
|
||||
|
||||
from datastructures import MusicMusterSignals
|
||||
from dbconfig import Session, scoped_session
|
||||
from dialogs import TrackSelectDialog
|
||||
from config import Config
|
||||
from helpers import (
|
||||
ask_yes_no,
|
||||
@ -48,11 +49,11 @@ from helpers import (
|
||||
set_track_metadata,
|
||||
)
|
||||
from log import log
|
||||
from models import Playlists, PlaylistRows, Settings, Tracks, NoteColours
|
||||
from playlistmodel import PlaylistModel
|
||||
from models import PlaylistRows, Settings, Tracks, NoteColours
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from musicmuster import Window, MusicMusterSignals
|
||||
from musicmuster import Window
|
||||
from playlistmodel import PlaylistModel
|
||||
|
||||
HEADER_NOTES_COLUMN = 2
|
||||
|
||||
@ -78,7 +79,8 @@ class EscapeDelegate(QStyledItemDelegate):
|
||||
Intercept createEditor call and make row just a little bit taller
|
||||
"""
|
||||
|
||||
signals.enable_escape_signal.emit(False)
|
||||
self.signals = MusicMusterSignals()
|
||||
self.signals.enable_escape_signal.emit(False)
|
||||
if isinstance(self.parent(), PlaylistTab):
|
||||
p = cast(PlaylistTab, self.parent())
|
||||
if isinstance(index.data(), str):
|
||||
@ -111,7 +113,7 @@ class EscapeDelegate(QStyledItemDelegate):
|
||||
return True
|
||||
elif key_event.key() == Qt.Key.Key_Escape:
|
||||
discard_edits = QMessageBox.question(
|
||||
self.parent(), "Abandon edit", "Discard changes?"
|
||||
cast(QWidget, self), "Abandon edit", "Discard changes?"
|
||||
)
|
||||
if discard_edits == QMessageBox.StandardButton.Yes:
|
||||
self.closeEditor.emit(editor)
|
||||
@ -134,8 +136,7 @@ class PlaylistStyle(QProxyStyle):
|
||||
def drawPrimitive(self, element, option, painter, widget=None):
|
||||
"""
|
||||
Draw a line across the entire row rather than just the column
|
||||
we're hovering over. This may not always work depending on global
|
||||
style - for instance I think it won't work on OSX.
|
||||
we're hovering over.
|
||||
"""
|
||||
if (
|
||||
element == QStyle.PrimitiveElement.PE_IndicatorItemViewItemDrop
|
||||
@ -178,9 +179,9 @@ class PlaylistTab(QTableView):
|
||||
# rows selected
|
||||
self.setDragEnabled(True)
|
||||
# Prepare for context menu
|
||||
# self.menu = QMenu()
|
||||
# self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
||||
# self.customContextMenuRequested.connect(self._context_menu)
|
||||
self.menu = QMenu()
|
||||
self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
||||
self.customContextMenuRequested.connect(self._context_menu)
|
||||
|
||||
# Connect signals
|
||||
# This dancing is to satisfy mypy
|
||||
@ -291,27 +292,27 @@ class PlaylistTab(QTableView):
|
||||
|
||||
# self.hide_or_show_played_tracks()
|
||||
|
||||
# def _add_context_menu(
|
||||
# self,
|
||||
# text: str,
|
||||
# action: Callable,
|
||||
# disabled: bool = False,
|
||||
# parent_menu: Optional[QMenu] = None,
|
||||
# ) -> Optional[QAction]:
|
||||
# """
|
||||
# Add item to self.menu
|
||||
# """
|
||||
def _add_context_menu(
|
||||
self,
|
||||
text: str,
|
||||
action: Callable,
|
||||
disabled: bool = False,
|
||||
parent_menu: Optional[QMenu] = None,
|
||||
) -> Optional[QAction]:
|
||||
"""
|
||||
Add item to self.menu
|
||||
"""
|
||||
|
||||
# if parent_menu is None:
|
||||
# parent_menu = self.menu
|
||||
if parent_menu is None:
|
||||
parent_menu = self.menu
|
||||
|
||||
# menu_item = parent_menu.addAction(text)
|
||||
# if not menu_item:
|
||||
# return None
|
||||
# menu_item.setDisabled(disabled)
|
||||
# menu_item.triggered.connect(action)
|
||||
menu_item = parent_menu.addAction(text)
|
||||
if not menu_item:
|
||||
return None
|
||||
menu_item.setDisabled(disabled)
|
||||
menu_item.triggered.connect(action)
|
||||
|
||||
# return menu_item
|
||||
return menu_item
|
||||
|
||||
# def mouseReleaseEvent(self, event):
|
||||
# """
|
||||
@ -1033,106 +1034,90 @@ class PlaylistTab(QTableView):
|
||||
"""Add a track to a section header making it a normal track row"""
|
||||
|
||||
with Session() as session:
|
||||
# Add track to playlist row
|
||||
plr = self._get_row_plr(session, row_number)
|
||||
if not plr:
|
||||
return
|
||||
dlg = TrackSelectDialog(
|
||||
session=session,
|
||||
new_row_number=row_number,
|
||||
playlist_id=self.playlist_id,
|
||||
add_to_header=True,
|
||||
)
|
||||
dlg.exec()
|
||||
|
||||
# Don't add track if there's already a track there
|
||||
if plr.track_id is not None:
|
||||
return
|
||||
def _build_context_menu(self, item: QTableWidgetItem) -> None:
|
||||
"""Used to process context (right-click) menu, which is defined here"""
|
||||
|
||||
# Get track
|
||||
track = self.musicmuster.get_one_track(session)
|
||||
if not track:
|
||||
return
|
||||
plr.track_id = track.id
|
||||
self.menu.clear()
|
||||
row_number = item.row()
|
||||
# track_id = self._get_row_track_id(row_number)
|
||||
# track_row = bool(track_id)
|
||||
header_row = False
|
||||
model = cast(PlaylistModel, self.model())
|
||||
if model:
|
||||
|
||||
# Reset row span
|
||||
self.setSpan(row_number, HEADER_NOTES_COLUMN, 1, 1)
|
||||
header_row = model.is_header_row(row_number)
|
||||
# current = row_number == self._get_current_track_row_number()
|
||||
# next_row = row_number == self._get_next_track_row_number()
|
||||
|
||||
# Update attributes of row
|
||||
self._update_row_track_info(session, row_number, track)
|
||||
self._set_row_bold(row_number)
|
||||
self._set_row_colour_default(row_number)
|
||||
self._set_row_note_text(session, row_number, plr.note)
|
||||
self.clear_selection()
|
||||
self.save_playlist(session)
|
||||
# Update times once display updated
|
||||
self._update_start_end_times(session)
|
||||
# # Play with mplayer
|
||||
# if track_row and not current:
|
||||
# self._add_context_menu(
|
||||
# "Play with mplayer", lambda: self._mplayer_play(row_number)
|
||||
# )
|
||||
|
||||
# def _build_context_menu(self, item: QTableWidgetItem) -> None:
|
||||
# """Used to process context (right-click) menu, which is defined here"""
|
||||
# # Paste
|
||||
# self._add_context_menu(
|
||||
# "Paste",
|
||||
# lambda: self.musicmuster.paste_rows(),
|
||||
# self.musicmuster.selected_plrs is None,
|
||||
# )
|
||||
|
||||
# self.menu.clear()
|
||||
# row_number = item.row()
|
||||
# track_id = self._get_row_track_id(row_number)
|
||||
# track_row = bool(track_id)
|
||||
# header_row = not track_row
|
||||
# current = row_number == self._get_current_track_row_number()
|
||||
# next_row = row_number == self._get_next_track_row_number()
|
||||
# # Open in Audacity
|
||||
# if track_row and not current:
|
||||
# self._add_context_menu(
|
||||
# "Open in Audacity", lambda: self._open_in_audacity(row_number)
|
||||
# )
|
||||
|
||||
# # Play with mplayer
|
||||
# if track_row and not current:
|
||||
# self._add_context_menu(
|
||||
# "Play with mplayer", lambda: self._mplayer_play(row_number)
|
||||
# )
|
||||
# # Rescan
|
||||
# if track_row and not current:
|
||||
# self._add_context_menu(
|
||||
# "Rescan track", lambda: self._rescan(row_number, track_id)
|
||||
# )
|
||||
|
||||
# # Paste
|
||||
# self._add_context_menu(
|
||||
# "Paste",
|
||||
# lambda: self.musicmuster.paste_rows(),
|
||||
# self.musicmuster.selected_plrs is None,
|
||||
# )
|
||||
# # ----------------------
|
||||
self.menu.addSeparator()
|
||||
|
||||
# # Open in Audacity
|
||||
# if track_row and not current:
|
||||
# self._add_context_menu(
|
||||
# "Open in Audacity", lambda: self._open_in_audacity(row_number)
|
||||
# )
|
||||
# # Remove row
|
||||
# if not current and not next_row:
|
||||
# self._add_context_menu("Delete row", self._delete_rows)
|
||||
|
||||
# # Rescan
|
||||
# if track_row and not current:
|
||||
# self._add_context_menu(
|
||||
# "Rescan track", lambda: self._rescan(row_number, track_id)
|
||||
# )
|
||||
# # Move to playlist
|
||||
# if not current and not next_row:
|
||||
# self._add_context_menu(
|
||||
# "Move to playlist...", self.musicmuster.move_selected
|
||||
# )
|
||||
|
||||
# # ----------------------
|
||||
# self.menu.addSeparator()
|
||||
# # ----------------------
|
||||
# self.menu.addSeparator()
|
||||
|
||||
# # Remove row
|
||||
# if not current and not next_row:
|
||||
# self._add_context_menu("Delete row", self._delete_rows)
|
||||
# # Remove track from row
|
||||
# if track_row and not current and not next_row:
|
||||
# self._add_context_menu(
|
||||
# "Remove track from row", lambda: self._remove_track(row_number)
|
||||
# )
|
||||
|
||||
# # Move to playlist
|
||||
# if not current and not next_row:
|
||||
# self._add_context_menu(
|
||||
# "Move to playlist...", self.musicmuster.move_selected
|
||||
# )
|
||||
# Add track to section header (ie, make this a track row)
|
||||
if header_row:
|
||||
self._add_context_menu("Add a track", lambda: self._add_track(row_number))
|
||||
|
||||
# # ----------------------
|
||||
# self.menu.addSeparator()
|
||||
# # Mark unplayed
|
||||
# if self._get_row_userdata(row_number, self.PLAYED):
|
||||
# self._add_context_menu("Mark unplayed", self._mark_unplayed)
|
||||
|
||||
# # Remove track from row
|
||||
# if track_row and not current and not next_row:
|
||||
# self._add_context_menu(
|
||||
# "Remove track from row", lambda: self._remove_track(row_number)
|
||||
# )
|
||||
# # Unmark as next
|
||||
# if next_row:
|
||||
# self._add_context_menu("Unmark as next track", self.clear_next)
|
||||
|
||||
# # Add track to section header (ie, make this a track row)
|
||||
# if header_row:
|
||||
# self._add_context_menu("Add a track", lambda: self._add_track(row_number))
|
||||
|
||||
# # Mark unplayed
|
||||
# if self._get_row_userdata(row_number, self.PLAYED):
|
||||
# self._add_context_menu("Mark unplayed", self._mark_unplayed)
|
||||
|
||||
# # Unmark as next
|
||||
# if next_row:
|
||||
# self._add_context_menu("Unmark as next track", self.clear_next)
|
||||
|
||||
# # ----------------------
|
||||
# self.menu.addSeparator()
|
||||
# # ----------------------
|
||||
self.menu.addSeparator()
|
||||
|
||||
# # Sort
|
||||
# sort_menu = self.menu.addMenu("Sort")
|
||||
@ -1198,12 +1183,12 @@ class PlaylistTab(QTableView):
|
||||
record = Settings.get_int_settings(session, attr_name)
|
||||
record.f_int = self.columnWidth(column_number)
|
||||
|
||||
# def _context_menu(self, pos):
|
||||
# """Display right-click menu"""
|
||||
def _context_menu(self, pos):
|
||||
"""Display right-click menu"""
|
||||
|
||||
# item = self.itemAt(pos)
|
||||
# self._build_context_menu(item)
|
||||
# self.menu.exec(self.mapToGlobal(pos))
|
||||
item = self.indexAt(pos)
|
||||
self._build_context_menu(item)
|
||||
self.menu.exec(self.mapToGlobal(pos))
|
||||
|
||||
def _copy_path(self, row_number: int) -> None:
|
||||
"""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user