aboutsummaryrefslogtreecommitdiffstats
path: root/src/ui/dialog/controller/GnuPGControllerDialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/dialog/controller/GnuPGControllerDialog.cpp')
-rw-r--r--src/ui/dialog/controller/GnuPGControllerDialog.cpp406
1 files changed, 406 insertions, 0 deletions
diff --git a/src/ui/dialog/controller/GnuPGControllerDialog.cpp b/src/ui/dialog/controller/GnuPGControllerDialog.cpp
new file mode 100644
index 00000000..b35d2a7d
--- /dev/null
+++ b/src/ui/dialog/controller/GnuPGControllerDialog.cpp
@@ -0,0 +1,406 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "GnuPGControllerDialog.h"
+
+#include "core/GpgModel.h"
+#include "core/function/GlobalSettingStation.h"
+#include "core/module/ModuleManager.h"
+#include "ui/UISignalStation.h"
+#include "ui/dialog/GeneralDialog.h"
+#include "ui_GnuPGControllerDialog.h"
+
+namespace GpgFrontend::UI {
+
+GnuPGControllerDialog::GnuPGControllerDialog(QWidget* parent)
+ : GeneralDialog("GnuPGControllerDialog", parent),
+ ui_(GpgFrontend::SecureCreateSharedObject<Ui_GnuPGControllerDialog>()) {
+ ui_->setupUi(this);
+
+ ui_->generalBox->setTitle(tr("General"));
+ ui_->keyDatabaseGroupBox->setTitle(tr("Key Database"));
+ ui_->advanceGroupBox->setTitle(tr("Advanced"));
+
+ ui_->asciiModeCheckBox->setText(tr("Use Binary Mode for File Operations"));
+ ui_->usePinentryAsPasswordInputDialogCheckBox->setText(
+ tr("Use Pinentry as Password Input Dialog"));
+ ui_->gpgmeDebugLogCheckBox->setText(tr("Enable GpgME Debug Log"));
+ ui_->useCustomGnuPGInstallPathCheckBox->setText(tr("Use Custom GnuPG"));
+ ui_->useCustomGnuPGInstallPathButton->setText(tr("Select GnuPG Path"));
+ ui_->keyDatabaseUseCustomCheckBox->setText(
+ tr("Use Custom GnuPG Key Database Path"));
+ ui_->customKeyDatabasePathSelectButton->setText(
+ tr("Select Key Database Path"));
+ ui_->restartGpgAgentOnStartCheckBox->setText(
+ tr("Restart Gpg Agent on start"));
+ ui_->killAllGnuPGDaemonCheckBox->setText(
+ tr("Kill all gnupg daemon at close"));
+
+ // tips
+ ui_->customGnuPGPathTipsLabel->setText(
+ tr("Tips: please select a directory where \"gpgconf\" is located in."));
+ ui_->restartTipsLabel->setText(
+ tr("Tips: notice that modify any of these settings will cause an "
+ "Application restart."));
+
+ // announce main window
+ connect(this, &GnuPGControllerDialog::SignalRestartNeeded,
+ UISignalStation::GetInstance(),
+ &UISignalStation::SignalRestartApplication);
+
+ connect(ui_->keyDatabaseUseCustomCheckBox, &QCheckBox::stateChanged, this,
+ [=](int state) {
+ ui_->customKeyDatabasePathSelectButton->setDisabled(
+ state != Qt::CheckState::Checked);
+ });
+
+ connect(ui_->useCustomGnuPGInstallPathCheckBox, &QCheckBox::stateChanged,
+ this, [=](int state) {
+ ui_->useCustomGnuPGInstallPathButton->setDisabled(
+ state != Qt::CheckState::Checked);
+ });
+
+ connect(ui_->keyDatabaseUseCustomCheckBox, &QCheckBox::stateChanged, this,
+ &GnuPGControllerDialog::slot_update_custom_key_database_path_label);
+
+ connect(ui_->useCustomGnuPGInstallPathCheckBox, &QCheckBox::stateChanged,
+ this,
+ &GnuPGControllerDialog::slot_update_custom_gnupg_install_path_label);
+
+ connect(
+ ui_->customKeyDatabasePathSelectButton, &QPushButton::clicked, this,
+ [=]() {
+ QString selected_custom_key_database_path =
+ QFileDialog::getExistingDirectory(
+ this, tr("Open Directory"), {},
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+
+ GF_UI_LOG_DEBUG("key database path selected: {}",
+ selected_custom_key_database_path);
+
+ custom_key_database_path_ = selected_custom_key_database_path;
+
+ // announce the restart
+ this->slot_set_restart_needed(kDeepRestartCode);
+
+ // update ui
+ this->slot_update_custom_key_database_path_label(
+ this->ui_->keyDatabaseUseCustomCheckBox->checkState());
+ });
+
+ connect(
+ ui_->useCustomGnuPGInstallPathButton, &QPushButton::clicked, this, [=]() {
+ QString selected_custom_gnupg_install_path =
+ QFileDialog::getExistingDirectory(
+ this, tr("Open Directory"), {},
+ QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+
+ GF_UI_LOG_DEBUG("gnupg install path selected: {}",
+ selected_custom_gnupg_install_path);
+
+ custom_gnupg_path_ = selected_custom_gnupg_install_path;
+
+ // announce the restart
+ this->slot_set_restart_needed(kDeepRestartCode);
+
+ // update ui
+ this->slot_update_custom_gnupg_install_path_label(
+ this->ui_->useCustomGnuPGInstallPathCheckBox->checkState());
+ });
+
+ connect(ui_->usePinentryAsPasswordInputDialogCheckBox,
+ &QCheckBox::stateChanged, this, [=](int) {
+ // announce the restart
+ this->slot_set_restart_needed(kDeepRestartCode);
+ });
+
+ connect(ui_->gpgmeDebugLogCheckBox, &QCheckBox::stateChanged, this, [=](int) {
+ // announce the restart
+ this->slot_set_restart_needed(kDeepRestartCode);
+ });
+
+ connect(ui_->asciiModeCheckBox, &QCheckBox::stateChanged, this, [=](int) {
+ // announce the restart
+ this->slot_set_restart_needed(kDeepRestartCode);
+ });
+
+ connect(ui_->restartGpgAgentOnStartCheckBox, &QCheckBox::stateChanged, this,
+ [=](int) {
+ // announce the restart
+ this->slot_set_restart_needed(kDeepRestartCode);
+ });
+
+#ifndef MACOS
+ connect(ui_->buttonBox, &QDialogButtonBox::accepted, this,
+ &GnuPGControllerDialog::SlotAccept);
+ connect(ui_->buttonBox, &QDialogButtonBox::rejected, this,
+ &GnuPGControllerDialog::reject);
+#else
+
+ // macOS style settings
+ ui_->buttonBox->setDisabled(true);
+ ui_->buttonBox->setHidden(true);
+
+ connect(this, &QDialog::finished, this, &GnuPGControllerDialog::SlotAccept);
+ connect(this, &QDialog::finished, this, &GnuPGControllerDialog::deleteLater);
+#endif
+
+ setWindowTitle(tr("GnuPG Controller"));
+ set_settings();
+}
+
+void GnuPGControllerDialog::SlotAccept() {
+ apply_settings();
+
+ GF_UI_LOG_DEBUG("gnupg controller apply done");
+ GF_UI_LOG_DEBUG("restart needed: {}", get_restart_needed());
+ if (get_restart_needed() != 0) {
+ emit SignalRestartNeeded(get_restart_needed());
+ }
+ close();
+}
+
+void GnuPGControllerDialog::slot_update_custom_key_database_path_label(
+ int state) {
+ // hide label (not necessary to show the default path)
+ this->ui_->currentKeyDatabasePathLabel->setHidden(state !=
+ Qt::CheckState::Checked);
+ if (state == Qt::CheckState::Checked) {
+ if (custom_key_database_path_.isEmpty()) {
+ // read from settings file
+ QString custom_key_database_path =
+ GlobalSettingStation::GetInstance()
+ .GetSettings()
+ .value("gnupg/custom_key_database_path")
+ .toString();
+ GF_UI_LOG_DEBUG("selected_custom_key_database_path from settings: {}",
+ custom_key_database_path);
+ custom_key_database_path_ = custom_key_database_path;
+ }
+
+ // notify the user
+ if (!check_custom_gnupg_key_database_path(custom_key_database_path_)) {
+ return;
+ };
+
+ // set label value
+ if (!custom_key_database_path_.isEmpty()) {
+ ui_->currentKeyDatabasePathLabel->setText(custom_key_database_path_);
+ }
+ }
+
+ if (ui_->currentKeyDatabasePathLabel->text().isEmpty()) {
+ const auto database_path = Module::RetrieveRTValueTypedOrDefault<>(
+ "core", "gpgme.ctx.database_path", QString{});
+ GF_UI_LOG_DEBUG("got gpgme.ctx.database_path from rt: {}", database_path);
+ ui_->currentKeyDatabasePathLabel->setText(database_path);
+ }
+}
+
+void GnuPGControllerDialog::slot_update_custom_gnupg_install_path_label(
+ int state) {
+ // hide label (not necessary to show the default path)
+ this->ui_->currentCustomGnuPGInstallPathLabel->setHidden(
+ state != Qt::CheckState::Checked);
+ do {
+ if (state == Qt::CheckState::Checked) {
+ if (custom_gnupg_path_.isEmpty()) {
+ // read from settings file
+ QString custom_gnupg_install_path =
+ GlobalSettingStation::GetInstance()
+ .GetSettings()
+ .value("gnupg/custom_gnupg_install_path")
+ .toString();
+ GF_UI_LOG_DEBUG("custom_gnupg_install_path from settings: {}",
+ custom_gnupg_install_path);
+ custom_gnupg_path_ = custom_gnupg_install_path;
+ }
+
+ // notify the user
+ if (!check_custom_gnupg_path(custom_gnupg_path_)) {
+ break;
+ }
+
+ // set label value
+ if (!custom_gnupg_path_.isEmpty()) {
+ ui_->currentCustomGnuPGInstallPathLabel->setText(custom_gnupg_path_);
+ }
+ }
+ } while (false);
+
+ if (ui_->currentCustomGnuPGInstallPathLabel->text().isEmpty()) {
+ const auto gnupg_path = Module::RetrieveRTValueTypedOrDefault<>(
+ "core", "gpgme.ctx.app_path", QString{});
+ GF_UI_LOG_DEBUG("got gnupg home path from rt: {}", gnupg_path);
+ auto dir = QFileInfo(gnupg_path).path();
+ ui_->currentCustomGnuPGInstallPathLabel->setText(dir);
+ }
+}
+
+void GnuPGControllerDialog::set_settings() {
+ auto settings = GlobalSettingStation::GetInstance().GetSettings();
+
+ auto non_ascii_at_file_operation =
+ settings.value("gnupg/non_ascii_at_file_operation", true).toBool();
+ if (non_ascii_at_file_operation) {
+ ui_->asciiModeCheckBox->setCheckState(Qt::Checked);
+ }
+
+ auto use_custom_key_database_path =
+ settings.value("gnupg/use_custom_key_database_path", false).toBool();
+ if (use_custom_key_database_path) {
+ ui_->keyDatabaseUseCustomCheckBox->setCheckState(Qt::Checked);
+ }
+
+ auto enable_gpgme_debug_log =
+ settings.value("gnupg/enable_gpgme_debug_log", false).toBool();
+ if (enable_gpgme_debug_log) {
+ ui_->gpgmeDebugLogCheckBox->setCheckState(Qt::Checked);
+ }
+
+ auto kill_all_gnupg_daemon_at_close =
+ settings.value("gnupg/kill_all_gnupg_daemon_at_close", false).toBool();
+ if (kill_all_gnupg_daemon_at_close) {
+ ui_->killAllGnuPGDaemonCheckBox->setCheckState(Qt::Checked);
+ }
+
+ this->slot_update_custom_key_database_path_label(
+ ui_->keyDatabaseUseCustomCheckBox->checkState());
+
+ auto use_custom_gnupg_install_path =
+ settings.value("gnupg/use_custom_gnupg_install_path", false).toBool();
+ if (use_custom_gnupg_install_path) {
+ ui_->useCustomGnuPGInstallPathCheckBox->setCheckState(Qt::Checked);
+ }
+
+ auto use_pinentry_as_password_input_dialog =
+ settings
+ .value("gnupg/use_pinentry_as_password_input_dialog",
+ QString::fromLocal8Bit(qgetenv("container")) != "flatpak")
+ .toBool();
+ if (use_pinentry_as_password_input_dialog) {
+ ui_->usePinentryAsPasswordInputDialogCheckBox->setCheckState(Qt::Checked);
+ }
+
+ auto restart_gpg_agent_on_start =
+ settings.value("gnupg/restart_gpg_agent_on_start", false).toBool();
+ if (restart_gpg_agent_on_start) {
+ ui_->restartGpgAgentOnStartCheckBox->setCheckState(Qt::Checked);
+ }
+
+ this->slot_update_custom_key_database_path_label(
+ use_custom_key_database_path ? Qt::Checked : Qt::Unchecked);
+
+ this->slot_update_custom_gnupg_install_path_label(
+ use_custom_gnupg_install_path ? Qt::Checked : Qt::Unchecked);
+
+ this->slot_set_restart_needed(kNonRestartCode);
+}
+
+void GnuPGControllerDialog::apply_settings() {
+ auto settings =
+ GpgFrontend::GlobalSettingStation::GetInstance().GetSettings();
+
+ settings.setValue("gnupg/non_ascii_at_file_operation",
+ ui_->asciiModeCheckBox->isChecked());
+ settings.setValue("gnupg/use_custom_key_database_path",
+ ui_->keyDatabaseUseCustomCheckBox->isChecked());
+ settings.setValue("gnupg/use_custom_gnupg_install_path",
+ ui_->useCustomGnuPGInstallPathCheckBox->isChecked());
+ settings.setValue("gnupg/use_pinentry_as_password_input_dialog",
+ ui_->usePinentryAsPasswordInputDialogCheckBox->isChecked());
+ settings.setValue("gnupg/enable_gpgme_debug_log",
+ ui_->gpgmeDebugLogCheckBox->isChecked());
+ settings.setValue("gnupg/custom_key_database_path",
+ ui_->currentKeyDatabasePathLabel->text());
+ settings.setValue("gnupg/custom_gnupg_install_path",
+ ui_->currentCustomGnuPGInstallPathLabel->text());
+ settings.setValue("gnupg/restart_gpg_agent_on_start",
+ ui_->restartGpgAgentOnStartCheckBox->isChecked());
+ settings.setValue("gnupg/kill_all_gnupg_daemon_at_close",
+ ui_->killAllGnuPGDaemonCheckBox->isChecked());
+}
+
+auto GnuPGControllerDialog::get_restart_needed() const -> int {
+ return this->restart_needed_;
+}
+
+void GnuPGControllerDialog::slot_set_restart_needed(int mode) {
+ GF_UI_LOG_INFO("announce restart needed, mode: {}", mode);
+ this->restart_needed_ = mode;
+}
+
+auto GnuPGControllerDialog::check_custom_gnupg_path(QString path) -> bool {
+ if (path.isEmpty()) return false;
+
+ QFileInfo const dir_info(path);
+ if (!dir_info.exists() || !dir_info.isReadable() || !dir_info.isDir()) {
+ QMessageBox::critical(
+ this, tr("Illegal GnuPG Path"),
+ tr("Target GnuPG Path is not an exists readable directory."));
+ return false;
+ }
+
+ QDir const dir(path);
+ if (!dir.isAbsolute()) {
+ QMessageBox::critical(this, tr("Illegal GnuPG Path"),
+ tr("Target GnuPG Path is not an absolute path."));
+ }
+#ifdef WINDOWS
+ QFileInfo const gpgconf_info(path + "/gpgconf.exe");
+#else
+ QFileInfo const gpgconf_info(path + "/gpgconf");
+#endif
+
+ if (!gpgconf_info.exists() || !gpgconf_info.isFile() ||
+ !gpgconf_info.isExecutable()) {
+ QMessageBox::critical(
+ this, tr("Illegal GnuPG Path"),
+ tr("Target GnuPG Path contains no \"gpgconf\" executable."));
+ return false;
+ }
+
+ return true;
+}
+
+auto GnuPGControllerDialog::check_custom_gnupg_key_database_path(QString path)
+ -> bool {
+ if (path.isEmpty()) return false;
+
+ QFileInfo const dir_info(path);
+ if (!dir_info.exists() || !dir_info.isReadable() || !dir_info.isDir()) {
+ QMessageBox::critical(this, tr("Illegal GnuPG Key Database Path"),
+ tr("Target GnuPG Key Database Path is not an "
+ "exists readable directory."));
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace GpgFrontend::UI