diff options
Diffstat (limited to 'src/ui/main_window')
-rw-r--r-- | src/ui/main_window/GeneralMainWindow.cpp | 135 | ||||
-rw-r--r-- | src/ui/main_window/GeneralMainWindow.h | 81 | ||||
-rw-r--r-- | src/ui/main_window/KeyMgmt.cpp | 462 | ||||
-rw-r--r-- | src/ui/main_window/KeyMgmt.h | 178 | ||||
-rw-r--r-- | src/ui/main_window/MainWindow.cpp | 70 | ||||
-rw-r--r-- | src/ui/main_window/MainWindow.h | 15 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowFileSlotFunction.cpp | 5 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowSlotFunction.cpp | 11 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowSlotUI.cpp | 10 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowUI.cpp | 9 |
10 files changed, 895 insertions, 81 deletions
diff --git a/src/ui/main_window/GeneralMainWindow.cpp b/src/ui/main_window/GeneralMainWindow.cpp new file mode 100644 index 00000000..7df73aba --- /dev/null +++ b/src/ui/main_window/GeneralMainWindow.cpp @@ -0,0 +1,135 @@ +/** + * 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 <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 "GeneralMainWindow.h" + +#include <utility> + +#include "ui/struct/SettingsObject.h" + +GpgFrontend::UI::GeneralMainWindow::GeneralMainWindow(std::string name, + QWidget* parent) + : name_(std::move(name)), QMainWindow(parent) { + slot_restore_settings(); +} + +GpgFrontend::UI::GeneralMainWindow::~GeneralMainWindow() = default; + +void GpgFrontend::UI::GeneralMainWindow::closeEvent(QCloseEvent* event) { + slot_save_settings(); + QMainWindow::closeEvent(event); +} + +void GpgFrontend::UI::GeneralMainWindow::slot_restore_settings() noexcept { + try { + LOG(INFO) << name_ << _("Called"); + + SettingsObject general_windows_state(name_ + "_state"); + + std::string window_state = general_windows_state.Check( + "window_state", saveState().toBase64().toStdString()); + + // state sets pos & size of dock-widgets + this->restoreState( + QByteArray::fromBase64(QByteArray::fromStdString(window_state))); + + bool window_save = general_windows_state.Check("window_save", true); + + // Restore window size & location + if (window_save) { + int x = general_windows_state.Check("window_pos").Check("x", 100), + y = general_windows_state.Check("window_pos").Check("y", 100); + + this->move({x, y}); + pos_ = {x, y}; + + int width = + general_windows_state.Check("window_size").Check("width", 800), + height = + general_windows_state.Check("window_size").Check("height", 450); + + this->resize({width, height}); + size_ = {width, height}; + } + + + // appearance + SettingsObject general_settings_state("general_settings_state"); + + int width = general_settings_state.Check("icon_size").Check("width", 24), + height = general_settings_state.Check("icon_size").Check("height", 24); + LOG(INFO) << "icon_size" << width << height; + + icon_size_ = {width, height}; + font_size_ = general_settings_state.Check("font_size", 10); + + this->setIconSize(icon_size_); + + // icon_style + int s_icon_style = + general_settings_state.Check("icon_style", Qt::ToolButtonTextUnderIcon); + this->setToolButtonStyle(static_cast<Qt::ToolButtonStyle>(s_icon_style)); + icon_style_ = toolButtonStyle(); + + } catch (...) { + LOG(ERROR) << name_ << "error"; + } +} + +void GpgFrontend::UI::GeneralMainWindow::slot_save_settings() noexcept { + try { + LOG(INFO) << name_ << _("Called"); + + SettingsObject general_windows_state(name_ + "_state"); + + // window position and size + general_windows_state["window_state"] = + saveState().toBase64().toStdString(); + general_windows_state["window_pos"]["x"] = pos().x(); + general_windows_state["window_pos"]["y"] = pos().y(); + + general_windows_state["window_size"]["width"] = size_.width(); + general_windows_state["window_size"]["height"] = size_.height(); + general_windows_state["window_save"] = true; + + SettingsObject general_settings_state("general_settings_state"); + + // icon size + general_settings_state["icon_size"]["width"] = icon_size_.width(); + general_settings_state["icon_size"]["height"] = icon_size_.height(); + + // font size + general_settings_state["font_size"] = font_size_; + + // tool button style + general_settings_state["icon_style"] = this->toolButtonStyle(); + + } catch (...) { + LOG(ERROR) << name_ << "error"; + } +} diff --git a/src/ui/main_window/GeneralMainWindow.h b/src/ui/main_window/GeneralMainWindow.h new file mode 100644 index 00000000..71327100 --- /dev/null +++ b/src/ui/main_window/GeneralMainWindow.h @@ -0,0 +1,81 @@ +/** + * 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 <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 + * + */ + +#ifndef GPGFRONTEND_GENERALMAINWINDOW_H +#define GPGFRONTEND_GENERALMAINWINDOW_H + +#include "ui/GpgFrontendUI.h" + +namespace GpgFrontend::UI { + +/** + * + */ +class GeneralMainWindow : public QMainWindow { + public: + /** + * + * @param name + */ + explicit GeneralMainWindow(std::string name, QWidget* parent = nullptr); + + /** + * + */ + ~GeneralMainWindow() override; + + protected: + /** + * + * @param event + */ + void closeEvent(QCloseEvent* event); + + QSize icon_size_{}; ///< + int font_size_{}; ///< + Qt::ToolButtonStyle icon_style_; ///< + + private slots: + /** + * + */ + void slot_restore_settings() noexcept; + + /** + * + */ + void slot_save_settings() noexcept; + + private: + std::string name_; ///< + QPoint pos_; ///< + QSize size_; ///< +}; +} // namespace GpgFrontend::UI + +#endif // GPGFRONTEND_GENERALMAINWINDOW_H diff --git a/src/ui/main_window/KeyMgmt.cpp b/src/ui/main_window/KeyMgmt.cpp new file mode 100644 index 00000000..6dc2b14f --- /dev/null +++ b/src/ui/main_window/KeyMgmt.cpp @@ -0,0 +1,462 @@ +/** + * 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 <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 "KeyMgmt.h" + +#include <utility> + +#include "core/function/GlobalSettingStation.h" +#include "core/function/KeyPackageOperator.h" +#include "core/function/gpg/GpgKeyGetter.h" +#include "core/function/gpg/GpgKeyImportExporter.h" +#include "core/function/gpg/GpgKeyOpera.h" +#include "ui/SignalStation.h" +#include "ui/UserInterfaceUtils.h" +#include "ui/dialog/import_export/ExportKeyPackageDialog.h" +#include "ui/dialog/key_generate/SubkeyGenerateDialog.h" +#include "ui/main_window/MainWindow.h" + +namespace GpgFrontend::UI { + +KeyMgmt::KeyMgmt(QWidget* parent) + : GeneralMainWindow("key_management", 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( + _("Only Public Key"), KeyListRow::SECRET_OR_PUBLIC_KEY, + KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | + KeyListColumn::Usage | KeyListColumn::Validity, + [](const GpgKey& key) -> bool { + return !key.IsPrivateKey() && + !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); + }); + + key_list_->AddListGroupTab( + _("Has Private Key"), KeyListRow::SECRET_OR_PUBLIC_KEY, + KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | + KeyListColumn::Usage | KeyListColumn::Validity, + [](const GpgKey& key) -> bool { + return key.IsPrivateKey() && + !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); + }); + + key_list_->AddListGroupTab( + _("No Primary Key"), KeyListRow::SECRET_OR_PUBLIC_KEY, + KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | + KeyListColumn::Usage | KeyListColumn::Validity, + [](const GpgKey& key) -> bool { + return !key.IsHasMasterKey() && + !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); + }); + + key_list_->AddListGroupTab( + _("Revoked"), KeyListRow::SECRET_OR_PUBLIC_KEY, + KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | + KeyListColumn::Usage | KeyListColumn::Validity, + [](const GpgKey& key) -> bool { return key.IsRevoked(); }); + + key_list_->AddListGroupTab( + _("Expired"), KeyListRow::SECRET_OR_PUBLIC_KEY, + KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | + KeyListColumn::Usage | KeyListColumn::Validity, + [](const GpgKey& key) -> bool { return key.IsExpired(); }); + + setCentralWidget(key_list_); + key_list_->SetDoubleClickedAction([this](const GpgKey& key, QWidget* parent) { + new KeyDetailsDialog(key, parent); + }); + + key_list_->SlotRefresh(); + + create_actions(); + create_menus(); + create_tool_bars(); + + connect(this, &KeyMgmt::SignalStatusBarChanged, + qobject_cast<MainWindow*>(this->parent()), + &MainWindow::SlotSetStatusBarText); + + auto& settings = GlobalSettingStation::GetInstance().GetUISettings(); + + this->statusBar()->show(); + + setWindowTitle(_("KeyPair Management")); + key_list_->AddMenuAction(delete_selected_keys_act_); + key_list_->AddMenuAction(show_key_details_act_); + + connect(this, &KeyMgmt::SignalKeyStatusUpdated, SignalStation::GetInstance(), + &SignalStation::SignalKeyDatabaseRefresh); + connect(SignalStation::GetInstance(), &SignalStation::SignalRefreshStatusBar, + this, [=](const QString& message, int timeout) { + statusBar()->showMessage(message, timeout); + }); +} + +void KeyMgmt::create_actions() { + open_key_file_act_ = new QAction(_("Open"), this); + open_key_file_act_->setShortcut(QKeySequence(_("Ctrl+O"))); + open_key_file_act_->setToolTip(_("Open Key File")); + connect(open_key_file_act_, &QAction::triggered, this, + [&]() { CommonUtils::GetInstance()->SlotImportKeyFromFile(this); }); + + close_act_ = new QAction(_("Close"), this); + close_act_->setShortcut(QKeySequence(_("Ctrl+Q"))); + close_act_->setIcon(QIcon(":exit.png")); + close_act_->setToolTip(_("Close")); + connect(close_act_, &QAction::triggered, this, &KeyMgmt::close); + + generate_key_pair_act_ = new QAction(_("New Keypair"), this); + generate_key_pair_act_->setShortcut(QKeySequence(_("Ctrl+N"))); + generate_key_pair_act_->setIcon(QIcon(":key_generate.png")); + generate_key_pair_act_->setToolTip(_("Generate KeyPair")); + connect(generate_key_pair_act_, &QAction::triggered, this, + &KeyMgmt::SlotGenerateKeyDialog); + + generate_subkey_act_ = new QAction(_("New Subkey"), this); + generate_subkey_act_->setShortcut(QKeySequence(_("Ctrl+Shift+N"))); + generate_subkey_act_->setIcon(QIcon(":key_generate.png")); + generate_subkey_act_->setToolTip(_("Generate Subkey For Selected KeyPair")); + connect(generate_subkey_act_, &QAction::triggered, this, + &KeyMgmt::SlotGenerateSubKey); + + import_key_from_file_act_ = new QAction(_("File"), this); + import_key_from_file_act_->setIcon(QIcon(":import_key_from_file.png")); + import_key_from_file_act_->setToolTip(_("Import New Key From File")); + connect(import_key_from_file_act_, &QAction::triggered, this, + [&]() { CommonUtils::GetInstance()->SlotImportKeyFromFile(this); }); + + import_key_from_clipboard_act_ = new QAction(_("Clipboard"), this); + import_key_from_clipboard_act_->setIcon( + QIcon(":import_key_from_clipboard.png")); + import_key_from_clipboard_act_->setToolTip( + _("Import New Key From Clipboard")); + connect(import_key_from_clipboard_act_, &QAction::triggered, this, [&]() { + CommonUtils::GetInstance()->SlotImportKeyFromClipboard(this); + }); + + import_key_from_key_server_act_ = new QAction(_("Keyserver"), this); + import_key_from_key_server_act_->setIcon( + QIcon(":import_key_from_server.png")); + import_key_from_key_server_act_->setToolTip( + _("Import New Key From Keyserver")); + connect(import_key_from_key_server_act_, &QAction::triggered, this, [&]() { + CommonUtils::GetInstance()->SlotImportKeyFromKeyServer(this); + }); + + import_keys_from_key_package_act_ = new QAction(_("Key Package"), this); + import_keys_from_key_package_act_->setIcon(QIcon(":key_package.png")); + import_keys_from_key_package_act_->setToolTip( + _("Import Key(s) From a Key Package")); + connect(import_keys_from_key_package_act_, &QAction::triggered, this, + &KeyMgmt::SlotImportKeyPackage); + + export_key_to_clipboard_act_ = new QAction(_("Export To Clipboard"), this); + export_key_to_clipboard_act_->setIcon(QIcon(":export_key_to_clipboard.png")); + export_key_to_clipboard_act_->setToolTip( + _("Export Selected Key(s) To Clipboard")); + connect(export_key_to_clipboard_act_, &QAction::triggered, this, + &KeyMgmt::SlotExportKeyToClipboard); + + export_key_to_file_act_ = new QAction(_("Export To Key Package"), this); + export_key_to_file_act_->setIcon(QIcon(":key_package.png")); + export_key_to_file_act_->setToolTip( + _("Export Checked Key(s) To a Key Package")); + connect(export_key_to_file_act_, &QAction::triggered, this, + &KeyMgmt::SlotExportKeyToKeyPackage); + + export_key_as_open_ssh_format_ = new QAction(_("Export As OpenSSH"), this); + export_key_as_open_ssh_format_->setIcon(QIcon(":ssh-key.png")); + export_key_as_open_ssh_format_->setToolTip( + _("Export Selected Key(s) As OpenSSH Format to File")); + connect(export_key_as_open_ssh_format_, &QAction::triggered, this, + &KeyMgmt::SlotExportAsOpenSSHFormat); + + delete_selected_keys_act_ = new QAction(_("Delete Selected Key(s)"), this); + delete_selected_keys_act_->setToolTip(_("Delete the Selected keys")); + connect(delete_selected_keys_act_, &QAction::triggered, this, + &KeyMgmt::SlotDeleteSelectedKeys); + + delete_checked_keys_act_ = new QAction(_("Delete Checked Key(s)"), this); + delete_checked_keys_act_->setToolTip(_("Delete the Checked keys")); + delete_checked_keys_act_->setIcon(QIcon(":button_delete.png")); + connect(delete_checked_keys_act_, &QAction::triggered, this, + &KeyMgmt::SlotDeleteCheckedKeys); + + show_key_details_act_ = new QAction(_("Show Key Details"), this); + show_key_details_act_->setToolTip(_("Show Details for this Key")); + connect(show_key_details_act_, &QAction::triggered, this, + &KeyMgmt::SlotShowKeyDetails); +} + +void KeyMgmt::create_menus() { + file_menu_ = menuBar()->addMenu(_("File")); + file_menu_->addAction(open_key_file_act_); + file_menu_->addAction(close_act_); + + key_menu_ = menuBar()->addMenu(_("Key")); + generate_key_menu_ = key_menu_->addMenu(_("Generate Key")); + generate_key_menu_->addAction(generate_key_pair_act_); + generate_key_menu_->addAction(generate_subkey_act_); + + import_key_menu_ = key_menu_->addMenu(_("Import Key")); + import_key_menu_->addAction(import_key_from_file_act_); + import_key_menu_->addAction(import_key_from_clipboard_act_); + import_key_menu_->addAction(import_key_from_key_server_act_); + import_key_menu_->addAction(import_keys_from_key_package_act_); + + key_menu_->addAction(export_key_to_file_act_); + key_menu_->addAction(export_key_to_clipboard_act_); + key_menu_->addAction(export_key_as_open_ssh_format_); + key_menu_->addSeparator(); + key_menu_->addAction(delete_checked_keys_act_); +} + +void KeyMgmt::create_tool_bars() { + QToolBar* keyToolBar = addToolBar(_("Key")); + keyToolBar->setObjectName("keytoolbar"); + + // add button with popup menu for import + auto* generateToolButton = new QToolButton(this); + generateToolButton->setMenu(generate_key_menu_); + generateToolButton->setPopupMode(QToolButton::InstantPopup); + generateToolButton->setIcon(QIcon(":key_generate.png")); + generateToolButton->setText(_("Generate")); + generateToolButton->setToolTip(_("Generate A New Keypair or Subkey")); + generateToolButton->setToolButtonStyle(icon_style_); + keyToolBar->addWidget(generateToolButton); + + // add button with popup menu for import + auto* toolButton = new QToolButton(this); + toolButton->setMenu(import_key_menu_); + toolButton->setPopupMode(QToolButton::InstantPopup); + toolButton->setIcon(QIcon(":key_import.png")); + toolButton->setToolTip(_("Import key")); + toolButton->setText(_("Import Key")); + toolButton->setToolButtonStyle(icon_style_); + keyToolBar->addWidget(toolButton); + + keyToolBar->addSeparator(); + keyToolBar->addAction(delete_checked_keys_act_); + keyToolBar->addSeparator(); + keyToolBar->addAction(export_key_to_file_act_); + keyToolBar->addAction(export_key_to_clipboard_act_); + keyToolBar->addAction(export_key_as_open_ssh_format_); +} + +void KeyMgmt::SlotDeleteSelectedKeys() { + delete_keys_with_warning(key_list_->GetSelected()); +} + +void KeyMgmt::SlotDeleteCheckedKeys() { + delete_keys_with_warning(key_list_->GetChecked()); +} + +void KeyMgmt::delete_keys_with_warning(KeyIdArgsListPtr uidList) { + /** + * TODO: Different Messages for private/public key, check if + * more than one selected... compare to seahorse "delete-dialog" + */ + + if (uidList->empty()) return; + QString keynames; + for (const auto& key_id : *uidList) { + auto key = GpgKeyGetter::GetInstance().GetKey(key_id); + if (!key.IsGood()) continue; + keynames.append(QString::fromStdString(key.GetName())); + keynames.append("<i> <"); + keynames.append(QString::fromStdString(key.GetEmail())); + keynames.append("> </i><br/>"); + } + + int ret = QMessageBox::warning( + this, _("Deleting Keys"), + "<b>" + + QString( + _("Are you sure that you want to delete the following keys?")) + + "</b><br/><br/>" + keynames + +"<br/>" + + _("The action can not be undone."), + QMessageBox::No | QMessageBox::Yes); + + if (ret == QMessageBox::Yes) { + GpgKeyOpera::GetInstance().DeleteKeys(std::move(uidList)); + emit SignalKeyStatusUpdated(); + } +} + +void KeyMgmt::SlotShowKeyDetails() { + auto keys_selected = key_list_->GetSelected(); + if (keys_selected->empty()) return; + + auto key = GpgKeyGetter::GetInstance().GetKey(keys_selected->front()); + + if (!key.IsGood()) { + QMessageBox::critical(this, _("Error"), _("Key Not Found.")); + return; + } + + new KeyDetailsDialog(key); +} + +void KeyMgmt::SlotExportKeyToKeyPackage() { + auto keys_checked = key_list_->GetChecked(); + if (keys_checked->empty()) { + QMessageBox::critical( + this, _("Forbidden"), + _("Please check some keys before doing this operation.")); + return; + } + auto dialog = new ExportKeyPackageDialog(std::move(keys_checked), this); + dialog->exec(); + emit SignalStatusBarChanged(QString(_("key(s) exported"))); +} + +void KeyMgmt::SlotExportKeyToClipboard() { + auto keys_checked = key_list_->GetChecked(); + if (keys_checked->empty()) { + QMessageBox::critical( + this, _("Forbidden"), + _("Please check some keys before doing this operation.")); + return; + } + + ByteArrayPtr key_export_data = nullptr; + if (!GpgKeyImportExporter::GetInstance().ExportKeys(keys_checked, + key_export_data)) { + return; + } + QApplication::clipboard()->setText(QString::fromStdString(*key_export_data)); +} + +void KeyMgmt::SlotGenerateKeyDialog() { + auto* keyGenDialog = new KeyGenDialog(this); + keyGenDialog->show(); +} + +void KeyMgmt::SlotGenerateSubKey() { + auto keys_selected = key_list_->GetSelected(); + if (keys_selected->empty()) { + QMessageBox::information( + this, _("Invalid Operation"), + _("Please select one KeyPair before doing this operation.")); + return; + } + const auto key = GpgKeyGetter::GetInstance().GetKey(keys_selected->front()); + if (!key.IsGood()) { + QMessageBox::critical(this, _("Error"), _("Key Not Found.")); + return; + } + if (!key.IsPrivateKey()) { + QMessageBox::critical(this, _("Invalid Operation"), + _("If a key pair does not have a private key then " + "it will not be able to generate sub-keys.")); + return; + } + + auto dialog = new SubkeyGenerateDialog(key.GetId(), this); + dialog->show(); +} + +void KeyMgmt::SlotExportAsOpenSSHFormat() { + ByteArrayPtr key_export_data = nullptr; + auto keys_checked = key_list_->GetChecked(); + + if (keys_checked->empty()) { + QMessageBox::critical( + this, _("Forbidden"), + _("Please select a key before performing this operation. If you select " + "multiple keys, only the first key will be exported.")); + return; + } + + auto key = GpgKeyGetter::GetInstance().GetKey(keys_checked->front()); + if (!GpgKeyImportExporter::GetInstance().ExportKeyOpenSSH(key, + key_export_data)) { + QMessageBox::critical(this, _("Error"), _("An error occur in exporting.")); + return; + } + + if (key_export_data->empty()) { + QMessageBox::critical( + this, _("Error"), + _("This key may not be able to export as OpenSSH format. Please check " + "the key-size of the subkey(s) used to sign.")); + return; + } + + key = GpgKeyGetter::GetInstance().GetKey(keys_checked->front()); + if (!key.IsGood()) { + QMessageBox::critical(this, _("Error"), _("Key Not Found.")); + return; + } + QString fileString = QString::fromStdString( + key.GetName() + " " + key.GetEmail() + "(" + key.GetId() + ").pub"); + + QString file_name = QFileDialog::getSaveFileName( + this, _("Export OpenSSH Key To File"), fileString, + QString(_("OpenSSH Public Key Files")) + " (*.pub);;All Files (*)"); + + if (!file_name.isEmpty()) { + write_buffer_to_file(file_name.toStdString(), *key_export_data); + emit SignalStatusBarChanged(QString(_("key(s) exported"))); + } +} + +void KeyMgmt::SlotImportKeyPackage() { + LOG(INFO) << "Importing key package..."; + + auto key_package_file_name = QFileDialog::getOpenFileName( + this, _("Import Key Package"), {}, + QString(_("Key Package")) + " (*.gfepack);;All Files (*)"); + + auto key_file_name = QFileDialog::getOpenFileName( + this, _("Import Key Package Passphrase File"), {}, + QString(_("Key Package Passphrase File")) + " (*.key);;All Files (*)"); + + if (key_package_file_name.isEmpty() || key_file_name.isEmpty()) return; + + GpgImportInformation info; + + LOG(INFO) << "Importing key package: " << key_package_file_name.toStdString(); + + if (KeyPackageOperator::ImportKeyPackage(key_package_file_name.toStdString(), + key_file_name.toStdString(), info)) { + emit SignalStatusBarChanged(QString(_("key(s) imported"))); + emit SignalKeyStatusUpdated(); + + auto dialog = new KeyImportDetailDialog(info, false, this); + dialog->exec(); + } else { + QMessageBox::critical(this, _("Error"), + _("An error occur in importing key package.")); + } +} + +} // namespace GpgFrontend::UI diff --git a/src/ui/main_window/KeyMgmt.h b/src/ui/main_window/KeyMgmt.h new file mode 100644 index 00000000..2073113a --- /dev/null +++ b/src/ui/main_window/KeyMgmt.h @@ -0,0 +1,178 @@ +/** + * 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 <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 + * + */ + +#ifndef __KEYMGMT_H__ +#define __KEYMGMT_H__ + +#include "ui/GpgFrontendUI.h" +#include "ui/dialog/import_export/KeyImportDetailDialog.h" +#include "ui/dialog/import_export/KeyServerImportDialog.h" +#include "ui/dialog/key_generate/KeygenDialog.h" +#include "ui/dialog/keypair_details/KeyDetailsDialog.h" +#include "ui/main_window/GeneralMainWindow.h" +#include "ui/widgets/KeyList.h" + +namespace GpgFrontend::UI { + +/** + * @brief + * + */ +class KeyMgmt : public GeneralMainWindow { + Q_OBJECT + + public: + /** + * @brief Construct a new Key Mgmt object + * + * @param parent + */ + explicit KeyMgmt(QWidget* parent = nullptr); + + public slots: + + /** + * @brief + * + */ + void SlotGenerateSubKey(); + + /** + * @brief + * + */ + void SlotExportKeyToKeyPackage(); + + /** + * @brief + * + */ + void SlotExportKeyToClipboard(); + + /** + * @brief + * + */ + void SlotExportAsOpenSSHFormat(); + + /** + * @brief + * + */ + void SlotDeleteSelectedKeys(); + + /** + * @brief + * + */ + void SlotDeleteCheckedKeys(); + + /** + * @brief + * + */ + void SlotGenerateKeyDialog(); + + /** + * @brief + * + */ + void SlotShowKeyDetails(); + + /** + * @brief + * + */ + void SlotImportKeyPackage(); + + signals: + + /** + * @brief + * + */ + void SignalStatusBarChanged(QString); + + /** + * @brief + * + */ + void SignalKeyStatusUpdated(); + + private: + /** + * @brief Create a menus object + * + */ + void create_menus(); + + /** + * @brief Create a actions object + * + */ + void create_actions(); + + /** + * @brief Create a tool bars object + * + */ + void create_tool_bars(); + + /** + * @brief + * + * @param uidList + */ + void delete_keys_with_warning(GpgFrontend::KeyIdArgsListPtr uidList); + + KeyList* key_list_; ///< + QMenu* file_menu_{}; ///< + QMenu* key_menu_{}; ///< + QMenu* generate_key_menu_{}; ///< + QMenu* import_key_menu_{}; ///< + QAction* open_key_file_act_{}; ///< + QAction* export_key_to_file_act_{}; ///< + QAction* export_key_as_open_ssh_format_{}; ///< + QAction* export_key_to_clipboard_act_{}; ///< + QAction* delete_checked_keys_act_{}; ///< + QAction* delete_selected_keys_act_{}; ///< + QAction* generate_key_dialog_act_{}; ///< + QAction* generate_key_pair_act_{}; ///< + QAction* generate_subkey_act_{}; ///< + QAction* import_key_from_clipboard_act_{}; ///< + QAction* import_key_from_file_act_{}; ///< + QAction* import_key_from_key_server_act_{}; ///< + QAction* import_keys_from_key_package_act_{}; ///< + QAction* close_act_{}; ///< + QAction* show_key_details_act_{}; ///< + KeyServerImportDialog* import_dialog_{}; ///< +}; + +} // namespace GpgFrontend::UI + +#endif // __KEYMGMT_H__ diff --git a/src/ui/main_window/MainWindow.cpp b/src/ui/main_window/MainWindow.cpp index d04e3dbd..e3e4c0ab 100644 --- a/src/ui/main_window/MainWindow.cpp +++ b/src/ui/main_window/MainWindow.cpp @@ -36,7 +36,7 @@ namespace GpgFrontend::UI { -MainWindow::MainWindow() { +MainWindow::MainWindow() : GeneralMainWindow("main_window") { this->setMinimumSize(1200, 700); this->setWindowTitle(qApp->applicationName()); } @@ -135,63 +135,14 @@ void MainWindow::restore_settings() { LOG(INFO) << _("Called"); try { - LOG(INFO) << "restore settings main_windows_state"; - - SettingsObject main_windows_state("main_windows_state"); - - std::string window_state = main_windows_state.Check( - "window_state", saveState().toBase64().toStdString()); - // state sets pos & size of dock-widgets - this->restoreState( - QByteArray::fromBase64(QByteArray::fromStdString(window_state))); - - bool window_save = main_windows_state.Check("window_save", true); - - // Restore window size & location - if (window_save) { - int x = main_windows_state.Check("window_pos").Check("x", 100), - y = main_windows_state.Check("window_pos").Check("y", 100); - - auto pos = QPoint(x, y); - - int width = main_windows_state.Check("window_size").Check("width", 800), - height = main_windows_state.Check("window_size").Check("height", 450); - - auto size = QSize(width, height); - this->resize(size); - this->move(pos); - } else { - this->resize(QSize(800, 450)); - this->move(QPoint(100, 100)); - } - - int width = main_windows_state.Check("icon_size").Check("width", 24), - height = main_windows_state.Check("icon_size").Check("height", 24); - LOG(INFO) << "icon_size" << width << height; - - main_windows_state.Check("info_font_size", 10); - - // icon_style - int s_icon_style = - main_windows_state.Check("icon_style", Qt::ToolButtonTextUnderIcon); - auto icon_style = static_cast<Qt::ToolButtonStyle>(s_icon_style); - this->setToolButtonStyle(icon_style); - import_button_->setToolButtonStyle(icon_style); - - // icons ize - this->setIconSize(QSize(width, height)); - import_button_->setIconSize(QSize(width, height)); - LOG(INFO) << "restore settings key_server"; SettingsObject key_server_json("key_server"); - - if (!key_server_json.contains("server_list")) { + if (!key_server_json.contains("server_list") || + key_server_json["server_list"].empty()) { key_server_json["server_list"] = {"https://keyserver.ubuntu.com", - "http://keys.gnupg.net", - "http://pool.sks-keyservers.net"}; + "https://keys.openpgp.org"}; } - if (!key_server_json.contains("default_server")) { key_server_json["default_server"] = 0; } @@ -216,6 +167,9 @@ void MainWindow::restore_settings() { bool save_key_checked = true; general.lookupValue("save_key_checked", save_key_checked); + // set appearance + import_button_->setToolButtonStyle(icon_style_); + try { LOG(INFO) << "restore settings default_key_checked"; @@ -255,16 +209,6 @@ void MainWindow::save_settings() { auto &settings = GlobalSettingStation::GetInstance().GetUISettings(); try { - SettingsObject main_windows_state("main_windows_state"); - - // window position and size - main_windows_state["window_state"] = saveState().toBase64().toStdString(); - main_windows_state["window_pos"]["x"] = pos().x(); - main_windows_state["window_pos"]["y"] = pos().y(); - - main_windows_state["window_size"]["width"] = size().width(); - main_windows_state["window_size"]["height"] = size().height(); - bool save_key_checked = settings.lookup("general.save_key_checked"); // keyid-list of private checked keys diff --git a/src/ui/main_window/MainWindow.h b/src/ui/main_window/MainWindow.h index a0f1a5d4..b31e2fcb 100644 --- a/src/ui/main_window/MainWindow.h +++ b/src/ui/main_window/MainWindow.h @@ -29,17 +29,18 @@ #ifndef __GPGWIN_H__ #define __GPGWIN_H__ +#include "KeyMgmt.h" #include "core/GpgConstants.h" #include "core/function/result_analyse/GpgDecryptResultAnalyse.h" #include "core/function/result_analyse/GpgEncryptResultAnalyse.h" #include "core/function/result_analyse/GpgSignResultAnalyse.h" #include "ui/GpgFrontendUI.h" -#include "ui/KeyMgmt.h" #include "ui/dialog/WaitingDialog.h" #include "ui/dialog/Wizard.h" -#include "ui/help/AboutDialog.h" -#include "ui/import_export/KeyUploadDialog.h" -#include "ui/settings/SettingsDialog.h" +#include "ui/dialog/help/AboutDialog.h" +#include "ui/dialog/import_export/KeyUploadDialog.h" +#include "ui/dialog/settings/SettingsDialog.h" +#include "ui/main_window/GeneralMainWindow.h" #include "ui/widgets/FindWidget.h" #include "ui/widgets/InfoBoardWidget.h" #include "ui/widgets/TextEdit.h" @@ -49,10 +50,13 @@ namespace GpgFrontend::UI { * @brief * */ -class MainWindow : public QMainWindow { +class MainWindow : public GeneralMainWindow { Q_OBJECT public: + /** + * + */ struct CryptoMenu { using OperationType = unsigned int; @@ -383,6 +387,7 @@ class MainWindow : public QMainWindow { QAction* about_act_{}; ///< Action to open about dialog QAction* check_update_act_{}; ///< Action to open about dialog QAction* translate_act_{}; ///< Action to open about dialog + QAction* gnupg_act_{}; ///< Action to open about dialog QAction* open_settings_act_{}; ///< Action to open settings dialog QAction* show_key_details_act_{}; ///< Action to open key-details dialog QAction* start_wizard_act_{}; ///< Action to open the wizard diff --git a/src/ui/main_window/MainWindowFileSlotFunction.cpp b/src/ui/main_window/MainWindowFileSlotFunction.cpp index 4ab23a22..526c27c0 100644 --- a/src/ui/main_window/MainWindowFileSlotFunction.cpp +++ b/src/ui/main_window/MainWindowFileSlotFunction.cpp @@ -32,8 +32,8 @@ #include "core/function/gpg/GpgFileOpera.h" #include "core/function/gpg/GpgKeyGetter.h" #include "core/thread/Task.h" +#include "dialog/SignersPicker.h" #include "ui/UserInterfaceUtils.h" -#include "ui/widgets/SignersPicker.h" namespace GpgFrontend::UI { @@ -618,6 +618,9 @@ void MainWindow::SlotFileEncryptSign() { connect(signersPicker, &SignersPicker::finished, &loop, &QEventLoop::quit); loop.exec(); + // return when canceled + if (!signersPicker->GetStatus()) return; + auto signer_key_ids = signersPicker->GetCheckedSigners(); auto p_signer_keys = GpgKeyGetter::GetInstance().GetKeys(signer_key_ids); diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp index 0ad52248..f715046c 100644 --- a/src/ui/main_window/MainWindowSlotFunction.cpp +++ b/src/ui/main_window/MainWindowSlotFunction.cpp @@ -26,7 +26,6 @@ * */ -#include <cstddef> #include <memory> #include <string> #include <utility> @@ -34,15 +33,12 @@ #include "MainWindow.h" #include "core/GpgConstants.h" #include "core/GpgModel.h" -#include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgBasicOperator.h" #include "core/function/gpg/GpgKeyGetter.h" #include "core/function/gpg/GpgKeyImportExporter.h" -#include "core/model/GpgKey.h" -#include "core/thread/TaskRunner.h" #include "ui/UserInterfaceUtils.h" -#include "ui/help/AboutDialog.h" -#include "ui/widgets/SignersPicker.h" +#include "ui/dialog/help/AboutDialog.h" +#include "dialog/SignersPicker.h" namespace GpgFrontend::UI { /** @@ -427,6 +423,9 @@ void MainWindow::slot_encrypt_sign() { connect(signersPicker, &SignersPicker::finished, &loop, &QEventLoop::quit); loop.exec(); + // return when canceled + if (!signersPicker->GetStatus()) return; + auto signer_key_ids = signersPicker->GetCheckedSigners(); auto signer_keys = GpgKeyGetter::GetInstance().GetKeys(signer_key_ids); diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp index 9d81b11c..9061349e 100644 --- a/src/ui/main_window/MainWindowSlotUI.cpp +++ b/src/ui/main_window/MainWindowSlotUI.cpp @@ -105,17 +105,17 @@ void MainWindow::slot_open_settings_dialog() { connect(dialog, &SettingsDialog::finished, this, [&]() -> void { LOG(INFO) << "Setting Dialog Finished"; - SettingsObject main_windows_state("main_windows_state"); + SettingsObject general_settings_state("general_settings_state"); - int width = main_windows_state.Check("icon_size").Check("width", 24), - height = main_windows_state.Check("icon_size").Check("height", 24); + int width = general_settings_state.Check("icon_size").Check("width", 24), + height = general_settings_state.Check("icon_size").Check("height", 24); LOG(INFO) << "icon_size" << width << height; - main_windows_state.Check("info_font_size", 10); + general_settings_state.Check("info_font_size", 10); // icon_style int s_icon_style = - main_windows_state.Check("icon_style", Qt::ToolButtonTextUnderIcon); + general_settings_state.Check("icon_style", Qt::ToolButtonTextUnderIcon); auto icon_style = static_cast<Qt::ToolButtonStyle>(s_icon_style); this->setToolButtonStyle(icon_style); import_button_->setToolButtonStyle(icon_style); diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp index 7d798c8b..1470b731 100644 --- a/src/ui/main_window/MainWindowUI.cpp +++ b/src/ui/main_window/MainWindowUI.cpp @@ -251,11 +251,17 @@ void MainWindow::create_actions() { connect(about_act_, &QAction::triggered, this, [=]() { new AboutDialog(0, this); }); + gnupg_act_ = new QAction(_("GnuPG"), this); + gnupg_act_->setIcon(QIcon(":help.png")); + gnupg_act_->setToolTip(_("Information about Gnupg")); + connect(gnupg_act_, &QAction::triggered, this, + [=]() { new AboutDialog(1, this); }); + translate_act_ = new QAction(_("Translate"), this); translate_act_->setIcon(QIcon(":help.png")); translate_act_->setToolTip(_("Information about translation")); connect(translate_act_, &QAction::triggered, this, - [=]() { new AboutDialog(1, this); }); + [=]() { new AboutDialog(2, this); }); /* * Check Update Menu @@ -377,6 +383,7 @@ void MainWindow::create_menus() { help_menu_->addSeparator(); help_menu_->addAction(check_update_act_); help_menu_->addAction(translate_act_); + help_menu_->addAction(gnupg_act_); help_menu_->addAction(about_act_); } |