[PATCH 4 of 4] Start implementation of software update installation
Wald Commits
scm-commit at wald.intevation.org
Tue May 20 18:40:34 CEST 2014
# HG changeset patch
# User Andre Heinecke <aheinecke at intevation.de>
# Date 1400604028 0
# Node ID 15121735805eb2f00ba2c7a6e904c99195fce3fd
# Parent 0ec3516bf65c62105125c8630585b9897636883f
Start implementation of software update installation
diff -r 0ec3516bf65c -r 15121735805e ui/mainwindow.cpp
--- a/ui/mainwindow.cpp Tue May 20 16:39:51 2014 +0000
+++ b/ui/mainwindow.cpp Tue May 20 16:40:28 2014 +0000
@@ -8,6 +8,7 @@
#include "mainwindow.h"
#include <QDebug>
+#include <QProcess>
#include <QProgressDialog>
#include <QMessageBox>
#include <QSystemTrayIcon>
@@ -35,7 +36,7 @@
#define SERVER_URL "https://files.intevation.de:443"
#define LIST_RESOURCE "/users/aheinecke/zertifikatsliste.txt"
-#define SW_RESOURCE "/users/aheinecke/zertifikatsliste.txt"
+#define SW_RESOURCE "/users/aheinecke/trustbridge.exe"
#ifdef Q_OS_WIN
#define SW_RESOURCE_VERSION "/users/aheinecke/trustbridge-%1.exe"
#else
@@ -50,6 +51,7 @@
#include "separatoritemdelegate.h"
#include "installwrapper.h"
#include "util.h"
+#include "logging.h"
MainWindow::MainWindow(bool trayMode):
mTrayMode(trayMode)
@@ -97,6 +99,11 @@
if (mCurState == NewListAvailable) {
show();
}
+
+ if (mCurState == NewSoftwareAvailable) {
+ checkUpdates(true);
+ mCurState = DownloadingSW;
+ }
}
void MainWindow::showMessage()
@@ -148,7 +155,7 @@
}
if (!swFileName.isEmpty()) {
- // TODO
+ // TODO Verify integrity of the software
} else {
mSettings.remove("Software/available");
mSettings.remove("Software/availableDate");
@@ -176,7 +183,8 @@
}
void MainWindow::handleNewSW(const QString& fileName, const QDateTime& modDate) {
- mCurMessage = tr("An update for %1 is available. Click here to install.").arg(
+ mCurMessage = tr("<h3>An update for %1 is available.</h3>\n"
+ "Click here to download and install the update.").arg(
QApplication::applicationName());
setState(NewSoftwareAvailable);
mSettings.setValue("Software/available", fileName);
@@ -186,12 +194,61 @@
showMessage();
}
+void MainWindow::installNewSW(const QString& fileName, const QDateTime& modDate) {
+ QFileInfo instProcInfo = QFileInfo(fileName);
+ if (!instProcInfo.isExecutable()) {
+ qWarning() << "Downloaded file: " << fileName << " is not executable.";
+ setState(TransferError);
+ return;
+ }
+#ifdef WIN32
+ SHELLEXECUTEINFOW shExecInfo;
+ shExecInfo.lpFile = reinterpret_cast<LPCWSTR> (fileName.utf16());
+
+ if (!is_admin()) {
+ shExecInfo.lpVerb = L"open";
+ } else {
+ shExecInfo.lpVerb = L"runas";
+ }
+
+ qDebug() << "Starting process " << fileName;
+
+ if (!ShellExecuteExW(&shExecInfo)) {
+ /* Execution failed, maybe the user aborted the UAC check? */
+ char* errmsg = getLastErrorMsg();
+ QString qerrmsg = QString::fromUtf8(errmsg);
+ free(errmsg);
+ qDebug() << "Failed to start process: " << qerrmsg;
+ setState(NewSoftwareAvailable);
+ return;
+ }
+
+#else /* WIN32 */
+ QProcess installerProcess;
+ installerProcess.setProgram(fileName);
+
+ qDebug() << "Starting process " << fileName;
+
+ if (!installerProcess.waitForStarted() ||
+ installerProcess.state() == QProcess::NotRunning) {
+ qDebug() << "Failed to start process.";
+ return;
+ }
+#endif
+ /* Installer process should now be running. We exit */
+
+ closeApp();
+}
+
void MainWindow::checkUpdates(bool downloadSW)
{
verifyAvailableData();
- if (!mSettings.contains("Software/installedDate")) {
- lookUpDateForVersion();
+ if (!mSettings.contains("Software/installedDate") ||
+ mSettings.value("Software/installedVersion").toString() != QApplication::applicationVersion()) {
+ /* This should only happen on initial startup and after an update has
+ * been installed */
+ getLastModForCurrentVersion();
return;
}
QDateTime listInstalledLastMod = mSettings.value("List/installedDate").toDateTime();
@@ -210,8 +267,7 @@
Downloader* downloader = new Downloader(this,
QString::fromLatin1(SERVER_URL),
QByteArray(),
- QDateTime::currentDateTime(),
-// TODO swInstalledLastMod,
+ swInstalledLastMod,
listInstalledLastMod,
swResource,
listResource,
@@ -221,19 +277,19 @@
this, SLOT(handleNewList(const QString&, const QDateTime&)));
if (!downloadSW) {
connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)),
- this, SLOT(newSWAvailable(const QString&, const QDateTime&)));
+ this, SLOT(handleNewSW(const QString&, const QDateTime&)));
+ } else {
+ connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)),
+ this, SLOT(installNewSW(const QString&, const QDateTime&)));
}
- else {
- connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)),
- this, SLOT(handleNewSW(const QString&, const QDateTime&)));
- }
+
connect(downloader, SIGNAL(finished()), downloader, SLOT(deleteLater()));
connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)),
this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode)));
downloader->start();
}
-void MainWindow::lookUpDateForVersion()
+void MainWindow::getLastModForCurrentVersion()
{
QString softwareVersion = QString::fromLatin1(SW_RESOURCE_VERSION).arg(
QApplication::applicationVersion());
@@ -251,39 +307,28 @@
connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)),
this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode)));
connect(downloader, SIGNAL(lastModifiedDate(const QDateTime&)),
- this, SLOT(setLastModifiedDate(const QDateTime&)));
+ this, SLOT(setLastModifiedSWDate(const QDateTime&)));
downloader->start();
}
-void MainWindow::setLastModifiedDate(const QDateTime &date)
+void MainWindow::setLastModifiedSWDate(const QDateTime &date)
{
mSettings.beginGroup("Software");
mSettings.setValue("installedDate", date);
+ mSettings.setValue("installedVersion", QApplication::applicationVersion());
mSettings.endGroup();
checkUpdates();
}
-void MainWindow::newSWAvailable(const QString &fileName, const QDateTime &date) {
- QMessageBox msgBox;
- msgBox.setIcon(QMessageBox::Information);
- msgBox.setText("<h3>" + tr("New Software version is available.") + "</h3>");
- msgBox.setInformativeText(tr("Do you want to install the new Version?"));
- msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
- msgBox.setDefaultButton(QMessageBox::Yes);
- int selection = msgBox.exec();
- if (selection == QMessageBox::Yes) {
- checkUpdates(true);
- }
-}
-
void MainWindow::downloaderError(const QString &message, SSLConnection::ErrorCode error)
{
+ /* TODO logging and handle error according to a plan */
mCurMessage = message;
showMessage();
+ setState(TransferError);
}
-
void MainWindow::createActions()
{
mCheckUpdates = new QAction(tr("Check for Updates"), this);
diff -r 0ec3516bf65c -r 15121735805e ui/mainwindow.h
--- a/ui/mainwindow.h Tue May 20 16:39:51 2014 +0000
+++ b/ui/mainwindow.h Tue May 20 16:40:28 2014 +0000
@@ -54,6 +54,7 @@
BeforeDownload,
NewListAvailable,
NewSoftwareAvailable,
+ DownloadingSW,
TransferError,
NothingChanged
};
@@ -76,13 +77,33 @@
void installerError(const QString& errMsg);
void installerSuccess();
void installCerts();
- void newSWAvailable(const QString& fileName, const QDateTime& modDate);
+
+ /* @brief Execute the file fileName to install the softwareupdate.
+ *
+ * Once the installer process is started this function terminates
+ * the application. */
+ void installNewSW(const QString& fileName, const QDateTime& modDate);
void saveAutoUpdate(int state);
void saveAutoStart(int state);
- void lookUpDateForVersion();
- void setLastModifiedDate(const QDateTime &date);
+ /** @brief get the last modified date on the download server for
+ * the current version.
+ *
+ * After the initial installation this function can be used to
+ * determine the DateTime that corresponds to the currently installed
+ * version on the download server.
+ *
+ * Calls setLastModifiedSWDate on success. Otherwise downloaderError
+ * is triggered. */
+ void getLastModForCurrentVersion();
+
+ /** @brief set the last modified software date/time
+ *
+ * The last modifiedSWDate is the corresponding last modified
+ * timestamp from the download server vor the currently installed version.
+ */
+ void setLastModifiedSWDate(const QDateTime &date);
/** @brief saves the currently unselected certificates
*
More information about the Trustbridge-commits
mailing list