aboutsummaryrefslogtreecommitdiffstats
path: root/src/core
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/core
parentfeat: support adsk (diff)
downloadGpgFrontend-b91a96e1bd50923100887efe2d8f262102447b39.tar.gz
GpgFrontend-b91a96e1bd50923100887efe2d8f262102447b39.zip
feat: add ui support for adsk features
Diffstat (limited to 'src/core')
-rw-r--r--src/core/function/gpg/GpgKeyOpera.cpp2
-rw-r--r--src/core/model/GpgAbstractKey.h59
-rw-r--r--src/core/model/GpgKey.cpp3
-rw-r--r--src/core/model/GpgKey.h13
-rw-r--r--src/core/model/GpgKeyTableModel.cpp8
-rw-r--r--src/core/model/GpgKeyTreeModel.cpp309
-rw-r--r--src/core/model/GpgKeyTreeModel.h424
-rw-r--r--src/core/model/GpgSubKey.cpp5
-rw-r--r--src/core/model/GpgSubKey.h23
-rw-r--r--src/core/utils/GpgUtils.cpp20
-rw-r--r--src/core/utils/GpgUtils.h16
11 files changed, 865 insertions, 17 deletions
diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp
index 931eae72..2378b518 100644
--- a/src/core/function/gpg/GpgKeyOpera.cpp
+++ b/src/core/function/gpg/GpgKeyOpera.cpp
@@ -371,7 +371,7 @@ auto AddADSKImpl(GpgContext& ctx, const GpgKey& key, const GpgSubKey& adsk,
unsigned int flags = GPGME_CREATE_ADSK;
LOG_D() << "add adsk args: " << key.GetId() << algo;
-
+
auto err =
gpgme_op_createsubkey(ctx.DefaultContext(), static_cast<gpgme_key_t>(key),
algo.toLatin1(), 0, 0, flags);
diff --git a/src/core/model/GpgAbstractKey.h b/src/core/model/GpgAbstractKey.h
new file mode 100644
index 00000000..b34643cd
--- /dev/null
+++ b/src/core/model/GpgAbstractKey.h
@@ -0,0 +1,59 @@
+/**
+ * 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
+
+namespace GpgFrontend {
+
+class GpgAbstractKey {
+ public:
+ [[nodiscard]] virtual auto ID() const -> QString = 0;
+ [[nodiscard]] virtual auto Fingerprint() const -> QString = 0;
+ [[nodiscard]] virtual auto IsSubKey() const -> bool = 0;
+ [[nodiscard]] virtual auto CreationTime() const -> QDateTime = 0;
+ [[nodiscard]] virtual auto IsHasEncrCap() const -> bool = 0;
+ [[nodiscard]] virtual auto IsHasSignCap() const -> bool = 0;
+ [[nodiscard]] virtual auto IsHasCertCap() const -> bool = 0;
+ [[nodiscard]] virtual auto IsHasAuthCap() const -> bool = 0;
+
+ //
+
+ [[nodiscard]] auto IsPrimaryKey() const -> bool { return IsHasCertCap(); }
+
+ auto operator==(const GpgAbstractKey& o) const -> bool {
+ return ID() == o.ID();
+ }
+
+ auto operator<(const GpgAbstractKey& o) const -> bool {
+ return ID() < o.ID();
+ }
+
+ virtual ~GpgAbstractKey() = default;
+};
+
+} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/model/GpgKey.cpp b/src/core/model/GpgKey.cpp
index 2bf15f3a..ce6f1c10 100644
--- a/src/core/model/GpgKey.cpp
+++ b/src/core/model/GpgKey.cpp
@@ -241,4 +241,7 @@ void GpgKey::KeyRefDeleter::operator()(gpgme_key_t _key) {
if (_key != nullptr) gpgme_key_unref(_key);
}
+auto GpgKey::GetPrimaryKey() const -> GpgSubKey {
+ return GpgSubKey(key_ref_->subkeys);
+}
} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/model/GpgKey.h b/src/core/model/GpgKey.h
index a3fe8396..e2743670 100644
--- a/src/core/model/GpgKey.h
+++ b/src/core/model/GpgKey.h
@@ -123,9 +123,9 @@ class GPGFRONTEND_CORE_EXPORT GpgKey {
auto operator<=(const GpgKey&) const -> bool;
/**
- * @brief
- *
- * @return gpgme_key_t
+ * @brief
+ *
+ * @return gpgme_key_t
*/
// NOLINTNEXTLINE(google-explicit-constructor)
operator gpgme_key_t() const;
@@ -364,6 +364,13 @@ class GPGFRONTEND_CORE_EXPORT GpgKey {
*/
[[nodiscard]] auto GetUIDs() const -> std::unique_ptr<QContainer<GpgUID>>;
+ /**
+ * @brief Get the Primary Key object
+ *
+ * @return GpgSubKey
+ */
+ [[nodiscard]] auto GetPrimaryKey() const -> GpgSubKey;
+
private:
/**
* @brief
diff --git a/src/core/model/GpgKeyTableModel.cpp b/src/core/model/GpgKeyTableModel.cpp
index b9d03bb6..53f5d1b1 100644
--- a/src/core/model/GpgKeyTableModel.cpp
+++ b/src/core/model/GpgKeyTableModel.cpp
@@ -30,6 +30,7 @@
#include "core/function/gpg/GpgKeyGetter.h"
#include "core/model/GpgKey.h"
+#include "core/utils/GpgUtils.h"
namespace GpgFrontend {
@@ -87,12 +88,7 @@ auto GpgKeyTableModel::data(const QModelIndex &index,
return key.GetEmail();
}
case 4: {
- QString usage_sym;
- if (key.IsHasActualCertCap()) usage_sym += "C";
- if (key.IsHasActualEncrCap()) usage_sym += "E";
- if (key.IsHasActualSignCap()) usage_sym += "S";
- if (key.IsHasActualAuthCap()) usage_sym += "A";
- return usage_sym;
+ return GetUsagesByKey(key);
}
case 5: {
return key.GetOwnerTrust();
diff --git a/src/core/model/GpgKeyTreeModel.cpp b/src/core/model/GpgKeyTreeModel.cpp
new file mode 100644
index 00000000..ce43d2d1
--- /dev/null
+++ b/src/core/model/GpgKeyTreeModel.cpp
@@ -0,0 +1,309 @@
+/**
+ * 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 "GpgKeyTreeModel.h"
+
+#include <utility>
+
+#include "core/model/GpgKey.h"
+#include "core/utils/GpgUtils.h"
+
+namespace GpgFrontend {
+
+GpgKeyTreeModel::GpgKeyTreeModel(int channel, const GpgKeyList &keys,
+ Detector checkable_detector,
+ Detector enable_detector, QObject *parent)
+ : QAbstractItemModel(parent),
+ gpg_context_channel_(channel),
+ column_headers_({
+ tr("Select"),
+ tr("Identity"),
+ tr("Key ID"),
+ tr("Type"),
+ tr("Usage"),
+ tr("Algorithm"),
+ tr("Create Date"),
+ }),
+ checkable_detector_(std::move(checkable_detector)),
+ enable_detector_(std::move(enable_detector)) {
+ setup_model_data(keys);
+}
+
+auto GpgKeyTreeModel::index(int row, int column,
+ const QModelIndex &parent) const -> QModelIndex {
+ if (!hasIndex(row, column, parent)) return {};
+
+ GpgKeyTreeItem *i_parent =
+ parent.isValid() ? static_cast<GpgKeyTreeItem *>(parent.internalPointer())
+ : root_.get();
+
+ auto *i_child = i_parent->Child(row);
+ if (i_child != nullptr) {
+ return createIndex(row, column, i_child);
+ }
+
+ return {};
+}
+
+auto GpgKeyTreeModel::rowCount(const QModelIndex &parent) const -> int {
+ if (parent.column() > 0) return 0;
+
+ const GpgKeyTreeItem *i_parent =
+ parent.isValid()
+ ? static_cast<const GpgKeyTreeItem *>(parent.internalPointer())
+ : root_.get();
+
+ return static_cast<int>(i_parent->ChildCount());
+}
+
+auto GpgKeyTreeModel::columnCount(const QModelIndex &parent) const -> int {
+ if (parent.isValid()) {
+ return static_cast<int>(
+ static_cast<GpgKeyTreeItem *>(parent.internalPointer())->ColumnCount());
+ }
+ return static_cast<int>(root_->ColumnCount());
+}
+
+auto GpgKeyTreeModel::data(const QModelIndex &index,
+ int role) const -> QVariant {
+ if (!index.isValid()) return {};
+
+ const auto *item =
+ static_cast<const GpgKeyTreeItem *>(index.internalPointer());
+
+ if (role == Qt::CheckStateRole) {
+ if (index.column() == 0 && item->Checkable()) {
+ return item->Checked() ? Qt::Checked : Qt::Unchecked;
+ }
+ }
+
+ if (role == Qt::DisplayRole) {
+ if (index.column() == 0) return item->Row();
+ return item->Data(index.column());
+ }
+
+ if (role == Qt::TextAlignmentRole) {
+ switch (index.column()) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ return Qt::AlignCenter;
+ default:
+ return {};
+ }
+ }
+
+ return {};
+}
+
+auto GpgKeyTreeModel::headerData(int section, Qt::Orientation orientation,
+ int role) const -> QVariant {
+ if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
+ return root_->Data(section);
+ }
+ return {};
+}
+
+auto GpgKeyTreeModel::flags(const QModelIndex &index) const -> Qt::ItemFlags {
+ if (!index.isValid()) return Qt::NoItemFlags;
+
+ const auto *item =
+ static_cast<const GpgKeyTreeItem *>(index.internalPointer());
+
+ if (index.column() == 0) {
+ return (item->Checkable() ? Qt::ItemIsUserCheckable : Qt::ItemFlags{0}) |
+ Qt::ItemIsSelectable |
+ (item->Enable() ? Qt::ItemIsEnabled : Qt::ItemFlags{0});
+ }
+
+ return Qt::ItemIsSelectable |
+ (item->Enable() ? Qt::ItemIsEnabled : Qt::ItemFlags{0});
+}
+
+auto GpgKeyTreeModel::setData(const QModelIndex &index, const QVariant &value,
+ int role) -> bool {
+ if (!index.isValid()) return false;
+
+ auto *item = static_cast<GpgKeyTreeItem *>(index.internalPointer());
+
+ if (index.column() == 0 && role == Qt::CheckStateRole) {
+ item->SetChecked(value == Qt::Checked);
+ emit dataChanged(index, index);
+ return true;
+ }
+
+ return false;
+}
+
+auto GpgKeyTreeModel::GetGpgContextChannel() const -> int {
+ return gpg_context_channel_;
+}
+
+void GpgKeyTreeModel::setup_model_data(const GpgKeyList &keys) {
+ auto root = QSharedPointer<GpgKeyTreeItem>::create(nullptr, column_headers_);
+ cached_items_.clear();
+
+ for (const auto &key : keys) {
+ auto pi_key = create_gpg_key_tree_items(key);
+ root->AppendChild(pi_key);
+ }
+
+ std::swap(root_, root);
+}
+
+auto GpgKeyTreeModel::parent(const QModelIndex &index) const -> QModelIndex {
+ if (!index.isValid()) return {};
+
+ auto *i_child = static_cast<GpgKeyTreeItem *>(index.internalPointer());
+ GpgKeyTreeItem *i_parent = i_child->ParentItem();
+
+ return i_parent != root_.get()
+ ? createIndex(static_cast<int>(i_parent->Row()), 0, i_parent)
+ : QModelIndex{};
+}
+
+auto GpgKeyTreeModel::GetAllCheckedKeyIds() -> KeyIdArgsList {
+ auto ret = KeyIdArgsList{};
+ for (const auto &item : cached_items_) {
+ if (!item->Checkable() || !item->Checked()) continue;
+ ret.push_back(item->Key()->ID());
+ }
+ return ret;
+}
+
+auto GpgKeyTreeModel::create_gpg_key_tree_items(const GpgKey &key)
+ -> QSharedPointer<GpgKeyTreeItem> {
+ QVariantList columns;
+ columns << "/";
+ columns << key.GetUIDs()->front().GetUID();
+ columns << key.GetId();
+ columns << "C";
+ columns << GetUsagesByKey(key);
+ columns << key.GetPublicKeyAlgo();
+ columns << key.GetKeyAlgo();
+ columns << QLocale().toString(key.GetCreateTime(), "yyyy-MM-dd");
+
+ auto i_key = QSharedPointer<GpgKeyTreeItem>::create(
+ QSharedPointer<GpgKeyAdapter>::create(key), columns);
+ i_key->SetEnable(enable_detector_(i_key->Key()));
+ i_key->SetCheckable(checkable_detector_(i_key->Key()));
+ cached_items_.push_back(i_key);
+
+ auto s_keys = key.GetSubKeys();
+ for (const auto &s_key : *s_keys) {
+ QVariantList columns;
+ columns << "/";
+ columns << key.GetUIDs()->front().GetUID();
+ columns << s_key.GetID();
+ columns << (s_key.IsHasCertCap() ? "P" : "S");
+ columns << GetUsagesBySubkey(s_key);
+ columns << s_key.GetPubkeyAlgo();
+ columns << s_key.GetKeyAlgo();
+ columns << QLocale().toString(s_key.GetCreateTime(), "yyyy-MM-dd");
+
+ auto i_s_key = QSharedPointer<GpgKeyTreeItem>::create(
+ QSharedPointer<GpgSubKeyAdapter>::create(s_key), columns);
+ i_s_key->SetEnable(enable_detector_(i_s_key->Key()));
+ i_s_key->SetCheckable(checkable_detector_(i_s_key->Key()));
+ i_key->AppendChild(i_s_key);
+ cached_items_.push_back(i_s_key);
+ }
+
+ return i_key;
+}
+
+auto GpgKeyTreeModel::GetAllCheckedSubKey() -> QContainer<GpgSubKey> {
+ QContainer<GpgSubKey> ret;
+ for (const auto &i : cached_items_) {
+ if (!i->Key()->IsSubKey() || !i->Checkable() || !i->Checked()) continue;
+
+ auto *adaptor = dynamic_cast<GpgSubKeyAdapter *>(i->Key());
+ if (adaptor == nullptr) continue;
+
+ ret.push_back(adaptor->GetRawKey());
+ }
+ return ret;
+}
+
+GpgKeyTreeItem::GpgKeyTreeItem(QSharedPointer<GpgAbstractKey> key,
+ QVariantList data)
+ : data_(std::move(data)), key_(std::move(key)) {}
+
+void GpgKeyTreeItem::AppendChild(const QSharedPointer<GpgKeyTreeItem> &child) {
+ child->parent_ = this;
+ children_.append(child);
+}
+
+auto GpgKeyTreeItem::Child(int row) -> GpgKeyTreeItem * {
+ return row >= 0 && row < ChildCount() ? children_.at(row).get() : nullptr;
+}
+
+auto GpgKeyTreeItem::ChildCount() const -> qsizetype {
+ return children_.size();
+}
+
+auto GpgKeyTreeItem::ColumnCount() const -> qsizetype { return data_.count(); }
+
+auto GpgKeyTreeItem::Data(qsizetype column) const -> QVariant {
+ return data_.value(column);
+}
+
+auto GpgKeyTreeItem::Row() const -> qsizetype {
+ if (parent_ == nullptr) return 0;
+ const auto it =
+ std::find_if(parent_->children_.cbegin(), parent_->children_.cend(),
+ [this](const auto &item) { return item.get() == this; });
+
+ if (it != parent_->children_.cend()) {
+ return std::distance(parent_->children_.cbegin(), it);
+ }
+
+ Q_ASSERT(false);
+ return -1;
+}
+
+auto GpgKeyTreeItem::ParentItem() -> GpgKeyTreeItem * { return parent_; }
+
+auto GpgKeyTreeItem::Checked() const -> bool { return checked_; }
+
+auto GpgKeyTreeItem::Checkable() const -> bool { return checkable_; }
+
+void GpgKeyTreeItem::SetChecked(bool checked) { checked_ = checked; }
+
+void GpgKeyTreeItem::SetCheckable(bool checkable) { checkable_ = checkable; }
+
+auto GpgKeyTreeItem::Key() const -> GpgAbstractKey * { return key_.get(); }
+
+auto GpgKeyTreeItem::Enable() const -> bool { return enable_; }
+
+void GpgKeyTreeItem::SetEnable(bool enable) { enable_ = enable; }
+
+} // namespace GpgFrontend
diff --git a/src/core/model/GpgKeyTreeModel.h b/src/core/model/GpgKeyTreeModel.h
new file mode 100644
index 00000000..96b78400
--- /dev/null
+++ b/src/core/model/GpgKeyTreeModel.h
@@ -0,0 +1,424 @@
+/**
+ * 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
+
+/**
+ * @brief
+ *
+ */
+#include <utility>
+
+#include "core/model/GpgAbstractKey.h"
+#include "core/model/GpgKey.h"
+#include "core/typedef/GpgTypedef.h"
+
+namespace GpgFrontend {
+
+enum class GpgKeyTreeColumn : unsigned int {
+ kNONE = 0,
+ kIDENTITY = 1 << 1,
+ kKEY_ID = 1 << 2,
+ kTYPE = 1 << 3,
+ kUSAGE = 1 << 4,
+ kALGO = 1 << 5,
+ kCREATE_DATE = 1 << 6,
+ kALL = ~0U
+};
+
+inline auto operator|(GpgKeyTreeColumn lhs,
+ GpgKeyTreeColumn rhs) -> GpgKeyTreeColumn {
+ using T = std::underlying_type_t<GpgKeyTreeColumn>;
+ return static_cast<GpgKeyTreeColumn>(static_cast<T>(lhs) |
+ static_cast<T>(rhs));
+}
+
+inline auto operator|=(GpgKeyTreeColumn &lhs,
+ GpgKeyTreeColumn rhs) -> GpgKeyTreeColumn & {
+ lhs = lhs | rhs;
+ return lhs;
+}
+
+inline auto operator&(GpgKeyTreeColumn lhs,
+ GpgKeyTreeColumn rhs) -> GpgKeyTreeColumn {
+ using T = std::underlying_type_t<GpgKeyTreeColumn>;
+ return static_cast<GpgKeyTreeColumn>(static_cast<T>(lhs) &
+ static_cast<T>(rhs));
+}
+
+inline auto operator&=(GpgKeyTreeColumn &lhs,
+ GpgKeyTreeColumn rhs) -> GpgKeyTreeColumn & {
+ lhs = lhs & rhs;
+ return lhs;
+}
+
+inline auto operator~(GpgKeyTreeColumn hs) -> GpgKeyTreeColumn {
+ using T = std::underlying_type_t<GpgKeyTreeColumn>;
+ return static_cast<GpgKeyTreeColumn>(~static_cast<T>(hs));
+}
+
+class GPGFRONTEND_CORE_EXPORT GpgKeyAdapter : public GpgAbstractKey {
+ public:
+ [[nodiscard]] auto ID() const -> QString override { return key_.GetId(); }
+
+ [[nodiscard]] auto Fingerprint() const -> QString override {
+ return key_.GetFingerprint();
+ }
+
+ [[nodiscard]] auto IsSubKey() const -> bool override { return false; }
+
+ [[nodiscard]] auto CreationTime() const -> QDateTime override {
+ return key_.GetCreateTime();
+ }
+
+ [[nodiscard]] auto IsHasEncrCap() const -> bool override {
+ return key_.IsHasActualEncrCap();
+ }
+
+ [[nodiscard]] auto IsHasSignCap() const -> bool override {
+ return key_.IsHasActualSignCap();
+ }
+
+ [[nodiscard]] auto IsHasCertCap() const -> bool override {
+ return key_.IsHasActualCertCap();
+ }
+
+ [[nodiscard]] auto IsHasAuthCap() const -> bool override {
+ return key_.IsHasActualAuthCap();
+ }
+
+ [[nodiscard]] auto GetRawKey() const -> const GpgKey & { return key_; }
+
+ explicit GpgKeyAdapter(GpgKey key) : key_(std::move(key)) {}
+
+ private:
+ GpgKey key_;
+};
+
+class GPGFRONTEND_CORE_EXPORT GpgSubKeyAdapter : public GpgAbstractKey {
+ public:
+ [[nodiscard]] auto ID() const -> QString override { return key_.GetID(); }
+
+ [[nodiscard]] auto Fingerprint() const -> QString override {
+ return key_.GetFingerprint();
+ }
+
+ [[nodiscard]] auto IsSubKey() const -> bool override { return true; }
+
+ [[nodiscard]] auto CreationTime() const -> QDateTime override {
+ return key_.GetCreateTime();
+ }
+
+ [[nodiscard]] auto IsHasEncrCap() const -> bool override {
+ return key_.IsHasEncrCap();
+ }
+
+ [[nodiscard]] auto IsHasSignCap() const -> bool override {
+ return key_.IsHasSignCap();
+ }
+
+ [[nodiscard]] auto IsHasCertCap() const -> bool override {
+ return key_.IsHasCertCap();
+ }
+
+ [[nodiscard]] auto IsHasAuthCap() const -> bool override {
+ return key_.IsHasAuthCap();
+ }
+
+ [[nodiscard]] auto GetRawKey() const -> const GpgSubKey & { return key_; }
+
+ explicit GpgSubKeyAdapter(const GpgSubKey &key) : key_(key) {}
+
+ private:
+ GpgSubKey key_;
+};
+
+class GPGFRONTEND_CORE_EXPORT GpgKeyTreeItem {
+ public:
+ GpgKeyTreeItem() = default;
+
+ /**
+ * @brief Construct a new Gpg Key Tree Item object
+ *
+ * @param headers
+ */
+ explicit GpgKeyTreeItem(QSharedPointer<GpgAbstractKey> key,
+ QVariantList data);
+
+ /**
+ * @brief
+ *
+ * @param child
+ */
+ void AppendChild(const QSharedPointer<GpgKeyTreeItem> &child);
+
+ /**
+ * @brief
+ *
+ * @param row
+ * @return GpgKeyTreeItem*
+ */
+ auto Child(int row) -> GpgKeyTreeItem *;
+
+ /**
+ * @brief
+ *
+ * @return qsizetype
+ */
+ [[nodiscard]] auto ChildCount() const -> qsizetype;
+
+ /**
+ * @brief
+ *
+ * @return qsizetype
+ */
+ [[nodiscard]] auto ColumnCount() const -> qsizetype;
+
+ /**
+ * @brief
+ *
+ * @param column
+ * @return QVariant
+ */
+ [[nodiscard]] auto Data(qsizetype column) const -> QVariant;
+
+ /**
+ * @brief
+ *
+ * @return qsizetype
+ */
+ [[nodiscard]] auto Row() const -> qsizetype;
+
+ /**
+ * @brief
+ *
+ * @return GpgKeyTreeItem*
+ */
+ auto ParentItem() -> GpgKeyTreeItem *;
+
+ /**
+ * @brief
+ *
+ * @return bool
+ */
+ [[nodiscard]] auto Checked() const -> bool;
+
+ /**
+ * @brief Set the Checked object
+ *
+ * @return true
+ * @return false
+ */
+ void SetChecked(bool);
+
+ /**
+ * @brief
+ *
+ * @return bool
+ */
+ [[nodiscard]] auto Checkable() const -> bool;
+
+ /**
+ * @brief
+ *
+ * @return bool
+ */
+ void SetCheckable(bool);
+
+ /**
+ * @brief
+ *
+ * @return bool
+ */
+ [[nodiscard]] auto Enable() const -> bool;
+
+ /**
+ * @brief
+ *
+ * @return bool
+ */
+ void SetEnable(bool);
+
+ /**
+ * @brief
+ *
+ * @return bool
+ */
+ [[nodiscard]] auto Key() const -> GpgAbstractKey *;
+
+ private:
+ QContainer<QSharedPointer<GpgKeyTreeItem>> children_;
+ QVariantList data_;
+ bool checked_;
+ bool checkable_;
+ bool enable_;
+ QSharedPointer<GpgAbstractKey> key_;
+ GpgKeyTreeItem *parent_ = nullptr;
+};
+
+class GPGFRONTEND_CORE_EXPORT GpgKeyTreeModel : public QAbstractItemModel {
+ Q_OBJECT
+ public:
+ using Detector = std::function<bool(GpgAbstractKey *)>;
+
+ /**
+ * @brief Construct a new Gpg Key Table Model object
+ *
+ * @param keys
+ * @param parent
+ */
+ explicit GpgKeyTreeModel(int channel, const GpgKeyList &keys,
+ Detector checkable, Detector enable,
+ QObject *parent = nullptr);
+
+ /**
+ * @brief
+ *
+ * @param row
+ * @param column
+ * @param parent
+ * @return QModelIndex
+ */
+ [[nodiscard]] auto index(int row, int column, const QModelIndex &parent) const
+ -> QModelIndex override;
+
+ /**
+ * @brief
+ *
+ * @param parent
+ * @return int
+ */
+ [[nodiscard]] auto rowCount(const QModelIndex &parent) const -> int override;
+
+ /**
+ * @brief
+ *
+ * @param parent
+ * @return int
+ */
+ [[nodiscard]] auto columnCount(const QModelIndex &parent) const
+ -> int override;
+
+ /**
+ * @brief
+ *
+ * @param index
+ * @param role
+ * @return QVariant
+ */
+ [[nodiscard]] auto data(const QModelIndex &index,
+ int role) const -> QVariant override;
+
+ /**
+ * @brief
+ *
+ * @param section
+ * @param orientation
+ * @param role
+ * @return QVariant
+ */
+ [[nodiscard]] auto headerData(int section, Qt::Orientation orientation,
+ int role) const -> QVariant override;
+
+ /**
+ * @brief Set the Data object
+ *
+ * @param index
+ * @param value
+ * @param role
+ * @return true
+ * @return false
+ */
+ auto setData(const QModelIndex &index, const QVariant &value,
+ int role) -> bool override;
+
+ /**
+ * @brief
+ *
+ * @param index
+ * @return Qt::ItemFlags
+ */
+ [[nodiscard]] auto flags(const QModelIndex &index) const
+ -> Qt::ItemFlags override;
+
+ /**
+ * @brief
+ *
+ * @param index
+ * @return QModelIndex
+ */
+ [[nodiscard]] auto parent(const QModelIndex &index) const
+ -> QModelIndex override;
+
+ /**
+ * @brief
+ *
+ * @return int
+ */
+ [[nodiscard]] auto GetGpgContextChannel() const -> int;
+
+ /**
+ * @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>;
+
+ private:
+ int gpg_context_channel_;
+ QVariantList column_headers_;
+ Detector checkable_detector_;
+ Detector enable_detector_;
+
+ QSharedPointer<GpgKeyTreeItem> root_;
+ QContainer<QSharedPointer<GpgKeyTreeItem>> cached_items_;
+
+ /**
+ * @brief
+ *
+ */
+ void setup_model_data(const GpgKeyList &keys);
+
+ /**
+ * @brief Create a gpg key tree items object
+ *
+ * @param key
+ * @return QSharedPointer<GpgKeyTreeItem>
+ */
+ auto create_gpg_key_tree_items(const GpgKey &key)
+ -> QSharedPointer<GpgKeyTreeItem>;
+};
+
+} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/model/GpgSubKey.cpp b/src/core/model/GpgSubKey.cpp
index 42fc476a..dbabf085 100644
--- a/src/core/model/GpgSubKey.cpp
+++ b/src/core/model/GpgSubKey.cpp
@@ -41,6 +41,10 @@ auto GpgSubKey::operator==(const GpgSubKey& o) const -> bool {
return GetFingerprint() == o.GetFingerprint();
}
+auto GpgSubKey::operator<(const GpgSubKey& o) const -> bool {
+ return GetID() < o.GetID();
+}
+
auto GpgSubKey::GetID() const -> QString { return subkey_ref_->keyid; }
auto GpgSubKey::GetFingerprint() const -> QString { return subkey_ref_->fpr; }
@@ -99,4 +103,5 @@ auto GpgSubKey::IsADSK() const -> bool { return subkey_ref_->can_renc; }
auto GpgSubKey::SmartCardSerialNumber() -> QString {
return subkey_ref_->card_number;
}
+
} // namespace GpgFrontend
diff --git a/src/core/model/GpgSubKey.h b/src/core/model/GpgSubKey.h
index e5a8a21b..6577ff5a 100644
--- a/src/core/model/GpgSubKey.h
+++ b/src/core/model/GpgSubKey.h
@@ -78,6 +78,15 @@ class GPGFRONTEND_CORE_EXPORT GpgSubKey {
/**
* @brief
*
+ * @param o
+ * @return true
+ * @return false
+ */
+ auto operator<(const GpgSubKey& o) const -> bool;
+
+ /**
+ * @brief
+ *
* @return QString
*/
[[nodiscard]] auto GetID() const -> QString;
@@ -205,17 +214,17 @@ class GPGFRONTEND_CORE_EXPORT GpgSubKey {
[[nodiscard]] auto GetExpireTime() const -> QDateTime;
/**
- * @brief
- *
- * @return true
- * @return false
+ * @brief
+ *
+ * @return true
+ * @return false
*/
[[nodiscard]] auto IsADSK() const -> bool;
/**
- * @brief
- *
- * @return QString
+ * @brief
+ *
+ * @return QString
*/
[[nodiscard]] auto SmartCardSerialNumber() -> QString;
diff --git a/src/core/utils/GpgUtils.cpp b/src/core/utils/GpgUtils.cpp
index c96f523b..c7040cc2 100644
--- a/src/core/utils/GpgUtils.cpp
+++ b/src/core/utils/GpgUtils.cpp
@@ -333,4 +333,24 @@ auto GPGFRONTEND_CORE_EXPORT Convert2RawGpgMEKeyList(
return recipients;
}
+
+auto GPGFRONTEND_CORE_EXPORT GetUsagesByKey(const GpgKey& key) -> QString {
+ QString usages;
+ if (key.IsHasActualCertCap()) usages += "C";
+ if (key.IsHasActualEncrCap()) usages += "E";
+ if (key.IsHasActualSignCap()) usages += "S";
+ if (key.IsHasActualAuthCap()) usages += "A";
+ return usages;
+}
+
+auto GPGFRONTEND_CORE_EXPORT GetUsagesBySubkey(const GpgSubKey& key)
+ -> QString {
+ QString usages;
+ if (key.IsHasCertCap()) usages += "C";
+ if (key.IsHasEncrCap()) usages += "E";
+ if (key.IsHasSignCap()) usages += "S";
+ if (key.IsHasAuthCap()) usages += "A";
+ if (key.IsADSK()) usages += "R";
+ return usages;
+}
} // namespace GpgFrontend
diff --git a/src/core/utils/GpgUtils.h b/src/core/utils/GpgUtils.h
index 7710f56e..b453cc0a 100644
--- a/src/core/utils/GpgUtils.h
+++ b/src/core/utils/GpgUtils.h
@@ -157,4 +157,20 @@ auto GPGFRONTEND_CORE_EXPORT GetGpgKeyDatabaseName(int channel) -> QString;
auto GPGFRONTEND_CORE_EXPORT Convert2RawGpgMEKeyList(
const QContainer<GpgKey>& keys) -> QContainer<gpgme_key_t>;
+/**
+ * @brief
+ *
+ * @param key
+ * @return QString
+ */
+auto GPGFRONTEND_CORE_EXPORT GetUsagesByKey(const GpgKey& key) -> QString;
+
+/**
+ * @brief
+ *
+ * @param key
+ * @return QString
+ */
+auto GPGFRONTEND_CORE_EXPORT GetUsagesBySubkey(const GpgSubKey& key) -> QString;
+
} // namespace GpgFrontend \ No newline at end of file