aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2024-06-02 20:03:59 +0000
committersaturneric <[email protected]>2024-06-02 20:03:59 +0000
commite7694f9a0729cb88064eda6623c99070f5a46dc0 (patch)
tree39c5339991212dc4eaf653ec3e016b8daa79fbb7
parentfix: cannot show version in about tab (diff)
downloadGpgFrontend-e7694f9a0729cb88064eda6623c99070f5a46dc0.tar.gz
GpgFrontend-e7694f9a0729cb88064eda6623c99070f5a46dc0.zip
feat: rewrite key list structure and logic
-rw-r--r--src/core/function/CacheManager.cpp3
-rw-r--r--src/core/function/gpg/GpgKeyGetter.cpp25
-rw-r--r--src/core/function/gpg/GpgKeyGetter.h8
-rw-r--r--src/core/model/GpgKeyTableModel.cpp162
-rw-r--r--src/core/model/GpgKeyTableModel.h196
-rw-r--r--src/core/model/GpgKeyTableProxyModel.cpp142
-rw-r--r--src/core/model/GpgKeyTableProxyModel.h82
-rw-r--r--src/core/typedef/GpgTypedef.h2
-rw-r--r--src/ui/UserInterfaceUtils.cpp46
-rw-r--r--src/ui/UserInterfaceUtils.h13
-rw-r--r--src/ui/dialog/SignersPicker.cpp7
-rw-r--r--src/ui/dialog/keypair_details/KeyUIDSignDialog.cpp6
-rw-r--r--src/ui/main_window/KeyMgmt.cpp57
-rw-r--r--src/ui/main_window/MainWindowSlotFunction.cpp4
-rw-r--r--src/ui/main_window/MainWindowUI.cpp39
-rw-r--r--src/ui/widgets/KeyList.cpp536
-rw-r--r--src/ui/widgets/KeyList.h166
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: