# HG changeset patch # User Raimund Renkert # Date 1397547894 -7200 # Node ID 78eec57bc133a175113152e4aea42d6c970fc240 # Parent f9c98f9e9f76e171bf8dea7c2a0627df58da4462# Parent c0d63a7f270ed5c66c9dbcf1eafeca758d5fcf7d merged. diff -r f9c98f9e9f76 -r 78eec57bc133 CMakeLists.txt --- a/CMakeLists.txt Tue Apr 15 09:44:32 2014 +0200 +++ b/CMakeLists.txt Tue Apr 15 09:44:54 2014 +0200 @@ -54,6 +54,12 @@ set(PROFILING_LIBS gcov) endif() +if(WIN32) + add_definitions(-D_WIN32_WINNT=0x0600) # Windows vista + add_definitions(-DWINVER=0x0600) + add_definitions(-DMINGW_HAS_SECURE_API) # for _s functions +endif(WIN32) + if(UNIX) set(HARDENING_FLAGS " ${HARDENING_FLAGS} -pie -fPIE -ftrapv") set(HARDENING_FLAGS " ${HARDENING_FLAGS} -Wl,-z,relro,-z,now") diff -r f9c98f9e9f76 -r 78eec57bc133 cinst/CMakeLists.txt --- a/cinst/CMakeLists.txt Tue Apr 15 09:44:32 2014 +0200 +++ b/cinst/CMakeLists.txt Tue Apr 15 09:44:54 2014 +0200 @@ -13,7 +13,7 @@ add_executable(cinst ${CINST_SOURCES}) if (WIN32) - set(WIN_EXTRA_LIBS -lcrypt32 -luserenv) + set(WIN_EXTRA_LIBS -lcrypt32 -luserenv -lshell32) endif(WIN32) target_link_libraries(cinst diff -r f9c98f9e9f76 -r 78eec57bc133 cinst/nssstore_win.c --- a/cinst/nssstore_win.c Tue Apr 15 09:44:32 2014 +0200 +++ b/cinst/nssstore_win.c Tue Apr 15 09:44:54 2014 +0200 @@ -158,8 +158,8 @@ cmd_line_len = wcslen (lpApplicationName) + wcslen(selection_file) + 1; lpCommandLine = xmalloc (cmd_line_len * sizeof(wchar_t)); - wcscpy (lpCommandLine, lpApplicationName); - wcscat (lpCommandLine, selection_file); + wcscpy_s (lpCommandLine, cmd_line_len, lpApplicationName); + wcscat_s (lpCommandLine, cmd_line_len, selection_file); success = CreateProcessAsUserW (hToken, lpApplicationName, @@ -201,7 +201,7 @@ * This creates a security attributes structure that restricts * write access to the Administrators group but allows everyone to read files * in that directory. - * Basically a very complicated vetrsion of mkdir path -m 604 + * Basically a very complicated version of mkdir path -m 644 * * If the directory exists the permissions of that directory are checked if * they are acceptable and true or false is returned accordingly. @@ -365,16 +365,11 @@ /* TODO */ } -#if 0 - result = SHGetKnownFolderPath (FOLDERID_ProgramData, /* Get program data dir */ + result = SHGetKnownFolderPath (&FOLDERID_ProgramData, /* Get program data dir */ KF_FLAG_CREATE | /* Create if it does not exist */ KF_FLAG_INIT, /* Initialize it if created */ - -1, /* Get it for the default user */ + INVALID_HANDLE_VALUE, /* Get it for the default user */ &folder_name); -#endif - /* TODO figure out how to do this with mingw */ - result = S_OK; - folder_name = L"C:\\ProgramData"; if (result != S_OK) { @@ -394,12 +389,12 @@ } path = xmalloc (path_len * sizeof (wchar_t)); - if (wcscpy (path, folder_name) != 0) + if (wcscpy_s (path, path_len, folder_name) != 0) { ERRORPRINTF ("Failed to copy folder name.\n"); -#if 0 + CoTaskMemFree (folder_name); -#endif + return NULL; } @@ -407,14 +402,14 @@ CoTaskMemFree (folder_name); #endif - if (wcscat (path, L"\\") != 0) + if (wcscat_s (path, path_len, L"\\") != 0) { ERRORPRINTF ("Failed to cat dirsep.\n"); xfree(path); return NULL; } - if (wcscat (path, APPNAME) != 0) + if (wcscat_s (path, path_len, APPNAME) != 0) { ERRORPRINTF ("Failed to cat appname.\n"); xfree(path); @@ -432,14 +427,14 @@ return NULL; } - if (wcscat (path, L"\\") != 0) + if (wcscat_s (path, path_len, L"\\") != 0) { ERRORPRINTF ("Failed to cat dirsep.\n"); xfree(path); return NULL; } - if (wcscat (path, SELECTION_FILE_NAME) != 0) + if (wcscat_s (path, path_len, SELECTION_FILE_NAME) != 0) { ERRORPRINTF ("Failed to cat filename.\n"); xfree(path); diff -r f9c98f9e9f76 -r 78eec57bc133 ui/CMakeLists.txt --- a/ui/CMakeLists.txt Tue Apr 15 09:44:32 2014 +0200 +++ b/ui/CMakeLists.txt Tue Apr 15 09:44:54 2014 +0200 @@ -16,7 +16,6 @@ set(M13UI_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/mainwindow.cpp ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/listupdatedialog.cpp ${CMAKE_CURRENT_SOURCE_DIR}/helpdialog.cpp ${CMAKE_CURRENT_SOURCE_DIR}/aboutdialog.cpp ${CMAKE_CURRENT_SOURCE_DIR}/statusdialog.cpp diff -r f9c98f9e9f76 -r 78eec57bc133 ui/installwrapper.cpp --- a/ui/installwrapper.cpp Tue Apr 15 09:44:32 2014 +0200 +++ b/ui/installwrapper.cpp Tue Apr 15 09:44:54 2014 +0200 @@ -1,6 +1,7 @@ #include "installwrapper.h" #include +#include #include #include #include @@ -11,10 +12,10 @@ #define INSTALL_TIMEOUT 3600000 /* Wait up to an hour */ InstallWrapper::InstallWrapper(QObject* parent, - const QString& path, const QStringList& instructions): + const QString& path, const QStringList& choices): QThread(parent), mCertListFile(path), - mInstructions(instructions) + mChoices(choices) { } @@ -28,16 +29,32 @@ return QFileInfo(myDir.absoluteFilePath(instProcName)); } -#ifdef WIN32 +bool InstallWrapper::writeChoices(QTemporaryFile* choicesFile) const +{ + if (!choicesFile->open()) { + return false; + } + + foreach (const QString &b64data, mChoices) { + if (!choicesFile->write(b64data.toLatin1())) { + return false; + } + if (!choicesFile->write("\n")) { + return false; + } + } + + choicesFile->close(); + + return true; +} + void InstallWrapper::run() { /* TODO: We need errorcodes here so that we can see if a user * cancled the UAC elevation */ - QTemporaryFile instructionsFile; + QTemporaryFile choicesFile; QFileInfo cinstProcInfo = getCinstProcInfo(); - DWORD retval = 0; - SHELLEXECUTEINFOW shExecInfo; - memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW)); QString cinstFileName = QDir::toNativeSeparators( getCinstProcInfo().absoluteFilePath()); @@ -47,17 +64,26 @@ return; } - instructionsFile.open(); - - foreach (const QString &b64data, mInstructions) { - instructionsFile.write(b64data.toLatin1()); - instructionsFile.write("\n"); + if (!writeChoices(&choicesFile)) { + emit error(tr("Failed to write temporary file.")); + return; } - instructionsFile.close(); + QString parameters = "\"list=" + mCertListFile + + "\" \"choices=" + choicesFile.fileName() + "\""; - QString parameters = "\"list=" + mCertListFile + - "\" \"instructions=" +instructionsFile.fileName() + "\""; +#ifdef WIN32 + /* QProcess on Windows uses CreateProcess but we have to + * use the runas shell command to get the UAC prompt if necessary. + * So we have to handle the process ourself. Starting with + * shell execute also means that we can not have stdout and stderr + * redirection. This is the reason we use command line parameters + * and not a pipe for communication. In debug mode the installer + * also makes use of output debug string. */ + DWORD retval = 0; + SHELLEXECUTEINFOW shExecInfo; + + memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW)); shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; @@ -106,9 +132,35 @@ /* TODO make this nicer */ emit error (tr("The process failed with return code. %1").arg(retval)); } + return; +#else /* WIN32 */ + QProcess installerProcess; + installerProcess.setProgram(cinstProcInfo.absoluteFilePath()); + installerProcess.waitForStarted(); + if (installerProcess.state() == QProcess::NotRunning) { + emit error (tr("Failed to start installer process.")); + return; + } + + installerProcess.waitForFinished(); + + if (installerProcess.exitStatus() == QProcess::CrashExit) { + /* Woops */ + qWarning() << "Installer process crashed"; + } else if (installerProcess.exitStatus() != QProcess::NormalExit) { + /* Can not Happen. there are only those two values but maybe + * qt changed.. */ + qWarning() << "Exit status neither normal nor crash."; + return; + } + + if (installerProcess.exitCode() == 0) { + qDebug() << "output: " << installerProcess.readAllStandardOutput(); + } else { + /* TODO handle errors defined by errorcodes.h */ + qDebug() << "Installer Process returned: " << installerProcess.exitCode(); + qDebug() << "output: " << installerProcess.readAllStandardOutput(); + return; + } +#endif } -#else -void InstallWrapper::run() -{ -} -#endif diff -r f9c98f9e9f76 -r 78eec57bc133 ui/installwrapper.h --- a/ui/installwrapper.h Tue Apr 15 09:44:32 2014 +0200 +++ b/ui/installwrapper.h Tue Apr 15 09:44:54 2014 +0200 @@ -1,14 +1,24 @@ #ifndef UI_INSTALLWRAPPER_H #define UI_INSTALLWRAPPER_H +#include #include #include +#include #include #include "certificate.h" /** @file installwrapper.h * @brief Wrapper around the call to the updated process */ +/** @brief Get the FileInfo for the installation process. + * + * This points to the file where the installation process is + * supposed to be. + * + * @returns A FileInfo with the path of the installation process.*/ +QFileInfo getCinstProcInfo(); + /** @brief wrapper around installer process * * This wrapper is mostly needed because QProcess executes @@ -36,14 +46,22 @@ * * @param[in] parent the parent object. * @param[in] listFileName the absolute path to the certificatelist. - * @param[in] instructions a list of instructions to execute. + * @param[in] choices a list of R: / I: lines to execute. */ InstallWrapper(QObject* parent, const QString& path, const QStringList& instructions); private: + /**@brief write the choices made into a temporary file + * + * @param[in] choicesFile the temporary file to write. + * + * @returns true on success. false on error. + */ + bool writeChoices(QTemporaryFile* choicesFile) const; + const QString mCertListFile; - const QStringList mInstructions; + const QStringList mChoices; protected: void run(); diff -r f9c98f9e9f76 -r 78eec57bc133 ui/listupdatedialog.cpp --- a/ui/listupdatedialog.cpp Tue Apr 15 09:44:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,195 +0,0 @@ -#include "listupdatedialog.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "certificate.h" -#include "installwrapper.h" - -ListUpdateDialog::ListUpdateDialog(QMainWindow *parent, - const CertificateList &listToInstall) : - QDialog(parent), - mCertificateList(listToInstall) -{ - setupGUI(); -} - -void ListUpdateDialog::setupGUI() -{ - /* Top level layout / widgets */ - QVBoxLayout *topLayout = new QVBoxLayout; - QHBoxLayout *headerLayout = new QHBoxLayout; - QHBoxLayout *listLayout = new QHBoxLayout; - QHBoxLayout *bottomLayout = new QHBoxLayout; - - QImage *logoImage = new QImage(":/img/logo-small.png"); - QLabel *logo = new QLabel; - logo->setBackgroundRole(QPalette::Base); - logo->setPixmap(QPixmap::fromImage(*logoImage)); - QLabel *title = new QLabel("

" + tr("Update Certificate") + "

"); - headerLayout->addWidget(logo); - headerLayout->addWidget(title); - headerLayout->setStretch(0, 0); - headerLayout->setStretch(1, 10); - - QPushButton *executeUpdate = new QPushButton(tr("Update Stores")); - connect(executeUpdate, &QPushButton::clicked, - this, &ListUpdateDialog::executeUpdate); - QPushButton *install = new QPushButton(tr("Install selected")); - QPushButton *later = new QPushButton(tr("Remind me later")); - bottomLayout->insertStretch(0, 10); - bottomLayout->addWidget(executeUpdate); - bottomLayout->addWidget(install); - bottomLayout->addWidget(later); - - /* The certificate groups */ - mCertListWidget = new QListWidget; - connect(mCertListWidget, SIGNAL(itemClicked(QListWidgetItem*)), - this, SLOT(showDetails(QListWidgetItem*))); - mDetailWidget = new QTextEdit; - mDetailWidget->setReadOnly(true); - listLayout->addWidget(mCertListWidget); - listLayout->addWidget(mDetailWidget); - QGroupBox *certGroup = new QGroupBox(tr("Select certificates")); - certGroup->setLayout(listLayout); - - foreach (const Certificate& cert, mCertificateList.getCertificates()) { - if (!cert.isValid()) { - qWarning() << "Invalid certificate in list"; - continue; - } - QListWidgetItem* item = new QListWidgetItem(cert.shortDescription()); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - item->setData(Qt::ToolTipRole, cert.details()); - item->setData(Qt::UserRole, cert.base64Line()); - item->setCheckState(Qt::Checked); - QIcon *certIcon = cert.isInstallCert() ? new QIcon(":/img/list-add.png") : - new QIcon(":/img/list-remove.png"); - item->setIcon(*certIcon); - - mCertListWidget->addItem(item); - } - - /* Fill top level layout */ - topLayout->addLayout(headerLayout); - topLayout->addWidget(certGroup); - topLayout->addLayout(bottomLayout); - - setLayout(topLayout); - - return; -} - -void ListUpdateDialog::installerError(const QString& errMsg) { - QMessageBox::warning(this, tr("Installation Error"), errMsg); -} - -void ListUpdateDialog::executeUpdate() { - - QStringList instructions; - - for (int i = 0; i < mCertListWidget->count(); i++) { - QListWidgetItem *item = mCertListWidget->item(i); - if (item->checkState() == Qt::Checked) { - instructions << item->data(Qt::UserRole).toString(); - } - - /* TODO: Check if it was an install instruction for an old certificate - * (already installed) and remove it in case it is unchecked. */ - } - - InstallWrapper *instWrap = new InstallWrapper(this, - mCertificateList.fileName(), - instructions); - connect(instWrap, SIGNAL(finished()), instWrap, SLOT(deleteLater())); - connect(instWrap, SIGNAL(error(const QString &)), - this, SLOT(installerError(const QString &))); - instWrap->start(); - -#if 0 - /* TODO move this in another dialog and call it async*/ - QProcess installerProcess; - QFileInfo fi(QCoreApplication::applicationFilePath()); - QDir myDir = fi.absoluteDir(); - QString instProcName = "cinst"; - if (!fi.suffix().isEmpty()) { - instProcName += "." + fi.suffix(); - } - QString instPath = myDir.absoluteFilePath(instProcName); - - installerProcess.setProgram(instPath); - installerProcess.start(); - installerProcess.waitForStarted(); - if (installerProcess.state() == QProcess::NotRunning) { - qWarning() << "Failed to start installer Process."; - /* TODO ERROR message for the user */ - return; - } - - installerProcess.write("-----BEGIN CERTIFICATE LIST-----\r\n"); - installerProcess.write(mCertificateList.rawData().toLatin1()); - installerProcess.write("-----END CERTIFICATE LIST-----\r\n"); - - /* Items to install */ - for (int i = 0; i < mCertListWidget->count(); i++) { - QListWidgetItem *item = mCertListWidget->item(i); - if (item->checkState() != Qt::Checked && - item->data(Qt::UserRole).toString().startsWith("I:")) { - continue; - } - installerProcess.write(item->data(Qt::UserRole).toString().toLatin1()); - installerProcess.write("\r\n"); - } - - /* Items to remove */ - for (int i = 0; i < mCertListWidget->count(); i++) { - QListWidgetItem *item = mCertListWidget->item(i); - if (!item->checkState() != Qt::Checked && - item->data(Qt::UserRole).toString().startsWith("R:")) { - continue; - } - installerProcess.write(item->data(Qt::UserRole).toString().toLatin1()); - installerProcess.write("\r\n"); - } - - installerProcess.waitForBytesWritten(); - installerProcess.closeWriteChannel(); - installerProcess.waitForFinished(); - - if (installerProcess.exitStatus() == QProcess::CrashExit) { - /* Woops */ - qWarning() << "Installer process crashed"; - } else if (installerProcess.exitStatus() != QProcess::NormalExit) { - /* Can not Happen. there are only those two values but maybe - * qt changed.. */ - qWarning() << "Exit status neither normal nor crash."; - return; - } - - if (installerProcess.exitCode() == 0) { - qDebug() << "Success!"; - qDebug() << "output: " << installerProcess.readAllStandardOutput(); - } else { - /* TODO handle errors defined by errorcodes.h */ - qDebug() << "Installer Process returned: " << installerProcess.exitCode(); - qDebug() << "output: " << installerProcess.readAllStandardOutput(); - return; - } -#endif -} - -void ListUpdateDialog::showDetails(QListWidgetItem *item) -{ - QString details = item->data(Qt::ToolTipRole).toString(); - mDetailWidget->setPlainText(details); -} diff -r f9c98f9e9f76 -r 78eec57bc133 ui/listupdatedialog.h --- a/ui/listupdatedialog.h Tue Apr 15 09:44:32 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -#ifndef LISTUPDATEDIALOG_H -#define LISTUPDATEDIALOG_H - -#include "certificatelist.h" -#include -#include -#include -#include -/** - * @file listupdatedialog.h - * @brief The dialog for certificate selection. - */ - -class QListWidget; - -class ListUpdateDialog : public QDialog -{ - Q_OBJECT -public: - /** @brief Create a list update dialog for the listToInstall */ - ListUpdateDialog(QMainWindow *parent, const CertificateList &listToInstall); - -private: - CertificateList mCertificateList; - void setupGUI(); - - QListWidget *mCertListWidget; - QTextEdit *mDetailWidget; - -private slots: - void installerError(const QString& errMsg); - void executeUpdate(); - void showDetails(QListWidgetItem*); -}; - -#endif // LISTUPDATEDIALOG_H diff -r f9c98f9e9f76 -r 78eec57bc133 ui/main.cpp --- a/ui/main.cpp Tue Apr 15 09:44:32 2014 +0200 +++ b/ui/main.cpp Tue Apr 15 09:44:54 2014 +0200 @@ -46,10 +46,7 @@ QApplication::setApplicationVersion(QString::fromLatin1(VERSION)); QSettings::setDefaultFormat(QSettings::IniFormat); - MainWindow mainWin; - if (!trayMode) { - mainWin.show(); - } + MainWindow mainWin(trayMode); return app.exec(); } diff -r f9c98f9e9f76 -r 78eec57bc133 ui/mainwindow.cpp --- a/ui/mainwindow.cpp Tue Apr 15 09:44:32 2014 +0200 +++ b/ui/mainwindow.cpp Tue Apr 15 09:44:54 2014 +0200 @@ -1,6 +1,7 @@ #include "mainwindow.h" #include +#include #include #include #include @@ -19,7 +20,7 @@ // The amount of time in minutes stay silent if we have // something to say -#define NAG_INTERVAL_MINUTES 2 +#define NAG_INTERVAL_MINUTES 60 #define SERVER_URL "https://files.kolab.org:443" #define LIST_RESOURCE "/incoming/aheinecke/test" @@ -27,14 +28,16 @@ #include "certificatelist.h" #include "downloader.h" -#include "listupdatedialog.h" #include "helpdialog.h" #include "aboutdialog.h" #include "statusdialog.h" #include "certificateitemdelegate.h" #include "separatoritemdelegate.h" +#include "installwrapper.h" -MainWindow::MainWindow() { +MainWindow::MainWindow(bool trayMode): + mTrayMode(trayMode) +{ createActions(); createTrayIcon(); createMenuBar(); @@ -50,6 +53,9 @@ mMessageTimer->setInterval(NAG_INTERVAL_MINUTES * 60 * 1000); mMessageTimer->start(); checkUpdates(); + if (!trayMode) { + show(); + } } void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) @@ -60,7 +66,7 @@ showMessage(); break; case QSystemTrayIcon::DoubleClick: - // TODO show menu + show(); break; default: ; @@ -70,16 +76,13 @@ void MainWindow::messageClicked() { if (mCurState == NewListAvailable) { - ListUpdateDialog *listUpdateDialog = new ListUpdateDialog(this, - mListToInstall); - listUpdateDialog->show(); - qDebug() << "NewListAvailable"; + show(); } } void MainWindow::showMessage() { - if (!mCurMessage.isEmpty()) { + if (!isVisible() && !mCurMessage.isEmpty()) { mTrayIcon->showMessage(QApplication::applicationName(), mCurMessage, QSystemTrayIcon::Information, 5000); mMessageTimer->start(); // Restart the timer so that we don't spam @@ -247,11 +250,11 @@ // The certificate list QGroupBox *certBox = new QGroupBox(tr("Managed Certificates")); - certificateList = new QListWidget; - certificateList->setItemDelegate(new CertificateItemDelegate); - connect(certificateList, SIGNAL(itemClicked(QListWidgetItem*)), + mCertListWidget = new QListWidget; + mCertListWidget->setItemDelegate(new CertificateItemDelegate); + connect(mCertListWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(showDetails(QListWidgetItem*))); - certLayout->addWidget(certificateList); + certLayout->addWidget(mCertListWidget); certBox->setLayout(certLayout); // The header (icon, about text) @@ -278,6 +281,7 @@ installButton = new QPushButton(tr("Install selected")); installButton->setFixedHeight(80); connect(installButton, SIGNAL(clicked()), this, SLOT(resizeButtons())); + connect(installButton, SIGNAL(clicked()), this, SLOT(installCerts())); quitButton = new QPushButton(tr("Quit")); quitButton->setFixedHeight(20); connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit())); @@ -313,7 +317,7 @@ void MainWindow::loadCertificateList() { qDebug() << "display certificates"; - certificateList->clear(); + mCertListWidget->clear(); int i = 0; foreach (const Certificate &cert, mListToInstall.getCertificates()) { if (!cert.isValid()) { @@ -337,8 +341,8 @@ } if (i == 3) { QListWidgetItem *sep = new QListWidgetItem("New certificates"); - certificateList->setItemDelegateForRow(i, separator); - certificateList->addItem(sep); + mCertListWidget->setItemDelegateForRow(i, separator); + mCertListWidget->addItem(sep); i++; } } @@ -354,7 +358,7 @@ item->setFlags(item->flags() | Qt::ItemIsUserCheckable); } } - certificateList->addItem(item); + mCertListWidget->addItem(item); i++; } } @@ -387,9 +391,7 @@ void MainWindow::showDetails(QListWidgetItem *item) { - qDebug() << "show details"; QString details = item->data(Qt::UserRole).toString(); - details.append("\rInstalled: 1.1.1971\rRemoved: 1.1.1971"); certificateDetails->setPlainText(details); } @@ -398,3 +400,44 @@ installButton->setFixedHeight(20); quitButton->setFixedHeight(80); } + +void MainWindow::installerError(const QString& errMsg) { + QMessageBox::warning(this, tr("Error executing update"), errMsg); +} + +void MainWindow::installCerts() { + QStringList choices; + + for (int i = 0; i < mCertListWidget->count(); i++) { + QListWidgetItem *item = mCertListWidget->item(i); + if (item->checkState() == Qt::Checked) { + choices << item->data(Qt::UserRole).toString(); + continue; + } + QString certLine = item->data(Qt::UserRole).toString(); + if (certLine.startsWith("I:")) { + certLine[0] = 'R'; + choices << certLine; + } + } + + QProgressDialog *progress = new QProgressDialog(this); + progress->setWindowModality(Qt::WindowModal); + progress->setLabelText(tr("Installing certificates...")); + progress->setCancelButton(0); + progress->setRange(0,0); + progress->setMinimumDuration(0); + progress->show(); + + InstallWrapper *instWrap = new InstallWrapper(this, + mListToInstall.fileName(), + choices); + /* Clean up object and progress dialog */ + connect(instWrap, SIGNAL(finished()), instWrap, SLOT(deleteLater())); + connect(instWrap, SIGNAL(finished()), progress, SLOT(deleteLater())); + connect(instWrap, SIGNAL(finished()), progress, SLOT(cancel())); + connect(instWrap, SIGNAL(error(const QString &)), + this, SLOT(installerError(const QString &))); + instWrap->start(); + +} diff -r f9c98f9e9f76 -r 78eec57bc133 ui/mainwindow.h --- a/ui/mainwindow.h Tue Apr 15 09:44:32 2014 +0200 +++ b/ui/mainwindow.h Tue Apr 15 09:44:54 2014 +0200 @@ -25,7 +25,16 @@ Q_OBJECT public: - MainWindow(); + /**@brief create a new Main Window object + * + * In tray mode this window is not shown and only shows + * notification messages if there is some actionable state + * reached. If tray mode is true it also exits after + * an update check. + * + * @param[in] trayMode set the tray mode + * */ + MainWindow(bool trayMode); void setMessage(const QString message) {mCurMessage = message;} QString getMessage() {return mCurMessage;} @@ -55,6 +64,8 @@ void showAbout(); void showDetails(QListWidgetItem*); void resizeButtons(); + void installerError(const QString& errMsg); + void installCerts(); private: /** @brief check the integrity of available files. @@ -72,6 +83,9 @@ void createContent(); void loadCertificateList(); + /* Are we running in tray mode ?*/ + const bool mTrayMode; + /* The message currently shown at intervals */ QString mCurMessage; QString mInstalledSWVersion; QString mInstalledListVersion; @@ -88,7 +102,7 @@ CertificateList mListToInstall; - QListWidget *certificateList; + QListWidget *mCertListWidget; QTextEdit *certificateDetails; QPushButton *installButton; QPushButton *quitButton;