Commit 1aa4ab48 authored by Ingo Klöcker's avatar Ingo Klöcker
Browse files

Show the sender's encryption key(s) separately

* should be better usability if the sender's key(s) are not "hidden"
  between the keys of the recipients
* in mixed mode we need two encryption keys for the sender (OpenPGP
  and S/MIME), but only one encryption key for the recipients (OpenPGP
  or S/MIME); clear separation of the keys should avoid confusion

GnuPG-bug-id: 5283
parent 7f7a0a20
......@@ -42,9 +42,10 @@ GpgME::Key createTestKey(const char *uid, GpgME::Protocol protocol = GpgME::Unkn
return GpgME::Key(key, false);
}
QList<QWidget *> visibleWidgets(const QList<QWidget *> &widgets)
template <typename T>
QList<T *> visibleWidgets(const QList<T *> &widgets)
{
QList<QWidget *> result;
QList<T *> result;
std::copy_if(widgets.begin(), widgets.end(),
std::back_inserter(result),
std::mem_fn(&QWidget::isVisible));
......@@ -73,21 +74,22 @@ private Q_SLOTS:
forcedProtocol,
presetProtocol);
dialog->show();
const QList<QWidget *> signingKeyWidgets = dialog->findChildren<QWidget *>(QStringLiteral("signing key"));
const QList<KeySelectionCombo *> signingKeyWidgets = dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key"));
QCOMPARE(signingKeyWidgets.size(), 2);
const auto visibleSigningKeyWidgets = visibleWidgets(signingKeyWidgets);
QCOMPARE(visibleSigningKeyWidgets.size(), 1);
for (auto widget : visibleSigningKeyWidgets) {
KeySelectionCombo *combo = qobject_cast<KeySelectionCombo *>(widget);
for (auto combo: visibleSigningKeyWidgets) {
QVERIFY(combo);
QVERIFY2(!combo->defaultKey(GpgME::OpenPGP).isEmpty(), "visible signing key widget should default to OpenPGP key");
}
const QList<QWidget *> encryptionKeyWidgets = dialog->findChildren<QWidget *>(QStringLiteral("encryption key"));
const QList<KeySelectionCombo *> encryptionKeyWidgets = dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key"));
QCOMPARE(encryptionKeyWidgets.size(), 4);
const auto visibleEncryptionKeyWidgets = visibleWidgets(encryptionKeyWidgets);
QCOMPARE(visibleEncryptionKeyWidgets.size(), 3);
for (auto widget : visibleEncryptionKeyWidgets) {
KeySelectionCombo *combo = qobject_cast<KeySelectionCombo *>(widget);
QCOMPARE(visibleEncryptionKeyWidgets[0]->property("address").toString(), sender);
QVERIFY2(!visibleEncryptionKeyWidgets[0]->defaultKey(GpgME::OpenPGP).isEmpty(),
"encryption key widget for sender's OpenPGP key is first visible widget");
for (auto combo: visibleEncryptionKeyWidgets) {
QVERIFY(combo);
QVERIFY2(combo->property("address").toString() != sender || !combo->defaultKey(GpgME::OpenPGP).isEmpty(),
"encryption key widget for sender's CMS key should be hidden");
......@@ -111,21 +113,22 @@ private Q_SLOTS:
forcedProtocol,
presetProtocol);
dialog->show();
const QList<QWidget *> signingKeyWidgets = dialog->findChildren<QWidget *>(QStringLiteral("signing key"));
const QList<KeySelectionCombo *> signingKeyWidgets = dialog->findChildren<KeySelectionCombo *>(QStringLiteral("signing key"));
QCOMPARE(signingKeyWidgets.size(), 2);
const auto visibleSigningKeyWidgets = visibleWidgets(signingKeyWidgets);
QCOMPARE(visibleSigningKeyWidgets.size(), 1);
for (auto widget : visibleSigningKeyWidgets) {
KeySelectionCombo *combo = qobject_cast<KeySelectionCombo *>(widget);
for (auto combo: visibleSigningKeyWidgets) {
QVERIFY(combo);
QVERIFY2(!combo->defaultKey(GpgME::CMS).isEmpty(), "visible signing key widget should default to S/MIME key");
}
const QList<QWidget *> encryptionKeyWidgets = dialog->findChildren<QWidget *>(QStringLiteral("encryption key"));
const QList<KeySelectionCombo *> encryptionKeyWidgets = dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key"));
QCOMPARE(encryptionKeyWidgets.size(), 4);
const auto visibleEncryptionKeyWidgets = visibleWidgets(encryptionKeyWidgets);
QCOMPARE(visibleEncryptionKeyWidgets.size(), 3);
for (auto widget : visibleEncryptionKeyWidgets) {
KeySelectionCombo *combo = qobject_cast<KeySelectionCombo *>(widget);
QCOMPARE(visibleEncryptionKeyWidgets[0]->property("address").toString(), sender);
QVERIFY2(!visibleEncryptionKeyWidgets[0]->defaultKey(GpgME::CMS).isEmpty(),
"encryption key widget for sender's CMS key is first visible widget");
for (auto combo: visibleEncryptionKeyWidgets) {
QVERIFY(combo);
QVERIFY2(combo->property("address").toString() != sender || !combo->defaultKey(GpgME::CMS).isEmpty(),
"encryption key widget for sender's OpenPGP key should be hidden");
......@@ -141,8 +144,9 @@ private Q_SLOTS:
GpgME::Protocol forcedProtocol = GpgME::UnknownProtocol;
GpgME::Protocol presetProtocol = GpgME::UnknownProtocol;
const auto resolvedSenders = resolved_senders_openpgp_and_smime();
const auto resolvedRecipients = resolved_recipients_openpgp_and_smime();
const auto dialog = std::make_unique<NewKeyApprovalDialog>(resolvedSenders,
resolved_recipients_openpgp_and_smime(),
resolvedRecipients,
unresolvedSenders,
unresolvedRecipients,
sender,
......@@ -165,12 +169,19 @@ private Q_SLOTS:
signingKeyWidgets[1]->defaultKey()
};
QCOMPARE(defaultKeys, signingKeyFingerprints);
const QList<QWidget *> encryptionKeyWidgets = dialog->findChildren<QWidget *>(QStringLiteral("encryption key"));
const QList<KeySelectionCombo *> encryptionKeyWidgets = dialog->findChildren<KeySelectionCombo *>(QStringLiteral("encryption key"));
QCOMPARE(encryptionKeyWidgets.size(), 4);
for (auto widget : encryptionKeyWidgets) {
QVERIFY2(widget->isVisible(),
qPrintable(QString("encryption key widget should be visible for address %1").arg(widget->property("address").toString())));
}
// encryption key widgets for sender's keys shall be first two widgets
QCOMPARE(encryptionKeyWidgets[0]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets[0]->defaultKey(),
QString::fromLatin1(resolvedRecipients["sender@example.net"][0].primaryFingerprint()));
QCOMPARE(encryptionKeyWidgets[1]->property("address").toString(), sender);
QCOMPARE(encryptionKeyWidgets[1]->defaultKey(),
QString::fromLatin1(resolvedRecipients["sender@example.net"][1].primaryFingerprint()));
}
private:
......
......@@ -526,58 +526,69 @@ public:
}
}
void addEncryptionAddr(const QString &addr, const std::vector<GpgME::Key> &keys,
QGridLayout *encGrid)
ComboWidget *createEncryptionCombo(const QString &addr, const GpgME::Key &key)
{
encGrid->addWidget(new QLabel(addr), encGrid->rowCount(), 0);
for (const auto &key: keys)
{
auto combo = new KeySelectionCombo(false);
auto combo = new KeySelectionCombo(false);
#ifndef NDEBUG
combo->setObjectName(QStringLiteral("encryption key"));
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());
}
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);
}
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."));
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);
}
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();
});
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);
return new ComboWidget(combo);
}
mEncCombos << combo;
mAllCombos << combo;
combo->setProperty("address", addr);
auto comboWidget = new ComboWidget(combo);
if (keys.size() > 1) {
comboWidget->setFromOverride(key.protocol());
}
void addEncryptionAddr(const QString &addr, const std::vector<GpgME::Key> &keys,
QGridLayout *encGrid)
{
if (addr != mSender) {
encGrid->addWidget(new QLabel(addr), encGrid->rowCount(), 0);
}
if (keys.empty()) {
ComboWidget* comboWidget = createEncryptionCombo(addr, GpgME::Key());
encGrid->addWidget(comboWidget, encGrid->rowCount(), 0, 1, 2);
} else {
for (const auto &key: keys) {
ComboWidget* comboWidget = createEncryptionCombo(addr, key);
if (keys.size() > 1) {
comboWidget->setFromOverride(key.protocol());
}
encGrid->addWidget(comboWidget, encGrid->rowCount(), 0, 1, 2);
}
}
}
......@@ -587,19 +598,30 @@ public:
if (resolved.empty() && unresolved.empty()) {
return;
}
auto group = new QGroupBox(i18n("Encrypt to:"));
{
auto group = new QGroupBox(i18nc("Encrypt to self (email address):", "Encrypt to self (%1):", mSender));
group->setAlignment(Qt::AlignLeft);
auto encGrid = new QGridLayout;
group->setLayout(encGrid);
mScrollLayout->addWidget(group);
addEncryptionAddr(mSender, resolved.value(mSender), encGrid);
}
auto group = new QGroupBox(i18n("Encrypt to others:"));
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);
if (addr != mSender) {
addEncryptionAddr(addr, resolved[addr], encGrid);
}
}
std::vector<GpgME::Key> dummy;
dummy.push_back(GpgME::Key());
for (const QString &addr: unresolved) {
addEncryptionAddr(addr, dummy, encGrid);
if (addr != mSender) {
addEncryptionAddr(addr, {}, encGrid);
}
}
encGrid->setColumnStretch(1, -1);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment