From b21993eee8f477e7e9843315182f74a9c4a5bb64 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sun, 24 Jan 2021 20:04:29 +0100 Subject: [PATCH] Add artist biography --- data/data.qrc | 1 + data/icons.qrc | 5 + data/icons/128x128/guitar.png | Bin 0 -> 11489 bytes data/icons/22x22/guitar.png | Bin 0 -> 1081 bytes data/icons/32x32/guitar.png | Bin 0 -> 1238 bytes data/icons/48x48/guitar.png | Bin 0 -> 2424 bytes data/icons/64x64/guitar.png | Bin 0 -> 3755 bytes data/icons/full/guitar.png | Bin 0 -> 127602 bytes data/style/artistbio.css | 7 + src/CMakeLists.txt | 27 +++ src/artistbio/artistbiofetcher.cpp | 126 ++++++++++ src/artistbio/artistbiofetcher.h | 75 ++++++ src/artistbio/artistbioprovider.cpp | 25 ++ src/artistbio/artistbioprovider.h | 53 +++++ src/artistbio/artistbioview.cpp | 287 ++++++++++++++++++++++ src/artistbio/artistbioview.h | 104 ++++++++ src/artistbio/lastfmartistbio.cpp | 209 ++++++++++++++++ src/artistbio/lastfmartistbio.h | 66 ++++++ src/artistbio/wikipediaartistbio.cpp | 316 +++++++++++++++++++++++++ src/artistbio/wikipediaartistbio.h | 72 ++++++ src/core/latch.cpp | 39 +++ src/core/latch.h | 39 +++ src/core/mainwindow.cpp | 19 ++ src/core/mainwindow.h | 3 + src/core/metatypes.cpp | 3 + src/settings/behavioursettingspage.cpp | 2 + src/settings/behavioursettingspage.ui | 7 + src/widgets/collapsibleinfoheader.cpp | 174 ++++++++++++++ src/widgets/collapsibleinfoheader.h | 82 +++++++ src/widgets/collapsibleinfopane.cpp | 64 +++++ src/widgets/collapsibleinfopane.h | 72 ++++++ src/widgets/infotextview.cpp | 89 +++++++ src/widgets/infotextview.h | 52 ++++ src/widgets/prettyimage.cpp | 257 ++++++++++++++++++++ src/widgets/prettyimage.h | 92 +++++++ src/widgets/prettyimageview.cpp | 189 +++++++++++++++ src/widgets/prettyimageview.h | 74 ++++++ src/widgets/widgetfadehelper.cpp | 185 +++++++++++++++ src/widgets/widgetfadehelper.h | 63 +++++ 39 files changed, 2878 insertions(+) create mode 100644 data/icons/128x128/guitar.png create mode 100644 data/icons/22x22/guitar.png create mode 100644 data/icons/32x32/guitar.png create mode 100644 data/icons/48x48/guitar.png create mode 100644 data/icons/64x64/guitar.png create mode 100644 data/icons/full/guitar.png create mode 100644 data/style/artistbio.css create mode 100644 src/artistbio/artistbiofetcher.cpp create mode 100644 src/artistbio/artistbiofetcher.h create mode 100644 src/artistbio/artistbioprovider.cpp create mode 100644 src/artistbio/artistbioprovider.h create mode 100644 src/artistbio/artistbioview.cpp create mode 100644 src/artistbio/artistbioview.h create mode 100644 src/artistbio/lastfmartistbio.cpp create mode 100644 src/artistbio/lastfmartistbio.h create mode 100644 src/artistbio/wikipediaartistbio.cpp create mode 100644 src/artistbio/wikipediaartistbio.h create mode 100644 src/core/latch.cpp create mode 100644 src/core/latch.h create mode 100644 src/widgets/collapsibleinfoheader.cpp create mode 100644 src/widgets/collapsibleinfoheader.h create mode 100644 src/widgets/collapsibleinfopane.cpp create mode 100644 src/widgets/collapsibleinfopane.h create mode 100644 src/widgets/infotextview.cpp create mode 100644 src/widgets/infotextview.h create mode 100644 src/widgets/prettyimage.cpp create mode 100644 src/widgets/prettyimage.h create mode 100644 src/widgets/prettyimageview.cpp create mode 100644 src/widgets/prettyimageview.h create mode 100644 src/widgets/widgetfadehelper.cpp create mode 100644 src/widgets/widgetfadehelper.h diff --git a/data/data.qrc b/data/data.qrc index 874f7ceb..c96fbe05 100644 --- a/data/data.qrc +++ b/data/data.qrc @@ -12,6 +12,7 @@ schema/schema-18.sql schema/device-schema.sql style/strawberry.css + style/artistbio.css style/smartplaylistsearchterm.css html/oauthsuccess.html pictures/strawberry.png diff --git a/data/icons.qrc b/data/icons.qrc index 847f5c96..27806c7f 100644 --- a/data/icons.qrc +++ b/data/icons.qrc @@ -97,6 +97,7 @@ icons/128x128/somafm.png icons/128x128/radioparadise.png icons/128x128/musicbrainz.png + icons/128x128/guitar.png icons/64x64/albums.png icons/64x64/alsa.png icons/64x64/application-exit.png @@ -195,6 +196,7 @@ icons/64x64/somafm.png icons/64x64/radioparadise.png icons/64x64/musicbrainz.png + icons/64x64/guitar.png icons/48x48/albums.png icons/48x48/alsa.png icons/48x48/application-exit.png @@ -297,6 +299,7 @@ icons/48x48/somafm.png icons/48x48/radioparadise.png icons/48x48/musicbrainz.png + icons/48x48/guitar.png icons/32x32/albums.png icons/32x32/alsa.png icons/32x32/application-exit.png @@ -399,6 +402,7 @@ icons/32x32/somafm.png icons/32x32/radioparadise.png icons/32x32/musicbrainz.png + icons/32x32/guitar.png icons/22x22/albums.png icons/22x22/alsa.png icons/22x22/application-exit.png @@ -501,5 +505,6 @@ icons/22x22/somafm.png icons/22x22/radioparadise.png icons/22x22/musicbrainz.png + icons/22x22/guitar.png diff --git a/data/icons/128x128/guitar.png b/data/icons/128x128/guitar.png new file mode 100644 index 0000000000000000000000000000000000000000..0844bbf9af68d47cc053d19597be35dd9ef6279a GIT binary patch literal 11489 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�@ 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 VsSl%-FbBxTEiFCGat*tn{{uu$SOWk6 literal 0 HcmV?d00001 diff --git a/data/style/artistbio.css b/data/style/artistbio.css new file mode 100644 index 00000000..5ac19618 --- /dev/null +++ b/data/style/artistbio.css @@ -0,0 +1,7 @@ +QScrollArea { + background: qpalette(base); +} + +QTextEdit { + border: 0px; +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 629f1fd7..68398d7d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -39,6 +39,7 @@ set(SOURCES core/scopedtransaction.cpp core/translations.cpp core/systemtrayicon.cpp + core/latch.cpp utilities/strutils.cpp utilities/envutils.cpp @@ -245,6 +246,12 @@ set(SOURCES widgets/loginstatewidget.cpp widgets/ratingwidget.cpp widgets/resizabletextedit.cpp + widgets/widgetfadehelper.cpp + widgets/prettyimageview.cpp + widgets/prettyimage.cpp + widgets/collapsibleinfoheader.cpp + widgets/collapsibleinfopane.cpp + widgets/infotextview.cpp osd/osdbase.cpp osd/osdpretty.cpp @@ -291,6 +298,12 @@ set(SOURCES organize/organizedialog.cpp organize/organizeerrordialog.cpp + artistbio/artistbioview.cpp + artistbio/artistbiofetcher.cpp + artistbio/artistbioprovider.cpp + artistbio/lastfmartistbio.cpp + artistbio/wikipediaartistbio.cpp + ) set(HEADERS @@ -316,6 +329,7 @@ set(HEADERS core/potranslator.h core/mimedata.h core/stylesheetloader.h + core/latch.h engine/enginebase.h engine/devicefinders.h @@ -486,6 +500,13 @@ set(HEADERS widgets/qsearchfield.h widgets/ratingwidget.h widgets/forcescrollperpixel.h + widgets/resizabletextedit.h + widgets/widgetfadehelper.h + widgets/prettyimage.h + widgets/prettyimageview.h + widgets/collapsibleinfoheader.h + widgets/collapsibleinfopane.h + widgets/infotextview.h osd/osdbase.h osd/osdpretty.h @@ -527,6 +548,12 @@ set(HEADERS organize/organizedialog.h organize/organizeerrordialog.h + artistbio/artistbiofetcher.h + artistbio/artistbioprovider.h + artistbio/artistbioview.h + artistbio/lastfmartistbio.h + artistbio/wikipediaartistbio.h + ) set(UI diff --git a/src/artistbio/artistbiofetcher.cpp b/src/artistbio/artistbiofetcher.cpp new file mode 100644 index 00000000..f30fe2bc --- /dev/null +++ b/src/artistbio/artistbiofetcher.cpp @@ -0,0 +1,126 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include +#include +#include + +#include "artistbiofetcher.h" +#include "artistbioprovider.h" +#include "core/logging.h" + +ArtistBioFetcher::ArtistBioFetcher(QObject *parent) + : QObject(parent), + timeout_duration_(kDefaultTimeoutDuration), + next_id_(1) {} + +void ArtistBioFetcher::AddProvider(ArtistBioProvider *provider) { + + providers_ << provider; + connect(provider, SIGNAL(ImageReady(int, QUrl)), SLOT(ImageReady(int, QUrl)), Qt::QueuedConnection); + connect(provider, SIGNAL(InfoReady(int, CollapsibleInfoPane::Data)), SLOT(InfoReady(int, CollapsibleInfoPane::Data)), Qt::QueuedConnection); + connect(provider, SIGNAL(Finished(int)), SLOT(ProviderFinished(int)), Qt::QueuedConnection); + +} + +ArtistBioFetcher::~ArtistBioFetcher() { + + while (!providers_.isEmpty()) { + ArtistBioProvider *provider = providers_.takeFirst(); + provider->deleteLater(); + } + +} + +int ArtistBioFetcher::FetchInfo(const Song &metadata) { + + const int id = next_id_++; + results_[id] = Result(); + timeout_timers_[id] = new QTimer(this); + timeout_timers_[id]->setSingleShot(true); + timeout_timers_[id]->setInterval(timeout_duration_); + timeout_timers_[id]->start(); + + connect(timeout_timers_[id], &QTimer::timeout, [this, id]() { Timeout(id); }); + + for (ArtistBioProvider *provider : providers_) { + if (provider->is_enabled()) { + waiting_for_[id].append(provider); + provider->Start(id, metadata); + } + } + return id; + +} + +void ArtistBioFetcher::ImageReady(const int id, const QUrl &url) { + + if (!results_.contains(id)) return; + results_[id].images_ << url; + +} + +void ArtistBioFetcher::InfoReady(const int id, const CollapsibleInfoPane::Data &data) { + + if (!results_.contains(id)) return; + results_[id].info_ << data; + + if (!waiting_for_.contains(id)) return; + emit InfoResultReady(id, data); + +} + +void ArtistBioFetcher::ProviderFinished(const int id) { + + if (!results_.contains(id)) return; + if (!waiting_for_.contains(id)) return; + + ArtistBioProvider *provider = qobject_cast(sender()); + if (!waiting_for_[id].contains(provider)) return; + + waiting_for_[id].removeAll(provider); + if (waiting_for_[id].isEmpty()) { + Result result = results_.take(id); + emit ResultReady(id, result); + waiting_for_.remove(id); + delete timeout_timers_.take(id); + } + +} + +void ArtistBioFetcher::Timeout(const int id) { + + if (!results_.contains(id)) return; + if (!waiting_for_.contains(id)) return; + + // Emit the results that we have already + emit ResultReady(id, results_.take(id)); + + // Cancel any providers that we're still waiting for + for (ArtistBioProvider *provider : waiting_for_[id]) { + qLog(Info) << "Request timed out from info provider" << provider->name(); + provider->Cancel(id); + } + waiting_for_.remove(id); + + // Remove the timer + delete timeout_timers_.take(id); + +} diff --git a/src/artistbio/artistbiofetcher.h b/src/artistbio/artistbiofetcher.h new file mode 100644 index 00000000..da56dca1 --- /dev/null +++ b/src/artistbio/artistbiofetcher.h @@ -0,0 +1,75 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef ARTISTBIOFETCHER_H +#define ARTISTBIOFETCHER_H + +#include +#include +#include +#include + +#include "widgets/collapsibleinfopane.h" +#include "core/song.h" + +class QTimer; +class ArtistBioProvider; + +class ArtistBioFetcher : public QObject { + Q_OBJECT + + public: + explicit ArtistBioFetcher(QObject *parent = nullptr); + ~ArtistBioFetcher() override; + + struct Result { + QList images_; + QList info_; + }; + + static const int kDefaultTimeoutDuration = 25000; + + void AddProvider(ArtistBioProvider *provider); + int FetchInfo(const Song &metadata); + + QList providers() const { return providers_; } + + signals: + void InfoResultReady(int, CollapsibleInfoPane::Data); + void ResultReady(int, ArtistBioFetcher::Result); + + private slots: + void ImageReady(const int id, const QUrl &url); + void InfoReady(const int id, const CollapsibleInfoPane::Data &data); + void ProviderFinished(const int id); + void Timeout(const int id); + + private: + QList providers_; + + QMap results_; + QMap> waiting_for_; + QMap timeout_timers_; + + int timeout_duration_; + int next_id_; +}; + +#endif // ARTISTBIOFETCHER_H diff --git a/src/artistbio/artistbioprovider.cpp b/src/artistbio/artistbioprovider.cpp new file mode 100644 index 00000000..a9db1041 --- /dev/null +++ b/src/artistbio/artistbioprovider.cpp @@ -0,0 +1,25 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include "artistbioprovider.h" + +ArtistBioProvider::ArtistBioProvider() : enabled_(true) {} + +QString ArtistBioProvider::name() const { return metaObject()->className(); } diff --git a/src/artistbio/artistbioprovider.h b/src/artistbio/artistbioprovider.h new file mode 100644 index 00000000..f7dd7f41 --- /dev/null +++ b/src/artistbio/artistbioprovider.h @@ -0,0 +1,53 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef ARTISTBIOPROVIDER_H +#define ARTISTBIOPROVIDER_H + +#include +#include + +#include "widgets/collapsibleinfopane.h" +#include "core/song.h" + +class ArtistBioProvider : public QObject { + Q_OBJECT + + public: + explicit ArtistBioProvider(); + + virtual void Start(const int id, const Song &song) = 0; + virtual void Cancel(const int) {} + + virtual QString name() const; + + bool is_enabled() const { return enabled_; } + void set_enabled(bool enabled) { enabled_ = enabled; } + + signals: + void ImageReady(int, QUrl); + void InfoReady(int, CollapsibleInfoPane::Data); + void Finished(int); + + private: + bool enabled_; +}; + +#endif // ARTISTBIOPROVIDER_H diff --git a/src/artistbio/artistbioview.cpp b/src/artistbio/artistbioview.cpp new file mode 100644 index 00000000..cc941777 --- /dev/null +++ b/src/artistbio/artistbioview.cpp @@ -0,0 +1,287 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/song.h" +#include "core/networkaccessmanager.h" +#include "widgets/prettyimageview.h" +#include "widgets/widgetfadehelper.h" +#include "artistbiofetcher.h" +#include "lastfmartistbio.h" +#include "wikipediaartistbio.h" + +#include "artistbioview.h" + +const char *ArtistBioView::kSettingsGroup = "ArtistBio"; + +ArtistBioView::ArtistBioView(QWidget *parent) + : QWidget(parent), + network_(new NetworkAccessManager(this)), + fetcher_(new ArtistBioFetcher(this)), + current_request_id_(-1), + container_(new QVBoxLayout), + section_container_(nullptr), + fader_(new WidgetFadeHelper(this, 1000)), + dirty_(false) { + + // Add the top-level scroll area + QScrollArea *scrollarea = new QScrollArea(this); + setLayout(new QVBoxLayout); + layout()->setContentsMargins(0, 0, 0, 0); + layout()->addWidget(scrollarea); + + // Add a container widget to the scroll area + QWidget *container_widget = new QWidget; + container_widget->setLayout(container_); + container_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + container_widget->setBackgroundRole(QPalette::Base); + container_->setSizeConstraint(QLayout::SetMinAndMaxSize); + container_->setContentsMargins(0, 0, 0, 0); + container_->setSpacing(6); + scrollarea->setWidget(container_widget); + scrollarea->setWidgetResizable(true); + + // Add a spacer to the bottom of the container + container_->addStretch(); + + // Set stylesheet + QFile stylesheet(":/style/artistbio.css"); + if (stylesheet.open(QIODevice::ReadOnly)) { + setStyleSheet(QString::fromLatin1(stylesheet.readAll())); + stylesheet.close(); + } + + fetcher_->AddProvider(new LastFMArtistBio); + fetcher_->AddProvider(new WikipediaArtistBio); + + connect(fetcher_, SIGNAL(ResultReady(int, ArtistBioFetcher::Result)), SLOT(ResultReady(int, ArtistBioFetcher::Result))); + connect(fetcher_, SIGNAL(InfoResultReady(int, CollapsibleInfoPane::Data)), SLOT(InfoResultReady(int, CollapsibleInfoPane::Data))); + +} + +ArtistBioView::~ArtistBioView() {} + +void ArtistBioView::showEvent(QShowEvent *e) { + + if (dirty_) { + MaybeUpdate(queued_metadata_); + dirty_ = false; + } + + QWidget::showEvent(e); + +} + +void ArtistBioView::ReloadSettings() { + + for (CollapsibleInfoPane *pane : sections_) { + QWidget *contents = pane->data().contents_; + if (!contents) continue; + + QMetaObject::invokeMethod(contents, "ReloadSettings"); + } + +} + +bool ArtistBioView::NeedsUpdate(const Song &old_metadata, const Song &new_metadata) const { + + if (new_metadata.artist().isEmpty()) return false; + + return old_metadata.artist() != new_metadata.artist(); + +} + +void ArtistBioView::InfoResultReady(const int id, const CollapsibleInfoPane::Data &_data) { + + if (id != current_request_id_) return; + + AddSection(new CollapsibleInfoPane(_data, this)); + CollapseSections(); + +} + +void ArtistBioView::ResultReady(const int id, const ArtistBioFetcher::Result &result) { + + if (id != current_request_id_) return; + + if (!result.images_.isEmpty()) { + // Image view goes at the top + PrettyImageView *image_view = new PrettyImageView(network_, this); + AddWidget(image_view); + + for (const QUrl& url : result.images_) { + image_view->AddImage(url); + } + } + + CollapseSections(); + +} + +void ArtistBioView::Clear() { + + fader_->StartFade(); + + qDeleteAll(widgets_); + widgets_.clear(); + if (section_container_) { + container_->removeWidget(section_container_); + delete section_container_; + } + sections_.clear(); + + // Container for collapsible 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(0, section_container_); + +} + +void ArtistBioView::AddSection(CollapsibleInfoPane *section) { + + int i = 0; + for (; i < sections_.count(); ++i) { + if (section->data() < sections_[i]->data()) break; + } + + ConnectWidget(section->data().contents_); + + sections_.insert(i, section); + qobject_cast(section_container_->layout())->insertWidget(i, section); + section->show(); + +} + +void ArtistBioView::AddWidget(QWidget *widget) { + + ConnectWidget(widget); + + container_->insertWidget(container_->count() - 2, widget); + widgets_ << widget; + +} + +void ArtistBioView::SongChanged(const Song &metadata) { + + if (isVisible()) { + MaybeUpdate(metadata); + dirty_ = false; + } + else { + queued_metadata_ = metadata; + dirty_ = true; + } + +} + +void ArtistBioView::SongFinished() { dirty_ = false; } + +void ArtistBioView::MaybeUpdate(const Song &metadata) { + + if (old_metadata_.is_valid()) { + if (!NeedsUpdate(old_metadata_, metadata)) { + return; + } + } + + Update(metadata); + old_metadata_ = metadata; + +} + +void ArtistBioView::Update(const Song &metadata) { + + current_request_id_ = fetcher_->FetchInfo(metadata); + + // Do this after the new pane has been shown otherwise it'll just grab a black rectangle. + Clear(); + QTimer::singleShot(0, fader_, SLOT(StartBlur())); + +} + +void ArtistBioView::CollapseSections() { + + QSettings s; + s.beginGroup(kSettingsGroup); + + // Sections are already sorted by type and relevance, so the algorithm we use to determine which ones to show by default is: + // * In the absence of any user preference, show the first (highest relevance section of each type and hide the rest) + // * If one or more sections in a type have been explicitly hidden/shown by the user before then hide all sections in that type and show only the ones that are explicitly shown. + + QMultiMap types_; + QSet has_user_preference_; + for (CollapsibleInfoPane *pane : sections_) { + const CollapsibleInfoPane::Data::Type type = pane->data().type_; + types_.insert(type, pane); + + QVariant preference = s.value(pane->data().id_); + if (preference.isValid()) { + has_user_preference_.insert(type); + if (preference.toBool()) { + pane->Expand(); + } + } + } + + for (CollapsibleInfoPane::Data::Type type : types_.keys()) { + if (!has_user_preference_.contains(type)) { + // Expand the first one + types_.values(type).last()->Expand(); + } + } + + for (CollapsibleInfoPane *pane : sections_) { + connect(pane, SIGNAL(Toggled(bool)), SLOT(SectionToggled(bool))); + } + +} + +void ArtistBioView::SectionToggled(const bool value) { + + CollapsibleInfoPane *pane = qobject_cast(sender()); + if (!pane || !sections_.contains(pane)) return; + + QSettings s; + s.beginGroup(kSettingsGroup); + s.setValue(pane->data().id_, value); + s.endGroup(); + +} + +void ArtistBioView::ConnectWidget(QWidget *widget) { + + const QMetaObject *m = widget->metaObject(); + + if (m->indexOfSignal("ShowSettingsDialog()") != -1) { + connect(widget, SIGNAL(ShowSettingsDialog()), SIGNAL(ShowSettingsDialog())); + } + +} diff --git a/src/artistbio/artistbioview.h b/src/artistbio/artistbioview.h new file mode 100644 index 00000000..90b09373 --- /dev/null +++ b/src/artistbio/artistbioview.h @@ -0,0 +1,104 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef ARTISTBIOVIEW_H +#define ARTISTBIOVIEW_H + +#include +#include +#include + +#include "core/song.h" +#include "widgets/collapsibleinfopane.h" +#include "widgets/widgetfadehelper.h" +#include "widgets/collapsibleinfopane.h" +#include "playlist/playlistitem.h" +#include "smartplaylists/playlistgenerator_fwd.h" +#include "artistbiofetcher.h" + +class QNetworkAccessManager; +class QTimeLine; +class QVBoxLayout; +class QScrollArea; +class QShowEvent; + +class PrettyImageView; +class CollapsibleInfoPane; +class WidgetFadeHelper; + +class ArtistBioView : public QWidget { + Q_OBJECT + + public: + explicit ArtistBioView(QWidget *parent = nullptr); + ~ArtistBioView() override; + + static const char *kSettingsGroup; + + public slots: + void SongChanged(const Song& metadata); + void SongFinished(); + virtual void ReloadSettings(); + + signals: + void ShowSettingsDialog(); + + protected: + void showEvent(QShowEvent *e) override; + + void Update(const Song &metadata); + void AddWidget(QWidget *widget); + void AddSection(CollapsibleInfoPane *section); + void Clear(); + void CollapseSections(); + + bool NeedsUpdate(const Song& old_metadata, const Song &new_metadata) const; + + protected slots: + void ResultReady(const int id, const ArtistBioFetcher::Result &result); + void InfoResultReady(const int id, const CollapsibleInfoPane::Data &data); + + protected: + QNetworkAccessManager *network_; + ArtistBioFetcher *fetcher_; + int current_request_id_; + + private: + void MaybeUpdate(const Song &metadata); + void ConnectWidget(QWidget *widget); + + private slots: + void SectionToggled(const bool value); + + private: + QVBoxLayout *container_; + QList widgets_; + + QWidget *section_container_; + QList sections_; + + WidgetFadeHelper *fader_; + + Song queued_metadata_; + Song old_metadata_; + bool dirty_; +}; + +#endif // ARTISTBIOVIEW_H diff --git a/src/artistbio/lastfmartistbio.cpp b/src/artistbio/lastfmartistbio.cpp new file mode 100644 index 00000000..91fa7c12 --- /dev/null +++ b/src/artistbio/lastfmartistbio.cpp @@ -0,0 +1,209 @@ +/* + * Strawberry Music Player + * Copyright 2020, Jonas Kvinge + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/networkaccessmanager.h" +#include "core/song.h" +#include "core/logging.h" +#include "core/iconloader.h" + +#include "lastfmartistbio.h" +#include "widgets/infotextview.h" +#include "scrobbler/scrobblingapi20.h" +#include "scrobbler/lastfmscrobbler.h" + +LastFMArtistBio::LastFMArtistBio() : ArtistBioProvider(), network_(new NetworkAccessManager(this)) {} + +LastFMArtistBio::~LastFMArtistBio() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + reply->abort(); + reply->deleteLater(); + } + +} + +void LastFMArtistBio::Start(const int id, const Song &song) { + + ParamList params = ParamList() + << Param("api_key", ScrobblingAPI20::kApiKey) + << Param("lang", QLocale().name().left(2).toLower()) + << Param("format", "json") + << Param("method", "artist.getinfo") + << Param("artist", song.artist()); + + std::sort(params.begin(), params.end()); + + QUrlQuery url_query; + for (const Param ¶m : params) { + url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second)); + } + + QUrl url(LastFMScrobbler::kApiUrl); + url.setQuery(url_query); + QNetworkRequest req(url); +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) + req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); +#else + req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); +#endif + req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + + QNetworkReply *reply = network_->get(req); + replies_ << reply; + connect(reply, &QNetworkReply::finished, [=] { RequestFinished(reply, id); }); + + qLog(Debug) << "Sending request" << url_query.toString(QUrl::FullyDecoded); + +} + +QByteArray LastFMArtistBio::GetReplyData(QNetworkReply *reply) { + + QByteArray data; + + if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200) { + data = reply->readAll(); + } + else { + if (reply->error() != QNetworkReply::NoError && reply->error() < 200) { + // This is a network error, there is nothing more to do. + Error(QString("%1 (%2)").arg(reply->errorString()).arg(reply->error())); + } + else { + QString error; + // See if there is Json data containing "error" and "message" - then use that instead. + data = reply->readAll(); + QJsonParseError json_error; + QJsonDocument json_doc = QJsonDocument::fromJson(data, &json_error); + int error_code = -1; + if (json_error.error == QJsonParseError::NoError && !json_doc.isEmpty() && json_doc.isObject()) { + QJsonObject json_obj = json_doc.object(); + if (json_obj.contains("error") && json_obj.contains("message")) { + error_code = json_obj["error"].toInt(); + QString error_message = json_obj["message"].toString(); + error = QString("%1 (%2)").arg(error_message).arg(error_code); + } + } + if (error.isEmpty()) { + if (reply->error() != QNetworkReply::NoError) { + error = QString("%1 (%2)").arg(reply->errorString()).arg(reply->error()); + } + else { + error = QString("Received HTTP code %1").arg(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()); + } + } + Error(error); + } + return QByteArray(); + } + + return data; + +} + +QJsonObject LastFMArtistBio::ExtractJsonObj(const QByteArray &data) { + + if (data.isEmpty()) return QJsonObject(); + + QJsonParseError error; + QJsonDocument json_doc = QJsonDocument::fromJson(data, &error); + + if (error.error != QJsonParseError::NoError) { + Error("Reply from server missing Json data.", data); + return QJsonObject(); + } + if (json_doc.isEmpty()) { + Error("Received empty Json document.", json_doc); + return QJsonObject(); + } + if (!json_doc.isObject()) { + Error("Json document is not an object.", json_doc); + return QJsonObject(); + } + QJsonObject json_obj = json_doc.object(); + if (json_obj.isEmpty()) { + Error("Received empty Json object.", json_doc); + return QJsonObject(); + } + + return json_obj; + +} + +void LastFMArtistBio::RequestFinished(QNetworkReply *reply, const int id) { + + if (!replies_.contains(reply)) return; + replies_.removeAll(reply); + disconnect(reply, nullptr, this, nullptr); + reply->deleteLater(); + + QJsonObject json_obj = ExtractJsonObj(GetReplyData(reply)); + + QString title; + QString text; + if (!json_obj.isEmpty() && json_obj.contains("artist") && json_obj["artist"].isObject()) { + json_obj = json_obj["artist"].toObject(); + if (json_obj.contains("bio") && json_obj["bio"].isObject()) { + title = json_obj["name"].toString(); + QJsonObject obj_bio = json_obj["bio"].toObject(); + if (obj_bio.contains("content")) { + text = obj_bio["content"].toString(); + } + } + } + + CollapsibleInfoPane::Data info_data; + info_data.id_ = title; + info_data.title_ = tr("Biography"); + info_data.type_ = CollapsibleInfoPane::Data::Type_Biography; + info_data.icon_ = IconLoader::Load("scrobble"); + InfoTextView *editor = new InfoTextView; + editor->SetHtml(text); + info_data.contents_ = editor; + emit InfoReady(id, info_data); + emit Finished(id); + +} + +void LastFMArtistBio::Error(const QString &error, const QVariant &debug) { + + qLog(Error) << error; + if (debug.isValid()) qLog(Debug) << debug; + +} diff --git a/src/artistbio/lastfmartistbio.h b/src/artistbio/lastfmartistbio.h new file mode 100644 index 00000000..d8867d22 --- /dev/null +++ b/src/artistbio/lastfmartistbio.h @@ -0,0 +1,66 @@ +/* + * Strawberry Music Player + * Copyright 2020, Jonas Kvinge + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef LASTFMARTISTBIO_H +#define LASTFMARTISTBIO_H + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "core/song.h" + +#include "artistbioprovider.h" + +class NetworkAccessManager; +class QNetworkReply; + +class LastFMArtistBio : public ArtistBioProvider { + Q_OBJECT + + public: + explicit LastFMArtistBio(); + ~LastFMArtistBio(); + + void Start(const int id, const Song &song) override; + + private: + typedef QPair Param; + typedef QList ParamList; + + QNetworkReply *CreateRequest(const ParamList &request_params); + QByteArray GetReplyData(QNetworkReply *reply); + QJsonObject ExtractJsonObj(const QByteArray &data); + void Error(const QString &error, const QVariant &debug = QVariant()); + + private slots: + void RequestFinished(QNetworkReply *reply, const int id); + + private: + NetworkAccessManager *network_; + QList replies_; + +}; + +#endif // LASTFMARTISTBIO_H diff --git a/src/artistbio/wikipediaartistbio.cpp b/src/artistbio/wikipediaartistbio.cpp new file mode 100644 index 00000000..78fe38f6 --- /dev/null +++ b/src/artistbio/wikipediaartistbio.cpp @@ -0,0 +1,316 @@ +/* + * Strawberry Music Player + * Copyright 2020, Jonas Kvinge + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/logging.h" +#include "core/networkaccessmanager.h" +#include "core/iconloader.h" +#include "core/latch.h" + +#include "widgets/infotextview.h" +#include "wikipediaartistbio.h" + +const char *WikipediaArtistBio::kApiUrl = "https://en.wikipedia.org/w/api.php"; +const int WikipediaArtistBio::kMinimumImageSize = 400; + +WikipediaArtistBio::WikipediaArtistBio() : ArtistBioProvider(), network_(new NetworkAccessManager(this)) {} + +WikipediaArtistBio::~WikipediaArtistBio() { + + while (!replies_.isEmpty()) { + QNetworkReply *reply = replies_.takeFirst(); + disconnect(reply, nullptr, this, nullptr); + if (reply->isRunning()) reply->abort(); + reply->deleteLater(); + } + +} + +QNetworkReply *WikipediaArtistBio::CreateRequest(QList ¶ms) { + + params << Param("format", "json"); + params << Param("action", "query"); + + QUrlQuery url_query; + for (const Param ¶m : params) { + url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second)); + } + + QUrl url(kApiUrl); + url.setQuery(url_query); + QNetworkRequest req(url); +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) + req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); +#else + req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); +#endif + req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + + QNetworkReply *reply = network_->get(req); + connect(reply, SIGNAL(sslErrors(QList)), this, SLOT(HandleSSLErrors(QList))); + replies_ << reply; + + return reply; + +} + +QByteArray WikipediaArtistBio::GetReplyData(QNetworkReply *reply) { + + QByteArray data; + + if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200) { + data = reply->readAll(); + } + else { + if (reply->error() == QNetworkReply::NoError) { + qLog(Error) << "Wikipedia artist biography error: Received HTTP code" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + } + else { + qLog(Error) << "Wikipedia artist biography error:" << reply->error() << reply->errorString(); + } + } + + return data; + +} + +QJsonObject WikipediaArtistBio::ExtractJsonObj(const QByteArray &data) { + + if (data.isEmpty()) return QJsonObject(); + + QJsonParseError json_error; + QJsonDocument json_doc = QJsonDocument::fromJson(data, &json_error); + + if (json_error.error != QJsonParseError::NoError) { + qLog(Error) << "Wikipedia artist biography error: Failed to parse json data:" << json_error.errorString(); + return QJsonObject(); + } + + if (json_doc.isEmpty()) { + qLog(Error) << "Wikipedia artist biography error: Received empty Json document."; + return QJsonObject(); + } + + if (!json_doc.isObject()) { + qLog(Error) << "Wikipedia artist biography error: Json document is not an object."; + return QJsonObject(); + } + + QJsonObject json_obj = json_doc.object(); + if (json_obj.isEmpty()) { + qLog(Error) << "Wikipedia artist biography error: Received empty Json object."; + return QJsonObject(); + } + + return json_obj; + +} + +void WikipediaArtistBio::HandleSSLErrors(QList) {} + +void WikipediaArtistBio::Start(const int id, const Song &metadata) { + + if (metadata.artist().isEmpty()) { + emit Finished(id); + return; + } + + CountdownLatch *latch = new CountdownLatch; + connect(latch, &CountdownLatch::Done, [this, id, latch](){ + latch->deleteLater(); + emit Finished(id); + }); + + GetImageTitles(id, metadata.artist(), latch); + //GetArticle(id, metadata.artist(), latch); + +} + +void WikipediaArtistBio::GetArticle(const int id, const QString &artist, CountdownLatch *latch) { + + latch->Wait(); + + ParamList params = ParamList() << Param("titles", artist) + << Param("prop", "extracts"); + + QNetworkReply *reply = CreateRequest(params); + connect(reply, &QNetworkReply::finished, [this, reply, id, latch]() { GetArticleReply(reply, id, latch); }); + +} + +void WikipediaArtistBio::GetArticleReply(QNetworkReply *reply, const int id, CountdownLatch *latch) { + + reply->deleteLater(); + replies_.removeAll(reply); + + QJsonObject json_obj = ExtractJsonObj(GetReplyData(reply)); + + QString title; + QString text; + if (!json_obj.isEmpty() && json_obj.contains("query") && json_obj["query"].isObject()) { + json_obj = json_obj["query"].toObject(); + if (json_obj.contains("pages") && json_obj["pages"].isObject()) { + QJsonObject value_pages = json_obj["pages"].toObject(); + for (const QJsonValue value_page : value_pages) { + if (!value_page.isObject()) continue; + QJsonObject obj_page = value_page.toObject(); + if (!obj_page.contains("title") || !obj_page.contains("extract")) continue; + title = obj_page["title"].toString(); + text = obj_page["extract"].toString(); + } + } + } + + CollapsibleInfoPane::Data info_data; + info_data.id_ = title; + info_data.title_ = tr("Biography"); + info_data.type_ = CollapsibleInfoPane::Data::Type_Biography; + info_data.icon_ = IconLoader::Load("wikipedia"); + InfoTextView *editor = new InfoTextView; + editor->SetHtml(text); + info_data.contents_ = editor; + emit InfoReady(id, info_data); + + latch->CountDown(); + +} + +void WikipediaArtistBio::GetImageTitles(const int id, const QString &artist, CountdownLatch *latch) { + + latch->Wait(); + + ParamList params = ParamList() << Param("titles", artist) + << Param("prop", "images") + << Param("imlimit", "25"); + + QNetworkReply *reply = CreateRequest(params); + connect(reply, &QNetworkReply::finished, [this, reply, id, latch]() { GetImageTitlesFinished(reply, id, latch); }); + +} + +void WikipediaArtistBio::GetImageTitlesFinished(QNetworkReply *reply, const int id, CountdownLatch *latch) { + + reply->deleteLater(); + replies_.removeAll(reply); + + QJsonObject json_obj = ExtractJsonObj(GetReplyData(reply)); + + QString title; + QStringList titles; + if (!json_obj.isEmpty() && json_obj.contains("query") && json_obj["query"].isObject()) { + json_obj = json_obj["query"].toObject(); + if (json_obj.contains("pages") && json_obj["pages"].isObject()) { + QJsonObject value_pages = json_obj["pages"].toObject(); + for (const QJsonValue value_page : value_pages) { + if (!value_page.isObject()) continue; + QJsonObject obj_page = value_page.toObject(); + if (!obj_page.contains("title") || !obj_page.contains("images") || !obj_page["images"].isArray()) continue; + title = obj_page["title"].toString(); + QJsonArray array_images = obj_page["images"].toArray(); + for (const QJsonValue value_image : array_images) { + if (!value_image.isObject()) continue; + QJsonObject obj_image = value_image.toObject(); + if (!obj_image.contains("title")) continue; + QString filename = obj_image["title"].toString(); + if (filename.endsWith(".jpg", Qt::CaseInsensitive) || filename.endsWith(".png", Qt::CaseInsensitive)) { + titles << filename; + } + } + } + } + } + + for (const QString &image_title : titles) { + GetImage(id, image_title, latch); + } + + latch->CountDown(); + +} + +void WikipediaArtistBio::GetImage(const int id, const QString &title, CountdownLatch *latch) { + + latch->Wait(); + + ParamList params2 = ParamList() << Param("titles", title) + << Param("prop", "imageinfo") + << Param("iiprop", "url|size"); + + QNetworkReply *reply = CreateRequest(params2); + connect(reply, &QNetworkReply::finished, [this, reply, id, latch]() { GetImageFinished(reply, id, latch); }); + +} + +void WikipediaArtistBio::GetImageFinished(QNetworkReply *reply, const int id, CountdownLatch *latch) { + + reply->deleteLater(); + replies_.removeAll(reply); + + QJsonObject json_obj = ExtractJsonObj(GetReplyData(reply)); + + if (!json_obj.isEmpty()) { + QList urls = ExtractImageUrls(json_obj); + for (const QUrl &url : urls) { + emit ImageReady(id, url); + } + } + + latch->CountDown(); + +} + +QList WikipediaArtistBio::ExtractImageUrls(QJsonObject json_obj) { + + QList urls; + if (json_obj.contains("query") && json_obj["query"].isObject()) { + json_obj = json_obj["query"].toObject(); + if (json_obj.contains("pages") && json_obj["pages"].isObject()) { + QJsonObject value_pages = json_obj["pages"].toObject(); + for (const QJsonValue value_page : value_pages) { + if (!value_page.isObject()) continue; + QJsonObject obj_page = value_page.toObject(); + if (!obj_page.contains("title") || !obj_page.contains("imageinfo") || !obj_page["imageinfo"].isArray()) continue; + QJsonArray array_images = obj_page["imageinfo"].toArray(); + for (const QJsonValue value_image : array_images) { + if (!value_image.isObject()) continue; + QJsonObject obj_image = value_image.toObject(); + if (!obj_image.contains("url") || !obj_image.contains("width") || !obj_image.contains("height")) continue; + QUrl url(obj_image["url"].toString()); + const int width = obj_image["width"].toInt(); + const int height = obj_image["height"].toInt(); + if (!url.isValid() || width < kMinimumImageSize || height < kMinimumImageSize) continue; + urls << url; + } + } + } + } + return urls; + +} diff --git a/src/artistbio/wikipediaartistbio.h b/src/artistbio/wikipediaartistbio.h new file mode 100644 index 00000000..e0f9b60b --- /dev/null +++ b/src/artistbio/wikipediaartistbio.h @@ -0,0 +1,72 @@ +/* + * Strawberry Music Player + * Copyright 2020, Jonas Kvinge + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef WIKIPEDIAARTISTBIO_H +#define WIKIPEDIAARTISTBIO_H + +#include +#include +#include +#include +#include +#include + +#include "artistbioprovider.h" + +class QNetworkReply; +class CountdownLatch; +class NetworkAccessManager; + +class WikipediaArtistBio : public ArtistBioProvider { + Q_OBJECT + + public: + explicit WikipediaArtistBio(); + ~WikipediaArtistBio(); + + void Start(const int id, const Song &song) override; + + private: + typedef QPair Param; + typedef QList ParamList; + + QNetworkReply *CreateRequest(QList ¶ms); + QByteArray GetReplyData(QNetworkReply *reply); + QJsonObject ExtractJsonObj(const QByteArray &data); + void GetArticle(const int id, const QString &artist, CountdownLatch* latch); + void GetImageTitles(const int id, const QString &artist, CountdownLatch* latch); + void GetImage(const int id, const QString &title, CountdownLatch *latch); + QList ExtractImageUrls(QJsonObject json_obj); + + private slots: + void HandleSSLErrors(QList ssl_errors); + void GetArticleReply(QNetworkReply *reply, const int id, CountdownLatch *latch); + void GetImageTitlesFinished(QNetworkReply *reply, const int id, CountdownLatch *latch); + void GetImageFinished(QNetworkReply *reply, const int id, CountdownLatch *latch); + + private: + static const char *kApiUrl; + static const int kMinimumImageSize; + + NetworkAccessManager *network_; + QList replies_; + +}; + +#endif // WIKIPEDIAARTISTBIO_H diff --git a/src/core/latch.cpp b/src/core/latch.cpp new file mode 100644 index 00000000..ac62762f --- /dev/null +++ b/src/core/latch.cpp @@ -0,0 +1,39 @@ +/* This file is part of Clementine. + Copyright 2016, John Maguire + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include + +#include "latch.h" + +CountdownLatch::CountdownLatch() : count_(0) {} + +void CountdownLatch::Wait() { + + QMutexLocker l(&mutex_); + ++count_; + +} + +void CountdownLatch::CountDown() { + + QMutexLocker l(&mutex_); + Q_ASSERT(count_ > 0); + --count_; + if (count_ == 0) { + emit Done(); + } + +} diff --git a/src/core/latch.h b/src/core/latch.h new file mode 100644 index 00000000..6e90df92 --- /dev/null +++ b/src/core/latch.h @@ -0,0 +1,39 @@ +/* This file is part of Clementine. + Copyright 2016, John Maguire + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef LATCH_H +#define LATCH_H + +#include +#include + +class CountdownLatch : public QObject { + Q_OBJECT + + public: + explicit CountdownLatch(); + void Wait(); + void CountDown(); + + signals: + void Done(); + + private: + QMutex mutex_; + int count_; +}; + +#endif // LATCH_H diff --git a/src/core/mainwindow.cpp b/src/core/mainwindow.cpp index 0195f2c0..893764d6 100644 --- a/src/core/mainwindow.cpp +++ b/src/core/mainwindow.cpp @@ -204,6 +204,8 @@ #include "smartplaylists/smartplaylistsviewcontainer.h" +#include "artistbio/artistbioview.h" + #ifdef Q_OS_WIN # include "windows7thumbbar.h" #endif @@ -218,6 +220,7 @@ using std::make_unique; using std::make_shared; + using namespace std::chrono_literals; const char *MainWindow::kSettingsGroup = "MainWindow"; @@ -308,6 +311,7 @@ MainWindow::MainWindow(Application *app, SharedPtr tray_icon, OS qobuz_view_(new InternetTabsView(app_, app->internet_services()->ServiceBySource(Song::Source::Qobuz), QobuzSettingsPage::kSettingsGroup, SettingsDialog::Page::Qobuz, this)), #endif radio_view_(new RadioViewContainer(this)), + artistbio_view_(new ArtistBioView(this)), lastfm_import_dialog_(new LastFMImportDialog(app_->lastfm_import(), this)), collection_show_all_(nullptr), collection_show_duplicates_(nullptr), @@ -389,6 +393,7 @@ MainWindow::MainWindow(Application *app, SharedPtr tray_icon, OS #ifdef HAVE_QOBUZ ui_->tabs->AddTab(qobuz_view_, "qobuz", IconLoader::Load("qobuz", true, 0, 32), tr("Qobuz")); #endif + ui_->tabs->AddTab(artistbio_view_, "artistbio", IconLoader::Load("guitar"), tr("Artist biography")); // Add the playing widget to the fancy tab widget ui_->tabs->addBottomWidget(ui_->widget_playing); @@ -907,6 +912,10 @@ MainWindow::MainWindow(Application *app, SharedPtr tray_icon, OS QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdateTotal, lastfm_import_dialog_, &LastFMImportDialog::UpdateTotal); QObject::connect(&*app_->lastfm_import(), &LastFMImport::UpdateProgress, lastfm_import_dialog_, &LastFMImportDialog::UpdateProgress); + connect(app_->playlist_manager(), SIGNAL(CurrentSongChanged(Song)), artistbio_view_, SLOT(SongChanged(Song))); + connect(app_->player(), SIGNAL(PlaylistFinished()), artistbio_view_, SLOT(SongFinished())); + connect(app_->player(), SIGNAL(Stopped()), artistbio_view_, SLOT(SongFinished())); + // Load settings qLog(Debug) << "Loading settings"; settings_.beginGroup(kSettingsGroup); @@ -1148,6 +1157,16 @@ void MainWindow::ReloadSettings() { album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings_.value("search_for_cover_auto", true).toBool()); + s.beginGroup(BehaviourSettingsPage::kSettingsGroup); + bool artistbio = s.value("artistbio", false).toBool(); + s.endGroup(); + if (artistbio) { + ui_->tabs->EnableTab(artistbio_view_); + } + else { + ui_->tabs->DisableTab(artistbio_view_); + } + #ifdef HAVE_SUBSONIC s.beginGroup(SubsonicSettingsPage::kSettingsGroup); bool enable_subsonic = s.value("enabled", false).toBool(); diff --git a/src/core/mainwindow.h b/src/core/mainwindow.h index 6053f92e..8823bb78 100644 --- a/src/core/mainwindow.h +++ b/src/core/mainwindow.h @@ -99,6 +99,7 @@ class Windows7ThumbBar; class AddStreamDialog; class LastFMImportDialog; class RadioViewContainer; +class ArtistBioView; class MainWindow : public QMainWindow, public PlatformInterface { Q_OBJECT @@ -343,6 +344,8 @@ class MainWindow : public QMainWindow, public PlatformInterface { RadioViewContainer *radio_view_; + ArtistBioView* artistbio_view_; + LastFMImportDialog *lastfm_import_dialog_; QAction *collection_show_all_; diff --git a/src/core/metatypes.cpp b/src/core/metatypes.cpp index a9be594c..93c02fcf 100644 --- a/src/core/metatypes.cpp +++ b/src/core/metatypes.cpp @@ -71,6 +71,7 @@ #include "smartplaylists/playlistgenerator_fwd.h" #include "radios/radiochannel.h" +#include "widgets/collapsibleinfopane.h" #ifdef HAVE_LIBMTP # include "device/mtpconnection.h" @@ -153,6 +154,8 @@ void RegisterMetaTypes() { qRegisterMetaType("RadioChannel"); qRegisterMetaType("RadioChannelList"); + qRegisterMetaType("CollapsibleInfoPane::Data"); + #ifdef HAVE_LIBMTP qRegisterMetaType("MtpConnection*"); #endif diff --git a/src/settings/behavioursettingspage.cpp b/src/settings/behavioursettingspage.cpp index bbf5fd92..99369af5 100644 --- a/src/settings/behavioursettingspage.cpp +++ b/src/settings/behavioursettingspage.cpp @@ -160,6 +160,7 @@ void BehaviourSettingsPage::Load() { ui_->checkbox_resumeplayback->setChecked(s.value("resumeplayback", false).toBool()); ui_->checkbox_playingwidget->setChecked(s.value("playing_widget", true).toBool()); + ui_->checkbox_artistbio->setChecked(s.value("artistbio", false).toBool()); #ifndef Q_OS_MACOS const StartupBehaviour startup_behaviour = static_cast(s.value("startupbehaviour", static_cast(StartupBehaviour::Remember)).toInt()); @@ -224,6 +225,7 @@ void BehaviourSettingsPage::Save() { s.setValue("trayicon_progress", ui_->checkbox_trayicon_progress->isChecked()); s.setValue("resumeplayback", ui_->checkbox_resumeplayback->isChecked()); s.setValue("playing_widget", ui_->checkbox_playingwidget->isChecked()); + s.setValue("artistbio", ui_->checkbox_artistbio->isChecked()); StartupBehaviour startup_behaviour = StartupBehaviour::Remember; if (ui_->radiobutton_remember->isChecked()) startup_behaviour = StartupBehaviour::Remember; diff --git a/src/settings/behavioursettingspage.ui b/src/settings/behavioursettingspage.ui index 480af77e..2a1aeda2 100644 --- a/src/settings/behavioursettingspage.ui +++ b/src/settings/behavioursettingspage.ui @@ -58,6 +58,13 @@ + + + + Artist biography + + + diff --git a/src/widgets/collapsibleinfoheader.cpp b/src/widgets/collapsibleinfoheader.cpp new file mode 100644 index 00000000..f141d244 --- /dev/null +++ b/src/widgets/collapsibleinfoheader.cpp @@ -0,0 +1,174 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "collapsibleinfoheader.h" + +const int CollapsibleInfoHeader::kHeight = 20; +const int CollapsibleInfoHeader::kIconSize = 16; + +CollapsibleInfoHeader::CollapsibleInfoHeader(QWidget* parent) + : QWidget(parent), + expanded_(false), + hovering_(false), + animation_(new QPropertyAnimation(this, "opacity", this)), + opacity_(0.0) { + + setMinimumHeight(kHeight); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + setCursor(QCursor(Qt::PointingHandCursor)); + +} + +void CollapsibleInfoHeader::SetTitle(const QString &title) { + title_ = title; + update(); +} + +void CollapsibleInfoHeader::SetIcon(const QIcon &icon) { + icon_ = icon; + update(); +} + +void CollapsibleInfoHeader::SetExpanded(const bool expanded) { + + expanded_ = expanded; + + emit ExpandedToggled(expanded); + if (expanded) + emit Expanded(); + else + emit Collapsed(); +} + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +void CollapsibleInfoHeader::enterEvent(QEnterEvent*) { +#else +void CollapsibleInfoHeader::enterEvent(QEvent*) { +#endif + + hovering_ = true; + if (!expanded_) { + animation_->stop(); + animation_->setEndValue(1.0); + animation_->setDuration(80); + animation_->start(); + } + +} + +void CollapsibleInfoHeader::leaveEvent(QEvent*) { + + hovering_ = false; + if (!expanded_) { + animation_->stop(); + animation_->setEndValue(0.0); + animation_->setDuration(160); + animation_->start(); + } + +} + +void CollapsibleInfoHeader::set_opacity(const float opacity) { + opacity_ = opacity; + update(); +} + +void CollapsibleInfoHeader::paintEvent(QPaintEvent*) { + + QPainter p(this); + + QColor active_text_color(palette().color(QPalette::Active, QPalette::HighlightedText)); + QColor inactive_text_color(palette().color(QPalette::Active, QPalette::Text)); + QColor text_color; + if (expanded_) { + text_color = active_text_color; + } + else { + p.setOpacity(0.4 + opacity_ * 0.6); + text_color = QColor(active_text_color.red() * opacity_ + inactive_text_color.red() * (1.0 - opacity_), active_text_color.green() * opacity_ + inactive_text_color.green() * (1.0 - opacity_), active_text_color.blue() * opacity_ + inactive_text_color.blue() * (1.0 - opacity_)); + } + + QRect indicator_rect(0, 0, height(), height()); + QRect icon_rect(height() + 2, (kHeight - kIconSize) / 2, kIconSize, kIconSize); + QRect text_rect(rect()); + text_rect.setLeft(icon_rect.right() + 4); + + // Draw the background + QColor highlight(palette().color(QPalette::Active, QPalette::Highlight)); + const QColor bg_color_1(highlight.lighter(120)); + const QColor bg_color_2(highlight.darker(120)); + const QColor bg_border(palette().color(QPalette::Dark)); + QLinearGradient bg_brush(rect().topLeft(), rect().bottomLeft()); + bg_brush.setColorAt(0.0, bg_color_1); + bg_brush.setColorAt(0.5, bg_color_1); + bg_brush.setColorAt(0.5, bg_color_2); + bg_brush.setColorAt(1.0, bg_color_2); + + p.setPen(Qt::NoPen); + p.fillRect(rect(), bg_brush); + + p.setPen(bg_border); + p.drawLine(rect().topLeft(), rect().topRight()); + p.drawLine(rect().bottomLeft(), rect().bottomRight()); + + // Draw the expand/collapse indicator + QStyleOption opt; + opt.initFrom(this); + opt.rect = indicator_rect; + opt.state |= QStyle::State_Children; + if (expanded_) opt.state |= QStyle::State_Open; + if (hovering_) opt.state |= QStyle::State_Active; + + // Have to use the application's style here because using the widget's style + // 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); + p.setFont(bold_font); + + p.setPen(text_color); + p.drawText(text_rect, Qt::AlignLeft | Qt::AlignVCenter, title_); + +} + +void CollapsibleInfoHeader::mouseReleaseEvent(QMouseEvent*) { + SetExpanded(!expanded_); +} diff --git a/src/widgets/collapsibleinfoheader.h b/src/widgets/collapsibleinfoheader.h new file mode 100644 index 00000000..e421f149 --- /dev/null +++ b/src/widgets/collapsibleinfoheader.h @@ -0,0 +1,82 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef COLLAPSIBLEINFOHEADER_H +#define COLLAPSIBLEINFOHEADER_H + +#include +#include +#include + +class QPropertyAnimation; +class QEnterEvent; +class QEvent; +class QPaintEvent; +class QMouseEvent; + +class CollapsibleInfoHeader : public QWidget { + Q_OBJECT + Q_PROPERTY(float opacity READ opacity WRITE set_opacity) + + public: + CollapsibleInfoHeader(QWidget *parent = nullptr); + + 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_; } + + float opacity() const { return opacity_; } + void set_opacity(const float opacity); + + public slots: + void SetExpanded(const bool expanded); + void SetTitle(const QString &title); + void SetIcon(const QIcon &icon); + + signals: + void Expanded(); + void Collapsed(); + void ExpandedToggled(const bool expanded); + + protected: +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + void enterEvent(QEnterEvent*) override; +#else + void enterEvent(QEvent*) override; +#endif + void leaveEvent(QEvent*) override; + void paintEvent(QPaintEvent*) override; + void mouseReleaseEvent(QMouseEvent*) override; + + private: + bool expanded_; + bool hovering_; + QString title_; + QIcon icon_; + + QPropertyAnimation *animation_; + float opacity_; +}; + +#endif // COLLAPSIBLEINFOHEADER_H diff --git a/src/widgets/collapsibleinfopane.cpp b/src/widgets/collapsibleinfopane.cpp new file mode 100644 index 00000000..8fce0fbb --- /dev/null +++ b/src/widgets/collapsibleinfopane.cpp @@ -0,0 +1,64 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include "collapsibleinfoheader.h" +#include "collapsibleinfopane.h" + +#include + +CollapsibleInfoPane::CollapsibleInfoPane(const Data &data, QWidget *parent) + : QWidget(parent), data_(data), header_(new CollapsibleInfoHeader(this)) { + + QVBoxLayout* layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(3); + layout->setSizeConstraint(QLayout::SetMinAndMaxSize); + setLayout(layout); + + layout->addWidget(header_); + layout->addWidget(data.contents_); + data.contents_->hide(); + + header_->SetTitle(data.title_); + header_->SetIcon(data.icon_); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + + connect(header_, SIGNAL(ExpandedToggled(bool)), SLOT(ExpandedToggled(bool))); + connect(header_, SIGNAL(ExpandedToggled(bool)), SIGNAL(Toggled(bool))); + +} + +void CollapsibleInfoPane::Collapse() { header_->SetExpanded(false); } + +void CollapsibleInfoPane::Expand() { header_->SetExpanded(true); } + +void CollapsibleInfoPane::ExpandedToggled(bool expanded) { + data_.contents_->setVisible(expanded); +} + +bool CollapsibleInfoPane::Data::operator<(const CollapsibleInfoPane::Data &other) const { + + const int my_score = (TypeCount - type_) * 1000 + relevance_; + const int other_score = (TypeCount - other.type_) * 1000 + other.relevance_; + + return my_score > other_score; + +} diff --git a/src/widgets/collapsibleinfopane.h b/src/widgets/collapsibleinfopane.h new file mode 100644 index 00000000..a5e8e1ab --- /dev/null +++ b/src/widgets/collapsibleinfopane.h @@ -0,0 +1,72 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef COLLAPSIBLEINFOPANE_H +#define COLLAPSIBLEINFOPANE_H + +#include +#include + +class CollapsibleInfoHeader; + +class CollapsibleInfoPane : public QWidget { + Q_OBJECT + + public: + struct Data { + explicit Data() : type_(Type_Biography), relevance_(0) {} + + bool operator<(const Data& other) const; + + enum Type { + Type_Biography, + TypeCount + }; + + QString id_; + QString title_; + QIcon icon_; + Type type_; + int relevance_; + + QWidget *contents_; + QObject *content_object_; + }; + + CollapsibleInfoPane(const Data &data, QWidget* parent = nullptr); + + const Data &data() const { return data_; } + + public slots: + void Expand(); + void Collapse(); + + signals: + void Toggled(const bool expanded); + + private slots: + void ExpandedToggled(const bool expanded); + + private: + Data data_; + CollapsibleInfoHeader *header_; +}; + +#endif // COLLAPSIBLEINFOPANE_H diff --git a/src/widgets/infotextview.cpp b/src/widgets/infotextview.cpp new file mode 100644 index 00000000..d75d5d0b --- /dev/null +++ b/src/widgets/infotextview.cpp @@ -0,0 +1,89 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include + +#include "core/logging.h" +#include "infotextview.h" + +InfoTextView::InfoTextView(QWidget *parent) : QTextBrowser(parent), last_width_(-1), recursion_filter_(false) { + + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setOpenExternalLinks(true); + +} + +void InfoTextView::resizeEvent(QResizeEvent *e) { + + const int w = qMax(100, width()); + if (w == last_width_) return; + last_width_ = w; + + document()->setTextWidth(w); + setMinimumHeight(document()->size().height()); + + QTextBrowser::resizeEvent(e); + +} + +QSize InfoTextView::sizeHint() const { return minimumSize(); } + +void InfoTextView::wheelEvent(QWheelEvent *e) { e->ignore(); } + +void InfoTextView::SetHtml(const QString &html) { + + QString copy(html.trimmed()); + + // Simplify newlines + copy.replace(QRegularExpression("\\r\\n?"), "\n"); + + // Convert two or more newlines to

, convert single newlines to
+ copy.replace(QRegularExpression("([^>])([\\t ]*\\n){2,}"), "\\1

"); + copy.replace(QRegularExpression("([^>])[\\t ]*\\n"), "\\1
"); + + // Strip any newlines from the end + copy.replace(QRegularExpression("((<\\s*br\\s*/?\\s*>)|(<\\s*/?\\s*p\\s*/?\\s*>))+$"), ""); + + setHtml(copy); + +} + +// Prevents QTextDocument from trying to load remote images before they are ready. +QVariant InfoTextView::loadResource(int type, const QUrl &name) { + + if (recursion_filter_) { + recursion_filter_ = false; + return QVariant(); + } + recursion_filter_ = true; + if (type == QTextDocument::ImageResource && name.scheme() == "http") { + if (document()->resource(type, name).isNull()) { + return QVariant(); + } + } + return QTextBrowser::loadResource(type, name); + +} diff --git a/src/widgets/infotextview.h b/src/widgets/infotextview.h new file mode 100644 index 00000000..da91543d --- /dev/null +++ b/src/widgets/infotextview.h @@ -0,0 +1,52 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef INFOTEXTVIEW_H +#define INFOTEXTVIEW_H + +#include +#include +#include + +class QResizeEvent; +class QWheelEvent; + +class InfoTextView : public QTextBrowser { + Q_OBJECT + + public: + explicit InfoTextView(QWidget *parent = nullptr); + + QSize sizeHint() const override; + + public slots: + void SetHtml(const QString &html); + + protected: + void resizeEvent(QResizeEvent *e) override; + void wheelEvent(QWheelEvent *e) override; + QVariant loadResource(int type, const QUrl &name) override; + + private: + int last_width_; + bool recursion_filter_; +}; + +#endif // INFOTEXTVIEW_H diff --git a/src/widgets/prettyimage.cpp b/src/widgets/prettyimage.cpp new file mode 100644 index 00000000..24edc47f --- /dev/null +++ b/src/widgets/prettyimage.cpp @@ -0,0 +1,257 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/logging.h" +#include "core/networkaccessmanager.h" +#include "core/iconloader.h" + +#include "prettyimage.h" + +const int PrettyImage::kTotalHeight = 200; +const int PrettyImage::kReflectionHeight = 40; +const int PrettyImage::kImageHeight = PrettyImage::kTotalHeight - PrettyImage::kReflectionHeight; + +const int PrettyImage::kMaxImageWidth = 300; + +const char *PrettyImage::kSettingsGroup = "PrettyImageView"; + +PrettyImage::PrettyImage(const QUrl &url, QNetworkAccessManager *network, QWidget *parent) + : QWidget(parent), + network_(network), + state_(State_WaitingForLazyLoad), + url_(url), + menu_(nullptr) { + + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + LazyLoad(); + +} + +void PrettyImage::LazyLoad() { + + if (state_ != State_WaitingForLazyLoad) return; + + // Start fetching the image + QNetworkReply *reply = network_->get(QNetworkRequest(url_)); + state_ = State_Fetching; + QObject::connect(reply, &QNetworkReply::finished, this, [this, reply]() { ImageFetched(reply); }); + +} + +QSize PrettyImage::image_size() const { + + if (state_ != State_Finished) return QSize(kImageHeight * 1.6, kImageHeight); + + QSize ret = image_.size(); + ret.scale(kMaxImageWidth, kImageHeight, Qt::KeepAspectRatio); + return ret; + +} + +QSize PrettyImage::sizeHint() const { + return QSize(image_size().width(), kTotalHeight); +} + +void PrettyImage::ImageFetched(QNetworkReply *reply) { + + reply->deleteLater(); + + QImage image = QImage::fromData(reply->readAll()); + if (image.isNull()) { + qLog(Debug) << "Image failed to load" << reply->request().url() << reply->error(); + deleteLater(); + } + else { + state_ = State_CreatingThumbnail; + image_ = image; + (void)QtConcurrent::run([=]{ ImageScaled(image_.scaled(image_size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); }); + } + +} + +void PrettyImage::ImageScaled(QImage image) { + + thumbnail_ = QPixmap::fromImage(image); + state_ = State_Finished; + + updateGeometry(); + update(); + emit Loaded(); + +} + +void PrettyImage::paintEvent(QPaintEvent*) { + + // Draw at the bottom of our area + QRect image_rect(QPoint(0, 0), image_size()); + image_rect.moveBottom(kImageHeight); + + QPainter p(this); + + // Draw the main image + DrawThumbnail(&p, image_rect); + + // Draw the reflection + // Figure out where to draw it + QRect reflection_rect(image_rect); + reflection_rect.moveTop(image_rect.bottom()); + + // Create the reflected pixmap + QImage reflection(reflection_rect.size(), QImage::Format_ARGB32_Premultiplied); + reflection.fill(palette().color(QPalette::Base).rgba()); + QPainter reflection_painter(&reflection); + + // Set up the transformation + QTransform transform; + transform.scale(1.0, -1.0); + transform.translate(0.0, -reflection_rect.height()); + reflection_painter.setTransform(transform); + + QRect fade_rect(reflection.rect().bottomLeft() - QPoint(0, kReflectionHeight), reflection.rect().bottomRight()); + + // Draw the reflection into the buffer + DrawThumbnail(&reflection_painter, reflection.rect()); + + // Make it fade out towards the bottom + QLinearGradient fade_gradient(fade_rect.topLeft(), fade_rect.bottomLeft()); + fade_gradient.setColorAt(0.0, QColor(0, 0, 0, 0)); + fade_gradient.setColorAt(1.0, QColor(0, 0, 0, 128)); + + reflection_painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); + reflection_painter.fillRect(fade_rect, fade_gradient); + + reflection_painter.end(); + + // Draw the reflection on the image + p.drawImage(reflection_rect, reflection); + +} + +void PrettyImage::DrawThumbnail(QPainter *p, const QRect &rect) { + + switch (state_) { + case State_WaitingForLazyLoad: + case State_Fetching: + case State_CreatingThumbnail: + p->setPen(palette().color(QPalette::Disabled, QPalette::Text)); + p->drawText(rect, Qt::AlignHCenter | Qt::AlignBottom, tr("Loading...")); + break; + + case State_Finished: + p->drawPixmap(rect, thumbnail_); + break; + } + +} + +void PrettyImage::contextMenuEvent(QContextMenuEvent *e) { + + if (e->pos().y() >= kImageHeight) return; + + if (!menu_) { + menu_ = new QMenu(this); + menu_->addAction(IconLoader::Load("zoom-in"), tr("Show fullsize..."), this, SLOT(ShowFullsize())); + menu_->addAction(IconLoader::Load("document-save"), tr("Save image") + "...", this, SLOT(SaveAs())); + } + + menu_->popup(e->globalPos()); + +} + +void PrettyImage::ShowFullsize() { + + // Create the window + QScrollArea *pwindow = new QScrollArea; + pwindow->setAttribute(Qt::WA_DeleteOnClose, true); + pwindow->setWindowTitle(tr("%1 image viewer").arg("Strawberry")); + + // Work out how large to make the window, based on the size of the screen +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + QScreen *screen = QWidget::screen(); +#else + QScreen *screen = (window() && window()->windowHandle() ? window()->windowHandle()->screen() : QGuiApplication::primaryScreen()); +#endif + if (screen) { + QRect desktop_rect(screen->availableGeometry()); + QSize window_size(qMin(desktop_rect.width() - 20, image_.width()), qMin(desktop_rect.height() - 20, image_.height())); + pwindow->resize(window_size); + } + + // Create the label that displays the image + QLabel *label = new QLabel(pwindow); + label->setPixmap(QPixmap::fromImage(image_)); + + // Show the label in the window + pwindow->setWidget(label); + pwindow->setFrameShape(QFrame::NoFrame); + pwindow->show(); + +} + +void PrettyImage::SaveAs() { + + QString filename = QFileInfo(url_.path()).fileName(); + + if (filename.isEmpty()) filename = "artwork.jpg"; + + QSettings s; + s.beginGroup(kSettingsGroup); + QString last_save_dir = s.value("last_save_dir", QDir::homePath()).toString(); + + QString path = last_save_dir.isEmpty() ? QDir::homePath() : last_save_dir; + QFileInfo path_info(path); + if (path_info.isDir()) { + path += "/" + filename; + } + else { + path = path_info.path() + "/" + filename; + } + + filename = QFileDialog::getSaveFileName(this, tr("Save image"), path); + if (filename.isEmpty()) return; + + image_.save(filename); + + s.setValue("last_save_dir", last_save_dir); + + s.endGroup(); + +} diff --git a/src/widgets/prettyimage.h b/src/widgets/prettyimage.h new file mode 100644 index 00000000..ee0f4d06 --- /dev/null +++ b/src/widgets/prettyimage.h @@ -0,0 +1,92 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef PRETTYIMAGE_H +#define PRETTYIMAGE_H + +#include +#include +#include +#include +#include +#include + +class QMenu; +class QNetworkAccessManager; +class QNetworkReply; +class QContextMenuEvent; +class QPaintEvent; + +class PrettyImage : public QWidget { + Q_OBJECT + + public: + PrettyImage(const QUrl &url, QNetworkAccessManager *network, QWidget *parent = nullptr); + + static const int kTotalHeight; + static const int kReflectionHeight; + static const int kImageHeight; + + static const int kMaxImageWidth; + + static const char *kSettingsGroup; + + QSize sizeHint() const override; + QSize image_size() const; + +signals: + void Loaded(); + + public slots: + void LazyLoad(); + void SaveAs(); + void ShowFullsize(); + + protected: + void contextMenuEvent(QContextMenuEvent*) override; + void paintEvent(QPaintEvent*) override; + + private slots: + void ImageFetched(QNetworkReply *reply); + void ImageScaled(QImage image); + + private: + enum State { + State_WaitingForLazyLoad, + State_Fetching, + State_CreatingThumbnail, + State_Finished, + }; + + void DrawThumbnail(QPainter *p, const QRect &rect); + + private: + QNetworkAccessManager *network_; + State state_; + QUrl url_; + + QImage image_; + QPixmap thumbnail_; + + QMenu *menu_; + QString last_save_dir_; +}; + +#endif // PRETTYIMAGE_H diff --git a/src/widgets/prettyimageview.cpp b/src/widgets/prettyimageview.cpp new file mode 100644 index 00000000..e59e2139 --- /dev/null +++ b/src/widgets/prettyimageview.cpp @@ -0,0 +1,189 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core/networkaccessmanager.h" + +#include "prettyimage.h" +#include "prettyimageview.h" + +PrettyImageView::PrettyImageView(QNetworkAccessManager *network, QWidget* parent) + : QScrollArea(parent), + network_(network), + container_(new QWidget(this)), + layout_(new QHBoxLayout(container_)), + current_index_(-1), + scroll_animation_(new QPropertyAnimation(horizontalScrollBar(), "value", this)), + recursion_filter_(false) { + + setWidget(container_); + setWidgetResizable(true); + setMinimumHeight(PrettyImage::kTotalHeight + 10); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + setFrameShape(QFrame::NoFrame); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + scroll_animation_->setDuration(250); + scroll_animation_->setEasingCurve(QEasingCurve::InOutCubic); + connect(horizontalScrollBar(), SIGNAL(sliderReleased()), SLOT(ScrollBarReleased())); + connect(horizontalScrollBar(), SIGNAL(actionTriggered(int)), SLOT(ScrollBarAction(int))); + + layout_->setSizeConstraint(QLayout::SetMinAndMaxSize); + layout_->setContentsMargins(6, 6, 6, 6); + layout_->setSpacing(6); + layout_->addSpacing(200); + layout_->addSpacing(200); + + container_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + +} + +bool PrettyImageView::eventFilter(QObject *obj, QEvent *event) { + + // Work around infinite recursion in QScrollArea resizes. + if (recursion_filter_) { + return false; + } + recursion_filter_ = true; + bool ret = QScrollArea::eventFilter(obj, event); + recursion_filter_ = false; + return ret; + +} + +void PrettyImageView::AddImage(const QUrl &url) { + + PrettyImage *image = new PrettyImage(url, network_, container_); + connect(image, SIGNAL(destroyed()), SLOT(ScrollToCurrent())); + connect(image, SIGNAL(Loaded()), SLOT(ScrollToCurrent())); + + layout_->insertWidget(layout_->count() - 1, image); + if (current_index_ == -1) ScrollTo(0); + +} + +void PrettyImageView::mouseReleaseEvent(QMouseEvent *e) { + + // Find the image that was clicked on + QWidget *widget = container_->childAt(container_->mapFrom(this, e->pos())); + if (!widget) return; + + // Get the index of that image + const int index = layout_->indexOf(widget) - 1; + if (index == -1) return; + + if (index == current_index_) { + // Show the image fullsize + PrettyImage* pretty_image = qobject_cast(widget); + if (pretty_image) { + pretty_image->ShowFullsize(); + } + } + else { + // Scroll to the image + ScrollTo(index); + } + +} + +void PrettyImageView::ScrollTo(const int index, const bool smooth) { + + current_index_ = qBound(0, index, layout_->count() - 3); + const int layout_index = current_index_ + 1; + + const QWidget *target_widget = layout_->itemAt(layout_index)->widget(); + if (!target_widget) return; + + const int current_x = horizontalScrollBar()->value(); + const int target_x = target_widget->geometry().center().x() - width() / 2; + + if (current_x == target_x) return; + + if (smooth) { + scroll_animation_->setStartValue(current_x); + scroll_animation_->setEndValue(target_x); + scroll_animation_->start(); + } + else { + scroll_animation_->stop(); + horizontalScrollBar()->setValue(target_x); + } + +} + +void PrettyImageView::ScrollToCurrent() { ScrollTo(current_index_); } + +void PrettyImageView::ScrollBarReleased() { + + // Find the nearest widget to where the scroll bar was released + const int current_x = horizontalScrollBar()->value() + width() / 2; + int layout_index = 1; + for (; layout_index < layout_->count() - 1; ++layout_index) { + const QWidget *widget = layout_->itemAt(layout_index)->widget(); + if (widget && widget->geometry().right() > current_x) { + break; + } + } + + ScrollTo(layout_index - 1); + +} + +void PrettyImageView::ScrollBarAction(const int action) { + + switch (action) { + case QAbstractSlider::SliderSingleStepAdd: + case QAbstractSlider::SliderPageStepAdd: + ScrollTo(current_index_ + 1); + break; + + case QAbstractSlider::SliderSingleStepSub: + case QAbstractSlider::SliderPageStepSub: + ScrollTo(current_index_ - 1); + break; + } + +} + +void PrettyImageView::resizeEvent(QResizeEvent *e) { + + QScrollArea::resizeEvent(e); + ScrollTo(current_index_, false); + +} + +void PrettyImageView::wheelEvent(QWheelEvent *e) { + + const int d = e->angleDelta().x() > 0 ? -1 : 1; + ScrollTo(current_index_ + d, true); + +} diff --git a/src/widgets/prettyimageview.h b/src/widgets/prettyimageview.h new file mode 100644 index 00000000..77e702b2 --- /dev/null +++ b/src/widgets/prettyimageview.h @@ -0,0 +1,74 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef PRETTYIMAGEVIEW_H +#define PRETTYIMAGEVIEW_H + +#include +#include +#include + +class QNetworkAccessManager; +class QNetworkReply; +class QMenu; +class QHBoxLayout; +class QPropertyAnimation; +class QTimeLine; +class QMouseEvent; +class QResizeEvent; +class QWheelEvent; + +class PrettyImageView : public QScrollArea { + Q_OBJECT + + public: + PrettyImageView(QNetworkAccessManager *network, QWidget *parent = nullptr); + + static const char* kSettingsGroup; + + public slots: + void AddImage(const QUrl& url); + + protected: + void mouseReleaseEvent(QMouseEvent*) override; + void resizeEvent(QResizeEvent *e) override; + void wheelEvent(QWheelEvent *e) override; + + private slots: + void ScrollBarReleased(); + void ScrollBarAction(const int action); + void ScrollTo(const int index, const bool smooth = true); + void ScrollToCurrent(); + + private: + bool eventFilter(QObject*, QEvent*) override; + + QNetworkAccessManager *network_; + + QWidget *container_; + QHBoxLayout *layout_; + + int current_index_; + QPropertyAnimation *scroll_animation_; + + bool recursion_filter_; +}; + +#endif // PRETTYIMAGEVIEW_H diff --git a/src/widgets/widgetfadehelper.cpp b/src/widgets/widgetfadehelper.cpp new file mode 100644 index 00000000..612a3bd7 --- /dev/null +++ b/src/widgets/widgetfadehelper.cpp @@ -0,0 +1,185 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "widgetfadehelper.h" +#include "core/qt_blurimage.h" + +const int WidgetFadeHelper::kLoadingPadding = 9; +const int WidgetFadeHelper::kLoadingBorderRadius = 10; + +WidgetFadeHelper::WidgetFadeHelper(QWidget *parent, const int msec) + : QWidget(parent), + parent_(parent), + blur_timeline_(new QTimeLine(msec, this)), + fade_timeline_(new QTimeLine(msec, this)) { + + parent->installEventFilter(this); + + connect(blur_timeline_, SIGNAL(valueChanged(qreal)), SLOT(update())); + connect(fade_timeline_, SIGNAL(valueChanged(qreal)), SLOT(update())); + connect(fade_timeline_, SIGNAL(finished()), SLOT(FadeFinished())); + + hide(); + +} + +bool WidgetFadeHelper::eventFilter(QObject *obj, QEvent *event) { + + // We're only interested in our parent's resize events + if (obj != parent_ || event->type() != QEvent::Resize) return false; + + // Don't care if we're hidden + if (!isVisible()) return false; + + QResizeEvent *re = static_cast(event); + if (re->oldSize() == re->size()) { + // Ignore phoney resize events + return false; + } + + // Get a new capture of the parent + hide(); + CaptureParent(); + show(); + return false; + +} + +void WidgetFadeHelper::StartBlur() { + + CaptureParent(); + + // Cover the parent + raise(); + show(); + + // Start the timeline + blur_timeline_->stop(); + blur_timeline_->start(); + + setAttribute(Qt::WA_TransparentForMouseEvents, false); + +} + +void WidgetFadeHelper::CaptureParent() { + + // Take a "screenshot" of the window + original_pixmap_ = parent_->grab(); + QImage original_image = original_pixmap_.toImage(); + + // Blur it + QImage blurred(original_image.size(), QImage::Format_ARGB32_Premultiplied); + blurred.fill(Qt::transparent); + + QPainter blur_painter(&blurred); + blur_painter.save(); + qt_blurImage(&blur_painter, original_image, 10.0, true, false); + blur_painter.restore(); + + // Draw some loading text over the top + QFont loading_font(font()); + loading_font.setBold(true); + QFontMetrics loading_font_metrics(loading_font); + + const QString loading_text = tr("Loading..."); +#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) + const QSize loading_size(kLoadingPadding * 2 + loading_font_metrics.horizontalAdvance(loading_text), kLoadingPadding * 2 + loading_font_metrics.height()); +#else + const QSize loading_size(kLoadingPadding * 2 + loading_font_metrics.width(loading_text), kLoadingPadding * 2 + loading_font_metrics.height()); +#endif + const QRect loading_rect((blurred.width() - loading_size.width()) / 2, 100, loading_size.width(), loading_size.height()); + + blur_painter.setRenderHint(QPainter::Antialiasing); + + blur_painter.translate(0.5, 0.5); + blur_painter.setPen(QColor(200, 200, 200, 255)); + blur_painter.setBrush(QColor(200, 200, 200, 192)); + blur_painter.drawRoundedRect(loading_rect, kLoadingBorderRadius, kLoadingBorderRadius); + + blur_painter.setPen(palette().brush(QPalette::Text).color()); + blur_painter.setFont(loading_font); + blur_painter.drawText(loading_rect.translated(-1, -1), Qt::AlignCenter, loading_text); + blur_painter.translate(-0.5, -0.5); + + blur_painter.end(); + + blurred_pixmap_ = QPixmap::fromImage(blurred); + + resize(parent_->size()); + +} + +void WidgetFadeHelper::StartFade() { + + if (blur_timeline_->state() == QTimeLine::Running) { + // Blur timeline is still running, so we need render the current state + // into a new pixmap. + QPixmap pixmap(original_pixmap_); + QPainter painter(&pixmap); + painter.setOpacity(blur_timeline_->currentValue()); + painter.drawPixmap(0, 0, blurred_pixmap_); + painter.end(); + blurred_pixmap_ = pixmap; + } + blur_timeline_->stop(); + original_pixmap_ = QPixmap(); + + // Start the timeline + fade_timeline_->stop(); + fade_timeline_->start(); + + setAttribute(Qt::WA_TransparentForMouseEvents, true); + +} + +void WidgetFadeHelper::paintEvent(QPaintEvent*) { + + QPainter p(this); + + if (fade_timeline_->state() != QTimeLine::Running) { + // We're fading in the blur + p.drawPixmap(0, 0, original_pixmap_); + p.setOpacity(blur_timeline_->currentValue()); + } + else { + // Fading out the blur into the new image + p.setOpacity(1.0 - fade_timeline_->currentValue()); + } + + p.drawPixmap(0, 0, blurred_pixmap_); + +} + +void WidgetFadeHelper::FadeFinished() { + + hide(); + original_pixmap_ = QPixmap(); + blurred_pixmap_ = QPixmap(); + +} diff --git a/src/widgets/widgetfadehelper.h b/src/widgets/widgetfadehelper.h new file mode 100644 index 00000000..879ced40 --- /dev/null +++ b/src/widgets/widgetfadehelper.h @@ -0,0 +1,63 @@ +/* + * Strawberry Music Player + * This file was part of Clementine. + * Copyright 2010, David Sansome + * + * Strawberry 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. + * + * Strawberry 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 Strawberry. If not, see . + * + */ + +#ifndef WIDGETFADEHELPER_H +#define WIDGETFADEHELPER_H + +#include +#include + +class QTimeLine; +class QPaintEvent; +class QEvent; + +class WidgetFadeHelper : public QWidget { + Q_OBJECT + + public: + WidgetFadeHelper(QWidget *parent, const int msec = 500); + + public slots: + void StartBlur(); + void StartFade(); + + protected: + void paintEvent(QPaintEvent*) override; + bool eventFilter(QObject *obj, QEvent *event) override; + + private slots: + void FadeFinished(); + + private: + void CaptureParent(); + + private: + static const int kLoadingPadding; + static const int kLoadingBorderRadius; + + QWidget* parent_; + QTimeLine* blur_timeline_; + QTimeLine* fade_timeline_; + + QPixmap original_pixmap_; + QPixmap blurred_pixmap_; +}; + +#endif // WIDGETFADEHELPER_H