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(AnyMatchContext);
119 FullCertificatesKeyFilter()
123 setValidity(IsAtLeast);
124 setValidityReferenceLevel(UserID::Full);
125 setSpecificity(UINT_MAX - 4);
128 setName(
i18nc(
"Certified Certificates",
"Certified"));
129 setDescription(
i18n(
"Certificates for which the primary user ID is certified (except disabled ones)"));
130 setId(QStringLiteral(
"trusted-certificates"));
131 setMatchContexts(Filtering);
138 OtherCertificatesKeyFilter()
141 setHasSecret(NotSet);
142 setValidity(IsAtMost);
143 setValidityReferenceLevel(UserID::Marginal);
144 setSpecificity(UINT_MAX - 6);
147 setName(
i18nc(
"Not Certified Certificates",
"Not Certified"));
148 setDescription(
i18n(
"Certificates for which the primary user ID is not certified (except disabled ones)"));
149 setId(QStringLiteral(
"other-certificates"));
150 setMatchContexts(Filtering);
159 UncertifiedOpenPGPKeysFilter()
162 setSpecificity(UINT_MAX - 7);
163 setName(
i18nc(
"Certificates to certify by the user",
"To Certify"));
164 setDescription(
i18n(
"Certificates that are not fully certified and that you may want to certify yourself (except disabled ones)"));
165 setId(QStringLiteral(
"not-certified-certificates"));
167 setMatchContexts(Filtering);
172 bool matches(
const Key &key, MatchContexts contexts)
const override
174 return DefaultKeyFilter::matches(key, contexts) && !Kleo::allUserIDsHaveFullValidity(key);
176 bool matches(
const UserID &userID, MatchContexts contexts)
const override
178 return DefaultKeyFilter::matches(userID.parent(), contexts) && userID.validity() < UserID::Full;
190 setSpecificity(UINT_MAX - 5);
192 setName(
i18nc(
"Not Fully Certified Certificates",
"Not Fully Certified"));
193 setDescription(
i18n(
"Certificates for which not all user IDs are certified (except disabled ones)"));
194 setId(QStringLiteral(
"not-validated-certificates"));
195 setMatchContexts(Filtering);
198 bool matches(
const Key &key, MatchContexts contexts)
const override
200 return DefaultKeyFilter::matches(key, contexts) && !Kleo::allUserIDsHaveFullValidity(key);
202 bool matches(
const UserID &userID, MatchContexts contexts)
const override
204 return DefaultKeyFilter::matches(userID.parent(), contexts) && userID.validity() < UserID::Full;
213 KeyFullyCertifiedFilter()
216 setSpecificity(UINT_MAX - 3);
217 setName(
i18nc(
"Fully Certified Certificates",
"Fully Certified"));
218 setDescription(
i18n(
"Certificates for which all user IDs are certified (except disabled ones)"));
219 setId(QStringLiteral(
"full-certificates"));
220 setMatchContexts(Filtering);
223 bool matches(
const Key &key, MatchContexts contexts)
const override
225 return DefaultKeyFilter::matches(key, contexts) && Kleo::allUserIDsHaveFullValidity(key);
227 bool matches(
const UserID &userID, MatchContexts contexts)
const override
229 return DefaultKeyFilter::matches(userID.parent(), contexts) && userID.validity() >= UserID::Full;
233static std::vector<std::shared_ptr<KeyFilter>> defaultFilters()
236 std::shared_ptr<KeyFilter>(
new MyCertificatesKeyFilter),
237 std::shared_ptr<KeyFilter>(
new FullCertificatesKeyFilter),
238 std::shared_ptr<KeyFilter>(
new OtherCertificatesKeyFilter),
239 std::shared_ptr<KeyFilter>(
new AllCertificatesKeyFilter),
240 std::shared_ptr<KeyFilter>(
new UncertifiedOpenPGPKeysFilter),
241 std::shared_ptr<KeyFilter>(
new KeyFullyCertifiedFilter),
242 std::shared_ptr<KeyFilter>(
new KeyNotValidFilter),
246class KeyFilterManager::Private
259 std::vector<std::shared_ptr<KeyFilter>> filters;
261 GpgME::Protocol protocol = GpgME::UnknownProtocol;
264KeyFilterManager *KeyFilterManager::mSelf =
nullptr;
266KeyFilterManager::KeyFilterManager(
QObject *parent)
278KeyFilterManager::~KeyFilterManager()
282 d->model.beginResetModel();
284 d->model.endResetModel();
288KeyFilterManager *KeyFilterManager::instance()
291 mSelf =
new KeyFilterManager();
296void KeyFilterManager::alwaysFilterByProtocol(GpgME::Protocol protocol)
298 if (protocol != d->protocol) {
299 d->protocol = protocol;
301 Q_EMIT alwaysFilterByProtocolChanged(protocol);
305const std::shared_ptr<KeyFilter> &KeyFilterManager::filterMatching(
const Key &key,
KeyFilter::MatchContexts contexts)
const
307 const auto it = std::find_if(d->filters.cbegin(), d->filters.cend(), [&key, contexts](
const std::shared_ptr<KeyFilter> &filter) {
308 return filter->matches(key, contexts);
310 if (it != d->filters.cend()) {
313 static const std::shared_ptr<KeyFilter> null;
317std::vector<std::shared_ptr<KeyFilter>> KeyFilterManager::filtersMatching(
const Key &key,
KeyFilter::MatchContexts contexts)
const
319 std::vector<std::shared_ptr<KeyFilter>> result;
320 result.reserve(d->filters.size());
321 std::remove_copy_if(d->filters.begin(), d->filters.end(), std::back_inserter(result), [&key, contexts](
const std::shared_ptr<KeyFilter> &filter) {
322 return !filter->matches(key, contexts);
329static const auto byDecreasingSpecificity = [](
const std::shared_ptr<KeyFilter> &lhs,
const std::shared_ptr<KeyFilter> &rhs) {
330 return lhs->specificity() > rhs->specificity();
334void KeyFilterManager::reload()
336 d->model.beginResetModel();
339 d->filters = defaultFilters();
343 const bool ignoreDeVs = !DeVSCompliance::isCompliant();
346 if (cfg.hasKey(
"is-de-vs") && ignoreDeVs) {
350 d->filters.push_back(std::shared_ptr<KeyFilter>(
new KConfigBasedKeyFilter(cfg)));
352 std::stable_sort(d->filters.begin(), d->filters.end(), byDecreasingSpecificity);
354 adjustFilters(d->filters, d->protocol);
355 d->model.endResetModel();
356 qCDebug(LIBKLEO_LOG) <<
"KeyFilterManager::" << __func__ <<
"final filter count is" << d->filters.size();
364const std::shared_ptr<KeyFilter> &KeyFilterManager::keyFilterByID(
const QString &
id)
const
366 const auto it = std::find_if(d->filters.begin(), d->filters.end(), [
id](
const std::shared_ptr<KeyFilter> &filter) {
367 return filter->id() == id;
369 if (it != d->filters.end()) {
372 static const std::shared_ptr<KeyFilter> null;
376const std::shared_ptr<KeyFilter> &KeyFilterManager::fromModelIndex(
const QModelIndex &idx)
const
378 if (!idx.
isValid() || idx.
model() != &d->model || idx.
row() < 0 ||
static_cast<unsigned>(idx.
row()) >= d->filters.size()) {
379 static const std::shared_ptr<KeyFilter> null;
382 return d->filters[idx.
row()];
385QModelIndex KeyFilterManager::toModelIndex(
const std::shared_ptr<KeyFilter> &kf)
const
390 const auto pair = std::equal_range(d->filters.cbegin(), d->filters.cend(), kf, byDecreasingSpecificity);
391 const auto it = std::find(pair.first, pair.second, kf);
392 if (it != pair.second) {
393 return d->model.index(it - d->filters.begin());
401 return m_keyFilterManagerPrivate->filters.size();
406 if (!idx.
isValid() || idx.
model() !=
this || idx.
row() < 0 ||
static_cast<unsigned>(idx.
row()) > m_keyFilterManagerPrivate->filters.size()) {
410 const auto filter = m_keyFilterManagerPrivate->filters[idx.
row()];
419 return filter->description();
421 case KeyFilterManager::FilterIdRole:
424 case KeyFilterManager::FilterMatchContextsRole:
427 case KeyFilterManager::FilterRole:
435static KeyFilter::FontDescription
436get_fontdescription(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const Key &key,
const KeyFilter::FontDescription &initial)
438 return kdtools::accumulate_if(
441 [&key](
const std::shared_ptr<KeyFilter> &filter) {
442 return filter->matches(key, KeyFilter::Appearance);
445 [](
const KeyFilter::FontDescription &lhs,
const std::shared_ptr<KeyFilter> &rhs) {
446 return lhs.resolve(rhs->fontDescription());
450QFont KeyFilterManager::font(
const Key &key,
const QFont &baseFont)
const
452 const KeyFilter::FontDescription fd = get_fontdescription(d->filters, key, KeyFilter::FontDescription());
454 return fd.font(baseFont);
457static QColor get_color(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const Key &key,
QColor (
KeyFilter::*fun)()
const)
459 const auto it = std::find_if(filters.cbegin(), filters.cend(), [&fun, &key](
const std::shared_ptr<KeyFilter> &filter) {
460 return filter->matches(key, KeyFilter::Appearance) && (filter.get()->*fun)().isValid();
462 if (it == filters.cend()) {
465 return (it->get()->*fun)();
469static QColor get_color(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const UserID &userID,
QColor (
KeyFilter::*fun)()
const)
471 const auto it = std::find_if(filters.cbegin(), filters.cend(), [&fun, &userID](
const std::shared_ptr<KeyFilter> &filter) {
472 return filter->matches(userID, KeyFilter::Appearance) && (filter.get()->*fun)().isValid();
474 if (it == filters.cend()) {
477 return (it->get()->*fun)();
481static QString get_string(
const std::vector<std::shared_ptr<KeyFilter>> &filters,
const Key &key,
QString (
KeyFilter::*fun)()
const)
483 const auto it = std::find_if(filters.cbegin(), filters.cend(), [&fun, &key](
const std::shared_ptr<KeyFilter> &filter) {
484 return filter->matches(key, KeyFilter::Appearance) && !(filter.get()->*fun)().isEmpty();
486 if (it == filters.cend()) {
489 return (*it)->icon();
493QColor KeyFilterManager::bgColor(
const Key &key)
const
495 return get_color(d->filters, key, &KeyFilter::bgColor);
498QColor KeyFilterManager::fgColor(
const Key &key)
const
500 return get_color(d->filters, key, &KeyFilter::fgColor);
503QColor KeyFilterManager::bgColor(
const UserID &userID)
const
505 return get_color(d->filters, userID, &KeyFilter::bgColor);
508QColor KeyFilterManager::fgColor(
const UserID &userID)
const
510 return get_color(d->filters, userID, &KeyFilter::fgColor);
513QIcon KeyFilterManager::icon(
const Key &key)
const
515 const QString icon = get_string(d->filters, key, &KeyFilter::icon);
519Protocol KeyFilterManager::protocol()
const
524class KeyFilterModel::Private
526 friend class KeyFilterModel;
527 std::vector<std::shared_ptr<KeyFilter>> customFilters;
530KeyFilterModel::KeyFilterModel(
QObject *parent)
535 connect(KeyFilterManager::instance(), &KeyFilterManager::alwaysFilterByProtocolChanged,
this, [
this](
auto protocol) {
537 adjustFilters(d->customFilters, protocol);
542void KeyFilterModel::prependCustomFilter(
const std::shared_ptr<KeyFilter> &filter)
545 d->customFilters.insert(d->customFilters.begin(), filter);
546 adjustFilters(d->customFilters, KeyFilterManager::instance()->protocol());
550bool KeyFilterModel::isCustomFilter(
int row)
const
552 return (row >= 0) && (row < int(d->customFilters.size()));
555int KeyFilterModel::rowCount(
const QModelIndex &parent)
const
560int KeyFilterModel::columnCount(
const QModelIndex &parent)
const
574 if (!isCustomFilter(index.
row())) {
575 const int sourceRow = index.
row() - d->customFilters.size();
589 if (row < 0 || row >= rowCount()) {
592 if (row <
int(d->customFilters.size())) {
618 if (isCustomFilter(index.
row())) {
619 const auto filter = d->customFilters[index.
row()];
628 return filter->description();
630 case KeyFilterManager::FilterIdRole:
633 case KeyFilterManager::FilterMatchContextsRole:
636 case KeyFilterManager::FilterRole:
647#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)