diff --git a/autotests/abstractkeylistmodeltest.cpp b/autotests/abstractkeylistmodeltest.cpp index 5f3d39d58..61173682b 100644 --- a/autotests/abstractkeylistmodeltest.cpp +++ b/autotests/abstractkeylistmodeltest.cpp @@ -1,164 +1,193 @@ /* autotests/abstractkeylistmodeltest.cpp This file is part of libkleopatra's test suite. SPDX-FileCopyrightText: 2021 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include "abstractkeylistmodeltest.h" #include "kleo/keygroup.h" #include "models/keylistmodel.h" #include #include #include using namespace Kleo; using namespace GpgME; namespace { Key createTestKey(const char *uid) { static int count = 0; count++; gpgme_key_t key; gpgme_key_from_uid(&key, uid); const QByteArray fingerprint = QByteArray::number(count, 16).rightJustified(40, '0'); key->fpr = strdup(fingerprint.constData()); return Key(key, false); } } void AbstractKeyListModelTest::testCreation() { QScopedPointer model(createModel()); QCOMPARE( model->rowCount(), 0 ); } void AbstractKeyListModelTest::testSetKeys() { QScopedPointer model(createModel()); const std::vector keys = { createTestKey("test1@example.net") }; model->setKeys(keys); QCOMPARE( model->rowCount(), 1 ); QVERIFY( model->index(keys[0]).isValid() ); const std::vector otherKeys = { createTestKey("test2@example.net"), createTestKey("test3@example.net") }; model->setKeys(otherKeys); QCOMPARE( model->rowCount(), 2 ); QVERIFY( model->index(otherKeys[0]).isValid() ); QVERIFY( model->index(otherKeys[1]).isValid() ); QVERIFY( !model->index(keys[0]).isValid() ); } void AbstractKeyListModelTest::testSetGroups() { QScopedPointer model(createModel()); const std::vector groups = { - KeyGroup("test1", std::vector()) + KeyGroup("test1", "test1", std::vector(), KeyGroup::UnknownSource) }; model->setGroups(groups); QCOMPARE( model->rowCount(), 1 ); QVERIFY( model->index(groups[0]).isValid() ); const std::vector otherGroups = { - KeyGroup("test2", std::vector()), - KeyGroup("test3", std::vector()) + KeyGroup("test2", "test2", std::vector(), KeyGroup::UnknownSource), + KeyGroup("test3", "test3", std::vector(), KeyGroup::UnknownSource) }; model->setGroups(otherGroups); QCOMPARE( model->rowCount(), 2 ); QVERIFY( model->index(otherGroups[0]).isValid() ); QVERIFY( model->index(otherGroups[1]).isValid() ); QVERIFY( !model->index(groups[0]).isValid() ); } void AbstractKeyListModelTest::testKeys() { QScopedPointer model(createModel()); const Key key = createTestKey("test@example.net"); - const KeyGroup group("test", {key}); + const KeyGroup group("test", "test", {key}, KeyGroup::UnknownSource); model->setKeys({key}); model->setGroups({group}); QCOMPARE( model->rowCount(), 2 ); const QModelIndex keyIndex = model->index(key); QVERIFY( keyIndex.isValid() ); const QModelIndex groupIndex = model->index(group); QVERIFY( groupIndex.isValid() ); { const auto keys = model->keys({}); QCOMPARE( keys.size(), 0 ); } { const auto keys = model->keys({keyIndex}); QCOMPARE( keys.size(), 1 ); QCOMPARE( keys[0].userID(0).addrSpec(), UserID::addrSpecFromString("test@example.net") ); } { // duplicate keys are removed from result const auto keys = model->keys({keyIndex, keyIndex}); QCOMPARE( keys.size(), 1 ); QCOMPARE( keys[0].userID(0).addrSpec(), UserID::addrSpecFromString("test@example.net") ); } { // null keys are removed from result const auto keys = model->keys({groupIndex}); QCOMPARE( keys.size(), 0 ); } } void AbstractKeyListModelTest::testIndex() { QScopedPointer model(createModel()); const Key key = createTestKey("test@example.net"); - const KeyGroup group("test", {key}); + const std::vector groups = { + KeyGroup("test", "test", {key}, KeyGroup::UnknownSource), + KeyGroup("test", "test", {key}, KeyGroup::GnuPGConfig), + KeyGroup("test", "test", {key}, KeyGroup::ApplicationConfig), + KeyGroup("otherId", "test", {key}, KeyGroup::UnknownSource) + }; model->setKeys({key}); - model->setGroups({group}); + model->setGroups(groups); const QModelIndex keyIndex = model->index(0, 0); QVERIFY( keyIndex.isValid() ); QVERIFY( !model->key(keyIndex).isNull() ); const QModelIndex groupIndex = model->index(1, 0); QVERIFY( groupIndex.isValid() ); QVERIFY( !model->group(groupIndex).isNull() ); } +void AbstractKeyListModelTest::testIndexForGroup() +{ + QScopedPointer model(createModel()); + + const Key key = createTestKey("test@example.net"); + const std::vector groups = { + KeyGroup("test", "test", {key}, KeyGroup::UnknownSource), + KeyGroup("test", "test", {key}, KeyGroup::GnuPGConfig), + KeyGroup("test", "test", {key}, KeyGroup::ApplicationConfig), + KeyGroup("otherId", "test", {key}, KeyGroup::UnknownSource) + }; + + model->setKeys({key}); + model->setGroups(groups); + + QSet rows; + for (const KeyGroup &group : groups) { + const QModelIndex groupIndex = model->index(group); + QVERIFY( groupIndex.isValid() ); + rows.insert(groupIndex.row()); + } + QCOMPARE(rows.size(), 4); +} + void AbstractKeyListModelTest::testClear() { QScopedPointer model(createModel()); - const KeyGroup group("test", std::vector()); + const KeyGroup group("test", "test", std::vector(), KeyGroup::UnknownSource); model->setGroups({group}); model->clear(AbstractKeyListModel::Keys); QCOMPARE( model->rowCount(), 1 ); model->clear(AbstractKeyListModel::Groups); QCOMPARE( model->rowCount(), 0 ); } diff --git a/autotests/abstractkeylistmodeltest.h b/autotests/abstractkeylistmodeltest.h index 00e4bbdcd..faeb4d865 100644 --- a/autotests/abstractkeylistmodeltest.h +++ b/autotests/abstractkeylistmodeltest.h @@ -1,36 +1,37 @@ /* autotests/abstractkeylistmodeltest.h This file is part of libkleopatra's test suite. SPDX-FileCopyrightText: 2021 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef ABSTRACTKEYLISTMODELTEST_H #define ABSTRACTKEYLISTMODELTEST_H #include namespace Kleo { class AbstractKeyListModel; } class AbstractKeyListModelTest: public QObject { Q_OBJECT private Q_SLOTS: void testCreation(); void testSetKeys(); void testSetGroups(); void testKeys(); void testIndex(); + void testIndexForGroup(); void testClear(); private: virtual Kleo::AbstractKeyListModel *createModel() = 0; }; #endif // ABSTRACTKEYLISTMODELTEST_H diff --git a/src/kleo/keygroup.cpp b/src/kleo/keygroup.cpp index 465c1495b..352f419d6 100644 --- a/src/kleo/keygroup.cpp +++ b/src/kleo/keygroup.cpp @@ -1,76 +1,90 @@ /* kleo/keygroup.cpp This file is part of libkleopatra, the KDE keymanagement library SPDX-FileCopyrightText: 2021 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include "keygroup.h" #include #include using namespace Kleo; using namespace GpgME; class KeyGroup::Private { public: - explicit Private(const QString &name, const std::vector &keys); + explicit Private(const QString &id, const QString &name, const std::vector &keys, Source source); + QString id; QString name; std::vector keys; + Source source; }; -KeyGroup::Private::Private(const QString &name_, const std::vector &keys_) - : name(name_) +KeyGroup::Private::Private(const QString &id_, const QString &name_, const std::vector &keys_, Source source_) + : id(id_) + , name(name_) , keys(keys_) + , source(source_) { } KeyGroup::KeyGroup() - : KeyGroup(QString(), {}) + : KeyGroup(QString(), QString(), {}, UnknownSource) { } KeyGroup::~KeyGroup() = default; -KeyGroup::KeyGroup(const QString &name, const std::vector &keys) - : d(new Private(name, keys)) +KeyGroup::KeyGroup(const QString &id, const QString &name, const std::vector &keys, Source source) + : d(new Private(id, name, keys, source)) { } KeyGroup::KeyGroup(const KeyGroup &other) : d(new Private(*other.d)) { } KeyGroup &KeyGroup::operator=(const KeyGroup &other) { *d = *other.d; return *this; } KeyGroup::KeyGroup(KeyGroup &&other) = default; KeyGroup &KeyGroup::operator=(KeyGroup &&other) = default; bool KeyGroup::isNull() const { - return !d || d->name.isEmpty(); + return !d || d->id.isEmpty(); +} + +QString KeyGroup::id() const +{ + return d ? d->id : QString(); } QString KeyGroup::name() const { return d ? d->name : QString(); } const std::vector &KeyGroup::keys() const { static const std::vector empty; return d ? d->keys : empty; } + +KeyGroup::Source KeyGroup::source() const +{ + return d ? d->source : UnknownSource; +} diff --git a/src/kleo/keygroup.h b/src/kleo/keygroup.h index b9e053bfe..578482aeb 100644 --- a/src/kleo/keygroup.h +++ b/src/kleo/keygroup.h @@ -1,56 +1,64 @@ /* kleo/keygroup.h This file is part of libkleopatra, the KDE keymanagement library SPDX-FileCopyrightText: 2021 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef LIBKLEO_KEYGROUP_H #define LIBKLEO_KEYGROUP_H #include "kleo_export.h" #include #include class QString; namespace GpgME { class Key; } namespace Kleo { class KLEO_EXPORT KeyGroup { public: + enum Source { + UnknownSource, + ApplicationConfig, + GnuPGConfig, + Tags + }; + KeyGroup(); ~KeyGroup(); - explicit KeyGroup(const QString &name, const std::vector &keys); + explicit KeyGroup(const QString &id, const QString &name, const std::vector &keys, Source source); KeyGroup(const KeyGroup &other); KeyGroup &operator=(const KeyGroup &other); KeyGroup(KeyGroup &&other); KeyGroup &operator=(KeyGroup &&other); bool isNull() const; + QString id() const; QString name() const; - const std::vector &keys() const; + Source source() const; private: class Private; std::unique_ptr d; }; } #endif // LIBKLEO_KEYGROUP_H diff --git a/src/models/keycache.cpp b/src/models/keycache.cpp index 428f7fd4c..308449d6b 100644 --- a/src/models/keycache.cpp +++ b/src/models/keycache.cpp @@ -1,1433 +1,1447 @@ /* -*- mode: c++; c-basic-offset:4 -*- models/keycache.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007, 2008 Klarälvdalens Datakonsult AB SPDX-FileCopyrightText: 2018 Intevation GmbH SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include "keycache.h" #include "keycache_p.h" #include "libkleo_debug.h" #include "kleo/keygroup.h" #include "kleo/predicates.h" #include "kleo/stl_util.h" #include "kleo/dn.h" #include "utils/filesystemwatcher.h" #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include using namespace Kleo; using namespace GpgME; using namespace KMime::Types; static const unsigned int hours2ms = 1000 * 60 * 60; // // // KeyCache // // namespace { make_comparator_str(ByEMail, .first.c_str()); } class KeyCache::Private { friend class ::Kleo::KeyCache; KeyCache *const q; public: explicit Private(KeyCache *qq) : q(qq), m_refreshInterval(1), m_initalized(false), m_pgpOnly(true), m_remarks_enabled(false) { connect(&m_autoKeyListingTimer, &QTimer::timeout, q, [this]() { q->startKeyListing(); }); updateAutoKeyListingTimer(); } ~Private() { if (m_refreshJob) { m_refreshJob->cancel(); } } template < template