diff options
author | RJ Ryan <rryan@mixxx.org> | 2014-01-29 01:40:48 -0500 |
---|---|---|
committer | RJ Ryan <rryan@mixxx.org> | 2014-02-13 23:31:31 -0500 |
commit | 3fa83e6f2d91ee63f40994c2c4171db09f04d983 (patch) | |
tree | e0810bb27026ed45d6caaac8ab64c78be31a9176 /src | |
parent | 47970a144612700e9f1b31617f11c815c6b37cc7 (diff) |
Handle creation of scoped bookmarks on drop of files in Mixxx.
* Clean up / unify processing of dropped URLs across all drop handlers.
* Support dropping of playlists on the analysis, playlists, crate, autodj, and
track table sections of the library (previously was only supported in
playlists).
Diffstat (limited to 'src')
-rw-r--r-- | src/library/analysisfeature.cpp | 11 | ||||
-rw-r--r-- | src/library/autodjfeature.cpp | 16 | ||||
-rw-r--r-- | src/library/cratefeature.cpp | 9 | ||||
-rw-r--r-- | src/library/mixxxlibraryfeature.cpp | 11 | ||||
-rw-r--r-- | src/library/playlistfeature.cpp | 30 | ||||
-rw-r--r-- | src/util/dnd.h | 95 | ||||
-rw-r--r-- | src/widget/wlibrarysidebar.cpp | 2 | ||||
-rw-r--r-- | src/widget/woverview.cpp | 21 | ||||
-rw-r--r-- | src/widget/wspinny.cpp | 23 | ||||
-rw-r--r-- | src/widget/wtracktableview.cpp | 32 | ||||
-rw-r--r-- | src/widget/wwaveformviewer.cpp | 23 |
11 files changed, 150 insertions, 123 deletions
diff --git a/src/library/analysisfeature.cpp b/src/library/analysisfeature.cpp index a6790ecd71..8e163b1854 100644 --- a/src/library/analysisfeature.cpp +++ b/src/library/analysisfeature.cpp @@ -12,6 +12,7 @@ #include "mixxxkeyboard.h" #include "analyserqueue.h" #include "soundsourceproxy.h" +#include "util/dnd.h" const QString AnalysisFeature::m_sAnalysisViewName = QString("Analysis"); @@ -134,15 +135,7 @@ void AnalysisFeature::cleanupAnalyser() { bool AnalysisFeature::dropAccept(QList<QUrl> urls, QObject* pSource) { Q_UNUSED(pSource); - QList<QFileInfo> files; - foreach (QUrl url, urls) { - // XXX: Possible WTF alert - Previously we thought we needed toString() here - // but what you actually want in any case when converting a QUrl to a file - // system path is QUrl::toLocalFile(). This is the second time we have - // flip-flopped on this, but I think toLocalFile() should work in any - // case. toString() absolutely does not work when you pass the result to a - files.append(url.toLocalFile()); - } + QList<QFileInfo> files = DragAndDropHelper::supportedTracksFromUrls(urls, false, true); // Adds track, does not insert duplicates, handles unremoving logic. QList<int> trackIds = m_pTrackCollection->getTrackDAO().addTracks(files, true); analyzeTracks(trackIds); diff --git a/src/library/autodjfeature.cpp b/src/library/autodjfeature.cpp index 9338842278..083fb8e0ab 100644 --- a/src/library/autodjfeature.cpp +++ b/src/library/autodjfeature.cpp @@ -15,6 +15,7 @@ #include "widget/wlibrary.h" #include "mixxxkeyboard.h" #include "soundsourceproxy.h" +#include "util/dnd.h" const QString AutoDJFeature::m_sAutoDJViewName = QString("Auto DJ"); @@ -119,17 +120,10 @@ bool AutoDJFeature::dropAccept(QList<QUrl> urls, QObject* pSource) { //TODO: Filter by supported formats regex and reject anything that doesn't match. TrackDAO &trackDao = m_pTrackCollection->getTrackDAO(); - //If a track is dropped onto a playlist's name, but the track isn't in the library, - //then add the track to the library before adding it to the playlist. - QList<QFileInfo> files; - foreach (QUrl url, urls) { - //XXX: See the note in PlaylistFeature::dropAccept() about using QUrl::toLocalFile() - // instead of toString() - QFileInfo file = url.toLocalFile(); - if (SoundSourceProxy::isFilenameSupported(file.fileName())) { - files.append(file); - } - } + // If a track is dropped onto a playlist's name, but the track isn't in the + // library, then add the track to the library before adding it to the + // playlist. + QList<QFileInfo> files = DragAndDropHelper::supportedTracksFromUrls(urls, false, true); QList<int> trackIds; if (pSource) { trackIds = trackDao.getTrackIds(files); diff --git a/src/library/cratefeature.cpp b/src/library/cratefeature.cpp index 6630b8e1de..2671d3d4be 100644 --- a/src/library/cratefeature.cpp +++ b/src/library/cratefeature.cpp @@ -20,6 +20,7 @@ #include "mixxxkeyboard.h" #include "treeitem.h" #include "soundsourceproxy.h" +#include "util/dnd.h" CrateFeature::CrateFeature(QObject* parent, TrackCollection* pTrackCollection, @@ -114,13 +115,7 @@ bool CrateFeature::dropAcceptChild(const QModelIndex& index, QList<QUrl> urls, QObject* pSource) { QString crateName = index.data().toString(); int crateId = m_crateDao.getCrateIdByName(crateName); - QList<QFileInfo> files; - foreach (QUrl url, urls) { - //XXX: See the comment in PlaylistFeature::dropAcceptChild() about - // QUrl::toLocalFile() vs. QUrl::toString() usage. - files.append(url.toLocalFile()); - } - + QList<QFileInfo> files = DragAndDropHelper::supportedTracksFromUrls(urls, false, true); QList<int> trackIds; if (pSource) { trackIds = m_pTrackCollection->getTrackDAO().getTrackIds(files); diff --git a/src/library/mixxxlibraryfeature.cpp b/src/library/mixxxlibraryfeature.cpp index 3badd625d0..09b6bfb036 100644 --- a/src/library/mixxxlibraryfeature.cpp +++ b/src/library/mixxxlibraryfeature.cpp @@ -14,6 +14,7 @@ #include "treeitem.h" #include "soundsourceproxy.h" #include "widget/wlibrary.h" +#include "util/dnd.h" MixxxLibraryFeature::MixxxLibraryFeature(QObject* parent, TrackCollection* pTrackCollection, @@ -162,15 +163,7 @@ bool MixxxLibraryFeature::dropAccept(QList<QUrl> urls, QObject* pSource) { if (pSource) { return false; } else { - QList<QFileInfo> files; - foreach (QUrl url, urls) { - // XXX: Possible WTF alert - Previously we thought we needed toString() here - // but what you actually want in any case when converting a QUrl to a file - // system path is QUrl::toLocalFile(). This is the second time we have - // flip-flopped on this, but I think toLocalFile() should work in any - // case. toString() absolutely does not work when you pass the result to a - files.append(url.toLocalFile()); - } + QList<QFileInfo> files = DragAndDropHelper::supportedTracksFromUrls(urls, false, true); // Adds track, does not insert duplicates, handles unremoving logic. QList<int> trackIds = m_trackDao.addTracks(files, true); diff --git a/src/library/playlistfeature.cpp b/src/library/playlistfeature.cpp index 6d7bd687fc..07bc6e7533 100644 --- a/src/library/playlistfeature.cpp +++ b/src/library/playlistfeature.cpp @@ -4,10 +4,6 @@ #include <QFileInfo> #include "library/playlistfeature.h" -#include "library/parser.h" -#include "library/parserm3u.h" -#include "library/parserpls.h" -#include "library/parsercsv.h" #include "widget/wlibrary.h" #include "widget/wlibrarysidebar.h" @@ -17,6 +13,7 @@ #include "library/treeitem.h" #include "mixxxkeyboard.h" #include "soundsourceproxy.h" +#include "util/dnd.h" PlaylistFeature::PlaylistFeature(QObject* parent, TrackCollection* pTrackCollection, @@ -90,29 +87,8 @@ bool PlaylistFeature::dropAcceptChild(const QModelIndex& index, QList<QUrl> urls QString playlistName = index.data().toString(); int playlistId = m_playlistDao.getPlaylistIdFromName(playlistName); //m_playlistDao.appendTrackToPlaylist(url.toLocalFile(), playlistId); - QList<QFileInfo> files; - foreach (QUrl url, urls) { - // XXX: Possible WTF alert - Previously we thought we needed toString() here - // but what you actually want in any case when converting a QUrl to a file - // system path is QUrl::toLocalFile(). This is the second time we have - // flip-flopped on this, but I think toLocalFile() should work in any - // case. toString() absolutely does not work when you pass the result to a - if (url.toString().endsWith(".m3u") || url.toString().endsWith(".m3u8")) { - QScopedPointer<ParserM3u> playlist_parser(new ParserM3u()); - QList<QString> track_list = playlist_parser->parse(url.toLocalFile()); - for (int i = 0; i < track_list.size(); i++) { - files.append(track_list.at(i)); - } - } else if (url.toString().endsWith(".pls")) { - QScopedPointer<ParserPls> playlist_parser(new ParserPls()); - QList<QString> track_list = playlist_parser->parse(url.toLocalFile()); - for (int i = 0; i < track_list.size(); i++) { - files.append(track_list.at(i)); - } - } else { - files.append(url.toLocalFile()); - } - } + + QList<QFileInfo> files = DragAndDropHelper::supportedTracksFromUrls(urls, false, true); QList<int> trackIds; if (pSource) { diff --git a/src/util/dnd.h b/src/util/dnd.h new file mode 100644 index 0000000000..415ceee762 --- /dev/null +++ b/src/util/dnd.h @@ -0,0 +1,95 @@ +#ifndef DND_H +#define DND_H + +#include <QUrl> +#include <QList> +#include <QString> +#include <QFileInfo> +#include <QRegExp> +#include <QScopedPointer> + +#include "soundsourceproxy.h" +#include "library/parser.h" +#include "library/parserm3u.h" +#include "library/parserpls.h" +#include "library/parsercsv.h" +#include "util/sandbox.h" + +class DragAndDropHelper { + public: + static QList<QFileInfo> supportedTracksFromUrls(const QList<QUrl>& urls, + bool firstOnly, + bool acceptPlaylists) { + QList<QFileInfo> fileLocations; + foreach (const QUrl& url, urls) { + + // XXX: Possible WTF alert - Previously we thought we needed + // toString() here but what you actually want in any case when + // converting a QUrl to a file system path is + // QUrl::toLocalFile(). This is the second time we have flip-flopped + // on this, but I think toLocalFile() should work in any + // case. toString() absolutely does not work when you pass the + // result to a (this comment was never finished by the original + // author). + QString file(url.toLocalFile()); + + // If the file is on a network share, try just converting the URL to + // a string... + if (file.isEmpty()) { + file = url.toString(); + } + + if (file.isEmpty()) { + continue; + } + + if (acceptPlaylists && (file.endsWith(".m3u") || file.endsWith(".m3u8"))) { + QScopedPointer<ParserM3u> playlist_parser(new ParserM3u()); + QList<QString> track_list = playlist_parser->parse(file); + foreach (const QString& playlistFile, track_list) { + addFileToList(playlistFile, &fileLocations); + } + } else if (acceptPlaylists && url.toString().endsWith(".pls")) { + QScopedPointer<ParserPls> playlist_parser(new ParserPls()); + QList<QString> track_list = playlist_parser->parse(file); + foreach (const QString& playlistFile, track_list) { + addFileToList(playlistFile, &fileLocations); + } + } else { + addFileToList(file, &fileLocations); + } + + if (firstOnly && !fileLocations.isEmpty()) { + break; + } + } + + return fileLocations; + } + + private: + + static bool addFileToList(const QString& file, QList<QFileInfo>* files) { + QFileInfo fileInfo(file); + + // Since the user just dropped these files into Mixxx we have permission + // to touch the file. Create a security token to keep this permission + // across reboots. + Sandbox::createSecurityToken(fileInfo); + + if (!fileInfo.exists()) { + return false; + } + + // Filter out invalid URLs (eg. files that aren't supported audio + // filetypes, etc.) + if (!SoundSourceProxy::isFilenameSupported(fileInfo.fileName())) { + return false; + } + + files->append(fileInfo); + return true; + } +}; + +#endif /* DND_H */ diff --git a/src/widget/wlibrarysidebar.cpp b/src/widget/wlibrarysidebar.cpp index f650eb3462..4d1a0625d6 100644 --- a/src/widget/wlibrarysidebar.cpp +++ b/src/widget/wlibrarysidebar.cpp @@ -111,7 +111,6 @@ void WLibrarySidebar::timerEvent(QTimerEvent *event) { // Drag-and-drop "drop" event. Occurs when something is dropped onto the track sources view void WLibrarySidebar::dropEvent(QDropEvent * event) { if (event->mimeData()->hasUrls()) { - QList<QUrl> urls(event->mimeData()->urls()); // Drag and drop within this widget if ((event->source() == this) && (event->possibleActions() & Qt::MoveAction)) { @@ -127,6 +126,7 @@ void WLibrarySidebar::dropEvent(QDropEvent * event) { QModelIndex destIndex = indexAt(event->pos()); // event->source() will return NULL if something is droped from // a different application + QList<QUrl> urls(event->mimeData()->urls()); if (sidebarModel->dropAccept(destIndex, urls, event->source())) { event->acceptProposedAction(); } else { diff --git a/src/widget/woverview.cpp b/src/widget/woverview.cpp index 134cf76d2c..b02cab4e5b 100644 --- a/src/widget/woverview.cpp +++ b/src/widget/woverview.cpp @@ -27,6 +27,7 @@ #include "trackinfoobject.h" #include "mathstuff.h" #include "util/timer.h" +#include "util/dnd.h" #include "waveform/waveform.h" #include "waveform/waveformwidgetfactory.h" @@ -499,18 +500,14 @@ void WOverview::dragEnterEvent(QDragEnterEvent* event) { } void WOverview::dropEvent(QDropEvent* event) { - if (event->mimeData()->hasUrls() && - event->mimeData()->urls().size() > 0) { - QList<QUrl> urls(event->mimeData()->urls()); - QUrl url = urls.first(); - QString name = url.toLocalFile(); - //If the file is on a network share, try just converting the URL to a string... - if (name == "") { - name = url.toString(); + if (event->mimeData()->hasUrls()) { + QList<QFileInfo> files = DragAndDropHelper::supportedTracksFromUrls( + event->mimeData()->urls(), true, false); + if (!files.isEmpty()) { + event->accept(); + emit(trackDropped(files.at(0).canonicalFilePath(), m_group)); + return; } - event->accept(); - emit(trackDropped(name, m_group)); - } else { - event->ignore(); } + event->ignore(); } diff --git a/src/widget/wspinny.cpp b/src/widget/wspinny.cpp index 212ab27561..8036acbd27 100644 --- a/src/widget/wspinny.cpp +++ b/src/widget/wspinny.cpp @@ -15,6 +15,7 @@ #include "widget/wspinny.h" #include "vinylcontrol/vinylcontrolmanager.h" #include "vinylcontrol/vinylcontrol.h" +#include "util/dnd.h" WSpinny::WSpinny(QWidget* parent, VinylControlManager* pVCMan) : QGLWidget(parent, SharedGLContext::getWidget()), @@ -498,19 +499,15 @@ void WSpinny::dragEnterEvent(QDragEnterEvent * event) } } -void WSpinny::dropEvent(QDropEvent * event) -{ +void WSpinny::dropEvent(QDropEvent * event) { if (event->mimeData()->hasUrls()) { - QList<QUrl> urls(event->mimeData()->urls()); - QUrl url = urls.first(); - QString name = url.toLocalFile(); - //If the file is on a network share, try just converting the URL to a string... - if (name == "") - name = url.toString(); - - event->accept(); - emit(trackDropped(name, m_group)); - } else { - event->ignore(); + QList<QFileInfo> files = DragAndDropHelper::supportedTracksFromUrls( + event->mimeData()->urls(), true, false); + if (!files.isEmpty()) { + event->accept(); + emit(trackDropped(files.at(0).canonicalFilePath(), m_group)); + return; + } } + event->ignore(); } diff --git a/src/widget/wtracktableview.cpp b/src/widget/wtracktableview.cpp index 0d7d44be27..3091f30038 100644 --- a/src/widget/wtracktableview.cpp +++ b/src/widget/wtracktableview.cpp @@ -16,6 +16,7 @@ #include "dlgtrackinfo.h" #include "soundsourceproxy.h" #include "playermanager.h" +#include "util/dnd.h" WTrackTableView::WTrackTableView(QWidget * parent, ConfigObject<ConfigValue> * pConfig, @@ -902,20 +903,6 @@ void WTrackTableView::dropEvent(QDropEvent * event) { event->ignore(); return; } - QList<QUrl> urls(event->mimeData()->urls()); - QUrl url; - QModelIndex selectedIndex; //Index of a selected track (iterator) - - // Filter out invalid URLs (eg. files that aren't supported audio filetypes, etc.) - QRegExp fileRx(SoundSourceProxy::supportedFileExtensionsRegex(), - Qt::CaseInsensitive); - for (int i = 0; i < urls.size(); ++i) { - if (fileRx.indexIn(urls.at(i).path()) == -1) { - // remove invalid urls and decrease i because the size of - // urls has changed. - urls.removeAt(--i); - } - } // Save the vertical scrollbar position. Adding new tracks and moving tracks in // the SQL data models causes a select() (ie. generation of a new result set), @@ -1038,9 +1025,18 @@ void WTrackTableView::dropEvent(QDropEvent * event) { // clears them) this->selectionModel()->clear(); + // Add all the dropped URLs/tracks to the track model (playlist/crate) + QList<QFileInfo> fileList = DragAndDropHelper::supportedTracksFromUrls( + event->mimeData()->urls(), false, true); + + QList<QString> fileLocationList; + foreach (const QFileInfo& fileInfo, fileList) { + fileLocationList.append(fileInfo.canonicalFilePath()); + } + // Drag-and-drop from an external application // eg. dragging a track from Windows Explorer onto the track table. - int numNewRows = urls.count(); + int numNewRows = fileLocationList.count(); // Have to do this here because the index is invalid after // addTrack @@ -1061,12 +1057,6 @@ void WTrackTableView::dropEvent(QDropEvent * event) { selectionStartRow = model()->rowCount(); } - // Add all the dropped URLs/tracks to the track model (playlist/crate) - QList<QString> fileLocationList; - foreach(url, urls) { - QString file(url.toLocalFile()); - fileLocationList.append(file); - } // calling the addTracks returns number of failed additions int tracksAdded = trackModel->addTracks(destIndex, fileLocationList); diff --git a/src/widget/wwaveformviewer.cpp b/src/widget/wwaveformviewer.cpp index f61368ffe8..ff0ed311b7 100644 --- a/src/widget/wwaveformviewer.cpp +++ b/src/widget/wwaveformviewer.cpp @@ -13,6 +13,7 @@ #include "waveform/widgets/waveformwidgetabstract.h" #include "widget/wwaveformviewer.h" #include "waveform/waveformwidgetfactory.h" +#include "util/dnd.h" WWaveformViewer::WWaveformViewer(const char *group, ConfigObject<ConfigValue>* pConfig, QWidget * parent) : WWidget(parent), @@ -161,20 +162,16 @@ void WWaveformViewer::dragEnterEvent(QDragEnterEvent * event) { } void WWaveformViewer::dropEvent(QDropEvent * event) { - if (event->mimeData()->hasUrls() && - event->mimeData()->urls().size() > 0) { - QList<QUrl> urls(event->mimeData()->urls()); - QUrl url = urls.first(); - QString name = url.toLocalFile(); - //If the file is on a network share, try just converting the URL to a string... - if (name == "") - name = url.toString(); - - event->accept(); - emit(trackDropped(name, m_pGroup)); - } else { - event->ignore(); + if (event->mimeData()->hasUrls()) { + QList<QFileInfo> files = DragAndDropHelper::supportedTracksFromUrls( + event->mimeData()->urls(), true, false); + if (!files.isEmpty()) { + event->accept(); + emit(trackDropped(files.at(0).canonicalFilePath(), m_pGroup)); + return; + } } + event->ignore(); } void WWaveformViewer::onTrackLoaded( TrackPointer track) { |