1
0
Fork 0
mirror of https://github.com/HenkKalkwater/harbour-sailfin.git synced 2025-09-05 10:12:46 +00:00

WIP: Slowly bringing back viewmodels

This commit is contained in:
Chris Josten 2021-03-29 23:48:16 +02:00
parent 9abee12658
commit 228f81984b
17 changed files with 292 additions and 96 deletions

View file

@ -62,7 +62,7 @@ void BaseModelLoader::setApiClient(ApiClient *newApiClient) {
void BaseModelLoader::setLimit(int newLimit) {
int oldLimit = this->m_limit;
m_limit = newLimit;
if (oldLimit != this->m_limit) {
if (oldLimit != newLimit) {
emit limitChanged(this->m_limit);
}
}
@ -76,6 +76,7 @@ void BaseModelLoader::setAutoReload(bool newAutoReload) {
bool BaseModelLoader::canReload() const {
return m_apiClient != nullptr
&& !m_isBeingParsed
// If the loader for this model needs authentication (almost every one does)
// block if the ApiClient is not authenticated yet.
&& (!m_needsAuthentication || m_apiClient->authenticated())
@ -88,6 +89,8 @@ void BaseApiModel::reload() {
qWarning() << " BaseApiModel slot called instead of overloaded method";
}
// Parameters injectors and result extractors
template <>
bool setRequestStartIndex(Loader::GetUserViewsParams &params, int startIndex) {
// Not supported
@ -112,6 +115,28 @@ int extractTotalRecordCount(const DTO::BaseItemDtoQueryResult &result) {
return result.totalRecordCount();
}
template <>
QList<DTO::BaseItemDto> extractRecords(const QList<DTO::BaseItemDto> &result) {
return result;
}
template <>
int extractTotalRecordCount(const QList<DTO::BaseItemDto> &result) {
return result.size();
}
template<>
void setRequestLimit(Loader::GetLatestMediaParams &params, int limit) {
params.setLimit(limit);
}
template<>
bool setRequestStartIndex(Loader::GetLatestMediaParams &params, int offset) {
Q_UNUSED(params)
Q_UNUSED(offset)
return false;
}
void registerModels(const char *URI) {
Q_UNUSED(URI)

View file

@ -22,20 +22,25 @@ namespace Jellyfin {
void registerTypes(const char *uri) {
qmlRegisterType<ApiClient>(uri, 1, 0, "ApiClient");
qmlRegisterType<ServerDiscoveryModel>(uri, 1, 0, "ServerDiscoveryModel");
qmlRegisterType<ViewModel::PlaybackManager>(uri, 1, 0, "PlaybackManager");
qmlRegisterUncreatableType<ViewModel::Item>(uri, 1, 0, "Item", "Acquire one via ItemLoader or exposed properties");
qmlRegisterUncreatableType<WebSocket>(uri, 1, 0, "WebSocket", "Obtain one via your ApiClient");
// AbstractItemModels
qmlRegisterUncreatableType<BaseApiModel>(uri, 1, 0, "BaseApiModel", "Please use one of its subclasses");
qmlRegisterUncreatableType<BaseModelLoader>(uri, 1, 0, "BaseModelLoader", "Please use one of its subclasses");
qmlRegisterUncreatableType<ViewModel::LoaderBase>(uri, 1, 0, "LoaderBase", "Use on eof its subclasses");
qmlRegisterUncreatableType<ViewModel::Item>(uri, 1, 0, "Item", "Acquire one via ItemLoader or exposed properties");
qmlRegisterType<ViewModel::ItemLoader>(uri, 1, 0, "ItemLoader");
qmlRegisterType<ViewModel::ItemModel>(uri, 1, 0, "ItemModel");
qmlRegisterType<ViewModel::UserViewsLoader>(uri, 1, 0, "UsersViewLoader");
qmlRegisterType<ViewModel::PlaybackManager>(uri, 1, 0, "PlaybackManager");
// Loaders
qmlRegisterUncreatableType<ViewModel::LoaderBase>(uri, 1, 0, "LoaderBase", "Use one of its subclasses");
qmlRegisterType<ViewModel::ItemLoader>(uri, 1, 0, "ItemLoader");
qmlRegisterType<ViewModel::LatestMediaLoader>(uri, 1, 0, "LatestMediaLoader");
qmlRegisterType<ViewModel::UserItemsLoader>(uri, 1, 0, "UserItemsLoader");
qmlRegisterType<ViewModel::UserViewsLoader>(uri, 1, 0, "UsersViewsLoader");
// Enumerations
qmlRegisterUncreatableType<DTO::GeneralCommandTypeClass>(uri, 1, 0, "GeneralCommandType", "Is an enum");
qmlRegisterUncreatableType<ViewModel::ModelStatusClass>(uri, 1, 0, "ModelStatus", "Is an enum");
}
}

View file

@ -22,6 +22,10 @@
namespace Jellyfin {
namespace Model {
Item::Item()
: Item(DTO::BaseItemDto(), nullptr) { }
Item::Item(const DTO::BaseItemDto &data, ApiClient *apiClient)
: DTO::BaseItemDto(data), m_apiClient(apiClient) {
if (m_apiClient != nullptr) {

View file

@ -149,8 +149,14 @@ QJsonValue toJsonValue<QStringList>(const QStringList &source, convertType<QStri
// QJsonObject
template <>
QJsonObject fromJsonValue<QJsonObject>(const QJsonValue &source, convertType<QJsonObject>) {
if (!source.isObject()) throw ParseException("Error parsing JSON value as object: not a double");
return source.toObject();
switch(source.type()) {
case QJsonValue::Null:
return QJsonObject();
case QJsonValue::Object:
return source.toObject();
default:
throw ParseException("Error parsing JSON value as object: not an object");
}
}
template <>
@ -161,7 +167,7 @@ QJsonValue toJsonValue<QJsonObject>(const QJsonObject &source, convertType<QJson
// Double
template <>
double fromJsonValue<double>(const QJsonValue &source, convertType<double>) {
if (!source.isDouble()) throw ParseException("Error parsing JSON value as integer: not a double");
if (!source.isDouble()) throw ParseException("Error parsing JSON value as double: not a double");
return source.toDouble();
}
@ -170,6 +176,18 @@ QJsonValue toJsonValue<double>(const double &source, convertType<double>) {
return QJsonValue(source);
}
// Float
template <>
float fromJsonValue<float>(const QJsonValue &source, convertType<float>) {
if (!source.isDouble()) throw ParseException("Error parsing JSON value as float: not a double");
return static_cast<float>(source.toDouble());
}
template <>
QJsonValue toJsonValue<float>(const float &source, convertType<float>) {
return QJsonValue(static_cast<double>(source));
}
// QDateTime
template <>
QDateTime fromJsonValue<QDateTime>(const QJsonValue &source, convertType<QDateTime>) {
@ -205,27 +223,37 @@ QJsonValue toJsonValue<QUuid>(const QUuid &source, convertType<QUuid>) {
// String types
template <>
QString toString(const QUuid &source) {
QString toString(const QUuid &source, convertType<QUuid>) {
return uuidToString(source);
}
template <>
QString toString(const qint32 &source) {
QString toString(const qint32 &source, convertType<qint32>) {
return QString::number(source);
}
template <>
QString toString(const qint64 &source) {
QString toString(const qint64 &source, convertType<qint64>) {
return QString::number(source);
}
template <>
QString toString(const bool &source) {
QString toString(const float &source, convertType<float>) {
return QString::number(source);
}
template <>
QString toString(const double &source, convertType<double>) {
return QString::number(source);
}
template <>
QString toString(const bool &source, convertType<bool>) {
return source ? QStringLiteral("true") : QStringLiteral("false");
}
template <>
QString toString(const QString &source) {
QString toString(const QString &source, convertType<QString>) {
return source;
}

View file

@ -21,11 +21,10 @@
namespace Jellyfin {
namespace ViewModel {
Item::Item(QObject *parent)
: Item(nullptr, parent){}
Item::Item(QObject *parent, QSharedPointer<Model::Item> data)
: QObject(parent), m_data(data){
Item::Item(QSharedPointer<Model::Item> data, QObject *parent)
: QObject(parent), m_data(data){}
}
void Item::setData(QSharedPointer<Model::Item> newData) {
Model::Item oldData = *m_data.data();
@ -36,7 +35,8 @@ void Item::setData(QSharedPointer<Model::Item> newData) {
// ItemLoader
ItemLoader::ItemLoader(QObject *parent)
: BaseClass(Jellyfin::Loader::HTTP::GetItemLoader(), parent) {
: BaseClass(new Jellyfin::Loader::HTTP::GetItemLoader(), parent) {
connect(this, &LoaderBase::apiClientChanged, this, &ItemLoader::onApiClientChanged);
}
void ItemLoader::onApiClientChanged(ApiClient *newApiClient) {
@ -54,7 +54,9 @@ void ItemLoader::setUserId(const QString &newUserId) {
}
bool ItemLoader::canReload() const {
return BaseClass::canReload() && !m_parameters.itemId().isEmpty();
return BaseClass::canReload()
&& !m_parameters.itemId().isEmpty()
&& !m_parameters.userId().isEmpty();
}
}

View file

@ -18,6 +18,9 @@
*/
#include "JellyfinQt/viewmodel/itemmodel.h"
#include "JellyfinQt/loader/http/getlatestmedia.h"
#include "JellyfinQt/loader/http/getitemsbyuserid.h"
#define JF_CASE(roleName) case roleName: \
try { \
return QVariant(item.roleName()); \
@ -30,37 +33,13 @@ namespace Jellyfin {
namespace ViewModel {
UserViewsLoader::UserViewsLoader(QObject *parent)
: UserViewsLoaderBase(new Jellyfin::Loader::HTTP::GetUserViewsLoader(), parent) {
connect(this, &BaseModelLoader::apiClientChanged, this, &UserViewsLoader::apiClientChanged);
}
: UserViewsLoaderBase(new Jellyfin::Loader::HTTP::GetUserViewsLoader(), parent) { }
void UserViewsLoader::apiClientChanged(ApiClient *newApiClient) {
if (m_apiClient != nullptr) disconnect(m_apiClient, &ApiClient::userIdChanged, this, &UserViewsLoader::userIdChanged);
if (newApiClient != nullptr) {
connect(newApiClient, &ApiClient::userIdChanged, this, &UserViewsLoader::userIdChanged);
if (!newApiClient->userId().isNull()) {
m_parameters.setUserId(newApiClient->userId());
}
}
}
LatestMediaLoader::LatestMediaLoader(QObject *parent)
: LatestMediaBase(new Jellyfin::Loader::HTTP::GetLatestMediaLoader(), parent){ }
void UserViewsLoader::userIdChanged(const QString &newUserId) {
m_parameters.setUserId(newUserId);
autoReloadIfNeeded();
}
void UserItemsLoader::apiClientChanged(ApiClient *newApiClient) {
if (m_apiClient != nullptr) disconnect(m_apiClient, &ApiClient::userIdChanged, this, &UserItemsLoader::userIdChanged);
if (newApiClient != nullptr) connect(newApiClient, &ApiClient::userIdChanged, this, &UserItemsLoader::userIdChanged);
}
void UserItemsLoader::userIdChanged(const QString &newUserId) {
m_parameters.setUserId(newUserId);
autoReloadIfNeeded();
}
bool UserItemsLoader::canReload() const {
return BaseModelLoader::canReload() && !m_parameters.userId().isNull();
}
UserItemsLoader::UserItemsLoader(QObject *parent)
: UserItemsLoaderBase(new Jellyfin::Loader::HTTP::GetItemsByUserIdLoader(), parent) {}
ItemModel::ItemModel(QObject *parent)
: ApiModel<Model::Item>(parent) { }
@ -81,6 +60,8 @@ QVariant ItemModel::data(const QModelIndex &index, int role) const {
JF_CASE(dateCreated)
JF_CASE(dateLastMediaAdded)
JF_CASE(extraType)
// Handpicked, important ones
JF_CASE(imageTags)
default:
return QVariant();
}