Show all the artist info at once rather than as it arrives, make resizing the text areas smoother, remove duplicate biogoraphies.

This commit is contained in:
David Sansome 2010-10-09 13:34:28 +00:00
parent 7e39bfece2
commit 547a009d73
8 changed files with 92 additions and 32 deletions

View File

@ -26,14 +26,47 @@ ArtistInfoFetcher::ArtistInfoFetcher(QObject* parent)
void ArtistInfoFetcher::AddProvider(ArtistInfoProvider* provider) {
providers_ << provider;
connect(provider, SIGNAL(ImageReady(int,QUrl)), SIGNAL(ImageReady(int,QUrl)));
connect(provider, SIGNAL(InfoReady(int,CollapsibleInfoPane::Data)), SIGNAL(InfoReady(int,CollapsibleInfoPane::Data)));
connect(provider, SIGNAL(ImageReady(int,QUrl)), SLOT(ImageReady(int,QUrl)));
connect(provider, SIGNAL(InfoReady(int,CollapsibleInfoPane::Data)), SLOT(InfoReady(int,CollapsibleInfoPane::Data)));
connect(provider, SIGNAL(Finished(int)), SLOT(ProviderFinished(int)));
}
int ArtistInfoFetcher::FetchInfo(const QString& artist) {
const int id = next_id_ ++;
results_[id] = Result();
foreach (ArtistInfoProvider* provider, providers_) {
waiting_for_[id].append(provider);
provider->FetchInfo(id, artist);
}
return id;
}
void ArtistInfoFetcher::ImageReady(int id, const QUrl& url) {
if (!results_.contains(id))
return;
results_[id].images_ << url;
}
void ArtistInfoFetcher::InfoReady(int id, const CollapsibleInfoPane::Data& data) {
if (!results_.contains(id))
return;
results_[id].info_ << data;
}
void ArtistInfoFetcher::ProviderFinished(int id) {
if (!results_.contains(id))
return;
if (!waiting_for_.contains(id))
return;
ArtistInfoProvider* provider = qobject_cast<ArtistInfoProvider*>(sender());
if (!waiting_for_[id].contains(provider))
return;
waiting_for_[id].removeAll(provider);
if (waiting_for_[id].isEmpty()) {
emit ResultReady(id, results_.take(id));
waiting_for_.remove(id);
}
}

View File

@ -17,6 +17,7 @@
#ifndef ARTISTINFOFETCHER_H
#define ARTISTINFOFETCHER_H
#include <QMap>
#include <QObject>
#include <QUrl>
@ -30,11 +31,20 @@ class ArtistInfoFetcher : public QObject {
public:
ArtistInfoFetcher(QObject* parent = 0);
struct Result {
QList<QUrl> images_;
QList<CollapsibleInfoPane::Data> info_;
};
int FetchInfo(const QString& artist);
signals:
void ResultReady(int id, const ArtistInfoFetcher::Result& result);
private slots:
void ImageReady(int id, const QUrl& url);
void InfoReady(int id, const CollapsibleInfoPane::Data&);
void InfoReady(int id, const CollapsibleInfoPane::Data& data);
void ProviderFinished(int id);
private:
void AddProvider(ArtistInfoProvider* provider);
@ -42,6 +52,9 @@ private:
private:
QList<ArtistInfoProvider*> providers_;
QMap<int, Result> results_;
QMap<int, QList<ArtistInfoProvider*> > waiting_for_;
int next_id_;
};

View File

@ -33,6 +33,7 @@ public:
signals:
void ImageReady(int id, const QUrl& url);
void InfoReady(int id, const CollapsibleInfoPane::Data& data);
void Finished(int id);
};
#endif // ARTISTINFOPROVIDER_H

View File

@ -34,8 +34,8 @@ ArtistInfoView::ArtistInfoView(NetworkAccessManager* network, QWidget *parent)
image_view_(NULL),
section_container_(NULL)
{
connect(fetcher_, SIGNAL(ImageReady(int,QUrl)), SLOT(ImageReady(int,QUrl)));
connect(fetcher_, SIGNAL(InfoReady(int,CollapsibleInfoPane::Data)), SLOT(InfoReady(int,CollapsibleInfoPane::Data)));
connect(fetcher_, SIGNAL(ResultReady(int,ArtistInfoFetcher::Result)),
SLOT(ResultReady(int,ArtistInfoFetcher::Result)));
// Add the top-level scroll area
setLayout(new QVBoxLayout);
@ -88,8 +88,14 @@ bool ArtistInfoView::NeedsUpdate(const Song& old_metadata, const Song& new_metad
}
void ArtistInfoView::Update(const Song& metadata) {
Clear();
current_request_id_ = fetcher_->FetchInfo(metadata.artist());
}
void ArtistInfoView::ResultReady(int id, const ArtistInfoFetcher::Result& result) {
if (id != current_request_id_)
return;
Clear();
// Image view goes at the top
image_view_ = new PrettyImageView(network_);
@ -102,20 +108,12 @@ void ArtistInfoView::Update(const Song& metadata) {
section_container_->layout()->setSpacing(1);
section_container_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
container_->insertWidget(1, section_container_);
}
void ArtistInfoView::ImageReady(int id, const QUrl& url) {
if (id != current_request_id_)
return;
image_view_->AddImage(url);
}
void ArtistInfoView::InfoReady(int id, const CollapsibleInfoPane::Data& data) {
if (id != current_request_id_) {
delete data.contents_;
return;
foreach (const QUrl& url, result.images_) {
image_view_->AddImage(url);
}
AddSection(new CollapsibleInfoPane(data, this));
foreach (const CollapsibleInfoPane::Data& data, result.info_) {
AddSection(new CollapsibleInfoPane(data, this));
}
}

View File

@ -17,6 +17,7 @@
#ifndef ARTISTINFOVIEW_H
#define ARTISTINFOVIEW_H
#include "artistinfofetcher.h"
#include "collapsibleinfopane.h"
#include "songinfobase.h"
@ -42,8 +43,7 @@ private:
void Clear();
private slots:
void ImageReady(int id, const QUrl& url);
void InfoReady(int id, const CollapsibleInfoPane::Data& data);
void ResultReady(int id, const ArtistInfoFetcher::Result& result);
private:
ArtistInfoFetcher* fetcher_;

View File

@ -24,6 +24,8 @@
struct EchoNestArtistInfo::Request {
Request(int id) : id_(id), artist_(new Echonest::Artist) {}
bool is_finished() const { return pending_replies_.isEmpty(); }
int id_;
boost::scoped_ptr<Echonest::Artist> artist_;
QList<QNetworkReply*> pending_replies_;
@ -33,7 +35,6 @@ EchoNestArtistInfo::EchoNestArtistInfo(QObject* parent)
: ArtistInfoProvider(parent)
{
site_relevance_["wikipedia"] = 100;
site_relevance_["last.fm"] = 60;
site_relevance_["lastfm"] = 60;
site_relevance_["amazon"] = 30;
@ -41,7 +42,6 @@ EchoNestArtistInfo::EchoNestArtistInfo(QObject* parent)
site_icons_["aol"] = QIcon(":/providers/aol.png");
site_icons_["cdbaby"] = QIcon(":/providers/cdbaby.png");
site_icons_["lastfm"] = QIcon(":/last.fm/as.png");
site_icons_["last.fm"] = QIcon(":/last.fm/as.png");
site_icons_["mog"] = QIcon(":/providers/mog.png");
site_icons_["mtvmusic"] = QIcon(":/providers/mtvmusic.png");
site_icons_["myspace"] = QIcon(":/providers/myspace.png");
@ -77,7 +77,7 @@ EchoNestArtistInfo::RequestPtr EchoNestArtistInfo::ReplyFinished(QNetworkReply*
request->pending_replies_.removeAll(reply);
if (request->pending_replies_.isEmpty()) {
if (request->is_finished()) {
requests_.removeAll(request);
}
@ -93,6 +93,9 @@ void EchoNestArtistInfo::ImagesFinished() {
foreach (const Echonest::ArtistImage& image, request->artist_->images()) {
emit ImageReady(request->id_, image.url());
}
if (request->is_finished())
emit Finished(request->id_);
}
void EchoNestArtistInfo::BiographiesFinished() {
@ -101,19 +104,21 @@ void EchoNestArtistInfo::BiographiesFinished() {
QSet<QString> already_seen;
foreach (const Echonest::Biography& bio, request->artist_->biographies()) {
if (already_seen.contains(bio.text()))
QString canonical_site = bio.site().toLower();
canonical_site.replace(QRegExp("[^a-z]"),"");
if (already_seen.contains(canonical_site))
continue;
already_seen.insert(bio.text());
already_seen.insert(canonical_site);
CollapsibleInfoPane::Data data;
data.title_ = tr("Biography from %1").arg(bio.site());
data.type_ = CollapsibleInfoPane::Data::Type_Biography;
const QString site = bio.site().toLower();
if (site_relevance_.contains(site))
data.relevance_ = site_relevance_[site];
if (site_icons_.contains(site))
data.icon_ = site_icons_[site];
if (site_relevance_.contains(canonical_site))
data.relevance_ = site_relevance_[canonical_site];
if (site_icons_.contains(canonical_site))
data.icon_ = site_icons_[canonical_site];
AutoSizedTextEdit* editor = new AutoSizedTextEdit;
editor->setHtml(bio.text());
@ -121,4 +126,7 @@ void EchoNestArtistInfo::BiographiesFinished() {
emit InfoReady(request->id_, data);
}
if (request->is_finished())
emit Finished(request->id_);
}

View File

@ -19,7 +19,8 @@
#include <QWheelEvent>
AutoSizedTextEdit::AutoSizedTextEdit(QWidget* parent)
: QTextEdit(parent)
: QTextEdit(parent),
last_width_(-1)
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@ -27,6 +28,9 @@ AutoSizedTextEdit::AutoSizedTextEdit(QWidget* parent)
void AutoSizedTextEdit::resizeEvent(QResizeEvent* e) {
const int w = qMax(100, width());
if (w == last_width_)
return;
last_width_ = w;
document()->setTextWidth(w);
setMinimumHeight(document()->size().height());

View File

@ -30,6 +30,9 @@ public:
protected:
void resizeEvent(QResizeEvent* e);
void wheelEvent(QWheelEvent* e);
private:
int last_width_;
};
#endif // AUTOSIZEDTEXTEDIT_H