diff --git a/src/models/useridproxymodel.cpp b/src/models/useridproxymodel.cpp index 10607b658..9fff40a66 100644 --- a/src/models/useridproxymodel.cpp +++ b/src/models/useridproxymodel.cpp @@ -1,254 +1,256 @@ /* SPDX-FileCopyrightText: 2024 g10 Code GmbH SPDX-FileContributor: Tobias Fella SPDX-License-Identifier: GPL-2.0-or-later */ #include "useridproxymodel.h" #include "keylist.h" #include "keylistmodel.h" #include "kleo/keyfiltermanager.h" #include "utils/algorithm.h" #include "utils/formatting.h" #include "utils/systeminfo.h" #include #include #include using namespace Kleo; class UserIDProxyModel::Private { public: Private(UserIDProxyModel *qq); void loadUserIDs(); QList> mIds; QAbstractItemModel *oldSourceModel = nullptr; UserIDProxyModel *q; }; void UserIDProxyModel::Private::loadUserIDs() { q->beginResetModel(); mIds.clear(); mIds.reserve(q->sourceModel()->rowCount()); for (auto i = 0; i < q->sourceModel()->rowCount(); ++i) { const auto key = q->sourceModel()->index(i, 0).data(KeyList::KeyRole).value(); QList ids; if (key.isNull()) { mIds += q->sourceModel()->index(i, 0).data(KeyList::GroupRole).value(); } else if (key.protocol() == GpgME::OpenPGP) { for (const auto &userID : key.userIDs()) { mIds += userID; } } else { QList> ids; for (const auto &userID : key.userIDs()) { const auto exists = Kleo::contains_if(ids, [userID](const auto &other) { return !qstrcmp(std::get(other).email(), userID.email()); }); if (!exists && userID.email() && *userID.email()) { ids += userID; } } if (ids.count() > 0) { mIds.append(ids); } else { mIds.append(key.userID(0)); } } } q->endResetModel(); } UserIDProxyModel::Private::Private(UserIDProxyModel *qq) : q(qq) { connect(q, &UserIDProxyModel::sourceModelChanged, q, [this]() { if (oldSourceModel) { disconnect(oldSourceModel, nullptr, q, nullptr); } connect(q->sourceModel(), &QAbstractItemModel::dataChanged, q, [this]() { loadUserIDs(); }); connect(q->sourceModel(), &QAbstractItemModel::rowsInserted, q, [this]() { loadUserIDs(); }); connect(q->sourceModel(), &QAbstractItemModel::modelReset, q, [this]() { loadUserIDs(); }); oldSourceModel = q->sourceModel(); loadUserIDs(); }); } UserIDProxyModel::UserIDProxyModel(QObject *parent) : AbstractKeyListSortFilterProxyModel(parent) , d{new Private(this)} { } UserIDProxyModel::~UserIDProxyModel() = default; static QVariant returnIfValid(const QColor &t) { if (t.isValid()) { return t; } else { return QVariant(); } } QModelIndex UserIDProxyModel::mapFromSource(const QModelIndex &sourceIndex) const { if (!sourceIndex.isValid()) { return {}; } const auto &sourceKey = sourceIndex.data(KeyList::KeyRole).value(); if (sourceKey.isNull()) { const auto &sourceKeyGroup = sourceIndex.data(KeyList::GroupRole).value(); for (int i = 0; i < d->mIds.count(); ++i) { if (std::holds_alternative(d->mIds[i]) && std::get(d->mIds[i]).id() == sourceKeyGroup.id()) { return index(i, sourceIndex.column(), {}); } } } else { const auto &fingerprint = sourceKey.primaryFingerprint(); for (int i = 0; i < d->mIds.count(); ++i) { if (std::holds_alternative(d->mIds[i]) && !qstrcmp(fingerprint, std::get(d->mIds[i]).parent().primaryFingerprint())) { return index(i, sourceIndex.column(), {}); } } } return {}; } QModelIndex UserIDProxyModel::mapToSource(const QModelIndex &proxyIndex) const { if (!proxyIndex.isValid()) { return {}; } const auto &entry = d->mIds[proxyIndex.row()]; if (std::holds_alternative(entry)) { const auto &id = std::get(entry).id(); for (int i = 0; i < sourceModel()->rowCount(); ++i) { if (sourceModel()->index(i, 0).data(KeyList::GroupRole).value().id() == id) { return sourceModel()->index(i, proxyIndex.column()); } } } else { const auto &fingerprint = std::get(entry).parent().primaryFingerprint(); for (int i = 0; i < sourceModel()->rowCount(); ++i) { if (!qstrcmp(sourceModel()->index(i, 0).data(KeyList::KeyRole).value().primaryFingerprint(), fingerprint)) { return sourceModel()->index(i, proxyIndex.column()); } } } return {}; } int UserIDProxyModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return d->mIds.count(); } QModelIndex UserIDProxyModel::index(int row, int column, const QModelIndex &parent) const { if (parent.isValid()) { return {}; } return createIndex(row, column, nullptr); } QModelIndex UserIDProxyModel::parent(const QModelIndex &) const { return {}; } int UserIDProxyModel::columnCount(const QModelIndex &index) const { if (!sourceModel()) { return 0; } return sourceModel()->columnCount(mapToSource(index)); } QVariant UserIDProxyModel::data(const QModelIndex &index, int role) const { const auto &entry = d->mIds[index.row()]; if (std::holds_alternative(entry)) { return AbstractKeyListSortFilterProxyModel::data(index, role); } const auto &userId = std::get(entry); const auto &key = userId.parent(); if (role == KeyList::UserIDRole) { return QVariant::fromValue(userId); } if ((role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::AccessibleTextRole)) { if (index.column() == KeyList::Columns::PrettyName) { if (key.protocol() == GpgME::OpenPGP) { return Formatting::prettyName(userId); } else { return Formatting::prettyName(key); } } if (index.column() == KeyList::Columns::PrettyEMail) { return Formatting::prettyEMail(userId); } if (index.column() == KeyList::Columns::Validity) { return Formatting::complianceStringShort(userId); } if (index.column() == KeyList::Columns::Summary) { return Formatting::summaryLine(userId); } if (index.column() == KeyList::Columns::Origin) { return Formatting::origin(userId.origin()); } if (index.column() == KeyList::Columns::LastUpdate) { if (role == Qt::AccessibleTextRole) { return Formatting::accessibleDate(userId.lastUpdate()); } else { return Formatting::dateString(userId.lastUpdate()); } } } if (role == Qt::BackgroundRole) { if (!SystemInfo::isHighContrastModeActive()) { return returnIfValid(KeyFilterManager::instance()->bgColor(userId)); } } else if (role == Qt::ForegroundRole) { if (!SystemInfo::isHighContrastModeActive()) { return returnIfValid(KeyFilterManager::instance()->fgColor(userId)); } } return AbstractKeyListSortFilterProxyModel::data(index, role); } UserIDProxyModel *UserIDProxyModel::clone() const { auto model = new UserIDProxyModel(QObject::parent()); model->setSourceModel(sourceModel()); return model; } QModelIndex UserIDProxyModel::index(const KeyGroup &group) const { Q_UNUSED(group); return {}; } QModelIndex UserIDProxyModel::index(const GpgME::Key &key) const { Q_UNUSED(key); return {}; } + +#include "moc_useridproxymodel.cpp" diff --git a/src/ui/adjustingscrollarea.cpp b/src/ui/adjustingscrollarea.cpp index 9c5cdf3f6..ce10f3b18 100644 --- a/src/ui/adjustingscrollarea.cpp +++ b/src/ui/adjustingscrollarea.cpp @@ -1,99 +1,101 @@ /* -*- mode: c++; c-basic-offset:4 -*- ui/adjustingscrollarea.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB SPDX-FileCopyrightText: 2022 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include "adjustingscrollarea.h" #include #include #include #include #include using namespace Kleo; AdjustingScrollArea::AdjustingScrollArea(QWidget *parent) : QScrollArea{parent} { auto w = new QWidget; w->setObjectName(QLatin1StringView("scrollarea_widget")); new QVBoxLayout{w}; setWidget(w); setWidgetResizable(true); w->installEventFilter(this); connect(qApp, &QApplication::focusChanged, this, [this](QWidget *old, QWidget *now) { Q_UNUSED(old); ensureWidgetVisible(now); }); } AdjustingScrollArea::~AdjustingScrollArea() { widget()->removeEventFilter(this); } QSize AdjustingScrollArea::minimumSizeHint() const { const int fw = frameWidth(); QSize sz{2 * fw, 2 * fw}; sz += {widget()->minimumSizeHint().width(), 0}; if (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { sz.setWidth(sz.width() + verticalScrollBar()->sizeHint().width()); } if (horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { sz.setHeight(sz.height() + horizontalScrollBar()->sizeHint().height()); } return QScrollArea::minimumSizeHint().expandedTo(sz); } QSize AdjustingScrollArea::sizeHint() const { const int fw = frameWidth(); QSize sz{2 * fw, 2 * fw}; sz += viewportSizeHint(); if (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { sz.setWidth(sz.width() + verticalScrollBar()->sizeHint().width()); } if (horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff) { sz.setHeight(sz.height() + horizontalScrollBar()->sizeHint().height()); } sz = QScrollArea::sizeHint().expandedTo(sz); return sz; } void AdjustingScrollArea::adjustSizeOfWindowBy(const QSize &extent) { if (auto w = window()) { const auto currentSize = w->size(); // we limit the automatic size adjustment to 2/3 of the screen's size const auto maxWindowSize = screen()->geometry().size() * 2 / 3; const auto newWindowSize = currentSize.expandedTo((currentSize + extent).boundedTo(maxWindowSize)); if (newWindowSize != currentSize) { w->resize(newWindowSize); } } } bool AdjustingScrollArea::eventFilter(QObject *obj, QEvent *ev) { if (ev->type() == QEvent::Resize && obj == widget() && sizeAdjustPolicy() == AdjustToContents) { const auto *const event = static_cast(ev); if (event->size().height() > event->oldSize().height()) { const auto currentViewportHeight = viewport()->height(); const auto wantedViewportHeight = event->size().height(); const auto wantedAdditionalHeight = wantedViewportHeight - currentViewportHeight; if (wantedAdditionalHeight > 0) { adjustSizeOfWindowBy(QSize{0, wantedAdditionalHeight}); } } } return QScrollArea::eventFilter(obj, ev); } + +#include "moc_adjustingscrollarea.cpp"