Mercurial > trustbridge
changeset 551:15121735805e
Start implementation of software update installation
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Tue, 20 May 2014 16:40:28 +0000 (2014-05-20) |
parents | 0ec3516bf65c |
children | fc61ef6612b0 |
files | ui/mainwindow.cpp ui/mainwindow.h |
diffstat | 2 files changed, 98 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- 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);
--- 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 *