File indexing completed on 2025-01-05 04:55:48

0001 /*  -*- c++ -*-
0002     keyapprovaldialog.h
0003 
0004     This file is part of libkleopatra, the KDE keymanagement library
0005     SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB
0006 
0007     Based on kpgpui.h
0008     SPDX-FileCopyrightText: 2001, 2002 the KPGP authors
0009     See file libkdenetwork/AUTHORS.kpgp for details
0010 
0011     SPDX-License-Identifier: GPL-2.0-or-later
0012 */
0013 
0014 #include <config-libkleo.h>
0015 
0016 #include "keyapprovaldialog.h"
0017 
0018 #include "keyrequester.h"
0019 
0020 #include <KLocalizedString>
0021 #include <KSeparator>
0022 
0023 #include <QGpgME/Protocol>
0024 
0025 #include <QComboBox>
0026 #include <QDialogButtonBox>
0027 #include <QGridLayout>
0028 #include <QLabel>
0029 #include <QPushButton>
0030 #include <QScreen>
0031 #include <QScrollArea>
0032 #include <QStringList>
0033 #include <QVBoxLayout>
0034 
0035 #include <gpgme++/key.h>
0036 
0037 static Kleo::EncryptionPreference cb2pref(int i)
0038 {
0039     switch (i) {
0040     default:
0041     case 0:
0042         return Kleo::UnknownPreference;
0043     case 1:
0044         return Kleo::NeverEncrypt;
0045     case 2:
0046         return Kleo::AlwaysEncrypt;
0047     case 3:
0048         return Kleo::AlwaysEncryptIfPossible;
0049     case 4:
0050         return Kleo::AlwaysAskForEncryption;
0051     case 5:
0052         return Kleo::AskWheneverPossible;
0053     }
0054 }
0055 
0056 static int pref2cb(Kleo::EncryptionPreference p)
0057 {
0058     switch (p) {
0059     default:
0060         return 0;
0061     case Kleo::NeverEncrypt:
0062         return 1;
0063     case Kleo::AlwaysEncrypt:
0064         return 2;
0065     case Kleo::AlwaysEncryptIfPossible:
0066         return 3;
0067     case Kleo::AlwaysAskForEncryption:
0068         return 4;
0069     case Kleo::AskWheneverPossible:
0070         return 5;
0071     }
0072 }
0073 
0074 static QStringList preferencesStrings()
0075 {
0076     return QStringList() << xi18n("<placeholder>none</placeholder>") //
0077                          << i18n("Never Encrypt with This Key") //
0078                          << i18n("Always Encrypt with This Key") //
0079                          << i18n("Encrypt Whenever Encryption is Possible") //
0080                          << i18n("Always Ask") //
0081                          << i18n("Ask Whenever Encryption is Possible");
0082 }
0083 
0084 class Q_DECL_HIDDEN Kleo::KeyApprovalDialog::KeyApprovalDialogPrivate
0085 {
0086 public:
0087     KeyApprovalDialogPrivate()
0088     {
0089     }
0090 
0091     Kleo::KeyRequester *selfRequester = nullptr;
0092     QStringList addresses;
0093     std::vector<Kleo::KeyRequester *> requesters;
0094     std::vector<QComboBox *> preferences;
0095     bool prefsChanged = false;
0096 };
0097 
0098 Kleo::KeyApprovalDialog::KeyApprovalDialog(const std::vector<Item> &recipients, const std::vector<GpgME::Key> &sender, QWidget *parent)
0099     : QDialog(parent)
0100     , d(new KeyApprovalDialogPrivate())
0101 {
0102     setWindowTitle(i18nc("@title:window", "Encryption Key Approval"));
0103     auto mainLayout = new QVBoxLayout(this);
0104     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
0105     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0106     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0107     connect(buttonBox, &QDialogButtonBox::accepted, this, &KeyApprovalDialog::accept);
0108     connect(buttonBox, &QDialogButtonBox::rejected, this, &KeyApprovalDialog::reject);
0109     okButton->setDefault(true);
0110     Q_ASSERT(!recipients.empty());
0111 
0112     QFrame *page = new QFrame(this);
0113     mainLayout->addWidget(page);
0114     mainLayout->addWidget(buttonBox);
0115     auto vlay = new QVBoxLayout(page);
0116     vlay->setContentsMargins(0, 0, 0, 0);
0117 
0118     vlay->addWidget(new QLabel(i18n("The following keys will be used for encryption:"), page));
0119 
0120     auto sv = new QScrollArea(page);
0121     sv->setWidgetResizable(true);
0122     vlay->addWidget(sv);
0123 
0124     QWidget *view = new QWidget(sv->viewport());
0125 
0126     auto glay = new QGridLayout(view);
0127     glay->setColumnStretch(1, 1);
0128     sv->setWidget(view);
0129 
0130     int row = -1;
0131 
0132     if (!sender.empty()) {
0133         ++row;
0134         glay->addWidget(new QLabel(i18n("Your keys:"), view), row, 0);
0135         d->selfRequester = new EncryptionKeyRequester(true, EncryptionKeyRequester::AllProtocols, view);
0136         d->selfRequester->setKeys(sender);
0137         glay->addWidget(d->selfRequester, row, 1);
0138         ++row;
0139         glay->addWidget(new KSeparator(Qt::Horizontal, view), row, 0, 1, 2);
0140     }
0141 
0142     const QStringList prefs = preferencesStrings();
0143 
0144     for (auto it = recipients.begin(); it != recipients.end(); ++it) {
0145         ++row;
0146         glay->addWidget(new QLabel(i18n("Recipient:"), view), row, 0);
0147         glay->addWidget(new QLabel(it->address, view), row, 1);
0148         d->addresses.push_back(it->address);
0149 
0150         ++row;
0151         glay->addWidget(new QLabel(i18n("Encryption keys:"), view), row, 0);
0152         KeyRequester *req = new EncryptionKeyRequester(true, EncryptionKeyRequester::AllProtocols, view);
0153         req->setKeys(it->keys);
0154         glay->addWidget(req, row, 1);
0155         d->requesters.push_back(req);
0156 
0157         ++row;
0158         glay->addWidget(new QLabel(i18n("Encryption preference:"), view), row, 0);
0159         auto cb = new QComboBox(view);
0160         cb->setEditable(false);
0161         cb->addItems(prefs);
0162         glay->addWidget(cb, row, 1);
0163         cb->setCurrentIndex(pref2cb(it->pref));
0164         connect(cb, qOverload<int>(&QComboBox::activated), this, &KeyApprovalDialog::slotPrefsChanged);
0165         d->preferences.push_back(cb);
0166     }
0167 
0168     QSize size = sizeHint();
0169 
0170     // don't make the dialog too large
0171     const QSize desk = screen()->size();
0172     resize(QSize(qMin(size.width(), 3 * desk.width() / 4), qMin(size.height(), 7 * desk.height() / 8)));
0173 }
0174 
0175 Kleo::KeyApprovalDialog::~KeyApprovalDialog() = default;
0176 
0177 std::vector<GpgME::Key> Kleo::KeyApprovalDialog::senderKeys() const
0178 {
0179     return d->selfRequester ? d->selfRequester->keys() : std::vector<GpgME::Key>();
0180 }
0181 
0182 std::vector<Kleo::KeyApprovalDialog::Item> Kleo::KeyApprovalDialog::items() const
0183 {
0184     Q_ASSERT(d->requesters.size() == static_cast<unsigned int>(d->addresses.size()));
0185     Q_ASSERT(d->requesters.size() == d->preferences.size());
0186 
0187     std::vector<Item> result;
0188     result.reserve(d->requesters.size());
0189     QStringList::const_iterator ait = d->addresses.constBegin();
0190     auto rit = d->requesters.begin();
0191     auto cit = d->preferences.begin();
0192     while (ait != d->addresses.constEnd()) {
0193         result.push_back(Item(*ait++, (*rit++)->keys(), cb2pref((*cit++)->currentIndex())));
0194     }
0195     return result;
0196 }
0197 
0198 bool Kleo::KeyApprovalDialog::preferencesChanged() const
0199 {
0200     return d->prefsChanged;
0201 }
0202 
0203 void Kleo::KeyApprovalDialog::slotPrefsChanged()
0204 {
0205     d->prefsChanged = true;
0206 }
0207 
0208 #include "moc_keyapprovaldialog.cpp"