307 lines
9.3 KiB
C++
307 lines
9.3 KiB
C++
/*
|
|
* Copyright (C) EdgeTX
|
|
*
|
|
* Based on code named
|
|
* opentx - https://github.com/opentx/opentx
|
|
* th9x - http://code.google.com/p/th9x
|
|
* er9x - http://code.google.com/p/er9x
|
|
* gruvin9x - http://code.google.com/p/gruvin9x
|
|
*
|
|
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <QtCore>
|
|
#include <QStandardItemModel>
|
|
#include <QSortFilterProxyModel>
|
|
|
|
constexpr char GITHUB_API_REPOS[] {"https://api.github.com/repos"};
|
|
constexpr char GH_REPOS_EDGETX[] {"https://api.github.com/repos/EdgeTX"};
|
|
|
|
constexpr char GH_ACCEPT_HEADER_BINARY[] {"application/octet-stream"};
|
|
constexpr char GH_ACCEPT_HEADER_METADATA[] {"application/vnd.github.v3+json"};
|
|
constexpr char GH_ACCEPT_HEADER_RAW[] {"application/vnd.github.v3.raw"};
|
|
|
|
enum MetaDataType {
|
|
MDT_Release,
|
|
MDT_Releases,
|
|
MDT_Asset,
|
|
MDT_ReleaseAssets
|
|
};
|
|
|
|
QString metaDataTypeToString(MetaDataType val);
|
|
|
|
class UpdatesItemModel : public QStandardItemModel
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
enum ItemModelDataRoles {
|
|
IMDR_Id = Qt::UserRole,
|
|
IMDR_Date,
|
|
IMDR_SortOrder,
|
|
IMDR_Tag,
|
|
IMDR_Prerelease,
|
|
IMDR_Content,
|
|
IMDR_Available,
|
|
IMDR_Flags,
|
|
IMDR_CopyFilter,
|
|
IMDR_SubDirectory
|
|
};
|
|
Q_ENUM(ItemModelDataRoles)
|
|
|
|
explicit UpdatesItemModel(QString name = "") :
|
|
QStandardItemModel(nullptr),
|
|
json(nullptr),
|
|
m_name(name) {}
|
|
|
|
virtual ~UpdatesItemModel() {}
|
|
|
|
protected:
|
|
QJsonDocument * json;
|
|
|
|
private:
|
|
QString m_name;
|
|
};
|
|
|
|
class ReleasesItemModel : public UpdatesItemModel
|
|
{
|
|
Q_OBJECT
|
|
|
|
friend class ReleasesMetaData;
|
|
|
|
public:
|
|
explicit ReleasesItemModel();
|
|
virtual ~ReleasesItemModel() {}
|
|
|
|
void setNightlyName(const QString name) { m_nightlyName = name.toLower(); }
|
|
void setSettingsIndex(const int index) { m_settingsIdx = index; }
|
|
void setReleaseChannel(const int channel);
|
|
|
|
void parseMetaData(const int mdt, QJsonDocument * json);
|
|
int settingsIndex() { return m_settingsIdx; }
|
|
bool refreshRequired() { return m_refreshRequired; }
|
|
|
|
private:
|
|
int m_settingsIdx;
|
|
QString m_nightlyName;
|
|
int m_releaseChannel;
|
|
bool m_refreshRequired;
|
|
|
|
void setDynamicItemData(QStandardItem * item);
|
|
void update();
|
|
bool isReleaseAvailable(QStandardItem * item);
|
|
|
|
void parseRelease();
|
|
void parseReleases();
|
|
void parseJsonObject(const QJsonObject & obj);
|
|
};
|
|
|
|
class AssetsItemModel : public UpdatesItemModel
|
|
{
|
|
Q_OBJECT
|
|
|
|
friend class AssetsMetaData;
|
|
|
|
public:
|
|
explicit AssetsItemModel();
|
|
virtual ~AssetsItemModel() {}
|
|
|
|
void parseMetaData(int mdt, QJsonDocument * json);
|
|
|
|
private:
|
|
void parseAsset();
|
|
void parseReleaseAssets();
|
|
void parseJsonObject(const QJsonObject & obj);
|
|
};
|
|
|
|
class UpdatesFilteredItemModel: public QSortFilterProxyModel
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit UpdatesFilteredItemModel(UpdatesItemModel * sourceModel, QString name = "");
|
|
virtual ~UpdatesFilteredItemModel() {};
|
|
|
|
void dumpContents();
|
|
QStringList list();
|
|
|
|
int id(const int row);
|
|
int id(const QVariant value, const Qt::MatchFlags flags = Qt::MatchExactly, const int role = Qt::DisplayRole);
|
|
int rows() { return rowCount(); }
|
|
|
|
QString date(const int id) { return metaDataValue(id, UpdatesItemModel::IMDR_Date).toString(); }
|
|
QString name(const int id) { return metaDataValue(id, Qt::DisplayRole).toString(); }
|
|
|
|
public slots:
|
|
void setFilterFlags(const int flags);
|
|
void setFilterPattern(const QString & pattern);
|
|
|
|
signals:
|
|
|
|
protected:
|
|
int filterFlags;
|
|
QRegularExpression filterText;
|
|
|
|
bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override;
|
|
|
|
QMap<int, QVariant> itemMetaData(int id);
|
|
QVariant metaDataValue(const int id, const int role);
|
|
bool setMetaDataValue(const int id, const int role, const QVariant value);
|
|
|
|
private:
|
|
QString m_name;
|
|
};
|
|
|
|
class ReleasesFilteredItemModel: public UpdatesFilteredItemModel
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
protected:
|
|
friend class ReleasesMetaData;
|
|
|
|
explicit ReleasesFilteredItemModel(UpdatesItemModel * sourceModel);
|
|
virtual ~ReleasesFilteredItemModel() {};
|
|
|
|
int channelLatestId();
|
|
|
|
bool prerelease(const int id) { return metaDataValue(id, UpdatesItemModel::IMDR_Prerelease).toBool(); }
|
|
QString version(const int id) { return metaDataValue(id, UpdatesItemModel::IMDR_Tag).toString(); }
|
|
|
|
private:
|
|
};
|
|
|
|
class AssetsFilteredItemModel : public UpdatesFilteredItemModel
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
protected:
|
|
friend class AssetsMetaData;
|
|
|
|
explicit AssetsFilteredItemModel(UpdatesItemModel * sourceModel);
|
|
virtual ~AssetsFilteredItemModel() {};
|
|
|
|
bool setFlags(const int id, const int flags);
|
|
bool setSubDirectory(const int id, const QString path);
|
|
bool setCopyFilter(const int id, const QString filter);
|
|
|
|
QString filename(int id) { return metaDataValue(id, Qt::DisplayRole).toString(); }
|
|
|
|
private:
|
|
};
|
|
|
|
class RepoMetaData : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit RepoMetaData(QObject * parent);
|
|
virtual ~RepoMetaData() {};
|
|
|
|
const QString urlReleases() { return QString("%1/releases").arg(m_repo); }
|
|
const QString urlReleaseLatest() { return QString("%1/latest").arg(urlReleases()); }
|
|
const QString urlContent(const QString & path) { return QString("%1/contents/%2").arg(m_repo).arg(path); }
|
|
|
|
protected:
|
|
QString m_repo;
|
|
int m_resultsPerPage;
|
|
};
|
|
|
|
class ReleasesMetaData : public RepoMetaData
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit ReleasesMetaData(QObject * parent);
|
|
virtual ~ReleasesMetaData() {};
|
|
|
|
void init(const QString repo, const QString nightly, const int settingsIndex, const int resultsPerPage);
|
|
|
|
bool refreshRequired();
|
|
void setReleaseChannel(const int channel) { itemModel->setReleaseChannel(channel); }
|
|
|
|
void setId(int id) { m_id = id; }
|
|
int id() { return m_id; }
|
|
|
|
int getSetId();
|
|
int getSetId(int row);
|
|
int getSetId(QVariant value, Qt::MatchFlags flags = Qt::MatchExactly, int role = Qt::DisplayRole);
|
|
|
|
void parseMetaData(int mdt, QJsonDocument * jsonDoc) { itemModel->parseMetaData(mdt, jsonDoc); }
|
|
|
|
int count() { return filteredItemModel->rows(); }
|
|
QStringList list() { return filteredItemModel->list(); }
|
|
void dumpContentsFiltered() { filteredItemModel->dumpContents(); }
|
|
|
|
QString date() { return filteredItemModel->date(m_id); }
|
|
QString name();
|
|
bool prerelease() { return filteredItemModel->prerelease(m_id); }
|
|
QString version();
|
|
|
|
const QString urlRelease() { return QString("%1/%2").arg(urlReleases()).arg(m_id); }
|
|
|
|
private:
|
|
ReleasesItemModel *itemModel;
|
|
ReleasesFilteredItemModel *filteredItemModel;
|
|
int m_id;
|
|
};
|
|
|
|
class AssetsMetaData : public RepoMetaData
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit AssetsMetaData(QObject * parent);
|
|
virtual ~AssetsMetaData() {};
|
|
|
|
void init(const QString repo, const int resultsPerPage);
|
|
|
|
void setId(int id) { m_id = id; }
|
|
int id() { return m_id; }
|
|
|
|
int getSetId(int row);
|
|
int getSetId(QVariant value, Qt::MatchFlags flags = Qt::MatchExactly, int role = Qt::DisplayRole);
|
|
|
|
void parseMetaData(int mdt, QJsonDocument * jsonDoc) { itemModel->parseMetaData(mdt, jsonDoc); }
|
|
|
|
bool setFlags(int flags) { return filteredItemModel->setFlags(m_id, flags); }
|
|
|
|
void setFilterFlags(int flags) { filteredItemModel->setFilterFlags(flags); }
|
|
void setFilterPattern(const QString & pattern) { filteredItemModel->setFilterPattern(pattern); }
|
|
|
|
bool setSubDirectory(const QString path) { return filteredItemModel->setSubDirectory(m_id, path); }
|
|
bool setCopyFilter(const QString filter) { return filteredItemModel->setCopyFilter(m_id, filter); }
|
|
|
|
int count() { return filteredItemModel->rows(); }
|
|
QStringList list() { return filteredItemModel->list(); }
|
|
void dumpContentsFiltered() { filteredItemModel->dumpContents(); }
|
|
|
|
QString date() { return filteredItemModel->date(m_id); }
|
|
QString name() { return filteredItemModel->name(m_id); }
|
|
QString filename() { return filteredItemModel->metaDataValue(m_id, Qt::DisplayRole).toString(); }
|
|
QString contentType() { return filteredItemModel->metaDataValue(m_id, UpdatesItemModel::IMDR_Content).toString(); }
|
|
QString subDirectory() { return filteredItemModel->metaDataValue(m_id, UpdatesItemModel::IMDR_SubDirectory).toString(); }
|
|
QString copyFilter() { return filteredItemModel->metaDataValue(m_id, UpdatesItemModel::IMDR_CopyFilter).toString(); }
|
|
int flags() { return filteredItemModel->metaDataValue(m_id, UpdatesItemModel::IMDR_Flags).toInt(); }
|
|
|
|
const QString urlReleaseAssets(int releaseId) {
|
|
return QString("%1/%2/assets").arg(urlReleases()).arg(releaseId) % (m_resultsPerPage > -1 ?
|
|
QString("\?per_page=%1").arg(m_resultsPerPage) : ""); }
|
|
const QString urlAsset() { return QString("%1/assets/%2").arg(urlReleases()).arg(m_id); }
|
|
|
|
private:
|
|
AssetsItemModel *itemModel;
|
|
AssetsFilteredItemModel *filteredItemModel;
|
|
int m_id;
|
|
};
|