fix: artist page top tracks and scrollable biography

- top_tracks is a flat array in the API response, not {items:[...]}
- Replace bio QLabel with scrollable QTextEdit (max 110px, scrolls if longer)
- Track model: handle artist.name as {display:...} object for top_tracks format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
joren
2026-03-25 14:02:26 +01:00
parent e37de6d897
commit fb58c0ac8c
3 changed files with 25 additions and 15 deletions

View File

@@ -4,6 +4,7 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QScrollArea>
#include <QTextEdit>
#include <QFont>
#include <QJsonValue>
#include <QRegularExpression>
@@ -89,11 +90,13 @@ ArtistView::ArtistView(QobuzBackend *backend, PlayQueue *queue, QWidget *parent)
m_nameLabel->setFont(f);
outerLayout->addWidget(m_nameLabel);
m_bioLabel = new QLabel(this);
m_bioLabel->setWordWrap(true);
m_bioLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
m_bioLabel->setMaximumHeight(80);
outerLayout->addWidget(m_bioLabel);
m_bioEdit = new QTextEdit(this);
m_bioEdit->setReadOnly(true);
m_bioEdit->setFrameShape(QFrame::NoFrame);
m_bioEdit->setMaximumHeight(110);
m_bioEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
m_bioEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
outerLayout->addWidget(m_bioEdit);
// Scrollable sections area
auto *scroll = new QScrollArea(this);
@@ -174,7 +177,6 @@ void ArtistView::setArtist(const QJsonObject &artist)
const QString bioHtml = artist["biography"].toObject()["content"].toString();
if (!bioHtml.isEmpty()) {
QString plain = bioHtml;
// Strip HTML entities and tags to prevent rendering injected content
plain.remove(QRegularExpression(QStringLiteral("<[^>]*>")));
plain.replace(QStringLiteral("&amp;"), QStringLiteral("&"));
plain.replace(QStringLiteral("&lt;"), QStringLiteral("<"));
@@ -183,15 +185,14 @@ void ArtistView::setArtist(const QJsonObject &artist)
plain.replace(QStringLiteral("&#39;"), QStringLiteral("'"));
plain.replace(QStringLiteral("&nbsp;"), QStringLiteral(" "));
plain = plain.trimmed();
m_bioLabel->setTextFormat(Qt::PlainText);
m_bioLabel->setText(plain);
m_bioLabel->setVisible(!plain.isEmpty());
m_bioEdit->setPlainText(plain);
m_bioEdit->setVisible(!plain.isEmpty());
} else {
m_bioLabel->setVisible(false);
m_bioEdit->setVisible(false);
}
// Top tracks are in the default artist/page response under "top_tracks"
const QJsonArray topTracks = artist["top_tracks"].toObject()["items"].toArray();
// top_tracks is a flat array in the artist/page response
const QJsonArray topTracks = artist["top_tracks"].toArray();
m_topTracks->loadTracks(topTracks);
m_topTracksSection->setVisible(!topTracks.isEmpty());