13#include <config-libkleo.h> 
   15#include "useridlistmodel.h" 
   19#include <libkleo/formatting.h> 
   21#include <KLocalizedString> 
   27#include <gpgme++/key.h> 
   39    explicit UIDModelItem(
const UserID::Signature &sig, UIDModelItem *parentItem, 
bool showRemarks)
 
   40        : mParentItem{parentItem}
 
   43        const auto name = Formatting::prettyName(sig);
 
   44        const auto email = Formatting::prettyEMail(sig);
 
   46            Formatting::prettyID(sig.signerKeyID()),
 
   49            Formatting::validityShort(sig),
 
   50            sig.isExportable() ? QStringLiteral(
"✓") : QString{},
 
   51            Formatting::creationDateString(sig),
 
   52            Formatting::expirationDateString(sig),
 
   56        if (showRemarks && parentItem) {
 
   57            for (
const auto ¬ation : sig.notations()) {
 
   58                if (notation.name() && !strcmp(notation.name(), 
"rem@gnupg.org")) {
 
   65        const auto trustSignatureDomain = Formatting::trustSignatureDomain(sig);
 
   66        mItemData.push_back(trustSignatureDomain);
 
   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{},
 
   72            sig.isExportable() ? 
i18nc(
"yes, is exportable", 
"yes") : 
i18nc(
"no, is not exportable", 
"no"),
 
   73            Formatting::accessibleDate(Formatting::creationDate(sig)),
 
   74            Formatting::accessibleExpirationDate(sig),
 
   75            lastNotation.isEmpty() ? 
i18nc(
"accessible text for empty list of tags", 
"none") : QVariant{},
 
   76            trustSignatureDomain.isEmpty() ? 
i18n(
"not applicable") : QVariant{},
 
   78        Q_ASSERT(mAccessibleText.size() == mItemData.size());
 
   81    explicit UIDModelItem(
const UserID &uid, UIDModelItem *parentItem)
 
   82        : mItemData{Formatting::prettyUserID(uid)}
 
   95        , mParentItem{parentItem}
 
  103              i18n(
"User ID / Certification Key ID"),
 
  111              i18n(
"Trust Signature For"),
 
  119        qDeleteAll(mChildItems);
 
  122    void appendChild(UIDModelItem *child)
 
  124        mChildItems << child;
 
  127    UIDModelItem *child(
int row)
 const 
  129        return mChildItems.value(row);
 
  132    const UIDModelItem *constChild(
int row)
 const 
  134        return mChildItems.value(row);
 
  137    int childCount()
 const 
  139        return mChildItems.count();
 
  142    int columnCount()
 const 
  148            return constChild(0)->columnCount();
 
  150        return mItemData.count();
 
  153    QVariant data(
int column)
 const 
  155        return mItemData.value(column);
 
  158    QVariant accessibleText(
int column)
 const 
  160        return mAccessibleText.value(column);
 
  163    QVariant toolTip(
int column)
 const 
  165        if (!mSig.isNull()) {
 
  166            if (column == 
static_cast<int>(UserIDListModel::Column::TrustSignatureDomain)) {
 
  167                return Formatting::trustSignature(mSig);
 
  170        return mItemData.value(column);
 
  173    QVariant icon(
int column)
 const 
  175        if (!mSig.isNull() && column == 
static_cast<int>(UserIDListModel::Column::Status)) {
 
  176            return Formatting::validityIcon(mSig);
 
  184            return mParentItem->mChildItems.indexOf(
const_cast<UIDModelItem *
>(
this));
 
  189    UIDModelItem *parentItem()
 const 
  194    UserID::Signature signature()
 const 
  204    const char *signerKeyId()
 const 
  206        return mSig.signerKeyID();
 
  210    QList<UIDModelItem *> mChildItems;
 
  211    QList<QVariant> mItemData;
 
  212    QList<QVariant> mAccessibleText;
 
  213    UIDModelItem *mParentItem = 
nullptr;
 
  214    UserID::Signature mSig;
 
  218UserIDListModel::UserIDListModel(QObject *p)
 
  219    : QAbstractItemModel{p}
 
  223UserIDListModel::~UserIDListModel() = 
default;
 
  225Key UserIDListModel::key()
 const 
  230static std::vector<UserID::Signature> effectiveSignatures(
const UserID &userID)
 
  232    std::vector<UserID::Signature> sigs = userID.signatures();
 
  233    std::sort(sigs.begin(), sigs.end());
 
  234    std::reverse(sigs.begin(), sigs.end());
 
  235    auto last = std::unique(sigs.begin(), sigs.end(), [](
const auto &sig1, 
const auto &sig2) {
 
  236        return !qstricmp(sig1.signerKeyID(), sig2.signerKeyID());
 
  238    sigs.erase(last, sigs.end());
 
  239    std::reverse(sigs.begin(), sigs.end());
 
  243void UserIDListModel::setKey(
const Key &key)
 
  248    mRootItem.reset(
new UIDModelItem);
 
  249    for (
int i = 0, ids = key.numUserIDs(); i < ids; ++i) {
 
  250        UserID uid = key.userID(i);
 
  251        auto uidItem = 
new UIDModelItem(uid, mRootItem.get());
 
  252        mRootItem->appendChild(uidItem);
 
  254        for (
const auto &sig : effectiveSignatures(uid)) {
 
  255            auto sigItem = 
new UIDModelItem(sig, uidItem, mRemarksEnabled);
 
  256            uidItem->appendChild(sigItem);
 
  263int UserIDListModel::columnCount(
const QModelIndex &parent)
 const 
  265    if (parent.isValid()) {
 
  266        return static_cast<UIDModelItem *
>(parent.internalPointer())->columnCount();
 
  273    return mRootItem->columnCount();
 
  276int UserIDListModel::rowCount(
const QModelIndex &parent)
 const 
  278    if (parent.column() > 0 || !mRootItem) {
 
  282    const UIDModelItem *
const parentItem = !parent.isValid() ? mRootItem.get() : 
static_cast<UIDModelItem *
>(parent.internalPointer());
 
  283    return parentItem->childCount();
 
  286QModelIndex UserIDListModel::index(
int row, 
int column, 
const QModelIndex &parent)
 const 
  288    if (!
hasIndex(row, column, parent)) {
 
  292    const UIDModelItem *
const parentItem = !parent.isValid() ? mRootItem.get() : 
static_cast<UIDModelItem *
>(parent.internalPointer());
 
  293    UIDModelItem *
const childItem = parentItem->child(row);
 
  297        return QModelIndex();
 
  303    if (!index.isValid()) {
 
  306    auto childItem = 
static_cast<UIDModelItem *
>(index.internalPointer());
 
  307    UIDModelItem *parentItem = childItem->parentItem();
 
  309    if (parentItem == mRootItem.get()) {
 
  310        return QModelIndex();
 
  313    return createIndex(parentItem->row(), 0, parentItem);
 
  316QVariant UserIDListModel::headerData(
int section, 
Qt::Orientation o, 
int role)
 const 
  320            return mRootItem->data(section);
 
  322            return mRootItem->accessibleText(section);
 
  328QVariant UserIDListModel::data(
const QModelIndex &index, 
int role)
 const 
  330    if (!index.isValid()) {
 
  334    auto item = 
static_cast<UIDModelItem *
>(index.internalPointer());
 
  339        return item->data(index.column());
 
  341        return item->accessibleText(index.column());
 
  343        return item->toolTip(index.column());
 
  345        return item->icon(index.column());
 
  346    case UserIDListModel::SignerKeyIdRole:
 
  354UserID UserIDListModel::userID(
const QModelIndex &index)
 const 
  356    if (!index.isValid()) {
 
  359    UIDModelItem *item = 
static_cast<UIDModelItem *
>(index.internalPointer());
 
  363QList<UserID> UserIDListModel::userIDs(
const QModelIndexList &indexes)
 const 
  365    QList<GpgME::UserID> ret;
 
  366    for (
const QModelIndex &idx : indexes) {
 
  367        if (!idx.isValid()) {
 
  370        auto item = 
static_cast<UIDModelItem *
>(idx.internalPointer());
 
  371        if (!item->uid().isNull()) {
 
  378UserID::Signature UserIDListModel::signature(
const QModelIndex &index)
 const 
  380    if (!index.isValid()) {
 
  381        return UserID::Signature();
 
  383    UIDModelItem *item = 
static_cast<UIDModelItem *
>(index.internalPointer());
 
  384    return item->signature();
 
  387QList<UserID::Signature> UserIDListModel::signatures(
const QModelIndexList &indexes)
 const 
  389    QList<GpgME::UserID::Signature> ret;
 
  390    for (
const QModelIndex &idx : indexes) {
 
  391        if (!idx.isValid()) {
 
  394        auto item = 
static_cast<UIDModelItem *
>(idx.internalPointer());
 
  395        if (!item->signature().isNull()) {
 
  396            ret << item->signature();
 
  402void UserIDListModel::enableRemarks(
bool value)
 
  404    mRemarksEnabled = value;
 
  407#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
 
QObject * parent() const const
 
QString fromUtf8(QByteArrayView str)
 
QVariant fromValue(T &&value)