Skip to content

Commit 8686932

Browse files
committed
Playlists: allow to adopt current order (sorted) as playlist order
1 parent 6326891 commit 8686932

9 files changed

+99
-3
lines changed

src/library/dao/playlistdao.cpp

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,48 @@ int PlaylistDAO::tracksInPlaylist(const int playlistId) const {
11161116
return count;
11171117
}
11181118

1119+
void PlaylistDAO::orderTracksByCurrPos(const int playlistId,
1120+
QList<std::pair<TrackId, int>>& newOrder) {
1121+
if (newOrder.isEmpty() || playlistId == kInvalidPlaylistId) {
1122+
return;
1123+
}
1124+
ScopedTransaction transaction(m_database);
1125+
QSqlQuery query(m_database);
1126+
query.prepare(QStringLiteral(
1127+
"UPDATE PlaylistTracks "
1128+
"SET position=:new_pos "
1129+
"WHERE position=:old_pos AND "
1130+
"track_id=:track_id AND "
1131+
"playlist_id=:pl_id"));
1132+
int newPos = 1;
1133+
for (auto oldIdAndPos : newOrder) {
1134+
int oldPos = oldIdAndPos.second;
1135+
const TrackId trackId = oldIdAndPos.first;
1136+
VERIFY_OR_DEBUG_ASSERT(trackId.isValid()) {
1137+
return;
1138+
}
1139+
query.bindValue(":new_pos", newPos++);
1140+
query.bindValue(":old_pos", oldPos);
1141+
query.bindValue(":track_id", trackId.toVariant());
1142+
query.bindValue(":pl_id", playlistId);
1143+
if (!query.exec()) {
1144+
// We temporarily have duplicate positions, so abort the entire operation
1145+
// to not leave the playlist with an invalid state.
1146+
LOG_FAILED_QUERY(query);
1147+
return;
1148+
}
1149+
}
1150+
1151+
transaction.commit();
1152+
1153+
// Print out any SQL error, if there was one.
1154+
if (query.lastError().isValid()) {
1155+
qDebug() << query.lastError();
1156+
}
1157+
1158+
emit tracksMoved(QSet<int>{playlistId});
1159+
}
1160+
11191161
void PlaylistDAO::moveTrack(const int playlistId, const int oldPosition, const int newPosition) {
11201162
ScopedTransaction transaction(m_database);
11211163
QSqlQuery query(m_database);
@@ -1341,9 +1383,7 @@ void PlaylistDAO::shuffleTracks(const int playlistId,
13411383
}
13421384
}
13431385

1344-
//qDebug() << "Swapping tracks " << trackAPosition << " and " << trackBPosition;
1345-
trackPositionIds.insert(trackAPosition, trackBId);
1346-
trackPositionIds.insert(trackBPosition, trackAId);
1386+
// qDebug() << "Swapping tracks " << trackAPosition << " and " << trackBPosition;
13471387

13481388
// TODO: The following use of QList<T>::swap(int, int) is deprecated
13491389
// and should be replaced with QList<T>::swapItemsAt(int, int)

src/library/dao/playlistdao.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ class PlaylistDAO : public QObject, public virtual DAO {
110110
bool copyPlaylistTracks(const int sourcePlaylistID, const int targetPlaylistID);
111111
// Returns the number of tracks in the given playlist.
112112
int tracksInPlaylist(const int playlistId) const;
113+
// This receives a track list that represents the current order (sorted by BPM for example)
114+
// and adopts this order for `position` in the playlist
115+
void orderTracksByCurrPos(const int playlistId, QList<std::pair<TrackId, int>>& newOrder);
113116
// moved Track to a new position
114117
void moveTrack(const int playlistId,
115118
const int oldPosition, const int newPosition);

src/library/playlisttablemodel.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,22 @@ void PlaylistTableModel::shuffleTracks(const QModelIndexList& shuffle, const QMo
339339
m_pTrackCollectionManager->internalCollection()->getPlaylistDAO().shuffleTracks(m_iPlaylistId, positions, allIds);
340340
}
341341

342+
void PlaylistTableModel::orderTracksByCurrPos() {
343+
QList<std::pair<TrackId, int>> idPosList;
344+
int numOfTracks = rowCount();
345+
const int positionColumn = fieldIndex(ColumnCache::COLUMN_PLAYLISTTRACKSTABLE_POSITION);
346+
const int idColumn = fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ID);
347+
// Set up list of all IDs
348+
for (int i = 0; i < numOfTracks; i++) {
349+
TrackId trackId(index(i, idColumn).data());
350+
int oldPosition = index(i, positionColumn).data().toInt();
351+
idPosList.append(std::make_pair(trackId, oldPosition));
352+
}
353+
m_pTrackCollectionManager->internalCollection()
354+
->getPlaylistDAO()
355+
.orderTracksByCurrPos(m_iPlaylistId, idPosList);
356+
}
357+
342358
const QList<int> PlaylistTableModel::getSelectedPositions(const QModelIndexList& indices) const {
343359
if (indices.isEmpty()) {
344360
return {};

src/library/playlisttablemodel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class PlaylistTableModel final : public TrackSetTableModel {
2222
void moveTrack(const QModelIndex& sourceIndex, const QModelIndex& destIndex) override;
2323
void removeTrack(const QModelIndex& index);
2424
void shuffleTracks(const QModelIndexList& shuffle, const QModelIndex& exclude);
25+
void orderTracksByCurrPos() override;
2526

2627
bool isColumnInternal(int column) final;
2728
bool isColumnHiddenByDefault(int column) final;

src/library/trackmodel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ class TrackModel {
187187
Q_UNUSED(sourceIndex);
188188
Q_UNUSED(destIndex);
189189
}
190+
virtual void orderTracksByCurrPos() {};
190191
virtual bool isLocked() {
191192
return false;
192193
}

src/widget/wtracktableview.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@ void WTrackTableView::loadTrackModel(QAbstractItemModel* model, bool restoreStat
307307
&WTrackTableViewHeader::shuffle,
308308
this,
309309
&WTrackTableView::slotRandomSorting);
310+
connect(pHeader,
311+
&WTrackTableViewHeader::adoptSortOrder,
312+
this,
313+
&WTrackTableView::slotAdoptSortOrderForPlaylist);
310314

311315
Qt::SortOrder sortOrder;
312316
TrackModel::SortColumnId sortColumn =
@@ -1838,6 +1842,24 @@ void WTrackTableView::slotSortingChanged(int headerSection, Qt::SortOrder order)
18381842
}
18391843
}
18401844

1845+
void WTrackTableView::slotAdoptSortOrderForPlaylist() {
1846+
TrackModel* pTrackModel = getTrackModel();
1847+
if (!pTrackModel) {
1848+
return;
1849+
}
1850+
if (!pTrackModel->hasCapabilities(TrackModel::Capability::Reorder)) {
1851+
return;
1852+
}
1853+
1854+
int sortColumnId = static_cast<int>(m_pSortColumn->get());
1855+
if (sortColumnId == static_cast<int>(TrackModel::SortColumnId::Position)) {
1856+
// If already sorted by number there's noting to do
1857+
return;
1858+
}
1859+
pTrackModel->orderTracksByCurrPos();
1860+
// TODO should we resort by # ??
1861+
}
1862+
18411863
void WTrackTableView::slotRandomSorting() {
18421864
// There's no need to remove the shuffle feature of the Preview column
18431865
// (and replace it with a dedicated randomize slot to BaseSqltableModel),

src/widget/wtracktableview.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class WTrackTableView : public WLibraryTableView {
146146

147147
void slotSortingChanged(int headerSection, Qt::SortOrder order);
148148
void slotRandomSorting();
149+
void slotAdoptSortOrderForPlaylist();
149150
void keyNotationChanged();
150151

151152
protected:

src/widget/wtracktableviewheader.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,17 @@ void WTrackTableViewHeader::setModel(QAbstractItemModel* model) {
218218
/*signal-to-signal*/ Qt::DirectConnection);
219219
m_menu.addAction(pShuffleAction);
220220
}
221+
// Only show the "adopt order" action in models that support reordering
222+
if (pTrackModel->hasCapabilities(TrackModel::Capability::Sorting) &&
223+
pTrackModel->hasCapabilities(TrackModel::Capability::Reorder)) {
224+
auto pAdoptSortorderAction = make_parented<QAction>(tr("Adopt sort order"), &m_menu);
225+
connect(pAdoptSortorderAction,
226+
&QAction::triggered,
227+
this,
228+
&WTrackTableViewHeader::adoptSortOrder,
229+
/*signal-to-signal*/ Qt::DirectConnection);
230+
m_menu.addAction(pAdoptSortorderAction);
231+
}
221232

222233
// Safety check against someone getting stuck with all columns hidden
223234
// (produces an empty library table). Just re-show them all.

src/widget/wtracktableviewheader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class WTrackTableViewHeader : public QHeaderView {
6868

6969
signals:
7070
void shuffle();
71+
void adoptSortOrder();
7172

7273
private slots:
7374
void showOrHideColumn(int);

0 commit comments

Comments
 (0)