Libkleo

useridproxymodel.cpp
1/*
2 SPDX-FileCopyrightText: 2024 g10 Code GmbH
3 SPDX-FileContributor: Tobias Fella <tobias.fella@gnupg.com>
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "useridproxymodel.h"
8
9#include "keylist.h"
10#include "keylistmodel.h"
11#include "kleo/keyfiltermanager.h"
12#include "utils/algorithm.h"
13#include "utils/formatting.h"
14#include "utils/systeminfo.h"
15
16#include <gpgme++/global.h>
17
18#include <QColor>
19
20#include <variant>
21
22using namespace Kleo;
23
24class UserIDProxyModel::Private
25{
26public:
27 Private(UserIDProxyModel *qq);
28 void loadUserIDs();
30 UserIDProxyModel *q;
31 QList<int> mSourceIndices;
32};
33
34void UserIDProxyModel::Private::loadUserIDs()
35{
36 q->beginResetModel();
37 auto oldIndicesSize = mSourceIndices.size();
38 mIds.clear();
39 mSourceIndices.clear();
40 mIds.reserve(q->sourceModel()->rowCount());
41 mSourceIndices.reserve(std::max(mIds.size(), oldIndicesSize));
42 for (auto i = 0; i < q->sourceModel()->rowCount(); ++i) {
43 const auto key = q->sourceModel()->index(i, 0).data(KeyList::KeyRole).value<GpgME::Key>();
44 if (key.isNull()) {
45 mIds += q->sourceModel()->index(i, 0).data(KeyList::GroupRole).value<KeyGroup>();
46 mSourceIndices.push_back(i);
47 } else if (key.protocol() == GpgME::OpenPGP) {
48 for (const auto &userID : key.userIDs()) {
49 mIds += userID;
50 mSourceIndices.push_back(i);
51 }
52 } else {
54 QList<int> indices;
55 for (const auto &userID : key.userIDs()) {
56 const auto exists = Kleo::contains_if(ids, [userID](const auto &other) {
57 return !qstrcmp(std::get<GpgME::UserID>(other).email(), userID.email());
58 });
59 if (!exists && userID.email() && *userID.email()) {
60 ids += userID;
61 indices.push_back(i);
62 }
63 }
64 if (!ids.isEmpty()) {
65 mIds.append(ids);
66 mSourceIndices.append(indices);
67 } else {
68 mIds.append(key.userID(0));
69 mSourceIndices.append(i);
70 }
71 }
72 }
73 q->endResetModel();
74}
75
76UserIDProxyModel::Private::Private(UserIDProxyModel *qq)
77 : q(qq)
78{
79}
80
81UserIDProxyModel::UserIDProxyModel(QObject *parent)
82 : AbstractKeyListSortFilterProxyModel(parent)
83 , d{new Private(this)}
84{
85}
86
87UserIDProxyModel::~UserIDProxyModel() = default;
88
89static QVariant returnIfValid(const QColor &t)
90{
91 if (t.isValid()) {
92 return t;
93 } else {
94 return QVariant();
95 }
96}
97
98QModelIndex UserIDProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
99{
100 if (!sourceIndex.isValid()) {
101 return {};
102 }
103 const auto &sourceKey = sourceIndex.data(KeyList::KeyRole).value<GpgME::Key>();
104 if (sourceKey.isNull()) {
105 const auto &sourceKeyGroup = sourceIndex.data(KeyList::GroupRole).value<KeyGroup>();
106 for (int i = 0; i < d->mIds.count(); ++i) {
107 if (std::holds_alternative<KeyGroup>(d->mIds[i]) && std::get<KeyGroup>(d->mIds[i]).id() == sourceKeyGroup.id()) {
108 return index(i, sourceIndex.column(), {});
109 }
110 }
111 } else {
112 const auto &fingerprint = sourceKey.primaryFingerprint();
113 for (int i = 0; i < d->mIds.count(); ++i) {
114 if (std::holds_alternative<GpgME::UserID>(d->mIds[i]) && !qstrcmp(fingerprint, std::get<GpgME::UserID>(d->mIds[i]).parent().primaryFingerprint())) {
115 return index(i, sourceIndex.column(), {});
116 }
117 }
118 }
119
120 return {};
121}
122
123QModelIndex UserIDProxyModel::mapToSource(const QModelIndex &proxyIndex) const
124{
125 if (!proxyIndex.isValid()) {
126 return {};
127 }
128
129 return sourceModel()->index(d->mSourceIndices[proxyIndex.row()], proxyIndex.column());
130}
131
132int UserIDProxyModel::rowCount(const QModelIndex &parent) const
133{
134 if (parent.isValid()) {
135 return 0;
136 }
137 return d->mIds.count();
138}
139
140QModelIndex UserIDProxyModel::index(int row, int column, const QModelIndex &parent) const
141{
142 if (parent.isValid()) {
143 return {};
144 }
145 return createIndex(row, column, nullptr);
146}
147
149{
150 return {};
151}
152
153int UserIDProxyModel::columnCount(const QModelIndex &index) const
154{
155 if (!sourceModel()) {
156 return 0;
157 }
158 return sourceModel()->columnCount(mapToSource(index));
159}
160
161QVariant UserIDProxyModel::data(const QModelIndex &index, int role) const
162{
163 const auto &entry = d->mIds[index.row()];
164 if (std::holds_alternative<KeyGroup>(entry)) {
166 }
167 const auto &userId = std::get<GpgME::UserID>(entry);
168 const auto &key = userId.parent();
169 if (role == KeyList::UserIDRole) {
170 return QVariant::fromValue(userId);
171 }
172 if ((role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::AccessibleTextRole || role == Kleo::ClipboardRole)) {
173 if (index.column() == KeyList::Columns::PrettyName) {
174 if (key.protocol() == GpgME::OpenPGP) {
175 return Formatting::prettyName(userId);
176 } else {
177 return Formatting::prettyName(key);
178 }
179 }
180 if (index.column() == KeyList::Columns::PrettyEMail) {
181 return Formatting::prettyEMail(userId);
182 }
183 if (index.column() == KeyList::Columns::Validity) {
184 return Formatting::complianceStringShort(userId);
185 }
186 if (index.column() == KeyList::Columns::Summary) {
187 return Formatting::summaryLine(userId);
188 }
189 if (index.column() == KeyList::Columns::Origin) {
190 return Formatting::origin(userId.origin());
191 }
192 if (index.column() == KeyList::Columns::LastUpdate) {
193 if (role == Qt::AccessibleTextRole) {
194 return Formatting::accessibleDate(userId.lastUpdate());
195 } else {
196 return Formatting::dateString(userId.lastUpdate());
197 }
198 }
199 }
200 if (role == Qt::BackgroundRole) {
201 if (!SystemInfo::isHighContrastModeActive()) {
202 return returnIfValid(KeyFilterManager::instance()->bgColor(userId));
203 }
204 } else if (role == Qt::ForegroundRole) {
205 if (!SystemInfo::isHighContrastModeActive()) {
206 return returnIfValid(KeyFilterManager::instance()->fgColor(userId));
207 }
208 }
210}
211
212UserIDProxyModel *UserIDProxyModel::clone() const
213{
214 auto model = new UserIDProxyModel(QObject::parent());
215 model->setSourceModel(sourceModel());
216 return model;
217}
218
219QModelIndex UserIDProxyModel::index(const KeyGroup &group) const
220{
221 Q_UNUSED(group);
222 return {};
223}
224
225QModelIndex UserIDProxyModel::index(const GpgME::Key &key) const
226{
227 Q_UNUSED(key);
228 return {};
229}
230
231void UserIDProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
232{
233 if (sourceModel == this->sourceModel()) {
234 return;
235 }
236
237 if (this->sourceModel()) {
238 disconnect(this->sourceModel(), nullptr, this, nullptr);
239 }
240
243 d->loadUserIDs();
244 });
246 d->loadUserIDs();
247 });
249 d->loadUserIDs();
250 });
251 d->loadUserIDs();
252}
253
254#include "moc_useridproxymodel.cpp"
QModelIndex createIndex(int row, int column, const void *ptr) const const
virtual QVariant data(const QModelIndex &index, int role) const const=0
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles)
void rowsInserted(const QModelIndex &parent, int first, int last)
bool isValid() const const
void append(QList< T > &&value)
void clear()
bool isEmpty() const const
void push_back(parameter_type value)
void reserve(qsizetype size)
qsizetype size() const const
int column() const const
QVariant data(int role) const const
bool isValid() const const
int row() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QObject * parent() const const
virtual void setSourceModel(QAbstractItemModel *sourceModel) override
DisplayRole
QVariant fromValue(T &&value)
T value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 13 2024 11:51:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.