Treat URLs specially in the global search widget
This commit is contained in:
parent
d74d4d65f0
commit
691cb9a392
@ -134,6 +134,7 @@ set(SOURCES
|
|||||||
globalsearch/somafmsearchprovider.cpp
|
globalsearch/somafmsearchprovider.cpp
|
||||||
globalsearch/tooltipactionwidget.cpp
|
globalsearch/tooltipactionwidget.cpp
|
||||||
globalsearch/tooltipresultwidget.cpp
|
globalsearch/tooltipresultwidget.cpp
|
||||||
|
globalsearch/urlsearchprovider.cpp
|
||||||
|
|
||||||
internet/digitallyimportedclient.cpp
|
internet/digitallyimportedclient.cpp
|
||||||
internet/digitallyimportedservicebase.cpp
|
internet/digitallyimportedservicebase.cpp
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "librarysearchprovider.h"
|
#include "librarysearchprovider.h"
|
||||||
#include "globalsearch.h"
|
#include "globalsearch.h"
|
||||||
|
#include "urlsearchprovider.h"
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "covers/albumcoverloader.h"
|
#include "covers/albumcoverloader.h"
|
||||||
|
|
||||||
@ -32,7 +33,8 @@ const int GlobalSearch::kMaxResultsPerEmission = 100;
|
|||||||
GlobalSearch::GlobalSearch(QObject* parent)
|
GlobalSearch::GlobalSearch(QObject* parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
next_id_(1),
|
next_id_(1),
|
||||||
cover_loader_(new BackgroundThreadImplementation<AlbumCoverLoader, AlbumCoverLoader>(this))
|
cover_loader_(new BackgroundThreadImplementation<AlbumCoverLoader, AlbumCoverLoader>(this)),
|
||||||
|
url_provider_(new UrlSearchProvider(this))
|
||||||
{
|
{
|
||||||
cover_loader_->Start(true);
|
cover_loader_->Start(true);
|
||||||
cover_loader_->Worker()->SetDesiredHeight(SearchProvider::kArtHeight);
|
cover_loader_->Worker()->SetDesiredHeight(SearchProvider::kArtHeight);
|
||||||
@ -42,11 +44,11 @@ GlobalSearch::GlobalSearch(QObject* parent)
|
|||||||
connect(cover_loader_->Worker().get(),
|
connect(cover_loader_->Worker().get(),
|
||||||
SIGNAL(ImageLoaded(quint64,QImage)),
|
SIGNAL(ImageLoaded(quint64,QImage)),
|
||||||
SLOT(AlbumArtLoaded(quint64,QImage)));
|
SLOT(AlbumArtLoaded(quint64,QImage)));
|
||||||
|
|
||||||
|
ConnectProvider(url_provider_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalSearch::AddProvider(SearchProvider* provider, bool enable_by_default) {
|
void GlobalSearch::ConnectProvider(SearchProvider* provider) {
|
||||||
Q_ASSERT(!provider->name().isEmpty());
|
|
||||||
|
|
||||||
connect(provider, SIGNAL(ResultsAvailable(int,SearchProvider::ResultList)),
|
connect(provider, SIGNAL(ResultsAvailable(int,SearchProvider::ResultList)),
|
||||||
SLOT(ResultsAvailableSlot(int,SearchProvider::ResultList)));
|
SLOT(ResultsAvailableSlot(int,SearchProvider::ResultList)));
|
||||||
connect(provider, SIGNAL(SearchFinished(int)),
|
connect(provider, SIGNAL(SearchFinished(int)),
|
||||||
@ -57,6 +59,12 @@ void GlobalSearch::AddProvider(SearchProvider* provider, bool enable_by_default)
|
|||||||
SIGNAL(TracksLoaded(int,MimeData*)));
|
SIGNAL(TracksLoaded(int,MimeData*)));
|
||||||
connect(provider, SIGNAL(destroyed(QObject*)),
|
connect(provider, SIGNAL(destroyed(QObject*)),
|
||||||
SLOT(ProviderDestroyedSlot(QObject*)));
|
SLOT(ProviderDestroyedSlot(QObject*)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalSearch::AddProvider(SearchProvider* provider, bool enable_by_default) {
|
||||||
|
Q_ASSERT(!provider->name().isEmpty());
|
||||||
|
|
||||||
|
ConnectProvider(provider);
|
||||||
|
|
||||||
ProviderData data;
|
ProviderData data;
|
||||||
data.enabled_ = providers_state_preference_.contains(provider->id()) ?
|
data.enabled_ = providers_state_preference_.contains(provider->id()) ?
|
||||||
@ -68,25 +76,29 @@ void GlobalSearch::AddProvider(SearchProvider* provider, bool enable_by_default)
|
|||||||
|
|
||||||
int GlobalSearch::SearchAsync(const QString& query) {
|
int GlobalSearch::SearchAsync(const QString& query) {
|
||||||
const int id = next_id_ ++;
|
const int id = next_id_ ++;
|
||||||
|
pending_search_providers_[id] = 0;
|
||||||
|
|
||||||
int timer_id = -1;
|
int timer_id = -1;
|
||||||
|
|
||||||
pending_search_providers_[id] = 0;
|
if (url_provider_->LooksLikeUrl(query)) {
|
||||||
foreach (SearchProvider* provider, providers_.keys()) {
|
url_provider_->SearchAsync(id, query);
|
||||||
if (!providers_[provider].enabled_)
|
} else {
|
||||||
continue;
|
foreach (SearchProvider* provider, providers_.keys()) {
|
||||||
|
if (!providers_[provider].enabled_)
|
||||||
|
continue;
|
||||||
|
|
||||||
pending_search_providers_[id] ++;
|
pending_search_providers_[id] ++;
|
||||||
|
|
||||||
if (provider->wants_delayed_queries()) {
|
if (provider->wants_delayed_queries()) {
|
||||||
if (timer_id == -1) {
|
if (timer_id == -1) {
|
||||||
timer_id = startTimer(kDelayedSearchTimeoutMs);
|
timer_id = startTimer(kDelayedSearchTimeoutMs);
|
||||||
delayed_searches_[timer_id].id_ = id;
|
delayed_searches_[timer_id].id_ = id;
|
||||||
delayed_searches_[timer_id].query_ = query;
|
delayed_searches_[timer_id].query_ = query;
|
||||||
|
}
|
||||||
|
delayed_searches_[timer_id].providers_ << provider;
|
||||||
|
} else {
|
||||||
|
provider->SearchAsync(id, query);
|
||||||
}
|
}
|
||||||
delayed_searches_[timer_id].providers_ << provider;
|
|
||||||
} else {
|
|
||||||
provider->SearchAsync(id, query);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +195,7 @@ int GlobalSearch::LoadArtAsync(const SearchProvider::Result& result) {
|
|||||||
|
|
||||||
pending_art_searches_[id] = result.pixmap_cache_key_;
|
pending_art_searches_[id] = result.pixmap_cache_key_;
|
||||||
|
|
||||||
if (!providers_.contains(result.provider_) ||
|
if (providers_.contains(result.provider_) &&
|
||||||
!providers_[result.provider_].enabled_) {
|
!providers_[result.provider_].enabled_) {
|
||||||
emit ArtLoaded(id, QPixmap());
|
emit ArtLoaded(id, QPixmap());
|
||||||
return id;
|
return id;
|
||||||
@ -192,7 +204,8 @@ int GlobalSearch::LoadArtAsync(const SearchProvider::Result& result) {
|
|||||||
if (result.provider_->art_is_in_song_metadata()) {
|
if (result.provider_->art_is_in_song_metadata()) {
|
||||||
quint64 loader_id = cover_loader_->Worker()->LoadImageAsync(result.metadata_);
|
quint64 loader_id = cover_loader_->Worker()->LoadImageAsync(result.metadata_);
|
||||||
cover_loader_tasks_[loader_id] = id;
|
cover_loader_tasks_[loader_id] = id;
|
||||||
} else if (result.provider_->wants_serialised_art()) {
|
} else if (providers_.contains(result.provider_) &&
|
||||||
|
result.provider_->wants_serialised_art()) {
|
||||||
QueuedArt request;
|
QueuedArt request;
|
||||||
request.id_ = id;
|
request.id_ = id;
|
||||||
request.result_ = result;
|
request.result_ = result;
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
|
|
||||||
class AlbumCoverLoader;
|
class AlbumCoverLoader;
|
||||||
|
class UrlSearchProvider;
|
||||||
|
|
||||||
class GlobalSearch : public QObject {
|
class GlobalSearch : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -86,6 +87,7 @@ private slots:
|
|||||||
void ProviderDestroyedSlot(QObject* object);
|
void ProviderDestroyedSlot(QObject* object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ConnectProvider(SearchProvider* provider);
|
||||||
void HandleLoadedArt(int id, const QImage& image, SearchProvider* provider);
|
void HandleLoadedArt(int id, const QImage& image, SearchProvider* provider);
|
||||||
void TakeNextQueuedArt(SearchProvider* provider);
|
void TakeNextQueuedArt(SearchProvider* provider);
|
||||||
QString PixmapCacheKey(const SearchProvider::Result& result) const;
|
QString PixmapCacheKey(const SearchProvider::Result& result) const;
|
||||||
@ -124,6 +126,9 @@ private:
|
|||||||
// Used for providers with ArtIsInSongMetadata set.
|
// Used for providers with ArtIsInSongMetadata set.
|
||||||
BackgroundThread<AlbumCoverLoader>* cover_loader_;
|
BackgroundThread<AlbumCoverLoader>* cover_loader_;
|
||||||
QMap<quint64, int> cover_loader_tasks_;
|
QMap<quint64, int> cover_loader_tasks_;
|
||||||
|
|
||||||
|
// Special search provider that's used for queries that look like URLs
|
||||||
|
UrlSearchProvider* url_provider_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GLOBALSEARCH_H
|
#endif // GLOBALSEARCH_H
|
||||||
|
@ -133,7 +133,7 @@ void GlobalSearchItemDelegate::paint(QPainter* p,
|
|||||||
case globalsearch::Type_Track:
|
case globalsearch::Type_Track:
|
||||||
case globalsearch::Type_Stream: {
|
case globalsearch::Type_Stream: {
|
||||||
// Title
|
// Title
|
||||||
line_1 += m.title() + " ";
|
line_1 += m.PrettyTitle() + " ";
|
||||||
|
|
||||||
// Artist - Album - Track n
|
// Artist - Album - Track n
|
||||||
if (!m.artist().isEmpty()) {
|
if (!m.artist().isEmpty()) {
|
||||||
|
@ -46,11 +46,8 @@ void SavedRadioSearchProvider::RecreateItems() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SavedRadioSearchProvider::LoadTracksAsync(int id, const Result& result) {
|
void SavedRadioSearchProvider::LoadTracksAsync(int id, const Result& result) {
|
||||||
Song metadata = result.metadata_;
|
|
||||||
metadata.set_filetype(Song::Type_Stream);
|
|
||||||
|
|
||||||
MimeData* mime_data = new MimeData;
|
MimeData* mime_data = new MimeData;
|
||||||
mime_data->setUrls(QList<QUrl>() << metadata.url());
|
mime_data->setUrls(QList<QUrl>() << result.metadata_.url());
|
||||||
|
|
||||||
emit TracksLoaded(id, mime_data);
|
emit TracksLoaded(id, mime_data);
|
||||||
}
|
}
|
||||||
|
59
src/globalsearch/urlsearchprovider.cpp
Normal file
59
src/globalsearch/urlsearchprovider.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2011, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Clementine is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "urlsearchprovider.h"
|
||||||
|
#include "core/mimedata.h"
|
||||||
|
#include "ui/iconloader.h"
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
const char* UrlSearchProvider::kUrlRegex = "^[a-zA-Z][a-zA-Z0-9+-.]*://";
|
||||||
|
|
||||||
|
UrlSearchProvider::UrlSearchProvider(QObject* parent)
|
||||||
|
: SearchProvider(parent),
|
||||||
|
url_regex_(kUrlRegex)
|
||||||
|
{
|
||||||
|
QIcon icon = IconLoader::Load("applications-internet");
|
||||||
|
image_ = ScaleAndPad(icon.pixmap(kArtHeight, kArtHeight).toImage());
|
||||||
|
|
||||||
|
Init("URL", "url", icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UrlSearchProvider::SearchAsync(int id, const QString& query) {
|
||||||
|
Result result(this);
|
||||||
|
result.match_quality_ = globalsearch::Quality_AtStart;
|
||||||
|
result.type_ = globalsearch::Type_Stream;
|
||||||
|
result.metadata_.set_url(QUrl::fromUserInput(query));
|
||||||
|
result.metadata_.set_filetype(Song::Type_Stream);
|
||||||
|
|
||||||
|
emit ResultsAvailable(id, ResultList() << result);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
42
src/globalsearch/urlsearchprovider.h
Normal file
42
src/globalsearch/urlsearchprovider.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2011, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Clementine is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef URLSEARCHPROVIDER_H
|
||||||
|
#define URLSEARCHPROVIDER_H
|
||||||
|
|
||||||
|
#include "searchprovider.h"
|
||||||
|
|
||||||
|
#include <QRegExp>
|
||||||
|
|
||||||
|
class UrlSearchProvider : public SearchProvider {
|
||||||
|
public:
|
||||||
|
UrlSearchProvider(QObject* parent);
|
||||||
|
|
||||||
|
bool LooksLikeUrl(const QString& query) const;
|
||||||
|
|
||||||
|
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;
|
||||||
|
QRegExp url_regex_;
|
||||||
|
|
||||||
|
QImage image_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // URLSEARCHPROVIDER_H
|
Loading…
x
Reference in New Issue
Block a user