aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaturneric <[email protected]>2023-07-13 07:39:41 +0000
committerSaturneric <[email protected]>2023-07-13 07:39:41 +0000
commit77838db2af8dc4d665cb4dc3d6b30e6d58683091 (patch)
tree62c1bd7251bfc52b6a72f1814093782a0c214231
parentfeat: support instant flush when save cache (diff)
downloadGpgFrontend-77838db2af8dc4d665cb4dc3d6b30e6d58683091.tar.gz
GpgFrontend-77838db2af8dc4d665cb4dc3d6b30e6d58683091.zip
feat: support searching keys
-rw-r--r--src/ui/UserInterfaceUtils.cpp4
-rw-r--r--src/ui/dialog/SignersPicker.cpp7
-rw-r--r--src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp2
-rw-r--r--src/ui/main_window/KeyMgmt.cpp14
-rw-r--r--src/ui/main_window/MainWindow.cpp7
-rw-r--r--src/ui/main_window/MainWindowUI.cpp8
-rw-r--r--src/ui/widgets/KeyList.cpp61
-rw-r--r--src/ui/widgets/KeyList.h42
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_; ///<