Merge lp:~mixxxdevelopers/mixxx/library_features into lp:~mixxxdevelopers/mixxx/trunk

Proposed by RJ Skerry-Ryan
Status: Needs review
Proposed branch: lp:~mixxxdevelopers/mixxx/library_features
Merge into: lp:~mixxxdevelopers/mixxx/trunk
Diff against target: 5250 lines (+1538/-949)
77 files modified
mixxx/build/depends.py (+1/-0)
mixxx/res/schema.xml (+14/-0)
mixxx/src/dlgautodj.cpp (+5/-2)
mixxx/src/dlgautodj.h (+1/-0)
mixxx/src/dlgpreferences.cpp (+5/-0)
mixxx/src/dlgpreferences.h (+2/-0)
mixxx/src/dlgprefplaylist.cpp (+87/-9)
mixxx/src/dlgprefplaylist.h (+9/-0)
mixxx/src/dlgprefplaylistdlg.ui (+40/-26)
mixxx/src/dlgprefrecord.cpp (+1/-4)
mixxx/src/library/autodjfeature.cpp (+2/-0)
mixxx/src/library/autodjfeature.h (+3/-0)
mixxx/src/library/baseexternalplaylistmodel.cpp (+3/-3)
mixxx/src/library/baseexternalplaylistmodel.h (+3/-1)
mixxx/src/library/baseexternaltrackmodel.cpp (+3/-3)
mixxx/src/library/baseexternaltrackmodel.h (+3/-1)
mixxx/src/library/baseplaylistfeature.cpp (+5/-4)
mixxx/src/library/baseplaylistfeature.h (+0/-1)
mixxx/src/library/basesqltablemodel.cpp (+79/-9)
mixxx/src/library/basesqltablemodel.h (+60/-48)
mixxx/src/library/basetrackcache.cpp (+2/-0)
mixxx/src/library/browse/browsefeature.cpp (+23/-2)
mixxx/src/library/browse/browsefeature.h (+3/-0)
mixxx/src/library/browse/browsetablemodel.cpp (+2/-1)
mixxx/src/library/browse/browsetablemodel.h (+1/-1)
mixxx/src/library/browse/browsethread.h (+7/-9)
mixxx/src/library/browse/foldertreemodel.cpp (+1/-0)
mixxx/src/library/cratefeature.cpp (+10/-7)
mixxx/src/library/cratefeature.h (+3/-0)
mixxx/src/library/cratetablemodel.cpp (+46/-62)
mixxx/src/library/cratetablemodel.h (+7/-20)
mixxx/src/library/dao/directorydao.cpp (+143/-0)
mixxx/src/library/dao/directorydao.h (+31/-0)
mixxx/src/library/dao/trackdao.cpp (+307/-76)
mixxx/src/library/dao/trackdao.h (+17/-7)
mixxx/src/library/hiddentablemodel.cpp (+42/-50)
mixxx/src/library/hiddentablemodel.h (+2/-15)
mixxx/src/library/itunes/itunesfeature.cpp (+24/-22)
mixxx/src/library/itunes/itunesfeature.h (+5/-1)
mixxx/src/library/library.cpp (+79/-19)
mixxx/src/library/library.h (+16/-1)
mixxx/src/library/libraryfeature.h (+4/-3)
mixxx/src/library/libraryscanner.cpp (+40/-26)
mixxx/src/library/libraryscanner.h (+6/-3)
mixxx/src/library/librarytablemodel.cpp (+44/-66)
mixxx/src/library/librarytablemodel.h (+2/-21)
mixxx/src/library/missingtablemodel.cpp (+0/-125)
mixxx/src/library/missingtablemodel.h (+0/-41)
mixxx/src/library/mixxxlibraryfeature.cpp (+4/-4)
mixxx/src/library/mixxxlibraryfeature.h (+5/-1)
mixxx/src/library/playlistfeature.cpp (+6/-5)
mixxx/src/library/playlistfeature.h (+5/-1)
mixxx/src/library/playlisttablemodel.cpp (+56/-96)
mixxx/src/library/playlisttablemodel.h (+14/-30)
mixxx/src/library/preparelibrarytablemodel.cpp (+2/-13)
mixxx/src/library/preparelibrarytablemodel.h (+2/-7)
mixxx/src/library/promotracksfeature.cpp (+1/-1)
mixxx/src/library/proxytrackmodel.cpp (+16/-11)
mixxx/src/library/proxytrackmodel.h (+3/-4)
mixxx/src/library/rhythmbox/rhythmboxfeature.cpp (+6/-4)
mixxx/src/library/rhythmbox/rhythmboxfeature.h (+4/-1)
mixxx/src/library/setlogfeature.cpp (+6/-5)
mixxx/src/library/stardelegate.cpp (+11/-3)
mixxx/src/library/stardelegate.h (+2/-0)
mixxx/src/library/trackcollection.cpp (+28/-14)
mixxx/src/library/trackcollection.h (+12/-1)
mixxx/src/library/trackmodel.h (+18/-12)
mixxx/src/library/traktor/traktorfeature.cpp (+14/-10)
mixxx/src/library/traktor/traktorfeature.h (+8/-3)
mixxx/src/library/treeitem.cpp (+6/-0)
mixxx/src/mixxx.cpp (+56/-27)
mixxx/src/mixxx.h (+2/-1)
mixxx/src/playermanager.cpp (+8/-0)
mixxx/src/soundsourceproxy.h (+1/-1)
mixxx/src/waveform/waveform.h (+1/-1)
mixxx/src/widget/wtracktableview.cpp (+44/-4)
mixxx/src/widget/wtracktableview.h (+4/-0)
To merge this branch: bzr merge lp:~mixxxdevelopers/mixxx/library_features
Reviewer Review Type Date Requested Status
Mixxx Development Team Pending
Review via email: mp+162700@code.launchpad.net

Description of the change

Getting the ball rolling on the code review for Max's library_features work.

To post a comment you must log in.
Revision history for this message
RJ Skerry-Ryan (rryan) wrote :
Download full text (3.2 KiB)

Hey Max -- I know you aren't ready to merge this yet but I gave it a quick skim while getting chromaprint on the build server and thought I'd shoot you some comments:

* DlgPrefPlaylist
  - SQL queries should not be done here -- need to be abstracted away by a DAO.
  - Shouldn't rely on the default DB connection existing -- TrackCollection needs to get passed into DlgPreferences. (We could change the creation order in the future and this code would break -- better to have it enforced by code)

* BaseSqlTableModel::relocateTracks
  - It would be cool if you could handle the use case where you select a whole album and hit relocate. Either maybe auto-magically detecting that the rest of the selected missing files are in the same directory as the first missing one relocated or maybe by letting the user pick a directory if it is clear that all the selected files were in the same directory originally. This would be a handy speedup.

* DirectoryDAO::addDirectory -- I don't see multiple queries so I don't think it needs a transaction.

* DirectoryDAO::relocateDirectory -- the string arguments in these queries are untrusted and need escaping. Use QSqlQuery::bindValue see TrackDAO::updateTrack for an example.

* DirectoryDAO::getDirIds, DirectoryDAO::getDirId -- same comment RE: escaping.

* DirectoryDAO::updateTrackLocations -- same comments re: escaping. Also this sets every track_locations entry to have the directory. Based on the calls to this function I'm not sure that was the intended functionality. What's this function supposed to do?

* TrackDAO::deleteTracksFromFS -- QMessageBox / GUI code shouldn't be in the DAO's (especially if all this code goes to its own thread eventually). Instead, have the caller pass in a list of stuff that you append un-removeable file paths to or something similar.

* TrackDAO -- some of your queries are using strings that need escaping .. you can only use string construction of the query for when you know the values are safe (i.e. a list of numeric IDs that you join together with commas.) or when you are using table names, column names, and other constants. Strings coming from user input (names, directories, paths, etc.) all need escaping.

* I'm scared of adding delete-on-filesystem code to Mixxx. Is it worth it to let the user do that? The cost of failure is huge in loss of user trust.

And now, about checksumming:

Checksumming every file when we add it to the library has to come with a huge performance hit to the library scanner. Have you noticed this? Albert and I considered checksums when we first wrote the SQLite library but didn't go with it because of this issue. I thought it would be a good compromise to do the checksums in the analyser queue (because it would be much less noticed there) and then only use the checksum for re-unification if it is present.

And now some comments about the checksum implementation itself:

* We should store version information about the checksum with it in a checksum_version column or with a unique string prefix to put on the front (I prefer a separate column since separators never end up being as unique as you thought they were).

* RE: md5 -- we probably don't need a c...

Read more...

3264. By Max Linke <kain88@640X4.kel.wh.lokal>

fix cratetablemodel.cpp, library is not shown there is something off

3265. By Max Linke <kain88@640X4.kel.wh.lokal>

disabled previewDeck to make everything work for now

3266. By Max Linke <kain88@640X4.kel.wh.lokal>

reenabled preview deck, fixed temporary view that is created by the tablemodels

3267. By Max Linke <kain88@640X4.kel.wh.lokal>

changed name for chromaprint library in scons

3268. By Max Linke <kain88@640X4.kel.wh.lokal>

added missing files

3269. By Max Linke <kain88@640X4.kel.wh.lokal>

I'm stupid -.-

3270. By Max Linke <kain88@640X4.kel.wh.lokal>

next try for the build server

3271. By RJ Skerry-Ryan

Check for chromaprint_p.

3272. By RJ Skerry-Ryan

Check for chromaprint_p.

3273. By RJ Skerry-Ryan

Try detecting chromaprint after chromaprint_p?

3274. By RJ Skerry-Ryan

Roll-back r3273.

3275. By RJ Skerry-Ryan

Add chromaprint to LIBS manually after CheckLib passes.

3276. By RJ Skerry-Ryan

Add CHROMAPRINT_NODLL to CPPDEFINES.

3277. By RJ Skerry-Ryan

Typo.

3278. By RJ Skerry-Ryan

Only define CHROMAPRINT_NODLL for static_dependencies.

3279. By RJ Skerry-Ryan

Link fftw3 on Windows only.

3280. By Max Linke <kain88@640X4.kel.wh.lokal>

merge with trunk, library scanner does not add songs

3281. By Max Linke <kain88@640X4.kel.wh.lokal>

does launchpad use my email now?

3282. By Max Linke <kain88@640X4.kel.wh.lokal>

next try

3283. By Max Linke <email address hidden>

next try 2

3284. By Max Linke <email address hidden>

removed fringerprinting feature that is moved into chromaprint branch

3285. By Max Linke <email address hidden>

merge with trunk

3286. By Max Linke <email address hidden>

merge with trunk

3287. By Max Linke <email address hidden>

merge with trunk

3288. By Max Linke <email address hidden>

merge with trunk

Unmerged revisions

3288. By Max Linke <email address hidden>

merge with trunk

3287. By Max Linke <email address hidden>

merge with trunk

3286. By Max Linke <email address hidden>

merge with trunk

3285. By Max Linke <email address hidden>

merge with trunk

3284. By Max Linke <email address hidden>

removed fringerprinting feature that is moved into chromaprint branch

3283. By Max Linke <email address hidden>

next try 2

3282. By Max Linke <kain88@640X4.kel.wh.lokal>

next try

3281. By Max Linke <kain88@640X4.kel.wh.lokal>

does launchpad use my email now?

3280. By Max Linke <kain88@640X4.kel.wh.lokal>

merge with trunk, library scanner does not add songs

3279. By RJ Skerry-Ryan

Link fftw3 on Windows only.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'mixxx/build/depends.py'
--- mixxx/build/depends.py 2013-05-16 01:40:06 +0000
+++ mixxx/build/depends.py 2013-05-18 16:32:26 +0000
@@ -569,6 +569,7 @@
569 "library/libraryfeature.cpp",569 "library/libraryfeature.cpp",
570 "library/preparefeature.cpp",570 "library/preparefeature.cpp",
571 "library/autodjfeature.cpp",571 "library/autodjfeature.cpp",
572 "library/dao/directorydao.cpp",
572 "library/mixxxlibraryfeature.cpp",573 "library/mixxxlibraryfeature.cpp",
573 "library/baseplaylistfeature.cpp",574 "library/baseplaylistfeature.cpp",
574 "library/playlistfeature.cpp",575 "library/playlistfeature.cpp",
575576
=== modified file 'mixxx/res/schema.xml'
--- mixxx/res/schema.xml 2013-05-07 03:17:23 +0000
+++ mixxx/res/schema.xml 2013-05-18 16:32:26 +0000
@@ -338,4 +338,18 @@
338 ALTER TABLE Library ADD COLUMN keys_sub_version TEXT;338 ALTER TABLE Library ADD COLUMN keys_sub_version TEXT;
339 </sql>339 </sql>
340 </revision>340 </revision>
341 <revision version="19" min_compatible="3">
342 <description>
343 Add directories table
344 </description>
345 <sql>
346 CREATE TABLE IF NOT EXISTS directories (
347 dir_id INTEGER primary key AUTOINCREMENT,
348 directory varchar(1024)
349 );
350 CREATE UNIQUE INDEX directory_idx ON directories(directory);
351 ALTER TABLE track_locations ADD COLUMN maindir_id INTEGER DEFAULT 0;
352 ALTER TABLE track_locations ADD COLUMN checksum varchar(1024);
353 </sql>
354 </revision>
341</schema>355</schema>
342356
=== modified file 'mixxx/src/dlgautodj.cpp'
--- mixxx/src/dlgautodj.cpp 2013-05-18 16:23:08 +0000
+++ mixxx/src/dlgautodj.cpp 2013-05-18 16:32:26 +0000
@@ -43,14 +43,17 @@
43 box->insertWidget(1, m_pTrackTableView);43 box->insertWidget(1, m_pTrackTableView);
4444
45 m_pAutoDJTableModel = new PlaylistTableModel(this, pTrackCollection,45 m_pAutoDJTableModel = new PlaylistTableModel(this, pTrackCollection,
46 "mixxx.db.model.autodj");46 "mixxx.db.model.autodj",
47 m_pConfig);
48 connect(this, SIGNAL(configChanged(QString,QString)),
49 m_pAutoDJTableModel, SLOT(slotConfigChanged(QString,QString)));
47 PlaylistDAO& playlistDao = pTrackCollection->getPlaylistDAO();50 PlaylistDAO& playlistDao = pTrackCollection->getPlaylistDAO();
48 int playlistId = playlistDao.getPlaylistIdFromName(AUTODJ_TABLE);51 int playlistId = playlistDao.getPlaylistIdFromName(AUTODJ_TABLE);
49 if (playlistId < 0) {52 if (playlistId < 0) {
50 playlistId = playlistDao.createPlaylist(AUTODJ_TABLE,53 playlistId = playlistDao.createPlaylist(AUTODJ_TABLE,
51 PlaylistDAO::PLHT_AUTO_DJ);54 PlaylistDAO::PLHT_AUTO_DJ);
52 }55 }
53 m_pAutoDJTableModel->setPlaylist(playlistId);56 m_pAutoDJTableModel->setTableModel(playlistId);
54 m_pTrackTableView->loadTrackModel(m_pAutoDJTableModel);57 m_pTrackTableView->loadTrackModel(m_pAutoDJTableModel);
5558
56 // Override some playlist-view properties:59 // Override some playlist-view properties:
5760
=== modified file 'mixxx/src/dlgautodj.h'
--- mixxx/src/dlgautodj.h 2013-04-12 15:27:07 +0000
+++ mixxx/src/dlgautodj.h 2013-05-18 16:32:26 +0000
@@ -47,6 +47,7 @@
4747
48 signals:48 signals:
49 void loadTrack(TrackPointer tio);49 void loadTrack(TrackPointer tio);
50 void configChanged(QString,QString);
50 void loadTrackToPlayer(TrackPointer tio, QString group, bool);51 void loadTrackToPlayer(TrackPointer tio, QString group, bool);
5152
52 private:53 private:
5354
=== modified file 'mixxx/src/dlgpreferences.cpp'
--- mixxx/src/dlgpreferences.cpp 2013-05-12 10:15:29 +0000
+++ mixxx/src/dlgpreferences.cpp 2013-05-18 16:32:26 +0000
@@ -80,6 +80,11 @@
80 addPageWidget(m_wsound);80 addPageWidget(m_wsound);
81 m_wplaylist = new DlgPrefPlaylist(this, config);81 m_wplaylist = new DlgPrefPlaylist(this, config);
82 addPageWidget(m_wplaylist);82 addPageWidget(m_wplaylist);
83 connect(m_wplaylist, SIGNAL(configChanged(QString,QString)),
84 this, SIGNAL(configChanged(QString,QString)));
85 connect(m_wplaylist, SIGNAL(dirsChanged(QString,QString)),
86 this, SIGNAL(dirsChanged(QString,QString)));
87
83 m_wcontrols = new DlgPrefControls(this, mixxx, pSkinLoader, pPlayerManager, config);88 m_wcontrols = new DlgPrefControls(this, mixxx, pSkinLoader, pPlayerManager, config);
84 addPageWidget(m_wcontrols);89 addPageWidget(m_wcontrols);
85 m_weq = new DlgPrefEQ(this, config);90 m_weq = new DlgPrefEQ(this, config);
8691
=== modified file 'mixxx/src/dlgpreferences.h'
--- mixxx/src/dlgpreferences.h 2013-05-12 10:15:29 +0000
+++ mixxx/src/dlgpreferences.h 2013-05-18 16:32:26 +0000
@@ -74,6 +74,8 @@
74signals:74signals:
75 void closeDlg();75 void closeDlg();
76 void showDlg();76 void showDlg();
77 void configChanged(QString, QString);
78 void dirsChanged(QString, QString);
77protected:79protected:
78 bool eventFilter(QObject*, QEvent*);80 bool eventFilter(QObject*, QEvent*);
79private:81private:
8082
=== modified file 'mixxx/src/dlgprefplaylist.cpp'
--- mixxx/src/dlgprefplaylist.cpp 2013-05-18 16:23:08 +0000
+++ mixxx/src/dlgprefplaylist.cpp 2013-05-18 16:32:26 +0000
@@ -15,6 +15,9 @@
15* *15* *
16***************************************************************************/16***************************************************************************/
1717
18#include <QSqlDatabase>
19#include <QSqlQuery>
20#include <QSqlRecord>
18#include <QUrl>21#include <QUrl>
19#include <QDesktopServices>22#include <QDesktopServices>
20#include <QFileDialog>23#include <QFileDialog>
@@ -30,6 +33,8 @@
3033
31DlgPrefPlaylist::DlgPrefPlaylist(QWidget * parent, ConfigObject<ConfigValue> * config)34DlgPrefPlaylist::DlgPrefPlaylist(QWidget * parent, ConfigObject<ConfigValue> * config)
32 : QWidget(parent), 35 : QWidget(parent),
36 m_model(),
37 m_dirsModified(false),
33 m_pconfig(config) {38 m_pconfig(config) {
34 setupUi(this);39 setupUi(this);
35 slotUpdate();40 slotUpdate();
@@ -51,6 +56,10 @@
5156
52 connect(PushButtonBrowsePlaylist, SIGNAL(clicked()),57 connect(PushButtonBrowsePlaylist, SIGNAL(clicked()),
53 this, SLOT(slotBrowseDir()));58 this, SLOT(slotBrowseDir()));
59 connect(PushButtonRemovePlaylist, SIGNAL(clicked()),
60 this, SLOT(slotRemoveDir()));
61 connect(pushButton_2, SIGNAL(clicked()),
62 this, SLOT(slotRelocateDir()));
54 //connect(pushButtonM4A, SIGNAL(clicked()), this, SLOT(slotM4ACheck()));63 //connect(pushButtonM4A, SIGNAL(clicked()), this, SLOT(slotM4ACheck()));
55 connect(pushButtonExtraPlugins, SIGNAL(clicked()),64 connect(pushButtonExtraPlugins, SIGNAL(clicked()),
56 this, SLOT(slotExtraPlugins()));65 this, SLOT(slotExtraPlugins()));
@@ -74,6 +83,40 @@
74DlgPrefPlaylist::~DlgPrefPlaylist() {83DlgPrefPlaylist::~DlgPrefPlaylist() {
75}84}
7685
86bool DlgPrefPlaylist::initializeModel(){
87 // this will hook into the default connection, so we don't need to
88 // provide anymore information. This works because the Library is
89 // created before the Preferences and a connection already exists.
90 // --kain88 July 2012
91 QSqlDatabase database = QSqlDatabase::database();
92 QSqlQuery query;
93 query.prepare("SELECT directory from directories");
94 if (!query.exec()) {
95 qDebug() << "damn there are no directories to display";
96 return false;
97 }
98 // save which index was selected
99 const int selected = list->currentIndex().row();
100 m_model.clear();
101 while(query.next()){
102 QStandardItem* pitem = new QStandardItem(
103 query.value(query.record().indexOf("directory"))
104 .toString());
105 m_model.appendRow(pitem);
106 }
107 list->setModel(&m_model);
108 // first select the first index then change it to selected if it still exists
109 list->setCurrentIndex(list->model()->index(0, 0));
110 for (int i=0 ; i<list->model()->rowCount() ; ++i) {
111 const QModelIndex index = list->model()->index(i, 0);
112 if (index.row() == selected) {
113 list->setCurrentIndex(index);
114 break;
115 }
116 }
117 return true;
118}
119
77void DlgPrefPlaylist::slotExtraPlugins() {120void DlgPrefPlaylist::slotExtraPlugins() {
78 QDesktopServices::openUrl(QUrl(MIXXX_ADDONS_URL));121 QDesktopServices::openUrl(QUrl(MIXXX_ADDONS_URL));
79}122}
@@ -141,9 +184,8 @@
141}*/184}*/
142185
143void DlgPrefPlaylist::slotUpdate() {186void DlgPrefPlaylist::slotUpdate() {
144 // Library Path187 // Song path
145 LineEditSongfiles->setText(m_pconfig->getValueString(188 initializeModel();
146 ConfigKey("[Playlist]","Directory")));
147 //Bundled songs stat tracking189 //Bundled songs stat tracking
148 checkBoxPromoStats->setChecked((bool)m_pconfig->getValueString(190 checkBoxPromoStats->setChecked((bool)m_pconfig->getValueString(
149 ConfigKey("[Promo]","StatTracking")).toInt());191 ConfigKey("[Promo]","StatTracking")).toInt());
@@ -159,14 +201,41 @@
159 ConfigKey("[Library]","ShowITunesLibrary"),"1").toInt());201 ConfigKey("[Library]","ShowITunesLibrary"),"1").toInt());
160 checkBox_show_traktor->setChecked((bool)m_pconfig->getValueString(202 checkBox_show_traktor->setChecked((bool)m_pconfig->getValueString(
161 ConfigKey("[Library]","ShowTraktorLibrary"),"1").toInt());203 ConfigKey("[Library]","ShowTraktorLibrary"),"1").toInt());
204 checkBox_show_missing->setChecked((bool)m_pconfig->getValueString(
205 ConfigKey("[Library]","ShowMissingSongs"),"1").toInt());
162}206}
163207
164void DlgPrefPlaylist::slotBrowseDir() {208void DlgPrefPlaylist::slotBrowseDir() {
165 QString fd = QFileDialog::getExistingDirectory(this,209 QString fd = QFileDialog::getExistingDirectory(this,
166 tr("Choose music library directory"),210 tr("Choose music library directory"),
167 m_pconfig->getValueString(ConfigKey("[Playlist]","Directory")));211 QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
168 if (fd != "") {212 if (fd != "") {
169 LineEditSongfiles->setText(fd);213 emit(dirsChanged("added",fd));
214 slotUpdate();
215 m_dirsModified = true;
216 }
217}
218
219void DlgPrefPlaylist::slotRemoveDir() {
220 QModelIndex index = list->currentIndex();
221 QString fd = index.data().toString();
222 emit(dirsChanged("removed",fd));
223 slotUpdate();
224 m_dirsModified = true;
225}
226
227void DlgPrefPlaylist::slotRelocateDir() {
228 QModelIndex index = list->currentIndex();
229 QString currentFd = index.data().toString();
230 QString fd = QFileDialog::getExistingDirectory(this,
231 tr("Choose music library directory"),
232 QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
233
234 //use !(~)! as a sign where the string has to be seperated later
235 if(!fd.isEmpty()){
236 emit(dirsChanged("relocate",fd+"!(~)!"+currentFd));
237 slotUpdate();
238 m_dirsModified = true;
170 }239 }
171}240}
172241
@@ -186,10 +255,19 @@
186 m_pconfig->set(ConfigKey("[Library]","ShowTraktorLibrary"),255 m_pconfig->set(ConfigKey("[Library]","ShowTraktorLibrary"),
187 ConfigValue((int)checkBox_show_traktor->isChecked()));256 ConfigValue((int)checkBox_show_traktor->isChecked()));
188257
189 if (LineEditSongfiles->text() !=258 // Update playlist if path has changed
190 m_pconfig->getValueString(ConfigKey("[Playlist]","Directory"))) {259 if (m_dirsModified) {
191 m_pconfig->set(ConfigKey("[Playlist]","Directory"), LineEditSongfiles->text());
192 emit(apply());260 emit(apply());
193 }261 }
262
263 //update TM if ShowMissingSongs has changed
264 if ((int)checkBox_show_missing->isChecked() != m_pconfig->getValueString(
265 ConfigKey("[Library]",
266 "ShowMissingSongs"),"1").toInt()) {
267 m_pconfig->set(ConfigKey("[Library]","ShowMissingSongs"),
268 ConfigValue((int)checkBox_show_missing->isChecked()));
269
270 emit(configChanged("[Library]","ShowMissingSongs"));
271 }
194 m_pconfig->Save();272 m_pconfig->Save();
195}273}
196274
=== modified file 'mixxx/src/dlgprefplaylist.h'
--- mixxx/src/dlgprefplaylist.h 2013-05-18 16:23:08 +0000
+++ mixxx/src/dlgprefplaylist.h 2013-05-18 16:32:26 +0000
@@ -18,6 +18,8 @@
18#ifndef DLGPREFPLAYLIST_H18#ifndef DLGPREFPLAYLIST_H
19#define DLGPREFPLAYLIST_H19#define DLGPREFPLAYLIST_H
2020
21#include <QStandardItemModel>
22
21#include "ui_dlgprefplaylistdlg.h"23#include "ui_dlgprefplaylistdlg.h"
22#include "configobject.h"24#include "configobject.h"
2325
@@ -37,6 +39,8 @@
37 void slotUpdate();39 void slotUpdate();
38 // Dialog to browse for music file directory 40 // Dialog to browse for music file directory
39 void slotBrowseDir();41 void slotBrowseDir();
42 void slotRemoveDir();
43 void slotRelocateDir();
40 // Apply changes to widget 44 // Apply changes to widget
41 void slotApply();45 void slotApply();
42 // Starts up the PluginDownloader if the plugin isn't present46 // Starts up the PluginDownloader if the plugin isn't present
@@ -53,8 +57,13 @@
5357
54 signals:58 signals:
55 void apply();59 void apply();
60 void configChanged(QString, QString);
61 void dirsChanged(QString, QString);
5662
57 private:63 private:
64 bool initializeModel();
65 QStandardItemModel m_model;
66 bool m_dirsModified;
58 ConfigObject<ConfigValue> *m_pconfig;67 ConfigObject<ConfigValue> *m_pconfig;
59 // SoundSource Plugin Downloader68 // SoundSource Plugin Downloader
60 //PluginDownloader* m_pPluginDownloader;69 //PluginDownloader* m_pPluginDownloader;
6170
=== modified file 'mixxx/src/dlgprefplaylistdlg.ui'
--- mixxx/src/dlgprefplaylistdlg.ui 2012-12-09 17:41:04 +0000
+++ mixxx/src/dlgprefplaylistdlg.ui 2013-05-18 16:32:26 +0000
@@ -41,30 +41,47 @@
41 <bool>false</bool>41 <bool>false</bool>
42 </property>42 </property>
43 <property name="buddy">43 <property name="buddy">
44 <cstring>LineEditSongfiles</cstring>44 <cstring>list</cstring>
45 </property>45 </property>
46 </widget>46 </widget>
47 </item>47 </item>
48 <item row="0" column="1">48 <item row="3" column="1">
49 <widget class="QLineEdit" name="LineEditSongfiles">49 <widget class="QPushButton" name="PushButtonRemovePlaylist">
50 <property name="minimumSize">50 <property name="font">
51 <font/>
52 </property>
53 <property name="text">
54 <string>Remove</string>
55 </property>
56 </widget>
57 </item>
58 <item row="1" column="0" rowspan="3">
59 <widget class="QListView" name="list">
60 <property name="iconSize">
51 <size>61 <size>
52 <width>100</width>62 <width>16</width>
53 <height>10</height>63 <height>16</height>
54 </size>64 </size>
55 </property>65 </property>
56 <property name="font">66 <property name="uniformItemSizes">
57 <font/>67 <bool>true</bool>
58 </property>68 </property>
59 </widget>69 </widget>
60 </item>70 </item>
61 <item row="0" column="2">71 <item row="1" column="1">
62 <widget class="QPushButton" name="PushButtonBrowsePlaylist">72 <widget class="QPushButton" name="PushButtonBrowsePlaylist">
63 <property name="font">73 <property name="font">
64 <font/>74 <font/>
65 </property>75 </property>
66 <property name="text">76 <property name="text">
67 <string>Browse...</string>77 <string>Add</string>
78 </property>
79 </widget>
80 </item>
81 <item row="2" column="1">
82 <widget class="QPushButton" name="pushButton_2">
83 <property name="text">
84 <string>Relocate</string>
68 </property>85 </property>
69 </widget>86 </widget>
70 </item>87 </item>
@@ -181,6 +198,16 @@
181 </property>198 </property>
182 </widget>199 </widget>
183 </item>200 </item>
201 <item row="4" column="0">
202 <widget class="QCheckBox" name="checkBox_show_missing">
203 <property name="text">
204 <string>Show Missing Songs</string>
205 </property>
206 <property name="checked">
207 <bool>true</bool>
208 </property>
209 </widget>
210 </item>
184 </layout>211 </layout>
185 </widget>212 </widget>
186 </item>213 </item>
@@ -230,19 +257,6 @@
230 </layout>257 </layout>
231 </widget>258 </widget>
232 </item>259 </item>
233 <item>
234 <spacer name="verticalSpacer">
235 <property name="orientation">
236 <enum>Qt::Vertical</enum>
237 </property>
238 <property name="sizeHint" stdset="0">
239 <size>
240 <width>20</width>
241 <height>40</height>
242 </size>
243 </property>
244 </spacer>
245 </item>
246 </layout>260 </layout>
247 </widget>261 </widget>
248 <layoutdefault spacing="6" margin="11"/>262 <layoutdefault spacing="6" margin="11"/>
249263
=== modified file 'mixxx/src/dlgprefrecord.cpp'
--- mixxx/src/dlgprefrecord.cpp 2013-05-15 06:09:40 +0000
+++ mixxx/src/dlgprefrecord.cpp 2013-05-18 16:32:26 +0000
@@ -47,10 +47,7 @@
47 if (recordingsPath == "") {47 if (recordingsPath == "") {
48 // Initialize recordings path in config to old default path.48 // Initialize recordings path in config to old default path.
49 // Do it here so we show current value in UI correctly.49 // Do it here so we show current value in UI correctly.
50 QString musicDir = config->getValueString(ConfigKey("[Playlist]","Directory"));50 QString musicDir = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);
51 if (musicDir.isEmpty()) {
52 musicDir = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);
53 }
54 QDir recordDir(musicDir + "/Mixxx/Recordings");51 QDir recordDir(musicDir + "/Mixxx/Recordings");
55 recordingsPath = recordDir.absolutePath();52 recordingsPath = recordDir.absolutePath();
56 }53 }
5754
=== modified file 'mixxx/src/library/autodjfeature.cpp'
--- mixxx/src/library/autodjfeature.cpp 2013-05-12 22:17:32 +0000
+++ mixxx/src/library/autodjfeature.cpp 2013-05-18 16:32:26 +0000
@@ -45,6 +45,8 @@
45 libraryWidget->registerView(m_sAutoDJViewName, m_pAutoDJView);45 libraryWidget->registerView(m_sAutoDJViewName, m_pAutoDJView);
46 connect(m_pAutoDJView, SIGNAL(loadTrack(TrackPointer)),46 connect(m_pAutoDJView, SIGNAL(loadTrack(TrackPointer)),
47 this, SIGNAL(loadTrack(TrackPointer)));47 this, SIGNAL(loadTrack(TrackPointer)));
48 connect(this, SIGNAL(configChanged(QString,QString)),
49 m_pAutoDJView, SIGNAL(configChanged(QString,QString)));
48 connect(m_pAutoDJView, SIGNAL(loadTrackToPlayer(TrackPointer, QString, bool)),50 connect(m_pAutoDJView, SIGNAL(loadTrackToPlayer(TrackPointer, QString, bool)),
49 this, SIGNAL(loadTrackToPlayer(TrackPointer, QString, bool)));51 this, SIGNAL(loadTrackToPlayer(TrackPointer, QString, bool)));
50}52}
5153
=== modified file 'mixxx/src/library/autodjfeature.h'
--- mixxx/src/library/autodjfeature.h 2012-12-12 17:23:33 +0000
+++ mixxx/src/library/autodjfeature.h 2013-05-18 16:32:26 +0000
@@ -35,6 +35,9 @@
3535
36 TreeItemModel* getChildModel();36 TreeItemModel* getChildModel();
3737
38 signals:
39 void configChanged(QString,QString);
40
38 public slots:41 public slots:
39 void activate();42 void activate();
4043
4144
=== modified file 'mixxx/src/library/baseexternalplaylistmodel.cpp'
--- mixxx/src/library/baseexternalplaylistmodel.cpp 2012-11-25 11:17:13 +0000
+++ mixxx/src/library/baseexternalplaylistmodel.cpp 2013-05-18 16:32:26 +0000
@@ -6,10 +6,10 @@
6BaseExternalPlaylistModel::BaseExternalPlaylistModel(6BaseExternalPlaylistModel::BaseExternalPlaylistModel(
7 QObject* parent, TrackCollection* pTrackCollection,7 QObject* parent, TrackCollection* pTrackCollection,
8 QString settingsNamespace, QString playlistsTable,8 QString settingsNamespace, QString playlistsTable,
9 QString playlistTracksTable, QString trackSource)9 QString playlistTracksTable, QString trackSource,
10 ConfigObject<ConfigValue>* pConfig)
10 : BaseSqlTableModel(parent, pTrackCollection,11 : BaseSqlTableModel(parent, pTrackCollection,
11 pTrackCollection->getDatabase(),12 pConfig, settingsNamespace),
12 settingsNamespace),
13 m_playlistsTable(playlistsTable),13 m_playlistsTable(playlistsTable),
14 m_playlistTracksTable(playlistTracksTable),14 m_playlistTracksTable(playlistTracksTable),
15 m_trackSource(trackSource),15 m_trackSource(trackSource),
1616
=== modified file 'mixxx/src/library/baseexternalplaylistmodel.h'
--- mixxx/src/library/baseexternalplaylistmodel.h 2012-11-22 06:59:01 +0000
+++ mixxx/src/library/baseexternalplaylistmodel.h 2013-05-18 16:32:26 +0000
@@ -10,13 +10,15 @@
10#include "library/librarytablemodel.h"10#include "library/librarytablemodel.h"
11#include "library/dao/playlistdao.h"11#include "library/dao/playlistdao.h"
12#include "library/dao/trackdao.h"12#include "library/dao/trackdao.h"
13#include "configobject.h"
1314
14class BaseExternalPlaylistModel : public BaseSqlTableModel {15class BaseExternalPlaylistModel : public BaseSqlTableModel {
15 Q_OBJECT16 Q_OBJECT
16 public:17 public:
17 BaseExternalPlaylistModel(QObject* pParent, TrackCollection* pTrackCollection,18 BaseExternalPlaylistModel(QObject* pParent, TrackCollection* pTrackCollection,
18 QString settingsNamespace, QString playlistsTable,19 QString settingsNamespace, QString playlistsTable,
19 QString playlistTracksTable, QString trackSource);20 QString playlistTracksTable, QString trackSource,
21 ConfigObject<ConfigValue>* pConfig);
20 virtual ~BaseExternalPlaylistModel();22 virtual ~BaseExternalPlaylistModel();
2123
22 virtual TrackPointer getTrack(const QModelIndex& index) const;24 virtual TrackPointer getTrack(const QModelIndex& index) const;
2325
=== modified file 'mixxx/src/library/baseexternaltrackmodel.cpp'
--- mixxx/src/library/baseexternaltrackmodel.cpp 2012-11-25 11:17:13 +0000
+++ mixxx/src/library/baseexternaltrackmodel.cpp 2013-05-18 16:32:26 +0000
@@ -6,10 +6,10 @@
6 TrackCollection* pTrackCollection,6 TrackCollection* pTrackCollection,
7 QString settingsNamespace,7 QString settingsNamespace,
8 QString trackTable,8 QString trackTable,
9 QString trackSource)9 QString trackSource,
10 ConfigObject<ConfigValue>* pConfig)
10 : BaseSqlTableModel(parent, pTrackCollection,11 : BaseSqlTableModel(parent, pTrackCollection,
11 pTrackCollection->getDatabase(),12 pConfig, settingsNamespace),
12 settingsNamespace),
13 m_pTrackCollection(pTrackCollection),13 m_pTrackCollection(pTrackCollection),
14 m_database(m_pTrackCollection->getDatabase()) {14 m_database(m_pTrackCollection->getDatabase()) {
15 connect(this, SIGNAL(doSearch(const QString&)),15 connect(this, SIGNAL(doSearch(const QString&)),
1616
=== modified file 'mixxx/src/library/baseexternaltrackmodel.h'
--- mixxx/src/library/baseexternaltrackmodel.h 2012-11-22 06:59:01 +0000
+++ mixxx/src/library/baseexternaltrackmodel.h 2013-05-18 16:32:26 +0000
@@ -9,6 +9,7 @@
9#include "library/trackmodel.h"9#include "library/trackmodel.h"
10#include "library/basesqltablemodel.h"10#include "library/basesqltablemodel.h"
11#include "trackinfoobject.h"11#include "trackinfoobject.h"
12#include "configobject.h"
1213
13class TrackCollection;14class TrackCollection;
1415
@@ -18,7 +19,8 @@
18 BaseExternalTrackModel(QObject* parent, TrackCollection* pTrackCollection,19 BaseExternalTrackModel(QObject* parent, TrackCollection* pTrackCollection,
19 QString settingsNamespace,20 QString settingsNamespace,
20 QString trackTable,21 QString trackTable,
21 QString trackSource);22 QString trackSource,
23 ConfigObject<ConfigValue>* pConfig);
22 virtual ~BaseExternalTrackModel();24 virtual ~BaseExternalTrackModel();
2325
24 TrackModel::CapabilitiesFlags getCapabilities() const;26 TrackModel::CapabilitiesFlags getCapabilities() const;
2527
=== modified file 'mixxx/src/library/baseplaylistfeature.cpp'
--- mixxx/src/library/baseplaylistfeature.cpp 2013-05-12 22:17:32 +0000
+++ mixxx/src/library/baseplaylistfeature.cpp 2013-05-18 16:32:26 +0000
@@ -22,6 +22,7 @@
22 m_trackDao(pTrackCollection->getTrackDAO()),22 m_trackDao(pTrackCollection->getTrackDAO()),
23 m_pPlaylistTableModel(NULL),23 m_pPlaylistTableModel(NULL),
24 m_rootViewName(rootViewName) {24 m_rootViewName(rootViewName) {
25
25 m_pCreatePlaylistAction = new QAction(tr("New Playlist"),this);26 m_pCreatePlaylistAction = new QAction(tr("New Playlist"),this);
26 connect(m_pCreatePlaylistAction, SIGNAL(triggered()),27 connect(m_pCreatePlaylistAction, SIGNAL(triggered()),
27 this, SLOT(slotCreatePlaylist()));28 this, SLOT(slotCreatePlaylist()));
@@ -96,7 +97,7 @@
96 QString playlistName = index.data().toString();97 QString playlistName = index.data().toString();
97 int playlistId = m_playlistDao.getPlaylistIdFromName(playlistName);98 int playlistId = m_playlistDao.getPlaylistIdFromName(playlistName);
98 if (m_pPlaylistTableModel) {99 if (m_pPlaylistTableModel) {
99 m_pPlaylistTableModel->setPlaylist(playlistId);100 m_pPlaylistTableModel->setTableModel(playlistId);
100 emit(showTrackModel(m_pPlaylistTableModel));101 emit(showTrackModel(m_pPlaylistTableModel));
101 }102 }
102}103}
@@ -337,11 +338,12 @@
337 }338 }
338339
339 // Create a new table model since the main one might have an active search.340 // Create a new table model since the main one might have an active search.
341 // This PTM will only use tracks that are not deleted from the FS
340 QScopedPointer<PlaylistTableModel> pPlaylistTableModel(342 QScopedPointer<PlaylistTableModel> pPlaylistTableModel(
341 new PlaylistTableModel(this, m_pTrackCollection,343 new PlaylistTableModel(this, m_pTrackCollection,
342 "mixxx.db.model.playlist_export"));344 "mixxx.db.model.playlist_export", m_pConfig));
343345
344 pPlaylistTableModel->setPlaylist(m_pPlaylistTableModel->getPlaylist());346 pPlaylistTableModel->setTableModel(m_pPlaylistTableModel->getPlaylist());
345 pPlaylistTableModel->setSort(pPlaylistTableModel->fieldIndex(PLAYLISTTRACKSTABLE_POSITION), Qt::AscendingOrder);347 pPlaylistTableModel->setSort(pPlaylistTableModel->fieldIndex(PLAYLISTTRACKSTABLE_POSITION), Qt::AscendingOrder);
346 pPlaylistTableModel->select();348 pPlaylistTableModel->select();
347349
@@ -476,4 +478,3 @@
476void BasePlaylistFeature::clearChildModel() {478void BasePlaylistFeature::clearChildModel() {
477 m_childModel.removeRows(0, m_playlistList.size());479 m_childModel.removeRows(0, m_playlistList.size());
478}480}
479
480481
=== modified file 'mixxx/src/library/baseplaylistfeature.h'
--- mixxx/src/library/baseplaylistfeature.h 2013-02-23 10:40:40 +0000
+++ mixxx/src/library/baseplaylistfeature.h 2013-05-18 16:32:26 +0000
@@ -76,7 +76,6 @@
7676
77 private:77 private:
78 virtual QString getRootViewHtml() const = 0;78 virtual QString getRootViewHtml() const = 0;
79
80 QString m_rootViewName;79 QString m_rootViewName;
81};80};
8281
8382
=== modified file 'mixxx/src/library/basesqltablemodel.cpp'
--- mixxx/src/library/basesqltablemodel.cpp 2013-05-14 22:25:44 +0000
+++ mixxx/src/library/basesqltablemodel.cpp 2013-05-18 16:32:26 +0000
@@ -20,16 +20,17 @@
2020
21BaseSqlTableModel::BaseSqlTableModel(QObject* pParent,21BaseSqlTableModel::BaseSqlTableModel(QObject* pParent,
22 TrackCollection* pTrackCollection,22 TrackCollection* pTrackCollection,
23 QSqlDatabase db,23 ConfigObject<ConfigValue>* pConfig,
24 QString settingsNamespace)24 QString settingsNamespace)
25 : QAbstractTableModel(pParent),25 : QAbstractTableModel(pParent),
26 TrackModel(db, settingsNamespace),26 TrackModel(pTrackCollection->getDatabase(), settingsNamespace),
27 m_currentSearch(""),
28 m_previewDeckGroup(PlayerManager::groupForPreviewDeck(0)),27 m_previewDeckGroup(PlayerManager::groupForPreviewDeck(0)),
29 m_iPreviewDeckTrackId(-1),28 m_iPreviewDeckTrackId(-1),
30 m_pTrackCollection(pTrackCollection),29 m_pTrackCollection(pTrackCollection),
31 m_trackDAO(m_pTrackCollection->getTrackDAO()),30 m_trackDAO(m_pTrackCollection->getTrackDAO()),
32 m_database(db) {31 m_pConfig(pConfig),
32 m_currentSearch(""),
33 m_database(pTrackCollection->getDatabase()) {
33 m_bInitialized = false;34 m_bInitialized = false;
34 m_bDirty = true;35 m_bDirty = true;
35 m_iSortColumn = 0;36 m_iSortColumn = 0;
@@ -214,7 +215,6 @@
214215
215 QLinkedList<int> tableColumnIndices;216 QLinkedList<int> tableColumnIndices;
216 foreach (QString column, m_tableColumns) {217 foreach (QString column, m_tableColumns) {
217 Q_ASSERT(record.indexOf(column) == m_tableColumnIndex[column]);
218 tableColumnIndices.push_back(record.indexOf(column));218 tableColumnIndices.push_back(record.indexOf(column));
219 }219 }
220220
@@ -227,6 +227,8 @@
227 QSet<int> trackIds;227 QSet<int> trackIds;
228 while (query.next()) {228 while (query.next()) {
229 int id = query.value(idColumn).toInt();229 int id = query.value(idColumn).toInt();
230
231
230 trackIds.insert(id);232 trackIds.insert(id);
231233
232 RowInfo thisRowInfo;234 RowInfo thisRowInfo;
@@ -359,7 +361,7 @@
359 m_bDirty = true;361 m_bDirty = true;
360}362}
361363
362void BaseSqlTableModel::search(const QString& searchText, const QString extraFilter) {364void BaseSqlTableModel::search(const QString& searchText, const QString& extraFilter) {
363 if (sDebug) {365 if (sDebug) {
364 qDebug() << this << "search" << searchText;366 qDebug() << this << "search" << searchText;
365 }367 }
@@ -436,7 +438,8 @@
436 if (!index.isValid() || (role != Qt::DisplayRole &&438 if (!index.isValid() || (role != Qt::DisplayRole &&
437 role != Qt::EditRole &&439 role != Qt::EditRole &&
438 role != Qt::CheckStateRole &&440 role != Qt::CheckStateRole &&
439 role != Qt::ToolTipRole)) {441 role != Qt::ToolTipRole &&
442 role != Qt::BackgroundColorRole)) {
440 return QVariant();443 return QVariant();
441 }444 }
442445
@@ -451,6 +454,13 @@
451 // role454 // role
452 switch (role) {455 switch (role) {
453 case Qt::ToolTipRole:456 case Qt::ToolTipRole:
457 if(index.sibling(index.row(),
458 fieldIndex(TRACKLOCATIONSTABLE_FSDELETED)).data().toInt()==1){
459 QString warning(tr("No such file at : "));
460 value = QVariant(QString(warning+index.sibling(index.row(),
461 fieldIndex(LIBRARYTABLE_LOCATION)).data().toString()));
462 }
463 break;
454 case Qt::DisplayRole:464 case Qt::DisplayRole:
455 if (column == fieldIndex(LIBRARYTABLE_DURATION)) {465 if (column == fieldIndex(LIBRARYTABLE_DURATION)) {
456 if (qVariantCanConvert<int>(value)) {466 if (qVariantCanConvert<int>(value)) {
@@ -499,6 +509,14 @@
499 value = locked ? Qt::Checked : Qt::Unchecked;509 value = locked ? Qt::Checked : Qt::Unchecked;
500 }510 }
501 break;511 break;
512 case Qt::BackgroundColorRole:
513 if (index.sibling(index.row(),
514 fieldIndex(TRACKLOCATIONSTABLE_FSDELETED)).data().toInt()==1){
515 //TODO kain88 choose a better looking color, this will also
516 // have to be changed in stardelegate
517 value = QVariant(QColor(Qt::red));
518 }
519 break;
502 default:520 default:
503 break;521 break;
504 }522 }
@@ -626,6 +644,10 @@
626 return index.sibling(index.row(), fieldIndex(m_idColumn)).data().toInt();644 return index.sibling(index.row(), fieldIndex(m_idColumn)).data().toInt();
627}645}
628646
647TrackPointer BaseSqlTableModel::getTrack(const QModelIndex& index) const {
648 return m_trackDAO.getTrack(getTrackId(index));
649}
650
629QString BaseSqlTableModel::getTrackLocation(const QModelIndex& index) const {651QString BaseSqlTableModel::getTrackLocation(const QModelIndex& index) const {
630 if (!index.isValid()) {652 if (!index.isValid()) {
631 return "";653 return "";
@@ -656,7 +678,6 @@
656 if (sDebug) {678 if (sDebug) {
657 qDebug() << this << "trackChanged" << trackIds.size();679 qDebug() << this << "trackChanged" << trackIds.size();
658 }680 }
659
660 const int numColumns = columnCount();681 const int numColumns = columnCount();
661 foreach (int trackId, trackIds) {682 foreach (int trackId, trackIds) {
662 QLinkedList<int> rows = getTrackRows(trackId);683 QLinkedList<int> rows = getTrackRows(trackId);
@@ -717,7 +738,8 @@
717 const QModelIndex& index, int role) const {738 const QModelIndex& index, int role) const {
718 if (role != Qt::DisplayRole &&739 if (role != Qt::DisplayRole &&
719 role != Qt::ToolTipRole &&740 role != Qt::ToolTipRole &&
720 role != Qt::EditRole) {741 role != Qt::EditRole &&
742 role != Qt::BackgroundColorRole) {
721 return QVariant();743 return QVariant();
722 }744 }
723745
@@ -822,3 +844,51 @@
822 // there.844 // there.
823 select(); //Repopulate the data model.845 select(); //Repopulate the data model.
824}846}
847
848void BaseSqlTableModel::slotConfigChanged(QString identifier, QString key){
849 Q_UNUSED(identifier);
850 if (key=="ShowMissingSongs") {
851 setTableModel();
852 select();
853 }
854}
855
856void BaseSqlTableModel::setTableModel(int id) {
857 Q_UNUSED(id);
858}
859
860void BaseSqlTableModel::relocateTracks(const QModelIndexList& indices) {
861 foreach (QModelIndex index, indices) {
862 int trackId = getTrackId(index);
863 TrackPointer ptrack = m_trackDAO.getTrack(trackId);
864 if (!ptrack) {
865 qDebug() << "strange I can't get that thing";
866 }
867 QString newLocation = QFileDialog::getOpenFileName(QApplication::desktop(),
868 QString(ptrack->getTitle()),
869 ptrack->getLocation());
870
871 if (!newLocation.isEmpty()) {
872 if (!m_trackDAO.relocateTrack(ptrack, newLocation)) {
873 QMessageBox::warning(NULL, tr("Mixxx"),
874 tr("The track could not be relocated"));
875 }
876 }
877 }
878 setTableModel();
879 select();
880}
881
882bool BaseSqlTableModel::isColumnInternal(int column) {
883 Q_UNUSED(column);
884 return false;
885}
886
887bool BaseSqlTableModel::isColumnHiddenByDefault(int column) {
888 Q_UNUSED(column);
889 return false;
890}
891
892TrackModel::CapabilitiesFlags BaseSqlTableModel::getCapabilities() const {
893 return TRACKMODELCAPS_NONE;
894}
825895
=== modified file 'mixxx/src/library/basesqltablemodel.h'
--- mixxx/src/library/basesqltablemodel.h 2013-01-17 08:16:08 +0000
+++ mixxx/src/library/basesqltablemodel.h 2013-05-18 16:32:26 +0000
@@ -22,21 +22,43 @@
22 public:22 public:
23 BaseSqlTableModel(QObject* pParent,23 BaseSqlTableModel(QObject* pParent,
24 TrackCollection* pTrackCollection,24 TrackCollection* pTrackCollection,
25 QSqlDatabase db, QString settingsNamespace);25 ConfigObject<ConfigValue>* pConfig,
26 QString settingsNamespace);
26 virtual ~BaseSqlTableModel();27 virtual ~BaseSqlTableModel();
2728
28 ////////////////////////////////////////////////////////////////////////////29 // functions that HAVE to be implemented in a child class
29 // Methods implemented from QAbstractItemModel30 virtual void setTableModel(int id=-1);
30 ////////////////////////////////////////////////////////////////////////////31 virtual bool isColumnInternal(int column);
3132 virtual bool isColumnHiddenByDefault(int column);
32 virtual void sort(int column, Qt::SortOrder order);33 virtual TrackModel::CapabilitiesFlags getCapabilities() const;
33 virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;34 // calls readWriteFlags() by default, reimplement this if the child calls
34 virtual bool setData(const QModelIndex& index, const QVariant& value, int role=Qt::EditRole);35 // should be readOnly
35 virtual int columnCount(const QModelIndex& parent=QModelIndex()) const;36 virtual Qt::ItemFlags flags(const QModelIndex &index) const;
36 virtual int rowCount(const QModelIndex& parent=QModelIndex()) const;37 // function to reimplement for external libraries
37 virtual bool setHeaderData(int section, Qt::Orientation orientation,38 virtual TrackPointer getTrack(const QModelIndex& index) const;
39
40 // Other public methods
41 int getTrackId(const QModelIndex& index) const;
42 void search(const QString& searchText, const QString& extraFilter=QString());
43 void setSearch(const QString& searchText, const QString extraFilter=QString());
44 const QString currentSearch() const;
45 void setSort(int column, Qt::SortOrder order);
46 int fieldIndex(const QString& fieldName) const;
47 void select();
48 QString getTrackLocation(const QModelIndex& index) const;
49 QAbstractItemDelegate* delegateForColumn(const int i, QObject* pParent);
50 void relocateTracks(const QModelIndexList& indices);
51 void hideTracks(const QModelIndexList& indices);
52
53 // Methods reimplemented from QAbstractItemModel
54 void sort(int column, Qt::SortOrder order);
55 int rowCount(const QModelIndex& parent=QModelIndex()) const;
56 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
57 bool setData(const QModelIndex& index, const QVariant& value, int role=Qt::EditRole);
58 int columnCount(const QModelIndex& parent=QModelIndex()) const;
59 bool setHeaderData(int section, Qt::Orientation orientation,
38 const QVariant &value, int role=Qt::EditRole);60 const QVariant &value, int role=Qt::EditRole);
39 virtual QVariant headerData(int section, Qt::Orientation orientation,61 QVariant headerData(int section, Qt::Orientation orientation,
40 int role=Qt::DisplayRole) const;62 int role=Qt::DisplayRole) const;
41 virtual QMimeData* mimeData(const QModelIndexList &indexes) const;63 virtual QMimeData* mimeData(const QModelIndexList &indexes) const;
4264
@@ -44,44 +66,33 @@
44 // Other public methods66 // Other public methods
45 ////////////////////////////////////////////////////////////////////////////67 ////////////////////////////////////////////////////////////////////////////
4668
47 virtual void search(const QString& searchText, const QString extraFilter=QString());
48 virtual void setSearch(const QString& searchText, const QString extraFilter=QString());
49 virtual const QString currentSearch() const;
50 virtual void setSort(int column, Qt::SortOrder order);
51 virtual int fieldIndex(const QString& fieldName) const;
52 virtual void select();
53 virtual int getTrackId(const QModelIndex& index) const;
54 virtual QString getTrackLocation(const QModelIndex& index) const;
55 virtual QAbstractItemDelegate* delegateForColumn(const int i, QObject* pParent);
56 virtual void hideTracks(const QModelIndexList& indices);
57 // Returns true if the BaseSqlTableModel has been initialized. Calling data69 // Returns true if the BaseSqlTableModel has been initialized. Calling data
58 // access methods on a BaseSqlTableModel which is not initialized is likely70 // access methods on a BaseSqlTableModel which is not initialized is likely
59 // to cause instability / crashes.71 // to cause instability / crashes.
60 bool initialized() const { return m_bInitialized; }72 bool initialized() const { return m_bInitialized; }
6173
62 protected:74 protected://functions
63 // Returns the row of trackId in this result set. If trackId is not present,75 // Returns the row of trackId in this result set. If trackId is not present,
64 // returns -1.76 // returns -1.
65 virtual const QLinkedList<int> getTrackRows(int trackId) const;77 const QLinkedList<int> getTrackRows(int trackId) const;
6678 void setTable(const QString& tableName, const QString& trackIdColumn,
67 virtual void setTable(const QString& tableName,79 const QStringList& tableColumns,
68 const QString& trackIdColumn,80 QSharedPointer<BaseTrackCache> trackSource);
69 const QStringList& tableColumns,81 void initHeaderData();
70 QSharedPointer<BaseTrackCache> trackSource);82
71 QSqlDatabase database() const;83 // Use this if you want a model that is read-only.
7284 Qt::ItemFlags readOnlyFlags(const QModelIndex &index) const;
73 /** Use this if you want a model that is read-only. */85 // Use this if you want a model that can be changed
74 virtual Qt::ItemFlags readOnlyFlags(const QModelIndex &index) const;86 Qt::ItemFlags readWriteFlags(const QModelIndex &index) const;
75 /** Use this if you want a model that can be changed */87
76 virtual Qt::ItemFlags readWriteFlags(const QModelIndex &index) const;88 //variables
77 /** calls readWriteFlags() by default */89 TrackCollection* m_pTrackCollection;
78 virtual Qt::ItemFlags flags(const QModelIndex &index) const;90 TrackDAO& m_trackDAO;
7991 ConfigObject<ConfigValue>* m_pConfig;
80 // Set the columns used for searching. Names must correspond to the column92 QSqlDatabase m_database;
81 // names in the table provided to setTable. Must be called after setTable is93
82 // called.94 protected slots:
83 virtual QString orderByClause() const;95 void slotConfigChanged(QString,QString);
84 virtual void initHeaderData();
8596
86 private slots:97 private slots:
87 void tracksChanged(QSet<int> trackIds);98 void tracksChanged(QSet<int> trackIds);
@@ -90,6 +101,11 @@
90 private:101 private:
91 inline void setTrackValueForColumn(TrackPointer pTrack, int column, QVariant value);102 inline void setTrackValueForColumn(TrackPointer pTrack, int column, QVariant value);
92 QVariant getBaseValue(const QModelIndex& index, int role = Qt::DisplayRole) const;103 QVariant getBaseValue(const QModelIndex& index, int role = Qt::DisplayRole) const;
104 // Set the columns used for searching. Names must correspond to the column
105 // names in the table provided to setTable. Must be called after setTable is
106 // called.
107 QString orderByClause() const;
108 QSqlDatabase database() const;
93109
94 struct RowInfo {110 struct RowInfo {
95 int trackId;111 int trackId;
@@ -106,6 +122,7 @@
106 return order < other.order;122 return order < other.order;
107 }123 }
108 };124 };
125 QVector<RowInfo> m_rowInfo;
109126
110 QString m_tableName;127 QString m_tableName;
111 QString m_idColumn;128 QString m_idColumn;
@@ -120,7 +137,6 @@
120 bool m_bInitialized;137 bool m_bInitialized;
121 bool m_bDirty;138 bool m_bDirty;
122 QSqlRecord m_queryRecord;139 QSqlRecord m_queryRecord;
123 QVector<RowInfo> m_rowInfo;
124 QHash<int, int> m_trackSortOrder;140 QHash<int, int> m_trackSortOrder;
125 QHash<int, QLinkedList<int> > m_trackIdToRows;141 QHash<int, QLinkedList<int> > m_trackIdToRows;
126142
@@ -132,10 +148,6 @@
132148
133 QVector<QHash<int, QVariant> > m_headerInfo;149 QVector<QHash<int, QVariant> > m_headerInfo;
134150
135 TrackCollection* m_pTrackCollection;
136 TrackDAO& m_trackDAO;
137 QSqlDatabase m_database;
138
139 DISALLOW_COPY_AND_ASSIGN(BaseSqlTableModel);151 DISALLOW_COPY_AND_ASSIGN(BaseSqlTableModel);
140};152};
141153
142154
=== modified file 'mixxx/src/library/basetrackcache.cpp'
--- mixxx/src/library/basetrackcache.cpp 2013-04-25 04:56:07 +0000
+++ mixxx/src/library/basetrackcache.cpp 2013-05-18 16:32:26 +0000
@@ -87,6 +87,7 @@
87 qDebug() << this << "slotTracksAdded" << trackIds.size();87 qDebug() << this << "slotTracksAdded" << trackIds.size();
88 }88 }
89 updateTracksInIndex(trackIds);89 updateTracksInIndex(trackIds);
90 buildIndex();
90}91}
9192
92void BaseTrackCache::slotDbTrackAdded(TrackPointer pTrack) {93void BaseTrackCache::slotDbTrackAdded(TrackPointer pTrack) {
@@ -118,6 +119,7 @@
118 }119 }
119 QSet<int> trackIds;120 QSet<int> trackIds;
120 trackIds.insert(trackId);121 trackIds.insert(trackId);
122 updateTracksInIndex(trackIds);
121 emit(tracksChanged(trackIds));123 emit(tracksChanged(trackIds));
122}124}
123125
124126
=== modified file 'mixxx/src/library/browse/browsefeature.cpp'
--- mixxx/src/library/browse/browsefeature.cpp 2013-01-01 11:53:13 +0000
+++ mixxx/src/library/browse/browsefeature.cpp 2013-05-18 16:32:26 +0000
@@ -29,7 +29,12 @@
29 m_pConfig(pConfig),29 m_pConfig(pConfig),
30 m_browseModel(this, pTrackCollection, pRecordingManager),30 m_browseModel(this, pTrackCollection, pRecordingManager),
31 m_proxyModel(&m_browseModel),31 m_proxyModel(&m_browseModel),
32 m_pTrackCollection(pTrackCollection) {32 m_pAddtoLibraryAction(NULL),
33 m_pLastRightClickedItem(NULL),
34 m_pTrackCollection(pTrackCollection){
35
36 connect(this, SIGNAL(dirsChanged(QString,QString)),
37 parent, SLOT(slotDirsChanged(QString,QString)));
3338
34 m_pAddQuickLinkAction = new QAction(tr("Add to Quick Links"),this);39 m_pAddQuickLinkAction = new QAction(tr("Add to Quick Links"),this);
35 connect(m_pAddQuickLinkAction, SIGNAL(triggered()), this, SLOT(slotAddQuickLink()));40 connect(m_pAddQuickLinkAction, SIGNAL(triggered()), this, SLOT(slotAddQuickLink()));
@@ -37,6 +42,10 @@
37 m_pRemoveQuickLinkAction = new QAction(tr("Remove from Quick Links"),this);42 m_pRemoveQuickLinkAction = new QAction(tr("Remove from Quick Links"),this);
38 connect(m_pRemoveQuickLinkAction, SIGNAL(triggered()), this, SLOT(slotRemoveQuickLink()));43 connect(m_pRemoveQuickLinkAction, SIGNAL(triggered()), this, SLOT(slotRemoveQuickLink()));
3944
45 m_pAddtoLibraryAction = new QAction(tr("Add to Library"),this);
46 connect(m_pAddtoLibraryAction, SIGNAL(triggered()),
47 this, SLOT(slotAddToLibrary()));
48
40 m_proxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);49 m_proxyModel.setFilterCaseSensitivity(Qt::CaseInsensitive);
41 m_proxyModel.setSortCaseSensitivity(Qt::CaseInsensitive);50 m_proxyModel.setSortCaseSensitivity(Qt::CaseInsensitive);
4251
@@ -75,7 +84,7 @@
7584
76 // show root directory on UNIX-based operating systems85 // show root directory on UNIX-based operating systems
77 TreeItem* root_folder_item = new TreeItem(86 TreeItem* root_folder_item = new TreeItem(
78 QDir::rootPath(), QDir::rootPath(), this, rootItem);87 QDir::homePath(), QDir::homePath(), this, rootItem);
79 rootItem->appendChild(root_folder_item);88 rootItem->appendChild(root_folder_item);
80#endif89#endif
8190
@@ -100,11 +109,14 @@
100 m_pQuickLinkItem->appendChild(item);109 m_pQuickLinkItem->appendChild(item);
101 }110 }
102111
112
103 // initialize the model113 // initialize the model
104 m_childModel.setRootItem(rootItem);114 m_childModel.setRootItem(rootItem);
105}115}
106116
107BrowseFeature::~BrowseFeature() {117BrowseFeature::~BrowseFeature() {
118 //delete m_pLastRightClickedItem;
119 // delete m_pQuickLinkItem;
108}120}
109121
110QVariant BrowseFeature::title() {122QVariant BrowseFeature::title() {
@@ -124,6 +136,14 @@
124 saveQuickLinks();136 saveQuickLinks();
125}137}
126138
139void BrowseFeature::slotAddToLibrary() {
140 if (!m_pLastRightClickedItem) {
141 return;
142 }
143 QString spath = m_pLastRightClickedItem->dataPath().toString();
144 emit dirsChanged("added" ,spath);
145}
146
127void BrowseFeature::slotRemoveQuickLink() {147void BrowseFeature::slotRemoveQuickLink() {
128 if (!m_pLastRightClickedItem) {148 if (!m_pLastRightClickedItem) {
129 return;149 return;
@@ -200,6 +220,7 @@
200 }220 }
201221
202 menu.addAction(m_pAddQuickLinkAction);222 menu.addAction(m_pAddQuickLinkAction);
223 menu.addAction(m_pAddtoLibraryAction);
203 menu.exec(globalPos);224 menu.exec(globalPos);
204 onLazyChildExpandation(index);225 onLazyChildExpandation(index);
205}226}
206227
=== modified file 'mixxx/src/library/browse/browsefeature.h'
--- mixxx/src/library/browse/browsefeature.h 2013-01-01 11:53:13 +0000
+++ mixxx/src/library/browse/browsefeature.h 2013-05-18 16:32:26 +0000
@@ -38,6 +38,7 @@
38 public slots:38 public slots:
39 void slotAddQuickLink();39 void slotAddQuickLink();
40 void slotRemoveQuickLink();40 void slotRemoveQuickLink();
41 void slotAddToLibrary();
41 void activate();42 void activate();
42 void activateChild(const QModelIndex& index);43 void activateChild(const QModelIndex& index);
43 void onRightClickChild(const QPoint& globalPos, QModelIndex index);44 void onRightClickChild(const QPoint& globalPos, QModelIndex index);
@@ -45,6 +46,7 @@
4546
46 signals:47 signals:
47 void setRootIndex(const QModelIndex&);48 void setRootIndex(const QModelIndex&);
49 void dirsChanged(QString,QString);
4850
49 private:51 private:
50 QString getRootViewHtml() const;52 QString getRootViewHtml() const;
@@ -60,6 +62,7 @@
60 FolderTreeModel m_childModel;62 FolderTreeModel m_childModel;
61 QAction* m_pAddQuickLinkAction;63 QAction* m_pAddQuickLinkAction;
62 QAction* m_pRemoveQuickLinkAction;64 QAction* m_pRemoveQuickLinkAction;
65 QAction* m_pAddtoLibraryAction;
63 TreeItem* m_pLastRightClickedItem;66 TreeItem* m_pLastRightClickedItem;
64 TreeItem* m_pQuickLinkItem;67 TreeItem* m_pQuickLinkItem;
65 QStringList m_quickLinkList;68 QStringList m_quickLinkList;
6669
=== modified file 'mixxx/src/library/browse/browsetablemodel.cpp'
--- mixxx/src/library/browse/browsetablemodel.cpp 2013-01-19 12:15:22 +0000
+++ mixxx/src/library/browse/browsetablemodel.cpp 2013-05-18 16:32:26 +0000
@@ -124,7 +124,8 @@
124 return QLinkedList<int>();124 return QLinkedList<int>();
125}125}
126126
127void BrowseTableModel::search(const QString& searchText) {127void BrowseTableModel::search(const QString& searchText, const QString& extraFilter) {
128 Q_UNUSED(extraFilter);
128 Q_UNUSED(searchText);129 Q_UNUSED(searchText);
129}130}
130131
131132
=== modified file 'mixxx/src/library/browse/browsetablemodel.h'
--- mixxx/src/library/browse/browsetablemodel.h 2012-08-10 15:03:46 +0000
+++ mixxx/src/library/browse/browsetablemodel.h 2013-05-18 16:32:26 +0000
@@ -42,7 +42,7 @@
42 virtual int getTrackId(const QModelIndex& index) const;42 virtual int getTrackId(const QModelIndex& index) const;
43 TrackModel::CapabilitiesFlags getCapabilities() const;43 TrackModel::CapabilitiesFlags getCapabilities() const;
44 virtual const QLinkedList<int> getTrackRows(int trackId) const;44 virtual const QLinkedList<int> getTrackRows(int trackId) const;
45 virtual void search(const QString& searchText);45 virtual void search(const QString& searchText,const QString& extraFilter=QString());
46 virtual void removeTrack(const QModelIndex& index);46 virtual void removeTrack(const QModelIndex& index);
47 virtual void removeTracks(const QModelIndexList& indices);47 virtual void removeTracks(const QModelIndexList& indices);
48 virtual bool addTrack(const QModelIndex& index, QString location);48 virtual bool addTrack(const QModelIndex& index, QString location);
4949
=== modified file 'mixxx/src/library/browse/browsethread.h'
--- mixxx/src/library/browse/browsethread.h 2012-03-13 04:36:19 +0000
+++ mixxx/src/library/browse/browsethread.h 2013-05-18 16:32:26 +0000
@@ -11,15 +11,13 @@
11#include <QStandardItem>11#include <QStandardItem>
12#include <QList>12#include <QList>
1313
14/*14// This class is a singleton and represents a thread
15 * This class is a singleton and represents a thread15// that is used to read ID3 metadata
16 * that is used to read ID3 metadata16// from a particular folder.
17 * from a particular folder.17//
18 *18// The BroseTableModel uses this class.
19 * The BroseTableModel uses this class.19// Note: Don't call getInstance() from places
20 * Note: Don't call getInstance() from places20// other than the GUI thread.
21 * other than the GUI thread.
22 */
23class BrowseTableModel;21class BrowseTableModel;
2422
25class BrowseThread : public QThread {23class BrowseThread : public QThread {
2624
=== modified file 'mixxx/src/library/browse/foldertreemodel.cpp'
--- mixxx/src/library/browse/foldertreemodel.cpp 2012-07-18 21:22:53 +0000
+++ mixxx/src/library/browse/foldertreemodel.cpp 2013-05-18 16:32:26 +0000
@@ -25,6 +25,7 @@
25}25}
2626
27FolderTreeModel::~FolderTreeModel() {27FolderTreeModel::~FolderTreeModel() {
28 qDebug() << "~FolderTreeModel()";
28}29}
2930
30/* A tree model of the filesystem should be initialized lazy.31/* A tree model of the filesystem should be initialized lazy.
3132
=== modified file 'mixxx/src/library/cratefeature.cpp'
--- mixxx/src/library/cratefeature.cpp 2013-04-22 19:29:54 +0000
+++ mixxx/src/library/cratefeature.cpp 2013-05-18 16:32:26 +0000
@@ -20,10 +20,11 @@
20#include "soundsourceproxy.h"20#include "soundsourceproxy.h"
2121
22CrateFeature::CrateFeature(QObject* parent,22CrateFeature::CrateFeature(QObject* parent,
23 TrackCollection* pTrackCollection, ConfigObject<ConfigValue>* pConfig)23 TrackCollection* pTrackCollection,
24 ConfigObject<ConfigValue>* pConfig)
24 : m_pTrackCollection(pTrackCollection),25 : m_pTrackCollection(pTrackCollection),
25 m_crateDao(pTrackCollection->getCrateDAO()),26 m_crateDao(pTrackCollection->getCrateDAO()),
26 m_crateTableModel(this, pTrackCollection),27 m_crateTableModel(this, pTrackCollection,pConfig),
27 m_pConfig(pConfig) {28 m_pConfig(pConfig) {
28 Q_UNUSED(parent);29 Q_UNUSED(parent);
29 m_pCreateCrateAction = new QAction(tr("New Crate"),this);30 m_pCreateCrateAction = new QAction(tr("New Crate"),this);
@@ -65,6 +66,9 @@
65 connect(&m_crateDao, SIGNAL(lockChanged(int)),66 connect(&m_crateDao, SIGNAL(lockChanged(int)),
66 this, SLOT(slotCrateTableChanged(int)));67 this, SLOT(slotCrateTableChanged(int)));
6768
69 connect(this, SIGNAL(configChanged(QString,QString)),
70 &m_crateTableModel, SLOT(slotConfigChanged(QString,QString)));
71
68 // construct child model72 // construct child model
69 TreeItem *rootItem = new TreeItem();73 TreeItem *rootItem = new TreeItem();
70 m_childModel.setRootItem(rootItem);74 m_childModel.setRootItem(rootItem);
@@ -156,7 +160,7 @@
156 return;160 return;
157 QString crateName = index.data().toString();161 QString crateName = index.data().toString();
158 int crateId = m_crateDao.getCrateIdByName(crateName);162 int crateId = m_crateDao.getCrateIdByName(crateName);
159 m_crateTableModel.setCrate(crateId);163 m_crateTableModel.setTableModel(crateId);
160 emit(showTrackModel(&m_crateTableModel));164 emit(showTrackModel(&m_crateTableModel));
161}165}
162166
@@ -473,7 +477,6 @@
473 }477 }
474478
475 QList<QString> entries = playlist_parser->parse(playlist_file);479 QList<QString> entries = playlist_parser->parse(playlist_file);
476 //qDebug() << "Size of Imported Playlist: " << entries.size();
477480
478 //Iterate over the List that holds URLs of playlist entires481 //Iterate over the List that holds URLs of playlist entires
479 m_crateTableModel.addTracks(QModelIndex(), entries);482 m_crateTableModel.addTracks(QModelIndex(), entries);
@@ -503,8 +506,8 @@
503 QList<QString> playlist_items;506 QList<QString> playlist_items;
504 // Create a new table model since the main one might have an active search.507 // Create a new table model since the main one might have an active search.
505 QScopedPointer<CrateTableModel> pCrateTableModel(508 QScopedPointer<CrateTableModel> pCrateTableModel(
506 new CrateTableModel(this, m_pTrackCollection));509 new CrateTableModel(this, m_pTrackCollection,m_pConfig));
507 pCrateTableModel->setCrate(m_crateTableModel.getCrate());510 pCrateTableModel->setTableModel(m_crateTableModel.getCrate());
508 pCrateTableModel->select();511 pCrateTableModel->select();
509512
510 if (file_location.endsWith(".csv", Qt::CaseInsensitive)) {513 if (file_location.endsWith(".csv", Qt::CaseInsensitive)) {
@@ -542,7 +545,7 @@
542 clearChildModel();545 clearChildModel();
543 m_lastRightClickedIndex = constructChildModel(crateId);546 m_lastRightClickedIndex = constructChildModel(crateId);
544 // Switch the view to the crate.547 // Switch the view to the crate.
545 m_crateTableModel.setCrate(crateId);548 m_crateTableModel.setTableModel(crateId);
546 // Update selection549 // Update selection
547 emit(featureSelect(this, m_lastRightClickedIndex));550 emit(featureSelect(this, m_lastRightClickedIndex));
548}551}
549552
=== modified file 'mixxx/src/library/cratefeature.h'
--- mixxx/src/library/cratefeature.h 2013-05-18 16:23:08 +0000
+++ mixxx/src/library/cratefeature.h 2013-05-18 16:32:26 +0000
@@ -34,6 +34,9 @@
3434
35 TreeItemModel* getChildModel();35 TreeItemModel* getChildModel();
3636
37 signals:
38 void configChanged(QString,QString);
39
37 public slots:40 public slots:
38 void activate();41 void activate();
39 void activateChild(const QModelIndex& index);42 void activateChild(const QModelIndex& index);
4043
=== modified file 'mixxx/src/library/cratetablemodel.cpp'
--- mixxx/src/library/cratetablemodel.cpp 2013-04-22 19:29:54 +0000
+++ mixxx/src/library/cratetablemodel.cpp 2013-05-18 16:32:26 +0000
@@ -4,53 +4,69 @@
4#include <QtDebug>4#include <QtDebug>
55
6#include "library/cratetablemodel.h"6#include "library/cratetablemodel.h"
7
8#include "library/dao/cratedao.h"
9#include "library/librarytablemodel.h"
10#include "library/queryutil.h"7#include "library/queryutil.h"
11#include "library/trackcollection.h"8#include "library/trackcollection.h"
12#include "mixxxutils.cpp"9#include "mixxxutils.cpp"
13#include "playermanager.h"10#include "playermanager.h"
1411
15CrateTableModel::CrateTableModel(QObject* pParent, TrackCollection* pTrackCollection)12CrateTableModel::CrateTableModel(QObject* pParent,
13 TrackCollection* pTrackCollection,
14 ConfigObject<ConfigValue>* pConfig)
16 : BaseSqlTableModel(pParent, pTrackCollection,15 : BaseSqlTableModel(pParent, pTrackCollection,
17 pTrackCollection->getDatabase(),16 pConfig, "mixxx.db.model.crate"),
18 "mixxx.db.model.crate"),17 m_iCrateId(-1),
19 m_pTrackCollection(pTrackCollection),18 m_crateDAO(pTrackCollection->getCrateDAO()) {
20 m_iCrateId(-1) {
21 connect(this, SIGNAL(doSearch(const QString&)),
22 this, SLOT(slotSearch(const QString&)));
23}19}
2420
25CrateTableModel::~CrateTableModel() {21CrateTableModel::~CrateTableModel() {
26}22}
2723
28void CrateTableModel::setCrate(int crateId) {24void CrateTableModel::setTableModel(int crateId) {
29 //qDebug() << "CrateTableModel::setCrate()" << crateId;25 //qDebug() << "CrateTableModel::setCrate()" << crateId;
26 if (crateId == m_iCrateId) {
27 qDebug() << "Already focused on crate " << crateId;
28 return;
29 } else if (crateId == -1) {
30 // calls from parent class use -1 as id then just set the current crate
31 crateId = m_iCrateId;
32 }
30 m_iCrateId = crateId;33 m_iCrateId = crateId;
3134
32 QString tableName = QString("crate_%1").arg(m_iCrateId);35 QString tableName = QString("crate_%1_").arg(m_iCrateId);
33 QSqlQuery query(m_pTrackCollection->getDatabase());36 QSqlQuery query(m_pTrackCollection->getDatabase());
34 FieldEscaper escaper(m_pTrackCollection->getDatabase());37 FieldEscaper escaper(m_pTrackCollection->getDatabase());
38
35 QStringList columns;39 QStringList columns;
36 columns << CRATETRACKSTABLE_TRACKID + " as " + LIBRARYTABLE_ID40 QStringList tableColumns;
41 QString filter;
42 columns << "crate_tracks."+CRATETRACKSTABLE_TRACKID + " as " + LIBRARYTABLE_ID
37 << "'' as preview";43 << "'' as preview";
44 tableColumns << CRATETRACKSTABLE_TRACKID;
45 bool showMissing = m_pConfig->getValueString(ConfigKey("[Library]","ShowMissingSongs"),"1").toInt();
46 if(showMissing){
47 filter = "library.mixxx_deleted=0";
48 tableName.append("_missing");
49 } else {
50 filter = "library.mixxx_deleted=0 AND track_locations.fs_deleted=0";
51 }
3852
39 // We drop files that have been explicitly deleted from mixxx53 // We drop files that have been explicitly deleted from mixxx
40 // (mixxx_deleted=0) from the view. There was a bug in <= 1.9.0 where54 // (mixxx_deleted=0) from the view. There was a bug in <= 1.9.0 where
41 // removed files were not removed from playlists, so some users will have55 // removed files were not removed from crates, so some users will have
42 // libraries where this is the case.56 // libraries where this is the case.
43 QString queryString = QString(57 QString queryString = QString(
44 "CREATE TEMPORARY VIEW IF NOT EXISTS %1 AS "58 "CREATE TEMPORARY VIEW IF NOT EXISTS %1 AS "
45 "SELECT %2 FROM %3 "59 "SELECT %2 FROM %3 "
46 "INNER JOIN library ON library.id = %3.%4 "60 "INNER JOIN library ON library.id = %3.%4 "
47 "WHERE %3.%5 = %6 AND library.mixxx_deleted = 0")61 "INNER JOIN track_locations ON track_locations.id=crate_tracks.track_id "
62 "WHERE %3.%5 = %6 AND %7")
48 .arg(escaper.escapeString(tableName),63 .arg(escaper.escapeString(tableName),
49 columns.join(","),64 columns.join(","),
50 CRATE_TRACKS_TABLE,65 CRATE_TRACKS_TABLE,
51 CRATETRACKSTABLE_TRACKID,66 CRATETRACKSTABLE_TRACKID,
52 CRATETRACKSTABLE_CRATEID,67 CRATETRACKSTABLE_CRATEID,
53 QString::number(crateId));68 QString::number(crateId),
69 filter);
54 query.prepare(queryString);70 query.prepare(queryString);
55 if (!query.exec()) {71 if (!query.exec()) {
56 LOG_FAILED_QUERY(query);72 LOG_FAILED_QUERY(query);
@@ -103,10 +119,9 @@
103 fileInfoList.append(QFileInfo(fileLocation));119 fileInfoList.append(QFileInfo(fileLocation));
104 }120 }
105121
106 TrackDAO& trackDao = m_pTrackCollection->getTrackDAO();122 QList<int> trackIDs = m_trackDAO.addTracks(fileInfoList, true);
107 QList<int> trackIDs = trackDao.addTracks(fileInfoList, true);
108123
109 int tracksAdded = m_pTrackCollection->getCrateDAO().addTracksToCrate(124 int tracksAdded = m_crateDAO.addTracksToCrate(
110 trackIDs, m_iCrateId);125 trackIDs, m_iCrateId);
111 if (tracksAdded > 0) {126 if (tracksAdded > 0) {
112 select();127 select();
@@ -120,58 +135,19 @@
120 return tracksAdded;135 return tracksAdded;
121}136}
122137
123TrackPointer CrateTableModel::getTrack(const QModelIndex& index) const {
124 int trackId = getTrackId(index);
125 return m_pTrackCollection->getTrackDAO().getTrack(trackId);
126}
127
128void CrateTableModel::removeTracks(const QModelIndexList& indices) {138void CrateTableModel::removeTracks(const QModelIndexList& indices) {
129 CrateDAO& crateDao = m_pTrackCollection->getCrateDAO();139 bool locked = m_crateDAO.isCrateLocked(m_iCrateId);
130 bool locked = crateDao.isCrateLocked(m_iCrateId);
131140
132 if (!locked) {141 if (!locked) {
133 QList<int> trackIds;142 QList<int> trackIds;
134 foreach (QModelIndex index, indices) {143 foreach (QModelIndex index, indices) {
135 trackIds.append(getTrackId(index));144 trackIds.append(getTrackId(index));
136 }145 }
137 crateDao.removeTracksFromCrate(trackIds, m_iCrateId);146 m_crateDAO.removeTracksFromCrate(trackIds, m_iCrateId);
138 select();147 select();
139 }148 }
140}149}
141150
142void CrateTableModel::removeTrack(const QModelIndex& index) {
143 CrateDAO& crateDao = m_pTrackCollection->getCrateDAO();
144 bool locked = crateDao.isCrateLocked(m_iCrateId);
145
146 if (!locked) {
147 int trackId = getTrackId(index);
148 if (m_pTrackCollection->getCrateDAO().
149 removeTrackFromCrate(trackId, m_iCrateId)) {
150 select();
151 } else {
152 // TODO(XXX) feedback
153 }
154 }
155}
156
157void CrateTableModel::moveTrack(const QModelIndex& sourceIndex,
158 const QModelIndex& destIndex) {
159 Q_UNUSED(sourceIndex);
160 Q_UNUSED(destIndex);
161 return;
162}
163
164void CrateTableModel::search(const QString& searchText) {
165 // qDebug() << "CrateTableModel::search()" << searchText
166 // << QThread::currentThread();
167 emit(doSearch(searchText));
168}
169
170void CrateTableModel::slotSearch(const QString& searchText) {
171 BaseSqlTableModel::search(
172 searchText, LibraryTableModel::DEFAULT_LIBRARYFILTER);
173}
174
175bool CrateTableModel::isColumnInternal(int column) {151bool CrateTableModel::isColumnInternal(int column) {
176 if (column == fieldIndex(LIBRARYTABLE_ID) ||152 if (column == fieldIndex(LIBRARYTABLE_ID) ||
177 column == fieldIndex(CRATETRACKSTABLE_TRACKID) ||153 column == fieldIndex(CRATETRACKSTABLE_TRACKID) ||
@@ -179,6 +155,7 @@
179 column == fieldIndex(LIBRARYTABLE_MIXXXDELETED) ||155 column == fieldIndex(LIBRARYTABLE_MIXXXDELETED) ||
180 column == fieldIndex(LIBRARYTABLE_BPM_LOCK) ||156 column == fieldIndex(LIBRARYTABLE_BPM_LOCK) ||
181 column == fieldIndex(TRACKLOCATIONSTABLE_FSDELETED) ||157 column == fieldIndex(TRACKLOCATIONSTABLE_FSDELETED) ||
158 column == fieldIndex(TRACKLOCATIONSTABLE_MAINDIRID) ||
182 (PlayerManager::numPreviewDecks() == 0 && column == fieldIndex("preview"))) {159 (PlayerManager::numPreviewDecks() == 0 && column == fieldIndex("preview"))) {
183 return true;160 return true;
184 }161 }
@@ -202,12 +179,12 @@
202 | TRACKMODELCAPS_LOADTOSAMPLER179 | TRACKMODELCAPS_LOADTOSAMPLER
203 | TRACKMODELCAPS_LOADTOPREVIEWDECK180 | TRACKMODELCAPS_LOADTOPREVIEWDECK
204 | TRACKMODELCAPS_REMOVE181 | TRACKMODELCAPS_REMOVE
182 | TRACKMODELCAPS_RELOCATE
205 | TRACKMODELCAPS_BPMLOCK183 | TRACKMODELCAPS_BPMLOCK
206 | TRACKMODELCAPS_CLEAR_BEATS184 | TRACKMODELCAPS_CLEAR_BEATS
207 | TRACKMODELCAPS_RESETPLAYED;185 | TRACKMODELCAPS_RESETPLAYED;
208186
209 CrateDAO& crateDao = m_pTrackCollection->getCrateDAO();187 bool locked = m_crateDAO.isCrateLocked(m_iCrateId);
210 bool locked = crateDao.isCrateLocked(m_iCrateId);
211188
212 if (locked) {189 if (locked) {
213 caps |= TRACKMODELCAPS_LOCKED;190 caps |= TRACKMODELCAPS_LOCKED;
@@ -215,3 +192,10 @@
215192
216 return caps;193 return caps;
217}194}
195
196void CrateTableModel::moveTrack(const QModelIndex& sourceIndex,
197 const QModelIndex& destIndex) {
198 Q_UNUSED(sourceIndex);
199 Q_UNUSED(destIndex);
200 return;
201}
218202
=== modified file 'mixxx/src/library/cratetablemodel.h'
--- mixxx/src/library/cratetablemodel.h 2013-04-22 19:29:54 +0000
+++ mixxx/src/library/cratetablemodel.h 2013-05-18 16:32:26 +0000
@@ -4,48 +4,35 @@
4#ifndef CRATETABLEMODEL_H4#ifndef CRATETABLEMODEL_H
5#define CRATETABLEMODEL_H5#define CRATETABLEMODEL_H
66
7#include <QItemDelegate>
8#include <QSqlTableModel>
9
10#include "library/basesqltablemodel.h"7#include "library/basesqltablemodel.h"
118#include "library/dao/cratedao.h"
12class TrackCollection;
139
14class CrateTableModel : public BaseSqlTableModel {10class CrateTableModel : public BaseSqlTableModel {
15 Q_OBJECT11 Q_OBJECT
16 public:12 public:
17 CrateTableModel(QObject* parent, TrackCollection* pTrackCollection);13 CrateTableModel(QObject* parent, TrackCollection* pTrackCollection,
14 ConfigObject<ConfigValue>* pConfig);
18 virtual ~CrateTableModel();15 virtual ~CrateTableModel();
1916
20 void setCrate(int crateId);17 void setTableModel(int crateId=-1);
21 int getCrate() const {18 int getCrate() const {
22 return m_iCrateId;19 return m_iCrateId;
23 }20 }
2421
25 // From TrackModel22 // From TrackModel
26 TrackPointer getTrack(const QModelIndex& index) const;
27 void search(const QString& searchText);
28 bool isColumnInternal(int column);23 bool isColumnInternal(int column);
29 bool isColumnHiddenByDefault(int column);24 bool isColumnHiddenByDefault(int column);
30 void removeTrack(const QModelIndex& index);
31 void removeTracks(const QModelIndexList& indices);25 void removeTracks(const QModelIndexList& indices);
32 bool addTrack(const QModelIndex& index, QString location);26 bool addTrack(const QModelIndex &index, QString location);
33 // Returns the number of unsuccessful track additions27 // Returns the number of unsuccessful track additions
34 int addTracks(const QModelIndex& index,28 int addTracks(const QModelIndex& index,const QList <QString> &locations);
35 const QList <QString> &locations);
36 void moveTrack(const QModelIndex& sourceIndex,29 void moveTrack(const QModelIndex& sourceIndex,
37 const QModelIndex& destIndex);30 const QModelIndex& destIndex);
38 TrackModel::CapabilitiesFlags getCapabilities() const;31 TrackModel::CapabilitiesFlags getCapabilities() const;
3932
40 private slots:
41 void slotSearch(const QString& searchText);
42
43 signals:
44 void doSearch(const QString& searchText);
45
46 private:33 private:
47 TrackCollection* m_pTrackCollection;
48 int m_iCrateId;34 int m_iCrateId;
35 CrateDAO& m_crateDAO;
49};36};
5037
51#endif /* CRATETABLEMODEL_H */38#endif /* CRATETABLEMODEL_H */
5239
=== added file 'mixxx/src/library/dao/directorydao.cpp'
--- mixxx/src/library/dao/directorydao.cpp 1970-01-01 00:00:00 +0000
+++ mixxx/src/library/dao/directorydao.cpp 2013-05-18 16:32:26 +0000
@@ -0,0 +1,143 @@
1#include <QtSql>
2#include <QtDebug>
3#include <QStringBuilder>
4
5#include "directorydao.h"
6#include "library/queryutil.h"
7
8DirectoryDAO::DirectoryDAO(QSqlDatabase& database)
9 : m_database(database) {
10}
11
12DirectoryDAO::DirectoryDAO(const DirectoryDAO& directoryDao)
13 : m_database(directoryDao.m_database){
14}
15
16DirectoryDAO::~DirectoryDAO(){
17}
18
19void DirectoryDAO::initialize()
20{
21 qDebug() << "DirectoryDAO::initialize" << QThread::currentThread()
22 << m_database.connectionName();
23}
24
25bool DirectoryDAO::addDirectory(QString dir){
26 ScopedTransaction transaction(m_database);
27 QSqlQuery query(m_database);
28 query.prepare("INSERT OR REPLACE INTO directories (directory) "
29 "VALUES (\""% dir %"\")");
30
31 if (!query.exec()) {
32 qDebug() << "Adding new dir ("% dir %") failed:"
33 <<query.lastError();
34 return false;
35 }
36 transaction.commit();
37 return true;
38}
39
40bool DirectoryDAO::purgeDirectory(QString dir){
41 QSqlQuery query(m_database);
42 query.prepare("DELETE FROM directories WHERE directory=\"" % dir % "\"");
43
44 if (!query.exec()) {
45 qDebug() << "purging dir ("%dir%") failed:"<<query.lastError();
46 return false;
47 }
48 return true;
49}
50
51bool DirectoryDAO::relocateDirectory(QString oldFolder, QString newFolder){
52 ScopedTransaction transaction(m_database);
53 QSqlQuery query(m_database);
54
55 // update directory in directories table
56 query.prepare("UPDATE "%DIRECTORYDAO_TABLE%" SET "%DIRECTORYDAO_DIR%"="
57 "\":newFolder\" WHERE "%DIRECTORYDAO_DIR%"=\":oldFolder\"");
58 query.bindValue(":newFolder", newFolder);
59 query.bindValue(":oldFolder", oldFolder);
60 if (!query.exec()) {
61 LOG_FAILED_QUERY(query) << "coud not relocate directory";
62 return false;
63 }
64
65 // update location and directory in track_locations table
66 query.prepare("UPDATE track_locations SET location="
67 "REPLACE(location,\":oldFolder\",\":newFolder\")"
68 ", directory="
69 "REPLACE(directory,\":oldFolder\",\":newFolder\") "
70 "WHERE "%DIRECTORYDAO_DIR%"=\":oldFolder\"");
71 query.bindValue(":newFolder", newFolder);
72 query.bindValue(":oldFolder", oldFolder);
73 if (!query.exec()) {
74 LOG_FAILED_QUERY(query) << "coud not relocate path of tracks";
75 return false;
76 }
77
78 // updating the dir_id column is not necessary because it does not change
79
80 transaction.commit();
81 return true;
82}
83
84QStringList DirectoryDAO::getDirs(){
85 QSqlQuery query(m_database);
86 query.prepare("SELECT " % DIRECTORYDAO_DIR % " FROM " % DIRECTORYDAO_TABLE);
87 if (!query.exec()) {
88 LOG_FAILED_QUERY(query) << "There are no directories saved in the db";
89 }
90 QStringList dirs;
91 while (query.next()) {
92 dirs << query.value(query.record().indexOf(DIRECTORYDAO_DIR)).toString();
93 }
94 return dirs;
95}
96
97QList<int> DirectoryDAO::getDirIds(QStringList& dirs){
98 QSqlQuery query(m_database);
99 query.prepare("SELECT " % DIRECTORYDAO_ID % " FROM " % DIRECTORYDAO_TABLE %
100 " WHERE " % DIRECTORYDAO_DIR %" in (\":dirs\")");
101 query.bindValue(":dirs", dirs.join("\",\"") );
102 if (!query.exec()) {
103 LOG_FAILED_QUERY(query) << "couldn't find directory:"<<dirs;
104 }
105 QList<int> ids;
106 while (query.next()) {
107 ids.append(query.value(query.record().indexOf(DIRECTORYDAO_ID)).toInt());
108 }
109
110 return ids;
111}
112
113//TODO(kain88) check if this is not obsolete because of getDirIds
114int DirectoryDAO::getDirId(const QString dir){
115 QSqlQuery query(m_database);
116 query.prepare("SELECT " % DIRECTORYDAO_ID % " FROM " % DIRECTORYDAO_TABLE %
117 " WHERE " % DIRECTORYDAO_DIR %" in (\":dir\")");
118 query.bindValue(":dir",dir);
119 if (!query.exec()) {
120 LOG_FAILED_QUERY(query) << "couldn't find directory:"<<dir;
121 }
122 int id=0;
123 while (query.next()) {
124 id = query.value(query.record().indexOf(DIRECTORYDAO_ID)).toInt();
125 }
126 return id;
127}
128
129// Only call this when an update happens from an old library version!!!
130// TODO move this into update code
131bool DirectoryDAO::updateTrackLocations(QString dir){
132 QString dirId = QString::number(getDirId(dir));
133 ScopedTransaction transaction(m_database);
134 QSqlQuery query(m_database);
135 query.prepare("UPDATE track_locations SET maindir_id = :dirId");
136 query.bindValue(":dirId", dirId);
137 if (!query.exec()) {
138 LOG_FAILED_QUERY(query) << " could not update TrackLocations";
139 return false;
140 }
141 transaction.commit();
142 return true;
143}
0144
=== added file 'mixxx/src/library/dao/directorydao.h'
--- mixxx/src/library/dao/directorydao.h 1970-01-01 00:00:00 +0000
+++ mixxx/src/library/dao/directorydao.h 2013-05-18 16:32:26 +0000
@@ -0,0 +1,31 @@
1#ifndef DIRECTORYDAO_H
2#define DIRECTORYDAO_H
3
4#include <QSqlDatabase>
5#include "library/dao/dao.h"
6
7const QString DIRECTORYDAO_DIR = "directory";
8const QString DIRECTORYDAO_ID = "dir_id";
9const QString DIRECTORYDAO_TABLE = "directories";
10
11class DirectoryDAO : public DAO {
12 public:
13 // normal method
14 DirectoryDAO(QSqlDatabase& database);
15 DirectoryDAO(const DirectoryDAO& directoryDao);
16 virtual ~DirectoryDAO();
17
18 void initialize();
19 bool addDirectory(QString dir);
20 bool purgeDirectory(QString dir);
21 bool relocateDirectory(QString oldFolder,QString newFolder);
22 bool updateTrackLocations(QString dir);
23 QList<int> getDirIds(QStringList& dirs);
24 int getDirId(const QString dir);
25 QStringList getDirs();
26
27 private:
28 QSqlDatabase m_database;
29};
30
31#endif //DIRECTORYDAO_H
032
=== modified file 'mixxx/src/library/dao/trackdao.cpp'
--- mixxx/src/library/dao/trackdao.cpp 2013-05-03 23:33:12 +0000
+++ mixxx/src/library/dao/trackdao.cpp 2013-05-18 16:32:26 +0000
@@ -1,6 +1,7 @@
1#include <QtDebug>1#include <QtDebug>
2#include <QtCore>2#include <QtCore>
3#include <QtSql>3#include <QtSql>
4#include <QMessageBox>
45
5#include "library/dao/trackdao.h"6#include "library/dao/trackdao.h"
67
@@ -14,6 +15,7 @@
14#include "library/dao/cuedao.h"15#include "library/dao/cuedao.h"
15#include "library/dao/playlistdao.h"16#include "library/dao/playlistdao.h"
16#include "library/dao/analysisdao.h"17#include "library/dao/analysisdao.h"
18#include "library/dao/directorydao.h"
1719
18QHash<int, TrackWeakPointer> TrackDAO::m_sTracks;20QHash<int, TrackWeakPointer> TrackDAO::m_sTracks;
19QMutex TrackDAO::m_sTracksMutex;21QMutex TrackDAO::m_sTracksMutex;
@@ -30,12 +32,14 @@
30 PlaylistDAO& playlistDao,32 PlaylistDAO& playlistDao,
31 CrateDAO& crateDao,33 CrateDAO& crateDao,
32 AnalysisDao& analysisDao,34 AnalysisDao& analysisDao,
35 DirectoryDAO& directoryDao,
33 ConfigObject<ConfigValue> * pConfig)36 ConfigObject<ConfigValue> * pConfig)
34 : m_database(database),37 : m_database(database),
35 m_cueDao(cueDao),38 m_cueDao(cueDao),
36 m_playlistDao(playlistDao),39 m_playlistDao(playlistDao),
37 m_crateDao(crateDao),40 m_crateDao(crateDao),
38 m_analysisDao(analysisDao),41 m_analysisDao(analysisDao),
42 m_directoryDAO(directoryDao),
39 m_pConfig(pConfig),43 m_pConfig(pConfig),
40 m_trackCache(TRACK_CACHE_SIZE),44 m_trackCache(TRACK_CACHE_SIZE),
41 m_pQueryTrackLocationInsert(NULL),45 m_pQueryTrackLocationInsert(NULL),
@@ -268,7 +272,8 @@
268272
269// No need to check here if the querys exist, this is already done in273// No need to check here if the querys exist, this is already done in
270// addTracksAdd, which is the only function that calls this274// addTracksAdd, which is the only function that calls this
271void TrackDAO::bindTrackToTrackLocationsInsert(TrackInfoObject* pTrack) {275void TrackDAO::bindTrackToTrackLocationsInsert(TrackInfoObject* pTrack, int dirId,
276 QString& checksum) {
272 // gets called only in addTracksAdd277 // gets called only in addTracksAdd
273 m_pQueryTrackLocationInsert->bindValue(":location", pTrack->getLocation());278 m_pQueryTrackLocationInsert->bindValue(":location", pTrack->getLocation());
274 m_pQueryTrackLocationInsert->bindValue(":directory", pTrack->getDirectory());279 m_pQueryTrackLocationInsert->bindValue(":directory", pTrack->getDirectory());
@@ -277,6 +282,8 @@
277 // Should this check pTrack->exists()?282 // Should this check pTrack->exists()?
278 m_pQueryTrackLocationInsert->bindValue(":fs_deleted", 0);283 m_pQueryTrackLocationInsert->bindValue(":fs_deleted", 0);
279 m_pQueryTrackLocationInsert->bindValue(":needs_verification", 0);284 m_pQueryTrackLocationInsert->bindValue(":needs_verification", 0);
285 m_pQueryTrackLocationInsert->bindValue(":maindir_id", dirId);
286 m_pQueryTrackLocationInsert->bindValue(":checksum", checksum);
280}287}
281288
282// No need to check here if the querys exist, this is already done in289// No need to check here if the querys exist, this is already done in
@@ -335,7 +342,6 @@
335}342}
336343
337void TrackDAO::addTracksPrepare() {344void TrackDAO::addTracksPrepare() {
338
339 if (m_pQueryLibraryInsert || m_pQueryTrackLocationInsert ||345 if (m_pQueryLibraryInsert || m_pQueryTrackLocationInsert ||
340 m_pQueryLibrarySelect || m_pQueryTrackLocationSelect ||346 m_pQueryLibrarySelect || m_pQueryTrackLocationSelect ||
341 m_pTransaction) {347 m_pTransaction) {
@@ -353,9 +359,8 @@
353 m_pQueryLibrarySelect = new QSqlQuery(m_database);359 m_pQueryLibrarySelect = new QSqlQuery(m_database);
354360
355 m_pQueryTrackLocationInsert->prepare("INSERT INTO track_locations "361 m_pQueryTrackLocationInsert->prepare("INSERT INTO track_locations "
356 "(location, directory, filename, filesize, fs_deleted, needs_verification) "362 "(location, directory, filename, filesize, fs_deleted, needs_verification, maindir_id, checksum) "
357 "VALUES (:location, :directory, :filename, :filesize, :fs_deleted, :needs_verification)"363 "VALUES (:location, :directory, :filename, :filesize, :fs_deleted, :needs_verification, :maindir_id, :checksum)");
358 );
359364
360 m_pQueryTrackLocationSelect->prepare("SELECT id FROM track_locations WHERE location=:location");365 m_pQueryTrackLocationSelect->prepare("SELECT id FROM track_locations WHERE location=:location");
361366
@@ -398,7 +403,8 @@
398 m_tracksAddedSet.clear();403 m_tracksAddedSet.clear();
399}404}
400405
401bool TrackDAO::addTracksAdd(TrackInfoObject* pTrack, bool unremove) {406bool TrackDAO::addTracksAdd(TrackInfoObject* pTrack, bool unremove,const int dirId) {
407
402408
403 if (!m_pQueryLibraryInsert || !m_pQueryTrackLocationInsert ||409 if (!m_pQueryLibraryInsert || !m_pQueryTrackLocationInsert ||
404 !m_pQueryLibrarySelect || !m_pQueryTrackLocationSelect) {410 !m_pQueryLibrarySelect || !m_pQueryTrackLocationSelect) {
@@ -409,11 +415,12 @@
409415
410 int trackLocationId = -1;416 int trackLocationId = -1;
411 int trackId = -1;417 int trackId = -1;
418 QString checksum = calcChecksum(*pTrack);
412419
413 // Insert the track location into the corresponding table. This will fail420 // Insert the track location into the corresponding table. This will fail
414 // silently if the location is already in the table because it has a UNIQUE421 // silently if the location is already in the table because it has a UNIQUE
415 // constraint.422 // constraint.
416 bindTrackToTrackLocationsInsert(pTrack);423 bindTrackToTrackLocationsInsert(pTrack,dirId,checksum);
417424
418 if (!m_pQueryTrackLocationInsert->exec()) {425 if (!m_pQueryTrackLocationInsert->exec()) {
419 qDebug() << "Location " << pTrack->getLocation() << " is already in the DB";426 qDebug() << "Location " << pTrack->getLocation() << " is already in the DB";
@@ -522,7 +529,7 @@
522 }529 }
523530
524 addTracksPrepare();531 addTracksPrepare();
525 addTracksAdd(pTrack, unremove);532 addTracksAdd(pTrack, unremove, 0);
526 addTracksFinish();533 addTracksFinish();
527}534}
528535
@@ -530,6 +537,8 @@
530 bool unremove) {537 bool unremove) {
531 QSqlQuery query(m_database);538 QSqlQuery query(m_database);
532 QList<int> trackIDs;539 QList<int> trackIDs;
540 TrackInfoObject* pTrack;
541
533542
534 // Create a temporary database of the paths of all the imported tracks.543 // Create a temporary database of the paths of all the imported tracks.
535 query.prepare("CREATE TEMP TABLE playlist_import "544 query.prepare("CREATE TEMP TABLE playlist_import "
@@ -589,7 +598,8 @@
589 while (query.next()) {598 while (query.next()) {
590 QString filePath = query.value(query.record().indexOf("location")).toString();599 QString filePath = query.value(query.record().indexOf("location")).toString();
591 TrackInfoObject* pTrack = new TrackInfoObject(QFileInfo(filePath));600 TrackInfoObject* pTrack = new TrackInfoObject(QFileInfo(filePath));
592 addTracksAdd(pTrack, unremove);601 //TODO kain88 fix dirID
602 addTracksAdd(pTrack, unremove,0);
593 int trackID = pTrack->getId();603 int trackID = pTrack->getId();
594 if (trackID >= 0) {604 if (trackID >= 0) {
595 trackIDs.append(trackID);605 trackIDs.append(trackID);
@@ -625,6 +635,7 @@
625635
626 // This signal is received by basetrackcache to remove the tracks from cache636 // This signal is received by basetrackcache to remove the tracks from cache
627 QSet<int> tracksRemovedSet = QSet<int>::fromList(ids);637 QSet<int> tracksRemovedSet = QSet<int>::fromList(ids);
638 uncacheTracks(tracksRemovedSet);
628 emit(tracksRemoved(tracksRemovedSet));639 emit(tracksRemoved(tracksRemovedSet));
629}640}
630641
@@ -647,6 +658,7 @@
647 LOG_FAILED_QUERY(query);658 LOG_FAILED_QUERY(query);
648 }659 }
649 QSet<int> tracksAddedSet = QSet<int>::fromList(ids);660 QSet<int> tracksAddedSet = QSet<int>::fromList(ids);
661 uncacheTracks(tracksAddedSet);
650 emit(tracksAdded(tracksAddedSet));662 emit(tracksAdded(tracksAddedSet));
651}663}
652664
@@ -675,18 +687,17 @@
675687
676 FieldEscaper escaper(m_database);688 FieldEscaper escaper(m_database);
677 QStringList locationList;689 QStringList locationList;
678 QSet<QString> dirs;690 QStringList dirs;
679 while (query.next()) {691 while (query.next()) {
680 QString filePath = query.value(query.record().indexOf("location")).toString();692 QString filePath = query.value(query.record().indexOf("location")).toString();
681 locationList << escaper.escapeString(filePath);693 locationList << escaper.escapeString(filePath);
682 QString directory = query.value(query.record().indexOf("directory")).toString();694 QString directory = query.value(query.record().indexOf("directory")).toString();
683 dirs.insert(directory);695 dirs << directory;
684 }696 }
685697
686 QStringList dirList;698 QStringList dirList;
687 for (QSet<QString>::const_iterator it = dirs.constBegin();699 foreach(QString dir, dirs) {
688 it != dirs.constEnd(); ++it) {700 dirList << escaper.escapeString(dir);
689 dirList << escaper.escapeString(*it);
690 }701 }
691702
692 if (locationList.empty()) {703 if (locationList.empty()) {
@@ -724,16 +735,68 @@
724 transaction.commit();735 transaction.commit();
725736
726 // also need to clean playlists, crates, cues and track_analyses737 // also need to clean playlists, crates, cues and track_analyses
727
728 m_cueDao.deleteCuesForTracks(ids);738 m_cueDao.deleteCuesForTracks(ids);
729 m_playlistDao.removeTracksFromPlaylists(ids);739 m_playlistDao.removeTracksFromPlaylists(ids);
730 m_crateDao.removeTracksFromCrates(ids);740 m_crateDao.removeTracksFromCrates(ids);
731 m_analysisDao.deleteAnalysises(ids);741 m_analysisDao.deleteAnalysises(ids);
732742
733 QSet<int> tracksRemovedSet = QSet<int>::fromList(ids);743 QSet<int> tracksRemovedSet = QSet<int>::fromList(ids);
744 uncacheTracks(tracksRemovedSet);
734 emit(tracksRemoved(tracksRemovedSet));745 emit(tracksRemoved(tracksRemovedSet));
735}746}
736747
748//TODO(kain88) check if this works as desired
749QStringList TrackDAO::deleteTracksFromFS(QList<int> ids){
750 if (ids.empty()) {
751 return QStringList();
752 }
753
754 QStringList idList;
755 foreach (int id, ids) {
756 idList << QString::number(id);
757 }
758
759 QSqlQuery query(m_database);
760 query.prepare("SELECT track_locations.location, track_locations.directory FROM "
761 "track_locations INNER JOIN library ON library.location = "
762 "track_locations.id WHERE library.id in (:idList)");
763 query.bindValue("idList", idList.join(","));
764 if (!query.exec()) {
765 LOG_FAILED_QUERY(query);
766 }
767
768 FieldEscaper escaper(m_database);
769 QStringList locationList;
770 while (query.next()) {
771 locationList << escaper.escapeString(query.value(
772 query.record().indexOf("location")).toString());
773 }
774
775 QStringList failed;
776 foreach (QString loc, locationList) {
777 if (!QFile::remove(loc)) {
778 failed.append(loc);
779 }
780 }
781
782 query.prepare("SELECT libary.id FROM library INNER JOIN track_locations ON "
783 "library.location = track_locations.id WHERE "
784 "track_locations.location in (:locList)");
785 query.bindValue(":locList", failed.join(","));
786
787 if (!query.exec()) {
788 LOG_FAILED_QUERY(query);
789 }
790
791 while (query.next()) {
792 ids.removeAll(query.value(query.record().indexOf("if")).toInt());
793 }
794 // clean all DB entries AFTER the file is removed, otherwise the remove
795 // function fails.
796 purgeTracks(ids);
797 return failed;
798}
799
737// deleter of the TrackInfoObject, for delete a Track from Library use hide or purge800// deleter of the TrackInfoObject, for delete a Track from Library use hide or purge
738// static801// static
739void TrackDAO::deleteTrack(TrackInfoObject* pTrack) {802void TrackDAO::deleteTrack(TrackInfoObject* pTrack) {
@@ -764,7 +827,8 @@
764 "filetype, rating, key, track_locations.location as location, "827 "filetype, rating, key, track_locations.location as location, "
765 "track_locations.filesize as filesize, comment, url, duration, bitrate, "828 "track_locations.filesize as filesize, comment, url, duration, bitrate, "
766 "samplerate, cuepoint, bpm, replaygain, channels, "829 "samplerate, cuepoint, bpm, replaygain, channels, "
767 "header_parsed, timesplayed, played, beats_version, beats_sub_version, beats, datetime_added, bpm_lock "830 "header_parsed, timesplayed, played, beats_version, beats_sub_version, beats, "
831 "datetime_added, bpm_lock "
768 "FROM Library "832 "FROM Library "
769 "INNER JOIN track_locations "833 "INNER JOIN track_locations "
770 "ON library.location = track_locations.id "834 "ON library.location = track_locations.id "
@@ -1035,19 +1099,16 @@
1035// Mark all the tracks whose paths begin with libraryPath as invalid.1099// Mark all the tracks whose paths begin with libraryPath as invalid.
1036// That means we'll need to later check that those tracks actually1100// That means we'll need to later check that those tracks actually
1037// (still) exist as part of the library scanning procedure.1101// (still) exist as part of the library scanning procedure.
1038void TrackDAO::invalidateTrackLocationsInLibrary(QString libraryPath) {1102void TrackDAO::invalidateTrackLocationsInLibrary() {
1039 //qDebug() << "TrackDAO::invalidateTrackLocations" << QThread::currentThread() << m_database.connectionName();1103 //qDebug() << "TrackDAO::invalidateTrackLocations" << QThread::currentThread() << m_database.connectionName();
1040 //qDebug() << "invalidateTrackLocations(" << libraryPath << ")";1104 //qDebug() << "invalidateTrackLocations(" << libraryPath << ")";
1041 libraryPath += "%"; //Add wildcard to SQL query to match subdirectories!
10421105
1043 QSqlQuery query(m_database);1106 QSqlQuery query(m_database);
1044 query.prepare("UPDATE track_locations "1107 query.prepare("UPDATE track_locations "
1045 "SET needs_verification=1 "1108 "SET needs_verification=1");
1046 "WHERE directory LIKE :directory");
1047 query.bindValue(":directory", libraryPath);
1048 if (!query.exec()) {1109 if (!query.exec()) {
1049 LOG_FAILED_QUERY(query)1110 LOG_FAILED_QUERY(query)
1050 << "Couldn't mark tracks in directory" << libraryPath1111 << "Couldn't mark tracks in directory "
1051 << "as needing verification.";1112 << "as needing verification.";
1052 }1113 }
1053}1114}
@@ -1087,13 +1148,24 @@
1087 LOG_FAILED_QUERY(query)1148 LOG_FAILED_QUERY(query)
1088 << "Couldn't mark tracks in" << directories.size() << "directories as verified.";1149 << "Couldn't mark tracks in" << directories.size() << "directories as verified.";
1089 }1150 }
1151 // qDebug() << directories;
1090}1152}
10911153
1092void TrackDAO::markUnverifiedTracksAsDeleted() {1154void TrackDAO::markUnverifiedTracksAsDeleted() {
1093 //qDebug() << "TrackDAO::markUnverifiedTracksAsDeleted" << QThread::currentThread() << m_database.connectionName();1155 //qDebug() << "TrackDAO::markUnverifiedTracksAsDeleted" << QThread::currentThread() << m_database.connectionName();
1094 //qDebug() << "markUnverifiedTracksAsDeleted()";1156 qDebug() << "markUnverifiedTracksAsDeleted()";
10951157
1096 QSqlQuery query(m_database);1158 QSqlQuery query(m_database);
1159 query.prepare("SELECT id FROM track_locations WHERE needs_verification=1");
1160 QSet<int> trackIds;
1161 if (!query.exec()) {
1162 LOG_FAILED_QUERY(query)
1163 << "Couldn't find unverified tracks";
1164 }
1165 while (query.next()){
1166 trackIds.insert(query.value(query.record().indexOf("id")).toInt());
1167 }
1168 emit(tracksRemoved(trackIds));
1097 query.prepare("UPDATE track_locations "1169 query.prepare("UPDATE track_locations "
1098 "SET fs_deleted=1, needs_verification=0 "1170 "SET fs_deleted=1, needs_verification=0 "
1099 "WHERE needs_verification=1");1171 "WHERE needs_verification=1");
@@ -1121,55 +1193,54 @@
1121// and see if another "file" with the same name and filesize exists in the track_locations1193// and see if another "file" with the same name and filesize exists in the track_locations
1122// table. That means the file has moved instead of being deleted outright, and so1194// table. That means the file has moved instead of being deleted outright, and so
1123// we can salvage your existing metadata that you have in your DB (like cue points, etc.).1195// we can salvage your existing metadata that you have in your DB (like cue points, etc.).
1124void TrackDAO::detectMovedFiles(QSet<int>* pTracksMovedSetOld, QSet<int>* pTracksMovedSetNew) {1196void TrackDAO::detectMovedFiles(QSet<int>& tracksMovedSetOld, QSet<int>& tracksMovedSetNew) {
1125 //This function should not start a transaction on it's own!1197 //This function should not start a transaction on it's own!
1126 //When it's called from libraryscanner.cpp, there already is a transaction1198 //When it's called from libraryscanner.cpp, there already is a transaction
1127 //started!1199 //started!
1128
1129 QSqlQuery query(m_database);1200 QSqlQuery query(m_database);
1130 QSqlQuery query2(m_database);1201 QSqlQuery query2(m_database);
1131 QSqlQuery query3(m_database);1202 QSqlQuery query3(m_database);
1132 int oldTrackLocationId = -1;1203 int oldTrackLocationId = -1;
1133 int newTrackLocationId = -1;1204 int newTrackLocationId = -1;
1134 QString filename;1205 QString checksum;
1135 int fileSize;1206 int duration = -1;
1207 int fileSize = -1;
11361208
1137 query.prepare("SELECT id, filename, filesize FROM track_locations WHERE fs_deleted=1");1209 query.prepare("SELECT track_locations.id, checksum, filesize, duration FROM track_locations "
1210 "INNER JOIN library ON track_locations.id=library.location "
1211 "WHERE fs_deleted=1");
11381212
1139 if (!query.exec()) {1213 if (!query.exec()) {
1140 LOG_FAILED_QUERY(query);1214 LOG_FAILED_QUERY(query);
1141 }1215 }
11421216
1143 query2.prepare("SELECT id FROM track_locations WHERE "1217 query2.prepare("SELECT track_locations.id FROM track_locations "
1144 "fs_deleted=0 AND "1218 "INNER JOIN library ON track_locations.id=library.location "
1145 "filename=:filename AND "1219 "WHERE fs_deleted=0 AND "
1146 "filesize=:filesize");1220 "checksum=:checksum AND "
1221 "filesize=:filesize AND "
1222 "duration=:duration");
11471223
1148 //For each track that's been "deleted" on disk...1224 //For each track that's been "deleted" on disk...
1149 while (query.next()) {1225 while (query.next()) {
1150 newTrackLocationId = -1; //Reset this var1226 newTrackLocationId = -1; //Reset this var
1151 oldTrackLocationId = query.value(query.record().indexOf("id")).toInt();1227 oldTrackLocationId = query.value(query.record().indexOf("id")).toInt();
1152 filename = query.value(query.record().indexOf("filename")).toString();1228 checksum = query.value(query.record().indexOf("checksum")).toString();
1153 fileSize = query.value(query.record().indexOf("filesize")).toInt();1229 fileSize = query.value(query.record().indexOf("filesize")).toInt();
1230 duration = query.value(query.record().indexOf("duration")).toInt();
11541231
1155 query2.bindValue(":filename", filename);1232 query2.bindValue(":checksum", checksum);
1156 query2.bindValue(":filesize", fileSize);1233 query2.bindValue(":filesize", fileSize);
1234 query2.bindValue(":duration", duration);
1157 Q_ASSERT(query2.exec());1235 Q_ASSERT(query2.exec());
11581236
1159 Q_ASSERT(query2.size() <= 1); //WTF duplicate tracks?1237 Q_ASSERT(query2.size() <= 1); //WTF duplicate tracks?
1160 while (query2.next())1238 while (query2.next()) {
1161 {
1162 newTrackLocationId = query2.value(query2.record().indexOf("id")).toInt();1239 newTrackLocationId = query2.value(query2.record().indexOf("id")).toInt();
1163 }1240 qDebug() << "Found moved track!" << checksum;
1164
1165 //If we found a moved track...
1166 if (newTrackLocationId >= 0)
1167 {
1168 qDebug() << "Found moved track!" << filename;
11691241
1170 //Remove old row from track_locations table1242 //Remove old row from track_locations table
1171 query3.prepare("DELETE FROM track_locations WHERE "1243 query3.prepare("DELETE FROM track_locations WHERE id=:id");
1172 "id=:id");
1173 query3.bindValue(":id", oldTrackLocationId);1244 query3.bindValue(":id", oldTrackLocationId);
1174 Q_ASSERT(query3.exec());1245 Q_ASSERT(query3.exec());
11751246
@@ -1181,42 +1252,37 @@
1181 "location=:location");1252 "location=:location");
1182 query3.bindValue(":location", newTrackLocationId);1253 query3.bindValue(":location", newTrackLocationId);
1183 Q_ASSERT(query3.exec());1254 Q_ASSERT(query3.exec());
11841255 // We collect all the new tracks the where added to BaseTrackCache as well
1185 while (query3.next())1256 while (query3.next()) {
1186 {1257 int newTrackId = query3.value(0).toInt();
1187 int newTrackId = query3.value(query3.record().indexOf("id")).toInt();1258 tracksMovedSetNew.insert(newTrackId);
1188 query3.prepare("DELETE FROM library WHERE "
1189 "id=:newid");
1190 query3.bindValue(":newid", newTrackLocationId);
1191 Q_ASSERT(query3.exec());
1192
1193 // We collect all the new tracks the where added to BaseTrackCache as well
1194 pTracksMovedSetNew->insert(newTrackId);
1195 }1259 }
1260 // Delete the track
1261 query3.prepare("DELETE FROM library WHERE "
1262 "id=:newid");
1263 query3.bindValue(":newid", newTrackLocationId);
1264 Q_ASSERT(query3.exec());
11961265
1197 //Update the location foreign key for the existing row in the library table1266 //Update the location foreign key for the existing row in the library table
1198 //to point to the correct row in the track_locations table.1267 //to point to the correct row in the track_locations table.
1268 query3.prepare("UPDATE library "
1269 "SET location=:newloc WHERE location=:oldloc");
1270 query3.bindValue(":newloc", newTrackLocationId);
1271 query3.bindValue(":oldloc", oldTrackLocationId);
1272 Q_ASSERT(query3.exec());
1273
1274 // We collect all the old tracks that has to be updated in BaseTrackCache as well
1199 query3.prepare("SELECT id FROM library WHERE "1275 query3.prepare("SELECT id FROM library WHERE "
1200 "location=:location");1276 "location=:location");
1201 query3.bindValue(":location", oldTrackLocationId);1277 query3.bindValue(":location", newTrackLocationId);
1202 Q_ASSERT(query3.exec());1278 Q_ASSERT(query3.exec());
12031279 while (query3.next()) {
12041280 int oldTrackId = query3.value(0).toInt();
1205 while (query3.next())1281 tracksMovedSetOld.insert(oldTrackId);
1206 {
1207 int oldTrackId = query3.value(query3.record().indexOf("id")).toInt();
1208
1209 query3.prepare("UPDATE library "
1210 "SET location=:newloc WHERE id=:oldid");
1211 query3.bindValue(":newloc", newTrackLocationId);
1212 query3.bindValue(":oldid", oldTrackId);
1213 Q_ASSERT(query3.exec());
1214
1215 // We collect all the old tracks that has to be updated in BaseTrackCache as well
1216 pTracksMovedSetOld->insert(oldTrackId);
1217 }1282 }
1218 }1283 }
1219 }1284 }
1285 databaseTracksMoved(tracksMovedSetOld, tracksMovedSetNew);
1220}1286}
12211287
1222void TrackDAO::clearCache() {1288void TrackDAO::clearCache() {
@@ -1248,7 +1314,125 @@
1248 return false;1314 return false;
1249}1315}
12501316
1251void TrackDAO::verifyTracksOutside(const QString& libraryPath, volatile bool* pCancel) {1317bool TrackDAO::relocateTrack(TrackPointer pTrack, QString newLocation) {
1318 int newFileSize=-1;
1319 int newDuration=-1;
1320 int newTrackLocationId = -1;
1321 int oldTrackLocationId = -1;
1322 QString oldCheckSum;
1323 QString newCheckSum;
1324 int newMainDirId=0;
1325 QString oldLocation = pTrack->getLocation();
1326 int oldFileSize = pTrack->getLength();
1327 int oldDuration = pTrack->getDuration();
1328 int id = getTrackId(pTrack->getLocation());
1329
1330 ScopedTransaction transaction(m_database);
1331 // see if this track is not already in the database and retrieve information
1332 QSqlQuery query(m_database);
1333 query.prepare("SELECT track_locations.id, checksum, filesize, duration FROM track_locations "
1334 "INNER JOIN library ON track_locations.id=library.location "
1335 "WHERE location= \"" + newLocation + "\"");
1336 if (!query.exec())
1337 LOG_FAILED_QUERY(query);
1338
1339 while (query.next()) {
1340 newTrackLocationId = query.value(query.record().indexOf("id")).toInt();
1341 newFileSize = query.value(query.record().indexOf("filesize")).toInt();
1342 newCheckSum = query.value(query.record().indexOf("checksum")).toString();
1343 newDuration = query.value(query.record().indexOf("duration")).toInt();
1344 }
1345
1346 // retrieve information about the old track
1347 query.prepare("SELECT id, checksum FROM track_locations "
1348 "WHERE location = \""+oldLocation+"\"");
1349 if (!query.exec())
1350 LOG_FAILED_QUERY(query);
1351 while (query.next()) {
1352 oldCheckSum = query.value(query.record().indexOf("checksum")).toString();
1353 oldTrackLocationId = query.value(query.record().indexOf("id")).toInt();
1354 //qDebug() << oldTrackLocationId << " old id";
1355 }
1356
1357 // check if the new track is in a Folder that mixxx watches
1358 query.prepare("SELECT dir_id, directory FROM directories");
1359 if (!query.exec()) {
1360 LOG_FAILED_QUERY(query) << "There are no directories saved in the db";
1361 }
1362 while (query.next()) {
1363 QString dir = query.value(query.record().indexOf("directory")).toString();
1364 if (newLocation.contains(dir)) {
1365 newMainDirId = query.value(query.record().indexOf("dir_id")).toInt();
1366 }
1367 }
1368
1369 // check we already know a track in that location and make sanity check
1370 // that this new track actually is the same as the old one
1371 if (newTrackLocationId >= 0 &&
1372 ((newFileSize == oldFileSize) &&
1373 (oldCheckSum==newCheckSum) &&
1374 (newDuration==oldDuration))) {
1375
1376 //The library scanner will have added a new row to the Library
1377 //table which corresponds to the track in the new location. We need
1378 //to remove that so we don't end up with two rows in the library table
1379 //for the same track.
1380 query.prepare("DELETE FROM library INNER JOIN track_locations ON "
1381 "library.locations = track_locations.id WHERE library.location=:newid");
1382 query.bindValue(":newid", newTrackLocationId);
1383 Q_ASSERT(query.exec());
1384
1385 // Update the location foreign key for the existing row in the library table
1386 // to point to the correct row in the track_locations table.
1387 query.prepare("UPDATE track_locations "
1388 "SET location=:newloc, maindir_id=:dirid WHERE location=:oldloc");
1389 query.bindValue(":newloc", "\"" +newLocation + "\"");
1390 query.bindValue(":dirid",newMainDirId);
1391 query.bindValue(":oldloc","\"" +oldLocation + "\"");
1392 Q_ASSERT(query.exec());
1393 } else {
1394 // New locazion was unknown,
1395 // we can simply change the location
1396 TrackInfoObject newTrack(newLocation);
1397 QString filename = newTrack.getFilename();
1398 QString location = newTrack.getLocation();
1399 QString directory = newTrack.getDirectory();
1400 newFileSize = newTrack.getLength();
1401 newDuration = newTrack.getDuration();
1402
1403 newCheckSum = calcChecksum(newLocation);
1404 if ((newCheckSum != oldCheckSum) && (oldFileSize != newFileSize)
1405 && (newDuration!=oldDuration)) {
1406 qDebug() << "that is another song";
1407 qDebug() << "checksum " << oldCheckSum << " vs " << newCheckSum;
1408 qDebug() << "filesize " << oldFileSize << " vs " << newFileSize;
1409 qDebug() << "duration " << oldDuration << " vs " << newDuration;
1410 return false;
1411 }
1412
1413 query.prepare("UPDATE track_locations "
1414 "SET location=\""+location+"\", filename=\""+filename+"\","
1415 " directory=\""+directory+"\", "
1416 "fs_deleted=0, maindir_id= "+QString::number(newMainDirId)+
1417 " WHERE id="+QString::number(oldTrackLocationId));
1418
1419 // qDebug() << "will update it";
1420 // qDebug() << query.lastQuery();
1421 if (!query.exec()) {
1422 LOG_FAILED_QUERY(query) << " update failed";
1423 return false;
1424 }
1425 }
1426 transaction.commit();
1427 // remove tracks from cache and BTC
1428 QSet<int> ids;
1429 ids.insert(id);
1430 databaseTracksMoved(ids,ids);
1431 uncacheTracks(ids);
1432 return true;
1433}
1434
1435void TrackDAO::verifyTracksOutside(volatile bool* pCancel) {
1252 // This function is called from the LibraryScanner Thread1436 // This function is called from the LibraryScanner Thread
1253 ScopedTransaction transaction(m_database);1437 ScopedTransaction transaction(m_database);
1254 QSqlQuery query(m_database);1438 QSqlQuery query(m_database);
@@ -1258,10 +1442,7 @@
1258 query.setForwardOnly(true);1442 query.setForwardOnly(true);
1259 query.prepare("SELECT location "1443 query.prepare("SELECT location "
1260 "FROM track_locations "1444 "FROM track_locations "
1261 "WHERE directory NOT LIKE '" +1445 "WHERE maindir_id=0");
1262 libraryPath +
1263 "/%'"); //Add wildcard to SQL query to match subdirectories!
1264
1265 if (!query.exec()) {1446 if (!query.exec()) {
1266 LOG_FAILED_QUERY(query);1447 LOG_FAILED_QUERY(query);
1267 return;1448 return;
@@ -1287,3 +1468,53 @@
1287 qDebug() << "verifyTracksOutside finished";1468 qDebug() << "verifyTracksOutside finished";
1288}1469}
12891470
1471void TrackDAO::markTrackAsDeleted(TrackPointer pTrack){
1472 int id = pTrack->getId();
1473 ScopedTransaction transaction(m_database);
1474 QSqlQuery query;
1475 query.prepare("UPDATE track_locations SET fs_deleted=1 WHERE id="+QString::number(id));
1476 if (!query.exec()) {
1477 LOG_FAILED_QUERY(query) << "Could not mark Track as deleted";
1478 return;
1479 }
1480 transaction.commit();
1481 QSet<int> ids;
1482 ids.insert(id);
1483 uncacheTracks(ids);
1484 emit(tracksRemoved(ids));
1485}
1486
1487
1488void TrackDAO::uncacheTracks(QSet<int> ids){
1489 QMutexLocker locker(&m_sTracksMutex);
1490 foreach (int id, ids) {
1491 m_sTracks.remove(id);
1492 m_trackCache.remove(id);
1493 }
1494}
1495
1496QString TrackDAO::calcChecksum(TrackInfoObject& pTrack) {
1497 return calcChecksum(pTrack.getLocation());
1498}
1499
1500QString TrackDAO::calcChecksum(QString location){
1501 QFile file(location);
1502 if (!file.exists()) {
1503 return QString();
1504 }
1505 file.open(QIODevice::ReadOnly);
1506 const int block_size = 4096;
1507 char buffer[block_size];
1508 int bytes_read;
1509 // only ID3v1-Tags are at the end of the file and have a fixed size of
1510 // 128byte this way we only calc the checksum of the audio
1511 file.seek(file.size() - 2*block_size);
1512
1513 QCryptographicHash hash(QCryptographicHash::Md5);
1514 if ( (bytes_read = file.read(buffer, block_size)) ) {
1515 hash.addData(buffer,bytes_read);
1516 }
1517 return hash.result().toHex();
1518}
1519
1520
12901521
=== modified file 'mixxx/src/library/dao/trackdao.h'
--- mixxx/src/library/dao/trackdao.h 2013-04-22 19:29:54 +0000
+++ mixxx/src/library/dao/trackdao.h 2013-05-18 16:32:26 +0000
@@ -52,12 +52,15 @@
52const QString TRACKLOCATIONSTABLE_FILESIZE = "filesize";52const QString TRACKLOCATIONSTABLE_FILESIZE = "filesize";
53const QString TRACKLOCATIONSTABLE_FSDELETED = "fs_deleted";53const QString TRACKLOCATIONSTABLE_FSDELETED = "fs_deleted";
54const QString TRACKLOCATIONSTABLE_NEEDSVERIFICATION = "needs_verification";54const QString TRACKLOCATIONSTABLE_NEEDSVERIFICATION = "needs_verification";
55const QString TRACKLOCATIONSTABLE_FINGERPRINT = "fingerprint";
56const QString TRACKLOCATIONSTABLE_MAINDIRID = "maindir_id";
5557
56class ScopedTransaction;58class ScopedTransaction;
57class PlaylistDAO;59class PlaylistDAO;
58class AnalysisDao;60class AnalysisDao;
59class CueDAO;61class CueDAO;
60class CrateDAO;62class CrateDAO;
63class DirectoryDAO;
6164
62class TrackDAO : public QObject, public virtual DAO {65class TrackDAO : public QObject, public virtual DAO {
63 Q_OBJECT66 Q_OBJECT
@@ -66,8 +69,8 @@
66 // synchronized on track metadata change69 // synchronized on track metadata change
67 TrackDAO(QSqlDatabase& database, CueDAO& cueDao,70 TrackDAO(QSqlDatabase& database, CueDAO& cueDao,
68 PlaylistDAO& playlistDao, CrateDAO& crateDao,71 PlaylistDAO& playlistDao, CrateDAO& crateDao,
69 AnalysisDao& analysisDao,72 AnalysisDao& analysisDao, DirectoryDAO& directoryDao,
70 ConfigObject<ConfigValue>* pConfig);73 ConfigObject<ConfigValue>* pConfig = NULL);
71 virtual ~TrackDAO();74 virtual ~TrackDAO();
7275
73 void finish();76 void finish();
@@ -81,25 +84,28 @@
81 int addTrack(const QString& file, bool unremove);84 int addTrack(const QString& file, bool unremove);
82 int addTrack(const QFileInfo& fileInfo, bool unremove);85 int addTrack(const QFileInfo& fileInfo, bool unremove);
83 void addTracksPrepare();86 void addTracksPrepare();
84 bool addTracksAdd(TrackInfoObject* pTrack, bool unremove);87 bool addTracksAdd(TrackInfoObject* pTrack, bool unremove,const int dirId);
85 void addTracksFinish();88 void addTracksFinish();
86 QList<int> addTracks(const QList<QFileInfo> &fileInfoList, bool unremove);89 QList<int> addTracks(const QList<QFileInfo> &fileInfoList, bool unremove);
87 void hideTracks(QList<int> ids);90 void hideTracks(QList<int> ids);
88 void purgeTracks(QList<int> ids);91 void purgeTracks(QList<int> ids);
92 QStringList deleteTracksFromFS(QList<int> ids);
89 void unhideTracks(QList<int> ids);93 void unhideTracks(QList<int> ids);
90 TrackPointer getTrack(int id, bool cacheOnly=false) const;94 TrackPointer getTrack(int id, bool cacheOnly=false) const;
91 bool isDirty(int trackId);95 bool isDirty(int trackId);
96 bool relocateTrack(TrackPointer pTrack, QString newLocation);
97 void markTrackAsDeleted(TrackPointer pTrack);
9298
93 // Scanning related calls. Should be elsewhere or private somehow.99 // Scanning related calls. Should be elsewhere or private somehow.
94 void markTrackLocationAsVerified(QString location);100 void markTrackLocationAsVerified(QString location);
95 void markTracksInDirectoriesAsVerified(QStringList directories);101 void markTracksInDirectoriesAsVerified(QStringList directories);
96 void invalidateTrackLocationsInLibrary(QString libraryPath);102 void invalidateTrackLocationsInLibrary();
97 void markUnverifiedTracksAsDeleted();103 void markUnverifiedTracksAsDeleted();
98 void markTrackLocationsAsDeleted(QString directory);104 void markTrackLocationsAsDeleted(QString directory);
99 void detectMovedFiles(QSet<int>* pTracksMovedSetNew, QSet<int>* pTracksMovedSetOld);105 void detectMovedFiles(QSet<int>& tracksMovedSetNew, QSet<int>& tracksMovedSetOld);
100 void databaseTrackAdded(TrackPointer pTrack);106 void databaseTrackAdded(TrackPointer pTrack);
101 void databaseTracksMoved(QSet<int> tracksMovedSetOld, QSet<int> tracksMovedSetNew);107 void databaseTracksMoved(QSet<int> tracksMovedSetOld, QSet<int> tracksMovedSetNew);
102 void verifyTracksOutside(const QString& libraryPath, volatile bool* pCancel);108 void verifyTracksOutside(volatile bool* pCancel);
103109
104 signals:110 signals:
105 void trackDirty(int trackId);111 void trackDirty(int trackId);
@@ -134,10 +140,13 @@
134 void saveTrack(TrackInfoObject* pTrack);140 void saveTrack(TrackInfoObject* pTrack);
135 void updateTrack(TrackInfoObject* pTrack);141 void updateTrack(TrackInfoObject* pTrack);
136 void addTrack(TrackInfoObject* pTrack, bool unremove);142 void addTrack(TrackInfoObject* pTrack, bool unremove);
143 QString calcChecksum(TrackInfoObject& pTrack);
144 QString calcChecksum(QString location);
137 TrackPointer getTrackFromDB(int id) const;145 TrackPointer getTrackFromDB(int id) const;
138 QString absoluteFilePath(QString location);146 QString absoluteFilePath(QString location);
147 void uncacheTracks(QSet<int> ids);
139148
140 void bindTrackToTrackLocationsInsert(TrackInfoObject* pTrack);149 void bindTrackToTrackLocationsInsert(TrackInfoObject* pTrack, int dirId,QString& checksum);
141 void bindTrackToLibraryInsert(TrackInfoObject* pTrack, int trackLocationId);150 void bindTrackToLibraryInsert(TrackInfoObject* pTrack, int trackLocationId);
142151
143 void writeAudioMetaData(TrackInfoObject* pTrack);152 void writeAudioMetaData(TrackInfoObject* pTrack);
@@ -149,6 +158,7 @@
149 PlaylistDAO &m_playlistDao;158 PlaylistDAO &m_playlistDao;
150 CrateDAO &m_crateDao;159 CrateDAO &m_crateDao;
151 AnalysisDao& m_analysisDao;160 AnalysisDao& m_analysisDao;
161 DirectoryDAO& m_directoryDAO;
152 ConfigObject<ConfigValue> * m_pConfig;162 ConfigObject<ConfigValue> * m_pConfig;
153 static QHash<int, TrackWeakPointer> m_sTracks;163 static QHash<int, TrackWeakPointer> m_sTracks;
154 static QMutex m_sTracksMutex;164 static QMutex m_sTracksMutex;
155165
=== modified file 'mixxx/src/library/hiddentablemodel.cpp'
--- mixxx/src/library/hiddentablemodel.cpp 2012-06-20 15:49:14 +0000
+++ mixxx/src/library/hiddentablemodel.cpp 2013-05-18 16:32:26 +0000
@@ -1,28 +1,25 @@
1#include <QtCore>1#include <QMessageBox>
2#include <QtGui>2
3#include <QtSql>
4#include "library/trackcollection.h"
5#include "library/hiddentablemodel.h"3#include "library/hiddentablemodel.h"
6#include "library/librarytablemodel.h"
7#include "mixxxutils.cpp"
8
94
10HiddenTableModel::HiddenTableModel(QObject* parent,5HiddenTableModel::HiddenTableModel(QObject* parent,
11 TrackCollection* pTrackCollection)6 TrackCollection* pTrackCollection)
12 : BaseSqlTableModel(parent, pTrackCollection,7 : BaseSqlTableModel(parent, pTrackCollection,
13 pTrackCollection->getDatabase(),8 NULL,"mixxx.db.model.missing") {
14 "mixxx.db.model.missing"),9 setTableModel();
15 m_pTrackCollection(pTrackCollection),10}
16 m_trackDao(m_pTrackCollection->getTrackDAO()) {11
1712HiddenTableModel::~HiddenTableModel() {
13}
14
15void HiddenTableModel::setTableModel(int id){
16 Q_UNUSED(id);
18 QSqlQuery query;17 QSqlQuery query;
19 QString tableName("hidden_songs");18 QString tableName("hidden_songs_");
2019
21 QStringList columns;20 QStringList columns;
22 columns << "library." + LIBRARYTABLE_ID;21 columns << "library." + LIBRARYTABLE_ID;
2322 QString filter("mixxx_deleted=1");
24 QString filter("mixxx_deleted");
25
26 query.prepare("CREATE TEMPORARY VIEW IF NOT EXISTS " + tableName + " AS "23 query.prepare("CREATE TEMPORARY VIEW IF NOT EXISTS " + tableName + " AS "
27 "SELECT "24 "SELECT "
28 + columns.join(",") +25 + columns.join(",") +
@@ -36,7 +33,7 @@
3633
37 //Print out any SQL error, if there was one.34 //Print out any SQL error, if there was one.
38 if (query.lastError().isValid()) {35 if (query.lastError().isValid()) {
39 qDebug() << __FILE__ << __LINE__ << query.lastError();36 qDebug() << __FILE__ << __LINE__ << query.lastError();
40 }37 }
4138
42 QStringList tableColumns;39 QStringList tableColumns;
@@ -48,26 +45,6 @@
48 setDefaultSort(fieldIndex("artist"), Qt::AscendingOrder);45 setDefaultSort(fieldIndex("artist"), Qt::AscendingOrder);
49 setSearch("");46 setSearch("");
5047
51 connect(this, SIGNAL(doSearch(const QString&)),
52 this, SLOT(slotSearch(const QString&)));
53}
54
55HiddenTableModel::~HiddenTableModel() {
56}
57
58bool HiddenTableModel::addTrack(const QModelIndex& index, QString location) {
59 Q_UNUSED(index);
60 Q_UNUSED(location);
61 return false;
62}
63
64TrackPointer HiddenTableModel::getTrack(const QModelIndex& index) const {
65 //FIXME: use position instead of location for playlist tracks?
66
67 //const int locationColumnIndex = this->fieldIndex(LIBRARYTABLE_LOCATION);
68 //QString location = index.sibling(index.row(), locationColumnIndex).data().toString();
69 int trackId = getTrackId(index);
70 return m_trackDao.getTrack(trackId);
71}48}
7249
73void HiddenTableModel::purgeTracks(const QModelIndexList& indices) {50void HiddenTableModel::purgeTracks(const QModelIndexList& indices) {
@@ -78,7 +55,7 @@
78 trackIds.append(trackId);55 trackIds.append(trackId);
79 }56 }
8057
81 m_trackDao.purgeTracks(trackIds);58 m_trackDAO.purgeTracks(trackIds);
8259
83 // TODO(rryan) : do not select, instead route event to BTC and notify from60 // TODO(rryan) : do not select, instead route event to BTC and notify from
84 // there.61 // there.
@@ -93,22 +70,34 @@
93 trackIds.append(trackId);70 trackIds.append(trackId);
94 }71 }
9572
96 m_trackDao.unhideTracks(trackIds);73 m_trackDAO.unhideTracks(trackIds);
9774
98 // TODO(rryan) : do not select, instead route event to BTC and notify from75 // TODO(rryan) : do not select, instead route event to BTC and notify from
99 // there.76 // there.
100 select(); //Repopulate the data model.77 select(); //Repopulate the data model.
101}78}
10279
10380void HiddenTableModel::deleteTracks(const QModelIndexList& indices) {
104void HiddenTableModel::search(const QString& searchText) {81 QMessageBox::StandardButton btn = QMessageBox::question(
105 // qDebug() << "HiddenTableModel::search()" << searchText82 NULL, tr("Confirm Delete"),
106 // << QThread::currentThread();83 tr("Are you sure you want to delete these files?"),
107 emit(doSearch(searchText));84 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
108}85 if (btn == QMessageBox::No) {
10986 return ;
110void HiddenTableModel::slotSearch(const QString& searchText) {87 }
111 BaseSqlTableModel::search(searchText);88
89 QList<int> trackIds;
90 foreach (QModelIndex index, indices) {
91 int trackId = getTrackId(index);
92 trackIds.append(trackId);
93 }
94 QStringList failed = m_trackDAO.deleteTracksFromFS(trackIds);
95 if (!failed.isEmpty()) {
96 QMessageBox::warning(NULL, tr("Mixxx"),
97 tr("The following track (%1) could not be removed"
98 "because the files are still in use").arg(failed.join(",")));
99 }
100 select(); //Repopulate the data model.
112}101}
113102
114bool HiddenTableModel::isColumnInternal(int column) {103bool HiddenTableModel::isColumnInternal(int column) {
@@ -116,7 +105,8 @@
116 column == fieldIndex(LIBRARYTABLE_PLAYED) ||105 column == fieldIndex(LIBRARYTABLE_PLAYED) ||
117 column == fieldIndex(LIBRARYTABLE_BPM_LOCK) ||106 column == fieldIndex(LIBRARYTABLE_BPM_LOCK) ||
118 column == fieldIndex(LIBRARYTABLE_MIXXXDELETED) ||107 column == fieldIndex(LIBRARYTABLE_MIXXXDELETED) ||
119 column == fieldIndex(TRACKLOCATIONSTABLE_FSDELETED)) {108 column == fieldIndex(TRACKLOCATIONSTABLE_FSDELETED) ||
109 column == fieldIndex(TRACKLOCATIONSTABLE_MAINDIRID)) {
120 return true;110 return true;
121 }111 }
122 return false;112 return false;
@@ -136,5 +126,7 @@
136TrackModel::CapabilitiesFlags HiddenTableModel::getCapabilities() const {126TrackModel::CapabilitiesFlags HiddenTableModel::getCapabilities() const {
137 return TRACKMODELCAPS_NONE127 return TRACKMODELCAPS_NONE
138 | TRACKMODELCAPS_PURGE128 | TRACKMODELCAPS_PURGE
139 | TRACKMODELCAPS_UNHIDE;129 | TRACKMODELCAPS_UNHIDE
130 | TRACKMODELCAPS_RELOCATE
131 | TRACKMODELCAPS_DELETEFS;
140}132}
141133
=== modified file 'mixxx/src/library/hiddentablemodel.h'
--- mixxx/src/library/hiddentablemodel.h 2013-05-18 16:23:08 +0000
+++ mixxx/src/library/hiddentablemodel.h 2013-05-18 16:32:26 +0000
@@ -3,33 +3,20 @@
33
4#include "library/basesqltablemodel.h"4#include "library/basesqltablemodel.h"
55
6class TrackCollection;
7
8class HiddenTableModel : public BaseSqlTableModel {6class HiddenTableModel : public BaseSqlTableModel {
9 Q_OBJECT7 Q_OBJECT
10 public:8 public:
11 HiddenTableModel(QObject* parent, TrackCollection* pTrackCollection);9 HiddenTableModel(QObject* parent, TrackCollection* pTrackCollection);
12 virtual ~HiddenTableModel();10 virtual ~HiddenTableModel();
13 TrackPointer getTrack(const QModelIndex& index) const;11 void setTableModel(int id = -1);
14 void search(const QString& searchText);
15 bool isColumnInternal(int column);12 bool isColumnInternal(int column);
16 bool isColumnHiddenByDefault(int column);13 bool isColumnHiddenByDefault(int column);
17 void purgeTracks(const QModelIndexList& indices);14 void purgeTracks(const QModelIndexList& indices);
15 void deleteTracks(const QModelIndexList& indices);
18 void unhideTracks(const QModelIndexList& indices);16 void unhideTracks(const QModelIndexList& indices);
19 bool addTrack(const QModelIndex& index, QString location);
2017
21 Qt::ItemFlags flags(const QModelIndex &index) const;18 Qt::ItemFlags flags(const QModelIndex &index) const;
22 TrackModel::CapabilitiesFlags getCapabilities() const;19 TrackModel::CapabilitiesFlags getCapabilities() const;
23
24 private slots:
25 void slotSearch(const QString& searchText);
26
27 signals:
28 void doSearch(const QString& searchText);
29
30 private:
31 TrackCollection* m_pTrackCollection;
32 TrackDAO& m_trackDao;
33};20};
3421
35#endif22#endif
3623
=== modified file 'mixxx/src/library/itunes/itunesfeature.cpp'
--- mixxx/src/library/itunes/itunesfeature.cpp 2013-01-01 11:53:13 +0000
+++ mixxx/src/library/itunes/itunesfeature.cpp 2013-05-18 16:32:26 +0000
@@ -25,10 +25,12 @@
25#endif25#endif
26}26}
2727
28ITunesFeature::ITunesFeature(QObject* parent, TrackCollection* pTrackCollection)28ITunesFeature::ITunesFeature(QObject* parent, TrackCollection* pTrackCollection
29 ,ConfigObject<ConfigValue>* pConfig)
29 : BaseExternalLibraryFeature(parent, pTrackCollection),30 : BaseExternalLibraryFeature(parent, pTrackCollection),
30 m_pTrackCollection(pTrackCollection),31 m_pTrackCollection(pTrackCollection),
31 m_cancelImport(false) {32 m_cancelImport(false),
33 m_pConfig(pConfig) {
32 QString tableName = "itunes_library";34 QString tableName = "itunes_library";
33 QString idColumn = "id";35 QString idColumn = "id";
34 QStringList columns;36 QStringList columns;
@@ -53,13 +55,13 @@
53 this, m_pTrackCollection,55 this, m_pTrackCollection,
54 "mixxx.db.model.itunes",56 "mixxx.db.model.itunes",
55 "itunes_library",57 "itunes_library",
56 "itunes");58 "itunes",m_pConfig);
57 m_pITunesPlaylistModel = new BaseExternalPlaylistModel(59 m_pITunesPlaylistModel = new BaseExternalPlaylistModel(
58 this, m_pTrackCollection,60 this, m_pTrackCollection,
59 "mixxx.db.model.itunes_playlist",61 "mixxx.db.model.itunes_playlist",
60 "itunes_playlists",62 "itunes_playlists",
61 "itunes_playlist_tracks",63 "itunes_playlist_tracks",
62 "itunes");64 "itunes",m_pConfig);
63 m_isActivated = false;65 m_isActivated = false;
64 m_title = tr("iTunes");66 m_title = tr("iTunes");
6567
@@ -86,7 +88,7 @@
86 "mixxx.db.model.itunes_playlist",88 "mixxx.db.model.itunes_playlist",
87 "itunes_playlists",89 "itunes_playlists",
88 "itunes_playlist_tracks",90 "itunes_playlist_tracks",
89 "itunes");91 "itunes", m_pConfig);
90 pModel->setPlaylist(playlist);92 pModel->setPlaylist(playlist);
91 return pModel;93 return pModel;
92}94}
@@ -360,12 +362,12 @@
360void ITunesFeature::parseTracks(QXmlStreamReader &xml) {362void ITunesFeature::parseTracks(QXmlStreamReader &xml) {
361 QSqlQuery query(m_database);363 QSqlQuery query(m_database);
362 query.prepare("INSERT INTO itunes_library (id, artist, title, album, year, genre, comment, tracknumber,"364 query.prepare("INSERT INTO itunes_library (id, artist, title, album, year, genre, comment, tracknumber,"
363 "bpm, bitrate,"365 "bpm, bitrate,"
364 "duration, location,"366 "duration, location,"
365 "rating ) "367 "rating ) "
366 "VALUES (:id, :artist, :title, :album, :year, :genre, :comment, :tracknumber,"368 "VALUES (:id, :artist, :title, :album, :year, :genre, :comment, :tracknumber,"
367 ":bpm, :bitrate,"369 ":bpm, :bitrate,"
368 ":duration, :location," ":rating )");370 ":duration, :location," ":rating )");
369371
370372
371 bool in_container_dictionary = false;373 bool in_container_dictionary = false;
@@ -533,7 +535,7 @@
533 TreeItem* rootItem = new TreeItem();535 TreeItem* rootItem = new TreeItem();
534 QSqlQuery query_insert_to_playlists(m_database);536 QSqlQuery query_insert_to_playlists(m_database);
535 query_insert_to_playlists.prepare("INSERT INTO itunes_playlists (id, name) "537 query_insert_to_playlists.prepare("INSERT INTO itunes_playlists (id, name) "
536 "VALUES (:id, :name)");538 "VALUES (:id, :name)");
537539
538 QSqlQuery query_insert_to_playlist_tracks(m_database);540 QSqlQuery query_insert_to_playlist_tracks(m_database);
539 query_insert_to_playlist_tracks.prepare(541 query_insert_to_playlist_tracks.prepare(
@@ -545,9 +547,9 @@
545 //We process and iterate the <dict> tags holding playlist summary information here547 //We process and iterate the <dict> tags holding playlist summary information here
546 if (xml.isStartElement() && xml.name() == "dict") {548 if (xml.isStartElement() && xml.name() == "dict") {
547 parsePlaylist(xml,549 parsePlaylist(xml,
548 query_insert_to_playlists,550 query_insert_to_playlists,
549 query_insert_to_playlist_tracks,551 query_insert_to_playlist_tracks,
550 rootItem);552 rootItem);
551 continue;553 continue;
552 }554 }
553 if (xml.isEndElement()) {555 if (xml.isEndElement()) {
@@ -570,7 +572,7 @@
570}572}
571573
572void ITunesFeature::parsePlaylist(QXmlStreamReader &xml, QSqlQuery &query_insert_to_playlists,574void ITunesFeature::parsePlaylist(QXmlStreamReader &xml, QSqlQuery &query_insert_to_playlists,
573 QSqlQuery &query_insert_to_playlist_tracks, TreeItem* root) {575 QSqlQuery &query_insert_to_playlist_tracks, TreeItem* root) {
574 //qDebug() << "Parse Playlist";576 //qDebug() << "Parse Playlist";
575577
576 QString playlistname;578 QString playlistname;
@@ -623,7 +625,7 @@
623 bool success = query_insert_to_playlists.exec();625 bool success = query_insert_to_playlists.exec();
624 if (!success) {626 if (!success) {
625 qDebug() << "SQL Error in ITunesTableModel.cpp: line" << __LINE__627 qDebug() << "SQL Error in ITunesTableModel.cpp: line" << __LINE__
626 << " " << query_insert_to_playlists.lastError();628 << " " << query_insert_to_playlists.lastError();
627 return;629 return;
628 }630 }
629 //append the playlist to the child model631 //append the playlist to the child model
@@ -646,7 +648,7 @@
646 //Insert tracks if we are not in a pre-build playlist648 //Insert tracks if we are not in a pre-build playlist
647 if (!isSystemPlaylist && !query_insert_to_playlist_tracks.exec()) {649 if (!isSystemPlaylist && !query_insert_to_playlist_tracks.exec()) {
648 qDebug() << "SQL Error in ITunesFeature.cpp: line" << __LINE__ << " "650 qDebug() << "SQL Error in ITunesFeature.cpp: line" << __LINE__ << " "
649 << query_insert_to_playlist_tracks.lastError();651 << query_insert_to_playlist_tracks.lastError();
650 qDebug() << "trackid" << track_reference;652 qDebug() << "trackid" << track_reference;
651 qDebug() << "playlistname; " << playlistname;653 qDebug() << "playlistname; " << playlistname;
652 qDebug() << "-----------------";654 qDebug() << "-----------------";
@@ -670,10 +672,10 @@
670672
671 if (!success) {673 if (!success) {
672 qDebug() << "Could not delete remove old entries from table "674 qDebug() << "Could not delete remove old entries from table "
673 << table_name << " : " << query.lastError();675 << table_name << " : " << query.lastError();
674 } else {676 } else {
675 qDebug() << "iTunes table entries of '"677 qDebug() << "iTunes table entries of '"
676 << table_name <<"' have been cleared.";678 << table_name <<"' have been cleared.";
677 }679 }
678}680}
679681
@@ -693,7 +695,7 @@
693 NULL,695 NULL,
694 tr("Error Loading iTunes Library"),696 tr("Error Loading iTunes Library"),
695 tr("There was an error loading your iTunes library. Some of "697 tr("There was an error loading your iTunes library. Some of "
696 "your iTunes tracks or playlists may not have loaded."));698 "your iTunes tracks or playlists may not have loaded."));
697 }699 }
698 // calls a slot in the sidebarmodel such that 'isLoading' is removed from the feature title.700 // calls a slot in the sidebarmodel such that 'isLoading' is removed from the feature title.
699 m_title = tr("iTunes");701 m_title = tr("iTunes");
700702
=== modified file 'mixxx/src/library/itunes/itunesfeature.h'
--- mixxx/src/library/itunes/itunesfeature.h 2013-01-01 11:53:13 +0000
+++ mixxx/src/library/itunes/itunesfeature.h 2013-05-18 16:32:26 +0000
@@ -14,6 +14,7 @@
14#include "library/trackcollection.h"14#include "library/trackcollection.h"
15#include "library/treeitemmodel.h"15#include "library/treeitemmodel.h"
16#include "library/treeitem.h"16#include "library/treeitem.h"
17#include "configobject.h"
1718
18class BaseExternalTrackModel;19class BaseExternalTrackModel;
19class BaseExternalPlaylistModel;20class BaseExternalPlaylistModel;
@@ -21,7 +22,8 @@
21class ITunesFeature : public BaseExternalLibraryFeature {22class ITunesFeature : public BaseExternalLibraryFeature {
22 Q_OBJECT23 Q_OBJECT
23 public:24 public:
24 ITunesFeature(QObject* parent, TrackCollection* pTrackCollection);25 ITunesFeature(QObject* parent, TrackCollection* pTrackCollection
26 ,ConfigObject<ConfigValue>* pConfig);
25 virtual ~ITunesFeature();27 virtual ~ITunesFeature();
26 static bool isSupported();28 static bool isSupported();
2729
@@ -62,6 +64,8 @@
62 bool m_isActivated;64 bool m_isActivated;
63 QString m_dbfile;65 QString m_dbfile;
6466
67 ConfigObject<ConfigValue>* m_pConfig;
68
65 QFutureWatcher<TreeItem*> m_future_watcher;69 QFutureWatcher<TreeItem*> m_future_watcher;
66 QFuture<TreeItem*> m_future;70 QFuture<TreeItem*> m_future;
67 QString m_title;71 QString m_title;
6872
=== modified file 'mixxx/src/library/library.cpp'
--- mixxx/src/library/library.cpp 2013-05-18 16:23:08 +0000
+++ mixxx/src/library/library.cpp 2013-05-18 16:32:26 +0000
@@ -2,6 +2,8 @@
2// Created 8/23/2009 by RJ Ryan (rryan@mit.edu)2// Created 8/23/2009 by RJ Ryan (rryan@mit.edu)
33
4#include <QItemSelectionModel>4#include <QItemSelectionModel>
5#include <QFuture>
6#include <QtConcurrentMap>
57
6#include "library/library.h"8#include "library/library.h"
7#include "library/libraryfeature.h"9#include "library/libraryfeature.h"
@@ -41,48 +43,50 @@
41 m_pSidebarModel(new SidebarModel(parent)),43 m_pSidebarModel(new SidebarModel(parent)),
42 m_pTrackCollection(new TrackCollection(pConfig)),44 m_pTrackCollection(new TrackCollection(pConfig)),
43 m_pLibraryControl(new LibraryControl),45 m_pLibraryControl(new LibraryControl),
44 m_pRecordingManager(pRecordingManager) {46 m_pRecordingManager(pRecordingManager),
47 m_directoryDAO(m_pTrackCollection->getDirectoryDAO()) {
4548
46 // TODO(rryan) -- turn this construction / adding of features into a static49 // TODO(rryan) -- turn this construction / adding of features into a static
47 // method or something -- CreateDefaultLibrary50 // method or something -- CreateDefaultLibrary
48 m_pMixxxLibraryFeature = new MixxxLibraryFeature(this, m_pTrackCollection,m_pConfig);51 m_pMixxxLibraryFeature = new MixxxLibraryFeature(this, m_pTrackCollection,pConfig);
49 addFeature(m_pMixxxLibraryFeature);52 addFeature(m_pMixxxLibraryFeature,true);
5053
51#ifdef __PROMO__54#ifdef __PROMO__
52 if (PromoTracksFeature::isSupported(m_pConfig)) {55 if (PromoTracksFeature::isSupported(m_pConfig)) {
53 m_pPromoTracksFeature = new PromoTracksFeature(this, pConfig,56 m_pPromoTracksFeature = new PromoTracksFeature(this, pConfig,
54 m_pTrackCollection,57 m_pTrackCollection,
55 firstRun);58 firstRun);
56 addFeature(m_pPromoTracksFeature);59 addFeature(m_pPromoTracksFeature,false);
57 } else {60 } else {
58 m_pPromoTracksFeature = NULL;61 m_pPromoTracksFeature = NULL;
59 }62 }
60#endif63#endif
6164
62 addFeature(new AutoDJFeature(this, pConfig, m_pTrackCollection));65 addFeature(new AutoDJFeature(this, pConfig, m_pTrackCollection),true);
63 m_pPlaylistFeature = new PlaylistFeature(this, m_pTrackCollection, pConfig);66 m_pPlaylistFeature = new PlaylistFeature(this, m_pTrackCollection, pConfig);
64 addFeature(m_pPlaylistFeature);67 addFeature(m_pPlaylistFeature,true);
65 m_pCrateFeature = new CrateFeature(this, m_pTrackCollection, pConfig);68 m_pCrateFeature = new CrateFeature(this, m_pTrackCollection, pConfig);
66 addFeature(m_pCrateFeature);69 addFeature(m_pCrateFeature,true);
67 addFeature(new BrowseFeature(this, pConfig, m_pTrackCollection, m_pRecordingManager));70 addFeature(new BrowseFeature(this, pConfig, m_pTrackCollection, m_pRecordingManager),false);
68 addFeature(new RecordingFeature(this, pConfig, m_pTrackCollection, m_pRecordingManager));71 addFeature(new RecordingFeature(this, pConfig, m_pTrackCollection, m_pRecordingManager),false);
69 addFeature(new SetlogFeature(this, pConfig, m_pTrackCollection));72 // the history should show ALL songs
73 addFeature(new SetlogFeature(this, pConfig, m_pTrackCollection),false);
70 m_pPrepareFeature = new PrepareFeature(this, pConfig, m_pTrackCollection);74 m_pPrepareFeature = new PrepareFeature(this, pConfig, m_pTrackCollection);
71 addFeature(m_pPrepareFeature);75 addFeature(m_pPrepareFeature,false);
72 //iTunes and Rhythmbox should be last until we no longer have an obnoxious76 //iTunes and Rhythmbox should be last until we no longer have an obnoxious
73 //messagebox popup when you select them. (This forces you to reach for your77 //messagebox popup when you select them. (This forces you to reach for your
74 //mouse or keyboard if you're using MIDI control and you scroll through them...)78 //mouse or keyboard if you're using MIDI control and you scroll through them...)
75 if (RhythmboxFeature::isSupported() &&79 if (RhythmboxFeature::isSupported() &&
76 pConfig->getValueString(ConfigKey("[Library]","ShowRhythmboxLibrary"),"1").toInt()) {80 pConfig->getValueString(ConfigKey("[Library]","ShowRhythmboxLibrary"),"1").toInt()) {
77 addFeature(new RhythmboxFeature(this, m_pTrackCollection));81 addFeature(new RhythmboxFeature(this, m_pTrackCollection,pConfig),false);
78 }82 }
79 if (ITunesFeature::isSupported() &&83 if (ITunesFeature::isSupported() &&
80 pConfig->getValueString(ConfigKey("[Library]","ShowITunesLibrary"),"1").toInt()) {84 pConfig->getValueString(ConfigKey("[Library]","ShowITunesLibrary"),"1").toInt()) {
81 addFeature(new ITunesFeature(this, m_pTrackCollection));85 addFeature(new ITunesFeature(this, m_pTrackCollection, pConfig),false);
82 }86 }
83 if (TraktorFeature::isSupported() &&87 if (TraktorFeature::isSupported() &&
84 pConfig->getValueString(ConfigKey("[Library]","ShowTraktorLibrary"),"1").toInt()) {88 pConfig->getValueString(ConfigKey("[Library]","ShowTraktorLibrary"),"1").toInt()) {
85 addFeature(new TraktorFeature(this, m_pTrackCollection));89 addFeature(new TraktorFeature(this, m_pTrackCollection,pConfig),false);
86 }90 }
8791
88 //Show the promo tracks view on first run, otherwise show the library92 //Show the promo tracks view on first run, otherwise show the library
@@ -157,7 +161,7 @@
157 }161 }
158}162}
159163
160void Library::addFeature(LibraryFeature* feature) {164void Library::addFeature(LibraryFeature* feature, bool config) {
161 Q_ASSERT(feature);165 Q_ASSERT(feature);
162 m_features.push_back(feature);166 m_features.push_back(feature);
163 m_pSidebarModel->addLibraryFeature(feature);167 m_pSidebarModel->addLibraryFeature(feature);
@@ -171,15 +175,19 @@
171 this, SLOT(slotLoadTrackToPlayer(TrackPointer, QString, bool)));175 this, SLOT(slotLoadTrackToPlayer(TrackPointer, QString, bool)));
172 connect(feature, SIGNAL(restoreSearch(const QString&)),176 connect(feature, SIGNAL(restoreSearch(const QString&)),
173 this, SLOT(slotRestoreSearch(const QString&)));177 this, SLOT(slotRestoreSearch(const QString&)));
178 if (config) {
179 connect(this, SIGNAL(configChanged(QString,QString)),
180 feature, SIGNAL(configChanged(QString,QString)));
181 }
174}182}
175183
176void Library::slotShowTrackModel(QAbstractItemModel* model) {184void Library::slotShowTrackModel(QAbstractItemModel* model) {
177 //qDebug() << "Library::slotShowTrackModel" << model;185 qDebug() << "Library::slotShowTrackModel" << model;
178 TrackModel* trackModel = dynamic_cast<TrackModel*>(model);186 m_ptrackModel = dynamic_cast<TrackModel*>(model);
179 Q_ASSERT(trackModel);187 Q_ASSERT(m_ptrackModel);
180 emit(showTrackModel(model));188 emit(showTrackModel(model));
181 emit(switchToView(m_sTrackViewName));189 emit(switchToView(m_sTrackViewName));
182 emit(restoreSearch(trackModel->currentSearch()));190 emit(restoreSearch(m_ptrackModel->currentSearch()));
183}191}
184192
185void Library::slotSwitchToView(const QString& view) {193void Library::slotSwitchToView(const QString& view) {
@@ -242,3 +250,55 @@
242#endif250#endif
243 return QList<TrackPointer>();251 return QList<TrackPointer>();
244}252}
253
254MixxxLibraryFeature* Library::getpMixxxLibraryFeature(){
255 return m_pMixxxLibraryFeature;
256}
257
258void Library::slotDirsChanged(QString op, QString dir){
259 qDebug() << "kain88 slotDirsChanged";
260 qDebug() << op << '\t' << dir;
261 if (op=="added") {
262 m_directoryDAO.addDirectory(dir);
263 } else if (op=="removed") {
264 purgeTracks(m_directoryDAO.getDirId(dir));
265 m_directoryDAO.purgeDirectory(dir);
266 } else if (op=="relocate") {
267 // see dlgprefplaylist for this
268 QStringList dirs = dir.split("!(~)!");
269 QString newFolder = dirs[0];
270 QString oldFolder = dirs[1];
271 m_directoryDAO.relocateDirectory(oldFolder,newFolder);
272 } else if (op=="update") {
273 // this will be signaled from the library scanner if the db needs to be
274 // updated
275 m_directoryDAO.addDirectory(dir);
276 m_directoryDAO.updateTrackLocations(dir);
277 }
278}
279
280void Library::purgeTracks(const int dirId) {
281 QSqlQuery query;
282 QList<int> trackIds;
283 query.prepare("SELECT library.id FROM library INNER JOIN track_locations "
284 "ON library.location=track_locations.id "
285 "WHERE maindir_id="+QString::number(dirId));
286
287 if (!query.exec()) {
288 qDebug() << "could not purge tracks from libraryPath "<<dirId;
289 }
290
291 while (query.next()) {
292 trackIds.append(query.value(query.record().indexOf("id")).toInt());
293 }
294 qDebug() << "starting to purge Tracks " << trackIds;
295 m_pTrackCollection->getTrackDAO().purgeTracks(trackIds);
296}
297
298void Library::slotLoadTrackFailed(TrackPointer pTrack){
299 m_pTrackCollection->getTrackDAO().markTrackAsDeleted(pTrack);
300}
301
302QStringList Library::getDirs(){
303 return m_directoryDAO.getDirs();
304}
245305
=== modified file 'mixxx/src/library/library.h'
--- mixxx/src/library/library.h 2013-02-09 00:38:39 +0000
+++ mixxx/src/library/library.h 2013-05-18 16:32:26 +0000
@@ -14,7 +14,9 @@
14#include "configobject.h"14#include "configobject.h"
15#include "trackinfoobject.h"15#include "trackinfoobject.h"
16#include "recording/recordingmanager.h"16#include "recording/recordingmanager.h"
17#include "mixxxlibraryfeature.h"
17#include "preparefeature.h"18#include "preparefeature.h"
19#include "library/dao/directorydao.h"
1820
19class TrackModel;21class TrackModel;
20class TrackCollection;22class TrackCollection;
@@ -24,6 +26,7 @@
24class WLibrarySidebar;26class WLibrarySidebar;
25class WLibrary;27class WLibrary;
26class WSearchLineEdit;28class WSearchLineEdit;
29class PromoTracksFeature;
27class MixxxLibraryFeature;30class MixxxLibraryFeature;
28class PlaylistFeature;31class PlaylistFeature;
29class CrateFeature;32class CrateFeature;
@@ -42,8 +45,10 @@
42 MixxxKeyboard* pKeyboard);45 MixxxKeyboard* pKeyboard);
43 void bindSidebarWidget(WLibrarySidebar* sidebarWidget);46 void bindSidebarWidget(WLibrarySidebar* sidebarWidget);
4447
45 void addFeature(LibraryFeature* feature);48 void addFeature(LibraryFeature* feature, bool config);
46 QList<TrackPointer> getTracksToAutoLoad();49 QList<TrackPointer> getTracksToAutoLoad();
50 MixxxLibraryFeature* getpMixxxLibraryFeature();
51 QStringList getDirs();
4752
48 // TODO(rryan) Transitionary only -- the only reason this is here is so the53 // TODO(rryan) Transitionary only -- the only reason this is here is so the
49 // waveform widgets can signal to a player to load a track. This can be54 // waveform widgets can signal to a player to load a track. This can be
@@ -65,6 +70,8 @@
65 void slotRefreshLibraryModels();70 void slotRefreshLibraryModels();
66 void slotCreatePlaylist();71 void slotCreatePlaylist();
67 void slotCreateCrate();72 void slotCreateCrate();
73 void slotDirsChanged(QString,QString);
74 void slotLoadTrackFailed(TrackPointer pTrack);
68 void onSkinLoadFinished();75 void onSkinLoadFinished();
6976
70 signals:77 signals:
@@ -73,11 +80,17 @@
73 void loadTrack(TrackPointer pTrack);80 void loadTrack(TrackPointer pTrack);
74 void loadTrackToPlayer(TrackPointer pTrack, QString group, bool play = false);81 void loadTrackToPlayer(TrackPointer pTrack, QString group, bool play = false);
75 void restoreSearch(const QString&);82 void restoreSearch(const QString&);
83 void configChanged(QString, QString);
84 void dirsChanged(QString,QString);
85 void loadTrackFailed(TrackPointer);
76 void search(const QString& text);86 void search(const QString& text);
77 void searchCleared();87 void searchCleared();
78 void searchStarting();88 void searchStarting();
7989
80 private:90 private:
91 void purgeTracks(const int dirId);
92 static QString mpChanged(const QString);
93
81 ConfigObject<ConfigValue>* m_pConfig;94 ConfigObject<ConfigValue>* m_pConfig;
82 SidebarModel* m_pSidebarModel;95 SidebarModel* m_pSidebarModel;
83 TrackCollection* m_pTrackCollection;96 TrackCollection* m_pTrackCollection;
@@ -94,6 +107,8 @@
94 PrepareFeature* m_pPrepareFeature;107 PrepareFeature* m_pPrepareFeature;
95 LibraryControl* m_pLibraryControl;108 LibraryControl* m_pLibraryControl;
96 RecordingManager* m_pRecordingManager;109 RecordingManager* m_pRecordingManager;
110 TrackModel* m_ptrackModel;
111 DirectoryDAO m_directoryDAO;
97};112};
98113
99#endif /* LIBRARY_H */114#endif /* LIBRARY_H */
100115
=== modified file 'mixxx/src/library/libraryfeature.h'
--- mixxx/src/library/libraryfeature.h 2013-02-03 18:50:24 +0000
+++ mixxx/src/library/libraryfeature.h 2013-05-18 16:32:26 +0000
@@ -9,6 +9,7 @@
9#include <QModelIndex>9#include <QModelIndex>
10#include <QObject>10#include <QObject>
11#include <QString>11#include <QString>
12#include <QStringList>
12#include <QVariant>13#include <QVariant>
13#include <QAbstractItemModel>14#include <QAbstractItemModel>
14#include <QUrl>15#include <QUrl>
@@ -87,11 +88,11 @@
87 void restoreSearch(const QString&);88 void restoreSearch(const QString&);
88 // emit this signal before you parse a large music collection, e.g., iTunes, Traktor.89 // emit this signal before you parse a large music collection, e.g., iTunes, Traktor.
89 void featureIsLoading(LibraryFeature*);90 void featureIsLoading(LibraryFeature*);
90 // emit this signal if the foreign music collection has been imported/parsed. 91 // emit this signal if the foreign music collection has been imported/parsed.
91 void featureLoadingFinished(LibraryFeature*s);92 void featureLoadingFinished(LibraryFeature*s);
92 // emit this signal to select pFeature 93 // emit this signal to select pFeature
93 void featureSelect(LibraryFeature* pFeature, const QModelIndex& index);94 void featureSelect(LibraryFeature* pFeature, const QModelIndex& index);
9495 void availableDirsChanged(QList<int>);
95};96};
9697
97#endif /* LIBRARYFEATURE_H */98#endif /* LIBRARYFEATURE_H */
9899
=== modified file 'mixxx/src/library/libraryscanner.cpp'
--- mixxx/src/library/libraryscanner.cpp 2013-02-09 22:06:46 +0000
+++ mixxx/src/library/libraryscanner.cpp 2013-05-18 16:32:26 +0000
@@ -33,9 +33,10 @@
33 m_cueDao(m_database),33 m_cueDao(m_database),
34 m_playlistDao(m_database),34 m_playlistDao(m_database),
35 m_crateDao(m_database),35 m_crateDao(m_database),
36 m_directoryDao(m_database),
36 m_analysisDao(m_database, collection->getConfig()),37 m_analysisDao(m_database, collection->getConfig()),
37 m_trackDao(m_database, m_cueDao, m_playlistDao, m_crateDao,38 m_trackDao(m_database, m_cueDao, m_playlistDao, m_crateDao,
38 m_analysisDao, collection->getConfig()),39 m_analysisDao,m_directoryDao, collection->getConfig()),
39 // Don't initialize m_database here, we need to do it in run() so the DB40 // Don't initialize m_database here, we need to do it in run() so the DB
40 // conn is in the right thread.41 // conn is in the right thread.
41 m_nameFilters(SoundSourceProxy::supportedFileExtensionsString().split(" ")),42 m_nameFilters(SoundSourceProxy::supportedFileExtensionsString().split(" ")),
@@ -51,6 +52,17 @@
51 connect(this, SIGNAL(scanFinished()),52 connect(this, SIGNAL(scanFinished()),
52 &(collection->getTrackDAO()), SLOT(clearCache()));53 &(collection->getTrackDAO()), SLOT(clearCache()));
5354
55 //connect the new trackDAO with the default BaseTrackCacheR
56 connect(&m_trackDao, SIGNAL(tracksRemoved(QSet<int>)),
57 &*(collection->getTrackSource(QString("default"))),
58 SLOT(slotTracksRemoved(QSet<int>)));
59 connect(&m_trackDao, SIGNAL(tracksAdded(QSet<int>)),
60 &*(collection->getTrackSource(QString("default"))),
61 SLOT(slotTracksAdded(QSet<int>)));
62 connect(this, SIGNAL(tracksRestored(QSet<int>)),
63 &*(collection->getTrackSource(QString("default"))),
64 SLOT(slotTracksAdded(QSet<int>)));
65
54 // The "Album Artwork" folder within iTunes stores Album Arts.66 // The "Album Artwork" folder within iTunes stores Album Arts.
55 // It has numerous hundreds of sub folders but no audio files67 // It has numerous hundreds of sub folders but no audio files
56 // We put this folder on a "black list"68 // We put this folder on a "black list"
@@ -128,7 +140,7 @@
128 // Rollback any uncommitted transaction140 // Rollback any uncommitted transaction
129 if (m_database.rollback()) {141 if (m_database.rollback()) {
130 qDebug() << "ERROR: There was a transaction in progress while closing the library scanner connection."142 qDebug() << "ERROR: There was a transaction in progress while closing the library scanner connection."
131 << "There is a logic error somewhere.";143 << "There is a logic error somewhere.";
132 }144 }
133 // Close our database connection145 // Close our database connection
134 m_database.close();146 m_database.close();
@@ -214,7 +226,7 @@
214 // verification of their existance...226 // verification of their existance...
215 // (ie. we want to check they're still on your hard drive where227 // (ie. we want to check they're still on your hard drive where
216 // we think they are)228 // we think they are)
217 m_trackDao.invalidateTrackLocationsInLibrary(m_qLibraryPath);229 m_trackDao.invalidateTrackLocationsInLibrary();
218230
219 qDebug() << "Recursively scanning library.";231 qDebug() << "Recursively scanning library.";
220 // Start scanning the library.232 // Start scanning the library.
@@ -224,19 +236,26 @@
224 m_trackDao.addTracksPrepare();236 m_trackDao.addTracksPrepare();
225 QStringList verifiedDirectories;237 QStringList verifiedDirectories;
226238
227 bool bScanFinishedCleanly = recursiveScan(m_qLibraryPath, verifiedDirectories);239 QStringList dirs = m_directoryDao.getDirs();
228240 QSet<int> restoredTracks;
229 if (!bScanFinishedCleanly) {241 bool bScanFinishedCleanly=false;
230 qDebug() << "Recursive scan interrupted.";242 //recursivly scan each dir that is saved in the directories table
231 } else {243 foreach (QString dir , dirs) {
232 qDebug() << "Recursive scan finished cleanly.";244 int dirId = m_directoryDao.getDirId(dir);
245 bScanFinishedCleanly = recursiveScan(dir,verifiedDirectories,restoredTracks,dirId);
246 //Verify all Tracks inside Library but outside the library path
247 if (!bScanFinishedCleanly) {
248 qDebug() << "Recursive scan interrupted.";
249 } else {
250 qDebug() << "Recursive scan finished cleanly.";
251 }
233 }252 }
253 m_trackDao.verifyTracksOutside(&m_bCancelLibraryScan);
234254
235 // Runs inside a transaction255 // Runs inside a transaction
236 m_trackDao.addTracksFinish();256 m_trackDao.addTracksFinish();
237257 // this will cause BaseTrackCache to update the index of all restored tracks
238 //Verify all Tracks inside Library but outside the library path258 emit(tracksRestored(restoredTracks));
239 m_trackDao.verifyTracksOutside(m_qLibraryPath, &m_bCancelLibraryScan);
240259
241 // Start a transaction for all the library hashing (moved file detection)260 // Start a transaction for all the library hashing (moved file detection)
242 // stuff.261 // stuff.
@@ -263,7 +282,7 @@
263 // Check to see if the "deleted" tracks showed up in another location,282 // Check to see if the "deleted" tracks showed up in another location,
264 // and if so, do some magic to update all our tables.283 // and if so, do some magic to update all our tables.
265 qDebug() << "Detecting moved files.";284 qDebug() << "Detecting moved files.";
266 m_trackDao.detectMovedFiles(&tracksMovedSetOld, &tracksMovedSetNew);285 m_trackDao.detectMovedFiles(tracksMovedSetOld, tracksMovedSetNew);
267286
268 // Remove the hashes for any directories that have been287 // Remove the hashes for any directories that have been
269 // marked as deleted to clean up. We need to do this otherwise288 // marked as deleted to clean up. We need to do this otherwise
@@ -289,10 +308,8 @@
289 emit(scanFinished());308 emit(scanFinished());
290}309}
291310
292void LibraryScanner::scan(QString libraryPath, QWidget *parent)311void LibraryScanner::scan() {
293{312 m_pProgress = new LibraryScannerDlg();
294 m_qLibraryPath = libraryPath;
295 m_pProgress = new LibraryScannerDlg(parent);
296 m_pProgress->setAttribute(Qt::WA_DeleteOnClose);313 m_pProgress->setAttribute(Qt::WA_DeleteOnClose);
297314
298 // The important part here is that we need to use315 // The important part here is that we need to use
@@ -314,7 +331,7 @@
314 this, SLOT(cancel()));331 this, SLOT(cancel()));
315 connect(&m_trackDao, SIGNAL(progressVerifyTracksOutside(QString)),332 connect(&m_trackDao, SIGNAL(progressVerifyTracksOutside(QString)),
316 m_pProgress, SLOT(slotUpdate(QString)));333 m_pProgress, SLOT(slotUpdate(QString)));
317 scan();334 start();
318}335}
319336
320//slot337//slot
@@ -328,15 +345,11 @@
328 m_bCancelLibraryScan = 0;345 m_bCancelLibraryScan = 0;
329}346}
330347
331void LibraryScanner::scan()
332{
333 start(); // Starts the thread by calling run()
334}
335
336// Recursively scan a music library. Doesn't import tracks for any directories that348// Recursively scan a music library. Doesn't import tracks for any directories that
337// have already been scanned and have not changed. Changes are tracked by performing349// have already been scanned and have not changed. Changes are tracked by performing
338// a hash of the directory's file list, and those hashes are stored in the database.350// a hash of the directory's file list, and those hashes are stored in the database.
339bool LibraryScanner::recursiveScan(QString dirPath, QStringList& verifiedDirectories) {351bool LibraryScanner::recursiveScan(QString dirPath, QStringList& verifiedDirectories,
352 QSet<int>& restoredTracks, const int dirId) {
340 QDirIterator fileIt(dirPath, m_nameFilters, QDir::Files | QDir::NoDotAndDotDot);353 QDirIterator fileIt(dirPath, m_nameFilters, QDir::Files | QDir::NoDotAndDotDot);
341 QString currentFile;354 QString currentFile;
342 bool bScanFinishedCleanly = true;355 bool bScanFinishedCleanly = true;
@@ -376,7 +389,8 @@
376 }389 }
377390
378 // Rescan that mofo!391 // Rescan that mofo!
379 bScanFinishedCleanly = m_pCollection->importDirectory(dirPath, m_trackDao, m_nameFilters, &m_bCancelLibraryScan);392 bScanFinishedCleanly = m_pCollection->importDirectory(dirPath, m_trackDao, m_nameFilters,
393 restoredTracks,dirId,&m_bCancelLibraryScan);
380 } else { //prevHash == newHash394 } else { //prevHash == newHash
381 // Add the directory to the verifiedDirectories list, so that later they395 // Add the directory to the verifiedDirectories list, so that later they
382 // (and the tracks inside them) will be marked as verified396 // (and the tracks inside them) will be marked as verified
@@ -401,7 +415,7 @@
401 if (m_directoriesBlacklist.contains(nextPath))415 if (m_directoriesBlacklist.contains(nextPath))
402 continue;416 continue;
403417
404 if (!recursiveScan(nextPath, verifiedDirectories)) {418 if (!recursiveScan(nextPath, verifiedDirectories,restoredTracks,dirId)) {
405 bScanFinishedCleanly = false;419 bScanFinishedCleanly = false;
406 }420 }
407 }421 }
408422
=== modified file 'mixxx/src/library/libraryscanner.h'
--- mixxx/src/library/libraryscanner.h 2012-12-06 17:11:14 +0000
+++ mixxx/src/library/libraryscanner.h 2013-05-18 16:32:26 +0000
@@ -16,7 +16,6 @@
16* *16* *
17***************************************************************************/17***************************************************************************/
1818
19
20#ifndef LIBRARYSCANNER_H19#ifndef LIBRARYSCANNER_H
21#define LIBRARYSCANNER_H20#define LIBRARYSCANNER_H
2221
@@ -27,6 +26,7 @@
27#include "library/dao/cratedao.h"26#include "library/dao/cratedao.h"
28#include "library/dao/cuedao.h"27#include "library/dao/cuedao.h"
29#include "library/dao/libraryhashdao.h"28#include "library/dao/libraryhashdao.h"
29#include "library/dao/directorydao.h"
30#include "library/dao/playlistdao.h"30#include "library/dao/playlistdao.h"
31#include "library/dao/trackdao.h"31#include "library/dao/trackdao.h"
32#include "library/dao/analysisdao.h"32#include "library/dao/analysisdao.h"
@@ -46,18 +46,20 @@
46 void run();46 void run();
47 void scan(QString libraryPath, QWidget *parent);47 void scan(QString libraryPath, QWidget *parent);
48 void scan();48 void scan();
49 bool recursiveScan(QString dirPath, QStringList& verifiedDirectories);49
50 public slots:50 public slots:
51 void cancel();51 void cancel();
52 void resetCancel();52 void resetCancel();
53 signals:53 signals:
54 void scanFinished();54 void scanFinished();
55 void progressHashing(QString);55 void progressHashing(QString);
56 void tracksRestored(QSet<int>);
56 private:57 private:
58 bool recursiveScan(QString dirPath, QStringList& verifiedDirectories,
59 QSet<int>& restoredTracks,const int dirId);
57 TrackCollection* m_pCollection; // The library trackcollection60 TrackCollection* m_pCollection; // The library trackcollection
58 QSqlDatabase m_database; // Hang on to a different DB connection61 QSqlDatabase m_database; // Hang on to a different DB connection
59 // since we run in a different thread */62 // since we run in a different thread */
60 QString m_qLibraryPath; // The path to the library on disk
61 LibraryScannerDlg* m_pProgress; // The library scanning window63 LibraryScannerDlg* m_pProgress; // The library scanning window
6264
63 LibraryHashDAO m_libraryHashDao;65 LibraryHashDAO m_libraryHashDao;
@@ -65,6 +67,7 @@
65 PlaylistDAO m_playlistDao;67 PlaylistDAO m_playlistDao;
66 CrateDAO m_crateDao;68 CrateDAO m_crateDao;
67 AnalysisDao m_analysisDao;69 AnalysisDao m_analysisDao;
70 DirectoryDAO m_directoryDao;
68 TrackDAO m_trackDao;71 TrackDAO m_trackDao;
6972
70 QStringList m_nameFilters;73 QStringList m_nameFilters;
7174
=== modified file 'mixxx/src/library/librarytablemodel.cpp'
--- mixxx/src/library/librarytablemodel.cpp 2012-11-25 11:17:13 +0000
+++ mixxx/src/library/librarytablemodel.cpp 2013-05-18 16:32:26 +0000
@@ -1,33 +1,53 @@
1#include <QtCore>
2#include <QtGui>
3#include <QtSql>
41
5#include "library/trackcollection.h"
6#include "library/librarytablemodel.h"2#include "library/librarytablemodel.h"
7#include "library/queryutil.h"3#include "library/queryutil.h"
4#include "controlobjectthread.h"
5#include "controlobject.h"
8#include "mixxxutils.cpp"6#include "mixxxutils.cpp"
9#include "playermanager.h"7#include "playermanager.h"
108
11const QString LibraryTableModel::DEFAULT_LIBRARYFILTER =9const QString LibraryTableModel::DEFAULT_LIBRARYFILTER =
12 "mixxx_deleted=0 AND fs_deleted=0";10 "mixxx_deleted=0 AND fs_deleted=0";
1311
14LibraryTableModel::LibraryTableModel(QObject* parent,12LibraryTableModel::LibraryTableModel(QObject* parent,
15 TrackCollection* pTrackCollection,13 TrackCollection* pTrackCollection,
14 ConfigObject<ConfigValue>* pConfig,
16 QString settingsNamespace)15 QString settingsNamespace)
17 : BaseSqlTableModel(parent, pTrackCollection,16 : BaseSqlTableModel(parent, pTrackCollection, pConfig, settingsNamespace){
18 pTrackCollection->getDatabase(),17 setTableModel();
19 settingsNamespace),18}
20 m_trackDao(pTrackCollection->getTrackDAO()) {19
20LibraryTableModel::~LibraryTableModel() {
21}
22
23void LibraryTableModel::setTableModel(int id){
24 Q_UNUSED(id);
21 QStringList columns;25 QStringList columns;
22 columns << "library." + LIBRARYTABLE_ID;26 columns << "library."+LIBRARYTABLE_ID << "'' as preview";
23 columns << "'' as preview";27
2428 //prepareLibrary give a NULL to the constructor so check for it
25 QSqlQuery query(pTrackCollection->getDatabase());29 bool showMissing;
26 QString queryString = "CREATE TEMPORARY VIEW IF NOT EXISTS library_view AS "30 if (m_pConfig) {
27 "SELECT " + columns.join(",") +31 showMissing = m_pConfig->getValueString(
32 ConfigKey("[Library]","ShowMissingSongs"),"1").toInt();
33 } else {
34 showMissing = false;
35 }
36 QString tableName = "library_view";
37 QString libraryFilter;
38 if (showMissing) {
39 libraryFilter = "mixxx_deleted=0";
40 tableName.append("_missing");
41 } else {
42 libraryFilter = "mixxx_deleted=0 AND fs_deleted=0";
43 }
44
45 QSqlQuery query(m_pTrackCollection->getDatabase());
46 QString queryString = "CREATE TEMPORARY VIEW IF NOT EXISTS "+tableName+" AS "
47 "SELECT " + columns.join(", ") +
28 " FROM library INNER JOIN track_locations "48 " FROM library INNER JOIN track_locations "
29 "ON library.location = track_locations.id "49 "ON library.location = track_locations.id "
30 "WHERE (" + LibraryTableModel::DEFAULT_LIBRARYFILTER + ")";50 "WHERE (" + libraryFilter + ")";
31 query.prepare(queryString);51 query.prepare(queryString);
32 if (!query.exec()) {52 if (!query.exec()) {
33 LOG_FAILED_QUERY(query);53 LOG_FAILED_QUERY(query);
@@ -36,36 +56,16 @@
36 QStringList tableColumns;56 QStringList tableColumns;
37 tableColumns << LIBRARYTABLE_ID;57 tableColumns << LIBRARYTABLE_ID;
38 tableColumns << "preview";58 tableColumns << "preview";
39 setTable("library_view", LIBRARYTABLE_ID, tableColumns,59 setTable(tableName, LIBRARYTABLE_ID, tableColumns,
40 pTrackCollection->getTrackSource("default"));60 m_pTrackCollection->getTrackSource("default"));
4161
42 // BaseSqlTabelModel will setup the header info62 // BaseSqlTabelModel will setup the header info
43 initHeaderData();63 initHeaderData();
4464
45 setSearch("");65 setSearch("");
46 setDefaultSort(fieldIndex("artist"), Qt::AscendingOrder);66 setDefaultSort(fieldIndex("artist"), Qt::AscendingOrder);
4767}
48 connect(this, SIGNAL(doSearch(const QString&)),68
49 this, SLOT(slotSearch(const QString&)));
50}
51
52LibraryTableModel::~LibraryTableModel() {
53}
54
55bool LibraryTableModel::addTrack(const QModelIndex& index, QString location) {
56 Q_UNUSED(index);
57 QFileInfo fileInfo(location);
58
59 // Adds track, does not insert duplicates, handles unremoving logic.
60 int trackId = m_trackDao.addTrack(fileInfo, true);
61 if (trackId >= 0) {
62 // TODO(rryan) do not select since we will get a signal. instead, do
63 // something nice UI wise and select the track they dropped.
64 select(); //Repopulate the data model.
65 return true;
66 }
67 return false;
68}
6969
70int LibraryTableModel::addTracks(const QModelIndex& index, QList<QString> locations) {70int LibraryTableModel::addTracks(const QModelIndex& index, QList<QString> locations) {
71 Q_UNUSED(index);71 Q_UNUSED(index);
@@ -73,35 +73,11 @@
73 foreach (QString fileLocation, locations) {73 foreach (QString fileLocation, locations) {
74 fileInfoList.append(QFileInfo(fileLocation));74 fileInfoList.append(QFileInfo(fileLocation));
75 }75 }
76 QList<int> trackIds = m_trackDao.addTracks(fileInfoList, true);76 QList<int> trackIds = m_trackDAO.addTracks(fileInfoList, true);
77 select();77 select();
78 return trackIds.size();78 return trackIds.size();
79}79}
8080
81TrackPointer LibraryTableModel::getTrack(const QModelIndex& index) const {
82 int trackId = getTrackId(index);
83 return m_trackDao.getTrack(trackId);
84}
85
86void LibraryTableModel::moveTrack(const QModelIndex& sourceIndex,
87 const QModelIndex& destIndex) {
88 Q_UNUSED(sourceIndex);
89 Q_UNUSED(destIndex);
90 // Does nothing because we don't support reordering tracks in the library,
91 // and getCapabilities() reports that.
92}
93
94void LibraryTableModel::search(const QString& searchText) {
95 // qDebug() << "LibraryTableModel::search()" << searchText
96 // << QThread::currentThread();
97 emit(doSearch(searchText));
98}
99
100void LibraryTableModel::slotSearch(const QString& searchText) {
101 // qDebug() << "slotSearch()" << searchText << QThread::currentThread();
102 BaseSqlTableModel::search(searchText);
103}
104
105bool LibraryTableModel::isColumnInternal(int column) {81bool LibraryTableModel::isColumnInternal(int column) {
106 if ((column == fieldIndex(LIBRARYTABLE_ID)) ||82 if ((column == fieldIndex(LIBRARYTABLE_ID)) ||
107 (column == fieldIndex(LIBRARYTABLE_URL)) ||83 (column == fieldIndex(LIBRARYTABLE_URL)) ||
@@ -115,6 +91,7 @@
115 (column == fieldIndex(LIBRARYTABLE_BPM_LOCK)) ||91 (column == fieldIndex(LIBRARYTABLE_BPM_LOCK)) ||
116 (column == fieldIndex(LIBRARYTABLE_CHANNELS)) ||92 (column == fieldIndex(LIBRARYTABLE_CHANNELS)) ||
117 (column == fieldIndex(TRACKLOCATIONSTABLE_FSDELETED)) ||93 (column == fieldIndex(TRACKLOCATIONSTABLE_FSDELETED)) ||
94 (column == fieldIndex(TRACKLOCATIONSTABLE_MAINDIRID)) ||
118 (PlayerManager::numPreviewDecks() == 0 && column == fieldIndex("preview"))) {95 (PlayerManager::numPreviewDecks() == 0 && column == fieldIndex("preview"))) {
119 return true;96 return true;
120 }97 }
@@ -141,5 +118,6 @@
141 | TRACKMODELCAPS_HIDE118 | TRACKMODELCAPS_HIDE
142 | TRACKMODELCAPS_BPMLOCK119 | TRACKMODELCAPS_BPMLOCK
143 | TRACKMODELCAPS_CLEAR_BEATS120 | TRACKMODELCAPS_CLEAR_BEATS
144 | TRACKMODELCAPS_RESETPLAYED;121 | TRACKMODELCAPS_RESETPLAYED
122 | TRACKMODELCAPS_RELOCATE;
145}123}
146124
=== modified file 'mixxx/src/library/librarytablemodel.h'
--- mixxx/src/library/librarytablemodel.h 2013-05-18 16:23:08 +0000
+++ mixxx/src/library/librarytablemodel.h 2013-05-18 16:32:26 +0000
@@ -1,43 +1,24 @@
1#ifndef LIBRARYTABLEMODEL_H1#ifndef LIBRARYTABLEMODEL_H
2#define LIBRARYTABLEMODEL_H2#define LIBRARYTABLEMODEL_H
33
4#include <QtSql>
5#include <QtCore>
6
7#include "library/basesqltablemodel.h"4#include "library/basesqltablemodel.h"
8#include "library/trackmodel.h"
9#include "library/dao/trackdao.h"
10
11class TrackCollection;
125
13class LibraryTableModel : public BaseSqlTableModel {6class LibraryTableModel : public BaseSqlTableModel {
14 Q_OBJECT7 Q_OBJECT
15 public:8 public:
16 LibraryTableModel(QObject* parent, TrackCollection* pTrackCollection,9 LibraryTableModel(QObject* parent, TrackCollection* pTrackCollection,
10 ConfigObject<ConfigValue>* pConfig,
17 QString settingsNamespace="mixxx.db.model.library");11 QString settingsNamespace="mixxx.db.model.library");
18 virtual ~LibraryTableModel();12 virtual ~LibraryTableModel();
13 void setTableModel(int id =-1);
1914
20 TrackPointer getTrack(const QModelIndex& index) const;
21 void search(const QString& searchText);
22 bool isColumnInternal(int column);15 bool isColumnInternal(int column);
23 bool isColumnHiddenByDefault(int column);16 bool isColumnHiddenByDefault(int column);
24 bool addTrack(const QModelIndex& index, QString location);
25 // Takes a list of locations and add the tracks to the library. Returns the17 // Takes a list of locations and add the tracks to the library. Returns the
26 // number of successful additions.18 // number of successful additions.
27 int addTracks(const QModelIndex& index, QList<QString> locations);19 int addTracks(const QModelIndex& index, QList<QString> locations);
28 void moveTrack(const QModelIndex& sourceIndex,
29 const QModelIndex& destIndex);
30 TrackModel::CapabilitiesFlags getCapabilities() const;20 TrackModel::CapabilitiesFlags getCapabilities() const;
31 static const QString DEFAULT_LIBRARYFILTER;21 static const QString DEFAULT_LIBRARYFILTER;
32
33 private:
34 TrackDAO& m_trackDao;
35
36 private slots:
37 void slotSearch(const QString& searchText);
38
39 signals:
40 void doSearch(const QString& searchText);
41};22};
4223
43#endif24#endif
4425
=== added file 'mixxx/src/library/missingtablemodel.cpp'
--- mixxx/src/library/missingtablemodel.cpp 1970-01-01 00:00:00 +0000
+++ mixxx/src/library/missingtablemodel.cpp 2013-05-18 16:32:26 +0000
@@ -0,0 +1,126 @@
1#include <QtCore>
2#include <QtGui>
3#include <QtSql>
4#include "library/trackcollection.h"
5#include "library/missingtablemodel.h"
6#include "library/librarytablemodel.h"
7#include "mixxxutils.cpp"
8
9const QString MissingTableModel::MISSINGFILTER = "mixxx_deleted=0 AND fs_deleted=1";
10
11MissingTableModel::MissingTableModel(QObject* parent,
12 TrackCollection* pTrackCollection)
13 : BaseSqlTableModel(parent, pTrackCollection,
14 //TODO kain88 this is not quite right
15 NULL,
16 "mixxx.db.model.missing"),
17 m_pTrackCollection(pTrackCollection),
18 m_trackDao(m_pTrackCollection->getTrackDAO()) {
19
20 QSqlQuery query;
21 //query.prepare("DROP VIEW " + playlistTableName);
22 //query.exec();
23 QString tableName("missing_songs");
24
25 QStringList columns;
26 columns << "library." + LIBRARYTABLE_ID;
27
28 query.prepare("CREATE TEMPORARY VIEW IF NOT EXISTS " + tableName + " AS "
29 "SELECT "
30 + columns.join(",") +
31 " FROM library "
32 "INNER JOIN track_locations "
33 "ON library.location=track_locations.id "
34 "WHERE " + MissingTableModel::MISSINGFILTER);
35 if (!query.exec()) {
36 qDebug() << query.executedQuery() << query.lastError();
37 }
38
39 //Print out any SQL error, if there was one.
40 if (query.lastError().isValid()) {
41 qDebug() << __FILE__ << __LINE__ << query.lastError();
42 }
43
44 QStringList tableColumns;
45 tableColumns << LIBRARYTABLE_ID;
46 setTable(tableName, LIBRARYTABLE_ID, tableColumns,
47 m_pTrackCollection->getTrackSource("default"));
48
49 initHeaderData();
50 setDefaultSort(fieldIndex("artist"), Qt::AscendingOrder);
51 setSearch("");
52
53 connect(this, SIGNAL(doSearch(const QString&)),
54 this, SLOT(slotSearch(const QString&)));
55}
56
57MissingTableModel::~MissingTableModel() {
58}
59
60bool MissingTableModel::addTrack(const QModelIndex& index, QString location) {
61 Q_UNUSED(index);
62 Q_UNUSED(location);
63 return false;
64}
65
66TrackPointer MissingTableModel::getTrack(const QModelIndex& index) const {
67 //FIXME: use position instead of location for playlist tracks?
68
69 //const int locationColumnIndex = this->fieldIndex(LIBRARYTABLE_LOCATION);
70 //QString location = index.sibling(index.row(), locationColumnIndex).data().toString();
71 int trackId = getTrackId(index);
72 return m_trackDao.getTrack(trackId);
73}
74
75void MissingTableModel::purgeTracks(const QModelIndexList& indices) {
76 QList<int> trackIds;
77
78 foreach (QModelIndex index, indices) {
79 int trackId = getTrackId(index);
80 trackIds.append(trackId);
81 }
82
83 m_trackDao.purgeTracks(trackIds);
84
85 // TODO(rryan) : do not select, instead route event to BTC and notify from
86 // there.
87 select(); //Repopulate the data model.
88}
89
90
91void MissingTableModel::search(const QString& searchText) {
92 // qDebug() << "MissingTableModel::search()" << searchText
93 // << QThread::currentThread();
94 emit(doSearch(searchText));
95}
96
97void MissingTableModel::slotSearch(const QString& searchText) {
98 BaseSqlTableModel::search(searchText);
99}
100
101bool MissingTableModel::isColumnInternal(int column) {
102 if (column == fieldIndex(LIBRARYTABLE_ID) ||
103 column == fieldIndex(LIBRARYTABLE_PLAYED) ||
104 column == fieldIndex(LIBRARYTABLE_BPM_LOCK) ||
105 column == fieldIndex(LIBRARYTABLE_MIXXXDELETED) ||
106 column == fieldIndex(TRACKLOCATIONSTABLE_FSDELETED)) {
107 return true;
108 }
109 return false;
110}
111bool MissingTableModel::isColumnHiddenByDefault(int column) {
112 if (column == fieldIndex(LIBRARYTABLE_KEY)) {
113 return true;
114 }
115 return false;
116}
117
118/** Override flags from BaseSqlModel since we don't want edit this model */
119Qt::ItemFlags MissingTableModel::flags(const QModelIndex &index) const {
120 return readOnlyFlags(index);
121}
122
123TrackModel::CapabilitiesFlags MissingTableModel::getCapabilities() const {
124 return TRACKMODELCAPS_NONE
125 | TRACKMODELCAPS_PURGE;
126}
0127
=== removed file 'mixxx/src/library/missingtablemodel.cpp'
--- mixxx/src/library/missingtablemodel.cpp 2013-05-01 02:15:05 +0000
+++ mixxx/src/library/missingtablemodel.cpp 1970-01-01 00:00:00 +0000
@@ -1,125 +0,0 @@
1#include <QtCore>
2#include <QtGui>
3#include <QtSql>
4#include "library/trackcollection.h"
5#include "library/missingtablemodel.h"
6#include "library/librarytablemodel.h"
7#include "mixxxutils.cpp"
8
9const QString MissingTableModel::MISSINGFILTER = "mixxx_deleted=0 AND fs_deleted=1";
10
11MissingTableModel::MissingTableModel(QObject* parent,
12 TrackCollection* pTrackCollection)
13 : BaseSqlTableModel(parent, pTrackCollection,
14 pTrackCollection->getDatabase(),
15 "mixxx.db.model.missing"),
16 m_pTrackCollection(pTrackCollection),
17 m_trackDao(m_pTrackCollection->getTrackDAO()) {
18
19 QSqlQuery query(pTrackCollection->getDatabase());
20 //query.prepare("DROP VIEW " + playlistTableName);
21 //query.exec();
22 QString tableName("missing_songs");
23
24 QStringList columns;
25 columns << "library." + LIBRARYTABLE_ID;
26
27 query.prepare("CREATE TEMPORARY VIEW IF NOT EXISTS " + tableName + " AS "
28 "SELECT "
29 + columns.join(",") +
30 " FROM library "
31 "INNER JOIN track_locations "
32 "ON library.location=track_locations.id "
33 "WHERE " + MissingTableModel::MISSINGFILTER);
34 if (!query.exec()) {
35 qDebug() << query.executedQuery() << query.lastError();
36 }
37
38 //Print out any SQL error, if there was one.
39 if (query.lastError().isValid()) {
40 qDebug() << __FILE__ << __LINE__ << query.lastError();
41 }
42
43 QStringList tableColumns;
44 tableColumns << LIBRARYTABLE_ID;
45 setTable(tableName, LIBRARYTABLE_ID, tableColumns,
46 m_pTrackCollection->getTrackSource("default"));
47
48 initHeaderData();
49 setDefaultSort(fieldIndex("artist"), Qt::AscendingOrder);
50 setSearch("");
51
52 connect(this, SIGNAL(doSearch(const QString&)),
53 this, SLOT(slotSearch(const QString&)));
54}
55
56MissingTableModel::~MissingTableModel() {
57}
58
59bool MissingTableModel::addTrack(const QModelIndex& index, QString location) {
60 Q_UNUSED(index);
61 Q_UNUSED(location);
62 return false;
63}
64
65TrackPointer MissingTableModel::getTrack(const QModelIndex& index) const {
66 //FIXME: use position instead of location for playlist tracks?
67
68 //const int locationColumnIndex = this->fieldIndex(LIBRARYTABLE_LOCATION);
69 //QString location = index.sibling(index.row(), locationColumnIndex).data().toString();
70 int trackId = getTrackId(index);
71 return m_trackDao.getTrack(trackId);
72}
73
74void MissingTableModel::purgeTracks(const QModelIndexList& indices) {
75 QList<int> trackIds;
76
77 foreach (QModelIndex index, indices) {
78 int trackId = getTrackId(index);
79 trackIds.append(trackId);
80 }
81
82 m_trackDao.purgeTracks(trackIds);
83
84 // TODO(rryan) : do not select, instead route event to BTC and notify from
85 // there.
86 select(); //Repopulate the data model.
87}
88
89
90void MissingTableModel::search(const QString& searchText) {
91 // qDebug() << "MissingTableModel::search()" << searchText
92 // << QThread::currentThread();
93 emit(doSearch(searchText));
94}
95
96void MissingTableModel::slotSearch(const QString& searchText) {
97 BaseSqlTableModel::search(searchText);
98}
99
100bool MissingTableModel::isColumnInternal(int column) {
101 if (column == fieldIndex(LIBRARYTABLE_ID) ||
102 column == fieldIndex(LIBRARYTABLE_PLAYED) ||
103 column == fieldIndex(LIBRARYTABLE_BPM_LOCK) ||
104 column == fieldIndex(LIBRARYTABLE_MIXXXDELETED) ||
105 column == fieldIndex(TRACKLOCATIONSTABLE_FSDELETED)) {
106 return true;
107 }
108 return false;
109}
110bool MissingTableModel::isColumnHiddenByDefault(int column) {
111 if (column == fieldIndex(LIBRARYTABLE_KEY)) {
112 return true;
113 }
114 return false;
115}
116
117/** Override flags from BaseSqlModel since we don't want edit this model */
118Qt::ItemFlags MissingTableModel::flags(const QModelIndex &index) const {
119 return readOnlyFlags(index);
120}
121
122TrackModel::CapabilitiesFlags MissingTableModel::getCapabilities() const {
123 return TRACKMODELCAPS_NONE
124 | TRACKMODELCAPS_PURGE;
125}
1260
=== added file 'mixxx/src/library/missingtablemodel.h'
--- mixxx/src/library/missingtablemodel.h 1970-01-01 00:00:00 +0000
+++ mixxx/src/library/missingtablemodel.h 2013-05-18 16:32:26 +0000
@@ -0,0 +1,41 @@
1#ifndef MISSINGTABLEMODEL_H
2#define MISSINGTABLEMODEL_H
3
4#include <QtSql>
5#include <QItemDelegate>
6#include <QtCore>
7
8#include "trackmodel.h"
9#include "library/dao/trackdao.h"
10#include "library/basesqltablemodel.h"
11
12class TrackCollection;
13
14class MissingTableModel : public BaseSqlTableModel {
15 Q_OBJECT
16 public:
17 MissingTableModel(QObject* parent, TrackCollection* pTrackCollection);
18 virtual ~MissingTableModel();
19 virtual TrackPointer getTrack(const QModelIndex& index) const;
20 virtual void search(const QString& searchText);
21 virtual bool isColumnInternal(int column);
22 virtual bool isColumnHiddenByDefault(int column);
23 virtual void purgeTracks(const QModelIndexList& indices);
24 virtual bool addTrack(const QModelIndex& index, QString location);
25
26 Qt::ItemFlags flags(const QModelIndex &index) const;
27 TrackModel::CapabilitiesFlags getCapabilities() const;
28
29 private slots:
30 void slotSearch(const QString& searchText);
31
32 signals:
33 void doSearch(const QString& searchText);
34
35 private:
36 TrackCollection* m_pTrackCollection;
37 TrackDAO& m_trackDao;
38 static const QString MISSINGFILTER;
39};
40
41#endif
042
=== removed file 'mixxx/src/library/missingtablemodel.h'
--- mixxx/src/library/missingtablemodel.h 2012-08-10 15:03:46 +0000
+++ mixxx/src/library/missingtablemodel.h 1970-01-01 00:00:00 +0000
@@ -1,41 +0,0 @@
1#ifndef MISSINGTABLEMODEL_H
2#define MISSINGTABLEMODEL_H
3
4#include <QtSql>
5#include <QItemDelegate>
6#include <QtCore>
7
8#include "trackmodel.h"
9#include "library/dao/trackdao.h"
10#include "library/basesqltablemodel.h"
11
12class TrackCollection;
13
14class MissingTableModel : public BaseSqlTableModel {
15 Q_OBJECT
16 public:
17 MissingTableModel(QObject* parent, TrackCollection* pTrackCollection);
18 virtual ~MissingTableModel();
19 virtual TrackPointer getTrack(const QModelIndex& index) const;
20 virtual void search(const QString& searchText);
21 virtual bool isColumnInternal(int column);
22 virtual bool isColumnHiddenByDefault(int column);
23 virtual void purgeTracks(const QModelIndexList& indices);
24 virtual bool addTrack(const QModelIndex& index, QString location);
25
26 Qt::ItemFlags flags(const QModelIndex &index) const;
27 TrackModel::CapabilitiesFlags getCapabilities() const;
28
29 private slots:
30 void slotSearch(const QString& searchText);
31
32 signals:
33 void doSearch(const QString& searchText);
34
35 private:
36 TrackCollection* m_pTrackCollection;
37 TrackDAO& m_trackDao;
38 static const QString MISSINGFILTER;
39};
40
41#endif
420
=== modified file 'mixxx/src/library/mixxxlibraryfeature.cpp'
--- mixxx/src/library/mixxxlibraryfeature.cpp 2013-01-17 08:16:08 +0000
+++ mixxx/src/library/mixxxlibraryfeature.cpp 2013-05-18 16:32:26 +0000
@@ -1,13 +1,10 @@
1// mixxxlibraryfeature.cpp1// mixxxlibraryfeature.cpp
2// Created 8/23/2009 by RJ Ryan (rryan@mit.edu)2// Created 8/23/2009 by RJ Ryan (rryan@mit.edu)
33
4#include <QtDebug>
5
6#include "library/mixxxlibraryfeature.h"4#include "library/mixxxlibraryfeature.h"
75
8#include "library/basetrackcache.h"6#include "library/basetrackcache.h"
9#include "library/librarytablemodel.h"7#include "library/librarytablemodel.h"
10#include "library/missingtablemodel.h"
11#include "library/hiddentablemodel.h"8#include "library/hiddentablemodel.h"
12#include "library/queryutil.h"9#include "library/queryutil.h"
13#include "library/trackcollection.h"10#include "library/trackcollection.h"
@@ -88,11 +85,14 @@
88 connect(&m_trackDao, SIGNAL(dbTrackAdded(TrackPointer)),85 connect(&m_trackDao, SIGNAL(dbTrackAdded(TrackPointer)),
89 pBaseTrackCache, SLOT(slotDbTrackAdded(TrackPointer)));86 pBaseTrackCache, SLOT(slotDbTrackAdded(TrackPointer)));
9087
88
91 m_pBaseTrackCache = QSharedPointer<BaseTrackCache>(pBaseTrackCache);89 m_pBaseTrackCache = QSharedPointer<BaseTrackCache>(pBaseTrackCache);
92 pTrackCollection->addTrackSource(QString("default"), m_pBaseTrackCache);90 pTrackCollection->addTrackSource(QString("default"), m_pBaseTrackCache);
9391
94 // These rely on the 'default' track source being present.92 // These rely on the 'default' track source being present.
95 m_pLibraryTableModel = new LibraryTableModel(this, pTrackCollection);93 m_pLibraryTableModel = new LibraryTableModel(this, pTrackCollection,pConfig);
94 connect(this,SIGNAL(configChanged(QString,QString)),
95 m_pLibraryTableModel, SLOT(slotConfigChanged(QString, QString)));
9696
97 TreeItem* pRootItem = new TreeItem();97 TreeItem* pRootItem = new TreeItem();
98 TreeItem* pmissingChildItem = new TreeItem(kMissingTitle, kMissingTitle,98 TreeItem* pmissingChildItem = new TreeItem(kMissingTitle, kMissingTitle,
9999
=== modified file 'mixxx/src/library/mixxxlibraryfeature.h'
--- mixxx/src/library/mixxxlibraryfeature.h 2013-01-17 08:16:08 +0000
+++ mixxx/src/library/mixxxlibraryfeature.h 2013-05-18 16:32:26 +0000
@@ -7,6 +7,7 @@
7#include <QStringListModel>7#include <QStringListModel>
88
9#include "library/libraryfeature.h"9#include "library/libraryfeature.h"
10#include "configobject.h"
10#include "library/dao/trackdao.h"11#include "library/dao/trackdao.h"
11#include "treeitemmodel.h"12#include "treeitemmodel.h"
12#include "configobject.h"13#include "configobject.h"
@@ -34,12 +35,16 @@
34 void bindWidget(WLibrary* pLibrary,35 void bindWidget(WLibrary* pLibrary,
35 MixxxKeyboard* pKeyboard);36 MixxxKeyboard* pKeyboard);
3637
38 signals:
39 void configChanged(QString, QString);
40
37 public slots:41 public slots:
38 void activate();42 void activate();
39 void activateChild(const QModelIndex& index);43 void activateChild(const QModelIndex& index);
40 void refreshLibraryModels();44 void refreshLibraryModels();
4145
42 private:46 private:
47 TrackCollection* m_pTrackCollection;
43 const QString kMissingTitle;48 const QString kMissingTitle;
44 const QString kHiddenTitle;49 const QString kHiddenTitle;
45 QSharedPointer<BaseTrackCache> m_pBaseTrackCache;50 QSharedPointer<BaseTrackCache> m_pBaseTrackCache;
@@ -49,7 +54,6 @@
49 TreeItemModel m_childModel;54 TreeItemModel m_childModel;
50 TrackDAO& m_trackDao;55 TrackDAO& m_trackDao;
51 ConfigObject<ConfigValue>* m_pConfig;56 ConfigObject<ConfigValue>* m_pConfig;
52 TrackCollection* m_pTrackCollection;
53};57};
5458
55#endif /* MIXXXLIBRARYFEATURE_H */59#endif /* MIXXXLIBRARYFEATURE_H */
5660
=== modified file 'mixxx/src/library/playlistfeature.cpp'
--- mixxx/src/library/playlistfeature.cpp 2013-05-12 22:17:32 +0000
+++ mixxx/src/library/playlistfeature.cpp 2013-05-18 16:32:26 +0000
@@ -22,11 +22,12 @@
22PlaylistFeature::PlaylistFeature(QObject* parent,22PlaylistFeature::PlaylistFeature(QObject* parent,
23 TrackCollection* pTrackCollection,23 TrackCollection* pTrackCollection,
24 ConfigObject<ConfigValue>* pConfig)24 ConfigObject<ConfigValue>* pConfig)
25 : BasePlaylistFeature(parent, pConfig, pTrackCollection,25 : BasePlaylistFeature(parent, pConfig, pTrackCollection,"PLAYLISTHOME") {
26 "PLAYLISTHOME") {
27 m_pPlaylistTableModel = new PlaylistTableModel(this, pTrackCollection,26 m_pPlaylistTableModel = new PlaylistTableModel(this, pTrackCollection,
28 "mixxx.db.model.playlist");27 "mixxx.db.model.playlist",
2928 pConfig);
29 connect(this, SIGNAL(configChanged(QString,QString)),
30 m_pPlaylistTableModel, SLOT(slotConfigChanged(QString,QString)));
30 //construct child model31 //construct child model
31 TreeItem *rootItem = new TreeItem();32 TreeItem *rootItem = new TreeItem();
32 m_childModel.setRootItem(rootItem);33 m_childModel.setRootItem(rootItem);
@@ -179,7 +180,7 @@
179180
180 if (type != PlaylistDAO::PLHT_UNKNOWN) {181 if (type != PlaylistDAO::PLHT_UNKNOWN) {
181 // Switch the view to the playlist.182 // Switch the view to the playlist.
182 m_pPlaylistTableModel->setPlaylist(playlistId);183 m_pPlaylistTableModel->setTableModel(playlistId);
183 // Update selection184 // Update selection
184 emit(featureSelect(this, m_lastRightClickedIndex));185 emit(featureSelect(this, m_lastRightClickedIndex));
185 }186 }
186187
=== modified file 'mixxx/src/library/playlistfeature.h'
--- mixxx/src/library/playlistfeature.h 2013-05-18 16:23:08 +0000
+++ mixxx/src/library/playlistfeature.h 2013-05-18 16:32:26 +0000
@@ -15,7 +15,8 @@
15class PlaylistFeature : public BasePlaylistFeature {15class PlaylistFeature : public BasePlaylistFeature {
16 Q_OBJECT16 Q_OBJECT
17 public:17 public:
18 PlaylistFeature(QObject* parent, TrackCollection* pTrackCollection,18 PlaylistFeature(QObject* parent,
19 TrackCollection* pTrackCollection,
19 ConfigObject<ConfigValue>* pConfig);20 ConfigObject<ConfigValue>* pConfig);
20 virtual ~PlaylistFeature();21 virtual ~PlaylistFeature();
2122
@@ -25,6 +26,9 @@
25 bool dropAcceptChild(const QModelIndex& index, QList<QUrl> urls, QWidget *pSource);26 bool dropAcceptChild(const QModelIndex& index, QList<QUrl> urls, QWidget *pSource);
26 bool dragMoveAcceptChild(const QModelIndex& index, QUrl url);27 bool dragMoveAcceptChild(const QModelIndex& index, QUrl url);
2728
29 signals:
30 void configChanged(QString,QString);
31
28 public slots:32 public slots:
29 void onRightClick(const QPoint& globalPos);33 void onRightClick(const QPoint& globalPos);
30 void onRightClickChild(const QPoint& globalPos, QModelIndex index);34 void onRightClickChild(const QPoint& globalPos, QModelIndex index);
3135
=== modified file 'mixxx/src/library/playlisttablemodel.cpp'
--- mixxx/src/library/playlisttablemodel.cpp 2013-05-12 22:17:32 +0000
+++ mixxx/src/library/playlisttablemodel.cpp 2013-05-18 16:32:26 +0000
@@ -1,50 +1,56 @@
1#include <QtCore>
2#include <QtGui>
3#include <QtSql>
4#include <QDateTime>
5#include "library/trackcollection.h"
6#include "library/playlisttablemodel.h"1#include "library/playlisttablemodel.h"
7#include "library/queryutil.h"2#include "library/queryutil.h"
8#include "mixxxutils.cpp"3#include "mixxxutils.cpp"
9#include "playermanager.h"4#include "playermanager.h"
105
11PlaylistTableModel::PlaylistTableModel(QObject* parent,6PlaylistTableModel::PlaylistTableModel(QObject* parent,
12 TrackCollection* pTrackCollection,7 TrackCollection* pTrackCollection,
13 QString settingsNamespace,8 QString settingsNamespace,
14 bool showAll)9 ConfigObject<ConfigValue>* pConfig,
15 : BaseSqlTableModel(parent, pTrackCollection,10 bool showAll)
16 pTrackCollection->getDatabase(),11 : BaseSqlTableModel(parent, pTrackCollection, pConfig, settingsNamespace),
17 settingsNamespace),12 m_playlistDao(m_pTrackCollection->getPlaylistDAO()),
18 m_pTrackCollection(pTrackCollection),13 m_iPlaylistId(-1),
19 m_playlistDao(m_pTrackCollection->getPlaylistDAO()),14 m_showAll(showAll) {
20 m_trackDao(m_pTrackCollection->getTrackDAO()),
21 m_iPlaylistId(-1) {
22 connect(this, SIGNAL(doSearch(const QString&)),
23 this, SLOT(slotSearch(const QString&)));
24 m_showAll = showAll;
25}15}
2616
27PlaylistTableModel::~PlaylistTableModel() {17PlaylistTableModel::~PlaylistTableModel() {
28}18}
2919
30void PlaylistTableModel::setPlaylist(int playlistId) {20void PlaylistTableModel::setTableModel(int playlistId) {
31 //qDebug() << "PlaylistTableModel::setPlaylist" << playlistId;21 //qDebug() << "PlaylistTableModel::setPlaylist" << playlistId;
3222
33 if (m_iPlaylistId == playlistId) {23 if (playlistId == m_iPlaylistId) {
34 qDebug() << "Already focused on playlist " << playlistId;24 qDebug() << "Already focused on playlist " << playlistId;
35 return;25 return;
26 } else if (playlistId == -1) {
27 // calls from parent class use -1 as id then just set the current playlist
28 playlistId = m_iPlaylistId;
36 }29 }
3730
38 m_iPlaylistId = playlistId;31 m_iPlaylistId = playlistId;
39 QString playlistTableName = "playlist_" + QString::number(m_iPlaylistId);32 QString playlistTableName = "playlist_" + QString::number(m_iPlaylistId)+"_";
33
40 QSqlQuery query(m_pTrackCollection->getDatabase());34 QSqlQuery query(m_pTrackCollection->getDatabase());
41 FieldEscaper escaper(m_pTrackCollection->getDatabase());35 FieldEscaper escaper(m_pTrackCollection->getDatabase());
4236
43 QStringList columns;37 QStringList columns;
44 columns << PLAYLISTTRACKSTABLE_TRACKID + " as " + LIBRARYTABLE_ID38 QStringList tableColumns;
45 << PLAYLISTTRACKSTABLE_POSITION39 QString filter;
46 << PLAYLISTTRACKSTABLE_DATETIMEADDED40 columns << "PlaylistTracks."+PLAYLISTTRACKSTABLE_TRACKID + " as " + LIBRARYTABLE_ID
47 << "'' as preview";41 << "PlaylistTracks."+PLAYLISTTRACKSTABLE_POSITION
42 << "PlaylistTracks."+PLAYLISTTRACKSTABLE_DATETIMEADDED
43 << "'' as preview";
44 tableColumns << PLAYLISTTRACKSTABLE_TRACKID
45 << PLAYLISTTRACKSTABLE_POSITION
46 << PLAYLISTTRACKSTABLE_DATETIMEADDED;
47 bool showMissing = m_pConfig->getValueString(ConfigKey("[Library]","ShowMissingSongs"),"1").toInt();
48 if (showMissing) {
49 filter = "library.mixxx_deleted=0";
50 playlistTableName.append("_missing");
51 } else {
52 filter = "library.mixxx_deleted=0 AND track_locations.fs_deleted=0";
53 }
4854
49 // We drop files that have been explicitly deleted from mixxx55 // We drop files that have been explicitly deleted from mixxx
50 // (mixxx_deleted=0) from the view. There was a bug in <= 1.9.0 where56 // (mixxx_deleted=0) from the view. There was a bug in <= 1.9.0 where
@@ -54,12 +60,13 @@
54 "CREATE TEMPORARY VIEW IF NOT EXISTS %1 AS "60 "CREATE TEMPORARY VIEW IF NOT EXISTS %1 AS "
55 "SELECT %2 FROM PlaylistTracks "61 "SELECT %2 FROM PlaylistTracks "
56 "INNER JOIN library ON library.id = PlaylistTracks.track_id "62 "INNER JOIN library ON library.id = PlaylistTracks.track_id "
63 "INNER JOIN track_locations ON track_locations.id=PlaylistTracks.track_id "
57 "WHERE PlaylistTracks.playlist_id = %3")64 "WHERE PlaylistTracks.playlist_id = %3")
58 .arg(escaper.escapeString(playlistTableName),65 .arg(escaper.escapeString(playlistTableName),
59 columns.join(","),66 columns.join(","),
60 QString::number(playlistId));67 QString::number(playlistId));
61 if (!m_showAll) {68 if (!m_showAll) {
62 queryString.append(" AND library.mixxx_deleted = 0");69 queryString.append(" AND " + filter);
63 }70 }
64 query.prepare(queryString);71 query.prepare(queryString);
65 if (!query.exec()) {72 if (!query.exec()) {
@@ -68,7 +75,7 @@
6875
69 columns[0] = LIBRARYTABLE_ID;76 columns[0] = LIBRARYTABLE_ID;
70 columns[3] = "preview";77 columns[3] = "preview";
71 setTable(playlistTableName, columns[0], columns,78 setTable(playlistTableName, tableColumns[0], tableColumns,
72 m_pTrackCollection->getTrackSource("default"));79 m_pTrackCollection->getTrackSource("default"));
73 initHeaderData();80 initHeaderData();
74 setSearch("");81 setSearch("");
@@ -76,45 +83,6 @@
76 setSort(defaultSortColumn(), defaultSortOrder());83 setSort(defaultSortColumn(), defaultSortOrder());
77}84}
7885
79bool PlaylistTableModel::addTrack(const QModelIndex& index, QString location) {
80 const int positionColumn = fieldIndex(PLAYLISTTRACKSTABLE_POSITION);
81 int position = index.sibling(index.row(), positionColumn).data().toInt();
82
83 // Handle weird cases like a drag-and-drop to an invalid index
84 if (position <= 0) {
85 position = rowCount() + 1;
86 }
87
88 // If a track is dropped but it isn't in the library, then add it because
89 // the user probably dropped a file from outside Mixxx into this playlist.
90 QFileInfo fileInfo(location);
91
92 // Adds track, does not insert duplicates, handles unremoving logic.
93 int trackId = m_trackDao.addTrack(fileInfo, true);
94
95 // Do nothing if the location still isn't in the database.
96 if (trackId < 0) {
97 return false;
98 }
99
100 m_playlistDao.insertTrackIntoPlaylist(trackId, m_iPlaylistId, position);
101
102 // TODO(rryan) signal an add to the base, don't select
103 select(); //Repopulate the data model.
104 return true;
105}
106
107bool PlaylistTableModel::appendTrack(int trackId) {
108 if (trackId < 0) {
109 return false;
110 }
111
112 bool bSuccess = m_playlistDao.appendTrackToPlaylist(trackId, m_iPlaylistId);
113
114 select(); //Repopulate the data model.
115 return bSuccess;
116}
117
118int PlaylistTableModel::addTracks(const QModelIndex& index, QList<QString> locations) {86int PlaylistTableModel::addTracks(const QModelIndex& index, QList<QString> locations) {
119 const int positionColumn = fieldIndex(PLAYLISTTRACKSTABLE_POSITION);87 const int positionColumn = fieldIndex(PLAYLISTTRACKSTABLE_POSITION);
120 int position = index.sibling(index.row(), positionColumn).data().toInt();88 int position = index.sibling(index.row(), positionColumn).data().toInt();
@@ -129,7 +97,7 @@
129 fileInfoList.append(QFileInfo(fileLocation));97 fileInfoList.append(QFileInfo(fileLocation));
130 }98 }
13199
132 QList<int> trackIds = m_trackDao.addTracks(fileInfoList, true);100 QList<int> trackIds = m_trackDAO.addTracks(fileInfoList, true);
133101
134 int tracksAdded = m_playlistDao.insertTracksIntoPlaylist(102 int tracksAdded = m_playlistDao.insertTracksIntoPlaylist(
135 trackIds, m_iPlaylistId, position);103 trackIds, m_iPlaylistId, position);
@@ -144,13 +112,15 @@
144 return tracksAdded;112 return tracksAdded;
145}113}
146114
147TrackPointer PlaylistTableModel::getTrack(const QModelIndex& index) const {115bool PlaylistTableModel::appendTrack(int trackId) {
148 //FIXME: use position instead of location for playlist tracks?116 if (trackId < 0) {
149117 return false;
150 //const int locationColumnIndex = this->fieldIndex(LIBRARYTABLE_LOCATION);118 }
151 //QString location = index.sibling(index.row(), locationColumnIndex).data().toString();119
152 int trackId = getTrackId(index);120 m_playlistDao.appendTrackToPlaylist(trackId, m_iPlaylistId);
153 return m_trackDao.getTrack(trackId);121
122 select(); //Repopulate the data model.
123 return true;
154}124}
155125
156void PlaylistTableModel::removeTrack(const QModelIndex& index) {126void PlaylistTableModel::removeTrack(const QModelIndex& index) {
@@ -226,18 +196,17 @@
226196
227 //Insert the song into the PlaylistTracks table197 //Insert the song into the PlaylistTracks table
228198
229 /** ALGORITHM for code below199 // ALGORITHM for code below
230 Case 1: destination < source (newPos < oldPos)200 // Case 1: destination < source (newPos < oldPos)
231 1) Set position = -1 where pos=source -- Gives that track a dummy index to keep stuff simple.201 // 1) Set position = -1 where pos=source -- Gives that track a dummy index to keep stuff simple.
232 2) Decrement position where pos > source202 // 2) Decrement position where pos > source
233 3) increment position where pos > dest203 // 3) increment position where pos > dest
234 4) Set position = dest where pos=-1 -- Move track from dummy pos to final destination.204 // 4) Set position = dest where pos=-1 -- Move track from dummy pos to final destination.
235205
236 Case 2: destination > source (newPos > oldPos)206 // Case 2: destination > source (newPos > oldPos)
237 1) Set position=-1 where pos=source -- Give track a dummy index again.207 // 1) Set position=-1 where pos=source -- Give track a dummy index again.
238 2) Decrement position where pos > source AND pos <= dest208 // 2) Decrement position where pos > source AND pos <= dest
239 3) Set postion=dest where pos=-1 -- Move that track from dummy pos to final destination209 // 3) Set postion=dest where pos=-1 -- Move that track from dummy pos to final destination
240 */
241210
242 QString queryString;211 QString queryString;
243 if (newPosition < oldPosition) {212 if (newPosition < oldPosition) {
@@ -336,17 +305,6 @@
336 select();305 select();
337}306}
338307
339void PlaylistTableModel::search(const QString& searchText) {
340 // qDebug() << "PlaylistTableModel::search()" << searchText
341 // << QThread::currentThread();
342 emit(doSearch(searchText));
343}
344
345void PlaylistTableModel::slotSearch(const QString& searchText) {
346 BaseSqlTableModel::search(
347 searchText, LibraryTableModel::DEFAULT_LIBRARYFILTER);
348}
349
350bool PlaylistTableModel::isColumnInternal(int column) {308bool PlaylistTableModel::isColumnInternal(int column) {
351 if (column == fieldIndex(LIBRARYTABLE_ID) ||309 if (column == fieldIndex(LIBRARYTABLE_ID) ||
352 column == fieldIndex(PLAYLISTTRACKSTABLE_TRACKID) ||310 column == fieldIndex(PLAYLISTTRACKSTABLE_TRACKID) ||
@@ -354,6 +312,7 @@
354 column == fieldIndex(LIBRARYTABLE_MIXXXDELETED) ||312 column == fieldIndex(LIBRARYTABLE_MIXXXDELETED) ||
355 column == fieldIndex(LIBRARYTABLE_BPM_LOCK) ||313 column == fieldIndex(LIBRARYTABLE_BPM_LOCK) ||
356 column == fieldIndex(TRACKLOCATIONSTABLE_FSDELETED) ||314 column == fieldIndex(TRACKLOCATIONSTABLE_FSDELETED) ||
315 column == fieldIndex(TRACKLOCATIONSTABLE_MAINDIRID) ||
357 (PlayerManager::numPreviewDecks() == 0 && column == fieldIndex("preview"))) {316 (PlayerManager::numPreviewDecks() == 0 && column == fieldIndex("preview"))) {
358 return true;317 return true;
359 }318 }
@@ -380,6 +339,7 @@
380 | TRACKMODELCAPS_LOADTOSAMPLER339 | TRACKMODELCAPS_LOADTOSAMPLER
381 | TRACKMODELCAPS_LOADTOPREVIEWDECK340 | TRACKMODELCAPS_LOADTOPREVIEWDECK
382 | TRACKMODELCAPS_REMOVE341 | TRACKMODELCAPS_REMOVE
342 | TRACKMODELCAPS_RELOCATE
383 | TRACKMODELCAPS_BPMLOCK343 | TRACKMODELCAPS_BPMLOCK
384 | TRACKMODELCAPS_CLEAR_BEATS344 | TRACKMODELCAPS_CLEAR_BEATS
385 | TRACKMODELCAPS_RESETPLAYED;345 | TRACKMODELCAPS_RESETPLAYED;
386346
=== modified file 'mixxx/src/library/playlisttablemodel.h'
--- mixxx/src/library/playlisttablemodel.h 2012-08-10 15:03:46 +0000
+++ mixxx/src/library/playlisttablemodel.h 2013-05-18 16:32:26 +0000
@@ -1,54 +1,38 @@
1#ifndef PLAYLISTTABLEMODEL_H1#ifndef PLAYLISTTABLEMODEL_H
2#define PLAYLISTTABLEMODEL_H2#define PLAYLISTTABLEMODEL_H
33
4#include <QtSql>
5#include <QItemDelegate>
6#include <QtCore>
7
8#include "library/basesqltablemodel.h"4#include "library/basesqltablemodel.h"
9#include "library/dao/playlistdao.h"5#include "library/dao/playlistdao.h"
10#include "library/dao/trackdao.h"
11#include "library/librarytablemodel.h"
12
13class TrackCollection;
146
15class PlaylistTableModel : public BaseSqlTableModel {7class PlaylistTableModel : public BaseSqlTableModel {
16 Q_OBJECT8 Q_OBJECT
17 public:9 public:
18 PlaylistTableModel(QObject* parent, TrackCollection* pTrackCollection,10 PlaylistTableModel(QObject* parent, TrackCollection* pTrackCollection,
19 QString settingsNamespace,bool showAll=false);11 QString settingsNamespace,
12 ConfigObject<ConfigValue>* pConfig,
13 bool showAll=false);
20 virtual ~PlaylistTableModel();14 virtual ~PlaylistTableModel();
21 void setPlaylist(int playlistId);15 void setTableModel(int playlistId = -1);
16
22 int getPlaylist() const {17 int getPlaylist() const {
23 return m_iPlaylistId;18 return m_iPlaylistId;
24 }19 }
25 virtual TrackPointer getTrack(const QModelIndex& index) const;
2620
27 virtual void search(const QString& searchText);21 bool isColumnInternal(int column);
28 virtual bool isColumnInternal(int column);22 bool isColumnHiddenByDefault(int column);
29 virtual bool isColumnHiddenByDefault(int column);23 void removeTrack(const QModelIndex& index);
30 virtual void removeTrack(const QModelIndex& index);24 void removeTracks(const QModelIndexList& indices);
31 virtual void removeTracks(const QModelIndexList& indices);
32 virtual bool addTrack(const QModelIndex& index, QString location);
33 virtual bool appendTrack(int trackId);
34 // Adding multiple tracks at one to a playlist. Returns the number of25 // Adding multiple tracks at one to a playlist. Returns the number of
35 // successful additions.26 // successful additions.
36 virtual int addTracks(const QModelIndex& index, QList<QString> locations);27 int addTracks(const QModelIndex& index, QList<QString> locations);
37 virtual void moveTrack(const QModelIndex& sourceIndex, const QModelIndex& destIndex);28 bool appendTrack(int trackId);
38 virtual void shuffleTracks(const QModelIndex& shuffleStartIndex);29 void moveTrack(const QModelIndex& sourceIndex,
3930 const QModelIndex& destIndex);
31 void shuffleTracks(const QModelIndex& shuffleStartIndex);
40 TrackModel::CapabilitiesFlags getCapabilities() const;32 TrackModel::CapabilitiesFlags getCapabilities() const;
4133
42 private slots:
43 void slotSearch(const QString& searchText);
44
45 signals:
46 void doSearch(const QString& searchText);
47
48 private:34 private:
49 TrackCollection* m_pTrackCollection;
50 PlaylistDAO& m_playlistDao;35 PlaylistDAO& m_playlistDao;
51 TrackDAO& m_trackDao;
52 int m_iPlaylistId;36 int m_iPlaylistId;
53 bool m_showAll;37 bool m_showAll;
54};38};
5539
=== modified file 'mixxx/src/library/preparelibrarytablemodel.cpp'
--- mixxx/src/library/preparelibrarytablemodel.cpp 2012-12-08 14:33:51 +0000
+++ mixxx/src/library/preparelibrarytablemodel.cpp 2013-05-18 16:32:26 +0000
@@ -2,34 +2,23 @@
22
3#include "preparelibrarytablemodel.h"3#include "preparelibrarytablemodel.h"
4#include "library/trackcollection.h"4#include "library/trackcollection.h"
5#include "configobject.h"
56
6const QString RECENT_FILTER = "datetime_added > datetime('now', '-7 days')";7const QString RECENT_FILTER = "datetime_added > datetime('now', '-7 days')";
78
8PrepareLibraryTableModel::PrepareLibraryTableModel(QObject* parent,9PrepareLibraryTableModel::PrepareLibraryTableModel(QObject* parent,
9 TrackCollection* pTrackCollection)10 TrackCollection* pTrackCollection)
10 : LibraryTableModel(parent, pTrackCollection,11 : LibraryTableModel(parent, pTrackCollection, NULL,
11 "mixxx.db.model.prepare") {12 "mixxx.db.model.prepare") {
12 m_bShowRecentSongs = true;13 m_bShowRecentSongs = true;
13 setSearch("", RECENT_FILTER);14 setSearch("", RECENT_FILTER);
1415
15 connect(this, SIGNAL(doSearch(const QString&)),
16 this, SLOT(slotSearch(const QString&)));
17}16}
1817
1918
20PrepareLibraryTableModel::~PrepareLibraryTableModel() {19PrepareLibraryTableModel::~PrepareLibraryTableModel() {
21}20}
2221
23void PrepareLibraryTableModel::search(const QString& searchText) {
24 // qDebug() << "PrepareLibraryTableModel::search()" << searchText
25 // << QThread::currentThread();
26 emit(doSearch(searchText));
27}
28
29void PrepareLibraryTableModel::slotSearch(const QString& searchText) {
30 BaseSqlTableModel::search(searchText,
31 m_bShowRecentSongs ? RECENT_FILTER : QString());
32}
3322
34void PrepareLibraryTableModel::showRecentSongs() {23void PrepareLibraryTableModel::showRecentSongs() {
35 m_bShowRecentSongs = true;24 m_bShowRecentSongs = true;
3625
=== modified file 'mixxx/src/library/preparelibrarytablemodel.h'
--- mixxx/src/library/preparelibrarytablemodel.h 2012-11-25 11:17:13 +0000
+++ mixxx/src/library/preparelibrarytablemodel.h 2013-05-18 16:32:26 +0000
@@ -8,18 +8,13 @@
8{8{
9 Q_OBJECT9 Q_OBJECT
10 public:10 public:
11 PrepareLibraryTableModel(QObject* parent, TrackCollection* pTrackCollection);11 PrepareLibraryTableModel(QObject* parent,
12 TrackCollection* pTrackCollection);
12 virtual ~PrepareLibraryTableModel();13 virtual ~PrepareLibraryTableModel();
1314
14 virtual void search(const QString& searchText);
15
16 public slots:15 public slots:
17 void showRecentSongs();16 void showRecentSongs();
18 void showAllSongs();17 void showAllSongs();
19 private slots:
20 void slotSearch(const QString& searchText);
21 signals:
22 void doSearch(const QString& searchText);
23 private:18 private:
24 bool m_bShowRecentSongs;19 bool m_bShowRecentSongs;
25};20};
2621
=== modified file 'mixxx/src/library/promotracksfeature.cpp'
--- mixxx/src/library/promotracksfeature.cpp 2012-12-12 17:23:33 +0000
+++ mixxx/src/library/promotracksfeature.cpp 2013-05-18 16:32:26 +0000
@@ -46,7 +46,7 @@
46 m_pTrackCollection(pTrackCollection),46 m_pTrackCollection(pTrackCollection),
47 m_pFeaturedArtistsView(NULL),47 m_pFeaturedArtistsView(NULL),
48 m_pBundledSongsView(NULL),48 m_pBundledSongsView(NULL),
49 m_downloadsTableModel(this, pTrackCollection),49 m_downloadsTableModel(this, pTrackCollection,config),
50 m_bFirstRun(firstRun) {50 m_bFirstRun(firstRun) {
5151
52 m_sPromoRemoteHTMLLocation = QString("http://promo.mixxx.org/%1/index.html").arg(MIXXX_PROMO_VERSION); //m_pConfig->getConfigPath() + "/promo/promotracks.html";52 m_sPromoRemoteHTMLLocation = QString("http://promo.mixxx.org/%1/index.html").arg(MIXXX_PROMO_VERSION); //m_pConfig->getConfigPath() + "/promo/promotracks.html";
5353
=== modified file 'mixxx/src/library/proxytrackmodel.cpp'
--- mixxx/src/library/proxytrackmodel.cpp 2013-01-19 12:15:22 +0000
+++ mixxx/src/library/proxytrackmodel.cpp 2013-05-18 16:32:26 +0000
@@ -2,6 +2,7 @@
2// Created 10/22/2009 by RJ Ryan (rryan@mit.edu)2// Created 10/22/2009 by RJ Ryan (rryan@mit.edu)
33
4#include <QtCore>4#include <QtCore>
5#include <QMessageBox>
5#include <QVariant>6#include <QVariant>
67
7#include "library/proxytrackmodel.h"8#include "library/proxytrackmodel.h"
@@ -40,7 +41,8 @@
40 return m_pTrackModel->getTrackLocation(indexSource);41 return m_pTrackModel->getTrackLocation(indexSource);
41}42}
4243
43void ProxyTrackModel::search(const QString& searchText) {44void ProxyTrackModel::search(const QString& searchText, const QString& extraFilter) {
45 Q_UNUSED(extraFilter);
44 if (m_bHandleSearches) {46 if (m_bHandleSearches) {
45 m_currentSearch = searchText;47 m_currentSearch = searchText;
46 setFilterFixedString(searchText);48 setFilterFixedString(searchText);
@@ -64,10 +66,6 @@
64 return m_pTrackModel->isColumnHiddenByDefault(column);66 return m_pTrackModel->isColumnHiddenByDefault(column);
65}67}
6668
67void ProxyTrackModel::removeTrack(const QModelIndex& index) {
68 QModelIndex indexSource = mapToSource(index);
69 m_pTrackModel->removeTrack(indexSource);
70}
7169
72void ProxyTrackModel::removeTracks(const QModelIndexList& indices) {70void ProxyTrackModel::removeTracks(const QModelIndexList& indices) {
73 QModelIndexList translatedList;71 QModelIndexList translatedList;
@@ -78,11 +76,6 @@
78 m_pTrackModel->removeTracks(translatedList);76 m_pTrackModel->removeTracks(translatedList);
79}77}
8078
81bool ProxyTrackModel::addTrack(const QModelIndex& index, QString location) {
82 QModelIndex indexSource = mapToSource(index);
83 return m_pTrackModel->addTrack(indexSource, location);
84}
85
86void ProxyTrackModel::moveTrack(const QModelIndex& sourceIndex,79void ProxyTrackModel::moveTrack(const QModelIndex& sourceIndex,
87 const QModelIndex& destIndex) {80 const QModelIndex& destIndex) {
88 QModelIndex sourceIndexSource = mapToSource(sourceIndex);81 QModelIndex sourceIndexSource = mapToSource(sourceIndex);
@@ -95,7 +88,19 @@
95}88}
9689
97TrackModel::CapabilitiesFlags ProxyTrackModel::getCapabilities() const {90TrackModel::CapabilitiesFlags ProxyTrackModel::getCapabilities() const {
98 return m_pTrackModel->getCapabilities();91 return TRACKMODELCAPS_NONE
92 | TRACKMODELCAPS_DELETEFS;
93}
94
95void ProxyTrackModel::deleteTracks(const QModelIndexList& indices){
96 QMessageBox::StandardButton btn = QMessageBox::question(
97 NULL, tr("Confirm Delete"),
98 tr("Are you sure you want to delete these files?"),
99 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
100 if (btn == QMessageBox::No) {
101 return ;
102 }
103 //TODO(kain88) ask rryan what the row of the location field is
99}104}
100105
101bool ProxyTrackModel::filterAcceptsRow(int sourceRow,106bool ProxyTrackModel::filterAcceptsRow(int sourceRow,
102107
=== modified file 'mixxx/src/library/proxytrackmodel.h'
--- mixxx/src/library/proxytrackmodel.h 2012-11-25 09:33:00 +0000
+++ mixxx/src/library/proxytrackmodel.h 2013-05-18 16:32:26 +0000
@@ -16,7 +16,7 @@
16// calling the composed TrackModel. If the bHandleSearches flag is set, the16// calling the composed TrackModel. If the bHandleSearches flag is set, the
17// TrackModel search calls will not be delivered to the composed TrackModel17// TrackModel search calls will not be delivered to the composed TrackModel
18// because filtering is handled by the QSortFilterProxyModel.18// because filtering is handled by the QSortFilterProxyModel.
19class ProxyTrackModel : public QSortFilterProxyModel, public virtual TrackModel {19class ProxyTrackModel : public QSortFilterProxyModel, public TrackModel {
20 public:20 public:
21 // Construct a new ProxyTrackModel with pTrackModel as the TrackModel it21 // Construct a new ProxyTrackModel with pTrackModel as the TrackModel it
22 // composes. If bHandleSearches is true, then search signals will not be22 // composes. If bHandleSearches is true, then search signals will not be
@@ -29,15 +29,14 @@
29 virtual QString getTrackLocation(const QModelIndex& index) const;29 virtual QString getTrackLocation(const QModelIndex& index) const;
30 virtual int getTrackId(const QModelIndex& index) const;30 virtual int getTrackId(const QModelIndex& index) const;
31 virtual const QLinkedList<int> getTrackRows(int trackId) const;31 virtual const QLinkedList<int> getTrackRows(int trackId) const;
32 virtual void search(const QString& searchText);32 virtual void search(const QString& searchText,const QString& extraFilter=QString());
33 virtual const QString currentSearch() const;33 virtual const QString currentSearch() const;
34 virtual bool isColumnInternal(int column);34 virtual bool isColumnInternal(int column);
35 virtual bool isColumnHiddenByDefault(int column);35 virtual bool isColumnHiddenByDefault(int column);
36 virtual void removeTrack(const QModelIndex& index);
37 virtual void removeTracks(const QModelIndexList& indices);36 virtual void removeTracks(const QModelIndexList& indices);
38 virtual bool addTrack(const QModelIndex& index, QString location);
39 virtual void moveTrack(const QModelIndex& sourceIndex,37 virtual void moveTrack(const QModelIndex& sourceIndex,
40 const QModelIndex& destIndex);38 const QModelIndex& destIndex);
39 void deleteTracks(const QModelIndexList& indices);
41 virtual QAbstractItemDelegate* delegateForColumn(const int i, QObject* pParent);40 virtual QAbstractItemDelegate* delegateForColumn(const int i, QObject* pParent);
42 virtual TrackModel::CapabilitiesFlags getCapabilities() const;41 virtual TrackModel::CapabilitiesFlags getCapabilities() const;
4342
4443
=== modified file 'mixxx/src/library/rhythmbox/rhythmboxfeature.cpp'
--- mixxx/src/library/rhythmbox/rhythmboxfeature.cpp 2013-01-01 11:53:13 +0000
+++ mixxx/src/library/rhythmbox/rhythmboxfeature.cpp 2013-05-18 16:32:26 +0000
@@ -9,9 +9,11 @@
9#include "library/treeitem.h"9#include "library/treeitem.h"
10#include "library/queryutil.h"10#include "library/queryutil.h"
1111
12RhythmboxFeature::RhythmboxFeature(QObject* parent, TrackCollection* pTrackCollection)12RhythmboxFeature::RhythmboxFeature(QObject* parent, TrackCollection* pTrackCollection,
13 ConfigObject<ConfigValue> *pConfig)
13 : BaseExternalLibraryFeature(parent, pTrackCollection),14 : BaseExternalLibraryFeature(parent, pTrackCollection),
14 m_pTrackCollection(pTrackCollection),15 m_pTrackCollection(pTrackCollection),
16 m_pConfig(pConfig),
15 m_cancelImport(false) {17 m_cancelImport(false) {
16 QString tableName = "rhythmbox_library";18 QString tableName = "rhythmbox_library";
17 QString idColumn = "id";19 QString idColumn = "id";
@@ -37,13 +39,13 @@
37 this, m_pTrackCollection,39 this, m_pTrackCollection,
38 "mixxx.db.model.rhythmbox",40 "mixxx.db.model.rhythmbox",
39 "rhythmbox_library",41 "rhythmbox_library",
40 "rhythmbox");42 "rhythmbox",m_pConfig);
41 m_pRhythmboxPlaylistModel = new BaseExternalPlaylistModel(43 m_pRhythmboxPlaylistModel = new BaseExternalPlaylistModel(
42 this, m_pTrackCollection,44 this, m_pTrackCollection,
43 "mixxx.db.model.rhythmbox_playlist",45 "mixxx.db.model.rhythmbox_playlist",
44 "rhythmbox_playlists",46 "rhythmbox_playlists",
45 "rhythmbox_playlist_tracks",47 "rhythmbox_playlist_tracks",
46 "rhythmbox");48 "rhythmbox",m_pConfig);
4749
48 m_isActivated = false;50 m_isActivated = false;
49 m_title = tr("Rhythmbox");51 m_title = tr("Rhythmbox");
@@ -76,7 +78,7 @@
76 "mixxx.db.model.rhythmbox_playlist",78 "mixxx.db.model.rhythmbox_playlist",
77 "rhythmbox_playlists",79 "rhythmbox_playlists",
78 "rhythmbox_playlist_tracks",80 "rhythmbox_playlist_tracks",
79 "rhythmbox");81 "rhythmbox", m_pConfig);
80 pModel->setPlaylist(playlist);82 pModel->setPlaylist(playlist);
81 return pModel;83 return pModel;
82}84}
8385
=== modified file 'mixxx/src/library/rhythmbox/rhythmboxfeature.h'
--- mixxx/src/library/rhythmbox/rhythmboxfeature.h 2013-01-01 11:53:13 +0000
+++ mixxx/src/library/rhythmbox/rhythmboxfeature.h 2013-05-18 16:32:26 +0000
@@ -14,6 +14,7 @@
14#include "library/baseexternallibraryfeature.h"14#include "library/baseexternallibraryfeature.h"
15#include "library/treeitemmodel.h"15#include "library/treeitemmodel.h"
16#include "library/trackcollection.h"16#include "library/trackcollection.h"
17#include "configobject.h"
1718
18class BaseExternalTrackModel;19class BaseExternalTrackModel;
19class BaseExternalPlaylistModel;20class BaseExternalPlaylistModel;
@@ -21,7 +22,8 @@
21class RhythmboxFeature : public BaseExternalLibraryFeature {22class RhythmboxFeature : public BaseExternalLibraryFeature {
22 Q_OBJECT23 Q_OBJECT
23 public:24 public:
24 RhythmboxFeature(QObject* parent, TrackCollection*);25 RhythmboxFeature(QObject* parent, TrackCollection* pTrackCollection,
26 ConfigObject<ConfigValue> *pConfig);
25 virtual ~RhythmboxFeature();27 virtual ~RhythmboxFeature();
26 static bool isSupported();28 static bool isSupported();
2729
@@ -54,6 +56,7 @@
54 QFutureWatcher<TreeItem*> m_track_watcher;56 QFutureWatcher<TreeItem*> m_track_watcher;
55 QFuture<TreeItem*> m_track_future;57 QFuture<TreeItem*> m_track_future;
56 TreeItemModel m_childModel;58 TreeItemModel m_childModel;
59 ConfigObject<ConfigValue> *m_pConfig;
57 bool m_cancelImport;60 bool m_cancelImport;
5861
59 // Removes all rows from a given table62 // Removes all rows from a given table
6063
=== modified file 'mixxx/src/library/setlogfeature.cpp'
--- mixxx/src/library/setlogfeature.cpp 2013-05-12 22:17:32 +0000
+++ mixxx/src/library/setlogfeature.cpp 2013-05-18 16:32:26 +0000
@@ -17,11 +17,10 @@
17SetlogFeature::SetlogFeature(QObject* parent,17SetlogFeature::SetlogFeature(QObject* parent,
18 ConfigObject<ConfigValue>* pConfig,18 ConfigObject<ConfigValue>* pConfig,
19 TrackCollection* pTrackCollection)19 TrackCollection* pTrackCollection)
20 : BasePlaylistFeature(parent, pConfig, pTrackCollection,20 : BasePlaylistFeature(parent, pConfig, pTrackCollection, "SETLOGHOME") {
21 "SETLOGHOME") {
22 m_pPlaylistTableModel = new PlaylistTableModel(this, pTrackCollection,21 m_pPlaylistTableModel = new PlaylistTableModel(this, pTrackCollection,
23 "mixxx.db.model.setlog",22 "mixxx.db.model.setlog",
24 true);//show all tracks23 pConfig, true);
25 m_pJoinWithPreviousAction = new QAction(tr("Join with previous"), this);24 m_pJoinWithPreviousAction = new QAction(tr("Join with previous"), this);
26 connect(m_pJoinWithPreviousAction, SIGNAL(triggered()),25 connect(m_pJoinWithPreviousAction, SIGNAL(triggered()),
27 this, SLOT(slotJoinWithPrevious()));26 this, SLOT(slotJoinWithPrevious()));
@@ -181,7 +180,7 @@
181 int previousPlaylistId = m_playlistDao.getPreviousPlaylist(currentPlaylistId, PlaylistDAO::PLHT_SET_LOG);180 int previousPlaylistId = m_playlistDao.getPreviousPlaylist(currentPlaylistId, PlaylistDAO::PLHT_SET_LOG);
182 if (previousPlaylistId >= 0) {181 if (previousPlaylistId >= 0) {
183182
184 m_pPlaylistTableModel->setPlaylist(previousPlaylistId);183 m_pPlaylistTableModel->setTableModel(previousPlaylistId);
185184
186 if (currentPlaylistId == m_playlistId) {185 if (currentPlaylistId == m_playlistId) {
187 // mark all the Tracks in the previous Playlist as played186 // mark all the Tracks in the previous Playlist as played
@@ -252,6 +251,8 @@
252 return;251 return;
253 }252 }
254253
254 m_playlistDao.appendTrackToPlaylist(currentPlayingTrackId,
255 m_playlistId);
255 if (m_pPlaylistTableModel->getPlaylist() == m_playlistId) {256 if (m_pPlaylistTableModel->getPlaylist() == m_playlistId) {
256 // View needs a refresh257 // View needs a refresh
257 m_pPlaylistTableModel->appendTrack(currentPlayingTrackId);258 m_pPlaylistTableModel->appendTrack(currentPlayingTrackId);
@@ -277,7 +278,7 @@
277278
278 if (type != PlaylistDAO::PLHT_UNKNOWN) {279 if (type != PlaylistDAO::PLHT_UNKNOWN) {
279 // Switch the view to the playlist.280 // Switch the view to the playlist.
280 m_pPlaylistTableModel->setPlaylist(playlistId);281 m_pPlaylistTableModel->setTableModel(playlistId);
281 // Update selection282 // Update selection
282 emit(featureSelect(this, m_lastRightClickedIndex));283 emit(featureSelect(this, m_lastRightClickedIndex));
283 }284 }
284285
=== modified file 'mixxx/src/library/stardelegate.cpp'
--- mixxx/src/library/stardelegate.cpp 2012-11-30 09:17:37 +0000
+++ mixxx/src/library/stardelegate.cpp 2013-05-18 16:32:26 +0000
@@ -18,15 +18,19 @@
1818
19#include <QtDebug>19#include <QtDebug>
20#include <QtGui>20#include <QtGui>
21#include <QTableView>
2122
22#include "stardelegate.h"23#include "stardelegate.h"
23#include "stareditor.h"24#include "stareditor.h"
24#include "starrating.h"25#include "starrating.h"
26#include "library/trackmodel.h"
27#include "library/dao/trackdao.h"
2528
26StarDelegate::StarDelegate(QObject *pParent)29StarDelegate::StarDelegate(QObject *pParent)
27 : QStyledItemDelegate(pParent),30 : QStyledItemDelegate(pParent),
28 m_isOneCellInEditMode(false) {31 m_isOneCellInEditMode(false) {
29 m_pTableView = qobject_cast<QTableView *>(pParent);32 m_pTableView = qobject_cast<QTableView *>(pParent);
33 m_pTrackModel = dynamic_cast<TrackModel*>(m_pTableView->model());
30 connect(pParent, SIGNAL(entered(QModelIndex)),34 connect(pParent, SIGNAL(entered(QModelIndex)),
31 this, SLOT(cellEntered(QModelIndex)));35 this, SLOT(cellEntered(QModelIndex)));
32}36}
@@ -41,7 +45,8 @@
41 // Populate the correct colors based on the styling45 // Populate the correct colors based on the styling
42 QStyleOptionViewItem newOption = option;46 QStyleOptionViewItem newOption = option;
43 initStyleOption(&newOption, index);47 initStyleOption(&newOption, index);
4448 bool fsDeleted=index.sibling(index.row(),
49 m_pTrackModel->fieldIndex(TRACKLOCATIONSTABLE_FSDELETED)).data().toInt();
45 // Set the palette appropriately based on whether the row is selected or50 // Set the palette appropriately based on whether the row is selected or
46 // not. We also have to check if it is inactive or not and use the51 // not. We also have to check if it is inactive or not and use the
47 // appropriate ColorGroup.52 // appropriate ColorGroup.
@@ -54,7 +59,11 @@
54 painter->setBrush(newOption.palette.color(59 painter->setBrush(newOption.palette.color(
55 colorGroup, QPalette::HighlightedText));60 colorGroup, QPalette::HighlightedText));
56 } else {61 } else {
57 painter->fillRect(newOption.rect, newOption.palette.base());62 if (fsDeleted) {
63 painter->fillRect(newOption.rect, QColor(Qt::red));
64 } else {
65 painter->fillRect(newOption.rect, newOption.palette.base());
66 }
58 painter->setBrush(newOption.palette.text());67 painter->setBrush(newOption.palette.text());
59 }68 }
6069
@@ -123,4 +132,3 @@
123 m_currentEditedCellIndex = QModelIndex();132 m_currentEditedCellIndex = QModelIndex();
124 }133 }
125}134}
126
127135
=== modified file 'mixxx/src/library/stardelegate.h'
--- mixxx/src/library/stardelegate.h 2012-06-03 14:37:44 +0000
+++ mixxx/src/library/stardelegate.h 2013-05-18 16:32:26 +0000
@@ -21,6 +21,7 @@
2121
22#include <QStyledItemDelegate>22#include <QStyledItemDelegate>
23#include <QTableView>23#include <QTableView>
24#include "library/trackmodel.h"
2425
25/*26/*
26 * When displaying data in a QListView, QTableView, or QTreeView,27 * When displaying data in a QListView, QTableView, or QTreeView,
@@ -57,6 +58,7 @@
57 QTableView *m_pTableView;58 QTableView *m_pTableView;
58 QPersistentModelIndex m_currentEditedCellIndex;59 QPersistentModelIndex m_currentEditedCellIndex;
59 bool m_isOneCellInEditMode;60 bool m_isOneCellInEditMode;
61 TrackModel* m_pTrackModel;
60};62};
6163
62#endif64#endif
6365
=== modified file 'mixxx/src/library/trackcollection.cpp'
--- mixxx/src/library/trackcollection.cpp 2013-05-07 03:17:23 +0000
+++ mixxx/src/library/trackcollection.cpp 2013-05-18 16:32:26 +0000
@@ -18,9 +18,10 @@
18 m_playlistDao(m_db),18 m_playlistDao(m_db),
19 m_crateDao(m_db),19 m_crateDao(m_db),
20 m_cueDao(m_db),20 m_cueDao(m_db),
21 m_directoryDao(m_db),
21 m_analysisDao(m_db, pConfig),22 m_analysisDao(m_db, pConfig),
22 m_trackDao(m_db, m_cueDao, m_playlistDao, m_crateDao,23 m_trackDao(m_db, m_cueDao, m_playlistDao, m_crateDao,
23 m_analysisDao, pConfig),24 m_analysisDao, m_directoryDao, pConfig),
24 m_supportedFileExtensionsRegex(25 m_supportedFileExtensionsRegex(
25 SoundSourceProxy::supportedFileExtensionsRegex(),26 SoundSourceProxy::supportedFileExtensionsRegex(),
26 Qt::CaseInsensitive) {27 Qt::CaseInsensitive) {
@@ -72,7 +73,7 @@
72 return false;73 return false;
73 }74 }
7475
75 int requiredSchemaVersion = 18;76 int requiredSchemaVersion = 19;
76 QString schemaFilename = m_pConfig->getResourcePath();77 QString schemaFilename = m_pConfig->getResourcePath();
77 schemaFilename.append("schema.xml");78 schemaFilename.append("schema.xml");
78 QString okToExit = tr("Click OK to exit.");79 QString okToExit = tr("Click OK to exit.");
@@ -116,12 +117,19 @@
116 return m_db;117 return m_db;
117}118}
118119
119/** Do a non-recursive import of all the songs in a directory. Does NOT decend into subdirectories.120// Do a non-recursive import of all the songs in a directory. Does NOT
120 @param trackDao The track data access object which provides a connection to the database. We use this parameter in order to make this function callable from separate threads. You need to use a different DB connection for each thread.121// decend into subdirectories.
121 @return true if the scan completed without being cancelled. False if the scan was cancelled part-way through.122// @param trackDao The track data access object which provides a
122*/123// connection to the database. We use this parameter in order to make
124// this function callable from separate threads. You need to use a
125// different DB connection for each thread.
126// @return true if the scan completed without being cancelled.
127// False if the scan was cancelled part-way through.
123bool TrackCollection::importDirectory(QString directory, TrackDAO &trackDao,128bool TrackCollection::importDirectory(QString directory, TrackDAO &trackDao,
124 const QStringList & nameFilters, volatile bool* cancel) {129 const QStringList & nameFilters,
130 QSet<int>& restoredTracks,
131 const int dirId,
132 volatile bool* cancel) {
125 //qDebug() << "TrackCollection::importDirectory(" << directory<< ")";133 //qDebug() << "TrackCollection::importDirectory(" << directory<< ")";
126134
127 emit(startedLoading());135 emit(startedLoading());
@@ -149,15 +157,17 @@
149 // it. If it does exist in the database, then it is either in the157 // it. If it does exist in the database, then it is either in the
150 // user's library OR the user has "removed" the track via158 // user's library OR the user has "removed" the track via
151 // "Right-Click -> Remove". These tracks stay in the library, but159 // "Right-Click -> Remove". These tracks stay in the library, but
152 // their mixxx_deleted column is 1.160 // their mixxx_deleted column is 1. It is also possible that the
153 if (!trackDao.trackExistsInDatabase(absoluteFilePath)) {161 // track was deleted and now restored, set these in restoredTracks
162 if (trackDao.trackExistsInDatabase(absoluteFilePath)) {
163 restoredTracks.insert(trackDao.getTrackId(absoluteFilePath));
164 } else {
154 //qDebug() << "Loading" << it.fileName();165 //qDebug() << "Loading" << it.fileName();
155 emit(progressLoading(it.fileName()));166 emit(progressLoading(it.fileName()));
156167
157 TrackPointer pTrack = TrackPointer(new TrackInfoObject(168 TrackPointer pTrack = TrackPointer(new TrackInfoObject(
158 absoluteFilePath), &QObject::deleteLater);169 absoluteFilePath), &QObject::deleteLater);
159170 if (trackDao.addTracksAdd(pTrack.data(), false,dirId)) {
160 if (trackDao.addTracksAdd(pTrack.data(), false)) {
161 // Successful added171 // Successful added
162 // signal the main instance of TrackDao, that there is a172 // signal the main instance of TrackDao, that there is a
163 // new Track in the database173 // new Track in the database
@@ -183,13 +193,17 @@
183 return m_playlistDao;193 return m_playlistDao;
184}194}
185195
196DirectoryDAO& TrackCollection::getDirectoryDAO() {
197 return m_directoryDao;
198}
199
186QSharedPointer<BaseTrackCache> TrackCollection::getTrackSource(200QSharedPointer<BaseTrackCache> TrackCollection::getTrackSource(
187 const QString name) {201 const QString name) {
188 return m_trackSources.value(name, QSharedPointer<BaseTrackCache>());202 return m_trackSources.value(name, QSharedPointer<BaseTrackCache>());
189}203}
190204
191void TrackCollection::addTrackSource(205void TrackCollection::addTrackSource(const QString name,
192 const QString name, QSharedPointer<BaseTrackCache> trackSource) {206 QSharedPointer<BaseTrackCache> trackSource) {
193 Q_ASSERT(!m_trackSources.contains(name));207 Q_ASSERT(!m_trackSources.contains(name));
194 m_trackSources[name] = trackSource;208 m_trackSources[name] = trackSource;
195}209}
196210
=== modified file 'mixxx/src/library/trackcollection.h'
--- mixxx/src/library/trackcollection.h 2013-02-09 22:06:46 +0000
+++ mixxx/src/library/trackcollection.h 2013-05-18 16:32:26 +0000
@@ -31,6 +31,7 @@
31#include "library/dao/cuedao.h"31#include "library/dao/cuedao.h"
32#include "library/dao/playlistdao.h"32#include "library/dao/playlistdao.h"
33#include "library/dao/analysisdao.h"33#include "library/dao/analysisdao.h"
34#include "library/dao/directorydao.h"
3435
35class TrackInfoObject;36class TrackInfoObject;
3637
@@ -51,7 +52,10 @@
5152
52 /** Import the files in a given diretory, without recursing into subdirectories */53 /** Import the files in a given diretory, without recursing into subdirectories */
53 bool importDirectory(QString directory, TrackDAO &trackDao,54 bool importDirectory(QString directory, TrackDAO &trackDao,
54 const QStringList & nameFilters, volatile bool* cancel);55 const QStringList & nameFilters,
56 QSet<int>& restoredTracks,
57 const int dirId,
58 volatile bool* cancel);
5559
56 void resetLibaryCancellation();60 void resetLibaryCancellation();
57 QSqlDatabase& getDatabase();61 QSqlDatabase& getDatabase();
@@ -59,6 +63,7 @@
59 CrateDAO& getCrateDAO();63 CrateDAO& getCrateDAO();
60 TrackDAO& getTrackDAO();64 TrackDAO& getTrackDAO();
61 PlaylistDAO& getPlaylistDAO();65 PlaylistDAO& getPlaylistDAO();
66 DirectoryDAO& getDirectoryDAO();
62 QSharedPointer<BaseTrackCache> getTrackSource(const QString name);67 QSharedPointer<BaseTrackCache> getTrackSource(const QString name);
63 void addTrackSource(const QString name, QSharedPointer<BaseTrackCache> trackSource);68 void addTrackSource(const QString name, QSharedPointer<BaseTrackCache> trackSource);
64 void cancelLibraryScan();69 void cancelLibraryScan();
@@ -81,7 +86,13 @@
81 CueDAO m_cueDao;86 CueDAO m_cueDao;
82 AnalysisDao m_analysisDao;87 AnalysisDao m_analysisDao;
83 TrackDAO m_trackDao;88 TrackDAO m_trackDao;
89 DirectoryDAO m_directoryDao;
84 const QRegExp m_supportedFileExtensionsRegex;90 const QRegExp m_supportedFileExtensionsRegex;
91 // Flag to raise when library scan should be cancelled
92 int bCancelLibraryScan;
93 QMutex m_libraryScanMutex;
94
95
85};96};
8697
87#endif98#endif
8899
=== modified file 'mixxx/src/library/trackmodel.h'
--- mixxx/src/library/trackmodel.h 2012-11-25 09:33:00 +0000
+++ mixxx/src/library/trackmodel.h 2013-05-18 16:32:26 +0000
@@ -43,7 +43,8 @@
43 TRACKMODELCAPS_RESETPLAYED = 0x04000,43 TRACKMODELCAPS_RESETPLAYED = 0x04000,
44 TRACKMODELCAPS_HIDE = 0x08000,44 TRACKMODELCAPS_HIDE = 0x08000,
45 TRACKMODELCAPS_UNHIDE = 0x10000,45 TRACKMODELCAPS_UNHIDE = 0x10000,
46 TRACKMODELCAPS_PURGE = 0x2000046 TRACKMODELCAPS_PURGE = 0x20000,
47 TRACKMODELCAPS_DELETEFS = 0x40000
47 };48 };
4849
49 typedef int CapabilitiesFlags; /** Enables us to do ORing */50 typedef int CapabilitiesFlags; /** Enables us to do ORing */
@@ -63,7 +64,10 @@
63 virtual const QLinkedList<int> getTrackRows(int trackId) const = 0;64 virtual const QLinkedList<int> getTrackRows(int trackId) const = 0;
6465
65 bool isTrackModel() { return true;}66 bool isTrackModel() { return true;}
66 virtual void search(const QString& searchText) = 0;67 virtual void search(const QString& searchText, const QString& extraFilter=QString()) {
68 Q_UNUSED(searchText);
69 Q_UNUSED(extraFilter);
70 };
67 virtual const QString currentSearch() const = 0;71 virtual const QString currentSearch() const = 0;
68 virtual bool isColumnInternal(int column) = 0;72 virtual bool isColumnInternal(int column) = 0;
69 // if no header state exists, we may hide some columns so that the user can73 // if no header state exists, we may hide some columns so that the user can
@@ -71,9 +75,7 @@
71 virtual bool isColumnHiddenByDefault(int column) = 0;75 virtual bool isColumnHiddenByDefault(int column) = 0;
72 virtual const QList<int>& showableColumns() const { return m_emptyColumns; }76 virtual const QList<int>& showableColumns() const { return m_emptyColumns; }
73 virtual const QList<int>& searchColumns() const { return m_emptyColumns; }77 virtual const QList<int>& searchColumns() const { return m_emptyColumns; }
74 virtual void removeTrack(const QModelIndex& index) {78
75 Q_UNUSED(index);
76 }
77 virtual void removeTracks(const QModelIndexList& indices) {79 virtual void removeTracks(const QModelIndexList& indices) {
78 Q_UNUSED(indices);80 Q_UNUSED(indices);
79 }81 }
@@ -83,14 +85,15 @@
83 virtual void unhideTracks(const QModelIndexList& indices) {85 virtual void unhideTracks(const QModelIndexList& indices) {
84 Q_UNUSED(indices);86 Q_UNUSED(indices);
85 }87 }
88 virtual void relocateTracks(const QModelIndexList& indices) {
89 Q_UNUSED(indices);
90 }
91 virtual void deleteTracks(const QModelIndexList& indices) {
92 Q_UNUSED(indices);
93 }
86 virtual void purgeTracks(const QModelIndexList& indices) {94 virtual void purgeTracks(const QModelIndexList& indices) {
87 Q_UNUSED(indices);95 Q_UNUSED(indices);
88 }96 }
89 virtual bool addTrack(const QModelIndex& index, QString location) {
90 Q_UNUSED(index);
91 Q_UNUSED(location);
92 return false;
93 }
94 virtual int addTracks(const QModelIndex& index, QList<QString> locations) {97 virtual int addTracks(const QModelIndex& index, QList<QString> locations) {
95 Q_UNUSED(index);98 Q_UNUSED(index);
96 Q_UNUSED(locations);99 Q_UNUSED(locations);
@@ -133,10 +136,13 @@
133 m_iDefaultSortColumn = sortColumn;136 m_iDefaultSortColumn = sortColumn;
134 m_eDefaultSortOrder = sortOrder;137 m_eDefaultSortOrder = sortOrder;
135 }138 }
136139
137 virtual int fieldIndex(const QString& fieldName) const {140 virtual int fieldIndex(const QString& fieldName) const {
138 Q_UNUSED(fieldName);141 Q_UNUSED(fieldName);
139 return 0;142 return -1;
143 }
144
145 virtual void select() {
140 }146 }
141147
142 private:148 private:
143149
=== modified file 'mixxx/src/library/traktor/traktorfeature.cpp'
--- mixxx/src/library/traktor/traktorfeature.cpp 2013-01-01 11:53:13 +0000
+++ mixxx/src/library/traktor/traktorfeature.cpp 2013-05-18 16:32:26 +0000
@@ -11,17 +11,17 @@
11#include "library/traktor/traktorfeature.h"11#include "library/traktor/traktorfeature.h"
1212
13#include "library/librarytablemodel.h"13#include "library/librarytablemodel.h"
14#include "library/missingtablemodel.h"
15#include "library/queryutil.h"14#include "library/queryutil.h"
16#include "library/trackcollection.h"15#include "library/trackcollection.h"
17#include "library/treeitem.h"16#include "library/treeitem.h"
1817
19TraktorTrackModel::TraktorTrackModel(QObject* parent,18TraktorTrackModel::TraktorTrackModel(QObject* parent,
20 TrackCollection* pTrackCollection)19 TrackCollection* pTrackCollection,
20 ConfigObject<ConfigValue> *pConfig)
21 : BaseExternalTrackModel(parent, pTrackCollection,21 : BaseExternalTrackModel(parent, pTrackCollection,
22 "mixxx.db.model.traktor_tablemodel",22 "mixxx.db.model.traktor_tablemodel",
23 "traktor_library",23 "traktor_library",
24 "traktor") {24 "traktor",pConfig) {
25}25}
2626
27bool TraktorTrackModel::isColumnHiddenByDefault(int column) {27bool TraktorTrackModel::isColumnHiddenByDefault(int column) {
@@ -33,12 +33,13 @@
33}33}
3434
35TraktorPlaylistModel::TraktorPlaylistModel(QObject* parent,35TraktorPlaylistModel::TraktorPlaylistModel(QObject* parent,
36 TrackCollection* pTrackCollection)36 TrackCollection* pTrackCollection,
37 ConfigObject<ConfigValue> *pConfig)
37 : BaseExternalPlaylistModel(parent, pTrackCollection,38 : BaseExternalPlaylistModel(parent, pTrackCollection,
38 "mixxx.db.model.traktor.playlistmodel",39 "mixxx.db.model.traktor.playlistmodel",
39 "traktor_playlists",40 "traktor_playlists",
40 "traktor_playlist_tracks",41 "traktor_playlist_tracks",
41 "traktor") {42 "traktor", pConfig) {
42}43}
4344
44bool TraktorPlaylistModel::isColumnHiddenByDefault(int column) {45bool TraktorPlaylistModel::isColumnHiddenByDefault(int column) {
@@ -49,10 +50,12 @@
49 return false;50 return false;
50}51}
5152
52TraktorFeature::TraktorFeature(QObject* parent, TrackCollection* pTrackCollection)53TraktorFeature::TraktorFeature(QObject* parent, TrackCollection* pTrackCollection,
54 ConfigObject<ConfigValue> *pConfig)
53 : BaseExternalLibraryFeature(parent, pTrackCollection),55 : BaseExternalLibraryFeature(parent, pTrackCollection),
54 m_pTrackCollection(pTrackCollection),56 m_pTrackCollection(pTrackCollection),
55 m_cancelImport(false) {57 m_cancelImport(false),
58 m_pConfig(pConfig) {
56 QString tableName = "traktor_library";59 QString tableName = "traktor_library";
57 QString idColumn = "id";60 QString idColumn = "id";
58 QStringList columns;61 QStringList columns;
@@ -75,8 +78,8 @@
75 columns, false)));78 columns, false)));
7679
77 m_isActivated = false;80 m_isActivated = false;
78 m_pTraktorTableModel = new TraktorTrackModel(this, m_pTrackCollection);81 m_pTraktorTableModel = new TraktorTrackModel(this, m_pTrackCollection,pConfig);
79 m_pTraktorPlaylistModel = new TraktorPlaylistModel(this, m_pTrackCollection);82 m_pTraktorPlaylistModel = new TraktorPlaylistModel(this, m_pTrackCollection,pConfig);
8083
81 m_title = tr("Traktor");84 m_title = tr("Traktor");
8285
@@ -101,7 +104,8 @@
101}104}
102105
103BaseSqlTableModel* TraktorFeature::getPlaylistModelForPlaylist(QString playlist) {106BaseSqlTableModel* TraktorFeature::getPlaylistModelForPlaylist(QString playlist) {
104 TraktorPlaylistModel* pModel = new TraktorPlaylistModel(this, m_pTrackCollection);107 TraktorPlaylistModel* pModel = new TraktorPlaylistModel(this, m_pTrackCollection
108 ,m_pConfig);
105 pModel->setPlaylist(playlist);109 pModel->setPlaylist(playlist);
106 return pModel;110 return pModel;
107}111}
108112
=== modified file 'mixxx/src/library/traktor/traktorfeature.h'
--- mixxx/src/library/traktor/traktorfeature.h 2013-01-01 11:53:13 +0000
+++ mixxx/src/library/traktor/traktorfeature.h 2013-05-18 16:32:26 +0000
@@ -15,6 +15,7 @@
15#include "library/baseexternaltrackmodel.h"15#include "library/baseexternaltrackmodel.h"
16#include "library/baseexternalplaylistmodel.h"16#include "library/baseexternalplaylistmodel.h"
17#include "library/treeitemmodel.h"17#include "library/treeitemmodel.h"
18#include "configobject.h"
1819
19class LibraryTableModel;20class LibraryTableModel;
20class MissingTableModel;21class MissingTableModel;
@@ -24,21 +25,24 @@
24class TraktorTrackModel : public BaseExternalTrackModel {25class TraktorTrackModel : public BaseExternalTrackModel {
25 public:26 public:
26 TraktorTrackModel(QObject* parent,27 TraktorTrackModel(QObject* parent,
27 TrackCollection* pTrackCollection);28 TrackCollection* pTrackCollection,
29 ConfigObject<ConfigValue> *pConfig);
28 virtual bool isColumnHiddenByDefault(int column);30 virtual bool isColumnHiddenByDefault(int column);
29};31};
3032
31class TraktorPlaylistModel : public BaseExternalPlaylistModel {33class TraktorPlaylistModel : public BaseExternalPlaylistModel {
32 public:34 public:
33 TraktorPlaylistModel(QObject* parent,35 TraktorPlaylistModel(QObject* parent,
34 TrackCollection* pTrackCollection);36 TrackCollection* pTrackCollection,
37 ConfigObject<ConfigValue> *pConfig);
35 virtual bool isColumnHiddenByDefault(int column);38 virtual bool isColumnHiddenByDefault(int column);
36};39};
3740
38class TraktorFeature : public BaseExternalLibraryFeature {41class TraktorFeature : public BaseExternalLibraryFeature {
39 Q_OBJECT42 Q_OBJECT
40 public:43 public:
41 TraktorFeature(QObject* parent, TrackCollection*);44 TraktorFeature(QObject* parent, TrackCollection*,
45 ConfigObject<ConfigValue> *pConfig);
42 virtual ~TraktorFeature();46 virtual ~TraktorFeature();
4347
44 QVariant title();48 QVariant title();
@@ -70,6 +74,7 @@
70 TrackCollection* m_pTrackCollection;74 TrackCollection* m_pTrackCollection;
71 // A separate db connection for the worker parsing thread75 // A separate db connection for the worker parsing thread
72 QSqlDatabase m_database;76 QSqlDatabase m_database;
77 ConfigObject<ConfigValue> *m_pConfig;
73 TraktorTrackModel* m_pTraktorTableModel;78 TraktorTrackModel* m_pTraktorTableModel;
74 TraktorPlaylistModel* m_pTraktorPlaylistModel;79 TraktorPlaylistModel* m_pTraktorPlaylistModel;
7580
7681
=== modified file 'mixxx/src/library/treeitem.cpp'
--- mixxx/src/library/treeitem.cpp 2013-05-18 16:23:08 +0000
+++ mixxx/src/library/treeitem.cpp 2013-05-18 16:32:26 +0000
@@ -45,6 +45,12 @@
45}45}
4646
47TreeItem::~TreeItem() {47TreeItem::~TreeItem() {
48 qDebug() << "~TreeItem()";
49 //TODO(kain88) this causes a segfault during shutdown, no idea why
50 qDebug() << m_childItems << " empty " << m_childItems.isEmpty();
51 if (m_childItems.isEmpty()) {
52 return;
53 }
48 qDeleteAll(m_childItems);54 qDeleteAll(m_childItems);
49}55}
5056
5157
=== modified file 'mixxx/src/mixxx.cpp'
--- mixxx/src/mixxx.cpp 2013-05-16 00:14:12 +0000
+++ mixxx/src/mixxx.cpp 2013-05-18 16:32:26 +0000
@@ -298,30 +298,14 @@
298 m_pEngine->addChannel(pMicrophone);298 m_pEngine->addChannel(pMicrophone);
299 m_pSoundManager->registerInput(micInput, pMicrophone);299 m_pSoundManager->registerInput(micInput, pMicrophone);
300300
301 // Get Music dir301 // library dies in seemingly unrelated qtsql error about not having a
302 bool hasChanged_MusicDir = false;302 // sqlite driver if this path doesn't exist. Normally config->Save()
303 QDir dir(m_pConfig->getValueString(ConfigKey("[Playlist]","Directory")));303 // above would make it but if it doesn't get run for whatever reason
304 if (m_pConfig->getValueString(304 // we get hosed -- bkgood
305 ConfigKey("[Playlist]","Directory")).length() < 1 || !dir.exists())305 if (!QDir(QDir::homePath().append("/").append(SETTINGS_PATH)).exists()) {
306 {306 QDir().mkpath(QDir::homePath().append("/").append(SETTINGS_PATH));
307 // TODO this needs to be smarter, we can't distinguish between an empty
308 // path return value (not sure if this is normally possible, but it is
309 // possible with the Windows 7 "Music" library, which is what
310 // QDesktopServices::storageLocation(QDesktopServices::MusicLocation)
311 // resolves to) and a user hitting 'cancel'. If we get a blank return
312 // but the user didn't hit cancel, we need to know this and let the
313 // user take some course of action -- bkgood
314 QString fd = QFileDialog::getExistingDirectory(
315 this, tr("Choose music library directory"),
316 QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
317
318 if (fd != "")
319 {
320 m_pConfig->set(ConfigKey("[Playlist]","Directory"), fd);
321 m_pConfig->Save();
322 hasChanged_MusicDir = true;
323 }
324 }307 }
308
325 // Do not write meta data back to ID3 when meta data has changed309 // Do not write meta data back to ID3 when meta data has changed
326 // Because multiple TrackDao objects can exists for a particular track310 // Because multiple TrackDao objects can exists for a particular track
327 // writing meta data may ruine your MP3 file if done simultaneously.311 // writing meta data may ruine your MP3 file if done simultaneously.
@@ -375,6 +359,46 @@
375 bFirstRun || bUpgraded,359 bFirstRun || bUpgraded,
376 m_pRecordingManager);360 m_pRecordingManager);
377 m_pPlayerManager->bindToLibrary(m_pLibrary);361 m_pPlayerManager->bindToLibrary(m_pLibrary);
362 connect(this, SIGNAL(dirsChanged(QString,QString)),
363 m_pLibrary, SLOT(slotDirsChanged(QString,QString)));
364
365 // Check if we update from an old db without relative library paths
366 // getValueString will return "" if no value was set
367 bool oldLibrary = m_pConfig->getValueString(ConfigKey("[Library]","newVersion"))=="";
368 qDebug() << "kain88 status of library version" << oldLibrary;
369 //TODO(kain88) mode this into update code
370 if (oldLibrary) {
371 QString dir = m_pConfig->getValueString(ConfigKey("[Playlist]","Directory"));
372 // adds the current library path to the directories table and updates
373 // track_locations for all tracks
374 if (dir!="") {
375 emit(dirsChanged("update",dir));
376 m_pConfig->set(ConfigKey("[Library]","newVersion"),ConfigValue((int)true));
377 m_pConfig->Save();
378 }
379 }
380
381 // Get Music dir
382 bool hasChanged_MusicDir = false;
383
384 QStringList dirs = m_pLibrary->getDirs();
385 if (dirs.size() < 1) {
386 // TODO(XXX) this needs to be smarter, we can't distinguish between an empty
387 // path return value (not sure if this is normally possible, but it is
388 // possible with the Windows 7 "Music" library, which is what
389 // QDesktopServices::storageLocation(QDesktopServices::MusicLocation)
390 // resolves to) and a user hitting 'cancel'. If we get a blank return
391 // but the user didn't hit cancel, we need to know this and let the
392 // user take some course of action -- bkgood
393 QString fd = QFileDialog::getExistingDirectory(
394 this, tr("Choose music library directory"),
395 QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
396 if (fd != "") {
397 //adds Folder to database
398 emit(dirsChanged("added",fd));
399 hasChanged_MusicDir = true;
400 }
401 }
378402
379 // Call inits to invoke all other construction parts403 // Call inits to invoke all other construction parts
380404
@@ -414,6 +438,11 @@
414 // Initialize preference dialog438 // Initialize preference dialog
415 m_pPrefDlg = new DlgPreferences(this, m_pSkinLoader, m_pSoundManager, m_pPlayerManager,439 m_pPrefDlg = new DlgPreferences(this, m_pSkinLoader, m_pSoundManager, m_pPlayerManager,
416 m_pControllerManager, m_pVCManager, m_pConfig);440 m_pControllerManager, m_pVCManager, m_pConfig);
441 connect(m_pPrefDlg, SIGNAL(configChanged(QString,QString)),
442 m_pLibrary, SIGNAL(configChanged(QString,QString)));
443 connect(m_pPrefDlg, SIGNAL(dirsChanged(QString,QString)),
444 m_pLibrary, SLOT(slotDirsChanged(QString,QString)));
445
417 m_pPrefDlg->setWindowIcon(QIcon(":/images/ic_mixxx_window.png"));446 m_pPrefDlg->setWindowIcon(QIcon(":/images/ic_mixxx_window.png"));
The diff has been truncated for viewing.