File indexing completed on 2025-01-05 04:55:46
0001 /* -*- mode: c++; c-basic-offset:4 -*- 0002 models/subkeylistmodel.cpp 0003 0004 This file is part of Kleopatra, the KDE keymanager 0005 SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include <config-libkleo.h> 0011 0012 #include "subkeylistmodel.h" 0013 0014 #include <libkleo/formatting.h> 0015 0016 #include <KLocalizedString> 0017 0018 #include <QDate> 0019 #include <QVariant> 0020 0021 #include <gpgme++/key.h> 0022 0023 #include <algorithm> 0024 #include <iterator> 0025 0026 using namespace GpgME; 0027 using namespace Kleo; 0028 0029 class SubkeyListModel::Private 0030 { 0031 friend class ::Kleo::SubkeyListModel; 0032 SubkeyListModel *const q; 0033 0034 public: 0035 explicit Private(SubkeyListModel *qq) 0036 : q(qq) 0037 , key() 0038 { 0039 } 0040 0041 private: 0042 Key key; 0043 }; 0044 0045 SubkeyListModel::SubkeyListModel(QObject *p) 0046 : QAbstractTableModel(p) 0047 , d(new Private(this)) 0048 { 0049 } 0050 0051 SubkeyListModel::~SubkeyListModel() 0052 { 0053 } 0054 0055 Key SubkeyListModel::key() const 0056 { 0057 return d->key; 0058 } 0059 0060 // slot 0061 void SubkeyListModel::setKey(const Key &key) 0062 { 0063 const Key oldKey = d->key; 0064 0065 if (qstricmp(key.primaryFingerprint(), oldKey.primaryFingerprint()) != 0) { 0066 // different key -> reset 0067 beginResetModel(); 0068 d->key = key; 0069 endResetModel(); 0070 return; 0071 } 0072 0073 d->key = key; 0074 0075 // ### diff them, and signal more fine-grained than this: 0076 0077 if (key.numSubkeys() > 0 && oldKey.numSubkeys() == key.numSubkeys()) { 0078 Q_EMIT dataChanged(index(0, 0), index(key.numSubkeys() - 1, NumColumns - 1)); 0079 } else { 0080 Q_EMIT layoutAboutToBeChanged(); 0081 Q_EMIT layoutChanged(); 0082 } 0083 } 0084 0085 Subkey SubkeyListModel::subkey(const QModelIndex &idx) const 0086 { 0087 if (idx.isValid()) { 0088 return d->key.subkey(idx.row()); 0089 } else { 0090 return Subkey(); 0091 } 0092 } 0093 0094 std::vector<Subkey> SubkeyListModel::subkeys(const QList<QModelIndex> &indexes) const 0095 { 0096 std::vector<Subkey> result; 0097 result.reserve(indexes.size()); 0098 std::transform(indexes.begin(), // 0099 indexes.end(), 0100 std::back_inserter(result), 0101 [this](const QModelIndex &idx) { 0102 return subkey(idx); 0103 }); 0104 return result; 0105 } 0106 0107 QModelIndex SubkeyListModel::index(const Subkey &subkey, int col) const 0108 { 0109 // O(N), but not sorted, so no better way... 0110 for (unsigned int row = 0, end = d->key.numSubkeys(); row != end; ++row) { 0111 if (qstricmp(subkey.keyID(), d->key.subkey(row).keyID()) == 0) { 0112 return index(row, col); 0113 } 0114 } 0115 return {}; 0116 } 0117 0118 QList<QModelIndex> SubkeyListModel::indexes(const std::vector<Subkey> &subkeys) const 0119 { 0120 QList<QModelIndex> result; 0121 result.reserve(subkeys.size()); 0122 // O(N*M), but who cares...? 0123 std::transform(subkeys.begin(), // 0124 subkeys.end(), 0125 std::back_inserter(result), 0126 [this](const Subkey &key) { 0127 return index(key); 0128 }); 0129 return result; 0130 } 0131 0132 void SubkeyListModel::clear() 0133 { 0134 beginResetModel(); 0135 d->key = Key::null; 0136 endResetModel(); 0137 } 0138 0139 int SubkeyListModel::columnCount(const QModelIndex &) const 0140 { 0141 return NumColumns; 0142 } 0143 0144 int SubkeyListModel::rowCount(const QModelIndex &pidx) const 0145 { 0146 return pidx.isValid() ? 0 : d->key.numSubkeys(); 0147 } 0148 0149 QVariant SubkeyListModel::headerData(int section, Qt::Orientation o, int role) const 0150 { 0151 if (o == Qt::Horizontal) { 0152 if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::ToolTipRole) { 0153 switch (section) { 0154 case ID: 0155 return i18n("ID"); 0156 case Type: 0157 return i18n("Type"); 0158 case ValidFrom: 0159 return i18n("Valid From"); 0160 case ValidUntil: 0161 return i18n("Valid Until"); 0162 case Status: 0163 return i18n("Status"); 0164 case Strength: 0165 return i18n("Strength"); 0166 case Usage: 0167 return i18n("Usage"); 0168 case NumColumns:; 0169 } 0170 } 0171 } 0172 return QVariant(); 0173 } 0174 0175 QVariant SubkeyListModel::data(const QModelIndex &idx, int role) const 0176 { 0177 if (role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::ToolTipRole) { 0178 return QVariant(); 0179 } 0180 0181 const Subkey subkey = this->subkey(idx); 0182 if (subkey.isNull()) { 0183 return QVariant(); 0184 } 0185 0186 switch (idx.column()) { 0187 case ID: 0188 return QString::fromLatin1(subkey.keyID()); 0189 case Type: 0190 return Formatting::type(subkey); 0191 case ValidFrom: 0192 if (role == Qt::EditRole) { 0193 return Formatting::creationDate(subkey); 0194 } else { 0195 return Formatting::creationDateString(subkey); 0196 } 0197 case ValidUntil: 0198 if (role == Qt::EditRole) { 0199 return Formatting::expirationDate(subkey); 0200 } else { 0201 return Formatting::expirationDateString(subkey); 0202 } 0203 case Status: 0204 return Formatting::validityShort(subkey); 0205 case Usage: 0206 return Formatting::usageString(subkey); 0207 case Strength: 0208 const QString algName = QString::fromStdString(subkey.algoName()); 0209 // For ECC keys the algo name is something like bp512 and directly 0210 // indicated the "strength" 0211 return algName.isEmpty() ? QVariant(subkey.length()) : algName; 0212 } 0213 0214 return QVariant(); 0215 } 0216 0217 #include "moc_subkeylistmodel.cpp"