diff --git a/app/model.py b/app/model.py index 91b848a..9bfca44 100644 --- a/app/model.py +++ b/app/model.py @@ -188,6 +188,14 @@ class PlaylistTracks(Base): plt.row = row session.commit() + @staticmethod + def remove_track(playlist_id, track_id): + DEBUG(f"remove_track({playlist_id}, {track_id})") + session.query(PlaylistTracks).filter( + PlaylistTracks.playlist_id == playlist_id, + PlaylistTracks.track_id == track_id + ).delete() + class Settings(Base): __tablename__ = 'settings' diff --git a/app/musicmuster.py b/app/musicmuster.py index 46c24b2..1553c26 100755 --- a/app/musicmuster.py +++ b/app/musicmuster.py @@ -5,7 +5,7 @@ import music from datetime import datetime, timedelta -from log import DEBUG +# from log import DEBUG from PyQt5.QtCore import Qt, QTimer from PyQt5.QtWidgets import ( diff --git a/app/playlists.py b/app/playlists.py index 34bea4c..42b6e36 100644 --- a/app/playlists.py +++ b/app/playlists.py @@ -1,13 +1,16 @@ +from PyQt5 import QtCore from PyQt5.QtCore import Qt from PyQt5.Qt import QFont from PyQt5.QtGui import QColor, QDropEvent from PyQt5.QtWidgets import ( - QTableWidget, QAbstractItemView, + QApplication, + QHBoxLayout, + QMenu, + QMessageBox, + QTableWidget, QTableWidgetItem, QWidget, - QHBoxLayout, - QApplication ) import helpers @@ -45,6 +48,14 @@ class Playlist(QTableWidget): self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setDragDropMode(QAbstractItemView.InternalMove) + # This property holds how the widget shows a context menu + self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + # This signal is emitted when the widget's contextMenuPolicy is + # Qt::CustomContextMenu, and the user has requested a context + # menu on the widget. + self.customContextMenuRequested.connect(self.context_menu) + self.viewport().installEventFilter(self) + self.current_track = None self.next_track = None self.playlist_name = None @@ -60,15 +71,6 @@ class Playlist(QTableWidget): if record.f_int is not None: self.setColumnWidth(column, record.f_int) - # How to put in non-track entries for later - # row = self.rowCount() - # self.insertRow(row) - # item = QTableWidgetItem("to be spanned") - # self.setItem(row, 1, item) - # self.setSpan(row, 1, 1, 3) - # colour = QColor(125, 75, 25) - # self.set_row_colour(row, colour) - def __del__(self): "Save column widths" @@ -79,6 +81,59 @@ class Playlist(QTableWidget): if record.f_int != self.columnWidth(column): record.update({'f_int': width}) + def eventFilter(self, source, event): + if(event.type() == QtCore.QEvent.MouseButtonPress and # noqa W504 + event.buttons() == QtCore.Qt.RightButton and # noqa W504 + source is self.viewport()): + item = self.itemAt(event.pos()) + if item is not None: + row = item.row() + DEBUG(f"Right-click on row {row}") + self.menu = QMenu(self) + if row not in self.meta_get_notes(): + act_setnext = self.menu.addAction("Set next") + act_setnext.triggered.connect(lambda: self.set_next(row)) + self.menu.addSeparator() + act_delete = self.menu.addAction('Delete') + act_delete.triggered.connect(lambda: self.delete_row(row)) + + return super(Playlist, self).eventFilter(source, event) + + def context_menu(self, pos): + + self.menu.exec_(self.mapToGlobal(pos)) + + def delete_row(self, row): + "Delete row" + + notes_rows = self.meta_get_notes() + if row in notes_rows: + # TODO + DEBUG("Delete notes not yet implemented") + elif row == self.meta_get_current(): + # TODO + DEBUG("Can't delete playing track") + elif row == self.meta_get_next(): + # TODO + DEBUG("Can't delete next track") + + else: + track_title = self.item(row, self.COL_TITLE).text() + + msg = QMessageBox() + msg.setIcon(QMessageBox.Warning) + msg.setText(f"Delete '{track_title}'?") + msg.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel) + msg.setDefaultButton(QMessageBox.Cancel) + msg.setWindowTitle("Delete row") + if msg.exec() == QMessageBox.Yes: + DEBUG(f"Delete row {row}") + track_id = int(self.item(row, self.COL_INDEX).text()) + PlaylistTracks.remove_track(self.playlist_id, track_id) + self.removeRow(row) + + self.repaint() + def add_note(self, text): """ Add note to playlist @@ -300,7 +355,6 @@ class Playlist(QTableWidget): data.append(([n.row], n)) # Now add data in row order - DEBUG(data) for item in sorted(data, key=lambda x: x[0]): DEBUG(f"Adding {item}") self.add_to_playlist(item[1], repaint=False) @@ -467,17 +521,19 @@ class Playlist(QTableWidget): Sets the selected track as the next track. """ - self.set_row_as_next_track(self.currentRow()) + self.set_next(self.currentRow()) - def set_row_as_next_track(self, row): + def set_next(self, row): """ - If passed row is track row, indicated by having a track_id in the - COL_INDEX column, set that track as the next track to be played - and return True. Otherwise return False. + If passed row is track row, set that track as the next track to + be played and return True. Otherwise return False. """ + if row in self.meta_get_notes(): + return False + if self.item(row, self.COL_INDEX): - self.meta_set_current(row) + self.meta_set_next(row) self.tracks_changed() return True @@ -509,8 +565,11 @@ class Playlist(QTableWidget): self.set_row_colour( row, QColor(Config.COLOUR_CURRENT_PLAYLIST) ) - running_end_time = datetime.strptime(self.item( - row, self.COL_ENDTIME).text(), "%H:%M:%S") + try: + running_end_time = datetime.strptime(self.item( + row, self.COL_ENDTIME).text(), "%H:%M:%S") + except AttributeError: + pass self.set_row_bold(row) elif row == next: