diff --git a/src/library/dao/playlistdao.cpp b/src/library/dao/playlistdao.cpp index 50aa06c9c8f3..1287b512f86e 100644 --- a/src/library/dao/playlistdao.cpp +++ b/src/library/dao/playlistdao.cpp @@ -246,6 +246,26 @@ bool PlaylistDAO::isPlaylistLocked(const int playlistId) const { return false; } +// TODO: Deduplicate with deletePlaylist? +bool PlaylistDAO::clearPlaylist(const int playlistId) { + ScopedTransaction transaction(m_database); + QSqlQuery query(m_database); + query.prepare("DELETE FROM PlaylistTracks WHERE playlist_id = :id"); + query.bindValue(":id", playlistId); + if (!query.exec()) { + LOG_FAILED_QUERY(query); + return false; + } + transaction.commit(); + emit(changed(playlistId)); + return true; +} + +bool PlaylistDAO::replaceTracksInPlaylist(const QList& trackIds, const int playlistId) { + return clearPlaylist(playlistId) + && appendTracksToPlaylist(trackIds, playlistId); +} + bool PlaylistDAO::appendTracksToPlaylist(const QList& trackIds, const int playlistId) { // qDebug() << "PlaylistDAO::appendTracksToPlaylist" // << QThread::currentThread() << m_database.connectionName(); diff --git a/src/library/dao/playlistdao.h b/src/library/dao/playlistdao.h index dd5a22149397..64ec0cc190c9 100644 --- a/src/library/dao/playlistdao.h +++ b/src/library/dao/playlistdao.h @@ -57,6 +57,8 @@ class PlaylistDAO : public QObject, public virtual DAO { bool setPlaylistLocked(const int playlistId, const bool locked); // Find out the state of a playlist lock bool isPlaylistLocked(const int playlistId) const; + // Replace all tracks in a playlist by a new list of tracks + bool replaceTracksInPlaylist(const QList& trackIds, const int playlistId); // Append a list of tracks to a playlist bool appendTracksToPlaylist(const QList& trackIds, const int playlistId); // Append a track to a playlist @@ -120,6 +122,7 @@ class PlaylistDAO : public QObject, public virtual DAO { void lockChanged(int playlistId); private: + bool clearPlaylist(const int playlistId); void removeTracksFromPlaylistsInner(const QStringList& idList); void searchForDuplicateTrack(const int fromPosition, const int toPosition, diff --git a/src/library/dlganalysis.cpp b/src/library/dlganalysis.cpp index 4c07e30a4295..b1762357b9c1 100644 --- a/src/library/dlganalysis.cpp +++ b/src/library/dlganalysis.cpp @@ -88,15 +88,19 @@ void DlgAnalysis::loadSelectedTrackToGroup(QString group, bool play) { m_pAnalysisLibraryTableView->loadSelectedTrackToGroup(group, play); } -void DlgAnalysis::slotSendToAutoDJ() { +void DlgAnalysis::slotSendToAutoDJBottom() { // append to auto DJ - m_pAnalysisLibraryTableView->slotSendToAutoDJ(); + m_pAnalysisLibraryTableView->slotSendToAutoDJBottom(); } void DlgAnalysis::slotSendToAutoDJTop() { m_pAnalysisLibraryTableView->slotSendToAutoDJTop(); } +void DlgAnalysis::slotSendToAutoDJReplace() { + m_pAnalysisLibraryTableView->slotSendToAutoDJReplace(); +} + void DlgAnalysis::moveSelection(int delta) { m_pAnalysisLibraryTableView->moveSelection(delta); } diff --git a/src/library/dlganalysis.h b/src/library/dlganalysis.h index 012fadaffabc..67c4a676649b 100644 --- a/src/library/dlganalysis.h +++ b/src/library/dlganalysis.h @@ -25,8 +25,9 @@ class DlgAnalysis : public QWidget, public Ui::DlgAnalysis, public virtual Libra bool hasFocus() const override; void loadSelectedTrack() override; void loadSelectedTrackToGroup(QString group, bool play) override; - void slotSendToAutoDJ() override; + void slotSendToAutoDJBottom() override; void slotSendToAutoDJTop() override; + void slotSendToAutoDJReplace() override; void moveSelection(int delta) override; inline const QString currentSearch() { return m_pAnalysisLibraryTableModel->currentSearch(); diff --git a/src/library/librarycontrol.cpp b/src/library/librarycontrol.cpp index 2a0c239272a3..d3d13e3472a4 100644 --- a/src/library/librarycontrol.cpp +++ b/src/library/librarycontrol.cpp @@ -285,7 +285,7 @@ void LibraryControl::slotAutoDjAddBottom(double v) { if (!activeView) { return; } - activeView->slotSendToAutoDJ(); + activeView->slotSendToAutoDJBottom(); } } diff --git a/src/library/libraryview.h b/src/library/libraryview.h index 1e5a5c03a289..7be3d9d1e528 100644 --- a/src/library/libraryview.h +++ b/src/library/libraryview.h @@ -22,8 +22,9 @@ class LibraryView { // track. Does nothing otherwise. virtual void loadSelectedTrack() {}; - virtual void slotSendToAutoDJ() {}; + virtual void slotSendToAutoDJBottom() {}; virtual void slotSendToAutoDJTop() {}; + virtual void slotSendToAutoDJReplace() {}; // If applicable, requests that the LibraryView load the selected track to // the specified group. Does nothing otherwise. diff --git a/src/library/recording/dlgrecording.cpp b/src/library/recording/dlgrecording.cpp index d55326b90c0d..e23af2577942 100644 --- a/src/library/recording/dlgrecording.cpp +++ b/src/library/recording/dlgrecording.cpp @@ -89,14 +89,18 @@ void DlgRecording::loadSelectedTrack() { m_pTrackTableView->loadSelectedTrack(); } -void DlgRecording::slotSendToAutoDJ() { - m_pTrackTableView->slotSendToAutoDJ(); +void DlgRecording::slotSendToAutoDJBottom() { + m_pTrackTableView->slotSendToAutoDJBottom(); } void DlgRecording::slotSendToAutoDJTop() { m_pTrackTableView->slotSendToAutoDJTop(); } +void DlgRecording::slotSendToAutoDJReplace() { + m_pTrackTableView->slotSendToAutoDJReplace(); +} + void DlgRecording::loadSelectedTrackToGroup(QString group, bool play) { m_pTrackTableView->loadSelectedTrackToGroup(group, play); } diff --git a/src/library/recording/dlgrecording.h b/src/library/recording/dlgrecording.h index caf8fd054722..56c8d9e4aa19 100644 --- a/src/library/recording/dlgrecording.h +++ b/src/library/recording/dlgrecording.h @@ -28,8 +28,9 @@ class DlgRecording : public QWidget, public Ui::DlgRecording, public virtual Lib void onShow() override; bool hasFocus() const override; void loadSelectedTrack() override; - void slotSendToAutoDJ() override; + void slotSendToAutoDJBottom() override; void slotSendToAutoDJTop() override; + void slotSendToAutoDJReplace() override; void loadSelectedTrackToGroup(QString group, bool play) override; void moveSelection(int delta) override; inline const QString currentSearch() { return m_proxyModel.currentSearch(); } diff --git a/src/widget/wtracktableview.cpp b/src/widget/wtracktableview.cpp index 4e1834ec5c6a..9d7ba16a6353 100644 --- a/src/widget/wtracktableview.cpp +++ b/src/widget/wtracktableview.cpp @@ -117,7 +117,7 @@ WTrackTableView::~WTrackTableView() { delete m_pReloadMetadataAct; delete m_pReloadMetadataFromMusicBrainzAct; delete m_pAddToPreviewDeck; - delete m_pAutoDJAct; + delete m_pAutoDJBottomAct; delete m_pAutoDJTopAct; delete m_pRemoveAct; delete m_pHideAct; @@ -383,13 +383,18 @@ void WTrackTableView::createActions() { connect(m_pFileBrowserAct, SIGNAL(triggered()), this, SLOT(slotOpenInFileBrowser())); - m_pAutoDJAct = new QAction(tr("Add to Auto DJ Queue (bottom)"), this); - connect(m_pAutoDJAct, SIGNAL(triggered()), this, SLOT(slotSendToAutoDJ())); + m_pAutoDJBottomAct = new QAction(tr("Add to Auto-DJ Queue (bottom)"), this); + connect(m_pAutoDJBottomAct, SIGNAL(triggered()), + this, SLOT(slotSendToAutoDJBottom())); m_pAutoDJTopAct = new QAction(tr("Add to Auto DJ Queue (top)"), this); connect(m_pAutoDJTopAct, SIGNAL(triggered()), this, SLOT(slotSendToAutoDJTop())); + m_pAutoDJReplaceAct = new QAction(tr("Add to Auto-DJ Queue (replace)"), this); + connect(m_pAutoDJReplaceAct, SIGNAL(triggered()), + this, SLOT(slotSendToAutoDJReplace())); + m_pReloadMetadataAct = new QAction(tr("Reload Metadata from File"), this); connect(m_pReloadMetadataAct, SIGNAL(triggered()), this, SLOT(slotReloadTrackMetadata())); @@ -465,10 +470,10 @@ void WTrackTableView::slotMouseDoubleClicked(const QModelIndex &index) { } switch (action) { case DlgPrefLibrary::ADD_TRACK_BOTTOM: - sendToAutoDJ(false); // add track to Auto-DJ Queue (bottom) + sendToAutoDJ(SEND_BOTTOM); // add track to Auto-DJ Queue (bottom) break; case DlgPrefLibrary::ADD_TRACK_TOP: - sendToAutoDJ(true); // add track to Auto-DJ Queue (top) + sendToAutoDJ(SEND_TOP); // add track to Auto-DJ Queue (top) break; default: // load track to next available deck TrackModel* trackModel = getTrackModel(); @@ -726,8 +731,9 @@ void WTrackTableView::contextMenuEvent(QContextMenuEvent* event) { m_pMenu->clear(); if (modelHasCapabilities(TrackModel::TRACKMODELCAPS_ADDTOAUTODJ)) { - m_pMenu->addAction(m_pAutoDJAct); + m_pMenu->addAction(m_pAutoDJBottomAct); m_pMenu->addAction(m_pAutoDJTopAct); + m_pMenu->addAction(m_pAutoDJReplaceAct); m_pMenu->addSeparator(); } @@ -1305,16 +1311,20 @@ void WTrackTableView::loadSelectedTrackToGroup(QString group, bool play) { loadSelectionToGroup(group, play); } -void WTrackTableView::slotSendToAutoDJ() { +void WTrackTableView::slotSendToAutoDJBottom() { // append to auto DJ - sendToAutoDJ(false); // bTop = false + sendToAutoDJ(SEND_BOTTOM); } void WTrackTableView::slotSendToAutoDJTop() { - sendToAutoDJ(true); // bTop = true + sendToAutoDJ(SEND_TOP); +} + +void WTrackTableView::slotSendToAutoDJReplace() { + sendToAutoDJ(SEND_REPLACE); } -void WTrackTableView::sendToAutoDJ(bool bTop) { +void WTrackTableView::sendToAutoDJ(AutoDJSendLoc loc) { if (!modelHasCapabilities(TrackModel::TRACKMODELCAPS_ADDTOAUTODJ)) { return; } @@ -1340,10 +1350,23 @@ void WTrackTableView::sendToAutoDJ(bool bTop) { } } - m_pTrackCollection->getTrackDAO().unhideTracks(trackIds); - - // TODO(XXX): Care whether the append succeeded. - playlistDao.sendToAutoDJ(trackIds, bTop); + switch (loc) { + case SEND_TOP: + // Load track to position two because position one is + // already loaded to the player + playlistDao.insertTracksIntoPlaylist(trackIds, + iAutoDJPlaylistId, 2); + break; + case SEND_BOTTOM: + // TODO(XXX): Care whether the append succeeded. + m_pTrackCollection->getTrackDAO().unhideTracks(trackIds); + playlistDao.appendTracksToPlaylist( + trackIds, iAutoDJPlaylistId); + break; + case SEND_REPLACE: + playlistDao.replaceTracksInPlaylist(trackIds, iAutoDJPlaylistId); + break; + } } void WTrackTableView::slotReloadTrackMetadata() { diff --git a/src/widget/wtracktableview.h b/src/widget/wtracktableview.h index 0363e026e2ff..c5943eae1421 100644 --- a/src/widget/wtracktableview.h +++ b/src/widget/wtracktableview.h @@ -44,8 +44,9 @@ class WTrackTableView : public WLibraryTableView { void slotPurge(); void onSearchStarting(); void onSearchCleared(); - void slotSendToAutoDJ() override; + void slotSendToAutoDJBottom() override; void slotSendToAutoDJTop() override; + void slotSendToAutoDJReplace() override; private slots: void slotRemove(); @@ -79,7 +80,13 @@ class WTrackTableView : public WLibraryTableView { void slotTagFetcherClosed(); private: - void sendToAutoDJ(bool bTop); + enum AutoDJSendLoc { + SEND_TOP, + SEND_BOTTOM, + SEND_REPLACE, + }; + + void sendToAutoDJ(AutoDJSendLoc loc); void showTrackInfo(QModelIndex index); void showDlgTagFetcher(QModelIndex index); void createActions(); @@ -128,8 +135,9 @@ class WTrackTableView : public WLibraryTableView { QAction* m_pAddToPreviewDeck; // Send to Auto-DJ Action - QAction *m_pAutoDJAct; + QAction *m_pAutoDJBottomAct; QAction *m_pAutoDJTopAct; + QAction *m_pAutoDJReplaceAct; // Remove from table QAction *m_pRemoveAct;