diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-09-24 11:10:24 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-09-28 11:19:29 +0200 |
commit | cb073f6eee9e21b62d7c14e0357beb6cecf33e31 (patch) | |
tree | 36a32fae9cf3f9c8d505a8dbaf31b228b08844f9 | |
parent | 5a7429cc895824a4eafd27e1a5c95b40bba86bdf (diff) |
shiboken2: Generate properties as fields
- Add an XML attribute specifying whether code is to
be generated to the XML properties.
- Split the generator functions for field setters and getters
apart so that they can be used for generating property
setters and getters.
- Generate code for all properties from XML when the PySide
extension is not used, otherwise only for those with
the attribute set.
Task-number: PYSIDE-1019
Change-Id: Iab2ba38b90038edc667a233c23c7113fdc6fb438
Reviewed-by: Christian Tismer <tismer@stackless.com>
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
14 files changed, 258 insertions, 42 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 268546d6c..466464807 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -1592,10 +1592,7 @@ public: m_propertySpecs << spec; } - QVector<QPropertySpec *> propertySpecs() const - { - return m_propertySpecs; - } + const QVector<QPropertySpec *> &propertySpecs() const { return m_propertySpecs; } QPropertySpec *propertySpecByName(const QString &name) const; QPropertySpec *propertySpecForRead(const QString &name) const; diff --git a/sources/shiboken2/ApiExtractor/propertyspec.cpp b/sources/shiboken2/ApiExtractor/propertyspec.cpp index fcb8286bf..f86a31d5b 100644 --- a/sources/shiboken2/ApiExtractor/propertyspec.cpp +++ b/sources/shiboken2/ApiExtractor/propertyspec.cpp @@ -48,7 +48,8 @@ QPropertySpec::QPropertySpec(const TypeSystemProperty &ts, m_write(ts.write), m_designable(ts.designable), m_reset(ts.reset), - m_type(type) + m_type(type), + m_generateGetSetDef(ts.generateGetSetDef) { } diff --git a/sources/shiboken2/ApiExtractor/propertyspec.h b/sources/shiboken2/ApiExtractor/propertyspec.h index 4abe75c84..611d4726e 100644 --- a/sources/shiboken2/ApiExtractor/propertyspec.h +++ b/sources/shiboken2/ApiExtractor/propertyspec.h @@ -79,6 +79,7 @@ public: QString write() const { return m_write; } void setWrite(const QString &write) { m_write = write; } + bool hasWrite() const { return !m_write.isEmpty(); } QString designable() const { return m_designable; } void setDesignable(const QString &designable) { m_designable = designable; } @@ -89,6 +90,9 @@ public: int index() const { return m_index; } void setIndex(int index) {m_index = index; } + bool generateGetSetDef() const { return m_generateGetSetDef; } + void setGenerateGetSetDef(bool generateGetSetDef) { m_generateGetSetDef = generateGetSetDef; } + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const; #endif @@ -101,6 +105,8 @@ private: QString m_reset; const AbstractMetaType *m_type = nullptr; int m_index = -1; + // Indicates whether actual code is generated instead of relying on libpyside. + bool m_generateGetSetDef = false; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 0c8f85738..8c4f1dc0e 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -563,6 +563,8 @@ struct TypeSystemProperty QString write; QString reset; QString designable; + // Indicates whether actual code is generated instead of relying on libpyside. + bool generateGetSetDef = false; }; class TypeEntry diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.cpp b/sources/shiboken2/ApiExtractor/typesystemparser.cpp index 04aadbb63..27e613280 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken2/ApiExtractor/typesystemparser.cpp @@ -70,6 +70,7 @@ static inline QString formatAttribute() { return QStringLiteral("format"); } static inline QString generateUsingAttribute() { return QStringLiteral("generate-using"); } static inline QString classAttribute() { return QStringLiteral("class"); } static inline QString generateAttribute() { return QStringLiteral("generate"); } +static inline QString generateGetSetDefAttribute() { return QStringLiteral("generate-getsetdef"); } static inline QString genericClassAttribute() { return QStringLiteral("generic-class"); } static inline QString indexAttribute() { return QStringLiteral("index"); } static inline QString invalidateAfterUseAttribute() { return QStringLiteral("invalidate-after-use"); } @@ -2256,6 +2257,10 @@ bool TypeSystemParser::parseProperty(const QXmlStreamReader &, const StackElemen property.type = attributes->takeAt(i).value().toString(); } else if (name == QLatin1String("set")) { property.write = attributes->takeAt(i).value().toString(); + } else if (name == generateGetSetDefAttribute()) { + property.generateGetSetDef = + convertBoolean(attributes->takeAt(i).value(), + generateGetSetDefAttribute(), false); } } if (!property.isValid()) { diff --git a/sources/shiboken2/doc/typesystem_manipulating_objects.rst b/sources/shiboken2/doc/typesystem_manipulating_objects.rst index 98f503074..fb0a50aba 100644 --- a/sources/shiboken2/doc/typesystem_manipulating_objects.rst +++ b/sources/shiboken2/doc/typesystem_manipulating_objects.rst @@ -238,14 +238,23 @@ conversion-rule property ^^^^^^^^ - The ``property`` element allows you to add properties complementing the - properties obtained from the ``Q_PROPERTY`` macro in Qt-based code when using - the PySide2 extension. It may appear as a child of a complex type such as - ``object-type`` or ``value-type``. + The ``property`` element allows you to specify properties consisting of + a type and getter and setter functions. + + It may appear as a child of a complex type such as ``object-type`` or + ``value-type``. + + If the PySide2 extension is not present, code will be generated using the + ``PyGetSetDef`` struct, similar to what is generated for fields. + + If the PySide2 extension is present, those properties complement the + properties obtained from the ``Q_PROPERTY`` macro in Qt-based code. + The properties will be handled in ``libpyside`` unless code generation + is forced. .. code-block:: xml - <property name="..." type="..." get="..." set="..." since="..."/> + <property name="..." type="..." get="..." set="..." " generate-getsetdef="yes | no" since="..."/> The ``name`` attribute specifies the name of the property, the ``type`` attribute specifies the C++ type and the ``get`` attribute specifies the @@ -253,15 +262,49 @@ property The optional ``set`` attribute specifies name of the setter function. + The optional ``generate-getsetdef`` attribute specifies whether to generate + code for if the PySide2 extension is present (indicating this property is not + handled by libpyside). It defaults to *no*. + The optional ``since`` attribute specifies the API version when this property appears. - For example: + For a typical C++ class, like: + + .. code-block:: c++ + + class Test { + public: + int getValue() const; + void setValue(); + }; + + ``value`` can then be specified to be a property: + + .. code-block:: xml + + <value-type name="Test"> + <property name="value" type="int" get="getValue" set="setValue"/> + + With that, a more pythonic style can be used: + + .. code-block:: python + + test = Test() + test.value = 42 + + For Qt classes (with the PySide2 extension present), additional setters + and getters that do not appear as ``Q_PROPERTY``, can be specified to + be properties: .. code-block:: xml <object-type name="QMainWindow"> <property name="centralWidget" type="QWidget *" get="centralWidget" set="setCentralWidget"/> - specifies ``centralWidget`` to be a Python property in addition to the normal properties - of ``QMainWindow`` defined for Qt Designer usage. + in addition to the normal properties of ``QMainWindow`` defined for + Qt Designer usage. + + .. note:: In the *Qt* coding style, the property name typically conflicts + with the getter name. It is recommended to exclude the getter from the + wrapper generation using the ``remove`` function modification. diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 32b9cf24f..6d9884d39 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -317,6 +317,13 @@ static QString buildPropertyString(QPropertySpec *spec) return text; } +static void writePyGetSetDefEntry(QTextStream &s, const QString &name, + const QString &getFunc, const QString &setFunc) +{ + s << "{const_cast<char *>(\"" << name << "\"), " << getFunc << ", " + << (setFunc.isEmpty() ? QLatin1String(NULL_PTR) : setFunc) << "},\n"; +} + /*! Function used to write the class generated binding code on the buffer \param s the output buffer @@ -590,8 +597,10 @@ void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classCo // PYSIDE-1019: Write a compressed list of all properties `name:getter[:setter]`. // Default values are suppressed. QStringList sorter; - for (const auto spec : metaClass->propertySpecs()) - sorter.append(buildPropertyString(spec)); + for (const auto spec : metaClass->propertySpecs()) { + if (!spec->generateGetSetDef()) + sorter.append(buildPropertyString(spec)); + } sorter.sort(); s << '\n'; @@ -689,19 +698,34 @@ void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classCo s << Qt::endl; } + for (const QPropertySpec *property : metaClass->propertySpecs()) { + if (property->generateGetSetDef() || !usePySideExtensions()) { + writeGetterFunction(s, property, classContext); + if (property->hasWrite()) + writeSetterFunction(s, property, classContext); + } + } + s << "// Getters and Setters for " << metaClass->name() << Qt::endl; s << "static PyGetSetDef " << cpythonGettersSettersDefinitionName(metaClass) << "[] = {\n"; for (const AbstractMetaField *metaField : fields) { - if (metaField->isStatic()) - continue; + if (!metaField->isStatic()) { + s << INDENT; + const QString setter = canGenerateFieldSetter(metaField) + ? cpythonSetterFunctionName(metaField) : QString(); + writePyGetSetDefEntry(s, metaField->name(), + cpythonGetterFunctionName(metaField), setter); + } + } - s << INDENT << "{const_cast<char *>(\"" << metaField->name() << "\"), "; - s << cpythonGetterFunctionName(metaField) << ", "; - if (canGenerateFieldSetter(metaField)) - s << cpythonSetterFunctionName(metaField); - else - s << NULL_PTR; - s << "},\n"; + for (const QPropertySpec *property : metaClass->propertySpecs()) { + if (property->generateGetSetDef() || !usePySideExtensions()) { + s << INDENT; + const QString setter = property->hasWrite() + ? cpythonSetterFunctionName(property, metaClass) : QString(); + writePyGetSetDefEntry(s, property->name(), + cpythonGetterFunctionName(property, metaClass), setter); + } } s << INDENT << '{' << NULL_PTR << "} // Sentinel\n"; s << "};\n\n"; @@ -3976,6 +4000,13 @@ bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass *metaClass) if (!f->isStatic()) return true; } + // Generate all user-added properties unless Pyside extensions are used, + // in which only the explicitly specified ones are generated (rest is handled + // in libpyside). + return usePySideExtensions() + ? std::any_of(metaClass->propertySpecs().cbegin(), metaClass->propertySpecs().cend(), + [] (const QPropertySpec *s) { return s->generateGetSetDef(); }) + : !metaClass->propertySpecs().isEmpty(); return false; } @@ -4416,13 +4447,18 @@ void CppGenerator::writeCopyFunction(QTextStream &s, const GeneratorContext &con s << Qt::endl; } +static inline void writeGetterFunctionStart(QTextStream &s, const QString &funcName) +{ + s << "static PyObject *" << funcName << "(PyObject *self, void *)\n"; + s << "{\n"; +} + void CppGenerator::writeGetterFunction(QTextStream &s, const AbstractMetaField *metaField, const GeneratorContext &context) { ErrorCode errorCode(QString::fromLatin1(NULL_PTR)); - s << "static PyObject *" << cpythonGetterFunctionName(metaField) << "(PyObject *self, void *)\n"; - s << "{\n"; + writeGetterFunctionStart(s, cpythonGetterFunctionName(metaField)); writeCppSelfDefinition(s, context); @@ -4503,12 +4539,35 @@ void CppGenerator::writeGetterFunction(QTextStream &s, s << "}\n"; } -void CppGenerator::writeSetterFunction(QTextStream &s, - const AbstractMetaField *metaField, +// Write a getter for QPropertySpec +void CppGenerator::writeGetterFunction(QTextStream &s, const QPropertySpec *property, const GeneratorContext &context) { ErrorCode errorCode(0); - s << "static int " << cpythonSetterFunctionName(metaField) << "(PyObject *self, PyObject *pyIn, void *)\n"; + writeGetterFunctionStart(s, cpythonGetterFunctionName(property, context.metaClass())); + writeCppSelfDefinition(s, context); + const QString value = QStringLiteral("value"); + s << INDENT << "auto " << value << " = " << CPP_SELF_VAR << "->" << property->read() << "();\n" + << INDENT << "auto pyResult = "; + writeToPythonConversion(s, property->type(), context.metaClass(), value); + s << ";\n" + << INDENT << "if (PyErr_Occurred() || !pyResult) {\n"; + { + Indentation indent(INDENT); + s << INDENT << "Py_XDECREF(pyResult);\n" + << INDENT << " return {};\n"; + } + s << INDENT << "}\n" + << INDENT << "return pyResult;\n}\n\n"; +} + +// Write setter function preamble (type checks on "pyIn") +void CppGenerator::writeSetterFunctionPreamble(QTextStream &s, const QString &name, + const QString &funcName, + const AbstractMetaType *type, + const GeneratorContext &context) +{ + s << "static int " << funcName << "(PyObject *self, PyObject *pyIn, void *)\n"; s << "{\n"; writeCppSelfDefinition(s, context); @@ -4517,24 +4576,33 @@ void CppGenerator::writeSetterFunction(QTextStream &s, { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_TypeError, \"'"; - s << metaField->name() << "' may not be deleted\");\n"; + s << name << "' may not be deleted\");\n"; s << INDENT << "return -1;\n"; } s << INDENT << "}\n"; - AbstractMetaType *fieldType = metaField->type(); - s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << "{nullptr};\n"; s << INDENT << "if (!"; - writeTypeCheck(s, fieldType, QLatin1String("pyIn"), isNumber(fieldType->typeEntry())); + writeTypeCheck(s, type, QLatin1String("pyIn"), isNumber(type->typeEntry())); s << ") {\n"; { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_TypeError, \"wrong type attributed to '"; - s << metaField->name() << "', '" << fieldType->name() << "' or convertible type expected\");\n"; + s << name << "', '" << type->name() << "' or convertible type expected\");\n"; s << INDENT << "return -1;\n"; } s << INDENT<< "}\n\n"; +} + +void CppGenerator::writeSetterFunction(QTextStream &s, + const AbstractMetaField *metaField, + const GeneratorContext &context) +{ + ErrorCode errorCode(0); + + AbstractMetaType *fieldType = metaField->type(); + writeSetterFunctionPreamble(s, metaField->name(), cpythonSetterFunctionName(metaField), + fieldType, context); QString cppField = QString::fromLatin1("%1->%2").arg(QLatin1String(CPP_SELF_VAR), metaField->name()); s << INDENT; @@ -4568,6 +4636,26 @@ void CppGenerator::writeSetterFunction(QTextStream &s, s << "}\n"; } +// Write a setter for QPropertySpec +void CppGenerator::writeSetterFunction(QTextStream &s, const QPropertySpec *property, + const GeneratorContext &context) +{ + ErrorCode errorCode(0); + writeSetterFunctionPreamble(s, property->name(), + cpythonSetterFunctionName(property, context.metaClass()), + property->type(), context); + + s << INDENT << "auto cppOut = " << CPP_SELF_VAR << "->" << property->read() << "();\n" + << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut);\n" + << INDENT << "if (PyErr_Occurred())\n"; + { + Indentation indent(INDENT); + s << INDENT << "return -1;\n"; + } + s << INDENT << CPP_SELF_VAR << "->" << property->write() << "(cppOut);\n" + << INDENT << "return 0;\n}\n\n"; +} + void CppGenerator::writeRichCompareFunction(QTextStream &s, const GeneratorContext &context) { const AbstractMetaClass *metaClass = context.metaClass(); diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h index 1cc6c1ca0..8c56dd758 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.h +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h @@ -290,9 +290,20 @@ private: void writeGetterFunction(QTextStream &s, const AbstractMetaField *metaField, const GeneratorContext &context); + void writeGetterFunction(QTextStream &s, + const QPropertySpec *property, + const GeneratorContext &context); + void writeSetterFunctionPreamble(QTextStream &s, + const QString &name, + const QString &funcName, + const AbstractMetaType *type, + const GeneratorContext &context); void writeSetterFunction(QTextStream &s, const AbstractMetaField *metaField, const GeneratorContext &context); + void writeSetterFunction(QTextStream &s, + const QPropertySpec *property, + const GeneratorContext &context); void writeRichCompareFunction(QTextStream &s, const GeneratorContext &context); diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index ff1478d58..df8bf392a 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -31,6 +31,7 @@ #include <abstractmetalang.h> #include <messages.h> #include "overloaddata.h" +#include "propertyspec.h" #include <reporthandler.h> #include <typedatabase.h> #include <abstractmetabuilder.h> @@ -452,14 +453,38 @@ QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClass * return cpythonBaseName(metaClass) + QLatin1String("_getattro"); } +QString ShibokenGenerator::cpythonGetterFunctionName(const QString &name, + const AbstractMetaClass *enclosingClass) +{ + return cpythonBaseName(enclosingClass) + QStringLiteral("_get_") + name; +} + +QString ShibokenGenerator::cpythonSetterFunctionName(const QString &name, + const AbstractMetaClass *enclosingClass) +{ + return cpythonBaseName(enclosingClass) + QStringLiteral("_set_") + name; +} + QString ShibokenGenerator::cpythonGetterFunctionName(const AbstractMetaField *metaField) { - return QStringLiteral("%1_get_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name()); + return cpythonGetterFunctionName(metaField->name(), metaField->enclosingClass()); } QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField *metaField) { - return QStringLiteral("%1_set_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name()); + return cpythonSetterFunctionName(metaField->name(), metaField->enclosingClass()); +} + +QString ShibokenGenerator::cpythonGetterFunctionName(const QPropertySpec *property, + const AbstractMetaClass *metaClass) +{ + return cpythonGetterFunctionName(property->name(), metaClass); +} + +QString ShibokenGenerator::cpythonSetterFunctionName(const QPropertySpec *property, + const AbstractMetaClass *metaClass) +{ + return cpythonSetterFunctionName(property->name(), metaClass); } static QString cpythonEnumFlagsName(const QString &moduleName, diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h index da0c16851..83e7cf5b9 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h @@ -53,6 +53,7 @@ extern const char *END_ALLOW_THREADS; class DocParser; class CodeSnip; +class QPropertySpec; class OverloadData; struct GeneratorClassInfoCacheEntry; @@ -308,9 +309,9 @@ protected: static QString cpythonBaseName(const AbstractMetaClass *metaClass); static QString cpythonBaseName(const TypeEntry *type); - QString cpythonBaseName(const AbstractMetaType *type); - QString cpythonTypeName(const AbstractMetaClass *metaClass); - QString cpythonTypeName(const TypeEntry *type); + static QString cpythonBaseName(const AbstractMetaType *type); + static QString cpythonTypeName(const AbstractMetaClass *metaClass); + static QString cpythonTypeName(const TypeEntry *type); QString cpythonTypeNameExt(const TypeEntry *type) const; QString cpythonTypeNameExt(const AbstractMetaType *type) const; QString cpythonCheckFunction(const TypeEntry *type, bool genericNumberType = false); @@ -341,8 +342,12 @@ protected: QString cpythonGettersSettersDefinitionName(const AbstractMetaClass *metaClass); static QString cpythonGetattroFunctionName(const AbstractMetaClass *metaClass); static QString cpythonSetattroFunctionName(const AbstractMetaClass *metaClass); - QString cpythonGetterFunctionName(const AbstractMetaField *metaField); - QString cpythonSetterFunctionName(const AbstractMetaField *metaField); + static QString cpythonGetterFunctionName(const AbstractMetaField *metaField); + static QString cpythonSetterFunctionName(const AbstractMetaField *metaField); + static QString cpythonGetterFunctionName(const QPropertySpec *property, + const AbstractMetaClass *metaClass); + static QString cpythonSetterFunctionName(const QPropertySpec *property, + const AbstractMetaClass *metaClass); QString cpythonWrapperCPtr(const AbstractMetaClass *metaClass, const QString &argName = QLatin1String("self")) const; QString cpythonWrapperCPtr(const AbstractMetaType *metaType, const QString &argName) const; @@ -461,6 +466,11 @@ protected: static QStringList m_knownPythonTypes; private: + static QString cpythonGetterFunctionName(const QString &name, + const AbstractMetaClass *enclosingClass); + static QString cpythonSetterFunctionName(const QString &name, + const AbstractMetaClass *enclosingClass); + static const GeneratorClassInfoCacheEntry &getGeneratorClassInfo(const AbstractMetaClass *scope); static FunctionGroups getFunctionGroupsImpl(const AbstractMetaClass *scope); static bool classNeedsGetattroFunctionImpl(const AbstractMetaClass *metaClass); diff --git a/sources/shiboken2/tests/libsample/pen.cpp b/sources/shiboken2/tests/libsample/pen.cpp index b08721f79..1f39e7cbb 100644 --- a/sources/shiboken2/tests/libsample/pen.cpp +++ b/sources/shiboken2/tests/libsample/pen.cpp @@ -69,3 +69,13 @@ int Pen::ctorType() void Pen::drawLine(int x1, int y1, int x2, int y2, RenderHints renderHints) { } + +Pen::RenderHints Pen::getRenderHints() const +{ + return m_renderHints; +} + +void Pen::setRenderHints(RenderHints h) +{ + m_renderHints = h; +} diff --git a/sources/shiboken2/tests/libsample/pen.h b/sources/shiboken2/tests/libsample/pen.h index 6b3bf9f1a..20977fdeb 100644 --- a/sources/shiboken2/tests/libsample/pen.h +++ b/sources/shiboken2/tests/libsample/pen.h @@ -60,8 +60,13 @@ public: void drawLine(int x1, int y1, int x2, int y2, RenderHints renderHints = {}); int ctorType(); + + RenderHints getRenderHints() const; + void setRenderHints(RenderHints h); + private: int m_ctor; + RenderHints m_renderHints = None; }; #endif diff --git a/sources/shiboken2/tests/samplebinding/pen_test.py b/sources/shiboken2/tests/samplebinding/pen_test.py index 89abf4d54..ff6ee5e0e 100644 --- a/sources/shiboken2/tests/samplebinding/pen_test.py +++ b/sources/shiboken2/tests/samplebinding/pen_test.py @@ -65,7 +65,19 @@ class TestPen(unittest.TestCase): self.assertEqual(pen.ctorType(), Pen.ColorCtor) pen.drawLine(0, 0, 5, 5) + def testPenRenderHintsProperty(self): + """Exercise the generated property setter and getters, checking + against the C++ getter/setter functions.""" + pen = Pen(1) + self.assertEqual(pen.getRenderHints(), Pen.RenderHints.None_) + self.assertEqual(pen.renderHints, Pen.RenderHints.None_) + pen.renderHints = Pen.RenderHints.TextAntialiasing + self.assertEqual(pen.getRenderHints(), Pen.RenderHints.TextAntialiasing) + self.assertEqual(pen.renderHints, Pen.RenderHints.TextAntialiasing) + pen.setRenderHints(Pen.RenderHints.Antialiasing) + self.assertEqual(pen.getRenderHints(), Pen.RenderHints.Antialiasing) + self.assertEqual(pen.renderHints, Pen.RenderHints.Antialiasing) + if __name__ == '__main__': unittest.main() - diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index 132bff4ed..73f8542fc 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -2342,6 +2342,7 @@ <value-type name="Pen"> <enum-type identified-by-value="EnumCtor"/> <enum-type name="RenderHints"/> + <property type="RenderHints" name="renderHints" get="getRenderHints" set="setRenderHints"/> </value-type> <value-type name="CtorConvRule"> |