view ui/listupdatedialog.cpp @ 214:aab742690bee

Fix check for selected items and wait for bytes written. According to the documentation closing the write channel should suffice. But in testing it did not sent over everything.
author Andre Heinecke <andre.heinecke@intevation.de>
date Wed, 26 Mar 2014 17:17:19 +0100
parents 3ebebd055d3a
children 431b058e903d
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.getInstallCertificates()) {
        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 = new QIcon(":/img/list-add.png");
        item->setIcon(*certIcon);
        mCertListWidget->addItem(item);
    }

    foreach (const Certificate& cert, mCertificateList.getRemoveCertificates()) {
        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 = 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() 1= 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/