diff options
author | Hugo Parente Lima <hugo.pl@gmail.com> | 2010-09-15 10:52:54 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-08 16:05:59 -0300 |
commit | c2042f5a384d9f47afdcc260e1efdd56f283ce5d (patch) | |
tree | 2c492ddbe062dade923ff3b7a875387e14818ac6 | |
parent | 889cbf56244075eda371ad46a8b483916d587716 (diff) |
Fix bug#347 - "Setting properties in constructors gives incorrect results"
Reviewer: Luciano Wolf <luciano.wolf@openbossa.org>
Renato Araújo <renato.filho@openbossa.org>
-rw-r--r-- | cppgenerator.cpp | 139 | ||||
-rw-r--r-- | cppgenerator.h | 1 |
2 files changed, 36 insertions, 104 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp index f264a1ea2..a37ea4145 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -756,6 +756,26 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun if (needsOverloadId) s << INDENT << "int overloadId = -1;" << endl; + QSet<QString> argNamesSet; + if (usePySideExtensions() && metaClass->isQObject()) { + // Write argNames variable with all known argument names. + foreach (const AbstractMetaFunction* func, overloadData.overloads()) { + foreach (const AbstractMetaArgument* arg, func->arguments()) { + if (arg->defaultValueExpression().isEmpty() || func->argumentRemoved(arg->argumentIndex() + 1)) + continue; + argNamesSet << arg->name(); + } + } + QStringList argNamesList = argNamesSet.toList(); + qSort(argNamesList.begin(), argNamesList.end()); + if (argNamesList.isEmpty()) + s << INDENT << "const char** argNames = 0;" << endl; + else + s << INDENT << "const char* argNames[] = {\"" << argNamesList.join("\", \"") << "\"};" << endl; + s << INDENT << "const QMetaObject* metaObject;" << endl; + } + + s << INDENT << "SbkBaseWrapper* sbkSelf = reinterpret_cast<SbkBaseWrapper*>(self);" << endl; if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { @@ -794,12 +814,8 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << endl; - if (metaClass->isQObject() || overloadData.hasArgumentWithDefaultValue()) { - // Check usage of unknown named arguments - writeNamedArgumentsCheck(s, overloadData); - if (!metaClass->isQObject()) - s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl; - } + if (!metaClass->isQObject() && overloadData.hasArgumentWithDefaultValue()) + s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl; if (overloadData.maxArgs() > 0) { s << endl << INDENT << "int numArgs = "; writeArgumentsInitializer(s, overloadData); @@ -833,46 +849,14 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << INDENT << "BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl; // Create metaObject and register signal/slot - if (metaClass->isQObject()) { - if (usePySideExtensions()) - s << INDENT << "PySide::signalUpdateSource(self);" << endl; - - s << INDENT << "cptr->metaObject();" << endl; - - if (metaClass->isQObject()) { - s << INDENT << "for (std::vector<PyObject*>::size_type i = 0; i < propertyKeys.size(); i++) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "const char* propName = PyString_AS_STRING(propertyKeys[i]);" << endl; - s << INDENT << "const QMetaObject* mo = cptr->metaObject();" << endl; - s << INDENT << "if (mo->indexOfProperty(propName) != -1) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "cptr->setProperty(propName, "; - s << "Shiboken::Converter<QVariant>::toCpp(PyDict_GetItem(kwds, propertyKeys[i])));" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "QString signalSignature = QString(\"%1()\").arg(propName);" << endl; - s << INDENT << "if (mo->indexOfSignal(qPrintable(signalSignature)) != -1) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "signalSignature = '2' + signalSignature;" << endl; - s << INDENT << "PySide::signal_connect(self, qPrintable(signalSignature), PyDict_GetItem(kwds, propertyKeys[i]));" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "delete cptr;" << endl; - s << INDENT << "PyErr_Format(PyExc_AttributeError, \"'%s' is not a Qt property or a signal\", propName);" << endl; - s << INDENT << "return -1;" << endl; - } - s << INDENT << "};" << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << '}' << endl; + if (metaClass->isQObject() && usePySideExtensions()) { + s << endl << INDENT << "// QObject setup" << endl; + s << INDENT << "PySide::signalUpdateSource(self);" << endl; + s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties" << endl; + s << INDENT << "if (kwds && !PySide::fillQtProperties(self, metaObject, kwds, argNames, " << argNamesSet.count() << "))" << endl; + { + Indentation indentation(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl; } } @@ -1067,8 +1051,6 @@ void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunction s << INDENT << "int overloadId = -1;" << endl; if (usesNamedArguments) { - // Check usage of unknown named arguments - writeNamedArgumentsCheck(s, overloadData); s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl; } @@ -1165,60 +1147,6 @@ void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunction s << '}' << endl << endl; } -void CppGenerator::writeNamedArgumentsCheck(QTextStream& s, OverloadData& overloadData) -{ - // Check usage of unknown named arguments - QSet<QString> argNamesSet; - foreach (const AbstractMetaFunction* func, overloadData.overloads()) { - foreach (const AbstractMetaArgument* arg, func->arguments()) { - if (arg->defaultValueExpression().isEmpty() - || func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - argNamesSet << QString("\"%1\"").arg(arg->name()); - } - } - QStringList argNamesList = argNamesSet.toList(); - qSort(argNamesList.begin(), argNamesList.end()); - - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - bool ownerClassIsQObject = rfunc->ownerClass() && rfunc->ownerClass()->isQObject() && rfunc->isConstructor(); - if (overloadData.hasArgumentWithDefaultValue() || (ownerClassIsQObject && rfunc->isConstructor())) { - s << INDENT << "std::vector<PyObject*> propertyKeys;" << endl << endl; - s << INDENT << "// Check existence of named argument." << endl; - s << INDENT << "if (kwds) {" << endl; - { - Indentation indent(INDENT); - if (argNamesList.size() > 0) - s << INDENT << "std::string argNames[] = { " << argNamesList.join(", ") << " };" << endl; - s << INDENT << "PyObject* keys = PyDict_Keys(kwds);" << endl; - s << INDENT << "Shiboken::AutoDecRef auto_keys(keys);" << endl; - s << INDENT << "for (int i = 0; i < PyList_GET_SIZE(keys); ++i) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject* argName = PyList_GET_ITEM(keys, i);" << endl; - if (argNamesList.size() > 0) { - s << INDENT << "if (!std::binary_search(argNames, argNames + " << argNamesList.count(); - s << ", std::string(PyString_AS_STRING(argName)))) {" << endl; - } - { - Indentation indent(INDENT); - if (ownerClassIsQObject) { - s << INDENT << "propertyKeys.push_back(argName);" << endl; - } else { - s << INDENT << "PyErr_Format(PyExc_TypeError, \"" << fullPythonFunctionName(overloadData.referenceFunction()); - s << "(): got an unexpected keyword argument '%s'\", PyString_AS_STRING(argName));" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - } - if (argNamesList.size() > 0) - s << INDENT << '}' << endl; - } - s << INDENT << '}' << endl; - } - } - s << INDENT << '}' << endl; -} - void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData) { const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); @@ -3471,11 +3399,16 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass s << INDENT << '}' << endl; } s << INDENT << "PyObject* attr = PyObject_GenericGetAttr(self, name);" << endl; - if (usePySideExtensions()) { + if (usePySideExtensions() && metaClass->isQObject()) { s << INDENT << "if (attr && PySide::isQPropertyType(attr)) {" << endl; { Indentation indent(INDENT); s << INDENT << "PyObject *value = PySide::qproperty_get(attr, self);" << endl; + s << INDENT << "if (!value)" << endl; + { + Indentation indentation(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } s << INDENT << "Py_DECREF(attr);" << endl; s << INDENT << "Py_INCREF(value);" << endl; s << INDENT << "attr = value;" << endl; diff --git a/cppgenerator.h b/cppgenerator.h index 1d2d122ca..b4d68dc45 100644 --- a/cppgenerator.h +++ b/cppgenerator.h @@ -53,7 +53,6 @@ private: void writeMinimalConstructorCallArguments(QTextStream& s, const AbstractMetaType* type); void writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList overloads); void writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData); - void writeNamedArgumentsCheck(QTextStream& s, OverloadData& overloadData); void writeCppSelfDefinition(QTextStream& s, const AbstractMetaFunction* func); void writeErrorSection(QTextStream& s, OverloadData& overloadData); |