1 /* crypto/gui/signencryptwidget.cpp
2
3 This file is part of Kleopatra, the KDE keymanager
4 SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
5 SPDX-FileContributor: Intevation GmbH
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "signencryptwidget.h"
11
12 #include "kleopatra_debug.h"
13
14 #include "certificatelineedit.h"
15 #include "fileoperationspreferences.h"
16 #include "kleopatraapplication.h"
17 #include "settings.h"
18 #include "unknownrecipientwidget.h"
19
20 #include "commands/detailscommand.h"
21
22 #include "dialogs/certificateselectiondialog.h"
23 #include "dialogs/groupdetailsdialog.h"
24
25 #include <QVBoxLayout>
26 #include <QHBoxLayout>
27 #include <QGroupBox>
28 #include <QCheckBox>
29 #include <QScrollArea>
30 #include <QScrollBar>
31
32 #include <Libkleo/DefaultKeyFilter>
33 #include <Libkleo/KeyCache>
34 #include <Libkleo/KeyGroup>
35 #include <Libkleo/KeyListModel>
36 #include <Libkleo/KeySelectionCombo>
37 #include <Libkleo/KeyListSortFilterProxyModel>
38
39 #include <Libkleo/GnuPG>
40
41 #include <KLocalizedString>
42 #include <KConfigGroup>
43 #include <KSharedConfig>
44 #include <KMessageBox>
45
46 using namespace Kleo;
47 using namespace Kleo::Dialogs;
48 using namespace GpgME;
49
50 namespace {
51 class SignCertificateFilter: public DefaultKeyFilter
52 {
53 public:
SignCertificateFilter(GpgME::Protocol proto)54 SignCertificateFilter(GpgME::Protocol proto) : DefaultKeyFilter()
55 {
56 setRevoked(DefaultKeyFilter::NotSet);
57 setExpired(DefaultKeyFilter::NotSet);
58 setHasSecret(DefaultKeyFilter::Set);
59 setCanSign(DefaultKeyFilter::Set);
60
61 if (proto == GpgME::OpenPGP) {
62 setIsOpenPGP(DefaultKeyFilter::Set);
63 } else if (proto == GpgME::CMS) {
64 setIsOpenPGP(DefaultKeyFilter::NotSet);
65 }
66 }
67 };
68 class EncryptCertificateFilter: public DefaultKeyFilter
69 {
70 public:
EncryptCertificateFilter(GpgME::Protocol proto)71 EncryptCertificateFilter(GpgME::Protocol proto): DefaultKeyFilter()
72 {
73 setRevoked(DefaultKeyFilter::NotSet);
74 setExpired(DefaultKeyFilter::NotSet);
75 setCanEncrypt(DefaultKeyFilter::Set);
76
77 if (proto == GpgME::OpenPGP) {
78 setIsOpenPGP(DefaultKeyFilter::Set);
79 } else if (proto == GpgME::CMS) {
80 setIsOpenPGP(DefaultKeyFilter::NotSet);
81 }
82 }
83 };
84 class EncryptSelfCertificateFilter: public EncryptCertificateFilter
85 {
86 public:
EncryptSelfCertificateFilter(GpgME::Protocol proto)87 EncryptSelfCertificateFilter(GpgME::Protocol proto): EncryptCertificateFilter(proto)
88 {
89 setRevoked(DefaultKeyFilter::NotSet);
90 setExpired(DefaultKeyFilter::NotSet);
91 setCanEncrypt(DefaultKeyFilter::Set);
92 setHasSecret(DefaultKeyFilter::Set);
93 }
94 };
95 }
96
SignEncryptWidget(QWidget * parent,bool sigEncExclusive)97 SignEncryptWidget::SignEncryptWidget(QWidget *parent, bool sigEncExclusive)
98 : QWidget(parent),
99 mModel(AbstractKeyListModel::createFlatKeyListModel(this)),
100 mIsExclusive(sigEncExclusive)
101 {
102 auto lay = new QVBoxLayout(this);
103 lay->setContentsMargins(0, 0, 0, 0);
104
105 mModel->useKeyCache(true, KeyList::IncludeGroups);
106
107 const bool haveSecretKeys = !KeyCache::instance()->secretKeys().empty();
108 const bool havePublicKeys = !KeyCache::instance()->keys().empty();
109 const bool symmetricOnly = FileOperationsPreferences().symmetricEncryptionOnly();
110
111 /* The signature selection */
112 auto sigLay = new QHBoxLayout;
113 auto sigGrp = new QGroupBox(i18nc("@title:group", "Prove authenticity (sign)"));
114 mSigChk = new QCheckBox(i18n("Sign as:"));
115 mSigChk->setEnabled(haveSecretKeys);
116 mSigChk->setChecked(haveSecretKeys);
117
118 mSigSelect = new KeySelectionCombo();
119 mSigSelect->setEnabled(mSigChk->isChecked());
120
121 sigLay->addWidget(mSigChk);
122 sigLay->addWidget(mSigSelect, 1);
123 sigGrp->setLayout(sigLay);
124 lay->addWidget(sigGrp);
125
126 connect(mSigChk, &QCheckBox::toggled, mSigSelect, &QWidget::setEnabled);
127 connect(mSigChk, &QCheckBox::toggled, this, &SignEncryptWidget::updateOp);
128 connect(mSigSelect, &KeySelectionCombo::currentKeyChanged,
129 this, &SignEncryptWidget::updateOp);
130
131 // Recipient selection
132 auto encBoxLay = new QVBoxLayout;
133 auto encBox = new QGroupBox(i18nc("@title:group", "Encrypt"));
134 encBox->setLayout(encBoxLay);
135 auto recipientGrid = new QGridLayout;
136
137 // Own key
138 mEncSelfChk = new QCheckBox(i18n("Encrypt for me:"));
139 mEncSelfChk->setEnabled(haveSecretKeys && !symmetricOnly);
140 mEncSelfChk->setChecked(haveSecretKeys && !symmetricOnly);
141 mSelfSelect = new KeySelectionCombo();
142 mSelfSelect->setEnabled(mEncSelfChk->isChecked());
143 recipientGrid->addWidget(mEncSelfChk, 0, 0);
144 recipientGrid->addWidget(mSelfSelect, 0, 1);
145
146 // Checkbox for other keys
147 mEncOtherChk = new QCheckBox(i18n("Encrypt for others:"));
148 mEncOtherChk->setEnabled(havePublicKeys && !symmetricOnly);
149 mEncOtherChk->setChecked(havePublicKeys && !symmetricOnly);
150 recipientGrid->addWidget(mEncOtherChk, 1, 0, Qt::AlignTop);
151 connect(mEncOtherChk, &QCheckBox::toggled, this,
152 [this](bool toggled) {
153 for (CertificateLineEdit *edit : std::as_const(mRecpWidgets)) {
154 edit->setEnabled(toggled);
155 }
156 updateOp();
157 });
158 mRecpLayout = new QVBoxLayout;
159 recipientGrid->addLayout(mRecpLayout, 1, 1);
160 recipientGrid->setRowStretch(2, 1);
161
162 // Scroll area for other keys
163 auto recipientWidget = new QWidget;
164 auto recipientScroll = new QScrollArea;
165 recipientWidget->setLayout(recipientGrid);
166 recipientScroll->setWidget(recipientWidget);
167 recipientScroll->setWidgetResizable(true);
168 recipientScroll->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
169 recipientScroll->setFrameStyle(QFrame::NoFrame);
170 recipientScroll->setFocusPolicy(Qt::NoFocus);
171 recipientGrid->setContentsMargins(0, 0, 0, 0);
172 encBoxLay->addWidget(recipientScroll, 1);
173
174 auto bar = recipientScroll->verticalScrollBar();
175 connect (bar, &QScrollBar::rangeChanged, this, [bar] (int, int max) {
176 bar->setValue(max);
177 });
178
179 addRecipientWidget();
180
181 // Checkbox for password
182 mSymmetric = new QCheckBox(i18n("Encrypt with password. Anyone you share the password with can read the data."));
183 mSymmetric->setToolTip(i18nc("Tooltip information for symmetric encryption",
184 "Additionally to the keys of the recipients you can encrypt your data with a password. "
185 "Anyone who has the password can read the data without any secret key. "
186 "Using a password is <b>less secure</b> then public key cryptography. Even if you pick a very strong password."));
187 mSymmetric->setChecked(symmetricOnly || !havePublicKeys);
188 encBoxLay->addWidget(mSymmetric);
189
190 // Connect it
191 connect(mEncSelfChk, &QCheckBox::toggled, mSelfSelect, &QWidget::setEnabled);
192 connect(mEncSelfChk, &QCheckBox::toggled, this, &SignEncryptWidget::updateOp);
193 connect(mSymmetric, &QCheckBox::toggled, this, &SignEncryptWidget::updateOp);
194 connect(mSelfSelect, &KeySelectionCombo::currentKeyChanged,
195 this, &SignEncryptWidget::updateOp);
196
197 if (mIsExclusive) {
198 connect(mEncOtherChk, &QCheckBox::toggled, this, [this](bool value) {
199 if (mCurrentProto != GpgME::CMS) {
200 return;
201 }
202 if (value) {
203 mSigChk->setChecked(false);
204 }
205 });
206 connect(mEncSelfChk, &QCheckBox::toggled, this, [this](bool value) {
207 if (mCurrentProto != GpgME::CMS) {
208 return;
209 }
210 if (value) {
211 mSigChk->setChecked(false);
212 }
213 });
214 connect(mSigChk, &QCheckBox::toggled, this, [this](bool value) {
215 if (mCurrentProto != GpgME::CMS) {
216 return;
217 }
218 if (value) {
219 mEncSelfChk->setChecked(false);
220 mEncOtherChk->setChecked(false);
221 }
222 });
223 }
224
225 // Ensure that the mSigChk is aligned togehter with the encryption check boxes.
226 mSigChk->setMinimumWidth(qMax(mEncOtherChk->width(), mEncSelfChk->width()));
227
228 lay->addWidget(encBox);
229
230 connect(KeyCache::instance().get(), &Kleo::KeyCache::keysMayHaveChanged,
231 this, &SignEncryptWidget::updateCheckBoxes);
232 connect(KleopatraApplication::instance(), &KleopatraApplication::configurationChanged,
233 this, &SignEncryptWidget::updateCheckBoxes);
234
235 loadKeys();
236 onProtocolChanged();
237 updateOp();
238 }
239
setSignAsText(const QString & text)240 void SignEncryptWidget::setSignAsText(const QString &text)
241 {
242 mSigChk->setText(text);
243 }
244
setEncryptForMeText(const QString & text)245 void SignEncryptWidget::setEncryptForMeText(const QString &text)
246 {
247 mEncSelfChk->setText(text);
248 }
249
setEncryptForOthersText(const QString & text)250 void SignEncryptWidget::setEncryptForOthersText(const QString &text)
251 {
252 mEncOtherChk->setText(text);
253 }
254
setEncryptWithPasswordText(const QString & text)255 void SignEncryptWidget::setEncryptWithPasswordText(const QString& text)
256 {
257 mSymmetric->setText(text);
258 }
259
addRecipientWidget()260 CertificateLineEdit *SignEncryptWidget::addRecipientWidget()
261 {
262 auto certSel = new CertificateLineEdit(mModel, this,
263 new EncryptCertificateFilter(mCurrentProto));
264 certSel->setEnabled(mEncOtherChk->isChecked());
265 mRecpWidgets << certSel;
266
267 if (mRecpLayout->count() > 0) {
268 auto lastWidget = mRecpLayout->itemAt(mRecpLayout->count() - 1)->widget();
269 setTabOrder(lastWidget, certSel);
270 }
271 mRecpLayout->addWidget(certSel);
272
273 connect(certSel, &CertificateLineEdit::keyChanged,
274 this, &SignEncryptWidget::recipientsChanged);
275 connect(certSel, &CertificateLineEdit::wantsRemoval,
276 this, &SignEncryptWidget::recpRemovalRequested);
277 connect(certSel, &CertificateLineEdit::editingStarted,
278 this, &SignEncryptWidget::recipientsChanged);
279 connect(certSel, &CertificateLineEdit::dialogRequested,
280 this, [this, certSel] () { dialogRequested(certSel); });
281
282 return certSel;
283 }
284
addRecipient(const Key & key)285 void SignEncryptWidget::addRecipient(const Key &key)
286 {
287 CertificateLineEdit *certSel = addRecipientWidget();
288 if (!key.isNull()) {
289 certSel->setKey(key);
290 mAddedKeys << key;
291 }
292 }
293
addRecipient(const KeyGroup & group)294 void SignEncryptWidget::addRecipient(const KeyGroup &group)
295 {
296 CertificateLineEdit *certSel = addRecipientWidget();
297 if (!group.isNull()) {
298 certSel->setGroup(group);
299 mAddedGroups << group;
300 }
301 }
302
dialogRequested(CertificateLineEdit * certificateLineEdit)303 void SignEncryptWidget::dialogRequested(CertificateLineEdit *certificateLineEdit)
304 {
305 if (!certificateLineEdit->key().isNull()) {
306 auto cmd = new Commands::DetailsCommand(certificateLineEdit->key(), nullptr);
307 cmd->start();
308 return;
309 }
310 if (!certificateLineEdit->group().isNull()) {
311 auto dlg = new GroupDetailsDialog;
312 dlg->setAttribute(Qt::WA_DeleteOnClose);
313 dlg->setGroup(certificateLineEdit->group());
314 dlg->show();
315 return;
316 }
317
318 auto const dlg = new CertificateSelectionDialog(this);
319
320 dlg->setOptions(CertificateSelectionDialog::Options(
321 CertificateSelectionDialog::MultiSelection |
322 CertificateSelectionDialog::EncryptOnly |
323 CertificateSelectionDialog::optionsFromProtocol(mCurrentProto) |
324 CertificateSelectionDialog::IncludeGroups));
325
326 if (dlg->exec()) {
327 const std::vector<Key> keys = dlg->selectedCertificates();
328 const std::vector<KeyGroup> groups = dlg->selectedGroups();
329 if (keys.size() == 0 && groups.size() == 0) {
330 return;
331 }
332 bool isFirstItem = true;
333 for (const Key &key : keys) {
334 if (isFirstItem) {
335 certificateLineEdit->setKey(key);
336 isFirstItem = false;
337 } else {
338 addRecipient(key);
339 }
340 }
341 for (const KeyGroup &group : groups) {
342 if (isFirstItem) {
343 certificateLineEdit->setGroup(group);
344 isFirstItem = false;
345 } else {
346 addRecipient(group);
347 }
348 }
349 }
350 delete dlg;
351 recipientsChanged();
352 }
353
clearAddedRecipients()354 void SignEncryptWidget::clearAddedRecipients()
355 {
356 for (auto w: std::as_const(mUnknownWidgets)) {
357 mRecpLayout->removeWidget(w);
358 delete w;
359 }
360
361 for (auto &key: std::as_const(mAddedKeys)) {
362 removeRecipient(key);
363 }
364
365 for (auto &group: std::as_const(mAddedGroups)) {
366 removeRecipient(group);
367 }
368 }
369
addUnknownRecipient(const char * keyID)370 void SignEncryptWidget::addUnknownRecipient(const char *keyID)
371 {
372 auto unknownWidget = new UnknownRecipientWidget(keyID);
373 mUnknownWidgets << unknownWidget;
374
375 if (mRecpLayout->count() > 0) {
376 auto lastWidget = mRecpLayout->itemAt(mRecpLayout->count() - 1)->widget();
377 setTabOrder(lastWidget, unknownWidget);
378 }
379 mRecpLayout->addWidget(unknownWidget);
380
381 connect(KeyCache::instance().get(), &Kleo::KeyCache::keysMayHaveChanged,
382 this, [this] () {
383 // Check if any unknown recipient can now be found.
384 for (auto w: mUnknownWidgets) {
385 auto key = KeyCache::instance()->findByKeyIDOrFingerprint(w->keyID().toLatin1().constData());
386 if (key.isNull()) {
387 std::vector<std::string> subids;
388 subids.push_back(std::string(w->keyID().toLatin1().constData()));
389 for (const auto &subkey: KeyCache::instance()->findSubkeysByKeyID(subids)) {
390 key = subkey.parent();
391 }
392 }
393 if (key.isNull()) {
394 continue;
395 }
396 // Key is now available replace by line edit.
397 qCDebug(KLEOPATRA_LOG) << "Removing widget for keyid: " << w->keyID();
398 mRecpLayout->removeWidget(w);
399 mUnknownWidgets.removeAll(w);
400 delete w;
401 addRecipient(key);
402 }
403 });
404 }
405
recipientsChanged()406 void SignEncryptWidget::recipientsChanged()
407 {
408 const bool hasEmptyRecpWidget =
409 std::any_of(std::cbegin(mRecpWidgets), std::cend(mRecpWidgets),
410 [](auto w) { return w->isEmpty(); });
411 if (!hasEmptyRecpWidget) {
412 addRecipientWidget();
413 }
414 updateOp();
415 }
416
signKey() const417 Key SignEncryptWidget::signKey() const
418 {
419 if (mSigSelect->isEnabled()) {
420 return mSigSelect->currentKey();
421 }
422 return Key();
423 }
424
selfKey() const425 Key SignEncryptWidget::selfKey() const
426 {
427 if (mSelfSelect->isEnabled()) {
428 return mSelfSelect->currentKey();
429 }
430 return Key();
431 }
432
recipients() const433 std::vector<Key> SignEncryptWidget::recipients() const
434 {
435 std::vector<Key> ret;
436 for (const CertificateLineEdit *w : std::as_const(mRecpWidgets)) {
437 if (!w->isEnabled()) {
438 // If one is disabled, all are disabled.
439 break;
440 }
441 const Key k = w->key();
442 const KeyGroup g = w->group();
443 if (!k.isNull()) {
444 ret.push_back(k);
445 } else if (!g.isNull()) {
446 const auto keys = g.keys();
447 std::copy(keys.begin(), keys.end(), std::back_inserter(ret));
448 }
449 }
450 const Key k = selfKey();
451 if (!k.isNull()) {
452 ret.push_back(k);
453 }
454 return ret;
455 }
456
isDeVsAndValid() const457 bool SignEncryptWidget::isDeVsAndValid() const
458 {
459 if (!signKey().isNull()
460 && (!IS_DE_VS(signKey()) || keyValidity(signKey()) < GpgME::UserID::Validity::Full)) {
461 return false;
462 }
463
464 if (!selfKey().isNull()
465 && (!IS_DE_VS(selfKey()) || keyValidity(selfKey()) < GpgME::UserID::Validity::Full)) {
466 return false;
467 }
468
469 for (const auto &key: recipients()) {
470 if (!IS_DE_VS(key) || keyValidity(key) < GpgME::UserID::Validity::Full) {
471 return false;
472 }
473 }
474
475 return true;
476 }
477
updateOp()478 void SignEncryptWidget::updateOp()
479 {
480 const Key sigKey = signKey();
481 const std::vector<Key> recp = recipients();
482
483 QString newOp;
484 if (!sigKey.isNull() && (!recp.empty() || encryptSymmetric())) {
485 newOp = i18nc("@action", "Sign / Encrypt");
486 } else if (!recp.empty() || encryptSymmetric()) {
487 newOp = i18nc("@action", "Encrypt");
488 } else if (!sigKey.isNull()) {
489 newOp = i18nc("@action", "Sign");
490 } else {
491 newOp = QString();
492 }
493 mOp = newOp;
494 Q_EMIT operationChanged(mOp);
495 Q_EMIT keysChanged();
496 }
497
currentOp() const498 QString SignEncryptWidget::currentOp() const
499 {
500 return mOp;
501 }
502
recpRemovalRequested(CertificateLineEdit * w)503 void SignEncryptWidget::recpRemovalRequested(CertificateLineEdit *w)
504 {
505 if (!w) {
506 return;
507 }
508 const int emptyEdits =
509 std::count_if(std::cbegin(mRecpWidgets), std::cend(mRecpWidgets),
510 [](auto w) { return w->isEmpty(); });
511 if (emptyEdits > 1) {
512 if (w->hasFocus()) {
513 const int index = mRecpLayout->indexOf(w);
514 const auto focusWidget = (index < mRecpLayout->count() - 1) ?
515 mRecpLayout->itemAt(index + 1)->widget() :
516 mRecpLayout->itemAt(mRecpLayout->count() - 2)->widget();
517 focusWidget->setFocus();
518 }
519 mRecpLayout->removeWidget(w);
520 mRecpWidgets.removeAll(w);
521 w->deleteLater();
522 }
523 }
524
removeRecipient(const GpgME::Key & key)525 void SignEncryptWidget::removeRecipient(const GpgME::Key &key)
526 {
527 for (CertificateLineEdit *edit: std::as_const(mRecpWidgets)) {
528 const auto editKey = edit->key();
529 if (key.isNull() && editKey.isNull()) {
530 recpRemovalRequested(edit);
531 return;
532 }
533 if (editKey.primaryFingerprint() &&
534 key.primaryFingerprint() &&
535 !strcmp(editKey.primaryFingerprint(), key.primaryFingerprint())) {
536 recpRemovalRequested(edit);
537 return;
538 }
539 }
540 }
541
removeRecipient(const KeyGroup & group)542 void SignEncryptWidget::removeRecipient(const KeyGroup &group)
543 {
544 for (CertificateLineEdit *edit: std::as_const(mRecpWidgets)) {
545 const auto editGroup = edit->group();
546 if (group.isNull() && editGroup.isNull()) {
547 recpRemovalRequested(edit);
548 return;
549 }
550 if (editGroup.name() == group.name()) {
551 recpRemovalRequested(edit);
552 return;
553 }
554 }
555 }
556
encryptSymmetric() const557 bool SignEncryptWidget::encryptSymmetric() const
558 {
559 return mSymmetric->isChecked();
560 }
561
loadKeys()562 void SignEncryptWidget::loadKeys()
563 {
564 KConfigGroup keys(KSharedConfig::openConfig(), "SignEncryptKeys");
565 auto cache = KeyCache::instance();
566 mSigSelect->setDefaultKey(keys.readEntry("SigningKey", QString()));
567 mSelfSelect->setDefaultKey(keys.readEntry("EncryptKey", QString()));
568 }
569
saveOwnKeys() const570 void SignEncryptWidget::saveOwnKeys() const
571 {
572 KConfigGroup keys(KSharedConfig::openConfig(), "SignEncryptKeys");
573 auto sigKey = mSigSelect->currentKey();
574 auto encKey = mSelfSelect->currentKey();
575 if (!sigKey.isNull()) {
576 keys.writeEntry("SigningKey", sigKey.primaryFingerprint());
577 }
578 if (!encKey.isNull()) {
579 keys.writeEntry("EncryptKey", encKey.primaryFingerprint());
580 }
581 }
582
setSigningChecked(bool value)583 void SignEncryptWidget::setSigningChecked(bool value)
584 {
585 mSigChk->setChecked(value && !KeyCache::instance()->secretKeys().empty());
586 }
587
setEncryptionChecked(bool checked)588 void SignEncryptWidget::setEncryptionChecked(bool checked)
589 {
590 if (checked) {
591 const bool haveSecretKeys = !KeyCache::instance()->secretKeys().empty();
592 const bool havePublicKeys = !KeyCache::instance()->keys().empty();
593 const bool symmetricOnly = FileOperationsPreferences().symmetricEncryptionOnly();
594 mEncSelfChk->setChecked(haveSecretKeys && !symmetricOnly);
595 mEncOtherChk->setChecked(havePublicKeys && !symmetricOnly);
596 mSymmetric->setChecked(symmetricOnly || !havePublicKeys);
597 } else {
598 mEncSelfChk->setChecked(false);
599 mEncOtherChk->setChecked(false);
600 mSymmetric->setChecked(false);
601 }
602 }
603
setProtocol(GpgME::Protocol proto)604 void SignEncryptWidget::setProtocol(GpgME::Protocol proto)
605 {
606 if (mCurrentProto == proto) {
607 return;
608 }
609 mCurrentProto = proto;
610 onProtocolChanged();
611 }
612
onProtocolChanged()613 void Kleo::SignEncryptWidget::onProtocolChanged()
614 {
615 mSigSelect->setKeyFilter(std::shared_ptr<KeyFilter>(new SignCertificateFilter(mCurrentProto)));
616 mSelfSelect->setKeyFilter(std::shared_ptr<KeyFilter>(new EncryptSelfCertificateFilter(mCurrentProto)));
617 const auto encFilter = std::shared_ptr<KeyFilter>(new EncryptCertificateFilter(mCurrentProto));
618 for (CertificateLineEdit *edit : std::as_const(mRecpWidgets)) {
619 edit->setKeyFilter(encFilter);
620 }
621
622 if (mIsExclusive) {
623 mSymmetric->setDisabled(mCurrentProto == GpgME::CMS);
624 if (mSymmetric->isChecked() && mCurrentProto == GpgME::CMS) {
625 mSymmetric->setChecked(false);
626 }
627 if (mSigChk->isChecked() && mCurrentProto == GpgME::CMS &&
628 (mEncSelfChk->isChecked() || mEncOtherChk->isChecked())) {
629 mSigChk->setChecked(false);
630 }
631 }
632 }
633
validate()634 bool SignEncryptWidget::validate()
635 {
636 QStringList unresolvedRecipients;
637 for (const auto edit: std::as_const(mRecpWidgets)) {
638 if (edit->isEnabled() && !edit->isEmpty() && edit->key().isNull() && edit->group().isNull()) {
639 unresolvedRecipients.push_back(edit->text().toHtmlEscaped());
640 }
641 }
642 if (!unresolvedRecipients.isEmpty()) {
643 KMessageBox::errorList(this,
644 i18n("Could not find a key for the following recipients:"),
645 unresolvedRecipients,
646 i18n("Failed to find some keys"));
647 }
648 return unresolvedRecipients.isEmpty();
649 }
650
updateCheckBoxes()651 void SignEncryptWidget::updateCheckBoxes()
652 {
653 const bool haveSecretKeys = !KeyCache::instance()->secretKeys().empty();
654 const bool havePublicKeys = !KeyCache::instance()->keys().empty();
655 const bool symmetricOnly = FileOperationsPreferences().symmetricEncryptionOnly();
656 mSigChk->setEnabled(haveSecretKeys);
657 mEncSelfChk->setEnabled(haveSecretKeys && !symmetricOnly);
658 mEncOtherChk->setEnabled(havePublicKeys && !symmetricOnly);
659 if (symmetricOnly) {
660 mEncSelfChk->setChecked(false);
661 mEncOtherChk->setChecked(false);
662 mSymmetric->setChecked(true);
663 }
664 }
665