ScreenTranslator/src/service/updates.h

133 lines
3.5 KiB
C
Raw Normal View History

2020-03-15 18:10:26 +07:00
#pragma once
#include <QDate>
#include <QStyledItemDelegate>
#include <QUrl>
class QNetworkAccessManager;
class QNetworkReply;
namespace update
{
enum class State { NotAvailable, NotInstalled, UpdateAvailable, Actual };
enum class Action { NoAction, Remove, Install };
struct File {
QUrl url;
QString rawPath;
QString expandedPath;
QString downloadPath;
QString md5;
QDateTime versionDate;
};
using UserActions = std::multimap<Action, File>;
class ActionDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit ActionDelegate(QObject* parent = nullptr);
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const override;
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
void setModelData(QWidget* editor, QAbstractItemModel* model,
const QModelIndex& index) const override;
};
class Model : public QAbstractItemModel
{
Q_OBJECT
public:
enum class Column { Name, State, Action, Version, Files, Count };
explicit Model(QObject* parent = nullptr);
void parse(const QByteArray& data);
void setExpansions(const std::map<QString, QString>& expansions);
UserActions userActions() const;
void updateStates();
2020-03-17 01:44:33 +07:00
bool hasUpdates() const;
2020-03-15 18:10:26 +07:00
QModelIndex index(int row, int column,
const QModelIndex& parent) const override;
QModelIndex parent(const QModelIndex& child) const override;
int rowCount(const QModelIndex& parent) const override;
int columnCount(const QModelIndex& parent) const override;
QVariant headerData(int section, Qt::Orientation orientation,
int role) const override;
QVariant data(const QModelIndex& index, int role) const override;
Qt::ItemFlags flags(const QModelIndex& index) const override;
bool setData(const QModelIndex& index, const QVariant& value,
int role) override;
private:
struct Component {
QString name;
State state{State::NotAvailable};
Action action{Action::NoAction};
QString version;
std::vector<File> files;
bool checkOnly{false};
2020-03-15 18:10:26 +07:00
std::vector<std::unique_ptr<Component>> children;
Component* parent{nullptr};
int index{-1};
};
std::unique_ptr<Component> parse(const QJsonObject& json) const;
void updateState(Component& component);
2020-03-17 01:44:33 +07:00
bool hasUpdates(const Component& component) const;
2020-03-15 18:10:26 +07:00
void fillUserActions(UserActions& actions, Component& component) const;
State currentState(const File& file) const;
QString expanded(const QString& source) const;
void emitColumnsChanged(const QModelIndex& parent);
std::unique_ptr<Component> root_;
std::map<QString, QString> expansions_;
};
class Installer
{
public:
explicit Installer(const UserActions& actions);
bool commit();
QString errorString() const;
private:
bool checkIsPossible();
UserActions actions_;
QStringList errors_;
};
class Loader : public QObject
{
Q_OBJECT
public:
explicit Loader(const QUrl& updateUrl, QObject* parent = nullptr);
void checkForUpdates();
void applyUserActions();
Model* model() const;
signals:
2020-03-17 01:44:33 +07:00
void updatesAvailable();
2020-03-15 18:10:26 +07:00
void updated();
void error(const QString& error);
private:
void handleReply(QNetworkReply* reply);
QString toError(QNetworkReply& reply) const;
void finishUpdate(const QString& error = {});
void commitUpdate();
QNetworkAccessManager* network_;
Model* model_;
QUrl updateUrl_;
QString downloadPath_;
std::map<QNetworkReply*, QString> componentReplyToPath_;
std::unique_ptr<Installer> installer_;
};
} // namespace update