aheinecke@404: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik aheinecke@404: * Software engineering by Intevation GmbH aheinecke@404: * aheinecke@404: * This file is Free Software under the GNU GPL (v>=2) aheinecke@404: * and comes with ABSOLUTELY NO WARRANTY! aheinecke@404: * See LICENSE.txt for details. aheinecke@404: */ aheinecke@0: #include "mainwindow.h" aheinecke@0: aheinecke@0: #include aheinecke@551: #include aheinecke@365: #include aheinecke@0: #include aheinecke@0: #include aheinecke@0: #include aheinecke@0: #include aheinecke@563: #include aheinecke@0: #include aheinecke@2: #include aheinecke@16: #include aheinecke@19: #include rrenkert@187: #include rrenkert@187: #include rrenkert@187: #include rrenkert@189: #include rrenkert@205: #include rrenkert@205: #include rrenkert@250: #include rrenkert@584: #include rrenkert@584: #include aheinecke@19: aheinecke@19: // The amount of time in minutes stay silent if we have aheinecke@19: // something to say aheinecke@548: #define NAG_INTERVAL_MINUTES 70 aheinecke@0: aheinecke@409: #ifndef APPNAME aheinecke@409: #define APPNAME "TrustBridge" aheinecke@409: #endif aheinecke@409: aheinecke@409: #define SERVER_URL "https://files.intevation.de:443" aheinecke@531: #define LIST_RESOURCE "/users/aheinecke/zertifikatsliste.txt" aheinecke@554: #define SW_RESOURCE "/users/aheinecke/TrustBridge.exe" rrenkert@486: #ifdef Q_OS_WIN aheinecke@554: #define SW_RESOURCE_VERSION "/users/aheinecke/TrustBridge-%1.exe" rrenkert@486: #else aheinecke@554: #define SW_RESOURCE_VERSION "/users/aheinecke/TrustBridge-%1.sh" rrenkert@486: #endif aheinecke@72: aheinecke@7: #include "certificatelist.h" aheinecke@10: #include "downloader.h" rrenkert@191: #include "helpdialog.h" rrenkert@200: #include "aboutdialog.h" rrenkert@267: #include "certificateitemdelegate.h" rrenkert@274: #include "separatoritemdelegate.h" aheinecke@365: #include "installwrapper.h" aheinecke@507: #include "util.h" aheinecke@551: #include "logging.h" aheinecke@7: aheinecke@365: MainWindow::MainWindow(bool trayMode): aheinecke@365: mTrayMode(trayMode) aheinecke@365: { rrenkert@640: mUpdatesNewSize = 0; rrenkert@640: mUpdatesRemoveSize = 0; rrenkert@640: mUpdatesManualSize = 0; aheinecke@0: createActions(); aheinecke@0: createTrayIcon(); rrenkert@187: createContent(); rrenkert@450: resize(950, 540); aheinecke@45: qRegisterMetaType("SSLConnection::ErrorCode"); rrenkert@265: qRegisterMetaType("Certificate::Status"); aheinecke@0: aheinecke@0: connect(mTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), aheinecke@0: this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); aheinecke@19: aheinecke@19: mMessageTimer = new QTimer(this); aheinecke@19: connect(mMessageTimer, SIGNAL(timeout()), this, SLOT(showMessage())); aheinecke@19: mMessageTimer->setInterval(NAG_INTERVAL_MINUTES * 60 * 1000); aheinecke@19: mMessageTimer->start(); aheinecke@71: checkUpdates(); andre@389: loadUnselectedCertificates(); andre@389: loadCertificateList(); aheinecke@365: if (!trayMode) { aheinecke@365: show(); aheinecke@365: } aheinecke@0: } aheinecke@0: aheinecke@0: void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) aheinecke@0: { aheinecke@0: switch (reason) { aheinecke@0: case QSystemTrayIcon::Trigger: aheinecke@0: case QSystemTrayIcon::MiddleClick: aheinecke@0: showMessage(); aheinecke@0: break; aheinecke@16: case QSystemTrayIcon::DoubleClick: aheinecke@365: show(); aheinecke@16: break; aheinecke@0: default: aheinecke@0: ; aheinecke@0: } aheinecke@0: } aheinecke@0: aheinecke@71: void MainWindow::messageClicked() aheinecke@71: { aheinecke@71: if (mCurState == NewListAvailable) { aheinecke@365: show(); aheinecke@71: } aheinecke@551: aheinecke@551: if (mCurState == NewSoftwareAvailable) { aheinecke@551: checkUpdates(true); aheinecke@551: mCurState = DownloadingSW; aheinecke@551: } aheinecke@71: } aheinecke@71: aheinecke@0: void MainWindow::showMessage() aheinecke@0: { aheinecke@365: if (!isVisible() && !mCurMessage.isEmpty()) { aheinecke@16: mTrayIcon->showMessage(QApplication::applicationName(), mCurMessage, aheinecke@16: QSystemTrayIcon::Information, 5000); aheinecke@19: mMessageTimer->start(); // Restart the timer so that we don't spam aheinecke@16: } aheinecke@0: } aheinecke@16: aheinecke@16: void MainWindow::verifyAvailableData() aheinecke@0: { andre@389: QString availableFileName = mSettings.value("List/available").toString(); andre@389: QString installedFileName = mSettings.value("List/installed").toString(); aheinecke@16: QString swFileName = mSettings.value("Software/available").toString(); aheinecke@16: andre@389: if (!availableFileName.isEmpty()) { andre@389: mListToInstall.readList(availableFileName.toLocal8Bit().constData()); aheinecke@71: if (!mListToInstall.isValid()) { aheinecke@82: mCurState = TransferError; aheinecke@16: // Probably a bug when Qt fileName is encoded and cFileName aheinecke@16: // fails because of this. This needs a unit test! aheinecke@16: // Maybe check that the file is in our data directory andre@389: QFile::remove(availableFileName); aheinecke@16: mSettings.remove("List/available"); aheinecke@16: mSettings.remove("List/availableDate"); aheinecke@16: } aheinecke@16: } else { aheinecke@16: // Make sure the available notation is also removed aheinecke@16: mSettings.remove("List/available"); aheinecke@16: mSettings.remove("List/availableDate"); aheinecke@16: } aheinecke@16: andre@389: if (!installedFileName.isEmpty()) { andre@389: mInstalledList.readList(installedFileName.toLocal8Bit().constData()); andre@389: if (!mInstalledList.isValid()) { andre@389: // Probably a bug when Qt fileName is encoded and cFileName andre@389: // fails because of this. This needs a unit test! andre@389: // Maybe check that the file is in our data directory andre@389: QFile::remove(installedFileName); andre@389: mSettings.remove("List/installed"); andre@389: mSettings.remove("List/installedDate"); andre@389: } andre@389: } else { andre@389: mSettings.remove("List/installed"); andre@389: mSettings.remove("List/installedDate"); andre@389: } andre@389: aheinecke@16: if (!swFileName.isEmpty()) { aheinecke@551: // TODO Verify integrity of the software aheinecke@16: } else { aheinecke@16: mSettings.remove("Software/available"); aheinecke@16: mSettings.remove("Software/availableDate"); aheinecke@16: } aheinecke@16: } aheinecke@16: aheinecke@16: void MainWindow::handleNewList(const QString& fileName, const QDateTime& modDate) { rrenkert@628: qDebug() << "new list available"; aheinecke@71: mSettings.setValue("List/available", fileName); aheinecke@71: mSettings.setValue("List/availableDate", modDate); aheinecke@16: aheinecke@71: verifyAvailableData(); aheinecke@71: if (!mListToInstall.isValid()) { aheinecke@71: /* Downloader provided invalid files */ aheinecke@71: /* TODO: Error count. Error handling. Otherwise aheinecke@71: * we can go into an endless loop here */ aheinecke@71: aheinecke@71: /* Retry the download again in 10 - 20 minutes */ aheinecke@71: QTimer::singleShot(600000 + (qrand() % 60000), this, SLOT(checkUpdates())); aheinecke@82: } else { aheinecke@82: mCurMessage = tr("An updated certificate list is available. Click here to install."); aheinecke@82: setState(NewListAvailable); aheinecke@82: showMessage(); rrenkert@189: loadCertificateList(); aheinecke@71: } aheinecke@16: } aheinecke@16: aheinecke@16: void MainWindow::handleNewSW(const QString& fileName, const QDateTime& modDate) { aheinecke@555: mCurMessage = tr("An update for %1 is available.\n" aheinecke@551: "Click here to download and install the update.").arg( aheinecke@16: QApplication::applicationName()); aheinecke@16: setState(NewSoftwareAvailable); aheinecke@16: mSettings.setValue("Software/available", fileName); aheinecke@16: mSettings.setValue("Software/availableDate", modDate); aheinecke@16: aheinecke@16: mSettings.sync(); aheinecke@16: showMessage(); aheinecke@16: } aheinecke@16: aheinecke@551: void MainWindow::installNewSW(const QString& fileName, const QDateTime& modDate) { aheinecke@551: QFileInfo instProcInfo = QFileInfo(fileName); aheinecke@551: if (!instProcInfo.isExecutable()) { aheinecke@551: qWarning() << "Downloaded file: " << fileName << " is not executable."; aheinecke@551: setState(TransferError); aheinecke@551: return; aheinecke@551: } aheinecke@563: QString filePath = QDir::toNativeSeparators(instProcInfo.absoluteFilePath()); aheinecke@551: #ifdef WIN32 aheinecke@551: SHELLEXECUTEINFOW shExecInfo; aheinecke@563: memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW)); aheinecke@563: shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); aheinecke@563: aheinecke@563: shExecInfo.lpFile = reinterpret_cast (filePath.utf16()); aheinecke@563: aheinecke@563: shExecInfo.fMask = SEE_MASK_NOASYNC; aheinecke@551: aheinecke@551: if (!is_admin()) { aheinecke@551: shExecInfo.lpVerb = L"open"; aheinecke@551: } else { aheinecke@551: shExecInfo.lpVerb = L"runas"; aheinecke@551: } aheinecke@551: aheinecke@563: qDebug() << "Starting process: " << filePath; aheinecke@551: aheinecke@551: if (!ShellExecuteExW(&shExecInfo)) { aheinecke@551: /* Execution failed, maybe the user aborted the UAC check? */ aheinecke@551: char* errmsg = getLastErrorMsg(); aheinecke@551: QString qerrmsg = QString::fromUtf8(errmsg); aheinecke@551: free(errmsg); aheinecke@551: qDebug() << "Failed to start process: " << qerrmsg; aheinecke@551: setState(NewSoftwareAvailable); aheinecke@551: return; aheinecke@551: } aheinecke@551: #else /* WIN32 */ aheinecke@563: qDebug() << "Starting process " << filePath; aheinecke@551: aheinecke@563: if (!QProcess::startDetached(filePath)) { aheinecke@551: qDebug() << "Failed to start process."; aheinecke@551: return; aheinecke@551: } aheinecke@551: #endif aheinecke@551: /* Installer process should now be running. We exit */ aheinecke@551: aheinecke@551: closeApp(); aheinecke@551: } aheinecke@551: rrenkert@461: void MainWindow::checkUpdates(bool downloadSW) aheinecke@16: { aheinecke@16: verifyAvailableData(); aheinecke@16: aheinecke@551: if (!mSettings.contains("Software/installedDate") || aheinecke@551: mSettings.value("Software/installedVersion").toString() != QApplication::applicationVersion()) { aheinecke@551: /* This should only happen on initial startup and after an update has aheinecke@551: * been installed */ aheinecke@551: getLastModForCurrentVersion(); rrenkert@486: return; rrenkert@486: } aheinecke@17: QDateTime listInstalledLastMod = mSettings.value("List/installedDate").toDateTime(); aheinecke@17: QDateTime swInstalledLastMod = mSettings.value("Software/installedDate").toDateTime(); aheinecke@16: andre@389: QString listResource = QString::fromLatin1(LIST_RESOURCE); andre@389: QString swResource = QString::fromLatin1(SW_RESOURCE); andre@389: andre@389: #ifndef RELEASE_BUILD andre@389: /* Use this for testing to specify another file name for updates */ andre@389: listResource = mSettings.value("List/resource", listResource).toString(); andre@389: swResource = mSettings.value("Software/resource", swResource).toString(); andre@389: #endif andre@389: andre@389: aheinecke@72: Downloader* downloader = new Downloader(this, aheinecke@72: QString::fromLatin1(SERVER_URL), aheinecke@72: QByteArray(), aheinecke@551: swInstalledLastMod, aheinecke@72: listInstalledLastMod, aheinecke@437: swResource, rrenkert@461: listResource, rrenkert@461: downloadSW); aheinecke@17: aheinecke@16: connect(downloader, SIGNAL(newListAvailable(const QString&, const QDateTime&)), aheinecke@16: this, SLOT(handleNewList(const QString&, const QDateTime&))); rrenkert@461: if (!downloadSW) { rrenkert@461: connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)), aheinecke@551: this, SLOT(handleNewSW(const QString&, const QDateTime&))); aheinecke@551: } else { aheinecke@551: connect(downloader, SIGNAL(newSoftwareAvailable(const QString&, const QDateTime&)), aheinecke@551: this, SLOT(installNewSW(const QString&, const QDateTime&))); rrenkert@461: } aheinecke@551: aheinecke@16: connect(downloader, SIGNAL(finished()), downloader, SLOT(deleteLater())); aheinecke@45: connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), aheinecke@45: this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); aheinecke@10: downloader->start(); aheinecke@0: } aheinecke@0: aheinecke@551: void MainWindow::getLastModForCurrentVersion() rrenkert@486: { rrenkert@486: QString softwareVersion = QString::fromLatin1(SW_RESOURCE_VERSION).arg( rrenkert@486: QApplication::applicationVersion()); rrenkert@486: qDebug() << softwareVersion; rrenkert@486: QString listResource = QString::fromLatin1(LIST_RESOURCE); rrenkert@486: Downloader* downloader = new Downloader(this, rrenkert@486: QString::fromLatin1(SERVER_URL), rrenkert@486: QByteArray(), rrenkert@486: QDateTime::currentDateTime(), rrenkert@486: QDateTime::currentDateTime(), rrenkert@486: softwareVersion, rrenkert@486: listResource, rrenkert@486: false); rrenkert@486: connect(downloader, SIGNAL(finished()), downloader, SLOT(deleteLater())); rrenkert@486: connect(downloader, SIGNAL(error(const QString &, SSLConnection::ErrorCode)), rrenkert@486: this, SLOT(downloaderError(const QString &, SSLConnection::ErrorCode))); rrenkert@486: connect(downloader, SIGNAL(lastModifiedDate(const QDateTime&)), aheinecke@551: this, SLOT(setLastModifiedSWDate(const QDateTime&))); rrenkert@486: rrenkert@486: downloader->start(); rrenkert@486: } rrenkert@486: aheinecke@551: void MainWindow::setLastModifiedSWDate(const QDateTime &date) rrenkert@486: { rrenkert@486: mSettings.beginGroup("Software"); rrenkert@486: mSettings.setValue("installedDate", date); aheinecke@551: mSettings.setValue("installedVersion", QApplication::applicationVersion()); rrenkert@486: mSettings.endGroup(); rrenkert@486: checkUpdates(); rrenkert@486: } rrenkert@486: aheinecke@45: void MainWindow::downloaderError(const QString &message, SSLConnection::ErrorCode error) aheinecke@16: { aheinecke@551: /* TODO logging and handle error according to a plan */ aheinecke@16: mCurMessage = message; andre@27: showMessage(); aheinecke@551: setState(TransferError); aheinecke@16: } aheinecke@16: aheinecke@0: void MainWindow::createActions() aheinecke@0: { aheinecke@0: mCheckUpdates = new QAction(tr("Check for Updates"), this); aheinecke@16: connect(mCheckUpdates, SIGNAL(triggered()), this, SLOT(checkUpdates())); aheinecke@2: mQuitAction = new QAction(tr("Quit"), this); aheinecke@2: connect(mQuitAction, SIGNAL(triggered()), qApp, SLOT(quit())); aheinecke@0: } aheinecke@0: aheinecke@0: void MainWindow::createTrayIcon() aheinecke@0: { aheinecke@11: QIcon trayImg(":/img/tray_22.png"); aheinecke@0: aheinecke@0: mTrayMenu = new QMenu(this); aheinecke@0: mTrayMenu->addAction(mCheckUpdates); aheinecke@2: mTrayMenu->addAction(mQuitAction); aheinecke@0: aheinecke@0: mTrayIcon = new QSystemTrayIcon(this); aheinecke@0: mTrayIcon->setContextMenu(mTrayMenu); aheinecke@0: aheinecke@0: mTrayIcon->setIcon(trayImg); aheinecke@0: setWindowIcon(trayImg); aheinecke@0: mTrayIcon->show(); aheinecke@407: mTrayIcon->setToolTip(tr("TrustBridge")); aheinecke@71: aheinecke@71: connect(mTrayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked())); aheinecke@0: } rrenkert@155: rrenkert@187: void MainWindow::createContent() rrenkert@187: { rrenkert@187: // Create a central widget containing the main layout. rrenkert@187: QWidget *base = new QWidget; rrenkert@187: rrenkert@250: // Layouts and Container rrenkert@584: QVBoxLayout *mainLayout = new QVBoxLayout; rrenkert@205: QHBoxLayout *headerLayout = new QHBoxLayout; rrenkert@205: QVBoxLayout *headerTextLayout = new QVBoxLayout; rrenkert@584: QHBoxLayout *centerLayout = new QHBoxLayout; rrenkert@584: QVBoxLayout *buttonBarLayout = new QVBoxLayout; rrenkert@271: QHBoxLayout *bottomLayout = new QHBoxLayout; rrenkert@584: QHBoxLayout *containerLayout = new QHBoxLayout; rrenkert@584: QVBoxLayout *updatesPanelLayout = new QVBoxLayout; rrenkert@187: rrenkert@584: // The header (icon, about text) rrenkert@584: QImage *logoImage = new QImage(":/img/logo.png"); rrenkert@584: QLabel *logo = new QLabel; rrenkert@584: logo->setBackgroundRole(QPalette::Base); rrenkert@584: logo->setPixmap(QPixmap::fromImage(*logoImage)); rrenkert@584: QLabel *title = new QLabel("

" + QString::fromLatin1(APPNAME) + "

"); rrenkert@584: QLabel *subTitle = new QLabel("This Software installs and removes Certificates"); rrenkert@584: headerTextLayout->addWidget(title); rrenkert@584: headerTextLayout->addWidget(subTitle); rrenkert@584: headerLayout->addWidget(logo); rrenkert@584: headerLayout->addLayout(headerTextLayout); rrenkert@584: headerLayout->setStretch(0, 0); rrenkert@584: headerLayout->setStretch(1, 10); rrenkert@584: rrenkert@584: // Buttonbar rrenkert@584: mButtonGroup = new QButtonGroup; rrenkert@584: rrenkert@584: QToolButton *updatesButton = new QToolButton; rrenkert@584: updatesButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); rrenkert@584: updatesButton->setIcon(QIcon(":/img/view-refresh.png")); rrenkert@584: updatesButton->setIconSize(QSize(32, 32)); rrenkert@584: updatesButton->setText(tr("Updates")); rrenkert@584: updatesButton->setFixedWidth(90); rrenkert@584: updatesButton->setFixedHeight(70); rrenkert@584: updatesButton->setCheckable(true); rrenkert@584: updatesButton->setChecked(true); rrenkert@584: rrenkert@584: QToolButton *allInstallButton = new QToolButton; rrenkert@584: allInstallButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); rrenkert@584: allInstallButton->setIcon(QIcon(":/img/document-encrypt.png")); rrenkert@584: allInstallButton->setIconSize(QSize(32, 32)); rrenkert@584: allInstallButton->setText(tr("Trusted\nCertificates")); rrenkert@584: allInstallButton->setFixedWidth(90); rrenkert@584: allInstallButton->setFixedHeight(70); rrenkert@584: allInstallButton->setCheckable(true); rrenkert@584: rrenkert@584: QToolButton *allRemoveButton = new QToolButton; rrenkert@584: allRemoveButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); rrenkert@584: allRemoveButton->setIcon(QIcon(":/img/task-attempt.png")); rrenkert@584: allRemoveButton->setIconSize(QSize(32, 32)); rrenkert@584: allRemoveButton->setText(tr("Insecure\nCertificates")); rrenkert@584: allRemoveButton->setFixedWidth(90); rrenkert@584: allRemoveButton->setFixedHeight(70); rrenkert@584: allRemoveButton->setCheckable(true); rrenkert@584: rrenkert@584: QToolButton *infoButton = new QToolButton; rrenkert@584: infoButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); rrenkert@584: infoButton->setIcon(QIcon(":/img/dialog-information.png")); rrenkert@584: infoButton->setIconSize(QSize(32, 32)); rrenkert@584: infoButton->setText(tr("Information")); rrenkert@584: infoButton->setFixedWidth(90); rrenkert@584: infoButton->setFixedHeight(70); rrenkert@584: infoButton->setCheckable(true); rrenkert@584: rrenkert@584: mButtonGroup->addButton(updatesButton); rrenkert@584: mButtonGroup->addButton(allInstallButton); rrenkert@584: mButtonGroup->addButton(allRemoveButton); rrenkert@584: mButtonGroup->addButton(infoButton); rrenkert@584: mButtonGroup->setId(updatesButton, 0); rrenkert@584: mButtonGroup->setId(allInstallButton, 1); rrenkert@584: mButtonGroup->setId(allRemoveButton, 2); rrenkert@584: mButtonGroup->setId(infoButton, 3); rrenkert@584: rrenkert@584: connect(mButtonGroup, SIGNAL(buttonClicked(int)), rrenkert@584: this, SLOT(togglePages(int))); rrenkert@584: buttonBarLayout->addWidget(updatesButton); rrenkert@584: buttonBarLayout->addWidget(allInstallButton); rrenkert@584: buttonBarLayout->addWidget(allRemoveButton); rrenkert@584: buttonBarLayout->insertStretch(3, 10); rrenkert@584: buttonBarLayout->addWidget(infoButton); rrenkert@584: rrenkert@584: //The main panels. rrenkert@584: //The updates page. rrenkert@584: mUpdatesPanel = new QScrollArea; rrenkert@584: mUpdatesWidget = new QWidget; rrenkert@584: QHBoxLayout *updatesHeaderLayout = new QHBoxLayout; rrenkert@584: QVBoxLayout *updatesHeaderTextLayout = new QVBoxLayout; rrenkert@584: QVBoxLayout *updatesHeaderSettLayout = new QVBoxLayout; rrenkert@584: rrenkert@628: mUpdatesHeader = rrenkert@584: new QLabel("

" + tr("Updates (%1/%2)").arg(2).arg(4)+ "

"); rrenkert@628: mLastCertUpdate = rrenkert@584: new QLabel(tr("Last certificate update: %1").arg("today")); rrenkert@628: mLastSWupdate = rrenkert@584: new QLabel(tr("Last Software update: %1").arg("today")); rrenkert@628: updatesHeaderTextLayout->addWidget(mUpdatesHeader); rrenkert@628: updatesHeaderTextLayout->addWidget(mLastCertUpdate); rrenkert@628: updatesHeaderTextLayout->addWidget(mLastSWupdate); rrenkert@584: rrenkert@584: QPushButton *searchUpdates = new QPushButton(tr("Search for Updates")); rrenkert@628: connect(searchUpdates, SIGNAL(clicked()), this, SLOT(checkUpdates())); rrenkert@584: updatesHeaderSettLayout->insertStretch(0, 10); rrenkert@584: updatesHeaderSettLayout->addWidget(searchUpdates); rrenkert@584: updatesHeaderLayout->addLayout(updatesHeaderTextLayout); rrenkert@584: updatesHeaderLayout->insertStretch(1, 10); rrenkert@584: updatesHeaderLayout->addLayout(updatesHeaderSettLayout); rrenkert@584: rrenkert@584: QVBoxLayout *updatesCenterLayout = new QVBoxLayout; rrenkert@584: QHBoxLayout *updatesNewLayout = new QHBoxLayout; rrenkert@584: QHBoxLayout *updatesRemoveLayout = new QHBoxLayout; rrenkert@584: QHBoxLayout *updatesManualLayout = new QHBoxLayout; rrenkert@584: QLabel *updatesTip = rrenkert@584: new QLabel(tr("The following certificate changes are recommended.")); rrenkert@628: mUpdatesNewCertificates = rrenkert@584: new QLabel("

" + rrenkert@584: tr("Install new Certificates (%1/%2)").arg(2).arg(2) + rrenkert@584: "

"); rrenkert@584: QPushButton *updatesDetailsNew = new QPushButton(tr("Details")); rrenkert@584: connect(updatesDetailsNew, rrenkert@584: SIGNAL(clicked()), rrenkert@584: this, rrenkert@584: SLOT(toggleUpdatesNew())); rrenkert@628: updatesNewLayout->addWidget(mUpdatesNewCertificates); rrenkert@584: updatesNewLayout->addWidget(updatesDetailsNew); rrenkert@584: updatesNewLayout->insertStretch(2, 10); rrenkert@584: mUpdatesNew = new CertificateListWidget(this); rrenkert@628: connect(mUpdatesNew, SIGNAL(certListChanged(int)), rrenkert@628: this, SLOT(listChanged(int))); rrenkert@584: mUpdatesNew->hide(); rrenkert@584: rrenkert@628: mUpdatesRemoveCertificates = rrenkert@584: new QLabel("

" + rrenkert@584: tr("Remove insecure Certificates (%1/%2)").arg(2).arg(2) + rrenkert@584: "

"); rrenkert@584: QPushButton *updatesDetailsRemove = new QPushButton(tr("Details")); rrenkert@584: connect(updatesDetailsRemove, rrenkert@584: SIGNAL(clicked()), rrenkert@584: this, rrenkert@584: SLOT(toggleUpdatesRemove())); rrenkert@628: updatesRemoveLayout->addWidget(mUpdatesRemoveCertificates); rrenkert@584: updatesRemoveLayout->addWidget(updatesDetailsRemove); rrenkert@584: updatesRemoveLayout->insertStretch(2, 10); rrenkert@584: mUpdatesRemove = new CertificateListWidget(this); rrenkert@642: connect(mUpdatesRemove, SIGNAL(certListChanged(int)), rrenkert@642: this, SLOT(listChanged(int))); rrenkert@584: mUpdatesRemove->hide(); rrenkert@584: rrenkert@628: mUpdatesManualCertificates = rrenkert@584: new QLabel("

" + rrenkert@584: tr("Manualy changed Certificates (%1)").arg(2) + rrenkert@584: "

"); rrenkert@584: QPushButton *updatesDetailsManual = new QPushButton(tr("Details")); rrenkert@584: connect(updatesDetailsManual, rrenkert@584: SIGNAL(clicked()), rrenkert@584: this, rrenkert@584: SLOT(toggleUpdatesManual())); rrenkert@628: updatesManualLayout->addWidget(mUpdatesManualCertificates); rrenkert@584: updatesManualLayout->addWidget(updatesDetailsManual); rrenkert@584: updatesManualLayout->insertStretch(2, 10); rrenkert@584: mUpdatesManual = new CertificateListWidget(this); rrenkert@584: mUpdatesManual->hide(); rrenkert@640: connect(mUpdatesManual, SIGNAL(certChanged(bool, const Certificate&)), rrenkert@640: this, SLOT(removeFromManual(bool, const Certificate&))); rrenkert@584: rrenkert@584: QHBoxLayout *updatesBottomLayout = new QHBoxLayout; rrenkert@641: QPushButton *quitButton = new QPushButton(tr("Quit without saving")); rrenkert@641: QPushButton *installButton = new QPushButton(tr("Update")); rrenkert@641: #ifdef Q_OS_WIN rrenkert@641: if (is_admin()) { rrenkert@641: QIcon uacShield = QApplication::style()->standardIcon(QStyle::SP_VistaShield); rrenkert@641: installButton->setIcon(uacShield); rrenkert@641: } rrenkert@641: #endif rrenkert@584: connect(quitButton, SIGNAL(clicked()), this, SLOT(closeApp())); rrenkert@641: connect(installButton, SIGNAL(clicked()), this, SLOT(installCerts())); rrenkert@584: updatesBottomLayout->insertStretch(0, 10); rrenkert@641: updatesBottomLayout->addWidget(installButton); rrenkert@584: updatesBottomLayout->addWidget(quitButton); rrenkert@640: updatesBottomLayout->setAlignment(Qt::AlignBottom); rrenkert@640: rrenkert@640: updatesNewLayout->setAlignment(Qt::AlignTop); rrenkert@640: updatesRemoveLayout->setAlignment(Qt::AlignTop); rrenkert@640: updatesManualLayout->setAlignment(Qt::AlignTop); rrenkert@640: updatesCenterLayout->addWidget(updatesTip, 0, Qt::AlignTop); rrenkert@640: updatesCenterLayout->addLayout(updatesNewLayout); rrenkert@640: // updatesCenterLayout->setStretchFactor(updatesNewLayout, 100); rrenkert@640: updatesCenterLayout->addWidget(mUpdatesNew, 1, Qt::AlignTop); rrenkert@640: updatesCenterLayout->addLayout(updatesRemoveLayout); rrenkert@640: // updatesCenterLayout->setStretchFactor(updatesRemoveLayout, 100); rrenkert@640: updatesCenterLayout->addWidget(mUpdatesRemove, 1, Qt::AlignTop); rrenkert@640: updatesCenterLayout->addLayout(updatesManualLayout); rrenkert@640: // updatesCenterLayout->setStretchFactor(updatesManualLayout, 100); rrenkert@640: updatesCenterLayout->addWidget(mUpdatesManual, 1, Qt::AlignTop); rrenkert@640: updatesCenterLayout->insertStretch(7, 0); rrenkert@640: updatesCenterLayout->addLayout(updatesBottomLayout); rrenkert@640: rrenkert@584: rrenkert@584: QFrame *updatesPanelSeparator = new QFrame(); rrenkert@584: updatesPanelSeparator->setFrameShape(QFrame::HLine); rrenkert@584: updatesPanelSeparator->setFrameShadow(QFrame::Sunken); rrenkert@584: updatesPanelLayout->addLayout(updatesHeaderLayout); rrenkert@584: updatesPanelLayout->addWidget(updatesPanelSeparator); rrenkert@584: updatesPanelLayout->addLayout(updatesCenterLayout); rrenkert@640: updatesPanelLayout->setStretchFactor(updatesCenterLayout, 1); rrenkert@640: //updatesPanelLayout->insertStretch(3, 2); rrenkert@640: //updatesPanelLayout->addLayout(updatesBottomLayout); rrenkert@584: mUpdatesWidget->setLayout(updatesPanelLayout); rrenkert@584: mUpdatesWidget->setMinimumSize(QSize(820, 440)); rrenkert@584: mUpdatesPanel->setWidget(mUpdatesWidget); rrenkert@584: rrenkert@584: // Panel for trusted certificates. rrenkert@584: mInstallPanel = new QScrollArea; rrenkert@584: rrenkert@584: QVBoxLayout *installPanelLayout = new QVBoxLayout; rrenkert@584: QVBoxLayout *installHeaderLayout = new QVBoxLayout; rrenkert@584: QVBoxLayout *installCenterLayout = new QVBoxLayout; rrenkert@584: rrenkert@584: QLabel *installHeaderLabel = rrenkert@584: new QLabel("

" + tr("Trusted Certificates") + "

"); rrenkert@584: QLabel *installHeaderText = new QLabel(tr("The following list of root" rrenkert@584: " certificates was created by the BSI. The BSI vaidates authenticity," rrenkert@584: " security and actuality of these certificates")); rrenkert@584: installHeaderLayout->addWidget(installHeaderLabel); rrenkert@584: installHeaderLayout->addWidget(installHeaderText); rrenkert@584: rrenkert@584: QLabel *installCenterText = new QLabel(tr("Please choose the certificates" rrenkert@584: " you want to trust. TrustBridge will install these certificates for" rrenkert@584: " secure communication via email or the internet (e.g. IE, Firefox," rrenkert@584: " Thunderbird)")); rrenkert@584: installCenterLayout->addWidget(installCenterText); rrenkert@584: mInstallList = new CertificateListWidget(this); rrenkert@640: connect(mInstallList, SIGNAL(certChanged(bool, const Certificate&)), rrenkert@640: this, SLOT(toggleInManual(bool, const Certificate&))); rrenkert@584: rrenkert@584: installPanelLayout->addLayout(installHeaderLayout); rrenkert@584: installPanelLayout->addLayout(installCenterLayout); rrenkert@584: installPanelLayout->addWidget(mInstallList); rrenkert@584: mInstallPanel->setLayout(installPanelLayout); rrenkert@584: rrenkert@584: // Panel for insecure certificates. rrenkert@584: mRemovePanel = new QScrollArea; rrenkert@584: QVBoxLayout *removePanelLayout = new QVBoxLayout; rrenkert@584: QVBoxLayout *removeHeaderLayout = new QVBoxLayout; rrenkert@584: QVBoxLayout *removeCenterLayout = new QVBoxLayout; rrenkert@584: rrenkert@584: QLabel *removeHeaderLabel = rrenkert@584: new QLabel("

" + tr("Insecure Certificates") + "

"); rrenkert@584: QLabel *removeHeaderText = new QLabel(tr("The following list of root" rrenkert@584: " certificates was created by the BSI. The BSI validates authenticity," rrenkert@584: " security and actuality of these certificates")); rrenkert@584: removeHeaderLayout->addWidget(removeHeaderLabel); rrenkert@584: removeHeaderLayout->addWidget(removeHeaderText); rrenkert@584: rrenkert@584: QLabel *removeCenterText = new QLabel(tr("Please choose the certificates" rrenkert@584: " you want to remove. TrustBridge will remove these certificates.")); rrenkert@584: removeCenterLayout->addWidget(removeCenterText); rrenkert@628: mRemoveList = new CertificateListWidget(this); rrenkert@640: connect(mRemoveList, SIGNAL(certChanged(bool, const Certificate&)), rrenkert@640: this, SLOT(toggleInManual(bool, const Certificate&))); rrenkert@584: rrenkert@584: removePanelLayout->addLayout(removeHeaderLayout); rrenkert@584: removePanelLayout->addLayout(removeCenterLayout); rrenkert@628: removePanelLayout->addWidget(mRemoveList); rrenkert@584: mRemovePanel->setLayout(removePanelLayout); rrenkert@584: rrenkert@584: // Info panel. rrenkert@584: mInfoPanel = new QScrollArea; rrenkert@584: rrenkert@584: QVBoxLayout *infoPanelLayout = new QVBoxLayout(this); rrenkert@584: QHBoxLayout *infoHeaderLayout = new QHBoxLayout; rrenkert@584: QVBoxLayout *infoHeaderTextLayout = new QVBoxLayout; rrenkert@584: QVBoxLayout *infoCenterLayout = new QVBoxLayout; rrenkert@584: rrenkert@584: QImage *infoLogoImage = new QImage(":/img/logo.png"); rrenkert@584: QLabel *infoLogo = new QLabel; rrenkert@584: infoLogo->setBackgroundRole(QPalette::Base); rrenkert@584: infoLogo->setPixmap(QPixmap::fromImage(*infoLogoImage)); rrenkert@584: QLabel *infoTitle = new QLabel("

" + tr("TrustBridge") + "

"); rrenkert@584: QString infoVersion = tr("Version: "); rrenkert@584: infoVersion.append(QApplication::applicationVersion()); rrenkert@584: QLabel *appVersion = new QLabel(infoVersion); rrenkert@584: appVersion->setTextInteractionFlags( rrenkert@584: Qt::TextSelectableByMouse | rrenkert@584: Qt::TextSelectableByKeyboard); rrenkert@584: rrenkert@584: QFrame *infoHeaderSeparator = new QFrame(); rrenkert@584: infoHeaderSeparator->setFrameShape(QFrame::HLine); rrenkert@584: infoHeaderSeparator->setFrameShadow(QFrame::Sunken); rrenkert@584: rrenkert@584: infoHeaderTextLayout->addWidget(infoTitle); rrenkert@584: infoHeaderTextLayout->addWidget(appVersion); rrenkert@584: infoHeaderLayout->addWidget(infoLogo); rrenkert@584: infoHeaderLayout->addLayout(infoHeaderTextLayout); rrenkert@584: infoHeaderLayout->insertStretch(2, 10); rrenkert@584: rrenkert@584: QLabel *textDesc = new QLabel(tr("TrustBridge is a root certificate" rrenkert@584: " installer for Windows and Linux.")); rrenkert@584: textDesc->setTextInteractionFlags( rrenkert@584: Qt::TextSelectableByMouse | rrenkert@584: Qt::TextSelectableByKeyboard); rrenkert@584: QLabel *textManage = new QLabel(tr("The root certificate lists are managed" rrenkert@584: " by the German " rrenkert@584: "Federal Office for Information Security (BSI).\n\n")); rrenkert@584: textManage->setTextInteractionFlags( rrenkert@584: Qt::TextBrowserInteraction | rrenkert@584: Qt::TextSelectableByKeyboard); rrenkert@584: QLabel *textDevel = new QLabel(tr("The software was developed by the companies" rrenkert@584: " Intevation GmbH and " rrenkert@584: " DN-Systems GmbH,
" rrenkert@584: " contracted by the German Federal Office for Information Security (BSI).\n\n")); rrenkert@584: textDevel->setTextInteractionFlags( rrenkert@584: Qt::TextBrowserInteraction | rrenkert@584: Qt::TextSelectableByKeyboard); rrenkert@584: QLabel *textLicense = new QLabel(tr("TrustBridge is Free Software licensed" rrenkert@584: " under GNU GPL v2+.\n\nCopyright (C) 2014 by Bundesamt für Sicherheit" rrenkert@584: " in der Informationstechnik")); rrenkert@584: textLicense->setTextInteractionFlags( rrenkert@584: Qt::TextSelectableByMouse | rrenkert@584: Qt::TextSelectableByKeyboard); rrenkert@584: rrenkert@584: infoCenterLayout->addWidget(infoHeaderSeparator); rrenkert@584: infoCenterLayout->addWidget(textDesc); rrenkert@584: infoCenterLayout->addWidget(textManage); rrenkert@584: infoCenterLayout->addWidget(textDevel); rrenkert@584: infoCenterLayout->addWidget(textLicense); rrenkert@584: infoCenterLayout->insertSpacing(2, 10); rrenkert@584: infoCenterLayout->insertSpacing(4, 10); rrenkert@584: infoCenterLayout->insertSpacing(6, 10); rrenkert@584: infoCenterLayout->insertStretch(8, 10); rrenkert@584: rrenkert@584: infoPanelLayout->addLayout(infoHeaderLayout); rrenkert@584: infoPanelLayout->addLayout(infoCenterLayout); rrenkert@584: mInfoPanel->setLayout(infoPanelLayout); rrenkert@584: rrenkert@584: // The main layout for pages. rrenkert@584: mInstallPanel->hide(); rrenkert@584: mRemovePanel->hide(); rrenkert@584: mInfoPanel->hide(); rrenkert@584: containerLayout->addWidget(mUpdatesPanel); rrenkert@584: containerLayout->addWidget(mInstallPanel); rrenkert@584: containerLayout->addWidget(mRemovePanel); rrenkert@584: containerLayout->addWidget(mInfoPanel); rrenkert@584: rrenkert@584: centerLayout->addLayout(buttonBarLayout); rrenkert@584: centerLayout->addLayout(containerLayout); rrenkert@584: rrenkert@584: QFrame *topSeparator = new QFrame(); rrenkert@584: topSeparator->setFrameShape(QFrame::HLine); rrenkert@584: topSeparator->setFrameShadow(QFrame::Sunken); rrenkert@584: rrenkert@584: mainLayout->addLayout(headerLayout); rrenkert@584: mainLayout->addWidget(topSeparator); rrenkert@584: mainLayout->addLayout(centerLayout); rrenkert@584: mainLayout->addLayout(bottomLayout); rrenkert@187: base->setLayout(mainLayout); rrenkert@187: setCentralWidget(base); rrenkert@187: } rrenkert@187: rrenkert@628: void MainWindow::listChanged(int selected) rrenkert@628: { rrenkert@628: mUpdatesHeader->setText("

" + tr("Updates (%1/%2)") rrenkert@628: .arg(mUpdatesRemove->selectedCertCount() + mUpdatesNew->selectedCertCount()) rrenkert@628: .arg(mUpdatesRemove->certificates().size() + mUpdatesNew->certificates().size()) + rrenkert@628: "

"); rrenkert@628: mUpdatesNewCertificates->setText("

" + rrenkert@628: tr("Install new Certificates (%1/%2)") rrenkert@628: .arg(mUpdatesNew->selectedCertCount()) rrenkert@628: .arg(mUpdatesNew->certificates().size()) + rrenkert@628: "

"); rrenkert@628: mUpdatesRemoveCertificates->setText("

" + rrenkert@628: tr("Remove insecure Certificates (%1/%2)") rrenkert@628: .arg(mUpdatesRemove->selectedCertCount()) rrenkert@628: .arg(mUpdatesRemove->certificates().size()) + rrenkert@628: "

"); rrenkert@628: } rrenkert@628: rrenkert@189: void MainWindow::loadCertificateList() rrenkert@189: { andre@389: /* TODO: if nothing is available (neither old nor new) add some progress andre@389: * indication */ rrenkert@628: mInstallList->clear(); rrenkert@628: mUpdatesNew->clear(); rrenkert@628: mRemoveList->clear(); rrenkert@628: mUpdatesRemove->clear(); rrenkert@445: QList newInstallCerts; rrenkert@445: QList newRemoveCerts; rrenkert@445: QList oldInstallCerts; rrenkert@445: QList oldRemoveCerts; andre@389: rrenkert@445: if (mListToInstall.getCertificates().isEmpty()) { rrenkert@445: // No new list available, add old certificates. rrenkert@445: foreach (const Certificate &cert, mInstalledList.getCertificates()) { rrenkert@640: bool state = !mPreviouslyUnselected.contains(cert.base64Line()); rrenkert@445: if (cert.isInstallCert()) { rrenkert@445: oldInstallCerts.append(cert); rrenkert@640: mInstallList->addCertificate(cert, state); rrenkert@267: } rrenkert@267: else { rrenkert@445: oldRemoveCerts.append(cert); rrenkert@640: mRemoveList->addCertificate(cert, state, !state); rrenkert@267: } rrenkert@267: } rrenkert@456: // Set the date of the old list. rrenkert@628: // mCurrentListDate->setText(tr("Current List Date: %1") rrenkert@628: // .arg(mInstalledList.date().toString())); rrenkert@445: } rrenkert@445: else { rrenkert@445: // Sort and filter both lists. rrenkert@445: foreach (const Certificate &cert, mListToInstall.getCertificates()) { rrenkert@640: bool state = !mPreviouslyUnselected.contains(cert.base64Line()); rrenkert@445: if (cert.isInstallCert()) { rrenkert@445: // Certificate with status "install". rrenkert@445: if (mInstalledList.getCertificates().contains(cert)) { rrenkert@445: // Was in the old list. rrenkert@445: oldInstallCerts.append(cert); rrenkert@640: mInstallList->addCertificate(cert, state); rrenkert@445: } rrenkert@445: else { rrenkert@445: // Is a brand new certificate rrenkert@445: newInstallCerts.append(cert); rrenkert@640: mUpdatesNew->addCertificate(cert, state); rrenkert@445: } rrenkert@267: } rrenkert@267: else { rrenkert@445: // Certificate with status "remove". rrenkert@445: if (mInstalledList.getCertificates().contains(cert)) { rrenkert@445: // Was in the old list. rrenkert@445: oldRemoveCerts.append(cert); rrenkert@640: // Is removed, so set editable to false. rrenkert@640: mRemoveList->addCertificate(cert, state, !state); rrenkert@445: } rrenkert@445: else { rrenkert@445: // Was in the old list with status "install" and now has the rrenkert@445: // status "remove". rrenkert@445: newRemoveCerts.append(cert); rrenkert@640: mUpdatesRemove->addCertificate(cert, state); rrenkert@445: } rrenkert@267: } rrenkert@267: } rrenkert@628: mUpdatesHeader->setText("

" + rrenkert@628: tr("Updates (%1/%2)") rrenkert@640: .arg(mUpdatesNew->selectedCertCount() + mUpdatesRemove->selectedCertCount()) rrenkert@628: .arg(newRemoveCerts.size() + newInstallCerts.size()) + "

"); rrenkert@628: mLastCertUpdate->setText(tr("Last certificate update: %1") rrenkert@628: .arg(mInstalledList.date().toString())); rrenkert@584: /* mCurrentListDate->setText(tr("Current List Date: %1") rrenkert@456: .arg(mInstalledList.date().toString())); rrenkert@584: mNewListDate->setText(tr("New List Date: %1").arg(mListToInstall.date().toString()));*/ rrenkert@189: } rrenkert@628: mUpdatesNewCertificates->setText("

" + rrenkert@628: tr("Install new Certificates (%1/%2)") rrenkert@628: .arg(mUpdatesNew->selectedCertCount()) rrenkert@628: .arg(mUpdatesNew->certificates().size()) + rrenkert@628: "

"); rrenkert@628: rrenkert@628: mUpdatesRemoveCertificates->setText("

" + rrenkert@628: tr("Remove insecure Certificates (%1/%2)") rrenkert@628: .arg(mUpdatesRemove->selectedCertCount()) rrenkert@628: .arg(mUpdatesRemove->certificates().size()) + rrenkert@628: "

"); rrenkert@628: mUpdatesManualCertificates->setText("

" + rrenkert@628: tr("Manualy changed Certificates (%1)").arg(0) + rrenkert@628: "

"); rrenkert@271: } aheinecke@365: aheinecke@365: void MainWindow::installerError(const QString& errMsg) { aheinecke@365: QMessageBox::warning(this, tr("Error executing update"), errMsg); aheinecke@365: } aheinecke@365: andre@389: void MainWindow::installerSuccess() { andre@389: if (mCurState == NewListAvailable) { andre@389: mCurState = NothingChanged; andre@389: mCurMessage = QString(); andre@389: andre@389: QString listFileName = mSettings.value("List/available").toString(); andre@389: QDateTime listFileDate = mSettings.value("List/availableDate").toDateTime(); andre@389: andre@389: mSettings.remove("List/available"); andre@389: mSettings.remove("List/availableDate"); andre@389: andre@389: if (listFileName.isEmpty() || !listFileDate.isValid()) { andre@389: qWarning() << "Error accessing settings"; andre@389: return; /* Try again with next check */ andre@389: } andre@389: andre@389: mSettings.setValue("List/installed", listFileName); andre@389: mSettings.setValue("List/installedDate", listFileDate); rrenkert@480: mInstalledList = mListToInstall; rrenkert@480: mListToInstall = CertificateList(); andre@389: } rrenkert@628: loadCertificateList(); andre@389: } andre@389: aheinecke@365: void MainWindow::installCerts() { aheinecke@365: QStringList choices; rrenkert@640: QStringList unselected; aheinecke@365: rrenkert@640: choices << mUpdatesNew->selectedCertificates(); rrenkert@640: choices << mUpdatesRemove->selectedCertificates(); rrenkert@640: rrenkert@640: choices << mUpdatesManual->selectedCertificates(); rrenkert@640: QStringList unselectedManuals = mUpdatesManual->unselectedCertificates(); rrenkert@640: for(int i = 0; i < unselectedManuals.size(); i++) { rrenkert@640: if (unselectedManuals.at(i).startsWith("I:")) { rrenkert@640: QString certLine = unselectedManuals.at(i); rrenkert@640: certLine[0] = 'R'; rrenkert@640: choices << certLine; rrenkert@640: } rrenkert@640: } rrenkert@640: rrenkert@640: unselected << mUpdatesNew->unselectedCertificates(); rrenkert@640: unselected << mUpdatesRemove->unselectedCertificates(); rrenkert@640: unselected << mInstallList->unselectedCertificates(); rrenkert@640: unselected << mRemoveList->unselectedCertificates(); rrenkert@628: aheinecke@365: QProgressDialog *progress = new QProgressDialog(this); aheinecke@365: progress->setWindowModality(Qt::WindowModal); aheinecke@365: progress->setLabelText(tr("Installing certificates...")); aheinecke@365: progress->setCancelButton(0); aheinecke@365: progress->setRange(0,0); aheinecke@365: progress->setMinimumDuration(0); aheinecke@365: progress->show(); aheinecke@365: aheinecke@365: InstallWrapper *instWrap = new InstallWrapper(this, andre@393: mListToInstall.isValid() ? andre@393: mListToInstall.fileName() : andre@393: mInstalledList.fileName(), aheinecke@365: choices); aheinecke@365: /* Clean up object and progress dialog */ aheinecke@365: connect(instWrap, SIGNAL(finished()), instWrap, SLOT(deleteLater())); aheinecke@365: connect(instWrap, SIGNAL(finished()), progress, SLOT(deleteLater())); aheinecke@365: connect(instWrap, SIGNAL(finished()), progress, SLOT(cancel())); andre@389: connect(instWrap, SIGNAL(installationSuccessful()), andre@389: this, SLOT(installerSuccess())); aheinecke@365: connect(instWrap, SIGNAL(error(const QString &)), andre@389: this, SLOT(installerError(const QString &))); aheinecke@365: instWrap->start(); rrenkert@640: rrenkert@640: if (!saveUnselectedCertificates(unselected)) { andre@372: qWarning() << "Failed to save previosly unselected certificates."; andre@372: } rrenkert@640: aheinecke@365: } andre@372: andre@372: void MainWindow::loadUnselectedCertificates() andre@372: { andre@372: mPreviouslyUnselected.clear(); andre@372: mSettings.beginGroup("unselected"); andre@372: QStringList keys = mSettings.allKeys(); andre@372: foreach (const QString &key, keys) { andre@372: mPreviouslyUnselected << mSettings.value(key, QString()).toString(); andre@372: } andre@372: mSettings.endGroup(); andre@372: } andre@372: rrenkert@640: bool MainWindow::saveUnselectedCertificates(QStringList unselected) andre@372: { rrenkert@479: mPreviouslyUnselected.clear(); andre@372: mSettings.beginGroup("unselected"); andre@372: mSettings.remove(""); /* Clears old choices */ rrenkert@640: for (int i = 0; i < unselected.size(); i++) { rrenkert@640: QString key = QString::fromLatin1("cert%1").arg(i); rrenkert@640: QString value = unselected.at(i); rrenkert@640: mSettings.setValue(key, value); rrenkert@640: mPreviouslyUnselected << value; andre@372: } andre@372: mSettings.endGroup(); andre@372: mSettings.sync(); andre@372: return mSettings.status() == QSettings::NoError; andre@372: } rrenkert@447: rrenkert@640: void MainWindow::toggleInManual(bool state, const Certificate &cert) rrenkert@640: { rrenkert@640: if (!mUpdatesManual->contains(cert)) { rrenkert@640: mUpdatesManual->addCertificate(cert, state); rrenkert@640: } rrenkert@640: else { rrenkert@640: mUpdatesManual->removeCertificate(cert); rrenkert@640: } rrenkert@640: rrenkert@640: mUpdatesManualCertificates->setText("

" + rrenkert@640: tr("Manualy changed Certificates (%1)") rrenkert@640: .arg(mUpdatesManual->certificates().size()) + rrenkert@640: "

"); rrenkert@640: } rrenkert@640: rrenkert@640: void MainWindow::removeFromManual(bool state, const Certificate &cert) rrenkert@640: { rrenkert@640: mUpdatesManual->removeCertificate(cert); rrenkert@640: rrenkert@640: mUpdatesManualCertificates->setText("

" + rrenkert@640: tr("Manualy changed Certificates (%1)") rrenkert@640: .arg(mUpdatesManual->certificates().size()) + rrenkert@640: "

"); rrenkert@640: rrenkert@640: if (cert.isInstallCert()) { rrenkert@640: mInstallList->setCertState(state, cert); rrenkert@640: } rrenkert@640: else { rrenkert@640: mRemoveList->setCertState(state, cert); rrenkert@640: } rrenkert@640: } rrenkert@640: rrenkert@447: void MainWindow::closeApp() rrenkert@447: { rrenkert@447: qApp->quit(); rrenkert@447: } rrenkert@584: rrenkert@584: void MainWindow::togglePages(int button) rrenkert@584: { rrenkert@584: mUpdatesPanel->hide(); rrenkert@584: mInstallPanel->hide(); rrenkert@584: mRemovePanel->hide(); rrenkert@584: mInfoPanel->hide(); rrenkert@584: switch(button) { rrenkert@584: case 0: mUpdatesPanel->show(); break; rrenkert@584: case 1: mInstallPanel->show(); break; rrenkert@584: case 2: mRemovePanel->show(); break; rrenkert@584: case 3: mInfoPanel->show(); break; rrenkert@584: default: mUpdatesPanel->show(); break; rrenkert@584: } rrenkert@584: return; rrenkert@584: } rrenkert@584: rrenkert@584: void MainWindow::toggleUpdatesNew() { rrenkert@584: QSize old = mUpdatesWidget->size(); rrenkert@584: if (!mUpdatesNew->isVisible()) { rrenkert@584: mUpdatesNew->show(); rrenkert@640: if (mUpdatesNewSize == 0) { rrenkert@640: mUpdatesNewSize = mUpdatesNew->height(); rrenkert@640: } rrenkert@640: mUpdatesWidget->resize(old.width(), old.height() + mUpdatesNewSize); rrenkert@584: } rrenkert@584: else { rrenkert@584: mUpdatesWidget->resize(old.width(), old.height() - mUpdatesNew->height()); rrenkert@584: mUpdatesNew->hide(); rrenkert@584: } rrenkert@584: } rrenkert@584: rrenkert@584: void MainWindow::toggleUpdatesRemove() { rrenkert@584: QSize old = mUpdatesWidget->size(); rrenkert@584: if (!mUpdatesRemove->isVisible()) { rrenkert@584: mUpdatesRemove->show(); rrenkert@640: if (mUpdatesRemoveSize == 0) { rrenkert@640: mUpdatesRemoveSize = mUpdatesRemove->height(); rrenkert@640: } rrenkert@640: mUpdatesWidget->resize(old.width(), old.height() + mUpdatesRemoveSize); rrenkert@584: } rrenkert@584: else { rrenkert@584: mUpdatesWidget->resize(old.width(), old.height() - mUpdatesRemove->height()); rrenkert@584: mUpdatesRemove->hide(); rrenkert@584: } rrenkert@584: } rrenkert@584: rrenkert@584: void MainWindow::toggleUpdatesManual() { rrenkert@584: QSize old = mUpdatesWidget->size(); rrenkert@584: if (!mUpdatesManual->isVisible()) { rrenkert@584: mUpdatesManual->show(); rrenkert@640: if (mUpdatesManualSize == 0) { rrenkert@640: mUpdatesManualSize = mUpdatesManual->height(); rrenkert@640: } rrenkert@640: mUpdatesWidget->resize(old.width(), old.height() + mUpdatesManualSize); rrenkert@584: } rrenkert@584: else { rrenkert@640: mUpdatesWidget->resize(old.width(), old.height() - mUpdatesManual->height()); rrenkert@584: mUpdatesManual->hide(); rrenkert@584: } rrenkert@584: }