20#ifndef JELLYFIN_API_MODEL
21#define JELLYFIN_API_MODEL
26#include <QAbstractListModel>
29#include <QFutureWatcher>
32#include <QJsonDocument>
34#include <QtConcurrent/QtConcurrent>
36#include <QQmlParserStatus>
69 Q_INTERFACES(QQmlParserStatus)
91 Q_INVOKABLE
virtual void reload() {};
133 if (this->m_status != newStatus) {
134 this->m_status = newStatus;
136 if (this->m_status == ViewModel::ModelStatus::Ready) {
171 loadMore(ViewModel::ModelStatus::Loading);
178 loadMore(ViewModel::ModelStatus::LoadingMore);
208template <
class T,
class R>
211 qDebug() <<
"extractRecords not implemented for type " <<
typeid(
R).name();
218 qDebug() <<
"extractTotalRecourdCount not implemented for type " <<
typeid(
R).name();
225 qDebug() <<
"setRequestLimit not implemented for type " <<
typeid(P).name();
235 qDebug() <<
"setRequestStartIndex not implemented for type " <<
typeid(P).name();
239#ifndef JELLYFIN_APIMODEL_CPP
241extern template void setRequestLimit(Loader::GetUserViewsParams ¶ms,
int limit);
248extern template void setRequestLimit(Loader::GetLatestMediaParams ¶ms,
int limit);
251extern template void setRequestLimit(Loader::GetItemsByUserIdParams ¶ms,
int limit);
254extern template void setRequestLimit(Loader::GetResumeItemsParams ¶ms,
int limit);
257extern template void setRequestLimit(Loader::GetPublicUsersParams ¶ms,
int limit);
260extern template void setRequestLimit(Loader::GetNextUpParams ¶ms,
int limit);
263extern template void setRequestLimit(Loader::GetAlbumArtistsParams ¶ms,
int limit);
266extern template void setRequestLimit(Loader::GetLiveTvChannelsParams ¶ms,
int limit);
281template <
class T,
class D,
class R,
class P>
285 :
ModelLoader<T>(parent), m_loader(QScopedPointer<Support::Loader<
R, P>>(loader)) {
293 if (m_loader->isRunning()) {
300 && suggestedModelStatus == ViewModel::ModelStatus::LoadingMore) {
307 if (suggestedModelStatus == ViewModel::ModelStatus::LoadingMore && this->m_explicitLimitSet) {
312 qCDebug(jellyfinApiModel) <<
"Explicit limit set: " << this->m_explicitLimitSet <<
", " << this->m_limit;
313 if (this->m_explicitLimitSet) {
318 this->setStatus(suggestedModelStatus);
322 this->m_loader->setApiClient(this->m_apiClient);
323 this->m_loader->setParameters(this->m_parameters);
324 this->m_loader->load();
332 R result = m_loader->result();
335 qDebug() <<
"Total record count: " << totalRecordCount <<
", records in request: " << records.size();
337 if (totalRecordCount < 0) {
338 totalRecordCount = records.size();
341 models.reserve(records.size());
344 for (
int i = 0; i < records.size(); i++) {
345 models.append(
new T(records[i], m_loader->apiClient()));
347 this->setStatus(ViewModel::ModelStatus::Ready);
348 this->m_result = { models, this->m_startIndex};
349 this->m_startIndex += records.size();
350 this->m_totalRecordCount = totalRecordCount;
351 this->emitItemsLoaded();
353 }
catch(QException &e) {
354 qWarning() <<
"Error while loading data: " << e.what();
355 this->setStatus(ViewModel::ModelStatus::Error);
361 this->setStatus(ViewModel::ModelStatus::Error);
370 : QAbstractListModel (parent) {}
379 emit loaderChanged();
382 if (oldLoader !=
nullptr) {
384 disconnect(oldLoader,
nullptr,
this,
nullptr);
388 virtual void reload() = 0;
440 int rowCount(
const QModelIndex &index)
const override {
441 if (!index.isValid())
return m_array.size();
446 QSharedPointer<T>
at(
int index)
const {
return m_array.at(index); }
451 return m_array.size();
454 void insert(
int index, QSharedPointer<T>
object) {
455 Q_ASSERT(index >= 0 && index <= size());
456 this->beginInsertRows(QModelIndex(), index, index);
457 m_array.insert(index,
object);
458 this->endInsertRows();
461 void append(QSharedPointer<T>
object) { insert(size(),
object); }
465 this->beginInsertRows(QModelIndex(), index, index + objects.size() - 1);
466 m_array.append(objects);
467 this->endInsertRows();
471 return m_array.mid(pos, length);
475 Q_ASSERT(index < size());
476 this->beginRemoveRows(QModelIndex(), index, index);
477 m_array.removeAt(index);
478 this->endRemoveRows();
482 this->beginRemoveRows(QModelIndex(), from , m_array.size());
483 while (m_array.size() != from) {
484 m_array.removeLast();
486 this->endRemoveRows();
490 int idx = m_array.indexOf(
object);
497 this->beginResetModel();
499 this->endResetModel();
510 if (parent.isValid())
return false;
511 if (m_loader ==
nullptr)
return false;
512 return m_loader->canLoadMore();
514 virtual void fetchMore(
const QModelIndex &parent)
override {
515 if (parent.isValid())
return;
516 if (m_loader !=
nullptr) {
517 m_loader->loadMore();
527 if (castedLoader !=
nullptr) {
531 m_loader = castedLoader;
534 qWarning() <<
"Somehow set a BaseModelLoader on ApiModel instead of a ModelLoader<T>";
539 if (m_loader !=
nullptr) {
550 Q_ASSERT(m_loader !=
nullptr);
551 std::pair<QList<T*>,
int> result = m_loader->
result();
552 qDebug() <<
"Results loaded: index: " << result.second <<
", count: " << result.first.size();
553 if (result.second == -1) {
555 }
else if (result.second == m_array.size()) {
556 m_array.reserve(m_array.size() + result.second);
557 for (
auto it = result.first.begin(); it != result.first.end(); it++) {
558 append(QSharedPointer<T>(*it));
560 }
else if (result.second < m_array.size()){
561 removeUntilEnd(result.second);
562 m_array.reserve(m_array.size() + result.second);
563 for (
auto it = result.first.begin(); it != result.first.end(); it++) {
564 append(QSharedPointer<T>(*it));
568 qWarning() <<
"Retrieved data from loader at position bigger than size()";
572 QMetaObject::Connection m_futureWatcherConnection;
An Api client for Jellyfin. Handles requests and authentication.
Definition apiclient.h:90
Abstract model for displaying collections.
Definition apimodel.h:405
void removeAt(int index)
Definition apimodel.h:474
virtual bool canFetchMore(const QModelIndex &parent) const override
Definition apimodel.h:509
void clear() override
Definition apimodel.h:496
void removeUntilEnd(int from)
Definition apimodel.h:481
QList< QSharedPointer< T > > m_array
Definition apimodel.h:546
void loadingFinished() override
Definition apimodel.h:549
void setLoader(BaseModelLoader *newLoader)
Definition apimodel.h:525
ApiModel(QObject *parent=nullptr)
Creates a new basemodel.
Definition apimodel.h:435
int rowCount(const QModelIndex &index) const override
Definition apimodel.h:440
void append(QList< QSharedPointer< T > > &objects)
Definition apimodel.h:463
void removeOne(QSharedPointer< T > object)
Definition apimodel.h:489
QList< T * > mid(int pos, int length=-1)
Definition apimodel.h:470
void append(QSharedPointer< T > object)
Definition apimodel.h:461
int size() const
Definition apimodel.h:450
void insert(int index, QSharedPointer< T > object)
Definition apimodel.h:454
const QList< QSharedPointer< T > > & toList()
Definition apimodel.h:502
void reload() override
Definition apimodel.h:538
virtual void fetchMore(const QModelIndex &parent) override
Definition apimodel.h:514
BaseModelLoader * loader() const override
Definition apimodel.h:521
QSharedPointer< T > at(int index) const
Definition apimodel.h:446
Definition apimodel.h:366
void disconnectOldLoader(BaseModelLoader *oldLoader)
Definition apimodel.h:381
virtual void reload()=0
Definition apimodel.cpp:94
virtual void loadingFinished()=0
BaseApiModel(QObject *parent=nullptr)
Definition apimodel.h:369
virtual void setLoader(BaseModelLoader *newLoader)
Definition apimodel.h:375
void modelShouldClear()
Emitted when the model should clear itself.
int limit() const
Definition apimodel.h:81
int m_totalRecordCount
Definition apimodel.h:125
int m_limit
Definition apimodel.h:123
void setLimit(int newLimit)
Definition apimodel.cpp:65
bool m_isBeingParsed
Definition apimodel.h:116
BaseModelLoader(QObject *parent=nullptr)
Definition apimodel.cpp:37
int limit
Definition apimodel.h:75
int m_startIndex
Definition apimodel.h:124
void limitChanged(int newLimit)
ApiClient * apiClient
Definition apimodel.h:73
virtual void classBegin() override
Definition apimodel.cpp:40
bool m_needsAuthentication
Definition apimodel.h:119
void setAutoReload(bool newAutoReload)
Definition apimodel.cpp:72
bool autoReload
Definition apimodel.h:76
ViewModel::ModelStatus status() const
Definition apimodel.h:86
const int DEFAULT_LIMIT
Definition apimodel.h:127
Jellyfin::ViewModel::ModelStatusClass::Value status
Definition apimodel.h:74
bool m_explicitLimitSet
Definition apimodel.h:126
void emitItemsLoaded()
Definition apimodel.h:129
void autoReloadIfNeeded()
Definition apimodel.cpp:49
virtual Q_INVOKABLE void reload()
Clears and reloads the model.
Definition apimodel.h:91
void apiClientChanged(ApiClient *newApiClient)
void emitModelShouldClear()
Definition apimodel.h:128
void autoReloadChanged(bool newAutoReload)
bool m_autoReload
Definition apimodel.h:118
ViewModel::ModelStatus m_status
Definition apimodel.h:131
virtual void componentComplete() override
Definition apimodel.cpp:44
void setApiClient(ApiClient *newApiClient)
Definition apimodel.cpp:56
void setStatus(ViewModel::ModelStatus newStatus)
Definition apimodel.h:132
bool m_manualLimitSet
Definition apimodel.h:120
virtual bool canReload() const
Determines if this model is able to reload.
Definition apimodel.cpp:83
ApiClient * m_apiClient
Definition apimodel.h:117
bool autoReload() const
Definition apimodel.h:83
Definition apimodel.h:282
void loaderError(QString error)
Definition apimodel.h:359
QScopedPointer< Support::Loader< R, P > > m_loader
Definition apimodel.h:327
P m_parameters
Definition apimodel.h:328
void loaderReady()
Definition apimodel.h:330
void loadMore(ViewModel::ModelStatus suggestedModelStatus) override
Loads data from the given offset with a maximum count of limit. The itemsLoaded() signal is emitted w...
Definition apimodel.h:290
LoaderModelLoader(Support::Loader< R, P > *loader, QObject *parent=nullptr)
Definition apimodel.h:284
Definition apimodel.h:158
virtual bool canLoadMore() const
Definition apimodel.h:181
virtual void loadMore(ViewModel::ModelStatus suggestedStatus)=0
Loads data from the given offset with a maximum count of limit. The itemsLoaded() signal is emitted w...
void reload() override
Clears and reloads the model.
Definition apimodel.h:164
void loadMore()
Definition apimodel.h:174
std::pair< QList< T * >, int > m_result
Definition apimodel.h:202
std::pair< QList< T * >, int > && result()
Holds the result. Moves it result to the caller and therefore can be only called once when the itemsL...
Definition apimodel.h:191
ModelLoader(QObject *parent=nullptr)
Definition apimodel.h:160
Value
Definition modelstatus.h:32
Definition mediaplayer2.h:20
QList< T > extractRecords(const R &result)
Definition apimodel.h:209
void setRequestLimit(P ¶meters, int limit)
Definition apimodel.h:222
int extractTotalRecordCount(const R &result)
Definition apimodel.h:216
bool setRequestStartIndex(P ¶meters, int startIndex)
Definition apimodel.h:232
void writeRequestTypesFile R(File headerFile, File implementationFile, R endpoints) if(is(ElementType!R
Definition openapigenerator.d:278
Q_DECLARE_LOGGING_CATEGORY(jellyfinWebSocket)