Merge lp:~shetyeakash/mixxx/bulk_operations into lp:mixxx/1.10

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
Reviewer Review Type Date Requested Status
RJ Skerry-Ryan Approve
Review via email: mp+104669@code.launchpad.net

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.
Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

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!

review: Approve

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() {

Subscribers

People subscribed via source and target branches