mirror of
https://github.com/HenkKalkwater/harbour-sailfin.git
synced 2024-11-22 09:15:18 +00:00
Fix a few bugs regarding loaders and models
* Properly keep track of the current offset and total recourd count in models. * Catch exceptions and store them in errorString properties wherever applicable in loaders.
This commit is contained in:
parent
1aae311b9b
commit
5ee2869db9
|
@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#define JELLYFIN_API_MODEL
|
#define JELLYFIN_API_MODEL
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QFlags>
|
#include <QFlags>
|
||||||
|
@ -114,6 +115,7 @@ protected:
|
||||||
ApiClient *m_apiClient = nullptr;
|
ApiClient *m_apiClient = nullptr;
|
||||||
bool m_autoReload = true;
|
bool m_autoReload = true;
|
||||||
bool m_needsAuthentication = true;
|
bool m_needsAuthentication = true;
|
||||||
|
bool m_manualLimitSet = false;
|
||||||
|
|
||||||
// Query/record controlling properties
|
// Query/record controlling properties
|
||||||
int m_limit = -1;
|
int m_limit = -1;
|
||||||
|
@ -158,7 +160,6 @@ public:
|
||||||
|
|
||||||
void reload() override {
|
void reload() override {
|
||||||
if (!canReload()) {
|
if (!canReload()) {
|
||||||
qDebug() << "Cannot yet reload ApiModel: canReload() returned false.";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_startIndex = 0;
|
m_startIndex = 0;
|
||||||
|
@ -169,7 +170,6 @@ public:
|
||||||
|
|
||||||
void loadMore() {
|
void loadMore() {
|
||||||
if (!canReload()) {
|
if (!canReload()) {
|
||||||
qDebug() << "Cannot yet reload ApiModel: canReload() returned false.";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loadMore(m_startIndex, m_limit, ViewModel::ModelStatus::LoadingMore);
|
loadMore(m_startIndex, m_limit, ViewModel::ModelStatus::LoadingMore);
|
||||||
|
@ -198,10 +198,6 @@ protected:
|
||||||
* Either LOADING or LOAD_MORE.
|
* Either LOADING or LOAD_MORE.
|
||||||
*/
|
*/
|
||||||
virtual void loadMore(int offset, int limit, ViewModel::ModelStatus suggestedStatus) = 0;
|
virtual void loadMore(int offset, int limit, ViewModel::ModelStatus suggestedStatus) = 0;
|
||||||
void updatePosition(int startIndex, int totalRecordCount) {
|
|
||||||
m_startIndex = startIndex;
|
|
||||||
m_totalRecordCount = totalRecordCount;
|
|
||||||
}
|
|
||||||
std::pair<QList<T*>, int> m_result;
|
std::pair<QList<T*>, int> m_result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -211,21 +207,21 @@ protected:
|
||||||
template <class T, class R>
|
template <class T, class R>
|
||||||
QList<T> extractRecords(const R &result) {
|
QList<T> extractRecords(const R &result) {
|
||||||
Q_UNUSED(result)
|
Q_UNUSED(result)
|
||||||
Q_UNIMPLEMENTED();
|
qDebug() << "extractRecords not implemented for type " << typeid(R).name();
|
||||||
return QList<T>();
|
return QList<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class R>
|
template <class R>
|
||||||
int extractTotalRecordCount(const R &result) {
|
int extractTotalRecordCount(const R &result) {
|
||||||
Q_UNUSED(result)
|
Q_UNUSED(result)
|
||||||
Q_UNIMPLEMENTED();
|
qDebug() << "extractTotalRecourdCount not implemented for type " << typeid(R).name();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
template <class R>
|
template <class P>
|
||||||
void setRequestLimit(R ¶meters, int limit) {
|
void setRequestLimit(P ¶meters, int limit) {
|
||||||
Q_UNUSED(parameters)
|
Q_UNUSED(parameters)
|
||||||
Q_UNUSED(limit)
|
Q_UNUSED(limit)
|
||||||
Q_UNIMPLEMENTED();
|
qDebug() << "setRequestLimit not implemented for type " << typeid(P).name();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -235,7 +231,7 @@ template <class P>
|
||||||
bool setRequestStartIndex(P ¶meters, int startIndex) {
|
bool setRequestStartIndex(P ¶meters, int startIndex) {
|
||||||
Q_UNUSED(parameters)
|
Q_UNUSED(parameters)
|
||||||
Q_UNUSED(startIndex)
|
Q_UNUSED(startIndex)
|
||||||
Q_UNIMPLEMENTED();
|
qDebug() << "setRequestStartIndex not implemented for type " << typeid(P).name();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +244,10 @@ extern template QList<DTO::BaseItemDto> extractRecords(const QList<DTO::BaseItem
|
||||||
extern template int extractTotalRecordCount(const QList<DTO::BaseItemDto> &result);
|
extern template int extractTotalRecordCount(const QList<DTO::BaseItemDto> &result);
|
||||||
extern template void setRequestLimit(Loader::GetLatestMediaParams ¶ms, int limit);
|
extern template void setRequestLimit(Loader::GetLatestMediaParams ¶ms, int limit);
|
||||||
extern template bool setRequestStartIndex(Loader::GetLatestMediaParams ¶ms, int offset);
|
extern template bool setRequestStartIndex(Loader::GetLatestMediaParams ¶ms, int offset);
|
||||||
|
extern template void setRequestLimit(Loader::GetItemsByUserIdParams ¶ms, int limit);
|
||||||
|
extern template bool setRequestStartIndex(Loader::GetItemsByUserIdParams ¶ms, int offset);
|
||||||
|
extern template void setRequestLimit(Loader::GetResumeItemsParams ¶ms, int limit);
|
||||||
|
extern template bool setRequestStartIndex(Loader::GetResumeItemsParams ¶ms, int offset);
|
||||||
|
|
||||||
extern template QList<DTO::UserDto> extractRecords(const QList<DTO::UserDto> &result);
|
extern template QList<DTO::UserDto> extractRecords(const QList<DTO::UserDto> &result);
|
||||||
extern template int extractTotalRecordCount(const QList<DTO::UserDto> &result);
|
extern template int extractTotalRecordCount(const QList<DTO::UserDto> &result);
|
||||||
|
@ -285,8 +285,16 @@ protected:
|
||||||
// meaning loadMore is not supported.
|
// meaning loadMore is not supported.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (limit > 0) {
|
if (limit > 0) {
|
||||||
setRequestLimit<P>(this->m_parameters, limit);
|
if (suggestedModelStatus == ViewModel::ModelStatus::Loading) {
|
||||||
|
setRequestLimit<P>(this->m_parameters, limit);
|
||||||
|
} else {
|
||||||
|
// If an explicit limit is set, we should load no more
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setRequestLimit<P>(this->m_parameters, this->DEFAULT_LIMIT);
|
||||||
}
|
}
|
||||||
this->setStatus(suggestedModelStatus);
|
this->setStatus(suggestedModelStatus);
|
||||||
|
|
||||||
|
@ -301,25 +309,32 @@ protected:
|
||||||
P m_parameters;
|
P m_parameters;
|
||||||
|
|
||||||
void loaderReady() {
|
void loaderReady() {
|
||||||
R result = m_loader->result();
|
try {
|
||||||
QList<D> records = extractRecords<D, R>(result);
|
R result = m_loader->result();
|
||||||
int totalRecordCount = extractTotalRecordCount<R>(result);
|
QList<D> records = extractRecords<D, R>(result);
|
||||||
qDebug() << "Total record count: " << totalRecordCount << ", records in request: " << records.size();
|
int totalRecordCount = extractTotalRecordCount<R>(result);
|
||||||
// If totalRecordCount < 0, it is not supported for this endpoint
|
qDebug() << "Total record count: " << totalRecordCount << ", records in request: " << records.size();
|
||||||
if (totalRecordCount < 0) {
|
// If totalRecordCount < 0, it is not supported for this endpoint
|
||||||
totalRecordCount = records.size();
|
if (totalRecordCount < 0) {
|
||||||
}
|
totalRecordCount = records.size();
|
||||||
QList<T*> models;
|
}
|
||||||
models.reserve(records.size());
|
QList<T*> models;
|
||||||
|
models.reserve(records.size());
|
||||||
|
|
||||||
// Convert the DTOs into models
|
// Convert the DTOs into models
|
||||||
for (int i = 0; i < records.size(); i++) {
|
for (int i = 0; i < records.size(); i++) {
|
||||||
models.append(new T(records[i], m_loader->apiClient()));
|
models.append(new T(records[i], m_loader->apiClient()));
|
||||||
|
}
|
||||||
|
this->setStatus(ViewModel::ModelStatus::Ready);
|
||||||
|
this->m_result = { models, this->m_startIndex};
|
||||||
|
this->m_startIndex += records.size();
|
||||||
|
this->m_totalRecordCount = totalRecordCount;
|
||||||
|
this->emitItemsLoaded();
|
||||||
|
|
||||||
|
} catch(QException &e) {
|
||||||
|
qWarning() << "Error while loading data: " << e.what();
|
||||||
|
this->setStatus(ViewModel::ModelStatus::Error);
|
||||||
}
|
}
|
||||||
this->setStatus(ViewModel::ModelStatus::Ready);
|
|
||||||
this->m_result = { models, this->m_startIndex};
|
|
||||||
this->m_startIndex += totalRecordCount;
|
|
||||||
this->emitItemsLoaded();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loaderError(QString error) {
|
void loaderError(QString error) {
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "viewmodel/item.h"
|
#include "viewmodel/item.h"
|
||||||
#include "viewmodel/itemmodel.h"
|
#include "viewmodel/itemmodel.h"
|
||||||
#include "viewmodel/loader.h"
|
#include "viewmodel/loader.h"
|
||||||
|
#include "viewmodel/mediastream.h"
|
||||||
#include "viewmodel/modelstatus.h"
|
#include "viewmodel/modelstatus.h"
|
||||||
#include "viewmodel/playbackmanager.h"
|
#include "viewmodel/playbackmanager.h"
|
||||||
#include "viewmodel/playlist.h"
|
#include "viewmodel/playlist.h"
|
||||||
|
|
|
@ -225,16 +225,16 @@ private:
|
||||||
|
|
||||||
void onResponseParsed() {
|
void onResponseParsed() {
|
||||||
Q_ASSERT(m_parsedWatcher.isFinished());
|
Q_ASSERT(m_parsedWatcher.isFinished());
|
||||||
if (m_parsedWatcher.result().has_value()) {
|
try {
|
||||||
try {
|
if (m_parsedWatcher.result().has_value()) {
|
||||||
this->m_result = m_parsedWatcher.result().value();
|
this->m_result = m_parsedWatcher.result().value();
|
||||||
this->m_isRunning = false;
|
this->m_isRunning = false;
|
||||||
emit this->ready();
|
emit this->ready();
|
||||||
} catch (QException &e) {
|
} else {
|
||||||
this->stopWithError(e.what());
|
this->m_isRunning = false;
|
||||||
}
|
}
|
||||||
} else {
|
} catch (QException &e) {
|
||||||
this->m_isRunning = false;
|
this->stopWithError(e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -141,6 +141,29 @@ bool setRequestStartIndex(Loader::GetLatestMediaParams ¶ms, int offset) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void setRequestLimit(Loader::GetItemsByUserIdParams ¶ms, int limit) {
|
||||||
|
params.setLimit(limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
bool setRequestStartIndex(Loader::GetItemsByUserIdParams ¶ms, int index) {
|
||||||
|
params.setLimit(index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void setRequestLimit(Loader::GetResumeItemsParams ¶ms, int limit) {
|
||||||
|
params.setLimit(limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
bool setRequestStartIndex(Loader::GetResumeItemsParams ¶ms, int index) {
|
||||||
|
params.setLimit(index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
QList<DTO::UserDto> extractRecords(const QList<DTO::UserDto> &result) {
|
QList<DTO::UserDto> extractRecords(const QList<DTO::UserDto> &result) {
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -27,6 +27,7 @@ void registerTypes(const char *uri) {
|
||||||
qmlRegisterUncreatableType<ViewModel::User>(uri, 1, 0, "User", "Acquire one via UserLoader or exposed properties");
|
qmlRegisterUncreatableType<ViewModel::User>(uri, 1, 0, "User", "Acquire one via UserLoader or exposed properties");
|
||||||
qmlRegisterUncreatableType<EventBus>(uri, 1, 0, "EventBus", "Obtain one via your ApiClient");
|
qmlRegisterUncreatableType<EventBus>(uri, 1, 0, "EventBus", "Obtain one via your ApiClient");
|
||||||
qmlRegisterUncreatableType<WebSocket>(uri, 1, 0, "WebSocket", "Obtain one via your ApiClient");
|
qmlRegisterUncreatableType<WebSocket>(uri, 1, 0, "WebSocket", "Obtain one via your ApiClient");
|
||||||
|
qmlRegisterUncreatableType<ViewModel::MediaStream>(uri, 1, 0, "MediaStream", "Obtain one via an Item");
|
||||||
qmlRegisterUncreatableType<ViewModel::UserData>(uri, 1, 0, "UserData", "Obtain one via an Item");
|
qmlRegisterUncreatableType<ViewModel::UserData>(uri, 1, 0, "UserData", "Obtain one via an Item");
|
||||||
|
|
||||||
// AbstractItemModels
|
// AbstractItemModels
|
||||||
|
@ -53,6 +54,7 @@ void registerTypes(const char *uri) {
|
||||||
qmlRegisterUncreatableType<Jellyfin::ViewModel::ModelStatusClass>(uri, 1, 0, "ModelStatus", "Is an enum");
|
qmlRegisterUncreatableType<Jellyfin::ViewModel::ModelStatusClass>(uri, 1, 0, "ModelStatus", "Is an enum");
|
||||||
qmlRegisterUncreatableType<Jellyfin::DTO::PlayMethodClass>(uri, 1, 0, "PlayMethod", "Is an enum");
|
qmlRegisterUncreatableType<Jellyfin::DTO::PlayMethodClass>(uri, 1, 0, "PlayMethod", "Is an enum");
|
||||||
qmlRegisterUncreatableType<Jellyfin::DTO::ItemFieldsClass>(uri, 1, 0, "ItemFields", "Is an enum");
|
qmlRegisterUncreatableType<Jellyfin::DTO::ItemFieldsClass>(uri, 1, 0, "ItemFields", "Is an enum");
|
||||||
|
qmlRegisterUncreatableType<Jellyfin::DTO::ImageTypeClass>(uri, 1, 0, "ImageType", "Is an enum");
|
||||||
qmlRegisterUncreatableType<Jellyfin::ViewModel::NowPlayingSection>(uri, 1, 0, "NowPlayingSection", "Is an enum");
|
qmlRegisterUncreatableType<Jellyfin::ViewModel::NowPlayingSection>(uri, 1, 0, "NowPlayingSection", "Is an enum");
|
||||||
|
|
||||||
qRegisterMetaType<Jellyfin::DTO::PlayMethodClass::Value>();
|
qRegisterMetaType<Jellyfin::DTO::PlayMethodClass::Value>();
|
||||||
|
|
Loading…
Reference in a new issue