diff --git a/src/conf/cryptooperationsconfigwidget.cpp b/src/conf/cryptooperationsconfigwidget.cpp
index d8505264b..9dbaca182 100644
--- a/src/conf/cryptooperationsconfigwidget.cpp
+++ b/src/conf/cryptooperationsconfigwidget.cpp
@@ -1,244 +1,244 @@
 /*
     cryptooperationsconfigwidget.cpp
 
     This file is part of kleopatra, the KDE key manager
     SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB
 
     SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
     SPDX-FileContributor: Intevation GmbH
 
     SPDX-FileCopyrightText: 2022 g10 Code GmbH
     SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
 
     SPDX-License-Identifier: GPL-2.0-or-later
  */
 
 #include <config-kleopatra.h>
 
 #include "cryptooperationsconfigwidget.h"
 #include "kleopatra_debug.h"
 
 #include "fileoperationspreferences.h"
 #include "settings.h"
 
 #include <Libkleo/ChecksumDefinition>
 #include <Libkleo/KeyFilterManager>
 #include <libkleo/classifyconfig.h>
 
 #include <KConfig>
 #include <KConfigGroup>
 #include <KLocalizedString>
 #include <KMessageBox>
 #include <KSharedConfig>
 
 #include <QCheckBox>
 #include <QComboBox>
 #include <QDir>
 #include <QGroupBox>
 #include <QHBoxLayout>
 #include <QLabel>
 #include <QPushButton>
 #include <QRegularExpression>
 #include <QVBoxLayout>
 
 #include <memory>
 
 using namespace Kleo;
 using namespace Kleo::Config;
 
 CryptoOperationsConfigWidget::CryptoOperationsConfigWidget(QWidget *p, Qt::WindowFlags f)
     : QWidget{p, f}
 {
     setupGui();
 }
 
 void CryptoOperationsConfigWidget::setupGui()
 {
     auto baseLay = new QVBoxLayout(this);
 
     mPGPFileExtCB = new QCheckBox(i18n(R"(Create OpenPGP encrypted files with ".pgp" file extensions instead of ".gpg")"));
     mASCIIArmorCB = new QCheckBox(i18n("Create signed or encrypted files as text files."));
     mASCIIArmorCB->setToolTip(i18nc("@info",
                                     "Set this option to encode encrypted or signed files as base64 encoded text. "
                                     "So that they can be opened with an editor or sent in a mail body. "
                                     "This will increase file size by one third."));
     mTreatP7mEmailCB = new QCheckBox(i18nc("@option:check", "Treat .p7m files without extensions as mails."));
     mAutoDecryptVerifyCB = new QCheckBox(i18n("Automatically start operation based on input detection for decrypt/verify."));
     mAutoExtractArchivesCB = new QCheckBox(i18n("Automatically extract file archives after decryption"));
     mTmpDirCB = new QCheckBox(i18n("Create temporary decrypted files in the folder of the encrypted file."));
     mTmpDirCB->setToolTip(i18nc("@info", "Set this option to avoid using the users temporary directory."));
     mSymmetricOnlyCB = new QCheckBox(i18n("Use symmetric encryption only."));
     mSymmetricOnlyCB->setToolTip(i18nc("@info", "Set this option to disable public key encryption."));
     mPublicKeyOnlyCB = new QCheckBox(i18n("Use public-key encryption only."));
     mPublicKeyOnlyCB->setToolTip(i18nc("@info", "Set this option to disable password-based encryption."));
 
     connect(mSymmetricOnlyCB, &QCheckBox::toggled, this, [this]() {
         if (mSymmetricOnlyCB->isChecked()) {
             mPublicKeyOnlyCB->setChecked(false);
         }
     });
 
     connect(mPublicKeyOnlyCB, &QCheckBox::toggled, this, [this]() {
         if (mPublicKeyOnlyCB->isChecked()) {
             mSymmetricOnlyCB->setChecked(false);
         }
     });
 
     baseLay->addWidget(mPGPFileExtCB);
     baseLay->addWidget(mTreatP7mEmailCB);
     baseLay->addWidget(mAutoDecryptVerifyCB);
     baseLay->addWidget(mAutoExtractArchivesCB);
     baseLay->addWidget(mASCIIArmorCB);
     baseLay->addWidget(mTmpDirCB);
     baseLay->addWidget(mSymmetricOnlyCB);
     baseLay->addWidget(mPublicKeyOnlyCB);
 
     auto comboLay = new QGridLayout;
 
     mChecksumDefinitionCB.createWidgets(this);
     mChecksumDefinitionCB.label()->setText(i18n("Checksum program to use when creating checksum files:"));
     comboLay->addWidget(mChecksumDefinitionCB.label(), 0, 0);
     comboLay->addWidget(mChecksumDefinitionCB.widget(), 0, 1);
 
     mArchiveDefinitionCB.createWidgets(this);
     mArchiveDefinitionCB.label()->setText(i18n("Archive command to use when archiving files:"));
     comboLay->addWidget(mArchiveDefinitionCB.label(), 1, 0);
     comboLay->addWidget(mArchiveDefinitionCB.widget(), 1, 1);
 
     baseLay->addLayout(comboLay);
     baseLay->addStretch(1);
 
-    for (auto cb : findChildren<QCheckBox *>()) {
-        connect(cb, &QCheckBox::toggled, this, &CryptoOperationsConfigWidget::changed);
+    for (const auto checkboxes = findChildren<QCheckBox *>(); auto checkbox : checkboxes) {
+        connect(checkbox, &QCheckBox::toggled, this, &CryptoOperationsConfigWidget::changed);
     }
-    for (auto combo : findChildren<QComboBox *>()) {
-        connect(combo, &QComboBox::currentIndexChanged, this, &CryptoOperationsConfigWidget::changed);
+    for (const auto comboboxes = findChildren<QComboBox *>(); auto combobox : comboboxes) {
+        connect(combobox, &QComboBox::currentIndexChanged, this, &CryptoOperationsConfigWidget::changed);
     }
 }
 
 CryptoOperationsConfigWidget::~CryptoOperationsConfigWidget()
 {
 }
 
 void CryptoOperationsConfigWidget::defaults()
 {
     FileOperationsPreferences filePrefs;
     filePrefs.setUsePGPFileExt(filePrefs.findItem(QStringLiteral("UsePGPFileExt"))->getDefault().toBool());
     filePrefs.setAutoDecryptVerify(filePrefs.findItem(QStringLiteral("AutoDecryptVerify"))->getDefault().toBool());
     filePrefs.setAutoExtractArchives(filePrefs.findItem(QStringLiteral("AutoExtractArchives"))->getDefault().toBool());
     filePrefs.setAddASCIIArmor(filePrefs.findItem(QStringLiteral("AddASCIIArmor"))->getDefault().toBool());
     filePrefs.setDontUseTmpDir(filePrefs.findItem(QStringLiteral("DontUseTmpDir"))->getDefault().toBool());
     filePrefs.setSymmetricEncryptionOnly(filePrefs.findItem(QStringLiteral("SymmetricEncryptionOnly"))->getDefault().toBool());
     filePrefs.setPublicKeyEncryptionOnly(filePrefs.findItem(QStringLiteral("PublicKeyEncryptionOnly"))->getDefault().toBool());
     filePrefs.setArchiveCommand(filePrefs.findItem(QStringLiteral("ArchiveCommand"))->getDefault().toString());
 
     ClassifyConfig classifyConfig;
     classifyConfig.setP7mWithoutExtensionAreEmail(classifyConfig.defaultP7mWithoutExtensionAreEmailValue());
 
     Settings settings;
     settings.setChecksumDefinitionId(settings.findItem(QStringLiteral("ChecksumDefinitionId"))->getDefault().toString());
 
     load(filePrefs, settings, classifyConfig);
 }
 
 void CryptoOperationsConfigWidget::load(const Kleo::FileOperationsPreferences &filePrefs,
                                         const Kleo::Settings &settings,
                                         const Kleo::ClassifyConfig &classifyConfig)
 {
     mPGPFileExtCB->setChecked(filePrefs.usePGPFileExt());
     mPGPFileExtCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("UsePGPFileExt")));
     mAutoDecryptVerifyCB->setChecked(filePrefs.autoDecryptVerify());
     mAutoDecryptVerifyCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("AutoDecryptVerify")));
     mAutoExtractArchivesCB->setChecked(filePrefs.autoExtractArchives());
     mAutoExtractArchivesCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("AutoExtractArchives")));
     mASCIIArmorCB->setChecked(filePrefs.addASCIIArmor());
     mASCIIArmorCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("AddASCIIArmor")));
     mTmpDirCB->setChecked(filePrefs.dontUseTmpDir());
     mTmpDirCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("DontUseTmpDir")));
     mSymmetricOnlyCB->setChecked(filePrefs.symmetricEncryptionOnly());
     mSymmetricOnlyCB->setEnabled(!filePrefs.isImmutable(QStringLiteral("SymmetricEncryptionOnly")));
     mPublicKeyOnlyCB->setChecked(filePrefs.publicKeyEncryptionOnly());
     mPublicKeyOnlyCB->setEnabled(!filePrefs.isPublicKeyEncryptionOnlyImmutable());
     mTreatP7mEmailCB->setChecked(classifyConfig.p7mWithoutExtensionAreEmail());
     mTreatP7mEmailCB->setEnabled(!classifyConfig.isP7mWithoutExtensionAreEmailImmutable());
 
     const auto defaultChecksumDefinitionId = settings.checksumDefinitionId();
     {
         const auto index = mChecksumDefinitionCB.widget()->findData(defaultChecksumDefinitionId);
         if (index >= 0) {
             mChecksumDefinitionCB.widget()->setCurrentIndex(index);
         } else {
             qCWarning(KLEOPATRA_LOG) << "No checksum definition found with id" << defaultChecksumDefinitionId;
         }
     }
     mChecksumDefinitionCB.setEnabled(!settings.isImmutable(QStringLiteral("ChecksumDefinitionId")));
 
     const auto ad_default_id = filePrefs.archiveCommand();
     {
         const auto index = mArchiveDefinitionCB.widget()->findData(ad_default_id);
         if (index >= 0) {
             mArchiveDefinitionCB.widget()->setCurrentIndex(index);
         } else {
             qCWarning(KLEOPATRA_LOG) << "No archive definition found with id" << ad_default_id;
         }
     }
     mArchiveDefinitionCB.setEnabled(!filePrefs.isImmutable(QStringLiteral("ArchiveCommand")));
 }
 
 void CryptoOperationsConfigWidget::load()
 {
     mChecksumDefinitionCB.widget()->clear();
     const auto cds = ChecksumDefinition::getChecksumDefinitions();
     for (const std::shared_ptr<ChecksumDefinition> &cd : cds) {
         mChecksumDefinitionCB.widget()->addItem(cd->label(), QVariant{cd->id()});
     }
 
     // This is a weird hack but because we are a KCM we can't link
     // against ArchiveDefinition which pulls in loads of other classes.
     // So we do the parsing which archive definitions exist here ourself.
     mArchiveDefinitionCB.widget()->clear();
     if (KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("libkleopatrarc"))) {
         const QStringList groups = config->groupList().filter(QRegularExpression(QStringLiteral("^Archive Definition #")));
         for (const QString &group : groups) {
             const KConfigGroup cGroup(config, group);
             const QString id = cGroup.readEntryUntranslated(QStringLiteral("id"));
             const QString name = cGroup.readEntry("Name");
             mArchiveDefinitionCB.widget()->addItem(name, QVariant(id));
         }
     }
 
     load(FileOperationsPreferences{}, Settings{}, ClassifyConfig{});
 }
 
 void CryptoOperationsConfigWidget::save()
 {
     FileOperationsPreferences filePrefs;
     filePrefs.setUsePGPFileExt(mPGPFileExtCB->isChecked());
     filePrefs.setAutoDecryptVerify(mAutoDecryptVerifyCB->isChecked());
     filePrefs.setAutoExtractArchives(mAutoExtractArchivesCB->isChecked());
     filePrefs.setAddASCIIArmor(mASCIIArmorCB->isChecked());
     filePrefs.setDontUseTmpDir(mTmpDirCB->isChecked());
     filePrefs.setSymmetricEncryptionOnly(mSymmetricOnlyCB->isChecked());
     filePrefs.setPublicKeyEncryptionOnly(mPublicKeyOnlyCB->isChecked());
 
     Settings settings;
     const int idx = mChecksumDefinitionCB.widget()->currentIndex();
     if (idx >= 0) {
         const auto id = mChecksumDefinitionCB.widget()->itemData(idx).toString();
         settings.setChecksumDefinitionId(id);
     }
     settings.save();
 
     const int aidx = mArchiveDefinitionCB.widget()->currentIndex();
     if (aidx >= 0) {
         const QString id = mArchiveDefinitionCB.widget()->itemData(aidx).toString();
         filePrefs.setArchiveCommand(id);
     }
     filePrefs.save();
 
     ClassifyConfig classifyConfig;
     classifyConfig.setP7mWithoutExtensionAreEmail(mTreatP7mEmailCB->isChecked());
     classifyConfig.save();
 }
 
 #include "moc_cryptooperationsconfigwidget.cpp"
diff --git a/src/crypto/gui/signencryptwidget.cpp b/src/crypto/gui/signencryptwidget.cpp
index c03f7c819..b66ff939e 100644
--- a/src/crypto/gui/signencryptwidget.cpp
+++ b/src/crypto/gui/signencryptwidget.cpp
@@ -1,935 +1,935 @@
 /*  crypto/gui/signencryptwidget.cpp
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
     SPDX-FileContributor: Intevation GmbH
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 #include "signencryptwidget.h"
 
 #include "kleopatra_debug.h"
 
 #include "certificatelineedit.h"
 #include "fileoperationspreferences.h"
 #include "kleopatraapplication.h"
 #include "settings.h"
 #include "unknownrecipientwidget.h"
 
 #include "dialogs/certificateselectiondialog.h"
 #include "utils/gui-helper.h"
 
 #include <QCheckBox>
 #include <QGroupBox>
 #include <QHBoxLayout>
 #include <QLabel>
 #include <QScrollArea>
 #include <QScrollBar>
 #include <QVBoxLayout>
 
 #include <Libkleo/Algorithm>
 #include <Libkleo/Compliance>
 #include <Libkleo/DefaultKeyFilter>
 #include <Libkleo/ExpiryChecker>
 #include <Libkleo/ExpiryCheckerConfig>
 #include <Libkleo/ExpiryCheckerSettings>
 #include <Libkleo/Formatting>
 #include <Libkleo/KeyCache>
 #include <Libkleo/KeyHelpers>
 #include <Libkleo/KeyListModel>
 #include <Libkleo/KeyListSortFilterProxyModel>
 #include <Libkleo/UserIDSelectionCombo>
 
 #include <Libkleo/GnuPG>
 
 #include <KConfigGroup>
 #include <KLocalizedString>
 #include <KMessageBox>
 #include <KMessageWidget>
 #include <KSharedConfig>
 
 using namespace Kleo;
 using namespace Kleo::Dialogs;
 using namespace GpgME;
 
 namespace
 {
 class SignCertificateFilter : public DefaultKeyFilter
 {
 public:
     SignCertificateFilter(GpgME::Protocol proto)
         : DefaultKeyFilter()
     {
         setIsBad(DefaultKeyFilter::NotSet);
         setHasSecret(DefaultKeyFilter::Set);
         setCanSign(DefaultKeyFilter::Set);
         setValidIfSMIME(DefaultKeyFilter::Set);
 
         if (proto == GpgME::OpenPGP) {
             setIsOpenPGP(DefaultKeyFilter::Set);
         } else if (proto == GpgME::CMS) {
             setIsOpenPGP(DefaultKeyFilter::NotSet);
         }
     }
 };
 class EncryptCertificateFilter : public DefaultKeyFilter
 {
 public:
     EncryptCertificateFilter(GpgME::Protocol proto)
         : DefaultKeyFilter()
     {
         setIsBad(DefaultKeyFilter::NotSet);
         setCanEncrypt(DefaultKeyFilter::Set);
         setValidIfSMIME(DefaultKeyFilter::Set);
 
         if (proto == GpgME::OpenPGP) {
             setIsOpenPGP(DefaultKeyFilter::Set);
         } else if (proto == GpgME::CMS) {
             setIsOpenPGP(DefaultKeyFilter::NotSet);
         }
     }
 };
 class EncryptSelfCertificateFilter : public EncryptCertificateFilter
 {
 public:
     EncryptSelfCertificateFilter(GpgME::Protocol proto)
         : EncryptCertificateFilter(proto)
     {
         setRevoked(DefaultKeyFilter::NotSet);
         setExpired(DefaultKeyFilter::NotSet);
         setCanEncrypt(DefaultKeyFilter::Set);
         setHasSecret(DefaultKeyFilter::Set);
         setValidIfSMIME(DefaultKeyFilter::Set);
     }
 };
 }
 
 class SignEncryptWidget::Private
 {
     SignEncryptWidget *const q;
 
 public:
     struct RecipientWidgets {
         CertificateLineEdit *edit;
         KMessageWidget *expiryMessage;
     };
 
     explicit Private(SignEncryptWidget *qq, bool sigEncExclusive)
         : q{qq}
         , mModel{AbstractKeyListModel::createFlatKeyListModel(qq)}
         , mIsExclusive{sigEncExclusive}
     {
     }
 
     CertificateLineEdit *addRecipientWidget();
     /* Inserts a new recipient widget after widget @p after or at the end
      * if @p after is null. */
     CertificateLineEdit *insertRecipientWidget(CertificateLineEdit *after);
     void recpRemovalRequested(const RecipientWidgets &recipient);
     void onProtocolChanged();
     void updateCheckBoxes();
     ExpiryChecker *expiryChecker();
     void updateExpiryMessages(KMessageWidget *w, const GpgME::UserID &userID, ExpiryChecker::CheckFlags flags);
     void updateAllExpiryMessages();
 
 public:
     UserIDSelectionCombo *mSigSelect = nullptr;
     KMessageWidget *mSignKeyExpiryMessage = nullptr;
     UserIDSelectionCombo *mSelfSelect = nullptr;
     KMessageWidget *mEncryptToSelfKeyExpiryMessage = nullptr;
     std::vector<RecipientWidgets> mRecpWidgets;
     QList<UnknownRecipientWidget *> mUnknownWidgets;
     QList<GpgME::Key> mAddedKeys;
     QList<KeyGroup> mAddedGroups;
     QVBoxLayout *mRecpLayout = nullptr;
     Operations mOp;
     AbstractKeyListModel *mModel = nullptr;
     QCheckBox *mSymmetric = nullptr;
     QCheckBox *mSigChk = nullptr;
     QLabel *mEncOtherLabel = nullptr;
     QCheckBox *mEncSelfChk = nullptr;
     GpgME::Protocol mCurrentProto = GpgME::UnknownProtocol;
     const bool mIsExclusive;
     std::unique_ptr<ExpiryChecker> mExpiryChecker;
 };
 
 SignEncryptWidget::SignEncryptWidget(QWidget *parent, bool sigEncExclusive)
     : QWidget{parent}
     , d{new Private{this, sigEncExclusive}}
 {
     auto lay = new QVBoxLayout(this);
     lay->setContentsMargins(0, 0, 0, 0);
 
     d->mModel->useKeyCache(true, KeyList::IncludeGroups);
 
     const bool haveSecretKeys = !KeyCache::instance()->secretKeys().empty();
     const bool havePublicKeys = !KeyCache::instance()->keys().empty();
     const bool symmetricOnly = FileOperationsPreferences().symmetricEncryptionOnly();
     const bool publicKeyOnly = FileOperationsPreferences().publicKeyEncryptionOnly();
 
     /* The signature selection */
     {
         auto sigGrp = new QGroupBox{i18nc("@title:group", "Prove authenticity (sign)"), this};
         d->mSigChk = new QCheckBox{i18n("Sign as:"), this};
         d->mSigChk->setEnabled(haveSecretKeys);
         d->mSigChk->setChecked(haveSecretKeys);
 
         d->mSigSelect = new UserIDSelectionCombo{KeyUsage::Sign, this};
         d->mSigSelect->setEnabled(d->mSigChk->isChecked());
 
         d->mSignKeyExpiryMessage = new KMessageWidget{this};
         d->mSignKeyExpiryMessage->setVisible(false);
 
         connect(d->mSigSelect, &UserIDSelectionCombo::certificateSelectionRequested, this, [this]() {
             ownCertificateSelectionRequested(CertificateSelectionDialog::SignOnly, d->mSigSelect);
         });
         connect(d->mSigSelect, &UserIDSelectionCombo::customItemSelected, this, [this]() {
             updateOp();
             d->updateExpiryMessages(d->mSignKeyExpiryMessage, signUserId(), ExpiryChecker::OwnSigningKey);
         });
 
         auto groupLayout = new QGridLayout{sigGrp};
         groupLayout->setColumnStretch(1, 1);
         groupLayout->addWidget(d->mSigChk, 0, 0);
         groupLayout->addWidget(d->mSigSelect, 0, 1);
         groupLayout->addWidget(d->mSignKeyExpiryMessage, 1, 1);
         lay->addWidget(sigGrp);
 
         connect(d->mSigChk, &QCheckBox::toggled, this, [this](bool checked) {
             d->mSigSelect->setEnabled(checked);
             updateOp();
             d->updateExpiryMessages(d->mSignKeyExpiryMessage, signUserId(), ExpiryChecker::OwnSigningKey);
         });
         connect(d->mSigSelect, &UserIDSelectionCombo::currentKeyChanged, this, [this]() {
             updateOp();
             d->updateExpiryMessages(d->mSignKeyExpiryMessage, signUserId(), ExpiryChecker::OwnSigningKey);
         });
     }
 
     // Recipient selection
     {
         auto encBox = new QGroupBox{i18nc("@title:group", "Encrypt"), this};
         auto encBoxLay = new QVBoxLayout{encBox};
         auto recipientGrid = new QGridLayout;
         int row = 0;
 
         // Own key
         d->mEncSelfChk = new QCheckBox{i18n("Encrypt for me:"), this};
         d->mEncSelfChk->setEnabled(haveSecretKeys && !symmetricOnly);
         d->mEncSelfChk->setChecked(haveSecretKeys && !symmetricOnly);
         d->mSelfSelect = new UserIDSelectionCombo{KeyUsage::Encrypt, this};
         d->mSelfSelect->setEnabled(d->mEncSelfChk->isChecked());
 
         connect(d->mSelfSelect, &UserIDSelectionCombo::certificateSelectionRequested, this, [this]() {
             ownCertificateSelectionRequested(CertificateSelectionDialog::EncryptOnly, d->mSelfSelect);
         });
         connect(d->mSelfSelect, &UserIDSelectionCombo::customItemSelected, this, [this]() {
             updateOp();
             d->updateExpiryMessages(d->mEncryptToSelfKeyExpiryMessage, selfUserId(), ExpiryChecker::OwnEncryptionKey);
         });
 
         d->mEncryptToSelfKeyExpiryMessage = new KMessageWidget{this};
         d->mEncryptToSelfKeyExpiryMessage->setVisible(false);
         recipientGrid->addWidget(d->mEncSelfChk, row, 0);
         recipientGrid->addWidget(d->mSelfSelect, row, 1);
         row++;
         recipientGrid->addWidget(d->mEncryptToSelfKeyExpiryMessage, row, 1);
 
         // Checkbox for other keys
         row++;
         d->mEncOtherLabel = new QLabel(i18nc("@label", "Encrypt for others:"), this);
         d->mEncOtherLabel->setEnabled(havePublicKeys && !symmetricOnly);
         recipientGrid->addWidget(d->mEncOtherLabel, row, 0, Qt::AlignTop | Qt::AlignRight);
         d->mRecpLayout = new QVBoxLayout;
         recipientGrid->addLayout(d->mRecpLayout, row, 1);
         recipientGrid->setRowStretch(row + 1, 1);
 
         // Scroll area for other keys
         auto recipientWidget = new QWidget;
         auto recipientScroll = new QScrollArea;
         recipientWidget->setLayout(recipientGrid);
         recipientScroll->setWidget(recipientWidget);
         recipientScroll->setWidgetResizable(true);
         recipientScroll->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
         recipientScroll->setFrameStyle(QFrame::NoFrame);
         recipientScroll->setFocusPolicy(Qt::NoFocus);
         recipientGrid->setContentsMargins(0, 0, 0, 0);
         encBoxLay->addWidget(recipientScroll, 1);
 
         auto bar = recipientScroll->verticalScrollBar();
         connect(bar, &QScrollBar::rangeChanged, this, [bar](int, int max) {
             bar->setValue(max);
         });
 
         d->addRecipientWidget();
 
         // Checkbox for password
         d->mSymmetric = new QCheckBox(i18n("Encrypt with password. Anyone you share the password with can read the data."));
         d->mSymmetric->setToolTip(i18nc("Tooltip information for symmetric encryption",
                                         "Additionally to the keys of the recipients you can encrypt your data with a password. "
                                         "Anyone who has the password can read the data without any secret key. "
                                         "Using a password is <b>less secure</b> then public key cryptography. Even if you pick a very strong password."));
         d->mSymmetric->setChecked((symmetricOnly || !havePublicKeys) && !publicKeyOnly);
         d->mSymmetric->setEnabled(!publicKeyOnly);
         encBoxLay->addWidget(d->mSymmetric);
 
         // Connect it
         connect(d->mEncSelfChk, &QCheckBox::toggled, this, [this](bool checked) {
             d->mSelfSelect->setEnabled(checked);
             updateOp();
             d->updateExpiryMessages(d->mEncryptToSelfKeyExpiryMessage, selfUserId(), ExpiryChecker::OwnEncryptionKey);
         });
         connect(d->mSelfSelect, &UserIDSelectionCombo::currentKeyChanged, this, [this]() {
             updateOp();
             d->updateExpiryMessages(d->mEncryptToSelfKeyExpiryMessage, selfUserId(), ExpiryChecker::OwnEncryptionKey);
         });
         connect(d->mSymmetric, &QCheckBox::toggled, this, &SignEncryptWidget::updateOp);
 
         if (d->mIsExclusive) {
             connect(d->mEncSelfChk, &QCheckBox::toggled, this, [this](bool value) {
                 if (d->mCurrentProto != GpgME::CMS) {
                     return;
                 }
                 if (value) {
                     d->mSigChk->setChecked(false);
                 }
             });
             connect(d->mSigChk, &QCheckBox::toggled, this, [this](bool value) {
                 if (d->mCurrentProto != GpgME::CMS) {
                     return;
                 }
                 if (value) {
                     d->mEncSelfChk->setChecked(false);
                     // Copying the vector makes sure that all items are actually deleted.
                     for (const auto &widget : std::vector(d->mRecpWidgets)) {
                         d->recpRemovalRequested(widget);
                     }
                     d->addRecipientWidget();
                 }
             });
         }
 
         // Ensure that the d->mSigChk is aligned together with the encryption check boxes.
         d->mSigChk->setMinimumWidth(qMax(d->mEncOtherLabel->width(), d->mEncSelfChk->width()));
 
         lay->addWidget(encBox);
     }
 
     connect(KeyCache::instance().get(), &Kleo::KeyCache::keysMayHaveChanged, this, [this]() {
         d->updateCheckBoxes();
         d->updateAllExpiryMessages();
     });
     connect(KleopatraApplication::instance(), &KleopatraApplication::configurationChanged, this, [this]() {
         d->updateCheckBoxes();
         d->mExpiryChecker.reset();
         d->updateAllExpiryMessages();
     });
 
     loadKeys();
     d->onProtocolChanged();
     updateOp();
 }
 
 SignEncryptWidget::~SignEncryptWidget() = default;
 
 void SignEncryptWidget::setSignAsText(const QString &text)
 {
     d->mSigChk->setText(text);
 }
 
 void SignEncryptWidget::setEncryptForMeText(const QString &text)
 {
     d->mEncSelfChk->setText(text);
 }
 
 void SignEncryptWidget::setEncryptWithPasswordText(const QString &text)
 {
     d->mSymmetric->setText(text);
 }
 
 CertificateLineEdit *SignEncryptWidget::Private::addRecipientWidget()
 {
     return insertRecipientWidget(nullptr);
 }
 
 CertificateLineEdit *SignEncryptWidget::Private::insertRecipientWidget(CertificateLineEdit *after)
 {
     Q_ASSERT(!after || mRecpLayout->indexOf(after) != -1);
 
     const auto index = after ? mRecpLayout->indexOf(after) + 2 : mRecpLayout->count();
 
     const RecipientWidgets recipient{new CertificateLineEdit{mModel, KeyUsage::Encrypt, new EncryptCertificateFilter{mCurrentProto}, q}, new KMessageWidget{q}};
     recipient.edit->setAccessibleNameOfLineEdit(i18nc("text for screen readers", "recipient key"));
     recipient.edit->setEnabled(!KeyCache::instance()->keys().empty() && !FileOperationsPreferences().symmetricEncryptionOnly());
     recipient.expiryMessage->setVisible(false);
     if (static_cast<unsigned>(index / 2) < mRecpWidgets.size()) {
         mRecpWidgets.insert(mRecpWidgets.begin() + index / 2, recipient);
     } else {
         mRecpWidgets.push_back(recipient);
     }
 
     if (mRecpLayout->count() > 0) {
         auto prevWidget = after ? after : mRecpLayout->itemAt(mRecpLayout->count() - 1)->widget();
         Kleo::forceSetTabOrder(prevWidget, recipient.edit);
         Kleo::forceSetTabOrder(recipient.edit, recipient.expiryMessage);
     }
     mRecpLayout->insertWidget(index, recipient.edit);
     mRecpLayout->insertWidget(index + 1, recipient.expiryMessage);
 
     connect(recipient.edit, &CertificateLineEdit::keyChanged, q, &SignEncryptWidget::recipientsChanged);
     connect(recipient.edit, &CertificateLineEdit::editingStarted, q, &SignEncryptWidget::recipientsChanged);
     connect(recipient.edit, &CertificateLineEdit::cleared, q, &SignEncryptWidget::recipientsChanged);
     connect(recipient.edit, &CertificateLineEdit::certificateSelectionRequested, q, [this, recipient]() {
         q->certificateSelectionRequested(recipient.edit);
     });
 
     if (mIsExclusive) {
         connect(recipient.edit, &CertificateLineEdit::keyChanged, q, [this]() {
             if (mCurrentProto != GpgME::CMS) {
                 return;
             }
             mSigChk->setChecked(false);
         });
     }
 
     return recipient.edit;
 }
 
 void SignEncryptWidget::addRecipient(const Key &key)
 {
     CertificateLineEdit *certSel = d->addRecipientWidget();
     if (!key.isNull()) {
         certSel->setKey(key);
         d->mAddedKeys << key;
     }
 }
 
 void SignEncryptWidget::addRecipient(const KeyGroup &group)
 {
     CertificateLineEdit *certSel = d->addRecipientWidget();
     if (!group.isNull()) {
         certSel->setGroup(group);
         d->mAddedGroups << group;
     }
 }
 
 void SignEncryptWidget::ownCertificateSelectionRequested(CertificateSelectionDialog::Options options, UserIDSelectionCombo *combo)
 {
     CertificateSelectionDialog dialog{this};
     dialog.setOptions(CertificateSelectionDialog::Options( //
                           CertificateSelectionDialog::SingleSelection | //
                           CertificateSelectionDialog::SecretKeys | //
                           CertificateSelectionDialog::optionsFromProtocol(d->mCurrentProto))
                       | //
                       options);
 
     if (dialog.exec()) {
         auto userId = dialog.selectedUserIDs()[0];
         auto index = combo->findUserId(userId);
         if (index == -1) {
             combo->appendCustomItem(QIcon::fromTheme(QStringLiteral("emblem-error")), Formatting::summaryLine(userId), QVariant::fromValue(userId));
             index = combo->combo()->count() - 1;
         }
         combo->combo()->setCurrentIndex(index);
     }
 
     recipientsChanged();
 }
 
 void SignEncryptWidget::certificateSelectionRequested(CertificateLineEdit *certificateLineEdit)
 {
     CertificateSelectionDialog dlg{this};
 
     dlg.setOptions(CertificateSelectionDialog::Options( //
         CertificateSelectionDialog::MultiSelection | //
         CertificateSelectionDialog::EncryptOnly | //
         CertificateSelectionDialog::optionsFromProtocol(d->mCurrentProto) | //
         CertificateSelectionDialog::IncludeGroups));
 
     if (!certificateLineEdit->key().isNull()) {
         const auto key = certificateLineEdit->key();
         const auto name = QString::fromUtf8(key.userID(0).name());
         const auto email = QString::fromUtf8(key.userID(0).email());
         dlg.setStringFilter(!name.isEmpty() ? name : email);
     } else if (!certificateLineEdit->group().isNull()) {
         dlg.setStringFilter(certificateLineEdit->group().name());
     } else if (!certificateLineEdit->userID().isNull()) {
         const auto userID = certificateLineEdit->userID();
         const auto name = QString::fromUtf8(userID.name());
         const auto email = QString::fromUtf8(userID.email());
         dlg.setStringFilter(!name.isEmpty() ? name : email);
     } else {
         dlg.setStringFilter(certificateLineEdit->text());
     }
 
     if (dlg.exec()) {
         const std::vector<UserID> userIds = dlg.selectedUserIDs();
         const std::vector<KeyGroup> groups = dlg.selectedGroups();
         if (userIds.size() == 0 && groups.size() == 0) {
             return;
         }
         CertificateLineEdit *certWidget = nullptr;
         for (const auto &userId : userIds) {
             if (!certWidget) {
                 certWidget = certificateLineEdit;
             } else {
                 certWidget = d->insertRecipientWidget(certWidget);
             }
             certWidget->setUserID(userId);
         }
         for (const KeyGroup &group : groups) {
             if (!certWidget) {
                 certWidget = certificateLineEdit;
             } else {
                 certWidget = d->insertRecipientWidget(certWidget);
             }
             certWidget->setGroup(group);
         }
     }
 
     recipientsChanged();
 }
 
 void SignEncryptWidget::clearAddedRecipients()
 {
     for (auto w : std::as_const(d->mUnknownWidgets)) {
         d->mRecpLayout->removeWidget(w);
         delete w;
     }
 
     for (auto &key : std::as_const(d->mAddedKeys)) {
         removeRecipient(key);
     }
 
     for (auto &group : std::as_const(d->mAddedGroups)) {
         removeRecipient(group);
     }
 }
 
 void SignEncryptWidget::addUnknownRecipient(const char *keyID)
 {
     auto unknownWidget = new UnknownRecipientWidget(keyID);
     d->mUnknownWidgets << unknownWidget;
 
     if (d->mRecpLayout->count() > 0) {
         auto lastWidget = d->mRecpLayout->itemAt(d->mRecpLayout->count() - 1)->widget();
         setTabOrder(lastWidget, unknownWidget);
     }
     d->mRecpLayout->addWidget(unknownWidget);
 
     connect(KeyCache::instance().get(), &Kleo::KeyCache::keysMayHaveChanged, this, [this]() {
         // Check if any unknown recipient can now be found.
-        for (auto w : d->mUnknownWidgets) {
+        for (auto w : std::as_const(d->mUnknownWidgets)) {
             auto key = KeyCache::instance()->findByKeyIDOrFingerprint(w->keyID().toLatin1().constData());
             if (key.isNull()) {
                 std::vector<std::string> subids;
                 subids.push_back(std::string(w->keyID().toLatin1().constData()));
                 for (const auto &subkey : KeyCache::instance()->findSubkeysByKeyID(subids)) {
                     key = subkey.parent();
                 }
             }
             if (key.isNull()) {
                 continue;
             }
             // Key is now available replace by line edit.
             qCDebug(KLEOPATRA_LOG) << "Removing widget for keyid: " << w->keyID();
             d->mRecpLayout->removeWidget(w);
             d->mUnknownWidgets.removeAll(w);
             delete w;
             addRecipient(key);
         }
     });
 }
 
 void SignEncryptWidget::recipientsChanged()
 {
     const bool hasEmptyRecpWidget = std::any_of(std::cbegin(d->mRecpWidgets), std::cend(d->mRecpWidgets), [](auto w) {
         return w.edit->isEmpty();
     });
     if (!hasEmptyRecpWidget) {
         d->addRecipientWidget();
     }
     updateOp();
     for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
         if (!recipient.edit->isEditingInProgress() || recipient.edit->isEmpty()) {
             d->updateExpiryMessages(recipient.expiryMessage, recipient.edit->userID(), ExpiryChecker::EncryptionKey);
         }
     }
 }
 
 UserID SignEncryptWidget::signUserId() const
 {
     if (d->mSigSelect->isEnabled()) {
         return d->mSigSelect->currentUserID();
     }
     return UserID();
 }
 
 UserID SignEncryptWidget::selfUserId() const
 {
     if (d->mSelfSelect->isEnabled()) {
         return d->mSelfSelect->currentUserID();
     }
     return UserID();
 }
 
 std::vector<Key> SignEncryptWidget::recipients() const
 {
     std::vector<Key> ret;
     for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
         const auto *const w = recipient.edit;
         if (!w->isEnabled()) {
             // If one is disabled, all are disabled.
             break;
         }
         const Key k = w->key();
         const KeyGroup g = w->group();
         const UserID u = w->userID();
         if (!k.isNull()) {
             ret.push_back(k);
         } else if (!g.isNull()) {
             const auto keys = g.keys();
             std::copy(keys.begin(), keys.end(), std::back_inserter(ret));
         } else if (!u.isNull()) {
             ret.push_back(u.parent());
         }
     }
     const Key k = selfUserId().parent();
     if (!k.isNull()) {
         ret.push_back(k);
     }
     return ret;
 }
 
 bool SignEncryptWidget::isDeVsAndValid() const
 {
     if (!signUserId().isNull() && !DeVSCompliance::userIDIsCompliant(signUserId())) {
         return false;
     }
 
     if (!selfUserId().isNull() && !DeVSCompliance::userIDIsCompliant(selfUserId())) {
         return false;
     }
 
     for (const auto &key : recipients()) {
         if (!DeVSCompliance::keyIsCompliant(key)) {
             return false;
         }
     }
 
     return true;
 }
 
 static QString expiryMessage(const ExpiryChecker::Result &result)
 {
     if (result.expiration.certificate.isNull()) {
         return {};
     }
     switch (result.expiration.status) {
     case ExpiryChecker::Expired:
         return i18nc("@info", "This certificate is expired.");
     case ExpiryChecker::ExpiresSoon: {
         if (result.expiration.duration.count() == 0) {
             return i18nc("@info", "This certificate expires today.");
         } else {
             return i18ncp("@info", "This certificate expires tomorrow.", "This certificate expires in %1 days.", result.expiration.duration.count());
         }
     }
     case ExpiryChecker::NoSuitableSubkey:
         if (result.checkFlags & ExpiryChecker::EncryptionKey) {
             return i18nc("@info", "This certificate cannot be used for encryption.");
         } else {
             return i18nc("@info", "This certificate cannot be used for signing.");
         }
     case ExpiryChecker::InvalidKey:
     case ExpiryChecker::InvalidCheckFlags:
         break; // wrong usage of ExpiryChecker; can be ignored
     case ExpiryChecker::NotNearExpiry:;
     }
     return {};
 }
 
 void SignEncryptWidget::updateOp()
 {
     const std::vector<Key> recp = recipients();
 
     Operations op = NoOperation;
     if (!signUserId().isNull()) {
         op |= Sign;
     }
     if (!recp.empty() || encryptSymmetric()) {
         op |= Encrypt;
     }
     d->mOp = op;
     Q_EMIT operationChanged(d->mOp);
     Q_EMIT keysChanged();
 }
 
 SignEncryptWidget::Operations SignEncryptWidget::currentOp() const
 {
     return d->mOp;
 }
 
 namespace
 {
 bool recipientWidgetHasFocus(QWidget *w)
 {
     // check if w (or its focus proxy) or a child widget of w has focus
     return w->hasFocus() || w->isAncestorOf(qApp->focusWidget());
 }
 }
 
 void SignEncryptWidget::Private::recpRemovalRequested(const RecipientWidgets &recipient)
 {
     if (!recipient.edit) {
         return;
     }
     if (recipientWidgetHasFocus(recipient.edit) || recipientWidgetHasFocus(recipient.expiryMessage)) {
         const int index = mRecpLayout->indexOf(recipient.edit);
         const auto focusWidget = (index < mRecpLayout->count() - 2) ? //
             mRecpLayout->itemAt(index + 2)->widget()
                                                                     : mRecpLayout->itemAt(mRecpLayout->count() - 3)->widget();
         focusWidget->setFocus();
     }
     mRecpLayout->removeWidget(recipient.expiryMessage);
     mRecpLayout->removeWidget(recipient.edit);
     const auto it = std::find_if(std::begin(mRecpWidgets), std::end(mRecpWidgets), [recipient](const auto &r) {
         return r.edit == recipient.edit;
     });
     mRecpWidgets.erase(it);
     recipient.expiryMessage->deleteLater();
     recipient.edit->deleteLater();
 }
 
 void SignEncryptWidget::removeRecipient(const GpgME::Key &key)
 {
     for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
         const auto editKey = recipient.edit->key();
         if (key.isNull() && editKey.isNull()) {
             d->recpRemovalRequested(recipient);
             return;
         }
         if (editKey.primaryFingerprint() && key.primaryFingerprint() && !strcmp(editKey.primaryFingerprint(), key.primaryFingerprint())) {
             d->recpRemovalRequested(recipient);
             return;
         }
     }
 }
 
 void SignEncryptWidget::removeRecipient(const KeyGroup &group)
 {
     for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
         const auto editGroup = recipient.edit->group();
         if (group.isNull() && editGroup.isNull()) {
             d->recpRemovalRequested(recipient);
             return;
         }
         if (editGroup.name() == group.name()) {
             d->recpRemovalRequested(recipient);
             return;
         }
     }
 }
 
 bool SignEncryptWidget::encryptSymmetric() const
 {
     return d->mSymmetric->isChecked();
 }
 
 void SignEncryptWidget::loadKeys()
 {
     KConfigGroup keys(KSharedConfig::openConfig(), QStringLiteral("SignEncryptKeys"));
     auto cache = KeyCache::instance();
     d->mSigSelect->setDefaultKey(keys.readEntry("SigningKey", QString()));
     d->mSelfSelect->setDefaultKey(keys.readEntry("EncryptKey", QString()));
 }
 
 void SignEncryptWidget::saveOwnKeys() const
 {
     KConfigGroup keys(KSharedConfig::openConfig(), QStringLiteral("SignEncryptKeys"));
     auto sigKey = d->mSigSelect->currentKey();
     auto encKey = d->mSelfSelect->currentKey();
     if (!sigKey.isNull()) {
         keys.writeEntry("SigningKey", sigKey.primaryFingerprint());
     }
     if (!encKey.isNull()) {
         keys.writeEntry("EncryptKey", encKey.primaryFingerprint());
     }
 }
 
 void SignEncryptWidget::setSigningChecked(bool value)
 {
     d->mSigChk->setChecked(value && !KeyCache::instance()->secretKeys().empty());
 }
 
 void SignEncryptWidget::setEncryptionChecked(bool checked)
 {
     if (checked) {
         const bool haveSecretKeys = !KeyCache::instance()->secretKeys().empty();
         const bool havePublicKeys = !KeyCache::instance()->keys().empty();
         const bool symmetricOnly = FileOperationsPreferences().symmetricEncryptionOnly();
         const bool publicKeyOnly = FileOperationsPreferences().publicKeyEncryptionOnly();
         d->mEncSelfChk->setChecked(haveSecretKeys && !symmetricOnly);
         d->mSymmetric->setChecked((symmetricOnly || !havePublicKeys) && !publicKeyOnly);
     } else {
         d->mEncSelfChk->setChecked(false);
         d->mSymmetric->setChecked(false);
     }
 }
 
 void SignEncryptWidget::setProtocol(GpgME::Protocol proto)
 {
     if (d->mCurrentProto == proto) {
         return;
     }
     d->mCurrentProto = proto;
     d->onProtocolChanged();
 }
 
 void Kleo::SignEncryptWidget::Private::onProtocolChanged()
 {
     auto encryptForOthers = q->recipients().size() > 0;
     mSigSelect->setKeyFilter(std::shared_ptr<KeyFilter>(new SignCertificateFilter(mCurrentProto)));
     mSelfSelect->setKeyFilter(std::shared_ptr<KeyFilter>(new EncryptSelfCertificateFilter(mCurrentProto)));
     const auto encFilter = std::shared_ptr<KeyFilter>(new EncryptCertificateFilter(mCurrentProto));
     for (const auto &widget : std::vector(mRecpWidgets)) {
         recpRemovalRequested(widget);
     }
     addRecipientWidget();
     for (const auto &recipient : std::as_const(mRecpWidgets)) {
         recipient.edit->setKeyFilter(encFilter);
     }
 
     if (mIsExclusive) {
         mSymmetric->setDisabled(mCurrentProto == GpgME::CMS);
         if (mSymmetric->isChecked() && mCurrentProto == GpgME::CMS) {
             mSymmetric->setChecked(false);
         }
         if (mSigChk->isChecked() && mCurrentProto == GpgME::CMS && (mEncSelfChk->isChecked() || encryptForOthers)) {
             mSigChk->setChecked(false);
         }
     }
 }
 
 static bool recipientIsOkay(const CertificateLineEdit *edit)
 {
     if (!edit->isEnabled() || edit->isEmpty()) {
         return true;
     }
     if (!edit->hasAcceptableInput()) {
         return false;
     }
     if (const auto userID = edit->userID(); !userID.isNull()) {
         return Kleo::canBeUsedForEncryption(userID.parent()) && !userID.isBad();
     }
     if (const auto key = edit->key(); !key.isNull()) {
         return Kleo::canBeUsedForEncryption(key);
     }
     if (const auto group = edit->group(); !group.isNull()) {
         return std::ranges::all_of(group.keys(), Kleo::canBeUsedForEncryption);
     }
     // we should never reach this point
     return false;
 }
 
 bool SignEncryptWidget::isComplete() const
 {
     if (currentOp() == NoOperation) {
         return false;
     }
     if ((currentOp() & SignEncryptWidget::Sign) && !Kleo::canBeUsedForSigning(signUserId().parent())) {
         return false;
     }
     if (currentOp() & SignEncryptWidget::Encrypt) {
         if (!selfUserId().isNull() && !Kleo::canBeUsedForEncryption(selfUserId().parent())) {
             return false;
         }
         const bool allOtherRecipientsAreOkay = std::ranges::all_of(d->mRecpWidgets, [](const auto &r) {
             return recipientIsOkay(r.edit);
         });
         if (!allOtherRecipientsAreOkay) {
             return false;
         }
     }
     return true;
 }
 
 bool SignEncryptWidget::validate()
 {
     CertificateLineEdit *firstUnresolvedRecipient = nullptr;
     QStringList unresolvedRecipients;
     for (const auto &recipient : std::as_const(d->mRecpWidgets)) {
         if (recipient.edit->isEnabled() && !recipient.edit->hasAcceptableInput()) {
             if (!firstUnresolvedRecipient) {
                 firstUnresolvedRecipient = recipient.edit;
             }
             unresolvedRecipients.push_back(recipient.edit->text().toHtmlEscaped());
         }
     }
     if (!unresolvedRecipients.isEmpty()) {
         KMessageBox::errorList(this,
                                i18n("Could not find a key for the following recipients:"),
                                unresolvedRecipients,
                                i18nc("@title:window", "Failed to find some keys"));
     }
     if (firstUnresolvedRecipient) {
         firstUnresolvedRecipient->setFocus();
     }
     return unresolvedRecipients.isEmpty();
 }
 
 void SignEncryptWidget::Private::updateCheckBoxes()
 {
     const bool haveSecretKeys = !KeyCache::instance()->secretKeys().empty();
     const bool symmetricOnly = FileOperationsPreferences().symmetricEncryptionOnly();
     mSigChk->setEnabled(haveSecretKeys);
     mEncSelfChk->setEnabled(haveSecretKeys && !symmetricOnly);
     if (symmetricOnly) {
         mEncSelfChk->setChecked(false);
         mSymmetric->setChecked(true);
     }
 }
 
 ExpiryChecker *Kleo::SignEncryptWidget::Private::expiryChecker()
 {
     if (!mExpiryChecker) {
         mExpiryChecker.reset(new ExpiryChecker{ExpiryCheckerConfig{}.settings()});
     }
     return mExpiryChecker.get();
 }
 
 void SignEncryptWidget::Private::updateExpiryMessages(KMessageWidget *messageWidget, const GpgME::UserID &userID, ExpiryChecker::CheckFlags flags)
 {
     messageWidget->setCloseButtonVisible(false);
 
     if (userID.isNull()) {
         messageWidget->setVisible(false);
     } else if (userID.parent().isExpired()) {
         messageWidget->setText(i18nc("@info", "This certificate is expired."));
         messageWidget->setVisible(true);
     } else if (userID.isRevoked() || userID.parent().isRevoked()) {
         messageWidget->setText(i18nc("@info", "This certificate is revoked."));
         messageWidget->setVisible(true);
     } else if (Settings{}.showExpiryNotifications()) {
         const auto result = expiryChecker()->checkKey(userID.parent(), flags);
         const auto message = expiryMessage(result);
         messageWidget->setText(message);
         messageWidget->setVisible(!message.isEmpty());
     } else {
         messageWidget->setVisible(false);
     }
 }
 
 void SignEncryptWidget::Private::updateAllExpiryMessages()
 {
     updateExpiryMessages(mSignKeyExpiryMessage, q->signUserId(), ExpiryChecker::OwnSigningKey);
     updateExpiryMessages(mEncryptToSelfKeyExpiryMessage, q->selfUserId(), ExpiryChecker::OwnEncryptionKey);
     for (const auto &recipient : std::as_const(mRecpWidgets)) {
         if (recipient.edit->isEnabled()) {
             updateExpiryMessages(recipient.expiryMessage, recipient.edit->userID(), ExpiryChecker::EncryptionKey);
         }
     }
 }
 
 #include "moc_signencryptwidget.cpp"
diff --git a/src/crypto/signencryptfilescontroller.cpp b/src/crypto/signencryptfilescontroller.cpp
index d7881f147..fc7abfb1f 100644
--- a/src/crypto/signencryptfilescontroller.cpp
+++ b/src/crypto/signencryptfilescontroller.cpp
@@ -1,814 +1,814 @@
 /* -*- mode: c++; c-basic-offset:4 -*-
     crypto/signencryptfilescontroller.cpp
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
 
     SPDX-FileCopyrightText: 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 "signencryptfilescontroller.h"
 
 #include "signencrypttask.h"
 
 #include "crypto/gui/signencryptfileswizard.h"
 #include "crypto/taskcollection.h"
 
 #include "fileoperationspreferences.h"
 
 #include "utils/archivedefinition.h"
 #include "utils/input.h"
 #include "utils/kleo_assert.h"
 #include "utils/output.h"
 #include "utils/path-helper.h"
 
 #include <Libkleo/Classify>
 #include <Libkleo/KleoException>
 
 #include "kleopatra_debug.h"
 #include <KLocalizedString>
 
 #include <QGpgME/SignEncryptArchiveJob>
 
 #include <QDir>
 #include <QFileInfo>
 #include <QPointer>
 #include <QTimer>
 
 using namespace Kleo;
 using namespace Kleo::Crypto;
 using namespace GpgME;
 
 class SignEncryptFilesController::Private
 {
     friend class ::Kleo::Crypto::SignEncryptFilesController;
     SignEncryptFilesController *const q;
 
 public:
     explicit Private(SignEncryptFilesController *qq);
     ~Private();
 
 private:
     void slotWizardOperationPrepared();
     void slotWizardCanceled();
 
 private:
     void ensureWizardCreated();
     void ensureWizardVisible();
     void updateWizardMode();
     void cancelAllTasks();
     void reportError(int err, const QString &details)
     {
         q->setLastError(err, details);
         q->emitDoneOrError();
     }
 
     void schedule();
     std::shared_ptr<SignEncryptTask> takeRunnable(GpgME::Protocol proto);
 
     static void assertValidOperation(unsigned int);
     static QString titleForOperation(unsigned int op);
 
 private:
     std::vector<std::shared_ptr<SignEncryptTask>> runnable, completed;
     std::shared_ptr<SignEncryptTask> cms, openpgp;
     QPointer<SignEncryptFilesWizard> wizard;
     QStringList files;
     unsigned int operation;
     Protocol protocol;
 };
 
 SignEncryptFilesController::Private::Private(SignEncryptFilesController *qq)
     : q(qq)
     , runnable()
     , cms()
     , openpgp()
     , wizard()
     , files()
     , operation(SignAllowed | EncryptAllowed | ArchiveAllowed)
     , protocol(UnknownProtocol)
 {
 }
 
 SignEncryptFilesController::Private::~Private()
 {
     qCDebug(KLEOPATRA_LOG) << q << __func__;
 }
 
 QString SignEncryptFilesController::Private::titleForOperation(unsigned int op)
 {
     const bool signDisallowed = (op & SignMask) == SignDisallowed;
     const bool encryptDisallowed = (op & EncryptMask) == EncryptDisallowed;
     const bool archiveSelected = (op & ArchiveMask) == ArchiveForced;
 
     kleo_assert(!signDisallowed || !encryptDisallowed);
 
     if (!signDisallowed && encryptDisallowed) {
         if (archiveSelected) {
             return i18n("Archive and Sign Files");
         } else {
             return i18n("Sign Files");
         }
     }
 
     if (signDisallowed && !encryptDisallowed) {
         if (archiveSelected) {
             return i18n("Archive and Encrypt Files");
         } else {
             return i18n("Encrypt Files");
         }
     }
 
     if (archiveSelected) {
         return i18n("Archive and Sign/Encrypt Files");
     } else {
         return i18n("Sign/Encrypt Files");
     }
 }
 
 SignEncryptFilesController::SignEncryptFilesController(QObject *p)
     : Controller(p)
     , d(new Private(this))
 {
 }
 
 SignEncryptFilesController::SignEncryptFilesController(const std::shared_ptr<const ExecutionContext> &ctx, QObject *p)
     : Controller(ctx, p)
     , d(new Private(this))
 {
 }
 
 SignEncryptFilesController::~SignEncryptFilesController()
 {
     qCDebug(KLEOPATRA_LOG) << this << __func__;
     if (d->wizard && !d->wizard->isVisible()) {
         delete d->wizard;
     }
     // d->wizard->close(); ### ?
 }
 
 void SignEncryptFilesController::setProtocol(Protocol proto)
 {
     kleo_assert(d->protocol == UnknownProtocol || d->protocol == proto);
     d->protocol = proto;
     d->ensureWizardCreated();
 }
 
 Protocol SignEncryptFilesController::protocol() const
 {
     return d->protocol;
 }
 
 // static
 void SignEncryptFilesController::Private::assertValidOperation(unsigned int op)
 {
     kleo_assert((op & SignMask) == SignDisallowed || //
                 (op & SignMask) == SignAllowed || //
                 (op & SignMask) == SignSelected);
     kleo_assert((op & EncryptMask) == EncryptDisallowed || //
                 (op & EncryptMask) == EncryptAllowed || //
                 (op & EncryptMask) == EncryptSelected);
     kleo_assert((op & ArchiveMask) == ArchiveDisallowed || //
                 (op & ArchiveMask) == ArchiveAllowed || //
                 (op & ArchiveMask) == ArchiveForced);
     kleo_assert((op & ~(SignMask | EncryptMask | ArchiveMask)) == 0);
 }
 
 void SignEncryptFilesController::setOperationMode(unsigned int mode)
 {
     Private::assertValidOperation(mode);
     d->operation = mode;
     d->updateWizardMode();
 }
 
 void SignEncryptFilesController::Private::updateWizardMode()
 {
     if (!wizard) {
         return;
     }
     wizard->setWindowTitle(titleForOperation(operation));
     const unsigned int signOp = (operation & SignMask);
     const unsigned int encrOp = (operation & EncryptMask);
     const unsigned int archOp = (operation & ArchiveMask);
 
     if (signOp == SignDisallowed) {
         wizard->setSigningUserMutable(false);
         wizard->setSigningPreset(false);
     } else {
         wizard->setSigningUserMutable(true);
         wizard->setSigningPreset(signOp == SignSelected);
     }
 
     if (encrOp == EncryptDisallowed) {
         wizard->setEncryptionPreset(false);
         wizard->setEncryptionUserMutable(false);
     } else {
         wizard->setEncryptionUserMutable(true);
         wizard->setEncryptionPreset(encrOp == EncryptSelected);
     }
 
     wizard->setArchiveForced(archOp == ArchiveForced);
     wizard->setArchiveMutable(archOp == ArchiveAllowed);
 }
 
 unsigned int SignEncryptFilesController::operationMode() const
 {
     return d->operation;
 }
 
 static QString extension(bool pgp, bool sign, bool encrypt, bool ascii, bool detached)
 {
     unsigned int cls = pgp ? Class::OpenPGP : Class::CMS;
     if (encrypt) {
         cls |= Class::CipherText;
     } else if (sign) {
         cls |= detached ? Class::DetachedSignature : Class::OpaqueSignature;
     }
     cls |= ascii ? Class::Ascii : Class::Binary;
     const bool usePGPFileExt = FileOperationsPreferences().usePGPFileExt();
     const auto ext = outputFileExtension(cls, usePGPFileExt);
     if (!ext.isEmpty()) {
         return ext;
     } else {
         return QStringLiteral("out");
     }
 }
 
 static std::shared_ptr<ArchiveDefinition> getDefaultAd()
 {
     const std::vector<std::shared_ptr<ArchiveDefinition>> ads = ArchiveDefinition::getArchiveDefinitions();
     Q_ASSERT(!ads.empty());
     std::shared_ptr<ArchiveDefinition> ad = ads.front();
     const FileOperationsPreferences prefs;
     const QString archiveCmd = prefs.archiveCommand();
     auto it = std::find_if(ads.cbegin(), ads.cend(), [&archiveCmd](const std::shared_ptr<ArchiveDefinition> &toCheck) {
         return toCheck->id() == archiveCmd;
     });
     if (it != ads.cend()) {
         ad = *it;
     }
     return ad;
 }
 
 static QMap<int, QString> buildOutputNames(const QStringList &files, const bool archive)
 {
     QMap<int, QString> nameMap;
 
     // Build the default names for the wizard.
     QString baseNameCms;
     QString baseNamePgp;
     const QFileInfo firstFile(files.first());
     if (archive) {
         QString baseName = files.size() > 1 ? i18nc("base name of an archive file, e.g. archive.zip or archive.tar.gz", "archive") : firstFile.baseName();
         baseName = QDir(heuristicBaseDirectory(files)).absoluteFilePath(baseName);
 
         const auto ad = getDefaultAd();
         baseNamePgp = baseName + QLatin1Char('.') + ad->extensions(GpgME::OpenPGP).first() + QLatin1Char('.');
         baseNameCms = baseName + QLatin1Char('.') + ad->extensions(GpgME::CMS).first() + QLatin1Char('.');
     } else {
         baseNameCms = baseNamePgp = files.first() + QLatin1Char('.');
     }
     const FileOperationsPreferences prefs;
     const bool ascii = prefs.addASCIIArmor();
 
     nameMap.insert(SignEncryptFilesWizard::SignatureCMS, baseNameCms + extension(false, true, false, ascii, true));
     nameMap.insert(SignEncryptFilesWizard::EncryptedCMS, baseNameCms + extension(false, false, true, ascii, false));
     nameMap.insert(SignEncryptFilesWizard::CombinedPGP, baseNamePgp + extension(true, true, true, ascii, false));
     nameMap.insert(SignEncryptFilesWizard::EncryptedPGP, baseNamePgp + extension(true, false, true, ascii, false));
     nameMap.insert(SignEncryptFilesWizard::SignaturePGP, baseNamePgp + extension(true, true, false, ascii, true));
     nameMap.insert(SignEncryptFilesWizard::Directory, heuristicBaseDirectory(files));
     return nameMap;
 }
 
 static QMap<int, QString> buildOutputNamesForDir(const QString &file, const QMap<int, QString> &orig)
 {
     QMap<int, QString> ret;
 
     const QString dir = orig.value(SignEncryptFilesWizard::Directory);
     if (dir.isEmpty()) {
         return orig;
     }
 
     // Build the default names for the wizard.
     const QFileInfo fi(file);
     const QString baseName = dir + QLatin1Char('/') + fi.fileName() + QLatin1Char('.');
 
     const FileOperationsPreferences prefs;
     const bool ascii = prefs.addASCIIArmor();
 
     ret.insert(SignEncryptFilesWizard::SignatureCMS, baseName + extension(false, true, false, ascii, true));
     ret.insert(SignEncryptFilesWizard::EncryptedCMS, baseName + extension(false, false, true, ascii, false));
     ret.insert(SignEncryptFilesWizard::CombinedPGP, baseName + extension(true, true, true, ascii, false));
     ret.insert(SignEncryptFilesWizard::EncryptedPGP, baseName + extension(true, false, true, ascii, false));
     ret.insert(SignEncryptFilesWizard::SignaturePGP, baseName + extension(true, true, false, ascii, true));
     return ret;
 }
 
 // strips all trailing slashes from the filename, but keeps filename "/"
 static QString stripTrailingSlashes(const QString &fileName)
 {
     if (fileName.size() < 2 || !fileName.endsWith(QLatin1Char('/'))) {
         return fileName;
     }
     auto tmp = QStringView{fileName}.chopped(1);
     while (tmp.size() > 1 && tmp.endsWith(QLatin1Char('/'))) {
         tmp.chop(1);
     }
     return tmp.toString();
 }
 
 static QStringList stripTrailingSlashesForAll(const QStringList &fileNames)
 {
     QStringList result;
     result.reserve(fileNames.size());
     std::transform(fileNames.begin(), fileNames.end(), std::back_inserter(result), &stripTrailingSlashes);
     return result;
 }
 
 void SignEncryptFilesController::setFiles(const QStringList &files)
 {
     kleo_assert(!files.empty());
     d->files = stripTrailingSlashesForAll(files);
     bool archive = false;
 
     if (d->files.size() > 1) {
         setOperationMode((operationMode() & ~ArchiveMask) | ArchiveAllowed);
         archive = true;
     }
-    for (const auto &file : d->files) {
+    for (const auto &file : std::as_const(d->files)) {
         if (QFileInfo(file).isDir()) {
             setOperationMode((operationMode() & ~ArchiveMask) | ArchiveForced);
             archive = true;
             break;
         }
     }
     d->ensureWizardCreated();
     d->wizard->setSingleFile(!archive);
     d->wizard->setOutputNames(buildOutputNames(d->files, archive));
 }
 
 void SignEncryptFilesController::Private::slotWizardCanceled()
 {
     qCDebug(KLEOPATRA_LOG) << q << __func__;
     q->cancel();
     reportError(gpg_error(GPG_ERR_CANCELED), i18n("User cancel"));
 }
 
 void SignEncryptFilesController::start()
 {
     d->ensureWizardVisible();
 }
 
 static std::shared_ptr<SignEncryptTask> createSignEncryptTaskForFileInfo(const QFileInfo &fi,
                                                                          bool ascii,
                                                                          const std::vector<Key> &recipients,
                                                                          const std::vector<Key> &signers,
                                                                          const QString &outputName,
                                                                          bool symmetric)
 {
     const std::shared_ptr<SignEncryptTask> task(new SignEncryptTask);
     Q_ASSERT(!signers.empty() || !recipients.empty() || symmetric);
     task->setAsciiArmor(ascii);
     if (!signers.empty()) {
         task->setSign(true);
         task->setSigners(signers);
         task->setDetachedSignature(true);
     } else {
         task->setSign(false);
     }
     if (!recipients.empty()) {
         task->setEncrypt(true);
         task->setRecipients(recipients);
         task->setDetachedSignature(false);
     } else {
         task->setEncrypt(false);
     }
     task->setEncryptSymmetric(symmetric);
     const QString input = fi.absoluteFilePath();
     task->setInputFileName(input);
 #if QGPGME_FILE_JOBS_SUPPORT_DIRECT_FILE_IO
     if (task->protocol() != GpgME::OpenPGP) {
         task->setInput(Input::createFromFile(input));
     }
 #else
     task->setInput(Input::createFromFile(input));
 #endif
 
     task->setOutputFileName(outputName);
 
     return task;
 }
 
 static bool archiveJobsCanBeUsed([[maybe_unused]] GpgME::Protocol protocol)
 {
     return (protocol == GpgME::OpenPGP) && QGpgME::SignEncryptArchiveJob::isSupported();
 }
 
 static std::shared_ptr<SignEncryptTask> createArchiveSignEncryptTaskForFiles(const QStringList &files,
                                                                              const std::shared_ptr<ArchiveDefinition> &ad,
                                                                              bool pgp,
                                                                              bool ascii,
                                                                              const std::vector<Key> &recipients,
                                                                              const std::vector<Key> &signers,
                                                                              const QString &outputName,
                                                                              bool symmetric)
 {
     const std::shared_ptr<SignEncryptTask> task(new SignEncryptTask);
     task->setCreateArchive(true);
     task->setEncryptSymmetric(symmetric);
     Q_ASSERT(!signers.empty() || !recipients.empty() || symmetric);
     task->setAsciiArmor(ascii);
     if (!signers.empty()) {
         task->setSign(true);
         task->setSigners(signers);
         task->setDetachedSignature(false);
     } else {
         task->setSign(false);
     }
     if (!recipients.empty()) {
         task->setEncrypt(true);
         task->setRecipients(recipients);
     } else {
         task->setEncrypt(false);
     }
 
     const Protocol proto = pgp ? OpenPGP : CMS;
 
     task->setInputFileNames(files);
     if (!archiveJobsCanBeUsed(proto)) {
         // use legacy archive creation
         kleo_assert(ad);
         task->setInput(ad->createInputFromPackCommand(proto, files));
     }
 
     task->setOutputFileName(outputName);
 
     return task;
 }
 
 static std::vector<std::shared_ptr<SignEncryptTask>> createSignEncryptTasksForFileInfo(const QFileInfo &fi,
                                                                                        bool ascii,
                                                                                        const std::vector<Key> &pgpRecipients,
                                                                                        const std::vector<Key> &pgpSigners,
                                                                                        const std::vector<Key> &cmsRecipients,
                                                                                        const std::vector<Key> &cmsSigners,
                                                                                        const QMap<int, QString> &outputNames,
                                                                                        bool symmetric)
 {
     std::vector<std::shared_ptr<SignEncryptTask>> result;
 
     const bool pgp = !pgpSigners.empty() || !pgpRecipients.empty();
 
     const bool cms = !cmsSigners.empty() || !cmsRecipients.empty();
 
     result.reserve(pgp + cms);
 
     if (pgp || symmetric) {
         // Symmetric encryption is only supported for PGP
         int outKind = 0;
         if ((!pgpRecipients.empty() || symmetric) && !pgpSigners.empty()) {
             outKind = SignEncryptFilesWizard::CombinedPGP;
         } else if (!pgpRecipients.empty() || symmetric) {
             outKind = SignEncryptFilesWizard::EncryptedPGP;
         } else {
             outKind = SignEncryptFilesWizard::SignaturePGP;
         }
         result.push_back(createSignEncryptTaskForFileInfo(fi, ascii, pgpRecipients, pgpSigners, outputNames[outKind], symmetric));
     }
     if (cms) {
         // There is no combined sign / encrypt in gpgsm so we create one sign task
         // and one encrypt task. Which leaves us with the age old dilemma, encrypt
         // then sign, or sign then encrypt. Ugly.
         if (!cmsSigners.empty()) {
             result.push_back(
                 createSignEncryptTaskForFileInfo(fi, ascii, std::vector<Key>(), cmsSigners, outputNames[SignEncryptFilesWizard::SignatureCMS], false));
         }
         if (!cmsRecipients.empty()) {
             result.push_back(
                 createSignEncryptTaskForFileInfo(fi, ascii, cmsRecipients, std::vector<Key>(), outputNames[SignEncryptFilesWizard::EncryptedCMS], false));
         }
     }
 
     return result;
 }
 
 static std::vector<std::shared_ptr<SignEncryptTask>> createArchiveSignEncryptTasksForFiles(const QStringList &files,
                                                                                            const std::shared_ptr<ArchiveDefinition> &ad,
                                                                                            bool ascii,
                                                                                            const std::vector<Key> &pgpRecipients,
                                                                                            const std::vector<Key> &pgpSigners,
                                                                                            const std::vector<Key> &cmsRecipients,
                                                                                            const std::vector<Key> &cmsSigners,
                                                                                            const QMap<int, QString> &outputNames,
                                                                                            bool symmetric)
 {
     std::vector<std::shared_ptr<SignEncryptTask>> result;
 
     const bool pgp = !pgpSigners.empty() || !pgpRecipients.empty();
 
     const bool cms = !cmsSigners.empty() || !cmsRecipients.empty();
 
     result.reserve(pgp + cms);
 
     if (pgp || symmetric) {
         int outKind = 0;
         if ((!pgpRecipients.empty() || symmetric) && !pgpSigners.empty()) {
             outKind = SignEncryptFilesWizard::CombinedPGP;
         } else if (!pgpRecipients.empty() || symmetric) {
             outKind = SignEncryptFilesWizard::EncryptedPGP;
         } else {
             outKind = SignEncryptFilesWizard::SignaturePGP;
         }
         result.push_back(createArchiveSignEncryptTaskForFiles(files, ad, true, ascii, pgpRecipients, pgpSigners, outputNames[outKind], symmetric));
     }
     if (cms) {
         if (!cmsSigners.empty()) {
             result.push_back(createArchiveSignEncryptTaskForFiles(files,
                                                                   ad,
                                                                   false,
                                                                   ascii,
                                                                   std::vector<Key>(),
                                                                   cmsSigners,
                                                                   outputNames[SignEncryptFilesWizard::SignatureCMS],
                                                                   false));
         }
         if (!cmsRecipients.empty()) {
             result.push_back(createArchiveSignEncryptTaskForFiles(files,
                                                                   ad,
                                                                   false,
                                                                   ascii,
                                                                   cmsRecipients,
                                                                   std::vector<Key>(),
                                                                   outputNames[SignEncryptFilesWizard::EncryptedCMS],
                                                                   false));
         }
     }
 
     return result;
 }
 
 namespace
 {
 static bool isDetachedOpenPGPSignature(const QString &fileName)
 {
     const auto classification = Kleo::classify(fileName);
     return Kleo::isOpenPGP(classification) && Kleo::isDetachedSignature(classification);
 }
 
 static auto resolveFileNameConflicts(const std::vector<std::shared_ptr<SignEncryptTask>> &tasks, QWidget *parent)
 {
     std::vector<std::shared_ptr<SignEncryptTask>> resolvedTasks;
 
     OverwritePolicy overwritePolicy{parent, tasks.size() > 1 ? OverwritePolicy::MultipleFiles : OverwritePolicy::Options{}};
     for (auto &task : tasks) {
         // by default, do not overwrite existing files
         task->setOverwritePolicy(std::make_shared<OverwritePolicy>(OverwritePolicy::Skip));
         const auto outputFileName = task->outputFileName();
         if (QFile::exists(outputFileName)) {
             const auto isDetachedOpenPGPSigningTask = (task->protocol() == GpgME::OpenPGP) && task->detachedSignatureEnabled();
             const auto extraOptions = (isDetachedOpenPGPSigningTask && isDetachedOpenPGPSignature(outputFileName) //
                                            ? OverwritePolicy::AllowAppend //
                                            : OverwritePolicy::Options{});
             const auto policyAndFileName = overwritePolicy.obtainOverwritePermission(outputFileName, extraOptions);
             if (policyAndFileName.policy == OverwritePolicy::Cancel) {
                 resolvedTasks.clear();
                 break;
             }
             switch (policyAndFileName.policy) {
             case OverwritePolicy::Skip:
                 // do not add task to the final task list
                 continue;
             case OverwritePolicy::Rename: {
                 task->setOutputFileName(policyAndFileName.fileName);
                 break;
             }
             case OverwritePolicy::Append: {
                 task->setOverwritePolicy(std::make_shared<OverwritePolicy>(OverwritePolicy::Append));
                 break;
             }
             case OverwritePolicy::Overwrite: {
                 task->setOverwritePolicy(std::make_shared<OverwritePolicy>(OverwritePolicy::Overwrite));
                 break;
             }
             case OverwritePolicy::Cancel:
                 // already handled outside of switch
                 break;
             case OverwritePolicy::None:
             case OverwritePolicy::Ask:
                 qCDebug(KLEOPATRA_LOG) << "Unexpected OverwritePolicy result" << policyAndFileName.policy << "for" << outputFileName;
             };
         }
         resolvedTasks.push_back(task);
     }
 
     return resolvedTasks;
 }
 }
 
 void SignEncryptFilesController::Private::slotWizardOperationPrepared()
 {
     try {
         kleo_assert(wizard);
         kleo_assert(!files.empty());
 
         const bool archive = ((wizard->outputNames().value(SignEncryptFilesWizard::Directory).isNull() && files.size() > 1) //
                               || ((operation & ArchiveMask) == ArchiveForced));
 
         const std::vector<Key> recipients = wizard->resolvedRecipients();
         const std::vector<Key> signers = wizard->resolvedSigners();
 
         const FileOperationsPreferences prefs;
         const bool ascii = prefs.addASCIIArmor();
 
         std::vector<Key> pgpRecipients, cmsRecipients, pgpSigners, cmsSigners;
         for (const Key &k : recipients) {
             if (k.protocol() == GpgME::OpenPGP) {
                 pgpRecipients.push_back(k);
             } else {
                 cmsRecipients.push_back(k);
             }
         }
 
         for (const Key &k : signers) {
             if (k.protocol() == GpgME::OpenPGP) {
                 pgpSigners.push_back(k);
             } else {
                 cmsSigners.push_back(k);
             }
         }
 
         std::vector<std::shared_ptr<SignEncryptTask>> tasks;
         if (!archive) {
             tasks.reserve(files.size());
         }
 
         if (archive) {
             tasks = createArchiveSignEncryptTasksForFiles(files,
                                                           getDefaultAd(),
                                                           ascii,
                                                           pgpRecipients,
                                                           pgpSigners,
                                                           cmsRecipients,
                                                           cmsSigners,
                                                           wizard->outputNames(),
                                                           wizard->encryptSymmetric());
         } else {
             for (const QString &file : std::as_const(files)) {
                 const std::vector<std::shared_ptr<SignEncryptTask>> created =
                     createSignEncryptTasksForFileInfo(QFileInfo(file),
                                                       ascii,
                                                       pgpRecipients,
                                                       pgpSigners,
                                                       cmsRecipients,
                                                       cmsSigners,
                                                       buildOutputNamesForDir(file, wizard->outputNames()),
                                                       wizard->encryptSymmetric());
                 tasks.insert(tasks.end(), created.begin(), created.end());
             }
         }
 
         tasks = resolveFileNameConflicts(tasks, wizard);
         if (tasks.empty()) {
             q->cancel();
             return;
         }
 
         kleo_assert(runnable.empty());
 
         runnable.swap(tasks);
 
         for (const auto &task : std::as_const(runnable)) {
             q->connectTask(task);
         }
 
         std::shared_ptr<TaskCollection> coll(new TaskCollection);
 
         std::vector<std::shared_ptr<Task>> tmp;
         std::copy(runnable.begin(), runnable.end(), std::back_inserter(tmp));
         coll->setTasks(tmp);
         wizard->setTaskCollection(coll);
 
         QTimer::singleShot(0, q, SLOT(schedule()));
 
     } catch (const Kleo::Exception &e) {
         reportError(e.error().encodedError(), e.message());
     } catch (const std::exception &e) {
         reportError(
             gpg_error(GPG_ERR_UNEXPECTED),
             i18n("Caught unexpected exception in SignEncryptFilesController::Private::slotWizardOperationPrepared: %1", QString::fromLocal8Bit(e.what())));
     } catch (...) {
         reportError(gpg_error(GPG_ERR_UNEXPECTED), i18n("Caught unknown exception in SignEncryptFilesController::Private::slotWizardOperationPrepared"));
     }
 }
 
 void SignEncryptFilesController::Private::schedule()
 {
     if (!cms)
         if (const std::shared_ptr<SignEncryptTask> t = takeRunnable(CMS)) {
             t->start();
             cms = t;
         }
 
     if (!openpgp)
         if (const std::shared_ptr<SignEncryptTask> t = takeRunnable(OpenPGP)) {
             t->start();
             openpgp = t;
         }
 
     if (!cms && !openpgp) {
         kleo_assert(runnable.empty());
         q->emitDoneOrError();
     }
 }
 
 std::shared_ptr<SignEncryptTask> SignEncryptFilesController::Private::takeRunnable(GpgME::Protocol proto)
 {
     const auto it = std::find_if(runnable.begin(), runnable.end(), [proto](const std::shared_ptr<Task> &task) {
         return task->protocol() == proto;
     });
     if (it == runnable.end()) {
         return std::shared_ptr<SignEncryptTask>();
     }
 
     const std::shared_ptr<SignEncryptTask> result = *it;
     runnable.erase(it);
     return result;
 }
 
 void SignEncryptFilesController::doTaskDone(const Task *task, const std::shared_ptr<const Task::Result> &result)
 {
     Q_UNUSED(result)
     Q_ASSERT(task);
 
     // We could just delete the tasks here, but we can't use
     // Qt::QueuedConnection here (we need sender()) and other slots
     // might not yet have executed. Therefore, we push completed tasks
     // into a burial container
 
     if (task == d->cms.get()) {
         d->completed.push_back(d->cms);
         d->cms.reset();
     } else if (task == d->openpgp.get()) {
         d->completed.push_back(d->openpgp);
         d->openpgp.reset();
     }
 
     QTimer::singleShot(0, this, SLOT(schedule()));
 }
 
 void SignEncryptFilesController::cancel()
 {
     qCDebug(KLEOPATRA_LOG) << this << __func__;
     try {
         if (d->wizard) {
             d->wizard->close();
         }
         d->cancelAllTasks();
     } catch (const std::exception &e) {
         qCDebug(KLEOPATRA_LOG) << "Caught exception: " << e.what();
     }
 }
 
 void SignEncryptFilesController::Private::cancelAllTasks()
 {
     // we just kill all runnable tasks - this will not result in
     // signal emissions.
     runnable.clear();
 
     // a cancel() will result in a call to
     if (cms) {
         cms->cancel();
     }
     if (openpgp) {
         openpgp->cancel();
     }
 }
 
 void SignEncryptFilesController::Private::ensureWizardCreated()
 {
     if (wizard) {
         return;
     }
 
     std::unique_ptr<SignEncryptFilesWizard> w(new SignEncryptFilesWizard);
     w->setAttribute(Qt::WA_DeleteOnClose);
 
     connect(w.get(), SIGNAL(operationPrepared()), q, SLOT(slotWizardOperationPrepared()), Qt::QueuedConnection);
     connect(w.get(), SIGNAL(rejected()), q, SLOT(slotWizardCanceled()), Qt::QueuedConnection);
     wizard = w.release();
 
     updateWizardMode();
 }
 
 void SignEncryptFilesController::Private::ensureWizardVisible()
 {
     ensureWizardCreated();
     q->bringToForeground(wizard);
 }
 
 #include "moc_signencryptfilescontroller.cpp"
diff --git a/src/kwatchgnupg/kwatchgnupgmainwin.cpp b/src/kwatchgnupg/kwatchgnupgmainwin.cpp
index 23cd9e67d..3dfdb14d3 100644
--- a/src/kwatchgnupg/kwatchgnupgmainwin.cpp
+++ b/src/kwatchgnupg/kwatchgnupgmainwin.cpp
@@ -1,267 +1,266 @@
 /*
     kwatchgnupgmainwin.cpp
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2001, 2002, 2004 Klar �vdalens Datakonsult AB
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 #include <config-kleopatra.h>
 
 #include "kwatchgnupgmainwin.h"
 
 #include "kwatchgnupg.h"
 #include "kwatchgnupgconfig.h"
 #include "tray.h"
 
 #include <QGpgME/CryptoConfig>
 #include <QGpgME/Protocol>
 
 #include <QTextEdit>
 
 #include <KActionCollection>
 #include <KConfig>
 #include <KConfigGroup>
 #include <KEditToolBar>
 #include <KLocalizedString>
 #include <KMessageBox>
 #include <KProcess>
 #include <KShortcutsDialog>
 #include <KStandardAction>
 #include <QAction>
 #include <QApplication>
 #include <QIcon>
 
 #include <KSharedConfig>
 #include <QDateTime>
 #include <QEventLoop>
 #include <QFileDialog>
 #include <QTextStream>
 
 KWatchGnuPGMainWindow::KWatchGnuPGMainWindow(QWidget *parent)
     : KXmlGuiWindow(parent, Qt::Window)
     , mConfig(nullptr)
 {
     createActions();
     createGUI();
 
     mCentralWidget = new QTextEdit(this);
     mCentralWidget->setReadOnly(true);
 
     setCentralWidget(mCentralWidget);
 
     mWatcher = new KProcess;
-    connect(mWatcher, &KProcess::finished, this, &KWatchGnuPGMainWindow::slotWatcherExited);
-
+    connect(mWatcher, &QProcess::finished, this, &KWatchGnuPGMainWindow::slotWatcherExited);
     connect(mWatcher, &QProcess::readyReadStandardOutput, this, &KWatchGnuPGMainWindow::slotReadStdout);
 
     slotReadConfig();
     mSysTray = new KWatchGnuPGTray(this);
     QAction *act = mSysTray->action(QStringLiteral("quit"));
     if (act) {
         connect(act, &QAction::triggered, this, &KWatchGnuPGMainWindow::slotQuit);
     }
 
     setAutoSaveSettings();
 }
 
 KWatchGnuPGMainWindow::~KWatchGnuPGMainWindow()
 {
     delete mWatcher;
 }
 
 void KWatchGnuPGMainWindow::slotClear()
 {
     mCentralWidget->clear();
     mCentralWidget->append(i18n("[%1] Log cleared", QDateTime::currentDateTime().toString(Qt::ISODate)));
 }
 
 void KWatchGnuPGMainWindow::createActions()
 {
     QAction *action = actionCollection()->addAction(QStringLiteral("clear_log"));
     action->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear-history")));
     action->setText(i18n("C&lear History"));
     connect(action, &QAction::triggered, this, &KWatchGnuPGMainWindow::slotClear);
     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_L));
     (void)KStandardAction::saveAs(this, &KWatchGnuPGMainWindow::slotSaveAs, actionCollection());
     (void)KStandardAction::close(this, &KWatchGnuPGMainWindow::close, actionCollection());
     (void)KStandardAction::quit(this, &KWatchGnuPGMainWindow::slotQuit, actionCollection());
     (void)KStandardAction::preferences(this, &KWatchGnuPGMainWindow::slotConfigure, actionCollection());
     (void)KStandardAction::keyBindings(this, &KWatchGnuPGMainWindow::configureShortcuts, actionCollection());
     (void)KStandardAction::configureToolbars(this, &KWatchGnuPGMainWindow::slotConfigureToolbars, actionCollection());
 }
 
 void KWatchGnuPGMainWindow::configureShortcuts()
 {
     KShortcutsDialog::showDialog(actionCollection(), KShortcutsEditor::LetterShortcutsAllowed, this);
 }
 
 void KWatchGnuPGMainWindow::slotConfigureToolbars()
 {
     KEditToolBar dlg(factory());
     dlg.exec();
 }
 
 void KWatchGnuPGMainWindow::startWatcher()
 {
     disconnect(mWatcher, &QProcess::finished, this, &KWatchGnuPGMainWindow::slotWatcherExited);
     if (mWatcher->state() == QProcess::Running) {
         mWatcher->kill();
         while (mWatcher->state() == QProcess::Running) {
             qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
         }
         mCentralWidget->append(i18n("[%1] Log stopped", QDateTime::currentDateTime().toString(Qt::ISODate)));
         mCentralWidget->ensureCursorVisible();
     }
     mWatcher->clearProgram();
 
     {
         const KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("WatchGnuPG"));
         *mWatcher << config.readEntry("Executable", WATCHGNUPGBINARY);
         *mWatcher << QStringLiteral("--force");
         *mWatcher << config.readEntry("Socket", WATCHGNUPGSOCKET);
     }
 
     mWatcher->setOutputChannelMode(KProcess::OnlyStdoutChannel);
     mWatcher->start();
     const bool ok = mWatcher->waitForStarted();
     if (!ok) {
         KMessageBox::error(this,
                            i18n("The watchgnupg logging process could not be started.\nPlease install watchgnupg somewhere in your $PATH.\nThis log window is "
                                 "unable to display any useful information."));
     } else {
         mCentralWidget->append(i18n("[%1] Log started", QDateTime::currentDateTime().toString(Qt::ISODate)));
         mCentralWidget->ensureCursorVisible();
     }
     connect(mWatcher, &QProcess::finished, this, &KWatchGnuPGMainWindow::slotWatcherExited);
 }
 
 void KWatchGnuPGMainWindow::setGnuPGConfig()
 {
     QStringList logclients;
     // Get config object
     QGpgME::CryptoConfig *const cconfig = QGpgME::cryptoConfig();
     if (!cconfig) {
         return;
     }
     KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("WatchGnuPG"));
     const QStringList comps = cconfig->componentList();
     for (QStringList::const_iterator it = comps.constBegin(); it != comps.constEnd(); ++it) {
         const QGpgME::CryptoConfigComponent *const comp = cconfig->component(*it);
         Q_ASSERT(comp);
         {
             QGpgME::CryptoConfigEntry *const entry = cconfig->entry(comp->name(), QStringLiteral("log-file"));
             if (entry) {
                 entry->setStringValue(QLatin1StringView("socket://") + config.readEntry("Socket", WATCHGNUPGSOCKET));
                 logclients << QStringLiteral("%1 (%2)").arg(*it, comp->description());
             }
         }
         {
             QGpgME::CryptoConfigEntry *const entry = cconfig->entry(comp->name(), QStringLiteral("debug-level"));
             if (entry) {
                 entry->setStringValue(config.readEntry("LogLevel", "basic"));
             }
         }
     }
     cconfig->sync(true);
     if (logclients.isEmpty()) {
         KMessageBox::error(nullptr, i18n("There are no components available that support logging."));
     }
 }
 
 void KWatchGnuPGMainWindow::slotWatcherExited(int, QProcess::ExitStatus)
 {
     if (KMessageBox::questionTwoActions(this,
                                         i18n("The watchgnupg logging process died.\nDo you want to try to restart it?"),
                                         QString(),
                                         KGuiItem(i18nc("@action:button", "Try Restart")),
                                         KGuiItem(i18nc("@action:button", "Do Not Try")))
         == KMessageBox::ButtonCode::PrimaryAction) {
         mCentralWidget->append(i18n("====== Restarting logging process ====="));
         mCentralWidget->ensureCursorVisible();
         startWatcher();
     } else {
         KMessageBox::error(this, i18n("The watchgnupg logging process is not running.\nThis log window is unable to display any useful information."));
     }
 }
 
 void KWatchGnuPGMainWindow::slotReadStdout()
 {
     if (!mWatcher) {
         return;
     }
     while (mWatcher->canReadLine()) {
         QString str = QString::fromUtf8(mWatcher->readLine());
         if (str.endsWith(QLatin1Char('\n'))) {
             str.chop(1);
         }
         if (str.endsWith(QLatin1Char('\r'))) {
             str.chop(1);
         }
         mCentralWidget->append(str);
         mCentralWidget->ensureCursorVisible();
         if (!isVisible()) {
             // Change tray icon to show something happened
             // PENDING(steffen)
             mSysTray->setAttention(true);
         }
     }
 }
 
 void KWatchGnuPGMainWindow::show()
 {
     mSysTray->setAttention(false);
     KMainWindow::show();
 }
 
 void KWatchGnuPGMainWindow::slotSaveAs()
 {
     const QString filename = QFileDialog::getSaveFileName(this, i18n("Save Log to File"));
     if (filename.isEmpty()) {
         return;
     }
     QFile file(filename);
     if (file.open(QIODevice::WriteOnly)) {
         QTextStream(&file) << mCentralWidget->document()->toPlainText();
     } else
         KMessageBox::information(this, i18n("Could not save file %1: %2", filename, file.errorString()));
 }
 
 void KWatchGnuPGMainWindow::slotQuit()
 {
     disconnect(mWatcher, &QProcess::finished, this, &KWatchGnuPGMainWindow::slotWatcherExited);
     mWatcher->kill();
     qApp->quit();
 }
 
 void KWatchGnuPGMainWindow::slotConfigure()
 {
     if (!mConfig) {
         mConfig = new KWatchGnuPGConfig(this);
         mConfig->setObjectName(QLatin1StringView("config dialog"));
         connect(mConfig, &KWatchGnuPGConfig::reconfigure, this, &KWatchGnuPGMainWindow::slotReadConfig);
     }
     mConfig->loadConfig();
     mConfig->exec();
 }
 
 void KWatchGnuPGMainWindow::slotReadConfig()
 {
     const KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("LogWindow"));
     const int maxLogLen = config.readEntry("MaxLogLen", 10000);
     mCentralWidget->document()->setMaximumBlockCount(maxLogLen < 1 ? -1 : maxLogLen);
     setGnuPGConfig();
     startWatcher();
 }
 
 bool KWatchGnuPGMainWindow::queryClose()
 {
     if (!qApp->isSavingSession()) {
         hide();
         return false;
     }
     return KMainWindow::queryClose();
 }
 
 #include "moc_kwatchgnupgmainwin.cpp"