diff options
author | saturneric <[email protected]> | 2024-06-02 20:03:59 +0000 |
---|---|---|
committer | saturneric <[email protected]> | 2024-06-02 20:03:59 +0000 |
commit | e7694f9a0729cb88064eda6623c99070f5a46dc0 (patch) | |
tree | 39c5339991212dc4eaf653ec3e016b8daa79fbb7 | |
parent | fix: cannot show version in about tab (diff) | |
download | GpgFrontend-e7694f9a0729cb88064eda6623c99070f5a46dc0.tar.gz GpgFrontend-e7694f9a0729cb88064eda6623c99070f5a46dc0.zip |
feat: rewrite key list structure and logic
-rw-r--r-- | src/core/function/CacheManager.cpp | 3 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyGetter.cpp | 25 | ||||
-rw-r--r-- | src/core/function/gpg/GpgKeyGetter.h | 8 | ||||
-rw-r--r-- | src/core/model/GpgKeyTableModel.cpp | 162 | ||||
-rw-r--r-- | src/core/model/GpgKeyTableModel.h | 196 | ||||
-rw-r--r-- | src/core/model/GpgKeyTableProxyModel.cpp | 142 | ||||
-rw-r--r-- | src/core/model/GpgKeyTableProxyModel.h | 82 | ||||
-rw-r--r-- | src/core/typedef/GpgTypedef.h | 2 | ||||
-rw-r--r-- | src/ui/UserInterfaceUtils.cpp | 46 | ||||
-rw-r--r-- | src/ui/UserInterfaceUtils.h | 13 | ||||
-rw-r--r-- | src/ui/dialog/SignersPicker.cpp | 7 | ||||
-rw-r--r-- | src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp | 6 | ||||
-rw-r--r-- | src/ui/main_window/KeyMgmt.cpp | 57 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowSlotFunction.cpp | 4 | ||||
-rw-r--r-- | src/ui/main_window/MainWindowUI.cpp | 39 | ||||
-rw-r--r-- | src/ui/widgets/KeyList.cpp | 536 | ||||
-rw-r--r-- | src/ui/widgets/KeyList.h | 166 |
17 files changed, 989 insertions, 505 deletions
diff --git a/src/core/function/CacheManager.cpp b/src/core/function/CacheManager.cpp index 719c962d..4dd12f59 100644 --- a/src/core/function/CacheManager.cpp +++ b/src/core/function/CacheManager.cpp @@ -165,9 +165,10 @@ class CacheManager::Impl : public QObject { * */ void slot_flush_cache_storage() { + GF_CORE_LOG_TRACE("write cache to file system..."); + for (const auto& cache : durable_cache_storage_.mirror()) { auto key = get_data_object_key(cache.first); - GF_CORE_LOG_TRACE("save cache into filesystem, key {}", key); GpgFrontend::DataObjectOperator::GetInstance().SaveDataObj( key, QJsonDocument(cache.second)); } diff --git a/src/core/function/gpg/GpgKeyGetter.cpp b/src/core/function/gpg/GpgKeyGetter.cpp index 4a35d3cd..870e68b3 100644 --- a/src/core/function/gpg/GpgKeyGetter.cpp +++ b/src/core/function/gpg/GpgKeyGetter.cpp @@ -92,6 +92,22 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { return keys_list; } + auto FetchGpgKeyList() -> GpgKeyList { + if (keys_search_cache_.empty()) { + FlushKeyCache(); + } + + auto keys_list = GpgKeyList{}; + { + // get the lock + std::lock_guard<std::mutex> lock(keys_cache_mutex_); + for (const auto& key : keys_cache_) { + keys_list.push_back(key); + } + } + return keys_list; + } + auto FlushKeyCache() -> bool { GF_CORE_LOG_DEBUG("flush key channel called, channel: {}", GetChannel()); @@ -165,6 +181,11 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { return keys_copy; } + auto GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel> { + return SecureCreateQSharedObject<GpgKeyTableModel>(FetchGpgKeyList(), + nullptr); + } + private: /** * @brief Get the gpgme context object @@ -248,4 +269,8 @@ auto GpgKeyGetter::GetKeysCopy(const KeyListPtr& keys) -> KeyListPtr { auto GpgKeyGetter::FetchKey() -> KeyLinkListPtr { return p_->FetchKey(); } +auto GpgKeyGetter::GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel> { + return p_->GetGpgKeyTableModel(); +} + } // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgKeyGetter.h b/src/core/function/gpg/GpgKeyGetter.h index 91138623..2c4c0706 100644 --- a/src/core/function/gpg/GpgKeyGetter.h +++ b/src/core/function/gpg/GpgKeyGetter.h @@ -29,6 +29,7 @@ #pragma once #include "core/function/basic/GpgFunctionObject.h" +#include "core/model/GpgKeyTableModel.h" #include "core/typedef/GpgTypedef.h" namespace GpgFrontend { @@ -106,6 +107,13 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter */ auto GetKeysCopy(const KeyLinkListPtr& keys) -> KeyLinkListPtr; + /** + * @brief + * + * @return GpgKeyTableModel + */ + auto GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel>; + private: class Impl; SecureUniquePtr<Impl> p_; diff --git a/src/core/model/GpgKeyTableModel.cpp b/src/core/model/GpgKeyTableModel.cpp new file mode 100644 index 00000000..cff619cd --- /dev/null +++ b/src/core/model/GpgKeyTableModel.cpp @@ -0,0 +1,162 @@ +/** + * Copyright (C) 2021 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 "GpgKeyTableModel.h" + +#include "core/function/gpg/GpgKeyGetter.h" +#include "core/model/GpgKey.h" + +namespace GpgFrontend { + +GpgKeyTableModel::GpgKeyTableModel(GpgKeyList keys, QObject *parent) + : QAbstractTableModel(parent), + buffered_keys_(keys), + column_headers_({tr("Select"), tr("Type"), tr("Name"), + tr("Email Address"), tr("Usage"), tr("Trust"), + tr("Key ID"), tr("Finger Print")}), + key_check_state_(buffered_keys_.size()) {} + +auto GpgKeyTableModel::rowCount(const QModelIndex & /*parent*/) const -> int { + return static_cast<int>(buffered_keys_.size()); +} + +auto GpgKeyTableModel::columnCount(const QModelIndex & /*parent*/) const + -> int { + return 8; +} + +auto GpgKeyTableModel::data(const QModelIndex &index, int role) const + -> QVariant { + if (!index.isValid() || buffered_keys_.empty()) return {}; + + if (role == Qt::TextAlignmentRole) { + return Qt::AlignCenter; + } + + if (role == Qt::CheckStateRole) { + if (index.column() == 0) { + return key_check_state_[index.row()] ? Qt::Checked : Qt::Unchecked; + } + return {}; + } + + const auto &key = buffered_keys_.at(index.row()); + + switch (index.column()) { + case 0: { + return index.row(); + } + case 1: { + QString type_sym; + type_sym += key.IsPrivateKey() ? "pub/sec" : "pub"; + if (key.IsPrivateKey() && !key.IsHasMasterKey()) type_sym += "#"; + if (key.IsHasCardKey()) type_sym += "^"; + return type_sym; + } + case 2: { + return key.GetName(); + } + case 3: { + return key.GetEmail(); + } + case 4: { + QString usage_sym; + if (key.IsHasActualCertificationCapability()) usage_sym += "C"; + if (key.IsHasActualEncryptionCapability()) usage_sym += "E"; + if (key.IsHasActualSigningCapability()) usage_sym += "S"; + if (key.IsHasActualAuthenticationCapability()) usage_sym += "A"; + return usage_sym; + } + case 5: { + return key.GetOwnerTrust(); + } + case 6: { + return key.GetId(); + } + case 7: { + return key.GetFingerprint(); + } + default: + return {}; + } +} + +auto GpgKeyTableModel::headerData(int section, Qt::Orientation orientation, + int role) const -> QVariant { + if (role != Qt::DisplayRole) return {}; + + if (orientation == Qt::Horizontal) { + return column_headers_[section]; + } + + return {}; +} + +auto GpgKeyTableModel::flags(const QModelIndex &index) const -> Qt::ItemFlags { + if (!index.isValid()) return Qt::NoItemFlags; + + if (index.column() == 0) { + return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled; + } + + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; +} + +auto GpgKeyTableModel::setData(const QModelIndex &index, const QVariant &value, + int role) -> bool { + if (!index.isValid()) return false; + + if (index.column() == 0 && role == Qt::CheckStateRole) { + key_check_state_[index.row()] = (value == Qt::Checked); + emit dataChanged(index, index); + return true; + } + + return false; +} + +auto GpgKeyTableModel::GetAllKeyIds() -> GpgKeyIDList { + GpgKeyIDList keys; + for (auto &key : buffered_keys_) { + keys.push_back(key.GetId()); + } + return keys; +} + +auto GpgKeyTableModel::GetKeyIDByRow(int row) const -> QString { + if (buffered_keys_.size() <= row) return {}; + + return buffered_keys_[row].GetId(); +} + +auto GpgKeyTableModel::IsPrivateKeyByRow(int row) const -> bool { + if (buffered_keys_.size() <= row) return false; + return buffered_keys_[row].IsPrivateKey(); +} + +} // namespace GpgFrontend diff --git a/src/core/model/GpgKeyTableModel.h b/src/core/model/GpgKeyTableModel.h new file mode 100644 index 00000000..047820a5 --- /dev/null +++ b/src/core/model/GpgKeyTableModel.h @@ -0,0 +1,196 @@ +/** + * Copyright (C) 2021 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 "core/model/GpgKey.h" +#include "core/typedef/GpgTypedef.h" + +namespace GpgFrontend { + +enum class GpgKeyTableColumn : unsigned int { + kNone = 0, + kType = 1 << 0, + kName = 1 << 1, + kEmailAddress = 1 << 2, + kUsage = 1 << 3, + kValidity = 1 << 4, + kFingerPrint = 1 << 5, + kKeyId = 1 << 6, + kOwnerTrust = 1 << 7, + kAll = ~0u +}; + +inline GpgKeyTableColumn operator|(GpgKeyTableColumn lhs, + GpgKeyTableColumn rhs) { + using T = std::underlying_type_t<GpgKeyTableColumn>; + return static_cast<GpgKeyTableColumn>(static_cast<T>(lhs) | + static_cast<T>(rhs)); +} + +inline GpgKeyTableColumn &operator|=(GpgKeyTableColumn &lhs, + GpgKeyTableColumn rhs) { + lhs = lhs | rhs; + return lhs; +} + +inline bool operator&(GpgKeyTableColumn lhs, GpgKeyTableColumn rhs) { + using T = std::underlying_type_t<GpgKeyTableColumn>; + return (static_cast<T>(lhs) & static_cast<T>(rhs)) != 0; +} + +enum class GpgKeyTableDisplayMode : unsigned int { + kNone = 0, + kPublicKey = 1 << 0, + kPrivateKey = 1 << 1, + kFavorites = 1 << 2, + kAll = ~0u +}; + +inline GpgKeyTableDisplayMode operator|(GpgKeyTableDisplayMode lhs, + GpgKeyTableDisplayMode rhs) { + using T = std::underlying_type_t<GpgKeyTableDisplayMode>; + return static_cast<GpgKeyTableDisplayMode>(static_cast<T>(lhs) | + static_cast<T>(rhs)); +} + +inline GpgKeyTableDisplayMode &operator|=(GpgKeyTableDisplayMode &lhs, + GpgKeyTableDisplayMode rhs) { + lhs = lhs | rhs; + return lhs; +} + +inline bool operator&(GpgKeyTableDisplayMode lhs, GpgKeyTableDisplayMode rhs) { + using T = std::underlying_type_t<GpgKeyTableDisplayMode>; + return (static_cast<T>(lhs) & static_cast<T>(rhs)) != 0; +} + +class GPGFRONTEND_CORE_EXPORT GpgKeyTableModel : public QAbstractTableModel { + Q_OBJECT + public: + /** + * @brief Construct a new Gpg Key Table Model object + * + * @param keys + * @param parent + */ + explicit GpgKeyTableModel(GpgKeyList keys, QObject *parent = nullptr); + + /** + * @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 Get the All Key Ids object + * + * @return auto + */ + auto GetAllKeyIds() -> GpgKeyIDList; + + /** + * @brief Get the Key ID By Row object + * + * @return QString + */ + [[nodiscard]] auto GetKeyIDByRow(int row) const -> QString; + + /** + * @brief + * + * @param row + * @return true + * @return false + */ + [[nodiscard]] auto IsPrivateKeyByRow(int row) const -> bool; + + private: + GpgKeyList buffered_keys_; + QStringList column_headers_; + QList<bool> key_check_state_; +}; + +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/model/GpgKeyTableProxyModel.cpp b/src/core/model/GpgKeyTableProxyModel.cpp new file mode 100644 index 00000000..7fdedff5 --- /dev/null +++ b/src/core/model/GpgKeyTableProxyModel.cpp @@ -0,0 +1,142 @@ +/** + * Copyright (C) 2021 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 "GpgKeyTableProxyModel.h" + +#include <utility> + +#include "core/function/gpg/GpgKeyGetter.h" +#include "core/model/CacheObject.h" +#include "core/model/GpgKey.h" + +namespace GpgFrontend { + +GpgKeyTableProxyModel::GpgKeyTableProxyModel( + QSharedPointer<GpgKeyTableModel> model, GpgKeyTableDisplayMode display_mode, + GpgKeyTableColumn columns, KeyFilter filter, QObject *parent) + : QSortFilterProxyModel(parent), + model_(std::move(model)), + display_mode_(display_mode), + filter_columns_(columns), + custom_filter_(std::move(filter)) { + setSourceModel(model_.get()); + + connect(this, &GpgKeyTableProxyModel::SignalFavoritesChanged, this, + &GpgKeyTableProxyModel::slot_update_favorites); + + emit SignalFavoritesChanged(); +} + +auto GpgKeyTableProxyModel::filterAcceptsRow( + int source_row, const QModelIndex &sourceParent) const -> bool { + auto index = sourceModel()->index(source_row, 6, sourceParent); + auto key_id = sourceModel()->data(index).toString(); + auto key = GpgKeyGetter::GetInstance().GetKey(key_id); + + if (!(display_mode_ & GpgKeyTableDisplayMode::kPrivateKey) && + key.IsPrivateKey()) { + return false; + } + + if (!(display_mode_ & GpgKeyTableDisplayMode::kPublicKey) && + !key.IsPrivateKey()) { + return false; + } + + if (!custom_filter_(key)) return false; + + if (display_mode_ & GpgKeyTableDisplayMode::kFavorites && + !favorite_fingerprints_.contains(key.GetFingerprint())) { + return false; + } + + if (filter_keywords_.isEmpty()) return true; + + QStringList infos; + for (int column = 0; column < sourceModel()->columnCount(); ++column) { + auto index = sourceModel()->index(source_row, column, sourceParent); + infos << sourceModel()->data(index).toString(); + } + + for (const QString &info : infos) { + if (info.contains(filter_keywords_, Qt::CaseInsensitive)) return true; + } + + return false; +} + +auto GpgKeyTableProxyModel::filterAcceptsColumn( + int sourceColumn, const QModelIndex &sourceParent) const -> bool { + switch (sourceColumn) { + case 0: { + return true; + } + case 1: { + return filter_columns_ & GpgKeyTableColumn::kType; + } + case 2: { + return filter_columns_ & GpgKeyTableColumn::kName; + } + case 3: { + return filter_columns_ & GpgKeyTableColumn::kEmailAddress; + } + case 4: { + return filter_columns_ & GpgKeyTableColumn::kUsage; + } + case 5: { + return filter_columns_ & GpgKeyTableColumn::kOwnerTrust; + } + case 6: { + return filter_columns_ & GpgKeyTableColumn::kKeyId; + } + case 7: { + return filter_columns_ & GpgKeyTableColumn::kFingerPrint; + } + default: + return false; + } +} + +void GpgKeyTableProxyModel::SetSearchKeywords(const QString &keywords) { + this->filter_keywords_ = keywords; + invalidateFilter(); +} + +void GpgKeyTableProxyModel::slot_update_favorites() { + // load cache + auto json_data = CacheObject("favourite_key_pair"); + if (!json_data.isArray()) return; + + auto key_fprs = json_data.array(); + for (const auto &key_fpr : key_fprs) { + if (key_fpr.isString()) favorite_fingerprints_.append(key_fpr.toString()); + } + + invalidateFilter(); +} +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/model/GpgKeyTableProxyModel.h b/src/core/model/GpgKeyTableProxyModel.h new file mode 100644 index 00000000..004fc87b --- /dev/null +++ b/src/core/model/GpgKeyTableProxyModel.h @@ -0,0 +1,82 @@ +/** + * Copyright (C) 2021 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/GpgKeyTableModel.h" + +namespace GpgFrontend { + +class GPGFRONTEND_CORE_EXPORT GpgKeyTableProxyModel + : public QSortFilterProxyModel { + Q_OBJECT + public: + using KeyFilter = std::function<bool(const GpgKey &)>; + + explicit GpgKeyTableProxyModel(QSharedPointer<GpgKeyTableModel> model, + GpgKeyTableDisplayMode display_mode, + GpgKeyTableColumn columns, KeyFilter filter, + QObject *parent); + + void SetSearchKeywords(const QString &keywords); + + protected: + [[nodiscard]] auto filterAcceptsRow(int sourceRow, + const QModelIndex &sourceParent) const + -> bool override; + + [[nodiscard]] auto filterAcceptsColumn(int sourceColumn, + const QModelIndex &sourceParent) const + -> bool override; + + signals: + + /** + * @brief + * + */ + void SignalFavoritesChanged(); + + private slots: + + /** + * @brief + * + */ + void slot_update_favorites(); + + private: + QSharedPointer<GpgKeyTableModel> model_; + GpgKeyTableDisplayMode display_mode_; + GpgKeyTableColumn filter_columns_; + QString filter_keywords_; + QList<QString> favorite_fingerprints_; + KeyFilter custom_filter_; +}; + +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/typedef/GpgTypedef.h b/src/core/typedef/GpgTypedef.h index 599c5c59..730bd4ee 100644 --- a/src/core/typedef/GpgTypedef.h +++ b/src/core/typedef/GpgTypedef.h @@ -58,6 +58,8 @@ using GpgKeyLinkList = std::list<GpgKey>; ///< using KeyLinkListPtr = std::unique_ptr<GpgKeyLinkList>; ///< using KeyPtr = std::unique_ptr<GpgKey>; ///< using KeyPtrArgsList = const std::initializer_list<KeyPtr>; ///< +using GpgKeyList = QList<GpgKey>; ///< +using GpgKeyIDList = QList<QString>; ///< using GpgSignMode = gpgme_sig_mode_t; diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp index 806ceb9e..06b784cc 100644 --- a/src/ui/UserInterfaceUtils.cpp +++ b/src/ui/UserInterfaceUtils.cpp @@ -529,34 +529,44 @@ auto CommonUtils::KeyExistsinFavouriteList(const GpgKey &key) -> bool { auto json_data = CacheObject("favourite_key_pair"); if (!json_data.isArray()) json_data.setArray(QJsonArray()); - auto key_array = json_data.array(); - return std::find(key_array.begin(), key_array.end(), key.GetFingerprint()) != - key_array.end(); + auto key_fpr_array = json_data.array(); + return std::find(key_fpr_array.begin(), key_fpr_array.end(), + key.GetFingerprint()) != key_fpr_array.end(); } void CommonUtils::AddKey2Favourtie(const GpgKey &key) { - auto json_data = CacheObject("favourite_key_pair"); - QJsonArray key_array; - if (json_data.isArray()) key_array = json_data.array(); + { + auto json_data = CacheObject("favourite_key_pair"); + QJsonArray key_array; + if (json_data.isArray()) key_array = json_data.array(); + + GF_UI_LOG_DEBUG("add key to favorites, key fpr: {}", key.GetFingerprint()); + key_array.push_back(key.GetFingerprint()); + json_data.setArray(key_array); + } - key_array.push_back(key.GetFingerprint()); - json_data.setArray(key_array); + emit SignalFavoritesChanged(); } void CommonUtils::RemoveKeyFromFavourite(const GpgKey &key) { - auto json_data = CacheObject("favourite_key_pair"); - QJsonArray key_array; - if (json_data.isArray()) key_array = json_data.array(); - - QString fingerprint = key.GetFingerprint(); - QJsonArray new_key_array; - for (auto &&item : key_array) { - if (item.isString() && item.toString() != fingerprint) { - new_key_array.append(item); + { + auto json_data = CacheObject("favourite_key_pair"); + QJsonArray key_array; + if (json_data.isArray()) key_array = json_data.array(); + + GF_UI_LOG_DEBUG("remove key from favorites, key fpr: {}", + key.GetFingerprint()); + auto fingerprint = key.GetFingerprint(); + QJsonArray new_key_array; + for (auto &&item : key_array) { + if (item.isString() && item.toString() != fingerprint) { + new_key_array.append(item); + } } + json_data.setArray(new_key_array); } - json_data.setArray(new_key_array); + emit SignalFavoritesChanged(); } /** diff --git a/src/ui/UserInterfaceUtils.h b/src/ui/UserInterfaceUtils.h index 304ba37b..ceb9fb5f 100644 --- a/src/ui/UserInterfaceUtils.h +++ b/src/ui/UserInterfaceUtils.h @@ -63,8 +63,8 @@ void show_verify_details(QWidget* parent, InfoBoardWidget* info_board, * @param parent * @param verify_res */ -void ImportUnknownKeyFromKeyserver( - QWidget* parent, const GpgVerifyResultAnalyse& verify_res); +void ImportUnknownKeyFromKeyserver(QWidget* parent, + const GpgVerifyResultAnalyse& verify_res); /** * @brief @@ -135,7 +135,7 @@ class CommonUtils : public QWidget { * * @return CommonUtils* */ - static CommonUtils* GetInstance(); + static auto GetInstance() -> CommonUtils*; /** * @brief @@ -214,7 +214,14 @@ class CommonUtils : public QWidget { */ void SignalRestartApplication(int); + /** + * @brief + * + */ + void SignalFavoritesChanged(); + public slots: + /** * @brief * diff --git a/src/ui/dialog/SignersPicker.cpp b/src/ui/dialog/SignersPicker.cpp index 9c342cc7..5ab33425 100644 --- a/src/ui/dialog/SignersPicker.cpp +++ b/src/ui/dialog/SignersPicker.cpp @@ -46,9 +46,10 @@ SignersPicker::SignersPicker(QWidget* parent) /*Setup KeyList*/ key_list_ = new KeyList(0U, this); key_list_->AddListGroupTab( - tr("Signers"), "signers", KeyListRow::ONLY_SECRET_KEY, - KeyListColumn::NAME | KeyListColumn::EmailAddress | KeyListColumn::Usage, - [](const GpgKey& key, const KeyTable&) -> bool { + tr("Signers"), "signers", GpgKeyTableDisplayMode::kPrivateKey, + GpgKeyTableColumn::kName | GpgKeyTableColumn::kEmailAddress | + GpgKeyTableColumn::kUsage, + [](const GpgKey& key) -> bool { return key.IsHasActualSigningCapability(); }); key_list_->SlotRefresh(); diff --git a/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp b/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp index a56a7fc7..f8d3d44b 100644 --- a/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp +++ b/src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp @@ -43,9 +43,9 @@ KeyUIDSignDialog::KeyUIDSignDialog(const GpgKey& key, UIDArgsListPtr uid, const auto key_id = m_key_.GetId(); m_key_list_ = new KeyList(KeyMenuAbility::NONE, this); m_key_list_->AddListGroupTab( - tr("Signers"), "signers", KeyListRow::ONLY_SECRET_KEY, - KeyListColumn::NAME | KeyListColumn::EmailAddress, - [key_id](const GpgKey& key, const KeyTable&) -> bool { + tr("Signers"), "signers", GpgKeyTableDisplayMode::kPrivateKey, + GpgKeyTableColumn::kName | GpgKeyTableColumn::kEmailAddress, + [key_id](const GpgKey& key) -> bool { return !(key.IsDisabled() || !key.IsHasCertificationCapability() || !key.IsHasMasterKey() || key.IsExpired() || key.IsRevoked() || key_id == key.GetId()); diff --git a/src/ui/main_window/KeyMgmt.cpp b/src/ui/main_window/KeyMgmt.cpp index afc6129c..85671ab2 100644 --- a/src/ui/main_window/KeyMgmt.cpp +++ b/src/ui/main_window/KeyMgmt.cpp @@ -54,53 +54,58 @@ KeyMgmt::KeyMgmt(QWidget* parent) /* the list of Keys available*/ key_list_ = new KeyList(KeyMenuAbility::ALL, this); - key_list_->AddListGroupTab(tr("All"), "all", - KeyListRow::SECRET_OR_PUBLIC_KEY); + key_list_->AddListGroupTab( + tr("All"), "all", + GpgKeyTableDisplayMode::kPublicKey | GpgKeyTableDisplayMode::kPrivateKey); key_list_->AddListGroupTab( tr("Only Public Key"), "only_public_key", - KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + GpgKeyTableDisplayMode::kPublicKey, + GpgKeyTableColumn::kType | GpgKeyTableColumn::kName | + GpgKeyTableColumn::kEmailAddress | GpgKeyTableColumn::kUsage | + GpgKeyTableColumn::kValidity, + [](const GpgKey& key) -> bool { return !key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); key_list_->AddListGroupTab( tr("Has Private Key"), "has_private_key", - KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + GpgKeyTableDisplayMode::kPrivateKey, + GpgKeyTableColumn::kType | GpgKeyTableColumn::kName | + GpgKeyTableColumn::kEmailAddress | GpgKeyTableColumn::kUsage | + GpgKeyTableColumn::kValidity, + [](const GpgKey& key) -> bool { return key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); key_list_->AddListGroupTab( - tr("No Primary Key"), "no_primary_key", KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + tr("No Primary Key"), "no_primary_key", + GpgKeyTableDisplayMode::kPublicKey | GpgKeyTableDisplayMode::kPrivateKey, + GpgKeyTableColumn::kType | GpgKeyTableColumn::kName | + GpgKeyTableColumn::kEmailAddress | GpgKeyTableColumn::kUsage | + GpgKeyTableColumn::kValidity, + [](const GpgKey& key) -> bool { return !key.IsHasMasterKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); key_list_->AddListGroupTab( - tr("Revoked"), "revoked", KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { - return key.IsRevoked(); - }); + tr("Revoked"), "revoked", + GpgKeyTableDisplayMode::kPublicKey | GpgKeyTableDisplayMode::kPrivateKey, + GpgKeyTableColumn::kType | GpgKeyTableColumn::kName | + GpgKeyTableColumn::kEmailAddress | GpgKeyTableColumn::kUsage | + GpgKeyTableColumn::kValidity, + [](const GpgKey& key) -> bool { return key.IsRevoked(); }); key_list_->AddListGroupTab( - tr("Expired"), "expired", KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { - return key.IsExpired(); - }); + tr("Expired"), "expired", + GpgKeyTableDisplayMode::kPublicKey | GpgKeyTableDisplayMode::kPrivateKey, + GpgKeyTableColumn::kType | GpgKeyTableColumn::kName | + GpgKeyTableColumn::kEmailAddress | GpgKeyTableColumn::kUsage | + GpgKeyTableColumn::kValidity, + [](const GpgKey& key) -> bool { return key.IsExpired(); }); setCentralWidget(key_list_); key_list_->SetDoubleClickedAction( diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp index 7d50b85a..e0df6710 100644 --- a/src/ui/main_window/MainWindowSlotFunction.cpp +++ b/src/ui/main_window/MainWindowSlotFunction.cpp @@ -202,10 +202,12 @@ void MainWindow::slot_show_key_details() { void MainWindow::slot_add_key_2_favourite() { auto key_ids = m_key_list_->GetSelected(); if (key_ids->empty()) return; + GF_UI_LOG_DEBUG("get selected key id: {}", key_ids->front()); auto key = GpgKeyGetter::GetInstance().GetKey(key_ids->front()); - CommonUtils::GetInstance()->AddKey2Favourtie(key); + if (!key.IsGood()) return; + CommonUtils::GetInstance()->AddKey2Favourtie(key); emit SignalUIRefresh(); } diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp index 8b611152..f96cf595 100644 --- a/src/ui/main_window/MainWindowUI.cpp +++ b/src/ui/main_window/MainWindowUI.cpp @@ -707,37 +707,44 @@ void MainWindow::create_dock_windows() { addDockWidget(Qt::RightDockWidgetArea, key_list_dock_); m_key_list_->AddListGroupTab( - tr("Default"), "default", KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + tr("Default"), "default", + GpgKeyTableDisplayMode::kPublicKey | GpgKeyTableDisplayMode::kPrivateKey, + GpgKeyTableColumn::kType | GpgKeyTableColumn::kName | + GpgKeyTableColumn::kEmailAddress | GpgKeyTableColumn::kUsage | + GpgKeyTableColumn::kValidity, + [](const GpgKey& key) -> bool { return !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); m_key_list_->AddListGroupTab( - tr("Favourite"), "favourite", KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + tr("Favourite"), "favourite", + GpgKeyTableDisplayMode::kPublicKey | GpgKeyTableDisplayMode::kPrivateKey | + GpgKeyTableDisplayMode::kFavorites, + GpgKeyTableColumn::kType | GpgKeyTableColumn::kName | + GpgKeyTableColumn::kEmailAddress | GpgKeyTableColumn::kUsage | + GpgKeyTableColumn::kValidity, + [](const GpgKey& key) -> bool { return CommonUtils::GetInstance()->KeyExistsinFavouriteList(key); }); m_key_list_->AddListGroupTab( tr("Only Public Key"), "only_public_key", - KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + GpgKeyTableDisplayMode::kPublicKey, + GpgKeyTableColumn::kType | GpgKeyTableColumn::kName | + GpgKeyTableColumn::kEmailAddress | GpgKeyTableColumn::kUsage | + GpgKeyTableColumn::kValidity, + [](const GpgKey& key) -> bool { return !key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); m_key_list_->AddListGroupTab( tr("Has Private Key"), "has_private_key", - KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::TYPE | KeyListColumn::NAME | KeyListColumn::EmailAddress | - KeyListColumn::Usage | KeyListColumn::Validity, - [](const GpgKey& key, const KeyTable&) -> bool { + GpgKeyTableDisplayMode::kPrivateKey, + GpgKeyTableColumn::kType | GpgKeyTableColumn::kName | + GpgKeyTableColumn::kEmailAddress | GpgKeyTableColumn::kUsage | + GpgKeyTableColumn::kValidity, + [](const GpgKey& key) -> bool { return key.IsPrivateKey() && !(key.IsRevoked() || key.IsDisabled() || key.IsExpired()); }); diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp index be79a6fd..4229a35f 100644 --- a/src/ui/widgets/KeyList.cpp +++ b/src/ui/widgets/KeyList.cpp @@ -30,6 +30,7 @@ #include <cstddef> #include <mutex> +#include <utility> #include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgKeyGetter.h" @@ -43,7 +44,8 @@ namespace GpgFrontend::UI { KeyList::KeyList(KeyMenuAbility::AbilityType menu_ability, QWidget* parent) : QWidget(parent), ui_(GpgFrontend::SecureCreateSharedObject<Ui_KeyList>()), - menu_ability_(menu_ability) { + menu_ability_(menu_ability), + model_(GpgKeyGetter::GetInstance().GetGpgKeyTableModel()) { init(); } @@ -60,7 +62,7 @@ void KeyList::init() { ui_->keyGroupTab->clear(); popup_menu_ = new QMenu(this); - bool forbid_all_gnupg_connection = + auto forbid_all_gnupg_connection = GlobalSettingStation::GetInstance() .GetSettings() .value("network/forbid_all_gnupg_connection", false) @@ -112,120 +114,66 @@ void KeyList::init() { } void KeyList::AddListGroupTab(const QString& name, const QString& id, - KeyListRow::KeyType selectType, - KeyListColumn::InfoType infoType, - const KeyTable::KeyTableFilter filter) { - GF_UI_LOG_DEBUG("add list group tab: {}", name); - - auto* key_list = new QTableWidget(this); - if (m_key_list_ == nullptr) { - m_key_list_ = key_list; - } - key_list->setObjectName(id); - ui_->keyGroupTab->addTab(key_list, name); - m_key_tables_.emplace_back(key_list, selectType, infoType, filter); - m_key_tables_.back().SetMenuAbility(menu_ability_); - - key_list->setColumnCount(8); - key_list->horizontalHeader()->setSectionResizeMode( - QHeaderView::ResizeToContents); - key_list->verticalHeader()->hide(); - key_list->setShowGrid(false); - key_list->sortByColumn(2, Qt::AscendingOrder); - key_list->setSelectionBehavior(QAbstractItemView::SelectRows); - key_list->setSelectionMode(QAbstractItemView::SingleSelection); - - // table items not editable - key_list->setEditTriggers(QAbstractItemView::NoEditTriggers); - // no focus (rectangle around table items) - // maybe it should focus on whole row - key_list->setFocusPolicy(Qt::NoFocus); - - key_list->setAlternatingRowColors(true); + GpgKeyTableDisplayMode select_type, + GpgKeyTableColumn info_type, + GpgKeyTableProxyModel::KeyFilter filter) { + auto* key_table = + new KeyTable(this, model_, select_type, info_type, std::move(filter)); - // Hidden Column For Purpose - if ((infoType & KeyListColumn::TYPE) == 0U) { - key_list->setColumnHidden(1, true); - } - if ((infoType & KeyListColumn::NAME) == 0U) { - key_list->setColumnHidden(2, true); - } - if ((infoType & KeyListColumn::EmailAddress) == 0U) { - key_list->setColumnHidden(3, true); - } - if ((infoType & KeyListColumn::Usage) == 0U) { - key_list->setColumnHidden(4, true); - } - if ((infoType & KeyListColumn::Validity) == 0U) { - key_list->setColumnHidden(5, true); - } - if ((infoType & KeyListColumn::KeyID) == 0U) { - key_list->setColumnHidden(6, true); - } - if ((infoType & KeyListColumn::FingerPrint) == 0U) { - key_list->setColumnHidden(7, true); - } - - QStringList labels; - labels << tr("Select") << tr("Type") << tr("Name") << tr("Email Address") - << tr("Usage") << tr("Trust") << tr("Key ID") << tr("Finger Print"); - - key_list->setHorizontalHeaderLabels(labels); - key_list->horizontalHeader()->setStretchLastSection(false); - - connect(key_list, &QTableWidget::doubleClicked, this, - &KeyList::slot_double_clicked); + key_table->setObjectName(id); + ui_->keyGroupTab->addTab(key_table, name); } void KeyList::SlotRefresh() { - GF_UI_LOG_DEBUG("refresh, address: {}", static_cast<void*>(this)); - ui_->refreshKeyListButton->setDisabled(true); ui_->syncButton->setDisabled(true); + model_ = GpgKeyGetter::GetInstance().GetGpgKeyTableModel(); + + for (int i = 0; i < ui_->keyGroupTab->count(); i++) { + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->widget(i)); + key_table->RefreshModel(model_); + } + emit SignalRefreshStatusBar(tr("Refreshing Key List..."), 3000); - this->buffered_keys_list_ = GpgKeyGetter::GetInstance().FetchKey(); - this->slot_refresh_ui(); + this->model_ = GpgKeyGetter::GetInstance().GetGpgKeyTableModel(); + + this->SlotRefreshUI(); } void KeyList::SlotRefreshUI() { - GF_UI_LOG_DEBUG("refresh, address: {}", static_cast<void*>(this)); - this->slot_refresh_ui(); + emit SignalRefreshStatusBar(tr("Key List Refreshed."), 1000); + ui_->refreshKeyListButton->setDisabled(false); + ui_->syncButton->setDisabled(false); } auto KeyList::GetChecked(const KeyTable& key_table) -> KeyIdArgsListPtr { auto ret = std::make_unique<KeyIdArgsList>(); - for (int i = 0; i < key_table.key_list_->rowCount(); i++) { - if (key_table.key_list_->item(i, 0)->checkState() == Qt::Checked) { - ret->push_back(key_table.buffered_keys_[i].GetId()); + for (int i = 0; i < key_table.GetRowCount(); i++) { + if (key_table.IsRowChecked(i)) { + ret->push_back(key_table.GetKeyIdByRow(i)); } } return ret; } auto KeyList::GetChecked() -> KeyIdArgsListPtr { - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); auto ret = std::make_unique<KeyIdArgsList>(); - for (int i = 0; i < key_list->rowCount(); i++) { - if (key_list->item(i, 0)->checkState() == Qt::Checked) { - ret->push_back(buffered_keys[i].GetId()); + for (int i = 0; i < key_table->GetRowCount(); i++) { + if (key_table->IsRowChecked(i)) { + ret->push_back(key_table->GetKeyIdByRow(i)); } } return ret; } auto KeyList::GetAllPrivateKeys() -> KeyIdArgsListPtr { - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); auto ret = std::make_unique<KeyIdArgsList>(); - for (int i = 0; i < key_list->rowCount(); i++) { - if ((key_list->item(i, 1) != nullptr) && buffered_keys[i].IsPrivateKey()) { - ret->push_back(buffered_keys[i].GetId()); + for (int i = 0; i < key_table->GetRowCount(); i++) { + if (key_table->IsPrivateKeyByRow(i)) { + ret->push_back(key_table->GetKeyIdByRow(i)); } } return ret; @@ -235,16 +183,11 @@ auto KeyList::GetCheckedPrivateKey() -> KeyIdArgsListPtr { auto ret = std::make_unique<KeyIdArgsList>(); if (ui_->keyGroupTab->size().isEmpty()) return ret; - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; - - for (int i = 0; i < key_list->rowCount(); i++) { - if ((key_list->item(i, 0)->checkState() == Qt::Checked) && - ((key_list->item(i, 1)) != nullptr) && - buffered_keys[i].IsPrivateKey()) { - ret->push_back(buffered_keys[i].GetId()); + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + + for (int i = 0; i < key_table->GetRowCount(); i++) { + if (key_table->IsRowChecked(i) && key_table->IsPrivateKeyByRow(i)) { + ret->push_back(key_table->GetKeyIdByRow(i)); } } return ret; @@ -254,16 +197,11 @@ auto KeyList::GetCheckedPublicKey() -> KeyIdArgsListPtr { auto ret = std::make_unique<KeyIdArgsList>(); if (ui_->keyGroupTab->size().isEmpty()) return ret; - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; - - for (int i = 0; i < key_list->rowCount(); i++) { - if ((key_list->item(i, 0)->checkState() == Qt::Checked) && - ((key_list->item(i, 1)) != nullptr) && - !buffered_keys[i].IsPrivateKey()) { - ret->push_back(buffered_keys[i].GetId()); + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + + for (int i = 0; i < key_table->GetRowCount(); i++) { + if (key_table->IsRowChecked(i) && key_table->IsPublicKeyByRow(i)) { + ret->push_back(key_table->GetKeyIdByRow(i)); } } return ret; @@ -272,52 +210,43 @@ auto KeyList::GetCheckedPublicKey() -> KeyIdArgsListPtr { void KeyList::SetChecked(const KeyIdArgsListPtr& keyIds, const KeyTable& key_table) { if (!keyIds->empty()) { - for (int i = 0; i < key_table.key_list_->rowCount(); i++) { + for (int i = 0; i < key_table.GetRowCount(); i++) { if (std::find(keyIds->begin(), keyIds->end(), - key_table.buffered_keys_[i].GetId()) != keyIds->end()) { - key_table.key_list_->item(i, 0)->setCheckState(Qt::Checked); - } - } - } -} - -void KeyList::SetChecked(KeyIdArgsListPtr key_ids) { - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - if (key_list == nullptr) return; - if (!m_key_tables_.empty()) { - for (auto& key_table : m_key_tables_) { - if (key_table.key_list_ == key_list) { - key_table.SetChecked(std::move(key_ids)); - break; + key_table.GetKeyIdByRow(i)) != keyIds->end()) { + key_table.SetRowChecked(i); } } } } -KeyIdArgsListPtr KeyList::GetSelected() { +auto KeyList::GetSelected() -> KeyIdArgsListPtr { auto ret = std::make_unique<KeyIdArgsList>(); if (ui_->keyGroupTab->size().isEmpty()) return ret; - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + if (key_table == nullptr) { + GF_UI_LOG_ERROR("fail to get current key table, nullptr"); + return ret; + } - for (int i = 0; i < key_list->rowCount(); i++) { - if (key_list->item(i, 0)->isSelected()) { - ret->push_back(buffered_keys[i].GetId()); - } + QItemSelectionModel* select = key_table->selectionModel(); + for (auto index : select->selectedRows()) { + ret->push_back(key_table->GetKeyIdByRow(index.row())); + } + + if (ret->empty()) { + GF_UI_LOG_WARN("nothing is selected at key list"); } return ret; } [[maybe_unused]] auto KeyList::ContainsPrivateKeys() -> bool { if (ui_->keyGroupTab->size().isEmpty()) return false; - m_key_list_ = qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); + auto* key_table = + qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - for (int i = 0; i < m_key_list_->rowCount(); i++) { - if (m_key_list_->item(i, 1) != nullptr) { + for (int i = 0; i < key_table->rowCount(); i++) { + if (key_table->item(i, 1) != nullptr) { return true; } } @@ -326,21 +255,26 @@ KeyIdArgsListPtr KeyList::GetSelected() { void KeyList::SetColumnWidth(int row, int size) { if (ui_->keyGroupTab->size().isEmpty()) return; - m_key_list_ = qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - - m_key_list_->setColumnWidth(row, size); + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + key_table->setColumnWidth(row, size); } void KeyList::contextMenuEvent(QContextMenuEvent* event) { - if (ui_->keyGroupTab->size().isEmpty()) return; - m_key_list_ = qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); + if (ui_->keyGroupTab->count() == 0) return; + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + + if (key_table == nullptr) { + GF_UI_LOG_DEBUG("m_key_list_ is nullptr, key group tab number: {}", + ui_->keyGroupTab->count()); + return; + } QString current_tab_widget_obj_name = ui_->keyGroupTab->widget(ui_->keyGroupTab->currentIndex())->objectName(); GF_UI_LOG_DEBUG("current tab widget object name: {}", current_tab_widget_obj_name); if (current_tab_widget_obj_name == "favourite") { - QList<QAction*> actions = popup_menu_->actions(); + auto actions = popup_menu_->actions(); for (QAction* action : actions) { if (action->data().toString() == "remove_key_from_favourtie_action") { action->setVisible(true); @@ -349,7 +283,7 @@ void KeyList::contextMenuEvent(QContextMenuEvent* event) { } } } else { - QList<QAction*> actions = popup_menu_->actions(); + auto actions = popup_menu_->actions(); for (QAction* action : actions) { if (action->data().toString() == "remove_key_from_favourtie_action") { action->setVisible(false); @@ -359,7 +293,7 @@ void KeyList::contextMenuEvent(QContextMenuEvent* event) { } } - if (m_key_list_->selectedItems().length() > 0) { + if (key_table->GetRowSelected() >= 0) { popup_menu_->exec(event->globalPos()); } } @@ -379,7 +313,7 @@ void KeyList::dropEvent(QDropEvent* event) { // "always import keys"-CheckBox auto* check_box = new QCheckBox(tr("Always import without bothering.")); - bool confirm_import_keys = GlobalSettingStation::GetInstance() + auto confirm_import_keys = GlobalSettingStation::GetInstance() .GetSettings() .value("basic/confirm_import_keys", true) .toBool(); @@ -435,11 +369,11 @@ void KeyList::import_keys(const QByteArray& in_buffer) { void KeyList::slot_double_clicked(const QModelIndex& index) { if (ui_->keyGroupTab->size().isEmpty()) return; - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; + + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); if (m_action_ != nullptr) { - const auto key = - GpgKeyGetter::GetInstance().GetKey(buffered_keys[index.row()].GetId()); + const auto key = GpgKeyGetter::GetInstance().GetKey( + key_table->GetKeyIdByRow(index.row())); m_action_(key, this); } } @@ -451,30 +385,15 @@ void KeyList::SetDoubleClickedAction( auto KeyList::GetSelectedKey() -> QString { if (ui_->keyGroupTab->size().isEmpty()) return {}; - const auto& buffered_keys = - m_key_tables_[ui_->keyGroupTab->currentIndex()].buffered_keys_; - for (int i = 0; i < m_key_list_->rowCount(); i++) { - if (m_key_list_->item(i, 0)->isSelected()) { - return buffered_keys[i].GetId(); - } - } - return {}; -} + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); -void KeyList::slot_refresh_ui() { - GF_UI_LOG_DEBUG("refresh: {}", static_cast<void*>(buffered_keys_list_.get())); - if (buffered_keys_list_ != nullptr) { - std::lock_guard<std::mutex> guard(buffered_key_list_mutex_); + QItemSelectionModel* select = key_table->selectionModel(); - for (auto& key_table : m_key_tables_) { - key_table.Refresh( - GpgKeyGetter::GetInstance().GetKeysCopy(buffered_keys_list_)); - } - } - emit SignalRefreshStatusBar(tr("Key List Refreshed."), 1000); - ui_->refreshKeyListButton->setDisabled(false); - ui_->syncButton->setDisabled(false); + auto selected_rows = select->selectedRows(); + if (selected_rows.empty()) return {}; + + return key_table->GetKeyIdByRow(selected_rows.first().row()); } void KeyList::slot_sync_with_key_server() { @@ -490,14 +409,12 @@ void KeyList::slot_sync_with_key_server() { QMessageBox::Yes | QMessageBox::No); if (reply == QMessageBox::No) return; - { - std::lock_guard<std::mutex> guard(buffered_key_list_mutex_); - for (const auto& key : *buffered_keys_list_) { - if (!(key.IsPrivateKey() && key.IsHasMasterKey())) { - key_ids.push_back(key.GetId()); - } - } + + auto all_key_ids = model_->GetAllKeyIds(); + for (auto& key_id : all_key_ids) { + key_ids.push_back(key_id); } + } else { key_ids = *checked_public_keys; } @@ -536,225 +453,128 @@ void KeyList::filter_by_keyword() { keyword = keyword.trimmed(); GF_UI_LOG_DEBUG("get new keyword of search bar: {}", keyword); - for (auto& table : m_key_tables_) { + + for (int i = 0; i < ui_->keyGroupTab->count(); i++) { + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->widget(i)); // refresh arguments - table.SetFilterKeyword(keyword.toLower()); - table.SetMenuAbility(menu_ability_); + key_table->SetFilterKeyword(keyword.toLower()); + key_table->SetMenuAbility(menu_ability_); } + // refresh ui SlotRefreshUI(); } void KeyList::uncheck_all() { - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - if (key_list == nullptr) return; - if (!m_key_tables_.empty()) { - for (auto& key_table : m_key_tables_) { - if (key_table.key_list_ == key_list) { - key_table.UncheckALL(); - break; - } - } - } + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + if (key_table == nullptr) return; + key_table->UncheckAll(); } void KeyList::check_all() { - auto* key_list = - qobject_cast<QTableWidget*>(ui_->keyGroupTab->currentWidget()); - if (key_list == nullptr) return; - if (!m_key_tables_.empty()) { - for (auto& key_table : m_key_tables_) { - if (key_table.key_list_ == key_list) { - key_table.CheckALL(); - break; - } - } - } + auto* key_table = qobject_cast<KeyTable*>(ui_->keyGroupTab->currentWidget()); + if (key_table == nullptr) return; + key_table->CheckAll(); } -KeyIdArgsListPtr& KeyTable::GetChecked() { - if (checked_key_ids_ == nullptr) { - checked_key_ids_ = std::make_unique<KeyIdArgsList>(); - } - auto& ret = checked_key_ids_; - for (size_t i = 0; i < buffered_keys_.size(); i++) { - auto key_id = buffered_keys_[i].GetId(); - if (key_list_->item(i, 0)->checkState() == Qt::Checked && - std::find(ret->begin(), ret->end(), key_id) == ret->end()) { - ret->push_back(key_id); - } +auto KeyTable::GetChecked() -> KeyIdArgsListPtr { + auto ret = std::make_unique<KeyIdArgsList>(); + for (size_t i = 0; i < GetRowCount(); i++) { + if (IsRowChecked(i)) ret->push_back(GetKeyIdByRow(i)); } return ret; } -void KeyTable::SetChecked(KeyIdArgsListPtr key_ids) { - checked_key_ids_ = std::move(key_ids); -} - -void KeyTable::Refresh(KeyLinkListPtr m_keys) { - auto& checked_key_list = GetChecked(); - // while filling the table, sort enabled causes errors - - key_list_->setSortingEnabled(false); - key_list_->clearContents(); - - // Optimization for copy - KeyLinkListPtr keys = nullptr; - if (m_keys == nullptr) { - keys = GpgKeyGetter::GetInstance().FetchKey(); - } else { - keys = std::move(m_keys); - } - - auto it = keys->begin(); - int row_count = 0; - - while (it != keys->end()) { - // filter by search bar's keyword - if (ability_ & KeyMenuAbility::SEARCH_BAR && !keyword_.isEmpty()) { - QStringList infos; - infos << it->GetName().toLower() << it->GetEmail().toLower() - << it->GetComment().toLower() << it->GetFingerprint().toLower(); - - auto subkeys = it->GetSubKeys(); - for (const auto& subkey : *subkeys) { - infos << subkey.GetFingerprint().toLower() << subkey.GetID().toLower(); - } - - if (infos.filter(keyword_.toLower()).isEmpty()) { - it = keys->erase(it); - continue; - } - } - - if (filter_ != nullptr) { - if (!filter_(*it, *this)) { - it = keys->erase(it); - continue; - } - } - - if (select_type_ == KeyListRow::ONLY_SECRET_KEY && !it->IsPrivateKey()) { - it = keys->erase(it); - continue; - } - row_count++; - it++; - } +KeyTable::KeyTable(QWidget* parent, QSharedPointer<GpgKeyTableModel> model, + GpgKeyTableDisplayMode select_type, + GpgKeyTableColumn info_type, + GpgKeyTableProxyModel::KeyFilter filter) + : QTableView(parent), + model_(std::move(model)), + proxy_model_(model_, select_type, info_type, std::move(filter), this) { + setModel(&proxy_model_); - key_list_->setRowCount(row_count); + verticalHeader()->hide(); + horizontalHeader()->setStretchLastSection(false); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - int row_index = 0; - it = keys->begin(); + setShowGrid(false); + sortByColumn(2, Qt::AscendingOrder); + setSelectionBehavior(QAbstractItemView::SelectRows); + setSelectionMode(QAbstractItemView::SingleSelection); - buffered_keys_.clear(); - - while (it != keys->end()) { - auto* tmp0 = new QTableWidgetItem(QString::number(row_index)); - tmp0->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | - Qt::ItemIsSelectable); - tmp0->setTextAlignment(Qt::AlignCenter); - tmp0->setCheckState(Qt::Unchecked); - key_list_->setItem(row_index, 0, tmp0); - - QString type_str; - QTextStream type_steam(&type_str); - if (it->IsPrivateKey()) { - type_steam << "pub/sec"; - } else { - type_steam << "pub"; - } - - if (it->IsPrivateKey() && !it->IsHasMasterKey()) { - type_steam << "#"; - } - - if (it->IsHasCardKey()) { - type_steam << "^"; - } - - auto* tmp1 = new QTableWidgetItem(type_str); - key_list_->setItem(row_index, 1, tmp1); - - auto* tmp2 = new QTableWidgetItem(it->GetName()); - key_list_->setItem(row_index, 2, tmp2); - auto* tmp3 = new QTableWidgetItem(it->GetEmail()); - key_list_->setItem(row_index, 3, tmp3); - - QString usage; - QTextStream usage_steam(&usage); + // table items not editable + setEditTriggers(QAbstractItemView::NoEditTriggers); - if (it->IsHasActualCertificationCapability()) usage_steam << "C"; - if (it->IsHasActualEncryptionCapability()) usage_steam << "E"; - if (it->IsHasActualSigningCapability()) usage_steam << "S"; - if (it->IsHasActualAuthenticationCapability()) usage_steam << "A"; + setFocusPolicy(Qt::NoFocus); + setAlternatingRowColors(true); - auto* temp_usage = new QTableWidgetItem(usage); - temp_usage->setTextAlignment(Qt::AlignCenter); - key_list_->setItem(row_index, 4, temp_usage); + connect(CommonUtils::GetInstance(), &CommonUtils::SignalFavoritesChanged, + &proxy_model_, &GpgKeyTableProxyModel::SignalFavoritesChanged); +} - auto* temp_validity = new QTableWidgetItem(it->GetOwnerTrust()); - temp_validity->setTextAlignment(Qt::AlignCenter); - key_list_->setItem(row_index, 5, temp_validity); +void KeyTable::SetMenuAbility(KeyMenuAbility::AbilityType ability) { + this->ability_ = ability; +} - auto* temp_id = new QTableWidgetItem(it->GetId()); - temp_id->setTextAlignment(Qt::AlignCenter); - key_list_->setItem(row_index, 6, temp_id); +void KeyTable::SetFilterKeyword(const QString& keyword) { + proxy_model_.SetSearchKeywords(keyword); +} - auto* temp_fpr = new QTableWidgetItem(it->GetFingerprint()); - temp_fpr->setTextAlignment(Qt::AlignCenter); - key_list_->setItem(row_index, 7, temp_fpr); +void KeyTable::RefreshModel(QSharedPointer<GpgKeyTableModel> model) { + model_ = std::move(model); + proxy_model_.setSourceModel(model_.get()); +} - QFont font = tmp2->font(); +auto KeyTable::IsRowChecked(int row) const -> bool { + auto index = model()->index(row, 0); + return index.data(Qt::CheckStateRole).toInt() == Qt::Checked; +} - // strike out expired keys - if (it->IsExpired() || it->IsRevoked()) font.setStrikeOut(true); - if (it->IsPrivateKey()) font.setBold(true); +auto KeyTable::GetRowCount() const -> int { return model()->rowCount(); } - tmp0->setFont(font); - temp_usage->setFont(font); - temp_fpr->setFont(font); - temp_validity->setFont(font); - tmp1->setFont(font); - tmp2->setFont(font); - tmp3->setFont(font); - temp_id->setFont(font); +auto KeyTable::GetKeyIdByRow(int row) const -> QString { + if (row < 0 || row >= model()->rowCount()) return {}; + auto origin_row = model()->index(row, 0).data().toInt(); + return model_->GetKeyIDByRow(origin_row); +} - // move to buffered keys - buffered_keys_.emplace_back(std::move(*it)); +auto KeyTable::IsPrivateKeyByRow(int row) const -> bool { + if (row < 0 || row >= model()->rowCount()) return false; + auto origin_row = model()->index(row, 0).data().toInt(); + return model_->IsPrivateKeyByRow(origin_row); +} - it++; - ++row_index; - } +auto KeyTable::IsPublicKeyByRow(int row) const -> bool { + if (row < 0 || row >= model()->rowCount()) return false; + auto origin_row = model()->index(row, 0).data().toInt(); + return !model_->IsPrivateKeyByRow(origin_row); +} - if (!checked_key_list->empty()) { - for (int i = 0; i < key_list_->rowCount(); i++) { - if (std::find(checked_key_list->begin(), checked_key_list->end(), - buffered_keys_[i].GetId()) != checked_key_list->end()) { - key_list_->item(i, 0)->setCheckState(Qt::Checked); - } - } - } +void KeyTable::SetRowChecked(int row) const { + if (row < 0 || row >= model()->rowCount()) return; + model()->setData(model()->index(row, 0), Qt::Checked, Qt::CheckStateRole); } -void KeyTable::UncheckALL() const { - for (int i = 0; i < key_list_->rowCount(); i++) { - key_list_->item(i, 0)->setCheckState(Qt::Unchecked); +void KeyTable::CheckAll() { + for (int row = 0; row < model()->rowCount(); ++row) { + auto index = model()->index(row, 0); + model()->setData(index, Qt::Checked, Qt::CheckStateRole); } } -void KeyTable::CheckALL() const { - for (int i = 0; i < key_list_->rowCount(); i++) { - key_list_->item(i, 0)->setCheckState(Qt::Checked); +void KeyTable::UncheckAll() { + for (int row = 0; row < model()->rowCount(); ++row) { + auto index = model()->index(row, 0); + model()->setData(index, Qt::Unchecked, Qt::CheckStateRole); } } -void KeyTable::SetMenuAbility(KeyMenuAbility::AbilityType ability) { - this->ability_ = ability; -} +[[nodiscard]] auto KeyTable::GetRowSelected() const -> int { + auto selected_indexes = selectedIndexes(); + if (selected_indexes.empty()) return -1; -void KeyTable::SetFilterKeyword(QString keyword) { - this->keyword_ = std::move(keyword); + return selected_indexes.first().row(); } + } // namespace GpgFrontend::UI diff --git a/src/ui/widgets/KeyList.h b/src/ui/widgets/KeyList.h index 1761fb23..70320519 100644 --- a/src/ui/widgets/KeyList.h +++ b/src/ui/widgets/KeyList.h @@ -29,6 +29,8 @@ #pragma once #include "core/model/GpgKey.h" +#include "core/model/GpgKeyTableModel.h" +#include "core/model/GpgKeyTableProxyModel.h" class Ui_KeyList; @@ -38,34 +40,6 @@ namespace GpgFrontend::UI { * @brief * */ -struct KeyListRow { - using KeyType = unsigned int; - - static const KeyType SECRET_OR_PUBLIC_KEY = 0; ///< - static const KeyType ONLY_SECRET_KEY = 1; ///< -}; - -/** - * @brief - * - */ -struct KeyListColumn { - using InfoType = unsigned int; - - static constexpr InfoType ALL = ~0; ///< - static constexpr InfoType TYPE = 1 << 0; ///< - static constexpr InfoType NAME = 1 << 1; ///< - static constexpr InfoType EmailAddress = 1 << 2; ///< - static constexpr InfoType Usage = 1 << 3; ///< - static constexpr InfoType Validity = 1 << 4; ///< - static constexpr InfoType FingerPrint = 1 << 5; ///< - static constexpr InfoType KeyID = 1 << 6; ///< -}; - -/** - * @brief - * - */ struct KeyMenuAbility { using AbilityType = unsigned int; @@ -82,18 +56,11 @@ struct KeyMenuAbility { * @brief * */ -struct KeyTable { +struct KeyTable : public QTableView { + Q_OBJECT + public: using KeyTableFilter = std::function<bool(const GpgKey&, const KeyTable&)>; - QTableWidget* key_list_; ///< - KeyListRow::KeyType select_type_; ///< - KeyListColumn::InfoType info_type_; ///< - std::vector<GpgKey> buffered_keys_; ///< - KeyTableFilter filter_; ///< - KeyIdArgsListPtr checked_key_ids_; ///< - KeyMenuAbility::AbilityType ability_; ///< - QString keyword_; ///< - /** * @brief Construct a new Key Table object * @@ -103,29 +70,25 @@ struct KeyTable { * @param _filter */ KeyTable( - QTableWidget* _key_list, KeyListRow::KeyType _select_type, - KeyListColumn::InfoType _info_type, - KeyTableFilter _filter = [](const GpgKey&, const KeyTable&) -> bool { + QWidget* parent, QSharedPointer<GpgKeyTableModel> model, + GpgKeyTableDisplayMode _select_type, GpgKeyTableColumn _info_type, + GpgKeyTableProxyModel::KeyFilter _filter = [](const GpgKey&) -> bool { return true; - }) - : key_list_(_key_list), - select_type_(_select_type), - info_type_(_info_type), - filter_(std::move(_filter)) {} + }); /** * @brief * - * @param m_keys + * @param model */ - void Refresh(KeyLinkListPtr m_keys = nullptr); + void RefreshModel(QSharedPointer<GpgKeyTableModel> model); /** * @brief Get the Checked object * * @return KeyIdArgsListPtr& */ - KeyIdArgsListPtr& GetChecked(); + auto GetChecked() -> KeyIdArgsListPtr; /** * @brief @@ -140,23 +103,90 @@ struct KeyTable { void CheckALL() const; /** - * @brief Set the Checked object + * @brief * - * @param key_ids */ - void SetChecked(KeyIdArgsListPtr key_ids); + void SetMenuAbility(KeyMenuAbility::AbilityType ability); /** * @brief * */ - void SetMenuAbility(KeyMenuAbility::AbilityType ability); + void SetFilterKeyword(const QString& keyword); /** * @brief * + * @param row + * @return true + * @return false + */ + [[nodiscard]] auto IsRowChecked(int row) const -> bool; + + /** + * @brief Set the Row Checked object + * + * @param row + */ + void SetRowChecked(int row) const; + + /** + * @brief Set the Row Checked object + * + * @param row + */ + [[nodiscard]] auto GetRowSelected() const -> int; + + /** + * @brief Get the Row Count object + * + * @return auto */ - void SetFilterKeyword(QString keyword); + [[nodiscard]] auto GetRowCount() const -> int; + + /** + * @brief Get the Key Id By Row object + * + * @param row + * @return QString + */ + [[nodiscard]] auto GetKeyIdByRow(int row) const -> QString; + + /** + * @brief + * + * @param row + * @return true + * @return false + */ + [[nodiscard]] auto IsPublicKeyByRow(int row) const -> bool; + + /** + * @brief + * + * @param row + * @return true + * @return false + */ + [[nodiscard]] auto IsPrivateKeyByRow(int row) const -> bool; + + /** + * @brief + * + */ + void CheckAll(); + + /** + * @brief + * + */ + void UncheckAll(); + + private: + KeyMenuAbility::AbilityType ability_; ///< + + QSharedPointer<GpgKeyTableModel> model_; + GpgKeyTableProxyModel proxy_model_; }; /** @@ -186,10 +216,11 @@ class KeyList : public QWidget { */ void AddListGroupTab( const QString& name, const QString& id, - KeyListRow::KeyType selectType = KeyListRow::SECRET_OR_PUBLIC_KEY, - KeyListColumn::InfoType infoType = KeyListColumn::ALL, - KeyTable::KeyTableFilter filter = - [](const GpgKey&, const KeyTable&) -> bool { return true; }); + GpgKeyTableDisplayMode selectType = GpgKeyTableDisplayMode::kPrivateKey, + GpgKeyTableColumn infoType = GpgKeyTableColumn::kAll, + GpgKeyTableProxyModel::KeyFilter filter = [](const GpgKey&) -> bool { + return true; + }); /** * @brief Set the Double Clicked Action object @@ -259,13 +290,6 @@ class KeyList : public QWidget { /** * @brief Set the Checked object * - * @param key_ids - */ - void SetChecked(KeyIdArgsListPtr key_ids); - - /** - * @brief Set the Checked object - * * @param keyIds * @param key_table */ @@ -355,15 +379,11 @@ class KeyList : public QWidget { */ void filter_by_keyword(); - std::mutex buffered_key_list_mutex_; ///< - std::shared_ptr<Ui_KeyList> ui_; ///< - QTableWidget* m_key_list_{}; ///< - std::vector<KeyTable> m_key_tables_; ///< QMenu* popup_menu_{}; ///< - GpgFrontend::KeyLinkListPtr buffered_keys_list_; ///< std::function<void(const GpgKey&, QWidget*)> m_action_ = nullptr; ///< KeyMenuAbility::AbilityType menu_ability_ = KeyMenuAbility::ALL; ///< + QSharedPointer<GpgKeyTableModel> model_; private slots: @@ -378,12 +398,6 @@ class KeyList : public QWidget { * @brief * */ - void slot_refresh_ui(); - - /** - * @brief - * - */ void slot_sync_with_key_server(); protected: |