108
static void destructionVisitor(SbkObject* pyObj, void* data)
110
void** realData = reinterpret_cast<void**>(data);
111
SbkObject* pyQApp = reinterpret_cast<SbkObject*>(realData[0]);
112
PyTypeObject* pyQObjectType = reinterpret_cast<PyTypeObject*>(realData[1]);
114
if (pyObj != pyQApp && PyObject_TypeCheck(pyObj, pyQObjectType)) {
115
if (Shiboken::Object::hasOwnership(pyObj) && Shiboken::Object::isValid(pyObj, false)) {
116
Py_BEGIN_ALLOW_THREADS
117
Shiboken::callCppDestructor<QObject>(Shiboken::Object::cppPointer(pyObj, pyQObjectType));
119
Shiboken::Object::setValidCpp(pyObj, false);
124
void destroyQCoreApplication()
126
SignalManager::instance().clear();
127
QCoreApplication* app = QCoreApplication::instance();
131
Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();
132
SbkObject* pyQApp = bm.retrieveWrapper(app);
133
PyTypeObject* pyQObjectType = Shiboken::TypeResolver::get("QObject*")->pythonType();
134
assert(pyQObjectType);
136
void* data[2] = {pyQApp, pyQObjectType};
137
bm.visitAllPyObjects(&destructionVisitor, &data);
139
// in the end destroy app
143
void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base)
145
QByteArray typeName = QByteArray(type->super.ht_type.tp_name).split('.').last();
146
DynamicQMetaObject* mo = new PySide::DynamicQMetaObject(typeName, base);
147
Shiboken::ObjectType::setTypeUserData(type, mo, &Shiboken::callCppDestructor<DynamicQMetaObject>);
150
void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds)
152
PyTypeObject* qObjType = Shiboken::TypeResolver::get("QObject*")->pythonType();
153
QByteArray className(PyString_AS_STRING(PyTuple_GET_ITEM(args, 0)));
155
PyObject* bases = PyTuple_GET_ITEM(args, 1);
156
int numBases = PyTuple_GET_SIZE(args);
157
QMetaObject* baseMo = 0;
159
for (int i = 0; i < numBases; ++i) {
160
PyTypeObject* base = reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(bases, i));
161
if (PyType_IsSubtype(base, qObjType)) {
162
baseMo = reinterpret_cast<QMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(base)));
163
// If it's a class like QObject, QWidget, etc, use the original QMetaObject instead of the dynamic one
164
// IMO this if is a bug, however it keeps the current behaviour.
165
if (!Shiboken::ObjectType::isUserType(base))
166
baseMo = const_cast<QMetaObject*>(baseMo->d.superdata);
171
qWarning("Sub class of QObject not inheriting QObject!? Crash will happen when using %s.", className.constData());
175
DynamicQMetaObject* mo = new PySide::DynamicQMetaObject(className.constData(), baseMo);
177
Shiboken::ObjectType::setTypeUserData(type, mo, &Shiboken::callCppDestructor<DynamicQMetaObject>);
179
PyObject* attrs = PyTuple_GET_ITEM(args, 2);
184
typedef std::pair<const char*, PyObject*> PropPair;
185
QList<PropPair> properties;
187
Shiboken::AutoDecRef slotAttrName(PyString_FromString(PYSIDE_SLOT_LIST_ATTR));
189
while (PyDict_Next(attrs, &pos, &key, &value)) {
190
if (PyType_IsSubtype(value->ob_type, &PySidePropertyType)) {
191
// Leave the properties to be register after signals because they may depend on notify signals
192
properties << PropPair(PyString_AS_STRING(key), value);
193
} else if (value->ob_type == &PySideSignalType) { // Register signals
194
PySideSignal* data = reinterpret_cast<PySideSignal*>(value);
195
const char* signalName = PyString_AS_STRING(key);
196
data->signalName = strdup(signalName);
199
for (int i = 0; i < data->signaturesSize; ++i) {
202
if (data->signatures[i])
203
sig += data->signatures[i];
205
if (baseMo->indexOfSignal(sig) == -1)
208
} else if (PyFunction_Check(value)) { // Register slots
209
if (PyObject_HasAttr(value, slotAttrName)) {
210
PyObject* signatureList = PyObject_GetAttr(value, slotAttrName);
211
for(Py_ssize_t i = 0, i_max = PyList_Size(signatureList); i < i_max; ++i) {
212
PyObject* signature = PyList_GET_ITEM(signatureList, i);
213
QByteArray sig(PyString_AS_STRING(signature));
214
//slot the slot type and signature
215
QList<QByteArray> slotInfo = sig.split(' ');
216
int index = baseMo->indexOfSlot(slotInfo[1]);
218
mo->addSlot(slotInfo[1], slotInfo[0]);
224
// Register properties
225
foreach (PropPair propPair, properties)
226
mo->addProperty(propPair.first, propPair.second);
229
PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, PyObject* name)
231
PyObject* attr = PyObject_GenericGetAttr(self, name);
232
if (attr && Property::isPropertyType(attr)) {
233
PyObject *value = Property::getValue(reinterpret_cast<PySideProperty*>(attr), self);
241
//mutate native signals to signal instance type
242
if (attr && PyObject_TypeCheck(attr, &PySideSignalType)) {
243
PyObject* signal = reinterpret_cast<PyObject*>(Signal::initialize(reinterpret_cast<PySideSignal*>(attr), name, self));
244
PyObject_SetAttr(self, name, reinterpret_cast<PyObject*>(signal));
248
//search on metaobject (avoid internal attributes started with '__')
249
if (!attr && !QString(PyString_AS_STRING(name)).startsWith("__")) {
250
const QMetaObject* metaObject = cppSelf->metaObject();
251
QByteArray cname(PyString_AS_STRING(name));
254
QList<QMetaMethod> signalList;
255
for(int i=0, i_max = metaObject->methodCount(); i < i_max; i++) {
256
QMetaMethod method = metaObject->method(i);
257
if (QString(method.signature()).startsWith(cname)) {
258
if (method.methodType() == QMetaMethod::Signal) {
259
signalList.append(method);
261
PySideMetaFunction* func = MetaFunction::newObject(cppSelf, i);
263
PyObject_SetAttr(self, name, (PyObject*)func);
264
return (PyObject*)func;
269
if (signalList.size() > 0) {
270
PyObject* pySignal = reinterpret_cast<PyObject*>(Signal::newObjectFromMethod(self, signalList));
271
PyObject_SetAttr(self, name, pySignal);
102
278
} //namespace PySide