Use qtpaths directly
[kdepim.git] / kleopatra / models / useridlistmodel.cpp
blob3ea0fff411d2a4d811c13fcb1410bcff0b871802
1 /* -*- mode: c++; c-basic-offset:4 -*-
2 models/useridlistmodel.cpp
4 This file is part of Kleopatra, the KDE keymanager
5 Copyright (c) 2007 Klarälvdalens Datakonsult AB
7 Kleopatra is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Kleopatra is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 In addition, as a special exception, the copyright holders give
22 permission to link the code of this program with any edition of
23 the Qt library by Trolltech AS, Norway (or with modified versions
24 of Qt that use the same license as Qt), and distribute linked
25 combinations including the two. You must obey the GNU General
26 Public License in all respects for all of the code used other than
27 Qt. If you modify this file, you may extend this exception to
28 your version of the file, but you are not obligated to do so. If
29 you do not wish to do so, delete this exception statement from
30 your version.
33 #include <config-kleopatra.h>
35 #include "useridlistmodel.h"
37 #include <utils/formatting.h>
39 #include <gpgme++/key.h>
41 #include <KLocalizedString>
43 #include <QVariant>
44 #include <QDate>
46 #include <boost/bind.hpp>
48 #include <algorithm>
49 #include <iterator>
51 using namespace GpgME;
52 using namespace Kleo;
53 using namespace boost;
55 namespace
58 static inline bool is_userid_level(const QModelIndex &idx)
60 return idx.isValid()/* && idx.internalId() < 0 */;
63 static inline int extract_uid_number(const QModelIndex &idx)
65 return idx.internalId();
68 static inline bool is_signature_level(const QModelIndex &idx)
70 return idx.isValid()/* && idx.internalId() >= 0*/;
75 class UserIDListModel::Private
77 friend class ::Kleo::UserIDListModel;
78 UserIDListModel *const q;
79 public:
80 explicit Private(UserIDListModel *qq)
81 : q(qq), key() {}
83 private:
84 Key key;
87 UserIDListModel::UserIDListModel(QObject *p)
88 : QAbstractItemModel(p), d(new Private(this))
93 UserIDListModel::~UserIDListModel() {}
95 Key UserIDListModel::key() const
97 return d->key;
100 // slot
101 void UserIDListModel::setKey(const Key &key)
104 const Key oldKey = d->key;
106 d->key = key;
108 if (qstricmp(key.primaryFingerprint(), oldKey.primaryFingerprint()) != 0) {
109 // different key -> reset
110 reset();
111 return;
114 // ### diff them, and signal more fine-grained than this:
116 if (key.numUserIDs() > 0 && oldKey.numUserIDs() == key.numUserIDs()) {
117 bool identical = true;
118 for (unsigned int i = 0, end = key.numUserIDs(); i != end; ++i) {
119 if (key.userID(i).numSignatures() != oldKey.userID(i).numSignatures()) {
120 identical = false;
121 break;
124 if (identical) {
125 Q_EMIT dataChanged(index(0, 0), index(key.numUserIDs() - 1, NumColumns - 1));
126 return;
129 Q_EMIT layoutAboutToBeChanged();
130 Q_EMIT layoutChanged();
133 UserID UserIDListModel::userID(const QModelIndex &idx, bool strict) const
135 if (is_userid_level(idx)) {
136 return d->key.userID(idx.row());
138 if (!strict && is_signature_level(idx)) {
139 return d->key.userID(extract_uid_number(idx));
141 return UserID();
144 std::vector<UserID> UserIDListModel::userIDs(const QList<QModelIndex> &indexes, bool strict) const
146 std::vector<UserID> result;
147 result.reserve(indexes.size());
148 std::transform(indexes.begin(), indexes.end(),
149 std::back_inserter(result),
150 boost::bind(&UserIDListModel::userID, this, _1, strict));
151 return result;
154 UserID::Signature UserIDListModel::signature(const QModelIndex &idx) const
156 if (is_signature_level(idx)) {
157 return d->key.userID(extract_uid_number(idx)).signature(idx.row());
158 } else {
159 return UserID::Signature();
163 std::vector<UserID::Signature> UserIDListModel::signatures(const QList<QModelIndex> &indexes) const
165 std::vector<UserID::Signature> result;
166 result.reserve(indexes.size());
167 std::transform(indexes.begin(), indexes.end(),
168 std::back_inserter(result),
169 boost::bind(&UserIDListModel::signature, this, _1));
170 return result;
173 QModelIndex UserIDListModel::index(const UserID &userID, int col) const
175 // O(N), but not sorted, so no better way...
176 for (unsigned int row = 0, end = d->key.numUserIDs(); row != end; ++row)
177 if (qstricmp(userID.id(), d->key.userID(row).id()) == 0) {
178 return createIndex(row, col, -1);
180 return QModelIndex();
183 QList<QModelIndex> UserIDListModel::indexes(const std::vector<UserID> &userIDs, int col) const
185 // O(N*M), but who cares...?
186 QList<QModelIndex> result;
187 Q_FOREACH (const UserID &uid, userIDs) {
188 result.push_back(index(uid, col));
190 return result;
193 QModelIndex UserIDListModel::index(const UserID::Signature &sig, int col) const
195 const UserID uid = sig.parent();
196 const QModelIndex pidx = index(uid);
197 if (!pidx.isValid()) {
198 return QModelIndex();
200 const std::vector<UserID::Signature> sigs = uid.signatures();
201 const std::vector<UserID::Signature>::const_iterator it
202 = std::find_if(sigs.begin(), sigs.end(),
203 boost::bind(qstricmp, boost::bind(&UserID::Signature::signerKeyID, _1), sig.signerKeyID()) == 0);
204 if (it == sigs.end()) {
205 return QModelIndex();
207 return createIndex(std::distance(sigs.begin(), it), col, pidx.row());
210 QList<QModelIndex> UserIDListModel::indexes(const std::vector<UserID::Signature> &signatures, int col) const
212 QList<QModelIndex> result;
213 Q_FOREACH (const UserID::Signature &sig, signatures) {
214 result.push_back(index(sig, col));
216 return result;
219 void UserIDListModel::clear()
221 d->key = Key::null;
222 reset();
225 int UserIDListModel::columnCount(const QModelIndex &) const
227 return NumColumns;
230 int UserIDListModel::rowCount(const QModelIndex &pidx) const
232 if (!pidx.isValid()) {
233 return d->key.numUserIDs();
235 if (is_userid_level(pidx)) {
236 return d->key.userID(pidx.row()).numSignatures();
238 return 0;
241 QModelIndex UserIDListModel::index(int row, int col, const QModelIndex &pidx) const
243 if (row < 0 || col < 0 || col >= NumColumns) {
244 return QModelIndex();
247 if (!pidx.isValid()) {
248 if (static_cast<unsigned>(row) < d->key.numUserIDs()) {
249 return createIndex(row, col, -1);
250 } else {
251 return QModelIndex();
255 if (!is_userid_level(pidx)) {
256 return QModelIndex();
259 const int numSigs = userID(pidx).numSignatures();
260 if (row < numSigs) {
261 return createIndex(row, col, pidx.row());
264 return QModelIndex();
267 QModelIndex UserIDListModel::parent(const QModelIndex &idx) const
269 if (is_signature_level(idx)) {
270 return createIndex(idx.internalId(), 0, -1);
271 } else {
272 return QModelIndex();
276 QVariant UserIDListModel::headerData(int section, Qt::Orientation o, int role) const
278 if (o == Qt::Horizontal)
279 if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::ToolTipRole)
280 switch (section) {
281 case ID: return i18n("ID");
282 case PrettyName: return i18n("Name");
283 case PrettyEMail: return i18n("EMail");
284 case ValidFrom: return i18n("Valid From");
285 case ValidUntil: return i18n("Valid Until");
286 case Status: return i18n("Status");
287 case NumColumns:;
289 return QVariant();
292 QVariant UserIDListModel::data(const QModelIndex &idx, int role) const
295 if (role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::ToolTipRole) {
296 return QVariant();
299 if (is_userid_level(idx)) {
301 const UserID uid = this->userID(idx);
302 if (uid.isNull()) {
303 return QVariant();
306 if (idx.column() == 0)
307 // we assume that the top-level items are spanned
309 return Formatting::prettyUserID(uid);
310 } else {
311 return QVariant();
314 } else if (is_signature_level(idx)) {
316 const UserID::Signature signature = this->signature(idx);
317 if (signature.isNull()) {
318 return QVariant();
321 switch (idx.column()) {
323 case ID:
324 return QString::fromLatin1(signature.signerKeyID());
325 case PrettyName:
326 return Formatting::prettyName(signature);
327 case PrettyEMail:
328 return Formatting::prettyEMail(signature);
329 case ValidFrom:
330 if (role == Qt::EditRole) {
331 return Formatting::creationDate(signature);
332 } else {
333 return Formatting::creationDateString(signature);
335 case ValidUntil:
336 if (role == Qt::EditRole) {
337 return Formatting::expirationDate(signature);
338 } else {
339 return Formatting::expirationDateString(signature);
341 case Status:
342 return Formatting::validityShort(signature);
343 #if 0
344 if (userID.isRevoked()) {
345 return i18n("revoked");
347 if (userID.isExpired()) {
348 return i18n("expired");
350 if (userID.isDisabled()) {
351 return i18n("disabled");
353 if (userID.isInvalid()) {
354 return i18n("invalid");
356 return i18n("good");
357 #endif
362 return QVariant();