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

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     crypto/gui/decryptverifywizard.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "decryptverifyfileswizard.h"
0013 
0014 #include "decryptverifyoperationwidget.h"
0015 
0016 #include <crypto/gui/resultpage.h>
0017 #include <crypto/gui/wizardpage.h>
0018 
0019 #include <crypto/task.h>
0020 #include <crypto/taskcollection.h>
0021 
0022 #include <utils/kleo_assert.h>
0023 #include <utils/scrollarea.h>
0024 
0025 #include <Libkleo/FileNameRequester>
0026 #include <Libkleo/Stl_Util>
0027 
0028 #include <KGuiItem>
0029 #include <KLocalizedString>
0030 
0031 #include <QBoxLayout>
0032 #include <QCheckBox>
0033 #include <QLabel>
0034 #include <QTimer>
0035 #include <QTreeView>
0036 
0037 #include <vector>
0038 
0039 using namespace Kleo;
0040 using namespace Kleo::Crypto;
0041 using namespace Kleo::Crypto::Gui;
0042 
0043 namespace
0044 {
0045 
0046 class HLine : public QFrame
0047 {
0048     Q_OBJECT
0049 public:
0050     explicit HLine(QWidget *p = nullptr, Qt::WindowFlags f = {})
0051         : QFrame(p, f)
0052     {
0053         setFrameStyle(static_cast<int>(QFrame::HLine) | static_cast<int>(QFrame::Sunken));
0054     }
0055 };
0056 
0057 class OperationsWidget : public WizardPage
0058 {
0059     Q_OBJECT
0060 public:
0061     explicit OperationsWidget(QWidget *p = nullptr);
0062     ~OperationsWidget() override;
0063 
0064     void setOutputDirectory(const QString &dir)
0065     {
0066         m_ui.outputDirectoryFNR.setFileName(dir);
0067     }
0068 
0069     QString outputDirectory() const
0070     {
0071         return m_ui.outputDirectoryFNR.fileName();
0072     }
0073 
0074     bool useOutputDirectory() const
0075     {
0076         return m_ui.useOutputDirectoryCB.isChecked();
0077     }
0078 
0079     void ensureIndexAvailable(unsigned int idx);
0080 
0081     DecryptVerifyOperationWidget *widget(unsigned int idx)
0082     {
0083         return m_widgets.at(idx);
0084     }
0085 
0086     bool isComplete() const override
0087     {
0088         return std::all_of(m_widgets.cbegin(), m_widgets.cend(), [](const auto &w) {
0089             switch (w->mode()) {
0090             case DecryptVerifyOperationWidget::VerifyDetachedWithSignature:
0091             case DecryptVerifyOperationWidget::VerifyDetachedWithSignedData: {
0092                 const QString sigFileName = w->inputFileName();
0093                 const QString dataFileName = w->signedDataFileName();
0094                 return !sigFileName.isEmpty() && !dataFileName.isEmpty() && QFile::exists(sigFileName) && QFile::exists(dataFileName);
0095             }
0096             case DecryptVerifyOperationWidget::DecryptVerifyOpaque:;
0097             }
0098             return true;
0099         });
0100     }
0101 
0102 private:
0103     std::vector<DecryptVerifyOperationWidget *> m_widgets;
0104 
0105     struct UI {
0106         QCheckBox useOutputDirectoryCB;
0107         QLabel outputDirectoryLB;
0108         FileNameRequester outputDirectoryFNR;
0109         ScrollArea scrollArea; // ### replace with KDScrollArea when done
0110         QVBoxLayout vlay;
0111         QHBoxLayout hlay;
0112 
0113         explicit UI(OperationsWidget *q);
0114     } m_ui;
0115 };
0116 }
0117 
0118 class DecryptVerifyFilesWizard::Private
0119 {
0120     friend class ::Kleo::Crypto::Gui::DecryptVerifyFilesWizard;
0121     DecryptVerifyFilesWizard *const q;
0122 
0123 public:
0124     Private(DecryptVerifyFilesWizard *qq);
0125     ~Private();
0126 
0127     void ensureIndexAvailable(unsigned int idx)
0128     {
0129         operationsPage.ensureIndexAvailable(idx);
0130     }
0131 
0132 private:
0133     OperationsWidget operationsPage;
0134     Gui::ResultPage resultPage;
0135 };
0136 
0137 DecryptVerifyFilesWizard::DecryptVerifyFilesWizard(QWidget *p, Qt::WindowFlags f)
0138     : Wizard(p, f)
0139     , d(new Private(this))
0140 {
0141 }
0142 
0143 DecryptVerifyFilesWizard::~DecryptVerifyFilesWizard()
0144 {
0145 }
0146 
0147 void DecryptVerifyFilesWizard::setOutputDirectory(const QString &dir)
0148 {
0149     d->operationsPage.setOutputDirectory(dir);
0150 }
0151 
0152 QString DecryptVerifyFilesWizard::outputDirectory() const
0153 {
0154     return d->operationsPage.outputDirectory();
0155 }
0156 
0157 bool DecryptVerifyFilesWizard::useOutputDirectory() const
0158 {
0159     return d->operationsPage.useOutputDirectory();
0160 }
0161 
0162 DecryptVerifyOperationWidget *DecryptVerifyFilesWizard::operationWidget(unsigned int idx)
0163 {
0164     d->ensureIndexAvailable(idx);
0165     return d->operationsPage.widget(idx);
0166 }
0167 
0168 void DecryptVerifyFilesWizard::onNext(int id)
0169 {
0170     if (id == OperationsPage) {
0171         QTimer::singleShot(0, this, &DecryptVerifyFilesWizard::operationPrepared);
0172     }
0173     Wizard::onNext(id);
0174 }
0175 
0176 void DecryptVerifyFilesWizard::setTaskCollection(const std::shared_ptr<TaskCollection> &coll)
0177 {
0178     kleo_assert(coll);
0179     d->resultPage.setTaskCollection(coll);
0180 }
0181 
0182 DecryptVerifyFilesWizard::Private::Private(DecryptVerifyFilesWizard *qq)
0183     : q(qq)
0184     , operationsPage(q)
0185     , resultPage(q)
0186 {
0187     q->setPage(DecryptVerifyFilesWizard::OperationsPage, &operationsPage);
0188     q->setPage(DecryptVerifyFilesWizard::ResultPage, &resultPage);
0189 
0190     std::vector<int> order;
0191     order.push_back(DecryptVerifyFilesWizard::OperationsPage);
0192     order.push_back(DecryptVerifyFilesWizard::ResultPage);
0193     q->setPageOrder(order);
0194     operationsPage.setCommitPage(true);
0195 }
0196 
0197 DecryptVerifyFilesWizard::Private::~Private()
0198 {
0199 }
0200 
0201 OperationsWidget::OperationsWidget(QWidget *p)
0202     : WizardPage(p)
0203     , m_widgets()
0204     , m_ui(this)
0205 {
0206     setTitle(i18n("<b>Choose operations to be performed</b>"));
0207     setSubTitle(
0208         i18n("Here you can check and, if needed, override "
0209              "the operations Kleopatra detected for the input given."));
0210     setCommitPage(true);
0211     setCustomNextButton(KGuiItem(i18n("&Decrypt/Verify")));
0212 }
0213 
0214 OperationsWidget::~OperationsWidget()
0215 {
0216 }
0217 
0218 OperationsWidget::UI::UI(OperationsWidget *q)
0219     : useOutputDirectoryCB(i18n("Create all output files in a single folder"), q)
0220     , outputDirectoryLB(i18n("&Output folder:"), q)
0221     , outputDirectoryFNR(q)
0222     , scrollArea(q)
0223     , vlay(q)
0224     , hlay()
0225 {
0226     KDAB_SET_OBJECT_NAME(useOutputDirectoryCB);
0227     KDAB_SET_OBJECT_NAME(outputDirectoryLB);
0228     KDAB_SET_OBJECT_NAME(outputDirectoryFNR);
0229     KDAB_SET_OBJECT_NAME(scrollArea);
0230 
0231     KDAB_SET_OBJECT_NAME(vlay);
0232     KDAB_SET_OBJECT_NAME(hlay);
0233 
0234     outputDirectoryFNR.setFilter(QDir::Dirs);
0235 
0236     useOutputDirectoryCB.setChecked(true);
0237     connect(&useOutputDirectoryCB, &QCheckBox::toggled, &outputDirectoryLB, &QLabel::setEnabled);
0238     connect(&useOutputDirectoryCB, &QCheckBox::toggled, &outputDirectoryFNR, &FileNameRequester::setEnabled);
0239 
0240     Q_ASSERT(qobject_cast<QBoxLayout *>(scrollArea.widget()->layout()));
0241     static_cast<QBoxLayout *>(scrollArea.widget()->layout())->addStretch(1);
0242     outputDirectoryLB.setBuddy(&outputDirectoryFNR);
0243 
0244     hlay.setContentsMargins(0, 0, 0, 0);
0245 
0246     vlay.addWidget(&scrollArea, 1);
0247     vlay.addWidget(&useOutputDirectoryCB);
0248     vlay.addLayout(&hlay);
0249     hlay.addWidget(&outputDirectoryLB);
0250     hlay.addWidget(&outputDirectoryFNR);
0251 }
0252 
0253 void OperationsWidget::ensureIndexAvailable(unsigned int idx)
0254 {
0255     if (idx < m_widgets.size()) {
0256         return;
0257     }
0258 
0259     Q_ASSERT(m_ui.scrollArea.widget());
0260     Q_ASSERT(qobject_cast<QBoxLayout *>(m_ui.scrollArea.widget()->layout()));
0261     QBoxLayout &blay = *static_cast<QBoxLayout *>(m_ui.scrollArea.widget()->layout());
0262 
0263     for (unsigned int i = m_widgets.size(); i < idx + 1; ++i) {
0264         if (i) {
0265             blay.insertWidget(blay.count() - 1, new HLine(m_ui.scrollArea.widget()));
0266         }
0267         auto w = new DecryptVerifyOperationWidget(m_ui.scrollArea.widget());
0268         blay.insertWidget(blay.count() - 1, w);
0269         w->show();
0270         connect(w, &DecryptVerifyOperationWidget::changed, this, &WizardPage::completeChanged);
0271         m_widgets.push_back(w);
0272     }
0273 }
0274 
0275 #include "decryptverifyfileswizard.moc"
0276 
0277 #include "moc_decryptverifyfileswizard.cpp"