view ui/listupdatedialog.cpp @ 256:84ae353688e0

Add installwrapper class to handle process communication
author Andre Heinecke <aheinecke@intevation.de>
date Tue, 01 Apr 2014 10:52:06 +0000
parents 6a7eb102716d
children 06089ba2614a
line wrap: on
line source
#include "listupdatedialog.h"
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QProcess>
#include <QPushButton>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QListWidget>
#include <QVBoxLayout>
#include <QLabel>
#include "certificate.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("<h3>" + tr("Update Certificate") + "</h3>");
    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::executeUpdate() {
    /* 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;
    }
}

void ListUpdateDialog::showDetails(QListWidgetItem *item)
{
    QString details = item->data(Qt::ToolTipRole).toString();
    mDetailWidget->setPlainText(details);
}

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