10#include <config-libkleo.h>
12#include "keyfiltermanager.h"
14#include "defaultkeyfilter.h"
15#include "kconfigbasedkeyfilter.h"
18#include <libkleo/algorithm.h>
19#include <libkleo/compliance.h>
20#include <libkleo/gnupg.h>
21#include <libkleo/keyhelpers.h>
23#include <libkleo_debug.h>
26#include <KConfigGroup>
27#include <KLocalizedString>
28#include <KSharedConfig>
30#include <QAbstractListModel>
31#include <QCoreApplication>
34#include <QRegularExpression>
46void adjustFilters(std::vector<std::shared_ptr<KeyFilter>> &filters, Protocol protocol)
48 if (protocol != GpgME::UnknownProtocol) {
50 const auto conflictingValue = (protocol == GpgME::OpenPGP) ? DefaultKeyFilter::NotSet :
DefaultKeyFilter::Set;
51 Kleo::erase_if(filters, [conflictingValue](
const auto &f) {
52 const auto filter = std::dynamic_pointer_cast<DefaultKeyFilter>(f);
54 return filter->isOpenPGP() == conflictingValue;
57 const auto isOpenPGPValue = (protocol == GpgME::OpenPGP) ? DefaultKeyFilter::Set :
DefaultKeyFilter::NotSet;
58 std::for_each(std::begin(filters), std::end(filters), [isOpenPGPValue](
auto &f) {
59 const auto filter = std::dynamic_pointer_cast<DefaultKeyFilter>(f);
61 return filter->setIsOpenPGP(isOpenPGPValue);
68 KeyFilterManager::Private *m_keyFilterManagerPrivate;
71 explicit Model(KeyFilterManager::Private *p)
73 , m_keyFilterManagerPrivate(p)
86 AllCertificatesKeyFilter()
89 setSpecificity(UINT_MAX);
90 setName(
i18nc(
"All Certificates",
"All"));
91 setDescription(
i18n(
"All certificates"));
92 setId(QStringLiteral(
"all-certificates"));
93 setMatchContexts(Filtering);
100 MyCertificatesKeyFilter()
104 setSpecificity(UINT_MAX - 2);
106 setName(
i18nc(
"My own Certificates",
"My Own"));
107 setDescription(
i18n(
"My own certificates"));
108 setId(QStringLiteral(
"my-certificates"));
109 setMatchContexts(AnyMatchContext);
117 FullCertificatesKeyFilter()
121 setValidity(IsAtLeast);
122 setValidityReferenceLevel(UserID::Full);
123 setSpecificity(UINT_MAX - 4);
125 setName(
i18nc(
"Certified Certificates",
"Certified"));
126 setDescription(
i18n(
"Certificates for which the primary user ID is certified"));
127 setId(QStringLiteral(
"trusted-certificates"));
128 setMatchContexts(Filtering);
135 OtherCertificatesKeyFilter()
138 setHasSecret(NotSet);
139 setValidity(IsAtMost);
140 setValidityReferenceLevel(UserID::Marginal);
141 setSpecificity(UINT_MAX - 6);
143 setName(
i18nc(
"Not Certified Certificates",
"Not Certified"));
144 setDescription(
i18n(
"Certificates for which the primary user ID is not certified"));
145 setId(QStringLiteral(
"other-certificates"));
146 setMatchContexts(Filtering);
155 UncertifiedOpenPGPKeysFilter()
158 setSpecificity(UINT_MAX - 7);
159 setName(
i18nc(
"Certificates to certify by the user",
"To Certify"));
160 setDescription(
i18n(
"Certificates that are not fully certified and that you may want to certify yourself"));
161 setId(QStringLiteral(
"not-certified-certificates"));
163 setMatchContexts(Filtering);
167 bool matches(
const Key &key, MatchContexts contexts)
const override
169 return DefaultKeyFilter::matches(key, contexts) && !Kleo::allUserIDsHaveFullValidity(key);
171 bool matches(
const UserID &userID, MatchContexts contexts)
const override
173 return DefaultKeyFilter::matches(userID.parent(), contexts) && userID.validity() < UserID::Full;
185 setSpecificity(UINT_MAX - 5);
187 setName(
i18nc(
"Not Fully Certified Certificates",
"Not Fully Certified"));
188 setDescription(
i18n(
"Certificates for which not all user IDs are certified"));
189 setId(QStringLiteral(
"not-validated-certificates"));
190 setMatchContexts(Filtering);
192 bool matches(
const Key &key, MatchContexts contexts)
const override
194 return DefaultKeyFilter::matches(key, contexts) && !Kleo::allUserIDsHaveFullValidity(key);
196 bool matches(
const UserID &userID, MatchContexts contexts)
const override
198 return DefaultKeyFilter::matches(userID.parent(), contexts) && userID.validity() < UserID::Full;
207 KeyFullyCertifiedFilter()
210 setSpecificity(UINT_MAX - 3);
211 setName(
i18nc(
"Fully Certified Certificates",
"Fully Certified"));
212 setDescription(
i18n(
"Certificates for which all user IDs are certified"));
213 setId(QStringLiteral(
"full-certificates"));
214 setMatchContexts(Filtering);
216 bool matches(
const Key &key, MatchContexts contexts)
const override
218 return DefaultKeyFilter::matches(key, contexts) && Kleo::allUserIDsHaveFullValidity(key);
220 bool matches(
const UserID &userID, MatchContexts contexts)
const override
222 return DefaultKeyFilter::matches(userID.parent(), contexts) && userID.validity() >= UserID::Full;
226static std::vector<std::shared_ptr<KeyFilter>> defaultFilters()
229 std::shared_ptr<KeyFilter>(
new MyCertificatesKeyFilter),
230 std::shared_ptr<KeyFilter>(
new FullCertificatesKeyFilter),
231 std::shared_ptr<KeyFilter>(
new OtherCertificatesKeyFilter),
232 std::shared_ptr<KeyFilter>(
new AllCertificatesKeyFilter),
233 std::shared_ptr<KeyFilter>(
new UncertifiedOpenPGPKeysFilter),
234 std::shared_ptr<KeyFilter>(
new KeyFullyCertifiedFilter),
235 std::shared_ptr<KeyFilter>(
new KeyNotValidFilter),
239class KeyFilterManager::Private
249 model.beginResetModel();
251 model.endResetModel();
254 std::vector<std::shared_ptr<KeyFilter>> filters;
256 GpgME::Protocol protocol = GpgME::UnknownProtocol;
259KeyFilterManager *KeyFilterManager::mSelf =
nullptr;
261KeyFilterManager::KeyFilterManager(
QObject *parent)
273KeyFilterManager::~KeyFilterManager()
281KeyFilterManager *KeyFilterManager::instance()
284 mSelf =
new KeyFilterManager();
289void KeyFilterManager::alwaysFilterByProtocol(GpgME::Protocol protocol)
291 if (protocol != d->protocol) {
292 d->protocol = protocol;
294 Q_EMIT alwaysFilterByProtocolChanged(protocol);
298const std::shared_ptr<KeyFilter> &KeyFilterManager::filterMatching(
const Key &key,
KeyFilter::MatchContexts contexts)
const
300 const auto it = std::find_if(d->filters.cbegin(), d->filters.cend(), [&key, contexts](
const std::shared_ptr<KeyFilter> &filter) {
301 return filter->matches(key, contexts);
303 if (it != d->filters.cend()) {
306 static const std::shared_ptr<KeyFilter> null;
310std::vector<std::shared_ptr<KeyFilter>> KeyFilterManager::filtersMatching(
const Key &key,
KeyFilter::MatchContexts contexts)
const
312 std::vector<std::shared_ptr<KeyFilter>> result;
313 result.reserve(d->filters.size());
314 std::remove_copy_if(d->filters.begin(), d->filters.end(), std::back_inserter(result), [&key, contexts](
const std::shared_ptr<KeyFilter> &filter) {
315 return !filter->matches(key, contexts);
322static const auto byDecreasingSpecificity = [](
const std::shared_ptr<KeyFilter> &lhs,
const std::shared_ptr<KeyFilter> &rhs) {
323 return lhs->specificity() > rhs->specificity();
327void KeyFilterManager::reload()
331 d->filters = defaultFilters();
335 const bool ignoreDeVs = !DeVSCompliance::isCompliant();
338 if (cfg.hasKey(
"is-de-vs") && ignoreDeVs) {
342 d->filters.push_back(std::shared_ptr<KeyFilter>(
new KConfigBasedKeyFilter(cfg)));
344 std::stable_sort(d->filters.begin(), d->filters.end(), byDecreasingSpecificity);
346 adjustFilters(d->filters, d->protocol);
347 qCDebug(LIBKLEO_LOG) <<
"KeyFilterManager::" << __func__ <<
"final filter count is" << d->filters.size();
355const std::shared_ptr<KeyFilter> &KeyFilterManager::keyFilterByID(
const QString &
id)
const
357 const auto it = std::find_if(d->filters.begin(), d->filters.end(), [
id](
const std::shared_ptr<KeyFilter> &filter) {
358 return filter->id() == id;
360 if (it != d->filters.end()) {
363 static const std::shared_ptr<KeyFilter> null;
367const std::shared_ptr<KeyFilter> &KeyFilterManager::fromModelIndex(
const QModelIndex &idx)
const
369 if (!idx.
isValid() || idx.
model() != &d->model || idx.
row() < 0 ||
static_cast<unsigned>(idx.
row()) >= d->filters.size()) {
370 static const std::shared_ptr<KeyFilter> null;
373 return d->filters[idx.
row()];
376QModelIndex KeyFilterManager::toModelIndex(
const std::shared_ptr<KeyFilter> &kf)
const
381 const auto pair = std::equal_range(d->filters.cbegin(), d->filters.cend(), kf, byDecreasingSpecificity);
382 const auto it = std::find(pair.first, pair.second, kf);
383 if (it != pair.second) {
384 return d->model.index(it - d->filters.begin());
392 return m_keyFilterManagerPrivate->filters.size();
397 if (!idx.
isValid() || idx.
model() !=
this || idx.
row() < 0 ||
static_cast<unsigned>(idx.
row()) > m_keyFilterManagerPrivate->filters.size()) {
401 const auto filter = m_keyFilterManagerPrivate->filters[idx.
row()];
410 return filter->description();
412 case KeyFilterManager::FilterIdRole:
415 case KeyFilterManager::FilterMatchContextsRole:
418 case KeyFilterManager::FilterRole:
426static KeyFilter::FontDescription
427get_fontdescription(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const Key &key,
const KeyFilter::FontDescription &initial)
429 return kdtools::accumulate_if(
432 [&key](
const std::shared_ptr<KeyFilter> &filter) {
433 return filter->matches(key, KeyFilter::Appearance);
436 [](
const KeyFilter::FontDescription &lhs,
const std::shared_ptr<KeyFilter> &rhs) {
437 return lhs.resolve(rhs->fontDescription());
441QFont KeyFilterManager::font(
const Key &key,
const QFont &baseFont)
const
443 const KeyFilter::FontDescription fd = get_fontdescription(d->filters, key, KeyFilter::FontDescription());
445 return fd.font(baseFont);
448static QColor get_color(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const Key &key,
QColor (
KeyFilter::*fun)()
const)
450 const auto it = std::find_if(filters.cbegin(), filters.cend(), [&fun, &key](
const std::shared_ptr<KeyFilter> &filter) {
451 return filter->matches(key, KeyFilter::Appearance) && (filter.get()->*fun)().isValid();
453 if (it == filters.cend()) {
456 return (it->get()->*fun)();
460static QColor get_color(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const UserID &userID,
QColor (
KeyFilter::*fun)()
const)
462 const auto it = std::find_if(filters.cbegin(), filters.cend(), [&fun, &userID](
const std::shared_ptr<KeyFilter> &filter) {
463 return filter->matches(userID, KeyFilter::Appearance) && (filter.get()->*fun)().isValid();
465 if (it == filters.cend()) {
468 return (it->get()->*fun)();
472static QString get_string(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const Key &key,
QString (
KeyFilter::*fun)()
const)
474 const auto it = std::find_if(filters.cbegin(), filters.cend(), [&fun, &key](
const std::shared_ptr<KeyFilter> &filter) {
475 return filter->matches(key, KeyFilter::Appearance) && !(filter.get()->*fun)().isEmpty();
477 if (it == filters.cend()) {
480 return (*it)->icon();
484QColor KeyFilterManager::bgColor(
const Key &key)
const
486 return get_color(d->filters, key, &KeyFilter::bgColor);
489QColor KeyFilterManager::fgColor(
const Key &key)
const
491 return get_color(d->filters, key, &KeyFilter::fgColor);
494QColor KeyFilterManager::bgColor(
const UserID &userID)
const
496 return get_color(d->filters, userID, &KeyFilter::bgColor);
499QColor KeyFilterManager::fgColor(
const UserID &userID)
const
501 return get_color(d->filters, userID, &KeyFilter::fgColor);
504QIcon KeyFilterManager::icon(
const Key &key)
const
506 const QString icon = get_string(d->filters, key, &KeyFilter::icon);
510Protocol KeyFilterManager::protocol()
const
515class KeyFilterModel::Private
517 friend class KeyFilterModel;
518 std::vector<std::shared_ptr<KeyFilter>> customFilters;
521KeyFilterModel::KeyFilterModel(
QObject *parent)
526 connect(KeyFilterManager::instance(), &KeyFilterManager::alwaysFilterByProtocolChanged,
this, [
this](
auto protocol) {
528 adjustFilters(d->customFilters, protocol);
533void KeyFilterModel::prependCustomFilter(
const std::shared_ptr<KeyFilter> &filter)
536 d->customFilters.insert(d->customFilters.begin(), filter);
537 adjustFilters(d->customFilters, KeyFilterManager::instance()->protocol());
541bool KeyFilterModel::isCustomFilter(
int row)
const
543 return (row >= 0) && (row < int(d->customFilters.size()));
546int KeyFilterModel::rowCount(
const QModelIndex &parent)
const
551int KeyFilterModel::columnCount(
const QModelIndex &parent)
const
565 if (!isCustomFilter(index.
row())) {
566 const int sourceRow = index.
row() - d->customFilters.size();
580 if (row < 0 || row >= rowCount()) {
583 if (row <
int(d->customFilters.size())) {
609 if (isCustomFilter(index.
row())) {
610 const auto filter = d->customFilters[index.
row()];
619 return filter->description();
621 case KeyFilterManager::FilterIdRole:
624 case KeyFilterManager::FilterMatchContextsRole:
627 case KeyFilterManager::FilterRole:
638#include "moc_keyfiltermanager.cpp"
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
Default implementation of key filter class.
An abstract base class key filters.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
const QList< QKeySequence > & reload()
QModelIndex createIndex(int row, int column, const void *ptr) const const
QCoreApplication * instance()
void * internalPointer() const const
bool isValid() const const
const QAbstractItemModel * model() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
virtual QVariant data(const QModelIndex &index, int role) const const override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const const override
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const const override
virtual int rowCount(const QModelIndex &parent) const const override
virtual void setSourceModel(QAbstractItemModel *sourceModel) override
bool isEmpty() const const
QStringList filter(QStringView str, Qt::CaseSensitivity cs) const const
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QVariant fromValue(T &&value)