Add a flag that search providers can set to indicate they want some delay between user input and being asked to search
This commit is contained in:
parent
8dea8a2664
commit
dbffe16d04
|
@ -22,6 +22,9 @@
|
|||
#include <QStringBuilder>
|
||||
#include <QUrl>
|
||||
|
||||
const int GlobalSearch::kDelayedSearchTimeoutMs = 200;
|
||||
|
||||
|
||||
GlobalSearch::GlobalSearch(QObject* parent)
|
||||
: QObject(parent),
|
||||
next_id_(1)
|
||||
|
@ -29,6 +32,8 @@ GlobalSearch::GlobalSearch(QObject* parent)
|
|||
}
|
||||
|
||||
void GlobalSearch::AddProvider(SearchProvider* provider) {
|
||||
Q_ASSERT(!provider->name().isEmpty());
|
||||
|
||||
connect(provider, SIGNAL(ResultsAvailable(int,SearchProvider::ResultList)),
|
||||
SLOT(ResultsAvailableSlot(int,SearchProvider::ResultList)));
|
||||
connect(provider, SIGNAL(SearchFinished(int)),
|
||||
|
@ -44,14 +49,47 @@ void GlobalSearch::AddProvider(SearchProvider* provider) {
|
|||
int GlobalSearch::SearchAsync(const QString& query) {
|
||||
const int id = next_id_ ++;
|
||||
|
||||
int timer_id = -1;
|
||||
|
||||
pending_search_providers_[id] = providers_.count();
|
||||
foreach (SearchProvider* provider, providers_) {
|
||||
provider->SearchAsync(id, query);
|
||||
if (provider->wants_delayed_queries()) {
|
||||
if (timer_id == -1) {
|
||||
timer_id = startTimer(kDelayedSearchTimeoutMs);
|
||||
delayed_searches_[id].timer_id_ = timer_id;
|
||||
delayed_searches_[id].query_ = query;
|
||||
}
|
||||
delayed_searches_[id].providers_ << provider;
|
||||
} else {
|
||||
provider->SearchAsync(id, query);
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void GlobalSearch::CancelSearch(int id) {
|
||||
if (delayed_searches_.contains(id)) {
|
||||
killTimer(delayed_searches_[id].timer_id_);
|
||||
delayed_searches_.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalSearch::timerEvent(QTimerEvent* e) {
|
||||
QMap<int, DelayedSearch>::iterator it;
|
||||
for (it = delayed_searches_.begin() ; it != delayed_searches_.end() ; ++it) {
|
||||
if (it.value().timer_id_ == e->timerId()) {
|
||||
foreach (SearchProvider* provider, it.value().providers_) {
|
||||
provider->SearchAsync(it.key(), it.value().query_);
|
||||
}
|
||||
delayed_searches_.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QObject::timerEvent(e);
|
||||
}
|
||||
|
||||
QString GlobalSearch::PixmapCacheKey(const SearchProvider::Result& result) const {
|
||||
return QString::number(qulonglong(result.provider_))
|
||||
% "," % QString::number(int(result.type_))
|
||||
|
|
|
@ -30,11 +30,16 @@ class GlobalSearch : public QObject {
|
|||
public:
|
||||
GlobalSearch(QObject* parent = 0);
|
||||
|
||||
static const int kDelayedSearchTimeoutMs;
|
||||
|
||||
void AddProvider(SearchProvider* provider);
|
||||
|
||||
int SearchAsync(const QString& query);
|
||||
int LoadArtAsync(const SearchProvider::Result& result);
|
||||
|
||||
void CancelSearch(int id);
|
||||
void CancelArt(int id);
|
||||
|
||||
bool FindCachedPixmap(const SearchProvider::Result& result, QPixmap* pixmap) const;
|
||||
|
||||
signals:
|
||||
|
@ -46,6 +51,9 @@ signals:
|
|||
|
||||
void ProviderDestroyed(SearchProvider* provider);
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent* e);
|
||||
|
||||
private slots:
|
||||
void ResultsAvailableSlot(int id, SearchProvider::ResultList results);
|
||||
void SearchFinishedSlot(int id);
|
||||
|
@ -58,8 +66,16 @@ private:
|
|||
QString PixmapCacheKey(const SearchProvider::Result& result) const;
|
||||
|
||||
private:
|
||||
struct DelayedSearch {
|
||||
int timer_id_;
|
||||
QString query_;
|
||||
QList<SearchProvider*> providers_;
|
||||
};
|
||||
|
||||
QList<SearchProvider*> providers_;
|
||||
|
||||
QMap<int, DelayedSearch> delayed_searches_;
|
||||
|
||||
int next_id_;
|
||||
QMap<int, int> pending_search_providers_;
|
||||
|
||||
|
|
|
@ -141,6 +141,7 @@ void GlobalSearchWidget::TextEdited(const QString& text) {
|
|||
}
|
||||
|
||||
clear_model_on_next_result_ = true;
|
||||
engine_->CancelSearch(last_id_);
|
||||
last_id_ = engine_->SearchAsync(trimmed_text);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,10 +27,12 @@ LibrarySearchProvider::LibrarySearchProvider(LibraryBackendInterface* backend,
|
|||
const QString& name,
|
||||
const QIcon& icon,
|
||||
QObject* parent)
|
||||
: BlockingSearchProvider(name, icon, parent),
|
||||
: BlockingSearchProvider(parent),
|
||||
backend_(backend),
|
||||
cover_loader_(new BackgroundThreadImplementation<AlbumCoverLoader, AlbumCoverLoader>(this))
|
||||
{
|
||||
Init(name, icon, false);
|
||||
|
||||
cover_loader_->Start(true);
|
||||
cover_loader_->Worker()->SetDesiredHeight(kArtHeight);
|
||||
cover_loader_->Worker()->SetPadOutputImage(true);
|
||||
|
|
|
@ -24,14 +24,17 @@
|
|||
const int SearchProvider::kArtHeight = 32;
|
||||
|
||||
|
||||
SearchProvider::SearchProvider(const QString& name, const QIcon& icon,
|
||||
QObject* parent)
|
||||
: QObject(parent),
|
||||
name_(name),
|
||||
icon_(icon)
|
||||
SearchProvider::SearchProvider(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void SearchProvider::Init(const QString& name, const QIcon& icon, bool query_lag) {
|
||||
name_ = name;
|
||||
icon_ = icon;
|
||||
query_lag_ = query_lag;
|
||||
}
|
||||
|
||||
QStringList SearchProvider::TokenizeQuery(const QString& query) {
|
||||
QStringList tokens(query.split(QRegExp("\\s+")));
|
||||
|
||||
|
@ -65,8 +68,8 @@ SearchProvider::Result::MatchQuality SearchProvider::MatchQuality(
|
|||
return ret;
|
||||
}
|
||||
|
||||
BlockingSearchProvider::BlockingSearchProvider(const QString& name, const QIcon& icon, QObject* parent)
|
||||
: SearchProvider(name, icon, parent) {
|
||||
BlockingSearchProvider::BlockingSearchProvider(QObject* parent)
|
||||
: SearchProvider(parent) {
|
||||
}
|
||||
|
||||
void BlockingSearchProvider::SearchAsync(int id, const QString& query) {
|
||||
|
|
|
@ -28,7 +28,7 @@ class SearchProvider : public QObject {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SearchProvider(const QString& name, const QIcon& icon, QObject* parent = 0);
|
||||
SearchProvider(QObject* parent = 0);
|
||||
|
||||
static const int kArtHeight;
|
||||
|
||||
|
@ -70,6 +70,7 @@ public:
|
|||
|
||||
const QString& name() const { return name_; }
|
||||
const QIcon& icon() const { return icon_; }
|
||||
const bool wants_delayed_queries() const { return query_lag_; }
|
||||
|
||||
// Starts a search. Must emit ResultsAvailable zero or more times and then
|
||||
// SearchFinished exactly once, using this ID.
|
||||
|
@ -100,9 +101,13 @@ protected:
|
|||
static QStringList TokenizeQuery(const QString& query);
|
||||
static Result::MatchQuality MatchQuality(const QStringList& tokens, const QString& string);
|
||||
|
||||
// Subclasses must call this from their constructor
|
||||
void Init(const QString& name, const QIcon& icon, bool query_lag);
|
||||
|
||||
private:
|
||||
QString name_;
|
||||
QIcon icon_;
|
||||
bool query_lag_;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(SearchProvider::Result)
|
||||
|
@ -112,8 +117,7 @@ class BlockingSearchProvider : public SearchProvider {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BlockingSearchProvider(const QString& name, const QIcon& icon,
|
||||
QObject* parent = 0);
|
||||
BlockingSearchProvider(QObject* parent = 0);
|
||||
|
||||
void SearchAsync(int id, const QString& query);
|
||||
|
||||
|
|
|
@ -21,10 +21,11 @@
|
|||
#include "internet/spotifyservice.h"
|
||||
|
||||
SpotifySearchProvider::SpotifySearchProvider(QObject* parent)
|
||||
: SearchProvider("Spotify", QIcon(":icons/svg/spotify.svg"), parent),
|
||||
: SearchProvider(parent),
|
||||
server_(NULL),
|
||||
service_(NULL)
|
||||
{
|
||||
Init("Spotify", QIcon(":icons/svg/spotify.svg"), true);
|
||||
}
|
||||
|
||||
SpotifyServer* SpotifySearchProvider::server() {
|
||||
|
|
Loading…
Reference in New Issue