Files
audiotube/src/localplaylistsmodel.cpp
T

126 lines
4.3 KiB
C++

// SPDX-FileCopyrightText: 2022 Jonah Brüchert <[email protected]>
//
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include "localplaylistsmodel.h"
#include "playlistutils.h"
#include "library.h"
#include <qglobal.h>
#include <qsqldatabase.h>
#include <threadeddatabase.h>
#include <KLocalizedString>
Q_DECLARE_METATYPE(std::vector<QString>);
LocalPlaylistsModel::LocalPlaylistsModel(QObject *parent)
: QAbstractListModel(parent)
{
importer = new PlaylistImporter(this);
connect(importer, &PlaylistImporter::playlistEntriesChanged, this, &LocalPlaylistsModel::playlistEntriesChanged);
connect(importer,&PlaylistImporter::importFinished, this, &LocalPlaylistsModel::importFinished);
connect(importer, &PlaylistImporter::refreshModel, this, &LocalPlaylistsModel::refreshModel);
connect(&Library::instance(), &Library::playlistsChanged,
this, &LocalPlaylistsModel::refreshModel);
refreshModel();
}
int LocalPlaylistsModel::rowCount(const QModelIndex &index) const
{
return index.isValid() ? 0 : m_playlists.size();
}
QHash<int, QByteArray> LocalPlaylistsModel::roleNames() const
{
return {
{Roles::PlaylistId, "playlistId"},
{Roles::Title, "title"},
{Roles::Description, "description"},
{Roles::CreatedOn, "createdOn"},
{Roles::ThumbnailIds, "thumbnailIds"},
};
}
QVariant LocalPlaylistsModel::data(const QModelIndex &index, int role) const
{
switch (role) {
case Roles::PlaylistId:
return m_playlists[index.row()].playlistId;
case Roles::Title:
return m_playlists[index.row()].title;
case Roles::Description:
return m_playlists[index.row()].description;
case Roles::CreatedOn:
return m_playlists[index.row()].createdOn;
case Roles::ThumbnailIds:
return QVariant::fromValue(m_thumbnailIds.at(index.row()));
}
Q_UNREACHABLE();
}
void LocalPlaylistsModel::refreshModel()
{
QCoro::connect(Library::instance().database().getResults<Playlist>("select * from playlists"), this, [this](const auto &&playlists) {
m_thumbnailIds.resize(playlists.size());
for (size_t i = 0; i < playlists.size(); i++) {
auto future = Library::instance().database().getResults<SingleValue<QString>>("select video_id from playlist_entries where playlist_id = ? order by random() limit 4", playlists.at(i).playlistId);
QCoro::connect(std::move(future), this, [this, playlists, i](auto &&ids) {
std::ranges::transform(ids, std::back_inserter(m_thumbnailIds[i]), [](auto &&id) { return id.value; });
dataChanged(index(i), index(i), {Roles::ThumbnailIds});
});
}
beginResetModel();
m_playlists = playlists;
endResetModel();
});
}
void LocalPlaylistsModel::addPlaylist(const QString &title, const QString &description)
{
QCoro::connect(Library::instance().database().execute("insert into playlists (title, description) values (?, ?)", title, description), &Library::instance(), &Library::playlistsChanged);
}
void LocalPlaylistsModel::addPlaylistEntry(qint64 playlistId, const QString &videoId, const QString &title, const QString &artist, const QString &album)
{
importer->addPlaylistEntry(playlistId, videoId, title, artist, album);
}
void LocalPlaylistsModel::addPlaylistEntry(qint64 playlistId, const playlist::Track &track)
{
importer->addPlaylistEntry(playlistId, track);
}
void LocalPlaylistsModel::importPlaylist(const QString &url)
{
importer->importPlaylist(url);
}
void LocalPlaylistsModel::renamePlaylist(qint64 playlistId, const QString &name, const QString &description)
{
importer->renamePlaylist(playlistId, name, description);
}
void LocalPlaylistsModel::deletePlaylist(qint64 playlistId)
{
QCoro::connect(Library::instance().database().execute("delete from playlists where playlist_id = ?", playlistId), this, &LocalPlaylistsModel::refreshModel);
}
QStringView LocalPlaylistsModel::cropURL(QStringView srcUrl)
{
// Find entry point
constexpr auto urlFragment = QStringView(u"?list=");
qsizetype urlPos = srcUrl.indexOf(urlFragment);
if (urlPos != -1) {
urlPos += urlFragment.size();
} else {
urlPos = 0;
}
auto mid = srcUrl.mid(urlPos);
// Find exit point
urlPos = std::min(mid.indexOf(u"?"), mid.indexOf(u"&"));
return mid.mid(0, urlPos);
}