diff options
author | Saturneric <[email protected]> | 2022-05-09 14:40:54 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2022-05-09 14:40:54 +0000 |
commit | 670733f7a90d337d546afab22ddedeedec6d3d67 (patch) | |
tree | 2c64c0667d2cac45040257802c40963f89737700 | |
parent | doc: add entry to developer document. (diff) | |
download | GpgFrontend-670733f7a90d337d546afab22ddedeedec6d3d67.tar.gz GpgFrontend-670733f7a90d337d546afab22ddedeedec6d3d67.zip |
fix: fix crash poblem when doing operations
1. refactor GpgFunctionObject to solve shared library problem.
2. fix multi-threading issues in refreshing.
3. improve loading speed for key list
4. improve ui operation
5. do other fixing and improving operations
24 files changed, 641 insertions, 257 deletions
diff --git a/src/core/GpgContext.cpp b/src/core/GpgContext.cpp index 0da963ee..733354fc 100644 --- a/src/core/GpgContext.cpp +++ b/src/core/GpgContext.cpp @@ -224,4 +224,8 @@ gpgme_error_t GpgContext::test_status_cb(void *hook, const char *keyword, return GPG_ERR_NO_ERROR; } +void GpgContext::_ctx_ref_deleter::operator()(gpgme_ctx_t _ctx) { + if (_ctx != nullptr) gpgme_release(_ctx); +} + } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/GpgContext.h b/src/core/GpgContext.h index b148fcb5..e1f1bda4 100644 --- a/src/core/GpgContext.h +++ b/src/core/GpgContext.h @@ -116,9 +116,7 @@ class GPGFRONTEND_CORE_EXPORT GpgContext * */ struct _ctx_ref_deleter { - void operator()(gpgme_ctx_t _ctx) { - if (_ctx != nullptr) gpgme_release(_ctx); - } + void operator()(gpgme_ctx_t _ctx); }; using CtxRefHandler = diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp index e9b8fcdc..41cf99cb 100644 --- a/src/core/GpgCoreInit.cpp +++ b/src/core/GpgCoreInit.cpp @@ -28,6 +28,9 @@ #include "GpgCoreInit.h" +#include <memory> + +#include "GpgFunctionObject.h" #include "core/GpgContext.h" #include "core/function/GlobalSettingStation.h" @@ -70,27 +73,25 @@ void init_logging() { void init_gpgfrontend_core() { // init default channel GpgFrontend::GpgContext::CreateInstance( - GPGFRONTEND_DEFAULT_CHANNEL, - [&]() -> std::unique_ptr<GpgFrontend::GpgContext> { + GPGFRONTEND_DEFAULT_CHANNEL, [&]() -> std::unique_ptr<ChannelObject> { GpgFrontend::GpgContextInitArgs args; - return std::make_unique<GpgFrontend::GpgContext>(args); + return std::unique_ptr<ChannelObject>(new GpgContext(args)); }); // init non-ascii channel GpgFrontend::GpgContext::CreateInstance( - GPGFRONTEND_NON_ASCII_CHANNEL, - [&]() -> std::unique_ptr<GpgFrontend::GpgContext> { + GPGFRONTEND_NON_ASCII_CHANNEL, [&]() -> std::unique_ptr<ChannelObject> { GpgFrontend::GpgContextInitArgs args; args.ascii = false; - return std::make_unique<GpgFrontend::GpgContext>(args); + return std::unique_ptr<ChannelObject>(new GpgContext(args)); }); } void new_default_settings_channel(int channel) { GpgFrontend::GpgContext::CreateInstance( - channel, [&]() -> std::unique_ptr<GpgFrontend::GpgContext> { + channel, [&]() -> std::unique_ptr<ChannelObject> { GpgFrontend::GpgContextInitArgs args; - return std::make_unique<GpgFrontend::GpgContext>(args); + return std::unique_ptr<ChannelObject>(new GpgContext(args)); }); } diff --git a/src/core/GpgFunctionObject.cpp b/src/core/GpgFunctionObject.cpp new file mode 100644 index 00000000..9fb55247 --- /dev/null +++ b/src/core/GpgFunctionObject.cpp @@ -0,0 +1,143 @@ +/** + * Copyright (C) 2021 Saturneric + * + * 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 "core/GpgFunctionObject.h" + +#include <cassert> +#include <functional> +#include <memory> +#include <mutex> +#include <shared_mutex> + +#include "easylogging++.h" + +void GpgFrontend::ChannelObject::SetChannel(int channel) { + this->channel_ = channel; +} + +int GpgFrontend::ChannelObject::GetChannel() const { return channel_; } + +int GpgFrontend::ChannelObject::GetDefaultChannel() { return _default_channel; } + +void GpgFrontend::SingletonStorage::ReleaseChannel(int channel) { + decltype(instances_map_.end()) _it; + { + std::shared_lock<std::shared_mutex> lock(instances_mutex_); + _it = instances_map_.find(channel); + } + if (_it != instances_map_.end()) instances_map_.erase(_it); + DLOG(INFO) << "channel" << channel << "released"; +} + +GpgFrontend::ChannelObject* GpgFrontend::SingletonStorage::FindObjectInChannel( + int channel) { + LOG(INFO) << "channel:" << channel << "instance address:" << &instances_map_; + // read instances_map_ + decltype(instances_map_.end()) _it; + { + std::shared_lock<std::shared_mutex> lock(instances_mutex_); + _it = instances_map_.find(channel); + if (_it == instances_map_.end()) { + LOG(INFO) << "channel:" << channel << "not found"; + return nullptr; + } else { + return _it->second.get(); + } + } +} + +std::vector<int> GpgFrontend::SingletonStorage::GetAllChannelId() { + std::vector<int> _channels; + for (const auto& [key, value] : instances_map_) { + _channels.push_back(key); + } + return _channels; +} + +GpgFrontend::ChannelObject* GpgFrontend::SingletonStorage::SetObjectInChannel( + int channel, std::unique_ptr<ChannelObject> p_obj) { + { + LOG(INFO) << "channel:" << channel + << "instance address:" << &instances_map_; + + assert(p_obj != nullptr); + if (p_obj == nullptr) return nullptr; + + auto raw_obj = p_obj.get(); + p_obj->SetChannel(channel); + { + std::unique_lock<std::shared_mutex> lock(instances_mutex_); + instances_map_.insert({channel, std::move(p_obj)}); + } + return raw_obj; + } +} + +GpgFrontend::SingletonStorage* +GpgFrontend::SingletonStorageCollection::GetSingletonStorage( + const std::type_info& type_id) { + const auto hash = type_id.hash_code(); + LOG(INFO) << "hash" << hash << "type_name:" << type_id.name(); + + while (true) { + decltype(storages_map_.end()) _it; + { + std::shared_lock<std::shared_mutex> lock(storages_mutex_); + _it = storages_map_.find(hash); + } + if (_it == storages_map_.end()) { + LOG(INFO) << "hash:" << hash << "not found"; + { + std::unique_lock<std::shared_mutex> lock(storages_mutex_); + storages_map_.insert({hash, std::make_unique<SingletonStorage>()}); + LOG(INFO) << "hash:" << hash << "created" + << "storage address:" << &storages_map_; + } + continue; + } else { + LOG(INFO) << "hash:" << hash << "found"; + return _it->second.get(); + } + } +} + +GpgFrontend::SingletonStorageCollection* +GpgFrontend::SingletonStorageCollection::GetInstance() { + static SingletonStorageCollection* instance = nullptr; + if (instance == nullptr) { + instance = new SingletonStorageCollection(); + } + return instance; +} + +GpgFrontend::ChannelObject::ChannelObject() noexcept = default; + +GpgFrontend::ChannelObject::ChannelObject(int channel) : channel_(channel) { + LOG(INFO) << "called" + << "channel:" << channel; +} diff --git a/src/core/GpgFunctionObject.h b/src/core/GpgFunctionObject.h index 391b1585..f16e4cae 100644 --- a/src/core/GpgFunctionObject.h +++ b/src/core/GpgFunctionObject.h @@ -35,20 +35,144 @@ #include <shared_mutex> #include <stdexcept> #include <string> +#include <typeinfo> +#include <utility> +#include <vector> #include "GpgConstants.h" +#include "easylogging++.h" namespace GpgFrontend { /** + * @brief object which in channel system + * + */ +class GPGFRONTEND_CORE_EXPORT ChannelObject { + public: + /** + * @brief Construct a new Default Channel Object object + * + */ + ChannelObject() noexcept; + + /** + * @brief Construct a new Channel Object object + * + * @param channel + */ + ChannelObject(int channel); + + /** + * @brief Get the Default Channel object + * + * @return int + */ + static int GetDefaultChannel(); + + /** + * @brief Get the Channel object + * + * @return int + */ + [[nodiscard]] int GetChannel() const; + + /** + * @brief Set the Channel object + * + * @param channel + */ + void SetChannel(int channel); + + private: + int channel_ = _default_channel; ///< The channel id + static constexpr int _default_channel = 0; ///< The default channel id +}; + +class GPGFRONTEND_CORE_EXPORT SingletonStorage { + public: + /** + * @brief + * + * @param channel + */ + void ReleaseChannel(int channel); + + /** + * @brief + * + * @param channel + * @return T* + */ + ChannelObject* FindObjectInChannel(int channel); + + /** + * @brief Get all the channel ids + * + * @return std::vector<int> + */ + std::vector<int> GetAllChannelId(); + + /** + * @brief Set a new object in channel object + * + * @param channel + * @param p_obj + * @return T* + */ + ChannelObject* SetObjectInChannel(int channel, + std::unique_ptr<ChannelObject> p_obj); + + private: + std::shared_mutex instances_mutex_; ///< mutex for _instances_map + std::map<int, std::unique_ptr<ChannelObject>> + instances_map_; ///< map of singleton instances +}; + +class GPGFRONTEND_CORE_EXPORT SingletonStorageCollection { + public: + /** + * @brief Get the Instance object + * + * @return SingletonStorageCollection* + */ + static SingletonStorageCollection* GetInstance(); + + /** + * @brief Get the Singleton Storage object + * + * @param singleton_function_object + * @return SingletonStorage* + */ + SingletonStorage* GetSingletonStorage(const std::type_info&); + + private: + std::shared_mutex storages_mutex_; ///< mutex for storages_map_ + std::map<size_t, std::unique_ptr<SingletonStorage>> storages_map_; +}; +/** * @brief * * @tparam T */ template <typename T> -class SingletonFunctionObject { +class SingletonFunctionObject : public ChannelObject { public: /** + * @brief prohibit copy + * + */ + SingletonFunctionObject(const SingletonFunctionObject<T>&) = delete; + + /** + * @brief prohibit copy + * + * @return SingletonFunctionObject& + */ + SingletonFunctionObject& operator=(const SingletonFunctionObject<T>&) = + delete; + + /** * @brief Get the Instance object * * @param channel @@ -59,10 +183,19 @@ class SingletonFunctionObject { static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value, "T not derived from SingletonFunctionObject<T>"); - auto _p_pbj = find_object_in_channel(channel); - if (_p_pbj == nullptr) - return *set_object_in_channel(channel, std::make_unique<T>(channel)); - else + auto p_storage = + SingletonStorageCollection::GetInstance()->GetSingletonStorage( + typeid(T)); + + auto* _p_pbj = (T*)(p_storage->FindObjectInChannel(channel)); + + LOG(INFO) << "object address" << _p_pbj; + + if (_p_pbj == nullptr) { + auto new_obj = std::unique_ptr<ChannelObject>(new T(channel)); + LOG(INFO) << "create new object"; + return *(T*)(p_storage->SetObjectInChannel(channel, std::move(new_obj))); + } else return *_p_pbj; } @@ -73,33 +206,22 @@ class SingletonFunctionObject { * @param factory * @return T& */ - static T& CreateInstance(int channel, - std::function<std::unique_ptr<T>(void)> factory) { + static T& CreateInstance( + int channel, + std::function<std::unique_ptr<ChannelObject>(void)> factory) { static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value, "T not derived from SingletonFunctionObject<T>"); - auto _p_pbj = find_object_in_channel(channel); - if (_p_pbj == nullptr) - return *set_object_in_channel(channel, std::move(factory())); - else - return *_p_pbj; - } + auto p_storage = + SingletonStorageCollection::GetInstance()->GetSingletonStorage( + typeid(T)); - /** - * @brief Create a Instance object - * - * @param channel - * @param p_obj - * @return T& - */ - static T& CreateInstance(int channel, std::unique_ptr<T> p_obj = nullptr) { - static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value, - "T not derived from SingletonFunctionObject<T>"); + auto _p_pbj = (T*)(p_storage->FindObjectInChannel(channel)); - auto _p_pbj = find_object_in_channel(channel); - if (_p_pbj == nullptr) - return *set_object_in_channel(channel, std::move(p_obj)); - else + if (_p_pbj == nullptr) { + return *( + T*)(p_storage->SetObjectInChannel(channel, std::move(factory()))); + } else return *_p_pbj; } @@ -109,14 +231,10 @@ class SingletonFunctionObject { * @param channel * @return T& */ - static T& ReleaseChannel(int channel) { - decltype(_instances_map.end()) _it; - { - std::shared_lock lock(_instances_mutex); - _it = _instances_map.find(channel); - } - if (_it != _instances_map.end()) _instances_map.erase(_it); - DLOG(INFO) << "channel" << channel << "released"; + static void ReleaseChannel(int channel) { + SingletonStorageCollection::GetInstance() + ->GetSingletonStorage(typeid(T)) + ->ReleaseChannel(channel); } /** @@ -124,14 +242,25 @@ class SingletonFunctionObject { * * @return int */ - static int GetDefaultChannel() { return _default_channel; } + static int GetDefaultChannel() { return ChannelObject::GetDefaultChannel(); } /** * @brief Get the Channel object * * @return int */ - [[nodiscard]] int GetChannel() const { return channel_; } + [[nodiscard]] int GetChannel() const { return ChannelObject::GetChannel(); } + + /** + * @brief Get all the channel ids + * + * @return std::vector<int> + */ + static std::vector<int> GetAllChannelId() { + return SingletonStorageCollection::GetInstance() + ->GetSingletonStorage(typeid(T)) + ->GetAllChannelId(); + } /** * @brief Construct a new Singleton Function Object object @@ -163,85 +292,17 @@ class SingletonFunctionObject { * * @param channel */ - explicit SingletonFunctionObject(int channel) : channel_(channel) {} + explicit SingletonFunctionObject(int channel) : ChannelObject(channel) { + LOG(INFO) << "called" + << "channel:" << channel; + } /** * @brief Destroy the Singleton Function Object object * */ virtual ~SingletonFunctionObject() = default; - - /** - * @brief Set the Channel object - * - * @param channel - */ - void SetChannel(int channel) { this->channel_ = channel; } - - private: - int channel_ = _default_channel; ///< - static int _default_channel; ///< - static std::mutex _instance_mutex; ///< - static std::shared_mutex _instances_mutex; ///< - static std::unique_ptr<T> _instance; ///< - static std::map<int, std::unique_ptr<T>> _instances_map; ///< - - /** - * @brief - * - * @param channel - * @return T* - */ - static T* find_object_in_channel(int channel) { - // read _instances_map - decltype(_instances_map.end()) _it; - { - std::shared_lock lock(_instances_mutex); - _it = _instances_map.find(channel); - if (_it == _instances_map.end()) - return nullptr; - else - return _it->second.get(); - } - } - - /** - * @brief Set the object in channel object - * - * @param channel - * @param p_obj - * @return T* - */ - static T* set_object_in_channel(int channel, std::unique_ptr<T> p_obj) { - { - if (p_obj == nullptr) p_obj = std::make_unique<T>(); - T* obj = p_obj.get(); - obj->SetChannel(channel); - { - std::unique_lock lock(_instances_mutex); - _instances_map.insert({channel, std::move(p_obj)}); - } - return obj; - } - } }; - -template <typename T> -int SingletonFunctionObject<T>::_default_channel = - GpgFrontend::GPGFRONTEND_DEFAULT_CHANNEL; - -template <typename T> -std::mutex SingletonFunctionObject<T>::_instance_mutex; - -template <typename T> -std::shared_mutex SingletonFunctionObject<T>::_instances_mutex; - -template <typename T> -std::unique_ptr<T> SingletonFunctionObject<T>::_instance = nullptr; - -template <typename T> -std::map<int, std::unique_ptr<T>> SingletonFunctionObject<T>::_instances_map; - } // namespace GpgFrontend #endif // GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H diff --git a/src/core/function/gpg/GpgKeyGetter.cpp b/src/core/function/gpg/GpgKeyGetter.cpp index cbd40efc..9a7b505c 100644 --- a/src/core/function/gpg/GpgKeyGetter.cpp +++ b/src/core/function/gpg/GpgKeyGetter.cpp @@ -30,12 +30,32 @@ #include <gpg-error.h> +#include <mutex> +#include <shared_mutex> +#include <utility> + #include "GpgConstants.h" +#include "easylogging++.h" +#include "model/GpgKey.h" GpgFrontend::GpgKeyGetter::GpgKeyGetter(int channel) - : SingletonFunctionObject<GpgKeyGetter>(channel) {} + : SingletonFunctionObject<GpgKeyGetter>(channel) { + LOG(INFO) << "called" + << "channel:" << channel; +} GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetKey(const std::string& fpr) { + LOG(INFO) << "called"; + + // find in cache first + { + std::lock_guard<std::mutex> lock(keys_cache_mutex_); + if (keys_cache_.find(fpr) != keys_cache_.end()) { + std::lock_guard<std::mutex> lock(ctx_mutex_); + return keys_cache_[fpr].Copy(); + } + } + gpgme_key_t _p_key = nullptr; gpgme_get_key(ctx_, fpr.c_str(), &_p_key, 1); if (_p_key == nullptr) { @@ -48,6 +68,15 @@ GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetKey(const std::string& fpr) { GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetPubkey( const std::string& fpr) { + // find in cache first + { + std::lock_guard<std::mutex> lock(keys_cache_mutex_); + if (keys_cache_.find(fpr) != keys_cache_.end()) { + std::lock_guard<std::mutex> lock(ctx_mutex_); + return keys_cache_[fpr].Copy(); + } + } + gpgme_key_t _p_key = nullptr; gpgme_get_key(ctx_, fpr.c_str(), &_p_key, 0); if (_p_key == nullptr) @@ -56,28 +85,59 @@ GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetPubkey( } GpgFrontend::KeyLinkListPtr GpgFrontend::GpgKeyGetter::FetchKey() { - gpgme_error_t err; + // get the lock + std::lock_guard<std::mutex> lock(keys_cache_mutex_); + + LOG(INFO) << "GpgKeyGetter FetchKey" + << "channel id:" << GetChannel(); auto keys_list = std::make_unique<GpgKeyLinkList>(); - LOG(INFO) << "GpgKeyGetter FetchKey" - << "ctx address" << ctx_; + LOG(INFO) << "cache address:" << &keys_cache_ << "object address" << this; - err = gpgme_op_keylist_start(ctx_, nullptr, 0); + for (const auto& [key, value] : keys_cache_) { + LOG(INFO) << "FetchKey Id:" << value.GetId(); + keys_list->push_back(value.Copy()); + } + LOG(INFO) << "ended"; + return keys_list; +} + +void GpgFrontend::GpgKeyGetter::FlushKeyCache() { + LOG(INFO) << "called" + << "channel id: " << GetChannel(); + + // clear the keys cache + keys_cache_.clear(); + + // init + GpgError err = gpgme_op_keylist_start(ctx_, nullptr, 0); + + // for debug assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR); - gpgme_key_t key; - while ((err = gpgme_op_keylist_next(ctx_, &key)) == GPG_ERR_NO_ERROR) { - keys_list->push_back(GetKey(key->fpr)); + // return when error + if (check_gpg_error_2_err_code(err) != GPG_ERR_NO_ERROR) return; + + { + // get the lock + std::lock_guard<std::mutex> lock(keys_cache_mutex_); + gpgme_key_t key; + while ((err = gpgme_op_keylist_next(ctx_, &key)) == GPG_ERR_NO_ERROR) { + LOG(INFO) << "LoadKey Fpr:" << key->fpr << "Id:" << key->subkeys->keyid; + keys_cache_.insert({key->subkeys->keyid, GpgKey(std::move(key))}); + } } + LOG(INFO) << "cache address:" << &keys_cache_ << "object address" << this; + + // for debug assert(check_gpg_error_2_err_code(err, GPG_ERR_EOF) == GPG_ERR_EOF); err = gpgme_op_keylist_end(ctx_); - assert(check_gpg_error_2_err_code(err, GPG_ERR_EOF) == GPG_ERR_NO_ERROR); - return keys_list; + LOG(INFO) << "ended"; } GpgFrontend::KeyListPtr GpgFrontend::GpgKeyGetter::GetKeys( @@ -89,6 +149,8 @@ GpgFrontend::KeyListPtr GpgFrontend::GpgKeyGetter::GetKeys( GpgFrontend::KeyLinkListPtr GpgFrontend::GpgKeyGetter::GetKeysCopy( const GpgFrontend::KeyLinkListPtr& keys) { + // get the lock + std::lock_guard<std::mutex> lock(ctx_mutex_); auto keys_copy = std::make_unique<GpgKeyLinkList>(); for (const auto& key : *keys) keys_copy->push_back(key.Copy()); return keys_copy; @@ -96,6 +158,8 @@ GpgFrontend::KeyLinkListPtr GpgFrontend::GpgKeyGetter::GetKeysCopy( GpgFrontend::KeyListPtr GpgFrontend::GpgKeyGetter::GetKeysCopy( const GpgFrontend::KeyListPtr& keys) { + // get the lock + std::lock_guard<std::mutex> lock(ctx_mutex_); auto keys_copy = std::make_unique<KeyArgsList>(); for (const auto& key : *keys) keys_copy->push_back(key.Copy()); return keys_copy; diff --git a/src/core/function/gpg/GpgKeyGetter.h b/src/core/function/gpg/GpgKeyGetter.h index d63238f5..72cd777c 100644 --- a/src/core/function/gpg/GpgKeyGetter.h +++ b/src/core/function/gpg/GpgKeyGetter.h @@ -29,6 +29,9 @@ #ifndef GPGFRONTEND_ZH_CN_TS_GPGKEYGETTER_H #define GPGFRONTEND_ZH_CN_TS_GPGKEYGETTER_H +#include <mutex> +#include <vector> + #include "core/GpgContext.h" #include "core/GpgFunctionObject.h" #include "core/GpgModel.h" @@ -56,7 +59,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter * @param fpr * @return GpgKey */ - GpgKey GetKey(const std::string& fpr); + GpgKey GetKey(const std::string& id); /** * @brief Get the Keys object @@ -72,22 +75,28 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter * @param fpr * @return GpgKey */ - GpgKey GetPubkey(const std::string& fpr); + GpgKey GetPubkey(const std::string& id); /** - * @brief + * @brief Get all the keys by receiving a linked list * * @return KeyLinkListPtr */ KeyLinkListPtr FetchKey(); /** + * @brief flush the keys in the cache + * + */ + void FlushKeyCache(); + + /** * @brief Get the Keys Copy object * * @param keys * @return KeyListPtr */ - static KeyListPtr GetKeysCopy(const KeyListPtr& keys); + KeyListPtr GetKeysCopy(const KeyListPtr& keys); /** * @brief Get the Keys Copy object @@ -95,7 +104,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter * @param keys * @return KeyLinkListPtr */ - static KeyLinkListPtr GetKeysCopy(const KeyLinkListPtr& keys); + KeyLinkListPtr GetKeysCopy(const KeyLinkListPtr& keys); private: /** @@ -104,6 +113,24 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter */ GpgContext& ctx_ = GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); + + /** + * @brief shared mutex for the keys cache + * + */ + mutable std::mutex ctx_mutex_; + + /** + * @brief cache the keys with key fpr + * + */ + std::map<std::string, GpgKey> keys_cache_; + + /** + * @brief shared mutex for the keys cache + * + */ + mutable std::mutex keys_cache_mutex_; }; } // namespace GpgFrontend diff --git a/src/core/thread/CtxCheckThread.cpp b/src/core/thread/CtxCheckThread.cpp index 77571dfd..edec8855 100644 --- a/src/core/thread/CtxCheckThread.cpp +++ b/src/core/thread/CtxCheckThread.cpp @@ -48,7 +48,7 @@ void GpgFrontend::CtxCheckThread::run() { if (!GpgContext::GetInstance().good()) { emit SignalGnupgNotInstall(); } - // Try fetching key + // Try flushing key cache else - GpgFrontend::GpgKeyGetter::GetInstance().FetchKey(); + GpgFrontend::GpgKeyGetter::GetInstance().FlushKeyCache(); } diff --git a/src/main.cpp b/src/main.cpp index 51d977b2..35204fd0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -165,8 +165,8 @@ int main(int argc, char* argv[]) { &QEventLoop::quit); loop.exec(); - // init ui logging - GpgFrontend::UI::init_logging(); + // init ui library + GpgFrontend::UI::InitGpgFrontendUI(); /** * internationalisation. loop to restart main window diff --git a/src/ui/GpgFrontendUIInit.cpp b/src/ui/GpgFrontendUIInit.cpp index 82746551..49f16ec5 100644 --- a/src/ui/GpgFrontendUIInit.cpp +++ b/src/ui/GpgFrontendUIInit.cpp @@ -28,6 +28,8 @@ #include "GpgFrontendUIInit.h" +#include "SignalStation.h" +#include "UserInterfaceUtils.h" #include "core/function/GlobalSettingStation.h" // init easyloggingpp library @@ -35,6 +37,14 @@ INITIALIZE_EASYLOGGINGPP namespace GpgFrontend::UI { +extern void init_logging(); + +void InitGpgFrontendUI() { + init_logging(); + SignalStation::GetInstance(); + CommonUtils::GetInstance(); +} + void init_logging() { using namespace boost::posix_time; using namespace boost::gregorian; diff --git a/src/ui/GpgFrontendUIInit.h b/src/ui/GpgFrontendUIInit.h index ddb791c3..6518256b 100644 --- a/src/ui/GpgFrontendUIInit.h +++ b/src/ui/GpgFrontendUIInit.h @@ -34,9 +34,10 @@ namespace GpgFrontend::UI { /** - * @brief + * @brief init the UI library + * */ -void init_logging(); +void InitGpgFrontendUI(); }; // namespace GpgFrontend::UI diff --git a/src/ui/SignalStation.cpp b/src/ui/SignalStation.cpp index 045b63f5..c1f1238f 100644 --- a/src/ui/SignalStation.cpp +++ b/src/ui/SignalStation.cpp @@ -28,6 +28,8 @@ #include "SignalStation.h" +#include "UserInterfaceUtils.h" + namespace GpgFrontend::UI { std::unique_ptr<SignalStation> SignalStation::_instance = nullptr; diff --git a/src/ui/SignalStation.h b/src/ui/SignalStation.h index dbf978be..eb7b3f74 100644 --- a/src/ui/SignalStation.h +++ b/src/ui/SignalStation.h @@ -60,6 +60,12 @@ class SignalStation : public QObject { /** * @brief * + */ + void SignalKeyDatabaseRefreshDone(); + + /** + * @brief + * * @param text * @param verify_label_status */ diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp index 52b7eb28..9859ff65 100644 --- a/src/ui/UserInterfaceUtils.cpp +++ b/src/ui/UserInterfaceUtils.cpp @@ -29,10 +29,13 @@ #include "UserInterfaceUtils.h" #include <utility> +#include <vector> #include "core/common/CoreCommonUtil.h" #include "core/function/FileOperator.h" #include "core/function/GlobalSettingStation.h" +#include "core/function/gpg/GpgKeyGetter.h" +#include "easylogging++.h" #include "ui/SignalStation.h" #include "ui/dialog/WaitingDialog.h" #include "ui/widgets/TextEdit.h" @@ -129,11 +132,24 @@ CommonUtils *CommonUtils::GetInstance() { } CommonUtils::CommonUtils() : QWidget(nullptr) { + LOG(INFO) << "common utils created"; + connect(CoreCommonUtil::GetInstance(), &CoreCommonUtil::SignalGnupgNotInstall, this, &CommonUtils::SignalGnupgNotInstall); connect(this, &CommonUtils::SignalKeyStatusUpdated, SignalStation::GetInstance(), &SignalStation::SignalKeyDatabaseRefresh); + connect(this, &CommonUtils::SignalKeyDatabaseRefreshDone, + SignalStation::GetInstance(), + &SignalStation::SignalKeyDatabaseRefreshDone); + + // directly connect to SignalKeyStatusUpdated + // to avoid the delay of signal emitting + // when the key database is refreshed + connect(SignalStation::GetInstance(), + &SignalStation::SignalKeyDatabaseRefresh, this, + &CommonUtils::slot_update_key_status); + connect(this, &CommonUtils::SignalGnupgNotInstall, this, []() { QMessageBox::critical( nullptr, _("ENV Loading Failed"), @@ -227,8 +243,7 @@ void CommonUtils::SlotExecuteGpgCommand( } void CommonUtils::SlotImportKeyFromKeyServer( - const KeyIdArgsList &key_ids, - const ImportCallbackFunctiopn &callback) { + const KeyIdArgsList &key_ids, const ImportCallbackFunctiopn &callback) { std::string target_keyserver; if (target_keyserver.empty()) { try { @@ -248,71 +263,95 @@ void CommonUtils::SlotImportKeyFromKeyServer( } } - auto thread = - QThread::create([target_keyserver, key_ids, callback]() { - QUrl target_keyserver_url(target_keyserver.c_str()); - - auto network_manager = std::make_unique<QNetworkAccessManager>(); - // LOOP - decltype(key_ids.size()) current_index = 1, all_index = key_ids.size(); - for (const auto &key_id : key_ids) { - // New Req Url - QUrl req_url(target_keyserver_url.scheme() + "://" + - target_keyserver_url.host() + - "/pks/lookup?op=get&search=0x" + key_id.c_str() + - "&options=mr"); - - LOG(INFO) << "request url" << req_url.toString().toStdString(); - - // Waiting for reply - QNetworkReply *reply = network_manager->get(QNetworkRequest(req_url)); - QEventLoop loop; - connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); - loop.exec(); - - // Get Data - auto key_data = reply->readAll(); - auto key_data_ptr = - std::make_unique<ByteArray>(key_data.data(), key_data.size()); - - // Detect status - std::string status; - auto error = reply->error(); - if (error != QNetworkReply::NoError) { - switch (error) { - case QNetworkReply::ContentNotFoundError: - status = _("Key Not Found"); - break; - case QNetworkReply::TimeoutError: - status = _("Timeout"); - break; - case QNetworkReply::HostNotFoundError: - status = _("Key Server Not Found"); - break; - default: - status = _("Connection Error"); - } - } - - reply->deleteLater(); - - // Try importing - GpgImportInformation result = - GpgKeyImportExporter::GetInstance() - .ImportKey(std::move(key_data_ptr)); - - if (result.imported == 1) { - status = _("The key has been updated"); - } else { - status = _("No need to update the key"); - } - callback(key_id, status, current_index, all_index); - current_index++; + auto thread = QThread::create([target_keyserver, key_ids, callback]() { + QUrl target_keyserver_url(target_keyserver.c_str()); + + auto network_manager = std::make_unique<QNetworkAccessManager>(); + // LOOP + decltype(key_ids.size()) current_index = 1, all_index = key_ids.size(); + for (const auto &key_id : key_ids) { + // New Req Url + QUrl req_url( + target_keyserver_url.scheme() + "://" + target_keyserver_url.host() + + "/pks/lookup?op=get&search=0x" + key_id.c_str() + "&options=mr"); + + LOG(INFO) << "request url" << req_url.toString().toStdString(); + + // Waiting for reply + QNetworkReply *reply = network_manager->get(QNetworkRequest(req_url)); + QEventLoop loop; + connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); + + // Get Data + auto key_data = reply->readAll(); + auto key_data_ptr = + std::make_unique<ByteArray>(key_data.data(), key_data.size()); + + // Detect status + std::string status; + auto error = reply->error(); + if (error != QNetworkReply::NoError) { + switch (error) { + case QNetworkReply::ContentNotFoundError: + status = _("Key Not Found"); + break; + case QNetworkReply::TimeoutError: + status = _("Timeout"); + break; + case QNetworkReply::HostNotFoundError: + status = _("Key Server Not Found"); + break; + default: + status = _("Connection Error"); } - }); + } + + reply->deleteLater(); + + // Try importing + GpgImportInformation result = + GpgKeyImportExporter::GetInstance().ImportKey( + std::move(key_data_ptr)); + + if (result.imported == 1) { + status = _("The key has been updated"); + } else { + status = _("No need to update the key"); + } + callback(key_id, status, current_index, all_index); + current_index++; + } + }); connect(thread, &QThread::finished, thread, &QThread::deleteLater); thread->start(); } +void CommonUtils::slot_update_key_status() { + LOG(INFO) << "called"; + + std::vector<QThread *> threads; + + // flush key cache for all GpgKeyGetter Intances. + for (const auto &channel_id : GpgKeyGetter::GetAllChannelId()) { + // multi threading + auto *thread = QThread::create([channel_id]() { + LOG(INFO) << "thread start" + << "channel:" << channel_id; + GpgKeyGetter::GetInstance(channel_id).FlushKeyCache(); + }); + thread->start(); + threads.push_back(thread); + } + + for (auto *thread : threads) { + thread->wait(); + thread->deleteLater(); + } + + emit SignalKeyDatabaseRefreshDone(); + LOG(INFO) << "finished"; +} + } // namespace GpgFrontend::UI
\ No newline at end of file diff --git a/src/ui/UserInterfaceUtils.h b/src/ui/UserInterfaceUtils.h index a7f20f10..85ef012b 100644 --- a/src/ui/UserInterfaceUtils.h +++ b/src/ui/UserInterfaceUtils.h @@ -59,8 +59,8 @@ void show_verify_details(QWidget* parent, InfoBoardWidget* info_board, * @param parent * @param verify_res */ -void import_unknown_key_from_keyserver(QWidget* parent, - const GpgVerifyResultAnalyse& verify_res); +void import_unknown_key_from_keyserver( + QWidget* parent, const GpgVerifyResultAnalyse& verify_res); /** * @brief @@ -144,6 +144,12 @@ class CommonUtils : public QWidget { */ void SignalGnupgNotInstall(); + /** + * @brief emit when the key database is refreshed + * + */ + void SignalKeyDatabaseRefreshDone(); + public slots: /** * @brief @@ -195,6 +201,14 @@ class CommonUtils : public QWidget { const QStringList& arguments, const std::function<void(QProcess*)>& interact_func); + private slots: + + /** + * @brief update the key status when signal is emitted + * + */ + void slot_update_key_status(); + private: static std::unique_ptr<CommonUtils> instance_; ///< }; diff --git a/src/ui/import_export/KeyServerImportDialog.cpp b/src/ui/import_export/KeyServerImportDialog.cpp index c35e3db7..2d30c021 100644 --- a/src/ui/import_export/KeyServerImportDialog.cpp +++ b/src/ui/import_export/KeyServerImportDialog.cpp @@ -30,9 +30,9 @@ #include <utility> +#include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgKeyImportExporter.h" #include "ui/SignalStation.h" -#include "core/function/GlobalSettingStation.h" namespace GpgFrontend::UI { @@ -47,12 +47,15 @@ KeyServerImportDialog::KeyServerImportDialog(bool automatic, QWidget* parent) // Buttons close_button_ = new QPushButton(_("Close")); - connect(close_button_, &QPushButton::clicked, this, &KeyServerImportDialog::close); + connect(close_button_, &QPushButton::clicked, this, + &KeyServerImportDialog::close); import_button_ = new QPushButton(_("Import ALL")); - connect(import_button_, &QPushButton::clicked, this, &KeyServerImportDialog::slot_import); + connect(import_button_, &QPushButton::clicked, this, + &KeyServerImportDialog::slot_import); import_button_->setDisabled(true); search_button_ = new QPushButton(_("Search")); - connect(search_button_, &QPushButton::clicked, this, &KeyServerImportDialog::slot_search); + connect(search_button_, &QPushButton::clicked, this, + &KeyServerImportDialog::slot_search); // Line edits for search string search_label_ = new QLabel(QString(_("Search String")) + _(": ")); @@ -139,11 +142,13 @@ KeyServerImportDialog::KeyServerImportDialog(bool automatic, QWidget* parent) this->setModal(true); - connect(this, &KeyServerImportDialog::SignalKeyImported, SignalStation::GetInstance(), + connect(this, &KeyServerImportDialog::SignalKeyImported, + SignalStation::GetInstance(), &SignalStation::SignalKeyDatabaseRefresh); // save window pos and size to configure file - connect(this, &KeyServerImportDialog::finished, this, &KeyServerImportDialog::slot_save_window_state); + connect(this, &KeyServerImportDialog::finished, this, + &KeyServerImportDialog::slot_save_window_state); } QComboBox* KeyServerImportDialog::create_comboBox() { @@ -222,7 +227,8 @@ void KeyServerImportDialog::slot_search() { QNetworkReply* reply = network_access_manager_->get(QNetworkRequest(url_from_remote)); - connect(reply, &QNetworkReply::finished, this, &KeyServerImportDialog::slot_search_finished); + connect(reply, &QNetworkReply::finished, this, + &KeyServerImportDialog::slot_search_finished); set_loading(true); this->search_button_->setDisabled(true); diff --git a/src/ui/key_generate/KeygenDialog.cpp b/src/ui/key_generate/KeygenDialog.cpp index 6df0bcf0..676539c7 100644 --- a/src/ui/key_generate/KeygenDialog.cpp +++ b/src/ui/key_generate/KeygenDialog.cpp @@ -28,10 +28,10 @@ #include "ui/key_generate/KeygenDialog.h" -#include "dialog/WaitingDialog.h" +#include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgKeyOpera.h" +#include "dialog/WaitingDialog.h" #include "ui/SignalStation.h" -#include "core/function/GlobalSettingStation.h" namespace GpgFrontend::UI { @@ -144,15 +144,19 @@ void KeyGenDialog::slot_key_gen_accept() { dialog->close(); + LOG(INFO) << "generate done"; + if (gpgme_err_code(error) == GPG_ERR_NO_ERROR) { - auto* msg_box = new QMessageBox(nullptr); + auto* msg_box = new QMessageBox((QWidget*)this->parent()); msg_box->setAttribute(Qt::WA_DeleteOnClose); msg_box->setStandardButtons(QMessageBox::Ok); msg_box->setWindowTitle(_("Success")); msg_box->setText(_("The new key pair has been generated.")); - msg_box->setModal(false); + msg_box->setModal(true); msg_box->open(); + LOG(INFO) << "generate success"; + emit SignalKeyGenerated(); this->close(); } else { diff --git a/src/ui/key_generate/SubkeyGenerateDialog.cpp b/src/ui/key_generate/SubkeyGenerateDialog.cpp index 4eb041aa..451c6521 100644 --- a/src/ui/key_generate/SubkeyGenerateDialog.cpp +++ b/src/ui/key_generate/SubkeyGenerateDialog.cpp @@ -26,11 +26,11 @@ #include "ui/key_generate/SubkeyGenerateDialog.h" -#include "dialog/WaitingDialog.h" +#include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgKeyGetter.h" #include "core/function/gpg/GpgKeyOpera.h" +#include "dialog/WaitingDialog.h" #include "ui/SignalStation.h" -#include "core/function/GlobalSettingStation.h" namespace GpgFrontend::UI { @@ -73,7 +73,8 @@ SubkeyGenerateDialog::SubkeyGenerateDialog(const KeyId& key_id, QWidget* parent) this->setLayout(vbox2); this->setModal(true); - connect(this, &SubkeyGenerateDialog::SignalSubKeyGenerated, SignalStation::GetInstance(), + connect(this, &SubkeyGenerateDialog::SignalSubKeyGenerated, + SignalStation::GetInstance(), &SignalStation::SignalKeyDatabaseRefresh); set_signal_slot(); @@ -156,8 +157,10 @@ QGroupBox* SubkeyGenerateDialog::create_basic_info_group_box() { } void SubkeyGenerateDialog::set_signal_slot() { - connect(button_box_, &QDialogButtonBox::accepted, this, &SubkeyGenerateDialog::slot_key_gen_accept); - connect(button_box_, &QDialogButtonBox::rejected, this, &SubkeyGenerateDialog::reject); + connect(button_box_, &QDialogButtonBox::accepted, this, + &SubkeyGenerateDialog::slot_key_gen_accept); + connect(button_box_, &QDialogButtonBox::rejected, this, + &SubkeyGenerateDialog::reject); connect(expire_check_box_, &QCheckBox::stateChanged, this, &SubkeyGenerateDialog::slot_expire_box_changed); @@ -171,8 +174,8 @@ void SubkeyGenerateDialog::set_signal_slot() { connect(key_usage_check_boxes_[3], &QCheckBox::stateChanged, this, &SubkeyGenerateDialog::slot_authentication_box_changed); - connect(key_type_combo_box_, qOverload<int>(&QComboBox::currentIndexChanged), this, - &SubkeyGenerateDialog::slot_activated_key_type); + connect(key_type_combo_box_, qOverload<int>(&QComboBox::currentIndexChanged), + this, &SubkeyGenerateDialog::slot_activated_key_type); } void SubkeyGenerateDialog::slot_expire_box_changed() { @@ -271,12 +274,12 @@ void SubkeyGenerateDialog::slot_key_gen_accept() { dialog->close(); if (check_gpg_error_2_err_code(error) == GPG_ERR_NO_ERROR) { - auto* msg_box = new QMessageBox(nullptr); + auto* msg_box = new QMessageBox((QWidget*)this->parent()); msg_box->setAttribute(Qt::WA_DeleteOnClose); msg_box->setStandardButtons(QMessageBox::Ok); msg_box->setWindowTitle(_("Success")); msg_box->setText(_("The new subkey has been generated.")); - msg_box->setModal(false); + msg_box->setModal(true); msg_box->open(); emit SignalSubKeyGenerated(); diff --git a/src/ui/keypair_details/KeyPairDetailTab.cpp b/src/ui/keypair_details/KeyPairDetailTab.cpp index 6174e67b..76f316e9 100644 --- a/src/ui/keypair_details/KeyPairDetailTab.cpp +++ b/src/ui/keypair_details/KeyPairDetailTab.cpp @@ -26,9 +26,9 @@ #include "ui/keypair_details/KeyPairDetailTab.h" -#include "dialog/WaitingDialog.h" #include "core/function/gpg/GpgKeyGetter.h" #include "core/function/gpg/GpgKeyImportExporter.h" +#include "dialog/WaitingDialog.h" #include "ui/SignalStation.h" namespace GpgFrontend::UI { @@ -152,7 +152,8 @@ KeyPairDetailTab::KeyPairDetailTab(const std::string& key_id, QWidget* parent) mvbox->setContentsMargins(0, 0, 0, 0); // when key database updated - connect(SignalStation::GetInstance(), &SignalStation::SignalKeyDatabaseRefresh, this, + connect(SignalStation::GetInstance(), + &SignalStation::SignalKeyDatabaseRefreshDone, this, &KeyPairDetailTab::slot_refresh_key); slot_refresh_key_info(); @@ -169,11 +170,12 @@ void KeyPairDetailTab::slot_copy_fingerprint() { void KeyPairDetailTab::slot_refresh_key_info() { // Show the situation that primary key not exists. - primary_key_exist_var_label_->setText(key_.IsHasMasterKey() ? _("Exists") - : _("Not Exists")); + primary_key_exist_var_label_->setText( + key_.IsHasMasterKey() ? _("Exists") : _("Not Exists")); if (!key_.IsHasMasterKey()) { auto palette_expired = primary_key_exist_var_label_->palette(); - palette_expired.setColor(primary_key_exist_var_label_->foregroundRole(), Qt::red); + palette_expired.setColor(primary_key_exist_var_label_->foregroundRole(), + Qt::red); primary_key_exist_var_label_->setPalette(palette_expired); } else { auto palette_valid = primary_key_exist_var_label_->palette(); diff --git a/src/ui/keypair_details/KeyPairSubkeyTab.cpp b/src/ui/keypair_details/KeyPairSubkeyTab.cpp index 067ce110..46de550c 100644 --- a/src/ui/keypair_details/KeyPairSubkeyTab.cpp +++ b/src/ui/keypair_details/KeyPairSubkeyTab.cpp @@ -124,10 +124,10 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(const std::string& key_id, QWidget* parent) // key database refresh signal connect(SignalStation::GetInstance(), - &SignalStation::SignalKeyDatabaseRefresh, this, + &SignalStation::SignalKeyDatabaseRefreshDone, this, &KeyPairSubkeyTab::slot_refresh_key_info); connect(SignalStation::GetInstance(), - &SignalStation::SignalKeyDatabaseRefresh, this, + &SignalStation::SignalKeyDatabaseRefreshDone, this, &KeyPairSubkeyTab::slot_refresh_subkey_list); baseLayout->setContentsMargins(0, 0, 0, 0); diff --git a/src/ui/keypair_details/KeyPairUIDTab.cpp b/src/ui/keypair_details/KeyPairUIDTab.cpp index 81d34684..4cc835a8 100644 --- a/src/ui/keypair_details/KeyPairUIDTab.cpp +++ b/src/ui/keypair_details/KeyPairUIDTab.cpp @@ -102,7 +102,7 @@ KeyPairUIDTab::KeyPairUIDTab(const std::string& key_id, QWidget* parent) // Key Database Refresh connect(SignalStation::GetInstance(), - &SignalStation::SignalKeyDatabaseRefresh, this, + &SignalStation::SignalKeyDatabaseRefreshDone, this, &KeyPairUIDTab::slot_refresh_key); connect(this, &KeyPairUIDTab::SignalUpdateUIDInfo, @@ -419,7 +419,7 @@ void KeyPairUIDTab::slot_set_primary_uid() { if (ret == QMessageBox::Yes) { if (!GpgUIDOperator::GetInstance().SetPrimaryUID(m_key_, - selected_uids->front())) { + selected_uids->front())) { QMessageBox::critical(nullptr, _("Operation Failed"), _("An error occurred during the operation.")); } else { diff --git a/src/ui/keypair_details/KeySetExpireDateDialog.cpp b/src/ui/keypair_details/KeySetExpireDateDialog.cpp index 79325e8b..785dce14 100644 --- a/src/ui/keypair_details/KeySetExpireDateDialog.cpp +++ b/src/ui/keypair_details/KeySetExpireDateDialog.cpp @@ -30,10 +30,10 @@ #include <utility> +#include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgKeyGetter.h" #include "core/function/gpg/GpgKeyOpera.h" #include "ui/SignalStation.h" -#include "core/function/GlobalSettingStation.h" #include "ui_ModifiedExpirationDateTime.h" namespace GpgFrontend::UI { @@ -72,21 +72,20 @@ void KeySetExpireDateDialog::slot_confirm() { auto err = GpgKeyOpera::GetInstance().SetExpire(m_key_, m_subkey_, expires); if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR) { - auto* msg_box = new QMessageBox(nullptr); + auto* msg_box = new QMessageBox((QWidget*)this->parent()); msg_box->setAttribute(Qt::WA_DeleteOnClose); msg_box->setStandardButtons(QMessageBox::Ok); msg_box->setWindowTitle(_("Success")); msg_box->setText(_("The expire date of the key pair has been updated.")); - msg_box->setModal(false); + msg_box->setModal(true); msg_box->open(); emit SignalKeyExpireDateUpdated(); + this->close(); } else { QMessageBox::critical(this, _("Failure"), _(gpgme_strerror(err))); } - - this->close(); } void KeySetExpireDateDialog::init() { @@ -113,8 +112,11 @@ void KeySetExpireDateDialog::init() { ui_->dateEdit->setMaximumDateTime(max_date_time); ui_->dateEdit->setMinimumDateTime(min_date_time); - ui_->dateEdit->setDateTime(max_date_time); - ui_->timeEdit->setDateTime(max_date_time); + // set default date time to expire date time + auto current_expire_time = + QDateTime::fromTime_t(to_time_t(m_key_.GetExpireTime())); + ui_->dateEdit->setDateTime(current_expire_time); + ui_->timeEdit->setDateTime(current_expire_time); connect(ui_->noExpirationCheckBox, &QCheckBox::stateChanged, this, &KeySetExpireDateDialog::slot_non_expired_checked); diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp index 0a322f6a..a1db4d61 100644 --- a/src/ui/main_window/MainWindowSlotFunction.cpp +++ b/src/ui/main_window/MainWindowSlotFunction.cpp @@ -27,7 +27,6 @@ */ #include "MainWindow.h" - #include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgBasicOperator.h" #include "core/function/gpg/GpgKeyGetter.h" @@ -74,7 +73,7 @@ void MainWindow::slot_encrypt() { } }); } else { - auto key_getter = GpgFrontend::GpgKeyGetter::GetInstance(); + auto& key_getter = GpgFrontend::GpgKeyGetter::GetInstance(); auto keys = GpgKeyGetter::GetInstance().GetKeys(key_ids); for (const auto& key : *keys) { if (!key.IsHasActualEncryptionCapability()) { diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp index 6292c1a9..237576ad 100644 --- a/src/ui/widgets/KeyList.cpp +++ b/src/ui/widgets/KeyList.cpp @@ -29,6 +29,7 @@ #include "ui/widgets/KeyList.h" #include <boost/format.hpp> +#include <mutex> #include <utility> #include "core/GpgCoreInit.h" @@ -63,7 +64,7 @@ void KeyList::init() { connect(this, &KeyList::SignalRefreshDatabase, SignalStation::GetInstance(), &SignalStation::SignalKeyDatabaseRefresh); connect(SignalStation::GetInstance(), - &SignalStation::SignalKeyDatabaseRefresh, this, + &SignalStation::SignalKeyDatabaseRefreshDone, this, &KeyList::SlotRefresh); connect(ui_->refreshKeyListButton, &QPushButton::clicked, this, &KeyList::SlotRefresh); @@ -154,19 +155,15 @@ void KeyList::AddListGroupTab( } void KeyList::SlotRefresh() { - LOG(INFO) << _("Called"); - emit SignalRefreshStatusBar(_("Refreshing Key List..."), 3000); - auto thread = QThread::create([this]() { - std::lock_guard<std::mutex> guard(buffered_key_list_mutex_); - buffered_keys_list_ = nullptr; - // buffered keys list - buffered_keys_list_ = GpgKeyGetter::GetInstance().FetchKey(); - }); - connect(thread, &QThread::finished, this, &KeyList::slot_refresh_ui); - connect(thread, &QThread::finished, thread, &QThread::deleteLater); + LOG(INFO) << _("Called") << "address" << this; + ui_->refreshKeyListButton->setDisabled(true); ui_->syncButton->setDisabled(true); - thread->start(); + + emit SignalRefreshStatusBar(_("Refreshing Key List..."), 3000); + + this->buffered_keys_list_ = GpgKeyGetter::GetInstance().FetchKey(); + this->slot_refresh_ui(); } KeyIdArgsListPtr KeyList::GetChecked(const KeyTable& key_table) { @@ -424,7 +421,8 @@ void KeyList::slot_refresh_ui() { if (buffered_keys_list_ != nullptr) { std::lock_guard<std::mutex> guard(buffered_key_list_mutex_); for (auto& key_table : m_key_tables_) { - key_table.Refresh(GpgKeyGetter::GetKeysCopy(buffered_keys_list_)); + key_table.Refresh( + GpgKeyGetter::GetInstance().GetKeysCopy(buffered_keys_list_)); } } emit SignalRefreshStatusBar(_("Key List Refreshed."), 1000); |