Show icons for each biography, order biographies by relevance, don't refresh artist info when switching to another song by the same artist.
|
@ -32,7 +32,7 @@
|
||||||
<file>last.fm/my_friends.png</file>
|
<file>last.fm/my_friends.png</file>
|
||||||
<file>last.fm/my_neighbours.png</file>
|
<file>last.fm/my_neighbours.png</file>
|
||||||
<file>last.fm/user_purple.png</file>
|
<file>last.fm/user_purple.png</file>
|
||||||
<file>somafm.png</file>
|
<file>providers/somafm.png</file>
|
||||||
<file>schema-1.sql</file>
|
<file>schema-1.sql</file>
|
||||||
<file>schema-2.sql</file>
|
<file>schema-2.sql</file>
|
||||||
<file>nocover.png</file>
|
<file>nocover.png</file>
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
<file>schema-7.sql</file>
|
<file>schema-7.sql</file>
|
||||||
<file>tiny-pause.png</file>
|
<file>tiny-pause.png</file>
|
||||||
<file>tiny-start.png</file>
|
<file>tiny-start.png</file>
|
||||||
<file>magnatune.png</file>
|
<file>providers/magnatune.png</file>
|
||||||
<file>schema-8.sql</file>
|
<file>schema-8.sql</file>
|
||||||
<file>schema-9.sql</file>
|
<file>schema-9.sql</file>
|
||||||
<file>icons/22x22/application-exit.png</file>
|
<file>icons/22x22/application-exit.png</file>
|
||||||
|
@ -266,5 +266,12 @@
|
||||||
<file>schema-17.sql</file>
|
<file>schema-17.sql</file>
|
||||||
<file>lyrics/ultimate_providers.xml</file>
|
<file>lyrics/ultimate_providers.xml</file>
|
||||||
<file>sidebar_background.png</file>
|
<file>sidebar_background.png</file>
|
||||||
|
<file>providers/wikipedia.png</file>
|
||||||
|
<file>providers/aol.png</file>
|
||||||
|
<file>providers/amazon.png</file>
|
||||||
|
<file>providers/myspace.png</file>
|
||||||
|
<file>providers/mog.png</file>
|
||||||
|
<file>providers/mtvmusic.png</file>
|
||||||
|
<file>providers/cdbaby.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 650 B |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 535 B |
After Width: | Height: | Size: 735 B |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 560 B After Width: | Height: | Size: 560 B |
After Width: | Height: | Size: 3.2 KiB |
|
@ -15,7 +15,7 @@
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/data.qrc">
|
||||||
<normaloff>:/magnatune.png</normaloff>:/magnatune.png</iconset>
|
<normaloff>:/providers/magnatune.png</normaloff>:/providers/magnatune.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -39,9 +39,6 @@
|
||||||
<attribute name="headerVisible">
|
<attribute name="headerVisible">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</attribute>
|
</attribute>
|
||||||
<attribute name="headerVisible">
|
|
||||||
<bool>false</bool>
|
|
||||||
</attribute>
|
|
||||||
<column>
|
<column>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Name</string>
|
<string>Name</string>
|
||||||
|
|
|
@ -106,7 +106,7 @@ void MagnatuneService::ReloadSettings() {
|
||||||
|
|
||||||
RadioItem* MagnatuneService::CreateRootItem(RadioItem *parent) {
|
RadioItem* MagnatuneService::CreateRootItem(RadioItem *parent) {
|
||||||
root_ = new RadioItem(this, RadioItem::Type_Service, kServiceName, parent);
|
root_ = new RadioItem(this, RadioItem::Type_Service, kServiceName, parent);
|
||||||
root_->icon = QIcon(":magnatune.png");
|
root_->icon = QIcon(":/providers/magnatune.png");
|
||||||
|
|
||||||
return root_;
|
return root_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ SomaFMService::~SomaFMService() {
|
||||||
|
|
||||||
RadioItem* SomaFMService::CreateRootItem(RadioItem* parent) {
|
RadioItem* SomaFMService::CreateRootItem(RadioItem* parent) {
|
||||||
root_ = new RadioItem(this, RadioItem::Type_Service, kServiceName, parent);
|
root_ = new RadioItem(this, RadioItem::Type_Service, kServiceName, parent);
|
||||||
root_->icon = QIcon(":somafm.png");
|
root_->icon = QIcon(":/providers/somafm.png");
|
||||||
return root_;
|
return root_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ ArtistInfoFetcher::ArtistInfoFetcher(QObject* parent)
|
||||||
void ArtistInfoFetcher::AddProvider(ArtistInfoProvider* provider) {
|
void ArtistInfoFetcher::AddProvider(ArtistInfoProvider* provider) {
|
||||||
providers_ << provider;
|
providers_ << provider;
|
||||||
connect(provider, SIGNAL(ImageReady(int,QUrl)), SIGNAL(ImageReady(int,QUrl)));
|
connect(provider, SIGNAL(ImageReady(int,QUrl)), SIGNAL(ImageReady(int,QUrl)));
|
||||||
connect(provider, SIGNAL(InfoReady(int,QString,QWidget*)), SIGNAL(InfoReady(int,QString,QWidget*)));
|
connect(provider, SIGNAL(InfoReady(int,CollapsibleInfoPane::Data)), SIGNAL(InfoReady(int,CollapsibleInfoPane::Data)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ArtistInfoFetcher::FetchInfo(const QString& artist) {
|
int ArtistInfoFetcher::FetchInfo(const QString& artist) {
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "collapsibleinfopane.h"
|
||||||
|
|
||||||
class ArtistInfoProvider;
|
class ArtistInfoProvider;
|
||||||
|
|
||||||
class ArtistInfoFetcher : public QObject {
|
class ArtistInfoFetcher : public QObject {
|
||||||
|
@ -32,7 +34,7 @@ public:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void ImageReady(int id, const QUrl& url);
|
void ImageReady(int id, const QUrl& url);
|
||||||
void InfoReady(int id, const QString& title, QWidget* widget);
|
void InfoReady(int id, const CollapsibleInfoPane::Data&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddProvider(ArtistInfoProvider* provider);
|
void AddProvider(ArtistInfoProvider* provider);
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "collapsibleinfopane.h"
|
||||||
|
|
||||||
class ArtistInfoProvider : public QObject {
|
class ArtistInfoProvider : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ public:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void ImageReady(int id, const QUrl& url);
|
void ImageReady(int id, const QUrl& url);
|
||||||
void InfoReady(int id, const QString& title, QWidget* widget);
|
void InfoReady(int id, const CollapsibleInfoPane::Data& data);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ARTISTINFOPROVIDER_H
|
#endif // ARTISTINFOPROVIDER_H
|
||||||
|
|
|
@ -30,10 +30,12 @@ ArtistInfoView::ArtistInfoView(NetworkAccessManager* network, QWidget *parent)
|
||||||
fetcher_(new ArtistInfoFetcher(this)),
|
fetcher_(new ArtistInfoFetcher(this)),
|
||||||
current_request_id_(-1),
|
current_request_id_(-1),
|
||||||
scroll_area_(new QScrollArea),
|
scroll_area_(new QScrollArea),
|
||||||
container_(new QVBoxLayout)
|
container_(new QVBoxLayout),
|
||||||
|
image_view_(NULL),
|
||||||
|
section_container_(NULL)
|
||||||
{
|
{
|
||||||
connect(fetcher_, SIGNAL(ImageReady(int,QUrl)), SLOT(ImageReady(int,QUrl)));
|
connect(fetcher_, SIGNAL(ImageReady(int,QUrl)), SLOT(ImageReady(int,QUrl)));
|
||||||
connect(fetcher_, SIGNAL(InfoReady(int,QString,QWidget*)), SLOT(InfoReady(int,QString,QWidget*)));
|
connect(fetcher_, SIGNAL(InfoReady(int,CollapsibleInfoPane::Data)), SLOT(InfoReady(int,CollapsibleInfoPane::Data)));
|
||||||
|
|
||||||
// Add the top-level scroll area
|
// Add the top-level scroll area
|
||||||
setLayout(new QVBoxLayout);
|
setLayout(new QVBoxLayout);
|
||||||
|
@ -47,6 +49,7 @@ ArtistInfoView::ArtistInfoView(NetworkAccessManager* network, QWidget *parent)
|
||||||
container_widget->setBackgroundRole(QPalette::Base);
|
container_widget->setBackgroundRole(QPalette::Base);
|
||||||
container_->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
container_->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
||||||
container_->setContentsMargins(0, 0, 0, 0);
|
container_->setContentsMargins(0, 0, 0, 0);
|
||||||
|
container_->setSpacing(0);
|
||||||
scroll_area_->setWidget(container_widget);
|
scroll_area_->setWidget(container_widget);
|
||||||
scroll_area_->setWidgetResizable(true);
|
scroll_area_->setWidgetResizable(true);
|
||||||
|
|
||||||
|
@ -62,23 +65,43 @@ ArtistInfoView::ArtistInfoView(NetworkAccessManager* network, QWidget *parent)
|
||||||
ArtistInfoView::~ArtistInfoView() {
|
ArtistInfoView::~ArtistInfoView() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArtistInfoView::AddChild(QWidget* widget) {
|
void ArtistInfoView::AddSection(CollapsibleInfoPane* section) {
|
||||||
children_ << widget;
|
int index = 0;
|
||||||
container_->insertWidget(container_->count() - 1, widget);
|
for ( ; index<sections_.count() ; ++index) {
|
||||||
widget->show();
|
if (section->data() < sections_[index]->data())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sections_.insert(index, section);
|
||||||
|
qobject_cast<QVBoxLayout*>(section_container_->layout())->insertWidget(index, section);
|
||||||
|
section->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArtistInfoView::Clear() {
|
void ArtistInfoView::Clear() {
|
||||||
qDeleteAll(children_);
|
delete image_view_;
|
||||||
children_.clear();
|
delete section_container_;
|
||||||
|
sections_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArtistInfoView::NeedsUpdate(const Song& old_metadata, const Song& new_metadata) const {
|
||||||
|
return old_metadata.artist() != new_metadata.artist();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArtistInfoView::Update(const Song& metadata) {
|
void ArtistInfoView::Update(const Song& metadata) {
|
||||||
Clear();
|
Clear();
|
||||||
current_request_id_ = fetcher_->FetchInfo(metadata.artist());
|
current_request_id_ = fetcher_->FetchInfo(metadata.artist());
|
||||||
|
|
||||||
|
// Image view goes at the top
|
||||||
image_view_ = new PrettyImageView(network_);
|
image_view_ = new PrettyImageView(network_);
|
||||||
AddChild(image_view_);
|
container_->insertWidget(0, image_view_);
|
||||||
|
|
||||||
|
// Container for collapsable sections goes below
|
||||||
|
section_container_ = new QWidget;
|
||||||
|
section_container_->setLayout(new QVBoxLayout);
|
||||||
|
section_container_->layout()->setContentsMargins(0, 0, 0, 0);
|
||||||
|
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) {
|
void ArtistInfoView::ImageReady(int id, const QUrl& url) {
|
||||||
|
@ -88,14 +111,11 @@ void ArtistInfoView::ImageReady(int id, const QUrl& url) {
|
||||||
image_view_->AddImage(url);
|
image_view_->AddImage(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArtistInfoView::InfoReady(int id, const QString& title, QWidget* widget) {
|
void ArtistInfoView::InfoReady(int id, const CollapsibleInfoPane::Data& data) {
|
||||||
if (id != current_request_id_) {
|
if (id != current_request_id_) {
|
||||||
delete widget;
|
delete data.contents_;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CollapsibleInfoPane* pane = new CollapsibleInfoPane(this);
|
AddSection(new CollapsibleInfoPane(data, this));
|
||||||
pane->SetTitle(title);
|
|
||||||
pane->SetWidget(widget);
|
|
||||||
AddChild(pane);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#ifndef ARTISTINFOVIEW_H
|
#ifndef ARTISTINFOVIEW_H
|
||||||
#define ARTISTINFOVIEW_H
|
#define ARTISTINFOVIEW_H
|
||||||
|
|
||||||
|
#include "collapsibleinfopane.h"
|
||||||
#include "songinfobase.h"
|
#include "songinfobase.h"
|
||||||
|
|
||||||
class ArtistInfoFetcher;
|
class ArtistInfoFetcher;
|
||||||
|
@ -34,14 +35,15 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Update(const Song& metadata);
|
void Update(const Song& metadata);
|
||||||
|
bool NeedsUpdate(const Song& old_metadata, const Song& new_metadata) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddChild(QWidget* widget);
|
void AddSection(CollapsibleInfoPane* section);
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ImageReady(int id, const QUrl& url);
|
void ImageReady(int id, const QUrl& url);
|
||||||
void InfoReady(int id, const QString& title, QWidget* widget);
|
void InfoReady(int id, const CollapsibleInfoPane::Data& data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ArtistInfoFetcher* fetcher_;
|
ArtistInfoFetcher* fetcher_;
|
||||||
|
@ -51,7 +53,8 @@ private:
|
||||||
QVBoxLayout* container_;
|
QVBoxLayout* container_;
|
||||||
PrettyImageView* image_view_;
|
PrettyImageView* image_view_;
|
||||||
|
|
||||||
QList<QWidget*> children_;
|
QWidget* section_container_;
|
||||||
|
QList<CollapsibleInfoPane*> sections_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ARTISTINFOVIEW_H
|
#endif // ARTISTINFOVIEW_H
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <QStyleOption>
|
#include <QStyleOption>
|
||||||
|
|
||||||
const int CollapsibleInfoHeader::kHeight = 20;
|
const int CollapsibleInfoHeader::kHeight = 20;
|
||||||
|
const int CollapsibleInfoHeader::kIconSize = 16;
|
||||||
|
|
||||||
CollapsibleInfoHeader::CollapsibleInfoHeader(QWidget* parent)
|
CollapsibleInfoHeader::CollapsibleInfoHeader(QWidget* parent)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
|
@ -38,6 +39,11 @@ void CollapsibleInfoHeader::SetTitle(const QString& title) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CollapsibleInfoHeader::SetIcon(const QIcon& icon) {
|
||||||
|
icon_ = icon;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void CollapsibleInfoHeader::SetExpanded(bool expanded) {
|
void CollapsibleInfoHeader::SetExpanded(bool expanded) {
|
||||||
expanded_ = expanded;
|
expanded_ = expanded;
|
||||||
|
|
||||||
|
@ -62,8 +68,9 @@ void CollapsibleInfoHeader::paintEvent(QPaintEvent* e) {
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
|
|
||||||
QRect indicator_rect(0, 0, height(), height());
|
QRect indicator_rect(0, 0, height(), height());
|
||||||
|
QRect icon_rect(height() + 2, (kHeight - kIconSize) / 2, kIconSize, kIconSize);
|
||||||
QRect text_rect(rect());
|
QRect text_rect(rect());
|
||||||
text_rect.setLeft(height() + 6);
|
text_rect.setLeft(icon_rect.right() + 4);
|
||||||
|
|
||||||
// Draw the background
|
// Draw the background
|
||||||
const QColor bg_color_1(palette().color(QPalette::Highlight).lighter(120));
|
const QColor bg_color_1(palette().color(QPalette::Highlight).lighter(120));
|
||||||
|
@ -96,6 +103,9 @@ void CollapsibleInfoHeader::paintEvent(QPaintEvent* e) {
|
||||||
// will trigger QStyleSheetStyle's recursion guard (I don't know why).
|
// will trigger QStyleSheetStyle's recursion guard (I don't know why).
|
||||||
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, &p, this);
|
QApplication::style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, &p, this);
|
||||||
|
|
||||||
|
// Draw the icon
|
||||||
|
p.drawPixmap(icon_rect, icon_.pixmap(kIconSize));
|
||||||
|
|
||||||
// Draw the title text
|
// Draw the title text
|
||||||
QFont bold_font(font());
|
QFont bold_font(font());
|
||||||
bold_font.setBold(true);
|
bold_font.setBold(true);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#ifndef COLLAPSIBLEINFOHEADER_H
|
#ifndef COLLAPSIBLEINFOHEADER_H
|
||||||
#define COLLAPSIBLEINFOHEADER_H
|
#define COLLAPSIBLEINFOHEADER_H
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
class CollapsibleInfoHeader : public QWidget {
|
class CollapsibleInfoHeader : public QWidget {
|
||||||
|
@ -26,14 +27,17 @@ public:
|
||||||
CollapsibleInfoHeader(QWidget* parent = 0);
|
CollapsibleInfoHeader(QWidget* parent = 0);
|
||||||
|
|
||||||
static const int kHeight;
|
static const int kHeight;
|
||||||
|
static const int kIconSize;
|
||||||
|
|
||||||
bool expanded() const { return expanded_; }
|
bool expanded() const { return expanded_; }
|
||||||
bool hovering() const { return hovering_; }
|
bool hovering() const { return hovering_; }
|
||||||
const QString& title() const { return title_; }
|
const QString& title() const { return title_; }
|
||||||
|
const QIcon& icon() const { return icon_; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void SetExpanded(bool expanded);
|
void SetExpanded(bool expanded);
|
||||||
void SetTitle(const QString& title);
|
void SetTitle(const QString& title);
|
||||||
|
void SetIcon(const QIcon& icon);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Expanded();
|
void Expanded();
|
||||||
|
@ -50,6 +54,7 @@ private:
|
||||||
bool expanded_;
|
bool expanded_;
|
||||||
bool hovering_;
|
bool hovering_;
|
||||||
QString title_;
|
QString title_;
|
||||||
|
QIcon icon_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COLLAPSIBLEINFOHEADER_H
|
#endif // COLLAPSIBLEINFOHEADER_H
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
CollapsibleInfoPane::CollapsibleInfoPane(QWidget* parent)
|
CollapsibleInfoPane::CollapsibleInfoPane(const Data& data, QWidget* parent)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
header_(new CollapsibleInfoHeader(this)),
|
data_(data),
|
||||||
widget_(NULL)
|
header_(new CollapsibleInfoHeader(this))
|
||||||
{
|
{
|
||||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
@ -31,24 +31,16 @@ CollapsibleInfoPane::CollapsibleInfoPane(QWidget* parent)
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
|
||||||
layout->addWidget(header_);
|
layout->addWidget(header_);
|
||||||
|
layout->addWidget(data.contents_);
|
||||||
|
|
||||||
|
header_->SetTitle(data.title_);
|
||||||
|
header_->SetIcon(data.icon_);
|
||||||
|
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
||||||
|
|
||||||
connect(header_, SIGNAL(ExpandedToggled(bool)), SLOT(ExpandedToggled(bool)));
|
connect(header_, SIGNAL(ExpandedToggled(bool)), SLOT(ExpandedToggled(bool)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollapsibleInfoPane::SetTitle(const QString& title) {
|
|
||||||
header_->SetTitle(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollapsibleInfoPane::SetWidget(QWidget* widget) {
|
|
||||||
if (widget_)
|
|
||||||
delete widget_;
|
|
||||||
|
|
||||||
widget_ = widget;
|
|
||||||
layout()->addWidget(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollapsibleInfoPane::Collapse() {
|
void CollapsibleInfoPane::Collapse() {
|
||||||
header_->SetExpanded(false);
|
header_->SetExpanded(false);
|
||||||
}
|
}
|
||||||
|
@ -58,5 +50,12 @@ void CollapsibleInfoPane::Expand() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollapsibleInfoPane::ExpandedToggled(bool expanded) {
|
void CollapsibleInfoPane::ExpandedToggled(bool expanded) {
|
||||||
widget_->setVisible(expanded);
|
data_.contents_->setVisible(expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CollapsibleInfoPane::Data::operator <(const CollapsibleInfoPane::Data& other) const {
|
||||||
|
const int my_score = type_ * 1000 + relevance_;
|
||||||
|
const int other_score = other.type_ * 1000 + other.relevance_;
|
||||||
|
|
||||||
|
return my_score > other_score;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#ifndef COLLAPSIBLEINFOPANE_H
|
#ifndef COLLAPSIBLEINFOPANE_H
|
||||||
#define COLLAPSIBLEINFOPANE_H
|
#define COLLAPSIBLEINFOPANE_H
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
class CollapsibleInfoHeader;
|
class CollapsibleInfoHeader;
|
||||||
|
@ -25,10 +26,28 @@ class CollapsibleInfoPane : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CollapsibleInfoPane(QWidget* parent = 0);
|
struct Data {
|
||||||
|
Data() : type_(Type_Biography), relevance_(0) {}
|
||||||
|
|
||||||
void SetTitle(const QString& title);
|
bool operator <(const Data& other) const;
|
||||||
void SetWidget(QWidget* widget);
|
|
||||||
|
enum Type {
|
||||||
|
Type_Biography = 0,
|
||||||
|
|
||||||
|
TypeCount
|
||||||
|
};
|
||||||
|
|
||||||
|
QString title_;
|
||||||
|
QIcon icon_;
|
||||||
|
Type type_;
|
||||||
|
int relevance_;
|
||||||
|
|
||||||
|
QWidget* contents_;
|
||||||
|
};
|
||||||
|
|
||||||
|
CollapsibleInfoPane(const Data& data, QWidget* parent = 0);
|
||||||
|
|
||||||
|
const Data& data() const { return data_; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void Expand();
|
void Expand();
|
||||||
|
@ -38,8 +57,8 @@ private slots:
|
||||||
void ExpandedToggled(bool expanded);
|
void ExpandedToggled(bool expanded);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Data data_;
|
||||||
CollapsibleInfoHeader* header_;
|
CollapsibleInfoHeader* header_;
|
||||||
QWidget* widget_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COLLAPSIBLEINFOPANE_H
|
#endif // COLLAPSIBLEINFOPANE_H
|
||||||
|
|
|
@ -32,6 +32,20 @@ struct EchoNestArtistInfo::Request {
|
||||||
EchoNestArtistInfo::EchoNestArtistInfo(QObject* parent)
|
EchoNestArtistInfo::EchoNestArtistInfo(QObject* parent)
|
||||||
: ArtistInfoProvider(parent)
|
: ArtistInfoProvider(parent)
|
||||||
{
|
{
|
||||||
|
site_relevance_["wikipedia"] = 100;
|
||||||
|
site_relevance_["last.fm"] = 60;
|
||||||
|
site_relevance_["lastfm"] = 60;
|
||||||
|
site_relevance_["amazon"] = 30;
|
||||||
|
|
||||||
|
site_icons_["amazon"] = QIcon(":/providers/amazon.png");
|
||||||
|
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");
|
||||||
|
site_icons_["wikipedia"] = QIcon(":/providers/wikipedia.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
void EchoNestArtistInfo::FetchInfo(int id, const QString& artist_name) {
|
void EchoNestArtistInfo::FetchInfo(int id, const QString& artist_name) {
|
||||||
|
@ -84,10 +98,27 @@ void EchoNestArtistInfo::ImagesFinished() {
|
||||||
void EchoNestArtistInfo::BiographiesFinished() {
|
void EchoNestArtistInfo::BiographiesFinished() {
|
||||||
RequestPtr request = ReplyFinished(qobject_cast<QNetworkReply*>(sender()));
|
RequestPtr request = ReplyFinished(qobject_cast<QNetworkReply*>(sender()));
|
||||||
|
|
||||||
foreach (const Echonest::Biography& bio, request->artist_->biographies()) {
|
QSet<QString> already_seen;
|
||||||
QTextEdit* editor = new AutoSizedTextEdit;
|
|
||||||
editor->setHtml(bio.text());
|
|
||||||
|
|
||||||
emit InfoReady(request->id_, tr("Biography from %1").arg(bio.site()), editor);
|
foreach (const Echonest::Biography& bio, request->artist_->biographies()) {
|
||||||
|
if (already_seen.contains(bio.text()))
|
||||||
|
continue;
|
||||||
|
already_seen.insert(bio.text());
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
AutoSizedTextEdit* editor = new AutoSizedTextEdit;
|
||||||
|
editor->setHtml(bio.text());
|
||||||
|
data.contents_ = editor;
|
||||||
|
|
||||||
|
emit InfoReady(request->id_, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include "artistinfoprovider.h"
|
#include "artistinfoprovider.h"
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
|
@ -44,6 +46,8 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<RequestPtr> requests_;
|
QList<RequestPtr> requests_;
|
||||||
|
QMap<QString, int> site_relevance_;
|
||||||
|
QMap<QString, QIcon> site_icons_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ECHONESTARTISTINFO_H
|
#endif // ECHONESTARTISTINFO_H
|
||||||
|
|
|
@ -25,7 +25,7 @@ SongInfoBase::SongInfoBase(NetworkAccessManager* network, QWidget* parent)
|
||||||
|
|
||||||
void SongInfoBase::SongChanged(const Song& metadata) {
|
void SongInfoBase::SongChanged(const Song& metadata) {
|
||||||
if (isVisible()) {
|
if (isVisible()) {
|
||||||
Update(metadata);
|
MaybeUpdate(metadata);
|
||||||
dirty_ = false;
|
dirty_ = false;
|
||||||
} else {
|
} else {
|
||||||
queued_metadata_ = metadata;
|
queued_metadata_ = metadata;
|
||||||
|
@ -39,8 +39,19 @@ void SongInfoBase::SongFinished() {
|
||||||
|
|
||||||
void SongInfoBase::showEvent(QShowEvent* e) {
|
void SongInfoBase::showEvent(QShowEvent* e) {
|
||||||
if (dirty_) {
|
if (dirty_) {
|
||||||
Update(queued_metadata_);
|
MaybeUpdate(queued_metadata_);
|
||||||
dirty_ = false;
|
dirty_ = false;
|
||||||
}
|
}
|
||||||
QWidget::showEvent(e);
|
QWidget::showEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SongInfoBase::MaybeUpdate(const Song& metadata) {
|
||||||
|
if (old_metadata_.is_valid()) {
|
||||||
|
if (!NeedsUpdate(old_metadata_, metadata)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Update(metadata);
|
||||||
|
old_metadata_ = metadata;
|
||||||
|
}
|
||||||
|
|
|
@ -37,11 +37,16 @@ protected:
|
||||||
void showEvent(QShowEvent* e);
|
void showEvent(QShowEvent* e);
|
||||||
|
|
||||||
virtual void Update(const Song& metadata) {}
|
virtual void Update(const Song& metadata) {}
|
||||||
|
virtual bool NeedsUpdate(const Song& old_metadata, const Song& new_metadata) const { return true; }
|
||||||
|
|
||||||
NetworkAccessManager* network_;
|
NetworkAccessManager* network_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void MaybeUpdate(const Song& metadata);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Song queued_metadata_;
|
Song queued_metadata_;
|
||||||
|
Song old_metadata_;
|
||||||
bool dirty_;
|
bool dirty_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/data.qrc">
|
||||||
<normaloff>:/magnatune.png</normaloff>:/magnatune.png</iconset>
|
<normaloff>:/providers/magnatune.png</normaloff>:/providers/magnatune.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
#include "autosizedtextedit.h"
|
#include "autosizedtextedit.h"
|
||||||
|
|
||||||
|
#include <QWheelEvent>
|
||||||
|
|
||||||
AutoSizedTextEdit::AutoSizedTextEdit(QWidget* parent)
|
AutoSizedTextEdit::AutoSizedTextEdit(QWidget* parent)
|
||||||
: QTextEdit(parent)
|
: QTextEdit(parent)
|
||||||
{
|
{
|
||||||
|
@ -28,8 +30,14 @@ void AutoSizedTextEdit::resizeEvent(QResizeEvent* e) {
|
||||||
|
|
||||||
document()->setTextWidth(w);
|
document()->setTextWidth(w);
|
||||||
setMinimumHeight(document()->size().height());
|
setMinimumHeight(document()->size().height());
|
||||||
|
|
||||||
|
QTextEdit::resizeEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize AutoSizedTextEdit::sizeHint() const {
|
QSize AutoSizedTextEdit::sizeHint() const {
|
||||||
return minimumSize();
|
return minimumSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoSizedTextEdit::wheelEvent(QWheelEvent* e) {
|
||||||
|
e->ignore();
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void resizeEvent(QResizeEvent* e);
|
void resizeEvent(QResizeEvent* e);
|
||||||
|
void wheelEvent(QWheelEvent* e);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AUTOSIZEDTEXTEDIT_H
|
#endif // AUTOSIZEDTEXTEDIT_H
|
||||||
|
|
|
@ -152,7 +152,7 @@ void OSD::MagnatuneDownloadFinished(const QStringList& albums) {
|
||||||
message = tr("%1 albums").arg(albums.count());
|
message = tr("%1 albums").arg(albums.count());
|
||||||
|
|
||||||
ShowMessage(tr("Magnatune download finished"), message, QString(),
|
ShowMessage(tr("Magnatune download finished"), message, QString(),
|
||||||
QImage(":magnatune.png"));
|
QImage(":/providers/magnatune.png"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSD::ShowMessage(const QString& summary,
|
void OSD::ShowMessage(const QString& summary,
|
||||||
|
|