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)
 
   72        : QAbstractListModel(nullptr)
 
   73        , m_keyFilterManagerPrivate(p)
 
   77    int rowCount(
const QModelIndex &) 
const override;
 
   78    QVariant data(
const QModelIndex &idx, 
int role) 
const override;
 
   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();
 
  341    const QStringList groups = config->groupList().filter(QRegularExpression(QStringLiteral(
"^Key Filter #\\d+$")));
 
  342    const bool ignoreDeVs = !DeVSCompliance::isCompliant();
 
  343    for (QStringList::const_iterator it = groups.
begin(); it != groups.
end(); ++it) {
 
  344        const KConfigGroup cfg(config, *it);
 
  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();
 
  358QAbstractItemModel *KeyFilterManager::model()
 const 
  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());
 
  394        return QModelIndex();
 
  398int Model::rowCount(
const QModelIndex &)
 const 
  400    return m_keyFilterManagerPrivate->filters.size();
 
  403QVariant Model::data(
const QModelIndex &idx, 
int role)
 const 
  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);
 
  515    return icon.isEmpty() ? QIcon() : QIcon::fromTheme(icon);
 
  518Protocol KeyFilterManager::protocol()
 const 
  523class KeyFilterModel::Private
 
  525    friend class KeyFilterModel;
 
  526    std::vector<std::shared_ptr<KeyFilter>> customFilters;
 
  529KeyFilterModel::KeyFilterModel(QObject *parent)
 
  530    : QSortFilterProxyModel(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 
  570QModelIndex KeyFilterModel::mapToSource(
const QModelIndex &index)
 const 
  572    if (!index.isValid()) {
 
  575    if (!isCustomFilter(index.row())) {
 
  576        const int sourceRow = index.row() - d->customFilters.size();
 
  582QModelIndex KeyFilterModel::mapFromSource(
const QModelIndex &source_index)
 const 
  588QModelIndex KeyFilterModel::index(
int row, 
int column, 
const QModelIndex &parent)
 const 
  590    if (row < 0 || row >= rowCount()) {
 
  593    if (row < 
int(d->customFilters.size())) {
 
  601Qt::ItemFlags KeyFilterModel::flags(
const QModelIndex &index)
 const 
  613QVariant KeyFilterModel::data(
const QModelIndex &index, 
int role)
 const 
  615    if (!index.isValid()) {
 
  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
 
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
 
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
 
QVariant fromValue(T &&value)