aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-09-24 11:10:24 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-09-28 11:19:29 +0200
commitcb073f6eee9e21b62d7c14e0357beb6cecf33e31 (patch)
tree36a32fae9cf3f9c8d505a8dbaf31b228b08844f9
parent5a7429cc895824a4eafd27e1a5c95b40bba86bdf (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>
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h5
-rw-r--r--sources/shiboken2/ApiExtractor/propertyspec.cpp3
-rw-r--r--sources/shiboken2/ApiExtractor/propertyspec.h6
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h2
-rw-r--r--sources/shiboken2/ApiExtractor/typesystemparser.cpp5
-rw-r--r--sources/shiboken2/doc/typesystem_manipulating_objects.rst59
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp130
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.h11
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp29
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.h20
-rw-r--r--sources/shiboken2/tests/libsample/pen.cpp10
-rw-r--r--sources/shiboken2/tests/libsample/pen.h5
-rw-r--r--sources/shiboken2/tests/samplebinding/pen_test.py14
-rw-r--r--sources/shiboken2/tests/samplebinding/typesystem_sample.xml1
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">