/** * Copyright (C) 2021 Saturneric * * 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 . * * 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 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_->setupUi(this); ui_->generalBox->setTitle(_("General")); ui_->keyDatabaseGroupBox->setTitle(_("Key Database")); ui_->advanceGroupBox->setTitle(_("Advanced")); ui_->asciiModeCheckBox->setText(_("No ASCII Mode")); ui_->usePinentryAsPasswordInputDialogCheckBox->setText( _("Use Pinentry as Password Input Dialog")); ui_->useCustomGnuPGInstallPathCheckBox->setText(_("Use Custom GnuPG")); ui_->useCustomGnuPGInstallPathButton->setText(_("Select GnuPG Path")); ui_->keyDatabseUseCustomCheckBox->setText( _("Use Custom GnuPG Key Database Path")); ui_->customKeyDatabasePathSelectButton->setText( _("Select Key Database Path")); // tips ui_->customGnuPGPathTipsLabel->setText( _("Tips: please select a directroy where \"gpgconf\" is located in.")); ui_->restartTipsLabel->setText( _("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_->keyDatabseUseCustomCheckBox, &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_->keyDatabseUseCustomCheckBox, &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, _("Open Directory"), {}, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); GF_UI_LOG_DEBUG("key databse path selected: {}", selected_custom_key_database_path); if (!check_custom_gnupg_key_database_path( selected_custom_key_database_path)) { return; } auto settings = GlobalSettingStation::GetInstance().GetSettings(); // update settings if (!settings.contains("basic/custom_key_database_path")) { settings.setValue("basic/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_->keyDatabseUseCustomCheckBox->checkState()); }); connect( ui_->useCustomGnuPGInstallPathButton, &QPushButton::clicked, this, [=]() { QString selected_custom_gnupg_install_path = QFileDialog::getExistingDirectory( this, _("Open Directory"), {}, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); GF_UI_LOG_DEBUG("gnupg install path selected: {}", selected_custom_gnupg_install_path); // notify the user and precheck if (!check_custom_gnupg_path(selected_custom_gnupg_install_path)) { return; } auto settings = GlobalSettingStation::GetInstance().GetSettings(); if (!settings.contains("basic/custom_gnupg_install_path")) { settings.setValue("basic/custom_gnupg_install_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 state) { // 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(_("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) { // announce the restart this->slot_set_restart_needed(kDeepRestartCode); 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); if (state != Qt::CheckState::Checked) { ui_->currentKeyDatabasePathLabel->setText(database_path); // hide label (not necessary to show the default path) this->ui_->currentKeyDatabasePathLabel->setHidden(true); } else { // read from settings file QString custom_key_database_path = GlobalSettingStation::GetInstance() .GetSettings() .value("basic/custom_key_database_path") .toString(); GF_UI_LOG_DEBUG("selected_custom_key_database_path from settings: {}", custom_key_database_path); // notify the user check_custom_gnupg_key_database_path(custom_key_database_path); // set label value if (!custom_key_database_path.isEmpty()) { ui_->currentKeyDatabasePathLabel->setText(custom_key_database_path); this->ui_->currentKeyDatabasePathLabel->setHidden(false); } else { this->ui_->currentKeyDatabasePathLabel->setHidden(true); } } } void GnuPGControllerDialog::slot_update_custom_gnupg_install_path_label( int state) { // announce the restart this->slot_set_restart_needed(kDeepRestartCode); const auto home_path = Module::RetrieveRTValueTypedOrDefault<>( "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering", "gnupg.home_path", QString{}); GF_UI_LOG_DEBUG("got gnupg home path from rt: {}", home_path); if (state != Qt::CheckState::Checked) { ui_->currentCustomGnuPGInstallPathLabel->setText(home_path); // hide label (not necessary to show the default path) this->ui_->currentCustomGnuPGInstallPathLabel->setHidden(true); } else { // read from settings file QString custom_gnupg_install_path = GlobalSettingStation::GetInstance() .GetSettings() .value("basic/custom_gnupg_install_path") .toString(); GF_UI_LOG_DEBUG("custom_gnupg_install_path from settings: {}", custom_gnupg_install_path); // notify the user check_custom_gnupg_path(custom_gnupg_install_path); // set label value if (!custom_gnupg_install_path.isEmpty()) { ui_->currentCustomGnuPGInstallPathLabel->setText( custom_gnupg_install_path); this->ui_->currentCustomGnuPGInstallPathLabel->setHidden(false); } else { this->ui_->currentCustomGnuPGInstallPathLabel->setHidden(true); } } } void GnuPGControllerDialog::set_settings() { auto& settings_station = GlobalSettingStation::GetInstance(); bool non_ascii_when_export = settings_station.GetSettings() .value("basic/non_ascii_when_export", true) .toBool(); GF_UI_LOG_DEBUG("non_ascii_when_export: {}", non_ascii_when_export); if (non_ascii_when_export) ui_->asciiModeCheckBox->setCheckState(Qt::Checked); bool const use_custom_key_database_path = settings_station.GetSettings() .value("basic/use_custom_key_database_path", false) .toBool(); if (use_custom_key_database_path) { ui_->keyDatabseUseCustomCheckBox->setCheckState(Qt::Checked); } this->slot_update_custom_key_database_path_label( ui_->keyDatabseUseCustomCheckBox->checkState()); bool const use_custom_gnupg_install_path = settings_station.GetSettings() .value("basic/use_custom_gnupg_install_path", false) .toBool(); if (use_custom_gnupg_install_path) { ui_->useCustomGnuPGInstallPathCheckBox->setCheckState(Qt::Checked); } bool const use_pinentry_as_password_input_dialog = settings_station.GetSettings() .value("basic/use_pinentry_as_password_input_dialog", false) .toBool(); if (use_pinentry_as_password_input_dialog) { ui_->usePinentryAsPasswordInputDialogCheckBox->setCheckState(Qt::Checked); } this->slot_update_custom_gnupg_install_path_label( ui_->useCustomGnuPGInstallPathCheckBox->checkState()); this->slot_set_restart_needed(false); } void GnuPGControllerDialog::apply_settings() { auto settings = GpgFrontend::GlobalSettingStation::GetInstance().GetSettings(); settings.setValue("basic/non_ascii_when_export", ui_->asciiModeCheckBox->isChecked()); settings.setValue("basic/use_custom_key_database_path", ui_->keyDatabseUseCustomCheckBox->isChecked()); settings.setValue("basic/use_custom_gnupg_install_path", ui_->useCustomGnuPGInstallPathCheckBox->isChecked()); settings.setValue("basic/use_pinentry_as_password_input_dialog", ui_->usePinentryAsPasswordInputDialogCheckBox->isChecked()); } int GnuPGControllerDialog::get_restart_needed() const { return this->restart_needed_; } void GnuPGControllerDialog::slot_set_restart_needed(int mode) { this->restart_needed_ = mode; } bool GnuPGControllerDialog::check_custom_gnupg_path(QString path) { if (path.isEmpty()) { QMessageBox::critical(this, _("Illegal GnuPG Path"), _("Target GnuPG Path is empty.")); return false; } QFileInfo dir_info(path); if (!dir_info.exists() || !dir_info.isReadable() || !dir_info.isDir()) { QMessageBox::critical( this, _("Illegal GnuPG Path"), _("Target GnuPG Path is not an exists readable directory.")); return false; } QDir dir(path); if (!dir.isAbsolute()) { QMessageBox::critical(this, _("Illegal GnuPG Path"), _("Target GnuPG Path is not an absolute path.")); } #ifdef WINDOWS QFileInfo gpgconf_info(path + "/gpgconf.exe"); #else QFileInfo gpgconf_info(path + "/gpgconf"); #endif if (!gpgconf_info.exists() || !gpgconf_info.isExecutable() || !gpgconf_info.isFile()) { QMessageBox::critical( this, _("Illegal GnuPG Path"), _("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()) { QMessageBox::critical(this, _("Illegal GnuPG Key Database Path"), _("Target GnuPG Key Database Path is empty.")); return false; } QFileInfo dir_info(path); if (!dir_info.exists() || !dir_info.isReadable() || !dir_info.isDir()) { QMessageBox::critical(this, _("Illegal GnuPG Key Database Path"), _("Target GnuPG Key Database Path is not an " "exists readable directory.")); return false; } return true; } } // namespace GpgFrontend::UI