feat(sdk): add status bar widget wrapper and origin query bindings (#356)

register_status_widget(): pure Python wrapper that adds a live widget
to the main window status bar with context menu discoverability.

Origin query bindings (kcsdk.list_origins, active_origin, get_origin,
set_active_origin): thin C++ forwarding to OriginManager with Python
wrappers using kcsdk-first routing.

IOriginProvider and IStatusBarProvider C++ interfaces dropped — existing
FileOrigin stack is already complete, and status bar widgets don't need
C++ lifecycle management.
This commit is contained in:
forbes
2026-03-01 14:13:31 -06:00
parent 747c458e23
commit a6a6cefc16
5 changed files with 276 additions and 16 deletions

View File

@@ -32,6 +32,9 @@
#include <Gui/SDK/ThemeEngine.h>
#include <Gui/SDK/Types.h>
#include <Gui/FileOrigin.h>
#include <Gui/OriginManager.h>
#include "PyIMenuProvider.h"
#include "PyIPanelProvider.h"
#include "PyIToolbarProvider.h"
@@ -47,6 +50,23 @@ using namespace KCSDK;
namespace
{
/// Build a Python dict from a FileOrigin* (same keys as ApplicationPy).
py::dict originToDict(Gui::FileOrigin* origin)
{
py::dict d;
d["id"] = origin->id();
d["name"] = origin->name();
d["nickname"] = origin->nickname();
d["type"] = static_cast<int>(origin->type());
d["tracksExternally"] = origin->tracksExternally();
d["requiresAuthentication"] = origin->requiresAuthentication();
d["supportsRevisions"] = origin->supportsRevisions();
d["supportsBOM"] = origin->supportsBOM();
d["supportsPartNumbers"] = origin->supportsPartNumbers();
d["connectionState"] = static_cast<int>(origin->connectionState());
return d;
}
/// Convert a ContextSnapshot to a Python dict (same keys as ApplicationPy).
py::dict contextSnapshotToDict(const ContextSnapshot& snap)
{
@@ -369,4 +389,53 @@ PYBIND11_MODULE(kcsdk, m)
},
py::arg("name") = "catppuccin-mocha",
"Load a named palette. Returns True on success.");
// -- Origin query API ---------------------------------------------------
m.def("list_origins",
[]() {
auto* mgr = Gui::OriginManager::instance();
return mgr ? mgr->originIds() : std::vector<std::string>{};
},
"Return IDs of all registered origins.");
m.def("active_origin",
[]() -> py::object {
auto* mgr = Gui::OriginManager::instance();
if (!mgr) {
return py::none();
}
Gui::FileOrigin* origin = mgr->currentOrigin();
if (!origin) {
return py::none();
}
return originToDict(origin);
},
"Return the active origin as a dict, or None.");
m.def("set_active_origin",
[](const std::string& id) {
auto* mgr = Gui::OriginManager::instance();
if (!mgr) {
return false;
}
return mgr->setCurrentOrigin(id);
},
py::arg("id"),
"Set the active origin by ID. Returns True on success.");
m.def("get_origin",
[](const std::string& id) -> py::object {
auto* mgr = Gui::OriginManager::instance();
if (!mgr) {
return py::none();
}
Gui::FileOrigin* origin = mgr->getOrigin(id);
if (!origin) {
return py::none();
}
return originToDict(origin);
},
py::arg("id"),
"Get origin info by ID as a dict, or None if not found.");
}