diff --git a/src/newcertificatewizard/newcertificatewizard.cpp b/src/newcertificatewizard/newcertificatewizard.cpp
index 4b523d1c4..37839dfb7 100644
--- a/src/newcertificatewizard/newcertificatewizard.cpp
+++ b/src/newcertificatewizard/newcertificatewizard.cpp
@@ -1,2046 +1,2054 @@
 /* -*- mode: c++; c-basic-offset:4 -*-
     newcertificatewizard/newcertificatewizard.cpp
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
 
     SPDX-FileCopyrightText: 2016, 2017 Bundesamt für Sicherheit in der Informationstechnik
     SPDX-FileContributor: Intevation GmbH
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 #include <config-kleopatra.h>
 
 #include "newcertificatewizard.h"
 
 #include <settings.h>
 
 #include "ui_chooseprotocolpage.h"
 #include "ui_enterdetailspage.h"
 #include "ui_keycreationpage.h"
 #include "ui_resultpage.h"
 
 #include "ui_advancedsettingsdialog.h"
 
 #ifdef QGPGME_SUPPORTS_SECRET_KEY_EXPORT
 # include "commands/exportsecretkeycommand.h"
 #else
 # include "commands/exportsecretkeycommand_old.h"
 #endif
 #include "commands/exportopenpgpcertstoservercommand.h"
 #include "commands/exportcertificatecommand.h"
 
 #include "kleopatraapplication.h"
 
 #include "utils/validation.h"
 #include "utils/filedialog.h"
 #include "utils/keyparameters.h"
 #include "utils/userinfo.h"
 
 #include <Libkleo/Compat>
 #include <Libkleo/GnuPG>
 #include <Libkleo/Stl_Util>
 #include <Libkleo/Dn>
 #include <Libkleo/OidMap>
 #include <Libkleo/KeyCache>
 #include <Libkleo/Formatting>
 
 #include <QGpgME/KeyGenerationJob>
 #include <QGpgME/Protocol>
 #include <QGpgME/CryptoConfig>
 
 #include <gpgme++/global.h>
 #include <gpgme++/keygenerationresult.h>
 #include <gpgme++/context.h>
 #include <gpgme++/interfaces/passphraseprovider.h>
 
 #include <KConfigGroup>
 #include <KLocalizedString>
 #include "kleopatra_debug.h"
 #include <QTemporaryDir>
 #include <KMessageBox>
 #include <QIcon>
 
 #include <QRegExpValidator>
 #include <QLineEdit>
 #include <QMetaProperty>
 #include <QDir>
 #include <QFile>
 #include <QUrl>
 #include <QDesktopServices>
 #include <QUrlQuery>
 
 #include <algorithm>
 
 #include <KSharedConfig>
 #include <QLocale>
 
 using namespace Kleo;
 using namespace Kleo::NewCertificateUi;
 using namespace Kleo::Commands;
 using namespace GpgME;
 #ifndef QGPGME_SUPPORTS_SECRET_KEY_EXPORT
 using Kleo::Commands::Compat::ExportSecretKeyCommand;
 #endif
 
 static const char RSA_KEYSIZES_ENTRY[] = "RSAKeySizes";
 static const char DSA_KEYSIZES_ENTRY[] = "DSAKeySizes";
 static const char ELG_KEYSIZES_ENTRY[] = "ELGKeySizes";
 
 static const char RSA_KEYSIZE_LABELS_ENTRY[] = "RSAKeySizeLabels";
 static const char DSA_KEYSIZE_LABELS_ENTRY[] = "DSAKeySizeLabels";
 static const char ELG_KEYSIZE_LABELS_ENTRY[] = "ELGKeySizeLabels";
 
 static const char PGP_KEY_TYPE_ENTRY[] = "PGPKeyType";
 static const char CMS_KEY_TYPE_ENTRY[] = "CMSKeyType";
 
 // This should come from gpgme in the future
 // For now we only support the basic 2.1 curves and check
 // for GnuPG 2.1. The whole subkey / usage generation needs
 // new api and a reworked dialog. (ah 10.3.16)
 // EDDSA should be supported, too.
 static const QStringList curveNames {
     { QStringLiteral("brainpoolP256r1") },
     { QStringLiteral("brainpoolP384r1") },
     { QStringLiteral("brainpoolP512r1") },
     { QStringLiteral("NIST P-256") },
     { QStringLiteral("NIST P-384") },
     { QStringLiteral("NIST P-521") },
 };
 
 namespace
 {
 
 class EmptyPassphraseProvider: public PassphraseProvider
 {
 public:
     char *getPassphrase(const char * /*useridHint*/, const char * /*description*/,
                         bool /*previousWasBad*/, bool &/*canceled*/) Q_DECL_OVERRIDE
     {
         return gpgrt_strdup ("");
     }
 };
 
 static void set_tab_order(const QList<QWidget *> &wl)
 {
     kdtools::for_each_adjacent_pair(wl.begin(), wl.end(), &QWidget::setTabOrder);
 }
 
 enum KeyAlgo { RSA, DSA, ELG, ECDSA, ECDH, EDDSA };
 
 static bool is_algo(Subkey::PubkeyAlgo algo, KeyAlgo what)
 {
     switch (algo) {
         case Subkey::AlgoRSA:
         case Subkey::AlgoRSA_E:
         case Subkey::AlgoRSA_S:
             return what == RSA;
         case Subkey::AlgoELG_E:
         case Subkey::AlgoELG:
             return what == ELG;
         case Subkey::AlgoDSA:
             return what == DSA;
         case Subkey::AlgoECDSA:
             return what == ECDSA;
         case Subkey::AlgoECDH:
             return what == ECDH;
         case Subkey::AlgoEDDSA:
             return what == EDDSA;
         default:
             break;
     }
     return false;
 }
 
 static bool is_rsa(unsigned int algo)
 {
     return is_algo(static_cast<Subkey::PubkeyAlgo>(algo), RSA);
 }
 
 static bool is_dsa(unsigned int algo)
 {
     return is_algo(static_cast<Subkey::PubkeyAlgo>(algo), DSA);
 }
 
 static bool is_elg(unsigned int algo)
 {
     return is_algo(static_cast<Subkey::PubkeyAlgo>(algo), ELG);
 }
 
 static bool is_ecdsa(unsigned int algo)
 {
     return is_algo(static_cast<Subkey::PubkeyAlgo>(algo), ECDSA);
 }
 
 static bool is_eddsa(unsigned int algo)
 {
     return is_algo(static_cast<Subkey::PubkeyAlgo>(algo), EDDSA);
 }
 
 static bool is_ecdh(unsigned int algo)
 {
     return is_algo(static_cast<Subkey::PubkeyAlgo>(algo), ECDH);
 }
 
 static void force_set_checked(QAbstractButton *b, bool on)
 {
     // work around Qt bug (tested: 4.1.4, 4.2.3, 4.3.4)
     const bool autoExclusive = b->autoExclusive();
     b->setAutoExclusive(false);
     b->setChecked(b->isEnabled() && on);
     b->setAutoExclusive(autoExclusive);
 }
 
 static void set_keysize(QComboBox *cb, unsigned int strength)
 {
     if (!cb) {
         return;
     }
     const int idx = cb->findData(static_cast<int>(strength));
     cb->setCurrentIndex(idx);
 }
 
 static unsigned int get_keysize(const QComboBox *cb)
 {
     if (!cb) {
         return 0;
     }
     const int idx = cb->currentIndex();
     if (idx < 0) {
         return 0;
     }
     return cb->itemData(idx).toInt();
 }
 
 static void set_curve(QComboBox *cb, const QString &curve)
 {
     if (!cb) {
         return;
     }
     const int idx = cb->findText(curve, Qt::MatchFixedString);
     if (idx < 0) {
         // Can't happen as we don't have them configurable.
         qCWarning(KLEOPATRA_LOG) << "curve " << curve << " not allowed";
     }
     cb->setCurrentIndex(idx);
 }
 
 static QString get_curve(const QComboBox *cb)
 {
     if (!cb) {
         return QString();
     }
     return cb->currentText();
 }
 
 // Extract the algo information from default_pubkey_algo format
 //
 // and put it into the return values size, algo and curve.
 //
 // Values look like:
 // RSA-2048
 // rsa2048/cert,sign+rsa2048/enc
 // brainpoolP256r1+brainpoolP256r1
 static void parseAlgoString(const QString &algoString, int *size, Subkey::PubkeyAlgo *algo, QString &curve)
 {
     const auto split = algoString.split(QLatin1Char('/'));
     bool isEncrypt = split.size() == 2 && split[1].contains(QLatin1String("enc"));
 
     // Normalize
     const auto lowered = split[0].toLower().remove(QLatin1Char('-'));
     if (!algo || !size) {
         return;
     }
     *algo = Subkey::AlgoUnknown;
     if (lowered.startsWith(QLatin1String("rsa"))) {
         *algo = Subkey::AlgoRSA;
     } else if (lowered.startsWith(QLatin1String("dsa"))) {
         *algo = Subkey::AlgoDSA;
     } else if (lowered.startsWith(QLatin1String("elg"))) {
         *algo = Subkey::AlgoELG;
     }
 
     if (*algo != Subkey::AlgoUnknown) {
         bool ok;
         *size = lowered.rightRef(lowered.size() - 3).toInt(&ok);
         if (!ok) {
             qCWarning(KLEOPATRA_LOG) << "Could not extract size from: " << lowered;
             *size = 3072;
         }
         return;
     }
 
     // Now the ECC Algorithms
     if (lowered.startsWith(QLatin1String("ed25519"))) {
         // Special handling for this as technically
         // this is a cv25519 curve used for EDDSA
         if (isEncrypt) {
             curve = QLatin1String("cv25519");
             *algo = Subkey::AlgoECDH;
         } else {
             curve = split[0];
             *algo = Subkey::AlgoEDDSA;
         }
         return;
     }
 
     if (lowered.startsWith(QLatin1String("cv25519")) ||
         lowered.startsWith(QLatin1String("nist")) ||
         lowered.startsWith(QLatin1String("brainpool")) ||
         lowered.startsWith(QLatin1String("secp"))) {
         curve = split[0];
         *algo = isEncrypt ? Subkey::AlgoECDH : Subkey::AlgoECDSA;
         return;
     }
 
     qCWarning(KLEOPATRA_LOG) << "Failed to parse default_pubkey_algo:" << algoString;
 }
 
 enum class OnUnlimitedValidity {
     ReturnInvalidDate,
     ReturnInternalDefault
 };
 QDate defaultExpirationDate(OnUnlimitedValidity onUnlimitedValidity)
 {
     QDate expirationDate{};
 
     const auto settings = Kleo::Settings{};
     const auto defaultExpirationInDays = settings.validityPeriodInDays();
     if (defaultExpirationInDays > 0) {
         expirationDate = QDate::currentDate().addDays(defaultExpirationInDays);
     } else if (defaultExpirationInDays < 0 || onUnlimitedValidity == OnUnlimitedValidity::ReturnInternalDefault) {
         expirationDate = QDate::currentDate().addYears(2);
     }
 
     return expirationDate;
 }
 
 }
 
 Q_DECLARE_METATYPE(GpgME::Subkey::PubkeyAlgo)
 namespace Kleo
 {
 namespace NewCertificateUi
 {
 class WizardPage : public QWizardPage
 {
     Q_OBJECT
 protected:
     explicit WizardPage(QWidget *parent = nullptr)
         : QWizardPage(parent) {}
 
     NewCertificateWizard *wizard() const
     {
         Q_ASSERT(static_cast<NewCertificateWizard *>(QWizardPage::wizard()) == qobject_cast<NewCertificateWizard *>(QWizardPage::wizard()));
         return static_cast<NewCertificateWizard *>(QWizardPage::wizard());
     }
 
     void resetProtocol()
     {
         wizard()->resetProtocol();
     }
 
     void restartAtEnterDetailsPage()
     {
         wizard()->restartAtEnterDetailsPage();
     }
 
     QDir tmpDir() const;
 
 protected:
 #define FIELD(type, name) type name() const { return field( QStringLiteral(#name) ).value<type>(); }
     FIELD(bool, pgp)
     FIELD(bool, signingAllowed)
     FIELD(bool, encryptionAllowed)
     FIELD(bool, certificationAllowed)
     FIELD(bool, authenticationAllowed)
 
     FIELD(QString, name)
     FIELD(QString, email)
     FIELD(QString, dn)
     FIELD(bool, protectedKey)
 
     FIELD(Subkey::PubkeyAlgo, keyType)
     FIELD(int, keyStrength)
     FIELD(QString, keyCurve)
 
     FIELD(Subkey::PubkeyAlgo, subkeyType)
     FIELD(int, subkeyStrength)
     FIELD(QString, subkeyCurve)
 
     FIELD(QDate, expiryDate)
 
     FIELD(QStringList, additionalUserIDs)
     FIELD(QStringList, additionalEMailAddresses)
     FIELD(QStringList, dnsNames)
     FIELD(QStringList, uris)
 
     FIELD(QString, url)
     FIELD(QString, error)
     FIELD(QString, result)
     FIELD(QString, fingerprint)
 #undef FIELD
 };
 } // namespace NewCertificateUi
 } // namespace Kleo
 
 using namespace Kleo::NewCertificateUi;
 
 namespace
 {
 
 class AdvancedSettingsDialog : public QDialog
 {
     Q_OBJECT
     Q_PROPERTY(QStringList additionalUserIDs READ additionalUserIDs WRITE setAdditionalUserIDs)
     Q_PROPERTY(QStringList additionalEMailAddresses READ additionalEMailAddresses WRITE setAdditionalEMailAddresses)
     Q_PROPERTY(QStringList dnsNames READ dnsNames WRITE setDnsNames)
     Q_PROPERTY(QStringList uris READ uris WRITE setUris)
     Q_PROPERTY(uint keyStrength READ keyStrength WRITE setKeyStrength)
     Q_PROPERTY(Subkey::PubkeyAlgo keyType READ keyType WRITE setKeyType)
     Q_PROPERTY(QString keyCurve READ keyCurve WRITE setKeyCurve)
     Q_PROPERTY(uint subkeyStrength READ subkeyStrength WRITE setSubkeyStrength)
     Q_PROPERTY(QString subkeyCurve READ subkeyCurve WRITE setSubkeyCurve)
     Q_PROPERTY(Subkey::PubkeyAlgo subkeyType READ subkeyType WRITE setSubkeyType)
     Q_PROPERTY(bool signingAllowed READ signingAllowed WRITE setSigningAllowed)
     Q_PROPERTY(bool encryptionAllowed READ encryptionAllowed WRITE setEncryptionAllowed)
     Q_PROPERTY(bool certificationAllowed READ certificationAllowed WRITE setCertificationAllowed)
     Q_PROPERTY(bool authenticationAllowed READ authenticationAllowed WRITE setAuthenticationAllowed)
     Q_PROPERTY(QDate expiryDate READ expiryDate WRITE setExpiryDate)
 public:
     explicit AdvancedSettingsDialog(QWidget *parent = nullptr)
         : QDialog(parent),
           protocol(UnknownProtocol),
           pgpDefaultAlgorithm(Subkey::AlgoELG_E),
           cmsDefaultAlgorithm(Subkey::AlgoRSA),
           keyTypeImmutable(false),
           ui(),
           mECCSupported(engineIsVersion(2, 1, 0)),
           mEdDSASupported(engineIsVersion(2, 1, 15))
     {
         qRegisterMetaType<Subkey::PubkeyAlgo>("Subkey::PubkeyAlgo");
         ui.setupUi(this);
         ui.expiryDE->setMinimumDate(QDate::currentDate());
         ui.emailLW->setDefaultValue(i18n("new email"));
         ui.dnsLW->setDefaultValue(i18n("new dns name"));
         ui.uriLW->setDefaultValue(i18n("new uri"));
         ui.elgCB->setToolTip(i18nc("@info:tooltip", "This subkey is required for encryption."));
         ui.ecdhCB->setToolTip(i18nc("@info:tooltip", "This subkey is required for encryption."));
 
         fillKeySizeComboBoxen();
 
         connect(ui.expiryCB, &QAbstractButton::toggled,
                 this, [this](bool checked) {
                     ui.expiryDE->setEnabled(checked);
                     if (checked && !ui.expiryDE->isValid()) {
                         ui.expiryDE->setDate(defaultExpirationDate(OnUnlimitedValidity::ReturnInternalDefault));
                     }
                 });
     }
 
     void setProtocol(GpgME::Protocol proto)
     {
         if (protocol == proto) {
             return;
         }
         protocol = proto;
         loadDefaults();
     }
 
     void setAdditionalUserIDs(const QStringList &items)
     {
         ui.uidLW->setItems(items);
     }
     QStringList additionalUserIDs() const
     {
         return ui.uidLW->items();
     }
 
     void setAdditionalEMailAddresses(const QStringList &items)
     {
         ui.emailLW->setItems(items);
     }
     QStringList additionalEMailAddresses() const
     {
         return ui.emailLW->items();
     }
 
     void setDnsNames(const QStringList &items)
     {
         ui.dnsLW->setItems(items);
     }
     QStringList dnsNames() const
     {
         return ui.dnsLW->items();
     }
 
     void setUris(const QStringList &items)
     {
         ui.uriLW->setItems(items);
     }
     QStringList uris() const
     {
         return ui.uriLW->items();
     }
 
     void setKeyStrength(unsigned int strength)
     {
         set_keysize(ui.rsaKeyStrengthCB, strength);
         set_keysize(ui.dsaKeyStrengthCB, strength);
     }
     unsigned int keyStrength() const
     {
         return
             ui.dsaRB->isChecked() ? get_keysize(ui.dsaKeyStrengthCB) :
             ui.rsaRB->isChecked() ? get_keysize(ui.rsaKeyStrengthCB) : 0;
     }
 
     void setKeyType(Subkey::PubkeyAlgo algo)
     {
         QRadioButton *const rb =
             is_rsa(algo) ? ui.rsaRB :
             is_dsa(algo) ? ui.dsaRB :
             is_ecdsa(algo) || is_eddsa(algo) ? ui.ecdsaRB : nullptr;
         if (rb) {
             rb->setChecked(true);
         }
     }
     Subkey::PubkeyAlgo keyType() const
     {
         return
             ui.dsaRB->isChecked() ? Subkey::AlgoDSA :
             ui.rsaRB->isChecked() ? Subkey::AlgoRSA :
             ui.ecdsaRB->isChecked() ?
                 ui.ecdsaKeyCurvesCB->currentText() == QLatin1String("ed25519") ? Subkey::AlgoEDDSA :
                 Subkey::AlgoECDSA :
             Subkey::AlgoUnknown;
     }
 
     void setKeyCurve(const QString &curve)
     {
         set_curve(ui.ecdsaKeyCurvesCB, curve);
     }
 
     QString keyCurve() const
     {
         return get_curve(ui.ecdsaKeyCurvesCB);
     }
 
     void setSubkeyType(Subkey::PubkeyAlgo algo)
     {
         ui.elgCB->setChecked(is_elg(algo));
         ui.rsaSubCB->setChecked(is_rsa(algo));
         ui.ecdhCB->setChecked(is_ecdh(algo));
     }
     Subkey::PubkeyAlgo subkeyType() const
     {
         if (ui.elgCB->isChecked()) {
             return Subkey::AlgoELG_E;
         } else if (ui.rsaSubCB->isChecked()) {
             return Subkey::AlgoRSA;
         } else if (ui.ecdhCB->isChecked()) {
             return Subkey::AlgoECDH;
         }
         return Subkey::AlgoUnknown;
     }
 
     void setSubkeyCurve(const QString &curve)
     {
         set_curve(ui.ecdhKeyCurvesCB, curve);
     }
 
     QString subkeyCurve() const
     {
         return get_curve(ui.ecdhKeyCurvesCB);
     }
 
     void setSubkeyStrength(unsigned int strength)
     {
         if (subkeyType() == Subkey::AlgoRSA) {
             set_keysize(ui.rsaKeyStrengthSubCB, strength);
         } else {
             set_keysize(ui.elgKeyStrengthCB, strength);
         }
     }
     unsigned int subkeyStrength() const
     {
         if (subkeyType() == Subkey::AlgoRSA) {
             return get_keysize(ui.rsaKeyStrengthSubCB);
         }
         return get_keysize(ui.elgKeyStrengthCB);
     }
 
     void setSigningAllowed(bool on)
     {
         ui.signingCB->setChecked(on);
     }
     bool signingAllowed() const
     {
         return ui.signingCB->isChecked();
     }
 
     void setEncryptionAllowed(bool on)
     {
         ui.encryptionCB->setChecked(on);
     }
     bool encryptionAllowed() const
     {
         return ui.encryptionCB->isChecked();
     }
 
     void setCertificationAllowed(bool on)
     {
         ui.certificationCB->setChecked(on);
     }
     bool certificationAllowed() const
     {
         return ui.certificationCB->isChecked();
     }
 
     void setAuthenticationAllowed(bool on)
     {
         ui.authenticationCB->setChecked(on);
     }
     bool authenticationAllowed() const
     {
         return ui.authenticationCB->isChecked();
     }
 
     void setExpiryDate(QDate date)
     {
         ui.expiryDE->setDate(date);
         ui.expiryCB->setChecked(ui.expiryDE->isValid());
     }
     QDate expiryDate() const
     {
         return ui.expiryCB->isChecked() ? ui.expiryDE->date() : QDate();
     }
 
 Q_SIGNALS:
     void changed();
 
 private Q_SLOTS:
     void slotKeyMaterialSelectionChanged()
     {
         const unsigned int algo = keyType();
         const unsigned int sk_algo = subkeyType();
 
         if (protocol == OpenPGP) {
             if (!keyTypeImmutable) {
                 ui.elgCB->setEnabled(is_dsa(algo));
                 ui.rsaSubCB->setEnabled(is_rsa(algo));
                 ui.ecdhCB->setEnabled(is_ecdsa(algo) || is_eddsa(algo));
                 if (sender() == ui.dsaRB || sender() == ui.rsaRB || sender() == ui.ecdsaRB) {
                     ui.elgCB->setChecked(is_dsa(algo));
                     ui.ecdhCB->setChecked(is_ecdsa(algo) || is_eddsa(algo));
                     ui.rsaSubCB->setChecked(is_rsa(algo));
                 }
                 if (is_rsa(algo)) {
                     ui.encryptionCB->setEnabled(true);
                     ui.encryptionCB->setChecked(true);
                     ui.signingCB->setEnabled(true);
                     ui.signingCB->setChecked(true);
                     ui.authenticationCB->setEnabled(true);
                     if (is_rsa(sk_algo)) {
                         ui.encryptionCB->setEnabled(false);
                         ui.encryptionCB->setChecked(true);
                     } else {
                         ui.encryptionCB->setEnabled(true);
                     }
                 } else if (is_dsa(algo)) {
                     ui.encryptionCB->setEnabled(false);
                     if (is_elg(sk_algo)) {
                         ui.encryptionCB->setChecked(true);
                     } else {
                         ui.encryptionCB->setChecked(false);
                     }
                 } else if (is_ecdsa(algo) || is_eddsa(algo)) {
                     ui.signingCB->setEnabled(true);
                     ui.signingCB->setChecked(true);
                     ui.authenticationCB->setEnabled(true);
                     ui.encryptionCB->setEnabled(false);
                     ui.encryptionCB->setChecked(is_ecdh(sk_algo));
                 }
             }
         } else {
             //assert( is_rsa( keyType() ) ); // it can happen through misconfiguration by the admin that no key type is selectable at all
         }
     }
 
     void slotSigningAllowedToggled(bool on)
     {
         if (!on && protocol == CMS && !encryptionAllowed()) {
             setEncryptionAllowed(true);
         }
     }
     void slotEncryptionAllowedToggled(bool on)
     {
         if (!on && protocol == CMS && !signingAllowed()) {
             setSigningAllowed(true);
         }
     }
 
 private:
     void fillKeySizeComboBoxen();
     void loadDefaultKeyType();
     void loadDefaultExpiration();
     void loadDefaultGnuPGKeyType();
     void loadDefaults();
     void updateWidgetVisibility();
     void setInitialFocus();
 
 private:
     GpgME::Protocol protocol;
     unsigned int pgpDefaultAlgorithm;
     unsigned int cmsDefaultAlgorithm;
     bool keyTypeImmutable;
     Ui_AdvancedSettingsDialog ui;
     bool mECCSupported;
     bool mEdDSASupported;
 };
 
 class ChooseProtocolPage : public WizardPage
 {
     Q_OBJECT
 public:
     explicit ChooseProtocolPage(QWidget *p = nullptr)
         : WizardPage(p),
           initialized(false),
           ui()
     {
         ui.setupUi(this);
         ui.pgpCLB->setAccessibleDescription(ui.pgpCLB->description());
         ui.x509CLB->setAccessibleDescription(ui.x509CLB->description());
         registerField(QStringLiteral("pgp"), ui.pgpCLB);
     }
 
     void setProtocol(Protocol proto)
     {
         if (proto == OpenPGP) {
             ui.pgpCLB->setChecked(true);
         } else if (proto == CMS) {
             ui.x509CLB->setChecked(true);
         } else {
             force_set_checked(ui.pgpCLB,  false);
             force_set_checked(ui.x509CLB, false);
         }
     }
 
     Protocol protocol() const
     {
         return
             ui.pgpCLB->isChecked()  ? OpenPGP :
             ui.x509CLB->isChecked() ? CMS : UnknownProtocol;
     }
 
     void initializePage() override {
         if (!initialized)
         {
             connect(ui.pgpCLB,  &QAbstractButton::clicked, wizard(), &QWizard::next, Qt::QueuedConnection);
             connect(ui.x509CLB, &QAbstractButton::clicked, wizard(), &QWizard::next, Qt::QueuedConnection);
         }
         initialized = true;
     }
 
     bool isComplete() const override
     {
         return protocol() != UnknownProtocol;
     }
 
 private:
     bool initialized : 1;
     Ui_ChooseProtocolPage ui;
 };
 
 struct Line {
     QString attr;
     QString label;
     QString regex;
     QLineEdit *edit;
 };
 
 class EnterDetailsPage : public WizardPage
 {
     Q_OBJECT
 public:
     explicit EnterDetailsPage(QWidget *p = nullptr)
         : WizardPage(p), dialog(this), ui()
     {
         ui.setupUi(this);
 
         Settings settings;
         if (settings.hideAdvanced()) {
             setSubTitle(i18n("Please enter your personal details below."));
         } else {
             setSubTitle(i18n("Please enter your personal details below. If you want more control over the parameters, click on the Advanced Settings button."));
         }
         ui.advancedPB->setVisible(!settings.hideAdvanced());
         ui.resultLE->setFocusPolicy(Qt::NoFocus);
 
         // set errorLB to have a fixed height of two lines:
         ui.errorLB->setText(QStringLiteral("2<br>1"));
         ui.errorLB->setFixedHeight(ui.errorLB->minimumSizeHint().height());
         ui.errorLB->clear();
 
         connect(ui.resultLE, &QLineEdit::textChanged,
                 this, &QWizardPage::completeChanged);
         // The email doesn't necessarily show up in ui.resultLE:
         connect(ui.emailLE, &QLineEdit::textChanged,
                 this, &QWizardPage::completeChanged);
         registerDialogPropertiesAsFields();
         registerField(QStringLiteral("dn"), ui.resultLE);
         registerField(QStringLiteral("name"), ui.nameLE);
         registerField(QStringLiteral("email"), ui.emailLE);
         registerField(QStringLiteral("protectedKey"), ui.withPassCB);
         updateForm();
         setCommitPage(true);
         setButtonText(QWizard::CommitButton, i18nc("@action", "Create"));
 
         const auto conf = QGpgME::cryptoConfig();
         if (!conf) {
             qCWarning(KLEOPATRA_LOG) << "Failed to obtain cryptoConfig.";
             return;
         }
         const auto entry = getCryptoConfigEntry(conf, "gpg-agent", "enforce-passphrase-constraints");
         if (entry && entry->boolValue()) {
             qCDebug(KLEOPATRA_LOG) << "Disabling passphrace cb because of agent config.";
             ui.withPassCB->setEnabled(false);
             ui.withPassCB->setChecked(true);
         } else {
             const KConfigGroup config(KSharedConfig::openConfig(), "CertificateCreationWizard");
             ui.withPassCB->setChecked(config.readEntry("WithPassphrase", false));
             ui.withPassCB->setEnabled(!config.isEntryImmutable("WithPassphrase"));
         }
     }
 
     bool isComplete() const override;
     void initializePage() override {
         updateForm();
         ui.withPassCB->setVisible(pgp());
         dialog.setProtocol(pgp() ? OpenPGP : CMS);
     }
     void cleanupPage() override {
         saveValues();
         // reset protocol when navigating back to "Choose Protocol" page
         resetProtocol();
     }
 
 private:
     void updateForm();
     void clearForm();
     void saveValues();
     void registerDialogPropertiesAsFields();
 
 private:
     QString pgpUserID() const;
     QString cmsDN() const;
 
 private Q_SLOTS:
     void slotAdvancedSettingsClicked();
     void slotUpdateResultLabel()
     {
         ui.resultLE->setText(pgp() ? pgpUserID() : cmsDN());
     }
 
 private:
     QVector<Line> lineList;
     QList<QWidget *> dynamicWidgets;
     QMap<QString, QString> savedValues;
     AdvancedSettingsDialog dialog;
     Ui_EnterDetailsPage ui;
 };
 
 class KeyCreationPage : public WizardPage
 {
     Q_OBJECT
 public:
     explicit KeyCreationPage(QWidget *p = nullptr)
         : WizardPage(p),
           ui()
     {
         ui.setupUi(this);
     }
 
     bool isComplete() const override
     {
         return !job;
     }
 
     void initializePage() override {
         startJob();
     }
 
 private:
     void startJob()
     {
         const auto proto = pgp() ? QGpgME::openpgp() : QGpgME::smime();
         if (!proto) {
             return;
         }
         QGpgME::KeyGenerationJob *const j = proto->keyGenerationJob();
         if (!j) {
             return;
         }
         if (!protectedKey() && pgp()) {
             auto ctx = QGpgME::Job::context(j);
             ctx->setPassphraseProvider(&mEmptyPWProvider);
             ctx->setPinentryMode(Context::PinentryLoopback);
         }
         connect(j, &QGpgME::KeyGenerationJob::result,
                 this, &KeyCreationPage::slotResult);
         if (const Error err = j->start(createGnupgKeyParms()))
             setField(QStringLiteral("error"), i18n("Could not start key pair creation: %1",
                                                    QString::fromLocal8Bit(err.asString())));
         else {
             job = j;
         }
     }
     QStringList keyUsages() const;
     QStringList subkeyUsages() const;
     QString createGnupgKeyParms() const;
     EmptyPassphraseProvider mEmptyPWProvider;
 
 private Q_SLOTS:
     void slotResult(const GpgME::KeyGenerationResult &result, const QByteArray &request, const QString &auditLog)
     {
         Q_UNUSED(auditLog)
         if (result.error().code() || (pgp() && !result.fingerprint())) {
             setField(QStringLiteral("error"), result.error().isCanceled()
                      ? i18n("Operation canceled.")
                      : i18n("Could not create key pair: %1",
                             QString::fromLocal8Bit(result.error().asString())));
             setField(QStringLiteral("url"), QString());
             setField(QStringLiteral("result"), QString());
         } else if (pgp()) {
             setField(QStringLiteral("error"), QString());
             setField(QStringLiteral("url"), QString());
             setField(QStringLiteral("result"), i18n("Key pair created successfully.\n"
                                                     "Fingerprint: %1", Formatting::prettyID(result.fingerprint())));
         } else {
             QFile file(tmpDir().absoluteFilePath(QStringLiteral("request.p10")));
 
             if (!file.open(QIODevice::WriteOnly)) {
                 setField(QStringLiteral("error"), i18n("Could not write output file %1: %2",
                                                        file.fileName(), file.errorString()));
                 setField(QStringLiteral("url"), QString());
                 setField(QStringLiteral("result"), QString());
             } else {
                 file.write(request);
                 setField(QStringLiteral("error"), QString());
                 setField(QStringLiteral("url"), QUrl::fromLocalFile(file.fileName()).toString());
                 setField(QStringLiteral("result"), i18n("Key pair created successfully."));
             }
         }
         // Ensure that we have the key in the keycache
         if (pgp() && !result.error().code() && result.fingerprint()) {
             auto ctx = Context::createForProtocol(OpenPGP);
             if (ctx) {
                 // Check is pretty useless something very buggy in that case.
                 Error e;
                 const auto key = ctx->key(result.fingerprint(), e, true);
                 if (!key.isNull()) {
                     KeyCache::mutableInstance()->insert(key);
                 } else {
                     qCDebug(KLEOPATRA_LOG) << "Failed to find newly generated key.";
                 }
                 delete ctx;
             }
         }
         setField(QStringLiteral("fingerprint"), result.fingerprint() ?
                  QString::fromLatin1(result.fingerprint()) : QString());
         job = nullptr;
         Q_EMIT completeChanged();
         const KConfigGroup config(KSharedConfig::openConfig(), "CertificateCreationWizard");
         if (config.readEntry("SkipResultPage", false)) {
             if (result.fingerprint()) {
                 KleopatraApplication::instance()->slotActivateRequested(QStringList() <<
                        QStringLiteral("kleopatra") << QStringLiteral("--query") << QLatin1String(result.fingerprint()), QString());
                 QMetaObject::invokeMethod(wizard(), "close", Qt::QueuedConnection);
             } else {
                 QMetaObject::invokeMethod(wizard(), "next", Qt::QueuedConnection);
             }
         } else {
             QMetaObject::invokeMethod(wizard(), "next", Qt::QueuedConnection);
         }
     }
 
 private:
     QPointer<QGpgME::KeyGenerationJob> job;
     Ui_KeyCreationPage ui;
 };
 
 class ResultPage : public WizardPage
 {
     Q_OBJECT
 public:
     explicit ResultPage(QWidget *p = nullptr)
         : WizardPage(p),
           initialized(false),
           successfullyCreatedSigningCertificate(false),
           successfullyCreatedEncryptionCertificate(false),
           ui()
     {
         ui.setupUi(this);
         ui.dragQueen->setPixmap(QIcon::fromTheme(QStringLiteral("kleopatra")).pixmap(64, 64));
         registerField(QStringLiteral("error"),  ui.errorTB,   "plainText");
         registerField(QStringLiteral("result"), ui.resultTB,  "plainText");
         registerField(QStringLiteral("url"),    ui.dragQueen, "url");
         // hidden field, since QWizard can't deal with non-widget-backed fields...
         auto le = new QLineEdit(this);
         le->hide();
         registerField(QStringLiteral("fingerprint"), le);
     }
 
     void initializePage() override {
         const bool error = isError();
 
         if (error)
         {
             setTitle(i18nc("@title", "Key Creation Failed"));
             setSubTitle(i18n("Key pair creation failed. Please find details about the failure below."));
         } else {
             setTitle(i18nc("@title", "Key Pair Successfully Created"));
             setSubTitle(i18n("Your new key pair was created successfully. Please find details on the result and some suggested next steps below."));
         }
 
         ui.resultTB                 ->setVisible(!error);
         ui.errorTB                  ->setVisible(error);
         ui.dragQueen                ->setVisible(!error &&!pgp());
         ui.restartWizardPB          ->setVisible(error);
         ui.nextStepsGB              ->setVisible(!error);
         ui.saveRequestToFilePB      ->setVisible(!pgp());
         ui.makeBackupPB             ->setVisible(pgp());
         ui.createRevocationRequestPB->setVisible(pgp() &&false);     // not implemented
 
         ui.sendCertificateByEMailPB ->setVisible(pgp());
         ui.sendRequestByEMailPB     ->setVisible(!pgp());
         ui.uploadToKeyserverPB      ->setVisible(pgp());
 
         if (!error && !pgp())
         {
             if (signingAllowed() && !encryptionAllowed()) {
                 successfullyCreatedSigningCertificate = true;
             } else if (!signingAllowed() && encryptionAllowed()) {
                 successfullyCreatedEncryptionCertificate = true;
             } else {
                 successfullyCreatedEncryptionCertificate = successfullyCreatedSigningCertificate = true;
             }
         }
 
         ui.createSigningCertificatePB->setVisible(successfullyCreatedEncryptionCertificate &&!successfullyCreatedSigningCertificate);
         ui.createEncryptionCertificatePB->setVisible(successfullyCreatedSigningCertificate &&!successfullyCreatedEncryptionCertificate);
 
         if (error) {
             wizard()->setOptions(wizard()->options() & ~QWizard::NoCancelButtonOnLastPage);
         } else {
             wizard()->setOptions(wizard()->options() | QWizard::NoCancelButtonOnLastPage);
         }
 
         if (!initialized) {
             connect(ui.restartWizardPB, &QAbstractButton::clicked,
                     this, [this]() {
                         restartAtEnterDetailsPage();
                     });
         }
         initialized = true;
     }
 
     bool isError() const
     {
         return !ui.errorTB->document()->isEmpty();
     }
 
     bool isComplete() const override
     {
         return !isError();
     }
 
 private:
     Key key() const
     {
         return KeyCache::instance()->findByFingerprint(fingerprint().toLatin1().constData());
     }
 
 private Q_SLOTS:
     void slotSaveRequestToFile()
     {
         QString fileName = FileDialog::getSaveFileName(this, i18nc("@title", "Save Request"),
                            QStringLiteral("imp"), i18n("PKCS#10 Requests (*.p10)"));
         if (fileName.isEmpty()) {
             return;
         }
         if (!fileName.endsWith(QLatin1String(".p10"), Qt::CaseInsensitive)) {
             fileName += QLatin1String(".p10");
         }
         QFile src(QUrl(url()).toLocalFile());
         if (!src.copy(fileName))
             KMessageBox::error(this,
                                xi18nc("@info",
                                       "Could not copy temporary file <filename>%1</filename> "
                                       "to file <filename>%2</filename>: <message>%3</message>",
                                       src.fileName(), fileName, src.errorString()),
                                i18nc("@title", "Error Saving Request"));
         else
             KMessageBox::information(this,
                                      xi18nc("@info",
                                             "<para>Successfully wrote request to <filename>%1</filename>.</para>"
                                             "<para>You should now send the request to the Certification Authority (CA).</para>",
                                             fileName),
                                      i18nc("@title", "Request Saved"));
     }
 
     void slotSendRequestByEMail()
     {
         if (pgp()) {
             return;
         }
         const KConfigGroup config(KSharedConfig::openConfig(), "CertificateCreationWizard");
         invokeMailer(config.readEntry("CAEmailAddress"),    // to
                      i18n("Please process this certificate."), // subject
                      i18n("Please process this certificate and inform the sender about the location to fetch the resulting certificate.\n\nThanks,\n"), // body
                      QUrl(url()).toLocalFile());    // attachment
     }
 
     void slotSendCertificateByEMail()
     {
         if (!pgp() || exportCertificateCommand) {
             return;
         }
         auto cmd = new ExportCertificateCommand(key());
         connect(cmd, &ExportCertificateCommand::finished, this, &ResultPage::slotSendCertificateByEMailContinuation);
         cmd->setOpenPGPFileName(tmpDir().absoluteFilePath(fingerprint() + QLatin1String(".asc")));
         cmd->start();
         exportCertificateCommand = cmd;
     }
 
     void slotSendCertificateByEMailContinuation()
     {
         if (!exportCertificateCommand) {
             return;
         }
         // ### better error handling?
         const QString fileName = exportCertificateCommand->openPGPFileName();
         qCDebug(KLEOPATRA_LOG) << "fileName" << fileName;
         exportCertificateCommand = nullptr;
         if (fileName.isEmpty()) {
             return;
         }
         invokeMailer(QString(),  // to
                      i18n("My new public OpenPGP key"), // subject
                      i18n("Please find attached my new public OpenPGP key."), // body
                      fileName);
     }
 
     QByteArray ol_quote(QByteArray str)
     {
 #ifdef Q_OS_WIN
         return "\"\"" + str.replace('"', "\\\"") + "\"\"";
         //return '"' + str.replace( '"', "\\\"" ) + '"';
 #else
         return str;
 #endif
     }
 
     void invokeMailer(const QString &to, const QString &subject, const QString &body, const QString &attachment)
     {
         qCDebug(KLEOPATRA_LOG) << "to:" << to << "subject:" << subject
                                << "body:" << body << "attachment:" << attachment;
 
         // RFC 2368 says body's linebreaks need to be encoded as
         // "%0D%0A", so normalize body to CRLF:
         //body.replace(QLatin1Char('\n'), QStringLiteral("\r\n")).remove(QStringLiteral("\r\r"));
 
         QUrlQuery query;
         query.addQueryItem(QStringLiteral("subject"), subject);
         query.addQueryItem(QStringLiteral("body"), body);
         if (!attachment.isEmpty()) {
             query.addQueryItem(QStringLiteral("attach"), attachment);
         }
         QUrl url;
         url.setScheme(QStringLiteral("mailto"));
         url.setQuery(query);
         qCDebug(KLEOPATRA_LOG) << "openUrl" << url;
         QDesktopServices::openUrl(url);
         KMessageBox::information(this,
                                  xi18nc("@info",
                                         "<para><application>Kleopatra</application> tried to send a mail via your default mail client.</para>"
                                         "<para>Some mail clients are known not to support attachments when invoked this way.</para>"
                                         "<para>If your mail client does not have an attachment, then drag the <application>Kleopatra</application> icon and drop it on the message compose window of your mail client.</para>"
                                         "<para>If that does not work, either, save the request to a file, and then attach that.</para>"),
                                  i18nc("@title", "Sending Mail"),
                                  QStringLiteral("newcertificatewizard-mailto-troubles"));
     }
 
     void slotUploadCertificateToDirectoryServer()
     {
         if (pgp()) {
             (new ExportOpenPGPCertsToServerCommand(key()))->start();
         }
     }
 
     void slotBackupCertificate()
     {
         if (pgp()) {
             (new ExportSecretKeyCommand(key()))->start();
         }
     }
 
     void slotCreateRevocationRequest()
     {
 
     }
 
     void slotCreateSigningCertificate()
     {
         if (successfullyCreatedSigningCertificate) {
             return;
         }
         toggleSignEncryptAndRestart();
     }
 
     void slotCreateEncryptionCertificate()
     {
         if (successfullyCreatedEncryptionCertificate) {
             return;
         }
         toggleSignEncryptAndRestart();
     }
 
 private:
     void toggleSignEncryptAndRestart()
     {
         if (!wizard()) {
             return;
         }
         if (KMessageBox::warningContinueCancel(
                     this,
                     i18nc("@info",
                           "This operation will delete the certification request. "
                           "Please make sure that you have sent or saved it before proceeding."),
                     i18nc("@title", "Certification Request About To Be Deleted")) != KMessageBox::Continue) {
             return;
         }
         const bool sign = signingAllowed();
         const bool encr = encryptionAllowed();
         setField(QStringLiteral("signingAllowed"),    !sign);
         setField(QStringLiteral("encryptionAllowed"), !encr);
         restartAtEnterDetailsPage();
     }
 
 private:
     bool initialized : 1;
     bool successfullyCreatedSigningCertificate : 1;
     bool successfullyCreatedEncryptionCertificate : 1;
     QPointer<ExportCertificateCommand> exportCertificateCommand;
     Ui_ResultPage ui;
 };
 }
 
 class NewCertificateWizard::Private
 {
     friend class ::Kleo::NewCertificateWizard;
     friend class ::Kleo::NewCertificateUi::WizardPage;
     NewCertificateWizard *const q;
 public:
     explicit Private(NewCertificateWizard *qq)
         : q(qq),
           tmp(QDir::temp().absoluteFilePath(QStringLiteral("kleo-"))),
           ui(q)
     {
         q->setWindowTitle(i18nc("@title:window", "Key Pair Creation Wizard"));
     }
 
 private:
     GpgME::Protocol initialProtocol = GpgME::UnknownProtocol;
     QTemporaryDir tmp;
     struct Ui {
         ChooseProtocolPage chooseProtocolPage;
         EnterDetailsPage enterDetailsPage;
         KeyCreationPage keyCreationPage;
         ResultPage resultPage;
 
         explicit Ui(NewCertificateWizard *q)
             : chooseProtocolPage(q),
               enterDetailsPage(q),
               keyCreationPage(q),
               resultPage(q)
         {
             KDAB_SET_OBJECT_NAME(chooseProtocolPage);
             KDAB_SET_OBJECT_NAME(enterDetailsPage);
             KDAB_SET_OBJECT_NAME(keyCreationPage);
             KDAB_SET_OBJECT_NAME(resultPage);
 
             q->setOptions(NoBackButtonOnStartPage|DisabledBackButtonOnLastPage);
 
             q->setPage(ChooseProtocolPageId, &chooseProtocolPage);
             q->setPage(EnterDetailsPageId,   &enterDetailsPage);
             q->setPage(KeyCreationPageId,    &keyCreationPage);
             q->setPage(ResultPageId,         &resultPage);
 
             q->setStartId(ChooseProtocolPageId);
         }
 
     } ui;
 
 };
 
 NewCertificateWizard::NewCertificateWizard(QWidget *p)
     : QWizard(p), d(new Private(this))
 {
-
 }
 
 NewCertificateWizard::~NewCertificateWizard() {}
 
+void NewCertificateWizard::showEvent(QShowEvent *event)
+{
+    // set WA_KeyboardFocusChange attribute to force visual focus of the
+    // focussed button when the wizard is shown (required for Breeze style
+    // and some other styles)
+    window()->setAttribute(Qt::WA_KeyboardFocusChange);
+    QWizard::showEvent(event);
+}
+
 void NewCertificateWizard::setProtocol(Protocol proto)
 {
     d->initialProtocol = proto;
     d->ui.chooseProtocolPage.setProtocol(proto);
     setStartId(proto == UnknownProtocol ? ChooseProtocolPageId : EnterDetailsPageId);
 }
 
 Protocol NewCertificateWizard::protocol() const
 {
     return d->ui.chooseProtocolPage.protocol();
 }
 
 void NewCertificateWizard::resetProtocol()
 {
     d->ui.chooseProtocolPage.setProtocol(d->initialProtocol);
 }
 
 void NewCertificateWizard::restartAtEnterDetailsPage()
 {
     const auto protocol = d->ui.chooseProtocolPage.protocol();
     restart();  // resets the protocol to the initial protocol
     d->ui.chooseProtocolPage.setProtocol(protocol);
     while (currentId() != NewCertificateWizard::EnterDetailsPageId) {
         next();
     }
 }
 
 static QString pgpLabel(const QString &attr)
 {
     if (attr == QLatin1String("NAME")) {
         return i18n("Name");
     }
     if (attr == QLatin1String("EMAIL")) {
         return i18n("EMail");
     }
     return QString();
 }
 
 static QString attributeLabel(const QString &attr, bool pgp)
 {
     if (attr.isEmpty()) {
         return QString();
     }
     const QString label = pgp ? pgpLabel(attr) : Kleo::DN::attributeNameToLabel(attr);
     if (!label.isEmpty())
         if (pgp) {
             return label;
         } else
             return i18nc("Format string for the labels in the \"Your Personal Data\" page",
                          "%1 (%2)", label, attr);
     else {
         return attr;
     }
 }
 
 #if 0
 //Not used anywhere
 static QString attributeLabelWithColor(const QString &attr, bool pgp)
 {
     const QString result = attributeLabel(attr, pgp);
     if (result.isEmpty()) {
         return QString();
     } else {
         return result + ':';
     }
 }
 #endif
 
 static QString attributeFromKey(QString key)
 {
     return key.remove(QLatin1Char('!'));
 }
 
 QDir WizardPage::tmpDir() const
 {
     return wizard() ? QDir(wizard()->d->tmp.path()) : QDir::home();
 }
 
 void EnterDetailsPage::registerDialogPropertiesAsFields()
 {
 
     const QMetaObject *const mo = dialog.metaObject();
     for (unsigned int i = mo->propertyOffset(), end = i + mo->propertyCount(); i != end; ++i) {
         const QMetaProperty mp = mo->property(i);
         if (mp.isValid()) {
             registerField(QLatin1String(mp.name()), &dialog, mp.name(), SIGNAL(accepted()));
         }
     }
 
 }
 
 void EnterDetailsPage::saveValues()
 {
     for (const Line &line : std::as_const(lineList)) {
         savedValues[ attributeFromKey(line.attr) ] = line.edit->text().trimmed();
     }
 }
 
 void EnterDetailsPage::clearForm()
 {
     qDeleteAll(dynamicWidgets);
     dynamicWidgets.clear();
     lineList.clear();
 
     ui.nameLE->hide();
     ui.nameLE->clear();
     ui.nameLB->hide();
     ui.nameRequiredLB->hide();
 
     ui.emailLE->hide();
     ui.emailLE->clear();
     ui.emailLB->hide();
     ui.emailRequiredLB->hide();
 }
 
 static int row_index_of(QWidget *w, QGridLayout *l)
 {
     const int idx = l->indexOf(w);
     int r, c, rs, cs;
     l->getItemPosition(idx, &r, &c, &rs, &cs);
     return r;
 }
 
 static QLineEdit *adjust_row(QGridLayout *l, int row, const QString &label, const QString &preset, QValidator *validator, bool readonly, bool required)
 {
     Q_ASSERT(l);
     Q_ASSERT(row >= 0);
     Q_ASSERT(row < l->rowCount());
 
     auto lb = qobject_cast<QLabel *>(l->itemAtPosition(row, 0)->widget());
     Q_ASSERT(lb);
     auto le = qobject_cast<QLineEdit *>(l->itemAtPosition(row, 1)->widget());
     Q_ASSERT(le);
     lb->setBuddy(le);   // For better accessibility
     auto reqLB = qobject_cast<QLabel *>(l->itemAtPosition(row, 2)->widget());
     Q_ASSERT(reqLB);
 
     lb->setText(i18nc("interpunctation for labels", "%1:", label));
     le->setText(preset);
     reqLB->setText(required ? i18n("(required)") : i18n("(optional)"));
     delete le->validator();
     if (validator) {
         if (!validator->parent()) {
             validator->setParent(le);
         }
         le->setValidator(validator);
     }
 
     le->setReadOnly(readonly && le->hasAcceptableInput());
 
     lb->show();
     le->show();
     reqLB->show();
 
     return le;
 }
 
 static int add_row(QGridLayout *l, QList<QWidget *> *wl)
 {
     Q_ASSERT(l);
     Q_ASSERT(wl);
     const int row = l->rowCount();
     QWidget *w1, *w2, *w3;
     l->addWidget(w1 = new QLabel(l->parentWidget()),    row, 0);
     l->addWidget(w2 = new QLineEdit(l->parentWidget()), row, 1);
     l->addWidget(w3 = new QLabel(l->parentWidget()),    row, 2);
     wl->push_back(w1);
     wl->push_back(w2);
     wl->push_back(w3);
     return row;
 }
 
 void EnterDetailsPage::updateForm()
 {
 
     clearForm();
 
     const auto settings = Kleo::Settings{};
     const KConfigGroup config(KSharedConfig::openConfig(), "CertificateCreationWizard");
 
     QStringList attrOrder = config.readEntry(pgp() ? "OpenPGPAttributeOrder" : "DNAttributeOrder", QStringList());
     if (attrOrder.empty()) {
         if (pgp()) {
             attrOrder << QStringLiteral("NAME") << QStringLiteral("EMAIL");
         } else {
             attrOrder << QStringLiteral("CN!") << QStringLiteral("L") << QStringLiteral("OU") << QStringLiteral("O") << QStringLiteral("C") << QStringLiteral("EMAIL!");
         }
     }
 
     QList<QWidget *> widgets;
     widgets.push_back(ui.nameLE);
     widgets.push_back(ui.emailLE);
 
     QMap<int, Line> lines;
 
     for (const QString &rawKey : std::as_const(attrOrder)) {
         const QString key = rawKey.trimmed().toUpper();
         const QString attr = attributeFromKey(key);
         if (attr.isEmpty()) {
             continue;
         }
         const QString preset = savedValues.value(attr, config.readEntry(attr, QString()));
         const bool required = key.endsWith(QLatin1Char('!'));
         const bool readonly = config.isEntryImmutable(attr);
         const QString label = config.readEntry(attr + QLatin1String("_label"),
                                                attributeLabel(attr, pgp()));
         const QString regex = config.readEntry(attr + QLatin1String("_regex"));
         const QString placeholder = config.readEntry(attr + QLatin1String{"_placeholder"});
 
         int row;
         bool known = true;
         QValidator *validator = nullptr;
         if (attr == QLatin1String("EMAIL")) {
             row = row_index_of(ui.emailLE, ui.gridLayout);
             validator = regex.isEmpty() ? Validation::email() : Validation::email(QRegExp(regex));
         } else if (attr == QLatin1String("NAME") || attr == QLatin1String("CN")) {
             if ((pgp() && attr == QLatin1String("CN")) || (!pgp() && attr == QLatin1String("NAME"))) {
                 continue;
             }
             if (pgp()) {
                 validator = regex.isEmpty() ? Validation::pgpName() : Validation::pgpName(QRegExp(regex));
             }
             row = row_index_of(ui.nameLE, ui.gridLayout);
         } else {
             known = false;
             row = add_row(ui.gridLayout, &dynamicWidgets);
         }
         if (!validator && !regex.isEmpty()) {
             validator = new QRegExpValidator(QRegExp(regex), nullptr);
         }
 
         QLineEdit *le = adjust_row(ui.gridLayout, row, label, preset, validator, readonly, required);
         le->setPlaceholderText(placeholder);
 
         const Line line = { key, label, regex, le };
         lines[row] = line;
 
         if (!known) {
             widgets.push_back(le);
         }
 
         // don't connect twice:
         disconnect(le, &QLineEdit::textChanged, this, &EnterDetailsPage::slotUpdateResultLabel);
         connect(le, &QLineEdit::textChanged, this, &EnterDetailsPage::slotUpdateResultLabel);
     }
 
     // create lineList in visual order, so requirementsAreMet()
     // complains from top to bottom:
     lineList.reserve(lines.count());
     std::copy(lines.cbegin(), lines.cend(), std::back_inserter(lineList));
 
     widgets.push_back(ui.withPassCB);
     widgets.push_back(ui.advancedPB);
 
     const bool prefillName = (pgp() && settings.prefillName()) || (!pgp() && settings.prefillCN());
     if (ui.nameLE->text().isEmpty() && prefillName) {
         ui.nameLE->setText(userFullName());
     }
     if (ui.emailLE->text().isEmpty() && settings.prefillEmail()) {
         ui.emailLE->setText(userEmailAddress());
     }
 
     slotUpdateResultLabel();
 
     set_tab_order(widgets);
 }
 
 QString EnterDetailsPage::cmsDN() const
 {
     DN dn;
     for (QVector<Line>::const_iterator it = lineList.begin(), end = lineList.end(); it != end; ++it) {
         const QString text = it->edit->text().trimmed();
         if (text.isEmpty()) {
             continue;
         }
         QString attr = attributeFromKey(it->attr);
         if (attr == QLatin1String("EMAIL")) {
             continue;
         }
         if (const char *const oid = oidForAttributeName(attr)) {
             attr = QString::fromUtf8(oid);
         }
         dn.append(DN::Attribute(attr, text));
     }
     return dn.dn();
 }
 
 QString EnterDetailsPage::pgpUserID() const
 {
     return Formatting::prettyNameAndEMail(OpenPGP, QString(),
                                           ui.nameLE->text().trimmed(),
                                           ui.emailLE->text().trimmed(),
                                           QString());
 }
 
 static bool has_intermediate_input(const QLineEdit *le)
 {
     QString text = le->text();
     int pos = le->cursorPosition();
     const QValidator *const v = le->validator();
     return v && v->validate(text, pos) == QValidator::Intermediate;
 }
 
 static bool requirementsAreMet(const QVector<Line> &list, QString &error)
 {
     bool allEmpty = true;
     for (const Line &line : list) {
         const QLineEdit *le = line.edit;
         if (!le) {
             continue;
         }
         const QString key = line.attr;
         qCDebug(KLEOPATRA_LOG) << "requirementsAreMet(): checking" << key << "against" << le->text() << ":";
         if (le->text().trimmed().isEmpty()) {
             if (key.endsWith(QLatin1Char('!'))) {
                 if (line.regex.isEmpty()) {
                     error = xi18nc("@info", "<interface>%1</interface> is required, but empty.", line.label);
                 } else
                     error = xi18nc("@info", "<interface>%1</interface> is required, but empty.<nl/>"
                                    "Local Admin rule: <icode>%2</icode>", line.label, line.regex);
                 return false;
             }
         } else if (has_intermediate_input(le)) {
             if (line.regex.isEmpty()) {
                 error = xi18nc("@info", "<interface>%1</interface> is incomplete.", line.label);
             } else
                 error = xi18nc("@info", "<interface>%1</interface> is incomplete.<nl/>"
                                "Local Admin rule: <icode>%2</icode>", line.label, line.regex);
             return false;
         } else if (!le->hasAcceptableInput()) {
             if (line.regex.isEmpty()) {
                 error = xi18nc("@info", "<interface>%1</interface> is invalid.", line.label);
             } else
                 error = xi18nc("@info", "<interface>%1</interface> is invalid.<nl/>"
                                "Local Admin rule: <icode>%2</icode>", line.label, line.regex);
             return false;
         } else {
             allEmpty = false;
         }
     }
     // Ensure that at least one value is acceptable
     return !allEmpty;
 }
 
 bool EnterDetailsPage::isComplete() const
 {
     QString error;
     const bool ok = requirementsAreMet(lineList, error);
     ui.errorLB->setText(error);
     return ok;
 }
 
 void EnterDetailsPage::slotAdvancedSettingsClicked()
 {
     dialog.exec();
 }
 
 QStringList KeyCreationPage::keyUsages() const
 {
     QStringList usages;
     if (signingAllowed()) {
         usages << QStringLiteral("sign");
     }
     if (encryptionAllowed() && !is_ecdh(subkeyType()) &&
         !is_dsa(keyType()) && !is_rsa(subkeyType())) {
         usages << QStringLiteral("encrypt");
     }
     if (authenticationAllowed()) {
         usages << QStringLiteral("auth");
     }
     if (usages.empty() && certificationAllowed()) {
         /* Empty usages cause an error so we need to
          * add at least certify if nothing else is selected */
         usages << QStringLiteral("cert");
     }
     return usages;
 }
 
 QStringList KeyCreationPage::subkeyUsages() const
 {
     QStringList usages;
     if (encryptionAllowed() && (is_dsa(keyType()) || is_rsa(subkeyType()) ||
                                 is_ecdh(subkeyType()))) {
         Q_ASSERT(subkeyType());
         usages << QStringLiteral("encrypt");
     }
     return usages;
 }
 
 namespace
 {
 template <typename T = QString>
 struct Row {
     QString key;
     T value;
 
     Row(const QString &k, const T &v) : key(k), value(v) {}
 };
 template <typename T>
 QTextStream &operator<<(QTextStream &s, const Row<T> &row)
 {
     if (row.key.isEmpty()) {
         return s;
     } else {
         return s << "<tr><td>" << row.key << "</td><td>" << row.value << "</td></tr>";
     }
 }
 }
 
 QString KeyCreationPage::createGnupgKeyParms() const
 {
     KeyParameters keyParameters(pgp() ? KeyParameters::OpenPGP : KeyParameters::CMS);
 
     keyParameters.setKeyType(keyType());
     if (is_ecdsa(keyType()) || is_eddsa(keyType())) {
         keyParameters.setKeyCurve(keyCurve());
     } else if (const unsigned int strength = keyStrength()) {
         keyParameters.setKeyLength(strength);
     }
     keyParameters.setKeyUsages(keyUsages());
 
     if (subkeyType()) {
         keyParameters.setSubkeyType(subkeyType());
         if (is_ecdh(subkeyType())) {
             keyParameters.setSubkeyCurve(subkeyCurve());
         } else if (const unsigned int strength = subkeyStrength()) {
             keyParameters.setSubkeyLength(strength);
         }
         keyParameters.setSubkeyUsages(subkeyUsages());
     }
 
     if (pgp()) {
         if (expiryDate().isValid()) {
             keyParameters.setExpirationDate(expiryDate());
         }
         if (!name().isEmpty()) {
             keyParameters.setName(name());
         }
         if (!email().isEmpty()) {
             keyParameters.setEmail(email());
         }
     } else {
         keyParameters.setDN(dn());
         keyParameters.setEmail(email());
         const auto addesses{additionalEMailAddresses()};
         for (const QString &email : addesses) {
             keyParameters.addEmail(email);
         }
         const auto dnsN{dnsNames()};
         for (const QString &dns : dnsN) {
             keyParameters.addDomainName(dns);
         }
         const auto urisList{uris()};
         for (const QString &uri : urisList) {
             keyParameters.addURI(uri);
         }
     }
 
     const QString result = keyParameters.toString();
     qCDebug(KLEOPATRA_LOG) << '\n' << result;
     return result;
 }
 
 static void fill_combobox(QComboBox &cb, const QList<int> &sizes, const QStringList &labels)
 {
     cb.clear();
     for (int i = 0, end = sizes.size(); i != end; ++i) {
         const int size = std::abs(sizes[i]);
         /* As we respect the defaults configurable in GnuPG, and we also have configurable
          * defaults in Kleopatra its difficult to print out "default" here. To avoid confusion
          * about that its better not to show any default indication.  */
         cb.addItem(i < labels.size() && !labels[i].trimmed().isEmpty()
                    ? i18ncp("%2: some admin-supplied text, %1: key size in bits", "%2 (1 bit)", "%2 (%1 bits)", size, labels[i].trimmed())
                    : i18ncp("%1: key size in bits", "1 bit", "%1 bits", size),
                    size);
         if (sizes[i] < 0) {
             cb.setCurrentIndex(cb.count() - 1);
         }
     }
 }
 
 void AdvancedSettingsDialog::fillKeySizeComboBoxen()
 {
 
     const KConfigGroup config(KSharedConfig::openConfig(), "CertificateCreationWizard");
 
     QList<int> rsaKeySizes = config.readEntry(RSA_KEYSIZES_ENTRY, QList<int>() << 2048 << -3072 << 4096);
     if (Kleo::gnupgUsesDeVsCompliance()) {
         rsaKeySizes = config.readEntry(RSA_KEYSIZES_ENTRY, QList<int>() << -3072 << 4096);
     }
     const QList<int> dsaKeySizes = config.readEntry(DSA_KEYSIZES_ENTRY, QList<int>() << -2048);
     const QList<int> elgKeySizes = config.readEntry(ELG_KEYSIZES_ENTRY, QList<int>() << -2048 << 3072 << 4096);
 
     const QStringList rsaKeySizeLabels = config.readEntry(RSA_KEYSIZE_LABELS_ENTRY, QStringList());
     const QStringList dsaKeySizeLabels = config.readEntry(DSA_KEYSIZE_LABELS_ENTRY, QStringList());
     const QStringList elgKeySizeLabels = config.readEntry(ELG_KEYSIZE_LABELS_ENTRY, QStringList());
 
     fill_combobox(*ui.rsaKeyStrengthCB, rsaKeySizes, rsaKeySizeLabels);
     fill_combobox(*ui.rsaKeyStrengthSubCB, rsaKeySizes, rsaKeySizeLabels);
     fill_combobox(*ui.dsaKeyStrengthCB, dsaKeySizes, dsaKeySizeLabels);
     fill_combobox(*ui.elgKeyStrengthCB, elgKeySizes, elgKeySizeLabels);
     if (mEdDSASupported) {
         // If supported we recommend cv25519
         ui.ecdsaKeyCurvesCB->addItem(QStringLiteral("ed25519"));
         ui.ecdhKeyCurvesCB->addItem(QStringLiteral("cv25519"));
     }
     ui.ecdhKeyCurvesCB->addItems(curveNames);
     ui.ecdsaKeyCurvesCB->addItems(curveNames);
 }
 
 // Try to load the default key type from GnuPG
 void AdvancedSettingsDialog::loadDefaultGnuPGKeyType()
 {
     const auto conf = QGpgME::cryptoConfig();
     if (!conf) {
         qCWarning(KLEOPATRA_LOG) << "Failed to obtain cryptoConfig.";
         return;
     }
     const auto entry = getCryptoConfigEntry(conf, protocol == CMS ? "gpgsm" : "gpg", "default_pubkey_algo");
     if (!entry) {
         qCDebug(KLEOPATRA_LOG) << "GnuPG does not have default key type. Fallback to RSA";
         setKeyType(Subkey::AlgoRSA);
         setSubkeyType(Subkey::AlgoRSA);
         return;
     }
 
     qCDebug(KLEOPATRA_LOG) << "Have default key type: " << entry->stringValue();
 
     // Format is <primarytype>[/usage]+<subkeytype>[/usage]
     const auto split = entry->stringValue().split(QLatin1Char('+'));
     int size = 0;
     Subkey::PubkeyAlgo algo = Subkey::AlgoUnknown;
     QString curve;
 
     parseAlgoString(split[0], &size, &algo, curve);
     if (algo == Subkey::AlgoUnknown) {
         setSubkeyType(Subkey::AlgoRSA);
         return;
     }
 
     setKeyType(algo);
 
     if (is_rsa(algo) || is_elg(algo) || is_dsa(algo)) {
         setKeyStrength(size);
     } else {
         setKeyCurve(curve);
     }
 
     {
         auto algoString = (split.size() == 2) ? split[1] : split[0];
         // If it has no usage we assume encrypt subkey
         if (!algoString.contains(QLatin1Char('/'))) {
             algoString += QStringLiteral("/enc");
         }
 
         parseAlgoString(algoString, &size, &algo, curve);
 
         if (algo == Subkey::AlgoUnknown) {
             setSubkeyType(Subkey::AlgoRSA);
             return;
         }
 
         setSubkeyType(algo);
 
         if (is_rsa(algo) || is_elg(algo)) {
             setSubkeyStrength(size);
         } else {
             setSubkeyCurve(curve);
         }
     }
 }
 
 void AdvancedSettingsDialog::loadDefaultKeyType()
 {
 
     if (protocol != CMS && protocol != OpenPGP) {
         return;
     }
 
     const KConfigGroup config(KSharedConfig::openConfig(), "CertificateCreationWizard");
 
     const QString entry = protocol == CMS ? QLatin1String(CMS_KEY_TYPE_ENTRY) : QLatin1String(PGP_KEY_TYPE_ENTRY);
     const QString keyType = config.readEntry(entry).trimmed().toUpper();
 
     if (protocol == OpenPGP && keyType == QLatin1String("DSA")) {
         setKeyType(Subkey::AlgoDSA);
         setSubkeyType(Subkey::AlgoUnknown);
     } else if (protocol == OpenPGP && keyType == QLatin1String("DSA+ELG")) {
         setKeyType(Subkey::AlgoDSA);
         setSubkeyType(Subkey::AlgoELG_E);
     } else if (keyType.isEmpty() && engineIsVersion(2, 1, 17)) {
         loadDefaultGnuPGKeyType();
     } else {
         if (!keyType.isEmpty() && keyType != QLatin1String("RSA"))
             qCWarning(KLEOPATRA_LOG) << "invalid value \"" << qPrintable(keyType)
                                      << "\" for entry \"[CertificateCreationWizard]"
                                      << qPrintable(entry) << "\"";
         setKeyType(Subkey::AlgoRSA);
         setSubkeyType(Subkey::AlgoRSA);
     }
 
     keyTypeImmutable = config.isEntryImmutable(entry);
 }
 
 void AdvancedSettingsDialog::loadDefaultExpiration()
 {
     if (protocol != OpenPGP) {
         return;
     }
 
     setExpiryDate(defaultExpirationDate(OnUnlimitedValidity::ReturnInvalidDate));
 }
 
 void AdvancedSettingsDialog::loadDefaults()
 {
     loadDefaultKeyType();
     loadDefaultExpiration();
 
     updateWidgetVisibility();
     setInitialFocus();
 }
 
 void AdvancedSettingsDialog::updateWidgetVisibility()
 {
     // Personal Details Page
     if (protocol == OpenPGP) {    // ### hide until multi-uid is implemented
         if (ui.tabWidget->indexOf(ui.personalTab) != -1) {
             ui.tabWidget->removeTab(ui.tabWidget->indexOf(ui.personalTab));
         }
     } else {
         if (ui.tabWidget->indexOf(ui.personalTab) == -1) {
             ui.tabWidget->addTab(ui.personalTab, tr2i18n("Personal Details", nullptr));
         }
     }
     ui.uidGB->setVisible(protocol == OpenPGP);
     ui.uidGB->setEnabled(false);
     ui.uidGB->setToolTip(i18nc("@info:tooltip", "Adding more than one User ID is not yet implemented."));
     ui.emailGB->setVisible(protocol == CMS);
     ui.dnsGB->setVisible(protocol == CMS);
     ui.uriGB->setVisible(protocol == CMS);
 
     ui.ecdhCB->setVisible(mECCSupported);
     ui.ecdhKeyCurvesCB->setVisible(mECCSupported);
     ui.ecdsaKeyCurvesCB->setVisible(mECCSupported);
     ui.ecdsaRB->setVisible(mECCSupported);
     if (mEdDSASupported) {
         // We use the same radio button for EdDSA as we use for
         // ECDSA GnuPG does the same and this is really super technical
         // land.
         ui.ecdsaRB->setText(QStringLiteral("ECDSA/EdDSA"));
     }
 
     const bool deVsHack = Kleo::gnupgUsesDeVsCompliance();
 
     if (deVsHack) {
         // GnuPG Provides no API to query which keys are compliant for
         // a mode. If we request a different one it will error out so
         // we have to remove the options.
         //
         // Does anyone want to use NIST anyway?
         int i;
         while ((i = ui.ecdsaKeyCurvesCB->findText(QStringLiteral("NIST"), Qt::MatchStartsWith)) != -1 ||
                (i = ui.ecdsaKeyCurvesCB->findText(QStringLiteral("25519"), Qt::MatchEndsWith)) != -1) {
             ui.ecdsaKeyCurvesCB->removeItem(i);
         }
         while ((i = ui.ecdhKeyCurvesCB->findText(QStringLiteral("NIST"), Qt::MatchStartsWith)) != -1 ||
                (i = ui.ecdhKeyCurvesCB->findText(QStringLiteral("25519"), Qt::MatchEndsWith)) != -1) {
             ui.ecdhKeyCurvesCB->removeItem(i);
         }
     }
     // Technical Details Page
     if (keyTypeImmutable) {
         ui.rsaRB->setEnabled(false);
         ui.rsaSubCB->setEnabled(false);
         ui.dsaRB->setEnabled(false);
         ui.elgCB->setEnabled(false);
         ui.ecdsaRB->setEnabled(false);
         ui.ecdhCB->setEnabled(false);
     } else {
         ui.rsaRB->setEnabled(true);
         ui.rsaSubCB->setEnabled(protocol == OpenPGP);
         ui.dsaRB->setEnabled(protocol == OpenPGP && !deVsHack);
         ui.elgCB->setEnabled(protocol == OpenPGP && !deVsHack);
         ui.ecdsaRB->setEnabled(protocol == OpenPGP);
         ui.ecdhCB->setEnabled(protocol == OpenPGP);
     }
     ui.certificationCB->setVisible(protocol == OpenPGP);   // gpgsm limitation?
     ui.authenticationCB->setVisible(protocol == OpenPGP);
     if (protocol == OpenPGP) {   // pgp keys must have certify capability
         ui.certificationCB->setChecked(true);
         ui.certificationCB->setEnabled(false);
     }
     if (protocol == CMS) {
         ui.encryptionCB->setEnabled(true);
         ui.rsaSubCB->setChecked(false);
         ui.rsaKeyStrengthSubCB->setEnabled(false);
     }
 
     ui.expiryDE->setVisible(protocol == OpenPGP);
     ui.expiryCB->setVisible(protocol == OpenPGP);
     const auto settings = Kleo::Settings{};
     if (settings.isImmutable(QStringLiteral("ValidityPeriodInDays"))) {
         ui.expiryDE->setEnabled(false);
         ui.expiryCB->setEnabled(false);
     }
 
     slotKeyMaterialSelectionChanged();
 }
 
 template<typename UnaryPredicate>
 bool focusFirstButtonIf(const std::vector<QAbstractButton *> &buttons, UnaryPredicate p)
 {
     auto it = std::find_if(std::begin(buttons), std::end(buttons), p);
     if (it != std::end(buttons)) {
         (*it)->setFocus();
         return true;
     }
     return false;
 }
 
 bool focusFirstCheckedButton(const std::vector<QAbstractButton *> &buttons)
 {
     return focusFirstButtonIf(buttons,
                               [](auto btn) {
                                   return btn && btn->isEnabled() && btn->isChecked();
                               });
 }
 
 bool focusFirstEnabledButton(const std::vector<QAbstractButton *> &buttons)
 {
     return focusFirstButtonIf(buttons,
                               [](auto btn) {
                                   return btn && btn->isEnabled();
                               });
 }
 
 void AdvancedSettingsDialog::setInitialFocus()
 {
     // first try the key type radio buttons
     if (focusFirstCheckedButton({ui.rsaRB, ui.dsaRB, ui.ecdsaRB})) {
         return;
     }
     // then try the usage check boxes and the expiration check box
     if (focusFirstEnabledButton({ui.signingCB, ui.certificationCB, ui.encryptionCB, ui.authenticationCB, ui.expiryCB})) {
         return;
     }
     // finally, focus the OK button
     ui.buttonBox->button(QDialogButtonBox::Ok)->setFocus();
 }
 
 #include "newcertificatewizard.moc"
diff --git a/src/newcertificatewizard/newcertificatewizard.h b/src/newcertificatewizard/newcertificatewizard.h
index ba58168d3..9ffe5be89 100644
--- a/src/newcertificatewizard/newcertificatewizard.h
+++ b/src/newcertificatewizard/newcertificatewizard.h
@@ -1,57 +1,60 @@
 /* -*- mode: c++; c-basic-offset:4 -*-
     newcertificatewizard/newcertificatewizard.h
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 #pragma once
 
 #include <QWizard>
 
 #include <utils/pimpl_ptr.h>
 
 #include <gpgme++/global.h>
 
 namespace Kleo
 {
 
 namespace NewCertificateUi
 {
 class WizardPage;
 }
 
 class NewCertificateWizard : public QWizard
 {
     Q_OBJECT
 public:
     explicit NewCertificateWizard(QWidget *parent = nullptr);
     ~NewCertificateWizard() override;
 
     void setProtocol(GpgME::Protocol protocol);
     GpgME::Protocol protocol() const;
 
     enum Pages {
         ChooseProtocolPageId,
         EnterDetailsPageId,
         OverviewPageId,
         KeyCreationPageId,
         ResultPageId,
 
         NumPages
     };
 
+protected:
+    void showEvent(QShowEvent *event) override;
+
 private:
     void resetProtocol();
     void restartAtEnterDetailsPage();
 
 private:
     class Private;
     kdtools::pimpl_ptr<Private> d;
     friend class ::Kleo::NewCertificateUi::WizardPage;
 };
 
 }