File indexing completed on 2024-06-23 05:13:52

0001 /*  crypto/gui/signencryptfileswizard.cpp
0002 
0003     This file is part of Kleopatra, the KDE keymanager
0004     SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB
0005 
0006     SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
0007     SPDX-FileContributor: Intevation GmbH
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #include <config-kleopatra.h>
0013 
0014 #include "signencryptfileswizard.h"
0015 #include "signencryptwidget.h"
0016 
0017 #include "newresultpage.h"
0018 
0019 #include <fileoperationspreferences.h>
0020 #include <settings.h>
0021 
0022 #include <KColorScheme>
0023 #include <KConfigGroup>
0024 #include <KLocalizedString>
0025 #include <KMessageBox>
0026 #include <KMessageWidget>
0027 #include <KSharedConfig>
0028 #include <KWindowConfig>
0029 
0030 #include "kleopatra_debug.h"
0031 #include <Libkleo/Compliance>
0032 #include <Libkleo/Formatting>
0033 #include <Libkleo/GnuPG>
0034 #include <Libkleo/SystemInfo>
0035 
0036 #include <Libkleo/FileNameRequester>
0037 #include <QCheckBox>
0038 #include <QGroupBox>
0039 #include <QIcon>
0040 #include <QLabel>
0041 #include <QPushButton>
0042 #include <QStyle>
0043 #include <QVBoxLayout>
0044 #include <QWindow>
0045 #include <QWizardPage>
0046 
0047 #include <gpgme++/key.h>
0048 
0049 #include <array>
0050 
0051 using namespace GpgME;
0052 using namespace Kleo;
0053 using namespace Kleo::Crypto::Gui;
0054 
0055 enum Page {
0056     SigEncPageId,
0057     ResultPageId,
0058 
0059     NumPages
0060 };
0061 
0062 class FileNameRequesterWithIcon : public QWidget
0063 {
0064     Q_OBJECT
0065 
0066 public:
0067     explicit FileNameRequesterWithIcon(QDir::Filters filter, QWidget *parent = nullptr)
0068         : QWidget(parent)
0069     {
0070         auto layout = new QHBoxLayout{this};
0071         layout->setContentsMargins(0, 0, 0, 0);
0072         mIconLabel = new QLabel{this};
0073         mRequester = new FileNameRequester{filter, this};
0074         mRequester->setExistingOnly(false);
0075         layout->addWidget(mIconLabel);
0076         layout->addWidget(mRequester);
0077 
0078         setFocusPolicy(mRequester->focusPolicy());
0079         setFocusProxy(mRequester);
0080 
0081         connect(mRequester, &FileNameRequester::fileNameChanged, this, &FileNameRequesterWithIcon::fileNameChanged);
0082     }
0083 
0084     void setIcon(const QIcon &icon)
0085     {
0086         mIconLabel->setPixmap(icon.pixmap(32, 32));
0087     }
0088 
0089     void setFileName(const QString &name)
0090     {
0091         mRequester->setFileName(name);
0092     }
0093 
0094     QString fileName() const
0095     {
0096         return mRequester->fileName();
0097     }
0098 
0099     void setNameFilter(const QString &nameFilter)
0100     {
0101         mRequester->setNameFilter(nameFilter);
0102     }
0103 
0104     QString nameFilter() const
0105     {
0106         return mRequester->nameFilter();
0107     }
0108 
0109     FileNameRequester *requester()
0110     {
0111         return mRequester;
0112     }
0113 
0114 Q_SIGNALS:
0115     void fileNameChanged(const QString &filename);
0116 
0117 protected:
0118     bool event(QEvent *e) override
0119     {
0120         if (e->type() == QEvent::ToolTipChange) {
0121             mRequester->setToolTip(toolTip());
0122         }
0123         return QWidget::event(e);
0124     }
0125 
0126 private:
0127     QLabel *mIconLabel;
0128     FileNameRequester *mRequester;
0129 };
0130 
0131 class SigEncPage : public QWizardPage
0132 {
0133     Q_OBJECT
0134 
0135 public:
0136     explicit SigEncPage(QWidget *parent = nullptr)
0137         : QWizardPage(parent)
0138         , mParent((SignEncryptFilesWizard *)parent)
0139         , mWidget(new SignEncryptWidget)
0140         , mOutLayout(new QVBoxLayout)
0141         , mOutputLabel{nullptr}
0142         , mArchive(false)
0143         , mUseOutputDir(false)
0144         , mSingleFile{true}
0145     {
0146         setTitle(i18nc("@title", "Sign / Encrypt Files"));
0147         auto vLay = new QVBoxLayout(this);
0148         vLay->setContentsMargins(0, 0, 0, 0);
0149         if (!Settings{}.cmsEnabled()) {
0150             mWidget->setProtocol(GpgME::OpenPGP);
0151         }
0152         mWidget->setSignAsText(i18nc("@option:check on SignEncryptPage", "&Sign as:"));
0153         mWidget->setEncryptForMeText(i18nc("@option:check on SignEncryptPage", "Encrypt for &me:"));
0154         mWidget->setEncryptForOthersText(i18nc("@option:check on SignEncryptPage", "Encrypt for &others:"));
0155         mWidget->setEncryptWithPasswordText(
0156             i18nc("@option:check on SignEncryptPage", "Encrypt with &password. Anyone you share the password with can read the data."));
0157         vLay->addWidget(mWidget);
0158         connect(mWidget, &SignEncryptWidget::operationChanged, this, &SigEncPage::updateCommitButton);
0159         connect(mWidget, &SignEncryptWidget::keysChanged, this, &SigEncPage::updateFileWidgets);
0160 
0161         auto outputGrp = new QGroupBox(i18nc("@title:group", "Output"));
0162         outputGrp->setLayout(mOutLayout);
0163 
0164         mPlaceholderWidget = new QLabel(i18n("Please select an action."));
0165         mOutLayout->addWidget(mPlaceholderWidget);
0166 
0167         mOutputLabel = new QLabel(i18nc("@label on SignEncryptPage", "Output &files/folder:"));
0168         mOutLayout->addWidget(mOutputLabel);
0169 
0170         createRequesters(mOutLayout);
0171 
0172         mUseOutputDirChk = new QCheckBox(i18nc("@option:check on SignEncryptPage", "Encrypt / Sign &each file separately."));
0173         mUseOutputDirChk->setToolTip(i18nc("@info:tooltip", "Keep each file separate instead of creating an archive for all."));
0174         mOutLayout->addWidget(mUseOutputDirChk);
0175         connect(mUseOutputDirChk, &QCheckBox::toggled, this, [this](bool state) {
0176             mUseOutputDir = state;
0177             mArchive = !mUseOutputDir && !mSingleFile;
0178             updateFileWidgets();
0179         });
0180 
0181         vLay->addWidget(outputGrp);
0182 
0183         auto messageWidget = new KMessageWidget;
0184         messageWidget->setMessageType(KMessageWidget::Error);
0185         messageWidget->setIcon(style()->standardIcon(QStyle::SP_MessageBoxCritical, nullptr, this));
0186         messageWidget->setText(i18n("Invalid compliance settings for signing and encrypting files."));
0187         messageWidget->setToolTip(xi18nc("@info %1 is a placeholder for the name of a compliance mode. E.g. NATO RESTRICTED compliant or VS-NfD compliant",
0188                                          "<para>You cannot use <application>Kleopatra</application> for signing or encrypting files "
0189                                          "because the <application>GnuPG</application> system used by <application>Kleopatra</application> is not %1.</para>",
0190                                          DeVSCompliance::name(true)));
0191         messageWidget->setCloseButtonVisible(false);
0192         messageWidget->setVisible(DeVSCompliance::isActive() && !DeVSCompliance::isCompliant());
0193         vLay->addWidget(messageWidget);
0194 
0195         setMinimumHeight(300);
0196     }
0197 
0198     void setEncryptionPreset(bool value)
0199     {
0200         mWidget->setEncryptionChecked(value);
0201     }
0202 
0203     void setSigningPreset(bool value)
0204     {
0205         mWidget->setSigningChecked(value);
0206     }
0207 
0208     bool isComplete() const override
0209     {
0210         if (DeVSCompliance::isActive() && !DeVSCompliance::isCompliant()) {
0211             return false;
0212         }
0213         return mWidget->isComplete();
0214     }
0215 
0216     int nextId() const override
0217     {
0218         return ResultPageId;
0219     }
0220 
0221     void initializePage() override
0222     {
0223         setCommitPage(true);
0224         updateCommitButton(mWidget->currentOp());
0225     }
0226 
0227     void setArchiveForced(bool archive)
0228     {
0229         mArchive = archive;
0230         setArchiveMutable(!archive);
0231     }
0232 
0233     void setArchiveMutable(bool archive)
0234     {
0235         mUseOutputDirChk->setVisible(archive);
0236         if (archive) {
0237             const KConfigGroup archCfg(KSharedConfig::openConfig(), QStringLiteral("SignEncryptFilesWizard"));
0238             mUseOutputDirChk->setChecked(archCfg.readEntry("LastUseOutputDir", false));
0239         } else {
0240             mUseOutputDirChk->setChecked(false);
0241         }
0242     }
0243 
0244     void setSingleFile(bool singleFile)
0245     {
0246         mSingleFile = singleFile;
0247         mArchive = !mUseOutputDir && !mSingleFile;
0248     }
0249 
0250     bool validatePage() override
0251     {
0252         if (DeVSCompliance::isActive() && !DeVSCompliance::isCompliant()) {
0253             KMessageBox::error(topLevelWidget(),
0254                                xi18nc("@info %1 is a placeholder for the name of a compliance mode. E.g. NATO RESTRICTED compliant or VS-NfD compliant",
0255                                       "<para>Sorry! You cannot use <application>Kleopatra</application> for signing or encrypting files "
0256                                       "because the <application>GnuPG</application> system used by <application>Kleopatra</application> is not %1.</para>",
0257                                       DeVSCompliance::name(true)));
0258             return false;
0259         }
0260         bool sign = !mWidget->signKey().isNull();
0261         bool encrypt = !mWidget->selfKey().isNull() || !mWidget->recipients().empty();
0262         if (!mWidget->validate()) {
0263             return false;
0264         }
0265         mWidget->saveOwnKeys();
0266         if (mUseOutputDirChk->isVisible()) {
0267             KConfigGroup archCfg(KSharedConfig::openConfig(), QStringLiteral("SignEncryptFilesWizard"));
0268             archCfg.writeEntry("LastUseOutputDir", mUseOutputDir);
0269         }
0270 
0271         if (sign && !encrypt && mArchive) {
0272             return KMessageBox::warningContinueCancel(
0273                        this,
0274                        xi18nc("@info",
0275                               "<para>Archiving in combination with sign-only currently requires what are known as opaque signatures - "
0276                               "unlike detached ones, these embed the content in the signature.</para>"
0277                               "<para>This format is rather unusual. You might want to archive the files separately, "
0278                               "and then sign the archive as one file with Kleopatra.</para>"
0279                               "<para>Future versions of Kleopatra are expected to also support detached signatures in this case.</para>"),
0280                        i18nc("@title:window", "Unusual Signature Warning"),
0281                        KStandardGuiItem::cont(),
0282                        KStandardGuiItem::cancel(),
0283                        QStringLiteral("signencryptfileswizard-archive+sign-only-warning"))
0284                 == KMessageBox::Continue;
0285         } else if (sign && !encrypt) {
0286             return true;
0287         }
0288 
0289         if (!mWidget->selfKey().isNull() || mWidget->encryptSymmetric()) {
0290             return true;
0291         }
0292         const auto recipientKeys = recipients();
0293         const bool hasSecret = std::any_of(std::begin(recipientKeys), std::end(recipientKeys), [](const auto &k) {
0294             return k.hasSecret();
0295         });
0296         if (!hasSecret) {
0297             if (KMessageBox::warningContinueCancel(this,
0298                                                    xi18nc("@info",
0299                                                           "<para>None of the recipients you are encrypting to seems to be your own.</para>"
0300                                                           "<para>This means that you will not be able to decrypt the data anymore, once encrypted.</para>"
0301                                                           "<para>Do you want to continue, or cancel to change the recipient selection?</para>"),
0302                                                    i18nc("@title:window", "Encrypt-To-Self Warning"),
0303                                                    KStandardGuiItem::cont(),
0304                                                    KStandardGuiItem::cancel(),
0305                                                    QStringLiteral("warn-encrypt-to-non-self"),
0306                                                    KMessageBox::Notify | KMessageBox::Dangerous)
0307                 == KMessageBox::Cancel) {
0308                 return false;
0309             }
0310         }
0311         return true;
0312     }
0313 
0314     std::vector<Key> recipients() const
0315     {
0316         return mWidget->recipients();
0317     }
0318 
0319     /* In the future we might find a usecase for multiple
0320      * signers */
0321     std::vector<Key> signers() const
0322     {
0323         const Key k = mWidget->signKey();
0324         if (!k.isNull()) {
0325             return {k};
0326         }
0327         return {};
0328     }
0329 
0330 private:
0331     struct RequesterInfo {
0332         SignEncryptFilesWizard::KindNames id;
0333         QString icon;
0334         QString toolTip;
0335         QString accessibleName;
0336         QString nameFilterBinary;
0337         QString nameFilterAscii;
0338     };
0339     void createRequesters(QBoxLayout *lay)
0340     {
0341         static const std::array<RequesterInfo, 6> requestersInfo = {{
0342             {
0343                 SignEncryptFilesWizard::SignatureCMS,
0344                 QStringLiteral("document-sign"),
0345                 i18nc("@info:tooltip", "This is the filename of the S/MIME signature."),
0346                 i18nc("Lineedit accessible name", "S/MIME signature file"),
0347                 i18nc("Name filter binary", "S/MIME Signatures (*.p7s)"),
0348                 i18nc("Name filter ASCII", "S/MIME Signatures (*.p7s *.pem)"),
0349             },
0350             {
0351                 SignEncryptFilesWizard::SignaturePGP,
0352                 QStringLiteral("document-sign"),
0353                 i18nc("@info:tooltip", "This is the filename of the detached OpenPGP signature."),
0354                 i18nc("Lineedit accessible name", "OpenPGP signature file"),
0355                 i18nc("Name filter binary", "OpenPGP Signatures (*.sig *.pgp)"),
0356                 i18nc("Name filter ASCII", "OpenPGP Signatures (*.asc *.sig)"),
0357             },
0358             {
0359                 SignEncryptFilesWizard::CombinedPGP,
0360                 QStringLiteral("document-edit-sign-encrypt"),
0361                 i18nc("@info:tooltip", "This is the filename of the OpenPGP-signed and encrypted file."),
0362                 i18nc("Lineedit accessible name", "OpenPGP signed and encrypted file"),
0363                 i18nc("Name filter binary", "OpenPGP Files (*.gpg *.pgp)"),
0364                 i18nc("Name filter ASCII", "OpenPGP Files (*.asc)"),
0365             },
0366             {
0367                 SignEncryptFilesWizard::EncryptedPGP,
0368                 QStringLiteral("document-encrypt"),
0369                 i18nc("@info:tooltip", "This is the filename of the OpenPGP encrypted file."),
0370                 i18nc("Lineedit accessible name", "OpenPGP encrypted file"),
0371                 i18nc("Name filter binary", "OpenPGP Files (*.gpg *.pgp)"),
0372                 i18nc("Name filter ASCII", "OpenPGP Files (*.asc)"),
0373             },
0374             {
0375                 SignEncryptFilesWizard::EncryptedCMS,
0376                 QStringLiteral("document-encrypt"),
0377                 i18nc("@info:tooltip", "This is the filename of the S/MIME encrypted file."),
0378                 i18nc("Lineedit accessible name", "S/MIME encrypted file"),
0379                 i18nc("Name filter binary", "S/MIME Files (*.p7m)"),
0380                 i18nc("Name filter ASCII", "S/MIME Files (*.p7m *.pem)"),
0381             },
0382             {
0383                 SignEncryptFilesWizard::Directory,
0384                 QStringLiteral("folder"),
0385                 i18nc("@info:tooltip", "The resulting files are written to this directory."),
0386                 i18nc("Lineedit accessible name", "Output directory"),
0387                 {},
0388                 {},
0389             },
0390         }};
0391 
0392         if (!mRequesters.empty()) {
0393             return;
0394         }
0395         const bool isAscii = FileOperationsPreferences().addASCIIArmor();
0396         for (const auto &requester : requestersInfo) {
0397             const auto id = requester.id;
0398             auto requesterWithIcon = new FileNameRequesterWithIcon{id == SignEncryptFilesWizard::Directory ? QDir::Dirs : QDir::Files, this};
0399             requesterWithIcon->setIcon(QIcon::fromTheme(requester.icon));
0400             requesterWithIcon->setToolTip(requester.toolTip);
0401             requesterWithIcon->requester()->setAccessibleNameOfLineEdit(requester.accessibleName);
0402             requesterWithIcon->setNameFilter(isAscii ? requester.nameFilterAscii : requester.nameFilterBinary);
0403             lay->addWidget(requesterWithIcon);
0404 
0405             connect(requesterWithIcon, &FileNameRequesterWithIcon::fileNameChanged, this, [this, id](const QString &newName) {
0406                 mOutNames[id] = newName;
0407             });
0408 
0409             mRequesters.insert(id, requesterWithIcon);
0410         }
0411     }
0412 
0413 public:
0414     void setOutputNames(const QMap<int, QString> &names)
0415     {
0416         Q_ASSERT(mOutNames.isEmpty());
0417         for (auto it = std::begin(names); it != std::end(names); ++it) {
0418             mRequesters.value(it.key())->setFileName(it.value());
0419         }
0420         mOutNames = names;
0421         updateFileWidgets();
0422     }
0423 
0424     QMap<int, QString> outputNames() const
0425     {
0426         if (!mUseOutputDir) {
0427             auto ret = mOutNames;
0428             ret.remove(SignEncryptFilesWizard::Directory);
0429             return ret;
0430         }
0431         return mOutNames;
0432     }
0433 
0434     bool encryptSymmetric() const
0435     {
0436         return mWidget->encryptSymmetric();
0437     }
0438 
0439 private Q_SLOTS:
0440     void updateCommitButton(const SignEncryptWidget::Operations op)
0441     {
0442         if (mParent->currentPage() != this) {
0443             return;
0444         }
0445         QString label;
0446         switch (op) {
0447         case SignEncryptWidget::Sign:
0448             label = i18nc("@action:button", "Sign");
0449             break;
0450         case SignEncryptWidget::Encrypt:
0451             label = i18nc("@action:button", "Encrypt");
0452             break;
0453         case SignEncryptWidget::SignAndEncrypt:
0454             label = i18nc("@action:button", "Sign / Encrypt");
0455             break;
0456         default:;
0457         };
0458         auto btn = qobject_cast<QPushButton *>(mParent->button(QWizard::CommitButton));
0459         if (!label.isEmpty()) {
0460             mParent->setButtonText(QWizard::CommitButton, label);
0461             if (DeVSCompliance::isActive()) {
0462                 const bool de_vs = DeVSCompliance::isCompliant() && mWidget->isDeVsAndValid();
0463                 DeVSCompliance::decorate(btn, de_vs);
0464                 mParent->setLabelText(DeVSCompliance::name(de_vs));
0465             }
0466         } else {
0467             mParent->setButtonText(QWizard::CommitButton, i18n("Next"));
0468             btn->setIcon(QIcon());
0469             btn->setStyleSheet(QString());
0470         }
0471         Q_EMIT completeChanged();
0472     }
0473 
0474     void updateFileWidgets()
0475     {
0476         if (mRequesters.isEmpty()) {
0477             return;
0478         }
0479         const std::vector<Key> recipients = mWidget->recipients();
0480         const Key sigKey = mWidget->signKey();
0481         const bool pgp = mWidget->encryptSymmetric() || std::any_of(std::cbegin(recipients), std::cend(recipients), [](const auto &k) {
0482                              return k.protocol() == Protocol::OpenPGP;
0483                          });
0484         const bool cms = std::any_of(std::cbegin(recipients), std::cend(recipients), [](const auto &k) {
0485             return k.protocol() == Protocol::CMS;
0486         });
0487 
0488         mOutLayout->setEnabled(false);
0489         if (cms || pgp || !sigKey.isNull()) {
0490             mPlaceholderWidget->setVisible(false);
0491             mOutputLabel->setVisible(true);
0492             mRequesters[SignEncryptFilesWizard::SignatureCMS]->setVisible(!mUseOutputDir && sigKey.protocol() == Protocol::CMS);
0493             mRequesters[SignEncryptFilesWizard::EncryptedCMS]->setVisible(!mUseOutputDir && cms);
0494             mRequesters[SignEncryptFilesWizard::CombinedPGP]->setVisible(!mUseOutputDir && sigKey.protocol() == Protocol::OpenPGP && pgp);
0495             mRequesters[SignEncryptFilesWizard::EncryptedPGP]->setVisible(!mUseOutputDir && sigKey.protocol() != Protocol::OpenPGP && pgp);
0496             mRequesters[SignEncryptFilesWizard::SignaturePGP]->setVisible(!mUseOutputDir && sigKey.protocol() == Protocol::OpenPGP && !pgp);
0497             mRequesters[SignEncryptFilesWizard::Directory]->setVisible(mUseOutputDir);
0498             auto firstNotHidden = std::find_if(std::cbegin(mRequesters), std::cend(mRequesters), [](auto w) {
0499                 return !w->isHidden();
0500             });
0501             mOutputLabel->setBuddy(*firstNotHidden);
0502         } else {
0503             mPlaceholderWidget->setVisible(true);
0504             mOutputLabel->setVisible(false);
0505             std::for_each(std::cbegin(mRequesters), std::cend(mRequesters), [](auto w) {
0506                 w->setVisible(false);
0507             });
0508             mOutputLabel->setBuddy(nullptr);
0509         }
0510         mOutLayout->setEnabled(true);
0511     }
0512 
0513 private:
0514     SignEncryptFilesWizard *mParent;
0515     SignEncryptWidget *mWidget;
0516     QMap<int, QString> mOutNames;
0517     QMap<int, FileNameRequesterWithIcon *> mRequesters;
0518     QVBoxLayout *mOutLayout;
0519     QWidget *mPlaceholderWidget;
0520     QCheckBox *mUseOutputDirChk;
0521     QLabel *mOutputLabel;
0522     bool mArchive;
0523     bool mUseOutputDir;
0524     bool mSingleFile;
0525 };
0526 
0527 class ResultPage : public NewResultPage
0528 {
0529     Q_OBJECT
0530 
0531 public:
0532     explicit ResultPage(QWidget *parent = nullptr)
0533         : NewResultPage(parent)
0534         , mParent((SignEncryptFilesWizard *)parent)
0535     {
0536         setTitle(i18nc("@title", "Results"));
0537         setSubTitle(i18nc("@title", "Status and progress of the crypto operations is shown here."));
0538     }
0539 
0540     void initializePage() override
0541     {
0542         mParent->setLabelText(QString());
0543     }
0544 
0545 private:
0546     SignEncryptFilesWizard *mParent;
0547 };
0548 
0549 SignEncryptFilesWizard::SignEncryptFilesWizard(QWidget *parent, Qt::WindowFlags f)
0550     : QWizard(parent, f)
0551 {
0552     readConfig();
0553 
0554     const bool de_vs = DeVSCompliance::isActive();
0555 #ifdef Q_OS_WIN
0556     // Enforce modern style to avoid vista style ugliness.
0557     setWizardStyle(QWizard::ModernStyle);
0558 #endif
0559     mSigEncPage = new SigEncPage(this);
0560     mResultPage = new ResultPage(this);
0561 
0562     connect(this, &QWizard::currentIdChanged, this, &SignEncryptFilesWizard::slotCurrentIdChanged);
0563     setPage(SigEncPageId, mSigEncPage);
0564     setPage(ResultPageId, mResultPage);
0565     setOptions(QWizard::IndependentPages | //
0566                (de_vs ? QWizard::HaveCustomButton1 : QWizard::WizardOption(0)) | //
0567                QWizard::NoBackButtonOnLastPage | //
0568                QWizard::NoBackButtonOnStartPage);
0569 
0570     if (de_vs) {
0571         /* We use a custom button to display a label next to the
0572            buttons.  */
0573         auto btn = button(QWizard::CustomButton1);
0574         /* We style the button so that it looks and acts like a
0575            label.  */
0576         btn->setStyleSheet(QStringLiteral("border: none"));
0577         btn->setFocusPolicy(Qt::NoFocus);
0578     }
0579 }
0580 
0581 void SignEncryptFilesWizard::setLabelText(const QString &label)
0582 {
0583     button(QWizard::CommitButton)->setToolTip(label);
0584     setButtonText(QWizard::CustomButton1, label);
0585 }
0586 
0587 void SignEncryptFilesWizard::slotCurrentIdChanged(int id)
0588 {
0589     if (id == ResultPageId) {
0590         Q_EMIT operationPrepared();
0591     }
0592 }
0593 
0594 SignEncryptFilesWizard::~SignEncryptFilesWizard()
0595 {
0596     qCDebug(KLEOPATRA_LOG) << this << __func__;
0597     writeConfig();
0598 }
0599 
0600 void SignEncryptFilesWizard::setSigningPreset(bool preset)
0601 {
0602     mSigEncPage->setSigningPreset(preset);
0603 }
0604 
0605 void SignEncryptFilesWizard::setSigningUserMutable(bool mut)
0606 {
0607     if (mut == mSigningUserMutable) {
0608         return;
0609     }
0610     mSigningUserMutable = mut;
0611 }
0612 
0613 void SignEncryptFilesWizard::setEncryptionPreset(bool preset)
0614 {
0615     mSigEncPage->setEncryptionPreset(preset);
0616 }
0617 
0618 void SignEncryptFilesWizard::setEncryptionUserMutable(bool mut)
0619 {
0620     if (mut == mEncryptionUserMutable) {
0621         return;
0622     }
0623     mEncryptionUserMutable = mut;
0624 }
0625 
0626 void SignEncryptFilesWizard::setArchiveForced(bool archive)
0627 {
0628     mSigEncPage->setArchiveForced(archive);
0629 }
0630 
0631 void SignEncryptFilesWizard::setArchiveMutable(bool archive)
0632 {
0633     mSigEncPage->setArchiveMutable(archive);
0634 }
0635 
0636 void SignEncryptFilesWizard::setSingleFile(bool singleFile)
0637 {
0638     mSigEncPage->setSingleFile(singleFile);
0639 }
0640 
0641 std::vector<Key> SignEncryptFilesWizard::resolvedRecipients() const
0642 {
0643     return mSigEncPage->recipients();
0644 }
0645 
0646 std::vector<Key> SignEncryptFilesWizard::resolvedSigners() const
0647 {
0648     return mSigEncPage->signers();
0649 }
0650 
0651 void SignEncryptFilesWizard::setTaskCollection(const std::shared_ptr<Kleo::Crypto::TaskCollection> &coll)
0652 {
0653     mResultPage->setTaskCollection(coll);
0654 }
0655 
0656 void SignEncryptFilesWizard::setOutputNames(const QMap<int, QString> &map) const
0657 {
0658     mSigEncPage->setOutputNames(map);
0659 }
0660 
0661 QMap<int, QString> SignEncryptFilesWizard::outputNames() const
0662 {
0663     return mSigEncPage->outputNames();
0664 }
0665 
0666 bool SignEncryptFilesWizard::encryptSymmetric() const
0667 {
0668     return mSigEncPage->encryptSymmetric();
0669 }
0670 
0671 void SignEncryptFilesWizard::readConfig()
0672 {
0673     winId(); // ensure there's a window created
0674 
0675     // set default window size
0676     windowHandle()->resize(640, 480);
0677 
0678     // restore size from config file
0679     KConfigGroup cfgGroup(KSharedConfig::openConfig(), QStringLiteral("SignEncryptFilesWizard"));
0680     KWindowConfig::restoreWindowSize(windowHandle(), cfgGroup);
0681 
0682     // NOTICE: QWindow::setGeometry() does NOT impact the backing QWidget geometry even if the platform
0683     // window was created -> QTBUG-40584. We therefore copy the size here.
0684     // TODO: remove once this was resolved in QWidget QPA
0685     resize(windowHandle()->size());
0686 }
0687 
0688 void SignEncryptFilesWizard::writeConfig()
0689 {
0690     KConfigGroup cfgGroup(KSharedConfig::openConfig(), QStringLiteral("SignEncryptFilesWizard"));
0691     KWindowConfig::saveWindowSize(windowHandle(), cfgGroup);
0692     cfgGroup.sync();
0693 }
0694 
0695 #include "signencryptfileswizard.moc"
0696 
0697 #include "moc_signencryptfileswizard.cpp"