Merge lp:~shetyeakash/mixxx/bulk_operations into lp:mixxx/1.10
- bulk_operations
- Merge into release-1.10.x
Proposed by
RJ Skerry-Ryan
Status: | Merged |
---|---|
Merged at revision: | 3088 |
Proposed branch: | lp:~shetyeakash/mixxx/bulk_operations |
Merge into: | lp:mixxx/1.10 |
Diff against target: |
391 lines (+209/-8) 14 files modified
mixxx/src/library/cratetablemodel.cpp (+26/-0) mixxx/src/library/cratetablemodel.h (+1/-0) mixxx/src/library/dao/cratedao.cpp (+32/-0) mixxx/src/library/dao/cratedao.h (+1/-0) mixxx/src/library/dao/playlistdao.cpp (+45/-0) mixxx/src/library/dao/playlistdao.h (+2/-0) mixxx/src/library/dao/trackdao.cpp (+21/-0) mixxx/src/library/dao/trackdao.h (+1/-0) mixxx/src/library/librarytablemodel.cpp (+17/-0) mixxx/src/library/librarytablemodel.h (+1/-0) mixxx/src/library/playlisttablemodel.cpp (+35/-0) mixxx/src/library/playlisttablemodel.h (+1/-0) mixxx/src/library/trackmodel.h (+5/-0) mixxx/src/widget/wtracktableview.cpp (+21/-8) |
To merge this branch: | bzr merge lp:~shetyeakash/mixxx/bulk_operations |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
RJ Skerry-Ryan | Approve | ||
Review via email: mp+104669@code.launchpad.net |
Commit message
Description of the change
Akash has added fixes to our DAOs that let you add tracks to playlists, crates, and the main library in bulk. This helps speed up bulk operations in the GUI like adding many tracks to a playlist or crate.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'mixxx/src/library/cratetablemodel.cpp' |
2 | --- mixxx/src/library/cratetablemodel.cpp 2012-05-04 03:00:08 +0000 |
3 | +++ mixxx/src/library/cratetablemodel.cpp 2012-05-04 05:15:32 +0000 |
4 | @@ -66,6 +66,7 @@ |
5 | bool CrateTableModel::addTrack(const QModelIndex& index, QString location) { |
6 | // If a track is dropped but it isn't in the library, then add it because |
7 | // the user probably dropped a file from outside Mixxx into this playlist. |
8 | + qDebug()<<"CrateTableModel's addTrack called"; |
9 | QFileInfo fileInfo(location); |
10 | |
11 | TrackDAO& trackDao = m_pTrackCollection->getTrackDAO(); |
12 | @@ -89,6 +90,31 @@ |
13 | } |
14 | } |
15 | |
16 | +//Returns the number of unsuccessful track additions |
17 | +//Violates the convention of passing QModelIndexes which aren't used though. |
18 | +int CrateTableModel::addTracks(const QModelIndex& index, QList <QString> locations) { |
19 | + int trackAddFails = 0; |
20 | + //prepare the list of QFileInfo's |
21 | + QList <QFileInfo> fileInfoList; |
22 | + QString fileLocation; |
23 | + foreach(fileLocation, locations) { |
24 | + qDebug()<<"Location "<< fileLocation; |
25 | + QFileInfo fileInfo(fileLocation); |
26 | + fileInfoList.append(fileInfo); |
27 | + } |
28 | + TrackDAO& trackDao = m_pTrackCollection->getTrackDAO(); |
29 | + QList <int> trackIDs; |
30 | + trackIDs = trackDao.addTracks(fileInfoList, true); // returns ids of tracks in QList |
31 | + //Assuming from trackdao implementation that -1 is returned on add fail |
32 | + trackAddFails = trackIDs.removeAll(-1); |
33 | + //add these trackIDs to the crate in bulk |
34 | + //returns number of unsucessful crate additions |
35 | + int crateAddFails = m_pTrackCollection->getCrateDAO().addTracksToCrate(trackIDs, m_iCrateId); |
36 | + //prompting the errors on console due to unsucessful crate additions are not done |
37 | + select();//doing a select on the model |
38 | + return crateAddFails;//return no of tracks failed to add to crate. |
39 | +} |
40 | + |
41 | TrackPointer CrateTableModel::getTrack(const QModelIndex& index) const { |
42 | int trackId = getTrackId(index); |
43 | return m_pTrackCollection->getTrackDAO().getTrack(trackId); |
44 | |
45 | === modified file 'mixxx/src/library/cratetablemodel.h' |
46 | --- mixxx/src/library/cratetablemodel.h 2011-11-27 06:59:02 +0000 |
47 | +++ mixxx/src/library/cratetablemodel.h 2012-05-04 05:15:32 +0000 |
48 | @@ -30,6 +30,7 @@ |
49 | virtual void removeTrack(const QModelIndex& index); |
50 | virtual void removeTracks(const QModelIndexList& indices); |
51 | virtual bool addTrack(const QModelIndex& index, QString location); |
52 | + virtual int addTracks(const QModelIndex& index, QList <QString> locations); |
53 | virtual void moveTrack(const QModelIndex& sourceIndex, |
54 | const QModelIndex& destIndex); |
55 | TrackModel::CapabilitiesFlags getCapabilities() const; |
56 | |
57 | === modified file 'mixxx/src/library/dao/cratedao.cpp' |
58 | --- mixxx/src/library/dao/cratedao.cpp 2012-03-14 04:49:35 +0000 |
59 | +++ mixxx/src/library/dao/cratedao.cpp 2012-05-04 05:15:32 +0000 |
60 | @@ -197,6 +197,38 @@ |
61 | return true; |
62 | } |
63 | |
64 | +//This method takes a list of track ids to be added to crate and returns # failed track additions |
65 | +int CrateDAO::addTracksToCrate(QList <int> trackIdList, int crateId) { |
66 | + int crateAddFails = 0; |
67 | + QSqlQuery query(m_database); |
68 | + //the transaction begins |
69 | + m_database.transaction(); |
70 | + for(int i = 0; i<trackIdList.size(); i++) { |
71 | + query.prepare("INSERT INTO " CRATE_TRACKS_TABLE "(crate_id, track_id) VALUES (:crate_id, :track_id)"); |
72 | + query.bindValue(":crate_id", crateId); |
73 | + query.bindValue(":track_id", (int) trackIdList.at(i)); |
74 | + if(!query.exec()) { |
75 | + LOG_FAILED_QUERY(query); |
76 | + //query failed so increment the # of failed additions to crate |
77 | + crateAddFails++; |
78 | + //we must emit only those trackID that were added |
79 | + //So we need to remove the failed ones |
80 | + trackIdList.removeAt(i); |
81 | + } |
82 | + } |
83 | + //Finished adding tracks to database, commit transaction |
84 | + m_database.commit(); |
85 | + int trackId; |
86 | + //Emitting the trackAdded signals for each trackID outside the transaction |
87 | + foreach(trackId, trackIdList) { |
88 | + emit(trackAdded(crateId, trackId)); |
89 | + } |
90 | + //Crate has been changed |
91 | + emit(changed(crateId)); |
92 | + //return the number of crate additions that have failed |
93 | + return crateAddFails; |
94 | +} |
95 | + |
96 | void CrateDAO::removeTrackFromCrates(int trackId) { |
97 | QSqlQuery query(m_database); |
98 | QString queryString = QString("DELETE FROM %1 WHERE %2 = %3") |
99 | |
100 | === modified file 'mixxx/src/library/dao/cratedao.h' |
101 | --- mixxx/src/library/dao/cratedao.h 2011-10-21 00:42:23 +0000 |
102 | +++ mixxx/src/library/dao/cratedao.h 2012-05-04 05:15:32 +0000 |
103 | @@ -38,6 +38,7 @@ |
104 | QString crateName(int crateId); |
105 | unsigned int crateSize(int crateId); |
106 | bool addTrackToCrate(int trackId, int crateId); |
107 | + int addTracksToCrate(QList <int> trackIdList, int crateId); |
108 | void removeTrackFromCrates(int trackId); |
109 | bool removeTrackFromCrate(int trackId, int crateId); |
110 | |
111 | |
112 | === modified file 'mixxx/src/library/dao/playlistdao.cpp' |
113 | --- mixxx/src/library/dao/playlistdao.cpp 2011-10-21 00:42:23 +0000 |
114 | +++ mixxx/src/library/dao/playlistdao.cpp 2012-05-04 05:15:32 +0000 |
115 | @@ -396,6 +396,51 @@ |
116 | emit(changed(playlistId)); |
117 | } |
118 | |
119 | +//Takes a list of trackIDs to be inserted into a given playlist |
120 | +void PlaylistDAO::insertTracksIntoPlaylist(QList <int> trackIDs, int playlistId, int position) { |
121 | + if (playlistId < 0 || position < 0 ) { |
122 | + return; |
123 | + } |
124 | + m_database.transaction(); |
125 | + |
126 | + int trackID = -1; |
127 | + foreach (trackID, trackIDs) { |
128 | + if (!(trackID < 0)) { |
129 | + //move all tracks in playlist up by 1 |
130 | + //Any reason why a prepared statement isn't used here ?? |
131 | + QString queryString = QString("UPDATE PlaylistTracks SET position=position+1 " |
132 | + "WHERE position>=%1 AND" |
133 | + "playlist_id=%2").arg(position).arg(playlistId); |
134 | + QSqlQuery query(m_database); |
135 | + if (!query.exec(queryString)) { |
136 | + LOG_FAILED_QUERY(query); |
137 | + } |
138 | + |
139 | + //Insert the track at the given position |
140 | + query.prepare("INSERT INTO PlaylistTracks (playlist_id, track_id, position)" |
141 | + "VALUES (:playlist_id, :track_id, :position)"); |
142 | + query.bindValue(":playlist_id", playlistId); |
143 | + query.bindValue(":track_id", trackID); |
144 | + query.bindValue(":position", position); |
145 | + |
146 | + if (!query.exec()) { |
147 | + LOG_FAILED_QUERY(query); |
148 | + } |
149 | + } |
150 | + } |
151 | + |
152 | + m_database.commit(); |
153 | + //all failed tracks are with trackID -1 |
154 | + trackIDs.removeAll(-1); |
155 | + |
156 | + foreach (trackID, trackIDs) { |
157 | + // The emitted position isn't actually the real position of the track |
158 | + emit(trackAdded(playlistId, trackID, position)); |
159 | + } |
160 | + emit(changed(playlistId)); |
161 | + |
162 | +} |
163 | + |
164 | void PlaylistDAO::addToAutoDJQueue(int playlistId) { |
165 | //qDebug() << "Adding tracks from playlist " << playlistId << " to the Auto-DJ Queue"; |
166 | |
167 | |
168 | === modified file 'mixxx/src/library/dao/playlistdao.h' |
169 | --- mixxx/src/library/dao/playlistdao.h 2011-10-21 00:42:23 +0000 |
170 | +++ mixxx/src/library/dao/playlistdao.h 2012-05-04 05:15:32 +0000 |
171 | @@ -52,6 +52,8 @@ |
172 | void removeTrackFromPlaylist(int playlistId, int position); |
173 | /** Insert a track into a specific position in a playlist */ |
174 | void insertTrackIntoPlaylist(int trackId, int playlistId, int position); |
175 | + /** Inserts a list of tracks into playlist*/ |
176 | + void insertTracksIntoPlaylist(QList <int> trackID, int playlistId, int position); |
177 | /** Add a playlist to the Auto-DJ Queue */ |
178 | void addToAutoDJQueue(int playlistId); |
179 | signals: |
180 | |
181 | === modified file 'mixxx/src/library/dao/trackdao.cpp' |
182 | --- mixxx/src/library/dao/trackdao.cpp 2012-04-24 22:07:26 +0000 |
183 | +++ mixxx/src/library/dao/trackdao.cpp 2012-05-04 05:15:32 +0000 |
184 | @@ -454,6 +454,27 @@ |
185 | return trackId; |
186 | } |
187 | |
188 | +QList <int> TrackDAO::addTracks(QList <QFileInfo> fileInfoList, bool unremove) { |
189 | + //returns the list with trackIDs of the added tracks |
190 | + QList <int> trackIDs; |
191 | + QList <TrackInfoObject *> pTrackList; |
192 | + QFileInfo fileInfo; |
193 | + //create the list of TrackInfoObjects from the fileInfoList |
194 | + foreach(fileInfo, fileInfoList) { |
195 | + TrackInfoObject * pTrack = new TrackInfoObject(fileInfo); |
196 | + pTrackList.append(pTrack); |
197 | + } |
198 | + //calling addTracks with the list of tracks to be added |
199 | + addTracks(pTrackList, unremove); |
200 | + TrackInfoObject * pTrack; |
201 | + foreach(pTrack, pTrackList){ |
202 | + int trackID = pTrack->getId(); |
203 | + trackIDs.append(trackID); |
204 | + delete pTrack; |
205 | + } |
206 | + return trackIDs; |
207 | +} |
208 | + |
209 | int TrackDAO::addTrack(QString absoluteFilePath, bool unremove) |
210 | { |
211 | QFileInfo fileInfo(absoluteFilePath); |
212 | |
213 | === modified file 'mixxx/src/library/dao/trackdao.h' |
214 | --- mixxx/src/library/dao/trackdao.h 2012-04-24 21:43:49 +0000 |
215 | +++ mixxx/src/library/dao/trackdao.h 2012-05-04 05:15:32 +0000 |
216 | @@ -74,6 +74,7 @@ |
217 | int addTrack(QString absoluteFilePath, bool unremove); |
218 | int addTrack(QFileInfo& fileInfo, bool unremove); |
219 | void addTracks(QList<TrackInfoObject*> tracksToAdd, bool unremove); |
220 | + QList <int> addTracks(QList <QFileInfo> fileInfoList, bool unremove); |
221 | void removeTrack(int id); |
222 | void removeTracks(QList<int> ids); |
223 | void unremoveTrack(int trackId); |
224 | |
225 | === modified file 'mixxx/src/library/librarytablemodel.cpp' |
226 | --- mixxx/src/library/librarytablemodel.cpp 2012-05-04 03:00:08 +0000 |
227 | +++ mixxx/src/library/librarytablemodel.cpp 2012-05-04 05:15:32 +0000 |
228 | @@ -64,6 +64,23 @@ |
229 | return false; |
230 | } |
231 | |
232 | +//Takes a list of locations and add the tracks to the library, returns the number of failed additions. |
233 | +int LibraryTableModel::addTracks(const QModelIndex& index, QList <QString> locations) { |
234 | + int trackAddFails = 0; |
235 | + //Prepare the list of QFileInfo's |
236 | + QList <QFileInfo> fileInfoList; |
237 | + QString fileLocation; |
238 | + foreach (fileLocation, locations) { |
239 | + QFileInfo fileInfo(fileLocation); |
240 | + fileInfoList.append(fileInfo); |
241 | + } |
242 | + QList <int> trackIDs; |
243 | + trackIDs = m_trackDao.addTracks(fileInfoList, true); //returns the ids of tracks in a QList |
244 | + //Assuming from the trackdao implementation that -1 is returned on an add fail |
245 | + trackAddFails = trackIDs.removeAll(-1); |
246 | + return trackAddFails; |
247 | +} |
248 | + |
249 | TrackPointer LibraryTableModel::getTrack(const QModelIndex& index) const { |
250 | int trackId = getTrackId(index); |
251 | return m_trackDao.getTrack(trackId); |
252 | |
253 | === modified file 'mixxx/src/library/librarytablemodel.h' |
254 | --- mixxx/src/library/librarytablemodel.h 2011-09-25 08:08:35 +0000 |
255 | +++ mixxx/src/library/librarytablemodel.h 2012-05-04 05:15:32 +0000 |
256 | @@ -24,6 +24,7 @@ |
257 | virtual void removeTrack(const QModelIndex& index); |
258 | virtual void removeTracks(const QModelIndexList& indices); |
259 | virtual bool addTrack(const QModelIndex& index, QString location); |
260 | + virtual int addTracks(const QModelIndex& index, QList <QString> locations); |
261 | virtual void moveTrack(const QModelIndex& sourceIndex, |
262 | const QModelIndex& destIndex); |
263 | |
264 | |
265 | === modified file 'mixxx/src/library/playlisttablemodel.cpp' |
266 | --- mixxx/src/library/playlisttablemodel.cpp 2012-05-04 03:00:08 +0000 |
267 | +++ mixxx/src/library/playlisttablemodel.cpp 2012-05-04 05:15:32 +0000 |
268 | @@ -94,6 +94,41 @@ |
269 | return true; |
270 | } |
271 | |
272 | +//Adding multiple tracks at once to a playlist, returns # of failed additions |
273 | +int PlaylistTableModel::addTracks(const QModelIndex& index, QList <QString> locations) { |
274 | + int trackAddFails = 0; |
275 | + const int positionColumn = fieldIndex(PLAYLISTTRACKSTABLE_POSITION); |
276 | + int position = index.sibling(index.row(), positionColumn).data().toInt(); |
277 | + |
278 | + //Handle weird cases like a drag and drop to an invalid index |
279 | + if (position <= 0) { |
280 | + position = rowCount() + 1; |
281 | + } |
282 | + |
283 | + //Prepare a list of QFileInfos |
284 | + QList <QFileInfo> fileInfoList; |
285 | + QString fileLocation; |
286 | + foreach (fileLocation, locations) { |
287 | + qDebug()<<"Location"<< fileLocation; |
288 | + QFileInfo fileInfo(fileLocation); |
289 | + fileInfoList.append(fileInfo); |
290 | + } |
291 | + |
292 | + //Use the addTracks of TrackDAO which returns a QList with trackIds |
293 | + QList <int> trackIDs; |
294 | + trackIDs = m_trackDao.addTracks(fileInfoList, true); |
295 | + |
296 | + //Assuming from the TrackDAO implementation of addTrack which returns -1 for add fails |
297 | + trackAddFails = trackIDs.removeAll(-1); |
298 | + //trackAddFails are # of tracks that couldn't be added to library |
299 | + |
300 | + //Unlike the way addTrack is implemented in CrateTableModel here it does not worry about failing to add track to playlist? |
301 | + m_playlistDao.insertTracksIntoPlaylist(trackIDs, m_iPlaylistId, position); |
302 | + select(); |
303 | + |
304 | + return trackAddFails; |
305 | +} |
306 | + |
307 | TrackPointer PlaylistTableModel::getTrack(const QModelIndex& index) const { |
308 | //FIXME: use position instead of location for playlist tracks? |
309 | |
310 | |
311 | === modified file 'mixxx/src/library/playlisttablemodel.h' |
312 | --- mixxx/src/library/playlisttablemodel.h 2011-11-30 05:27:44 +0000 |
313 | +++ mixxx/src/library/playlisttablemodel.h 2012-05-04 05:15:32 +0000 |
314 | @@ -30,6 +30,7 @@ |
315 | virtual void removeTrack(const QModelIndex& index); |
316 | virtual void removeTracks(const QModelIndexList& indices); |
317 | virtual bool addTrack(const QModelIndex& index, QString location); |
318 | + virtual int addTracks(const QModelIndex& index, QList <QString> locations); |
319 | virtual void moveTrack(const QModelIndex& sourceIndex, const QModelIndex& destIndex); |
320 | virtual void shuffleTracks(const QModelIndex& currentIndex); |
321 | |
322 | |
323 | === modified file 'mixxx/src/library/trackmodel.h' |
324 | --- mixxx/src/library/trackmodel.h 2012-05-04 03:00:08 +0000 |
325 | +++ mixxx/src/library/trackmodel.h 2012-05-04 05:15:32 +0000 |
326 | @@ -74,6 +74,11 @@ |
327 | Q_UNUSED(location); |
328 | return false; |
329 | } |
330 | + virtual int addTracks(const QModelIndex& index, QList <QString> locations) { |
331 | + Q_UNUSED(index); |
332 | + Q_UNUSED(locations); |
333 | + return -1; |
334 | + } |
335 | virtual void moveTrack(const QModelIndex& sourceIndex, |
336 | const QModelIndex& destIndex) { |
337 | Q_UNUSED(sourceIndex); |
338 | |
339 | === modified file 'mixxx/src/widget/wtracktableview.cpp' |
340 | --- mixxx/src/widget/wtracktableview.cpp 2012-05-04 03:00:08 +0000 |
341 | +++ mixxx/src/widget/wtracktableview.cpp 2012-05-04 05:15:32 +0000 |
342 | @@ -708,7 +708,7 @@ |
343 | |
344 | } |
345 | } |
346 | - else |
347 | + else//Drag and drop inside Mixxx is only for few rows, bulks happen here |
348 | { |
349 | //Reset the selected tracks (if you had any tracks highlighted, it |
350 | //clears them) |
351 | @@ -741,13 +741,25 @@ |
352 | } |
353 | |
354 | //Add all the dropped URLs/tracks to the track model (playlist/crate) |
355 | - foreach (url, urls) |
356 | - { |
357 | - QFileInfo file(url.toLocalFile()); |
358 | - if (!trackModel->addTrack(destIndex, file.absoluteFilePath())) |
359 | - numNewRows--; //# of rows to select must be decremented if we skipped some tracks |
360 | - } |
361 | - |
362 | + if(urls.size() > 1) {//if many items are being dropped |
363 | + //prepare the list of QFileInfos |
364 | + QList <QString> fileLocationList; |
365 | + foreach(url, urls) { |
366 | + QString file(url.toLocalFile()); |
367 | + fileLocationList.append(file); |
368 | + } |
369 | + //calling the addTracks returns number of failed additions |
370 | + int failedAdds = trackModel->addTracks(destIndex, fileLocationList); |
371 | + //Decrement # of rows to select if some were skipped |
372 | + numNewRows = numNewRows - failedAdds; |
373 | + } |
374 | + else { |
375 | + QFileInfo file(url.toLocalFile()); |
376 | + if(!trackModel->addTrack(destIndex, file.absoluteFilePath())) { |
377 | + numNewRows--; |
378 | + } |
379 | + |
380 | + } |
381 | //Create the selection, but only if the track model supports reordering. |
382 | //(eg. crates don't support reordering/indexes) |
383 | if (modelHasCapabilities(TrackModel::TRACKMODELCAPS_REORDER)) { |
384 | @@ -767,6 +779,7 @@ |
385 | } else { |
386 | event->ignore(); |
387 | } |
388 | + qDebug()<<"Track drop of wtracktavleview occured"; |
389 | } |
390 | |
391 | TrackModel* WTrackTableView::getTrackModel() { |
I've massaged your branch a little bit to fix some style issues (4-spaces instead of tabs, variable naming, etc.) but it looks good to me otherwise. Thanks Akash!