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 /src | |
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
Diffstat (limited to 'src')
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); |