diff --git a/src/PythonQtClassInfo.cpp b/src/PythonQtClassInfo.cpp index 0062d72..f56dd50 100644 --- a/src/PythonQtClassInfo.cpp +++ b/src/PythonQtClassInfo.cpp @@ -118,6 +118,8 @@ int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar) bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName) { + if (!_meta) return false; + bool found = false; bool nameMapped = false; const char* attributeName = memberName; diff --git a/src/PythonQtInstanceWrapper.cpp b/src/PythonQtInstanceWrapper.cpp index 697ef31..4b859f0 100644 --- a/src/PythonQtInstanceWrapper.cpp +++ b/src/PythonQtInstanceWrapper.cpp @@ -241,6 +241,17 @@ static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name) std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data(); } } + + QList dynamicProps = wrapper->_obj->dynamicPropertyNames(); + foreach (QByteArray name, dynamicProps) { + PyObject* o = PyObject_GetAttrString(obj, name.data()); + if (o) { + PyDict_SetItemString(dict, name.data(), o); + Py_DECREF(o); + } else { + std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data(); + } + } } // Note: we do not put children into the dict, is would look confusing?! return dict; @@ -255,8 +266,6 @@ static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name) // mlabDebugConst("Python","get " << attributeName); - // TODO: dynamic properties are missing - PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName); switch (member._type) { case PythonQtMemberInfo::Property: @@ -290,6 +299,15 @@ static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name) return enumWrapper; } break; + case PythonQtMemberInfo::NotFound: + // handle dynamic properties + if (wrapper->_obj) { + QVariant v = wrapper->_obj->property(attributeName); + if (v.isValid()) { + return PythonQtConv::QVariantToPyObject(v); + } + } + break; default: // is an invalid type, go on break; @@ -367,6 +385,23 @@ static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec } else if (member._type == PythonQtMemberInfo::EnumWrapper) { error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object"; } else if (member._type == PythonQtMemberInfo::NotFound) { + // handle dynamic properties + if (wrapper->_obj) { + QVariant prop = wrapper->_obj->property(attributeName); + if (prop.isValid()) { + QVariant v = PythonQtConv::PyObjToQVariant(value); + if (v.isValid()) { + wrapper->_obj->setProperty(attributeName, v); + return 0; + } else { + error = QString("Dynamic property '") + attributeName + "' does not accept an object of type " + + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")"; + PyErr_SetString(PyExc_AttributeError, error.toLatin1().data()); + return -1; + } + } + } + // if we are a derived python class, we allow setting attributes. // if we are a direct CPP wrapper, we do NOT allow it, since // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore diff --git a/src/PythonQtStdDecorators.cpp b/src/PythonQtStdDecorators.cpp index 19d12fe..7b24f52 100644 --- a/src/PythonQtStdDecorators.cpp +++ b/src/PythonQtStdDecorators.cpp @@ -149,6 +149,16 @@ const QObjectList* PythonQtStdDecorators::children(QObject* o) return &o->children(); } +bool PythonQtStdDecorators::setProperty(QObject* o, const char* name, const QVariant& value) +{ + return o->setProperty(name, value); +} + +QVariant PythonQtStdDecorators::property(QObject* o, const char* name) +{ + return o->property(name); +} + QString PythonQtStdDecorators::tr(QObject* obj, const QByteArray& text, const QByteArray& ambig, int n) { return QCoreApplication::translate(obj->metaObject()->className(), text.constData(), ambig.constData(), QCoreApplication::CodecForTr, n); diff --git a/src/PythonQtStdDecorators.h b/src/PythonQtStdDecorators.h index 781261c..087981d 100644 --- a/src/PythonQtStdDecorators.h +++ b/src/PythonQtStdDecorators.h @@ -75,6 +75,9 @@ public slots: QList findChildren(QObject* parent, PyObject* type, const QString& name= QString()); QList findChildren(QObject* parent, PyObject* type, const QRegExp& regExp); + bool setProperty(QObject* o, const char* name, const QVariant& value); + QVariant property(QObject* o, const char* name); + double static_Qt_qAbs(double a) { return qAbs(a); } double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); } void static_Qt_qDebug(const QByteArray& msg) { qDebug(msg.constData()); }