From 925809823638085caf5aa47022a2f64e3c21b33b Mon Sep 17 00:00:00 2001 From: saturneric Date: Wed, 23 Sep 2026 23:04:17 +0200 Subject: feat(gpg-info): expose GnuPG details through scripted UI - register a native GnuPG information widget with the host - add a command for opening the information dialog - mount the Help menu action through the Lua UI script - remove legacy menu and dialog event handling - declare the command and Lua script in module metadata --- src/m_gpg_info/CMakeLists.txt | 3 +- src/m_gpg_info/GnuPGInfoGatheringModule.cpp | 114 ++++++++++++---------------- src/m_gpg_info/GnupgTab.cpp | 2 - src/m_gpg_info/module.json | 5 +- src/m_gpg_info/ui/main.lua | 13 ++++ 5 files changed, 67 insertions(+), 70 deletions(-) create mode 100644 src/m_gpg_info/ui/main.lua (limited to 'src') diff --git a/src/m_gpg_info/CMakeLists.txt b/src/m_gpg_info/CMakeLists.txt index 3967bbb..c89ccfb 100644 --- a/src/m_gpg_info/CMakeLists.txt +++ b/src/m_gpg_info/CMakeLists.txt @@ -27,4 +27,5 @@ # capabilities and translation context -- lives in module.json beside this file. gf_add_module( NAME gpg_info - QT Core Widgets Concurrent) + QT Core Widgets Concurrent + LUA_SCRIPTS ui/main.lua) diff --git a/src/m_gpg_info/GnuPGInfoGatheringModule.cpp b/src/m_gpg_info/GnuPGInfoGatheringModule.cpp index 72998c1..2405910 100644 --- a/src/m_gpg_info/GnuPGInfoGatheringModule.cpp +++ b/src/m_gpg_info/GnuPGInfoGatheringModule.cpp @@ -32,15 +32,11 @@ #include // qt -#include #include #include -#include #include #include #include -#include -#include #include #include @@ -49,6 +45,7 @@ #include "GFModule.h" #include "GFModuleIdentity.h" +#include "GFSDKHostCommands.hpp" #include "GnupgTab.h" #include "GpgInfo.h" @@ -67,40 +64,51 @@ extern auto StartStartGatheringGnuPGComponentsInfo( const QString &gpgme_version, const QString &gpgconf_path, const QString &default_home_path) -> int; -extern auto GnupgTabFactory(void *id) -> void *; - using Context = struct { QString gpgme_version; QString gpgconf_path; GpgComponentInfo component_info; }; -auto OnActivate() -> GFResult { - LOG_INFO("gnupg info gathering module registering"); - return GFResult::Ok(); -} - namespace { -auto RaiseUpdateDialog(QWidget *parent) -> QDialog * { - auto *dialog = new QDialog(parent); - dialog->setWindowTitle(QCoreApplication::translate("GTrC", "GnuPG")); - dialog->setModal(true); - dialog->setAttribute(Qt::WA_DeleteOnClose); - auto *layout = new QVBoxLayout(); - auto *update_tab = new GnupgTab(dialog); - layout->addWidget(update_tab); - dialog->setLayout(layout); - dialog->resize(500, 600); - dialog->show(); - return dialog; +/// What GnuPG is installed and how it is configured, in a dialog frame the +/// Host owns. +class GnupgInfoWidget : public QWidget, public gf::ui::DialogWidget { + public: + GnupgInfoWidget() { + auto* layout = new QVBoxLayout(this); + layout->addWidget(new GnupgTab(this)); + } +}; + +/// Help > GnuPG. Its title and whereabouts are the command's and the +/// script's; it only opens the module's own dialog. +struct ShowGnupgInfo { + static constexpr gf::cmd::Meta kMeta{ + GF_MODULE_ID ".show_gnupg_info", GC_TR("GnuPG"), + GC_TR("Information about GnuPG"), "", 0, gf::cmd::kNeedsGuiThread}; + using Args = gf::cmd::Unit; + using Result = gf::cmd::Unit; +}; + +auto DoShowGnupgInfo(const gf::cmd::CommandContext& /*ctx*/, + const gf::cmd::Unit& /*args*/) + -> gf::cmd::Outcome { + Commands().Invoke( + {gf::cmd::ViewRef{QStringLiteral(GF_MODULE_ID ".info")}}); + return gf::cmd::Outcome::Success({}); } + } // namespace -auto OnApplicationLoaded(const GFEvent & /*event*/) -> GFEventResult { - // Subscribed but with nothing to do: the module wants the host to consider - // it a listener of this event, and answering is all that is required. - return GFEventResult::Ok(); +auto OnActivate() -> GFResult { + LOG_INFO("gnupg info gathering module registering"); + const bool ok = gf::ui::RegisterNativeWidget( + "info", {GC_TR("GnuPG"), "", "", "", ":/icons/key.png", 500, 600}, + [](const QCborMap& /*args*/) { return new GnupgInfoWidget(); }); + return ok ? GFResult::Ok() + : GFResult::Fail("the GnuPG information widget was not registered"); } auto OnRequestGatheringAllGnuPGInfo(const GFEvent & /*event*/) @@ -113,53 +121,29 @@ auto OnUnload() -> void { LOG_INFO("gnupg info gathering module unregistering"); } -auto OnMainWindowMenuMounted(const GFEvent &event) -> GFEventResult { - QMainWindow *main_window = nullptr; - if (auto r = event.RequireGui("main_window", main_window); !r.ok) return r; - - QMenu *help_menu = nullptr; - if (auto r = event.RequireGui("help_menu", help_menu); !r.ok) return r; - - LOG_DEBUG("adding check update action to help menu"); - - QMetaObject::invokeMethod( - QApplication::instance(), - [&]() -> void { - QWidget *parent = - qobject_cast(static_cast(main_window)); - auto *action = - new QAction(QCoreApplication::translate("GTrC", "GnuPG"), nullptr); - action->setToolTip( - QCoreApplication::translate("GTrC", "Information about GnuPG")); - action->setIcon(QIcon(":/icons/key.png")); - QObject::connect(action, &QAction::triggered, parent, - [=]() { RaiseUpdateDialog(parent); }); - help_menu->addAction(action); - }, - Qt::BlockingQueuedConnection); - - return GFEventResult::Ok(); -} - -// The module's whole framework surface: which events it handles, what runs at -// each lifecycle point, and one forwarder to the runtime that implements all -// of it. Everything above is business logic. -constexpr GFEventBinding kEvents[] = { - {"APPLICATION_LOADED", &OnApplicationLoaded}, - {"MAINWINDOW_MENU_MOUNTED", &OnMainWindowMenuMounted}, +// The module's whole framework surface: which events it handles, what it +// provides, what runs at each lifecycle point, and one forwarder to the +// runtime that implements all of it. Everything above is business logic. +constexpr std::array kEvents = {{ {"REQUEST_GATHERING_ALL_GNUPG_INFO", &OnRequestGatheringAllGnuPGInfo}, +}}; + +const std::array kCommands = { + gf::cmd::Bind(), }; -constexpr GFModuleHooks kHooks = { +const GFModuleHooks kHooks = { sizeof(GFModuleHooks), GF_MODULE_ID, GF_MODULE_VERSION, GF_MODULE_TRANSLATION_CONTEXT, &OnActivate, - nullptr, // nothing registered with the host, so nothing to undo + nullptr, // the Host withdraws the command, widget and script itself &OnUnload, - kEvents, - std::size(kEvents), + kEvents.data(), + kEvents.size(), + kCommands.data(), + kCommands.size(), }; extern "C" GF_MODULE_EXPORT auto GFModuleGetApi(uint32_t abi) diff --git a/src/m_gpg_info/GnupgTab.cpp b/src/m_gpg_info/GnupgTab.cpp index 4581480..a340551 100644 --- a/src/m_gpg_info/GnupgTab.cpp +++ b/src/m_gpg_info/GnupgTab.cpp @@ -335,5 +335,3 @@ void GnupgTab::showEvent(QShowEvent* event) { slot_gather_gnupg_info(); } } - -auto GnupgTabFactory(void*) -> void* { return new GnupgTab(); } \ No newline at end of file diff --git a/src/m_gpg_info/module.json b/src/m_gpg_info/module.json index db9257e..0f3efd4 100644 --- a/src/m_gpg_info/module.json +++ b/src/m_gpg_info/module.json @@ -13,9 +13,10 @@ "ui.custom" ], "events": [ - "APPLICATION_LOADED", - "MAINWINDOW_MENU_MOUNTED", "REQUEST_GATHERING_ALL_GNUPG_INFO" ], + "commands": [ + "com.bktus.gpgfrontend.module.gnupg_info_gathering.show_gnupg_info" + ], "translation_context": "ModuleGnuPGInfoGathering" } diff --git a/src/m_gpg_info/ui/main.lua b/src/m_gpg_info/ui/main.lua new file mode 100644 index 0000000..c5629ed --- /dev/null +++ b/src/m_gpg_info/ui/main.lua @@ -0,0 +1,13 @@ +-- GnuPG information: where it is offered. The dialog is the module's own +-- widget, in a frame the Host owns; the entry's title is the command's. + +local show = commands.get("com.bktus.gpgfrontend.module.gnupg_info_gathering.show_gnupg_info") + +ui.mount { id = "info", anchor = ui.anchor.dialog {}, widget = native.widget("info") } + +ui.action { + id = "help", + anchor = ui.anchor("main.menu.help"), + command = show, + icon = ":/icons/key.png", +} -- cgit