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 (except disabled ones)"));
92 setId(QStringLiteral(
"all-certificates"));
93 setMatchContexts(Filtering);
101 MyCertificatesKeyFilter()
105 setSpecificity(UINT_MAX - 2);
108 setName(
i18nc(
"My own Certificates",
"My Own"));
109 setDescription(
i18n(
"My own certificates (except disabled ones)"));
110 setId(QStringLiteral(
"my-certificates"));
111 setMatchContexts(Filtering);
118 FullCertificatesKeyFilter()
122 setValidity(IsAtLeast);
123 setValidityReferenceLevel(UserID::Full);
124 setSpecificity(UINT_MAX - 4);
127 setName(
i18nc(
"Certified Certificates",
"Certified"));
128 setDescription(
i18n(
"Certificates for which the primary user ID is certified (except disabled ones)"));
129 setId(QStringLiteral(
"trusted-certificates"));
130 setMatchContexts(Filtering);
137 OtherCertificatesKeyFilter()
140 setHasSecret(NotSet);
141 setValidity(IsAtMost);
142 setValidityReferenceLevel(UserID::Marginal);
143 setSpecificity(UINT_MAX - 6);
146 setName(
i18nc(
"Not Certified Certificates",
"Not Certified"));
147 setDescription(
i18n(
"Certificates for which the primary user ID is not certified (except disabled ones)"));
148 setId(QStringLiteral(
"other-certificates"));
149 setMatchContexts(Filtering);
158 UncertifiedOpenPGPKeysFilter()
161 setSpecificity(UINT_MAX - 7);
162 setName(
i18nc(
"Certificates to certify by the user",
"To Certify"));
163 setDescription(
i18n(
"Certificates that are not fully certified and that you may want to certify yourself (except disabled ones)"));
164 setId(QStringLiteral(
"not-certified-certificates"));
166 setMatchContexts(Filtering);
171 bool matches(
const Key &key, MatchContexts contexts)
const override
173 return DefaultKeyFilter::matches(key, contexts) && !Kleo::allUserIDsHaveFullValidity(key);
175 bool matches(
const UserID &userID, MatchContexts contexts)
const override
177 return DefaultKeyFilter::matches(userID.parent(), contexts) && userID.validity() < UserID::Full;
189 setSpecificity(UINT_MAX - 5);
191 setName(
i18nc(
"Not Fully Certified Certificates",
"Not Fully Certified"));
192 setDescription(
i18n(
"Certificates for which not all user IDs are certified (except disabled ones)"));
193 setId(QStringLiteral(
"not-validated-certificates"));
194 setMatchContexts(Filtering);
197 bool matches(
const Key &key, MatchContexts contexts)
const override
199 return DefaultKeyFilter::matches(key, contexts) && !Kleo::allUserIDsHaveFullValidity(key);
201 bool matches(
const UserID &userID, MatchContexts contexts)
const override
203 return DefaultKeyFilter::matches(userID.parent(), contexts) && userID.validity() < UserID::Full;
212 KeyFullyCertifiedFilter()
215 setSpecificity(UINT_MAX - 3);
216 setName(
i18nc(
"Fully Certified Certificates",
"Fully Certified"));
217 setDescription(
i18n(
"Certificates for which all user IDs are certified (except disabled ones)"));
218 setId(QStringLiteral(
"full-certificates"));
219 setMatchContexts(Filtering);
222 bool matches(
const Key &key, MatchContexts contexts)
const override
224 return DefaultKeyFilter::matches(key, contexts) && Kleo::allUserIDsHaveFullValidity(key);
226 bool matches(
const UserID &userID, MatchContexts contexts)
const override
228 return DefaultKeyFilter::matches(userID.parent(), contexts) && userID.validity() >= UserID::Full;
232static std::vector<std::shared_ptr<KeyFilter>> defaultFilters()
235 std::shared_ptr<KeyFilter>(
new MyCertificatesKeyFilter),
236 std::shared_ptr<KeyFilter>(
new FullCertificatesKeyFilter),
237 std::shared_ptr<KeyFilter>(
new OtherCertificatesKeyFilter),
238 std::shared_ptr<KeyFilter>(
new AllCertificatesKeyFilter),
239 std::shared_ptr<KeyFilter>(
new UncertifiedOpenPGPKeysFilter),
240 std::shared_ptr<KeyFilter>(
new KeyFullyCertifiedFilter),
241 std::shared_ptr<KeyFilter>(
new KeyNotValidFilter),
245class KeyFilterManager::Private
258 std::vector<std::shared_ptr<KeyFilter>> filters;
260 GpgME::Protocol protocol = GpgME::UnknownProtocol;
263KeyFilterManager *KeyFilterManager::mSelf =
nullptr;
265KeyFilterManager::KeyFilterManager(
QObject *parent)
277KeyFilterManager::~KeyFilterManager()
281 d->model.beginResetModel();
283 d->model.endResetModel();
287KeyFilterManager *KeyFilterManager::instance()
290 mSelf =
new KeyFilterManager();
295void KeyFilterManager::alwaysFilterByProtocol(GpgME::Protocol protocol)
297 if (protocol != d->protocol) {
298 d->protocol = protocol;
300 Q_EMIT alwaysFilterByProtocolChanged(protocol);
304const std::shared_ptr<KeyFilter> &KeyFilterManager::filterMatching(
const Key &key,
KeyFilter::MatchContexts contexts)
const
306 const auto it = std::find_if(d->filters.cbegin(), d->filters.cend(), [&key, contexts](
const std::shared_ptr<KeyFilter> &filter) {
307 return filter->matches(key, contexts);
309 if (it != d->filters.cend()) {
312 static const std::shared_ptr<KeyFilter> null;
316std::vector<std::shared_ptr<KeyFilter>> KeyFilterManager::filtersMatching(
const Key &key,
KeyFilter::MatchContexts contexts)
const
318 std::vector<std::shared_ptr<KeyFilter>> result;
319 result.reserve(d->filters.size());
320 std::remove_copy_if(d->filters.begin(), d->filters.end(), std::back_inserter(result), [&key, contexts](
const std::shared_ptr<KeyFilter> &filter) {
321 return !filter->matches(key, contexts);
328static const auto byDecreasingSpecificity = [](
const std::shared_ptr<KeyFilter> &lhs,
const std::shared_ptr<KeyFilter> &rhs) {
329 return lhs->specificity() > rhs->specificity();
333void KeyFilterManager::reload()
335 d->model.beginResetModel();
338 d->filters = defaultFilters();
342 const bool ignoreDeVs = !DeVSCompliance::isCompliant();
345 if (cfg.hasKey(
"is-de-vs") && ignoreDeVs) {
349 d->filters.push_back(std::shared_ptr<KeyFilter>(
new KConfigBasedKeyFilter(cfg)));
351 std::stable_sort(d->filters.begin(), d->filters.end(), byDecreasingSpecificity);
353 adjustFilters(d->filters, d->protocol);
354 d->model.endResetModel();
355 qCDebug(LIBKLEO_LOG) <<
"KeyFilterManager::" << __func__ <<
"final filter count is" << d->filters.size();
363const std::shared_ptr<KeyFilter> &KeyFilterManager::keyFilterByID(
const QString &
id)
const
365 const auto it = std::find_if(d->filters.begin(), d->filters.end(), [
id](
const std::shared_ptr<KeyFilter> &filter) {
366 return filter->id() == id;
368 if (it != d->filters.end()) {
371 static const std::shared_ptr<KeyFilter> null;
375const std::shared_ptr<KeyFilter> &KeyFilterManager::fromModelIndex(
const QModelIndex &idx)
const
377 if (!idx.
isValid() || idx.
model() != &d->model || idx.
row() < 0 ||
static_cast<unsigned>(idx.
row()) >= d->filters.size()) {
378 static const std::shared_ptr<KeyFilter> null;
381 return d->filters[idx.
row()];
384QModelIndex KeyFilterManager::toModelIndex(
const std::shared_ptr<KeyFilter> &kf)
const
389 const auto pair = std::equal_range(d->filters.cbegin(), d->filters.cend(), kf, byDecreasingSpecificity);
390 const auto it = std::find(pair.first, pair.second, kf);
391 if (it != pair.second) {
392 return d->model.index(it - d->filters.begin());
400 return m_keyFilterManagerPrivate->filters.size();
405 if (!idx.
isValid() || idx.
model() !=
this || idx.
row() < 0 ||
static_cast<unsigned>(idx.
row()) > m_keyFilterManagerPrivate->filters.size()) {
409 const auto filter = m_keyFilterManagerPrivate->filters[idx.
row()];
418 return filter->description();
420 case KeyFilterManager::FilterIdRole:
423 case KeyFilterManager::FilterMatchContextsRole:
426 case KeyFilterManager::FilterRole:
434static KeyFilter::FontDescription
435get_fontdescription(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const Key &key,
const KeyFilter::FontDescription &initial)
437 return kdtools::accumulate_if(
440 [&key](
const std::shared_ptr<KeyFilter> &filter) {
441 return filter->matches(key, KeyFilter::Appearance);
444 [](
const KeyFilter::FontDescription &lhs,
const std::shared_ptr<KeyFilter> &rhs) {
445 return lhs.resolve(rhs->fontDescription());
449QFont KeyFilterManager::font(
const Key &key,
const QFont &baseFont)
const
451 const KeyFilter::FontDescription fd = get_fontdescription(d->filters, key, KeyFilter::FontDescription());
453 return fd.font(baseFont);
456static QColor get_color(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const Key &key,
QColor (
KeyFilter::*fun)()
const)
458 const auto it = std::find_if(filters.cbegin(), filters.cend(), [&fun, &key](
const std::shared_ptr<KeyFilter> &filter) {
459 return filter->matches(key, KeyFilter::Appearance) && (filter.get()->*fun)().isValid();
461 if (it == filters.cend()) {
464 return (it->get()->*fun)();
468static QColor get_color(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const UserID &userID,
QColor (
KeyFilter::*fun)()
const)
470 const auto it = std::find_if(filters.cbegin(), filters.cend(), [&fun, &userID](
const std::shared_ptr<KeyFilter> &filter) {
471 return filter->matches(userID, KeyFilter::Appearance) && (filter.get()->*fun)().isValid();
473 if (it == filters.cend()) {
476 return (it->get()->*fun)();
480static QString get_string(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const Key &key,
QString (
KeyFilter::*fun)()
const)
482 const auto it = std::find_if(filters.cbegin(), filters.cend(), [&fun, &key](
const std::shared_ptr<KeyFilter> &filter) {
483 return filter->matches(key, KeyFilter::Appearance) && !(filter.get()->*fun)().isEmpty();
485 if (it == filters.cend()) {
488 return (*it)->icon();
492QColor KeyFilterManager::bgColor(
const Key &key)
const
494 return get_color(d->filters, key, &KeyFilter::bgColor);
497QColor KeyFilterManager::fgColor(
const Key &key)
const
499 return get_color(d->filters, key, &KeyFilter::fgColor);
502QColor KeyFilterManager::bgColor(
const UserID &userID)
const
504 return get_color(d->filters, userID, &KeyFilter::bgColor);
507QColor KeyFilterManager::fgColor(
const UserID &userID)
const
509 return get_color(d->filters, userID, &KeyFilter::fgColor);
512QIcon KeyFilterManager::icon(
const Key &key)
const
514 const QString icon = get_string(d->filters, key, &KeyFilter::icon);
518Protocol KeyFilterManager::protocol()
const
523class KeyFilterModel::Private
525 friend class KeyFilterModel;
526 std::vector<std::shared_ptr<KeyFilter>> customFilters;
529KeyFilterModel::KeyFilterModel(
QObject *parent)
534 connect(KeyFilterManager::instance(), &KeyFilterManager::alwaysFilterByProtocolChanged,
this, [
this](
auto protocol) {
536 adjustFilters(d->customFilters, protocol);
541KeyFilterModel::~KeyFilterModel() =
default;
543void KeyFilterModel::prependCustomFilter(
const std::shared_ptr<KeyFilter> &filter)
546 d->customFilters.insert(d->customFilters.begin(), filter);
547 adjustFilters(d->customFilters, KeyFilterManager::instance()->protocol());
551bool KeyFilterModel::isCustomFilter(
int row)
const
553 return (row >= 0) && (row < int(d->customFilters.size()));
556int KeyFilterModel::rowCount(
const QModelIndex &parent)
const
561int KeyFilterModel::columnCount(
const QModelIndex &parent)
const
575 if (!isCustomFilter(index.
row())) {
576 const int sourceRow = index.
row() - d->customFilters.size();
590 if (row < 0 || row >= rowCount()) {
593 if (row <
int(d->customFilters.size())) {
619 if (isCustomFilter(index.
row())) {
620 const auto filter = d->customFilters[index.
row()];
629 return filter->description();
631 case KeyFilterManager::FilterIdRole:
634 case KeyFilterManager::FilterMatchContextsRole:
637 case KeyFilterManager::FilterRole:
648#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)