1
/***************************************************************************
2
* Copyright (c) 2021 Werner Mayer <wmayer[at]users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
26
# include <unordered_map>
29
# include <QApplication>
38
// Uncomment this block to remove PySide C++ support and switch to its Python interface
39
//#undef HAVE_SHIBOKEN2
41
//#undef HAVE_SHIBOKEN6
48
#pragma warning( disable : 4099 )
49
#pragma warning( disable : 4522 )
54
# pragma clang diagnostic push
55
# pragma clang diagnostic ignored "-Wmismatched-tags"
56
# pragma clang diagnostic ignored "-Wunused-parameter"
57
# if __clang_major__ > 3
58
# pragma clang diagnostic ignored "-Wkeyword-macro"
60
#elif defined (__GNUC__)
61
# pragma GCC diagnostic push
62
# pragma GCC diagnostic ignored "-Wunused-parameter"
63
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
66
//-----------------------------------------------------------------------------
68
// shiboken2 and PySide2 specific defines and includes
71
// class and struct used for SbkObject
78
// Since version 5.12 shiboken offers a method to get wrapper by class name (typeForTypeName)
79
// This helps to avoid to include the PySide2 headers since MSVC has a compiler bug when
80
// compiling together with std::bitset (https://bugreports.qt.io/browse/QTBUG-72073)
82
// Do not use SHIBOKEN_MICRO_VERSION; it might contain a dot
83
# define SHIBOKEN_FULL_VERSION QT_VERSION_CHECK(SHIBOKEN_MAJOR_VERSION, SHIBOKEN_MINOR_VERSION, 0)
84
# if (SHIBOKEN_FULL_VERSION >= QT_VERSION_CHECK(5, 12, 0))
85
# define HAVE_SHIBOKEN_TYPE_FOR_TYPENAME
88
# ifndef HAVE_SHIBOKEN_TYPE_FOR_TYPENAME
89
# include <pyside2_qtcore_python.h>
90
# include <pyside2_qtgui_python.h>
91
# include <pyside2_qtwidgets_python.h>
93
# endif // HAVE_PYSIDE2
94
#endif // HAVE_SHIBOKEN2
96
//-----------------------------------------------------------------------------
98
// shiboken6 and PySide6 specific defines and includes
101
// class and struct used for SbkObject
104
# define HAVE_SHIBOKEN
107
# define HAVE_SHIBOKEN_TYPE_FOR_TYPENAME
108
# endif // HAVE_PYSIDE6
109
#endif // HAVE_SHIBOKEN6
111
//-----------------------------------------------------------------------------
114
# undef _POSIX_C_SOURCE
116
# include <basewrapper.h>
117
# include <sbkconverter.h>
118
# include <sbkmodule.h>
119
# include <shiboken.h>
120
#endif // HAVE_SHIBOKEN
123
# include <signalmanager.h>
126
//-----------------------------------------------------------------------------
128
#if defined(__clang__)
129
# pragma clang diagnostic pop
130
#elif defined (__GNUC__)
131
# pragma GCC diagnostic pop
134
// Must be imported after PySide headers
136
# include <QGraphicsItem>
137
# include <QGraphicsObject>
140
#include <App/Application.h>
141
#include <Base/Interpreter.h>
142
#include <Base/Quantity.h>
143
#include <Base/QuantityPy.h>
145
#include "PythonWrapper.h"
147
#include "MetaTypes.h"
150
#if defined(HAVE_SHIBOKEN2)
151
PyTypeObject** SbkPySide2_QtCoreTypes = nullptr;
152
PyTypeObject** SbkPySide2_QtGuiTypes = nullptr;
153
PyTypeObject** SbkPySide2_QtWidgetsTypes = nullptr;
154
PyTypeObject** SbkPySide2_QtPrintSupportTypes = nullptr;
155
PyTypeObject** SbkPySide2_QtUiToolsTypes = nullptr;
156
constexpr auto &SbkPySide_QtCoreTypes = SbkPySide2_QtCoreTypes;
157
constexpr auto &SbkPySide_QtGuiTypes = SbkPySide2_QtGuiTypes;
158
constexpr auto &SbkPySide_QtWidgetsTypes = SbkPySide2_QtWidgetsTypes;
159
constexpr auto &SbkPySide_QtPrintSupportTypes = SbkPySide2_QtPrintSupportTypes;
160
constexpr auto &SbkPySide_QtUiToolsTypes = SbkPySide2_QtUiToolsTypes;
161
#if !defined(HAVE_PYSIDE2)
162
constexpr const char* ModuleShiboken = "shiboken2";
164
constexpr const char* ModulePySide = "PySide2";
165
#elif defined(HAVE_SHIBOKEN6)
166
PyTypeObject** SbkPySide6_QtCoreTypes = nullptr;
167
PyTypeObject** SbkPySide6_QtGuiTypes = nullptr;
168
PyTypeObject** SbkPySide6_QtWidgetsTypes = nullptr;
169
PyTypeObject** SbkPySide6_QtPrintSupportTypes = nullptr;
170
PyTypeObject** SbkPySide6_QtUiToolsTypes = nullptr;
171
constexpr auto &SbkPySide_QtCoreTypes = SbkPySide6_QtCoreTypes;
172
constexpr auto &SbkPySide_QtGuiTypes = SbkPySide6_QtGuiTypes;
173
constexpr auto &SbkPySide_QtWidgetsTypes = SbkPySide6_QtWidgetsTypes;
174
constexpr auto &SbkPySide_QtPrintSupportTypes = SbkPySide6_QtPrintSupportTypes;
175
constexpr auto &SbkPySide_QtUiToolsTypes = SbkPySide6_QtUiToolsTypes;
176
#if !defined(HAVE_PYSIDE6)
177
constexpr const char* ModuleShiboken = "shiboken6";
179
constexpr const char* ModulePySide = "PySide6";
181
static PyTypeObject** SbkPySide_DummyTypes;
182
constexpr auto &SbkPySide_QtCoreTypes = SbkPySide_DummyTypes;
183
constexpr auto &SbkPySide_QtGuiTypes = SbkPySide_DummyTypes;
184
constexpr auto &SbkPySide_QtWidgetsTypes = SbkPySide_DummyTypes;
185
constexpr auto &SbkPySide_QtPrintSupportTypes = SbkPySide_DummyTypes;
186
constexpr auto &SbkPySide_QtUiToolsTypes = SbkPySide_DummyTypes;
187
# if QT_VERSION < QT_VERSION_CHECK(6,0,0)
188
constexpr const char* ModuleShiboken = "shiboken2";
189
constexpr const char* ModulePySide = "PySide2";
191
constexpr const char* ModuleShiboken = "shiboken6";
192
constexpr const char* ModulePySide = "PySide6";
199
#if defined (HAVE_SHIBOKEN)
204
ui = FreeCADGui.UiLoader()
205
w = ui.createWidget("Gui::InputField")
207
w.property("quantity")
211
PyObject* toPythonFuncQuantityTyped(Base::Quantity cpx)
213
return new Base::QuantityPy(new Base::Quantity(cpx));
216
PyObject* toPythonFuncQuantity(const void* cpp)
218
return toPythonFuncQuantityTyped(*static_cast<const Base::Quantity*>(cpp));
221
void toCppPointerConvFuncQuantity(PyObject* pyobj,void* cpp)
223
*static_cast<Base::Quantity*>(cpp) = *static_cast<Base::QuantityPy*>(pyobj)->getQuantityPtr();
226
PythonToCppFunc toCppPointerCheckFuncQuantity(PyObject* obj)
228
if (PyObject_TypeCheck(obj, &(Base::QuantityPy::Type))) {
229
return toCppPointerConvFuncQuantity;
234
void BaseQuantity_PythonToCpp_QVariant(PyObject* pyIn, void* cppOut)
236
Base::Quantity* q = static_cast<Base::QuantityPy*>(pyIn)->getQuantityPtr();
237
*((QVariant*)cppOut) = QVariant::fromValue<Base::Quantity>(*q);
240
PythonToCppFunc isBaseQuantity_PythonToCpp_QVariantConvertible(PyObject* obj)
242
if (PyObject_TypeCheck(obj, &(Base::QuantityPy::Type))) {
243
return BaseQuantity_PythonToCpp_QVariant;
248
#if defined (HAVE_PYSIDE)
249
Base::Quantity convertWrapperToQuantity(const PySide::PyObjectWrapper &w)
251
auto pyIn = static_cast<PyObject*>(w);
252
if (PyObject_TypeCheck(pyIn, &(Base::QuantityPy::Type))) {
253
return *static_cast<Base::QuantityPy*>(pyIn)->getQuantityPtr();
256
return Base::Quantity(std::numeric_limits<double>::quiet_NaN());
262
SbkConverter* convert = Shiboken::Conversions::createConverter(&Base::QuantityPy::Type,
263
toPythonFuncQuantity);
264
Shiboken::Conversions::setPythonToCppPointerFunctions(convert,
265
toCppPointerConvFuncQuantity,
266
toCppPointerCheckFuncQuantity);
267
Shiboken::Conversions::registerConverterName(convert, "Base::Quantity");
269
SbkConverter* qvariant_conv = Shiboken::Conversions::getConverter("QVariant");
271
// The type QVariant already has a converter from PyBaseObject_Type which will
272
// come before our own converter.
273
Shiboken::Conversions::addPythonToCppValueConversion(qvariant_conv,
274
BaseQuantity_PythonToCpp_QVariant,
275
isBaseQuantity_PythonToCpp_QVariantConvertible);
278
#if defined (HAVE_PYSIDE)
279
QMetaType::registerConverter<PySide::PyObjectWrapper, Base::Quantity>(&convertWrapperToQuantity);
284
// --------------------------------------------------------
288
static std::string getPySideModuleName(const std::string& moduleName)
290
std::string name(ModulePySide);
297
static bool loadPySideModule(const std::string& moduleName, PyTypeObject**& types)
299
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
301
Shiboken::AutoDecRef requiredModule(Shiboken::Module::import(getPySideModuleName(moduleName).c_str()));
302
if (requiredModule.isNull()) {
305
types = Shiboken::Module::getTypes(requiredModule);
314
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
315
template<typename qttype>
316
#if defined (HAVE_SHIBOKEN2)
321
getPyTypeObjectForTypeName()
323
#if defined (HAVE_SHIBOKEN_TYPE_FOR_TYPENAME)
324
# if defined (HAVE_SHIBOKEN2)
325
auto sbkType = Shiboken::ObjectType::typeForTypeName(typeid(qttype).name());
327
return reinterpret_cast<SbkObjectType*>&(sbkType->type);
330
return Shiboken::ObjectType::typeForTypeName(typeid(qttype).name());
333
# if defined (HAVE_SHIBOKEN2)
334
return reinterpret_cast<SbkObjectType*>(Shiboken::SbkType<qttype>());
336
return Shiboken::SbkType<qttype>();
341
template<typename qttype>
342
qttype* qt_getCppType(PyObject* pyobj)
344
auto type = getPyTypeObjectForTypeName<qttype>();
346
if (Shiboken::Object::checkType(pyobj)) {
347
auto skbobj = reinterpret_cast<SbkObject *>(pyobj);
348
auto pytypeobj = reinterpret_cast<PyTypeObject *>(type);
349
return static_cast<qttype*>(Shiboken::Object::cppPointer(skbobj, pytypeobj));
356
* \brief The WrapperManager class
357
* This is a helper class that records the Python wrappers of a QObject and invalidates
358
* them when the QObject is about to be destroyed.
359
* This is to make sure that if the Python wrapper doesn't own the QObject it won't be notified
360
* if the QObject is destroyed.
362
* ui = Gui.UiLoader()
363
* lineedit = ui.createWidget("QLineEdit")
364
* lineedit.deleteLater()
365
* # Make sure this won't crash
369
class WrapperManager : public QObject
373
static WrapperManager& instance()
375
static WrapperManager singleton;
382
* Connects destruction event of a QObject with invalidation of its PythonWrapper via a helper QObject.
384
void addQObject(QObject* obj, PyObject* pyobj)
386
const auto PyW_unique_name = QString::number(reinterpret_cast <quintptr> (pyobj));
387
auto PyW_invalidator = findChild <QObject *> (PyW_unique_name, Qt::FindDirectChildrenOnly);
389
if (PyW_invalidator == nullptr) {
390
PyW_invalidator = new QObject(this);
391
PyW_invalidator->setObjectName(PyW_unique_name);
396
PyW_invalidator->disconnect();
399
auto destroyedFun = [pyobj](){
400
Base::PyGILStateLocker lock;
401
auto sbk_ptr = reinterpret_cast <SbkObject *> (pyobj);
402
if (sbk_ptr != nullptr) {
403
Shiboken::Object::setValidCpp(sbk_ptr, false);
406
Base::Console().DeveloperError("WrapperManager", "A QObject has just been destroyed after its Pythonic wrapper.\n");
411
QObject::connect(PyW_invalidator, &QObject::destroyed, this, destroyedFun);
412
QObject::connect(obj, &QObject::destroyed, PyW_invalidator, &QObject::deleteLater);
416
void wrapQApplication()
418
// We have to explicitly hold a reference to the wrapper of the QApplication
419
// as otherwise it can happen that when running the gc the program crashes
420
// The code snippet below caused a crash on older versions:
421
// mw = Gui.getMainWindow()
425
auto type = getPyTypeObjectForTypeName<QApplication>();
427
PyObject* pyobj = Shiboken::Object::newObject(type, qApp, false, false, "QApplication");
428
addQObject(qApp, pyobj);
436
~WrapperManager() override = default;
441
static std::string formatModuleError(const std::string& name)
443
std::string error = "Cannot load " + name + " module";
447
static PyObject* importShiboken()
449
PyObject* obj = PyImport_ImportModule(ModuleShiboken);
454
throw Py::Exception(PyExc_ImportError, formatModuleError(ModuleShiboken));
457
static PyObject* importPySide(const std::string& moduleName)
459
std::string name = getPySideModuleName(moduleName);
460
PyObject* obj = PyImport_ImportModule(name.c_str());
465
throw Py::Exception(PyExc_ImportError, formatModuleError(name));
468
template<typename qttype>
469
qttype* qt_getCppType(PyObject* pyobj)
471
// https://github.com/PySide/Shiboken/blob/master/shibokenmodule/typesystem_shiboken.xml
472
Py::Module mainmod(importShiboken(), true);
473
Py::Callable func = mainmod.getDict().getItem("getCppPointer");
475
throw Py::RuntimeError("Failed to get C++ pointer");
478
Py::Tuple arguments(1);
479
arguments[0] = Py::Object(pyobj); // PySide pointer
480
Py::Tuple result(func.apply(arguments));
481
return reinterpret_cast<qttype*>(PyLong_AsVoidPtr(result[0].ptr()));
484
template<typename qttype>
485
Py::Object qt_wrapInstance(qttype object,
486
const std::string& className,
487
const std::string& moduleName)
489
Py::Module mainmod(importShiboken(), true);
490
Py::Callable func = mainmod.getDict().getItem("wrapInstance");
492
// Failure will be handled in the calling instance
496
Py::Module qtmod(importPySide(moduleName));
497
Py::Object item = qtmod.getDict().getItem(className);
499
// Failure will be handled in the calling instance
503
Py::Tuple arguments(2);
504
arguments[0] = Py::asObject(PyLong_FromVoidPtr((void*)object));
507
return func.apply(arguments);
510
const char* qt_identifyType(QObject* ptr, const std::string& moduleName)
512
Py::Module qtmod(importPySide(moduleName));
513
const QMetaObject* metaObject = ptr->metaObject();
515
const char* className = metaObject->className();
516
if (qtmod.getDict().hasKey(className)) {
519
metaObject = metaObject->superClass();
529
// --------------------------------------------------------
531
PythonWrapper::PythonWrapper()
533
#if defined (HAVE_SHIBOKEN)
542
bool PythonWrapper::toCString(const Py::Object& pyobject, std::string& str)
544
if (PyUnicode_Check(pyobject.ptr())) {
545
PyObject* unicode = PyUnicode_AsUTF8String(pyobject.ptr());
546
str = PyBytes_AsString(unicode);
550
else if (PyBytes_Check(pyobject.ptr())) {
551
str = PyBytes_AsString(pyobject.ptr());
554
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
555
if (Shiboken::String::check(pyobject.ptr())) {
556
const char* s = Shiboken::String::toCString(pyobject.ptr());
564
QObject* PythonWrapper::toQObject(const Py::Object& pyobject)
566
return qt_getCppType<QObject>(pyobject.ptr());
569
QGraphicsItem* PythonWrapper::toQGraphicsItem(PyObject* pyPtr)
571
return qt_getCppType<QGraphicsItem>(pyPtr);
574
QGraphicsItem* PythonWrapper::toQGraphicsItem(const Py::Object& pyobject)
576
return toQGraphicsItem(pyobject.ptr());
579
QGraphicsObject* PythonWrapper::toQGraphicsObject(PyObject* pyPtr)
581
return qt_getCppType<QGraphicsObject>(pyPtr);
584
QGraphicsObject* PythonWrapper::toQGraphicsObject(const Py::Object& pyobject)
586
return toQGraphicsObject(pyobject.ptr());
589
Py::Object PythonWrapper::fromQImage(const QImage& img)
591
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
592
auto type = getPyTypeObjectForTypeName<QImage>();
594
PyObject* pyobj = Shiboken::Conversions::copyToPython(type, const_cast<QImage*>(&img));
595
return Py::asObject(pyobj);
598
// Access shiboken/PySide via Python
599
Py::Object obj = qt_wrapInstance<const QImage*>(&img, "QImage", "QtGui");
604
throw Py::RuntimeError("Failed to wrap image");
607
QImage *PythonWrapper::toQImage(PyObject *pyobj)
609
return qt_getCppType<QImage>(pyobj);
612
Py::Object PythonWrapper::fromQIcon(const QIcon* icon)
614
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
615
auto type = getPyTypeObjectForTypeName<QIcon>();
617
const char* typeName = typeid(*const_cast<QIcon*>(icon)).name();
618
PyObject* pyobj = Shiboken::Object::newObject(type, const_cast<QIcon*>(icon), true, false, typeName);
619
return Py::asObject(pyobj);
622
// Access shiboken/PySide via Python
623
Py::Object obj = qt_wrapInstance<const QIcon*>(icon, "QIcon", "QtGui");
628
throw Py::RuntimeError("Failed to wrap icon");
631
QIcon *PythonWrapper::toQIcon(PyObject *pyobj)
633
return qt_getCppType<QIcon>(pyobj);
636
Py::Object PythonWrapper::fromQDir(const QDir& dir)
638
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
639
auto type = getPyTypeObjectForTypeName<QDir>();
641
const char* typeName = typeid(dir).name();
642
PyObject* pyobj = Shiboken::Object::newObject(type, const_cast<QDir*>(&dir), false, false, typeName);
643
return Py::asObject(pyobj);
646
// Access shiboken/PySide via Python
647
Py::Object obj = qt_wrapInstance<const QDir*>(&dir, "QDir", "QtGui");
652
throw Py::RuntimeError("Failed to wrap directory");
655
QDir* PythonWrapper::toQDir(PyObject* pyobj)
657
return qt_getCppType<QDir>(pyobj);
660
Py::Object PythonWrapper::fromQAction(QAction* action)
662
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
663
// Access shiboken/PySide via C++
664
auto type = getPyTypeObjectForTypeName<QAction>();
666
PyObject* pyobj = Shiboken::Object::newObject(type, action, false, false, "QAction");
667
WrapperManager::instance().addQObject(action, pyobj);
668
return Py::asObject(pyobj);
671
// Access shiboken/PySide via Python
672
# if QT_VERSION < QT_VERSION_CHECK(6,0,0)
673
constexpr const char* qtModWithQAction = "QtWidgets";
675
constexpr const char* qtModWithQAction = "QtGui";
677
Py::Object obj = qt_wrapInstance<QAction*>(action, "QAction", qtModWithQAction);
682
throw Py::RuntimeError("Failed to wrap action");
685
Py::Object PythonWrapper::fromQPrinter(QPrinter* printer)
690
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
691
// Access shiboken/PySide via C++
692
auto type = getPyTypeObjectForTypeName<QPrinter>();
694
// XXX: Why is QPrinter special?
695
#if defined (HAVE_SHIBOKEN2)
696
type = reinterpret_cast<SbkObjectType*>(Shiboken::Conversions::getPythonTypeObject("QPrinter"));
698
type = Shiboken::Conversions::getPythonTypeObject("QPrinter");
702
PyObject* pyobj = Shiboken::Object::newObject(type, printer, false, false, "QPrinter");
703
return Py::asObject(pyobj);
706
// Access shiboken/PySide via Python
707
Py::Object obj = qt_wrapInstance<QPrinter*>(printer, "QPrinter", "QtCore");
712
throw Py::RuntimeError("Failed to wrap printer");
715
Py::Object PythonWrapper::fromQObject(QObject* object, const char* className)
720
const char* typeName;
722
typeName = className;
725
typeName = object->metaObject()->className();
727
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
728
// Access shiboken/PySide via C++
729
auto type = getPyTypeObjectForTypeName<QObject>();
731
PyObject* pyobj = Shiboken::Object::newObject(type, object, false, false, typeName);
732
WrapperManager::instance().addQObject(object, pyobj);
733
return Py::asObject(pyobj);
736
// Access shiboken/PySide via Python
737
Py::Object obj = qt_wrapInstance<QObject*>(object, typeName, "QtCore");
742
throw Py::RuntimeError("Failed to wrap object");
745
Py::Object PythonWrapper::fromQWidget(QWidget* widget, const char* className)
747
const char* typeName;
749
typeName = className;
752
typeName = widget->metaObject()->className();
754
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
755
// Access shiboken/PySide via C++
756
auto type = getPyTypeObjectForTypeName<QWidget>();
758
PyObject* pyobj = Shiboken::Object::newObject(type, widget, false, false, typeName);
759
WrapperManager::instance().addQObject(widget, pyobj);
760
return Py::asObject(pyobj);
763
// Access shiboken/PySide via Python
764
Py::Object obj = qt_wrapInstance<QWidget*>(widget, typeName, "QtWidgets");
769
throw Py::RuntimeError("Failed to wrap widget");
772
const char* PythonWrapper::getWrapperName(QObject* obj) const
774
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
775
const QMetaObject* meta = obj->metaObject();
777
const char* typeName = meta->className();
778
PyTypeObject* exactType = Shiboken::Conversions::getPythonTypeObject(typeName);
782
meta = meta->superClass();
786
QStringList names = ui.availableWidgets();
787
const QMetaObject* meta = obj->metaObject();
789
const char* typeName = meta->className();
790
if (names.indexOf(QLatin1String(typeName)) >= 0) {
793
meta = meta->superClass();
799
bool PythonWrapper::loadCoreModule()
801
return loadPySideModule("QtCore", SbkPySide_QtCoreTypes);
804
bool PythonWrapper::loadGuiModule()
806
return loadPySideModule("QtGui", SbkPySide_QtGuiTypes);
809
bool PythonWrapper::loadWidgetsModule()
811
return loadPySideModule("QtWidgets", SbkPySide_QtWidgetsTypes);
814
bool PythonWrapper::loadPrintSupportModule()
816
return loadPySideModule("QtPrintSupport", SbkPySide_QtPrintSupportTypes);
819
bool PythonWrapper::loadUiToolsModule()
821
return loadPySideModule("QtUiTools", SbkPySide_QtUiToolsTypes);
824
void PythonWrapper::createChildrenNameAttributes(PyObject* root, QObject* object)
826
Q_FOREACH (QObject* child, object->children()) {
827
const QByteArray name = child->objectName().toLocal8Bit();
829
if (!name.isEmpty() && !name.startsWith("_") && !name.startsWith("qt_")) {
830
bool hasAttr = PyObject_HasAttrString(root, name.constData());
832
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
833
Shiboken::AutoDecRef pyChild(Shiboken::Conversions::pointerToPython(getPyTypeObjectForTypeName<QObject>(), child));
834
PyObject_SetAttrString(root, name.constData(), pyChild);
836
const char* className = qt_identifyType(child, "QtWidgets");
838
if (qobject_cast<QWidget*>(child)) {
839
className = "QWidget";
842
className = "QObject";
846
Py::Object pyChild(qt_wrapInstance<QObject*>(child, className, "QtWidgets"));
847
if (!pyChild.isNull()) {
848
PyObject_SetAttrString(root, name.constData(), pyChild.ptr());
852
createChildrenNameAttributes(root, child);
854
createChildrenNameAttributes(root, child);
858
void PythonWrapper::setParent(PyObject* pyWdg, QObject* parent)
860
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
862
Shiboken::AutoDecRef pyParent(Shiboken::Conversions::pointerToPython(getPyTypeObjectForTypeName<QWidget>(), parent));
863
Shiboken::Object::setParent(pyParent, pyWdg);