Libkleo

useridlistmodel.cpp
1/* -*- mode: c++; c-basic-offset:4 -*-
2 models/useridlistmodel.cpp
3
4 This file is part of Kleopatra, the KDE keymanager
5 SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
6 SPDX-FileCopyrightText: 2016 Andre Heinecke <aheinecke@gnupg.org>
7 SPDX-FileCopyrightText: 2021 g10 Code GmbH
8 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
9
10 SPDX-License-Identifier: GPL-2.0-or-later
11*/
12
13#include <config-libkleo.h>
14
15#include "useridlistmodel.h"
16
17#include "keycache.h"
18
19#include <libkleo/formatting.h>
20
21#include <KLocalizedString>
22
23#include <QDate>
24#include <QIcon>
25#include <QVariant>
26
27#include <gpgme++/key.h>
28
29using namespace GpgME;
30using namespace Kleo;
31
32class UIDModelItem
33{
34 // A uid model item can either be a UserID::Signature or a UserID.
35 // you can find out which it is if the uid or the signature return
36 // null values. (Not null but isNull)
37 //
38public:
39 explicit UIDModelItem(const UserID::Signature &sig, UIDModelItem *parentItem, bool showRemarks)
40 : mParentItem{parentItem}
41 , mSig{sig}
42 {
43 const auto name = Formatting::prettyName(sig);
44 const auto email = Formatting::prettyEMail(sig);
45 mItemData = {
46 Formatting::prettyID(sig.signerKeyID()),
47 name,
48 email,
49 Formatting::creationDateString(sig),
50 Formatting::expirationDateString(sig),
51 Formatting::validityShort(sig),
52 sig.isExportable() ? QStringLiteral("✓") : QString{},
53 };
54
55 QString lastNotation;
56 if (showRemarks && parentItem) {
57 for (const auto &notation : sig.notations()) {
58 if (notation.name() && !strcmp(notation.name(), "rem@gnupg.org")) {
59 lastNotation = QString::fromUtf8(notation.value());
60 }
61 }
62 }
63 mItemData.push_back(lastNotation);
64
65 const auto trustSignatureDomain = Formatting::trustSignatureDomain(sig);
66 mItemData.push_back(trustSignatureDomain);
67 mAccessibleText = {
68 Formatting::accessibleHexID(sig.signerKeyID()),
69 name.isEmpty() ? i18nc("text for screen readers for an empty name", "no name") : QVariant{},
70 email.isEmpty() ? i18nc("text for screen readers for an empty email address", "no email") : QVariant{},
71 Formatting::accessibleDate(Formatting::creationDate(sig)),
72 Formatting::accessibleExpirationDate(sig),
73 {}, // display text is always okay
74 sig.isExportable() ? i18nc("yes, is exportable", "yes") : i18nc("no, is not exportable", "no"),
75 lastNotation.isEmpty() ? i18nc("accessible text for empty list of tags", "none") : QVariant{},
76 trustSignatureDomain.isEmpty() ? i18n("not applicable") : QVariant{},
77 };
78 Q_ASSERT(mAccessibleText.size() == mItemData.size());
79 }
80
81 explicit UIDModelItem(const UserID &uid, UIDModelItem *parentItem)
82 : mParentItem{parentItem}
83 , mUid{uid}
84 {
85 mItemData = {Formatting::prettyUserID(uid)};
86 // for the empty cells of the user ID rows we announce "User ID"
87 mAccessibleText = {
88 {}, // use displayed user ID
89 i18n("User ID"),
90 i18n("User ID"),
91 i18n("User ID"),
92 i18n("User ID"),
93 i18n("User ID"),
94 i18n("User ID"),
95 i18n("User ID"),
96 i18n("User ID"),
97 };
98 }
99
100 // The root item
101 UIDModelItem()
102 {
103 mItemData = {
104 i18n("User ID / Certification Key ID"),
105 i18n("Name"),
106 i18n("E-Mail"),
107 i18n("Valid From"),
108 i18n("Valid Until"),
109 i18n("Status"),
110 i18n("Exportable"),
111 i18n("Tags"),
112 i18n("Trust Signature For"),
113 };
114 // mAccessibleText is explicitly left empty
115 }
116
117 ~UIDModelItem()
118 {
119 qDeleteAll(mChildItems);
120 }
121
122 void appendChild(UIDModelItem *child)
123 {
124 mChildItems << child;
125 }
126
127 UIDModelItem *child(int row) const
128 {
129 return mChildItems.value(row);
130 }
131
132 const UIDModelItem *constChild(int row) const
133 {
134 return mChildItems.value(row);
135 }
136
137 int childCount() const
138 {
139 return mChildItems.count();
140 }
141
142 int columnCount() const
143 {
144 if (childCount()) {
145 // We take the value from the first child
146 // as we are likely a UID and our children
147 // are UID Signatures.
148 return constChild(0)->columnCount();
149 }
150 return mItemData.count();
151 }
152
153 QVariant data(int column) const
154 {
155 return mItemData.value(column);
156 }
157
158 QVariant accessibleText(int column) const
159 {
160 return mAccessibleText.value(column);
161 }
162
163 QVariant toolTip(int column) const
164 {
165 if (!mSig.isNull()) {
166 if (column == static_cast<int>(UserIDListModel::Column::Status)) {
167 return i18n("class %1", mSig.certClass());
168 } else if (column == static_cast<int>(UserIDListModel::Column::TrustSignatureDomain)) {
169 return Formatting::trustSignature(mSig);
170 }
171 }
172 return mItemData.value(column);
173 }
174
175 QVariant icon(int column) const
176 {
177 if (!mSig.isNull() && column == static_cast<int>(UserIDListModel::Column::Status)) {
178 return Formatting::validityIcon(mSig);
179 }
180 return {};
181 }
182
183 int row() const
184 {
185 if (mParentItem) {
186 return mParentItem->mChildItems.indexOf(const_cast<UIDModelItem *>(this));
187 }
188 return 0;
189 }
190
191 UIDModelItem *parentItem() const
192 {
193 return mParentItem;
194 }
195
196 UserID::Signature signature() const
197 {
198 return mSig;
199 }
200
201 UserID uid() const
202 {
203 return mUid;
204 }
205
206private:
207 QList<UIDModelItem *> mChildItems;
208 QList<QVariant> mItemData;
209 QList<QVariant> mAccessibleText;
210 UIDModelItem *mParentItem = nullptr;
211 UserID::Signature mSig;
212 UserID mUid;
213};
214
215UserIDListModel::UserIDListModel(QObject *p)
217{
218}
219
220UserIDListModel::~UserIDListModel() = default;
221
222Key UserIDListModel::key() const
223{
224 return mKey;
225}
226
227void UserIDListModel::setKey(const Key &key)
228{
230 mKey = key;
231
232 mRootItem.reset(new UIDModelItem);
233 for (int i = 0, ids = key.numUserIDs(); i < ids; ++i) {
234 UserID uid = key.userID(i);
235 auto uidItem = new UIDModelItem(uid, mRootItem.get());
236 mRootItem->appendChild(uidItem);
237 std::vector<UserID::Signature> sigs = uid.signatures();
238 std::sort(sigs.begin(), sigs.end());
239 for (const auto &sig : sigs) {
240 auto sigItem = new UIDModelItem(sig, uidItem, mRemarksEnabled);
241 uidItem->appendChild(sigItem);
242 }
243 }
244
246}
247
248int UserIDListModel::columnCount(const QModelIndex &parent) const
249{
250 if (parent.isValid()) {
251 return static_cast<UIDModelItem *>(parent.internalPointer())->columnCount();
252 }
253
254 if (!mRootItem) {
255 return 0;
256 }
257
258 return mRootItem->columnCount();
259}
260
261int UserIDListModel::rowCount(const QModelIndex &parent) const
262{
263 if (parent.column() > 0 || !mRootItem) {
264 return 0;
265 }
266
267 const UIDModelItem *const parentItem = !parent.isValid() ? mRootItem.get() : static_cast<UIDModelItem *>(parent.internalPointer());
268 return parentItem->childCount();
269}
270
271QModelIndex UserIDListModel::index(int row, int column, const QModelIndex &parent) const
272{
273 if (!hasIndex(row, column, parent)) {
274 return {};
275 }
276
277 const UIDModelItem *const parentItem = !parent.isValid() ? mRootItem.get() : static_cast<UIDModelItem *>(parent.internalPointer());
278 UIDModelItem *const childItem = parentItem->child(row);
279 if (childItem) {
280 return createIndex(row, column, childItem);
281 } else {
282 return QModelIndex();
283 }
284}
285
287{
288 if (!index.isValid()) {
289 return {};
290 }
291 auto childItem = static_cast<UIDModelItem *>(index.internalPointer());
292 UIDModelItem *parentItem = childItem->parentItem();
293
294 if (parentItem == mRootItem.get()) {
295 return QModelIndex();
296 }
297
298 return createIndex(parentItem->row(), 0, parentItem);
299}
300
301QVariant UserIDListModel::headerData(int section, Qt::Orientation o, int role) const
302{
303 if (o == Qt::Horizontal && mRootItem) {
304 if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::ToolTipRole) {
305 return mRootItem->data(section);
306 } else if (role == Qt::AccessibleTextRole) {
307 return mRootItem->accessibleText(section);
308 }
309 }
310 return QVariant();
311}
312
313QVariant UserIDListModel::data(const QModelIndex &index, int role) const
314{
315 if (!index.isValid()) {
316 return QVariant();
317 }
318
319 auto item = static_cast<UIDModelItem *>(index.internalPointer());
320
321 switch (role) {
322 case Qt::DisplayRole:
323 case Qt::EditRole:
324 return item->data(index.column());
326 return item->accessibleText(index.column());
327 case Qt::ToolTipRole:
328 return item->toolTip(index.column());
330 return item->icon(index.column());
331 default:;
332 }
333
334 return {};
335}
336
337UserID UserIDListModel::userID(const QModelIndex &index) const
338{
339 if (!index.isValid()) {
340 return UserID();
341 }
342 UIDModelItem *item = static_cast<UIDModelItem *>(index.internalPointer());
343 return item->uid();
344}
345
346QList<UserID> UserIDListModel::userIDs(const QModelIndexList &indexes) const
347{
349 for (const QModelIndex &idx : indexes) {
350 if (!idx.isValid()) {
351 continue;
352 }
353 auto item = static_cast<UIDModelItem *>(idx.internalPointer());
354 if (!item->uid().isNull()) {
355 ret << item->uid();
356 }
357 }
358 return ret;
359}
360
361UserID::Signature UserIDListModel::signature(const QModelIndex &index) const
362{
363 if (!index.isValid()) {
364 return UserID::Signature();
365 }
366 UIDModelItem *item = static_cast<UIDModelItem *>(index.internalPointer());
367 return item->signature();
368}
369
370QList<UserID::Signature> UserIDListModel::signatures(const QModelIndexList &indexes) const
371{
373 for (const QModelIndex &idx : indexes) {
374 if (!idx.isValid()) {
375 continue;
376 }
377 auto item = static_cast<UIDModelItem *>(idx.internalPointer());
378 if (!item->signature().isNull()) {
379 ret << item->signature();
380 }
381 }
382 return ret;
383}
384
385void UserIDListModel::enableRemarks(bool value)
386{
387 mRemarksEnabled = value;
388}
389
390#include "moc_useridlistmodel.cpp"
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QModelIndex createIndex(int row, int column, const void *ptr) const const
bool hasIndex(int row, int column, const QModelIndex &parent) const const
qsizetype count() const const
qsizetype indexOf(const AT &value, qsizetype from) const const
void push_back(parameter_type value)
qsizetype size() const const
T value(qsizetype i) const const
int column() const const
void * internalPointer() const const
bool isValid() const const
QObject * parent() const const
QString fromUtf8(QByteArrayView str)
DisplayRole
Orientation
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:12 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.