feat: album list, artist list, and artist detail views

- Fav albums: now shows a sortable list (title/artist/year/tracks);
  double-click opens the album
- Fav artists: now shows a sortable list; double-click opens the artist
- Artist detail page: name, biography summary, and their album list
- Rust ArtistDto gains albums field; get_artist fixed to extra=albums only
- Volume popup minimum width set so "100%" label is never clipped

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
joren
2026-03-24 00:59:02 +01:00
parent 2436b53697
commit d5dedacc36
11 changed files with 255 additions and 16 deletions

View File

@@ -0,0 +1,53 @@
#pragma once
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QHeaderView>
#include <QJsonObject>
#include <QJsonArray>
/// A simple list of artists.
/// Double-clicking an item emits artistSelected(artistId).
class ArtistListView : public QTreeWidget
{
Q_OBJECT
public:
explicit ArtistListView(QWidget *parent = nullptr) : QTreeWidget(parent)
{
setColumnCount(2);
setHeaderLabels({tr("Artist"), tr("Albums")});
setRootIsDecorated(false);
setAlternatingRowColors(true);
setSelectionBehavior(QAbstractItemView::SelectRows);
header()->setStretchLastSection(false);
header()->setSectionResizeMode(0, QHeaderView::Stretch);
header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
connect(this, &QTreeWidget::itemDoubleClicked,
this, [this](QTreeWidgetItem *item, int) {
const qint64 id = item->data(0, Qt::UserRole).toLongLong();
if (id > 0) emit artistSelected(id);
});
}
void setArtists(const QJsonArray &artists)
{
clear();
for (const auto &v : artists) {
const QJsonObject a = v.toObject();
const qint64 id = static_cast<qint64>(a["id"].toDouble());
const QString name = a["name"].toString();
const int albums = a["albums_count"].toInt();
auto *item = new QTreeWidgetItem(this);
item->setText(0, name);
item->setText(1, albums > 0 ? QString::number(albums) : QString());
item->setData(0, Qt::UserRole, id);
}
}
signals:
void artistSelected(qint64 artistId);
};