mirror of
https://github.com/HenkKalkwater/harbour-sailfin.git
synced 2024-12-22 14:05: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
|
||||
|
||||
#include <optional>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QFlags>
|
||||
|
@ -114,6 +115,7 @@ protected:
|
|||
ApiClient *m_apiClient = nullptr;
|
||||
bool m_autoReload = true;
|
||||
bool m_needsAuthentication = true;
|
||||
bool m_manualLimitSet = false;
|
||||
|
||||
// Query/record controlling properties
|
||||
int m_limit = -1;
|
||||
|
@ -158,7 +160,6 @@ public:
|
|||
|
||||
void reload() override {
|
||||
if (!canReload()) {
|
||||
qDebug() << "Cannot yet reload ApiModel: canReload() returned false.";
|
||||
return;
|
||||
}
|
||||
m_startIndex = 0;
|
||||
|
@ -169,7 +170,6 @@ public:
|
|||
|
||||
void loadMore() {
|
||||
if (!canReload()) {
|
||||
qDebug() << "Cannot yet reload ApiModel: canReload() returned false.";
|
||||
return;
|
||||
}
|
||||
loadMore(m_startIndex, m_limit, ViewModel::ModelStatus::LoadingMore);
|
||||
|
@ -198,10 +198,6 @@ protected:
|
|||
* Either LOADING or LOAD_MORE.
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -211,21 +207,21 @@ protected:
|
|||
template <class T, class R>
|
||||
QList<T> extractRecords(const R &result) {
|
||||
Q_UNUSED(result)
|
||||
Q_UNIMPLEMENTED();
|
||||
qDebug() << "extractRecords not implemented for type " << typeid(R).name();
|
||||
return QList<T>();
|
||||
}
|
||||
|
||||
template <class R>
|
||||
int extractTotalRecordCount(const R &result) {
|
||||
Q_UNUSED(result)
|
||||
Q_UNIMPLEMENTED();
|
||||
qDebug() << "extractTotalRecourdCount not implemented for type " << typeid(R).name();
|
||||
return -1;
|
||||
}
|
||||
template <class R>
|
||||
void setRequestLimit(R ¶meters, int limit) {
|
||||
template <class P>
|
||||
void setRequestLimit(P ¶meters, int limit) {
|
||||
Q_UNUSED(parameters)
|
||||
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) {
|
||||
Q_UNUSED(parameters)
|
||||
Q_UNUSED(startIndex)
|
||||
Q_UNIMPLEMENTED();
|
||||
qDebug() << "setRequestStartIndex not implemented for type " << typeid(P).name();
|
||||
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 void setRequestLimit(Loader::GetLatestMediaParams ¶ms, int limit);
|
||||
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 int extractTotalRecordCount(const QList<DTO::UserDto> &result);
|
||||
|
@ -285,8 +285,16 @@ protected:
|
|||
// meaning loadMore is not supported.
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -301,25 +309,32 @@ protected:
|
|||
P m_parameters;
|
||||
|
||||
void loaderReady() {
|
||||
R result = m_loader->result();
|
||||
QList<D> records = extractRecords<D, R>(result);
|
||||
int totalRecordCount = extractTotalRecordCount<R>(result);
|
||||
qDebug() << "Total record count: " << totalRecordCount << ", records in request: " << records.size();
|
||||
// If totalRecordCount < 0, it is not supported for this endpoint
|
||||
if (totalRecordCount < 0) {
|
||||
totalRecordCount = records.size();
|
||||
}
|
||||
QList<T*> models;
|
||||
models.reserve(records.size());
|
||||
try {
|
||||
R result = m_loader->result();
|
||||
QList<D> records = extractRecords<D, R>(result);
|
||||
int totalRecordCount = extractTotalRecordCount<R>(result);
|
||||
qDebug() << "Total record count: " << totalRecordCount << ", records in request: " << records.size();
|
||||
// If totalRecordCount < 0, it is not supported for this endpoint
|
||||
if (totalRecordCount < 0) {
|
||||
totalRecordCount = records.size();
|
||||
}
|
||||
QList<T*> models;
|
||||
models.reserve(records.size());
|
||||
|
||||
// Convert the DTOs into models
|
||||
for (int i = 0; i < records.size(); i++) {
|
||||
models.append(new T(records[i], m_loader->apiClient()));
|
||||
// Convert the DTOs into models
|
||||
for (int i = 0; i < records.size(); i++) {
|
||||
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) {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "viewmodel/item.h"
|
||||
#include "viewmodel/itemmodel.h"
|
||||
#include "viewmodel/loader.h"
|
||||
#include "viewmodel/mediastream.h"
|
||||
#include "viewmodel/modelstatus.h"
|
||||
#include "viewmodel/playbackmanager.h"
|
||||
#include "viewmodel/playlist.h"
|
||||
|
|
|
@ -225,16 +225,16 @@ private:
|
|||
|
||||
void onResponseParsed() {
|
||||
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_isRunning = false;
|
||||
emit this->ready();
|
||||
} catch (QException &e) {
|
||||
this->stopWithError(e.what());
|
||||
} else {
|
||||
this->m_isRunning = false;
|
||||
}
|
||||
} else {
|
||||
this->m_isRunning = false;
|
||||
} catch (QException &e) {
|
||||
this->stopWithError(e.what());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -141,6 +141,29 @@ bool setRequestStartIndex(Loader::GetLatestMediaParams ¶ms, int offset) {
|
|||
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<>
|
||||
QList<DTO::UserDto> extractRecords(const QList<DTO::UserDto> &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<EventBus>(uri, 1, 0, "EventBus", "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");
|
||||
|
||||
// AbstractItemModels
|
||||
|
@ -53,6 +54,7 @@ void registerTypes(const char *uri) {
|
|||
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::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");
|
||||
|
||||
qRegisterMetaType<Jellyfin::DTO::PlayMethodClass::Value>();
|
||||
|
|
Loading…
Reference in a new issue