Stores the raw downloaded pixmap and rescales it (smooth, aspect-ratio preserved) whenever the dock is resized, so the image always fills the available width. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
3.1 KiB
C++
100 lines
3.1 KiB
C++
#include "view.hpp"
|
|
|
|
#include <QWidget>
|
|
#include <QVBoxLayout>
|
|
#include <QNetworkRequest>
|
|
|
|
namespace Context
|
|
{
|
|
|
|
View::View(QobuzBackend *backend, QWidget *parent)
|
|
: QDockWidget(tr("Now Playing"), parent)
|
|
, m_backend(backend)
|
|
{
|
|
setObjectName(QStringLiteral("contextDock"));
|
|
setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable);
|
|
|
|
m_nam = new QNetworkAccessManager(this);
|
|
connect(m_nam, &QNetworkAccessManager::finished, this, &View::onArtReady);
|
|
|
|
auto *container = new QWidget(this);
|
|
auto *layout = new QVBoxLayout(container);
|
|
layout->setContentsMargins(8, 8, 8, 8);
|
|
layout->setSpacing(6);
|
|
|
|
m_albumArt = new QLabel(container);
|
|
m_albumArt->setAlignment(Qt::AlignCenter);
|
|
m_albumArt->setStyleSheet(QStringLiteral(
|
|
"background: #1a1a1a; border-radius: 4px;"));
|
|
m_albumArt->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
layout->addWidget(m_albumArt);
|
|
|
|
m_title = new QLabel(tr("Not playing"), container);
|
|
m_title->setAlignment(Qt::AlignCenter);
|
|
m_title->setWordWrap(true);
|
|
QFont titleFont = m_title->font();
|
|
titleFont.setPointSizeF(titleFont.pointSizeF() * 1.05);
|
|
titleFont.setBold(true);
|
|
m_title->setFont(titleFont);
|
|
layout->addWidget(m_title);
|
|
|
|
m_artist = new QLabel(QString(), container);
|
|
m_artist->setAlignment(Qt::AlignCenter);
|
|
m_artist->setWordWrap(true);
|
|
layout->addWidget(m_artist);
|
|
|
|
layout->addStretch();
|
|
setWidget(container);
|
|
setMinimumWidth(160);
|
|
|
|
connect(m_backend, &QobuzBackend::trackChanged, this, &View::onTrackChanged);
|
|
}
|
|
|
|
void View::onTrackChanged(const QJsonObject &track)
|
|
{
|
|
const QString title = track["title"].toString();
|
|
const QString artist = track["performer"].toObject()["name"].toString().isEmpty()
|
|
? track["album"].toObject()["artist"].toObject()["name"].toString()
|
|
: track["performer"].toObject()["name"].toString();
|
|
|
|
m_title->setText(title.isEmpty() ? tr("Not playing") : title);
|
|
m_artist->setText(artist);
|
|
|
|
// Prefer "large" image, fall back to "small"
|
|
const QJsonObject img = track["album"].toObject()["image"].toObject();
|
|
QString artUrl = img["large"].toString();
|
|
if (artUrl.isEmpty())
|
|
artUrl = img["small"].toString();
|
|
|
|
if (!artUrl.isEmpty() && artUrl != m_currentArtUrl) {
|
|
m_currentArtUrl = artUrl;
|
|
m_nam->get(QNetworkRequest(QUrl(artUrl)));
|
|
}
|
|
}
|
|
|
|
void View::onArtReady(QNetworkReply *reply)
|
|
{
|
|
reply->deleteLater();
|
|
if (reply->error() != QNetworkReply::NoError)
|
|
return;
|
|
if (m_artPixmap.loadFromData(reply->readAll()))
|
|
scaleArtToWidth();
|
|
}
|
|
|
|
void View::resizeEvent(QResizeEvent *event)
|
|
{
|
|
QDockWidget::resizeEvent(event);
|
|
scaleArtToWidth();
|
|
}
|
|
|
|
void View::scaleArtToWidth()
|
|
{
|
|
if (m_artPixmap.isNull()) return;
|
|
// Available width = dock width minus the 8px margins on each side
|
|
const int side = qMax(32, widget() ? widget()->width() - 16 : width() - 16);
|
|
m_albumArt->setFixedSize(side, side);
|
|
m_albumArt->setPixmap(m_artPixmap.scaled(side, side, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
|
}
|
|
|
|
} // namespace Context
|