File indexing completed on 2024-06-16 04:56:17
0001 /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; -*- 0002 view/searchbar.cpp 0003 0004 This file is part of Kleopatra, the KDE keymanager 0005 SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB 0006 SPDX-FileCopyrightText: 2022 g10 Code GmbH 0007 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de> 0008 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #include <config-kleopatra.h> 0013 0014 #include "searchbar.h" 0015 0016 #include <Libkleo/Algorithm> 0017 #include <Libkleo/KeyCache> 0018 #include <Libkleo/KeyFilter> 0019 #include <Libkleo/KeyFilterManager> 0020 0021 #include <KLocalizedString> 0022 0023 #include <QComboBox> 0024 #include <QHBoxLayout> 0025 #include <QLineEdit> 0026 #include <QPushButton> 0027 #include <QSortFilterProxyModel> 0028 0029 #include <gpgme++/key.h> 0030 0031 #include "kleopatra_debug.h" 0032 0033 using namespace Kleo; 0034 0035 namespace 0036 { 0037 0038 class ProxyModel : public QSortFilterProxyModel 0039 { 0040 Q_OBJECT 0041 0042 public: 0043 using QSortFilterProxyModel::QSortFilterProxyModel; 0044 0045 protected: 0046 bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override 0047 { 0048 const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); 0049 const auto matchContexts = qvariant_cast<KeyFilter::MatchContexts>(sourceModel()->data(index, KeyFilterManager::FilterMatchContextsRole)); 0050 return matchContexts & KeyFilter::Filtering; 0051 } 0052 }; 0053 0054 } 0055 0056 class SearchBar::Private 0057 { 0058 friend class ::Kleo::SearchBar; 0059 SearchBar *const q; 0060 0061 public: 0062 explicit Private(SearchBar *qq); 0063 ~Private(); 0064 0065 private: 0066 void slotKeyFilterChanged(int idx) 0067 { 0068 Q_EMIT q->keyFilterChanged(keyFilter(idx)); 0069 } 0070 0071 std::shared_ptr<KeyFilter> keyFilter(int idx) const 0072 { 0073 const QModelIndex mi = proxyModel->mapToSource(proxyModel->index(idx, 0)); 0074 return KeyFilterManager::instance()->fromModelIndex(mi); 0075 } 0076 0077 std::shared_ptr<KeyFilter> currentKeyFilter() const 0078 { 0079 return keyFilter(combo->currentIndex()); 0080 } 0081 0082 QString currentKeyFilterID() const 0083 { 0084 if (const std::shared_ptr<KeyFilter> f = currentKeyFilter()) { 0085 return f->id(); 0086 } else { 0087 return QString(); 0088 } 0089 } 0090 0091 static auto notCertifiedKeysFilterId() 0092 { 0093 static const QString filterId = QStringLiteral("not-certified-certificates"); 0094 return filterId; 0095 } 0096 0097 void listNotCertifiedKeys() const 0098 { 0099 lineEdit->clear(); 0100 combo->setCurrentIndex(combo->findData(notCertifiedKeysFilterId())); 0101 Q_EMIT q->keyFilterChanged(keyFilter(combo->currentIndex())); 0102 } 0103 0104 void showOrHideCertifyButton() const 0105 { 0106 if (!KeyCache::instance()->initialized()) { 0107 return; 0108 } 0109 const auto filter = KeyFilterManager::instance()->keyFilterByID(notCertifiedKeysFilterId()); 0110 if (filter) { 0111 if (Kleo::any_of(KeyCache::instance()->keys(), [filter](const auto &key) { 0112 return filter->matches(key, KeyFilter::Filtering); 0113 })) { 0114 certifyButton->show(); 0115 return; 0116 } 0117 } else { 0118 qCDebug(KLEOPATRA_LOG) << __func__ << "Key filter with id" << notCertifiedKeysFilterId() << "not found"; 0119 } 0120 certifyButton->hide(); 0121 } 0122 0123 private: 0124 ProxyModel *proxyModel; 0125 QLineEdit *lineEdit; 0126 QComboBox *combo; 0127 QPushButton *certifyButton; 0128 }; 0129 0130 SearchBar::Private::Private(SearchBar *qq) 0131 : q(qq) 0132 { 0133 auto layout = new QHBoxLayout(q); 0134 layout->setContentsMargins(0, 0, 0, 0); 0135 lineEdit = new QLineEdit(q); 0136 lineEdit->setClearButtonEnabled(true); 0137 lineEdit->setPlaceholderText(i18n("Search...")); 0138 lineEdit->setAccessibleName(i18n("Filter certificates by text")); 0139 lineEdit->setToolTip(i18n("Show only certificates that match the entered search term.")); 0140 layout->addWidget(lineEdit, /*stretch=*/1); 0141 combo = new QComboBox(q); 0142 combo->setAccessibleName(i18n("Filter certificates by category")); 0143 combo->setToolTip(i18n("Show only certificates that belong to the selected category.")); 0144 layout->addWidget(combo); 0145 certifyButton = new QPushButton(q); 0146 certifyButton->setIcon(QIcon::fromTheme(QStringLiteral("security-medium"))); 0147 certifyButton->setAccessibleName(i18n("Show not certified certificates")); 0148 certifyButton->setToolTip( 0149 i18n("Some certificates are not yet certified. " 0150 "Click here to see a list of these certificates." 0151 "<br/><br/>" 0152 "Certification is required to make sure that the certificates " 0153 "actually belong to the identity they claim to belong to.")); 0154 certifyButton->hide(); 0155 layout->addWidget(certifyButton); 0156 0157 proxyModel = new ProxyModel{q}; 0158 proxyModel->setSourceModel(KeyFilterManager::instance()->model()); 0159 proxyModel->sort(0, Qt::AscendingOrder); 0160 combo->setModel(proxyModel); 0161 0162 KDAB_SET_OBJECT_NAME(layout); 0163 KDAB_SET_OBJECT_NAME(lineEdit); 0164 KDAB_SET_OBJECT_NAME(combo); 0165 KDAB_SET_OBJECT_NAME(certifyButton); 0166 0167 connect(lineEdit, &QLineEdit::textChanged, q, &SearchBar::stringFilterChanged); 0168 connect(combo, &QComboBox::currentIndexChanged, q, [this](int index) { 0169 slotKeyFilterChanged(index); 0170 }); 0171 connect(certifyButton, &QPushButton::clicked, q, [this]() { 0172 listNotCertifiedKeys(); 0173 }); 0174 0175 connect(KeyCache::instance().get(), &KeyCache::keyListingDone, q, [this]() { 0176 showOrHideCertifyButton(); 0177 }); 0178 showOrHideCertifyButton(); 0179 } 0180 0181 SearchBar::Private::~Private() 0182 { 0183 } 0184 0185 SearchBar::SearchBar(QWidget *parent, Qt::WindowFlags f) 0186 : QWidget(parent, f) 0187 , d(new Private(this)) 0188 { 0189 } 0190 0191 SearchBar::~SearchBar() 0192 { 0193 } 0194 0195 void SearchBar::updateClickMessage(const QString &shortcutStr) 0196 { 0197 d->lineEdit->setPlaceholderText(i18n("Search...<%1>", shortcutStr)); 0198 } 0199 0200 // slot 0201 void SearchBar::setStringFilter(const QString &filter) 0202 { 0203 d->lineEdit->setText(filter); 0204 } 0205 0206 // slot 0207 void SearchBar::setKeyFilter(const std::shared_ptr<KeyFilter> &kf) 0208 { 0209 const QModelIndex sourceIndex = KeyFilterManager::instance()->toModelIndex(kf); 0210 const QModelIndex proxyIndex = d->proxyModel->mapFromSource(sourceIndex); 0211 if (proxyIndex.isValid()) { 0212 d->combo->setCurrentIndex(proxyIndex.row()); 0213 } else { 0214 d->combo->setCurrentIndex(0); 0215 } 0216 } 0217 0218 // slot 0219 void SearchBar::setChangeStringFilterEnabled(bool on) 0220 { 0221 d->lineEdit->setEnabled(on); 0222 } 0223 0224 // slot 0225 void SearchBar::setChangeKeyFilterEnabled(bool on) 0226 { 0227 d->combo->setEnabled(on); 0228 } 0229 0230 QLineEdit *SearchBar::lineEdit() const 0231 { 0232 return d->lineEdit; 0233 } 0234 0235 #include "moc_searchbar.cpp" 0236 #include "searchbar.moc"