aboutsummaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2025-04-12 10:15:20 +0000
committersaturneric <[email protected]>2025-04-12 10:15:20 +0000
commitb91a96e1bd50923100887efe2d8f262102447b39 (patch)
treed58d71c23dcf5d8ae528c9fa54c1a6236101dc99 /src/ui
parentfeat: support adsk (diff)
downloadGpgFrontend-b91a96e1bd50923100887efe2d8f262102447b39.tar.gz
GpgFrontend-b91a96e1bd50923100887efe2d8f262102447b39.zip
feat: add ui support for adsk features
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/dialog/SubKeysPicker.cpp82
-rw-r--r--src/ui/dialog/SubKeysPicker.h74
-rw-r--r--src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp92
-rw-r--r--src/ui/dialog/keypair_details/KeyPairSubkeyTab.h8
-rw-r--r--src/ui/widgets/KeyTreeView.cpp84
-rw-r--r--src/ui/widgets/KeyTreeView.h85
6 files changed, 413 insertions, 12 deletions
diff --git a/src/ui/dialog/SubKeysPicker.cpp b/src/ui/dialog/SubKeysPicker.cpp
new file mode 100644
index 00000000..af9c5c6d
--- /dev/null
+++ b/src/ui/dialog/SubKeysPicker.cpp
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2021-2024 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 "SubKeysPicker.h"
+
+#include "core/GpgModel.h"
+#include "ui/widgets/KeyTreeView.h"
+
+namespace GpgFrontend::UI {
+
+SubKeysPicker::SubKeysPicker(int channel,
+ const GpgKeyTreeModel::Detector& enable_detector,
+ QWidget* parent)
+ : GeneralDialog(typeid(SubKeysPicker).name(), parent),
+ tree_view_(new KeyTreeView(
+ channel, [](GpgAbstractKey* k) { return k->IsSubKey(); },
+ [=](GpgAbstractKey* k) {
+ return (!k->IsSubKey() || (k->IsSubKey() && !k->IsPrimaryKey() &&
+ k->IsHasEncrCap())) &&
+ enable_detector(k);
+ })) {
+ auto* confirm_button = new QPushButton(tr("Confirm"));
+ auto* cancel_button = new QPushButton(tr("Cancel"));
+
+ connect(confirm_button, &QPushButton::clicked,
+ [=]() { this->accepted_ = true; });
+ connect(confirm_button, &QPushButton::clicked, this, &QDialog::accept);
+ connect(cancel_button, &QPushButton::clicked, this, &QDialog::reject);
+
+ auto* vbox2 = new QVBoxLayout();
+ vbox2->addWidget(new QLabel(tr("Select Subkey(s)") + ": "));
+ vbox2->addWidget(tree_view_);
+ vbox2->addWidget(new QLabel(
+ tr("Please select one or more subkeys you use for operation.")));
+ vbox2->addWidget(confirm_button);
+ vbox2->addWidget(cancel_button);
+ setLayout(vbox2);
+
+ tree_view_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ this->setWindowFlags(Qt::Window | Qt::WindowTitleHint |
+ Qt::CustomizeWindowHint);
+
+ this->setModal(true);
+ this->setWindowTitle(tr("Subkeys Picker"));
+
+ movePosition2CenterOfParent();
+ this->show();
+}
+
+auto SubKeysPicker::GetCheckedSubkeys() -> QContainer<GpgSubKey> {
+ return tree_view_->GetAllCheckedSubKey();
+}
+
+auto SubKeysPicker::GetStatus() const -> bool { return this->accepted_; }
+
+} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/SubKeysPicker.h b/src/ui/dialog/SubKeysPicker.h
new file mode 100644
index 00000000..a7a1b200
--- /dev/null
+++ b/src/ui/dialog/SubKeysPicker.h
@@ -0,0 +1,74 @@
+/**
+ * Copyright (C) 2021-2024 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
+ *
+ */
+
+#pragma once
+
+#include "GpgFrontendUI.h"
+#include "core/model/GpgKeyTreeModel.h"
+#include "core/typedef/GpgTypedef.h"
+#include "ui/dialog//GeneralDialog.h"
+
+namespace GpgFrontend::UI {
+
+class KeyTreeView;
+
+/**
+ * @brief
+ *
+ */
+class SubKeysPicker : public GeneralDialog {
+ Q_OBJECT
+
+ public:
+ /**
+ * @brief Construct a new Signers Picker object
+ *
+ * @param parent
+ */
+ explicit SubKeysPicker(int channel, const GpgKeyTreeModel::Detector& enable,
+ QWidget* parent = nullptr);
+
+ /**
+ * @brief Get the Checked Signers object
+ *
+ * @return GpgFrontend::KeyIdArgsListPtr
+ */
+ auto GetCheckedSubkeys() -> QContainer<GpgSubKey>;
+
+ /**
+ *
+ * @return
+ */
+ [[nodiscard]] auto GetStatus() const -> bool;
+
+ private:
+ KeyTreeView* tree_view_; ///<
+ bool accepted_ = false;
+};
+
+} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp
index 548b3473..526b9dd5 100644
--- a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp
+++ b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.cpp
@@ -32,12 +32,14 @@
#include "core/function/gpg/GpgKeyGetter.h"
#include "core/function/gpg/GpgKeyImportExporter.h"
#include "core/function/gpg/GpgKeyManager.h"
+#include "core/function/gpg/GpgKeyOpera.h"
#include "core/utils/CommonUtils.h"
#include "core/utils/GpgUtils.h"
#include "core/utils/IOUtils.h"
#include "ui/UISignalStation.h"
#include "ui/UserInterfaceUtils.h"
#include "ui/dialog/RevocationOptionsDialog.h"
+#include "ui/dialog/SubKeysPicker.h"
namespace GpgFrontend::UI {
@@ -58,12 +60,17 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(int channel, const QString& key_id,
auto* uid_buttons_layout = new QGridLayout();
auto* add_subkey_button = new QPushButton(tr("Generate A New Subkey"));
+ auto* add_adsk_button = new QPushButton(tr("Add ADSK(s)"));
if (!key_.IsPrivateKey() || !key_.IsHasMasterKey()) {
add_subkey_button->setDisabled(true);
- setHidden(add_subkey_button);
+ add_subkey_button->hide();
+
+ add_adsk_button->setDisabled(true);
+ add_adsk_button->hide();
}
uid_buttons_layout->addWidget(add_subkey_button, 0, 1);
+ uid_buttons_layout->addWidget(add_adsk_button, 1, 1);
auto* base_layout = new QVBoxLayout();
@@ -137,6 +144,8 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(int channel, const QString& key_id,
connect(add_subkey_button, &QPushButton::clicked, this,
&KeyPairSubkeyTab::slot_add_subkey);
+ connect(add_adsk_button, &QPushButton::clicked, this,
+ &KeyPairSubkeyTab::slot_add_adsk);
connect(subkey_list_, &QTableWidget::itemSelectionChanged, this,
&KeyPairSubkeyTab::slot_refresh_subkey_detail);
@@ -205,8 +214,10 @@ void KeyPairSubkeyTab::slot_refresh_subkey_list() {
tmp0->setTextAlignment(Qt::AlignCenter);
subkey_list_->setItem(row, 0, tmp0);
- auto* tmp1 = new QTableWidgetItem(subkey.IsHasCertCap() ? tr("Primary Key")
- : tr("Subkey"));
+ auto type = subkey.IsHasCertCap() ? tr("Primary Key") : tr("Subkey");
+ if (subkey.IsADSK()) type = tr("ADSK");
+
+ auto* tmp1 = new QTableWidgetItem(type);
tmp1->setTextAlignment(Qt::AlignCenter);
subkey_list_->setItem(row, 1, tmp1);
@@ -276,6 +287,72 @@ void KeyPairSubkeyTab::slot_add_subkey() {
dialog->show();
}
+void KeyPairSubkeyTab::slot_add_adsk() {
+ QStringList except_key_ids;
+ except_key_ids.append(key_.GetId());
+ auto except_sub_keys = key_.GetSubKeys();
+ for (const auto& sub_key : *except_sub_keys) {
+ except_key_ids.append(sub_key.GetID());
+ }
+
+ auto* dialog = new SubKeysPicker(
+ current_gpg_context_channel_,
+ [=](GpgAbstractKey* key) { return !except_key_ids.contains(key->ID()); },
+ this);
+ dialog->exec();
+
+ if (!dialog->GetStatus()) {
+ dialog->deleteLater();
+ return;
+ }
+
+ auto sub_keys = dialog->GetCheckedSubkeys();
+ dialog->deleteLater();
+
+ if (sub_keys.isEmpty()) {
+ QMessageBox::information(this, tr("No Subkeys Selected"),
+ tr("Please select at least one subkey."));
+ return;
+ }
+
+ QContainer<GpgSubKey> err_sub_keys;
+ for (const auto& sub_key : sub_keys) {
+ auto [err, data_object] =
+ GpgKeyOpera::GetInstance(current_gpg_context_channel_)
+ .AddADSKSync(key_, sub_key);
+ if (CheckGpgError(err) == GPG_ERR_NO_ERROR) continue;
+
+ err_sub_keys.append(sub_key);
+ }
+
+ if (err_sub_keys.isEmpty()) {
+ QMessageBox::information(
+ this, tr("Success"),
+ tr("All selected subkeys were successfully added as ADSKs."));
+ } else {
+ QStringList failed_info;
+ for (const auto& sub_key : err_sub_keys) {
+ QString key_id = sub_key.GetID();
+ failed_info << tr("Key ID: %1").arg(key_id);
+ }
+
+ QString details = failed_info.join("\n\n");
+
+ QMessageBox msg_box(this);
+ msg_box.setIcon(QMessageBox::Warning);
+ msg_box.setWindowTitle(err_sub_keys.size() == sub_keys.size()
+ ? tr("Failed")
+ : tr("Partially Failed"));
+ msg_box.setText(err_sub_keys.size() == sub_keys.size()
+ ? tr("Failed to add all selected subkeys.")
+ : tr("Some subkeys failed to be added as ADSKs."));
+ msg_box.setDetailedText(details);
+ msg_box.exec();
+ }
+
+ emit SignalKeyDatabaseRefresh();
+}
+
void KeyPairSubkeyTab::slot_refresh_subkey_detail() {
const auto& subkey = get_selected_subkey();
@@ -306,14 +383,7 @@ void KeyPairSubkeyTab::slot_refresh_subkey_detail() {
QString buffer;
QTextStream usage_steam(&buffer);
- if (subkey.IsHasCertCap()) {
- usage_steam << tr("Certificate") << " ";
- }
- if (subkey.IsHasEncrCap()) usage_steam << tr("Encrypt") << " ";
- if (subkey.IsHasSignCap()) usage_steam << tr("Sign") << " ";
- if (subkey.IsHasAuthCap()) usage_steam << tr("Auth") << " ";
-
- usage_var_label_->setText(usage_steam.readAll());
+ usage_var_label_->setText(GetUsagesBySubkey(subkey));
// Show the situation that secret key not exists.
master_key_exist_var_label_->setText(subkey.IsSecretKey() ? tr("Exists")
diff --git a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.h b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.h
index b4aa9a00..d06ee032 100644
--- a/src/ui/dialog/keypair_details/KeyPairSubkeyTab.h
+++ b/src/ui/dialog/keypair_details/KeyPairSubkeyTab.h
@@ -65,7 +65,7 @@ class KeyPairSubkeyTab : public QWidget {
*
* @return const GpgSubKey&
*/
- const GpgSubKey& get_selected_subkey();
+ auto get_selected_subkey() -> const GpgSubKey&;
int current_gpg_context_channel_;
GpgKey key_; ///<
@@ -147,6 +147,12 @@ class KeyPairSubkeyTab : public QWidget {
*/
void slot_delete_subkey();
+ /**
+ * @brief
+ *
+ */
+ void slot_add_adsk();
+
signals:
/**
diff --git a/src/ui/widgets/KeyTreeView.cpp b/src/ui/widgets/KeyTreeView.cpp
new file mode 100644
index 00000000..0e8ab859
--- /dev/null
+++ b/src/ui/widgets/KeyTreeView.cpp
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2021-2024 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 "ui/widgets/KeyTreeView.h"
+
+#include "core/function/gpg/GpgKeyGetter.h"
+
+namespace GpgFrontend::UI {
+
+KeyTreeView::KeyTreeView(int channel,
+ GpgKeyTreeModel::Detector checkable_detector,
+ GpgKeyTreeModel::Detector enable_detector,
+ QWidget* parent)
+ : QTreeView(parent), channel_(channel) {
+ model_ = QSharedPointer<GpgKeyTreeModel>::create(
+ channel, GpgKeyGetter::GetInstance(channel_).FetchKey(),
+ checkable_detector, enable_detector, this);
+
+ setModel(model_.get());
+
+ sortByColumn(2, Qt::AscendingOrder);
+ setSelectionBehavior(QAbstractItemView::SelectRows);
+ setSelectionMode(QAbstractItemView::SingleSelection);
+
+ setEditTriggers(QAbstractItemView::NoEditTriggers);
+ header()->resizeSections(QHeaderView::Interactive);
+ header()->setDefaultAlignment(Qt::AlignCenter);
+
+ setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
+
+ setFocusPolicy(Qt::NoFocus);
+ setAlternatingRowColors(true);
+ setSortingEnabled(true);
+}
+
+void KeyTreeView::paintEvent(QPaintEvent* event) {
+ QTreeView::paintEvent(event);
+
+ if (!init_) {
+ slot_adjust_column_widths();
+ init_ = true;
+ }
+}
+
+void KeyTreeView::slot_adjust_column_widths() {
+ for (int i = 1; i < model_->columnCount({}); ++i) {
+ this->resizeColumnToContents(i);
+ }
+}
+
+auto KeyTreeView::GetAllCheckedKeyIds() -> KeyIdArgsList {
+ return model_->GetAllCheckedKeyIds();
+}
+
+auto KeyTreeView::GetAllCheckedSubKey() -> QContainer<GpgSubKey> {
+ return model_->GetAllCheckedSubKey();
+}
+
+} // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/KeyTreeView.h b/src/ui/widgets/KeyTreeView.h
new file mode 100644
index 00000000..ba0f09a4
--- /dev/null
+++ b/src/ui/widgets/KeyTreeView.h
@@ -0,0 +1,85 @@
+/**
+ * Copyright (C) 2021-2024 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
+ *
+ */
+
+#pragma once
+
+#include "core/model/GpgKey.h"
+#include "core/model/GpgKeyTreeModel.h"
+
+namespace GpgFrontend::UI {
+
+/**
+ * @brief
+ *
+ */
+class KeyTreeView : public QTreeView {
+ Q_OBJECT
+ public:
+ /**
+ * @brief Construct a new Key Table object
+ *
+ * @param _key_list
+ * @param _select_type
+ * @param _info_type
+ * @param _filter
+ */
+ explicit KeyTreeView(int channel,
+ GpgKeyTreeModel::Detector checkable_detector,
+ GpgKeyTreeModel::Detector enable_detector,
+ QWidget* parent = nullptr);
+
+ /**
+ * @brief Get the All Checked Key Ids object
+ *
+ * @return KeyIdArgsList
+ */
+ auto GetAllCheckedKeyIds() -> KeyIdArgsList;
+
+ /**
+ * @brief Get the All Checked Sub Key object
+ *
+ * @return QContainer<GpgSubKey>
+ */
+ auto GetAllCheckedSubKey() -> QContainer<GpgSubKey>;
+
+ protected:
+ /**
+ * @brief
+ *
+ */
+ void paintEvent(QPaintEvent* event) override;
+
+ private:
+ bool init_;
+ int channel_;
+ QSharedPointer<GpgKeyTreeModel> model_; ///<
+
+ void slot_adjust_column_widths();
+};
+
+} // namespace GpgFrontend::UI \ No newline at end of file