aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/cmd.cpp16
-rw-r--r--src/core/module/Event.cpp1
-rw-r--r--src/core/module/GlobalModuleContext.cpp45
-rw-r--r--src/core/module/GlobalModuleContext.h4
-rw-r--r--src/core/module/Module.cpp57
-rw-r--r--src/core/module/Module.h8
-rw-r--r--src/core/module/ModuleManager.cpp17
-rw-r--r--src/core/module/ModuleManager.h4
-rw-r--r--src/core/utils/BuildInfoUtils.cpp26
-rw-r--r--src/core/utils/BuildInfoUtils.h82
-rw-r--r--src/core/utils/CommonUtils.cpp2
-rw-r--r--src/core/utils/IOUtils.cpp38
-rw-r--r--src/core/utils/IOUtils.h9
-rw-r--r--src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp94
-rw-r--r--src/module/integrated/version_checking_module/VersionCheckTask.cpp9
-rw-r--r--src/module/integrated/version_checking_module/VersionCheckingModule.h2
-rw-r--r--src/module/sdk/Basic.cpp20
-rw-r--r--src/module/sdk/Basic.h32
-rw-r--r--src/module/sdk/Module.cpp22
-rw-r--r--src/ui/CMakeLists.txt2
-rw-r--r--src/ui/GpgFrontendApplication.cpp12
-rw-r--r--src/ui/UserInterfaceUtils.cpp6
-rw-r--r--src/ui/dialog/SignersPicker.h4
-rw-r--r--src/ui/dialog/controller/GnuPGControllerDialog.cpp (renamed from src/ui/dialog/gnupg/GnuPGControllerDialog.cpp)0
-rw-r--r--src/ui/dialog/controller/GnuPGControllerDialog.h (renamed from src/ui/dialog/gnupg/GnuPGControllerDialog.h)0
-rw-r--r--src/ui/dialog/controller/ModuleControllerDialog.cpp111
-rw-r--r--src/ui/dialog/controller/ModuleControllerDialog.h61
-rw-r--r--src/ui/dialog/help/AboutDialog.cpp10
-rw-r--r--src/ui/dialog/import_export/KeyUploadDialog.cpp5
-rw-r--r--src/ui/main_window/MainWindow.h3
-rw-r--r--src/ui/main_window/MainWindowUI.cpp23
-rw-r--r--src/ui/thread/KeyServerImportTask.cpp4
-rw-r--r--src/ui/thread/KeyServerSearchTask.cpp5
-rw-r--r--src/ui/thread/ListedKeyServerTestTask.cpp5
-rw-r--r--src/ui/thread/ProxyConnectionTestTask.cpp5
-rw-r--r--src/ui/widgets/ModuleListView.cpp63
-rw-r--r--src/ui/widgets/ModuleListView.h53
-rw-r--r--ui/ModuleControllerDialog.ui212
39 files changed, 963 insertions, 111 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index eae20641..cebfa67b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -220,7 +220,7 @@ endif ()
set(BUILD_VERSION ${PROJECT_VERSION}_${CMAKE_SYSTEM}_${CMAKE_SYSTEM_PROCESSOR}_${CMAKE_BUILD_TYPE})
set(GIT_VERSION ${GIT_BRANCH_NAME}_${GIT_COMMIT_HASH})
-string(TIMESTAMP BUILD_TIMESTAMP "%Y-%m-%d %H:%M:%S")
+string(TIMESTAMP BUILD_TIMESTAMP UTC)
# Convert BUILD_VERSION and GIT_VERSION to lowercase
string(TOLOWER "${BUILD_VERSION}" BUILD_VERSION)
diff --git a/src/cmd.cpp b/src/cmd.cpp
index cef0a984..d41b6de0 100644
--- a/src/cmd.cpp
+++ b/src/cmd.cpp
@@ -28,13 +28,13 @@
#include "cmd.h"
+#include "core/utils/BuildInfoUtils.h"
#include "main.h"
// std
#include <iostream>
// GpgFrontend
-#include "GpgFrontendBuildInfo.h"
#include "GpgFrontendContext.h"
#include "test/GpgFrontendTest.h"
@@ -42,19 +42,19 @@ namespace GpgFrontend {
auto PrintVersion() -> int {
QTextStream stream(stdout);
- stream << PROJECT_NAME << " "
- << "v" << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_PATCH
- << '\n';
+ stream << PROJECT_NAME << " " << GetProjectVersion() << '\n';
stream << "Copyright (©) 2021 Saturneric <[email protected]>" << '\n'
<< QCoreApplication::tr(
"This is free software; see the source for copying conditions.")
<< '\n'
<< '\n';
- stream << QCoreApplication::tr("Build DateTime: ") << BUILD_TIMESTAMP << '\n'
- << QCoreApplication::tr("Build Version: ") << BUILD_VERSION << '\n'
- << QCoreApplication::tr("Source Code Version: ") << GIT_VERSION
- << '\n';
+ stream << QCoreApplication::tr("Build DateTime: ")
+ << QLocale().toString(GetProjectBuildTimestamp()) << '\n'
+ << QCoreApplication::tr("Build Version: ") << GetProjectBuildVersion()
+ << '\n'
+ << QCoreApplication::tr("Source Code Version: ")
+ << GetProjectBuildGitVersion() << '\n';
stream << Qt::endl;
return 0;
diff --git a/src/core/module/Event.cpp b/src/core/module/Event.cpp
index 5a7b324c..01f7bf9b 100644
--- a/src/core/module/Event.cpp
+++ b/src/core/module/Event.cpp
@@ -105,6 +105,7 @@ class Event::Impl {
auto* event = static_cast<ModuleEvent*>(SecureMalloc(sizeof(ModuleEvent)));
event->id = GFStrDup(event_identifier_);
+ event->triggger_id = GFStrDup(trigger_uuid_);
ModuleEventParam* l_param = nullptr;
ModuleEventParam* p_param;
diff --git a/src/core/module/GlobalModuleContext.cpp b/src/core/module/GlobalModuleContext.cpp
index cf3e134b..cd970df4 100644
--- a/src/core/module/GlobalModuleContext.cpp
+++ b/src/core/module/GlobalModuleContext.cpp
@@ -179,6 +179,15 @@ class GlobalModuleContext::Impl {
GF_CORE_LOG_DEBUG("new event {} of module system created", event);
}
+ // module -> event
+ auto module_info_opt = search_module_register_table(module_id);
+ if (!module_info_opt.has_value()) {
+ GF_CORE_LOG_ERROR("cannot find module id {} at register table",
+ module_id);
+ return false;
+ }
+ module_info_opt.value()->listening_event_ids.push_back(event);
+
auto& listeners_set = met_it->second;
// Add the listener (module) to the event.
auto listener_it = listeners_set.find(module_id);
@@ -199,7 +208,7 @@ class GlobalModuleContext::Impl {
auto module_info = module_info_opt.value();
// Activate the module if it is not already deactive.
- if (!module_info->activate && module_info->module->Deactive()) {
+ if (!module_info->activate && (module_info->module->Deactive() == 0)) {
module_info->activate = false;
}
@@ -303,11 +312,27 @@ class GlobalModuleContext::Impl {
return m.has_value() && m->get()->activate;
}
+ auto ListAllRegisteredModuleID() -> QList<ModuleIdentifier> {
+ QList<ModuleIdentifier> module_ids;
+ for (const auto& module : module_register_table_) {
+ module_ids.append(module.first);
+ }
+ return module_ids;
+ }
+
+ auto GetModuleListening(const ModuleIdentifier& module_id)
+ -> QList<EventIdentifier> {
+ auto module_info = search_module_register_table(module_id);
+ if (!module_info.has_value()) return {};
+ return module_info->get()->listening_event_ids;
+ }
+
private:
struct ModuleRegisterInfo {
int channel;
ModulePtr module;
bool activate;
+ QList<QString> listening_event_ids;
};
using ModuleRegisterInfoPtr = std::shared_ptr<ModuleRegisterInfo>;
@@ -335,7 +360,8 @@ class GlobalModuleContext::Impl {
}
// Function to search for a module in the register table.
- auto search_module_register_table(const ModuleIdentifier& identifier) const
+ [[nodiscard]] auto search_module_register_table(
+ const ModuleIdentifier& identifier) const
-> std::optional<ModuleRegisterInfoPtr> {
auto mrt_it = module_register_table_.find(identifier);
if (mrt_it == module_register_table_.end()) {
@@ -375,7 +401,7 @@ auto GlobalModuleContext::GetGlobalTaskRunner()
}
auto GlobalModuleContext::RegisterModule(ModulePtr module) -> bool {
- return p_->RegisterModule(std::move(module));
+ return p_->RegisterModule(module);
}
auto GlobalModuleContext::ActiveModule(ModuleIdentifier module_id) -> bool {
@@ -392,7 +418,7 @@ auto GlobalModuleContext::DeactivateModule(ModuleIdentifier module_id) -> bool {
}
auto GlobalModuleContext::TriggerEvent(EventRefrernce event) -> bool {
- return p_->TriggerEvent(std::move(event));
+ return p_->TriggerEvent(event);
}
auto GlobalModuleContext::SearchEvent(EventTriggerIdentifier trigger_id)
@@ -409,7 +435,16 @@ auto GlobalModuleContext::GetDefaultChannel(ModuleRawPtr channel) -> int {
}
auto GlobalModuleContext::IsModuleActivated(ModuleIdentifier m_id) -> bool {
- return p_->IsModuleActivated(std::move(m_id));
+ return p_->IsModuleActivated(m_id);
}
+auto GlobalModuleContext::ListAllRegisteredModuleID()
+ -> QList<ModuleIdentifier> {
+ return p_->ListAllRegisteredModuleID();
+}
+
+auto GlobalModuleContext::GetModuleListening(ModuleIdentifier module_id)
+ -> QList<EventIdentifier> {
+ return p_->GetModuleListening(module_id);
+}
} // namespace GpgFrontend::Module
diff --git a/src/core/module/GlobalModuleContext.h b/src/core/module/GlobalModuleContext.h
index 7034fd77..ae4300af 100644
--- a/src/core/module/GlobalModuleContext.h
+++ b/src/core/module/GlobalModuleContext.h
@@ -82,8 +82,12 @@ class GPGFRONTEND_CORE_EXPORT GlobalModuleContext : public QObject {
auto SearchEvent(EventTriggerIdentifier) -> std::optional<EventRefrernce>;
+ auto GetModuleListening(ModuleIdentifier) -> QList<EventIdentifier>;
+
auto IsModuleActivated(ModuleIdentifier) -> bool;
+ auto ListAllRegisteredModuleID() -> QList<ModuleIdentifier>;
+
private:
class Impl;
SecureUniquePtr<Impl> p_;
diff --git a/src/core/module/Module.cpp b/src/core/module/Module.cpp
index e943ab09..0534d261 100644
--- a/src/core/module/Module.cpp
+++ b/src/core/module/Module.cpp
@@ -29,6 +29,7 @@
#include "Module.h"
#include "core/module/GlobalModuleContext.h"
+#include "core/utils/IOUtils.h"
namespace GpgFrontend::Module {
@@ -47,7 +48,10 @@ class Module::Impl {
good_(true) {}
Impl(ModuleRawPtr m_ptr, QLibrary& module_library)
- : m_ptr_(m_ptr), good_(false) {
+ : m_ptr_(m_ptr),
+ module_hash_(CalculateBinaryChacksum(module_library.fileName())),
+ module_library_path_(module_library.fileName()),
+ good_(false) {
for (auto& required_symbol : module_required_symbols_) {
*required_symbol.pointer =
reinterpret_cast<void*>(module_library.resolve(required_symbol.name));
@@ -59,13 +63,26 @@ class Module::Impl {
}
}
- SPDLOG_INFO("module loaded, name: {}, verison: {}",
- QString::fromUtf8(get_id_api_()),
- QString::fromUtf8(get_version_api_()));
+ GF_CORE_LOG_INFO("module loaded, id: {}, verison: {}, hash: {}, path: {}",
+ QString::fromUtf8(get_id_api_()),
+ QString::fromUtf8(get_version_api_()), module_hash_,
+ module_library_path_);
identifier_ = QString::fromUtf8(get_id_api_());
version_ = QString::fromUtf8(get_version_api_());
+ ::ModuleMetaData* p_meta_data = get_metadata_api_();
+ ::ModuleMetaData* l_meta_data;
+
+ GF_CORE_LOG_DEBUG("AAAAAA: {}", static_cast<void*>(p_meta_data));
+ while (p_meta_data != nullptr) {
+ meta_data_[QString::fromUtf8(p_meta_data->key)] =
+ QString::fromUtf8(p_meta_data->value);
+ l_meta_data = p_meta_data;
+ p_meta_data = p_meta_data->next;
+ SecureFree(l_meta_data);
+ }
+
good_ = true;
}
@@ -116,6 +133,20 @@ class Module::Impl {
return identifier_;
}
+ [[nodiscard]] auto GetModuleVersion() const -> ModuleVersion {
+ return version_;
+ }
+
+ [[nodiscard]] auto GetModuleMetaData() const -> ModuleMetaData {
+ return meta_data_;
+ }
+
+ [[nodiscard]] auto GetModulePath() const -> QString {
+ return module_library_path_;
+ }
+
+ [[nodiscard]] auto GetModuleHash() const -> QString { return module_hash_; }
+
void SetGPC(GlobalModuleContext* gpc) { gpc_ = gpc; }
private:
@@ -124,6 +155,8 @@ class Module::Impl {
ModuleIdentifier identifier_;
ModuleVersion version_;
ModuleMetaData meta_data_;
+ QString module_hash_;
+ QString module_library_path_;
bool good_;
ModuleAPIGetModuleID get_id_api_;
@@ -198,5 +231,21 @@ auto Module::GetModuleIdentifier() const -> ModuleIdentifier {
return p_->GetModuleIdentifier();
}
+[[nodiscard]] auto Module::GetModuleVersion() const -> ModuleVersion {
+ return p_->GetModuleVersion();
+}
+
+[[nodiscard]] auto Module::GetModuleMetaData() const -> ModuleMetaData {
+ return p_->GetModuleMetaData();
+}
+
+[[nodiscard]] auto Module::GetModulePath() const -> QString {
+ return p_->GetModulePath();
+}
+
+[[nodiscard]] auto Module::GetModuleHash() const -> QString {
+ return p_->GetModuleHash();
+}
+
void Module::SetGPC(GlobalModuleContext* gpc) { p_->SetGPC(gpc); }
} // namespace GpgFrontend::Module \ No newline at end of file
diff --git a/src/core/module/Module.h b/src/core/module/Module.h
index 5eb214cc..097c7b00 100644
--- a/src/core/module/Module.h
+++ b/src/core/module/Module.h
@@ -68,6 +68,14 @@ class GPGFRONTEND_CORE_EXPORT Module : public QObject {
[[nodiscard]] auto GetModuleIdentifier() const -> ModuleIdentifier;
+ [[nodiscard]] auto GetModuleVersion() const -> ModuleVersion;
+
+ [[nodiscard]] auto GetModuleMetaData() const -> ModuleMetaData;
+
+ [[nodiscard]] auto GetModulePath() const -> QString;
+
+ [[nodiscard]] auto GetModuleHash() const -> QString;
+
void SetGPC(GlobalModuleContext *);
protected:
diff --git a/src/core/module/ModuleManager.cpp b/src/core/module/ModuleManager.cpp
index 17191af2..f49a0b1e 100644
--- a/src/core/module/ModuleManager.cpp
+++ b/src/core/module/ModuleManager.cpp
@@ -84,6 +84,10 @@ class ModuleManager::Impl {
return gmc_->SearchModule(std::move(module_id));
}
+ auto ListAllRegisteredModuleID() -> QList<ModuleIdentifier> {
+ return gmc_->ListAllRegisteredModuleID();
+ }
+
void RegisterModule(const ModulePtr& module) {
Thread::TaskRunnerGetter::GetInstance()
.GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default)
@@ -123,6 +127,11 @@ class ModuleManager::Impl {
return gmc_->SearchEvent(std::move(trigger_id));
}
+ auto GetModuleListening(ModuleIdentifier module_id)
+ -> QList<EventIdentifier> {
+ return gmc_->GetModuleListening(std::move(module_id));
+ }
+
void ActiveModule(const ModuleIdentifier& identifier) {
Thread::TaskRunnerGetter::GetInstance()
.GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default)
@@ -209,6 +218,11 @@ void ModuleManager::ListenEvent(ModuleIdentifier module,
return p_->ListenEvent(module, event);
}
+auto ModuleManager::GetModuleListening(ModuleIdentifier module_id)
+ -> QList<EventIdentifier> {
+ return p_->GetModuleListening(module_id);
+}
+
void ModuleManager::TriggerEvent(EventRefrernce event) {
return p_->TriggerEvent(event);
}
@@ -250,4 +264,7 @@ auto ModuleManager::IsModuleActivated(ModuleIdentifier id) -> bool {
return p_->IsModuleActivated(id);
}
+auto ModuleManager::ListAllRegisteredModuleID() -> QList<ModuleIdentifier> {
+ return p_->ListAllRegisteredModuleID();
+};
} // namespace GpgFrontend::Module \ No newline at end of file
diff --git a/src/core/module/ModuleManager.h b/src/core/module/ModuleManager.h
index 5bebe934..5110dfc2 100644
--- a/src/core/module/ModuleManager.h
+++ b/src/core/module/ModuleManager.h
@@ -69,6 +69,8 @@ class GPGFRONTEND_CORE_EXPORT ModuleManager
auto SearchModule(ModuleIdentifier) -> ModulePtr;
+ auto ListAllRegisteredModuleID() -> QList<ModuleIdentifier>;
+
void RegisterModule(ModulePtr);
auto IsModuleActivated(ModuleIdentifier) -> bool;
@@ -79,6 +81,8 @@ class GPGFRONTEND_CORE_EXPORT ModuleManager
auto SearchEvent(EventTriggerIdentifier) -> std::optional<EventRefrernce>;
+ auto GetModuleListening(ModuleIdentifier) -> QList<EventIdentifier>;
+
void ActiveModule(ModuleIdentifier);
void DeactiveModule(ModuleIdentifier);
diff --git a/src/core/utils/BuildInfoUtils.cpp b/src/core/utils/BuildInfoUtils.cpp
new file mode 100644
index 00000000..a7d914ef
--- /dev/null
+++ b/src/core/utils/BuildInfoUtils.cpp
@@ -0,0 +1,26 @@
+
+#include "BuildInfoUtils.h"
+
+#include "GpgFrontendBuildInfo.h"
+
+namespace GpgFrontend {
+
+auto GetProjectVersion() -> QString {
+ return QString("v") + VERSION_MAJOR + "." + VERSION_MINOR + "." +
+ VERSION_PATCH;
+}
+
+auto GetProjectBuildVersion() -> QString { return BUILD_VERSION; }
+
+auto GetProjectBuildTimestamp() -> QDateTime {
+ return QDateTime::fromString(BUILD_TIMESTAMP, Qt::ISODate);
+}
+
+auto GetProjectBuildGitBranchName() -> QString { return GIT_BRANCH_NAME; }
+
+auto GetProjectBuildGitCommitHash() -> QString { return GIT_COMMIT_HASH; }
+
+auto GetProjectBuildGitVersion() -> QString { return GIT_VERSION; }
+
+auto GetHttpRequestUserAgent() -> QString { return HTTP_REQUEST_USER_AGENT; }
+}; // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/utils/BuildInfoUtils.h b/src/core/utils/BuildInfoUtils.h
new file mode 100644
index 00000000..bac5d8a5
--- /dev/null
+++ b/src/core/utils/BuildInfoUtils.h
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#pragma once
+
+namespace GpgFrontend {
+
+/**
+ * @brief
+ *
+ * @return QString
+ */
+auto GPGFRONTEND_CORE_EXPORT GetProjectVersion() -> QString;
+
+/**
+ * @brief
+ *
+ * @return QString
+ */
+auto GPGFRONTEND_CORE_EXPORT GetProjectBuildVersion() -> QString;
+
+/**
+ * @brief
+ *
+ * @return QString
+ */
+auto GPGFRONTEND_CORE_EXPORT GetProjectBuildTimestamp() -> QDateTime;
+
+/**
+ * @brief
+ *
+ * @return QString
+ */
+auto GPGFRONTEND_CORE_EXPORT GetProjectBuildGitBranchName() -> QString;
+
+/**
+ * @brief
+ *
+ * @return QString
+ */
+auto GPGFRONTEND_CORE_EXPORT GetProjectBuildGitCommitHash() -> QString;
+
+/**
+ * @brief
+ *
+ * @return QString
+ */
+auto GPGFRONTEND_CORE_EXPORT GetProjectBuildGitVersion() -> QString;
+
+/**
+ * @brief
+ *
+ * @return QString
+ */
+auto GPGFRONTEND_CORE_EXPORT GetHttpRequestUserAgent() -> QString;
+
+} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/utils/CommonUtils.cpp b/src/core/utils/CommonUtils.cpp
index 36dfe0a7..20851cca 100644
--- a/src/core/utils/CommonUtils.cpp
+++ b/src/core/utils/CommonUtils.cpp
@@ -72,7 +72,7 @@ auto CompareSoftwareVersion(const QString& a, const QString& b) -> int {
return 0;
}
-auto GPGFRONTEND_CORE_EXPORT GFStrDup(const QString& str) -> char* {
+auto GFStrDup(const QString& str) -> char* {
auto utf8_str = str.toUtf8();
auto* c_str =
static_cast<char*>(SecureMalloc((utf8_str.size() + 1) * sizeof(char)));
diff --git a/src/core/utils/IOUtils.cpp b/src/core/utils/IOUtils.cpp
index 1002badd..79b879f9 100644
--- a/src/core/utils/IOUtils.cpp
+++ b/src/core/utils/IOUtils.cpp
@@ -180,4 +180,42 @@ auto GetFullExtension(const QString& path) -> QString {
return filename.mid(dot_index);
}
+auto CalculateBinaryChacksum(const QString& path) -> QString {
+ // check file info and access rights
+ QFileInfo info(path);
+ if (!info.exists() || !info.isFile() || !info.isReadable()) {
+ GF_CORE_LOG_ERROR("get info for file {} error, exists: {}", info.filePath(),
+ info.exists());
+ return {};
+ }
+
+ // open and read file
+ QFile f(info.filePath());
+ if (!f.open(QIODevice::ReadOnly)) {
+ GF_CORE_LOG_ERROR("open {} to calculate checksum error: {}",
+ path.toStdString(), f.errorString().toStdString());
+ return {};
+ }
+
+ QCryptographicHash hash_sha(QCryptographicHash::Sha256);
+
+ // read data by chunks
+ const qint64 buffer_size = 8192; // Define a suitable buffer size
+ while (!f.atEnd()) {
+ QByteArray buffer = f.read(buffer_size);
+ if (buffer.isEmpty()) {
+ GF_CORE_LOG_ERROR("error reading file {} during checksum calculation",
+ path.toStdString());
+ return {};
+ }
+ hash_sha.addData(buffer);
+ }
+
+ // close the file
+ f.close();
+
+ // return the SHA-256 hash of the file
+ return hash_sha.result().toHex();
+}
+
} // namespace GpgFrontend \ No newline at end of file
diff --git a/src/core/utils/IOUtils.h b/src/core/utils/IOUtils.h
index 2c48f38c..3e18394d 100644
--- a/src/core/utils/IOUtils.h
+++ b/src/core/utils/IOUtils.h
@@ -85,6 +85,15 @@ auto GPGFRONTEND_CORE_EXPORT CalculateHash(const QString &file_path) -> QString;
* @brief
*
* @param path
+ * @return QString
+ */
+auto GPGFRONTEND_CORE_EXPORT CalculateBinaryChacksum(const QString &path)
+ -> QString;
+
+/**
+ * @brief
+ *
+ * @param path
* @param out_buffer
* @return true
* @return false
diff --git a/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp b/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp
index 67dd5227..0595a8ac 100644
--- a/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp
+++ b/src/module/integrated/gnupg_info_gathering_module/GnuPGInfoGatheringModule.cpp
@@ -32,9 +32,8 @@
#include "GpgInfo.h"
#include "Log.h"
-ModuleMetaData *g_module_metadata = nullptr;
-
-extern auto CheckBinaryChacksum(QString path) -> std::optional<QString>;
+extern auto CalculateBinaryChacksum(const QString &path)
+ -> std::optional<QString>;
extern void GetGpgComponentInfos(void *, int, const char *, const char *);
@@ -50,30 +49,33 @@ using Context = struct {
auto RegisterModule() -> int {
ModuleLogDebug("gnupg info gathering module registering");
+ return 0;
+}
- g_module_metadata =
+auto GetModuleID() -> const char * {
+ return GFModuleStrDup(
+ "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering");
+}
+
+auto GetModuleVersion() -> const char * { return GFModuleStrDup("1.0.0"); }
+
+auto GetModuleMetaData() -> ModuleMetaData * {
+ auto *p_meta =
static_cast<ModuleMetaData *>(AllocateMemory(sizeof(ModuleMetaData)));
+ auto *h_meta = p_meta;
- auto *p_meta = g_module_metadata;
- p_meta->key = "description";
- p_meta->value = "try to gathering gnupg informations";
+ p_meta->key = "Description";
+ p_meta->value = "Try to gathering gnupg informations";
p_meta->next =
static_cast<ModuleMetaData *>(AllocateMemory(sizeof(ModuleMetaData)));
p_meta = p_meta->next;
- p_meta->key = "author";
- p_meta->value = "saturneric";
+ p_meta->key = "Author";
+ p_meta->value = "Saturneric";
p_meta->next = nullptr;
- return 0;
-}
-auto GetModuleID() -> const char * {
- return "com.bktus.gpgfrontend.module.integrated.gnupg-info-gathering";
+ return h_meta;
}
-auto GetModuleVersion() -> const char * { return "1.0.0"; }
-
-auto GetModuleMetaData() -> ModuleMetaData * { return g_module_metadata; }
-
auto ActiveModule() -> int {
ModuleLogDebug("gnupg info gathering module activating");
ListenEvent(GetModuleID(), "GPGFRONTEND_CORE_INITLIZED");
@@ -101,12 +103,16 @@ auto ExecuteModule(ModuleEvent *event) -> int {
auto context = Context{gpgme_version, gpgconf_path};
// get all components
- const char *argv[] = {"--list-components"};
+ const char *argv[] = {GFModuleStrDup("--list-components")};
ExecuteCommandSync(gpgconf_path, 1, argv, GetGpgComponentInfos, &context);
+ ModuleLogDebug("load gnupg component info done.");
QList<CommandExecuteContext> exec_contexts;
- const char *argv_0[] = {"--list-dirs"};
+ const char **argv_0 =
+ static_cast<const char **>(AllocateMemory(sizeof(const char *)));
+ argv_0[0] = GFModuleStrDup("--list-dirs");
+
exec_contexts.push_back(
{gpgconf_path, 1, argv_0, GetGpgDirectoryInfos, nullptr});
@@ -139,9 +145,12 @@ auto ExecuteModule(ModuleEvent *event) -> int {
auto context = Context{gpgme_version, gpgconf_path, component_info};
- const char *argv_0[] = {"--list-options", component_info.name.toUtf8()};
+ const char **argv_0 =
+ static_cast<const char **>(AllocateMemory(sizeof(const char *) * 2));
+ argv_0[0] = GFModuleStrDup("--list-options"),
+ argv_0[1] = GFModuleStrDup(component_info.name.toUtf8());
exec_contexts.push_back(
- {gpgconf_path, 1, argv_0, GetGpgDirectoryInfos, &context});
+ {gpgconf_path, 2, argv_0, GetGpgDirectoryInfos, &context});
}
ExecuteCommandBatchSync(static_cast<int32_t>(exec_contexts.size()),
@@ -149,10 +158,8 @@ auto ExecuteModule(ModuleEvent *event) -> int {
UpsertRTValue(GetModuleID(), "gnupg.gathering_done", "true");
- char **event_argv = static_cast<char **>(AllocateMemory(sizeof(char *) * 1));
- event_argv[0] = static_cast<char *>(AllocateMemory(5));
- memcpy(event_argv[0], "true", 4);
- event_argv[0][4] = '\0';
+ char **event_argv = static_cast<char **>(AllocateMemory(sizeof(char **) * 1));
+ event_argv[0] = GFModuleStrDup("true");
TriggerModuleEventCallback(event, GetModuleID(), 1, event_argv);
@@ -164,11 +171,10 @@ auto DeactiveModule() -> int { return 0; }
auto UnregisterModule() -> int {
ModuleLogDebug("gnupg info gathering module unregistering");
- FreeMemory(g_module_metadata);
return 0;
}
-auto CheckBinaryChacksum(QString path) -> std::optional<QString> {
+auto CalculateBinaryChacksum(const QString &path) -> std::optional<QString> {
// check file info and access rights
QFileInfo info(path);
if (!info.exists() || !info.isFile() || !info.isReadable()) {
@@ -181,19 +187,33 @@ auto CheckBinaryChacksum(QString path) -> std::optional<QString> {
// open and read file
QFile f(info.filePath());
if (!f.open(QIODevice::ReadOnly)) {
- ModuleLogError(fmt::format("open {} to calculate check sum error: {}", path,
- f.errorString())
+ ModuleLogError(fmt::format("open {} to calculate checksum error: {}",
+ path.toStdString(),
+ f.errorString().toStdString())
.c_str());
return {};
}
- // read all data from file
- auto buffer = f.readAll();
+ QCryptographicHash hash_sha(QCryptographicHash::Sha256);
+
+ // read data by chunks
+ const qint64 buffer_size = 8192; // Define a suitable buffer size
+ while (!f.atEnd()) {
+ QByteArray buffer = f.read(buffer_size);
+ if (buffer.isEmpty()) {
+ ModuleLogError(
+ fmt::format("error reading file {} during checksum calculation",
+ path.toStdString())
+ .c_str());
+ return {};
+ }
+ hash_sha.addData(buffer);
+ }
+
+ // close the file
f.close();
- auto hash_sha = QCryptographicHash(QCryptographicHash::Sha256);
- // md5
- hash_sha.addData(buffer);
+ // return the first 6 characters of the SHA-256 hash of the file
return QString(hash_sha.result().toHex()).left(6);
}
@@ -229,7 +249,7 @@ void GetGpgComponentInfos(void *data, int exit_code, const char *out,
c_i_gpgconf.desc = "GPG Configure";
c_i_gpgconf.version = "/";
c_i_gpgconf.path = context->gpgconf_path;
- auto gpgconf_binary_checksum = CheckBinaryChacksum(context->gpgconf_path);
+ auto gpgconf_binary_checksum = CalculateBinaryChacksum(context->gpgconf_path);
c_i_gpgconf.binary_checksum =
(gpgconf_binary_checksum.has_value() ? gpgconf_binary_checksum.value()
: QString("/"));
@@ -260,7 +280,7 @@ void GetGpgComponentInfos(void *data, int exit_code, const char *out,
component_path.replace("%3a", ":");
#endif
- auto binary_checksum = CheckBinaryChacksum(component_path);
+ auto binary_checksum = CalculateBinaryChacksum(component_path);
ModuleLogDebug(
fmt::format("gnupg component name: {} desc: {} checksum: {} path: {} ",
@@ -305,6 +325,8 @@ void GetGpgComponentInfos(void *data, int exit_code, const char *out,
component_infos.push_back(c_i);
}
+
+ ModuleLogDebug("load gnupg component info actually done.");
}
}
diff --git a/src/module/integrated/version_checking_module/VersionCheckTask.cpp b/src/module/integrated/version_checking_module/VersionCheckTask.cpp
index 91d5edff..eeb0231c 100644
--- a/src/module/integrated/version_checking_module/VersionCheckTask.cpp
+++ b/src/module/integrated/version_checking_module/VersionCheckTask.cpp
@@ -31,15 +31,14 @@
#include <QMetaType>
#include <QtNetwork>
-#include "GpgFrontendBuildInfo.h"
+#include "core/utils/BuildInfoUtils.h"
namespace GpgFrontend::Module::Integrated::VersionCheckingModule {
VersionCheckTask::VersionCheckTask()
: Task("version_check_task"),
network_manager_(new QNetworkAccessManager(this)),
- current_version_(QString("v") + VERSION_MAJOR + "." + VERSION_MINOR +
- "." + VERSION_PATCH) {
+ current_version_(GetProjectVersion()) {
HoldOnLifeCycle(true);
qRegisterMetaType<SoftwareVersion>("SoftwareVersion");
version_.current_version = current_version_;
@@ -53,7 +52,7 @@ auto VersionCheckTask::Run() -> int {
QNetworkRequest latest_request(latest_version_url);
latest_request.setHeader(QNetworkRequest::UserAgentHeader,
- HTTP_REQUEST_USER_AGENT);
+ GetHttpRequestUserAgent());
latest_reply_ = network_manager_->get(latest_request);
connect(latest_reply_, &QNetworkReply::finished, this,
@@ -122,7 +121,7 @@ void VersionCheckTask::slot_parse_latest_version_info() {
QNetworkRequest current_request(current_version_url);
current_request.setHeader(QNetworkRequest::UserAgentHeader,
- HTTP_REQUEST_USER_AGENT);
+ GetHttpRequestUserAgent());
current_reply_ = network_manager_->get(current_request);
diff --git a/src/module/integrated/version_checking_module/VersionCheckingModule.h b/src/module/integrated/version_checking_module/VersionCheckingModule.h
index 65b20198..387cdb3c 100644
--- a/src/module/integrated/version_checking_module/VersionCheckingModule.h
+++ b/src/module/integrated/version_checking_module/VersionCheckingModule.h
@@ -32,6 +32,8 @@
#include "SoftwareVersion.h"
#include "core/module/Module.h"
+
+
namespace GpgFrontend::Module::Integrated::VersionCheckingModule {
class GF_MODULE_EXPORT VersionCheckingModule : public Module {
diff --git a/src/module/sdk/Basic.cpp b/src/module/sdk/Basic.cpp
index 35ce8054..ce222fbd 100644
--- a/src/module/sdk/Basic.cpp
+++ b/src/module/sdk/Basic.cpp
@@ -57,12 +57,16 @@ void ExecuteCommandSync(const char* cmd, int32_t argc, const char** argv,
void ExecuteCommandBatchSync(int32_t context_size,
const CommandExecuteContext* context) {
QList<GpgFrontend::GpgCommandExecutor::ExecuteContext> contexts;
+
for (int i = 0; i < context_size; i++) {
- auto exec_context = context[i];
+ const auto& exec_context = context[i];
+
QStringList args;
- for (int i = 0; i < exec_context.argc; i++) {
- args.append(QString::fromUtf8(exec_context.argv[i]));
+ const char** argv = exec_context.argv;
+ for (int j = 0; j < exec_context.argc; j++) {
+ args.append(QString::fromUtf8(argv[j]));
}
+
contexts.append(
{exec_context.cmd, args,
[data = exec_context.data, cb = exec_context.cb](
@@ -72,4 +76,14 @@ void ExecuteCommandBatchSync(int32_t context_size,
}
GpgFrontend::GpgCommandExecutor::ExecuteConcurrentlySync(contexts);
+}
+
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleStrDup(const char* src) -> char* {
+ auto len = strlen(src);
+
+ char* dst = static_cast<char*>(AllocateMemory((len + 1) * sizeof(char)));
+ memcpy(dst, src, len);
+ dst[len] = '\0';
+
+ return dst;
} \ No newline at end of file
diff --git a/src/module/sdk/Basic.h b/src/module/sdk/Basic.h
index a232fd64..123b3783 100644
--- a/src/module/sdk/Basic.h
+++ b/src/module/sdk/Basic.h
@@ -43,16 +43,48 @@ using CommandExecuteContext = struct {
void* data;
};
+/**
+ * @brief
+ *
+ * @param size
+ * @return void*
+ */
auto GPGFRONTEND_MODULE_SDK_EXPORT AllocateMemory(uint32_t size) -> void*;
+/**
+ * @brief
+ *
+ */
void GPGFRONTEND_MODULE_SDK_EXPORT FreeMemory(void*);
+/**
+ * @brief
+ *
+ * @param cmd
+ * @param argc
+ * @param argv
+ * @param cb
+ * @param data
+ */
void GPGFRONTEND_MODULE_SDK_EXPORT ExecuteCommandSync(const char* cmd,
int32_t argc,
const char** argv,
CommandExeucteCallback cb,
void* data);
+/**
+ * @brief
+ *
+ * @param context_size
+ * @param context
+ */
void GPGFRONTEND_MODULE_SDK_EXPORT ExecuteCommandBatchSync(
int32_t context_size, const CommandExecuteContext* context);
+
+/**
+ * @brief
+ *
+ * @return char*
+ */
+auto GPGFRONTEND_MODULE_SDK_EXPORT GFModuleStrDup(const char*) -> char*;
} \ No newline at end of file
diff --git a/src/module/sdk/Module.cpp b/src/module/sdk/Module.cpp
index 36fe7b91..c69f6e5c 100644
--- a/src/module/sdk/Module.cpp
+++ b/src/module/sdk/Module.cpp
@@ -29,9 +29,9 @@
#include "Module.h"
#include <core/module/ModuleManager.h>
+#include <core/utils/CommonUtils.h>
#include "Basic.h"
-#include "core/utils/CommonUtils.h"
void ListenEvent(const char *module_id, const char *event_id) {
return GpgFrontend::Module::ModuleManager::GetInstance().ListenEvent(
@@ -40,13 +40,16 @@ void ListenEvent(const char *module_id, const char *event_id) {
auto RetrieveRTValueOrDefault(const char *namespace_, const char *key,
const char *default_value) -> const char * {
- return GpgFrontend::Module::RetrieveRTValueTypedOrDefault(
- namespace_, key, QString::fromUtf8(default_value))
- .toUtf8();
+ return GpgFrontend::GFStrDup(
+ GpgFrontend::Module::RetrieveRTValueTypedOrDefault(
+ QString::fromUtf8(namespace_), QString::fromUtf8(key),
+ QString::fromUtf8(default_value)));
}
void UpsertRTValue(const char *namespace_, const char *key, const char *vaule) {
- GpgFrontend::Module::UpsertRTValue(namespace_, key, vaule);
+ GpgFrontend::Module::UpsertRTValue(QString::fromUtf8(namespace_),
+ QString::fromUtf8(key),
+ QString::fromUtf8(vaule));
}
auto ListRTChildKeys(const char *namespace_, const char *key,
@@ -57,15 +60,10 @@ auto ListRTChildKeys(const char *namespace_, const char *key,
if (keys.empty()) return 0;
*child_keys =
- static_cast<char **>(AllocateMemory(sizeof(const char **) * keys.size()));
+ static_cast<char **>(AllocateMemory(sizeof(char **) * keys.size()));
for (int i = 0; i < keys.size(); i++) {
- *child_keys[i] =
- static_cast<char *>(AllocateMemory(sizeof(char) * keys[i].size() + 1));
-
- auto key = keys[i].toUtf8();
- memcpy(reinterpret_cast<void *>(*child_keys[i]), key, key.size());
- (*child_keys[i])[key.size()] = '\0';
+ (*child_keys)[i] = GpgFrontend::GFStrDup(keys[i]);
}
return static_cast<int32_t>(keys.size());
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 3f0686e2..5f22be00 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -36,7 +36,7 @@ aux_source_directory(thread UI_SOURCE)
aux_source_directory(dialog/details UI_SOURCE)
aux_source_directory(struct UI_SOURCE)
aux_source_directory(dialog/import_export UI_SOURCE)
-aux_source_directory(dialog/gnupg UI_SOURCE)
+aux_source_directory(dialog/controller UI_SOURCE)
aux_source_directory(dialog UI_SOURCE)
aux_source_directory(function UI_SOURCE)
diff --git a/src/ui/GpgFrontendApplication.cpp b/src/ui/GpgFrontendApplication.cpp
index c832ffe0..ad07fa7b 100644
--- a/src/ui/GpgFrontendApplication.cpp
+++ b/src/ui/GpgFrontendApplication.cpp
@@ -30,7 +30,7 @@
#include <QTextCodec>
-#include "GpgFrontendBuildInfo.h"
+#include "core/utils/BuildInfoUtils.h"
namespace GpgFrontend::UI {
@@ -42,10 +42,12 @@ GpgFrontendApplication::GpgFrontendApplication(int &argc, char *argv[])
#endif
// set the extra information of the build
- GpgFrontendApplication::setApplicationVersion(BUILD_VERSION);
- GpgFrontendApplication::setApplicationName(PROJECT_NAME);
- GpgFrontendApplication::setApplicationDisplayName(PROJECT_NAME);
- GpgFrontendApplication::setOrganizationName(PROJECT_NAME);
+ GpgFrontendApplication::setApplicationVersion(GetProjectBuildVersion());
+ GpgFrontendApplication::setApplicationName(QString::fromUtf8((PROJECT_NAME)));
+ GpgFrontendApplication::setApplicationDisplayName(
+ QString::fromUtf8((PROJECT_NAME)));
+ GpgFrontendApplication::setOrganizationName(
+ QString::fromUtf8((PROJECT_NAME)));
GpgFrontendApplication::setQuitOnLastWindowClosed(true);
// don't show icons in menus
diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp
index 9daca57b..5e24c8eb 100644
--- a/src/ui/UserInterfaceUtils.cpp
+++ b/src/ui/UserInterfaceUtils.cpp
@@ -30,7 +30,6 @@
#include <cstddef>
-#include "GpgFrontendBuildInfo.h"
#include "core/GpgConstants.h"
#include "core/function/CoreSignalStation.h"
#include "core/function/gpg/GpgKeyGetter.h"
@@ -39,12 +38,13 @@
#include "core/thread/Task.h"
#include "core/thread/TaskRunnerGetter.h"
#include "core/typedef/GpgTypedef.h"
+#include "core/utils/BuildInfoUtils.h"
#include "core/utils/GpgUtils.h"
#include "core/utils/IOUtils.h"
#include "thread/KeyServerImportTask.h"
#include "ui/UISignalStation.h"
#include "ui/dialog/WaitingDialog.h"
-#include "ui/dialog/gnupg/GnuPGControllerDialog.h"
+#include "ui/dialog/controller/GnuPGControllerDialog.h"
#include "ui/dialog/import_export/KeyServerImportDialog.h"
#include "ui/struct/CacheObject.h"
#include "ui/struct/SettingsObject.h"
@@ -431,7 +431,7 @@ void CommonUtils::SlotImportKeyFromKeyServer(
// Waiting for reply
auto request = QNetworkRequest(req_url);
request.setHeader(QNetworkRequest::UserAgentHeader,
- HTTP_REQUEST_USER_AGENT);
+ GetHttpRequestUserAgent());
QNetworkReply *reply = network_manager->get(request);
QEventLoop loop;
diff --git a/src/ui/dialog/SignersPicker.h b/src/ui/dialog/SignersPicker.h
index c7e1bfa5..cea8dd9a 100644
--- a/src/ui/dialog/SignersPicker.h
+++ b/src/ui/dialog/SignersPicker.h
@@ -56,13 +56,13 @@ class SignersPicker : public GeneralDialog {
*
* @return GpgFrontend::KeyIdArgsListPtr
*/
- KeyIdArgsListPtr GetCheckedSigners();
+ auto GetCheckedSigners() -> KeyIdArgsListPtr;
/**
*
* @return
*/
- [[nodiscard]] bool GetStatus() const;
+ [[nodiscard]] auto GetStatus() const -> bool;
private:
KeyList* key_list_; ///<
diff --git a/src/ui/dialog/gnupg/GnuPGControllerDialog.cpp b/src/ui/dialog/controller/GnuPGControllerDialog.cpp
index f1fa87e2..f1fa87e2 100644
--- a/src/ui/dialog/gnupg/GnuPGControllerDialog.cpp
+++ b/src/ui/dialog/controller/GnuPGControllerDialog.cpp
diff --git a/src/ui/dialog/gnupg/GnuPGControllerDialog.h b/src/ui/dialog/controller/GnuPGControllerDialog.h
index 6e8ef797..6e8ef797 100644
--- a/src/ui/dialog/gnupg/GnuPGControllerDialog.h
+++ b/src/ui/dialog/controller/GnuPGControllerDialog.h
diff --git a/src/ui/dialog/controller/ModuleControllerDialog.cpp b/src/ui/dialog/controller/ModuleControllerDialog.cpp
new file mode 100644
index 00000000..db177155
--- /dev/null
+++ b/src/ui/dialog/controller/ModuleControllerDialog.cpp
@@ -0,0 +1,111 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "ModuleControllerDialog.h"
+
+#include "ui_ModuleControllerDialog.h"
+
+//
+#include "core/module/ModuleManager.h"
+#include "ui/widgets/ModuleListView.h"
+
+namespace GpgFrontend::UI {
+
+ModuleControllerDialog::ModuleControllerDialog(QWidget* parent)
+ : QDialog(parent),
+ ui_(std::make_shared<Ui_ModuleControllerDialog>()),
+ model_list_view_(new ModuleListView(this)) {
+ ui_->setupUi(this);
+
+ model_list_view_->setMinimumWidth(250);
+ model_list_view_->setViewMode(QListView::ListMode);
+ model_list_view_->setMovement(QListView::Static);
+
+ ui_->moduleListViewLayout->addWidget(model_list_view_);
+ connect(model_list_view_, &ModuleListView::SignalSelectModule, this,
+ &ModuleControllerDialog::slot_load_module_details);
+
+ connect(ui_->activateButton, &QPushButton::clicked, this, [=]() {
+ auto module_id = model_list_view_->GetCurrentModuleID();
+ if (module_id.isEmpty()) return;
+
+ Module::ModuleManager::GetInstance().ActiveModule(module_id);
+ QTimer::singleShot(1000, [=]() { slot_load_module_details(module_id); });
+ });
+
+ connect(ui_->triggerEventButton, &QPushButton::clicked, this, [=]() {
+ auto event_id =
+ QInputDialog::getText(this, "Please provide an Event ID", "Event ID");
+ Module::TriggerEvent(event_id);
+ });
+}
+
+void ModuleControllerDialog::slot_load_module_details(
+ Module::ModuleIdentifier module_id) {
+ GF_UI_LOG_DEBUG("loading module detailes, module id: {}", module_id);
+
+ auto module = Module::ModuleManager::GetInstance().SearchModule(module_id);
+
+ ui_->moduleIDLabel->setText(module->GetModuleIdentifier());
+
+ QString buffer;
+ QTextStream info(&buffer);
+
+ info << "# BASIC INFO" << Qt::endl << Qt::endl;
+
+ info << tr("Version") << ": " << module->GetModuleVersion() << Qt::endl;
+ info << tr("Hash") << ": " << module->GetModuleHash() << Qt::endl;
+ info << tr("Path") << ": " << module->GetModulePath() << Qt::endl;
+
+ info << tr("Active") << ": "
+ << (Module::ModuleManager::GetInstance().IsModuleActivated(module_id)
+ ? tr("True")
+ : tr("False"))
+ << Qt::endl;
+
+ info << Qt::endl;
+
+ info << "# METADATA" << Qt::endl << Qt::endl;
+
+ for (const auto& metadata : module->GetModuleMetaData()) {
+ info << metadata.first << ": " << metadata.second << "\n";
+ }
+
+ info << Qt::endl;
+
+ info << "# Listening Event" << Qt::endl << Qt::endl;
+
+ auto listening_event_ids =
+ Module::ModuleManager::GetInstance().GetModuleListening(module_id);
+ for (const auto& event_id : listening_event_ids) {
+ info << " - " << event_id << "\n";
+ }
+
+ ui_->moduleInfoTextBrowser->setText(buffer);
+}
+} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/controller/ModuleControllerDialog.h b/src/ui/dialog/controller/ModuleControllerDialog.h
new file mode 100644
index 00000000..59b6cc6b
--- /dev/null
+++ b/src/ui/dialog/controller/ModuleControllerDialog.h
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#pragma once
+
+#include "core/module/Module.h"
+
+class Ui_ModuleControllerDialog;
+
+namespace GpgFrontend::UI {
+
+class ModuleListView;
+
+class ModuleControllerDialog : public QDialog {
+ Q_OBJECT
+ public:
+ /**
+ * @brief Construct a new Module Controller Dialog object
+ *
+ * @param parent
+ */
+ explicit ModuleControllerDialog(QWidget* parent);
+
+ private slots:
+ /**
+ * @brief
+ *
+ */
+ void slot_load_module_details(Module::ModuleIdentifier);
+
+ private:
+ std::shared_ptr<Ui_ModuleControllerDialog> ui_; ///<
+ ModuleListView* model_list_view_;
+};
+
+} // namespace GpgFrontend::UI
diff --git a/src/ui/dialog/help/AboutDialog.cpp b/src/ui/dialog/help/AboutDialog.cpp
index 61b01dfe..e1fa3535 100644
--- a/src/ui/dialog/help/AboutDialog.cpp
+++ b/src/ui/dialog/help/AboutDialog.cpp
@@ -30,8 +30,8 @@
#include <openssl/opensslv.h>
-#include "GpgFrontendBuildInfo.h"
#include "core/module/ModuleManager.h"
+#include "core/utils/BuildInfoUtils.h"
#include "ui/dialog/help/GnupgTab.h"
namespace GpgFrontend::UI {
@@ -84,7 +84,7 @@ InfoTab::InfoTab(QWidget* parent) : QWidget(parent) {
auto text =
"<center><h2>" + qApp->applicationName() + "</h2></center>" +
"<center><b>" + qApp->applicationVersion() + "</b></center>" +
- "<center>" + GIT_VERSION + "</center>" + "<br><center>" +
+ "<center>" + GetProjectBuildGitVersion() + "</center>" + "<br><center>" +
tr("GpgFrontend is an easy-to-use, compact, cross-platform, "
"and installation-free GnuPG Frontend."
"It visualizes most of the common operations of GnuPG."
@@ -99,7 +99,8 @@ InfoTab::InfoTab(QWidget* parent) : QWidget(parent) {
"href=\"mailto:[email protected]\">[email protected]</a>." + "<br><br> " +
tr("Built with Qt") + " " + qVersion() + ", " + OPENSSL_VERSION_TEXT +
" " + tr("and") + " " + "GPGME" + " " + gpgme_version + "<br>" +
- tr("Built at") + " " + BUILD_TIMESTAMP + "</center>";
+ tr("Built at") + " " + QLocale().toString(GetProjectBuildTimestamp()) +
+ "</center>";
auto* layout = new QGridLayout();
auto* pixmap_label = new QLabel();
@@ -140,8 +141,7 @@ TranslatorsTab::TranslatorsTab(QWidget* parent) : QWidget(parent) {
UpdateTab::UpdateTab(QWidget* parent) : QWidget(parent) {
auto* layout = new QGridLayout();
- current_version_ =
- QString("v") + VERSION_MAJOR + "." + VERSION_MINOR + "." + VERSION_PATCH;
+ current_version_ = GetProjectVersion();
auto* tips_label = new QLabel();
tips_label->setText(
diff --git a/src/ui/dialog/import_export/KeyUploadDialog.cpp b/src/ui/dialog/import_export/KeyUploadDialog.cpp
index 0e0dca4d..3fc37c83 100644
--- a/src/ui/dialog/import_export/KeyUploadDialog.cpp
+++ b/src/ui/dialog/import_export/KeyUploadDialog.cpp
@@ -30,10 +30,10 @@
#include <QtNetwork>
-#include "GpgFrontendBuildInfo.h"
#include "core/GpgModel.h"
#include "core/function/gpg/GpgKeyGetter.h"
#include "core/function/gpg/GpgKeyImportExporter.h"
+#include "core/utils/BuildInfoUtils.h"
#include "core/utils/GpgUtils.h"
#include "ui/UserInterfaceUtils.h"
#include "ui/struct/SettingsObject.h"
@@ -116,7 +116,8 @@ void KeyUploadDialog::slot_upload_key_to_server(
data.replace(" ", "+");
QNetworkRequest request(req_url);
- request.setHeader(QNetworkRequest::UserAgentHeader, HTTP_REQUEST_USER_AGENT);
+ request.setHeader(QNetworkRequest::UserAgentHeader,
+ GetHttpRequestUserAgent());
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/x-www-form-urlencoded");
diff --git a/src/ui/main_window/MainWindow.h b/src/ui/main_window/MainWindow.h
index 523c14f0..6847ec4a 100644
--- a/src/ui/main_window/MainWindow.h
+++ b/src/ui/main_window/MainWindow.h
@@ -430,7 +430,7 @@ class MainWindow : public GeneralMainWindow {
QMenu* file_menu_{}; ///< Submenu for file-operations
QMenu* edit_menu_{}; ///< Submenu for text-operations
QMenu* crypt_menu_{}; ///< Submenu for crypt-operations
- QMenu* gpg_menu_{}; ///< Submenu for help-operations
+ QMenu* advance_menu_{}; ///< Submenu for help-operations
QMenu* help_menu_{}; ///< Submenu for help-operations
QMenu* key_menu_{}; ///< Submenu for key-operations
QMenu* view_menu_{}; ///< Submenu for view operations
@@ -473,6 +473,7 @@ class MainWindow : public GeneralMainWindow {
///< breaks
QAction* gnupg_controller_open_act_{}; ///<
+ QAction* module_controller_open_act_{}; ///<
QAction* clean_gpg_password_cache_act_{}; ///<
QAction* reload_components_act_{}; ///<
QAction* restart_components_act_{}; ///<
diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp
index 8b6fc74c..3d321264 100644
--- a/src/ui/main_window/MainWindowUI.cpp
+++ b/src/ui/main_window/MainWindowUI.cpp
@@ -30,8 +30,9 @@
#include "core/function/GlobalSettingStation.h"
#include "core/function/gpg/GpgAdvancedOperator.h"
#include "core/module/ModuleManager.h"
+#include "dialog/controller/ModuleControllerDialog.h"
#include "ui/UserInterfaceUtils.h"
-#include "ui/dialog/gnupg/GnuPGControllerDialog.h"
+#include "ui/dialog/controller/GnuPGControllerDialog.h"
#include "ui/dialog/help/AboutDialog.h"
#include "ui/widgets/KeyList.h"
#include "ui/widgets/TextEdit.h"
@@ -404,6 +405,12 @@ void MainWindow::create_actions() {
connect(gnupg_controller_open_act_, &QAction::triggered, this,
[this]() { (new GnuPGControllerDialog(this))->exec(); });
+ module_controller_open_act_ = new QAction(tr("Open Module Controller"), this);
+ module_controller_open_act_->setIcon(QIcon(":/icons/configure.png"));
+ module_controller_open_act_->setToolTip(tr("Open Module Controller Dialog"));
+ connect(module_controller_open_act_, &QAction::triggered, this,
+ [this]() { (new ModuleControllerDialog(this))->exec(); });
+
/*
* About Menu
*/
@@ -587,13 +594,13 @@ void MainWindow::create_menus() {
import_key_menu_->addAction(import_key_from_key_server_act_);
key_menu_->addAction(open_key_management_act_);
- gpg_menu_ = menuBar()->addMenu(tr("GnuPG"));
- gpg_menu_->addAction(clean_gpg_password_cache_act_);
- gpg_menu_->addSeparator();
- gpg_menu_->addAction(reload_components_act_);
- gpg_menu_->addAction(restart_components_act_);
- gpg_menu_->addSeparator();
- gpg_menu_->addAction(gnupg_controller_open_act_);
+ advance_menu_ = menuBar()->addMenu(tr("Advance"));
+ advance_menu_->addAction(clean_gpg_password_cache_act_);
+ advance_menu_->addAction(reload_components_act_);
+ advance_menu_->addAction(restart_components_act_);
+ advance_menu_->addSeparator();
+ advance_menu_->addAction(gnupg_controller_open_act_);
+ advance_menu_->addAction(module_controller_open_act_);
steganography_menu_ = menuBar()->addMenu(tr("Steganography"));
steganography_menu_->addAction(cut_pgp_header_act_);
diff --git a/src/ui/thread/KeyServerImportTask.cpp b/src/ui/thread/KeyServerImportTask.cpp
index c908f5d7..ed8b7646 100644
--- a/src/ui/thread/KeyServerImportTask.cpp
+++ b/src/ui/thread/KeyServerImportTask.cpp
@@ -28,8 +28,8 @@
#include "ui/thread/KeyServerImportTask.h"
-#include "GpgFrontendBuildInfo.h"
#include "core/function/gpg/GpgKeyImportExporter.h"
+#include "core/utils/BuildInfoUtils.h"
#include "ui/struct/SettingsObject.h"
#include "ui/struct/settings/KeyServerSO.h"
@@ -57,7 +57,7 @@ auto GpgFrontend::UI::KeyServerImportTask::Run() -> int {
auto request = QNetworkRequest(req_url);
request.setHeader(QNetworkRequest::UserAgentHeader,
- HTTP_REQUEST_USER_AGENT);
+ GetHttpRequestUserAgent());
reply_ = manager_->get(request);
connect(reply_, &QNetworkReply::finished, this,
diff --git a/src/ui/thread/KeyServerSearchTask.cpp b/src/ui/thread/KeyServerSearchTask.cpp
index eb650c4b..828ce5ac 100644
--- a/src/ui/thread/KeyServerSearchTask.cpp
+++ b/src/ui/thread/KeyServerSearchTask.cpp
@@ -28,7 +28,7 @@
#include "ui/thread/KeyServerSearchTask.h"
-#include "GpgFrontendBuildInfo.h"
+#include "core/utils/BuildInfoUtils.h"
GpgFrontend::UI::KeyServerSearchTask::KeyServerSearchTask(QString keyserver_url,
QString search_string)
@@ -45,7 +45,8 @@ auto GpgFrontend::UI::KeyServerSearchTask::Run() -> int {
"&op=index&options=mr";
auto request = QNetworkRequest(url_from_remote);
- request.setHeader(QNetworkRequest::UserAgentHeader, HTTP_REQUEST_USER_AGENT);
+ request.setHeader(QNetworkRequest::UserAgentHeader,
+ GetHttpRequestUserAgent());
reply_ = manager_->get(request);
connect(reply_, &QNetworkReply::finished, this,
diff --git a/src/ui/thread/ListedKeyServerTestTask.cpp b/src/ui/thread/ListedKeyServerTestTask.cpp
index 15ea959f..5f7e2dca 100644
--- a/src/ui/thread/ListedKeyServerTestTask.cpp
+++ b/src/ui/thread/ListedKeyServerTestTask.cpp
@@ -29,9 +29,8 @@
#include "ListedKeyServerTestTask.h"
#include <QtNetwork>
-#include <vector>
-#include "GpgFrontendBuildInfo.h"
+#include "core/utils/BuildInfoUtils.h"
GpgFrontend::UI::ListedKeyServerTestTask::ListedKeyServerTestTask(
QStringList urls, int timeout, QWidget* /*parent*/)
@@ -53,7 +52,7 @@ auto GpgFrontend::UI::ListedKeyServerTestTask::Run() -> int {
auto request = QNetworkRequest(key_url);
request.setHeader(QNetworkRequest::UserAgentHeader,
- HTTP_REQUEST_USER_AGENT);
+ GetHttpRequestUserAgent());
auto* network_reply = network_manager_->get(request);
auto* timer = new QTimer(this);
diff --git a/src/ui/thread/ProxyConnectionTestTask.cpp b/src/ui/thread/ProxyConnectionTestTask.cpp
index 003205e5..c1d2f3e6 100644
--- a/src/ui/thread/ProxyConnectionTestTask.cpp
+++ b/src/ui/thread/ProxyConnectionTestTask.cpp
@@ -30,7 +30,7 @@
#include <QtNetwork>
-#include "GpgFrontendBuildInfo.h"
+#include "core/utils/BuildInfoUtils.h"
GpgFrontend::UI::ProxyConnectionTestTask::ProxyConnectionTestTask(QString url,
int timeout)
@@ -43,7 +43,8 @@ GpgFrontend::UI::ProxyConnectionTestTask::ProxyConnectionTestTask(QString url,
auto GpgFrontend::UI::ProxyConnectionTestTask::Run() -> int {
auto request = QNetworkRequest(url_);
- request.setHeader(QNetworkRequest::UserAgentHeader, HTTP_REQUEST_USER_AGENT);
+ request.setHeader(QNetworkRequest::UserAgentHeader,
+ GetHttpRequestUserAgent());
auto* network_reply = network_manager_->get(request);
auto* timer = new QTimer(this);
diff --git a/src/ui/widgets/ModuleListView.cpp b/src/ui/widgets/ModuleListView.cpp
new file mode 100644
index 00000000..05e4c021
--- /dev/null
+++ b/src/ui/widgets/ModuleListView.cpp
@@ -0,0 +1,63 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#include "ModuleListView.h"
+
+#include "core/module/ModuleManager.h"
+
+namespace GpgFrontend::UI {
+
+ModuleListView::ModuleListView(QWidget *parent)
+ : QListView(parent), model_(new QStringListModel(this)) {
+ setModel(model_);
+
+ load_module_informations();
+}
+
+void ModuleListView::currentChanged(const QModelIndex &current,
+ const QModelIndex &previous) {
+ QListView::currentChanged(current, previous);
+ emit this->SignalSelectModule(model_->data(current).toString());
+}
+
+void ModuleListView::load_module_informations() {
+ auto module_ids =
+ Module::ModuleManager::GetInstance().ListAllRegisteredModuleID();
+
+ QStringList model_data;
+ for (const auto &module_id : module_ids) {
+ model_data.append(module_id);
+ }
+
+ model_->setStringList(model_data);
+}
+
+auto ModuleListView::GetCurrentModuleID() -> Module::ModuleIdentifier {
+ return model_->data(currentIndex()).toString();
+}
+}; // namespace GpgFrontend::UI
diff --git a/src/ui/widgets/ModuleListView.h b/src/ui/widgets/ModuleListView.h
new file mode 100644
index 00000000..ba569a6f
--- /dev/null
+++ b/src/ui/widgets/ModuleListView.h
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2021 Saturneric <[email protected]>
+ *
+ * This file is part of GpgFrontend.
+ *
+ * GpgFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgFrontend is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from
+ * the gpg4usb project, which is under GPL-3.0-or-later.
+ *
+ * All the source code of GpgFrontend was modified and released by
+ * Saturneric <[email protected]> starting on May 12, 2021.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#pragma once
+
+#include "core/module/Module.h"
+
+namespace GpgFrontend::UI {
+class ModuleListView : public QListView {
+ Q_OBJECT
+ public:
+ explicit ModuleListView(QWidget *parent);
+
+ auto GetCurrentModuleID() -> Module::ModuleIdentifier;
+
+ signals:
+ void SignalSelectModule(Module::ModuleIdentifier);
+
+ protected:
+ void currentChanged(const QModelIndex &current,
+ const QModelIndex &previous) override;
+
+ private:
+ QStringListModel *model_;
+
+ void load_module_informations();
+};
+}; // namespace GpgFrontend::UI \ No newline at end of file
diff --git a/ui/ModuleControllerDialog.ui b/ui/ModuleControllerDialog.ui
new file mode 100644
index 00000000..7a81d2ca
--- /dev/null
+++ b/ui/ModuleControllerDialog.ui
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ModuleControllerDialog</class>
+ <widget class="QDialog" name="ModuleControllerDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>829</width>
+ <height>660</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Module Controller</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="registeredModuleTab">
+ <attribute name="title">
+ <string>Registered Modules</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <layout class="QHBoxLayout" name="moduleControllerLayout">
+ <item>
+ <layout class="QVBoxLayout" name="moduleListViewLayout"/>
+ </item>
+ <item>
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Module ID:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="moduleIDLabel">
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Module Informations</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextBrowser" name="moduleInfoTextBrowser">
+ <property name="lineWrapMode">
+ <enum>QTextEdit::NoWrap</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="activateButton">
+ <property name="text">
+ <string>Activate</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="deactivateButton">
+ <property name="text">
+ <string>Deactivate</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>Debugger</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_8">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_7">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_10">
+ <item>
+ <widget class="QPushButton" name="triggerEventButton">
+ <property name="text">
+ <string>Trigger Event</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_11">
+ <item>
+ <widget class="QPushButton" name="pushButton_4">
+ <property name="text">
+ <string>PushButton</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>