Add support of multiple update urls
This commit is contained in:
parent
d931015d6b
commit
576d9d5662
@ -28,10 +28,11 @@ const auto updatesUrl =
|
|||||||
#endif
|
#endif
|
||||||
const auto resultHideWaitUs = 300'000;
|
const auto resultHideWaitUs = 300'000;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
using Loader = update::Loader;
|
||||||
|
|
||||||
Manager::Manager()
|
Manager::Manager()
|
||||||
: settings_(std::make_unique<Settings>())
|
: settings_(std::make_unique<Settings>())
|
||||||
, updater_(std::make_unique<update::Loader>(QUrl(updatesUrl)))
|
, updater_(std::make_unique<Loader>(Loader::Urls{{updatesUrl}}))
|
||||||
, updateAutoChecker_(std::make_unique<update::AutoChecker>(*updater_))
|
, updateAutoChecker_(std::make_unique<update::AutoChecker>(*updater_))
|
||||||
, models_(std::make_unique<CommonModels>())
|
, models_(std::make_unique<CommonModels>())
|
||||||
{
|
{
|
||||||
|
@ -92,22 +92,26 @@ QStringList toList(const QJsonValue &value)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Loader::Loader(const QUrl &updateUrl, QObject *parent)
|
Loader::Loader(const update::Loader::Urls &updateUrls, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, network_(new QNetworkAccessManager(this))
|
, network_(new QNetworkAccessManager(this))
|
||||||
, model_(new Model(this))
|
, model_(new Model(this))
|
||||||
, updateUrl_(updateUrl)
|
, updateUrls_(updateUrls)
|
||||||
, downloadPath_(
|
, downloadPath_(
|
||||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) +
|
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) +
|
||||||
"/updates")
|
"/updates")
|
||||||
{
|
{
|
||||||
|
std::random_device device;
|
||||||
|
std::mt19937 generator(device());
|
||||||
|
std::shuffle(updateUrls_.begin(), updateUrls_.end(), generator);
|
||||||
|
|
||||||
connect(network_, &QNetworkAccessManager::finished, //
|
connect(network_, &QNetworkAccessManager::finished, //
|
||||||
this, &Loader::handleReply);
|
this, &Loader::handleReply);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::handleReply(QNetworkReply *reply)
|
void Loader::handleReply(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
if (reply->url() == updateUrl_) {
|
if (updateUrls_.contains(reply->url())) {
|
||||||
handleUpdateReply(reply);
|
handleUpdateReply(reply);
|
||||||
} else {
|
} else {
|
||||||
handleComponentReply(reply);
|
handleComponentReply(reply);
|
||||||
@ -116,7 +120,28 @@ void Loader::handleReply(QNetworkReply *reply)
|
|||||||
|
|
||||||
void Loader::checkForUpdates()
|
void Loader::checkForUpdates()
|
||||||
{
|
{
|
||||||
auto reply = network_->get(QNetworkRequest(updateUrl_));
|
startDownloadUpdates({});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Loader::startDownloadUpdates(const QUrl &previous)
|
||||||
|
{
|
||||||
|
SOFT_ASSERT(!updateUrls_.isEmpty(), return );
|
||||||
|
|
||||||
|
QUrl url;
|
||||||
|
if (previous.isEmpty())
|
||||||
|
url = updateUrls_.first();
|
||||||
|
else {
|
||||||
|
const auto index = updateUrls_.indexOf(previous);
|
||||||
|
SOFT_ASSERT(index != -1, return );
|
||||||
|
if (index == updateUrls_.size() - 1)
|
||||||
|
return;
|
||||||
|
url = updateUrls_[index + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto reply = network_->get(QNetworkRequest(url));
|
||||||
if (reply->error() != QNetworkReply::NoError)
|
if (reply->error() != QNetworkReply::NoError)
|
||||||
handleUpdateReply(reply);
|
handleUpdateReply(reply);
|
||||||
}
|
}
|
||||||
@ -127,13 +152,28 @@ void Loader::handleUpdateReply(QNetworkReply *reply)
|
|||||||
|
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
emit error(toError(*reply));
|
emit error(toError(*reply));
|
||||||
|
startDownloadUpdates(reply->url());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto replyData = reply->readAll();
|
const auto replyData = reply->readAll();
|
||||||
|
if (replyData.isEmpty()) {
|
||||||
|
emit error(
|
||||||
|
tr("Received empty updates info from %1").arg(reply->url().toString()));
|
||||||
|
startDownloadUpdates(reply->url());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SOFT_ASSERT(model_, return );
|
SOFT_ASSERT(model_, return );
|
||||||
model_->parse(replyData);
|
const auto parseError = model_->parse(replyData);
|
||||||
|
if (!parseError.isEmpty()) {
|
||||||
|
emit error(tr("Failed to parse updates from %1 (%2)")
|
||||||
|
.arg(reply->url().toString(), parseError));
|
||||||
|
startDownloadUpdates(reply->url());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (model_->hasUpdates())
|
if (model_->hasUpdates())
|
||||||
emit updatesAvailable();
|
emit updatesAvailable();
|
||||||
}
|
}
|
||||||
@ -324,20 +364,20 @@ void Model::initView(QTreeView *view)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::parse(const QByteArray &data)
|
QString Model::parse(const QByteArray &data)
|
||||||
{
|
{
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
const auto doc = QJsonDocument::fromJson(data, &error);
|
const auto doc = QJsonDocument::fromJson(data, &error);
|
||||||
if (doc.isNull()) {
|
if (doc.isNull()) {
|
||||||
LERROR() << error.errorString();
|
return tr("Failed to parse: %1 at %2")
|
||||||
return;
|
.arg(error.errorString())
|
||||||
|
.arg(error.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto json = doc.object();
|
const auto json = doc.object();
|
||||||
const auto version = json[versionKey].toInt();
|
const auto version = json[versionKey].toInt();
|
||||||
if (version != 1) {
|
if (version != 1) {
|
||||||
LERROR() << "Wrong updates.json version" << version;
|
return tr("Wrong updates version %1").arg(version);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
@ -347,6 +387,11 @@ void Model::parse(const QByteArray &data)
|
|||||||
updateState(*root_);
|
updateState(*root_);
|
||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
||||||
|
if (!root_) {
|
||||||
|
return tr("No data parsed");
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Model::Component> Model::parse(const QJsonObject &json) const
|
std::unique_ptr<Model::Component> Model::parse(const QJsonObject &json) const
|
||||||
|
@ -58,7 +58,7 @@ public:
|
|||||||
|
|
||||||
void initView(QTreeView* view);
|
void initView(QTreeView* view);
|
||||||
|
|
||||||
void parse(const QByteArray& data);
|
QString parse(const QByteArray& data);
|
||||||
void setExpansions(const std::map<QString, QString>& expansions);
|
void setExpansions(const std::map<QString, QString>& expansions);
|
||||||
UserActions userActions() const;
|
UserActions userActions() const;
|
||||||
void updateStates();
|
void updateStates();
|
||||||
@ -130,7 +130,8 @@ class Loader : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit Loader(const QUrl& updateUrl, QObject* parent = nullptr);
|
using Urls = QVector<QUrl>;
|
||||||
|
explicit Loader(const Urls& updateUrls, QObject* parent = nullptr);
|
||||||
|
|
||||||
void checkForUpdates();
|
void checkForUpdates();
|
||||||
void applyUserActions();
|
void applyUserActions();
|
||||||
@ -150,10 +151,11 @@ private:
|
|||||||
void commitUpdate();
|
void commitUpdate();
|
||||||
void updateProgress(qint64 bytesSent, qint64 bytesTotal);
|
void updateProgress(qint64 bytesSent, qint64 bytesTotal);
|
||||||
bool startDownload(File& file);
|
bool startDownload(File& file);
|
||||||
|
void startDownloadUpdates(const QUrl& previous);
|
||||||
|
|
||||||
QNetworkAccessManager* network_;
|
QNetworkAccessManager* network_;
|
||||||
Model* model_;
|
Model* model_;
|
||||||
QUrl updateUrl_;
|
Urls updateUrls_;
|
||||||
QString downloadPath_;
|
QString downloadPath_;
|
||||||
std::map<QNetworkReply*, File*> downloads_;
|
std::map<QNetworkReply*, File*> downloads_;
|
||||||
UserActions currentActions_;
|
UserActions currentActions_;
|
||||||
|
Loading…
Reference in New Issue
Block a user