aboutsummaryrefslogtreecommitdiffstats
path: root/src/m_pgp_inspect
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2026-09-23 23:07:07 +0200
committersaturneric <[email protected]>2026-09-23 23:07:07 +0200
commitd06e0d6f50afbb8254fa228e03befcaac4511ad2 (patch)
tree0f9a1a8139b9f7c8fec5552484dcc69a99c0e760 /src/m_pgp_inspect
parentfeat(gpg-info): expose GnuPG details through scripted UI (diff)
downloadmodules-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.txt3
-rw-r--r--src/m_pgp_inspect/PGPInspectDialog.cpp12
-rw-r--r--src/m_pgp_inspect/PGPInspectDialog.h4
-rw-r--r--src/m_pgp_inspect/PGPInspectModule.cpp115
-rw-r--r--src/m_pgp_inspect/module.json5
-rw-r--r--src/m_pgp_inspect/ui/main.lua16
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 }