diff options
author | Saturneric <[email protected]> | 2023-07-13 07:39:41 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2023-07-13 07:39:41 +0000 |
commit | 77838db2af8dc4d665cb4dc3d6b30e6d58683091 (patch) | |
tree | 62c1bd7251bfc52b6a72f1814093782a0c214231 | |
parent | feat: support instant flush when save cache (diff) | |
download | GpgFrontend-77838db2af8dc4d665cb4dc3d6b30e6d58683091.tar.gz GpgFrontend-77838db2af8dc4d665cb4dc3d6b30e6d58683091.zip |
feat: support searching keys
-rw-r--r-- | src/ui/UserInterfaceUtils.cpp | 4 | ||||
-rw-r--r-- | src/ui/dialog/SignersPicker.cpp | 7 | ||||
-rw-r--r-- | src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp | 2 | ||||
-rw-r--r-- | src/ui/main_window/KeyMgmt.cpp | 14 | ||||
-rw-r--r-- | src/ui/main_window/MainWindow.cpp | 7 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowUI.cpp | 8 | ||||
-rw-r--r-- | src/ui/widgets/KeyList.cpp | 61 | ||||
-rw-r--r-- | src/ui/widgets/KeyList.h | 42 |
8 files changed, 113 insertions, 32 deletions
diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp index 3154aa2b..7e236c02 100644 --- a/src/ui/UserInterfaceUtils.cpp +++ b/src/ui/UserInterfaceUtils.cpp @@ -500,14 +500,14 @@ void CommonUtils::AddKey2Favourtie(const GpgKey &key) { nlohmann::json::array()); } key_array.push_back(key.GetFingerprint()); - CacheManager::GetInstance().SaveCache("favourite_key_pair", key_array); + CacheManager::GetInstance().SaveCache("favourite_key_pair", key_array, true); } void CommonUtils::RemoveKeyFromFavourite(const GpgKey &key) { auto key_array = CacheManager::GetInstance().LoadCache("favourite_key_pair"); if (!key_array.is_array()) { CacheManager::GetInstance().SaveCache("favourite_key_pair", - nlohmann::json::array()); + nlohmann::json::array(), true); return; } auto it = std::find(key_array.begin(), key_array.end(), key.GetFingerprint()); diff --git a/src/ui/dialog/SignersPicker.cpp b/src/ui/dialog/SignersPicker.cpp index 7e26de09..8969618e 100644 --- a/src/ui/dialog/SignersPicker.cpp +++ b/src/ui/dialog/SignersPicker.cpp @@ -36,9 +36,8 @@ SignersPicker::SignersPicker(QWidget* parent) auto confirm_button = new QPushButton(_("Confirm")); auto cancel_button = new QPushButton(_("Cancel")); - connect(confirm_button, &QPushButton::clicked, [=]() { - this->accepted_ = true; - }); + connect(confirm_button, &QPushButton::clicked, + [=]() { this->accepted_ = true; }); connect(confirm_button, &QPushButton::clicked, this, &QDialog::accept); connect(cancel_button, &QPushButton::clicked, this, &QDialog::reject); @@ -47,7 +46,7 @@ SignersPicker::SignersPicker(QWidget* parent) key_list_->AddListGroupTab( _("Signers"), "signers", KeyListRow::ONLY_SECRET_KEY, KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage, - [](const GpgKey& key) -> bool { + [](const GpgKey& key, const KeyTable&) -> bool { return key.IsHasActualSigningCapability(); }); key_list_->SlotRefresh(); diff --git a/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp b/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp index f0ab0a6e..12da3284 100644 --- a/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp +++ b/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp @@ -42,7 +42,7 @@ KeyUIDSignDialog::KeyUIDSignDialog(const GpgKey& key, UIDArgsListPtr uid, m_key_list_->AddListGroupTab( _("Signers"), "signers", KeyListRow::ONLY_SECRET_KEY, KeyListColumn::NAME | KeyListColumn::EmailAddress, - [key_id](const GpgKey& key) -> bool { + [key_id](const GpgKey& key, const KeyTable&) -> bool { if (key.IsDisabled() || !key.IsHasCertificationCapability() || !key.IsHasMasterKey() || key.IsExpired() || key.IsRevoked() || key_id == key.GetId()) diff --git a/src/ui/main_window/KeyMgmt.cpp b/src/ui/main_window/KeyMgmt.cpp index 9cd93985..47b0dcb0 100644 --- a/src/ui/main_window/KeyMgmt.cpp +++ b/src/ui/main_window/KeyMgmt.cpp @@ -54,7 +54,7 @@ KeyMgmt::KeyMgmt(QWidget* parent) _("Only Public Key"), "only_public_key", KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key) -> bool { + [](const GpgKey& key, const KeyTable&) -> bool { return !key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); @@ -63,7 +63,7 @@ KeyMgmt::KeyMgmt(QWidget* parent) _("Has Private Key"), "has_private_key", KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key) -> bool { + [](const GpgKey& key, const KeyTable&) -> bool { return key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); @@ -72,7 +72,7 @@ KeyMgmt::KeyMgmt(QWidget* parent) _("No Primary Key"), "no_primary_key", KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key) -> bool { + [](const GpgKey& key, const KeyTable&) -> bool { return !key.IsHasMasterKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); @@ -81,13 +81,17 @@ KeyMgmt::KeyMgmt(QWidget* parent) _("Revoked"), "revoked", KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key) -> bool { return key.IsRevoked(); }); + [](const GpgKey& key, const KeyTable&) -> bool { + return key.IsRevoked(); + }); key_list_->AddListGroupTab( _("Expired"), "expired", KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key) -> bool { return key.IsExpired(); }); + [](const GpgKey& key, const KeyTable&) -> bool { + return key.IsExpired(); + }); setCentralWidget(key_list_); key_list_->SetDoubleClickedAction([this](const GpgKey& key, QWidget* parent) { diff --git a/src/ui/main_window/MainWindow.cpp b/src/ui/main_window/MainWindow.cpp index 486cb47a..c31abeff 100644 --- a/src/ui/main_window/MainWindow.cpp +++ b/src/ui/main_window/MainWindow.cpp @@ -35,6 +35,7 @@ #include "ui/UserInterfaceUtils.h" #include "ui/struct/SettingsObject.h" #include "ui/thread/VersionCheckTask.h" +#include "widgets/KeyList.h" namespace GpgFrontend::UI { @@ -53,8 +54,10 @@ void MainWindow::Init() noexcept { setCentralWidget(edit_); /* the list of Keys available*/ - m_key_list_ = new KeyList( - KeyMenuAbility::REFRESH | KeyMenuAbility::UNCHECK_ALL, this); + m_key_list_ = + new KeyList(KeyMenuAbility::REFRESH | KeyMenuAbility::UNCHECK_ALL | + KeyMenuAbility::SEARCH_BAR, + this); info_board_ = new InfoBoardWidget(this); diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp index 77128ece..760561eb 100644 --- a/src/ui/main_window/MainWindowUI.cpp +++ b/src/ui/main_window/MainWindowUI.cpp @@ -609,7 +609,7 @@ void MainWindow::create_dock_windows() { _("Default"), "default", KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key) -> bool { + [](const GpgKey& key, const KeyTable&) -> bool { return !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); @@ -617,7 +617,7 @@ void MainWindow::create_dock_windows() { _("Favourite"), "favourite", KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key) -> bool { + [](const GpgKey& key, const KeyTable&) -> bool { return CommonUtils::GetInstance()->KeyExistsinFavouriteList(key); }); @@ -625,7 +625,7 @@ void MainWindow::create_dock_windows() { _("Only Public Key"), "only_public_key", KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key) -> bool { + [](const GpgKey& key, const KeyTable&) -> bool { return !key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); @@ -634,7 +634,7 @@ void MainWindow::create_dock_windows() { _("Has Private Key"), "has_private_key", KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key) -> bool { + [](const GpgKey& key, const KeyTable&) -> bool { return key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp index 51a2936a..e411e036 100644 --- a/src/ui/widgets/KeyList.cpp +++ b/src/ui/widgets/KeyList.cpp @@ -39,6 +39,7 @@ #include "ui/SignalStation.h" #include "ui/UserInterfaceUtils.h" #include "ui_KeyList.h" +#include "widgets/TextEdit.h" namespace GpgFrontend::UI { @@ -57,6 +58,7 @@ void KeyList::init() { KeyMenuAbility::REFRESH); ui_->syncButton->setHidden(~menu_ability_ & KeyMenuAbility::SYNC_PUBLIC_KEY); ui_->uncheckButton->setHidden(~menu_ability_ & KeyMenuAbility::UNCHECK_ALL); + ui_->searchBarEdit->setHidden(~menu_ability_ & KeyMenuAbility::SEARCH_BAR); ui_->keyGroupTab->clear(); popup_menu_ = new QMenu(this); @@ -87,6 +89,8 @@ void KeyList::init() { &KeyList::check_all); connect(ui_->syncButton, &QPushButton::clicked, this, &KeyList::slot_sync_with_key_server); + connect(ui_->searchBarEdit, &QLineEdit::textChanged, this, + &KeyList::filter_by_keyword); connect(this, &KeyList::SignalRefreshStatusBar, SignalStation::GetInstance(), &SignalStation::SignalRefreshStatusBar); @@ -104,12 +108,13 @@ void KeyList::init() { ui_->checkALLButton->setText(_("Check ALL")); ui_->checkALLButton->setToolTip( _("Check all items in the current tab at once")); + ui_->searchBarEdit->setPlaceholderText(_("Search for keys...")); } -void KeyList::AddListGroupTab( - const QString& name, const QString& id, KeyListRow::KeyType selectType, - KeyListColumn::InfoType infoType, - const std::function<bool(const GpgKey&)>& filter) { +void KeyList::AddListGroupTab(const QString& name, const QString& id, + KeyListRow::KeyType selectType, + KeyListColumn::InfoType infoType, + const KeyTable::KeyTableFilter filter) { SPDLOG_DEBUG("add tab: {}", name.toStdString()); auto key_list = new QTableWidget(this); @@ -119,6 +124,7 @@ void KeyList::AddListGroupTab( key_list->setObjectName(id); ui_->keyGroupTab->addTab(key_list, name); m_key_tables_.emplace_back(key_list, selectType, infoType, filter); + m_key_tables_.back().SetMenuAbility(menu_ability_); key_list->setColumnCount(7); key_list->horizontalHeader()->setSectionResizeMode( @@ -459,6 +465,7 @@ void KeyList::slot_refresh_ui() { SPDLOG_DEBUG("refresh: {}", static_cast<void*>(buffered_keys_list_.get())); if (buffered_keys_list_ != nullptr) { std::lock_guard<std::mutex> guard(buffered_key_list_mutex_); + for (auto& key_table : m_key_tables_) { key_table.Refresh( GpgKeyGetter::GetInstance().GetKeysCopy(buffered_keys_list_)); @@ -506,6 +513,20 @@ void KeyList::slot_sync_with_key_server() { }); } +void KeyList::filter_by_keyword() { + auto keyword = ui_->searchBarEdit->text(); + keyword = keyword.trimmed(); + + SPDLOG_DEBUG("get new keyword of search bar: {}", keyword.toStdString()); + for (auto& table : m_key_tables_) { + // refresh arguments + table.SetFilterKeyword(keyword.toLower().toStdString()); + table.SetMenuAbility(menu_ability_); + } + // refresh ui + SlotRefreshUI(); +} + void KeyList::uncheck_all() { auto key_list = qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); @@ -572,8 +593,30 @@ void KeyTable::Refresh(KeyLinkListPtr m_keys) { while (it != keys->end()) { SPDLOG_DEBUG("filtering key id: {}", it->GetId()); + // filter by search bar's keyword + if (ability_ & KeyMenuAbility::SEARCH_BAR && !keyword_.empty()) { + auto name = it->GetName(); + std::transform(name.begin(), name.end(), name.begin(), + [](unsigned char c) { return std::tolower(c); }); + + auto email = it->GetEmail(); + std::transform(email.begin(), email.end(), email.begin(), + [](unsigned char c) { return std::tolower(c); }); + + auto comment = it->GetComment(); + std::transform(comment.begin(), comment.end(), comment.begin(), + [](unsigned char c) { return std::tolower(c); }); + + if (name.find(keyword_) == std::string::npos && + email.find(keyword_) == std::string::npos && + comment.find(keyword_) == std::string::npos) { + it = keys->erase(it); + continue; + } + } + if (filter_ != nullptr) { - if (!filter_(*it)) { + if (!filter_(*it, *this)) { it = keys->erase(it); continue; } @@ -692,4 +735,12 @@ void KeyTable::CheckALL() const { key_list_->item(i, 0)->setCheckState(Qt::Checked); } } + +void KeyTable::SetMenuAbility(KeyMenuAbility::AbilityType ability) { + this->ability_ = ability; +} + +void KeyTable::SetFilterKeyword(std::string keyword) { + this->keyword_ = keyword; +} } // namespace GpgFrontend::UI diff --git a/src/ui/widgets/KeyList.h b/src/ui/widgets/KeyList.h index 63b5f7af..eb346740 100644 --- a/src/ui/widgets/KeyList.h +++ b/src/ui/widgets/KeyList.h @@ -29,6 +29,7 @@ #ifndef __KEYLIST_H__ #define __KEYLIST_H__ +#include <string> #include <utility> #include "core/GpgContext.h" @@ -78,6 +79,7 @@ struct KeyMenuAbility { static constexpr AbilityType SYNC_PUBLIC_KEY = 1 << 1; ///< static constexpr AbilityType UNCHECK_ALL = 1 << 3; ///< static constexpr AbilityType CHECK_ALL = 1 << 5; ///< + static constexpr AbilityType SEARCH_BAR = 1 << 6; ///< }; /** @@ -85,12 +87,16 @@ struct KeyMenuAbility { * */ struct KeyTable { - QTableWidget* key_list_; ///< - KeyListRow::KeyType select_type_; ///< - KeyListColumn::InfoType info_type_; ///< - std::vector<GpgKey> buffered_keys_; ///< - std::function<bool(const GpgKey&)> filter_; ///< - KeyIdArgsListPtr checked_key_ids_; ///< + using KeyTableFilter = std::function<bool(const GpgKey&, const KeyTable&)>; + + QTableWidget* key_list_; ///< + KeyListRow::KeyType select_type_; ///< + KeyListColumn::InfoType info_type_; ///< + std::vector<GpgKey> buffered_keys_; ///< + KeyTableFilter filter_; ///< + KeyIdArgsListPtr checked_key_ids_; ///< + KeyMenuAbility::AbilityType ability_; ///< + std::string keyword_; ///< /** * @brief Construct a new Key Table object @@ -103,7 +109,7 @@ struct KeyTable { KeyTable( QTableWidget* _key_list, KeyListRow::KeyType _select_type, KeyListColumn::InfoType _info_type, - std::function<bool(const GpgKey&)> _filter = [](const GpgKey&) -> bool { + KeyTableFilter _filter = [](const GpgKey&, const KeyTable&) -> bool { return true; }) : key_list_(_key_list), @@ -143,6 +149,18 @@ struct KeyTable { * @param key_ids */ void SetChecked(KeyIdArgsListPtr key_ids); + + /** + * @brief + * + */ + void SetMenuAbility(KeyMenuAbility::AbilityType ability); + + /** + * @brief + * + */ + void SetFilterKeyword(std::string keyword); }; /** @@ -174,8 +192,8 @@ class KeyList : public QWidget { const QString& name, const QString& id, KeyListRow::KeyType selectType = KeyListRow::SECRET_OR_PUBLIC_KEY, KeyListColumn::InfoType infoType = KeyListColumn::ALL, - const std::function<bool(const GpgKey&)>& filter = - [](const GpgKey&) -> bool { return true; }); + const KeyTable::KeyTableFilter filter = + [](const GpgKey&, const KeyTable&) -> bool { return true; }); /** * @brief Set the Double Clicked Action object @@ -335,6 +353,12 @@ class KeyList : public QWidget { */ void check_all(); + /** + * @brief + * + */ + void filter_by_keyword(); + std::mutex buffered_key_list_mutex_; ///< std::shared_ptr<Ui_KeyList> ui_; ///< |