Skip to content

Commit f4cdede

Browse files
committed
Update feature completed for Windows
1 parent 5b0b2fa commit f4cdede

File tree

8 files changed

+140
-35
lines changed

8 files changed

+140
-35
lines changed

data/misc/update.cmd

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
set AppFileSlashesEsc=%~1
44
set InstallPath=%~2
55
set UpdatePath=%~3
6+
set "PrevVersionBackupPath=%InstallPath%_old"
67

78
:: Wait for all processes running from this .exe to finish
89
:loop
@@ -13,7 +14,7 @@ if %errorlevel% neq 1 (
1314
)
1415

1516
:: Rename an application directory into a temporary folder with the previous version backup
16-
move /y "%InstallPath%" "%InstallPath%Tmp"
17+
move /y "%InstallPath%" "%PrevVersionBackupPath%"
1718
if %errorlevel% neq 0 (
1819
set "ResultCode=10"
1920
set "ResultMsg=Failed to rename an installation directory to create a previous version backup"
@@ -25,17 +26,17 @@ mkdir "%InstallPath%"
2526
(robocopy "%UpdatePath%" "%InstallPath%" *.* /r:5 /w:2 /e /move >nul) & if %errorlevel% lss 8 set errorlevel=0
2627
if %errorlevel% neq 0 (
2728
:: Restore backup
28-
move /y "%InstallPath%Tmp" "%InstallPath%"
29+
move /y "%PrevVersionBackupPath%" "%InstallPath%"
2930
set "ResultCode=20"
3031
set "ResultMsg=Failed to move an update to the installation directory"
3132
goto :run
3233
)
3334

3435
:: Remove a temporary folder with the previous version backup
35-
rmdir /S /Q "%InstallPath%Tmp" | rem
36+
rmdir /S /Q "%PrevVersionBackupPath%" | rem
3637
if %errorlevel% neq 0 (
3738
set "ResultCode=30"
38-
set "ResultMsg=Updated successfully but failed to remove temporary folder %InstallPath%Tmp"
39+
set "ResultMsg=Updated successfully but failed to remove temporary folder %PrevVersionBackupPath%"
3940
goto :run
4041
)
4142

src/Application.cpp

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,11 @@ QString Application::getDocumentationPath() const
191191
return QDir::current().absoluteFilePath("doc");
192192
}
193193

194+
QString Application::getUpdatePath() const
195+
{
196+
return QDir::temp().absoluteFilePath("CEEDUpdate");
197+
}
198+
194199
void Application::checkForUpdates()
195200
{
196201
if (!Utils::isInternetConnected())
@@ -225,10 +230,25 @@ void Application::checkForUpdates()
225230

226231
QVersionNumber latestVersion = QVersionNumber::fromString(latestVersionStr);
227232
QVersionNumber currentVersion = QVersionNumber::fromString(applicationVersion());
228-
//if (latestVersion.normalized() > currentVersion.normalized())
233+
if (latestVersion.normalized() > currentVersion.normalized())
229234
{
230-
// TODO: check if we failed to update to the latestVersion before, write in a statusbar?
231-
//!!!forced update check must clear this value before calling app::checkForUpdate()!
235+
if (_settings->getQSettings()->value("update/failed").toBool())
236+
{
237+
auto savedVersion = QVersionNumber::fromString(_settings->getQSettings()->value("update/version").toString());
238+
if (latestVersion.normalized() == savedVersion.normalized())
239+
{
240+
_mainWindow->setStatusMessage(tr("Auto-update to %1 is blocked because it failed before. "
241+
"Use Help->Check For Updates to try again.").arg(latestVersionStr));
242+
return;
243+
}
244+
else
245+
{
246+
_settings->getQSettings()->remove("update");
247+
248+
QDir updateDir(getUpdatePath());
249+
if (updateDir.exists()) updateDir.removeRecursively();
250+
}
251+
}
232252

233253
UpdateDialog dlg(currentVersion, latestVersion, releaseInfo);
234254
dlg.exec();
@@ -247,10 +267,10 @@ void Application::checkForUpdates()
247267
void Application::onUpdateError(const QUrl& url, const QString& errorString)
248268
{
249269
_mainWindow->setStatusMessage("Failed to check for updates");
250-
qCritical() << "Network error '" << errorString << "' accessing " << url;
270+
qCritical() << "Update error: '" << errorString << "' accessing " << url;
251271

252-
const auto response = QMessageBox::question(_mainWindow, "Update check failed",
253-
QString("Update failed with error:\n%1\n\nOpen releases web page?").arg(errorString),
272+
const auto response = QMessageBox::question(_mainWindow, tr("Update check failed"),
273+
tr("Update failed with error:\n%1\n\nOpen releases web page?").arg(errorString),
254274
QMessageBox::Yes | QMessageBox::No,
255275
QMessageBox::Yes);
256276

@@ -269,13 +289,75 @@ void Application::checkUpdateResults()
269289
if (!updateLaunched)
270290
QMessageBox::warning(_mainWindow, tr("Warning"), tr("An application was launched by an updater script but no update was scheduled!"));
271291

292+
int updateResult = -1;
293+
QString updateMessage = "<Not launched by updater>";
272294
if (startedByUpdater)
273295
{
274-
const auto updateResult = _cmdLine->value("updateResult").toInt();
275-
const auto updateMessage = _cmdLine->value("updateMessage");
296+
updateResult = _cmdLine->value("updateResult").toInt();
297+
updateMessage = tr(_cmdLine->value("updateMessage").toUtf8());
298+
}
299+
300+
auto currentVersion = QVersionNumber::fromString(applicationVersion());
301+
auto savedVersion = QVersionNumber::fromString(_settings->getQSettings()->value("update/version").toString());
302+
if (currentVersion.normalized() == savedVersion.normalized())
303+
{
304+
// Updated but couldn't remove a tmp folder, let's try again
305+
if (updateResult == 30)
306+
{
307+
QDir backupDir(applicationDirPath() + "_old");
308+
if (!backupDir.exists() || backupDir.removeRecursively())
309+
{
310+
updateResult = 0;
311+
updateMessage = tr("Updated successfully");
312+
}
313+
}
276314

277-
//!!!DBG TMP!
278-
QMessageBox::warning(_mainWindow, "Update results", tr("Code: %1\nMsg: %2").arg(updateResult).arg(updateMessage));
315+
QDir updateDir(getUpdatePath());
316+
if (updateDir.exists()) updateDir.removeRecursively();
317+
318+
auto releaseWebPage = _settings->getQSettings()->value("update/webPage").toString();
319+
if (releaseWebPage.isEmpty())
320+
releaseWebPage= "https://github.com/cegui/ceed-cpp/releases/tag/v" + currentVersion.toString();
321+
322+
_settings->getQSettings()->remove("update");
323+
324+
if (updateResult == 0 && startedByUpdater)
325+
{
326+
// NB: \n is replaced with <br/> to indicate Qt that this is a rich text
327+
QMessageBox::information(_mainWindow, tr("Updated"),
328+
tr("Updated to %1.<br/>"
329+
"Visit <a href=\"%2\">release page</a> for the full release description.<br/><br/>"
330+
"Updater result code: %3<br/>"
331+
"Updater message: %4")
332+
.arg(currentVersion.toString())
333+
.arg(releaseWebPage)
334+
.arg(updateResult)
335+
.arg(updateMessage));
336+
}
337+
else
338+
{
339+
QMessageBox::warning(_mainWindow, tr("Updated with problems"),
340+
tr("Application executable is updated to %1, yet something gone wrong. "
341+
"Please check updater results and reinstall manually if you encounter problems.\n\n"
342+
"Updater result code: %2\n"
343+
"Updater message: %3")
344+
.arg(currentVersion.toString())
345+
.arg(updateResult)
346+
.arg(updateMessage));
347+
}
348+
}
349+
else
350+
{
351+
QMessageBox::critical(_mainWindow, tr("Update failed"),
352+
tr("Failed to update to %1.\n"
353+
"Automatic update will be blocked for this version.\n"
354+
"Use Help->Check For Updates to remove the block.\n\n"
355+
"Updater result code: %2\n"
356+
"Updater message: %3")
357+
.arg(savedVersion.toString())
358+
.arg(updateResult)
359+
.arg(updateMessage));
360+
_settings->getQSettings()->setValue("update/failed", true);
279361
}
280362
}
281363

src/Application.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class Application : public QApplication
3232
void setActionsEnabled(const QString& groupId, bool enabled);
3333

3434
QString getDocumentationPath() const;
35+
QString getUpdatePath() const;
3536

3637
void checkForUpdates();
3738

src/ui/MainWindow.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,14 @@ void MainWindow::on_actionNewOtherFile_triggered()
13501350
}
13511351
}
13521352

1353+
void MainWindow::on_actionCheckForUpdates_triggered()
1354+
{
1355+
// Forced check for update removes a failed flag which prevents an auto-update
1356+
auto app = qobject_cast<Application*>(qApp);
1357+
app->getSettings()->getQSettings()->remove("update/failed");
1358+
app->checkForUpdates();
1359+
}
1360+
13531361
void MainWindow::openNewEditor(EditorBasePtr editor)
13541362
{
13551363
if (!editor) return;

src/ui/MainWindow.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ private slots:
119119
void on_actionNewLayout_triggered();
120120
void on_actionNewImageset_triggered();
121121
void on_actionNewOtherFile_triggered();
122+
void on_actionCheckForUpdates_triggered();
122123

123124
private:
124125

src/ui/dialogs/UpdateDialog.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,14 @@ UpdateDialog::UpdateDialog(const QVersionNumber& currentVersion, const QVersionN
6464
}
6565
else
6666
{
67+
#ifdef Q_OS_WIN
6768
versionStr += tr(" (%3 MB)").arg(static_cast<double>(_releaseAssetSize) / MB, 0, 'f', 1);
69+
#else
70+
// TODO: support auto-update for Linux & Mac!
71+
ui->btnUpdate->setEnabled(false);
72+
ui->btnUpdate->setText(tr("<Not auto-updatable>"));
73+
ui->btnUpdate->setToolTip(tr("Auto-updates are not yet implemented for your OS,\nplease visit a release web page and download manually"));
74+
#endif
6875
}
6976

7077
_releaseWebPage = releaseInfo.value("html_url").toString();
@@ -119,7 +126,8 @@ void UpdateDialog::closeEvent(QCloseEvent* event)
119126

120127
void UpdateDialog::on_btnUpdate_clicked()
121128
{
122-
QSettings* settings = qobject_cast<Application*>(qApp)->getSettings()->getQSettings();
129+
auto app = qobject_cast<Application*>(qApp);
130+
QSettings* settings = app->getSettings()->getQSettings();
123131

124132
// Check if we already have an update package downloaded
125133
QString packageName;
@@ -133,8 +141,8 @@ void UpdateDialog::on_btnUpdate_clicked()
133141
packageName = settings->value("update/package", QString()).toString();
134142
if (!packageName.isEmpty())
135143
{
136-
const QString fileName = QDir::tempPath() + QDir::separator() + "CEEDUpdate" + QDir::separator() + packageName + ".zip";
137-
if (!QFileInfo::exists(fileName))
144+
const QString fileName = QDir(app->getUpdatePath()).absoluteFilePath(packageName + ".zip");
145+
if (QFileInfo(fileName).size() != _releaseAssetSize)
138146
packageName.clear();
139147
}
140148
}
@@ -162,22 +170,18 @@ void UpdateDialog::downloadUpdate()
162170
// FIXME QTBUG: Qt 5.15.2 freezes in QMessageBox::question below
163171
//setWindowFlags(windowFlags() & ~Qt::WindowCloseButtonHint);
164172

165-
QDir tmpDir = QDir::temp();
166-
if (tmpDir.cd("CEEDUpdate"))
167-
{
168-
// Our cache is verified to be invalid, let's erase it and start clean
169-
tmpDir.removeRecursively();
170-
tmpDir.cdUp();
171-
}
173+
auto app = qobject_cast<Application*>(qApp);
172174

173-
tmpDir.mkdir("CEEDUpdate");
174-
tmpDir.cd("CEEDUpdate");
175+
// Our cache is verified to be invalid, let's erase it and start clean
176+
QDir updateDir(app->getUpdatePath());
177+
if (updateDir.exists()) updateDir.removeRecursively();
178+
updateDir.mkpath(".");
175179

176-
QSettings* settings = qobject_cast<Application*>(qApp)->getSettings()->getQSettings();
180+
QSettings* settings = app->getSettings()->getQSettings();
177181
settings->remove("update");
178182

179183
// Reserve disk space for the download
180-
QFile file(tmpDir.absoluteFilePath(_releaseAssetFileName));
184+
QFile file(updateDir.absoluteFilePath(_releaseAssetFileName));
181185
try
182186
{
183187
if (file.open(QFile::WriteOnly))
@@ -327,7 +331,9 @@ void UpdateDialog::installUpdate(const QString& packageName)
327331

328332
// Unpack a zip package
329333

330-
QDir updateDir = QDir(QDir::temp().absoluteFilePath("CEEDUpdate"));
334+
auto app = qobject_cast<Application*>(qApp);
335+
336+
QDir updateDir = QDir(app->getUpdatePath());
331337
QString packageDirPath = updateDir.absoluteFilePath(packageName);
332338
QDir packageDir(packageDirPath);
333339
const QString packageZipPath = packageDirPath + ".zip";
@@ -388,11 +394,11 @@ void UpdateDialog::installUpdate(const QString& packageName)
388394
#endif
389395

390396
// Remember that we started an update to check results on the next CEED launch
391-
QSettings* settings = qobject_cast<Application*>(qApp)->getSettings()->getQSettings();
397+
QSettings* settings = app->getSettings()->getQSettings();
392398
settings->setValue("update/launched", true);
399+
settings->setValue("update/webPage", _releaseWebPage.toString());
393400

394-
//!!!DBG TMP! TODO: uncomment!
395-
//exit(0);
401+
exit(0);
396402
}
397403

398404
void UpdateDialog::onUpdateError(const QString& error)

src/util/Utils.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717
#undef min
1818
#undef max
1919

20-
//!!!DBG TMP!
21-
#include <qdebug.h>
22-
2320
namespace Utils
2421
{
2522

ui/MainWindow.ui

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
<addaction name="actionQt"/>
156156
<addaction name="actionLicense"/>
157157
<addaction name="separator"/>
158+
<addaction name="actionCheckForUpdates"/>
158159
<addaction name="actionAbout"/>
159160
</widget>
160161
<widget class="QMenu" name="menu_Edit">
@@ -754,6 +755,14 @@
754755
<string>Ctrl+D</string>
755756
</property>
756757
</action>
758+
<action name="actionCheckForUpdates">
759+
<property name="text">
760+
<string>Check For Updates</string>
761+
</property>
762+
<property name="toolTip">
763+
<string>Checks the latest official release on GitHub</string>
764+
</property>
765+
</action>
757766
</widget>
758767
<resources>
759768
<include location="../data/Resources.qrc"/>

0 commit comments

Comments
 (0)