Compare commits
3 Commits
e453f8acf3
...
28771e12d5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28771e12d5 | ||
|
|
e9a9077ece | ||
|
|
86b5673e8a |
@@ -9,6 +9,56 @@ TrackListModel::TrackListModel(QObject *parent)
|
|||||||
: QAbstractTableModel(parent)
|
: QAbstractTableModel(parent)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
TrackItem TrackListModel::parseTrackItem(const QJsonObject &t,
|
||||||
|
bool usePosition,
|
||||||
|
bool useSequential,
|
||||||
|
int &seq)
|
||||||
|
{
|
||||||
|
TrackItem item;
|
||||||
|
item.id = static_cast<qint64>(t["id"].toDouble());
|
||||||
|
item.playlistTrackId = static_cast<qint64>(t["playlist_track_id"].toDouble());
|
||||||
|
item.discNumber = t["media_number"].toInt(1);
|
||||||
|
item.duration = static_cast<qint64>(t["duration"].toDouble());
|
||||||
|
item.streamable = t["streamable"].toBool(true);
|
||||||
|
item.hiRes = t["hires_streamable"].toBool();
|
||||||
|
item.raw = t;
|
||||||
|
|
||||||
|
// Combine title + version ("Melody" + "Vocal Remix" → "Melody (Vocal Remix)")
|
||||||
|
const QString base = t["title"].toString();
|
||||||
|
const QString version = t["version"].toString().trimmed();
|
||||||
|
item.title = version.isEmpty() ? base
|
||||||
|
: base + QStringLiteral(" (") + version + QLatin1Char(')');
|
||||||
|
|
||||||
|
if (useSequential) {
|
||||||
|
item.number = seq++;
|
||||||
|
} else if (usePosition) {
|
||||||
|
const int pos = t["position"].toInt();
|
||||||
|
item.number = pos > 0 ? pos : seq;
|
||||||
|
++seq;
|
||||||
|
} else {
|
||||||
|
item.number = t["track_number"].toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QJsonObject performer = t["performer"].toObject();
|
||||||
|
item.artist = performer["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();
|
||||||
|
item.albumId = album["id"].toString();
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
void TrackListModel::setTracks(const QJsonArray &tracks,
|
void TrackListModel::setTracks(const QJsonArray &tracks,
|
||||||
bool usePosition,
|
bool usePosition,
|
||||||
bool useSequential)
|
bool useSequential)
|
||||||
@@ -22,52 +72,8 @@ void TrackListModel::setTracks(const QJsonArray &tracks,
|
|||||||
parsed.reserve(tracks.size());
|
parsed.reserve(tracks.size());
|
||||||
|
|
||||||
int seq = 1;
|
int seq = 1;
|
||||||
for (const QJsonValue &v : tracks) {
|
for (const QJsonValue &v : tracks)
|
||||||
const QJsonObject t = v.toObject();
|
parsed.append(parseTrackItem(v.toObject(), usePosition, useSequential, seq));
|
||||||
TrackItem item;
|
|
||||||
item.id = static_cast<qint64>(t["id"].toDouble());
|
|
||||||
item.playlistTrackId = static_cast<qint64>(t["playlist_track_id"].toDouble());
|
|
||||||
item.discNumber = t["media_number"].toInt(1);
|
|
||||||
item.duration = static_cast<qint64>(t["duration"].toDouble());
|
|
||||||
item.streamable = t["streamable"].toBool(true);
|
|
||||||
item.hiRes = t["hires_streamable"].toBool();
|
|
||||||
item.raw = t;
|
|
||||||
|
|
||||||
// Combine title + version ("Melody" + "Vocal Remix" → "Melody (Vocal Remix)")
|
|
||||||
const QString base = t["title"].toString();
|
|
||||||
const QString version = t["version"].toString().trimmed();
|
|
||||||
item.title = version.isEmpty() ? base
|
|
||||||
: base + QStringLiteral(" (") + version + QLatin1Char(')');
|
|
||||||
|
|
||||||
if (useSequential) {
|
|
||||||
item.number = seq++;
|
|
||||||
} else if (usePosition) {
|
|
||||||
const int pos = t["position"].toInt();
|
|
||||||
item.number = pos > 0 ? pos : seq;
|
|
||||||
++seq;
|
|
||||||
} else {
|
|
||||||
item.number = t["track_number"].toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
const QJsonObject performer = t["performer"].toObject();
|
|
||||||
item.artist = performer["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();
|
|
||||||
item.albumId = album["id"].toString();
|
|
||||||
|
|
||||||
parsed.append(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multi-disc only makes sense for album context (not playlists / fav / search)
|
// Multi-disc only makes sense for album context (not playlists / fav / search)
|
||||||
int maxDisc = 1;
|
int maxDisc = 1;
|
||||||
@@ -134,49 +140,8 @@ void TrackListModel::appendTracks(const QJsonArray &tracks,
|
|||||||
|
|
||||||
QVector<TrackItem> parsed;
|
QVector<TrackItem> parsed;
|
||||||
parsed.reserve(tracks.size());
|
parsed.reserve(tracks.size());
|
||||||
for (const QJsonValue &v : tracks) {
|
for (const QJsonValue &v : tracks)
|
||||||
const QJsonObject t = v.toObject();
|
parsed.append(parseTrackItem(v.toObject(), usePosition, useSequential, seq));
|
||||||
TrackItem item;
|
|
||||||
item.id = static_cast<qint64>(t["id"].toDouble());
|
|
||||||
item.playlistTrackId = static_cast<qint64>(t["playlist_track_id"].toDouble());
|
|
||||||
item.discNumber = t["media_number"].toInt(1);
|
|
||||||
item.duration = static_cast<qint64>(t["duration"].toDouble());
|
|
||||||
item.streamable = t["streamable"].toBool(true);
|
|
||||||
item.hiRes = t["hires_streamable"].toBool();
|
|
||||||
item.raw = t;
|
|
||||||
|
|
||||||
const QString base = t["title"].toString();
|
|
||||||
const QString version = t["version"].toString().trimmed();
|
|
||||||
item.title = version.isEmpty() ? base
|
|
||||||
: base + QStringLiteral(" (") + version + QLatin1Char(')');
|
|
||||||
|
|
||||||
if (useSequential) {
|
|
||||||
item.number = seq++;
|
|
||||||
} else if (usePosition) {
|
|
||||||
const int pos = t["position"].toInt();
|
|
||||||
item.number = pos > 0 ? pos : seq;
|
|
||||||
++seq;
|
|
||||||
} else {
|
|
||||||
item.number = t["track_number"].toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
const QJsonObject performer = t["performer"].toObject();
|
|
||||||
item.artist = performer["name"].toString();
|
|
||||||
if (item.artist.isEmpty()) {
|
|
||||||
const QJsonValue n = t["album"].toObject()["artist"].toObject()["name"];
|
|
||||||
item.artist = n.isObject() ? n.toObject()["display"].toString() : n.toString();
|
|
||||||
}
|
|
||||||
if (item.artist.isEmpty()) {
|
|
||||||
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();
|
|
||||||
item.albumId = album["id"].toString();
|
|
||||||
|
|
||||||
parsed.append(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parsed.isEmpty())
|
if (parsed.isEmpty())
|
||||||
return;
|
return;
|
||||||
@@ -210,6 +175,16 @@ void TrackListModel::removeTrack(int row)
|
|||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrackListModel::notifyFavChanged(qint64 id)
|
||||||
|
{
|
||||||
|
for (int r = 0; r < m_tracks.size(); ++r) {
|
||||||
|
if (m_tracks[r].id == id) {
|
||||||
|
const auto idx = index(r, ColTitle);
|
||||||
|
emit dataChanged(idx, idx, {Qt::DecorationRole});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TrackListModel::setFavIds(const QSet<qint64> &ids)
|
void TrackListModel::setFavIds(const QSet<qint64> &ids)
|
||||||
{
|
{
|
||||||
m_favIds = ids;
|
m_favIds = ids;
|
||||||
@@ -221,23 +196,13 @@ void TrackListModel::setFavIds(const QSet<qint64> &ids)
|
|||||||
void TrackListModel::addFavId(qint64 id)
|
void TrackListModel::addFavId(qint64 id)
|
||||||
{
|
{
|
||||||
m_favIds.insert(id);
|
m_favIds.insert(id);
|
||||||
for (int r = 0; r < m_tracks.size(); ++r) {
|
notifyFavChanged(id);
|
||||||
if (m_tracks[r].id == id) {
|
|
||||||
const auto idx = index(r, ColTitle);
|
|
||||||
emit dataChanged(idx, idx, {Qt::DecorationRole});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackListModel::removeFavId(qint64 id)
|
void TrackListModel::removeFavId(qint64 id)
|
||||||
{
|
{
|
||||||
m_favIds.remove(id);
|
m_favIds.remove(id);
|
||||||
for (int r = 0; r < m_tracks.size(); ++r) {
|
notifyFavChanged(id);
|
||||||
if (m_tracks[r].id == id) {
|
|
||||||
const auto idx = index(r, ColTitle);
|
|
||||||
emit dataChanged(idx, idx, {Qt::DecorationRole});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrackListModel::setPlayingId(qint64 id)
|
void TrackListModel::setPlayingId(qint64 id)
|
||||||
|
|||||||
@@ -105,4 +105,10 @@ private:
|
|||||||
|
|
||||||
// Sort m_tracks in-place without emitting any signals.
|
// Sort m_tracks in-place without emitting any signals.
|
||||||
void sortData(int column, Qt::SortOrder order);
|
void sortData(int column, Qt::SortOrder order);
|
||||||
|
|
||||||
|
// Parse a single JSON track object into a TrackItem.
|
||||||
|
static TrackItem parseTrackItem(const QJsonObject &t, bool usePosition, bool useSequential, int &seq);
|
||||||
|
|
||||||
|
// Emit dataChanged(DecorationRole) for all rows matching id.
|
||||||
|
void notifyFavChanged(qint64 id);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,7 +9,9 @@
|
|||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
#include <QScrollBar>
|
||||||
#include <QSignalBlocker>
|
#include <QSignalBlocker>
|
||||||
|
#include <QTimer>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
@@ -120,8 +122,18 @@ GenreBrowserView::GenreBrowserView(QobuzBackend *backend, PlayQueue *queue, QWid
|
|||||||
m_playlistList->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
|
m_playlistList->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
|
||||||
m_playlistList->header()->setStretchLastSection(false);
|
m_playlistList->header()->setStretchLastSection(false);
|
||||||
|
|
||||||
|
auto *playlistPage = new QWidget(this);
|
||||||
|
auto *playlistPageLayout = new QVBoxLayout(playlistPage);
|
||||||
|
playlistPageLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
playlistPageLayout->setSpacing(0);
|
||||||
|
playlistPageLayout->addWidget(m_playlistList, 1);
|
||||||
|
|
||||||
|
m_loadMorePlaylistsBtn = new QPushButton(tr("Load more playlists…"), this);
|
||||||
|
m_loadMorePlaylistsBtn->hide();
|
||||||
|
playlistPageLayout->addWidget(m_loadMorePlaylistsBtn);
|
||||||
|
|
||||||
m_resultsStack->addWidget(m_albumList);
|
m_resultsStack->addWidget(m_albumList);
|
||||||
m_resultsStack->addWidget(m_playlistList);
|
m_resultsStack->addWidget(playlistPage);
|
||||||
layout->addWidget(m_resultsStack, 1);
|
layout->addWidget(m_resultsStack, 1);
|
||||||
|
|
||||||
connect(m_backend, &QobuzBackend::genresLoaded,
|
connect(m_backend, &QobuzBackend::genresLoaded,
|
||||||
@@ -180,6 +192,12 @@ GenreBrowserView::GenreBrowserView(QobuzBackend *backend, PlayQueue *queue, QWid
|
|||||||
this, &GenreBrowserView::onAlbumScroll);
|
this, &GenreBrowserView::onAlbumScroll);
|
||||||
connect(m_playlistList->verticalScrollBar(), &QScrollBar::valueChanged,
|
connect(m_playlistList->verticalScrollBar(), &QScrollBar::valueChanged,
|
||||||
this, &GenreBrowserView::onPlaylistScroll);
|
this, &GenreBrowserView::onPlaylistScroll);
|
||||||
|
connect(m_loadMorePlaylistsBtn, &QPushButton::clicked, this, [this] {
|
||||||
|
m_loadMorePlaylistsBtn->hide();
|
||||||
|
requestPlaylistsPage(m_lastPlaylistGenreIds, m_lastPlaylistType,
|
||||||
|
m_lastPlaylistTags, m_lastPlaylistQuery,
|
||||||
|
m_playlistOffset, true);
|
||||||
|
});
|
||||||
|
|
||||||
m_kindCombo->setCurrentIndex(0);
|
m_kindCombo->setCurrentIndex(0);
|
||||||
refreshModeUi();
|
refreshModeUi();
|
||||||
@@ -391,9 +409,12 @@ void GenreBrowserView::onFeaturedAlbumsLoaded(const QJsonObject &result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the viewport is not scrollable yet, eagerly fetch more pages.
|
// If the viewport is not scrollable yet, eagerly fetch more pages.
|
||||||
QScrollBar *bar = m_albumList->verticalScrollBar();
|
// Deferred: the scrollbar maximum isn't updated until after layout runs.
|
||||||
if (bar && bar->maximum() == 0 && m_albumOffset < m_albumTotal)
|
QTimer::singleShot(0, this, [this] {
|
||||||
requestAlbumsPage(m_lastAlbumGenreIds, m_lastAlbumType, m_albumOffset, true);
|
QScrollBar *bar = m_albumList->verticalScrollBar();
|
||||||
|
if (bar && bar->maximum() == 0 && m_albumOffset < m_albumTotal)
|
||||||
|
requestAlbumsPage(m_lastAlbumGenreIds, m_lastAlbumType, m_albumOffset, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenreBrowserView::onFeaturedPlaylistsLoaded(const QJsonObject &result)
|
void GenreBrowserView::onFeaturedPlaylistsLoaded(const QJsonObject &result)
|
||||||
@@ -413,9 +434,11 @@ void GenreBrowserView::onFeaturedPlaylistsLoaded(const QJsonObject &result)
|
|||||||
m_playlistTotal = m_playlistOffset;
|
m_playlistTotal = m_playlistOffset;
|
||||||
m_loadingPlaylists = false;
|
m_loadingPlaylists = false;
|
||||||
|
|
||||||
QScrollBar *bar = m_playlistList->verticalScrollBar();
|
QTimer::singleShot(0, this, [this] {
|
||||||
if (bar && bar->maximum() == 0 && m_playlistOffset < m_playlistTotal)
|
QScrollBar *bar = m_playlistList->verticalScrollBar();
|
||||||
requestPlaylistsPage(m_lastPlaylistGenreIds, m_lastPlaylistType, m_lastPlaylistTags, m_lastPlaylistQuery, m_playlistOffset, true);
|
if (bar && bar->maximum() == 0 && m_playlistOffset < m_playlistTotal)
|
||||||
|
requestPlaylistsPage(m_lastPlaylistGenreIds, m_lastPlaylistType, m_lastPlaylistTags, m_lastPlaylistQuery, m_playlistOffset, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenreBrowserView::onDiscoverPlaylistsLoaded(const QJsonObject &result)
|
void GenreBrowserView::onDiscoverPlaylistsLoaded(const QJsonObject &result)
|
||||||
@@ -435,9 +458,11 @@ void GenreBrowserView::onDiscoverPlaylistsLoaded(const QJsonObject &result)
|
|||||||
m_playlistTotal = m_playlistOffset;
|
m_playlistTotal = m_playlistOffset;
|
||||||
m_loadingPlaylists = false;
|
m_loadingPlaylists = false;
|
||||||
|
|
||||||
QScrollBar *bar = m_playlistList->verticalScrollBar();
|
QTimer::singleShot(0, this, [this] {
|
||||||
if (bar && bar->maximum() == 0 && m_playlistOffset < m_playlistTotal)
|
QScrollBar *bar = m_playlistList->verticalScrollBar();
|
||||||
requestPlaylistsPage(m_lastPlaylistGenreIds, m_lastPlaylistType, m_lastPlaylistTags, m_lastPlaylistQuery, m_playlistOffset, true);
|
if (bar && bar->maximum() == 0 && m_playlistOffset < m_playlistTotal)
|
||||||
|
requestPlaylistsPage(m_lastPlaylistGenreIds, m_lastPlaylistType, m_lastPlaylistTags, m_lastPlaylistQuery, m_playlistOffset, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenreBrowserView::onPlaylistSearchLoaded(const QJsonObject &result)
|
void GenreBrowserView::onPlaylistSearchLoaded(const QJsonObject &result)
|
||||||
@@ -456,9 +481,25 @@ void GenreBrowserView::onPlaylistSearchLoaded(const QJsonObject &result)
|
|||||||
m_playlistTotal = m_playlistOffset;
|
m_playlistTotal = m_playlistOffset;
|
||||||
m_loadingPlaylists = false;
|
m_loadingPlaylists = false;
|
||||||
|
|
||||||
QScrollBar *bar = m_playlistList->verticalScrollBar();
|
// Eagerly fill the viewport, then switch to a manual "Load more" button.
|
||||||
if (bar && bar->maximum() == 0 && m_playlistOffset < m_playlistTotal)
|
if (m_playlistOffset >= m_playlistTotal) {
|
||||||
requestPlaylistsPage(m_lastPlaylistGenreIds, m_lastPlaylistType, m_lastPlaylistTags, m_lastPlaylistQuery, m_playlistOffset, true);
|
m_loadMorePlaylistsBtn->hide();
|
||||||
|
m_searchViewportFilled = true;
|
||||||
|
} else if (!m_searchViewportFilled) {
|
||||||
|
QTimer::singleShot(0, this, [this] {
|
||||||
|
QScrollBar *bar = m_playlistList->verticalScrollBar();
|
||||||
|
if (bar && bar->maximum() == 0 && m_playlistOffset < m_playlistTotal) {
|
||||||
|
requestPlaylistsPage(m_lastPlaylistGenreIds, m_lastPlaylistType,
|
||||||
|
m_lastPlaylistTags, m_lastPlaylistQuery,
|
||||||
|
m_playlistOffset, true);
|
||||||
|
} else {
|
||||||
|
m_searchViewportFilled = true;
|
||||||
|
m_loadMorePlaylistsBtn->setVisible(m_playlistOffset < m_playlistTotal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
m_loadMorePlaylistsBtn->setVisible(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenreBrowserView::onSelectionChanged()
|
void GenreBrowserView::onSelectionChanged()
|
||||||
@@ -571,6 +612,9 @@ void GenreBrowserView::requestPlaylistsPage(const QString &genreIds, const QStri
|
|||||||
m_loadingPlaylists = false;
|
m_loadingPlaylists = false;
|
||||||
m_playlistOffset = 0;
|
m_playlistOffset = 0;
|
||||||
m_playlistTotal = 0;
|
m_playlistTotal = 0;
|
||||||
|
m_loadMorePlaylistsBtn->hide();
|
||||||
|
if (type == QStringLiteral("search"))
|
||||||
|
m_searchViewportFilled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastPlaylistGenreIds = genreIds;
|
m_lastPlaylistGenreIds = genreIds;
|
||||||
@@ -580,7 +624,7 @@ void GenreBrowserView::requestPlaylistsPage(const QString &genreIds, const QStri
|
|||||||
m_loadingPlaylists = true;
|
m_loadingPlaylists = true;
|
||||||
|
|
||||||
if (type == QStringLiteral("search")) {
|
if (type == QStringLiteral("search")) {
|
||||||
m_backend->searchPlaylists(query, 8, static_cast<quint32>(offset));
|
m_backend->searchPlaylists(query, 25, static_cast<quint32>(offset));
|
||||||
} else if (type.startsWith(QStringLiteral("discover-"))) {
|
} else if (type.startsWith(QStringLiteral("discover-"))) {
|
||||||
m_backend->discoverPlaylists(genreIds, tags, 25, static_cast<quint32>(offset));
|
m_backend->discoverPlaylists(genreIds, tags, 25, static_cast<quint32>(offset));
|
||||||
} else {
|
} else {
|
||||||
@@ -608,6 +652,9 @@ void GenreBrowserView::onAlbumScroll(int value)
|
|||||||
|
|
||||||
void GenreBrowserView::onPlaylistScroll(int value)
|
void GenreBrowserView::onPlaylistScroll(int value)
|
||||||
{
|
{
|
||||||
|
// Search results use a manual "Load more" button instead of infinite scroll.
|
||||||
|
if (m_lastPlaylistType == QStringLiteral("search"))
|
||||||
|
return;
|
||||||
if (m_loadingPlaylists)
|
if (m_loadingPlaylists)
|
||||||
return;
|
return;
|
||||||
if (m_playlistOffset >= m_playlistTotal)
|
if (m_playlistOffset >= m_playlistTotal)
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ private:
|
|||||||
QStackedWidget *m_resultsStack = nullptr;
|
QStackedWidget *m_resultsStack = nullptr;
|
||||||
AlbumListView *m_albumList = nullptr;
|
AlbumListView *m_albumList = nullptr;
|
||||||
QTreeWidget *m_playlistList = nullptr;
|
QTreeWidget *m_playlistList = nullptr;
|
||||||
|
QPushButton *m_loadMorePlaylistsBtn = nullptr;
|
||||||
|
bool m_searchViewportFilled = false;
|
||||||
BrowseMode m_mode = BrowseMode::Genres;
|
BrowseMode m_mode = BrowseMode::Genres;
|
||||||
bool m_genresLoaded = false;
|
bool m_genresLoaded = false;
|
||||||
int m_lastGenreComboIndex = 0;
|
int m_lastGenreComboIndex = 0;
|
||||||
|
|||||||
@@ -61,14 +61,14 @@ MainContent::MainContent(QobuzBackend *backend, PlayQueue *queue, QWidget *paren
|
|||||||
m_artistView = new ArtistView(backend, queue, this);
|
m_artistView = new ArtistView(backend, queue, this);
|
||||||
m_genreBrowser = new GenreBrowserView(backend, queue, this);
|
m_genreBrowser = new GenreBrowserView(backend, queue, this);
|
||||||
|
|
||||||
m_stack->addWidget(m_welcome); // 0
|
m_stack->addWidget(m_welcome); // PageWelcome
|
||||||
m_stack->addWidget(tracksPage); // 1
|
m_stack->addWidget(tracksPage); // PageTracks
|
||||||
m_stack->addWidget(m_albumList); // 2
|
m_stack->addWidget(m_albumList); // PageAlbumList
|
||||||
m_stack->addWidget(m_artistList); // 3
|
m_stack->addWidget(m_artistList); // PageArtistList
|
||||||
m_stack->addWidget(m_artistView); // 4
|
m_stack->addWidget(m_artistView); // PageArtistDetail
|
||||||
m_stack->addWidget(m_genreBrowser); // 5
|
m_stack->addWidget(m_genreBrowser); // PageGenreBrowser
|
||||||
|
|
||||||
m_stack->setCurrentIndex(0);
|
m_stack->setCurrentIndex(PageWelcome);
|
||||||
|
|
||||||
connect(m_albumList, &AlbumListView::albumSelected, this, &MainContent::albumRequested);
|
connect(m_albumList, &AlbumListView::albumSelected, this, &MainContent::albumRequested);
|
||||||
connect(m_artistList, &ArtistListView::artistSelected, this, &MainContent::artistRequested);
|
connect(m_artistList, &ArtistListView::artistSelected, this, &MainContent::artistRequested);
|
||||||
@@ -80,7 +80,7 @@ MainContent::MainContent(QobuzBackend *backend, PlayQueue *queue, QWidget *paren
|
|||||||
connect(m_genreBrowser, &GenreBrowserView::playTrackRequested, this, &MainContent::playTrackRequested);
|
connect(m_genreBrowser, &GenreBrowserView::playTrackRequested, this, &MainContent::playTrackRequested);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::showWelcome() { m_stack->setCurrentIndex(0); }
|
void MainContent::showWelcome() { m_stack->setCurrentIndex(PageWelcome); }
|
||||||
|
|
||||||
void MainContent::showAlbum(const QJsonObject &album)
|
void MainContent::showAlbum(const QJsonObject &album)
|
||||||
{
|
{
|
||||||
@@ -89,46 +89,46 @@ void MainContent::showAlbum(const QJsonObject &album)
|
|||||||
albumId = QString::number(static_cast<qint64>(album["id"].toDouble()));
|
albumId = QString::number(static_cast<qint64>(album["id"].toDouble()));
|
||||||
m_header->setAlbum(album, m_favAlbumIds.contains(albumId));
|
m_header->setAlbum(album, m_favAlbumIds.contains(albumId));
|
||||||
m_tracks->loadAlbum(album);
|
m_tracks->loadAlbum(album);
|
||||||
m_stack->setCurrentIndex(1);
|
m_stack->setCurrentIndex(PageTracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::showPlaylist(const QJsonObject &playlist, bool isFollowed, bool isOwned)
|
void MainContent::showPlaylist(const QJsonObject &playlist, bool isFollowed, bool isOwned)
|
||||||
{
|
{
|
||||||
m_header->setPlaylist(playlist, isFollowed, isOwned);
|
m_header->setPlaylist(playlist, isFollowed, isOwned);
|
||||||
m_tracks->loadPlaylist(playlist);
|
m_tracks->loadPlaylist(playlist);
|
||||||
m_stack->setCurrentIndex(1);
|
m_stack->setCurrentIndex(PageTracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::showFavTracks(const QJsonObject &result)
|
void MainContent::showFavTracks(const QJsonObject &result)
|
||||||
{
|
{
|
||||||
m_header->hide();
|
m_header->hide();
|
||||||
m_tracks->loadTracks(result["items"].toArray());
|
m_tracks->loadTracks(result["items"].toArray());
|
||||||
m_stack->setCurrentIndex(1);
|
m_stack->setCurrentIndex(PageTracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::showSearchTracks(const QJsonArray &tracks)
|
void MainContent::showSearchTracks(const QJsonArray &tracks)
|
||||||
{
|
{
|
||||||
m_header->hide();
|
m_header->hide();
|
||||||
m_tracks->loadSearchTracks(tracks);
|
m_tracks->loadSearchTracks(tracks);
|
||||||
m_stack->setCurrentIndex(1);
|
m_stack->setCurrentIndex(PageTracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::showFavAlbums(const QJsonObject &result)
|
void MainContent::showFavAlbums(const QJsonObject &result)
|
||||||
{
|
{
|
||||||
m_albumList->setAlbums(result["items"].toArray());
|
m_albumList->setAlbums(result["items"].toArray());
|
||||||
m_stack->setCurrentIndex(2);
|
m_stack->setCurrentIndex(PageAlbumList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::showFavArtists(const QJsonObject &result)
|
void MainContent::showFavArtists(const QJsonObject &result)
|
||||||
{
|
{
|
||||||
m_artistList->setArtists(result["items"].toArray());
|
m_artistList->setArtists(result["items"].toArray());
|
||||||
m_stack->setCurrentIndex(3);
|
m_stack->setCurrentIndex(PageArtistList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::showArtist(const QJsonObject &artist)
|
void MainContent::showArtist(const QJsonObject &artist)
|
||||||
{
|
{
|
||||||
m_artistView->setArtist(artist);
|
m_artistView->setArtist(artist);
|
||||||
m_stack->setCurrentIndex(4);
|
m_stack->setCurrentIndex(PageArtistDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::updateArtistReleases(const QString &releaseType, const QJsonArray &items, bool hasMore, int offset)
|
void MainContent::updateArtistReleases(const QString &releaseType, const QJsonArray &items, bool hasMore, int offset)
|
||||||
@@ -160,14 +160,14 @@ void MainContent::showGenreBrowser()
|
|||||||
{
|
{
|
||||||
m_genreBrowser->ensureGenresLoaded();
|
m_genreBrowser->ensureGenresLoaded();
|
||||||
m_genreBrowser->setBrowseMode(GenreBrowserView::BrowseMode::Genres);
|
m_genreBrowser->setBrowseMode(GenreBrowserView::BrowseMode::Genres);
|
||||||
m_stack->setCurrentIndex(5);
|
m_stack->setCurrentIndex(PageGenreBrowser);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::showPlaylistBrowser()
|
void MainContent::showPlaylistBrowser()
|
||||||
{
|
{
|
||||||
m_genreBrowser->ensureGenresLoaded();
|
m_genreBrowser->ensureGenresLoaded();
|
||||||
m_genreBrowser->setBrowseMode(GenreBrowserView::BrowseMode::PlaylistSearch);
|
m_genreBrowser->setBrowseMode(GenreBrowserView::BrowseMode::PlaylistSearch);
|
||||||
m_stack->setCurrentIndex(5);
|
m_stack->setCurrentIndex(PageGenreBrowser);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContent::setCurrentPlaylistFollowed(bool followed)
|
void MainContent::setCurrentPlaylistFollowed(bool followed)
|
||||||
|
|||||||
@@ -52,6 +52,15 @@ signals:
|
|||||||
void playTrackRequested(qint64 trackId);
|
void playTrackRequested(qint64 trackId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum StackPage {
|
||||||
|
PageWelcome = 0,
|
||||||
|
PageTracks = 1,
|
||||||
|
PageAlbumList = 2,
|
||||||
|
PageArtistList = 3,
|
||||||
|
PageArtistDetail = 4,
|
||||||
|
PageGenreBrowser = 5,
|
||||||
|
};
|
||||||
|
|
||||||
QobuzBackend *m_backend = nullptr;
|
QobuzBackend *m_backend = nullptr;
|
||||||
QStackedWidget *m_stack = nullptr;
|
QStackedWidget *m_stack = nullptr;
|
||||||
QLabel *m_welcome = nullptr;
|
QLabel *m_welcome = nullptr;
|
||||||
|
|||||||
Reference in New Issue
Block a user