diff --git a/src/Base/PyObjectBase.h b/src/Base/PyObjectBase.h index 6c52c67d86..58efd7afed 100644 --- a/src/Base/PyObjectBase.h +++ b/src/Base/PyObjectBase.h @@ -527,6 +527,44 @@ inline void PyTypeCheck(PyObject** ptr, int (*method)(PyObject*), const char* ms } } +/** + * @brief Registers a C++ enum as a Python IntEnum in the specified module. + * + * This function dynamically creates a Python `IntEnum` class using the provided + * C++ enum entries and registers it under the given name within the specified + * Python module. It allows seamless integration of C++ enums into Python, making + * them accessible and usable in Python scripts. + * + * @tparam T The type of the enum values. + * @param module The Python module where the enum will be registered. + * @param name The name to be given to the Python IntEnum. + * @param entries A map of string keys to enum values, representing the enum definition. + */ +template +void PyRegisterEnum(PyObject* module, const char* name, const std::map& entries) +{ + PyObject* pyEnumModule = PyImport_ImportModule("enum"); + if (!pyEnumModule) { + return; + } + + PyObject* pyConstantsDict = PyDict_New(); + + // Populate dictionary + for (const auto& [key, value] : entries) { + PyDict_SetItemString(pyConstantsDict, key, PyLong_FromLong(static_cast(value))); + } + + PyObject* pyEnumClass = PyObject_CallMethod(pyEnumModule, "IntEnum", "sO", name, pyConstantsDict); + + Py_CLEAR(pyConstantsDict); + Py_CLEAR(pyEnumModule); + + if (pyEnumClass && PyModule_AddObject(module, name, pyEnumClass) < 0) { + Py_CLEAR(pyEnumClass); + } +} + } // namespace Base diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 41a1bf7993..2f7466b13f 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -139,6 +139,8 @@ #include "3Dconnexion/navlib/NavlibInterface.h" #include "QtWidgets.h" +#include + #ifdef BUILD_TRACY_FRAME_PROFILER #include #endif @@ -505,6 +507,17 @@ Application::Application(bool GUIenabled) Gui::TaskView::TaskDialogPy::init_type(); registerUserInputEnumInPython(module); + Base::PyRegisterEnum(module, "PlacementIndicatorParts", { + {"Axes", SoFCPlacementIndicatorKit::Axes}, + {"ArrowHeads", SoFCPlacementIndicatorKit::ArrowHeads}, + {"Labels", SoFCPlacementIndicatorKit::Labels}, + {"PlaneIndicator", SoFCPlacementIndicatorKit::PlaneIndicator}, + {"OriginIndicator", SoFCPlacementIndicatorKit::OriginIndicator}, + + // common configurations + {"AllParts", SoFCPlacementIndicatorKit::AllParts}, + {"AxisCross", SoFCPlacementIndicatorKit::AxisCross}, + }); CommandActionPy::init_type(); Base::Interpreter().addType(CommandActionPy::type_object(), module, "CommandAction"); diff --git a/src/Gui/InputHintPy.cpp b/src/Gui/InputHintPy.cpp index 069a734281..9551039101 100644 --- a/src/Gui/InputHintPy.cpp +++ b/src/Gui/InputHintPy.cpp @@ -30,15 +30,6 @@ void Gui::registerUserInputEnumInPython(PyObject* module) { using enum Gui::InputHint::UserInput; - constexpr const char* name = "UserInput"; - - PyObject* py_enum_module = PyImport_ImportModule("enum"); - if (!py_enum_module) { - return; - } - - PyObject* py_constants_dict = PyDict_New(); - // clang-format off // this structure is repetition of each and every UserInput enum case // it can be regenerated by copying and pasting all entries and performing one substitution: @@ -202,17 +193,5 @@ void Gui::registerUserInputEnumInPython(PyObject* module) }; // clang-format on - // Populate dictionary - for (const auto& [key, value] : userInputEntries) { - PyDict_SetItemString(py_constants_dict, key, PyLong_FromLong(static_cast(value))); - } - - PyObject* py_enum_class = PyObject_CallMethod(py_enum_module, "IntEnum", "sO", name, py_constants_dict); - - Py_CLEAR(py_constants_dict); - Py_CLEAR(py_enum_module); - - if (py_enum_class && PyModule_AddObject(module, name, py_enum_class) < 0) { - Py_CLEAR(py_enum_class); - } + Base::PyRegisterEnum(module, "UserInput", userInputEntries); } diff --git a/src/Mod/CAM/Path/Main/Gui/Job.py b/src/Mod/CAM/Path/Main/Gui/Job.py index 1efc2c14cd..ea33864664 100644 --- a/src/Mod/CAM/Path/Main/Gui/Job.py +++ b/src/Mod/CAM/Path/Main/Gui/Job.py @@ -132,11 +132,10 @@ class ViewProvider: self.axs.axisLength.setValue(1.2) # enum values for SoFCPlacementIndicatorKit - AXES = 1 - LABELS = 4 - ARROWHEADS = 8 - - self.axs.parts.setValue(AXES | LABELS | ARROWHEADS) + parts = FreeCADGui.PlacementIndicatorParts + self.axs.parts.setValue( + parts.Axes | parts.Labels | parts.ArrowHeads | parts.OriginIndicator + ) self.sep.addChild(self.axs) self.switch.addChild(self.sep)