mirror of
https://github.com/clementine-player/Clementine
synced 2025-02-03 04:37:33 +01:00
Use a common LoadTracks implementation for most search providers
This commit is contained in:
parent
99463215bf
commit
c9745bca5d
@ -56,8 +56,6 @@ void GlobalSearch::ConnectProvider(SearchProvider* provider) {
|
||||
SLOT(SearchFinishedSlot(int)));
|
||||
connect(provider, SIGNAL(ArtLoaded(int,QImage)),
|
||||
SLOT(ArtLoadedSlot(int,QImage)));
|
||||
connect(provider, SIGNAL(TracksLoaded(int,MimeData*)),
|
||||
SIGNAL(TracksLoaded(int,MimeData*)));
|
||||
connect(provider, SIGNAL(destroyed(QObject*)),
|
||||
SLOT(ProviderDestroyedSlot(QObject*)));
|
||||
}
|
||||
@ -278,12 +276,23 @@ bool GlobalSearch::FindCachedPixmap(const SearchProvider::Result& result,
|
||||
return pixmap_cache_.find(result.pixmap_cache_key_, pixmap);
|
||||
}
|
||||
|
||||
int GlobalSearch::LoadTracksAsync(const SearchProvider::Result& result) {
|
||||
const int id = next_id_ ++;
|
||||
MimeData* GlobalSearch::LoadTracks(const SearchProvider::ResultList& results) {
|
||||
// Different providers might create MimeData in different ways, so it's not
|
||||
// possible to combine different providers. Just take the results from a
|
||||
// single provider.
|
||||
if (results.isEmpty()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result.provider_->LoadTracksAsync(id, result);
|
||||
SearchProvider* first_provider = results[0].provider_;
|
||||
SearchProvider::ResultList results_copy;
|
||||
foreach (const SearchProvider::Result& result, results) {
|
||||
if (result.provider_ == first_provider) {
|
||||
results_copy << result;
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
return first_provider->LoadTracks(results);
|
||||
}
|
||||
|
||||
bool GlobalSearch::SetProviderEnabled(const SearchProvider* const_provider,
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
|
||||
int SearchAsync(const QString& query);
|
||||
int LoadArtAsync(const SearchProvider::Result& result);
|
||||
int LoadTracksAsync(const SearchProvider::Result& result);
|
||||
MimeData* LoadTracks(const SearchProvider::ResultList& results);
|
||||
QStringList GetSuggestions(int max);
|
||||
|
||||
void CancelSearch(int id);
|
||||
@ -72,8 +72,6 @@ signals:
|
||||
|
||||
void ArtLoaded(int id, const QPixmap& pixmap);
|
||||
|
||||
void TracksLoaded(int id, MimeData* mime_data);
|
||||
|
||||
void ProviderAdded(const SearchProvider* provider);
|
||||
void ProviderRemoved(const SearchProvider* provider);
|
||||
|
||||
|
@ -109,8 +109,6 @@ GlobalSearchView::GlobalSearchView(Application* app, QWidget* parent)
|
||||
Qt::QueuedConnection);
|
||||
connect(engine_, SIGNAL(ArtLoaded(int,QPixmap)), SLOT(ArtLoaded(int,QPixmap)),
|
||||
Qt::QueuedConnection);
|
||||
connect(engine_, SIGNAL(TracksLoaded(int,MimeData*)), SLOT(TracksLoaded(int,MimeData*)),
|
||||
Qt::QueuedConnection);
|
||||
|
||||
ReloadSettings();
|
||||
}
|
||||
@ -373,24 +371,54 @@ void GlobalSearchView::ArtLoaded(int id, const QPixmap& pixmap) {
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalSearchView::LoadTracks() {
|
||||
QModelIndex index = ui_->results->currentIndex();
|
||||
if (!index.isValid())
|
||||
index = front_proxy_->index(0, 0);
|
||||
|
||||
if (!index.isValid())
|
||||
void GlobalSearchView::GetChildResults(const QStandardItem* item,
|
||||
SearchProvider::ResultList* results,
|
||||
QSet<const QStandardItem*>* visited) const {
|
||||
if (visited->contains(item)) {
|
||||
return;
|
||||
}
|
||||
visited->insert(item);
|
||||
|
||||
const SearchProvider::Result result =
|
||||
index.data(Role_Result).value<SearchProvider::Result>();
|
||||
|
||||
engine_->LoadTracksAsync(result);
|
||||
// Does this item have children?
|
||||
if (item->rowCount()) {
|
||||
// Yes - visit all the children
|
||||
for (int i=0 ; i<item->rowCount() ; ++i) {
|
||||
GetChildResults(item->child(i), results, visited);
|
||||
}
|
||||
} else {
|
||||
// No - it's a song, add its result
|
||||
results->append(item->data(Role_Result).value<SearchProvider::Result>());
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalSearchView::TracksLoaded(int id, MimeData* mime_data) {
|
||||
if (!mime_data)
|
||||
return;
|
||||
MimeData* GlobalSearchView::LoadSelectedTracks() {
|
||||
// Get all selected model indexes
|
||||
QModelIndexList indexes = ui_->results->selectionModel()->selectedRows();
|
||||
if (indexes.isEmpty()) {
|
||||
// There's nothing selected - take the first thing in the model that isn't
|
||||
// a divider.
|
||||
for (int i=0 ; i<front_proxy_->rowCount() ; ++i) {
|
||||
QModelIndex index = front_proxy_->index(i, 0);
|
||||
if (!index.data(LibraryModel::Role_IsDivider).toBool()) {
|
||||
indexes << index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mime_data->from_doubleclick_ = true;
|
||||
emit AddToPlaylist(mime_data);
|
||||
// Still got nothing? Give up.
|
||||
if (indexes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get all the results in these indexes
|
||||
SearchProvider::ResultList results;
|
||||
QSet<const QStandardItem*> visited;
|
||||
foreach (const QModelIndex& index, indexes) {
|
||||
GetChildResults(front_model_->itemFromIndex(front_proxy_->mapToSource(index)),
|
||||
&results, &visited);
|
||||
}
|
||||
|
||||
// Get a MimeData for these results
|
||||
return engine_->LoadTracks(results);
|
||||
}
|
||||
|
@ -73,12 +73,15 @@ private slots:
|
||||
void AddResults(int id, const SearchProvider::ResultList& results);
|
||||
|
||||
void ArtLoaded(int id, const QPixmap& pixmap);
|
||||
void TracksLoaded(int id, MimeData* mime_data);
|
||||
|
||||
private:
|
||||
void LoadTracks();
|
||||
MimeData* LoadSelectedTracks();
|
||||
QStandardItem* BuildContainers(const Song& metadata, QStandardItem* parent,
|
||||
ContainerKey* key, int level = 0);
|
||||
|
||||
void GetChildResults(const QStandardItem* item,
|
||||
SearchProvider::ResultList* results,
|
||||
QSet<const QStandardItem*>* visited) const;
|
||||
|
||||
private:
|
||||
Application* app_;
|
||||
|
@ -113,13 +113,6 @@ void GroovesharkSearchProvider::AlbumArtLoaded(quint64 id, const QImage& image)
|
||||
emit ArtLoaded(original_id, image);
|
||||
}
|
||||
|
||||
void GroovesharkSearchProvider::LoadTracksAsync(int id, const Result& result) {
|
||||
InternetSongMimeData* mime_data = new InternetSongMimeData(service_);
|
||||
mime_data->songs << result.metadata_;
|
||||
|
||||
emit TracksLoaded(id, mime_data);
|
||||
}
|
||||
|
||||
bool GroovesharkSearchProvider::IsLoggedIn() {
|
||||
return (service_ && service_->IsLoggedIn());
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ class GroovesharkSearchProvider : public SearchProvider {
|
||||
// SearchProvider
|
||||
void SearchAsync(int id, const QString& query);
|
||||
void LoadArtAsync(int id, const Result& result);
|
||||
void LoadTracksAsync(int id, const Result& result);
|
||||
bool IsLoggedIn();
|
||||
void ShowConfig();
|
||||
|
||||
|
@ -68,12 +68,11 @@ SearchProvider::ResultList LibrarySearchProvider::Search(int id, const QString&
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LibrarySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
||||
SongMimeData* mime_data = new SongMimeData;
|
||||
mime_data->backend = backend_;
|
||||
mime_data->songs = SongList() << result.metadata_;
|
||||
MimeData* LibrarySearchProvider::LoadTracks(const ResultList& results) {
|
||||
MimeData* ret = SearchProvider::LoadTracks(results);
|
||||
static_cast<SongMimeData*>(ret)->backend = backend_;
|
||||
|
||||
emit TracksLoaded(id, mime_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString LibrarySearchProvider::GetSuggestion() {
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
Application* app, QObject* parent = 0);
|
||||
|
||||
ResultList Search(int id, const QString& query);
|
||||
void LoadTracksAsync(int id, const Result& result);
|
||||
MimeData* LoadTracks(const ResultList& results);
|
||||
QString GetSuggestion();
|
||||
|
||||
private:
|
||||
|
@ -25,7 +25,8 @@ SavedRadioSearchProvider::SavedRadioSearchProvider(SavedRadio* service,
|
||||
: SimpleSearchProvider(app, parent),
|
||||
service_(service)
|
||||
{
|
||||
Init(tr("Your radio streams"), "savedradio", IconLoader::Load("document-open-remote"));
|
||||
Init(tr("Your radio streams"), "savedradio", IconLoader::Load("document-open-remote"),
|
||||
MimeDataContainsUrlsOnly);
|
||||
|
||||
connect(service_, SIGNAL(StreamsChanged()), SLOT(MaybeRecreateItems()));
|
||||
|
||||
@ -45,10 +46,3 @@ void SavedRadioSearchProvider::RecreateItems() {
|
||||
|
||||
SetItems(items);
|
||||
}
|
||||
|
||||
void SavedRadioSearchProvider::LoadTracksAsync(int id, const Result& result) {
|
||||
MimeData* mime_data = new MimeData;
|
||||
mime_data->setUrls(QList<QUrl>() << result.metadata_.url());
|
||||
|
||||
emit TracksLoaded(id, mime_data);
|
||||
}
|
||||
|
@ -26,8 +26,6 @@ class SavedRadioSearchProvider : public SimpleSearchProvider {
|
||||
public:
|
||||
SavedRadioSearchProvider(SavedRadio* service, Application* app, QObject* parent);
|
||||
|
||||
void LoadTracksAsync(int id, const Result& result);
|
||||
|
||||
protected:
|
||||
void RecreateItems();
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "playlist/songmimedata.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QUrl>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
const int SearchProvider::kArtHeight = 32;
|
||||
@ -123,9 +124,25 @@ void SearchProvider::LoadArtAsync(int id, const Result& result) {
|
||||
emit ArtLoaded(id, QImage());
|
||||
}
|
||||
|
||||
void SearchProvider::LoadTracksAsync(int id, const Result& result) {
|
||||
SongMimeData* mime_data = new SongMimeData;
|
||||
mime_data->songs = SongList() << result.metadata_;
|
||||
MimeData* SearchProvider::LoadTracks(const ResultList& results) {
|
||||
MimeData* mime_data = NULL;
|
||||
|
||||
emit TracksLoaded(id, mime_data);
|
||||
if (mime_data_contains_urls_only()) {
|
||||
mime_data = new MimeData;
|
||||
} else {
|
||||
SongMimeData* song_mime_data = new SongMimeData;
|
||||
mime_data = song_mime_data;
|
||||
|
||||
foreach (const Result& result, results) {
|
||||
song_mime_data->songs << result.metadata_;
|
||||
}
|
||||
}
|
||||
|
||||
QList<QUrl> urls;
|
||||
foreach (const Result& result, results) {
|
||||
urls << result.metadata_.url();
|
||||
}
|
||||
mime_data->setUrls(urls);
|
||||
|
||||
return mime_data;
|
||||
}
|
||||
|
@ -91,7 +91,13 @@ public:
|
||||
// Normally providers get enabled unless the user chooses otherwise.
|
||||
// Setting this flag indicates that this provider is disabled by default
|
||||
// instead.
|
||||
DisabledByDefault = 0x40
|
||||
DisabledByDefault = 0x40,
|
||||
|
||||
// The default implementation of LoadTracksAsync normally creates a
|
||||
// SongMimeData containing the entire metadata for each result being loaded.
|
||||
// Setting this flag will cause a plain MimeData to be created containing
|
||||
// only the URLs of the results.
|
||||
MimeDataContainsUrlsOnly = 0x80
|
||||
};
|
||||
Q_DECLARE_FLAGS(Hints, Hint)
|
||||
|
||||
@ -108,6 +114,7 @@ public:
|
||||
bool can_give_suggestions() const { return hints() & CanGiveSuggestions; }
|
||||
bool is_disabled_by_default() const { return hints() & DisabledByDefault; }
|
||||
bool is_enabled_by_default() const { return !is_disabled_by_default(); }
|
||||
bool mime_data_contains_urls_only() const { return hints() & MimeDataContainsUrlsOnly; }
|
||||
|
||||
// Starts a search. Must emit ResultsAvailable zero or more times and then
|
||||
// SearchFinished exactly once, using this ID.
|
||||
@ -117,9 +124,10 @@ public:
|
||||
// ResultsAvailable. Must emit ArtLoaded exactly once with this ID.
|
||||
virtual void LoadArtAsync(int id, const Result& result);
|
||||
|
||||
// Starts loading tracks for a result that was previously emitted by
|
||||
// ResultsAvailable. Must emit TracksLoaded exactly once with this ID.
|
||||
virtual void LoadTracksAsync(int id, const Result& result);
|
||||
// Loads tracks for results that were previously emitted by ResultsAvailable.
|
||||
// The default implementation creates a SongMimeData with one Song for each
|
||||
// Result, unless the MimeDataContainsUrlsOnly flag is set.
|
||||
virtual MimeData* LoadTracks(const ResultList& results);
|
||||
|
||||
// Returns an example search string to display in the UI. The provider should
|
||||
// pick one of its items at random. Remember to set the CanGiveSuggestions
|
||||
@ -139,8 +147,6 @@ signals:
|
||||
|
||||
void ArtLoaded(int id, const QImage& image);
|
||||
|
||||
void TracksLoaded(int id, MimeData* mime_data);
|
||||
|
||||
protected:
|
||||
// These functions treat queries in the same way as LibraryQuery. They're
|
||||
// useful for figuring out whether you got a result because it matched in
|
||||
|
@ -91,19 +91,12 @@ SearchProvider::ResultList SimpleSearchProvider::Search(int id, const QString& q
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SimpleSearchProvider::LoadTracksAsync(int id, const Result& result) {
|
||||
Song metadata = result.metadata_;
|
||||
metadata.set_filetype(Song::Type_Stream);
|
||||
|
||||
SongMimeData* mime_data = new SongMimeData;
|
||||
mime_data->songs = SongList() << metadata;
|
||||
|
||||
emit TracksLoaded(id, mime_data);
|
||||
}
|
||||
|
||||
void SimpleSearchProvider::SetItems(const ItemList& items) {
|
||||
QMutexLocker l(&items_mutex_);
|
||||
items_ = items;
|
||||
for (ItemList::iterator it = items_.begin() ; it != items_.end() ; ++it) {
|
||||
it->metadata_.set_filetype(Song::Type_Stream);
|
||||
}
|
||||
}
|
||||
|
||||
QString SimpleSearchProvider::GetSuggestion() {
|
||||
|
@ -32,7 +32,6 @@ public:
|
||||
ResultList Search(int id, const QString& query);
|
||||
|
||||
// SearchProvider
|
||||
void LoadTracksAsync(int id, const Result& result);
|
||||
QString GetSuggestion();
|
||||
|
||||
protected slots:
|
||||
|
@ -47,8 +47,6 @@ SpotifyServer* SpotifySearchProvider::server() {
|
||||
SLOT(SearchFinishedSlot(pb::spotify::SearchResponse)));
|
||||
connect(server_, SIGNAL(ImageLoaded(QString,QImage)),
|
||||
SLOT(ArtLoadedSlot(QString,QImage)));
|
||||
connect(server_, SIGNAL(AlbumBrowseResults(pb::spotify::BrowseAlbumResponse)),
|
||||
SLOT(AlbumBrowseResponse(pb::spotify::BrowseAlbumResponse)));
|
||||
connect(server_, SIGNAL(destroyed()), SLOT(ServerDestroyed()));
|
||||
|
||||
return server_;
|
||||
@ -133,32 +131,6 @@ void SpotifySearchProvider::ArtLoadedSlot(const QString& id, const QImage& image
|
||||
emit ArtLoaded(orig_id, ScaleAndPad(image));
|
||||
}
|
||||
|
||||
void SpotifySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
||||
SongMimeData* mime_data = new SongMimeData;
|
||||
mime_data->songs << result.metadata_;
|
||||
emit TracksLoaded(id, mime_data);
|
||||
}
|
||||
|
||||
void SpotifySearchProvider::AlbumBrowseResponse(const pb::spotify::BrowseAlbumResponse& response) {
|
||||
QString uri = QStringFromStdString(response.uri());
|
||||
QMap<QString, int>::iterator it = pending_tracks_.find(uri);
|
||||
if (it == pending_tracks_.end())
|
||||
return;
|
||||
|
||||
const int orig_id = it.value();
|
||||
pending_tracks_.erase(it);
|
||||
|
||||
SongMimeData* mime_data = new SongMimeData;
|
||||
|
||||
for (int i=0 ; i<response.track_size() ; ++i) {
|
||||
Song song;
|
||||
SpotifyService::SongFromProtobuf(response.track(i), &song);
|
||||
mime_data->songs << song;
|
||||
}
|
||||
|
||||
emit TracksLoaded(orig_id, mime_data);
|
||||
}
|
||||
|
||||
bool SpotifySearchProvider::IsLoggedIn() {
|
||||
if (server()) {
|
||||
return service_->IsLoggedIn();
|
||||
|
@ -33,7 +33,6 @@ public:
|
||||
|
||||
void SearchAsync(int id, const QString& query);
|
||||
void LoadArtAsync(int id, const Result& result);
|
||||
void LoadTracksAsync(int id, const Result& result);
|
||||
|
||||
bool IsLoggedIn();
|
||||
void ShowConfig();
|
||||
@ -43,8 +42,6 @@ private slots:
|
||||
void SearchFinishedSlot(const pb::spotify::SearchResponse& response);
|
||||
void ArtLoadedSlot(const QString& id, const QImage& image);
|
||||
|
||||
void AlbumBrowseResponse(const pb::spotify::BrowseAlbumResponse& response);
|
||||
|
||||
private:
|
||||
SpotifyServer* server();
|
||||
|
||||
|
@ -31,7 +31,7 @@ UrlSearchProvider::UrlSearchProvider(Application* app, QObject* parent)
|
||||
QIcon icon = IconLoader::Load("applications-internet");
|
||||
image_ = ScaleAndPad(icon.pixmap(kArtHeight, kArtHeight).toImage());
|
||||
|
||||
Init("URL", "url", icon);
|
||||
Init("URL", "url", icon, MimeDataContainsUrlsOnly);
|
||||
}
|
||||
|
||||
void UrlSearchProvider::SearchAsync(int id, const QString& query) {
|
||||
@ -47,13 +47,6 @@ void UrlSearchProvider::LoadArtAsync(int id, const Result&) {
|
||||
emit ArtLoaded(id, image_);
|
||||
}
|
||||
|
||||
void UrlSearchProvider::LoadTracksAsync(int id, const Result& result) {
|
||||
MimeData* mime_data = new MimeData;
|
||||
mime_data->setUrls(QList<QUrl>() << result.metadata_.url());
|
||||
|
||||
emit TracksLoaded(id, mime_data);
|
||||
}
|
||||
|
||||
bool UrlSearchProvider::LooksLikeUrl(const QString& query) const {
|
||||
return url_regex_.indexIn(query) == 0;
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ public:
|
||||
|
||||
void SearchAsync(int id, const QString& query);
|
||||
void LoadArtAsync(int id, const Result& result);
|
||||
void LoadTracksAsync(int id, const Result& result);
|
||||
|
||||
private:
|
||||
static const char* kUrlRegex;
|
||||
|
Loading…
x
Reference in New Issue
Block a user