comparison ui/mainwindow.cpp @ 551:15121735805e

Start implementation of software update installation
author Andre Heinecke <aheinecke@intevation.de>
date Tue, 20 May 2014 16:40:28 +0000
parents c84dc8f6d017
children d512d8eef8f6
comparison
equal deleted inserted replaced
550:0ec3516bf65c 551:15121735805e
6 * See LICENSE.txt for details. 6 * See LICENSE.txt for details.
7 */ 7 */
8 #include "mainwindow.h" 8 #include "mainwindow.h"
9 9
10 #include <QDebug> 10 #include <QDebug>
11 #include <QProcess>
11 #include <QProgressDialog> 12 #include <QProgressDialog>
12 #include <QMessageBox> 13 #include <QMessageBox>
13 #include <QSystemTrayIcon> 14 #include <QSystemTrayIcon>
14 #include <QAction> 15 #include <QAction>
15 #include <QDialog> 16 #include <QDialog>
33 #define APPNAME "TrustBridge" 34 #define APPNAME "TrustBridge"
34 #endif 35 #endif
35 36
36 #define SERVER_URL "https://files.intevation.de:443" 37 #define SERVER_URL "https://files.intevation.de:443"
37 #define LIST_RESOURCE "/users/aheinecke/zertifikatsliste.txt" 38 #define LIST_RESOURCE "/users/aheinecke/zertifikatsliste.txt"
38 #define SW_RESOURCE "/users/aheinecke/zertifikatsliste.txt" 39 #define SW_RESOURCE "/users/aheinecke/trustbridge.exe"
39 #ifdef Q_OS_WIN 40 #ifdef Q_OS_WIN
40 #define SW_RESOURCE_VERSION "/users/aheinecke/trustbridge-%1.exe" 41 #define SW_RESOURCE_VERSION "/users/aheinecke/trustbridge-%1.exe"
41 #else 42 #else
42 #define SW_RESOURCE_VERSION "/users/aheinecke/trustbridge-%1.sh" 43 #define SW_RESOURCE_VERSION "/users/aheinecke/trustbridge-%1.sh"
43 #endif 44 #endif
48 #include "aboutdialog.h" 49 #include "aboutdialog.h"
49 #include "certificateitemdelegate.h" 50 #include "certificateitemdelegate.h"
50 #include "separatoritemdelegate.h" 51 #include "separatoritemdelegate.h"
51 #include "installwrapper.h" 52 #include "installwrapper.h"
52 #include "util.h" 53 #include "util.h"
54 #include "logging.h"
53 55
54 MainWindow::MainWindow(bool trayMode): 56 MainWindow::MainWindow(bool trayMode):
55 mTrayMode(trayMode) 57 mTrayMode(trayMode)
56 { 58 {
57 createActions(); 59 createActions();
95 void MainWindow::messageClicked() 97 void MainWindow::messageClicked()
96 { 98 {
97 if (mCurState == NewListAvailable) { 99 if (mCurState == NewListAvailable) {
98 show(); 100 show();
99 } 101 }
102
103 if (mCurState == NewSoftwareAvailable) {
104 checkUpdates(true);
105 mCurState = DownloadingSW;
106 }
100 } 107 }
101 108
102 void MainWindow::showMessage() 109 void MainWindow::showMessage()
103 { 110 {
104 if (!isVisible() && !mCurMessage.isEmpty()) { 111 if (!isVisible() && !mCurMessage.isEmpty()) {
146 mSettings.remove("List/installed"); 153 mSettings.remove("List/installed");
147 mSettings.remove("List/installedDate"); 154 mSettings.remove("List/installedDate");
148 } 155 }
149 156
150 if (!swFileName.isEmpty()) { 157 if (!swFileName.isEmpty()) {
151 // TODO 158 // TODO Verify integrity of the software
152 } else { 159 } else {
153 mSettings.remove("Software/available"); 160 mSettings.remove("Software/available");
154 mSettings.remove("Software/availableDate"); 161 mSettings.remove("Software/availableDate");
155 } 162 }
156 } 163 }
174 loadCertificateList(); 181 loadCertificateList();
175 } 182 }
176 } 183 }
177 184
178 void MainWindow::handleNewSW(const QString& fileName, const QDateTime& modDate) { 185 void MainWindow::handleNewSW(const QString& fileName, const QDateTime& modDate) {
179 mCurMessage = tr("An update for %1 is available. Click here to install.").arg( 186 mCurMessage = tr("<h3>An update for %1 is available.</h3>\n"
187 "Click here to download and install the update.").arg(
180 QApplication::applicationName()); 188 QApplication::applicationName());
181 setState(NewSoftwareAvailable); 189 setState(NewSoftwareAvailable);
182 mSettings.setValue("Software/available", fileName); 190 mSettings.setValue("Software/available", fileName);
183 mSettings.setValue("Software/availableDate", modDate); 191 mSettings.setValue("Software/availableDate", modDate);
184 192
185 mSettings.sync(); 193 mSettings.sync();
186 showMessage(); 194 showMessage();
187 } 195 }
188 196
197 void MainWindow::installNewSW(const QString& fileName, const QDateTime& modDate) {
198 QFileInfo instProcInfo = QFileInfo(fileName);
199 if (!instProcInfo.isExecutable()) {
200 qWarning() << "Downloaded file: " << fileName << " is not executable.";
201 setState(TransferError);
202 return;
203 }
204 #ifdef WIN32
205 SHELLEXECUTEINFOW shExecInfo;
206 shExecInfo.lpFile = reinterpret_cast<LPCWSTR> (fileName.utf16());
207
208 if (!is_admin()) {
209 shExecInfo.lpVerb = L"open";
210 } else {
211 shExecInfo.lpVerb = L"runas";
212 }
213
214 qDebug() << "Starting process " << fileName;
215
216 if (!ShellExecuteExW(&shExecInfo)) {
217 /* Execution failed, maybe the user aborted the UAC check? */
218 char* errmsg = getLastErrorMsg();
219 QString qerrmsg = QString::fromUtf8(errmsg);
220 free(errmsg);
221 qDebug() << "Failed to start process: " << qerrmsg;
222 setState(NewSoftwareAvailable);
223 return;
224 }
225
226 #else /* WIN32 */
227 QProcess installerProcess;
228 installerProcess.setProgram(fileName);
229
230 qDebug() << "Starting process " << fileName;
231
232 if (!installerProcess.waitForStarted() ||
233 installerProcess.state() == QProcess::NotRunning) {
234 qDebug() << "Failed to start process.";
235 return;
236 }
237 #endif
238 /* Installer process should now be running. We exit */
239
240 closeApp();
241 }
242
189 void MainWindow::checkUpdates(bool downloadSW) 243 void MainWindow::checkUpdates(bool downloadSW)
190 { 244 {
191 verifyAvailableData(); 245 verifyAvailableData();
192 246
193 if (!mSettings.contains("Software/installedDate")) { 247 if (!mSettings.contains("Software/installedDate") ||
194 lookUpDateForVersion(); 248 mSettings.value("Software/installedVersion").toString() != QApplication::applicationVersion()) {
249 /* This should only happen on initial startup and after an update has
250 * been installed */
251 getLastModForCurrentVersion();
195 return; 252 return;
196 } 253 }
197 QDateTime listInstalledLastMod = mSettings.value("List/installedDate").toDateTime(); 254 QDateTime listInstalledLastMod = mSettings.value("List/installedDate").toDateTime();
198 QDateTime swInstalledLastMod = mSettings.value("Software/installedDate").toDateTime(); 255 QDateTime swInstalledLastMod = mSettings.value("Software/installedDate").toDateTime();
199 256
208 265
209 266
210 Downloader* downloader = new Downloader(this, 267 Downloader* downloader = new Downloader(this,
211 QString::fromLatin1(SERVER_URL), 268 QString::fromLatin1(SERVER_URL),
212 QByteArray(), 269 QByteArray(),
213 QDateTime::currentDateTime(), 270 swInstalledLastMod,
214 // TODO swInstalledLastMod,
215 listInstalledLastMod, 271 listInstalledLastMod,
216 swResource, 272 swResource,
217 listResource, 273 listResource,
218 downloadSW); 274 downloadSW);
219 275
220 connect(downloader, SIGNAL(newListAvailable(const QString&, const QDateTime&)), 276 connect(downloader, SIGNAL(newListAvailable(const QString&, const QDateTime&)),
221 this, SLOT(handleNewList(const QString&, const QDateTime&))); 277 this, SLOT(handleNewList(const QString&, const QDateTime&)));
222 if (!downloadSW) { 278 if (!downloadSW) {
223 connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)), 279 connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)),
224 this, SLOT(newSWAvailable(const QString&, const QDateTime&))); 280 this, SLOT(handleNewSW(const QString&, const QDateTime&)));
225 } 281 } else {
226 else {
227 connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)), 282 connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)),
228 this, SLOT(handleNewSW(const QString&, const QDateTime&))); 283 this, SLOT(installNewSW(const QString&, const QDateTime&)));
229 } 284 }
285
230 connect(downloader, SIGNAL(finished()), downloader, SLOT(deleteLater())); 286 connect(downloader, SIGNAL(finished()), downloader, SLOT(deleteLater()));
231 connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), 287 connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)),
232 this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); 288 this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode)));
233 downloader->start(); 289 downloader->start();
234 } 290 }
235 291
236 void MainWindow::lookUpDateForVersion() 292 void MainWindow::getLastModForCurrentVersion()
237 { 293 {
238 QString softwareVersion = QString::fromLatin1(SW_RESOURCE_VERSION).arg( 294 QString softwareVersion = QString::fromLatin1(SW_RESOURCE_VERSION).arg(
239 QApplication::applicationVersion()); 295 QApplication::applicationVersion());
240 qDebug() << softwareVersion; 296 qDebug() << softwareVersion;
241 QString listResource = QString::fromLatin1(LIST_RESOURCE); 297 QString listResource = QString::fromLatin1(LIST_RESOURCE);
249 false); 305 false);
250 connect(downloader, SIGNAL(finished()), downloader, SLOT(deleteLater())); 306 connect(downloader, SIGNAL(finished()), downloader, SLOT(deleteLater()));
251 connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), 307 connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)),
252 this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); 308 this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode)));
253 connect(downloader, SIGNAL(lastModifiedDate(const QDateTime&)), 309 connect(downloader, SIGNAL(lastModifiedDate(const QDateTime&)),
254 this, SLOT(setLastModifiedDate(const QDateTime&))); 310 this, SLOT(setLastModifiedSWDate(const QDateTime&)));
255 311
256 downloader->start(); 312 downloader->start();
257 } 313 }
258 314
259 void MainWindow::setLastModifiedDate(const QDateTime &date) 315 void MainWindow::setLastModifiedSWDate(const QDateTime &date)
260 { 316 {
261 mSettings.beginGroup("Software"); 317 mSettings.beginGroup("Software");
262 mSettings.setValue("installedDate", date); 318 mSettings.setValue("installedDate", date);
319 mSettings.setValue("installedVersion", QApplication::applicationVersion());
263 mSettings.endGroup(); 320 mSettings.endGroup();
264 checkUpdates(); 321 checkUpdates();
265 } 322 }
266 323
267 void MainWindow::newSWAvailable(const QString &fileName, const QDateTime &date) {
268 QMessageBox msgBox;
269 msgBox.setIcon(QMessageBox::Information);
270 msgBox.setText("<h3>" + tr("New Software version is available.") + "</h3>");
271 msgBox.setInformativeText(tr("Do you want to install the new Version?"));
272 msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
273 msgBox.setDefaultButton(QMessageBox::Yes);
274 int selection = msgBox.exec();
275 if (selection == QMessageBox::Yes) {
276 checkUpdates(true);
277 }
278 }
279
280 void MainWindow::downloaderError(const QString &message, SSLConnection::ErrorCode error) 324 void MainWindow::downloaderError(const QString &message, SSLConnection::ErrorCode error)
281 { 325 {
326 /* TODO logging and handle error according to a plan */
282 mCurMessage = message; 327 mCurMessage = message;
283 showMessage(); 328 showMessage();
284 } 329 setState(TransferError);
285 330 }
286 331
287 void MainWindow::createActions() 332 void MainWindow::createActions()
288 { 333 {
289 mCheckUpdates = new QAction(tr("Check for Updates"), this); 334 mCheckUpdates = new QAction(tr("Check for Updates"), this);
290 connect(mCheckUpdates, SIGNAL(triggered()), this, SLOT(checkUpdates())); 335 connect(mCheckUpdates, SIGNAL(triggered()), this, SLOT(checkUpdates()));

http://wald.intevation.org/projects/trustbridge/