feat(client): 迁移Hub更新客户端实现
This commit is contained in:
+125
-315
@@ -1,28 +1,75 @@
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QProcess>
|
||||
#include <QProgressDialog>
|
||||
#include <QInputDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QTranslator>
|
||||
#include <QUuid>
|
||||
|
||||
#include "UpdateLogic.h"
|
||||
#include "../Common/ConfigHelper.h"
|
||||
#include "../Common/PolicyHelper.h"
|
||||
#include "../Common/LocalStateHelper.h"
|
||||
#include "../Common/TicketHelper.h"
|
||||
#include "../Common/DeviceIdentityHelper.h"
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QDir>
|
||||
|
||||
#include "../Common/ConfigHelper.h"
|
||||
#include "../Common/TicketHelper.h"
|
||||
|
||||
namespace {
|
||||
|
||||
QString configValue(const QString& key, const QString& fallback = QString())
|
||||
{
|
||||
const QString value = ConfigHelper::instance().getValue(QString(), key).trimmed();
|
||||
return value.isEmpty() ? fallback : value;
|
||||
}
|
||||
|
||||
QString productCode()
|
||||
{
|
||||
return configValue(QStringLiteral("product_code"),
|
||||
configValue(QStringLiteral("app_id")));
|
||||
}
|
||||
|
||||
QString ensureDeviceId()
|
||||
{
|
||||
ConfigHelper& config = ConfigHelper::instance();
|
||||
QString deviceId = config.getValue(QStringLiteral("Update"), QStringLiteral("device_id")).trimmed();
|
||||
if (!deviceId.isEmpty())
|
||||
return deviceId;
|
||||
|
||||
deviceId = config.getValue(QStringLiteral("Device"), QStringLiteral("installation_id")).trimmed();
|
||||
if (deviceId.isEmpty())
|
||||
deviceId = QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||
|
||||
config.setValue(QStringLiteral("Device"), QStringLiteral("installation_id"), deviceId);
|
||||
config.setValue(QStringLiteral("Update"), QStringLiteral("device_id"), deviceId);
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
QString authFailureMessage(const QJsonObject& response, const QString& fallback)
|
||||
{
|
||||
const QString msg = response.value(QStringLiteral("msg")).toString();
|
||||
if (!msg.isEmpty())
|
||||
return msg;
|
||||
const QJsonValue detail = response.value(QStringLiteral("detail"));
|
||||
if (detail.isObject()) {
|
||||
const QJsonObject object = detail.toObject();
|
||||
const QString detailMsg = object.value(QStringLiteral("msg")).toString();
|
||||
if (!detailMsg.isEmpty())
|
||||
return detailMsg;
|
||||
const QString error = object.value(QStringLiteral("error")).toString();
|
||||
if (!error.isEmpty())
|
||||
return error;
|
||||
}
|
||||
const QString detailText = detail.toString();
|
||||
return detailText.isEmpty() ? fallback : detailText;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
QApplication::setApplicationName("Marsco Launcher");
|
||||
QApplication::setApplicationName("SimCAE Launcher");
|
||||
QTranslator translator;
|
||||
if (translator.load(":/i18n/update-client_zh_CN.qm"))
|
||||
if (translator.load(QStringLiteral(":/i18n/update-client_zh_CN.qm")))
|
||||
app.installTranslator(&translator);
|
||||
|
||||
const int elevatedWriteExitCode = ConfigHelper::runElevatedWriteCommandIfRequested();
|
||||
@@ -30,188 +77,45 @@ int main(int argc, char* argv[])
|
||||
return elevatedWriteExitCode;
|
||||
|
||||
QProgressDialog progress(QCoreApplication::translate("Launcher", "Checking for software updates..."), QString(), 0, 0);
|
||||
progress.setWindowTitle(QCoreApplication::translate("Launcher", "Marsco Launcher"));
|
||||
progress.setCancelButton(nullptr);
|
||||
progress.setWindowModality(Qt::ApplicationModal);
|
||||
progress.setMinimumDuration(0);
|
||||
progress.setAutoClose(false);
|
||||
progress.show();
|
||||
QApplication::processEvents();
|
||||
|
||||
const QString appDir = QApplication::applicationDirPath();
|
||||
progress.setWindowTitle(QCoreApplication::translate("Launcher", "SimCAE Launcher"));
|
||||
progress.setCancelButton(nullptr);
|
||||
progress.setWindowModality(Qt::ApplicationModal);
|
||||
progress.setMinimumDuration(0);
|
||||
progress.setAutoClose(false);
|
||||
progress.show();
|
||||
QApplication::processEvents();
|
||||
|
||||
ConfigHelper& config = ConfigHelper::instance();
|
||||
const auto isLicenseError = [](const QString& errorText) {
|
||||
const QString text = errorText.toLower();
|
||||
return text.contains("license")
|
||||
|| text.contains("authorization")
|
||||
|| text.contains("expired")
|
||||
|| text.contains("device limit")
|
||||
|| text.contains("bound to another license");
|
||||
};
|
||||
const auto clearDeviceCredential = [&]() {
|
||||
ConfigHelper::removeFileWithElevationIfNeeded(ConfigHelper::instance().clientIdentityPath());
|
||||
config.setValue("Update", "device_id", QString());
|
||||
};
|
||||
QString licenseKey = config.getValue("License", "license_key").trimmed();
|
||||
auto promptAndSaveLicense = [&](const QString& reason) -> QString {
|
||||
QString promptReason = reason;
|
||||
while (true) {
|
||||
progress.close();
|
||||
bool accepted = false;
|
||||
const QString appName = config.getValue("App", "app_name").trimmed();
|
||||
const QString prompt = promptReason.trimmed().isEmpty()
|
||||
? QCoreApplication::translate("Launcher", "Please enter the License for %1:")
|
||||
.arg(appName.isEmpty() ? QCoreApplication::translate("Launcher", "the application") : appName)
|
||||
: QCoreApplication::translate("Launcher", "%1\n\nPlease enter a new License for %2:")
|
||||
.arg(promptReason, appName.isEmpty() ? QCoreApplication::translate("Launcher", "the application") : appName);
|
||||
licenseKey = QInputDialog::getText(
|
||||
nullptr,
|
||||
QCoreApplication::translate("Launcher", "Enter License"),
|
||||
prompt,
|
||||
QLineEdit::Normal,
|
||||
QString(),
|
||||
&accepted
|
||||
).trimmed();
|
||||
if (!accepted) {
|
||||
QMessageBox::information(nullptr,
|
||||
QCoreApplication::translate("Launcher", "License Required"),
|
||||
QCoreApplication::translate("Launcher", "A License provided by the administrator is required for the first launch."));
|
||||
return QString();
|
||||
}
|
||||
if (licenseKey.isEmpty()) {
|
||||
QMessageBox::warning(nullptr,
|
||||
QCoreApplication::translate("Launcher", "License Cannot Be Empty"),
|
||||
QCoreApplication::translate("Launcher", "Please paste the License created in the admin page."));
|
||||
promptReason.clear();
|
||||
continue;
|
||||
}
|
||||
if (!config.setValue("License", "license_key", licenseKey)) {
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Failed to Save License"),
|
||||
QCoreApplication::translate("Launcher", "Cannot write the configuration file:\n%1\n%2").arg(config.configPath(), config.lastError()));
|
||||
return QString();
|
||||
}
|
||||
progress.show();
|
||||
progress.setLabelText(QCoreApplication::translate("Launcher", "Verifying License..."));
|
||||
QApplication::processEvents();
|
||||
return licenseKey;
|
||||
}
|
||||
};
|
||||
|
||||
while (true) {
|
||||
// License 首次为空、过期或已达设备上限时,在 Launcher 内引导用户重新输入。
|
||||
// 成功后服务端会签发 client_identity.dat,并把真实 device_id 写入运行配置。
|
||||
if (licenseKey.isEmpty()) {
|
||||
licenseKey = promptAndSaveLicense(QString());
|
||||
if (licenseKey.isEmpty()) return 0;
|
||||
}
|
||||
DeviceIdentityHelper identity(appDir);
|
||||
if (identity.ensureIssued(config.getValue("Server", "api_base_url"),
|
||||
config.getValue("Server", "client_token"),
|
||||
config.getValue("App", "app_id"),
|
||||
config.getValue("App", "channel"),
|
||||
licenseKey)) {
|
||||
break;
|
||||
}
|
||||
const QString error = identity.errorString();
|
||||
if (!isLicenseError(error)) {
|
||||
progress.close();
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Device Authentication Failed"),
|
||||
error);
|
||||
return -1;
|
||||
}
|
||||
clearDeviceCredential();
|
||||
licenseKey = promptAndSaveLicense(QCoreApplication::translate("Launcher", "The current License cannot be used: %1").arg(error));
|
||||
if (licenseKey.isEmpty()) return 0;
|
||||
}
|
||||
|
||||
UpdateLogic logic;
|
||||
logic.checkUpdate();
|
||||
|
||||
const bool needUpdate = logic.getNeedUpdate();
|
||||
const bool networkOk = logic.isNetworkOk();
|
||||
const QString latestVer = logic.getLatestVersion();
|
||||
const QString appDir = QApplication::applicationDirPath();
|
||||
|
||||
progress.setLabelText(QCoreApplication::translate("Launcher", "Checking authorized updates..."));
|
||||
QApplication::processEvents();
|
||||
UpdateLogic logic;
|
||||
logic.checkUpdate();
|
||||
|
||||
const bool needUpdate = logic.getNeedUpdate();
|
||||
const bool networkOk = logic.isNetworkOk();
|
||||
const QString latestVer = logic.getLatestVersion();
|
||||
const QJsonObject response = logic.getCheckResult();
|
||||
const int targetVersionId = response.value("version_id").toInt();
|
||||
const QString appId = logic.getAppId();
|
||||
const QString releaseId = response.value(QStringLiteral("release_id")).toString(
|
||||
response.value(QStringLiteral("id")).toString());
|
||||
const QString appId = logic.getProductCode();
|
||||
const QString channel = logic.getChannel();
|
||||
const QString launchToken = config.getValue("App", "launch_token");
|
||||
const QString currentVersion = config.getValue("App", "current_version");
|
||||
|
||||
if (logic.lastStatusCode() == 401 || logic.lastStatusCode() == 403) {
|
||||
progress.close();
|
||||
const QJsonValue detail = response.value("detail");
|
||||
const QString message = detail.isObject() ? detail.toObject().value("msg").toString() : detail.toString();
|
||||
const QString displayMessage = message.isEmpty()
|
||||
? QCoreApplication::translate("Launcher", "The device or License authorization is invalid.")
|
||||
: message;
|
||||
if (isLicenseError(displayMessage)) {
|
||||
clearDeviceCredential();
|
||||
const QString newLicense = promptAndSaveLicense(QCoreApplication::translate("Launcher", "The current authorization was rejected by the server: %1").arg(displayMessage));
|
||||
if (!newLicense.isEmpty()) {
|
||||
progress.close();
|
||||
QMessageBox::information(nullptr,
|
||||
QCoreApplication::translate("Launcher", "License Saved"),
|
||||
QCoreApplication::translate("Launcher", "Please restart Launcher to complete device authorization and update checking."));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Authorization Rejected"),
|
||||
displayMessage);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const QString launchToken = config.getValue(QStringLiteral("App"), QStringLiteral("launch_token"));
|
||||
const QString currentVersion = config.getValue(QStringLiteral("App"), QStringLiteral("current_version"));
|
||||
const QString deviceId = ensureDeviceId();
|
||||
|
||||
const auto configuredName = [&](const QString& key, const QString& fallback) {
|
||||
return ConfigHelper::executableNameForCurrentPlatform(
|
||||
config.getValue("Runtime", key), fallback);
|
||||
config.getValue(QStringLiteral("Runtime"), key), fallback);
|
||||
};
|
||||
const QString mainExecutable = configuredName("main_executable", "MainApp");
|
||||
const QString updaterExecutable = configuredName("updater_executable", "Updater");
|
||||
const QString mainExecutable = configuredName(QStringLiteral("main_executable"), QStringLiteral("MainApp"));
|
||||
const QString updaterExecutable = configuredName(QStringLiteral("updater_executable"), QStringLiteral("Updater"));
|
||||
const QString mainAppPath = QDir(appDir).filePath(mainExecutable);
|
||||
const QString updaterPath = QDir(appDir).filePath(updaterExecutable);
|
||||
const auto importOfflinePackage = [&]() {
|
||||
const QString package = QFileDialog::getOpenFileName(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Select Offline Update Package"),
|
||||
QString(),
|
||||
QCoreApplication::translate("Launcher", "Marsco offline update package (*.upd)"));
|
||||
if (package.isEmpty())
|
||||
return false;
|
||||
if (!QFileInfo::exists(updaterPath)) {
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Updater Startup Failed"),
|
||||
QCoreApplication::translate(
|
||||
"Launcher",
|
||||
"Cannot import the offline update package because the updater executable does not exist.\nUpdater: %1\nOffline package: %2")
|
||||
.arg(updaterPath, package));
|
||||
return false;
|
||||
}
|
||||
if (!QProcess::startDetached(updaterPath, QStringList{QString("--offline-package=%1").arg(package)})) {
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Updater Startup Failed"),
|
||||
QCoreApplication::translate(
|
||||
"Launcher",
|
||||
"Cannot start the updater for offline package import.\nUpdater: %1\nOffline package: %2\nCheck file permissions and dependent DLLs/shared libraries.")
|
||||
.arg(updaterPath, package));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const QString deviceId = config.getValue("Update", "device_id");
|
||||
if (QCoreApplication::arguments().contains("--import-offline")) {
|
||||
progress.close();
|
||||
if (!importOfflinePackage())
|
||||
QMessageBox::information(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Offline Update"),
|
||||
QCoreApplication::translate("Launcher", "No offline update package was selected."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
QString mainStartupError;
|
||||
const auto startMainApp = [&]() {
|
||||
// 只允许 Launcher 启动业务主程序:先生成一次性 ticket,再通过 --ticket-file 传给主程序。
|
||||
// 业务主程序必须消费并校验 ticket,避免用户直接双击 SimCAE/MainApp 绕过更新和授权检查。
|
||||
mainStartupError.clear();
|
||||
if (!QFileInfo::exists(mainAppPath)) {
|
||||
mainStartupError = QCoreApplication::translate(
|
||||
@@ -220,9 +124,10 @@ int main(int argc, char* argv[])
|
||||
.arg(mainAppPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
QString ticketPath;
|
||||
QString ticketError;
|
||||
if (!TicketHelper::createTicket(logic.getAppId(), deviceId, currentVersion,
|
||||
if (!TicketHelper::createTicket(appId, deviceId, currentVersion,
|
||||
launchToken, &ticketPath, &ticketError)) {
|
||||
qDebug() << "Cannot create launch ticket:" << ticketError;
|
||||
mainStartupError = QCoreApplication::translate(
|
||||
@@ -231,8 +136,9 @@ int main(int argc, char* argv[])
|
||||
.arg(mainAppPath, ticketError);
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool started = QProcess::startDetached(mainAppPath,
|
||||
QStringList{QString("--ticket-file=%1").arg(ticketPath)});
|
||||
QStringList{QStringLiteral("--ticket-file=%1").arg(ticketPath)});
|
||||
if (!started) {
|
||||
QFile::remove(ticketPath);
|
||||
mainStartupError = QCoreApplication::translate(
|
||||
@@ -242,97 +148,33 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
return started;
|
||||
};
|
||||
|
||||
progress.setLabelText(QCoreApplication::translate("Launcher", "Verifying local runtime policy..."));
|
||||
QApplication::processEvents();
|
||||
|
||||
PolicyHelper policy(appDir);
|
||||
if (!policy.loadPolicy("config/version_policy.dat") || !policy.isValid())
|
||||
{
|
||||
progress.close();
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Cannot Start"),
|
||||
QCoreApplication::translate("Launcher", "The local version policy is invalid: %1").arg(policy.errorString()));
|
||||
return -1;
|
||||
}
|
||||
if (policy.isExpired())
|
||||
{
|
||||
progress.close();
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Cannot Start"),
|
||||
QCoreApplication::translate("Launcher", "The local version policy has expired. Please connect to the network or contact the administrator."));
|
||||
return -1;
|
||||
}
|
||||
if ((!policy.allowRun() || !policy.isVersionAllowed(currentVersion)) && !(networkOk && needUpdate))
|
||||
{
|
||||
progress.close();
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Current Version Cannot Run"),
|
||||
policy.message().isEmpty() ? QCoreApplication::translate("Launcher", "The current version %1 has been disabled by the administrator.").arg(currentVersion)
|
||||
: policy.message());
|
||||
return -1;
|
||||
}
|
||||
|
||||
LocalStateHelper state(appDir);
|
||||
if (!state.loadState())
|
||||
{
|
||||
progress.close();
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Cannot Start"),
|
||||
QCoreApplication::translate("Launcher", "Cannot read the local state: %1").arg(state.errorString()));
|
||||
return -1;
|
||||
}
|
||||
if (state.isPolicySeqRolledBack(policy.policySeq()))
|
||||
{
|
||||
progress.close();
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Security Check Failed"),
|
||||
QCoreApplication::translate("Launcher", "A version policy sequence rollback was detected. Startup has been blocked."));
|
||||
return -1;
|
||||
}
|
||||
if (state.isSystemTimeRewound())
|
||||
{
|
||||
|
||||
if (logic.lastStatusCode() == 401 || logic.lastStatusCode() == 403) {
|
||||
progress.close();
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Security Check Failed"),
|
||||
QCoreApplication::translate("Launcher", "A possible system time rollback was detected. Startup has been blocked."));
|
||||
QCoreApplication::translate("Launcher", "Update Client Rejected"),
|
||||
authFailureMessage(response,
|
||||
QCoreApplication::translate("Launcher", "The update client token is missing or invalid. Please download a valid package from the customer portal.")));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (networkOk && policy.gitTagsEnabled())
|
||||
{
|
||||
progress.setLabelText(QCoreApplication::translate("Launcher", "Generating Git tag list..."));
|
||||
QApplication::processEvents();
|
||||
const QString tagsPath = QDir(appDir).filePath("tags.txt");
|
||||
if (!logic.refreshGitTagsFile(tagsPath))
|
||||
{
|
||||
progress.close();
|
||||
QMessageBox::warning(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Git Tag List Failed"),
|
||||
QCoreApplication::translate("Launcher", "Cannot generate tags.txt, but startup will continue:\n%1").arg(logic.errorString()));
|
||||
progress.show();
|
||||
QApplication::processEvents();
|
||||
}
|
||||
} else if (!networkOk) {
|
||||
progress.close();
|
||||
QMessageBox::warning(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Update Server Unavailable"),
|
||||
QCoreApplication::translate("Launcher", "Cannot connect to the update server. The installed application will be started without downloading an update."));
|
||||
progress.show();
|
||||
}
|
||||
|
||||
if (networkOk && needUpdate)
|
||||
{
|
||||
progress.close();
|
||||
const bool rollbackOperation = response.value("action").toString() == "rollback_allowed";
|
||||
const QString dialogTitle = rollbackOperation ? QCoreApplication::translate("Launcher", "Version Rollback")
|
||||
: (policy.forceUpdate() ? QCoreApplication::translate("Launcher", "Update Required") : QCoreApplication::translate("Launcher", "New Version Available"));
|
||||
const QString prompt = policy.message().isEmpty()
|
||||
? (rollbackOperation
|
||||
? QCoreApplication::translate("Launcher", "The administrator provided version %1 as the rollback target. Downgrade now?").arg(latestVer)
|
||||
: QCoreApplication::translate("Launcher", "Version %1 is available. Update now?").arg(latestVer))
|
||||
: policy.message() + QCoreApplication::translate("Launcher", "\nTarget version: %1").arg(latestVer);
|
||||
bool accepted = true;
|
||||
if (policy.forceUpdate()) {
|
||||
QMessageBox::information(nullptr, dialogTitle, prompt);
|
||||
} else {
|
||||
accepted = QMessageBox::question(nullptr, dialogTitle, prompt,
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes;
|
||||
}
|
||||
const QString prompt = QCoreApplication::translate(
|
||||
"Launcher",
|
||||
"Version %1 is available. Update now?").arg(latestVer);
|
||||
const bool accepted = QMessageBox::question(nullptr,
|
||||
QCoreApplication::translate("Launcher", "New Version Available"),
|
||||
prompt,
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::No) == QMessageBox::Yes;
|
||||
if (!accepted) {
|
||||
if (!startMainApp()) {
|
||||
QMessageBox::critical(nullptr,
|
||||
@@ -344,7 +186,14 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
const QStringList updaterArgs{appId, channel, latestVer, QString::number(targetVersionId)};
|
||||
|
||||
const QStringList updaterArgs{
|
||||
appId,
|
||||
channel,
|
||||
latestVer,
|
||||
QStringLiteral("0"),
|
||||
QStringLiteral("--release-id=%1").arg(releaseId)
|
||||
};
|
||||
if (!QFileInfo::exists(updaterPath))
|
||||
{
|
||||
QMessageBox::critical(nullptr,
|
||||
@@ -368,49 +217,10 @@ int main(int argc, char* argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (networkOk && !needUpdate && targetVersionId > 0 && latestVer == currentVersion)
|
||||
{
|
||||
progress.setLabelText(QCoreApplication::translate("Launcher", "Caching signed version manifest..."));
|
||||
QApplication::processEvents();
|
||||
const QString manifestCacheDir = QDir(ConfigHelper::instance().updateRoot()).filePath("manifest_cache");
|
||||
if (!logic.cacheManifest(appId, channel, currentVersion, targetVersionId, manifestCacheDir))
|
||||
{
|
||||
progress.close();
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Manifest Cache Failed"),
|
||||
QCoreApplication::translate("Launcher", "Cannot cache the signed manifest for the current version: %1").arg(logic.errorString()));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!networkOk) {
|
||||
progress.close();
|
||||
if (QMessageBox::question(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Server Unavailable"),
|
||||
QCoreApplication::translate("Launcher", "Cannot connect to the update server. Import an offline update package?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
|
||||
if (!importOfflinePackage())
|
||||
QMessageBox::information(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Offline Update"),
|
||||
QCoreApplication::translate("Launcher", "No offline update package was selected, or the updater could not be started."));
|
||||
return 0;
|
||||
}
|
||||
progress.show();
|
||||
}
|
||||
|
||||
if (!networkOk && !policy.isOfflineAllowed())
|
||||
{
|
||||
progress.close();
|
||||
QMessageBox::critical(nullptr,
|
||||
QCoreApplication::translate("Launcher", "Network Unavailable"),
|
||||
QCoreApplication::translate("Launcher", "Cannot connect to the update server, and the current policy does not allow offline startup."));
|
||||
return -1;
|
||||
}
|
||||
|
||||
progress.setLabelText(networkOk
|
||||
? QCoreApplication::translate("Launcher", "The application is up to date. Starting...")
|
||||
: QCoreApplication::translate("Launcher", "Offline mode is active. Starting..."));
|
||||
QApplication::processEvents();
|
||||
: QCoreApplication::translate("Launcher", "Offline startup. Starting..."));
|
||||
QApplication::processEvents();
|
||||
if (!startMainApp())
|
||||
{
|
||||
progress.close();
|
||||
@@ -421,6 +231,6 @@ int main(int argc, char* argv[])
|
||||
: mainStartupError);
|
||||
return -1;
|
||||
}
|
||||
progress.close();
|
||||
return 0;
|
||||
}
|
||||
progress.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user