12#include <config-libkleo.h>
14#include "newkeyapprovaldialog.h"
16#include "keyselectioncombo.h"
17#include "progressdialog.h"
19#include <libkleo/algorithm.h>
20#include <libkleo/applicationpalettewatcher.h>
21#include <libkleo/compliance.h>
22#include <libkleo/debug.h>
23#include <libkleo/defaultkeyfilter.h>
24#include <libkleo/formatting.h>
25#include <libkleo/gnupg.h>
26#include <libkleo/keyhelpers.h>
27#include <libkleo/systeminfo.h>
29#include <libkleo_debug.h>
31#include <KAdjustingScrollArea>
32#include <KColorScheme>
33#include <KLocalizedString>
36#include <QGpgME/Protocol>
37#include <QGpgME/QuickJob>
39#include <QButtonGroup>
41#include <QDialogButtonBox>
47#include <QRadioButton>
52#include <gpgme++/context.h>
53#include <gpgme++/key.h>
54#include <gpgme++/keygenerationresult.h>
67 setHasEncrypt(DefaultKeyFilter::Set);
70static std::shared_ptr<KeyFilter> s_encryptFilter = std::shared_ptr<KeyFilter>(
new EncryptFilter);
78 setIsOpenPGP(DefaultKeyFilter::Set);
79 setHasEncrypt(DefaultKeyFilter::Set);
82static std::shared_ptr<KeyFilter> s_pgpEncryptFilter = std::shared_ptr<KeyFilter>(
new OpenPGPFilter);
91 setDisabled(DefaultKeyFilter::NotSet);
92 setRevoked(DefaultKeyFilter::NotSet);
93 setExpired(DefaultKeyFilter::NotSet);
94 setCanSign(DefaultKeyFilter::Set);
95 setHasSecret(DefaultKeyFilter::Set);
96 setIsOpenPGP(DefaultKeyFilter::Set);
99static std::shared_ptr<KeyFilter> s_pgpSignFilter = std::shared_ptr<KeyFilter>(
new OpenPGPSignFilter);
107 setIsOpenPGP(DefaultKeyFilter::NotSet);
108 setHasEncrypt(DefaultKeyFilter::Set);
111static std::shared_ptr<KeyFilter> s_smimeEncryptFilter = std::shared_ptr<KeyFilter>(
new SMIMEFilter);
119 setDisabled(DefaultKeyFilter::NotSet);
120 setRevoked(DefaultKeyFilter::NotSet);
121 setExpired(DefaultKeyFilter::NotSet);
122 setCanSign(DefaultKeyFilter::Set);
123 setIsOpenPGP(DefaultKeyFilter::NotSet);
124 setHasSecret(DefaultKeyFilter::Set);
127static std::shared_ptr<KeyFilter> s_smimeSignFilter = std::shared_ptr<KeyFilter>(
new SMIMESignFilter);
130class ComboWidget :
public QWidget
134 explicit ComboWidget(KeySelectionCombo *combo)
136 , mFilterBtn(new QPushButton)
138 auto hLay =
new QHBoxLayout(
this);
139 auto infoBtn =
new QPushButton;
141 infoBtn->setIconSize(QSize(22, 22));
142 infoBtn->setFlat(
true);
143 infoBtn->setAccessibleName(
i18nc(
"@action:button",
"Show Details"));
144 hLay->addWidget(infoBtn);
145 hLay->addWidget(combo, 1);
146 hLay->addWidget(mFilterBtn, 0);
159 mFilterBtn->setMinimumHeight(23);
161 updateFilterButton();
164 const QString curFilter = mCombo->idFilter();
166 setIdFilter(mLastIdFilter);
167 mLastIdFilter = QString();
169 setIdFilter(QString());
170 mLastIdFilter = curFilter;
175 void setIdFilter(
const QString &
id)
177 mCombo->setIdFilter(
id);
178 updateFilterButton();
181 void updateFilterButton()
183 if (mCombo->idFilter().isEmpty()) {
185 mFilterBtn->setAccessibleName(
i18nc(
"@action:button",
"Show Matching Keys"));
186 mFilterBtn->setToolTip(
i18nc(
"@info:tooltip",
"Show keys matching the email address"));
189 mFilterBtn->setAccessibleName(
i18nc(
"@action:button short for 'Show all keys'",
"Show All"));
190 mFilterBtn->setToolTip(
i18nc(
"@info:tooltip",
"Show all keys"));
194 KeySelectionCombo *combo()
199 GpgME::Protocol fixedProtocol()
const
201 return mFixedProtocol;
204 void setFixedProtocol(GpgME::Protocol proto)
206 mFixedProtocol = proto;
210 KeySelectionCombo *mCombo;
211 QPushButton *mFilterBtn;
212 QString mLastIdFilter;
213 GpgME::Protocol mFixedProtocol = GpgME::UnknownProtocol;
216static bool key_has_addr(
const GpgME::Key &key,
const QString &addr)
218 for (
const auto &uid : key.userIDs()) {
226Key findfirstKeyOfType(
const std::vector<Key> &keys, GpgME::Protocol protocol)
228 const auto it = std::find_if(std::begin(keys), std::end(keys), [protocol](
const auto &key) {
229 return key.protocol() == protocol;
231 return it != std::end(keys) ? *it : Key();
236class NewKeyApprovalDialog::Private
254 GpgME::Protocol forcedProtocol,
255 GpgME::Protocol presetProtocol,
258 : mForcedProtocol{forcedProtocol}
262 , mAllowMixed{allowMixed}
265 Q_ASSERT(forcedProtocol == GpgME::UnknownProtocol || presetProtocol == GpgME::UnknownProtocol || presetProtocol == forcedProtocol);
266 Q_ASSERT(!allowMixed || (allowMixed && forcedProtocol == GpgME::UnknownProtocol));
267 Q_ASSERT(!(!allowMixed && presetProtocol == GpgME::UnknownProtocol));
270 mGenerateTooltip =
i18nc(
271 "@info:tooltip for a 'Generate new key pair' action "
272 "in a combobox when a user does not yet have an OpenPGP or S/MIME key.",
273 "Generate a new key using your email address.<br/><br/>"
274 "The key is necessary to decrypt and sign emails. "
275 "You will be asked for a passphrase to protect this key and the protected key "
276 "will be stored in your home directory.");
277 mMainLay =
new QVBoxLayout;
289 mScrollArea =
new KAdjustingScrollArea;
290 mScrollArea->setWidget(
new QWidget);
291 mScrollLayout =
new QVBoxLayout;
292 mScrollArea->widget()->setLayout(mScrollLayout);
293 mScrollArea->setWidgetResizable(
true);
296 mScrollLayout->setContentsMargins(0, 0, 0, 0);
298 q->setWindowTitle(
i18nc(
"@title:window",
"Security approval"));
300 auto fmtLayout =
new QHBoxLayout;
301 mFormatBtns =
new QButtonGroup(qq);
302 QAbstractButton *pgpBtn;
303 QAbstractButton *smimeBtn;
305 pgpBtn =
new QCheckBox(
i18nc(
"@option:check",
"OpenPGP"));
306 smimeBtn =
new QCheckBox(
i18nc(
"@option:check",
"S/MIME"));
308 pgpBtn =
new QRadioButton(
i18nc(
"@option:radio",
"OpenPGP"));
309 smimeBtn =
new QRadioButton(
i18nc(
"@option:radio",
"S/MIME"));
315 mFormatBtns->addButton(pgpBtn, OpenPGPButtonId);
316 mFormatBtns->addButton(smimeBtn, SMIMEButtonId);
317 mFormatBtns->setExclusive(!mAllowMixed);
322 connect(&appPaletteWatcher, &ApplicationPaletteWatcher::paletteChanged, q, [
this]() {
326 fmtLayout->addStretch(-1);
327 fmtLayout->addWidget(pgpBtn);
328 fmtLayout->addWidget(smimeBtn);
329 mMainLay->addLayout(fmtLayout);
331 if (mForcedProtocol != GpgME::UnknownProtocol) {
332 pgpBtn->
setChecked(mForcedProtocol == GpgME::OpenPGP);
333 smimeBtn->
setChecked(mForcedProtocol == GpgME::CMS);
337 pgpBtn->
setChecked(presetProtocol == GpgME::OpenPGP || presetProtocol == GpgME::UnknownProtocol);
338 smimeBtn->
setChecked(presetProtocol == GpgME::CMS || presetProtocol == GpgME::UnknownProtocol);
343 if (mAllowMixed && !mFormatBtns->button(OpenPGPButtonId)->isChecked() && !mFormatBtns->button(SMIMEButtonId)->isChecked()) {
344 mFormatBtns->button(buttonId == OpenPGPButtonId ? SMIMEButtonId : OpenPGPButtonId)->setChecked(
true);
349 mMainLay->addWidget(mScrollArea);
351 mComplianceLbl =
new QLabel;
352 mComplianceLbl->setVisible(
false);
354 mComplianceLbl->setObjectName(QLatin1StringView(
"compliance label"));
357 auto btnLayout =
new QHBoxLayout;
358 btnLayout->addWidget(mComplianceLbl);
359 btnLayout->addWidget(btnBox);
360 mMainLay->addLayout(btnLayout);
362 q->setLayout(mMainLay);
365 ~Private() =
default;
367 GpgME::Protocol currentProtocol()
369 const bool openPGPButtonChecked = mFormatBtns->button(OpenPGPButtonId)->isChecked();
370 const bool smimeButtonChecked = mFormatBtns->button(SMIMEButtonId)->isChecked();
372 if (openPGPButtonChecked && !smimeButtonChecked) {
373 return GpgME::OpenPGP;
375 if (!openPGPButtonChecked && smimeButtonChecked) {
378 }
else if (openPGPButtonChecked) {
379 return GpgME::OpenPGP;
380 }
else if (smimeButtonChecked) {
383 return GpgME::UnknownProtocol;
386 auto findVisibleKeySelectionComboWithGenerateKey()
388 const auto it = std::find_if(std::begin(mAllCombos), std::end(mAllCombos), [](
auto combo) {
391 return it != std::end(mAllCombos) ? *it :
nullptr;
394 void generateKey(KeySelectionCombo *combo)
396 if (!mRunningJobs.empty()) {
400 auto job = QGpgME::openpgp()->quickJob();
402 new Kleo::ProgressDialog(job,
i18n(
"Generating key for '%1'...", addr) + QStringLiteral(
"\n\n") +
i18n(
"This can take several minutes."), q);
404 progress->setWindowTitle(
i18nc(
"@title:window",
"Key generation"));
405 progress->setModal(
true);
406 progress->setAutoClose(
true);
407 progress->setMinimumDuration(0);
408 progress->setValue(0);
411 if (!
connect(job, &QGpgME::QuickJob::result, q, [
this, job, combo]() {
412 handleKeyGenResult(QGpgME::Job::context(job)->keyGenerationResult(), job, combo);
414 qCWarning(LIBKLEO_LOG) <<
"new-style connect failed; connecting to QGpgME::QuickJob::result the old way";
415 connect(job, SIGNAL(
result(
const GpgME::Error &)), q, SLOT(handleKeyGenResult()));
417 job->startCreate(addr,
nullptr);
421 void handleKeyGenResult(
const GpgME::KeyGenerationResult &
result, QGpgME::Job *job, KeySelectionCombo *combo)
423 mLastError =
result.error();
425 connect(combo, &KeySelectionCombo::keyListingFinished, q, [
this, job]() {
426 mRunningJobs.removeAll(job);
429 for (
auto c : std::as_const(mAllCombos)) {
430 if (c->currentData(
Qt::UserRole).toInt() == GenerateKey) {
436 mRunningJobs.removeAll(job);
444 mRunningJobs.clear();
448 if (!mRunningJobs.empty()) {
453 mAcceptedResult.
protocol = currentProtocol();
454 for (
const auto combo : std::as_const(mEncCombos)) {
456 const auto key = combo->currentKey();
457 if (!combo->
isVisible() || key.isNull()) {
460 mAcceptedResult.encryptionKeys[addr].push_back(key);
462 for (
const auto combo : std::as_const(mSigningCombos)) {
463 const auto key = combo->currentKey();
464 if (!combo->
isVisible() || key.isNull()) {
467 mAcceptedResult.signingKeys.push_back(key);
478 if (
auto combo = findVisibleKeySelectionComboWithGenerateKey()) {
485 auto encryptionKeyFilter(GpgME::Protocol protocol)
489 return s_pgpEncryptFilter;
491 return s_smimeEncryptFilter;
493 return s_encryptFilter;
499 const GpgME::Protocol protocol = currentProtocol();
500 const auto encryptionFilter = encryptionKeyFilter(protocol);
502 for (
auto combo : std::as_const(mSigningCombos)) {
505 qCDebug(LIBKLEO_LOG) <<
"Failed to find signature combo widget";
508 widget->setVisible(protocol == GpgME::UnknownProtocol || widget->fixedProtocol() == GpgME::UnknownProtocol || widget->fixedProtocol() == protocol);
510 for (
auto combo : std::as_const(mEncCombos)) {
513 qCDebug(LIBKLEO_LOG) <<
"Failed to find combo widget";
516 widget->setVisible(protocol == GpgME::UnknownProtocol || widget->fixedProtocol() == GpgME::UnknownProtocol || widget->fixedProtocol() == protocol);
517 if (widget->isVisible() && combo->
property(
"address") != mSender) {
518 combo->setKeyFilter(encryptionFilter);
522 const auto protocolLabels = q->findChildren<QLabel *>(QStringLiteral(
"protocol label"));
523 for (
auto label : protocolLabels) {
524 label->setVisible(protocol == GpgME::UnknownProtocol);
528 auto createProtocolLabel(GpgME::Protocol protocol)
530 auto label =
new QLabel(Formatting::displayName(protocol));
531 label->setObjectName(QLatin1StringView(
"protocol label"));
535 ComboWidget *createSigningCombo(
const QString &addr,
const GpgME::Key &key, GpgME::Protocol protocol = GpgME::UnknownProtocol)
537 Q_ASSERT(!key.isNull() || protocol != UnknownProtocol);
538 protocol = !key.isNull() ? key.protocol() : protocol;
540 auto combo =
new KeySelectionCombo{
true, KeyUsage::Sign};
541 auto comboWidget =
new ComboWidget(combo);
545 if (protocol == GpgME::OpenPGP) {
546 combo->setKeyFilter(s_pgpSignFilter);
547 }
else if (protocol == GpgME::CMS) {
548 combo->setKeyFilter(s_smimeSignFilter);
550 if (key.isNull() || key_has_addr(key, mSender)) {
551 comboWidget->setIdFilter(mSender);
553 comboWidget->setFixedProtocol(protocol);
557 if (key.isNull() && protocol == OpenPGP) {
558 combo->appendCustomItem(
QIcon::fromTheme(QStringLiteral(
"document-new")),
i18n(
"Generate a new key pair"), GenerateKey, mGenerateTooltip);
560 combo->appendCustomItem(Formatting::unavailableIcon(),
561 i18n(
"Do not sign this email"),
563 i18nc(
"@info:tooltip for not selecting a key for signing.",
"The email will not be cryptographically signed."));
565 mSigningCombos << combo;
569 connect(combo, &KeySelectionCombo::currentKeyChanged, q, [
this]() {
579 void setSigningKeys(
const std::vector<GpgME::Key> &preferredKeys,
const std::vector<GpgME::Key> &alternativeKeys)
581 auto group =
new QGroupBox(
i18nc(
"Caption for signing key selection",
"Confirm identity '%1' as:", mSender));
583 auto sigLayout =
new QVBoxLayout(group);
585 const bool mayNeedOpenPGP = mForcedProtocol != CMS;
586 const bool mayNeedCMS = mForcedProtocol != OpenPGP;
587 if (mayNeedOpenPGP) {
589 sigLayout->addWidget(createProtocolLabel(OpenPGP));
591 const Key preferredKey = findfirstKeyOfType(preferredKeys, OpenPGP);
592 const Key alternativeKey = findfirstKeyOfType(alternativeKeys, OpenPGP);
593 if (!preferredKey.isNull()) {
594 qCDebug(LIBKLEO_LOG) <<
"setSigningKeys - creating signing combo for" << preferredKey;
595 auto comboWidget = createSigningCombo(mSender, preferredKey);
596 sigLayout->addWidget(comboWidget);
597 }
else if (!alternativeKey.isNull()) {
598 qCDebug(LIBKLEO_LOG) <<
"setSigningKeys - creating signing combo for" << alternativeKey;
599 auto comboWidget = createSigningCombo(mSender, alternativeKey);
600 sigLayout->addWidget(comboWidget);
602 qCDebug(LIBKLEO_LOG) <<
"setSigningKeys - creating signing combo for OpenPGP key";
603 auto comboWidget = createSigningCombo(mSender,
Key(), OpenPGP);
604 sigLayout->addWidget(comboWidget);
609 sigLayout->addWidget(createProtocolLabel(CMS));
611 const Key preferredKey = findfirstKeyOfType(preferredKeys, CMS);
612 const Key alternativeKey = findfirstKeyOfType(alternativeKeys, CMS);
613 if (!preferredKey.isNull()) {
614 qCDebug(LIBKLEO_LOG) <<
"setSigningKeys - creating signing combo for" << preferredKey;
615 auto comboWidget = createSigningCombo(mSender, preferredKey);
616 sigLayout->addWidget(comboWidget);
617 }
else if (!alternativeKey.isNull()) {
618 qCDebug(LIBKLEO_LOG) <<
"setSigningKeys - creating signing combo for" << alternativeKey;
619 auto comboWidget = createSigningCombo(mSender, alternativeKey);
620 sigLayout->addWidget(comboWidget);
622 qCDebug(LIBKLEO_LOG) <<
"setSigningKeys - creating signing combo for S/MIME key";
623 auto comboWidget = createSigningCombo(mSender,
Key(), CMS);
624 sigLayout->addWidget(comboWidget);
628 mScrollLayout->addWidget(group);
631 ComboWidget *createEncryptionCombo(
const QString &addr,
const GpgME::Key &key, GpgME::Protocol fixedProtocol)
633 auto combo =
new KeySelectionCombo{
false, KeyUsage::Encrypt};
634 auto comboWidget =
new ComboWidget(combo);
636 combo->setObjectName(QLatin1StringView(
"encryption key"));
638 if (fixedProtocol == GpgME::OpenPGP) {
639 combo->setKeyFilter(s_pgpEncryptFilter);
640 }
else if (fixedProtocol == GpgME::CMS) {
641 combo->setKeyFilter(s_smimeEncryptFilter);
643 combo->setKeyFilter(s_encryptFilter);
645 if (key.isNull() || key_has_addr(key, addr)) {
646 comboWidget->setIdFilter(addr);
648 comboWidget->setFixedProtocol(fixedProtocol);
653 if (addr == mSender && key.isNull() && fixedProtocol == OpenPGP) {
654 combo->appendCustomItem(
QIcon::fromTheme(QStringLiteral(
"document-new")),
i18n(
"Generate a new key pair"), GenerateKey, mGenerateTooltip);
657 combo->appendCustomItem(Formatting::unavailableIcon(),
658 i18n(
"No key. Recipient will be unable to decrypt."),
660 i18nc(
"@info:tooltip for No Key selected for a specific recipient.",
661 "Do not select a key for this recipient.<br/><br/>"
662 "The recipient will receive the encrypted email, but it can only "
663 "be decrypted with the other keys selected in this dialog."));
665 connect(combo, &KeySelectionCombo::currentKeyChanged, q, [
this]() {
674 combo->setProperty(
"address", addr);
678 void addEncryptionAddr(
const QString &addr,
679 GpgME::Protocol preferredKeysProtocol,
680 const std::vector<GpgME::Key> &preferredKeys,
681 GpgME::Protocol alternativeKeysProtocol,
682 const std::vector<GpgME::Key> &alternativeKeys,
683 QGridLayout *encGrid)
685 if (addr == mSender) {
686 const bool mayNeedOpenPGP = mForcedProtocol != CMS;
687 const bool mayNeedCMS = mForcedProtocol != OpenPGP;
688 if (mayNeedOpenPGP) {
692 for (
const auto &key : preferredKeys) {
693 if (key.protocol() == OpenPGP) {
694 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for" << key;
695 auto comboWidget = createEncryptionCombo(addr, key, OpenPGP);
699 for (
const auto &key : alternativeKeys) {
700 if (key.protocol() == OpenPGP) {
701 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for" << key;
702 auto comboWidget = createEncryptionCombo(addr, key, OpenPGP);
706 if (!anyKeyHasProtocol(preferredKeys, OpenPGP) && !anyKeyHasProtocol(alternativeKeys, OpenPGP)) {
707 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for OpenPGP key";
708 auto comboWidget = createEncryptionCombo(addr, GpgME::Key(), OpenPGP);
716 for (
const auto &key : preferredKeys) {
717 if (key.protocol() == CMS) {
718 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for" << key;
719 auto comboWidget = createEncryptionCombo(addr, key, CMS);
723 for (
const auto &key : alternativeKeys) {
724 if (key.protocol() == CMS) {
725 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for" << key;
726 auto comboWidget = createEncryptionCombo(addr, key, CMS);
730 if (!anyKeyHasProtocol(preferredKeys, CMS) && !anyKeyHasProtocol(alternativeKeys, CMS)) {
731 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for S/MIME key";
732 auto comboWidget = createEncryptionCombo(addr, GpgME::Key(), CMS);
739 for (
const auto &key : preferredKeys) {
740 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for" << key;
741 auto comboWidget = createEncryptionCombo(addr, key, preferredKeysProtocol);
744 for (
const auto &key : alternativeKeys) {
745 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for" << key;
746 auto comboWidget = createEncryptionCombo(addr, key, alternativeKeysProtocol);
750 if (preferredKeys.empty()) {
751 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for" << Formatting::displayName(preferredKeysProtocol)
753 auto comboWidget = createEncryptionCombo(addr, GpgME::Key(), preferredKeysProtocol);
756 if (alternativeKeys.empty() && alternativeKeysProtocol != UnknownProtocol) {
757 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for"
758 << Formatting::displayName(alternativeKeysProtocol) <<
"key";
759 auto comboWidget = createEncryptionCombo(addr, GpgME::Key(), alternativeKeysProtocol);
763 if (preferredKeys.empty() && alternativeKeys.empty()) {
764 qCDebug(LIBKLEO_LOG) <<
"setEncryptionKeys -" << addr <<
"- creating encryption combo for any key";
765 auto comboWidget = createEncryptionCombo(addr, GpgME::Key(), UnknownProtocol);
772 void setEncryptionKeys(GpgME::Protocol preferredKeysProtocol,
773 const QMap<QString, std::vector<GpgME::Key>> &preferredKeys,
774 GpgME::Protocol alternativeKeysProtocol,
775 const QMap<QString, std::vector<GpgME::Key>> &alternativeKeys)
778 auto group =
new QGroupBox(
i18nc(
"Encrypt to self (email address):",
"Encrypt to self (%1):", mSender));
780 group->setObjectName(QLatin1StringView(
"encrypt-to-self box"));
783 auto encGrid =
new QGridLayout(group);
785 addEncryptionAddr(mSender, preferredKeysProtocol, preferredKeys.value(mSender), alternativeKeysProtocol, alternativeKeys.value(mSender), encGrid);
788 mScrollLayout->addWidget(group);
791 const bool hasOtherRecipients = std::any_of(preferredKeys.keyBegin(), preferredKeys.keyEnd(), [
this](
const auto &recipient) {
792 return recipient != mSender;
794 if (hasOtherRecipients) {
795 auto group =
new QGroupBox(
i18n(
"Encrypt to others:"));
797 group->setObjectName(QLatin1StringView(
"encrypt-to-others box"));
800 auto encGrid =
new QGridLayout{group};
802 for (
auto it = std::begin(preferredKeys); it != std::end(preferredKeys); ++it) {
803 const auto &
address = it.key();
804 const auto &keys = it.value();
805 if (address != mSender) {
806 addEncryptionAddr(address, preferredKeysProtocol, keys, alternativeKeysProtocol, alternativeKeys.value(address), encGrid);
811 mScrollLayout->addWidget(group);
814 mScrollLayout->addStretch(-1);
817 void updateOkButton()
819 static QString origOkText = mOkButton->text();
820 const bool isGenerate = bool(findVisibleKeySelectionComboWithGenerateKey());
821 const bool allVisibleEncryptionKeysAreIgnored = Kleo::all_of(mEncCombos, [](
auto combo) {
822 return !combo->isVisible() || combo->currentData(
Qt::UserRole).toInt() == IgnoreKey;
824 const bool allVisibleEncryptionKeysAreUsable = Kleo::all_of(mEncCombos, [](
auto combo) {
825 return !combo->isVisible() || combo->currentKey().isNull() || Kleo::canBeUsedForEncryption(combo->currentKey());
831 mOkButton->setEnabled(isGenerate || !mEncrypt || (!allVisibleEncryptionKeysAreIgnored && allVisibleEncryptionKeysAreUsable));
833 mOkButton->setText(isGenerate ?
i18n(
"Generate") : origOkText);
835 if (!DeVSCompliance::isActive()) {
840 bool de_vs = DeVSCompliance::isCompliant();
843 const GpgME::Protocol protocol = currentProtocol();
845 for (
const auto combo : std::as_const(mAllCombos)) {
846 if (!combo->isVisible()) {
849 const auto key = combo->currentKey();
853 if (protocol != GpgME::UnknownProtocol && key.protocol() != protocol) {
856 if (!DeVSCompliance::keyIsCompliant(key)) {
863 const auto doNotSign = Kleo::any_of(mSigningCombos, [](
const auto &combo) {
864 return combo->isVisible() && combo->currentData() == IgnoreKey;
868 mOkButton->setStyleSheet({});
870 DeVSCompliance::decorate(mOkButton, de_vs);
872 mComplianceLbl->setText(DeVSCompliance::name(de_vs));
873 mComplianceLbl->setVisible(!doNotSign);
876 ApplicationPaletteWatcher appPaletteWatcher;
877 GpgME::Protocol mForcedProtocol;
878 QList<KeySelectionCombo *> mSigningCombos;
879 QList<KeySelectionCombo *> mEncCombos;
880 QList<KeySelectionCombo *> mAllCombos;
881 QScrollArea *mScrollArea;
882 QVBoxLayout *mScrollLayout;
883 QPushButton *mOkButton;
884 QVBoxLayout *mMainLay;
885 QButtonGroup *mFormatBtns;
891 QList<QGpgME::Job *> mRunningJobs;
892 GpgME::Error mLastError;
893 QLabel *mComplianceLbl;
894 KeyResolver::Solution mAcceptedResult;
895 QString mGenerateTooltip;
904 GpgME::Protocol forcedProtocol,
908 , d{std::make_unique<Private>(this, encrypt, sign, forcedProtocol, preferredSolution.protocol,
sender, allowMixed)}
914 d->setEncryptionKeys(allowMixed ? UnknownProtocol : preferredSolution.
protocol,
916 allowMixed ? UnknownProtocol : alternativeSolution.
protocol,
924 resize(
QSize(desk.width() / 3, qMin(
size.height(), desk.height() / 2)));
927Kleo::NewKeyApprovalDialog::~NewKeyApprovalDialog() =
default;
931 return d->mAcceptedResult;
934void NewKeyApprovalDialog::handleKeyGenResult()
936 if (d->mRunningJobs.empty()) {
937 qCWarning(LIBKLEO_LOG) << __func__ <<
"No running job";
939 const auto job = d->mRunningJobs.front();
940 const auto result = QGpgME::Job::context(job)->keyGenerationResult();
941 const auto combo = d->findVisibleKeySelectionComboWithGenerateKey();
942 d->handleKeyGenResult(
result, job, combo);
945#include "newkeyapprovaldialog.moc"
947#include "moc_newkeyapprovaldialog.cpp"
Default implementation of key filter class.
NewKeyApprovalDialog(bool encrypt, bool sign, const QString &sender, KeyResolver::Solution preferredSolution, KeyResolver::Solution alternativeSolution, bool allowMixed, GpgME::Protocol forcedProtocol, QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
Create a new Key Approval Dialog.
KeyResolver::Solution result()
The selected signing and/or encryption keys.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
PostalAddress address(const QVariant &location)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
QString label(StandardShortcut id)
void currentIndexChanged(int index)
QDialog(QWidget *parent, Qt::WindowFlags f)
virtual QSize sizeHint() const const override
int rowCount() const const
void setColumnStretch(int column, int stretch)
QIcon fromTheme(const QString &name)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
QVariant property(const char *name) const const
T qobject_cast(QObject *object)
QObject * sender() const const
void setObjectName(QAnyStringView name)
bool setProperty(const char *name, QVariant &&value)
QString fromLatin1(QByteArrayView str)
QString fromStdString(const std::string &str)
bool isEmpty() const const
QString toLower() const const
WindowContextHelpButtonHint
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void showText(const QPoint &pos, const QString &text, QWidget *w, const QRect &rect, int msecDisplayTime)
QString toString() const const
Solution represents the solution found by the KeyResolver.
GpgME::Protocol protocol
This property holds a hint at the protocol of the signing and encryption keys, i.e.
QMap< QString, std::vector< GpgME::Key > > encryptionKeys
This property contains the encryption keys to use for the different recipients.
std::vector< GpgME::Key > signingKeys
This property contains the signing keys to use.