Page MenuHome GnuPG

newkeyapprovaldialog.cpp
No OneTemporary

newkeyapprovaldialog.cpp

/* -*- c++ -*-
newkeyapprovaldialog.cpp
This file is part of libkleopatra, the KDE keymanagement library
SPDX-FileCopyrightText: 2018 Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "newkeyapprovaldialog.h"
#include "kleo/defaultkeyfilter.h"
#include "keyselectioncombo.h"
#include "progressdialog.h"
#include "utils/formatting.h"
#include "libkleo_debug.h"
#include <QApplication>
#include <QButtonGroup>
#include <QDesktopWidget>
#include <QDialogButtonBox>
#include <QGroupBox>
#include <QLabel>
#include <QMap>
#include <QPushButton>
#include <QRadioButton>
#include <QScrollArea>
#include <QToolTip>
#include <QVBoxLayout>
#include <QGpgME/DefaultKeyGenerationJob>
#include <QGpgME/CryptoConfig>
#include <QGpgME/Protocol>
#include <gpgme++/keygenerationresult.h>
#include <gpgme++/key.h>
#include <KLocalizedString>
#include <KMessageBox>
using namespace Kleo;
namespace {
class OpenPGPFilter: public DefaultKeyFilter
{
public:
OpenPGPFilter() : DefaultKeyFilter()
{
setIsOpenPGP(DefaultKeyFilter::Set);
setCanEncrypt(DefaultKeyFilter::Set);
}
};
static std::shared_ptr<KeyFilter> s_pgpFilter = std::shared_ptr<KeyFilter> (new OpenPGPFilter);
class OpenPGPSignFilter: public DefaultKeyFilter
{
public:
OpenPGPSignFilter() : DefaultKeyFilter()
{
/* Also list unusable keys to make it transparent why they are unusable */
setDisabled(DefaultKeyFilter::NotSet);
setRevoked(DefaultKeyFilter::NotSet);
setExpired(DefaultKeyFilter::NotSet);
setCanSign(DefaultKeyFilter::Set);
setHasSecret(DefaultKeyFilter::Set);
setIsOpenPGP(DefaultKeyFilter::Set);
}
};
static std::shared_ptr<KeyFilter> s_pgpSignFilter = std::shared_ptr<KeyFilter> (new OpenPGPSignFilter);
class SMIMEFilter: public DefaultKeyFilter
{
public:
SMIMEFilter(): DefaultKeyFilter()
{
setIsOpenPGP(DefaultKeyFilter::NotSet);
setCanEncrypt(DefaultKeyFilter::Set);
}
};
static std::shared_ptr<KeyFilter> s_smimeFilter = std::shared_ptr<KeyFilter> (new SMIMEFilter);
class SMIMESignFilter: public DefaultKeyFilter
{
public:
SMIMESignFilter(): DefaultKeyFilter()
{
setDisabled(DefaultKeyFilter::NotSet);
setRevoked(DefaultKeyFilter::NotSet);
setExpired(DefaultKeyFilter::NotSet);
setCanSign(DefaultKeyFilter::Set);
setIsOpenPGP(DefaultKeyFilter::NotSet);
setHasSecret(DefaultKeyFilter::Set);
}
};
static std::shared_ptr<KeyFilter> s_smimeSignFilter = std::shared_ptr<KeyFilter> (new SMIMESignFilter);
static std::shared_ptr<KeyFilter> s_defaultFilter= std::shared_ptr<KeyFilter> (new DefaultKeyFilter);
class SignFilter: public DefaultKeyFilter
{
public:
SignFilter(): DefaultKeyFilter()
{
setHasSecret(DefaultKeyFilter::Set);
}
};
static std::shared_ptr<KeyFilter> s_signFilter = std::shared_ptr<KeyFilter> (new SignFilter);
/* Some decoration and a button to remove the filter for a keyselectioncombo */
class ComboWidget: public QWidget
{
Q_OBJECT
public:
explicit ComboWidget(KeySelectionCombo *combo):
mCombo(combo),
mFilterBtn(new QPushButton),
mFromOverride(GpgME::UnknownProtocol)
{
auto hLay = new QHBoxLayout(this);
auto infoBtn = new QPushButton;
infoBtn->setIcon(QIcon::fromTheme(QStringLiteral("help-contextual")));
infoBtn->setIconSize(QSize(22,22));
infoBtn->setFlat(true);
hLay->addWidget(infoBtn);
hLay->addWidget(combo, 1);
hLay->addWidget(mFilterBtn, 0);
connect(infoBtn, &QPushButton::clicked, this, [this, infoBtn] () {
QToolTip::showText(infoBtn->mapToGlobal(QPoint()) + QPoint(infoBtn->width(), 0),
mCombo->currentData(Qt::ToolTipRole).toString(), infoBtn, QRect(), 30000);
});
// Assume that combos start out with a filter
mFilterBtn->setIcon(QIcon::fromTheme(QStringLiteral("kt-remove-filters")));
mFilterBtn->setToolTip(i18n("Remove Filter"));
// FIXME: This is ugly to enforce but otherwise the
// icon is broken.
combo->setMinimumHeight(22);
mFilterBtn->setMinimumHeight(23);
connect(mFilterBtn, &QPushButton::clicked, this, [this] () {
const QString curFilter = mCombo->idFilter();
if (curFilter.isEmpty()) {
mCombo->setIdFilter(mLastIdFilter);
mLastIdFilter = QString();
mFilterBtn->setIcon(QIcon::fromTheme(QStringLiteral("kt-remove-filters")));
mFilterBtn->setToolTip(i18n("Remove Filter"));
} else {
mLastIdFilter = curFilter;
mFilterBtn->setIcon(QIcon::fromTheme(QStringLiteral("kt-add-filters")));
mFilterBtn->setToolTip(i18n("Add Filter"));
mCombo->setIdFilter(QString());
}
});
}
KeySelectionCombo *combo()
{
return mCombo;
}
GpgME::Protocol fromOverride() const
{
return mFromOverride;
}
void setFromOverride(GpgME::Protocol proto)
{
mFromOverride = proto;
}
private:
KeySelectionCombo *mCombo;
QPushButton *mFilterBtn;
QString mLastIdFilter;
GpgME::Protocol mFromOverride;
};
static enum GpgME::UserID::Validity keyValidity(const GpgME::Key &key)
{
enum GpgME::UserID::Validity validity = GpgME::UserID::Validity::Unknown;
for (const auto &uid: key.userIDs()) {
if (validity == GpgME::UserID::Validity::Unknown
|| validity > uid.validity()) {
validity = uid.validity();
}
}
return validity;
}
static bool key_has_addr(const GpgME::Key &key, const QString &addr)
{
for (const auto &uid: key.userIDs()) {
if (QString::fromStdString(uid.addrSpec()).toLower() == addr.toLower()) {
return true;
}
}
return false;
}
} // namespace
class NewKeyApprovalDialog::Private
{
private:
enum Action {
Unset,
GenerateKey,
IgnoreKey,
};
public:
Private(NewKeyApprovalDialog *pub,
GpgME::Protocol forcedProtocol,
GpgME::Protocol presetProtocol,
const QString &sender, bool allowMixed):
mProto(forcedProtocol),
mSender(sender),
mAllowMixed(allowMixed),
q(pub)
{
// We do the translation here to avoid having the same string multiple times.
mGenerateTooltip = i18nc("@info:tooltip for a 'Generate new key pair' action "
"in a combobox when a user does not yet have an OpenPGP or S/MIME key.",
"Generate a new key using your E-Mail address.<br/><br/>"
"The key is necessary to decrypt and sign E-Mails. "
"You will be asked for a passphrase to protect this key and the protected key "
"will be stored in your home directory.");
mMainLay = new QVBoxLayout;
QDialogButtonBox *btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
mOkButton = btnBox->button(QDialogButtonBox::Ok);
QObject::connect (btnBox, &QDialogButtonBox::accepted, q, [this] () {
accepted();
});
QObject::connect (btnBox, &QDialogButtonBox::rejected, q, &QDialog::reject);
mScrollArea = new QScrollArea;
mScrollArea->setWidget(new QWidget);
mScrollLayout = new QVBoxLayout;
mScrollArea->widget()->setLayout(mScrollLayout);
mScrollArea->setWidgetResizable(true);
mScrollArea->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
mScrollArea->setFrameStyle(QFrame::NoFrame);
mScrollLayout->setContentsMargins(0, 0, 0, 0);
q->setWindowTitle(i18nc("@title:window", "Security approval"));
auto fmtLayout = new QHBoxLayout;
mFormatBtns = new QButtonGroup;
auto pgpBtn = new QRadioButton(i18n("OpenPGP"));
auto smimeBtn = new QRadioButton(i18n("S/MIME"));
mFormatBtns->addButton(pgpBtn, 1);
mFormatBtns->addButton(smimeBtn, 2);
mFormatBtns->setExclusive(true);
fmtLayout->addStretch(-1);
fmtLayout->addWidget(pgpBtn);
fmtLayout->addWidget(smimeBtn);
mMainLay->addLayout(fmtLayout);
// Handle force / preset
if (forcedProtocol == GpgME::OpenPGP) {
pgpBtn->setChecked(true);
pgpBtn->setVisible(false);
smimeBtn->setVisible(false);
} else if (forcedProtocol == GpgME::CMS) {
smimeBtn->setChecked(true);
pgpBtn->setVisible(false);
smimeBtn->setVisible(false);
} else if (presetProtocol == GpgME::CMS) {
smimeBtn->setChecked(true);
} else if (!mAllowMixed) {
pgpBtn->setChecked(true);
} else if (mAllowMixed) {
smimeBtn->setVisible(false);
pgpBtn->setVisible(false);
}
updateFilter();
QObject::connect (mFormatBtns, static_cast<void (QButtonGroup::*)(QAbstractButton *, bool)> (&QButtonGroup::buttonToggled),
q, [this](QAbstractButton *, bool) {
updateFilter();
});
mMainLay->addWidget(mScrollArea);
mComplianceLbl = new QLabel;
mComplianceLbl->setVisible(false);
auto btnLayout = new QHBoxLayout;
btnLayout->addWidget(mComplianceLbl);
btnLayout->addWidget(btnBox);
mMainLay->addLayout(btnLayout);
q->setLayout(mMainLay);
}
~Private() = default;
void generateKey(KeySelectionCombo *combo)
{
const auto &addr = combo->property("address").toString();
auto job = new QGpgME::DefaultKeyGenerationJob(q);
auto progress = new Kleo::ProgressDialog(job, i18n("Generating key for '%1'...", addr) + QStringLiteral("\n\n") +
i18n("This can take several minutes."), q);
progress->setWindowFlags(progress->windowFlags() & ~Qt::WindowContextHelpButtonHint);
progress->setWindowTitle(i18nc("@title:window", "Key generation"));
progress->setModal(true);
progress->setAutoClose(true);
progress->setMinimumDuration(0);
progress->setValue(0);
mRunningJobs << job;
connect (job, &QGpgME::DefaultKeyGenerationJob::result, q,
[this, job, combo] (const GpgME::KeyGenerationResult &result) {
handleKeyGenResult(result, job, combo);
});
job->start(addr, QString());
return;
}
void handleKeyGenResult(const GpgME::KeyGenerationResult &result, QGpgME::Job *job, KeySelectionCombo *combo)
{
mLastError = result.error();
if (!mLastError || mLastError.isCanceled()) {
combo->setDefaultKey(QString::fromLatin1(result.fingerprint()), GpgME::OpenPGP);
connect (combo, &KeySelectionCombo::keyListingFinished, q, [this, job] () {
mRunningJobs.removeAll(job);
});
combo->refreshKeys();
} else {
mRunningJobs.removeAll(job);
}
}
void checkAccepted()
{
if (mLastError || mLastError.isCanceled()) {
KMessageBox::error(q, QString::fromLocal8Bit(mLastError.asString()), i18n("Operation Failed"));
mRunningJobs.clear();
return;
}
if (!mRunningJobs.empty()) {
return;
}
/* Save the keys */
bool isPGP = mFormatBtns->checkedId() == 1;
bool isSMIME = mFormatBtns->checkedId() == 2;
mAcceptedEnc.clear();
mAcceptedSig.clear();
for (const auto combo: qAsConst(mEncCombos)) {
const auto &addr = combo->property("address").toString();
const auto &key = combo->currentKey();
if (!combo->isVisible()) {
continue;
}
if (isSMIME && key.protocol() != GpgME::CMS) {
continue;
}
if (isPGP && key.protocol() != GpgME::OpenPGP) {
continue;
}
if (mAcceptedEnc.contains(addr)) {
mAcceptedEnc[addr].push_back(key);
} else {
std::vector<GpgME::Key> vec;
vec.push_back(key);
mAcceptedEnc.insert(addr, vec);
}
}
for (const auto combo: qAsConst(mSigningCombos)) {
const auto key = combo->currentKey();
if (!combo->isVisible()) {
continue;
}
if (isSMIME && key.protocol() != GpgME::CMS) {
continue;
}
if (isPGP && key.protocol() != GpgME::OpenPGP) {
continue;
}
mAcceptedSig.push_back(combo->currentKey());
}
q->accept();
}
void accepted()
{
// We can assume everything was validly resolved, otherwise
// the OK button would have been disabled.
// Handle custom items now.
for (auto combo: qAsConst(mAllCombos)) {
auto act = combo->currentData(Qt::UserRole).toInt();
if (act == GenerateKey) {
generateKey(combo);
// Only generate once
return;
}
}
checkAccepted();
}
void updateFilter()
{
const bool isPGP = !mAllowMixed && mFormatBtns->checkedId() == 1;
const bool isSMIME = !mAllowMixed && mFormatBtns->checkedId() == 2;
if (isSMIME) {
mCurEncFilter = s_smimeFilter;
mCurSigFilter = s_smimeSignFilter;
} else if (isPGP) {
mCurEncFilter = s_pgpFilter;
mCurSigFilter = s_pgpSignFilter;
} else {
mCurEncFilter = s_defaultFilter;
mCurSigFilter = s_signFilter;
}
for (auto combo: qAsConst(mSigningCombos)) {
combo->setKeyFilter(mCurSigFilter);
auto widget = qobject_cast <ComboWidget *>(combo->parentWidget());
if (!widget) {
qCDebug(LIBKLEO_LOG) << "Failed to find signature combo widget";
continue;
}
widget->setVisible(mAllowMixed ||
widget->fromOverride() == GpgME::UnknownProtocol ||
((isSMIME && widget->fromOverride() == GpgME::CMS) ||
(isPGP && widget->fromOverride() == GpgME::OpenPGP)));
}
for (auto combo: qAsConst(mEncCombos)) {
combo->setKeyFilter(mCurEncFilter);
auto widget = qobject_cast <ComboWidget *>(combo->parentWidget());
if (!widget) {
qCDebug(LIBKLEO_LOG) << "Failed to find combo widget";
continue;
}
widget->setVisible(mAllowMixed ||
widget->fromOverride() == GpgME::UnknownProtocol ||
((isSMIME && widget->fromOverride() == GpgME::CMS) ||
(isPGP && widget->fromOverride() == GpgME::OpenPGP)));
}
}
ComboWidget *createSigningCombo(const QString &addr, const GpgME::Key &key)
{
auto combo = new KeySelectionCombo();
#ifndef NDEBUG
combo->setObjectName(QStringLiteral("signing key"));
#endif
combo->setKeyFilter(mCurSigFilter);
if (!key.isNull()) {
if (mAllowMixed) {
// do not set the key for a specific protocol if mixed protocols are allowed
combo->setDefaultKey(QString::fromLatin1(key.primaryFingerprint()));
} else {
combo->setDefaultKey(QString::fromLatin1(key.primaryFingerprint()), key.protocol());
}
}
if (key.isNull() && mProto != GpgME::CMS) {
combo->appendCustomItem(QIcon::fromTheme(QStringLiteral("document-new")),
i18n("Generate a new key pair"), GenerateKey,
mGenerateTooltip);
}
combo->appendCustomItem(QIcon::fromTheme(QStringLiteral("emblem-unavailable")),
i18n("Don't confirm identity and integrity"), IgnoreKey,
i18nc("@info:tooltip for not selecting a key for signing.",
"The E-Mail will not be cryptographically signed."));
mSigningCombos << combo;
mAllCombos << combo;
combo->setProperty("address", addr);
connect(combo, &KeySelectionCombo::currentKeyChanged, q, [this] () {
updateOkButton();
});
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), q, [this] () {
updateOkButton();
});
return new ComboWidget(combo);
}
void addSigningKeys(const QMap<QString, std::vector<GpgME::Key> > &resolved,
const QStringList &unresolved)
{
if (resolved.empty() && unresolved.empty()) {
return;
}
for (const QString &addr: resolved.keys()) {
auto group = new QGroupBox(i18nc("Caption for signing key selection",
"Confirm identity '%1' as:", addr));
group->setAlignment(Qt::AlignLeft);
mScrollLayout->addWidget(group);
auto sigLayout = new QVBoxLayout;
group->setLayout(sigLayout);
for (const auto &key: resolved[addr])
{
auto comboWidget = createSigningCombo(addr, key);
if (key_has_addr (key, addr)) {
comboWidget->combo()->setIdFilter(addr);
}
if (resolved[addr].size() > 1) {
comboWidget->setFromOverride(key.protocol());
}
sigLayout->addWidget(comboWidget);
}
}
for (const QString &addr: qAsConst(unresolved)) {
auto group = new QGroupBox(i18nc("Caption for signing key selection, no key found",
"No key found for the address '%1':", addr));
group->setAlignment(Qt::AlignLeft);
mScrollLayout->addWidget(group);
auto sigLayout = new QHBoxLayout;
group->setLayout(sigLayout);
auto comboWidget = createSigningCombo(addr, GpgME::Key());
comboWidget->combo()->setIdFilter(addr);
sigLayout->addWidget(comboWidget);
}
}
void addEncryptionAddr(const QString &addr, const std::vector<GpgME::Key> &keys,
QGridLayout *encGrid)
{
encGrid->addWidget(new QLabel(addr), encGrid->rowCount(), 0);
for (const auto &key: keys)
{
auto combo = new KeySelectionCombo(false);
#ifndef NDEBUG
combo->setObjectName(QStringLiteral("encryption key"));
#endif
combo->setKeyFilter(mCurEncFilter);
if (!key.isNull()) {
if (mAllowMixed) {
// do not set the key for a specific protocol if mixed protocols are allowed
combo->setDefaultKey(QString::fromLatin1(key.primaryFingerprint()));
} else {
combo->setDefaultKey(QString::fromLatin1(key.primaryFingerprint()), key.protocol());
}
}
if (mSender == addr && key.isNull()) {
combo->appendCustomItem(QIcon::fromTheme(QStringLiteral("document-new")),
i18n("Generate a new key pair"), GenerateKey,
mGenerateTooltip);
}
combo->appendCustomItem(QIcon::fromTheme(QStringLiteral("emblem-unavailable")),
i18n("No key. Recipient will be unable to decrypt."), IgnoreKey,
i18nc("@info:tooltip for No Key selected for a specific recipient.",
"Do not select a key for this recipient.<br/><br/>"
"The recipient will receive the encrypted E-Mail, but it can only "
"be decrypted with the other keys selected in this dialog."));
if (key.isNull() || key_has_addr (key, addr)) {
combo->setIdFilter(addr);
}
connect(combo, &KeySelectionCombo::currentKeyChanged, q, [this] () {
updateOkButton();
});
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), q, [this] () {
updateOkButton();
});
mEncCombos << combo;
mAllCombos << combo;
combo->setProperty("address", addr);
auto comboWidget = new ComboWidget(combo);
if (keys.size() > 1) {
comboWidget->setFromOverride(key.protocol());
}
encGrid->addWidget(comboWidget, encGrid->rowCount(), 0, 1, 2);
}
}
void addEncryptionKeys(const QMap<QString, std::vector<GpgME::Key> > &resolved,
const QStringList &unresolved)
{
if (resolved.empty() && unresolved.empty()) {
return;
}
auto group = new QGroupBox(i18n("Encrypt to:"));
group->setAlignment(Qt::AlignLeft);
auto encGrid = new QGridLayout;
group->setLayout(encGrid);
mScrollLayout->addWidget(group);
for (const QString &addr: resolved.keys()) {
addEncryptionAddr(addr, resolved[addr], encGrid);
}
std::vector<GpgME::Key> dummy;
dummy.push_back(GpgME::Key());
for (const QString &addr: unresolved) {
addEncryptionAddr(addr, dummy, encGrid);
}
encGrid->setColumnStretch(1, -1);
mScrollLayout->addStretch(-1);
}
void updateOkButton()
{
static QString origOkText = mOkButton->text();
bool isGenerate = false;
bool isAllIgnored = true;
// Check if generate is selected.
for (auto combo: mAllCombos) {
auto act = combo->currentData(Qt::UserRole).toInt();
if (act == GenerateKey) {
mOkButton->setText(i18n("Generate"));
isGenerate = true;
}
if (act != IgnoreKey) {
isAllIgnored = false;
}
}
// If we don't encrypt the ok button is always enabled. But otherwise
// we only enable it if we encrypt to at least one recipient.
if (!mEncCombos.size()) {
mOkButton->setEnabled(true);
} else {
mOkButton->setEnabled(!isAllIgnored);
}
if (!isGenerate) {
mOkButton->setText(origOkText);
}
if (Formatting::complianceMode() != QLatin1String("de-vs")) {
return;
}
// Handle compliance
bool de_vs = true;
bool isPGP = mFormatBtns->checkedId() == 1;
bool isSMIME = mFormatBtns->checkedId() == 2;
for (const auto combo: qAsConst(mEncCombos)) {
const auto &key = combo->currentKey();
if (!combo->isVisible()) {
continue;
}
if (isSMIME && key.protocol() != GpgME::CMS) {
continue;
}
if (isPGP && key.protocol() != GpgME::OpenPGP) {
continue;
}
if (!Formatting::isKeyDeVs(key) || keyValidity(key) < GpgME::UserID::Validity::Full) {
de_vs = false;
break;
}
}
if (de_vs) {
for (const auto combo: qAsConst(mSigningCombos)) {
const auto key = combo->currentKey();
if (!combo->isVisible()) {
continue;
}
if (isSMIME && key.protocol() != GpgME::CMS) {
continue;
}
if (isPGP && key.protocol() != GpgME::OpenPGP) {
continue;
}
if (!Formatting::isKeyDeVs(key) || keyValidity(key) < GpgME::UserID::Validity::Full) {
de_vs = false;
break;
}
}
}
mOkButton->setIcon(QIcon::fromTheme(de_vs
? QStringLiteral("security-high")
: QStringLiteral("security-medium")));
mOkButton->setStyleSheet(QStringLiteral("background-color: ") + (de_vs
? QStringLiteral("#D5FAE2") // KColorScheme(QPalette::Active, KColorScheme::View).background(KColorScheme::PositiveBackground).color().name()
: QStringLiteral("#FAE9EB"))); //KColorScheme(QPalette::Active, KColorScheme::View).background(KColorScheme::NegativeBackground).color().name()));
mComplianceLbl->setText(de_vs
? i18nc("%1 is a placeholder for the name of a compliance mode. E.g. NATO RESTRICTED compliant or VS-NfD compliant",
"%1 communication possible.", Formatting::deVsString())
: i18nc("%1 is a placeholder for the name of a compliance mode. E.g. NATO RESTRICTED compliant or VS-NfD compliant",
"%1 communication not possible.", Formatting::deVsString()));
mComplianceLbl->setVisible(true);
}
void selectionChanged()
{
bool isPGP = false;
bool isCMS = false;
for (const auto combo: mEncCombos) {
isPGP |= combo->currentKey().protocol() == GpgME::OpenPGP;
isCMS |= combo->currentKey().protocol() == GpgME::CMS;
if (isPGP && isCMS) {
break;
}
}
}
GpgME::Protocol mProto;
QList<KeySelectionCombo *> mSigningCombos;
QList<KeySelectionCombo *> mEncCombos;
QList<KeySelectionCombo *> mAllCombos;
QScrollArea *mScrollArea;
QVBoxLayout *mScrollLayout;
QPushButton *mOkButton;
QVBoxLayout *mMainLay;
QButtonGroup *mFormatBtns;
std::shared_ptr<KeyFilter> mCurSigFilter;
std::shared_ptr<KeyFilter> mCurEncFilter;
QString mSender;
bool mAllowMixed;
NewKeyApprovalDialog *q;
QList <QGpgME::Job *> mRunningJobs;
GpgME::Error mLastError;
QLabel *mComplianceLbl;
QMap<QString, std::vector<GpgME::Key> > mAcceptedEnc;
std::vector<GpgME::Key> mAcceptedSig;
QString mGenerateTooltip;
};
NewKeyApprovalDialog::NewKeyApprovalDialog(const QMap<QString, std::vector<GpgME::Key> > &resolvedSigningKeys,
const QMap<QString, std::vector<GpgME::Key> > &resolvedRecp,
const QStringList &unresolvedSigKeys,
const QStringList &unresolvedRecp,
const QString &sender,
bool allowMixed,
GpgME::Protocol forcedProtocol,
GpgME::Protocol presetProtocol,
QWidget *parent,
Qt::WindowFlags f): QDialog(parent, f),
d(new Private(this, forcedProtocol, presetProtocol, sender, allowMixed))
{
d->addSigningKeys(resolvedSigningKeys, unresolvedSigKeys);
d->addEncryptionKeys(resolvedRecp, unresolvedRecp);
d->updateFilter();
d->updateOkButton();
const auto size = sizeHint();
const auto desk = QApplication::desktop()->screenGeometry(this);
resize(QSize(desk.width() / 3, qMin(size.height(), desk.height() / 2)));
}
Kleo::NewKeyApprovalDialog::~NewKeyApprovalDialog() = default;
std::vector<GpgME::Key> NewKeyApprovalDialog::signingKeys()
{
return d->mAcceptedSig;
}
QMap <QString, std::vector<GpgME::Key> > NewKeyApprovalDialog::encryptionKeys()
{
return d->mAcceptedEnc;
}
#include "newkeyapprovaldialog.moc"

File Metadata

Mime Type
text/x-c++
Expires
Thu, Jan 1, 2:22 AM (21 h, 2 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
98/c6/18b09f9dfc712a273f4be4119ffb

Event Timeline