diff --git a/src/kleo/keyfiltermanager.cpp b/src/kleo/keyfiltermanager.cpp --- a/src/kleo/keyfiltermanager.cpp +++ b/src/kleo/keyfiltermanager.cpp @@ -37,6 +37,7 @@ #include "stl_util.h" #include "libkleo_debug.h" +#include "utils/formatting.h" #include #include @@ -153,6 +154,57 @@ setMatchContexts(Filtering); } }; + +/* This filter selects only VS-compliant keys if Kleopatra is used in + * CO_DE_VS mode. */ +class DeVsCompliantKeyFilter : public DefaultKeyFilter +{ +public: + DeVsCompliantKeyFilter() + : DefaultKeyFilter() + { + setName(i18n("VS-compliant Certificates")); + setId(QStringLiteral("vs-compliant-certificates")); + setSpecificity(UINT_MAX - 5); // overly high for ordering + } + bool matches (const Key &key, MatchContexts contexts) const override + { + return (contexts & Filtering) && Formatting::isKeyDeVs(key); + } +}; + +/* This filter gives VS-compliant keys a light green background if + * Kleopatra is used in CO_DE_VS mode. */ +class DeVsCompliantKeyAppearanceFilter : public DefaultKeyFilter +{ +public: + DeVsCompliantKeyAppearanceFilter() + : DefaultKeyFilter() + { + setBgColor(QColor("lightgreen")); + } + bool matches (const Key &key, MatchContexts contexts) const override + { + return (contexts & Appearance) && Formatting::isKeyDeVs(key); + } +}; + +/* This filter gives non-VS-compliant keys a light red background if + * Kleopatra is used in CO_DE_VS mode. */ +class NotDeVsCompliantKeyAppearanceFilter : public DefaultKeyFilter +{ +public: + NotDeVsCompliantKeyAppearanceFilter() + : DefaultKeyFilter() + { + setBgColor(QColor("lightpink")); + } + bool matches (const Key &key, MatchContexts contexts) const override + { + return (contexts & Appearance) && ! Formatting::isKeyDeVs(key); + } +}; + } static std::vector> defaultFilters() @@ -164,20 +216,36 @@ result.push_back(std::shared_ptr(new FullCertificatesKeyFilter)); result.push_back(std::shared_ptr(new OtherCertificatesKeyFilter)); result.push_back(std::shared_ptr(new AllCertificatesKeyFilter)); + if (Formatting::complianceMode() == QStringLiteral("de-vs")) { + result.push_back(std::shared_ptr(new DeVsCompliantKeyFilter)); + } + return result; +} + +static std::vector> defaultAppearanceFilters() +{ + std::vector > result; + if (Formatting::complianceMode() == QStringLiteral("de-vs")) { + result.reserve(2); + result.push_back(std::shared_ptr(new DeVsCompliantKeyAppearanceFilter)); + result.push_back(std::shared_ptr(new NotDeVsCompliantKeyAppearanceFilter)); + } return result; } class KeyFilterManager::Private { public: - Private() : filters(), model(this) {} + Private() : filters(), appearanceFilters(), model(this) {} void clear() { filters.clear(); + appearanceFilters.clear(); model.reset(); } std::vector> filters; + std::vector> appearanceFilters; Model model; }; @@ -251,6 +319,7 @@ d->clear(); d->filters = defaultFilters(); + d->appearanceFilters = defaultAppearanceFilters(); KSharedConfigPtr config = KSharedConfig::openConfig(QStringLiteral("libkleopatrarc")); const QStringList groups = config->groupList().filter(QRegularExpression(QStringLiteral("^Key Filter #\\d+$"))); @@ -324,25 +393,35 @@ } } -QFont KeyFilterManager::font(const Key &key, const QFont &baseFont) const +static KeyFilter::FontDescription get_fontdescription(const std::vector> &filters, const Key &key, const KeyFilter::FontDescription &initial) { - return kdtools::accumulate_if(d->filters.begin(), d->filters.end(), + return kdtools::accumulate_if(filters.begin(), filters.end(), [&key](const std::shared_ptr &filter) { return filter->matches(key, KeyFilter::Appearance); }, - KeyFilter::FontDescription(), + initial, [](const KeyFilter::FontDescription &lhs, const std::shared_ptr &rhs) { return lhs.resolve(rhs->fontDescription()); - }).font(baseFont); + }); +} + +QFont KeyFilterManager::font(const Key &key, const QFont &baseFont) const +{ + KeyFilter::FontDescription fd; + + fd = get_fontdescription(d->appearanceFilters, key, KeyFilter::FontDescription()); + fd = get_fontdescription(d->filters, key, fd); + + return fd.font(baseFont); } static QColor get_color(const std::vector> &filters, const Key &key, QColor(KeyFilter::*fun)() const) { const auto it = std::find_if(filters.cbegin(), filters.cend(), [&fun, &key](const std::shared_ptr &filter) { return filter->matches(key, KeyFilter::Appearance) - && !(filter.get()->*fun)().isValid(); + && (filter.get()->*fun)().isValid(); }); if (it == filters.cend()) { return QColor(); @@ -367,17 +446,34 @@ QColor KeyFilterManager::bgColor(const Key &key) const { - return get_color(d->filters, key, &KeyFilter::bgColor); + QColor color; + + color = get_color(d->appearanceFilters, key, &KeyFilter::bgColor); + if (! color.isValid()) + color = get_color(d->filters, key, &KeyFilter::bgColor); + + return color; } QColor KeyFilterManager::fgColor(const Key &key) const { - return get_color(d->filters, key, &KeyFilter::fgColor); + QColor color; + + color = get_color(d->appearanceFilters, key, &KeyFilter::fgColor); + if (! color.isValid()) + color = get_color(d->filters, key, &KeyFilter::fgColor); + + return color; } QIcon KeyFilterManager::icon(const Key &key) const { - const QString icon = get_string(d->filters, key, &KeyFilter::icon); + QString icon; + + icon = get_string(d->appearanceFilters, key, &KeyFilter::icon); + if (icon.isEmpty()) + icon = get_string(d->filters, key, &KeyFilter::icon); + return icon.isEmpty() ? QIcon() : QIcon::fromTheme(icon); } diff --git a/src/utils/formatting.h b/src/utils/formatting.h --- a/src/utils/formatting.h +++ b/src/utils/formatting.h @@ -137,6 +137,9 @@ * mode is not set. */ KLEO_EXPORT QString complianceMode(); +/* Is the given key in compliance with CO_DE_VS? */ +KLEO_EXPORT bool isKeyDeVs(const GpgME::Key &key); + /* A sentence if the key confirms to the current compliance mode */ KLEO_EXPORT QString complianceStringForKey(const GpgME::Key &key); } diff --git a/src/utils/formatting.cpp b/src/utils/formatting.cpp --- a/src/utils/formatting.cpp +++ b/src/utils/formatting.cpp @@ -318,13 +318,13 @@ } if (fullyTrusted == key.numUserIDs()) { result = i18n("All identities are certified."); - const auto compliance = complianceStringForKey(key); - if (!compliance.isEmpty()) { - result += QStringLiteral("
") + compliance; - } } else { result = i18np("One identity is not certified.", "%1 identities are not certified.", key.numUserIDs() - fullyTrusted); } + const auto compliance = complianceStringForKey(key); + if (!compliance.isEmpty()) { + result += QStringLiteral("
") + compliance; + } } else { result = i18n("The validity cannot be checked at the moment."); @@ -834,34 +834,35 @@ return entry->stringValue(); } -QString Formatting::complianceStringForKey(const GpgME::Key &key) +bool Formatting::isKeyDeVs(const GpgME::Key &key) { #ifdef GPGME_HAS_KEY_IS_DEVS + for (const auto &sub: key.subkeys()) { + if (sub.isExpired() || sub.isRevoked()) { + // Ignore old subkeys + continue; + } + if (!sub.isDeVs()) + return false; + } + return true; +#else + return false; +#endif +} + +QString Formatting::complianceStringForKey(const GpgME::Key &key) +{ // There will likely be more in the future for other institutions // for now we only have DE-VS if (complianceMode() == QStringLiteral("de-vs")) { - bool compliant = false; - for (const auto &sub: key.subkeys()) { - if (sub.isExpired() || sub.isRevoked()) { - // Ignore old subkeys - continue; - } - if (!sub.isDeVs()) { - compliant = false; - break; - } - compliant = true; - } - if (compliant) { + if (isKeyDeVs(key)) { return i18nc("VS-conforming is a German standard for restricted documents. For which special restrictions about algorithms apply. The string describes if a key is compliant with that..", "May be used for VS-compliant communication."); } else { return i18nc("VS-conforming is a German standard for restricted documents. For which special restrictions about algorithms apply. The string describes if a key is compliant to that..", "May not be used for VS-compliant communication."); } } -#else - Q_UNUSED(key); -#endif return QString(); }