aboutsummaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/SignalStation.h6
-rw-r--r--src/ui/UserInterfaceUtils.cpp40
-rw-r--r--src/ui/UserInterfaceUtils.h19
-rw-r--r--src/ui/dialog/SignersPicker.cpp9
-rw-r--r--src/ui/dialog/Wizard.cpp32
-rw-r--r--src/ui/dialog/help/AboutDialog.cpp4
-rw-r--r--src/ui/dialog/keypair_details/KeyPairDetailTab.cpp23
-rw-r--r--src/ui/dialog/keypair_details/KeyPairDetailTab.h1
-rw-r--r--src/ui/dialog/keypair_details/KeyPairOperaTab.cpp60
-rw-r--r--src/ui/dialog/keypair_details/KeyPairOperaTab.h13
-rw-r--r--src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp4
-rw-r--r--src/ui/dialog/settings/SettingsGeneral.cpp55
-rw-r--r--src/ui/main_window/GeneralMainWindow.cpp4
-rw-r--r--src/ui/main_window/KeyMgmt.cpp26
-rw-r--r--src/ui/main_window/MainWindow.cpp71
-rw-r--r--src/ui/main_window/MainWindow.h34
-rw-r--r--src/ui/main_window/MainWindowSlotFunction.cpp71
-rw-r--r--src/ui/main_window/MainWindowUI.cpp41
-rw-r--r--src/ui/widgets/FilePage.cpp21
-rw-r--r--src/ui/widgets/FilePage.h6
-rw-r--r--src/ui/widgets/KeyList.cpp96
-rw-r--r--src/ui/widgets/KeyList.h50
-rw-r--r--src/ui/widgets/TextEdit.cpp76
-rw-r--r--src/ui/widgets/TextEdit.h6
24 files changed, 686 insertions, 82 deletions
diff --git a/src/ui/SignalStation.h b/src/ui/SignalStation.h
index 5037ef4f..17e866f5 100644
--- a/src/ui/SignalStation.h
+++ b/src/ui/SignalStation.h
@@ -66,6 +66,12 @@ class SignalStation : public QObject {
/**
* @brief
*
+ */
+ void SignalUIRefresh();
+
+ /**
+ * @brief
+ *
* @param text
* @param verify_label_status
*/
diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp
index 80b6f482..7e236c02 100644
--- a/src/ui/UserInterfaceUtils.cpp
+++ b/src/ui/UserInterfaceUtils.cpp
@@ -34,6 +34,7 @@
#include "core/GpgConstants.h"
#include "core/common/CoreCommonUtil.h"
+#include "core/function/CacheManager.h"
#include "core/function/CoreSignalStation.h"
#include "core/function/FileOperator.h"
#include "core/function/GlobalSettingStation.h"
@@ -189,7 +190,7 @@ CommonUtils::CommonUtils() : QWidget(nullptr) {
msgBox.setText(_("GnuPG Context Loading Failed"));
msgBox.setInformativeText(
_("Gnupg(gpg) is not installed correctly, please follow "
- "<a href='https://www.gpgfrontend.pub/#/"
+ "<a href='https://www.gpgfrontend.bktus.com/#/"
"faq?id=how-to-deal-with-39env-loading-failed39'>this notes</a>"
" in FAQ to install Gnupg and then open "
"GpgFrontend. Or, you can open GnuPG Controller to set a custom "
@@ -481,4 +482,41 @@ bool CommonUtils::isApplicationNeedRestart() {
return application_need_to_restart_at_once_;
}
+bool CommonUtils::KeyExistsinFavouriteList(const GpgKey &key) {
+ // load cache
+ auto key_array = CacheManager::GetInstance().LoadCache("favourite_key_pair");
+ if (!key_array.is_array()) {
+ CacheManager::GetInstance().SaveCache("favourite_key_pair",
+ nlohmann::json::array());
+ }
+ return std::find(key_array.begin(), key_array.end(), key.GetFingerprint()) !=
+ key_array.end();
+}
+
+void CommonUtils::AddKey2Favourtie(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());
+ }
+ key_array.push_back(key.GetFingerprint());
+ 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(), true);
+ return;
+ }
+ auto it = std::find(key_array.begin(), key_array.end(), key.GetFingerprint());
+ if (it != key_array.end()) {
+ auto rm_it =
+ std::remove(key_array.begin(), key_array.end(), key.GetFingerprint());
+ key_array.erase(rm_it, key_array.end());
+ CacheManager::GetInstance().SaveCache("favourite_key_pair", key_array);
+ }
+}
+
} // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/src/ui/UserInterfaceUtils.h b/src/ui/UserInterfaceUtils.h
index 7dd7bb1e..59c803b9 100644
--- a/src/ui/UserInterfaceUtils.h
+++ b/src/ui/UserInterfaceUtils.h
@@ -31,6 +31,7 @@
#include "core/GpgModel.h"
#include "core/function/result_analyse/GpgVerifyResultAnalyse.h"
+#include "core/model/GpgKey.h"
#include "ui/GpgFrontendUI.h"
namespace GpgFrontend {
@@ -150,6 +151,24 @@ class CommonUtils : public QWidget {
*/
bool isApplicationNeedRestart();
+ /**
+ * @brief
+ *
+ */
+ bool KeyExistsinFavouriteList(const GpgKey& key);
+
+ /**
+ * @brief
+ *
+ */
+ void AddKey2Favourtie(const GpgKey& key);
+
+ /**
+ * @brief
+ *
+ */
+ void RemoveKeyFromFavourite(const GpgKey& key);
+
signals:
/**
* @brief
diff --git a/src/ui/dialog/SignersPicker.cpp b/src/ui/dialog/SignersPicker.cpp
index a670e514..8969618e 100644
--- a/src/ui/dialog/SignersPicker.cpp
+++ b/src/ui/dialog/SignersPicker.cpp
@@ -36,18 +36,17 @@ 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);
/*Setup KeyList*/
key_list_ = new KeyList(false, this);
key_list_->AddListGroupTab(
- _("Signers"), KeyListRow::ONLY_SECRET_KEY,
+ _("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/Wizard.cpp b/src/ui/dialog/Wizard.cpp
index 5235a5dd..77f07559 100644
--- a/src/ui/dialog/Wizard.cpp
+++ b/src/ui/dialog/Wizard.cpp
@@ -83,11 +83,11 @@ IntroPage::IntroPage(QWidget* parent) : QWizardPage(parent) {
auto* topLabel = new QLabel(
QString(_("Welcome to use GpgFrontend for decrypting and signing text or "
"file!")) +
- " <br><br><a href='https://gpgfrontend.pub'>GpgFrontend</a> " +
+ " <br><br><a href='https://gpgfrontend.bktus.com'>GpgFrontend</a> " +
_("is a Powerful, Easy-to-Use, Compact, Cross-Platform, and "
"Installation-Free OpenPGP Crypto Tool.") +
_("For brief information have a look at the") +
- " <a href='https://gpgfrontend.pub/index.html#/overview'>" +
+ " <a href='https://gpgfrontend.bktus.com/index.html#/overview'>" +
_("Overview") + "</a> (" +
_("by clicking the link, the page will open in the web browser") +
"). <br>");
@@ -124,7 +124,9 @@ ChoosePage::ChoosePage(QWidget* parent) : QWizardPage(parent) {
"If you have never used GpgFrontend before and also don't own a gpg "
"key yet you "
"may possibly want to read how to")) +
- " <a href=\"https://gpgfrontend.pub/index.html#/manual/generate-key\">" +
+ " <a "
+ "href=\"https://gpgfrontend.bktus.com/index.html#/manual/"
+ "generate-key\">" +
_("Generate Key") + "</a><hr>");
keygenLabel->setTextFormat(Qt::RichText);
keygenLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
@@ -136,11 +138,12 @@ ChoosePage::ChoosePage(QWidget* parent) : QWizardPage(parent) {
"If you want to learn how to encrypt, decrypt, sign and verify text, "
"you can read ")) +
"<a "
- "href=\"https://gpgfrontend.pub/index.html#/manual/"
+ "href=\"https://gpgfrontend.bktus.com/index.html#/manual/"
"encrypt-decrypt-text\">" +
_("Encrypt & Decrypt Text") + "</a> " + _("or") +
" <a "
- "href=\"https://gpgfrontend.pub/index.html#/manual/sign-verify-text\">" +
+ "href=\"https://gpgfrontend.bktus.com/index.html#/manual/"
+ "sign-verify-text\">" +
_("Sign & Verify Text") + "</a><hr>");
encrDecyTextLabel->setTextFormat(Qt::RichText);
@@ -148,15 +151,16 @@ ChoosePage::ChoosePage(QWidget* parent) : QWizardPage(parent) {
encrDecyTextLabel->setOpenExternalLinks(true);
encrDecyTextLabel->setWordWrap(true);
- auto* signVerifyTextLabel = new QLabel(
- QString(_("If you want to operate file, you can read ")) +
- "<a "
- "href=\"https://gpgfrontend.pub/index.html#/manual/"
- "encrypt-decrypt-file\">" +
- _("Encrypt & Sign File") + "</a> " + _("or") +
- " <a "
- "href=\"https://gpgfrontend.pub/index.html#/manual/sign-verify-file\">" +
- _("Sign & Verify File") + "</a><hr>");
+ auto* signVerifyTextLabel =
+ new QLabel(QString(_("If you want to operate file, you can read ")) +
+ "<a "
+ "href=\"https://gpgfrontend.bktus.com/index.html#/manual/"
+ "encrypt-decrypt-file\">" +
+ _("Encrypt & Sign File") + "</a> " + _("or") +
+ " <a "
+ "href=\"https://gpgfrontend.bktus.com/index.html#/manual/"
+ "sign-verify-file\">" +
+ _("Sign & Verify File") + "</a><hr>");
signVerifyTextLabel->setTextFormat(Qt::RichText);
signVerifyTextLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
signVerifyTextLabel->setOpenExternalLinks(true);
diff --git a/src/ui/dialog/help/AboutDialog.cpp b/src/ui/dialog/help/AboutDialog.cpp
index faf2b316..111a77af 100644
--- a/src/ui/dialog/help/AboutDialog.cpp
+++ b/src/ui/dialog/help/AboutDialog.cpp
@@ -231,7 +231,7 @@ void UpdateTab::slot_show_version_status(const SoftwareVersion& version) {
"github.")) +
"</center><center>" + _("Please click") +
" <a "
- "href=\"https://www.gpgfrontend.pub/#/downloads\">" +
+ "href=\"https://www.gpgfrontend.bktus.com/#/downloads\">" +
_("Here") + "</a> " + _("to download the latest stable version.") +
"</center>");
upgrade_label_->show();
@@ -254,7 +254,7 @@ void UpdateTab::slot_show_version_status(const SoftwareVersion& version) {
"stability, please do not use this version.")) +
"</center><center>" + _("Please click") +
" <a "
- "href=\"https://www.gpgfrontend.pub/#/downloads\">" +
+ "href=\"https://www.gpgfrontend.bktus.com/#/downloads\">" +
_("Here") + "</a> " + _("to download the latest stable version.") +
"</center>");
upgrade_label_->show();
diff --git a/src/ui/dialog/keypair_details/KeyPairDetailTab.cpp b/src/ui/dialog/keypair_details/KeyPairDetailTab.cpp
index 2785603b..578e3279 100644
--- a/src/ui/dialog/keypair_details/KeyPairDetailTab.cpp
+++ b/src/ui/dialog/keypair_details/KeyPairDetailTab.cpp
@@ -56,6 +56,7 @@ KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
usage_var_label_ = new QLabel();
actual_usage_var_label_ = new QLabel();
+ owner_trust_var_label_ = new QLabel();
key_size_var_label_ = new QLabel();
expire_var_label_ = new QLabel();
created_var_label_ = new QLabel();
@@ -79,13 +80,14 @@ KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
vboxKD->addWidget(new QLabel(QString(_("Key Size")) + ": "), 2, 0);
vboxKD->addWidget(new QLabel(QString(_("Nominal Usage")) + ": "), 3, 0);
vboxKD->addWidget(new QLabel(QString(_("Actual Usage")) + ": "), 4, 0);
+ vboxKD->addWidget(new QLabel(QString(_("Owner Trust Level")) + ": "), 5, 0);
vboxKD->addWidget(new QLabel(QString(_("Create Date (Local Time)")) + ": "),
- 5, 0);
- vboxKD->addWidget(new QLabel(QString(_("Expires on (Local Time)")) + ": "), 6,
+ 6, 0);
+ vboxKD->addWidget(new QLabel(QString(_("Expires on (Local Time)")) + ": "), 7,
0);
vboxKD->addWidget(new QLabel(QString(_("Last Update (Local Time)")) + ": "),
- 7, 0);
- vboxKD->addWidget(new QLabel(QString(_("Primary Key Existence")) + ": "), 8,
+ 8, 0);
+ vboxKD->addWidget(new QLabel(QString(_("Primary Key Existence")) + ": "), 9,
0);
key_id_var_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
@@ -94,10 +96,11 @@ KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent)
vboxKD->addWidget(key_size_var_label_, 2, 1, 1, 2);
vboxKD->addWidget(usage_var_label_, 3, 1, 1, 2);
vboxKD->addWidget(actual_usage_var_label_, 4, 1, 1, 2);
- vboxKD->addWidget(created_var_label_, 5, 1, 1, 2);
- vboxKD->addWidget(expire_var_label_, 6, 1, 1, 2);
- vboxKD->addWidget(last_update_var_label_, 7, 1, 1, 2);
- vboxKD->addWidget(primary_key_exist_var_label_, 8, 1, 1, 2);
+ vboxKD->addWidget(owner_trust_var_label_, 5, 1, 1, 2);
+ vboxKD->addWidget(created_var_label_, 6, 1, 1, 2);
+ vboxKD->addWidget(expire_var_label_, 7, 1, 1, 2);
+ vboxKD->addWidget(last_update_var_label_, 8, 1, 1, 2);
+ vboxKD->addWidget(primary_key_exist_var_label_, 9, 1, 1, 2);
auto* copyKeyIdButton = new QPushButton(_("Copy"));
copyKeyIdButton->setFlat(true);
@@ -222,7 +225,9 @@ void KeyPairDetailTab::slot_refresh_key_info() {
if (key_.IsHasActualAuthenticationCapability())
actual_usage_steam << _("Auth") << " ";
- actual_usage_var_label_->setText(actual_usage_steam.str().c_str());
+ actual_usage_var_label_->setText(
+ QString::fromStdString(actual_usage_steam.str()));
+ owner_trust_var_label_->setText(QString::fromStdString(key_.GetOwnerTrust()));
std::string key_size_val, key_expire_val, key_create_time_val, key_algo_val,
key_last_update_val;
diff --git a/src/ui/dialog/keypair_details/KeyPairDetailTab.h b/src/ui/dialog/keypair_details/KeyPairDetailTab.h
index 91ccdab8..efa3269c 100644
--- a/src/ui/dialog/keypair_details/KeyPairDetailTab.h
+++ b/src/ui/dialog/keypair_details/KeyPairDetailTab.h
@@ -79,6 +79,7 @@ class KeyPairDetailTab : public QWidget {
QLabel* usage_var_label_;
QLabel* actual_usage_var_label_;
QLabel* primary_key_exist_var_label_;
+ QLabel* owner_trust_var_label_;
QLabel* icon_label_; ///<
QLabel* exp_label_; ///<
diff --git a/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp b/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp
index 9be77923..13c857a0 100644
--- a/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp
+++ b/src/ui/dialog/keypair_details/KeyPairOperaTab.cpp
@@ -29,6 +29,7 @@
#include "KeySetExpireDateDialog.h"
#include "core/function/GlobalSettingStation.h"
#include "core/function/gpg/GpgKeyImportExporter.h"
+#include "core/function/gpg/GpgKeyManager.h"
#include "core/function/gpg/GpgKeyOpera.h"
#include "ui/SignalStation.h"
#include "ui/UserInterfaceUtils.h"
@@ -105,13 +106,25 @@ KeyPairOperaTab::KeyPairOperaTab(const std::string& key_id, QWidget* parent)
connect(modify_tofu_button, &QPushButton::clicked, this,
&KeyPairOperaTab::slot_modify_tofu_policy);
+ auto* set_owner_trust_level_button =
+ new QPushButton(_("Set Owner Trust Level"));
+ connect(set_owner_trust_level_button, &QPushButton::clicked, this,
+ &KeyPairOperaTab::slot_set_owner_trust_level);
+
vbox_p_k->addLayout(advance_h_box_layout);
opera_key_box->setLayout(vbox_p_k);
m_vbox->addWidget(opera_key_box);
+ // modify owner trust of public key
+ if (!m_key_.IsPrivateKey()) vbox_p_k->addWidget(set_owner_trust_level_button);
vbox_p_k->addWidget(modify_tofu_button);
m_vbox->addStretch(0);
setLayout(m_vbox);
+
+ // set up signal
+ connect(this, &KeyPairOperaTab::SignalKeyDatabaseRefresh,
+ SignalStation::GetInstance(),
+ &SignalStation::SignalKeyDatabaseRefresh);
}
void KeyPairOperaTab::CreateOperaMenu() {
@@ -389,4 +402,51 @@ void KeyPairOperaTab::slot_modify_tofu_policy() {
}
}
+void KeyPairOperaTab::slot_set_owner_trust_level() {
+ QStringList items;
+
+ items << _("Unknown") << _("Undefined") << _("Never") << _("Marginal")
+ << _("Full") << _("Ultimate");
+ bool ok;
+ QString item = QInputDialog::getItem(this, _("Modify Owner Trust Level"),
+ _("Trust for the Key Pair:"), items,
+ m_key_.GetOwnerTrustLevel(), false, &ok);
+
+ if (ok && !item.isEmpty()) {
+ SPDLOG_DEBUG("selected policy: {}", item.toStdString());
+ int trust_level = 0; // Unknown Level
+ if (item == _("Ultimate")) {
+ trust_level = 5;
+ } else if (item == _("Full")) {
+ trust_level = 4;
+ } else if (item == _("Marginal")) {
+ trust_level = 3;
+ } else if (item == _("Never")) {
+ trust_level = 2;
+ } else if (item == _("Undefined")) {
+ trust_level = 1;
+ }
+
+ if (trust_level == 0) {
+ QMessageBox::warning(
+ this, _("Warning"),
+ QString(_("Owner Trust Level cannot set to Unknown level, automately "
+ "changing it into Undefined level.")));
+ trust_level = 1;
+ }
+
+ bool status =
+ GpgKeyManager::GetInstance().SetOwnerTrustLevel(m_key_, trust_level);
+ if (!status) {
+ QMessageBox::critical(this, _("Failed"),
+ QString(_("Modify Owner Trust Level failed.")));
+ } else {
+ QMessageBox::information(this, _("Success"),
+ QString(_("Set Owner Trust Level successful.")));
+ // update key database and refresh ui
+ emit SignalKeyDatabaseRefresh();
+ }
+ }
+}
+
} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/keypair_details/KeyPairOperaTab.h b/src/ui/dialog/keypair_details/KeyPairOperaTab.h
index af6b1eee..0c4a7916 100644
--- a/src/ui/dialog/keypair_details/KeyPairOperaTab.h
+++ b/src/ui/dialog/keypair_details/KeyPairOperaTab.h
@@ -48,6 +48,13 @@ class KeyPairOperaTab : public QWidget {
*/
void CreateOperaMenu();
+ signals:
+ /**
+ * @brief
+ *
+ */
+ void SignalKeyDatabaseRefresh();
+
private slots:
/**
@@ -103,6 +110,12 @@ class KeyPairOperaTab : public QWidget {
*/
void slot_modify_tofu_policy();
+ /**
+ * @brief
+ *
+ */
+ void slot_set_owner_trust_level();
+
private:
GpgKey m_key_; ///<
QMenu* key_server_opera_menu_{}; ///<
diff --git a/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp b/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp
index ca83dbfd..12da3284 100644
--- a/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp
+++ b/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp
@@ -40,9 +40,9 @@ KeyUIDSignDialog::KeyUIDSignDialog(const GpgKey& key, UIDArgsListPtr uid,
const auto key_id = m_key_.GetId();
m_key_list_ = new KeyList(KeyMenuAbility::NONE, this);
m_key_list_->AddListGroupTab(
- _("Signers"), KeyListRow::ONLY_SECRET_KEY,
+ _("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/dialog/settings/SettingsGeneral.cpp b/src/ui/dialog/settings/SettingsGeneral.cpp
index c967b8fd..be5190dd 100644
--- a/src/ui/dialog/settings/SettingsGeneral.cpp
+++ b/src/ui/dialog/settings/SettingsGeneral.cpp
@@ -48,6 +48,9 @@ GeneralTab::GeneralTab(QWidget* parent)
_("Save checked private keys on exit and restore them on next start."));
ui_->clearGpgPasswordCacheCheckBox->setText(
_("Clear gpg password cache when closing GpgFrontend."));
+ ui_->restoreTextEditorPageCheckBox->setText(
+ _("Automatically restore unsaved Text Editor pages after an application "
+ "crash."));
ui_->importConfirmationBox->setTitle(_("Operation"));
ui_->longerKeyExpirationDateCheckBox->setText(
@@ -60,6 +63,16 @@ GeneralTab::GeneralTab(QWidget* parent)
"<b>" + QString(_("NOTE")) + _(": ") + "</b>" +
_("GpgFrontend will restart automatically if you change the language!"));
+ ui_->dataBox->setTitle(_("Data"));
+ ui_->clearAllLogFilesButton->setText(QString::fromStdString(
+ (boost::format(_("Clear All Log (Total Size: %s)")) %
+ GlobalSettingStation::GetInstance().GetLogFilesSize())
+ .str()));
+ ui_->clearAllDataObjectsButton->setText(QString::fromStdString(
+ (boost::format(_("Clear All Data Objects (Total Size: %s)")) %
+ GlobalSettingStation::GetInstance().GetDataObjectsFilesSize())
+ .str()));
+
#ifdef MULTI_LANG_SUPPORT
lang_ = SettingsDialog::ListLanguages();
for (const auto& l : lang_) {
@@ -69,6 +82,31 @@ GeneralTab::GeneralTab(QWidget* parent)
this, &GeneralTab::slot_language_changed);
#endif
+ connect(ui_->clearAllLogFilesButton, &QPushButton::clicked, this, [=]() {
+ GlobalSettingStation::GetInstance().ClearAllLogFiles();
+ ui_->clearAllLogFilesButton->setText(QString::fromStdString(
+ (boost::format(_("Clear All Log (Total Size: %s)")) %
+ GlobalSettingStation::GetInstance().GetLogFilesSize())
+ .str()));
+ });
+
+ connect(ui_->clearAllDataObjectsButton, &QPushButton::clicked, this, [=]() {
+ QMessageBox::StandardButton reply;
+ reply = QMessageBox::question(
+ this, _("Confirm"),
+ _("Are you sure you want to clear all data objects?\nThis will result "
+ "in "
+ "loss of all cached form positions, statuses, key servers, etc."),
+ QMessageBox::Yes | QMessageBox::No);
+ if (reply == QMessageBox::Yes) {
+ GlobalSettingStation::GetInstance().ClearAllDataObjects();
+ ui_->clearAllDataObjectsButton->setText(QString::fromStdString(
+ (boost::format(_("Clear All Data Objects (Total Size: %s)")) %
+ GlobalSettingStation::GetInstance().GetDataObjectsFilesSize())
+ .str()));
+ }
+ });
+
SetSettings();
}
@@ -98,6 +136,15 @@ void GeneralTab::SetSettings() {
}
try {
+ bool restore_text_editor_page =
+ settings.lookup("general.restore_text_editor_page");
+ if (restore_text_editor_page)
+ ui_->restoreTextEditorPageCheckBox->setCheckState(Qt::Checked);
+ } catch (...) {
+ SPDLOG_ERROR("setting operation error: restore_text_editor_page");
+ }
+
+ try {
bool longer_expiration_date =
settings.lookup("general.longer_expiration_date");
SPDLOG_DEBUG("longer_expiration_date: {}", longer_expiration_date);
@@ -170,6 +217,14 @@ void GeneralTab::ApplySettings() {
ui_->saveCheckedKeysCheckBox->isChecked();
}
+ if (!general.exists("restore_text_editor_page"))
+ general.add("restore_text_editor_page", libconfig::Setting::TypeBoolean) =
+ ui_->restoreTextEditorPageCheckBox->isChecked();
+ else {
+ general["restore_text_editor_page"] =
+ ui_->restoreTextEditorPageCheckBox->isChecked();
+ }
+
#ifdef MULTI_LANG_SUPPORT
if (!general.exists("lang"))
general.add("lang", libconfig::Setting::TypeBoolean) =
diff --git a/src/ui/main_window/GeneralMainWindow.cpp b/src/ui/main_window/GeneralMainWindow.cpp
index 66255a08..0acedec6 100644
--- a/src/ui/main_window/GeneralMainWindow.cpp
+++ b/src/ui/main_window/GeneralMainWindow.cpp
@@ -41,7 +41,9 @@ GpgFrontend::UI::GeneralMainWindow::GeneralMainWindow(std::string name,
GpgFrontend::UI::GeneralMainWindow::~GeneralMainWindow() = default;
void GpgFrontend::UI::GeneralMainWindow::closeEvent(QCloseEvent *event) {
+ SPDLOG_DEBUG("main window close event caught, event type: {}", event->type());
slot_save_settings();
+
QMainWindow::closeEvent(event);
}
@@ -51,6 +53,7 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept {
std::string window_state = general_windows_state.Check(
"window_state", saveState().toBase64().toStdString());
+ SPDLOG_DEBUG("restore main window state: {}", window_state);
// state sets pos & size of dock-widgets
this->restoreState(
@@ -133,6 +136,7 @@ void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept {
void GpgFrontend::UI::GeneralMainWindow::slot_save_settings() noexcept {
try {
+ SPDLOG_DEBUG("save main window state, name: {}", name_);
SettingsObject general_windows_state(name_ + "_state");
// window position and size
diff --git a/src/ui/main_window/KeyMgmt.cpp b/src/ui/main_window/KeyMgmt.cpp
index 758a7af1..47b0dcb0 100644
--- a/src/ui/main_window/KeyMgmt.cpp
+++ b/src/ui/main_window/KeyMgmt.cpp
@@ -48,46 +48,50 @@ KeyMgmt::KeyMgmt(QWidget* parent)
/* the list of Keys available*/
key_list_ = new KeyList(KeyMenuAbility::ALL, this);
- key_list_->AddListGroupTab(_("All"), KeyListRow::SECRET_OR_PUBLIC_KEY);
+ key_list_->AddListGroupTab(_("All"), "all", KeyListRow::SECRET_OR_PUBLIC_KEY);
key_list_->AddListGroupTab(
- _("Only Public Key"), KeyListRow::SECRET_OR_PUBLIC_KEY,
+ _("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());
});
key_list_->AddListGroupTab(
- _("Has Private Key"), KeyListRow::SECRET_OR_PUBLIC_KEY,
+ _("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());
});
key_list_->AddListGroupTab(
- _("No Primary Key"), KeyListRow::SECRET_OR_PUBLIC_KEY,
+ _("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());
});
key_list_->AddListGroupTab(
- _("Revoked"), KeyListRow::SECRET_OR_PUBLIC_KEY,
+ _("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"), KeyListRow::SECRET_OR_PUBLIC_KEY,
+ _("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 9e02c095..b07ad309 100644
--- a/src/ui/main_window/MainWindow.cpp
+++ b/src/ui/main_window/MainWindow.cpp
@@ -29,12 +29,17 @@
#include "MainWindow.h"
#include "core/GpgConstants.h"
+#include "core/function/CacheManager.h"
#include "core/function/GlobalSettingStation.h"
#include "core/function/gpg/GpgAdvancedOperator.h"
+#include "main_window/GeneralMainWindow.h"
+#include "nlohmann/json_fwd.hpp"
+#include "spdlog/spdlog.h"
#include "ui/SignalStation.h"
#include "ui/UserInterfaceUtils.h"
#include "ui/struct/SettingsObject.h"
#include "ui/thread/VersionCheckTask.h"
+#include "widgets/KeyList.h"
namespace GpgFrontend::UI {
@@ -53,8 +58,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);
@@ -80,6 +87,12 @@ void MainWindow::Init() noexcept {
SignalStation::GetInstance(),
&SignalStation::SignalRestartApplication);
+ connect(this, &MainWindow::SignalUIRefresh, SignalStation::GetInstance(),
+ &SignalStation::SignalUIRefresh);
+ connect(this, &MainWindow::SignalKeyDatabaseRefresh,
+ SignalStation::GetInstance(),
+ &SignalStation::SignalKeyDatabaseRefresh);
+
connect(edit_->tab_widget_, &QTabWidget::currentChanged, this,
&MainWindow::slot_disable_tab_actions);
connect(SignalStation::GetInstance(),
@@ -96,6 +109,10 @@ void MainWindow::Init() noexcept {
m_key_list_->AddMenuAction(copy_mail_address_to_clipboard_act_);
m_key_list_->AddMenuAction(copy_key_default_uid_to_clipboard_act_);
m_key_list_->AddMenuAction(copy_key_id_to_clipboard_act_);
+ m_key_list_->AddMenuAction(set_owner_trust_of_key_act_);
+ m_key_list_->AddMenuAction(add_key_2_favourtie_act_);
+ m_key_list_->AddMenuAction(remove_key_from_favourtie_act_);
+
m_key_list_->AddSeparator();
m_key_list_->AddMenuAction(show_key_details_act_);
@@ -155,6 +172,9 @@ void MainWindow::Init() noexcept {
}
});
+ // recover unsaved page from cache if it exists
+ recover_editor_unsaved_pages_from_cache();
+
} catch (...) {
SPDLOG_ERROR(_("Critical error occur while loading GpgFrontend."));
QMessageBox::critical(nullptr, _("Loading Failed"),
@@ -235,6 +255,40 @@ void MainWindow::restore_settings() {
SPDLOG_DEBUG("settings restored");
}
+void MainWindow::recover_editor_unsaved_pages_from_cache() {
+ auto unsaved_page_array =
+ CacheManager::GetInstance().LoadCache("editor_unsaved_pages");
+
+ if (!unsaved_page_array.is_array() || unsaved_page_array.empty()) {
+ return;
+ }
+
+ SPDLOG_DEBUG("plan ot recover unsaved page from cache, page array: {}",
+ unsaved_page_array.dump());
+
+ bool first = true;
+
+ for (auto &unsaved_page_json : unsaved_page_array) {
+ if (!unsaved_page_json.contains("title") ||
+ !unsaved_page_json.contains("content")) {
+ continue;
+ }
+ std::string title = unsaved_page_json["title"];
+ std::string content = unsaved_page_json["content"];
+
+ SPDLOG_DEBUG(
+ "recovering unsaved page from cache, page title: {}, content size",
+ title, content.size());
+
+ if (first) {
+ edit_->SlotCloseTab();
+ first = false;
+ }
+
+ edit_->SlotNewTabWithContent(title, content);
+ }
+}
+
void MainWindow::save_settings() {
bool save_key_checked = GlobalSettingStation::GetInstance().LookupSettings(
"general.save_key_checked", false);
@@ -277,8 +331,17 @@ void MainWindow::closeEvent(QCloseEvent *event) {
event->ignore();
}
- // clear password from memory
- // GpgContext::GetInstance().clearPasswordCache();
+ if (event->isAccepted()) {
+ // clear cache of unsaved page
+ CacheManager::GetInstance().SaveCache("editor_unsaved_pages",
+ nlohmann::json::array(), true);
+
+ // clear password from memory
+ // GpgContext::GetInstance().clearPasswordCache();
+
+ // call parent
+ GeneralMainWindow::closeEvent(event);
+ }
}
} // namespace GpgFrontend::UI
diff --git a/src/ui/main_window/MainWindow.h b/src/ui/main_window/MainWindow.h
index 8f0b2e4d..42f9daf3 100644
--- a/src/ui/main_window/MainWindow.h
+++ b/src/ui/main_window/MainWindow.h
@@ -97,6 +97,16 @@ class MainWindow : public GeneralMainWindow {
*/
void SignalRestartApplication(int);
+ /**
+ * @brief
+ */
+ void SignalUIRefresh();
+
+ /**
+ * @brief
+ */
+ void SignalKeyDatabaseRefresh();
+
public slots:
/**
@@ -307,6 +317,21 @@ class MainWindow : public GeneralMainWindow {
*/
void slot_version_upgrade(const SoftwareVersion& version);
+ /**
+ * @details
+ */
+ void slot_add_key_2_favourite();
+
+ /**
+ * @details
+ */
+ void slot_remove_key_from_favourite();
+
+ /**
+ * @details
+ */
+ void slot_set_owner_trust_level_of_key();
+
private:
/**
* @details Create actions for the main-menu and the context-menu of the
@@ -350,6 +375,11 @@ class MainWindow : public GeneralMainWindow {
void restore_settings();
/**
+ * @details
+ */
+ void recover_editor_unsaved_pages_from_cache();
+
+ /**
* @details Save settings to ini-file.
*/
void save_settings();
@@ -421,6 +451,10 @@ class MainWindow : public GeneralMainWindow {
QAction* copy_key_id_to_clipboard_act_{}; ///<
QAction* copy_key_default_uid_to_clipboard_act_{}; ///<
+ QAction* add_key_2_favourtie_act_{}; ///<
+ QAction* remove_key_from_favourtie_act_{}; ///<
+ QAction* set_owner_trust_of_key_act_{}; ///<
+
QAction* open_key_management_act_{}; ///< Action to open key management
QAction* copy_act_{}; ///< Action to copy text
QAction* quote_act_{}; ///< Action to quote text
diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp
index 841c8680..1adf2d4e 100644
--- a/src/ui/main_window/MainWindowSlotFunction.cpp
+++ b/src/ui/main_window/MainWindowSlotFunction.cpp
@@ -39,6 +39,7 @@
#include "core/function/gpg/GpgBasicOperator.h"
#include "core/function/gpg/GpgKeyGetter.h"
#include "core/function/gpg/GpgKeyImportExporter.h"
+#include "core/function/gpg/GpgKeyManager.h"
#include "dialog/SignersPicker.h"
#include "spdlog/spdlog.h"
#include "ui/UserInterfaceUtils.h"
@@ -747,6 +748,26 @@ void MainWindow::slot_show_key_details() {
}
}
+void MainWindow::slot_add_key_2_favourite() {
+ auto key_ids = m_key_list_->GetSelected();
+ if (key_ids->empty()) return;
+
+ auto key = GpgKeyGetter::GetInstance().GetKey(key_ids->front());
+ CommonUtils::GetInstance()->AddKey2Favourtie(key);
+
+ emit SignalUIRefresh();
+}
+
+void MainWindow::slot_remove_key_from_favourite() {
+ auto key_ids = m_key_list_->GetSelected();
+ if (key_ids->empty()) return;
+
+ auto key = GpgKeyGetter::GetInstance().GetKey(key_ids->front());
+ CommonUtils::GetInstance()->RemoveKeyFromFavourite(key);
+
+ emit SignalUIRefresh();
+}
+
void MainWindow::refresh_keys_from_key_server() {
auto key_ids = m_key_list_->GetSelected();
if (key_ids->empty()) return;
@@ -756,6 +777,56 @@ void MainWindow::refresh_keys_from_key_server() {
dialog->SlotImport(key_ids);
}
+void MainWindow::slot_set_owner_trust_level_of_key() {
+ auto key_ids = m_key_list_->GetSelected();
+ if (key_ids->empty()) return;
+
+ auto key = GpgKeyGetter::GetInstance().GetKey(key_ids->front());
+
+ QStringList items;
+
+ items << _("Unknown") << _("Undefined") << _("Never") << _("Marginal")
+ << _("Full") << _("Ultimate");
+ bool ok;
+ QString item = QInputDialog::getItem(this, _("Modify Owner Trust Level"),
+ _("Trust for the Key Pair:"), items,
+ key.GetOwnerTrustLevel(), false, &ok);
+
+ if (ok && !item.isEmpty()) {
+ SPDLOG_DEBUG("selected policy: {}", item.toStdString());
+ int trust_level = 0; // Unknown Level
+ if (item == _("Ultimate")) {
+ trust_level = 5;
+ } else if (item == _("Full")) {
+ trust_level = 4;
+ } else if (item == _("Marginal")) {
+ trust_level = 3;
+ } else if (item == _("Never")) {
+ trust_level = 2;
+ } else if (item == _("Undefined")) {
+ trust_level = 1;
+ }
+
+ if (trust_level == 0) {
+ QMessageBox::warning(
+ this, _("Warning"),
+ QString(_("Owner Trust Level cannot set to Unknown level, automately "
+ "changing it into Undefined level.")));
+ trust_level = 1;
+ }
+
+ bool status =
+ GpgKeyManager::GetInstance().SetOwnerTrustLevel(key, trust_level);
+ if (!status) {
+ QMessageBox::critical(this, _("Failed"),
+ QString(_("Modify Owner Trust Level failed.")));
+ } else {
+ // update key database and refresh ui
+ emit SignalKeyDatabaseRefresh();
+ }
+ }
+}
+
void MainWindow::upload_key_to_server() {
auto key_ids = m_key_list_->GetSelected();
auto* dialog = new KeyUploadDialog(key_ids, this);
diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp
index 6e664988..d1a3cb68 100644
--- a/src/ui/main_window/MainWindowUI.cpp
+++ b/src/ui/main_window/MainWindowUI.cpp
@@ -418,6 +418,27 @@ void MainWindow::create_actions() {
connect(show_key_details_act_, &QAction::triggered, this,
&MainWindow::slot_show_key_details);
+ add_key_2_favourtie_act_ = new QAction(_("Add To Favourite"), this);
+ add_key_2_favourtie_act_->setToolTip(_("Add this key to Favourite Table"));
+ add_key_2_favourtie_act_->setData(QVariant("add_key_2_favourite_action"));
+ connect(add_key_2_favourtie_act_, &QAction::triggered, this,
+ &MainWindow::slot_add_key_2_favourite);
+
+ remove_key_from_favourtie_act_ =
+ new QAction(_("Remove From Favourite"), this);
+ remove_key_from_favourtie_act_->setToolTip(
+ _("Remove this key from Favourite Table"));
+ remove_key_from_favourtie_act_->setData(
+ QVariant("remove_key_from_favourtie_action"));
+ connect(remove_key_from_favourtie_act_, &QAction::triggered, this,
+ &MainWindow::slot_remove_key_from_favourite);
+
+ set_owner_trust_of_key_act_ = new QAction(_("Set Owner Trust Level"), this);
+ set_owner_trust_of_key_act_->setToolTip(_("Set Owner Trust Level"));
+ set_owner_trust_of_key_act_->setData(QVariant("set_owner_trust_level"));
+ connect(set_owner_trust_of_key_act_, &QAction::triggered, this,
+ &MainWindow::slot_set_owner_trust_level_of_key);
+
/* Key-Shortcuts for Tab-Switchung-Action
*/
switch_tab_up_act_ = new QAction(this);
@@ -591,27 +612,35 @@ void MainWindow::create_dock_windows() {
addDockWidget(Qt::RightDockWidgetArea, key_list_dock_);
m_key_list_->AddListGroupTab(
- _("Default"), KeyListRow::SECRET_OR_PUBLIC_KEY,
+ _("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());
});
m_key_list_->AddListGroupTab(
- _("Only Public Key"), KeyListRow::SECRET_OR_PUBLIC_KEY,
+ _("Favourite"), "favourite", KeyListRow::SECRET_OR_PUBLIC_KEY,
+ KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress |
+ KeyListColumn::Usage | KeyListColumn::Validity,
+ [](const GpgKey& key, const KeyTable&) -> bool {
+ return CommonUtils::GetInstance()->KeyExistsinFavouriteList(key);
+ });
+
+ m_key_list_->AddListGroupTab(
+ _("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());
});
m_key_list_->AddListGroupTab(
- _("Has Private Key"), KeyListRow::SECRET_OR_PUBLIC_KEY,
+ _("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/FilePage.cpp b/src/ui/widgets/FilePage.cpp
index 144de3d8..b5243da0 100644
--- a/src/ui/widgets/FilePage.cpp
+++ b/src/ui/widgets/FilePage.cpp
@@ -249,14 +249,23 @@ void FilePage::create_popup_menu() {
connect(ui_->actionCompressFiles, &QAction::triggered, this,
&FilePage::slot_compress_files);
+ ui_->actionOpenWithSystemDefaultApplication->setText(
+ _("Open with Default System Application"));
+ connect(ui_->actionOpenWithSystemDefaultApplication, &QAction::triggered,
+ this, &FilePage::slot_open_item_by_system_application);
+
auto new_item_action_menu = new QMenu(this);
new_item_action_menu->setTitle(_("New"));
new_item_action_menu->addAction(ui_->actionCreateEmptyFile);
new_item_action_menu->addAction(ui_->actionMakeDirectory);
popup_menu_->addAction(ui_->actionOpenFile);
+ popup_menu_->addAction(ui_->actionOpenWithSystemDefaultApplication);
+
+ popup_menu_->addSeparator();
popup_menu_->addMenu(new_item_action_menu);
popup_menu_->addSeparator();
+
popup_menu_->addAction(ui_->actionRenameFile);
popup_menu_->addAction(ui_->actionDeleteFile);
popup_menu_->addAction(ui_->actionCompressFiles);
@@ -349,6 +358,18 @@ void FilePage::slot_open_item() {
}
}
+void FilePage::slot_open_item_by_system_application() {
+ QFileInfo info(QString::fromStdString(selected_path_.u8string()));
+ auto q_selected_path = QString::fromStdString(selected_path_.u8string());
+ if (info.isDir()) {
+ const auto file_path = info.filePath().toUtf8().toStdString();
+ QDesktopServices::openUrl(QUrl::fromLocalFile(q_selected_path));
+
+ } else {
+ QDesktopServices::openUrl(QUrl::fromLocalFile(q_selected_path));
+ }
+}
+
void FilePage::slot_rename_item() {
auto new_name_path = selected_path_, old_name_path = selected_path_;
auto old_name = old_name_path.filename();
diff --git a/src/ui/widgets/FilePage.h b/src/ui/widgets/FilePage.h
index 8e278de7..74548b13 100644
--- a/src/ui/widgets/FilePage.h
+++ b/src/ui/widgets/FilePage.h
@@ -114,6 +114,12 @@ class FilePage : public QWidget {
* @brief
*
*/
+ void slot_open_item_by_system_application();
+
+ /**
+ * @brief
+ *
+ */
void slot_rename_item();
/**
diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp
index 2d4c925a..e411e036 100644
--- a/src/ui/widgets/KeyList.cpp
+++ b/src/ui/widgets/KeyList.cpp
@@ -35,9 +35,11 @@
#include "core/GpgCoreInit.h"
#include "core/function/GlobalSettingStation.h"
#include "core/function/gpg/GpgKeyGetter.h"
+#include "spdlog/spdlog.h"
#include "ui/SignalStation.h"
#include "ui/UserInterfaceUtils.h"
#include "ui_KeyList.h"
+#include "widgets/TextEdit.h"
namespace GpgFrontend::UI {
@@ -56,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);
@@ -73,6 +76,8 @@ void KeyList::init() {
connect(SignalStation::GetInstance(),
&SignalStation::SignalKeyDatabaseRefreshDone, this,
&KeyList::SlotRefresh);
+ connect(SignalStation::GetInstance(), &SignalStation::SignalUIRefresh, this,
+ &KeyList::SlotRefreshUI);
// register key database sync signal for refresh button
connect(ui_->refreshKeyListButton, &QPushButton::clicked, this,
@@ -84,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);
@@ -101,20 +108,23 @@ 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, 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);
if (m_key_list_ == nullptr) {
m_key_list_ = key_list;
}
+ 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(
@@ -155,7 +165,7 @@ void KeyList::AddListGroupTab(
QStringList labels;
labels << _("Select") << _("Type") << _("Name") << _("Email Address")
- << _("Usage") << _("Validity") << _("Finger Print");
+ << _("Usage") << _("Trust") << _("Finger Print");
key_list->setHorizontalHeaderLabels(labels);
key_list->horizontalHeader()->setStretchLastSection(false);
@@ -175,6 +185,11 @@ void KeyList::SlotRefresh() {
this->slot_refresh_ui();
}
+void KeyList::SlotRefreshUI() {
+ SPDLOG_DEBUG("refresh, address: {}", static_cast<void*>(this));
+ this->slot_refresh_ui();
+}
+
KeyIdArgsListPtr KeyList::GetChecked(const KeyTable& key_table) {
auto ret = std::make_unique<KeyIdArgsList>();
for (int i = 0; i < key_table.key_list_->rowCount(); i++) {
@@ -297,6 +312,30 @@ void KeyList::contextMenuEvent(QContextMenuEvent* event) {
if (ui_->keyGroupTab->size().isEmpty()) return;
m_key_list_ = qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget());
+ QString current_tab_widget_obj_name =
+ ui_->keyGroupTab->widget(ui_->keyGroupTab->currentIndex())->objectName();
+ SPDLOG_DEBUG("current tab widget object name: {}",
+ current_tab_widget_obj_name.toStdString());
+ if (current_tab_widget_obj_name == "favourite") {
+ QList<QAction*> actions = popup_menu_->actions();
+ for (QAction* action : actions) {
+ if (action->data().toString() == "remove_key_from_favourtie_action") {
+ action->setVisible(true);
+ } else if (action->data().toString() == "add_key_2_favourite_action") {
+ action->setVisible(false);
+ }
+ }
+ } else {
+ QList<QAction*> actions = popup_menu_->actions();
+ for (QAction* action : actions) {
+ if (action->data().toString() == "remove_key_from_favourtie_action") {
+ action->setVisible(false);
+ } else if (action->data().toString() == "add_key_2_favourite_action") {
+ action->setVisible(true);
+ }
+ }
+ }
+
if (m_key_list_->selectedItems().length() > 0) {
popup_menu_->exec(event->globalPos());
}
@@ -426,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_));
@@ -473,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());
@@ -539,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;
}
@@ -659,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 f1c88cc6..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);
};
/**
@@ -171,11 +189,11 @@ class KeyList : public QWidget {
* @param filter
*/
void AddListGroupTab(
- const QString& name,
+ 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
@@ -303,6 +321,12 @@ class KeyList : public QWidget {
*/
void SlotRefresh();
+ /**
+ * @brief
+ *
+ */
+ void SlotRefreshUI();
+
private:
/**
* @brief
@@ -329,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_; ///<
diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp
index d22c091a..7af4d5f8 100644
--- a/src/ui/widgets/TextEdit.cpp
+++ b/src/ui/widgets/TextEdit.cpp
@@ -33,6 +33,9 @@
#include <tuple>
#include <vector>
+#include "core/function/CacheManager.h"
+#include "core/function/GlobalSettingStation.h"
+#include "nlohmann/json_fwd.hpp"
#include "spdlog/spdlog.h"
namespace GpgFrontend::UI {
@@ -70,6 +73,33 @@ void TextEdit::SlotNewTab() {
this, &TextEdit::slot_save_status_to_cache_for_revovery);
}
+void TextEdit::SlotNewTabWithContent(std::string title,
+ const std::string& content) {
+ QString header = _("untitled") + QString::number(++count_page_) + ".txt";
+ if (!title.empty()) {
+ // modify title
+ if (!title.empty() && title[0] == '*') {
+ title.erase(0, 1);
+ }
+ // set title
+ header = QString::fromStdString(title);
+ }
+
+ auto* page = new PlainTextEditorPage();
+ auto index = tab_widget_->addTab(page, header);
+ tab_widget_->setTabIcon(index, QIcon(":file.png"));
+ tab_widget_->setCurrentIndex(tab_widget_->count() - 1);
+ page->GetTextPage()->setFocus();
+ connect(page->GetTextPage()->document(), &QTextDocument::modificationChanged,
+ this, &TextEdit::SlotShowModified);
+ connect(page->GetTextPage()->document(), &QTextDocument::contentsChanged,
+ this, &TextEdit::slot_save_status_to_cache_for_revovery);
+
+ // set content with modified status
+ page->GetTextPage()->document()->setPlainText(
+ QString::fromStdString(content));
+}
+
void TextEdit::slotNewHelpTab(const QString& title, const QString& path) const {
auto* page = new HelpPage(path);
tab_widget_->addTab(page, title);
@@ -599,15 +629,29 @@ void TextEdit::slot_file_page_path_changed(const QString& path) const {
}
void TextEdit::slot_save_status_to_cache_for_revovery() {
- SPDLOG_DEBUG("catch text page modified event, count: {}",
- text_page_data_modified_count_);
- if (this->text_page_data_modified_count_++ % 3 != 0) return;
+ if (this->text_page_data_modified_count_++ % 8 != 0) return;
+
+ auto& settings = GlobalSettingStation::GetInstance().GetUISettings();
+ bool restore_text_editor_page = false;
+ try {
+ restore_text_editor_page =
+ settings.lookup("general.restore_text_editor_page");
+ } catch (...) {
+ SPDLOG_ERROR("setting operation error: restore_text_editor_page");
+ }
+
+ if (!restore_text_editor_page) {
+ SPDLOG_DEBUG("restore_text_editor_page is false, ignoring...");
+ return;
+ }
-#ifdef DEBUG
int tab_count = tab_widget_->count();
- SPDLOG_DEBUG("current tabs count {}", tab_count);
+ SPDLOG_DEBUG(
+ "restore_text_editor_page is true, pan to save pages, current tabs "
+ "count: "
+ "{}",
+ tab_count);
- std::vector<std::pair<int, std::string>> saved_pages;
std::vector<std::tuple<int, std::string, std::string>> unsaved_pages;
for (int i = 0; i < tab_count; i++) {
@@ -623,11 +667,6 @@ void TextEdit::slot_save_status_to_cache_for_revovery() {
auto tab_title = tab_widget_->tabText(i).toStdString();
if (!target_page->ReadDone() || !target_page->isEnabled() ||
!document->isModified()) {
- auto file_path = target_page->GetFilePath().toStdString();
- SPDLOG_DEBUG("saved page index: {}, tab title: {} tab file path: {}", i,
- tab_title, file_path);
-
- saved_pages.push_back({i, file_path});
continue;
}
@@ -636,7 +675,20 @@ void TextEdit::slot_save_status_to_cache_for_revovery() {
tab_title, raw_text.size());
unsaved_pages.push_back({i, tab_title, raw_text});
}
-#endif
+
+ nlohmann::json unsaved_page_array = nlohmann::json::array();
+ for (const auto& page : unsaved_pages) {
+ nlohmann::json page_json;
+ page_json["index"] = std::get<0>(page);
+ page_json["title"] = std::get<1>(page);
+ page_json["content"] = std::get<2>(page);
+
+ unsaved_page_array.push_back(page_json);
+ }
+
+ SPDLOG_DEBUG("unsaved page json array: {}", unsaved_page_array.dump());
+ CacheManager::GetInstance().SaveCache("editor_unsaved_pages",
+ unsaved_page_array);
}
} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/TextEdit.h b/src/ui/widgets/TextEdit.h
index 2e2f949d..f69bda4c 100644
--- a/src/ui/widgets/TextEdit.h
+++ b/src/ui/widgets/TextEdit.h
@@ -151,6 +151,12 @@ class TextEdit : public QWidget {
void SlotNewTab();
/**
+ * @details
+ *
+ */
+ void SlotNewTabWithContent(std::string title, const std::string& content);
+
+ /**
* @details Adds a new tab with opening file by path
*/
void SlotOpenFile(const QString& path);