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

@@ -51,8 +51,16 @@ void TrackListModel::setTracks(const QJsonArray &tracks,
const QJsonObject performer = t["performer"].toObject();
item.artist = performer["name"].toString();
if (item.artist.isEmpty())
item.artist = t["album"].toObject()["artist"].toObject()["name"].toString();
if (item.artist.isEmpty()) {
// album.artist.name may be a plain string or {display:"..."} object
const QJsonValue n = t["album"].toObject()["artist"].toObject()["name"];
item.artist = n.isObject() ? n.toObject()["display"].toString() : n.toString();
}
if (item.artist.isEmpty()) {
// top_tracks format: artist.name.display
const QJsonValue n = t["artist"].toObject()["name"];
item.artist = n.isObject() ? n.toObject()["display"].toString() : n.toString();
}
const QJsonObject album = t["album"].toObject();
item.album = album["title"].toString();

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());

View File

@@ -7,6 +7,7 @@
#include <QWidget>
#include <QLabel>
#include <QTextEdit>
#include <QToolButton>
#include <QPushButton>
#include <QJsonObject>
@@ -54,7 +55,7 @@ signals:
private:
QLabel *m_nameLabel = nullptr;
QLabel *m_bioLabel = nullptr;
QTextEdit *m_bioEdit = nullptr;
// Top tracks section
QWidget *m_topTracksSection = nullptr;