From 7e39bfece26371ff23d09f479a5ce25a15898b8d Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sat, 9 Oct 2010 12:39:49 +0000 Subject: [PATCH] Show icons for each biography, order biographies by relevance, don't refresh artist info when switching to another song by the same artist. --- data/data.qrc | 11 +++++- data/providers/amazon.png | Bin 0 -> 1454 bytes data/providers/aol.png | Bin 0 -> 1292 bytes data/providers/cdbaby.png | Bin 0 -> 650 bytes data/{ => providers}/magnatune.png | Bin data/providers/mog.png | Bin 0 -> 535 bytes data/providers/mtvmusic.png | Bin 0 -> 735 bytes data/providers/myspace.png | Bin 0 -> 1281 bytes data/{ => providers}/somafm.png | Bin data/providers/wikipedia.png | Bin 0 -> 3311 bytes src/radio/magnatunedownloaddialog.ui | 5 +-- src/radio/magnatuneservice.cpp | 2 +- src/radio/somafmservice.cpp | 2 +- src/songinfo/artistinfofetcher.cpp | 2 +- src/songinfo/artistinfofetcher.h | 4 +- src/songinfo/artistinfoprovider.h | 4 +- src/songinfo/artistinfoview.cpp | 50 +++++++++++++++++-------- src/songinfo/artistinfoview.h | 9 +++-- src/songinfo/collapsibleinfoheader.cpp | 12 +++++- src/songinfo/collapsibleinfoheader.h | 5 +++ src/songinfo/collapsibleinfopane.cpp | 31 ++++++++------- src/songinfo/collapsibleinfopane.h | 27 +++++++++++-- src/songinfo/echonestartistinfo.cpp | 39 +++++++++++++++++-- src/songinfo/echonestartistinfo.h | 4 ++ src/songinfo/songinfobase.cpp | 15 +++++++- src/songinfo/songinfobase.h | 5 +++ src/ui/settingsdialog.ui | 2 +- src/widgets/autosizedtextedit.cpp | 8 ++++ src/widgets/autosizedtextedit.h | 1 + src/widgets/osd.cpp | 2 +- 30 files changed, 182 insertions(+), 58 deletions(-) create mode 100644 data/providers/amazon.png create mode 100644 data/providers/aol.png create mode 100644 data/providers/cdbaby.png rename data/{ => providers}/magnatune.png (100%) create mode 100644 data/providers/mog.png create mode 100644 data/providers/mtvmusic.png create mode 100644 data/providers/myspace.png rename data/{ => providers}/somafm.png (100%) create mode 100644 data/providers/wikipedia.png diff --git a/data/data.qrc b/data/data.qrc index 1ac53717f..f9fa31171 100644 --- a/data/data.qrc +++ b/data/data.qrc @@ -32,7 +32,7 @@ last.fm/my_friends.png last.fm/my_neighbours.png last.fm/user_purple.png - somafm.png + providers/somafm.png schema-1.sql schema-2.sql nocover.png @@ -45,7 +45,7 @@ schema-7.sql tiny-pause.png tiny-start.png - magnatune.png + providers/magnatune.png schema-8.sql schema-9.sql icons/22x22/application-exit.png @@ -266,5 +266,12 @@ schema-17.sql lyrics/ultimate_providers.xml sidebar_background.png + providers/wikipedia.png + providers/aol.png + providers/amazon.png + providers/myspace.png + providers/mog.png + providers/mtvmusic.png + providers/cdbaby.png diff --git a/data/providers/amazon.png b/data/providers/amazon.png new file mode 100644 index 0000000000000000000000000000000000000000..d7a2ba0237aa3119a731bd7cb13ed182ed98d79e GIT binary patch literal 1454 zcmV;f1yTBmP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FZT01FZU(%pXi00007bV*G`2igh= z3mzTw+kPbg00k~dL_t(o!>yNJY!r16$3L^Td%Ys9r3IzMs1OK=G0~C&CY*_hAVNZ- zFGA27V}gl3D2P4~UgQOgMtRW01o6RYz!1eoO*APy5Tj9prKL&kw4u(fY=5MyqNmAbEon` z!S)d|d#u>_H`Cd|rk7q)vZ6w6GAS>aRKj)TdY;^5Qm*Hzamf<(_xDSZ!Z4i5+`hu% z^CXQ*D*K{fq_eYAwRLp@l<+*co~K07JC(>fd`b^q+TIE7y13zF_tzpmFcBdtSCuWfS%soTL(~_|8=ux^TeuE01OWglgVT_-qpq7!-whX z>w|Ieb{yyS04PX%dpmpf?4j+@Ax>v9+jEDFUf1K7TOJ3DvoB;mSoNOD0y)6%6pyKy7+4Gkc%VZ(+zu!x9L zq+m&mCrrcs{(jZe)QqKJ^!wiX@0aLxcXtaYNyCR8e)!hY@cSQrU~q5{6%n$wwwBko zY$GlJwQVgKiZ-aGWy`c<$Bq&g4_vyW zwQJXE>(;Fbf*|fXBuOLZq^sHSYZL*vmX*48N&e*-FI?#p zq)R6z;DA>J-ks1o2TtxSj?t90;`;YMq5>M zMu7!|$>?j~sWNw(fkOE86*#jue=o&{eymb-1e<`n)+D*YHA)Rdq`F3WFus`f^QARK7IOxN~Hn-5JDi1W4Kl>modqh z8A6D$--q5malt3q>gp=om?(ti6xr_b>mzTUOW-8c>n+@<-LTYlprE+5!VbM zW94$$f)Wv=lwf8sGo+Mv3NSPF_xHWYSpXq~2R?~hrBd5EAw2agT9PE_^?FnD z`%rCUZCbn#0?lUg?pbTi%#5c`pL%Q!0k`NLYuPq*O=}G)<*fqWzkeSCUt3#4r_;g7 z$qAO1m;Z?XGvnak0PS`gjYb2-V$mZdFbw(i>({)nurL;vBncA{ zcRC#|7K^qc%(^n0a{#DTt6sGd5uzyaR1iX-QmG(G63;(;_+X`;)+5SKB0fAkh(ILln8>rs^}i^*)sqD5XZ5Xvqq!AM8wzE*Sxf}#HCV+Z*Fc_Yt4s;haP)o z=AE4#7D8A*KR>rQpPilMTCK)J#O-#Q=jP^YoK-+6g)j^O0AUzHDFtT6U@*Yk+#HI< zA_jv2q?9(!&1b9Cvi|`fO;az%97vPS1ZKvQAP5je5z;h86h(OU>=}d*$mjFe+1c^# z@0pnytgo-*=g*&Zyi_XT+qZAHy1GIT1bFr86#!s39AYpS*qhG)20?($%}o>v1@!xU zJP|^mTCD;Alu}-mn@MgiS5{WgXf%+fDU?!JSy@341UNZ4!ONE~5d;AMpxJEV;^M+n zLkNMbtu1V9Y}{eEx1sTFx9in~Qi^~7{%vbxd3l+YQrziu*vvO;+}zyo*RNk~zsGUR zT5Ed_BuT>m9smAq2mrla55Io>!u$8{y^2lK6koo4!H*w5aCvzNr4*XYCRSHh@%i&- z42MGiK)>I|-rgQ6m5S~6;c$r4(^K^OecM^BRtwE$6TM#V_KPT6G_L$v3A0ygHbv87 zvt}>5?2Br(ItF5F+C4uBXwsPJ2y@@q8pzf`xm@;o8~1zxO>=jyyT;gwZ1!!Z0O;EB6*{zp+{PeCH`3Am~F`0?XE6L3{9;7Td`F=|@S z5-@`X+yw0I?*1aGMJq-C0000-gcs zIm>Q}#;!0&1C16Z^GmI+zeIO!`OEQ5yChQcmaprF#(tNcMN5@-6sUGNu`c%9qEOX) zWzOW=uCu09JXWr^=(c=*CO_@m8Nq*AGJLnEEXXj?Vqm&(`+E4K;<$}VRVU7yH-R_d zmoxhFOG?MF^2{nGlY(BZDh+hAk%!Ibr*DeFq^R?99|i$2$Y?+rFy+6*OO|8JL6 z?={);YWcF&vzupfPO=ZnXWcR7lE%`DR`x!fpOBEfoA<+s8mGz!n$OwoPcG4yeYz!#`@L06&COGr1pnVJt-N?AsD!P} zUM(`-eCE7QcW<(C+GOi-&6wHCJi%+{PphzVNmq3EKA79-bIpkN5V^5(%547k+Ma56 z&7V1BzMGuN`MH?wqea6$#tY@lZf<*e`lTbLS(|6w9qy%v@$Rd`YzLhq9HdwB{QuOsKLNe*T7uY$UFq7+Qibz*aV{CegE2Q Ppaup{S3j3^P6-?hGCdAG6l-iyI8he%?KIX8y%9|JHx_ z@aw}LHlD_L(`PXT&RH67w1VZMpair26=g=Y!fAT`ygHS9B|G@C6?!(8NZvRQG3mC~ zMgFLg{5-}8neRT`x;qWmElIXqxXHSH*O|$DKX&Y1zV^z^6L%!sc8lJ(Z{^vaUA^J* z6RjfOycJKk{&rkF>CJkz3zt7VEnC+dzgSw5*CKm^#XD)vy540W5)J=D>nBJb-g4vA z1s~>#IudWgruynVQCfb)(&4fr+l6Nr;h=m5G6sfiXmbP0g;mKn;>0 u8-nxGO3D+9QW+dm@{>{(JaZG%Q-e|yQz{EjrrH1%F?hQAxvXb#C>)%7RIaMBuIzqKT%YFj(j<*cA1bZ0wOn=~$v$SMopRt`& z!Dq?VUn~kD{%={8Jyvb-G`ZAeSTEEwT_KJox@(FQyGFc?Ps#sWJGop5i*4*13YKjX zz8ANo=&8oG6t+Vmok1!WJ=8kHC-3{wQ~pa)D1~9h`?|imoqSO%?pWNDOPEm<|AB>p}%)H}P@%`#9k4X|7rb60F7Ein{*g82lK-;jOOnyh~ zb*ru~XT^{7n{~NNP@KqgS9Im#gH5+CvoXBo_qJ^0e)x6zjme>Rnyr6vOlgd8oTHRD zsXjCQ#QKIekA=c?W;|v1T9>NaxVJhZ*1O@B+x4?v4h3&5d&D-ncUNBA_jU8X-)8?< z!W9+6IPJ1_oDF zY80So$jwj5OsfQHFtF4$FxNFS2{AOaGP1BTFo9@T@OSk&paup{S3j3^P6Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igh= z3ljh(b8N8y00eB&t+id{s`6QRDo!Qu%oZa6uIx?JX80)YLbz za?vanrcLJHiSOC8{U|l{%>bk%j$!ZCHHg6Cmv(gLeHCLH$>FzNU{d0305e472j9B? z`HlcqG&x#%?VV#BKb;T2#jb|*rR&heUF=ZRkHSJNPj6kn z1c1wxb-a?ffb{7}WG+jk@|vBx1_y>1Oh|}kZN?mIw??q*NDf7%RlNYFB*!p!=6G+I z<6k%Vjq6chTVr!8I}e@Ve0~}AjV+X4{gW|KBUqSrCsQZH;&OSIF)5BsFD_zA@>r~4 z!6e1mD7jLDv$X@W*}xhW!pzC>yuM*Mmo8spVnQ^J%$Y=lH5A}C z;3*NwSJit(7>p5(p!J>ZateA5>|IWR6|$!035?Sr=KnCOvM%x20eYJ1h9MuxNT zxdmh{OT{n*-~kai)7KWby}$H&R8egY*xb9qo8LahXQzJlrq=bhhQlI0!$3w92GG{tIphGXZ5`Cw9rSBNT}F|ye#JcOO-@XPV6m7f zEUx54P9ZM$&`-u6;7uUo?HyFEfgXl?7Ds;&`_M~4j{2jKo0 z$sFCj4v$B@ZiXNf6jze@>V6!~_Td2#kp@-W9~xp=9UC1P(B(wrrjEcE_|BCzfE9=b z61v_~0XjO}!+sBVAzFYIpFgd!zK>kP4iG@ymK|&{<8lqoAKdOC+GSN0RV~mPQ`JyG rM62qjs#>S2ZG(J$sj7GIzkKu;+g?|q1`=jS00000NkvXXu0mjfTA)`) literal 0 HcmV?d00001 diff --git a/data/somafm.png b/data/providers/somafm.png similarity index 100% rename from data/somafm.png rename to data/providers/somafm.png diff --git a/data/providers/wikipedia.png b/data/providers/wikipedia.png new file mode 100644 index 0000000000000000000000000000000000000000..dbcf2a16572df71d8ea411fbe456cf06ad0b6f87 GIT binary patch literal 3311 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 literal 0 HcmV?d00001 diff --git a/src/radio/magnatunedownloaddialog.ui b/src/radio/magnatunedownloaddialog.ui index 5796b103d..d2925964b 100644 --- a/src/radio/magnatunedownloaddialog.ui +++ b/src/radio/magnatunedownloaddialog.ui @@ -15,7 +15,7 @@ - :/magnatune.png:/magnatune.png + :/providers/magnatune.png:/providers/magnatune.png @@ -39,9 +39,6 @@ false - - false - Name diff --git a/src/radio/magnatuneservice.cpp b/src/radio/magnatuneservice.cpp index b98860602..df6156600 100644 --- a/src/radio/magnatuneservice.cpp +++ b/src/radio/magnatuneservice.cpp @@ -106,7 +106,7 @@ void MagnatuneService::ReloadSettings() { RadioItem* MagnatuneService::CreateRootItem(RadioItem *parent) { root_ = new RadioItem(this, RadioItem::Type_Service, kServiceName, parent); - root_->icon = QIcon(":magnatune.png"); + root_->icon = QIcon(":/providers/magnatune.png"); return root_; } diff --git a/src/radio/somafmservice.cpp b/src/radio/somafmservice.cpp index d34543258..bda276c68 100644 --- a/src/radio/somafmservice.cpp +++ b/src/radio/somafmservice.cpp @@ -51,7 +51,7 @@ SomaFMService::~SomaFMService() { RadioItem* SomaFMService::CreateRootItem(RadioItem* parent) { root_ = new RadioItem(this, RadioItem::Type_Service, kServiceName, parent); - root_->icon = QIcon(":somafm.png"); + root_->icon = QIcon(":/providers/somafm.png"); return root_; } diff --git a/src/songinfo/artistinfofetcher.cpp b/src/songinfo/artistinfofetcher.cpp index 2a7f1407a..9f326ffab 100644 --- a/src/songinfo/artistinfofetcher.cpp +++ b/src/songinfo/artistinfofetcher.cpp @@ -27,7 +27,7 @@ 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,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) { diff --git a/src/songinfo/artistinfofetcher.h b/src/songinfo/artistinfofetcher.h index 82e8076d8..e329391be 100644 --- a/src/songinfo/artistinfofetcher.h +++ b/src/songinfo/artistinfofetcher.h @@ -20,6 +20,8 @@ #include #include +#include "collapsibleinfopane.h" + class ArtistInfoProvider; class ArtistInfoFetcher : public QObject { @@ -32,7 +34,7 @@ public: signals: void ImageReady(int id, const QUrl& url); - void InfoReady(int id, const QString& title, QWidget* widget); + void InfoReady(int id, const CollapsibleInfoPane::Data&); private: void AddProvider(ArtistInfoProvider* provider); diff --git a/src/songinfo/artistinfoprovider.h b/src/songinfo/artistinfoprovider.h index 9bcbd6458..a42caebb5 100644 --- a/src/songinfo/artistinfoprovider.h +++ b/src/songinfo/artistinfoprovider.h @@ -20,6 +20,8 @@ #include #include +#include "collapsibleinfopane.h" + class ArtistInfoProvider : public QObject { Q_OBJECT @@ -30,7 +32,7 @@ public: signals: 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 diff --git a/src/songinfo/artistinfoview.cpp b/src/songinfo/artistinfoview.cpp index c5a1db6bd..8a66aed48 100644 --- a/src/songinfo/artistinfoview.cpp +++ b/src/songinfo/artistinfoview.cpp @@ -30,10 +30,12 @@ ArtistInfoView::ArtistInfoView(NetworkAccessManager* network, QWidget *parent) fetcher_(new ArtistInfoFetcher(this)), current_request_id_(-1), 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(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 setLayout(new QVBoxLayout); @@ -47,6 +49,7 @@ ArtistInfoView::ArtistInfoView(NetworkAccessManager* network, QWidget *parent) container_widget->setBackgroundRole(QPalette::Base); container_->setSizeConstraint(QLayout::SetMinAndMaxSize); container_->setContentsMargins(0, 0, 0, 0); + container_->setSpacing(0); scroll_area_->setWidget(container_widget); scroll_area_->setWidgetResizable(true); @@ -62,23 +65,43 @@ ArtistInfoView::ArtistInfoView(NetworkAccessManager* network, QWidget *parent) ArtistInfoView::~ArtistInfoView() { } -void ArtistInfoView::AddChild(QWidget* widget) { - children_ << widget; - container_->insertWidget(container_->count() - 1, widget); - widget->show(); +void ArtistInfoView::AddSection(CollapsibleInfoPane* section) { + int index = 0; + for ( ; indexdata() < sections_[index]->data()) + break; + } + + sections_.insert(index, section); + qobject_cast(section_container_->layout())->insertWidget(index, section); + section->show(); } void ArtistInfoView::Clear() { - qDeleteAll(children_); - children_.clear(); + delete image_view_; + 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) { Clear(); current_request_id_ = fetcher_->FetchInfo(metadata.artist()); + // Image view goes at the top 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) { @@ -88,14 +111,11 @@ void ArtistInfoView::ImageReady(int id, const QUrl& 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_) { - delete widget; + delete data.contents_; return; } - CollapsibleInfoPane* pane = new CollapsibleInfoPane(this); - pane->SetTitle(title); - pane->SetWidget(widget); - AddChild(pane); + AddSection(new CollapsibleInfoPane(data, this)); } diff --git a/src/songinfo/artistinfoview.h b/src/songinfo/artistinfoview.h index 4a395ad85..1648cb2a2 100644 --- a/src/songinfo/artistinfoview.h +++ b/src/songinfo/artistinfoview.h @@ -17,6 +17,7 @@ #ifndef ARTISTINFOVIEW_H #define ARTISTINFOVIEW_H +#include "collapsibleinfopane.h" #include "songinfobase.h" class ArtistInfoFetcher; @@ -34,14 +35,15 @@ public: protected: void Update(const Song& metadata); + bool NeedsUpdate(const Song& old_metadata, const Song& new_metadata) const; private: - void AddChild(QWidget* widget); + void AddSection(CollapsibleInfoPane* section); void Clear(); private slots: 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: ArtistInfoFetcher* fetcher_; @@ -51,7 +53,8 @@ private: QVBoxLayout* container_; PrettyImageView* image_view_; - QList children_; + QWidget* section_container_; + QList sections_; }; #endif // ARTISTINFOVIEW_H diff --git a/src/songinfo/collapsibleinfoheader.cpp b/src/songinfo/collapsibleinfoheader.cpp index ec5b61b76..611b5fc56 100644 --- a/src/songinfo/collapsibleinfoheader.cpp +++ b/src/songinfo/collapsibleinfoheader.cpp @@ -22,6 +22,7 @@ #include const int CollapsibleInfoHeader::kHeight = 20; +const int CollapsibleInfoHeader::kIconSize = 16; CollapsibleInfoHeader::CollapsibleInfoHeader(QWidget* parent) : QWidget(parent), @@ -38,6 +39,11 @@ void CollapsibleInfoHeader::SetTitle(const QString& title) { update(); } +void CollapsibleInfoHeader::SetIcon(const QIcon& icon) { + icon_ = icon; + update(); +} + void CollapsibleInfoHeader::SetExpanded(bool expanded) { expanded_ = expanded; @@ -62,8 +68,9 @@ void CollapsibleInfoHeader::paintEvent(QPaintEvent* e) { QPainter p(this); QRect indicator_rect(0, 0, height(), height()); + QRect icon_rect(height() + 2, (kHeight - kIconSize) / 2, kIconSize, kIconSize); QRect text_rect(rect()); - text_rect.setLeft(height() + 6); + text_rect.setLeft(icon_rect.right() + 4); // Draw the background 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). QApplication::style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, &p, this); + // Draw the icon + p.drawPixmap(icon_rect, icon_.pixmap(kIconSize)); + // Draw the title text QFont bold_font(font()); bold_font.setBold(true); diff --git a/src/songinfo/collapsibleinfoheader.h b/src/songinfo/collapsibleinfoheader.h index c74b0c6d8..9e91525d0 100644 --- a/src/songinfo/collapsibleinfoheader.h +++ b/src/songinfo/collapsibleinfoheader.h @@ -17,6 +17,7 @@ #ifndef COLLAPSIBLEINFOHEADER_H #define COLLAPSIBLEINFOHEADER_H +#include #include class CollapsibleInfoHeader : public QWidget { @@ -26,14 +27,17 @@ public: CollapsibleInfoHeader(QWidget* parent = 0); static const int kHeight; + static const int kIconSize; bool expanded() const { return expanded_; } bool hovering() const { return hovering_; } const QString& title() const { return title_; } + const QIcon& icon() const { return icon_; } public slots: void SetExpanded(bool expanded); void SetTitle(const QString& title); + void SetIcon(const QIcon& icon); signals: void Expanded(); @@ -50,6 +54,7 @@ private: bool expanded_; bool hovering_; QString title_; + QIcon icon_; }; #endif // COLLAPSIBLEINFOHEADER_H diff --git a/src/songinfo/collapsibleinfopane.cpp b/src/songinfo/collapsibleinfopane.cpp index 99f60805c..f52808317 100644 --- a/src/songinfo/collapsibleinfopane.cpp +++ b/src/songinfo/collapsibleinfopane.cpp @@ -19,10 +19,10 @@ #include -CollapsibleInfoPane::CollapsibleInfoPane(QWidget* parent) +CollapsibleInfoPane::CollapsibleInfoPane(const Data& data, QWidget* parent) : QWidget(parent), - header_(new CollapsibleInfoHeader(this)), - widget_(NULL) + data_(data), + header_(new CollapsibleInfoHeader(this)) { QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); @@ -31,24 +31,16 @@ CollapsibleInfoPane::CollapsibleInfoPane(QWidget* parent) setLayout(layout); layout->addWidget(header_); + layout->addWidget(data.contents_); + + header_->SetTitle(data.title_); + header_->SetIcon(data.icon_); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); 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() { header_->SetExpanded(false); } @@ -58,5 +50,12 @@ void CollapsibleInfoPane::Expand() { } 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; } diff --git a/src/songinfo/collapsibleinfopane.h b/src/songinfo/collapsibleinfopane.h index 8847de39b..4c029aab1 100644 --- a/src/songinfo/collapsibleinfopane.h +++ b/src/songinfo/collapsibleinfopane.h @@ -17,6 +17,7 @@ #ifndef COLLAPSIBLEINFOPANE_H #define COLLAPSIBLEINFOPANE_H +#include #include class CollapsibleInfoHeader; @@ -25,10 +26,28 @@ class CollapsibleInfoPane : public QWidget { Q_OBJECT public: - CollapsibleInfoPane(QWidget* parent = 0); + struct Data { + Data() : type_(Type_Biography), relevance_(0) {} - void SetTitle(const QString& title); - void SetWidget(QWidget* widget); + bool operator <(const Data& other) const; + + 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: void Expand(); @@ -38,8 +57,8 @@ private slots: void ExpandedToggled(bool expanded); private: + Data data_; CollapsibleInfoHeader* header_; - QWidget* widget_; }; #endif // COLLAPSIBLEINFOPANE_H diff --git a/src/songinfo/echonestartistinfo.cpp b/src/songinfo/echonestartistinfo.cpp index 0dc2602b7..ec4b8c2b9 100644 --- a/src/songinfo/echonestartistinfo.cpp +++ b/src/songinfo/echonestartistinfo.cpp @@ -32,6 +32,20 @@ struct EchoNestArtistInfo::Request { EchoNestArtistInfo::EchoNestArtistInfo(QObject* 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) { @@ -84,10 +98,27 @@ void EchoNestArtistInfo::ImagesFinished() { void EchoNestArtistInfo::BiographiesFinished() { RequestPtr request = ReplyFinished(qobject_cast(sender())); - foreach (const Echonest::Biography& bio, request->artist_->biographies()) { - QTextEdit* editor = new AutoSizedTextEdit; - editor->setHtml(bio.text()); + QSet already_seen; - 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); } } diff --git a/src/songinfo/echonestartistinfo.h b/src/songinfo/echonestartistinfo.h index cb174deb1..7a344d187 100644 --- a/src/songinfo/echonestartistinfo.h +++ b/src/songinfo/echonestartistinfo.h @@ -19,6 +19,8 @@ #include "artistinfoprovider.h" +#include + #include class QNetworkReply; @@ -44,6 +46,8 @@ private: private: QList requests_; + QMap site_relevance_; + QMap site_icons_; }; #endif // ECHONESTARTISTINFO_H diff --git a/src/songinfo/songinfobase.cpp b/src/songinfo/songinfobase.cpp index cd7b9e154..8d473bd71 100644 --- a/src/songinfo/songinfobase.cpp +++ b/src/songinfo/songinfobase.cpp @@ -25,7 +25,7 @@ SongInfoBase::SongInfoBase(NetworkAccessManager* network, QWidget* parent) void SongInfoBase::SongChanged(const Song& metadata) { if (isVisible()) { - Update(metadata); + MaybeUpdate(metadata); dirty_ = false; } else { queued_metadata_ = metadata; @@ -39,8 +39,19 @@ void SongInfoBase::SongFinished() { void SongInfoBase::showEvent(QShowEvent* e) { if (dirty_) { - Update(queued_metadata_); + MaybeUpdate(queued_metadata_); dirty_ = false; } 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; +} diff --git a/src/songinfo/songinfobase.h b/src/songinfo/songinfobase.h index 4e3ee3c3a..0e9885964 100644 --- a/src/songinfo/songinfobase.h +++ b/src/songinfo/songinfobase.h @@ -37,11 +37,16 @@ protected: void showEvent(QShowEvent* e); virtual void Update(const Song& metadata) {} + virtual bool NeedsUpdate(const Song& old_metadata, const Song& new_metadata) const { return true; } NetworkAccessManager* network_; +private: + void MaybeUpdate(const Song& metadata); + private: Song queued_metadata_; + Song old_metadata_; bool dirty_; }; diff --git a/src/ui/settingsdialog.ui b/src/ui/settingsdialog.ui index 3e245ae8a..106dd6e35 100644 --- a/src/ui/settingsdialog.ui +++ b/src/ui/settingsdialog.ui @@ -99,7 +99,7 @@ - :/magnatune.png:/magnatune.png + :/providers/magnatune.png:/providers/magnatune.png diff --git a/src/widgets/autosizedtextedit.cpp b/src/widgets/autosizedtextedit.cpp index 1d6103456..d29a9986e 100644 --- a/src/widgets/autosizedtextedit.cpp +++ b/src/widgets/autosizedtextedit.cpp @@ -16,6 +16,8 @@ #include "autosizedtextedit.h" +#include + AutoSizedTextEdit::AutoSizedTextEdit(QWidget* parent) : QTextEdit(parent) { @@ -28,8 +30,14 @@ void AutoSizedTextEdit::resizeEvent(QResizeEvent* e) { document()->setTextWidth(w); setMinimumHeight(document()->size().height()); + + QTextEdit::resizeEvent(e); } QSize AutoSizedTextEdit::sizeHint() const { return minimumSize(); } + +void AutoSizedTextEdit::wheelEvent(QWheelEvent* e) { + e->ignore(); +} diff --git a/src/widgets/autosizedtextedit.h b/src/widgets/autosizedtextedit.h index 766c715dd..c9f09fb10 100644 --- a/src/widgets/autosizedtextedit.h +++ b/src/widgets/autosizedtextedit.h @@ -29,6 +29,7 @@ public: protected: void resizeEvent(QResizeEvent* e); + void wheelEvent(QWheelEvent* e); }; #endif // AUTOSIZEDTEXTEDIT_H diff --git a/src/widgets/osd.cpp b/src/widgets/osd.cpp index 186a99b06..cfef14abb 100644 --- a/src/widgets/osd.cpp +++ b/src/widgets/osd.cpp @@ -152,7 +152,7 @@ void OSD::MagnatuneDownloadFinished(const QStringList& albums) { message = tr("%1 albums").arg(albums.count()); ShowMessage(tr("Magnatune download finished"), message, QString(), - QImage(":magnatune.png")); + QImage(":/providers/magnatune.png")); } void OSD::ShowMessage(const QString& summary,