changeset 743:a467204a35f5

Rework User Interface. Certificate lists are now plain lists of widgets and no longer a ListWidget. Details are no longer shown extra but included in the list. List entries are somewhat larger accordingly.
author Andre Heinecke <andre.heinecke@intevation.de>
date Fri, 04 Jul 2014 16:15:59 +0200
parents 627e8d678b6d
children b6172b9f885d
files ui/certificateitemwidget.cpp ui/certificatelistwidget.cpp ui/certificatelistwidget.h ui/img/security-high.png ui/img/security-low.png ui/img/security-medium.png ui/img/trash-empty.png ui/mainwindow.cpp ui/mainwindow.h ui/textoverlaybutton.cpp
diffstat 10 files changed, 344 insertions(+), 411 deletions(-) [+]
line wrap: on
line diff
--- a/ui/certificateitemwidget.cpp	Fri Jul 04 16:13:40 2014 +0200
+++ b/ui/certificateitemwidget.cpp	Fri Jul 04 16:15:59 2014 +0200
@@ -33,7 +33,7 @@
 
 void CertificateItemWidget::setupGUI()
 {
-    mLabel = new QLabel(mCertificate.subjectCN());
+    mLabel = new QLabel;
     mComboBox = new IconOnlyTextPopupBox;
     QStyle *fusionStyle = QStyleFactory::create("Fusion");
     if (!fusionStyle) {
@@ -42,7 +42,17 @@
         mComboBox->setStyle(fusionStyle);
     }
 
-    mComboBox->setFixedWidth(46);
+    mComboBox->setIconSize(QSize(48, 48));
+    mComboBox->setFixedWidth(68);
+
+    const QString validity = tr("Vopalid: %1 until %2").arg(
+            QLocale::system().toString(mCertificate.validFrom().date(), QLocale::ShortFormat)).arg(
+            QLocale::system().toString(mCertificate.validTo().date(), QLocale::ShortFormat));
+    const QString fpstring = tr("Fingerprint (SHA1): &lt;%1&gt;").arg(mCertificate.fingerprint());
+    mLabel->setText(QString::fromLatin1("<big><b>%1</b><br/>%2<br/>%3<br/>%4</big>").arg
+        (mCertificate.subjectCN()).arg(mCertificate.subjectO()).arg(validity).arg
+        (fpstring));
+    mLabel->setTextFormat(Qt::RichText);
 
     mLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
     mComboBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
@@ -64,7 +74,7 @@
         QImage *img = new QImage(":/img/trash-empty.png");
         QLabel *imgLabel = new QLabel;
         imgLabel->setPixmap(QPixmap::fromImage(*img));
-        imgLabel->setFixedSize(28, 28);
+        imgLabel->setFixedSize(48, 48);
         imgLabel->setMargin(2);
         layout->addWidget(imgLabel);
     }
--- a/ui/certificatelistwidget.cpp	Fri Jul 04 16:13:40 2014 +0200
+++ b/ui/certificatelistwidget.cpp	Fri Jul 04 16:15:59 2014 +0200
@@ -8,63 +8,16 @@
 #include "certificatelistwidget.h"
 #include <QDebug>
 #include <QVBoxLayout>
-#include <QHBoxLayout>
 #include <QGroupBox>
 #include <QLabel>
+#include <QApplication>
 
 #include "certificateitemwidget.h"
 
 CertificateListWidget::CertificateListWidget(QWidget *parent, Qt::WindowFlags flags) :
     QWidget(parent, flags)
 {
-    setupGUI();
-}
-
-void CertificateListWidget::setupGUI()
-{
-    QHBoxLayout *mainLayout = new QHBoxLayout;
-    QVBoxLayout *detailMainLayout = new QVBoxLayout;
-    mCertificateList = new QListWidget;
-    mCertificateList->setFixedWidth(250);
-    connect(mCertificateList,
-        SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
-        this,
-        SLOT(updateDetails(QListWidgetItem*)));
-
-    QHBoxLayout *detailLayout = new QHBoxLayout;
-    QVBoxLayout *detailLabelLayout = new QVBoxLayout;
-    QVBoxLayout *detailContentLayout = new QVBoxLayout;
-    QGroupBox *detailBox = new QGroupBox(tr("Details"));
-    QLabel *subjectCN = new QLabel(tr("Subject Common Name:"));
-    QLabel *subjectOU = new QLabel(tr("Subject Organisation:"));
-    QLabel *validFrom = new QLabel(tr("Valid from:"));
-    QLabel *validTo = new QLabel(tr("Valid to:"));
-    QLabel *fingerprint = new QLabel(tr("Fingerprint (SHA1):"));
-    detailLabelLayout->addWidget(subjectCN);
-    detailLabelLayout->addWidget(subjectOU);
-    detailLabelLayout->addWidget(validFrom);
-    detailLabelLayout->addWidget(validTo);
-    detailLabelLayout->addWidget(fingerprint);
-    mSubjectCN = new QLabel(tr(""));
-    mSubjectO = new QLabel(tr(""));
-    mValidFrom = new QLabel(tr(""));
-    mValidTo = new QLabel(tr(""));
-    mFingerprint = new QLabel(tr(""));
-    mFingerprint->setFont(QFont("DejaVu Sans Mono"));
-    detailContentLayout->addWidget(mSubjectCN);
-    detailContentLayout->addWidget(mSubjectO);
-    detailContentLayout->addWidget(mValidFrom);
-    detailContentLayout->addWidget(mValidTo);
-    detailContentLayout->addWidget(mFingerprint);
-    detailLayout->addLayout(detailLabelLayout);
-    detailLayout->addLayout(detailContentLayout);
-    detailBox->setLayout(detailLayout);
-    detailMainLayout->addWidget(detailBox);
-    detailMainLayout->addStretch(1);
-
-    mainLayout->addWidget(mCertificateList);
-    mainLayout->addLayout(detailMainLayout);
-    this->setLayout(mainLayout);
+    setLayout(&mLayout);
 }
 
 void CertificateListWidget::addCertificate(
@@ -74,34 +27,25 @@
     const QString &installLabel,
     const QString &removeLabel)
 {
-    QListWidgetItem* item = new QListWidgetItem(mCertificateList);
-    item->setData(Qt::UserRole,
-        QVariant::fromValue(certificate));
-    mCertificateList->addItem(item);
     CertificateItemWidget *widget =
-        new CertificateItemWidget(mCertificateList, certificate, state, editable,
+        new CertificateItemWidget(this, certificate, state, editable,
                 installLabel, removeLabel);
     connect(widget, SIGNAL(stateChanged(bool, const Certificate&)),
         this, SLOT(certStateChanged(bool, const Certificate&)));
-    item->setSizeHint(widget->minimumSizeHint());
-    mCertificateList->setItemWidget(item, widget);
+
+    mCertificateWidgets << widget;
+    mLayout.addWidget(widget);
     emit certListChanged(-1);
 }
 
-void CertificateListWidget::addCertificates(const QList<Certificate> &list)
-{
-
-}
-
 void CertificateListWidget::removeCertificate(const Certificate &cert)
 {
-    for (int i = 0; i < mCertificateList->count(); i++) {
-        QListWidgetItem *item = mCertificateList->item(i);
-        CertificateItemWidget *itemWidget =
-            static_cast<CertificateItemWidget*>(mCertificateList->itemWidget(item));
-        if (itemWidget->certificate() == cert) {
-            QListWidgetItem* item = mCertificateList->takeItem(i);
-            delete(item);
+    for (int i = 0; i < mCertificateWidgets.size(); i++) {
+        if (mCertificateWidgets[i]->certificate() == cert) {
+            mLayout.removeWidget(mCertificateWidgets[i]);
+            delete(mCertificateWidgets[i]);
+            mCertificateWidgets.removeAt(i);
+            break;
         }
     }
     emit certListChanged(-1);
@@ -109,29 +53,27 @@
 
 void CertificateListWidget::clear()
 {
-    mCertificateList->clear();
+    foreach (CertificateItemWidget * item, mCertificateWidgets) {
+        mLayout.removeWidget(item);
+        delete item;
+    }
+    mCertificateWidgets.clear();
 }
 
 QStringList CertificateListWidget::certificates()
 {
     QStringList list;
-    for (int i = 0; i < mCertificateList->count(); i++) {
-        QListWidgetItem *item = mCertificateList->item(i);
-        CertificateItemWidget *itemWidget =
-            static_cast<CertificateItemWidget*>(mCertificateList->itemWidget(item));
-        list <<  itemWidget->certificate().base64Line();
+    foreach (CertificateItemWidget * item, mCertificateWidgets) {
+        list <<  item->certificate().base64Line();
     }
     return list;
 }
 
 QStringList CertificateListWidget::selectedCertificates() {
     QStringList list;
-    for (int i = 0; i < mCertificateList->count(); i++) {
-        QListWidgetItem *item = mCertificateList->item(i);
-        CertificateItemWidget *itemWidget =
-            static_cast<CertificateItemWidget*>(mCertificateList->itemWidget(item));
-        if (itemWidget->state()) {
-            list << itemWidget->certificate().base64Line();
+    foreach (CertificateItemWidget * item, mCertificateWidgets) {
+        if (item->state()) {
+            list << item->certificate().base64Line();
         }
     }
     return list;
@@ -139,12 +81,9 @@
 
 QStringList CertificateListWidget::unselectedCertificates() {
     QStringList list;
-    for (int i = 0; i < mCertificateList->count(); i++) {
-        QListWidgetItem *item = mCertificateList->item(i);
-        CertificateItemWidget *itemWidget =
-            static_cast<CertificateItemWidget*>(mCertificateList->itemWidget(item));
-        if (!itemWidget->state()) {
-            list << itemWidget->certificate().base64Line();
+    foreach (CertificateItemWidget * item, mCertificateWidgets) {
+        if (!item->state()) {
+            list << item->certificate().base64Line();
         }
     }
     return list;
@@ -153,65 +92,34 @@
 QList<Certificate> CertificateListWidget::certificateList()
 {
     QList<Certificate> list;
-    for (int i = 0; i < mCertificateList->count(); i++) {
-        QListWidgetItem *item = mCertificateList->item(i);
-        CertificateItemWidget *itemWidget =
-            static_cast<CertificateItemWidget*>(mCertificateList->itemWidget(item));
-        list << itemWidget->certificate();
+    foreach (CertificateItemWidget * item, mCertificateWidgets) {
+        list <<  item->certificate();
     }
-
     return list;
 }
 
 void CertificateListWidget::setCertState(bool state, const Certificate &cert)
 {
-    for (int i = 0; i < mCertificateList->count(); i++) {
-        QListWidgetItem *item = mCertificateList->item(i);
-        CertificateItemWidget *itemWidget =
-            static_cast<CertificateItemWidget*>(mCertificateList->itemWidget(item));
-        if (itemWidget->certificate() == cert &&
-            itemWidget->state() != state) {
-            itemWidget->setState(state);
+    foreach (CertificateItemWidget * item, mCertificateWidgets) {
+        if (item->certificate() == cert &&
+            item->state() != state) {
+            item->setState(state);
         }
     }
 }
 
-void CertificateListWidget::updateDetails(QListWidgetItem *item)
-{
-    if (item == NULL) {
-        return;
-    }
-    Certificate cert = item->data(Qt::UserRole).value<Certificate>();
-    mSubjectCN->setText(cert.subjectCN());
-    mSubjectO->setText(cert.subjectO());
-    mValidFrom->setText(cert.validFrom().toString());
-    mValidTo->setText(cert.validTo().toString());
-    mFingerprint->setText(cert.fingerprint());
-}
 
 void CertificateListWidget::certStateChanged(bool state, const Certificate &cert)
 {
-    int selected = 0;
-    for (int i = 0; i < mCertificateList->count(); i++) {
-        QListWidgetItem *item = mCertificateList->item(i);
-        CertificateItemWidget *itemWidget =
-            static_cast<CertificateItemWidget*>(mCertificateList->itemWidget(item));
-        if (itemWidget->state()) {
-            selected++;
-        }
-    }
-    emit certListChanged(selected);
+    emit certListChanged(-1);
     emit certChanged(state, cert);
 }
 
 int CertificateListWidget::selectedCertCount()
 {
     int selected = 0;
-    for (int i = 0; i < mCertificateList->count(); i++) {
-        QListWidgetItem *item = mCertificateList->item(i);
-        CertificateItemWidget *itemWidget =
-            static_cast<CertificateItemWidget*>(mCertificateList->itemWidget(item));
-        if (itemWidget->state()) {
+    foreach (CertificateItemWidget * item, mCertificateWidgets) {
+        if (item->state()) {
             selected++;
         }
     }
@@ -220,23 +128,10 @@
 
 bool CertificateListWidget::contains(const Certificate &cert)
 {
-    for (int i = 0; i < mCertificateList->count(); i++) {
-        QListWidgetItem *item = mCertificateList->item(i);
-        CertificateItemWidget *itemWidget =
-            static_cast<CertificateItemWidget*>(mCertificateList->itemWidget(item));
-        if (itemWidget->certificate() == cert) {
+    foreach (CertificateItemWidget * item, mCertificateWidgets) {
+        if (item->certificate() == cert) {
             return true;
         }
     }
     return false;
 }
-
-void CertificateListWidget::setSelected(int index)
-{
-    if (index <= 0) {
-        index = 0;
-    }
-    mCertificateList->setFocus();
-    mCertificateList->item(index)->setSelected(true);
-    mCertificateList->setCurrentRow(index);
-}
--- a/ui/certificatelistwidget.h	Fri Jul 04 16:13:40 2014 +0200
+++ b/ui/certificatelistwidget.h	Fri Jul 04 16:15:59 2014 +0200
@@ -12,6 +12,7 @@
 #include <QMainWindow>
 #include <QLabel>
 #include <QListWidget>
+#include <QVBoxLayout>
 
 #include "certificate.h"
 /**
@@ -20,6 +21,8 @@
  * certificate.
  */
 
+class CertificateItemWidget;
+
 Q_DECLARE_METATYPE(Certificate);
 class CertificateListWidget : public QWidget
 {
@@ -31,7 +34,6 @@
                         bool editable = true,
                         const QString& installLabel = tr("install"),
                         const QString& removeLabel = tr("remove"));
-    void addCertificates(const QList<Certificate> &list);
     void removeCertificate(const Certificate &cert);
     void setCertState(bool state, const Certificate &cert);
     void clear();
@@ -41,23 +43,13 @@
     QList<Certificate> certificateList();
     int selectedCertCount();
     bool contains(const Certificate &cert);
-    void setSelected(int index);
-    int selected() { return mCertificateList->currentRow(); }
 
 private:
-    void setupGUI();
 
-    QListWidget *mCertificateList;
-    QLabel *mSubjectCN;
-    QLabel *mSubjectO;
-    QLabel *mIssuerCN;
-    QLabel *mIssuerO;
-    QLabel *mValidFrom;
-    QLabel *mValidTo;
-    QLabel *mFingerprint;
+    QList <CertificateItemWidget*> mCertificateWidgets;
+    QVBoxLayout mLayout;
 
 private slots:
-    void updateDetails(QListWidgetItem *item);
     void certStateChanged(bool state, const Certificate &cert);
 
 signals:
Binary file ui/img/security-high.png has changed
Binary file ui/img/security-low.png has changed
Binary file ui/img/security-medium.png has changed
Binary file ui/img/trash-empty.png has changed
--- a/ui/mainwindow.cpp	Fri Jul 04 16:13:40 2014 +0200
+++ b/ui/mainwindow.cpp	Fri Jul 04 16:15:59 2014 +0200
@@ -34,7 +34,6 @@
 #include "downloader.h"
 #include "helpdialog.h"
 #include "aboutdialog.h"
-#include "certificateitemdelegate.h"
 #include "separatoritemdelegate.h"
 #include "installwrapper.h"
 #include "util.h"
@@ -433,8 +432,9 @@
     connect(mTrayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked()));
 }
 
-QLayout * createInfoPanelLayout()
+QWidget * MainWindow::createInfoWidget()
 {
+    QWidget *theWidget = new QWidget;
     QVBoxLayout *infoPanelLayout = new QVBoxLayout;
     QHBoxLayout *infoHeaderLayout = new QHBoxLayout;
     QVBoxLayout *infoHeaderTextLayout = new QVBoxLayout;
@@ -444,8 +444,8 @@
     QLabel *infoLogo = new QLabel;
     infoLogo->setBackgroundRole(QPalette::Base);
     infoLogo->setPixmap(QPixmap::fromImage(*infoLogoImage));
-    QLabel *infoTitle = new QLabel("<h1>" + QObject::tr("TrustBridge") + "</h1>");
-    QString infoVersion = QObject::tr("Version: ");
+    QLabel *infoTitle = new QLabel("<h1>" + tr("TrustBridge") + "</h1>");
+    QString infoVersion = tr("Version: ");
     infoVersion.append(QApplication::applicationVersion());
     QLabel *appVersion = new QLabel(infoVersion);
     appVersion->setTextInteractionFlags(
@@ -462,25 +462,25 @@
     infoHeaderLayout->addLayout(infoHeaderTextLayout);
     infoHeaderLayout->insertStretch(2, 10);
 
-    QLabel *textDesc = new QLabel(QObject::tr("TrustBridge is a root certificate"
+    QLabel *textDesc = new QLabel(tr("TrustBridge is a root certificate"
         " installer for Windows and Linux."));
     textDesc->setTextInteractionFlags(
         Qt::TextSelectableByMouse |
         Qt::TextSelectableByKeyboard);
-    QLabel *textManage = new QLabel(QObject::tr("The root certificate lists are managed"
+    QLabel *textManage = new QLabel(tr("The root certificate lists are managed"
         " by the German <a href=\"https://www.bsi.bund.de\">"
         "Federal Office for Information Security (BSI)</a>.\n\n"));
     textManage->setTextInteractionFlags(
         Qt::TextBrowserInteraction |
         Qt::TextSelectableByKeyboard);
-    QLabel *textDevel = new QLabel(QObject::tr("The software was developed by the companies"
+    QLabel *textDevel = new QLabel(tr("The software was developed by the companies"
         " <a href=\"http://www.intevation.de\">Intevation GmbH</a> and "
         " <a href=\"http://www.dn-systems.de\">DN-Systems GmbH</a>, <br>"
         " contracted by the German Federal Office for Information Security (BSI).\n\n"));
     textDevel->setTextInteractionFlags(
         Qt::TextBrowserInteraction |
         Qt::TextSelectableByKeyboard);
-    QLabel *textLicense = new QLabel(QObject::tr("TrustBridge is Free Software licensed"
+    QLabel *textLicense = new QLabel(tr("TrustBridge is Free Software licensed"
         " under GNU GPL v2+.\n\nCopyright (C) 2014 by Bundesamt für Sicherheit"
         " in der Informationstechnik"));
     textLicense->setTextInteractionFlags(
@@ -499,7 +499,240 @@
 
     infoPanelLayout->addLayout(infoHeaderLayout);
     infoPanelLayout->addLayout(infoCenterLayout);
-    return infoPanelLayout;
+    theWidget->setLayout(infoPanelLayout);
+
+    return theWidget;
+}
+
+QWidget * MainWindow::createUpdatesWidget()
+{
+    QWidget * theWidget = new QWidget;
+    QVBoxLayout *updatesMainLayout = new QVBoxLayout;
+
+    /* The header */
+    QGridLayout *updatesHeaderLayout = new QGridLayout;
+
+    /* Header 1: Update date and search button */
+    mUpdatesHeader =
+        new QLabel("<h2>" + tr("Certificates unchanged")+ "</h2>");
+    mLastCertUpdate =
+        new QLabel("");
+    mLastCertUpdate->hide();
+    mSoftwareVersionLabel =
+        new QLabel(tr("TrustBridge Version: %1").arg(QApplication::applicationVersion()));
+    const QDateTime lastCheck = mSettings.value("lastUpdateCheck").toDateTime().toLocalTime();
+    if (lastCheck.isValid()) {
+        const QString lastUpdateCheck = QLocale::system().toString(lastCheck, DATETIME_FORMAT);
+        mLastUpdateCheck =
+            new QLabel(tr("Last sucessful update check: %1").arg(lastUpdateCheck));
+    } else {
+        mLastUpdateCheck = new QLabel("");
+        mLastUpdateCheck->hide();
+    }
+    QPushButton *searchUpdates = new QPushButton(" " + tr("Check for updates"));
+    searchUpdates->setIcon(QIcon(":/img/edit-find.png"));
+    connect(searchUpdates, SIGNAL(clicked()), this, SLOT(checkUpdates()));
+
+    // addWidget(*Widget, row, column, rowspan, colspan, [Qt::Alignment])
+    updatesHeaderLayout->addWidget(mUpdatesHeader, 0, 0, 1, 2);
+    updatesHeaderLayout->addWidget(mSoftwareVersionLabel, 1, 0, 1, 1);
+    updatesHeaderLayout->addWidget(mLastUpdateCheck, 2, 0, 1, 1);
+    updatesHeaderLayout->addWidget(mLastCertUpdate, 3, 0, 1, 1);
+    updatesHeaderLayout->addWidget(searchUpdates, 1, 2, 2, 1, Qt::AlignRight);
+    updatesHeaderLayout->setRowMinimumHeight(4, 15);
+
+    /* Header 2: Action text and buttons */
+    mUpdatesTip =
+        new QLabel(tr("There are currently no changes for your certificate stores."));
+    mUpdatesTip->setWordWrap(true);
+    QHBoxLayout *updatesHeaderActionButtonLayout = new QHBoxLayout;
+    mQuitButton = new QPushButton(" " + tr("Quit without saving"));
+    mQuitButton->setIcon(QIcon(":/img/application-exit.png"));
+    mQuitButton->setFixedHeight(30);
+
+    mInstallButton = new QPushButton(" " + tr("Install certificates again"));
+    mInstallButton->setFixedHeight(30);
+#ifdef Q_OS_WIN
+    if (is_admin()) {
+        QIcon uacShield = QApplication::style()->standardIcon(QStyle::SP_VistaShield);
+        mInstallButton->setIcon(uacShield);
+    }
+#else
+    mInstallButton->setIcon(QIcon(":/img/view-refresh_16px.png"));
+#endif
+    connect(mQuitButton, SIGNAL(clicked()), this, SLOT(closeApp()));
+    connect(mInstallButton, SIGNAL(clicked()), this, SLOT(checkAndInstallCerts()));
+
+    // addWidget(*Widget, row, column, rowspan, colspan)
+    updatesHeaderLayout->addWidget(mUpdatesTip, 5, 0, 1, 2);
+    updatesHeaderActionButtonLayout->addWidget(mInstallButton);
+    updatesHeaderActionButtonLayout->addWidget(mQuitButton);
+    updatesHeaderLayout->addLayout(updatesHeaderActionButtonLayout, 6, 0, 1, 1);
+    updatesHeaderLayout->setRowMinimumHeight(7, 10);
+
+    /* The central panels. */
+    QScrollArea *centralScrollArea = new QScrollArea;
+    QVBoxLayout *updatesCenterLayout = new QVBoxLayout;
+    QHBoxLayout *updatesNewLayout = new QHBoxLayout;
+    QHBoxLayout *updatesRemoveLayout = new QHBoxLayout;
+    QHBoxLayout *updatesManualLayout = new QHBoxLayout;
+    mUpdatesNewCertificates =
+        new QLabel("<h3>" +
+            tr("Install new trusted certificates (%1/%2)").arg(0).arg(0) +
+            "</h3>");
+    mUpdatesDetailsNew = new QPushButton(tr("Show details"));
+    connect(mUpdatesDetailsNew,
+        SIGNAL(clicked()),
+        this,
+        SLOT(toggleUpdatesNew()));
+    updatesNewLayout->addWidget(mUpdatesNewCertificates);
+    updatesNewLayout->addStretch(1);
+    updatesNewLayout->addWidget(mUpdatesDetailsNew);
+    mUpdatesNew = new CertificateListWidget(this);
+    connect(mUpdatesNew, SIGNAL(certListChanged(int)),
+        this, SLOT(listChanged(int)));
+    mUpdatesNew->hide();
+
+    mUpdatesRemoveCertificates =
+        new QLabel("<h3>" +
+            tr("Remove revoked certificates (%1/%2)").arg(0).arg(0) +
+            "</h3>");
+    mUpdatesDetailsRemove = new QPushButton(tr("Show details"));
+    connect(mUpdatesDetailsRemove,
+        SIGNAL(clicked()),
+        this,
+        SLOT(toggleUpdatesRemove()));
+    updatesRemoveLayout->addWidget(mUpdatesRemoveCertificates);
+    updatesRemoveLayout->addWidget(mUpdatesDetailsRemove);
+    mUpdatesRemove = new CertificateListWidget(this);
+    connect(mUpdatesRemove, SIGNAL(certListChanged(int)),
+        this, SLOT(listChanged(int)));
+    mUpdatesRemove->hide();
+
+    mUpdatesManualCertificates =
+        new QLabel("<h3>" +
+            tr("Manually changed certificates (%1)").arg(0) +
+            "</h3>");
+    mUpdatesDetailsManual = new QPushButton(tr("Show details"));
+    connect(mUpdatesDetailsManual,
+        SIGNAL(clicked()),
+        this,
+        SLOT(toggleUpdatesManual()));
+    mUpdatesDetailsManual->hide();
+    mUpdatesManualCertificates->hide();
+    updatesManualLayout->addWidget(mUpdatesManualCertificates);
+    updatesManualLayout->addWidget(mUpdatesDetailsManual);
+    mUpdatesManual = new CertificateListWidget(this);
+    mUpdatesManual->hide();
+    connect(mUpdatesManual, SIGNAL(certChanged(bool, const Certificate&)),
+        this, SLOT(removeFromManual(bool, const Certificate&)));
+    connect(mUpdatesManual, SIGNAL(certListChanged(int)),
+        this, SLOT(listChanged(int)));
+
+    updatesNewLayout->setAlignment(Qt::AlignTop);
+    updatesRemoveLayout->setAlignment(Qt::AlignTop);
+    updatesManualLayout->setAlignment(Qt::AlignTop);
+    updatesCenterLayout->addLayout(updatesNewLayout);
+    updatesCenterLayout->addWidget(mUpdatesNew);
+    updatesCenterLayout->addLayout(updatesRemoveLayout);
+    updatesCenterLayout->addWidget(mUpdatesRemove);
+    updatesCenterLayout->addLayout(updatesManualLayout);
+    updatesCenterLayout->addWidget(mUpdatesManual);
+
+    QWidget *dummyWidget = new QWidget;
+    dummyWidget->setLayout(updatesCenterLayout);
+    centralScrollArea->setWidgetResizable(true);
+    centralScrollArea->setWidget(dummyWidget);
+    centralScrollArea->setFrameShape(QFrame::NoFrame);
+    centralScrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+    updatesMainLayout->addLayout(updatesHeaderLayout);
+    updatesMainLayout->addWidget(centralScrollArea);
+    updatesCenterLayout->addSpacerItem(new QSpacerItem(0, 0,
+                QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
+    theWidget->setLayout(updatesMainLayout);
+    return theWidget;
+}
+
+
+QWidget *MainWindow::createInstallWidget()
+{
+    QWidget *theWidget = new QWidget;
+    QScrollArea *scrollArea = new QScrollArea;
+    QVBoxLayout *installPanelLayout = new QVBoxLayout;
+    QVBoxLayout *installHeaderLayout = new QVBoxLayout;
+    QVBoxLayout *installCenterLayout = new QVBoxLayout;
+
+    QLabel *installHeaderLabel =
+        new QLabel("<h2>" + tr("Trusted certificates") + "</h2>");
+    QLabel *installHeaderText = new QLabel(tr("The following list of trusted root"
+        " certificates is managed by the BSI. The BSI validates independently the"
+        " authenticity, security and actuality of these certificates."));
+    installHeaderText->setWordWrap(true);
+    installHeaderLayout->addWidget(installHeaderLabel);
+    installHeaderLayout->addWidget(installHeaderText);
+
+    QLabel *installCenterText = new QLabel(tr("Please choose the certificates"
+        " you want to trust or untrust. TrustBridge will install these certificates for your"
+        " secure communication for email and internet."));
+    installCenterText->setWordWrap(true);
+    installCenterLayout->addWidget(installCenterText);
+
+    installPanelLayout->addLayout(installHeaderLayout);
+    installPanelLayout->addLayout(installCenterLayout);
+
+    mInstallList = new CertificateListWidget(this);
+    connect(mInstallList, SIGNAL(certChanged(bool, const Certificate&)),
+        this, SLOT(toggleInManual(bool, const Certificate&)));
+
+    scrollArea->setWidgetResizable(true);
+    scrollArea->setWidget(mInstallList);
+    scrollArea->setFrameShape(QFrame::NoFrame);
+
+    installPanelLayout->addWidget(scrollArea);
+
+    theWidget->setLayout(installPanelLayout);
+
+    return theWidget;
+}
+
+QWidget *MainWindow::createRemoveWidget()
+{
+    QWidget * theWidget = new QWidget;
+    QScrollArea *scrollArea = new QScrollArea;
+    QVBoxLayout *removePanelLayout = new QVBoxLayout;
+    QVBoxLayout *removeHeaderLayout = new QVBoxLayout;
+    QVBoxLayout *removeCenterLayout = new QVBoxLayout;
+
+    QLabel *removeHeaderLabel =
+        new QLabel("<h2>" + tr("Revoked certificates") + "</h2>");
+    QLabel *removeHeaderText = new QLabel(tr("Certificates can be corrupted"
+        " or stolen and misused in many ways. Therefore the BSI recommends"
+        " to remove all revoked certificates from your system."));
+    removeHeaderText->setWordWrap(true);
+    removeHeaderLayout->addWidget(removeHeaderLabel);
+    removeHeaderLayout->addWidget(removeHeaderText);
+
+    QLabel *removeCenterText = new QLabel(tr("The follwing unsecure certificates were"
+        " revoked by the BSI. Already uninstalled certificates cannot be reinstalled."
+        " It is recommended that you select all certificates to uninstall if you still"
+        " have revoked certificates installed."));
+    removeCenterText->setWordWrap(true);
+    removeCenterLayout->addWidget(removeCenterText);
+    mRemoveList = new CertificateListWidget(this);
+    connect(mRemoveList, SIGNAL(certChanged(bool, const Certificate&)),
+        this, SLOT(toggleInManual(bool, const Certificate&)));
+
+    removePanelLayout->addLayout(removeHeaderLayout);
+    removePanelLayout->addLayout(removeCenterLayout);
+
+    scrollArea->setWidgetResizable(true);
+    scrollArea->setWidget(mRemoveList);
+    scrollArea->setFrameShape(QFrame::NoFrame);
+    removePanelLayout->addWidget(scrollArea);
+    theWidget->setLayout(removePanelLayout);
+
+    return theWidget;
 }
 
 void MainWindow::setupGUI()
@@ -592,239 +825,34 @@
     buttonBarLayout->insertStretch(3, 10);
     buttonBarLayout->addWidget(infoButton);
 
-    /********************************
-     * The main pages.
-     ********************************/
-
-    /********************************
-     * The updates page.
-     ********************************/
-    QVBoxLayout *updatesMainLayout = new QVBoxLayout;
-    mUpdatesPanel = new QScrollArea;
-    QScrollArea *updatesContent = new QScrollArea;
-    mUpdatesWidget = new QWidget;
-
-    /* The header */
-    QGridLayout *updatesHeaderLayout = new QGridLayout;
-
-    /* Header 1: Update date and search button */
-    mUpdatesHeader =
-        new QLabel("<h2>" + tr("Certificates unchanged")+ "</h2>");
-    mLastCertUpdate =
-        new QLabel("");
-    mLastCertUpdate->hide();
-    mSoftwareVersionLabel =
-        new QLabel(tr("TrustBridge Version: %1").arg(QApplication::applicationVersion()));
-    const QDateTime lastCheck = mSettings.value("lastUpdateCheck").toDateTime().toLocalTime();
-    if (lastCheck.isValid()) {
-        const QString lastUpdateCheck = QLocale::system().toString(lastCheck, DATETIME_FORMAT);
-        mLastUpdateCheck =
-            new QLabel(tr("Last sucessful update check: %1").arg(lastUpdateCheck));
-    } else {
-        mLastUpdateCheck = new QLabel("");
-        mLastUpdateCheck->hide();
-    }
-    QPushButton *searchUpdates = new QPushButton(" " + tr("Check for updates"));
-    searchUpdates->setIcon(QIcon(":/img/edit-find.png"));
-    connect(searchUpdates, SIGNAL(clicked()), this, SLOT(checkUpdates()));
-
-    // addWidget(*Widget, row, column, rowspan, colspan, [Qt::Alignment])
-    updatesHeaderLayout->addWidget(mUpdatesHeader, 0, 0, 1, 2);
-    updatesHeaderLayout->addWidget(mSoftwareVersionLabel, 1, 0, 1, 1);
-    updatesHeaderLayout->addWidget(mLastUpdateCheck, 2, 0, 1, 1);
-    updatesHeaderLayout->addWidget(mLastCertUpdate, 3, 0, 1, 1);
-    updatesHeaderLayout->addWidget(searchUpdates, 1, 2, 2, 1, Qt::AlignRight);
-    updatesHeaderLayout->setRowMinimumHeight(4, 15);
-
-    /* Header 2: Action text and buttons */
-    mUpdatesTip =
-        new QLabel(tr("There are currently no changes for your certificate stores."));
-    mUpdatesTip->setWordWrap(true);
-    QHBoxLayout *updatesHeaderActionButtonLayout = new QHBoxLayout;
-    mQuitButton = new QPushButton(" " + tr("Quit without saving"));
-    mQuitButton->setIcon(QIcon(":/img/application-exit.png"));
-    mQuitButton->setFixedHeight(30);
-
-    mInstallButton = new QPushButton(" " + tr("Install certificates again"));
-    mInstallButton->setFixedHeight(30);
-#ifdef Q_OS_WIN
-    if (is_admin()) {
-        QIcon uacShield = QApplication::style()->standardIcon(QStyle::SP_VistaShield);
-        mInstallButton->setIcon(uacShield);
-    }
-#else
-    mInstallButton->setIcon(QIcon(":/img/view-refresh_16px.png"));
-#endif
-    connect(mQuitButton, SIGNAL(clicked()), this, SLOT(closeApp()));
-    connect(mInstallButton, SIGNAL(clicked()), this, SLOT(checkAndInstallCerts()));
-
-    // addWidget(*Widget, row, column, rowspan, colspan)
-    updatesHeaderLayout->addWidget(mUpdatesTip, 5, 0, 1, 2);
-    updatesHeaderActionButtonLayout->addWidget(mInstallButton);
-    updatesHeaderActionButtonLayout->addWidget(mQuitButton);
-    updatesHeaderLayout->addLayout(updatesHeaderActionButtonLayout, 6, 0, 1, 1);
-    updatesHeaderLayout->setRowMinimumHeight(7, 10);
+    /* The main pages.*/
 
-    /* The central panels. */
-    QVBoxLayout *updatesCenterLayout = new QVBoxLayout;
-    QHBoxLayout *updatesNewLayout = new QHBoxLayout;
-    QHBoxLayout *updatesRemoveLayout = new QHBoxLayout;
-    QHBoxLayout *updatesManualLayout = new QHBoxLayout;
-    mUpdatesNewCertificates =
-        new QLabel("<h3>" +
-            tr("Install new trusted certificates (%1/%2)").arg(0).arg(0) +
-            "</h3>");
-    mUpdatesDetailsNew = new QPushButton(tr("Show details"));
-    connect(mUpdatesDetailsNew,
-        SIGNAL(clicked()),
-        this,
-        SLOT(toggleUpdatesNew()));
-    updatesNewLayout->addWidget(mUpdatesNewCertificates);
-    updatesNewLayout->addWidget(mUpdatesDetailsNew);
-    updatesNewLayout->insertStretch(2, 10);
-    mUpdatesNew = new CertificateListWidget(this);
-    connect(mUpdatesNew, SIGNAL(certListChanged(int)),
-        this, SLOT(listChanged(int)));
-    mUpdatesNew->hide();
-
-    mUpdatesRemoveCertificates =
-        new QLabel("<h3>" +
-            tr("Remove revoked certificates (%1/%2)").arg(0).arg(0) +
-            "</h3>");
-    mUpdatesDetailsRemove = new QPushButton(tr("Show details"));
-    connect(mUpdatesDetailsRemove,
-        SIGNAL(clicked()),
-        this,
-        SLOT(toggleUpdatesRemove()));
-    updatesRemoveLayout->addWidget(mUpdatesRemoveCertificates);
-    updatesRemoveLayout->addWidget(mUpdatesDetailsRemove);
-    updatesRemoveLayout->insertStretch(2, 10);
-    mUpdatesRemove = new CertificateListWidget(this);
-    connect(mUpdatesRemove, SIGNAL(certListChanged(int)),
-        this, SLOT(listChanged(int)));
-    mUpdatesRemove->hide();
+    /* The updates page. */
+    mUpdatesWidget = createUpdatesWidget();
 
-    mUpdatesManualCertificates =
-        new QLabel("<h3>" +
-            tr("Manually changed certificates (%1)").arg(0) +
-            "</h3>");
-    mUpdatesDetailsManual = new QPushButton(tr("Show details"));
-    connect(mUpdatesDetailsManual,
-        SIGNAL(clicked()),
-        this,
-        SLOT(toggleUpdatesManual()));
-    mUpdatesDetailsManual->hide();
-    mUpdatesManualCertificates->hide();
-    updatesManualLayout->addWidget(mUpdatesManualCertificates);
-    updatesManualLayout->addWidget(mUpdatesDetailsManual);
-    updatesManualLayout->insertStretch(2, 10);
-    mUpdatesManual = new CertificateListWidget(this);
-    mUpdatesManual->hide();
-    connect(mUpdatesManual, SIGNAL(certChanged(bool, const Certificate&)),
-        this, SLOT(removeFromManual(bool, const Certificate&)));
-    connect(mUpdatesManual, SIGNAL(certListChanged(int)),
-        this, SLOT(listChanged(int)));
-
-    updatesNewLayout->setAlignment(Qt::AlignTop);
-    updatesRemoveLayout->setAlignment(Qt::AlignTop);
-    updatesManualLayout->setAlignment(Qt::AlignTop);
-    updatesCenterLayout->addLayout(updatesNewLayout);
-    updatesCenterLayout->addWidget(mUpdatesNew);
-    updatesCenterLayout->addLayout(updatesRemoveLayout);
-    updatesCenterLayout->addWidget(mUpdatesRemove);
-    updatesCenterLayout->addLayout(updatesManualLayout);
-    updatesCenterLayout->addWidget(mUpdatesManual);
-    updatesCenterLayout->addStretch(1);
-
-    updatesCenterLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
-    mUpdatesWidget->setLayout(updatesCenterLayout);
-    updatesContent->setWidget(mUpdatesWidget);
-
-    updatesMainLayout->addLayout(updatesHeaderLayout);
-    updatesMainLayout->addWidget(updatesContent);
-    mUpdatesPanel->setLayout(updatesMainLayout);
-
-    /*********************************
-     * Panel for trusted certificates.
-     *********************************/
-    mInstallPanel = new QScrollArea;
-
-    QVBoxLayout *installPanelLayout = new QVBoxLayout;
-    QVBoxLayout *installHeaderLayout = new QVBoxLayout;
-    QVBoxLayout *installCenterLayout = new QVBoxLayout;
-
-    QLabel *installHeaderLabel =
-        new QLabel("<h2>" + tr("Trusted certificates") + "</h2>");
-    QLabel *installHeaderText = new QLabel(tr("The following list of trusted root"
-        " certificates is managed by the BSI. The BSI validates independently the"
-        " authenticity, security and actuality of these certificates."));
-    installHeaderText->setWordWrap(true);
-    installHeaderLayout->addWidget(installHeaderLabel);
-    installHeaderLayout->addWidget(installHeaderText);
-
-    QLabel *installCenterText = new QLabel(tr("Please choose the certificates"
-        " you want to trust or untrust. TrustBridge will install these certificates for your"
-        " secure communication for email and internet."));
-    installCenterText->setWordWrap(true);
-    installCenterLayout->addWidget(installCenterText);
-    mInstallList = new CertificateListWidget(this);
-    connect(mInstallList, SIGNAL(certChanged(bool, const Certificate&)),
-        this, SLOT(toggleInManual(bool, const Certificate&)));
-
-    installPanelLayout->addLayout(installHeaderLayout);
-    installPanelLayout->addLayout(installCenterLayout);
-    installPanelLayout->addWidget(mInstallList);
-    mInstallPanel->setLayout(installPanelLayout);
+    /* Install (trusted certs) Page */
+    mInstallWidget = createInstallWidget();
 
     /**********************************
-     * Panel for certificates to be removed.
+     * Page for certificates to be removed.
      **********************************/
-    mRemovePanel = new QScrollArea;
-    QVBoxLayout *removePanelLayout = new QVBoxLayout;
-    QVBoxLayout *removeHeaderLayout = new QVBoxLayout;
-    QVBoxLayout *removeCenterLayout = new QVBoxLayout;
-
-    QLabel *removeHeaderLabel =
-        new QLabel("<h2>" + tr("Revoked certificates") + "</h2>");
-    QLabel *removeHeaderText = new QLabel(tr("Certificates can be corrupted"
-        " or stolen and misused in many ways. Therefore the BSI recommends"
-        " to remove all revoked certificates from your system."));
-    removeHeaderText->setWordWrap(true);
-    removeHeaderLayout->addWidget(removeHeaderLabel);
-    removeHeaderLayout->addWidget(removeHeaderText);
-
-    QLabel *removeCenterText = new QLabel(tr("The follwing unsecure certificates were"
-        " revoked by the BSI. Already uninstalled certificates cannot be reinstalled."
-        " It is recommended that you select all certificates to uninstall if you still"
-        " have revoked certificates installed."));
-    removeCenterText->setWordWrap(true);
-    removeCenterLayout->addWidget(removeCenterText);
-    mRemoveList = new CertificateListWidget(this);
-    connect(mRemoveList, SIGNAL(certChanged(bool, const Certificate&)),
-        this, SLOT(toggleInManual(bool, const Certificate&)));
-
-    removePanelLayout->addLayout(removeHeaderLayout);
-    removePanelLayout->addLayout(removeCenterLayout);
-    removePanelLayout->addWidget(mRemoveList);
-    mRemovePanel->setLayout(removePanelLayout);
+    mRemoveWidget = createRemoveWidget();
 
     /**********************************
-     * The info panel.
+     * The info page.
      **********************************/
-    mInfoPanel = new QScrollArea;
-    mInfoPanel->setLayout(createInfoPanelLayout());
-
+    mInfoWidget = createInfoWidget();
 
     /********************************
      * The main layout for pages.
      ********************************/
-    mInstallPanel->hide();
-    mRemovePanel->hide();
-    mInfoPanel->hide();
-    containerLayout->addWidget(mUpdatesPanel);
-    containerLayout->addWidget(mInstallPanel);
-    containerLayout->addWidget(mRemovePanel);
-    containerLayout->addWidget(mInfoPanel);
+    mInstallWidget->hide();
+    mRemoveWidget->hide();
+    mInfoWidget->hide();
+    containerLayout->addWidget(mUpdatesWidget);
+    containerLayout->addWidget(mInstallWidget);
+    containerLayout->addWidget(mRemoveWidget);
+    containerLayout->addWidget(mInfoWidget);
 
     centerLayout->addLayout(buttonBarLayout);
     centerLayout->addLayout(containerLayout);
@@ -930,6 +958,7 @@
             if (cert.isInstallCert()) {
                 oldInstallCerts.append(cert);
                 mInstallList->addCertificate(cert, state);
+                    qDebug() << "Added cert to installList";
             }
             else {
                 oldRemoveCerts.append(cert);
@@ -1159,16 +1188,16 @@
 
 void MainWindow::togglePages(int button)
 {
-    mUpdatesPanel->hide();
-    mInstallPanel->hide();
-    mRemovePanel->hide();
-    mInfoPanel->hide();
+    mUpdatesWidget->hide();
+    mInstallWidget->hide();
+    mRemoveWidget->hide();
+    mInfoWidget->hide();
     switch(button) {
-    case 0: mUpdatesPanel->show(); break;
-    case 1: mInstallPanel->show(); break;
-    case 2: mRemovePanel->show(); break;
-    case 3: mInfoPanel->show(); break;
-    default: mUpdatesPanel->show(); break;
+    case 0: mUpdatesWidget->show(); break;
+    case 1: mInstallWidget->show(); break;
+    case 2: mRemoveWidget->show(); break;
+    case 3: mInfoWidget->show(); break;
+    default: mUpdatesWidget->show(); break;
     }
     return;
 }
@@ -1177,13 +1206,10 @@
     if (!mUpdatesNew->isVisible()) {
         mUpdatesDetailsNew->setText(tr("Hide details"));
         mUpdatesNew->show();
-        mUpdatesNew->setSelected(mUpdatesNew->selected());
     }
     else {
         mUpdatesNew->hide();
         mUpdatesDetailsNew->setText(tr("Show details"));
-        QSize old = mUpdatesWidget->size();
-        mUpdatesWidget->resize(old.width(), old.height() - mUpdatesNew->height());
     }
 }
 
@@ -1191,13 +1217,10 @@
     if (!mUpdatesRemove->isVisible()) {
         mUpdatesDetailsRemove->setText(tr("Hide details"));
         mUpdatesRemove->show();
-        mUpdatesRemove->setSelected(0);
     }
     else {
         mUpdatesRemove->hide();
         mUpdatesDetailsRemove->setText(tr("Show details"));
-        QSize old = mUpdatesWidget->size();
-        mUpdatesWidget->resize(old.width(), old.height() - mUpdatesRemove->height());
     }
 }
 
@@ -1205,13 +1228,10 @@
     if (!mUpdatesManual->isVisible()) {
         mUpdatesDetailsManual->setText(tr("Hide details"));
         mUpdatesManual->show();
-        mUpdatesManual->setSelected(0);
     }
     else {
         mUpdatesDetailsManual->setText(tr("Show details"));
         mUpdatesManual->hide();
-        QSize old = mUpdatesWidget->size();
-        mUpdatesWidget->resize(old.width(), old.height() - mUpdatesManual->height());
     }
 }
 
--- a/ui/mainwindow.h	Fri Jul 04 16:13:40 2014 +0200
+++ b/ui/mainwindow.h	Fri Jul 04 16:15:59 2014 +0200
@@ -194,8 +194,21 @@
 
     void createTrayIcon();
     void createActions();
+    void loadCertificateList();
+
+    /** @brief UI setup */
     void setupGUI();
-    void loadCertificateList();
+
+    /** @brief create and set up the info widget (accessible via button panel) */
+    QWidget *createInfoWidget();
+    /** @brief create and set up the updates widget (accessible via button panel) */
+    QWidget *createUpdatesWidget();
+    /** @brief create and set up the certifcates to install widget
+     * (accessible via button panel) */
+    QWidget *createInstallWidget();
+    /** @brief create and set up the certifcates to remove widget
+     * (accessible via button panel) */
+    QWidget *createRemoveWidget();
 
     /* Are we running in tray mode ?*/
     const bool mTrayMode;
@@ -227,11 +240,10 @@
     QLabel *mNewListDate;
 
     QButtonGroup *mButtonGroup;
-    QScrollArea *mUpdatesPanel;
     QWidget *mUpdatesWidget;
-    QScrollArea *mInstallPanel;
-    QScrollArea *mRemovePanel;
-    QScrollArea *mInfoPanel;
+    QWidget *mInstallWidget;
+    QWidget *mRemoveWidget;
+    QWidget *mInfoWidget;
 
     QLabel *mUpdatesHeader;
     QLabel *mLastCertUpdate;
@@ -242,6 +254,10 @@
     QLabel *mUpdatesManualCertificates;
     QLabel *mUpdatesTip;
 
+    /* These are a bit of a pattern break, they should
+     * be accessed over the according page widgets.
+     *
+     * They are initialized in the create*widget functions.*/
     CertificateListWidget *mUpdatesNew;
     CertificateListWidget *mUpdatesRemove;
     CertificateListWidget *mUpdatesManual;
--- a/ui/textoverlaybutton.cpp	Fri Jul 04 16:13:40 2014 +0200
+++ b/ui/textoverlaybutton.cpp	Fri Jul 04 16:15:59 2014 +0200
@@ -18,7 +18,7 @@
 void TextOverlayButton::paintEvent(QPaintEvent *e)
 {
     QToolButton::paintEvent(e);
-    if (mOverlay == "0") {
+    if (mOverlay == "0" || mOverlay.isEmpty()) {
         return;
     }
     QPainter painter(this);

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