feat: add deep shuffle in genre browse and tighten toolbar layout
Some checks failed
Build for Windows / build-windows (push) Has been cancelled
Some checks failed
Build for Windows / build-windows (push) Has been cancelled
This commit is contained in:
@@ -15,9 +15,10 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
GenreBrowserView::GenreBrowserView(QobuzBackend *backend, QWidget *parent)
|
GenreBrowserView::GenreBrowserView(QobuzBackend *backend, PlayQueue *queue, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, m_backend(backend)
|
, m_backend(backend)
|
||||||
|
, m_queue(queue)
|
||||||
{
|
{
|
||||||
auto *layout = new QVBoxLayout(this);
|
auto *layout = new QVBoxLayout(this);
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
@@ -26,31 +27,34 @@ GenreBrowserView::GenreBrowserView(QobuzBackend *backend, QWidget *parent)
|
|||||||
auto *topBar = new QWidget(this);
|
auto *topBar = new QWidget(this);
|
||||||
auto *topLayout = new QHBoxLayout(topBar);
|
auto *topLayout = new QHBoxLayout(topBar);
|
||||||
topLayout->setContentsMargins(8, 6, 8, 6);
|
topLayout->setContentsMargins(8, 6, 8, 6);
|
||||||
|
topLayout->setSpacing(6);
|
||||||
|
|
||||||
m_browseLabel = new QLabel(tr("Show:"), this);
|
m_browseLabel = new QLabel(tr("Show:"), this);
|
||||||
topLayout->addWidget(m_browseLabel);
|
topLayout->addWidget(m_browseLabel);
|
||||||
m_kindCombo = new QComboBox(this);
|
m_kindCombo = new QComboBox(this);
|
||||||
m_kindCombo->addItem(tr("Albums"), QStringLiteral("albums"));
|
m_kindCombo->addItem(tr("Albums"), QStringLiteral("albums"));
|
||||||
m_kindCombo->addItem(tr("Playlists"), QStringLiteral("playlists"));
|
m_kindCombo->addItem(tr("Playlists"), QStringLiteral("playlists"));
|
||||||
|
m_kindCombo->setMinimumWidth(110);
|
||||||
topLayout->addWidget(m_kindCombo);
|
topLayout->addWidget(m_kindCombo);
|
||||||
|
|
||||||
m_gapAfterKind = new QWidget(this);
|
m_gapAfterKind = new QWidget(this);
|
||||||
m_gapAfterKind->setFixedWidth(12);
|
m_gapAfterKind->setFixedWidth(6);
|
||||||
topLayout->addWidget(m_gapAfterKind);
|
topLayout->addWidget(m_gapAfterKind);
|
||||||
|
|
||||||
m_genreLabel = new QLabel(tr("Genre:"), this);
|
m_genreLabel = new QLabel(tr("Genre:"), this);
|
||||||
topLayout->addWidget(m_genreLabel);
|
topLayout->addWidget(m_genreLabel);
|
||||||
m_genreCombo = new QComboBox(this);
|
m_genreCombo = new QComboBox(this);
|
||||||
m_genreCombo->setMinimumWidth(160);
|
m_genreCombo->setMinimumWidth(180);
|
||||||
topLayout->addWidget(m_genreCombo);
|
topLayout->addWidget(m_genreCombo);
|
||||||
|
|
||||||
m_gapAfterGenre = new QWidget(this);
|
m_gapAfterGenre = new QWidget(this);
|
||||||
m_gapAfterGenre->setFixedWidth(16);
|
m_gapAfterGenre->setFixedWidth(10);
|
||||||
topLayout->addWidget(m_gapAfterGenre);
|
topLayout->addWidget(m_gapAfterGenre);
|
||||||
|
|
||||||
m_typeLabel = new QLabel(tr("Type:"), this);
|
m_typeLabel = new QLabel(tr("Type:"), this);
|
||||||
topLayout->addWidget(m_typeLabel);
|
topLayout->addWidget(m_typeLabel);
|
||||||
m_typeCombo = new QComboBox(this);
|
m_typeCombo = new QComboBox(this);
|
||||||
|
m_typeCombo->setMinimumWidth(180);
|
||||||
topLayout->addWidget(m_typeCombo);
|
topLayout->addWidget(m_typeCombo);
|
||||||
|
|
||||||
m_playlistSearchLabel = new QLabel(tr("Search:"), this);
|
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->setPlaceholderText(tr("Search playlists..."));
|
||||||
m_playlistSearchBox->setClearButtonEnabled(true);
|
m_playlistSearchBox->setClearButtonEnabled(true);
|
||||||
m_playlistSearchBox->setVisible(false);
|
m_playlistSearchBox->setVisible(false);
|
||||||
m_playlistSearchBox->setMinimumWidth(180);
|
m_playlistSearchBox->setMinimumWidth(220);
|
||||||
m_playlistSearchBox->setMaximumWidth(320);
|
m_playlistSearchBox->setMaximumWidth(320);
|
||||||
topLayout->addWidget(m_playlistSearchBox);
|
topLayout->addWidget(m_playlistSearchBox);
|
||||||
|
|
||||||
m_playlistSearchBtn = new QPushButton(tr("Search"), this);
|
m_playlistSearchBtn = new QPushButton(tr("Go"), this);
|
||||||
m_playlistSearchBtn->setVisible(false);
|
m_playlistSearchBtn->setVisible(false);
|
||||||
topLayout->addWidget(m_playlistSearchBtn);
|
topLayout->addWidget(m_playlistSearchBtn);
|
||||||
|
|
||||||
|
m_deepShuffleBtn = new QPushButton(tr("⇄ Deep Shuffle"), this);
|
||||||
|
m_deepShuffleBtn->setVisible(false);
|
||||||
|
topLayout->addWidget(m_deepShuffleBtn);
|
||||||
|
|
||||||
topLayout->addStretch();
|
topLayout->addStretch();
|
||||||
layout->addWidget(topBar);
|
layout->addWidget(topBar);
|
||||||
|
|
||||||
@@ -137,6 +145,8 @@ GenreBrowserView::GenreBrowserView(QobuzBackend *backend, QWidget *parent)
|
|||||||
this, &GenreBrowserView::onSelectionChanged);
|
this, &GenreBrowserView::onSelectionChanged);
|
||||||
connect(m_playlistSearchBtn, &QPushButton::clicked,
|
connect(m_playlistSearchBtn, &QPushButton::clicked,
|
||||||
this, &GenreBrowserView::onSelectionChanged);
|
this, &GenreBrowserView::onSelectionChanged);
|
||||||
|
connect(m_deepShuffleBtn, &QPushButton::clicked,
|
||||||
|
this, &GenreBrowserView::onDeepShuffleClicked);
|
||||||
connect(m_albumList, &AlbumListView::albumSelected,
|
connect(m_albumList, &AlbumListView::albumSelected,
|
||||||
this, &GenreBrowserView::albumSelected);
|
this, &GenreBrowserView::albumSelected);
|
||||||
connect(m_albumList, &QTreeWidget::customContextMenuRequested,
|
connect(m_albumList, &QTreeWidget::customContextMenuRequested,
|
||||||
@@ -183,6 +193,7 @@ void GenreBrowserView::refreshModeUi()
|
|||||||
m_playlistSearchBox->setVisible(false);
|
m_playlistSearchBox->setVisible(false);
|
||||||
m_playlistSearchLabel->setVisible(false);
|
m_playlistSearchLabel->setVisible(false);
|
||||||
m_playlistSearchBtn->setVisible(false);
|
m_playlistSearchBtn->setVisible(false);
|
||||||
|
m_deepShuffleBtn->setVisible(m_kindCombo->currentData().toString() == QStringLiteral("albums"));
|
||||||
refreshGenreTypeChoices();
|
refreshGenreTypeChoices();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -194,6 +205,7 @@ void GenreBrowserView::refreshModeUi()
|
|||||||
m_playlistSearchLabel->setVisible(true);
|
m_playlistSearchLabel->setVisible(true);
|
||||||
m_playlistSearchBox->setVisible(true);
|
m_playlistSearchBox->setVisible(true);
|
||||||
m_playlistSearchBtn->setVisible(true);
|
m_playlistSearchBtn->setVisible(true);
|
||||||
|
m_deepShuffleBtn->setVisible(false);
|
||||||
m_resultsStack->setCurrentIndex(1);
|
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: Focus"), QStringLiteral("discover-focus"));
|
||||||
m_typeCombo->addItem(tr("Discover: Qobuz Digs"), QStringLiteral("discover-qobuzdigs"));
|
m_typeCombo->addItem(tr("Discover: Qobuz Digs"), QStringLiteral("discover-qobuzdigs"));
|
||||||
m_resultsStack->setCurrentIndex(1);
|
m_resultsStack->setCurrentIndex(1);
|
||||||
|
m_deepShuffleBtn->setVisible(false);
|
||||||
} else {
|
} else {
|
||||||
m_typeCombo->addItem(tr("New Releases"), QStringLiteral("new-releases"));
|
m_typeCombo->addItem(tr("New Releases"), QStringLiteral("new-releases"));
|
||||||
m_typeCombo->addItem(tr("Best Sellers"), QStringLiteral("best-sellers"));
|
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("Editor Picks"), QStringLiteral("editor-picks"));
|
||||||
m_typeCombo->addItem(tr("Press Awards"), QStringLiteral("press-awards"));
|
m_typeCombo->addItem(tr("Press Awards"), QStringLiteral("press-awards"));
|
||||||
m_resultsStack->setCurrentIndex(0);
|
m_resultsStack->setCurrentIndex(0);
|
||||||
|
m_deepShuffleBtn->setVisible(m_mode == BrowseMode::Genres);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_typeCombo->blockSignals(false);
|
m_typeCombo->blockSignals(false);
|
||||||
@@ -351,6 +365,7 @@ void GenreBrowserView::onSelectionChanged()
|
|||||||
m_playlistSearchLabel->setVisible(true);
|
m_playlistSearchLabel->setVisible(true);
|
||||||
m_playlistSearchBox->setVisible(true);
|
m_playlistSearchBox->setVisible(true);
|
||||||
m_playlistSearchBtn->setVisible(true);
|
m_playlistSearchBtn->setVisible(true);
|
||||||
|
m_deepShuffleBtn->setVisible(false);
|
||||||
const QString query = m_playlistSearchBox->text().trimmed();
|
const QString query = m_playlistSearchBox->text().trimmed();
|
||||||
if (query.size() < 2) {
|
if (query.size() < 2) {
|
||||||
m_playlistList->clear();
|
m_playlistList->clear();
|
||||||
@@ -384,10 +399,55 @@ void GenreBrowserView::onSelectionChanged()
|
|||||||
m_backend->getFeaturedPlaylists(genreIds, type, 25, 0);
|
m_backend->getFeaturedPlaylists(genreIds, type, 25, 0);
|
||||||
} else {
|
} else {
|
||||||
m_resultsStack->setCurrentIndex(0);
|
m_resultsStack->setCurrentIndex(0);
|
||||||
|
m_deepShuffleBtn->setVisible(m_mode == BrowseMode::Genres);
|
||||||
m_backend->getFeaturedAlbums(genreIds, type, 50, 0);
|
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)
|
void GenreBrowserView::onAlbumContextMenu(const QPoint &pos)
|
||||||
{
|
{
|
||||||
QTreeWidgetItem *item = m_albumList->itemAt(pos);
|
QTreeWidgetItem *item = m_albumList->itemAt(pos);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../backend/qobuzbackend.hpp"
|
#include "../backend/qobuzbackend.hpp"
|
||||||
|
#include "../playqueue.hpp"
|
||||||
#include "albumlistview.hpp"
|
#include "albumlistview.hpp"
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
@@ -24,15 +25,17 @@ public:
|
|||||||
PlaylistSearch,
|
PlaylistSearch,
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit GenreBrowserView(QobuzBackend *backend, QWidget *parent = nullptr);
|
explicit GenreBrowserView(QobuzBackend *backend, PlayQueue *queue, QWidget *parent = nullptr);
|
||||||
|
|
||||||
void ensureGenresLoaded();
|
void ensureGenresLoaded();
|
||||||
void setBrowseMode(BrowseMode mode);
|
void setBrowseMode(BrowseMode mode);
|
||||||
|
bool tryHandleDeepShuffleTracks(const QJsonArray &tracks);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void albumSelected(const QString &albumId);
|
void albumSelected(const QString &albumId);
|
||||||
void artistSelected(qint64 artistId);
|
void artistSelected(qint64 artistId);
|
||||||
void playlistSelected(qint64 playlistId);
|
void playlistSelected(qint64 playlistId);
|
||||||
|
void playTrackRequested(qint64 trackId);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onGenresLoaded(const QJsonObject &result);
|
void onGenresLoaded(const QJsonObject &result);
|
||||||
@@ -44,9 +47,11 @@ private slots:
|
|||||||
void onAlbumContextMenu(const QPoint &pos);
|
void onAlbumContextMenu(const QPoint &pos);
|
||||||
void onPlaylistActivated(QTreeWidgetItem *item, int column);
|
void onPlaylistActivated(QTreeWidgetItem *item, int column);
|
||||||
void onPlaylistContextMenu(const QPoint &pos);
|
void onPlaylistContextMenu(const QPoint &pos);
|
||||||
|
void onDeepShuffleClicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QobuzBackend *m_backend = nullptr;
|
QobuzBackend *m_backend = nullptr;
|
||||||
|
PlayQueue *m_queue = nullptr;
|
||||||
QLabel *m_browseLabel = nullptr;
|
QLabel *m_browseLabel = nullptr;
|
||||||
QLabel *m_genreLabel = nullptr;
|
QLabel *m_genreLabel = nullptr;
|
||||||
QLabel *m_typeLabel = nullptr;
|
QLabel *m_typeLabel = nullptr;
|
||||||
@@ -58,6 +63,7 @@ private:
|
|||||||
QComboBox *m_typeCombo = nullptr;
|
QComboBox *m_typeCombo = nullptr;
|
||||||
QLineEdit *m_playlistSearchBox = nullptr;
|
QLineEdit *m_playlistSearchBox = nullptr;
|
||||||
QPushButton *m_playlistSearchBtn = nullptr;
|
QPushButton *m_playlistSearchBtn = nullptr;
|
||||||
|
QPushButton *m_deepShuffleBtn = nullptr;
|
||||||
QStackedWidget *m_resultsStack = nullptr;
|
QStackedWidget *m_resultsStack = nullptr;
|
||||||
AlbumListView *m_albumList = nullptr;
|
AlbumListView *m_albumList = nullptr;
|
||||||
QTreeWidget *m_playlistList = nullptr;
|
QTreeWidget *m_playlistList = nullptr;
|
||||||
@@ -65,10 +71,12 @@ private:
|
|||||||
bool m_genresLoaded = false;
|
bool m_genresLoaded = false;
|
||||||
int m_lastGenreComboIndex = 0;
|
int m_lastGenreComboIndex = 0;
|
||||||
QSet<qint64> m_multiGenreIds;
|
QSet<qint64> m_multiGenreIds;
|
||||||
|
bool m_waitingDeepShuffle = false;
|
||||||
|
|
||||||
void refreshModeUi();
|
void refreshModeUi();
|
||||||
void refreshGenreTypeChoices();
|
void refreshGenreTypeChoices();
|
||||||
QString currentGenreIds() const;
|
QString currentGenreIds() const;
|
||||||
|
QStringList currentAlbumIds() const;
|
||||||
bool chooseMultiGenres();
|
bool chooseMultiGenres();
|
||||||
void updateMultiGenreLabel();
|
void updateMultiGenreLabel();
|
||||||
void setPlaylistItems(const QJsonArray &items);
|
void setPlaylistItems(const QJsonArray &items);
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ MainContent::MainContent(QobuzBackend *backend, PlayQueue *queue, QWidget *paren
|
|||||||
m_albumList = new AlbumListView(this);
|
m_albumList = new AlbumListView(this);
|
||||||
m_artistList = new ArtistListView(this);
|
m_artistList = new ArtistListView(this);
|
||||||
m_artistView = new ArtistView(backend, queue, 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(m_welcome); // 0
|
||||||
m_stack->addWidget(tracksPage); // 1
|
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::albumSelected, this, &MainContent::albumRequested);
|
||||||
connect(m_genreBrowser, &GenreBrowserView::artistSelected, this, &MainContent::artistRequested);
|
connect(m_genreBrowser, &GenreBrowserView::artistSelected, this, &MainContent::artistRequested);
|
||||||
connect(m_genreBrowser, &GenreBrowserView::playlistSelected, this, &MainContent::playlistRequested);
|
connect(m_genreBrowser, &GenreBrowserView::playlistSelected, this, &MainContent::playlistRequested);
|
||||||
|
connect(m_genreBrowser, &GenreBrowserView::playTrackRequested, this, &MainContent::playTrackRequested);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::showWelcome() { m_stack->setCurrentIndex(0); }
|
void MainContent::showWelcome() { m_stack->setCurrentIndex(0); }
|
||||||
@@ -132,6 +133,8 @@ void MainContent::setFavArtistIds(const QSet<qint64> &ids)
|
|||||||
|
|
||||||
void MainContent::onDeepShuffleTracks(const QJsonArray &tracks)
|
void MainContent::onDeepShuffleTracks(const QJsonArray &tracks)
|
||||||
{
|
{
|
||||||
|
if (m_genreBrowser->tryHandleDeepShuffleTracks(tracks))
|
||||||
|
return;
|
||||||
m_artistView->onDeepShuffleTracks(tracks);
|
m_artistView->onDeepShuffleTracks(tracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user