feat: add deep shuffle in genre browse and tighten toolbar layout
Some checks failed
Build for Windows / build-windows (push) Has been cancelled

This commit is contained in:
joren
2026-03-31 00:37:00 +02:00
parent 96bb21adff
commit 5673d6cd30
3 changed files with 79 additions and 8 deletions

View File

@@ -15,9 +15,10 @@
#include <algorithm>
GenreBrowserView::GenreBrowserView(QobuzBackend *backend, QWidget *parent)
GenreBrowserView::GenreBrowserView(QobuzBackend *backend, PlayQueue *queue, QWidget *parent)
: QWidget(parent)
, m_backend(backend)
, m_queue(queue)
{
auto *layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
@@ -26,31 +27,34 @@ GenreBrowserView::GenreBrowserView(QobuzBackend *backend, QWidget *parent)
auto *topBar = new QWidget(this);
auto *topLayout = new QHBoxLayout(topBar);
topLayout->setContentsMargins(8, 6, 8, 6);
topLayout->setSpacing(6);
m_browseLabel = new QLabel(tr("Show:"), this);
topLayout->addWidget(m_browseLabel);
m_kindCombo = new QComboBox(this);
m_kindCombo->addItem(tr("Albums"), QStringLiteral("albums"));
m_kindCombo->addItem(tr("Playlists"), QStringLiteral("playlists"));
m_kindCombo->setMinimumWidth(110);
topLayout->addWidget(m_kindCombo);
m_gapAfterKind = new QWidget(this);
m_gapAfterKind->setFixedWidth(12);
m_gapAfterKind->setFixedWidth(6);
topLayout->addWidget(m_gapAfterKind);
m_genreLabel = new QLabel(tr("Genre:"), this);
topLayout->addWidget(m_genreLabel);
m_genreCombo = new QComboBox(this);
m_genreCombo->setMinimumWidth(160);
m_genreCombo->setMinimumWidth(180);
topLayout->addWidget(m_genreCombo);
m_gapAfterGenre = new QWidget(this);
m_gapAfterGenre->setFixedWidth(16);
m_gapAfterGenre->setFixedWidth(10);
topLayout->addWidget(m_gapAfterGenre);
m_typeLabel = new QLabel(tr("Type:"), this);
topLayout->addWidget(m_typeLabel);
m_typeCombo = new QComboBox(this);
m_typeCombo->setMinimumWidth(180);
topLayout->addWidget(m_typeCombo);
m_playlistSearchLabel = new QLabel(tr("Search:"), this);
@@ -61,14 +65,18 @@ GenreBrowserView::GenreBrowserView(QobuzBackend *backend, QWidget *parent)
m_playlistSearchBox->setPlaceholderText(tr("Search playlists..."));
m_playlistSearchBox->setClearButtonEnabled(true);
m_playlistSearchBox->setVisible(false);
m_playlistSearchBox->setMinimumWidth(180);
m_playlistSearchBox->setMinimumWidth(220);
m_playlistSearchBox->setMaximumWidth(320);
topLayout->addWidget(m_playlistSearchBox);
m_playlistSearchBtn = new QPushButton(tr("Search"), this);
m_playlistSearchBtn = new QPushButton(tr("Go"), this);
m_playlistSearchBtn->setVisible(false);
topLayout->addWidget(m_playlistSearchBtn);
m_deepShuffleBtn = new QPushButton(tr("⇄ Deep Shuffle"), this);
m_deepShuffleBtn->setVisible(false);
topLayout->addWidget(m_deepShuffleBtn);
topLayout->addStretch();
layout->addWidget(topBar);
@@ -137,6 +145,8 @@ GenreBrowserView::GenreBrowserView(QobuzBackend *backend, QWidget *parent)
this, &GenreBrowserView::onSelectionChanged);
connect(m_playlistSearchBtn, &QPushButton::clicked,
this, &GenreBrowserView::onSelectionChanged);
connect(m_deepShuffleBtn, &QPushButton::clicked,
this, &GenreBrowserView::onDeepShuffleClicked);
connect(m_albumList, &AlbumListView::albumSelected,
this, &GenreBrowserView::albumSelected);
connect(m_albumList, &QTreeWidget::customContextMenuRequested,
@@ -183,6 +193,7 @@ void GenreBrowserView::refreshModeUi()
m_playlistSearchBox->setVisible(false);
m_playlistSearchLabel->setVisible(false);
m_playlistSearchBtn->setVisible(false);
m_deepShuffleBtn->setVisible(m_kindCombo->currentData().toString() == QStringLiteral("albums"));
refreshGenreTypeChoices();
return;
}
@@ -194,6 +205,7 @@ void GenreBrowserView::refreshModeUi()
m_playlistSearchLabel->setVisible(true);
m_playlistSearchBox->setVisible(true);
m_playlistSearchBtn->setVisible(true);
m_deepShuffleBtn->setVisible(false);
m_resultsStack->setCurrentIndex(1);
}
@@ -210,6 +222,7 @@ void GenreBrowserView::refreshGenreTypeChoices()
m_typeCombo->addItem(tr("Discover: Focus"), QStringLiteral("discover-focus"));
m_typeCombo->addItem(tr("Discover: Qobuz Digs"), QStringLiteral("discover-qobuzdigs"));
m_resultsStack->setCurrentIndex(1);
m_deepShuffleBtn->setVisible(false);
} else {
m_typeCombo->addItem(tr("New Releases"), QStringLiteral("new-releases"));
m_typeCombo->addItem(tr("Best Sellers"), QStringLiteral("best-sellers"));
@@ -217,6 +230,7 @@ void GenreBrowserView::refreshGenreTypeChoices()
m_typeCombo->addItem(tr("Editor Picks"), QStringLiteral("editor-picks"));
m_typeCombo->addItem(tr("Press Awards"), QStringLiteral("press-awards"));
m_resultsStack->setCurrentIndex(0);
m_deepShuffleBtn->setVisible(m_mode == BrowseMode::Genres);
}
m_typeCombo->blockSignals(false);
@@ -351,6 +365,7 @@ void GenreBrowserView::onSelectionChanged()
m_playlistSearchLabel->setVisible(true);
m_playlistSearchBox->setVisible(true);
m_playlistSearchBtn->setVisible(true);
m_deepShuffleBtn->setVisible(false);
const QString query = m_playlistSearchBox->text().trimmed();
if (query.size() < 2) {
m_playlistList->clear();
@@ -384,10 +399,55 @@ void GenreBrowserView::onSelectionChanged()
m_backend->getFeaturedPlaylists(genreIds, type, 25, 0);
} else {
m_resultsStack->setCurrentIndex(0);
m_deepShuffleBtn->setVisible(m_mode == BrowseMode::Genres);
m_backend->getFeaturedAlbums(genreIds, type, 50, 0);
}
}
QStringList GenreBrowserView::currentAlbumIds() const
{
QStringList ids;
for (int i = 0; i < m_albumList->topLevelItemCount(); ++i) {
const QString id = m_albumList->topLevelItem(i)->data(1, Qt::UserRole).toString();
if (!id.isEmpty())
ids.push_back(id);
}
return ids;
}
void GenreBrowserView::onDeepShuffleClicked()
{
const QStringList albumIds = currentAlbumIds();
if (albumIds.isEmpty())
return;
m_waitingDeepShuffle = true;
m_deepShuffleBtn->setEnabled(false);
m_deepShuffleBtn->setText(tr("Loading…"));
m_backend->getAlbumsTracks(albumIds);
}
bool GenreBrowserView::tryHandleDeepShuffleTracks(const QJsonArray &tracks)
{
if (!m_waitingDeepShuffle)
return false;
m_waitingDeepShuffle = false;
m_deepShuffleBtn->setEnabled(true);
m_deepShuffleBtn->setText(tr("⇄ Deep Shuffle"));
if (tracks.isEmpty())
return true;
m_queue->setContext(tracks, 0);
m_queue->shuffleNow();
const QJsonObject first = m_queue->current();
const qint64 id = static_cast<qint64>(first["id"].toDouble());
if (id > 0)
emit playTrackRequested(id);
return true;
}
void GenreBrowserView::onAlbumContextMenu(const QPoint &pos)
{
QTreeWidgetItem *item = m_albumList->itemAt(pos);

View File

@@ -1,6 +1,7 @@
#pragma once
#include "../backend/qobuzbackend.hpp"
#include "../playqueue.hpp"
#include "albumlistview.hpp"
#include <QComboBox>
@@ -24,15 +25,17 @@ public:
PlaylistSearch,
};
explicit GenreBrowserView(QobuzBackend *backend, QWidget *parent = nullptr);
explicit GenreBrowserView(QobuzBackend *backend, PlayQueue *queue, QWidget *parent = nullptr);
void ensureGenresLoaded();
void setBrowseMode(BrowseMode mode);
bool tryHandleDeepShuffleTracks(const QJsonArray &tracks);
signals:
void albumSelected(const QString &albumId);
void artistSelected(qint64 artistId);
void playlistSelected(qint64 playlistId);
void playTrackRequested(qint64 trackId);
private slots:
void onGenresLoaded(const QJsonObject &result);
@@ -44,9 +47,11 @@ private slots:
void onAlbumContextMenu(const QPoint &pos);
void onPlaylistActivated(QTreeWidgetItem *item, int column);
void onPlaylistContextMenu(const QPoint &pos);
void onDeepShuffleClicked();
private:
QobuzBackend *m_backend = nullptr;
PlayQueue *m_queue = nullptr;
QLabel *m_browseLabel = nullptr;
QLabel *m_genreLabel = nullptr;
QLabel *m_typeLabel = nullptr;
@@ -58,6 +63,7 @@ private:
QComboBox *m_typeCombo = nullptr;
QLineEdit *m_playlistSearchBox = nullptr;
QPushButton *m_playlistSearchBtn = nullptr;
QPushButton *m_deepShuffleBtn = nullptr;
QStackedWidget *m_resultsStack = nullptr;
AlbumListView *m_albumList = nullptr;
QTreeWidget *m_playlistList = nullptr;
@@ -65,10 +71,12 @@ private:
bool m_genresLoaded = false;
int m_lastGenreComboIndex = 0;
QSet<qint64> m_multiGenreIds;
bool m_waitingDeepShuffle = false;
void refreshModeUi();
void refreshGenreTypeChoices();
QString currentGenreIds() const;
QStringList currentAlbumIds() const;
bool chooseMultiGenres();
void updateMultiGenreLabel();
void setPlaylistItems(const QJsonArray &items);

View File

@@ -52,7 +52,7 @@ MainContent::MainContent(QobuzBackend *backend, PlayQueue *queue, QWidget *paren
m_albumList = new AlbumListView(this);
m_artistList = new ArtistListView(this);
m_artistView = new ArtistView(backend, queue, this);
m_genreBrowser = new GenreBrowserView(backend, this);
m_genreBrowser = new GenreBrowserView(backend, queue, this);
m_stack->addWidget(m_welcome); // 0
m_stack->addWidget(tracksPage); // 1
@@ -70,6 +70,7 @@ MainContent::MainContent(QobuzBackend *backend, PlayQueue *queue, QWidget *paren
connect(m_genreBrowser, &GenreBrowserView::albumSelected, this, &MainContent::albumRequested);
connect(m_genreBrowser, &GenreBrowserView::artistSelected, this, &MainContent::artistRequested);
connect(m_genreBrowser, &GenreBrowserView::playlistSelected, this, &MainContent::playlistRequested);
connect(m_genreBrowser, &GenreBrowserView::playTrackRequested, this, &MainContent::playTrackRequested);
}
void MainContent::showWelcome() { m_stack->setCurrentIndex(0); }
@@ -132,6 +133,8 @@ void MainContent::setFavArtistIds(const QSet<qint64> &ids)
void MainContent::onDeepShuffleTracks(const QJsonArray &tracks)
{
if (m_genreBrowser->tryHandleDeepShuffleTracks(tracks))
return;
m_artistView->onDeepShuffleTracks(tracks);
}