From 61bca929416542687de696996505f75f89b62afa Mon Sep 17 00:00:00 2001 From: Ladislav Michl Date: Sat, 24 Feb 2024 02:21:30 +0100 Subject: [PATCH] Gui: Implement PythonWrapper::fromQAction Wrapping QAction through QObject does not work as QAction class is a part of QtGui not QtCore, so Py::Object with internal pointer being null is returned causing a crash later. Therefore implement fromQAction conversion method. --- src/Gui/CommandActionPy.cpp | 2 +- src/Gui/CommandPyImp.cpp | 4 ++-- src/Gui/PythonWrapper.cpp | 23 +++++++++++++++++++++++ src/Gui/PythonWrapper.h | 2 ++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Gui/CommandActionPy.cpp b/src/Gui/CommandActionPy.cpp index 389f68783c..b3671882bb 100644 --- a/src/Gui/CommandActionPy.cpp +++ b/src/Gui/CommandActionPy.cpp @@ -59,7 +59,7 @@ Py::Object CommandActionPy::getAction() PythonWrapper wrap; wrap.loadWidgetsModule(); - return wrap.fromQObject(action->action()); + return wrap.fromQAction(action->action()); } else { return Py::None(); diff --git a/src/Gui/CommandPyImp.cpp b/src/Gui/CommandPyImp.cpp index 09cbf9fcd5..57d6b9bac2 100644 --- a/src/Gui/CommandPyImp.cpp +++ b/src/Gui/CommandPyImp.cpp @@ -274,10 +274,10 @@ PyObject* CommandPy::getAction(PyObject *args) if (group) { const auto actions = group->actions(); for (auto a : actions) - list.append(wrap.fromQObject(a)); + list.append(wrap.fromQAction(a)); } else if (action) { - list.append(wrap.fromQObject(action->action())); + list.append(wrap.fromQAction(action->action())); } return Py::new_reference_to(list); diff --git a/src/Gui/PythonWrapper.cpp b/src/Gui/PythonWrapper.cpp index e2128e3ec0..a65d3d4f13 100644 --- a/src/Gui/PythonWrapper.cpp +++ b/src/Gui/PythonWrapper.cpp @@ -25,6 +25,7 @@ # include # include # include +# include # include # include # include @@ -635,6 +636,28 @@ QDir* PythonWrapper::toQDir(PyObject* pyobj) return qt_getCppType(pyobj); } +Py::Object PythonWrapper::fromQAction(QAction* action) +{ +#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE) + // Access shiboken/PySide via C++ + auto type = getPyTypeObjectForTypeName(); + if (type) { + PyObject* pyobj = Shiboken::Object::newObject(type, action, false, false, "QAction"); + WrapperManager::instance().addQObject(action, pyobj); + return Py::asObject(pyobj); + } + throw Py::RuntimeError("Failed to wrap action"); +#else + // Access shiboken/PySide via Python +# if QT_VERSION < QT_VERSION_CHECK(6,0,0) + constexpr const char* qtModWithQAction = "QtWidgets"; +# else + constexpr const char* qtModWithQAction = "QtGui"; +# endif + return qt_wrapInstance(action, "QAction", qtModWithQAction); +#endif +} + Py::Object PythonWrapper::fromQPrinter(QPrinter* printer) { if (!printer) { diff --git a/src/Gui/PythonWrapper.h b/src/Gui/PythonWrapper.h index b854ae3fa9..f108d37285 100644 --- a/src/Gui/PythonWrapper.h +++ b/src/Gui/PythonWrapper.h @@ -29,6 +29,7 @@ #include QT_BEGIN_NAMESPACE +class QAction; class QDir; class QIcon; class QImage; @@ -58,6 +59,7 @@ public: QGraphicsObject* toQGraphicsObject(PyObject* pyPtr); QGraphicsObject* toQGraphicsObject(const Py::Object& pyObject); + Py::Object fromQAction(QAction*); Py::Object fromQPrinter(QPrinter*); Py::Object fromQObject(QObject*, const char* className=nullptr); Py::Object fromQWidget(QWidget*, const char* className=nullptr);