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

Proposed by RAFFI TEA
Status: Superseded
Proposed branch: lp:~mixxxdevelopers/mixxx/tree_item_browser
Merge into: lp:~mixxxdevelopers/mixxx/trunk
Diff against target: 444 lines (+222/-136)
5 files modified
mixxx/build/depends.py (+1/-0)
mixxx/src/library/browsetablemodel.cpp (+22/-124)
mixxx/src/library/browsetablemodel.h (+22/-12)
mixxx/src/library/browsethread.cpp (+140/-0)
mixxx/src/library/browsethread.h (+37/-0)
To merge this branch: bzr merge lp:~mixxxdevelopers/mixxx/tree_item_browser
Reviewer Review Type Date Requested Status
RJ Skerry-Ryan Approve
Review via email: mp+47206@code.launchpad.net

Description of the change

This a rewrite of the BrowseFeature and has been tested on OS X, Windows and Linux.

The BrowseFeature is now expandable showing drive letters and folders. All supported audio files are listed in the right track table view along with their metadata.

Known bug:

Folders may have large content. Therefore, the population of the track table view is thread-based. Clicking quickly through the folder structure will cause Mixxx to crash. I need some help to get things thread-safe.

Thanks,

Tobias

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

Hey Tobias,

Checking out this I've got a couple of questions and things to fix:

1) Why the updates to libmad, libid3tag, and libtag?

2) I assume you're adding shell32 because you use system-specific calls in foldertreemodel.cpp? Could you comment that line in the SConscript to mention that's why it's there (mostly so I don't blindly remove it in the future thinking "gee we don't need this" :) )

3) In browsefeature.cpp the "My Music" literal needs a tr(). Also the naming of My Music might make Windows users actually think it's their "My Music" folder, while it's actually the library folder they picked in Mixxx. Maybe we should say "My Library" instead?

4) I think we should add some other useful links, e.g. a 'My Home' for the user's home directory, 'My Documents' or 'My Music' for their Music folder (if it isn't the same as their Mixxx library). You can do this in a cross-platform way with the QDesktopServices::storageLocation method

5) I noticed that when expanding directories in the sidebar, if you hit the expand triangle on a folder that you are not currently selecting, it won't expand. Is this the case in general? Can we fix it so that they expand? I'm on Ubuntu 10.04 with standard Qt.

6) BrowseTableModel::BrowseTableModel() all those header column names need tr()'s

7) (sorry for nitpicking) can isBackgroundThreadActive get an "m_b" prefix, also can you move the initialization of isBackgroundThreadActive and m_currentPath to the constructor initializer list?

8) For the populateModel method in BrowseTableModel, I think you should change it a little bit. Particularly, the lock'ing of the mutex in the setPath is problematic because it could block (not deadlock, but still) the GUI thread if it was called twice before the populateModel method runs. I would change it like this: get rid of the isBackgroundThreadActive boolean and m_currentPath. Make the currentPath an argument of the populateModel method and add the path to be set as the last argument of the QtConcurrent::run call. You should still lock the populateMutex in populateModel to prevent the populateModel() method from running more than once concurrently. This may result in populateModel being run more than once if someone quickly sets the path and sets it again. I think that's not too terrible, as the UI will eventually update to be correct.

9) In SidebarModel::hasChildren, can you use dynamic_cast instead of a bare cast (and check that it's not null as a result of the dynamic_cast?)

General comment: It looks like there are still a lot of places where there are tabs. One place I noticed is the addition to sidebarmodel.h and also the additions to depends.py -- could you double check your editor is using 4-space indents?

Based on these things getting fixed, everything else looks good. Thanks Tobias!

If you don't have time to work on this stuff I'm happy to lend a hand.

RJ

review: Needs Fixing
Revision history for this message
RAFFI TEA (raffitea) wrote :
Download full text (4.9 KiB)

Thanks RJ for your detailed review :-)

> Hey Tobias,
>
> Checking out this I've got a couple of questions and things to fix:
>
> 1) Why the updates to libmad, libid3tag, and libtag?

Sean has used MSVC++ 2005 on Windows to compile Mixxx and its dependencies.
If I compile Mixxx with MSVC++ 2008 library scanning but also track loadings will cause a segfault by taglib for some reason. Other contributors have observed same issues, see Bug #714337. Solution: Compile taglib with MSVC++ 2008 and replace the *.lib and *.dll.
>
> 2) I assume you're adding shell32 because you use system-specific calls in
> foldertreemodel.cpp? Could you comment that line in the SConscript to mention
> that's why it's there (mostly so I don't blindly remove it in the future
> thinking "gee we don't need this" :) )

Good catch, I'll place a comment. System-specific calls are necessary to quickly test if a folder has subfolders. QT is too slow here.
>
> 3) In browsefeature.cpp the "My Music" literal needs a tr(). Also the naming
> of My Music might make Windows users actually think it's their "My Music"
> folder, while it's actually the library folder they picked in Mixxx. Maybe we
> should say "My Library" instead?

I'm happy for this discussion here. I think "My Library" is the best word and others common places should be added, too.

> 4) I think we should add some other useful links, e.g. a 'My Home' for the
> user's home directory, 'My Documents' or 'My Music' for their Music folder (if
> it isn't the same as their Mixxx library). You can do this in a cross-platform
> way with the QDesktopServices::storageLocation method
>
> 5) I noticed that when expanding directories in the sidebar, if you hit the
> expand triangle on a folder that you are not currently selecting, it won't
> expand. Is this the case in general? Can we fix it so that they expand? I'm on
> Ubuntu 10.04 with standard Qt.

At the moment, this behavior is same on all platforms. I'm pretty sure we can change the behavior somehow. We'll need to change the sidebar view. The models can't change the behavior.

> 6) BrowseTableModel::BrowseTableModel() all those header column names need
> tr()'s

Will be done soon.

> 7) (sorry for nitpicking) can isBackgroundThreadActive get an "m_b" prefix,
> also can you move the initialization of isBackgroundThreadActive and
> m_currentPath to the constructor initializer list?

The points 7 and 8 are my problem. Have you ever tried to browse very quickly through the folder structure? Just to for reproduction. Create some folder that that contain > 100 tracks. Now try to click through the folder in Mixxx very quickly using keyboard. At least on Windows and OS X, Mixxx crashes in a regular manner .

I really don't know why. I introduced 'populateMutex ' to prevent the populateModel() method
from running more than once concurrently. However, I think more threads are created. You, RJ, are more thread-experienced as I am. Maybe an implementation of QRunnable is mode suitable. using signal/slots for updating the track table view. I would be thankful if someone can help me out. All previous points can be quickly addressed by me. What really prevents this feature to ge...

Read more...

Revision history for this message
RAFFI TEA (raffitea) wrote :

RJ, I've addresses most of the problems. In particular, I've categorized the BrowseFeature. There's now a 'Quick Link" and a 'Devices' item under the root item. The first provides quick access to common places, e.g., Mixxx library, My Music, Desktop and so on. The second item provides access to (removable) drives/devices on all operating systems.

I would be happy if you could lend a hand. I face a second problem: At the moment you can only expand an item by double clicking. The underlying foldertreemodel populates incrementally (lazy). The SidebarTreeView calls canFetchMore() in lazy models if an item is activated somehow (triangle, double click, etc.). The SidebarTreeView will fetch more data from the model if canFetchMore() returns true.

I've implemented the (can)fetchMore methods in SideBarModel and FolderTreeModel. Recall that QAbstracItemModel::canFetchMore returns false by default, whenever it returns true in the overridden FolderTreeModel::canFetchMore() Mixxx crashes.

RJ, could you please take a look at my code? This might be helpful http://benjamin-meyer.blogspot.com/2006/10/dynamic-models.html

Thank you very much!

Revision history for this message
RAFFI TEA (raffitea) wrote :

I have solved the triangle issue!!! Please ignore my previous comment :-)

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

All my issues are fixed now, looks good to me.

Thanks Tobias!

review: Approve
Revision history for this message
RAFFI TEA (raffitea) wrote :

RJ, could you review once again please?

I've introduced signal/slots now to prevent segfaults through quick library navigation. Revision r2653 which is part of trunk works on OS X and Linux, but on Win it caused segfaults. This should be fixed now (at least for me it is).

Revision history for this message
RJ Skerry-Ryan (rryan) wrote :

It's looking good -- just merged it into trunk. Thanks Tobias!

review: Approve
2659. By Raffitea

Fixed some typos.

2660. By Raffitea

Implemented Playlist Export to M3U and PLS.

2661. By Raffitea

merging from trunk

2662. By Raffitea

Implemented relative M3U and PLS playlist export. Works fine on OS X with VLC but iTunes does not support relative paths.

2663. By Raffitea

Added an option to preferences to make relative playlist export optional.

2664. By Raffitea

Fixed a compiler warning on Windows. Also tested PLS and M3U export on Windows. Works as expected with Media Player and iTunes but also VLC, RealPlayer and Winamp.

2665. By Raffitea

Added a comment about QDir::relativePath().

2666. By Raffitea

Merging from trunk

2667. By Raffitea

Remove qDebug for TIO

2668. By Raffitea

Improved Playlist export dialog.

2669. By Raffitea

Drastically improved the population of the tracktable view in BrowseFeature. Hopefully does not freez the GUI while clicking through the folder structure.

2670. By Tobias <Tobias@Silverstar>

Merging manually from trunk

2671. By Tobias <Tobias@Silverstar>

Merging manually from trunk the third time.

2672. By Tobias <Tobias@Silverstar>

Merging from trunk to get library caching fixes

2673. By Raffitea

made BrowseTableModel singleton because the recording feature will use the BrowseTableModel to display contents of a special recording directory. This approach avoids two BrowseThreads. If I had made BrowseThread singleton there would be two BrowseTableModel objects and both would populate when the Thread is active. This is not performant

2674. By Raffitea

Merging from trunk to get PrepareFeature fixes

2675. By Raffitea

Merging from trunk

2676. By Raffitea

Merging from trunk

2677. By Raffitea

Removed the singleton character of BrowseTableModel. This was a really stupid idea....

2678. By Raffitea

Now made BrowseThread singleton. BrowseTableModel objects will only process received signals if they have asked the thread to do so.

2679. By Raffitea

Merging from trunk to get auto-expand feature

2680. By Raffitea

Merging from trunk

2681. By Raffitea

Renamed context menu entry for crate export/import; If file extension is missing, append .m3u to the export file and continue to export in m3u; Replaced Qt::BlockingQueuedConnection with QueuedConnection, which seems to work for rapid sidebar folder iterations with keyboard/MIDI; Added a global static member for BrowseThread::getInstance().

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'mixxx/build/depends.py'
2--- mixxx/build/depends.py 2011-02-13 21:30:36 +0000
3+++ mixxx/build/depends.py 2011-02-16 20:55:20 +0000
4@@ -498,6 +498,7 @@
5 "library/traktorfeature.cpp",
6 "library/traktortablemodel.cpp",
7 "library/traktorplaylistmodel.cpp",
8+ "library/browsethread.cpp",
9
10 "xmlparse.cpp",
11 "library/parser.cpp",
12
13=== modified file 'mixxx/src/library/browsetablemodel.cpp'
14--- mixxx/src/library/browsetablemodel.cpp 2011-02-13 22:09:54 +0000
15+++ mixxx/src/library/browsetablemodel.cpp 2011-02-16 20:55:20 +0000
16@@ -3,26 +3,13 @@
17 #include <QtSql>
18 #include <QStringList>
19 #include <QtConcurrentRun>
20+#include <QMetaType>
21
22 #include "browsetablemodel.h"
23 #include "soundsourceproxy.h"
24 #include "mixxxutils.cpp"
25
26-//constants
27-const int COLUMN_FILENAME = 0;
28-const int COLUMN_ARTIST = 1;
29-const int COLUMN_TITLE = 2;
30-const int COLUMN_ALBUM = 3;
31-const int COLUMN_TRACK_NUMBER = 4;
32-const int COLUMN_YEAR = 5;
33-const int COLUMN_GENRE = 6;
34-const int COLUMN_COMMENT = 7;
35-const int COLUMN_DURATION = 8;
36-const int COLUMN_BPM = 9;
37-const int COLUMN_KEY = 10;
38-const int COLUMN_TYPE = 11;
39-const int COLUMN_BITRATE = 12;
40-const int COLUMN_LOCATION = 13;
41+
42
43 BrowseTableModel::BrowseTableModel(QObject* parent)
44 : QStandardItemModel(parent),
45@@ -53,26 +40,22 @@
46 addSearchColumn(COLUMN_GENRE);
47 addSearchColumn(COLUMN_KEY);
48 addSearchColumn(COLUMN_COMMENT);
49-
50- setHorizontalHeaderLabels(header_data);
51-
52- /*
53- * Start background thread.
54- * Used to read the ID3 tags
55- */
56- m_bStopThread = false;
57- m_future = QtConcurrent::run(this, &BrowseTableModel::browserThread);
58- m_path = "";
59+
60+ //m_backgroundThread.moveToThread(&m_backgroundThread);
61+ m_backgroundThread.start(QThread::LowestPriority);
62+
63+ setHorizontalHeaderLabels(header_data);
64+
65+ QObject::connect(&m_backgroundThread, SIGNAL(clearModel()),
66+ this, SLOT(slotClear()));
67+ QObject::connect(&m_backgroundThread, SIGNAL(rowDataAppended(const QList<QStandardItem*>&)),
68+ this, SLOT(slotInsert(const QList<QStandardItem*>&)), Qt::DirectConnection);
69+
70 }
71
72 BrowseTableModel::~BrowseTableModel()
73 {
74- qDebug() << "Wait to finish browser background thread";
75- m_bStopThread = true;
76- //wake up thread since it might wait for user input
77- m_locationUpdated.wakeAll();
78- m_future.waitForFinished();
79- qDebug() << "Browser background thread terminated!";
80+
81 }
82
83 const QList<int>& BrowseTableModel::searchColumns() const {
84@@ -83,8 +66,7 @@
85 }
86 void BrowseTableModel::setPath(QString absPath)
87 {
88- m_path = absPath;
89- m_locationUpdated.wakeAll();
90+ m_backgroundThread.setPath(absPath);
91
92 }
93
94@@ -169,99 +151,15 @@
95 mimeData->setUrls(urls);
96 return mimeData;
97 }
98-void BrowseTableModel::populateModel()
99+
100+void BrowseTableModel::slotClear()
101 {
102- //Refresh the name filters in case we loaded new
103- //SoundSource plugins.
104- QStringList nameFilters(SoundSourceProxy::supportedFileExtensionsString().split(" "));
105- QDirIterator fileIt(m_path, nameFilters, QDir::Files | QDir::NoDotAndDotDot);
106- QString thisPath(m_path);
107- //remove all rows
108 removeRows(0, rowCount());
109-
110- int row = 0;
111- //Iterate over the files
112- while (fileIt.hasNext())
113- {
114- /*
115- * If a user quickly jumps through the folders
116- * the current task becomes "dirty"
117- */
118- if(thisPath != m_path){
119- //qDebug() << "Exit populateModel()";
120- return;
121- }
122- QString filepath = fileIt.next();
123- TrackInfoObject tio(filepath);
124-
125- QStandardItem* item = new QStandardItem(tio.getFilename());
126- setItem(row, COLUMN_FILENAME, item);
127-
128- item = new QStandardItem(tio.getArtist());
129- setItem(row, COLUMN_ARTIST, item);
130-
131- item = new QStandardItem(tio.getTitle());
132- setItem(row, COLUMN_TITLE, item);
133-
134- item = new QStandardItem(tio.getAlbum());
135- setItem(row, COLUMN_ALBUM, item);
136-
137- QString duration = MixxxUtils::secondsToMinutes(qVariantValue<int>(tio.getDuration()));
138- item = new QStandardItem(duration);
139- setItem(row, COLUMN_DURATION, item);
140-
141- item = new QStandardItem(tio.getBpmStr());
142- setItem(row, COLUMN_BPM, item);
143-
144- item = new QStandardItem(tio.getKey());
145- setItem(row, COLUMN_KEY, item);
146-
147- item = new QStandardItem(tio.getYear());
148- setItem(row, COLUMN_YEAR, item);
149-
150- item = new QStandardItem(tio.getBitrateStr());
151- setItem(row, COLUMN_BITRATE, item);
152-
153- item = new QStandardItem(tio.getType());
154- setItem(row, COLUMN_TYPE, item);
155-
156- item = new QStandardItem(tio.getGenre());
157- setItem(row, COLUMN_GENRE, item);
158-
159- item = new QStandardItem(tio.getTrackNumber());
160- setItem(row, COLUMN_TRACK_NUMBER, item);
161-
162- item = new QStandardItem(tio.getComment());
163- setItem(row, COLUMN_COMMENT, item);
164-
165- item = new QStandardItem(filepath);
166- setItem(row, COLUMN_LOCATION, item);
167-
168- ++row;
169-
170- }
171 }
172-void BrowseTableModel::browserThread()
173+void BrowseTableModel::slotInsert(const QList<QStandardItem*> &column_data)
174 {
175- //Give the thread low priority to prevent GUI freezing
176- QThread* thisThread = QThread::currentThread();
177- thisThread->setPriority(QThread::LowestPriority);
178-
179- while(1){
180- m_mutex.lock();
181- //Wait until the user has selected a folder
182- m_locationUpdated.wait(&m_mutex);
183-
184- //Terminate thread if Mixxx closes
185- if(m_bStopThread)
186- return;
187-
188- /*
189- * Populate the model
190- */
191- populateModel();
192-
193- m_mutex.unlock();
194-
195- }
196+ qDebug() << "BrowseTableModel::slotInsert";
197+ appendRow(column_data);
198+ //Does not work for some reason
199+ //setItem(row, column, item);
200 }
201
202=== modified file 'mixxx/src/library/browsetablemodel.h'
203--- mixxx/src/library/browsetablemodel.h 2011-02-13 19:42:53 +0000
204+++ mixxx/src/library/browsetablemodel.h 2011-02-16 20:55:20 +0000
205@@ -3,9 +3,26 @@
206
207 #include <QStandardItemModel>
208 #include "trackmodel.h"
209+#include "browsethread.h"
210
211 class QMimeData;
212
213+//constants
214+const int COLUMN_FILENAME = 0;
215+const int COLUMN_ARTIST = 1;
216+const int COLUMN_TITLE = 2;
217+const int COLUMN_ALBUM = 3;
218+const int COLUMN_TRACK_NUMBER = 4;
219+const int COLUMN_YEAR = 5;
220+const int COLUMN_GENRE = 6;
221+const int COLUMN_COMMENT = 7;
222+const int COLUMN_DURATION = 8;
223+const int COLUMN_BPM = 9;
224+const int COLUMN_KEY = 10;
225+const int COLUMN_TYPE = 11;
226+const int COLUMN_BITRATE = 12;
227+const int COLUMN_LOCATION = 13;
228+
229 class BrowseTableModel : public QStandardItemModel, public TrackModel
230 {
231
232@@ -30,20 +47,13 @@
233 virtual bool isColumnHiddenByDefault(int column);
234 virtual const QList<int>& searchColumns() const;
235 private:
236- void populateModel();
237- //This method is executed in a Thread
238- void browserThread();
239- // Add a column to be searched when searching occurs
240 void addSearchColumn(int index);
241
242- QMutex m_mutex;
243- QWaitCondition m_locationUpdated;
244-
245- QFuture<void> m_future;
246- QList<int> m_searchColumns;
247- QString m_path;
248-
249- bool m_bStopThread;
250+ BrowseThread m_backgroundThread;
251+ QList<int> m_searchColumns;
252+public slots:
253+ void slotClear();
254+ void slotInsert(const QList<QStandardItem*> &item);
255 };
256
257 #endif
258
259=== added file 'mixxx/src/library/browsethread.cpp'
260--- mixxx/src/library/browsethread.cpp 1970-01-01 00:00:00 +0000
261+++ mixxx/src/library/browsethread.cpp 2011-02-16 20:55:20 +0000
262@@ -0,0 +1,140 @@
263+#include "browsethread.h"
264+#include "browsetablemodel.h"
265+#include "soundsourceproxy.h"
266+#include "mixxxutils.cpp"
267+
268+#include <QStringList>
269+#include <QDirIterator>
270+#include <QtCore>
271+
272+
273+BrowseThread::BrowseThread(QObject *parent) : QThread(parent)
274+{
275+ //start thread
276+ m_bStopThread = false;
277+
278+ //QObject::moveToThread(this);
279+}
280+BrowseThread::~BrowseThread()
281+{
282+ qDebug() << "Wait to finish browser background thread";
283+ m_bStopThread = true;
284+ //wake up thread since it might wait for user input
285+ m_locationUpdated.wakeAll();
286+ //Wait until thread terminated
287+ //terminate();
288+ wait();
289+ qDebug() << "Browser background thread terminated!";
290+
291+}
292+
293+void BrowseThread::setPath(QString& path)
294+{
295+ m_path = path;
296+ m_locationUpdated.wakeAll();
297+
298+}
299+
300+void BrowseThread::run()
301+{
302+
303+ while(1){
304+ m_mutex.lock();
305+ //Wait until the user has selected a folder
306+ m_locationUpdated.wait(&m_mutex);
307+
308+ //Terminate thread if Mixxx closes
309+ if(m_bStopThread)
310+ return;
311+
312+ /*
313+ * Populate the model
314+ */
315+ populateModel();
316+ m_mutex.unlock();
317+
318+ }
319+
320+}
321+void BrowseThread::populateModel()
322+{
323+ //Refresh the name filters in case we loaded new
324+ //SoundSource plugins.
325+ QStringList nameFilters(SoundSourceProxy::supportedFileExtensionsString().split(" "));
326+ QDirIterator fileIt(m_path, nameFilters, QDir::Files | QDir::NoDotAndDotDot);
327+ QString thisPath(m_path);
328+ //remove all rows
329+ emit(clearModel());
330+ QCoreApplication::processEvents();
331+
332+ int row = 0;
333+ //Iterate over the files
334+ while (fileIt.hasNext())
335+ {
336+ /*
337+ * If a user quickly jumps through the folders
338+ * the current task becomes "dirty"
339+ */
340+ if(thisPath != m_path){
341+ qDebug() << "Exit populateModel()";
342+ return populateModel();
343+ }
344+
345+ QString filepath = fileIt.next();
346+ TrackInfoObject tio(filepath);
347+ QList<QStandardItem*> column_data;
348+
349+ QStandardItem* item = new QStandardItem(tio.getFilename());
350+ column_data.insert(COLUMN_FILENAME, item);
351+
352+
353+ item = new QStandardItem(tio.getArtist());
354+ column_data.insert(COLUMN_ARTIST, item);
355+
356+ item = new QStandardItem(tio.getTitle());
357+ column_data.insert(COLUMN_TITLE, item);
358+
359+ item = new QStandardItem(tio.getAlbum());
360+ column_data.insert(COLUMN_ALBUM, item);
361+
362+ item = new QStandardItem(tio.getTrackNumber());
363+ column_data.insert(COLUMN_TRACK_NUMBER, item);
364+
365+ item = new QStandardItem(tio.getYear());
366+ column_data.insert(COLUMN_YEAR, item);
367+
368+ item = new QStandardItem(tio.getGenre());
369+ column_data.insert(COLUMN_GENRE, item);
370+
371+ item = new QStandardItem(tio.getComment());
372+ column_data.insert(COLUMN_COMMENT, item);
373+
374+ QString duration = MixxxUtils::secondsToMinutes(qVariantValue<int>(tio.getDuration()));
375+ item = new QStandardItem(duration);
376+ column_data.insert(COLUMN_DURATION, item);
377+
378+ item = new QStandardItem(tio.getBpmStr());
379+ column_data.insert(COLUMN_BPM, item);
380+
381+ item = new QStandardItem(tio.getKey());
382+ column_data.insert(COLUMN_KEY, item);
383+
384+ item = new QStandardItem(tio.getType());
385+ column_data.insert(COLUMN_TYPE, item);
386+
387+ item = new QStandardItem(tio.getBitrateStr());
388+ column_data.insert(COLUMN_BITRATE, item);
389+
390+ item = new QStandardItem(filepath);
391+ column_data.insert(COLUMN_LOCATION, item);
392+
393+ emit(rowDataAppended(column_data));
394+
395+ QCoreApplication::processEvents();
396+ ++row;
397+
398+ //Sleep for 50ms which prevents us from GUI freezes
399+ msleep(50);
400+ }
401+
402+}
403
404=== added file 'mixxx/src/library/browsethread.h'
405--- mixxx/src/library/browsethread.h 1970-01-01 00:00:00 +0000
406+++ mixxx/src/library/browsethread.h 2011-02-16 20:55:20 +0000
407@@ -0,0 +1,37 @@
408+#ifndef BROWSETHREAD_H
409+#define BROWSETHREAD_H
410+
411+#include <QThread>
412+#include <QMutex>
413+#include <QWaitCondition>
414+#include <QStandardItem>
415+#include <QList>
416+
417+class BrowseThread : public QThread
418+{
419+ Q_OBJECT
420+public:
421+ BrowseThread(QObject *parent = 0);
422+ ~BrowseThread();
423+ void setPath(QString& path);
424+ void run();
425+signals:
426+ void rowDataAppended(const QList<QStandardItem*>&);
427+ void clearModel();
428+private:
429+ void populateModel();
430+ QMutex m_mutex;
431+ QWaitCondition m_locationUpdated;
432+
433+
434+ QList<int> m_searchColumns;
435+ QString m_path;
436+
437+ bool m_bStopThread;
438+
439+
440+
441+
442+};
443+
444+#endif // BROWSETHREAD_H