generic wrapper/unwrapper for PySide and PyQt classes
This commit is contained in:
@@ -31,9 +31,11 @@
|
||||
# include <QMetaType>
|
||||
#endif
|
||||
|
||||
// Uncomment this block to remove PySide support and switch back to PyQt
|
||||
// #undef HAVE_SHIBOKEN
|
||||
// #undef HAVE_PYSIDE
|
||||
// Uncomment this block to remove PySide C++ support and switch to its Python interface
|
||||
//#undef HAVE_SHIBOKEN
|
||||
//#undef HAVE_PYSIDE
|
||||
//#undef HAVE_SHIBOKEN2
|
||||
//#undef HAVE_PYSIDE2
|
||||
|
||||
#ifdef FC_OS_WIN32
|
||||
#undef max
|
||||
@@ -187,6 +189,63 @@ void registerTypes()
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
namespace Gui {
|
||||
template<typename qttype>
|
||||
Py::Object qt_wrapInstance(qttype object, const char* className,
|
||||
const char* shiboken, const char* pyside,
|
||||
const char* wrap)
|
||||
{
|
||||
PyObject* module = PyImport_ImportModule(shiboken);
|
||||
if (!module) {
|
||||
std::string error = "Cannot load ";
|
||||
error += shiboken;
|
||||
error += " module";
|
||||
throw Py::Exception(PyExc_ImportError, error);
|
||||
}
|
||||
|
||||
Py::Module mainmod(module, true);
|
||||
Py::Callable func = mainmod.getDict().getItem(wrap);
|
||||
|
||||
Py::Tuple arguments(2);
|
||||
arguments[0] = Py::asObject(PyLong_FromVoidPtr((void*)object));
|
||||
|
||||
module = PyImport_ImportModule(pyside);
|
||||
if (!module) {
|
||||
std::string error = "Cannot load ";
|
||||
error += pyside;
|
||||
error += " module";
|
||||
throw Py::Exception(PyExc_ImportError, error);
|
||||
}
|
||||
|
||||
Py::Module qtmod(module);
|
||||
arguments[1] = qtmod.getDict().getItem(className);
|
||||
return func.apply(arguments);
|
||||
}
|
||||
|
||||
void* qt_getCppPointer(const Py::Object& pyobject, const char* shiboken, const char* unwrap)
|
||||
{
|
||||
// https://github.com/PySide/Shiboken/blob/master/shibokenmodule/typesystem_shiboken.xml
|
||||
PyObject* module = PyImport_ImportModule(shiboken);
|
||||
if (!module) {
|
||||
std::string error = "Cannot load ";
|
||||
error += shiboken;
|
||||
error += " module";
|
||||
throw Py::Exception(PyExc_ImportError, error);
|
||||
}
|
||||
|
||||
Py::Module mainmod(module, true);
|
||||
Py::Callable func = mainmod.getDict().getItem(unwrap);
|
||||
|
||||
Py::Tuple arguments(1);
|
||||
arguments[0] = pyobject; //PySide pointer
|
||||
Py::Tuple result(func.apply(arguments));
|
||||
void* ptr = PyLong_AsVoidPtr(result[0].ptr());
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
PythonWrapper::PythonWrapper()
|
||||
{
|
||||
#if defined (HAVE_SHIBOKEN)
|
||||
@@ -235,7 +294,6 @@ QObject* PythonWrapper::toQObject(const Py::Object& pyobject)
|
||||
{
|
||||
// http://pastebin.com/JByDAF5Z
|
||||
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
|
||||
#if 1
|
||||
PyTypeObject * type = Shiboken::SbkType<QObject>();
|
||||
if (type) {
|
||||
if (Shiboken::Object::checkType(pyobject.ptr())) {
|
||||
@@ -244,33 +302,20 @@ QObject* PythonWrapper::toQObject(const Py::Object& pyobject)
|
||||
return reinterpret_cast<QObject*>(cppobject);
|
||||
}
|
||||
}
|
||||
#else // does the same using shiboken's Python interface
|
||||
// https://github.com/PySide/Shiboken/blob/master/shibokenmodule/typesystem_shiboken.xml
|
||||
PyObject* module = PyImport_ImportModule((char*)"shiboken");
|
||||
if (!module)
|
||||
throw Py::Exception(PyExc_ImportError, "Cannot load shiboken module");
|
||||
|
||||
Py::Module mainmod(module, true);
|
||||
Py::Callable func = mainmod.getDict().getItem("getCppPointer");
|
||||
|
||||
Py::Tuple arguments(1);
|
||||
arguments[0] = pyobject; //PySide pointer
|
||||
Py::Tuple result(func.apply(arguments));
|
||||
void* ptr = PyLong_AsVoidPtr(result[0].ptr());
|
||||
#elif QT_VERSION >= 0x050000
|
||||
// Access shiboken2/PySide2 via Python
|
||||
//
|
||||
void* ptr = qt_getCppPointer(pyobject, "shiboken2", "getCppPointer");
|
||||
return reinterpret_cast<QObject*>(ptr);
|
||||
#else
|
||||
// Access shiboken/PySide via Python
|
||||
//
|
||||
void* ptr = qt_getCppPointer(pyobject, "shiboken", "getCppPointer");
|
||||
return reinterpret_cast<QObject*>(ptr);
|
||||
#endif
|
||||
#else
|
||||
PyObject* module = PyImport_ImportModule((char*)"sip");
|
||||
if (!module)
|
||||
throw Py::Exception(PyExc_ImportError, "Cannot load sip module");
|
||||
|
||||
Py::Module mainmod(module, true);
|
||||
Py::Callable func = mainmod.getDict().getItem("unwrapinstance");
|
||||
|
||||
Py::Tuple arguments(1);
|
||||
arguments[0] = pyobject; //PyQt pointer
|
||||
Py::Object result = func.apply(arguments);
|
||||
void* ptr = PyLong_AsVoidPtr(result.ptr());
|
||||
#if 0 // Unwrapping using sip/PyQt
|
||||
void* ptr = qt_getCppPointer(pyobject, "sip", "unwrapinstance");
|
||||
return reinterpret_cast<QObject*>(ptr);
|
||||
#endif
|
||||
|
||||
@@ -285,8 +330,14 @@ Py::Object PythonWrapper::fromQIcon(const QIcon* icon)
|
||||
const_cast<QIcon*>(icon), true, false, typeName);
|
||||
if (pyobj)
|
||||
return Py::asObject(pyobj);
|
||||
#elif QT_VERSION >= 0x050000
|
||||
// Access shiboken2/PySide2 via Python
|
||||
//
|
||||
return qt_wrapInstance<const QIcon*>(icon, "QIcon", "shiboken2", "PySide2.QtGui", "wrapInstance");
|
||||
#else
|
||||
Q_UNUSED(icon);
|
||||
// Access shiboken/PySide via Python
|
||||
//
|
||||
return qt_wrapInstance<const QIcon*>(icon, "QIcon", "shiboken", "PySide.QtGui", "wrapInstance");
|
||||
#endif
|
||||
throw Py::RuntimeError("Failed to wrap icon");
|
||||
}
|
||||
@@ -294,7 +345,8 @@ Py::Object PythonWrapper::fromQIcon(const QIcon* icon)
|
||||
Py::Object PythonWrapper::fromQWidget(QWidget* widget, const char* className)
|
||||
{
|
||||
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
|
||||
#if 1
|
||||
// Access shiboken/PySide via C++
|
||||
//
|
||||
PyTypeObject * type = Shiboken::SbkType<QWidget>();
|
||||
if (type) {
|
||||
SbkObjectType* sbk_type = reinterpret_cast<SbkObjectType*>(type);
|
||||
@@ -307,50 +359,24 @@ Py::Object PythonWrapper::fromQWidget(QWidget* widget, const char* className)
|
||||
return Py::asObject(pyobj);
|
||||
}
|
||||
throw Py::RuntimeError("Failed to wrap widget");
|
||||
#else // does the same using shiboken's Python interface
|
||||
PyObject* module = PyImport_ImportModule((char*)"shiboken");
|
||||
if (!module)
|
||||
throw Py::Exception(PyExc_ImportError, "Cannot load shiboken module");
|
||||
|
||||
Py::Module mainmod(module, true);
|
||||
Py::Callable func = mainmod.getDict().getItem("wrapInstance");
|
||||
|
||||
Py::Tuple arguments(2);
|
||||
arguments[0] = Py::asObject(PyLong_FromVoidPtr(widget));
|
||||
|
||||
module = PyImport_ImportModule((char*)"PySide.QtGui");
|
||||
if (!module)
|
||||
throw Py::Exception(PyExc_ImportError, "Cannot load PySide.QtGui module");
|
||||
|
||||
Py::Module qtmod(module);
|
||||
arguments[1] = qtmod.getDict().getItem(className);
|
||||
return func.apply(arguments);
|
||||
#endif
|
||||
#elif QT_VERSION >= 0x050000
|
||||
// Access shiboken2/PySide2 via Python
|
||||
//
|
||||
return qt_wrapInstance<QWidget*>(widget, className, "shiboken2", "PySide2.QtWidgets", "wrapInstance");
|
||||
#else
|
||||
// Access shiboken/PySide via Python
|
||||
//
|
||||
return qt_wrapInstance<QWidget*>(widget, className, "shiboken", "PySide.QtGui", "wrapInstance");
|
||||
#endif
|
||||
|
||||
#if 0 // Unwrapping using sip/PyQt
|
||||
Q_UNUSED(className);
|
||||
PyObject* module = PyImport_ImportModule((char*)"sip");
|
||||
if (!module)
|
||||
throw Py::Exception(PyExc_ImportError, "Cannot load sip module");
|
||||
|
||||
Py::Module sipmod(module, true);
|
||||
Py::Callable func = sipmod.getDict().getItem("wrapinstance");
|
||||
|
||||
Py::Tuple arguments(2);
|
||||
arguments[0] = Py::asObject(PyLong_FromVoidPtr(widget));
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
module = PyImport_ImportModule((char*)"PyQt5.QtWidgets");
|
||||
if (!module)
|
||||
throw Py::Exception(PyExc_ImportError, "Cannot load PyQt5.QtWidgets module");
|
||||
return qt_wrapInstance<QWidget*>(widget, "QWidget", "sip", "PyQt5.QtWidgets", "wrapinstance");
|
||||
#else
|
||||
module = PyImport_ImportModule((char*)"PyQt4.Qt");
|
||||
if (!module)
|
||||
throw Py::Exception(PyExc_ImportError, "Cannot load PyQt4.Qt module");
|
||||
return qt_wrapInstance<QWidget*>(widget, "QWidget", "sip", "PyQt4.Qt", "wrapinstance");
|
||||
#endif
|
||||
|
||||
Py::Module qtmod(module);
|
||||
arguments[1] = qtmod.getDict().getItem("QWidget");
|
||||
return func.apply(arguments);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -366,10 +392,17 @@ const char* PythonWrapper::getWrapperName(QObject* obj) const
|
||||
meta = meta->superClass();
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(obj);
|
||||
QUiLoader ui;
|
||||
QStringList names = ui.availableWidgets();
|
||||
const QMetaObject* meta = obj->metaObject();
|
||||
while (meta) {
|
||||
const char* typeName = meta->className();
|
||||
if (names.indexOf(QLatin1String(typeName)) >= 0)
|
||||
return typeName;
|
||||
meta = meta->superClass();
|
||||
}
|
||||
#endif
|
||||
|
||||
return nullptr;
|
||||
return "QObject";
|
||||
}
|
||||
|
||||
bool PythonWrapper::loadCoreModule()
|
||||
|
||||
Reference in New Issue
Block a user