--- mixxx/src/library/autodjfeature.cpp 2013-05-10 15:55:01.552534000 -0700 +++ mixxx-build/src/library/autodjfeature.cpp 2013-05-11 16:04:35.986341748 -0700 @@ -88,8 +88,9 @@ trackIds.removeAt(trackId--); } } - m_playlistDao.appendTracksToPlaylist(trackIds, playlistId); - return true; + + // Return whether the tracks were appended. + return m_playlistDao.appendTracksToPlaylist(trackIds, playlistId); } bool AutoDJFeature::dragMoveAccept(QUrl url) { --- mixxx/src/library/baseexternallibraryfeature.cpp 2013-05-10 15:55:01.552534000 -0700 +++ mixxx-build/src/library/baseexternallibraryfeature.cpp 2013-05-11 16:04:56.021888163 -0700 @@ -93,6 +93,7 @@ // Start at position 2 because position 1 was already loaded to the deck playlistDao.insertTrackIntoPlaylist(track->getId(), autoDJId, i+2); } else { + // TODO(XXX): Care whether the append succeeded. playlistDao.appendTrackToPlaylist(track->getId(), autoDJId); } } @@ -142,6 +143,7 @@ if (index.isValid()) { qDebug() << pPlaylistModelToAdd->getTrackLocation(index); TrackPointer track = pPlaylistModelToAdd->getTrack(index); + // TODO(XXX): Care whether the append succeeded. playlistDao.appendTrackToPlaylist(track->getId(), playlistId); } } --- mixxx/src/library/baseplaylistfeature.cpp 2013-05-10 15:55:01.552534000 -0700 +++ mixxx-build/src/library/baseplaylistfeature.cpp 2013-05-11 16:05:10.681751356 -0700 @@ -188,11 +188,10 @@ } while (!validNameGiven); int newPlaylistId = m_playlistDao.createPlaylist(name); - m_playlistDao.copyPlaylistTracks(oldPlaylistId, newPlaylistId); - if (newPlaylistId != -1) { + if (newPlaylistId != -1 + && m_playlistDao.copyPlaylistTracks(oldPlaylistId, newPlaylistId)) emit(showTrackModel(m_pPlaylistTableModel)); - } } void BasePlaylistFeature::slotTogglePlaylistLock() { --- mixxx/src/library/basesqltablemodel.cpp 2013-05-11 16:48:41.297547199 -0700 +++ mixxx-build/src/library/basesqltablemodel.cpp 2013-05-11 16:49:32.668076129 -0700 @@ -472,7 +472,7 @@ } else if (column == fieldIndex(PLAYLISTTRACKSTABLE_DATETIMEADDED)) { QDateTime gmtDate = value.toDateTime(); gmtDate.setTimeSpec(Qt::UTC); - value = gmtDate.toLocalTime().time(); + value = gmtDate.toLocalTime(); } else if (column == fieldIndex(LIBRARYTABLE_BPM_LOCK)) { value = value.toBool(); } --- mixxx/src/library/dao/playlistdao.cpp 2013-05-10 15:55:01.552534000 -0700 +++ mixxx-build/src/library/dao/playlistdao.cpp 2013-05-11 16:56:47.724369547 -0700 @@ -177,7 +177,7 @@ return false; } -void PlaylistDAO::appendTracksToPlaylist(QList trackIds, int playlistId) { +bool PlaylistDAO::appendTracksToPlaylist(QList trackIds, int playlistId) { // qDebug() << "PlaylistDAO::appendTracksToPlaylist" // << QThread::currentThread() << m_database.connectionName(); @@ -203,6 +203,7 @@ query.bindValue(":position", insertPosition++); if (!query.exec()) { LOG_FAILED_QUERY(query); + return false; } } @@ -215,12 +216,13 @@ emit(trackAdded(playlistId, trackId, insertPosition++)); } emit(changed(playlistId)); + return true; } -void PlaylistDAO::appendTrackToPlaylist(int trackId, int playlistId) { +bool PlaylistDAO::appendTrackToPlaylist(int trackId, int playlistId) { QList tracks; tracks.append(trackId); - appendTracksToPlaylist(tracks, playlistId); + return appendTracksToPlaylist(tracks, playlistId); } /** Find out how many playlists exist. */ @@ -523,6 +525,7 @@ if (bTop) { insertTracksIntoPlaylist(ids, autoDJId, 2); } else { + // TODO(XXX): Care whether the append succeeded. appendTracksToPlaylist(ids, autoDJId); } } @@ -549,23 +552,59 @@ return previousPlaylistId; } -void PlaylistDAO::copyPlaylistTracks(int sourcePlaylistID, int targetPlaylistId) { - // Query Tracks from the source Playlist - QSqlQuery query(m_database); - query.prepare("SELECT track_id FROM PlaylistTracks " - "WHERE playlist_id = :plid"); - query.bindValue(":plid", sourcePlaylistID); +bool PlaylistDAO::copyPlaylistTracks(int sourcePlaylistID, int targetPlaylistID) { + // Start the transaction + ScopedTransaction transaction(m_database); + + // Copy the new tracks after the last track in the target playlist. + int positionOffset = getMaxPosition(targetPlaylistID); + + // Copy the tracks from one playlist to another, adjusting the position of + // each copied track, and preserving the date/time added. + // INSERT INTO PlaylistTracks (playlist_id, track_id, position, pl_datetime_added) SELECT :target_plid, track_id, position + :position_offset, pl_datetime_added FROM PlaylistTracks WHERE playlist_id = :source_plid; + QSqlQuery query(m_database); + query.prepare(QString("INSERT INTO " PLAYLIST_TRACKS_TABLE + " (%1, %2, %3, %4) SELECT :target_plid, %2, " + "%3 + :position_offset, %4 FROM " PLAYLIST_TRACKS_TABLE + " WHERE %1 = :source_plid") + .arg(PLAYLISTTRACKSTABLE_PLAYLISTID) // %1 + .arg(PLAYLISTTRACKSTABLE_TRACKID) // %2 + .arg(PLAYLISTTRACKSTABLE_POSITION) // %3 + .arg(PLAYLISTTRACKSTABLE_DATETIMEADDED)); // %4 + query.bindValue(":position_offset", positionOffset); + query.bindValue(":source_plid", sourcePlaylistID); + query.bindValue(":target_plid", targetPlaylistID); if (!query.exec()) { LOG_FAILED_QUERY(query); - return; + return false; } - QList trackIds; + // Query each added track and its new position. + // SELECT track_id, position FROM PlaylistTracks WHERE playlist_id = :target_plid AND position > :position_offset; + query.prepare(QString("SELECT %2, %3 FROM " PLAYLIST_TRACKS_TABLE + " WHERE %1 = :target_plid AND %3 > :position_offset") + .arg(PLAYLISTTRACKSTABLE_PLAYLISTID) // %1 + .arg(PLAYLISTTRACKSTABLE_TRACKID) // %2 + .arg(PLAYLISTTRACKSTABLE_POSITION)); // %3 + query.bindValue(":target_plid", targetPlaylistID); + query.bindValue(":position_offset", positionOffset); + if (!query.exec()) { + LOG_FAILED_QUERY(query); + return false; + } + + // Commit the transaction + transaction.commit(); + + // Let subscribers know about each added track. while (query.next()) { - trackIds.append(query.value(0).toInt()); + int copiedTrackId = query.value(0).toInt(); + int copiedPosition = query.value(1).toInt(); + emit(trackAdded(targetPlaylistID, copiedTrackId, copiedPosition)); } - appendTracksToPlaylist(trackIds, targetPlaylistId); + emit(changed(targetPlaylistID)); + return true; } int PlaylistDAO::getMaxPosition(int playlistId) { --- mixxx/src/library/dao/playlistdao.h 2013-05-10 15:55:01.552534000 -0700 +++ mixxx-build/src/library/dao/playlistdao.h 2013-05-11 16:03:41.919470126 -0700 @@ -44,9 +44,9 @@ // Find out the state of a playlist lock bool isPlaylistLocked(int playlistId); // Append a list of tracks to a playlist - void appendTracksToPlaylist(QList trackIds, int playlistId); + bool appendTracksToPlaylist(QList trackIds, int playlistId); // Append a track to a playlist - void appendTrackToPlaylist(int trackId, int playlistId); + bool appendTrackToPlaylist(int trackId, int playlistId); // Find out how many playlists exist. unsigned int playlistCount(); // Find out the name of the playlist at the given Id @@ -79,7 +79,7 @@ // hidden. Returns -1 if no such playlist exists. int getPreviousPlaylist(int currentPlaylistId, HiddenType hidden); // Append all the tracks in the source playlist to the target playlist. - void copyPlaylistTracks(int sourcePlaylistID, int targetPlaylistId); + bool copyPlaylistTracks(int sourcePlaylistID, int targetPlaylistID); // Returns the number of tracks in the given playlist. int tracksInPlaylist(int playlistId); signals: --- mixxx/src/library/legacylibraryimporter.cpp 2013-05-10 15:55:01.552534000 -0700 +++ mixxx-build/src/library/legacylibraryimporter.cpp 2013-05-11 16:05:20.750030982 -0700 @@ -171,7 +171,8 @@ int dbTrackId = m_trackDao.getTrackId(trackLocation); if (dbTrackId >= 0) { - //Add it to the database's playlist. + // Add it to the database's playlist. + // TODO(XXX): Care if the append succeeded. m_playlistDao.appendTrackToPlaylist(dbTrackId, playlistId); } } --- mixxx/src/library/playlistfeature.cpp 2013-05-10 15:55:01.552534000 -0700 +++ mixxx-build/src/library/playlistfeature.cpp 2013-05-11 16:05:44.789086223 -0700 @@ -117,10 +117,8 @@ } } - // appendTracksToPlaylist doesn't return whether it succeeded, so assume it - // did. - m_playlistDao.appendTracksToPlaylist(trackIds, playlistId); - return true; + // Return whether appendTracksToPlaylist succeeded. + return m_playlistDao.appendTracksToPlaylist(trackIds, playlistId); } bool PlaylistFeature::dragMoveAcceptChild(const QModelIndex& index, QUrl url) { --- mixxx/src/library/playlisttablemodel.cpp 2013-05-10 15:55:01.552534000 -0700 +++ mixxx-build/src/library/playlisttablemodel.cpp 2013-05-11 16:05:53.039134762 -0700 @@ -109,10 +109,10 @@ return false; } - m_playlistDao.appendTrackToPlaylist(trackId, m_iPlaylistId); + bool bSuccess = m_playlistDao.appendTrackToPlaylist(trackId, m_iPlaylistId); select(); //Repopulate the data model. - return true; + return bSuccess; } int PlaylistTableModel::addTracks(const QModelIndex& index, QList locations) { --- mixxx/src/library/setlogfeature.cpp 2013-05-10 15:55:01.552534000 -0700 +++ mixxx-build/src/library/setlogfeature.cpp 2013-05-11 16:06:11.983542498 -0700 @@ -202,10 +202,11 @@ m_playlistId = previousPlaylistId; } qDebug() << "slotJoinWithPrevious() current:" << currentPlaylistId << " previous:" << previousPlaylistId; - m_playlistDao.copyPlaylistTracks(currentPlaylistId, previousPlaylistId); - m_playlistDao.deletePlaylist(currentPlaylistId); - slotPlaylistTableChanged(previousPlaylistId); // For moving selection - emit(showTrackModel(m_pPlaylistTableModel)); + if (m_playlistDao.copyPlaylistTracks(currentPlaylistId, previousPlaylistId)) { + m_playlistDao.deletePlaylist(currentPlaylistId); + slotPlaylistTableChanged(previousPlaylistId); // For moving selection + emit(showTrackModel(m_pPlaylistTableModel)); + } } } } @@ -255,6 +256,7 @@ // View needs a refresh m_pPlaylistTableModel->appendTrack(currentPlayingTrackId); } else { + // TODO(XXX): Care whether the append succeeded. m_playlistDao.appendTrackToPlaylist(currentPlayingTrackId, m_playlistId); } --- mixxx/src/widget/wtracktableview.cpp 2013-05-10 15:55:01.552534000 -0700 +++ mixxx-build/src/widget/wtracktableview.cpp 2013-05-11 16:06:27.210477763 -0700 @@ -1040,6 +1040,7 @@ playlistDao.insertTracksIntoPlaylist(trackIds, iAutoDJPlaylistId, 2); } else { + // TODO(XXX): Care whether the append succeeded. playlistDao.appendTracksToPlaylist( trackIds, iAutoDJPlaylistId); } @@ -1104,6 +1105,7 @@ } } if (trackIds.size() > 0) { + // TODO(XXX): Care whether the append succeeded. playlistDao.appendTracksToPlaylist(trackIds, iPlaylistId); } }