diff options
author | saturneric <[email protected]> | 2024-04-14 12:56:18 +0000 |
---|---|---|
committer | saturneric <[email protected]> | 2024-04-14 12:56:18 +0000 |
commit | cb2672ca430c54244df7bd46ef97256c3d840cbf (patch) | |
tree | a54bb28d61cf9dbf608261782c4f3febec72ea8c /src/core/module/GlobalRegisterTable.cpp | |
parent | fix: use qt designer placeholder instead of custom initialized (diff) | |
download | GpgFrontend-cb2672ca430c54244df7bd46ef97256c3d840cbf.tar.gz GpgFrontend-cb2672ca430c54244df7bd46ef97256c3d840cbf.zip |
feat: add a grt viewer and solve some issues in gnupg info tab
Diffstat (limited to 'src/core/module/GlobalRegisterTable.cpp')
-rw-r--r-- | src/core/module/GlobalRegisterTable.cpp | 238 |
1 files changed, 208 insertions, 30 deletions
diff --git a/src/core/module/GlobalRegisterTable.cpp b/src/core/module/GlobalRegisterTable.cpp index c16eba37..006118b3 100644 --- a/src/core/module/GlobalRegisterTable.cpp +++ b/src/core/module/GlobalRegisterTable.cpp @@ -31,10 +31,10 @@ #include <any> #include <optional> #include <shared_mutex> -#include <sstream> -#include <unordered_map> +#include <utility> #include <vector> +#include "GlobalRegisterTableTreeModel.h" #include "function/SecureMemoryAllocator.h" #include "utils/MemoryUtils.h" @@ -43,33 +43,45 @@ namespace GpgFrontend::Module { class GlobalRegisterTable::Impl { public: struct RTNode { - std::optional<std::any> value = std::nullopt; - std::unordered_map<QString, SecureUniquePtr<RTNode>> children; + QString name; + QString type = "NODE"; int version = 0; - const std::type_info* type = nullptr; + const std::type_info* value_type = nullptr; + std::optional<std::any> value = std::nullopt; + QMap<QString, QSharedPointer<RTNode>> children; + QWeakPointer<RTNode> parent; + + explicit RTNode(QString name, const QSharedPointer<RTNode>& parent) + : name(std::move(name)), parent(parent) {} }; - explicit Impl(GlobalRegisterTable* parent) : parent_(parent) {} + using RTNodePtr = QSharedPointer<RTNode>; + + explicit Impl(GlobalRegisterTable* parent) + : parent_(parent), + root_node_(SecureCreateQSharedObject<RTNode>("", nullptr)) {} auto PublishKV(const Namespace& n, const Key& k, std::any v) -> bool { - QStringList const segments = k.split('.'); + QStringList const segments = (n + "." + k).split('.'); int version = 0; { std::unique_lock lock(lock_); - auto& root_rt_node = - global_register_table_.emplace(n, SecureCreateUniqueObject<RTNode>()) - .first->second; - RTNode* current = root_rt_node.get(); + auto current = root_node_; for (const QString& segment : segments) { - current = current->children - .emplace(segment, SecureCreateUniqueObject<RTNode>()) - .first->second.get(); + auto it = current->children.find(segment); + if (it == current->children.end()) { + it = current->children.insert( + segment, SecureCreateQSharedObject<RTNode>(segment, current)); + } + current = it.value(); } + current->name = segments.back(); + current->type = "LEAF"; current->value = v; - current->type = &v.type(); + current->value_type = &v.type(); version = ++current->version; } @@ -78,19 +90,17 @@ class GlobalRegisterTable::Impl { } auto LookupKV(const Namespace& n, const Key& k) -> std::optional<std::any> { - QStringList const segments = k.split('.'); + QStringList const segments = (n + "." + k).split('.'); std::optional<std::any> rtn = std::nullopt; { std::shared_lock const lock(lock_); - auto it = global_register_table_.find(n); - if (it == global_register_table_.end()) return std::nullopt; - RTNode* current = it->second.get(); + auto current = root_node_; for (const QString& segment : segments) { auto it = current->children.find(segment); if (it == current->children.end()) return std::nullopt; - current = it->second.get(); + current = it.value(); } rtn = current->value; } @@ -98,24 +108,20 @@ class GlobalRegisterTable::Impl { } auto ListChildKeys(const Namespace& n, const Key& k) -> std::vector<Key> { - QStringList const segments = k.split('.'); + QStringList const segments = (n + "." + k).split('.'); std::vector<Key> rtn; { std::shared_lock lock(lock_); - auto it = global_register_table_.find(n); - if (it == global_register_table_.end()) return {}; - RTNode* current = it->second.get(); + auto current = root_node_; for (const QString& segment : segments) { auto it = current->children.find(segment); if (it == current->children.end()) return {}; - current = it->second.get(); + current = it.value(); } - for (auto& it : current->children) { - rtn.emplace_back(it.first); - } + for (auto& key : current->children.keys()) rtn.emplace_back(key); } return rtn; } @@ -132,12 +138,149 @@ class GlobalRegisterTable::Impl { }) == nullptr; } + auto RootRTNode() -> RTNode* { return root_node_.get(); } + private: - using Table = std::map<Namespace, SecureUniquePtr<RTNode>>; std::shared_mutex lock_; GlobalRegisterTable* parent_; - Table global_register_table_; + RTNodePtr root_node_; +}; + +class GlobalRegisterTableTreeModel::Impl { + public: + using RTNode = GlobalRegisterTable::Impl::RTNode; + + Impl(GlobalRegisterTableTreeModel* parent, GlobalRegisterTable::Impl* grt) + : parent_(parent), root_node_(grt->RootRTNode()) {} + + [[nodiscard]] auto RowCount(const QModelIndex& parent) const -> int { + auto* parent_node = !parent.isValid() + ? root_node_.get() + : static_cast<RTNode*>(parent.internalPointer()); + return parent_node->children.size(); + } + + [[nodiscard]] auto ColumnCount(const QModelIndex& parent) const -> int { + return 4; + } + + [[nodiscard]] auto Data(const QModelIndex& index, int role) const + -> QVariant { + if (!index.isValid()) return {}; + + if (role == Qt::DisplayRole) { + auto* node = static_cast<RTNode*>(index.internalPointer()); + switch (index.column()) { + case 0: + return node->name; + case 1: + return node->type; + case 2: + return QString(node->value && node->value.has_value() + ? node->value->type().name() + : ""); + case 3: + return Any2QVariant(node->value); + default: + return {}; + } + } + return {}; + } + + static auto Any2QVariant(std::optional<std::any> op) -> QVariant { + if (!op) return "<EMPTY>"; + + auto& o = op.value(); + if (o.type() == typeid(QString)) { + return QVariant::fromValue(std::any_cast<QString>(o)); + } + if (o.type() == typeid(std::string)) { + return QVariant::fromValue( + QString::fromStdString(std::any_cast<std::string>(o))); + } + if (o.type() == typeid(int)) { + return QVariant::fromValue(std::any_cast<int>(o)); + } + if (o.type() == typeid(long)) { + return QVariant::fromValue( + static_cast<qlonglong>(std::any_cast<long>(o))); + } + if (o.type() == typeid(long long)) { + return QVariant::fromValue(std::any_cast<long long>(o)); + } + if (o.type() == typeid(unsigned)) { + return QVariant::fromValue(std::any_cast<unsigned>(o)); + } + if (o.type() == typeid(unsigned long)) { + return QVariant::fromValue( + static_cast<qulonglong>(std::any_cast<unsigned long>(o))); + } + if (o.type() == typeid(unsigned long long)) { + return QVariant::fromValue(std::any_cast<unsigned long long>(o)); + } + if (o.type() == typeid(float)) { + return QVariant::fromValue(std::any_cast<float>(o)); + } + if (o.type() == typeid(double)) { + return QVariant::fromValue(std::any_cast<double>(o)); + } + if (o.type() == typeid(bool)) { + return QVariant::fromValue(std::any_cast<bool>(o)); + } + return "<UNSUPPORTED>"; + } + + [[nodiscard]] auto Index(int row, int column, const QModelIndex& parent) const + -> QModelIndex { + if (!parent_->hasIndex(row, column, parent)) return {}; + + auto* parent_node = !parent.isValid() + ? root_node_.get() + : static_cast<RTNode*>(parent.internalPointer()); + auto key = parent_node->children.keys().at(row); + auto child_node = parent_node->children.value(key); + return parent_->createIndex(row, column, child_node.get()); + } + + [[nodiscard]] auto Parent(const QModelIndex& index) const -> QModelIndex { + if (!index.isValid()) return {}; + + auto* child_node = static_cast<RTNode*>(index.internalPointer()); + auto parent_node = child_node->parent.lock(); + + if (!parent_node || parent_node == root_node_) return {}; + + int row = + parent_node->parent.lock()->children.keys().indexOf(parent_node->name); + return parent_->createIndex(row, 0, parent_node.data()); + } + + [[nodiscard]] static auto HeaderData(int section, Qt::Orientation orientation, + int role) -> QVariant { + if (role != Qt::DisplayRole) return QVariant(); + + if (orientation == Qt::Horizontal) { + switch (section) { + case 0: + return QString("Key"); + case 1: + return QString("Type"); + case 2: + return QString("Value Type"); + case 3: + return QString("Value"); + default: + return {}; + } + } + return {}; + } + + private: + GlobalRegisterTableTreeModel* parent_; + GlobalRegisterTable::Impl::RTNodePtr root_node_; }; GlobalRegisterTable::GlobalRegisterTable() @@ -164,4 +307,39 @@ auto GlobalRegisterTable::ListChildKeys(Namespace n, Key k) return p_->ListChildKeys(n, k); } +GlobalRegisterTableTreeModel::GlobalRegisterTableTreeModel( + GlobalRegisterTable* grt) + : p_(SecureCreateUniqueObject<Impl>(this, grt->p_.get())) {} + +auto GlobalRegisterTableTreeModel::rowCount(const QModelIndex& parent) const + -> int { + return p_->RowCount(parent); +} + +auto GlobalRegisterTableTreeModel::columnCount(const QModelIndex& parent) const + -> int { + return p_->ColumnCount(parent); +} + +auto GlobalRegisterTableTreeModel::data(const QModelIndex& index, + int role) const -> QVariant { + return p_->Data(index, role); +} + +auto GlobalRegisterTableTreeModel::index(int row, int column, + const QModelIndex& parent) const + -> QModelIndex { + return p_->Index(row, column, parent); +} + +auto GlobalRegisterTableTreeModel::parent(const QModelIndex& index) const + -> QModelIndex { + return p_->Parent(index); +} + +auto GlobalRegisterTableTreeModel::headerData(int section, + Qt::Orientation orientation, + int role) const -> QVariant { + return p_->HeaderData(section, orientation, role); +} } // namespace GpgFrontend::Module
\ No newline at end of file |