diff options
| author | saturneric <[email protected]> | 2026-09-23 23:07:07 +0200 |
|---|---|---|
| committer | saturneric <[email protected]> | 2026-09-23 23:07:07 +0200 |
| commit | d06e0d6f50afbb8254fa228e03befcaac4511ad2 (patch) | |
| tree | 0f9a1a8139b9f7c8fec5552484dcc69a99c0e760 /src/m_pgp_inspect | |
| parent | feat(gpg-info): expose GnuPG details through scripted UI (diff) | |
| download | modules-d06e0d6f50afbb8254fa228e03befcaac4511ad2.tar.gz modules-d06e0d6f50afbb8254fa228e03befcaac4511ad2.zip | |
feat(ui): migrate modules to command mounts
- replace legacy menu and settings events with typed commands
- add Lua scripts for module UI placement and native widget mounts
- migrate key server, inspector, and update dialogs to host-owned views
- route module settings through storage capabilities
- update lifecycle hooks, event manifests, and widget interfaces
- fix key server task cleanup and theme color resolution
Diffstat (limited to 'src/m_pgp_inspect')
| -rw-r--r-- | src/m_pgp_inspect/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/m_pgp_inspect/PGPInspectDialog.cpp | 12 | ||||
| -rw-r--r-- | src/m_pgp_inspect/PGPInspectDialog.h | 4 | ||||
| -rw-r--r-- | src/m_pgp_inspect/PGPInspectModule.cpp | 115 | ||||
| -rw-r--r-- | src/m_pgp_inspect/module.json | 5 | ||||
| -rw-r--r-- | src/m_pgp_inspect/ui/main.lua | 16 |
6 files changed, 81 insertions, 74 deletions
diff --git a/src/m_pgp_inspect/CMakeLists.txt b/src/m_pgp_inspect/CMakeLists.txt index 705ac23..e052bf4 100644 --- a/src/m_pgp_inspect/CMakeLists.txt +++ b/src/m_pgp_inspect/CMakeLists.txt @@ -34,7 +34,8 @@ gf_add_module( QT Core Widgets SOURCES PGPInspectModule.cpp PGPInspectModel.cpp - PGPInspectDialog.cpp) + PGPInspectDialog.cpp + LUA_SCRIPTS ui/main.lua) if(GPGFRONTEND_MODULES_BUILD_TESTS) add_subdirectory(test) diff --git a/src/m_pgp_inspect/PGPInspectDialog.cpp b/src/m_pgp_inspect/PGPInspectDialog.cpp index e3bde03..9dcab4e 100644 --- a/src/m_pgp_inspect/PGPInspectDialog.cpp +++ b/src/m_pgp_inspect/PGPInspectDialog.cpp @@ -170,12 +170,10 @@ void PGPInspectDialog::render_document() { if (block.has_armor && block.armor.crc24 == QLatin1String("mismatch")) { item->setForeground( - kLabelColumn, QBrush(QColor(GFUIThemeColor( - GFModuleSdkContext(), GF_UI_COLOR_DANGER, this)))); + kLabelColumn, QBrush(QColor(GFUIThemeColorForRole(GFModuleSdkContext(), GF_UI_COLOR_DANGER)))); } else if (!block.error.isEmpty()) { item->setForeground( - kLabelColumn, QBrush(QColor(GFUIThemeColor( - GFModuleSdkContext(), GF_UI_COLOR_WARNING, this)))); + kLabelColumn, QBrush(QColor(GFUIThemeColorForRole(GFModuleSdkContext(), GF_UI_COLOR_WARNING)))); } add_packets(item, block.packets); @@ -205,8 +203,7 @@ void PGPInspectDialog::add_packets(QTreeWidgetItem* parent, if (packet.Malformed()) { item->setForeground( - kLabelColumn, QBrush(QColor(GFUIThemeColor( - GFModuleSdkContext(), GF_UI_COLOR_WARNING, this)))); + kLabelColumn, QBrush(QColor(GFUIThemeColorForRole(GFModuleSdkContext(), GF_UI_COLOR_WARNING)))); } auto fields = packet.fields; @@ -228,8 +225,7 @@ void PGPInspectDialog::add_fields(QTreeWidgetItem* parent, row->setText(kValueColumn, field.value); row->setForeground( kLabelColumn, - QBrush(QColor(GFUIThemeColor(GFModuleSdkContext(), - GF_UI_COLOR_MUTED_TEXT, this)))); + QBrush(QColor(GFUIThemeColorForRole(GFModuleSdkContext(), GF_UI_COLOR_MUTED_TEXT)))); } } diff --git a/src/m_pgp_inspect/PGPInspectDialog.h b/src/m_pgp_inspect/PGPInspectDialog.h index d84b7c9..93e4224 100644 --- a/src/m_pgp_inspect/PGPInspectDialog.h +++ b/src/m_pgp_inspect/PGPInspectDialog.h @@ -29,6 +29,8 @@ #pragma once #include <QByteArray> +#include <GFModule.h> + #include <QDialog> #include "PGPInspectModel.h" @@ -56,7 +58,7 @@ auto PGPInspectBytes(const QByteArray& data) -> PGPInspectDocument; * Every rule about what the bytes mean lives in PGPInspectModel.h and, below * that, in the Rust packet walk. */ -class PGPInspectDialog : public QDialog { +class PGPInspectDialog : public QDialog, public gf::ui::DialogWidget { Q_OBJECT public: diff --git a/src/m_pgp_inspect/PGPInspectModule.cpp b/src/m_pgp_inspect/PGPInspectModule.cpp index 2130cda..5753b9a 100644 --- a/src/m_pgp_inspect/PGPInspectModule.cpp +++ b/src/m_pgp_inspect/PGPInspectModule.cpp @@ -27,12 +27,7 @@ */ #include <GFModule.h> - -#include <QAction> -#include <QApplication> -#include <QMainWindow> -#include <QMenu> -#include <QPointer> +#include <GFSDKHostCommands.hpp> #include "GFModuleIdentity.h" #include "PGPInspectDialog.h" @@ -52,77 +47,73 @@ auto InspectCurrentTab() -> PGPInspectDocument { return PGPInspectBytes(bytes); } -void RaiseInspectDialog(QWidget *parent) { - const auto bytes = PGPInspectCurrentTabBytes(); - auto *dialog = - new PGPInspectDialog(PGPInspectBytes(bytes), bytes.size(), parent); - dialog->setModal(false); - dialog->show(); -} +/** + * @brief The module's one action: show the current tab's packet structure. + * + * Enabled only when the tab holds something to show -- decided when the + * menu opens, because what the current tab holds changes constantly and an + * entry enabled over plain text promises a window with nothing in it. + */ +struct OpenInspector { + static constexpr gf::cmd::Meta kMeta{ + GF_MODULE_ID ".open_inspector", + GC_TR("Open OpenPGP Structure Inspector"), + GC_TR("Show the packet structure of the current tab"), "", 0, + gf::cmd::kNeedsGuiThread}; + using Args = gf::cmd::Unit; + using Result = gf::cmd::Unit; -} // namespace + static auto State(const gf::cmd::CommandContext& /*ctx*/) -> uint32_t { + return PGPInspectHasStructure(InspectCurrentTab()) + ? GF_CMD_STATE_ENABLED | GF_CMD_STATE_VISIBLE + : GF_CMD_STATE_VISIBLE; + } +}; -auto OnActivate() -> GFResult { - // Nothing to register with the host: the module owns no settings page, no - // tab view and no metatype. Its whole surface is one menu action, added - // when the menu is mounted. - return GFResult::Ok(); +auto DoOpenInspector(const gf::cmd::CommandContext& /*ctx*/, + const gf::cmd::Unit& /*args*/) + -> gf::cmd::Outcome<gf::cmd::Unit> { + // The dialog is the module's mount; the Host owns its frame and opens it. + Commands().Invoke<gf::cmd::host::ViewOpen>( + {gf::cmd::ViewRef{QStringLiteral(GF_MODULE_ID ".inspector")}}); + return gf::cmd::Outcome<gf::cmd::Unit>::Success({}); } -auto OnMainWindowMenuMounted(const GFEvent &event) -> GFEventResult { - QMainWindow *main_window = nullptr; - if (auto r = event.RequireGui("main_window", main_window); !r.ok) return r; - - QMenu *advance_menu = nullptr; - if (auto r = event.RequireGui("advance_menu", advance_menu); !r.ok) return r; - - LOG_DEBUG("adding openpgp structure inspector to the advanced menu"); - - QMetaObject::invokeMethod( - QApplication::instance(), - [=]() -> void { - auto *action = - new QAction(QCoreApplication::translate( - "GTrC", "Open OpenPGP Structure Inspector"), - nullptr); - action->setToolTip(QCoreApplication::translate( - "GTrC", "Show the packet structure of the current tab")); - QObject::connect(action, &QAction::triggered, main_window, - [=]() { RaiseInspectDialog(main_window); }); - advance_menu->addAction(action); - - // Decided when the menu opens rather than once at mount time: what - // the current tab holds changes constantly, and an entry that is - // enabled over plain text promises a window that would have nothing - // in it. - QPointer<QAction> guarded(action); - QObject::connect(advance_menu, &QMenu::aboutToShow, action, [guarded] { - if (guarded.isNull()) return; - guarded->setEnabled(PGPInspectHasStructure(InspectCurrentTab())); - }); - }, - Qt::BlockingQueuedConnection); +} // namespace - return GFEventResult::Ok(); +auto OnActivate() -> GFResult { + // The inspector, built from the current tab each time it is opened. Where + // it is offered is ui/main.lua's business. + const bool ok = gf::ui::RegisterNativeWidget<PGPInspectDialog>( + "inspector", + {GC_TR("OpenPGP Structure"), "", "", "", ":/icons/help.png", 820, 620}, + [](const QCborMap& /*args*/) { + const auto bytes = PGPInspectCurrentTabBytes(); + return new PGPInspectDialog(PGPInspectBytes(bytes), bytes.size()); + }); + return ok ? GFResult::Ok() + : GFResult::Fail("the inspector widget was not registered"); } -// 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[] = { - {"MAINWINDOW_MENU_MOUNTED", &OnMainWindowMenuMounted}, +// The module's whole framework surface: 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. +const std::array<gf::cmd::Binding, 1> kCommands = { + gf::cmd::Bind<OpenInspector, &DoOpenInspector>(), }; -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 nullptr, - kEvents, - std::size(kEvents), + nullptr, // no events + 0, + kCommands.data(), + kCommands.size(), }; extern "C" GF_MODULE_EXPORT auto GFModuleGetApi(uint32_t abi) diff --git a/src/m_pgp_inspect/module.json b/src/m_pgp_inspect/module.json index 8a52688..9cb6754 100644 --- a/src/m_pgp_inspect/module.json +++ b/src/m_pgp_inspect/module.json @@ -11,8 +11,9 @@ "ui", "ui.custom" ], - "events": [ - "MAINWINDOW_MENU_MOUNTED" + "events": [], + "commands": [ + "com.bktus.gpgfrontend.module.pgp_inspect.open_inspector" ], "translation_context": "ModulePGPInspect" } diff --git a/src/m_pgp_inspect/ui/main.lua b/src/m_pgp_inspect/ui/main.lua new file mode 100644 index 0000000..e85975d --- /dev/null +++ b/src/m_pgp_inspect/ui/main.lua @@ -0,0 +1,16 @@ +-- OpenPGP structure inspector: where it is offered. +-- +-- What the entry does, what it is called and when it is enabled all belong +-- to the module's command; this file only places it. The dialog is the +-- module's own widget, in a frame the Host owns. + +local open = commands.get("com.bktus.gpgfrontend.module.pgp_inspect.open_inspector") + +ui.mount { + id = "inspector", + anchor = ui.anchor.dialog {}, + widget = native.widget("inspector"), +} + +ui.action { id = "menu", anchor = ui.anchor("main.menu.advanced"), command = open } +ui.action { id = "context", anchor = ui.anchor("editor.context"), command = open } |
