1
0
Fork 0
mirror of https://github.com/HenkKalkwater/harbour-sailfin.git synced 2025-09-04 01:42:44 +00:00

Rewire more of Sailfish frontend into new backend

This should encompass most simple things, besides some larger, trickier
things, like the video streams and the now-broken userdata
This commit is contained in:
Chris Josten 2021-08-11 23:35:33 +02:00
parent df1e134821
commit 7b6c272aa9
47 changed files with 620 additions and 291 deletions

View file

@ -124,7 +124,7 @@ public:
Q_ENUM(ApiError)
const QString &baseUrl() const { return this->m_baseUrl; }
const QString &userId() const { return m_userId; }
const QString userId() const { return m_userId; }
const QString &deviceId() const { return m_deviceId; }
/**
* @brief QML applications can set this type to indicate which commands they support.
@ -275,7 +275,7 @@ private:
QString m_token;
QString m_deviceName;
QString m_deviceId;
QString m_userId = "";
QString m_userId;
QJsonObject m_deviceProfile;
QJsonObject m_playbackDeviceProfile;
bool m_online = true;

View file

@ -188,7 +188,7 @@ public:
* @return pair containing the items loaded and the integer containing the starting offset. A starting
* offset of -1 means an error has occurred.
*/
std::pair<QList<T>, int> &&result() { return std::move(m_result); }
std::pair<QList<T*>, int> &&result() { return std::move(m_result); }
protected:
/**
* @brief Loads data from the given offset with a maximum count of limit.
@ -205,7 +205,7 @@ protected:
m_startIndex = startIndex;
m_totalRecordCount = totalRecordCount;
}
std::pair<QList<T>, int> m_result;
std::pair<QList<T*>, int> m_result;
};
/**
@ -275,7 +275,7 @@ protected:
// If futureWatcher's future is running, this method should not be called again.
if (m_futureWatcher.isRunning()) return;
// Set an invalid result.
this->m_result = { QList<T>(), -1 };
this->m_result = { QList<T*>(), -1 };
if (!setRequestStartIndex<P>(this->m_parameters, offset)
&& suggestedModelStatus == ViewModel::ModelStatus::LoadingMore) {
@ -326,12 +326,12 @@ protected:
if (totalRecordCount < 0) {
totalRecordCount = records.size();
}
QList<T> models;
QList<T*> models;
models.reserve(records.size());
// Convert the DTOs into models
for (int i = 0; i < records.size(); i++) {
models.append(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};
@ -441,7 +441,7 @@ public:
}
// QList-like API
const T& at(int index) const { return m_array.at(index); }
QSharedPointer<T> at(int index) const { return m_array.at(index); }
/**
* @return the amount of objects in this model.
*/
@ -449,22 +449,23 @@ public:
return m_array.size();
}
void insert(int index, T &object) {
void insert(int index, QSharedPointer<T> object) {
Q_ASSERT(index >= 0 && index <= size());
this->beginInsertRows(QModelIndex(), index, index);
m_array.insert(index, object);
this->endInsertRows();
}
void append(T &object) { insert(size(), object); }
void append(QList<T> &objects) {
void append(QSharedPointer<T> object) { insert(size(), object); }
//void append(T &object) { insert(size(), object); }
void append(QList<QSharedPointer<T>> &objects) {
int index = size();
this->beginInsertRows(QModelIndex(), index, index + objects.size() - 1);
m_array.append(objects);
this->endInsertRows();
};
QList<T> mid(int pos, int length = -1) {
QList<T*> mid(int pos, int length = -1) {
return m_array.mid(pos, length);
}
@ -483,7 +484,7 @@ public:
this->endRemoveRows();
}
void removeOne(T &object) {
void removeOne(QSharedPointer<T> object) {
int idx = m_array.indexOf(object);
if (idx >= 0) {
removeAt(idx);
@ -535,20 +536,26 @@ public:
protected:
// Model-specific properties.
QList<T> m_array;
QList<QSharedPointer<T>> m_array;
ModelLoader<T> *m_loader = nullptr;
void loadingFinished() override {
Q_ASSERT(m_loader != nullptr);
std::pair<QList<T>, int> result = m_loader->result();
std::pair<QList<T*>, int> result = m_loader->result();
qDebug() << "Results loaded: index: " << result.second << ", count: " << result.first.size();
if (result.second == -1) {
clear();
} else if (result.second == m_array.size()) {
append(result.first);
m_array.reserve(m_array.size() + result.second);
for (auto it = result.first.begin(); it != result.first.end(); it++) {
append(QSharedPointer<T>(*it));
}
} else if (result.second < m_array.size()){
removeUntilEnd(result.second);
append(result.first);
m_array.reserve(m_array.size() + result.second);
for (auto it = result.first.begin(); it != result.first.end(); it++) {
append(QSharedPointer<T>(*it));
}
} else {
// result.second > m_array.size()
qWarning() << "Retrieved data from loader at position bigger than size()";

View file

@ -123,7 +123,6 @@ public:
private:
QString urlToGroupName(const QString &url) const;
QString groupNameToUrl(const QString &group) const;
QSettings m_settings;
};

View file

@ -20,9 +20,11 @@
#ifndef JELLYFIN_MODEL_ITEM
#define JELLYFIN_MODEL_ITEM
#include <functional>
#include <map>
#include <QObject>
#include <QList>
#include <QThreadPool>
#include <QtConcurrent/QtConcurrent>
#include "../dto/baseitemdto.h"
#include "../support/loader.h"
@ -31,20 +33,22 @@
namespace Jellyfin {
namespace Model {
class Item : public DTO::BaseItemDto {
class Item : public QObject, public DTO::BaseItemDto {
Q_OBJECT
public:
using UserDataChangedCallback = std::function<void(DTO::UserItemDataDto)>;
/**
* @brief Constructor that creates an empty item.
*/
Item();
Item(QObject *parent = nullptr);
/**
* @brief Copies the data from the DTO into this model and attaches an ApiClient
* @param data The DTO to copy information from
* @param apiClient The ApiClient to attach to, to listen for updates and so on.
*/
Item(const DTO::BaseItemDto &data, ApiClient *apiClient = nullptr);
virtual ~Item();
Item(const DTO::BaseItemDto &data, ApiClient *apiClient = nullptr, QObject *parent = nullptr);
//virtual ~Item();
/**
* @brief sameAs Returns true if this item represents the same item as `other`
@ -58,11 +62,13 @@ public:
bool sameAs(const DTO::BaseItemDto &other);
void setApiClient(ApiClient *apiClient);
signals:
void userDataChanged(const DTO::UserItemDataDto &newUserData);
private:
ApiClient *m_apiClient = nullptr;
QList<QMetaObject::Connection> m_apiClientConnections;
void updateUserData(const QString &itemId, const DTO::UserItemDataDto &userData);
void onUserDataUpdated(const QString &itemId, const DTO::UserItemDataDto &userData);
};
}

View file

@ -76,7 +76,7 @@ public:
/**
* @brief Appends all items from the given itemModel to this list
*/
void appendToList(const ViewModel::ItemModel &model);
void appendToList(ViewModel::ItemModel &model);
/**
* @brief Start playing this playlist

View file

@ -46,15 +46,22 @@
#include "loader.h"
namespace Jellyfin {
namespace DTO {
class UserItemDataDto;
} // NS DTO
namespace ViewModel {
class UserData;
class Item : public QObject {
Q_OBJECT
public:
explicit Item(QObject *parent = nullptr, QSharedPointer<Model::Item> data = QSharedPointer<Model::Item>::create());
// Please keep the order of the properties the same as in the file linked above.
Q_PROPERTY(QUuid jellyfinId READ jellyfinId NOTIFY jellyfinIdChanged)
Q_PROPERTY(QString jellyfinId READ jellyfinId NOTIFY jellyfinIdChanged)
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(QString originalTitle READ originalTitle NOTIFY originalTitleChanged)
Q_PROPERTY(QString serverId READ serverId NOTIFY serverIdChanged)
@ -81,27 +88,29 @@ public:
//SKIP: ExternalUrls
//SKIP: MediaSources
Q_PROPERTY(float criticRating READ criticRating NOTIFY criticRatingChanged)
Q_PROPERTY(QStringList productionLocations READ productionLocations NOTIFY productionLocationsChanged)
Q_PROPERTY(QStringList productionLocations READ productionLocations NOTIFY productionLocationsChanged)*/
// Handpicked, important ones
Q_PROPERTY(qint64 runTimeTicks READ runTimeTicks NOTIFY runTimeTicksChanged)*/
Q_PROPERTY(qint64 runTimeTicks READ runTimeTicks NOTIFY runTimeTicksChanged)
Q_PROPERTY(QString overview READ overview NOTIFY overviewChanged)
Q_PROPERTY(int productionYear READ productionYear NOTIFY productionYearChanged)
Q_PROPERTY(int indexNumber READ indexNumber NOTIFY indexNumberChanged)
Q_PROPERTY(int indexNumberEnd READ indexNumberEnd NOTIFY indexNumberEndChanged)
Q_PROPERTY(bool isFolder READ isFolder NOTIFY isFolderChanged)
Q_PROPERTY(QString type READ type NOTIFY typeChanged)
/*Q_PROPERTY(QString parentBackdropItemId READ parentBackdropItemId NOTIFY parentBackdropItemIdChanged)
Q_PROPERTY(QString parentBackdropItemId READ parentBackdropItemId NOTIFY parentBackdropItemIdChanged)
Q_PROPERTY(QStringList parentBackdropImageTags READ parentBackdropImageTags NOTIFY parentBackdropImageTagsChanged)
Q_PROPERTY(UserData *userData READ userData NOTIFY userDataChanged)
Q_PROPERTY(int recursiveItemCount READ recursiveItemCount NOTIFY recursiveItemCountChanged)
Q_PROPERTY(int childCount READ childCount NOTIFY childCountChanged)
Q_PROPERTY(QString albumArtist READ albumArtist NOTIFY albumArtistChanged)
Q_PROPERTY(QVariantList albumArtists READ albumArtists NOTIFY albumArtistsChanged)
/*Q_PROPERTY(QVariantList albumArtists READ albumArtists NOTIFY albumArtistsChanged)*/
Q_PROPERTY(QString seriesName READ seriesName NOTIFY seriesNameChanged)
Q_PROPERTY(QString seriesId READ seriesId NOTIFY seriesIdChanged)
Q_PROPERTY(QString seasonId READ seasonId NOTIFY seasonIdChanged)
Q_PROPERTY(QString seasonName READ seasonName NOTIFY seasonNameChanged)
Q_PROPERTY(QList<MediaStream *> __list__mediaStreams MEMBER __list__m_mediaStreams NOTIFY mediaStreamsChanged)
Q_PROPERTY(QVariantList mediaStreams READ mediaStreams NOTIFY mediaStreamsChanged STORED false)
/*Q_PROPERTY(QList<MediaStream *> __list__mediaStreams MEMBER __list__m_mediaStreams NOTIFY mediaStreamsChanged)
Q_PROPERTY(QVariantList mediaStreams READ mediaStreams NOTIFY mediaStreamsChanged STORED false)*/
Q_PROPERTY(QStringList artists READ artists NOTIFY artistsChanged)
// Why is this a QJsonObject? Well, because I couldn't be bothered to implement the deserialisations of
// a QHash at the moment.
@ -110,9 +119,9 @@ public:
Q_PROPERTY(QJsonObject imageBlurHashes READ imageBlurHashes NOTIFY imageBlurHashesChanged)
Q_PROPERTY(QString mediaType READ mediaType READ mediaType NOTIFY mediaTypeChanged)
Q_PROPERTY(int width READ width NOTIFY widthChanged)
Q_PROPERTY(int height READ height NOTIFY heightChanged)*/
Q_PROPERTY(int height READ height NOTIFY heightChanged)
QUuid jellyfinId() const { return m_data->jellyfinId(); }
QString jellyfinId() const { return m_data->jellyfinId(); }
QString name() const { return m_data->name(); }
QString originalTitle() const { return m_data->originalTitle(); }
QString serverId() const { return m_data->serverId(); }
@ -125,17 +134,36 @@ public:
int airsBeforeSeasonNumber() const { return m_data->airsBeforeSeasonNumber().value_or(0); }
int airsAfterSeasonNumber() const { return m_data->airsAfterSeasonNumber().value_or(999); }
int airsBeforeEpisodeNumber() const { return m_data->airsBeforeEpisodeNumber().value_or(0); }
qint64 runTimeTicks() const { return m_data->runTimeTicks().value_or(0); }
QString overview() const { return m_data->overview(); }
int productionYear() const { return m_data->productionYear().value_or(0); }
int indexNumber() const { return m_data->indexNumber().value_or(-1); }
int indexNumberEnd() const { return m_data->indexNumberEnd().value_or(-1); }
bool isFolder() const { return m_data->isFolder().value_or(false); }
QString type() const { return m_data->type(); }
QString parentBackdropItemId() const { return m_data->parentBackdropItemId(); }
QStringList parentBackdropImageTags() const { return m_data->parentBackdropImageTags(); }
UserData *userData() const { return m_userData; }
int recursiveItemCount() const { return m_data->recursiveItemCount().value_or(0); }
int childCount() const { return m_data->childCount().value_or(0); }
QString albumArtist() const { return m_data->albumArtist(); }
QString seriesName() const { return m_data->seriesName(); }
QString seriesId() const { return m_data->seriesId(); }
QString seasonId() const { return m_data->seasonId(); }
QString seasonName() const { return m_data->seasonName(); }
QStringList artists() const { return m_data->artists(); }
QJsonObject imageTags() const { return m_data->imageTags(); }
QStringList backdropImageTags() const { return m_data->backdropImageTags(); }
QJsonObject imageBlurHashes() const { return m_data->imageBlurHashes(); }
QString mediaType() const { return m_data->mediaType(); }
int width() const { return m_data->width().value_or(0); }
int height() const { return m_data->height().value_or(0); }
QSharedPointer<Model::Item> data() const { return m_data; }
void setData(QSharedPointer<Model::Item> newData);
signals:
void jellyfinIdChanged(const QUuid &newId);
void jellyfinIdChanged(const QString &newId);
void nameChanged(const QString &newName);
void originalTitleChanged(const QString &newOriginalTitle);
void serverIdChanged(const QString &newServerId);
@ -171,12 +199,14 @@ signals:
void typeChanged(const QString &newType);
void parentBackdropItemIdChanged();
void parentBackdropImageTagsChanged();
//void userDataChanged(UserData *newUserData);
void userDataChanged(UserData *newUserData);
void recursiveItemCountChanged(int newRecursiveItemCount);
void childCountChanged(int newChildCount);
void albumArtistChanged(const QString &newAlbumArtist);
//void albumArtistsChanged(NameGuidPair *newAlbumArtists);
void seriesNameChanged(const QString &newSeriesName);
void seriesIdChanged(const QString &newSeriesId);
void seasonIdChanged(const QString &newSeasonId);
void seasonNameChanged(const QString &newSeasonName);
void mediaStreamsChanged(/*const QList<MediaStream *> &newMediaStreams*/);
void artistsChanged(const QStringList &newArtists);
@ -187,7 +217,13 @@ signals:
void widthChanged(int newWidth);
void heightChanged(int newHeight);
protected:
void setUserData(DTO::UserItemDataDto &newData);
void setUserData(QSharedPointer<DTO::UserItemDataDto> newData);
QSharedPointer<Model::Item> m_data;
UserData *m_userData = nullptr;
private slots:
void onUserDataChanged(const DTO::UserItemDataDto &userData);
};
class ItemLoader : public Loader<ViewModel::Item, DTO::BaseItemDto, Jellyfin::Loader::GetItemParams> {

View file

@ -134,12 +134,108 @@ public:
FWDPROP(QList<Jellyfin::DTO::LocationTypeClass::Value>, excludeLocationTypes, ExcludeLocationTypes)
FWDPROP(QList<Jellyfin::DTO::ItemFieldsClass::Value>, fields, Fields)
FWDPROP(QList<Jellyfin::DTO::ItemFilterClass::Value>, filters, Filters)
FWDPROP(QStringList, genreIds, GenreIds)
FWDPROP(QStringList, genres, Genres)
FWDPROP(bool, hasImdbId, HasImdbId)
FWDPROP(bool, hasOfficialRating, HasOfficialRating)
FWDPROP(bool, hasOverview, HasOverview)
FWDPROP(bool, hasParentalRating, HasParentalRating)
FWDPROP(bool, hasSpecialFeature, HasSpecialFeature)
FWDPROP(bool, hasSubtitles, HasSubtitles)
FWDPROP(bool, hasThemeSong, HasThemeSong)
FWDPROP(bool, hasThemeVideo, HasThemeVideo)
FWDPROP(bool, hasTmdbId, HasTmdbId)
FWDPROP(bool, hasTrailer, HasTrailer)
FWDPROP(bool, hasTvdbId, HasTvdbId)
FWDPROP(QStringList, ids, Ids)
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
FWDPROP(QList<Jellyfin::DTO::ImageTypeClass::Value>, imageTypes, ImageTypes)
FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
FWDPROP(bool, is3D, Is3D)
FWDPROP(bool, is4K, Is4K)
FWDPROP(bool, isFavorite, IsFavorite)
FWDPROP(bool, isHd, IsHd)
FWDPROP(bool, isLocked, IsLocked)
FWDPROP(bool, isMissing, IsMissing)
FWDPROP(bool, isPlaceHolder, IsPlaceHolder)
FWDPROP(bool, isPlayed, IsPlayed)
FWDPROP(bool, isUnaired, IsUnaired)
FWDPROP(QList<Jellyfin::DTO::LocationTypeClass::Value>, locationTypes, LocationTypes)
FWDPROP(qint32, maxHeight, MaxHeight)
FWDPROP(QString, maxOfficialRating, MaxOfficialRating)
FWDPROP(QDateTime, maxPremiereDate, MaxPremiereDate)
FWDPROP(qint32, maxWidth, MaxWidth)
FWDPROP(QStringList, mediaTypes, MediaTypes)
FWDPROP(qint32, minHeight, MinHeight)
FWDPROP(QString, minOfficialRating, MinOfficialRating)
FWDPROP(QDateTime, minPremiereDate, MinPremiereDate)
FWDPROP(qint32, minWidth, MinWidth)
FWDPROP(QString, sortBy, SortBy)
FWDPROP(QString, sortOrder, SortOrder)
FWDPROP(QStringList, tags, Tags)
FWDPROP(QList<qint32>, years, Years)
FWDPROP(QString, parentId, ParentId)
FWDPROP(bool, recursive, Recursive)
FWDPROP(QString, searchTerm, SearchTerm)
//FWDPROP(bool, collapseBoxSetItems)
};
using ResumeItemsLoaderBase = AbstractUserParameterLoader<Model::Item, DTO::BaseItemDto, DTO::BaseItemDtoQueryResult, Jellyfin::Loader::GetResumeItemsParams>;
class ResumeItemsLoader : public ResumeItemsLoaderBase {
Q_OBJECT
public:
explicit ResumeItemsLoader(QObject *parent = nullptr);
FWDPROP(QList<Jellyfin::DTO::ImageTypeClass::Value>, enableImageTypes, EnableImageTypes);
FWDPROP(bool, enableImages, EnableImages)
FWDPROP(bool, enableTotalRecordCount, EnableTotalRecordCount)
FWDPROP(bool, enableUserData, EnableUserData)
FWDPROP(QStringList, excludeItemTypes, ExcludeItemTypes)
FWDPROP(QList<Jellyfin::DTO::ItemFieldsClass::Value>, fields, Fields)
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
FWDPROP(QStringList, includeItemTypes, IncludeItemTypes)
FWDPROP(QStringList, mediaTypes, MediaTypes)
FWDPROP(QString, parentId, ParentId)
FWDPROP(QString, searchTerm, SearchTerm)
};
using ShowSeasonsLoaderBase = AbstractUserParameterLoader<Model::Item, DTO::BaseItemDto, DTO::BaseItemDtoQueryResult, Jellyfin::Loader::GetSeasonsParams>;
class ShowSeasonsLoader : public ShowSeasonsLoaderBase {
Q_OBJECT
public:
explicit ShowSeasonsLoader(QObject *parent = nullptr);
FWDPROP(QString, seriesId, SeriesId)
FWDPROP(QString, adjacentTo, AdjacentTo)
FWDPROP(QList<Jellyfin::DTO::ImageTypeClass::Value>, enableImageTypes, EnableImageTypes)
FWDPROP(bool, enableImages, EnableImages)
FWDPROP(bool, enableUserData, EnableUserData)
FWDPROP(QList<Jellyfin::DTO::ItemFieldsClass::Value>, fields, Fields)
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
FWDPROP(bool, isMissing, IsMissing)
FWDPROP(bool, isSpecialSeason, IsSpecialSeason)
};
using ShowEpisodesLoaderBase = AbstractUserParameterLoader<Model::Item, DTO::BaseItemDto, DTO::BaseItemDtoQueryResult, Jellyfin::Loader::GetEpisodesParams>;
class ShowEpisodesLoader : public ShowEpisodesLoaderBase {
Q_OBJECT
public:
explicit ShowEpisodesLoader(QObject *parent = nullptr);
FWDPROP(QString, seriesId, SeriesId)
FWDPROP(QString, adjacentTo, AdjacentTo)
FWDPROP(bool, enableImages, EnableImages)
FWDPROP(bool, enableUserData, EnableUserData)
FWDPROP(QList<Jellyfin::DTO::ItemFieldsClass::Value>, fields, Fields)
FWDPROP(qint32, imageTypeLimit, ImageTypeLimit)
FWDPROP(bool, isMissing, IsMissing)
FWDPROP(qint32, season, Season)
FWDPROP(QString, seasonId, SeasonId)
FWDPROP(QString, sortBy, SortBy)
FWDPROP(QString, startItemId, StartItemId)
};
/**
@ -167,6 +263,11 @@ public:
mediaType,
type,
collectionType,
indexNumber,
runTimeTicks,
artists,
isFolder,
parentIndexNumber,
jellyfinExtendModelAfterHere = Qt::UserRole + 300 // Should be enough for now
};
@ -191,6 +292,11 @@ public:
JFRN(mediaType),
JFRN(type),
JFRN(collectionType),
JFRN(indexNumber),
JFRN(runTimeTicks),
JFRN(artists),
JFRN(isFolder),
JFRN(parentIndexNumber),
};
}
QVariant data(const QModelIndex &index, int role) const override;

View file

@ -91,6 +91,7 @@ public:
Q_PROPERTY(QMediaPlayer::Error error READ error NOTIFY errorChanged)
Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged)
Q_PROPERTY(bool hasVideo READ hasVideo NOTIFY hasVideoChanged)
Q_PROPERTY(bool seekable READ seekable NOTIFY seekableChanged)
Q_PROPERTY(QObject* mediaObject READ mediaObject NOTIFY mediaObjectChanged)
Q_PROPERTY(QMediaPlayer::MediaStatus mediaStatus READ mediaStatus NOTIFY mediaStatusChanged)
Q_PROPERTY(QMediaPlayer::State playbackState READ playbackState NOTIFY playbackStateChanged)
@ -108,9 +109,10 @@ public:
int queueIndex() const { return m_queueIndex; }
// Current media player related property getters
QMediaPlayer::State playbackState() const { return m_playbackState; }
QMediaPlayer::State playbackState() const { return m_mediaPlayer->state()/*m_playbackState*/; }
QMediaPlayer::MediaStatus mediaStatus() const { return m_mediaPlayer->mediaStatus(); }
bool hasVideo() const { return m_mediaPlayer->isVideoAvailable(); }
bool seekable() const { return m_mediaPlayer->isSeekable(); }
QMediaPlayer::Error error () const { return m_mediaPlayer->error(); }
QString errorString() const { return m_mediaPlayer->errorString(); }
signals:
@ -132,6 +134,7 @@ signals:
void playbackStateChanged(QMediaPlayer::State newState);
void mediaStatusChanged(QMediaPlayer::MediaStatus newMediaStatus);
void hasVideoChanged(bool newHasVideo);
void seekableChanged(bool newSeekable);
void errorChanged(QMediaPlayer::Error newError);
void errorStringChanged(const QString &newErrorString);
public slots:

View file

@ -0,0 +1,81 @@
/*
* Sailfin: a Jellyfin client written using Qt
* Copyright (C) 2021 Chris Josten and the Sailfin Contributors.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef JELLYFIN_VIEWMODEL_USERDATA_H
#define JELLYFIN_VIEWMODEL_USERDATA_H
#include <QDateTime>
#include <QObject>
#include <QSharedPointer>
#include "../dto/useritemdatadto.h"
namespace Jellyfin {
namespace ViewModel{
class UserData : public QObject {
Q_OBJECT
public:
explicit UserData(QObject* parent = nullptr);
explicit UserData(QSharedPointer<DTO::UserItemDataDto> data, QObject* parent = nullptr);
void setData(QSharedPointer<DTO::UserItemDataDto> data);
Q_PROPERTY(double rating READ rating NOTIFY ratingChanged)
Q_PROPERTY(double playedPercentage READ playedPercentage NOTIFY playedPercentageChanged)
Q_PROPERTY(int unplayedItemCount READ unplayedItemCount NOTIFY unplayedItemCountChanged)
Q_PROPERTY(qint64 playbackPositionTicks READ playbackPositionTicks NOTIFY playbackPositionTicksChanged);
Q_PROPERTY(int playCount READ playCount NOTIFY playCountChanged)
Q_PROPERTY(bool favorite READ favorite NOTIFY favoriteChanged)
Q_PROPERTY(bool m_likes READ likes NOTIFY likesChanged)
Q_PROPERTY(QDateTime lastPlayedDate READ lastPlayedDate NOTIFY lastPlayedDateChanged)
Q_PROPERTY(bool played READ played NOTIFY playedChanged)
Q_PROPERTY(QString key READ key NOTIFY keyChanged)
double rating() const { return m_data->rating().value_or(0); }
double playedPercentage() const { return m_data->playedPercentage().value_or(0); }
int unplayedItemCount() const { return m_data->unplayedItemCount().value_or(0); }
qint64 playbackPositionTicks() const { return m_data->playbackPositionTicks(); }
int playCount() const { return m_data->playCount(); }
bool favorite() const { return m_data->isFavorite(); }
bool likes() const { return m_data->likes().value_or(false); }
QDateTime lastPlayedDate() const { return m_data->lastPlayedDate(); }
bool played() const { return m_data->played(); }
QString key() const { return m_data->key(); }
signals:
void ratingChanged(double newRating);
void playedPercentageChanged(double newPlayedPercentage);
void unplayedItemCountChanged(int newUnplayedItemCount);
void playbackPositionTicksChanged(qint64 newPlaybackPositionTicks);
void playCountChanged(int newPlayCount);
void favoriteChanged(bool newFavorite);
void likesChanged(bool newLikes);
void lastPlayedDateChanged(QDateTime newLastPlayedDate);
void playedChanged(bool newPLayed);
void keyChanged(QString newKey);
private:
QSharedPointer<DTO::UserItemDataDto> m_data;
};
} // NS ViewModel
} // NS Jellyfin
#endif // JELLYFIN_VIEWMODEL_USERDATA_H