diff --git a/src/crypto/gui/certificatelineedit.cpp b/src/crypto/gui/certificatelineedit.cpp index 11ec5ecee..52ac6b2bc 100644 --- a/src/crypto/gui/certificatelineedit.cpp +++ b/src/crypto/gui/certificatelineedit.cpp @@ -1,254 +1,257 @@ /* crypto/gui/certificatelineedit.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik SPDX-FileContributor: Intevation GmbH SPDX-License-Identifier: GPL-2.0-or-later */ #include "certificatelineedit.h" #include #include #include #include #include "kleopatra_debug.h" #include "commands/detailscommand.h" #include #include #include #include #include #include #include #include #include #include using namespace Kleo; using namespace Kleo::Dialogs; using namespace GpgME; Q_DECLARE_METATYPE(GpgME::Key) static QStringList s_lookedUpKeys; namespace { class ProxyModel : public KeyListSortFilterProxyModel { Q_OBJECT public: ProxyModel(QObject *parent = nullptr) : KeyListSortFilterProxyModel(parent) { } QVariant data(const QModelIndex &index, int role) const override { if (!index.isValid()) { return QVariant(); } switch (role) { case Qt::DecorationRole: { const auto key = KeyListSortFilterProxyModel::data(index, Kleo::KeyListModelInterface::KeyRole).value(); Q_ASSERT(!key.isNull()); if (key.isNull()) { return QVariant(); } return Kleo::Formatting::iconForUid(key.userID(0)); } default: return KeyListSortFilterProxyModel::data(index, role); } } }; } // namespace CertificateLineEdit::CertificateLineEdit(AbstractKeyListModel *model, QWidget *parent, KeyFilter *filter) : QLineEdit(parent), mFilterModel(new KeyListSortFilterProxyModel(this)), mFilter(std::shared_ptr(filter)), mLineAction(new QAction(this)) { setPlaceholderText(i18n("Please enter a name or email address...")); setClearButtonEnabled(true); addAction(mLineAction, QLineEdit::LeadingPosition); auto *completer = new QCompleter(this); auto *completeFilterModel = new ProxyModel(completer); completeFilterModel->setKeyFilter(mFilter); completeFilterModel->setSourceModel(model); completer->setModel(completeFilterModel); completer->setCompletionColumn(KeyListModelInterface::Summary); completer->setFilterMode(Qt::MatchContains); completer->setCaseSensitivity(Qt::CaseInsensitive); setCompleter(completer); mFilterModel->setSourceModel(model); mFilterModel->setFilterKeyColumn(KeyListModelInterface::Summary); if (filter) { mFilterModel->setKeyFilter(mFilter); } connect(KeyCache::instance().get(), &Kleo::KeyCache::keyListingDone, this, &CertificateLineEdit::updateKey); connect(this, &QLineEdit::editingFinished, this, &CertificateLineEdit::editFinished); connect(this, &QLineEdit::textChanged, this, &CertificateLineEdit::editChanged); connect(mLineAction, &QAction::triggered, this, &CertificateLineEdit::dialogRequested); connect(this, &QLineEdit::editingFinished, this, &CertificateLineEdit::checkLocate); updateKey(); /* Take ownership of the model to prevent double deletion when the * filter models are deleted */ model->setParent(parent ? parent : this); } void CertificateLineEdit::editChanged() { updateKey(); if (!mEditStarted) { Q_EMIT editingStarted(); mEditStarted = true; } mEditFinished = false; } void CertificateLineEdit::editFinished() { mEditStarted = false; mEditFinished = true; updateKey(); } void CertificateLineEdit::checkLocate() { if (!key().isNull()) { // Already have a key return; } // Only check once per mailbox const auto mailText = text(); if (s_lookedUpKeys.contains(mailText)) { return; } s_lookedUpKeys << mailText; qCDebug(KLEOPATRA_LOG) << "Lookup job for" << mailText; QGpgME::KeyForMailboxJob *job = QGpgME::openpgp()->keyForMailboxJob(); job->start(mailText); } void CertificateLineEdit::updateKey() { const auto mailText = text(); auto newKey = Key(); if (mailText.isEmpty()) { mLineAction->setIcon(QIcon::fromTheme(QStringLiteral("resource-group-new"))); mLineAction->setToolTip(i18n("Open selection dialog.")); } else { mFilterModel->setFilterFixedString(mailText); if (mFilterModel->rowCount() > 1) { if (mEditFinished) { mLineAction->setIcon(QIcon::fromTheme(QStringLiteral("question")).pixmap(KIconLoader::SizeSmallMedium)); mLineAction->setToolTip(i18n("Multiple certificates")); + } else { + mLineAction->setIcon(QIcon::fromTheme(QStringLiteral("resource-group-new"))); + mLineAction->setToolTip(i18n("Open selection dialog.")); } } else if (mFilterModel->rowCount() == 1) { newKey = mFilterModel->data(mFilterModel->index(0, 0), KeyListModelInterface::KeyRole).value(); mLineAction->setToolTip(Formatting::validity(newKey.userID(0)) + QStringLiteral("
Click here for details.")); /* FIXME: This needs to be solved by a multiple UID supporting model */ mLineAction->setIcon(Formatting::iconForUid(newKey.userID(0))); } else { mLineAction->setIcon(QIcon::fromTheme(QStringLiteral("emblem-error"))); mLineAction->setToolTip(i18n("No matching certificates found.
Click here to import a certificate.")); } } mKey = newKey; if (mKey.isNull()) { setToolTip(QString()); } else { setToolTip(Formatting::toolTip(newKey, Formatting::ToolTipOption::AllOptions)); } Q_EMIT keyChanged(); if (mailText.isEmpty()) { Q_EMIT wantsRemoval(this); } } Key CertificateLineEdit::key() const { if (isEnabled()) { return mKey; } else { return Key(); } } void CertificateLineEdit::dialogRequested() { if (!mKey.isNull()) { auto cmd = new Commands::DetailsCommand(mKey, nullptr); cmd->start(); return; } CertificateSelectionDialog *const dlg = new CertificateSelectionDialog(this); dlg->setKeyFilter(mFilter); if (dlg->exec()) { const std::vector keys = dlg->selectedCertificates(); if (!keys.size()) { return; } for (unsigned int i = 0; i < keys.size(); i++) { if (!i) { setKey(keys[i]); } else { Q_EMIT addRequested(keys[i]); } } } delete dlg; updateKey(); } void CertificateLineEdit::setKey(const Key &k) { QSignalBlocker blocky(this); qCDebug(KLEOPATRA_LOG) << "Setting Key. " << Formatting::summaryLine(k); setText(Formatting::summaryLine(k)); updateKey(); } bool CertificateLineEdit::isEmpty() const { return text().isEmpty(); } void CertificateLineEdit::setKeyFilter(const std::shared_ptr &filter) { mFilter = filter; mFilterModel->setKeyFilter(filter); } #include "certificatelineedit.moc"