@@ -79,7 +79,7 QString rename_operator(const QString &oper) | |||||
79 | operator_names->insert("&", "__and__"); |
|
79 | operator_names->insert("&", "__and__"); | |
80 | operator_names->insert("|", "__or__"); |
|
80 | operator_names->insert("|", "__or__"); | |
81 | operator_names->insert("^", "__xor__"); |
|
81 | operator_names->insert("^", "__xor__"); | |
82 |
operator_names->insert("~", "__ |
|
82 | operator_names->insert("~", "__invert__"); | |
83 | operator_names->insert("<<", "__lshift__"); |
|
83 | operator_names->insert("<<", "__lshift__"); | |
84 | operator_names->insert(">>", "__rshift__"); |
|
84 | operator_names->insert(">>", "__rshift__"); | |
85 |
|
85 | |||
@@ -106,12 +106,12 QString rename_operator(const QString &oper) | |||||
106 | operator_names->insert("--", "decrement"); |
|
106 | operator_names->insert("--", "decrement"); | |
107 |
|
107 | |||
108 | // compare |
|
108 | // compare | |
109 |
operator_names->insert("<", " |
|
109 | operator_names->insert("<", "__lt__"); | |
110 |
operator_names->insert(">", " |
|
110 | operator_names->insert(">", "__gt__"); | |
111 |
operator_names->insert("<=", "le |
|
111 | operator_names->insert("<=", "__le__"); | |
112 |
operator_names->insert(">=", "g |
|
112 | operator_names->insert(">=", "__ge__"); | |
113 |
operator_names->insert("!=", " |
|
113 | operator_names->insert("!=", "__ne__"); | |
114 |
operator_names->insert("==", " |
|
114 | operator_names->insert("==", "__eq__"); | |
115 |
|
115 | |||
116 | // other |
|
116 | // other | |
117 | operator_names->insert("[]", "subscript"); |
|
117 | operator_names->insert("[]", "subscript"); |
@@ -849,6 +849,16 AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString & | |||||
849 | return returned; |
|
849 | return returned; | |
850 | } |
|
850 | } | |
851 |
|
851 | |||
|
852 | bool AbstractMetaClass::hasDefaultIsNull() const | |||
|
853 | { | |||
|
854 | foreach(const AbstractMetaFunction* fun, queryFunctionsByName("isNull")) { | |||
|
855 | if (fun->actualMinimumArgumentCount()==0) { | |||
|
856 | return true; | |||
|
857 | } | |||
|
858 | } | |||
|
859 | return false; | |||
|
860 | } | |||
|
861 | ||||
852 | /******************************************************************************* |
|
862 | /******************************************************************************* | |
853 | * Returns all reference count modifications for any function in the class |
|
863 | * Returns all reference count modifications for any function in the class | |
854 | */ |
|
864 | */ |
@@ -796,6 +796,8 public: | |||||
796 | void setHasCloneOperator(bool on) { m_has_clone_operator = on; } |
|
796 | void setHasCloneOperator(bool on) { m_has_clone_operator = on; } | |
797 | bool hasCloneOperator() const { return m_has_clone_operator; } |
|
797 | bool hasCloneOperator() const { return m_has_clone_operator; } | |
798 |
|
798 | |||
|
799 | bool hasDefaultIsNull() const; | |||
|
800 | ||||
799 | void addPropertySpec(QPropertySpec *spec) { m_property_specs << spec; } |
|
801 | void addPropertySpec(QPropertySpec *spec) { m_property_specs << spec; } | |
800 | QList<QPropertySpec *> propertySpecs() const { return m_property_specs; } |
|
802 | QList<QPropertySpec *> propertySpecs() const { return m_property_specs; } | |
801 |
|
803 |
@@ -55,6 +55,64 void maybeDeclareMetaType(QTextStream &stream, const QString &typeName, | |||||
55 | QSet<QString> ®isteredTypeNames); |
|
55 | QSet<QString> ®isteredTypeNames); | |
56 | bool hasDefaultConstructor(const AbstractMetaClass *meta_class); |
|
56 | bool hasDefaultConstructor(const AbstractMetaClass *meta_class); | |
57 |
|
57 | |||
|
58 | static QStringList getOperatorCodes(const AbstractMetaClass* cls) { | |||
|
59 | QSet<QString> operatorCodes; | |||
|
60 | AbstractMetaFunctionList returned; | |||
|
61 | AbstractMetaFunctionList functions = cls->functions(); | |||
|
62 | foreach (AbstractMetaFunction *function, functions) { | |||
|
63 | if (function->originalName().startsWith("operator")) { | |||
|
64 | QString op = function->originalName().mid(8); | |||
|
65 | operatorCodes.insert(op); | |||
|
66 | } | |||
|
67 | } | |||
|
68 | QSet<QString> r; | |||
|
69 | foreach(QString op, operatorCodes.toList()) { | |||
|
70 | if (op == ">" || op == "<" || op == ">=" || op == "<=" || op == "==" || op == "!=") { | |||
|
71 | r.insert("PythonQt::Type_RichCompare"); | |||
|
72 | } else if (op == "+") { | |||
|
73 | r.insert("PythonQt::Type_Add"); | |||
|
74 | } else if (op == "-") { | |||
|
75 | r.insert("PythonQt::Type_Subtract"); | |||
|
76 | } else if (op == "/") { | |||
|
77 | r.insert("PythonQt::Type_Divide"); | |||
|
78 | } else if (op == "*") { | |||
|
79 | r.insert("PythonQt::Type_Multiply"); | |||
|
80 | } else if (op == "%") { | |||
|
81 | r.insert("PythonQt::Type_Mod"); | |||
|
82 | } else if (op == "&") { | |||
|
83 | r.insert("PythonQt::Type_And"); | |||
|
84 | } else if (op == "|") { | |||
|
85 | r.insert("PythonQt::Type_Or"); | |||
|
86 | } else if (op == "^") { | |||
|
87 | r.insert("PythonQt::Type_Xor"); | |||
|
88 | } else if (op == "~") { | |||
|
89 | r.insert("PythonQt::Type_Invert"); | |||
|
90 | ||||
|
91 | } else if (op == "+=") { | |||
|
92 | r.insert("PythonQt::Type_InplaceAdd"); | |||
|
93 | } else if (op == "-=") { | |||
|
94 | r.insert("PythonQt::Type_InplaceSubtract"); | |||
|
95 | } else if (op == "/=") { | |||
|
96 | r.insert("PythonQt::Type_InplaceDivide"); | |||
|
97 | } else if (op == "*=") { | |||
|
98 | r.insert("PythonQt::Type_InplaceMultiply"); | |||
|
99 | } else if (op == "%=") { | |||
|
100 | r.insert("PythonQt::Type_InplaceMod"); | |||
|
101 | } else if (op == "&=") { | |||
|
102 | r.insert("PythonQt::Type_InplaceAnd"); | |||
|
103 | } else if (op == "|=") { | |||
|
104 | r.insert("PythonQt::Type_InplaceOr"); | |||
|
105 | } else if (op == "^=") { | |||
|
106 | r.insert("PythonQt::Type_InplaceXor"); | |||
|
107 | } | |||
|
108 | } | |||
|
109 | if (cls->hasDefaultIsNull()) { | |||
|
110 | r.insert("PythonQt::Type_NonZero"); | |||
|
111 | } | |||
|
112 | QStringList result = r.toList(); | |||
|
113 | return result; | |||
|
114 | } | |||
|
115 | ||||
58 | void SetupGenerator::generate() |
|
116 | void SetupGenerator::generate() | |
59 | { |
|
117 | { | |
60 | AbstractMetaClassList classes_with_polymorphic_id; |
|
118 | AbstractMetaClassList classes_with_polymorphic_id; | |
@@ -138,11 +196,15 void SetupGenerator::generate() | |||||
138 | } else { |
|
196 | } else { | |
139 | shellCreator = ", NULL"; |
|
197 | shellCreator = ", NULL"; | |
140 | } |
|
198 | } | |
|
199 | QString operatorCodes = getOperatorCodes(cls).join("|"); | |||
|
200 | if (operatorCodes.isEmpty()) { | |||
|
201 | operatorCodes = "0"; | |||
|
202 | } | |||
141 | if (cls->isQObject()) { |
|
203 | if (cls->isQObject()) { | |
142 | s << "PythonQt::priv()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module);" << endl; |
|
204 | s << "PythonQt::priv()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl; | |
143 | } else { |
|
205 | } else { | |
144 | QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():""; |
|
206 | QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():""; | |
145 | s << "PythonQt::priv()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module);" << endl; |
|
207 | s << "PythonQt::priv()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl; | |
146 | } |
|
208 | } | |
147 | foreach(AbstractMetaClass* interface, cls->interfaces()) { |
|
209 | foreach(AbstractMetaClass* interface, cls->interfaces()) { | |
148 | // the interface might be our own class... (e.g. QPaintDevice) |
|
210 | // the interface might be our own class... (e.g. QPaintDevice) |
@@ -282,6 +282,9 void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_c | |||||
282 | if (meta_class->hasDefaultToStringFunction() || meta_class->hasToStringCapability()) { |
|
282 | if (meta_class->hasDefaultToStringFunction() || meta_class->hasToStringCapability()) { | |
283 | s << " QString py_toString(" << meta_class->qualifiedCppName() << "*);" << endl; |
|
283 | s << " QString py_toString(" << meta_class->qualifiedCppName() << "*);" << endl; | |
284 | } |
|
284 | } | |
|
285 | if (meta_class->hasDefaultIsNull()) { | |||
|
286 | s << " bool __nonzero__(" << meta_class->qualifiedCppName() << "* obj) { return !obj->isNull(); }" << endl; | |||
|
287 | } | |||
285 |
|
288 | |||
286 | // Field accessors |
|
289 | // Field accessors | |
287 | foreach (const AbstractMetaField *field, meta_class->fields()) { |
|
290 | foreach (const AbstractMetaField *field, meta_class->fields()) { |
@@ -227,7 +227,7 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, | |||||
227 | _p->registerClass(metaobject, package, wrapperCreator, shell); |
|
227 | _p->registerClass(metaobject, package, wrapperCreator, shell); | |
228 | } |
|
228 | } | |
229 |
|
229 | |||
230 | void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module) |
|
230 | void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots) | |
231 | { |
|
231 | { | |
232 | // we register all classes in the hierarchy |
|
232 | // we register all classes in the hierarchy | |
233 | const QMetaObject* m = metaobject; |
|
233 | const QMetaObject* m = metaobject; | |
@@ -235,6 +235,7 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* p | |||||
235 | while (m) { |
|
235 | while (m) { | |
236 | PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className()); |
|
236 | PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className()); | |
237 | if (!info->pythonQtClassWrapper()) { |
|
237 | if (!info->pythonQtClassWrapper()) { | |
|
238 | info->setTypeSlots(typeSlots); | |||
238 | info->setupQObject(m); |
|
239 | info->setupQObject(m); | |
239 | createPythonQtClassWrapper(info, package, module); |
|
240 | createPythonQtClassWrapper(info, package, module); | |
240 | if (m->superClass()) { |
|
241 | if (m->superClass()) { | |
@@ -1130,10 +1131,11 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTyp | |||||
1130 | } |
|
1131 | } | |
1131 | } |
|
1132 | } | |
1132 |
|
1133 | |||
1133 | void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module) |
|
1134 | void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots) | |
1134 | { |
|
1135 | { | |
1135 | PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName); |
|
1136 | PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName); | |
1136 | if (!info->pythonQtClassWrapper()) { |
|
1137 | if (!info->pythonQtClassWrapper()) { | |
|
1138 | info->setTypeSlots(typeSlots); | |||
1137 | info->setupCPPObject(typeName); |
|
1139 | info->setupCPPObject(typeName); | |
1138 | createPythonQtClassWrapper(info, package, module); |
|
1140 | createPythonQtClassWrapper(info, package, module); | |
1139 | } |
|
1141 | } |
@@ -96,6 +96,42 public: | |||||
96 | ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal |
|
96 | ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal | |
97 | }; |
|
97 | }; | |
98 |
|
98 | |||
|
99 | //! flags that tell PythonQt which operators to expect on the registered type | |||
|
100 | enum TypeSlots { | |||
|
101 | Type_Add = 1, | |||
|
102 | Type_Subtract = 1 << 1, | |||
|
103 | Type_Multiply = 1 << 2, | |||
|
104 | Type_Divide = 1 << 3, | |||
|
105 | Type_Mod = 1 << 4, | |||
|
106 | Type_And = 1 << 5, | |||
|
107 | Type_Or = 1 << 6, | |||
|
108 | Type_Xor = 1 << 7, | |||
|
109 | Type_LShift = 1 << 8, | |||
|
110 | Type_RShift = 1 << 9, | |||
|
111 | ||||
|
112 | Type_InplaceAdd = 1 << 10, | |||
|
113 | Type_InplaceSubtract = 1 << 11, | |||
|
114 | Type_InplaceMultiply = 1 << 12, | |||
|
115 | Type_InplaceDivide = 1 << 13, | |||
|
116 | Type_InplaceMod = 1 << 14, | |||
|
117 | Type_InplaceAnd = 1 << 15, | |||
|
118 | Type_InplaceOr = 1 << 16, | |||
|
119 | Type_InplaceXor = 1 << 17, | |||
|
120 | Type_InplaceLShift = 1 << 18, | |||
|
121 | Type_InplaceRShift = 1 << 19, | |||
|
122 | ||||
|
123 | // Not yet needed/nicely mappable/generated... | |||
|
124 | //Type_Positive = 1 << 29, | |||
|
125 | //Type_Negative = 1 << 29, | |||
|
126 | //Type_Abs = 1 << 29, | |||
|
127 | //Type_Hash = 1 << 29, | |||
|
128 | ||||
|
129 | Type_Invert = 1 << 29, | |||
|
130 | Type_RichCompare = 1 << 30, | |||
|
131 | Type_NonZero = 1 << 31, | |||
|
132 | ||||
|
133 | }; | |||
|
134 | ||||
99 | //! initialize the python qt binding (flags are a or combination of InitFlags), if \c pythonQtModuleName is given |
|
135 | //! initialize the python qt binding (flags are a or combination of InitFlags), if \c pythonQtModuleName is given | |
100 | //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used. |
|
136 | //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used. | |
101 | //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible. |
|
137 | //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible. | |
@@ -432,7 +468,7 public: | |||||
432 | //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well) |
|
468 | //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well) | |
433 | /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject, |
|
469 | /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject, | |
434 | you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */ |
|
470 | you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */ | |
435 | void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL); |
|
471 | void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0); | |
436 |
|
472 | |||
437 | //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants |
|
473 | //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants | |
438 | //! (ownership of wrapper is passed to PythonQt) |
|
474 | //! (ownership of wrapper is passed to PythonQt) | |
@@ -442,7 +478,7 public: | |||||
442 | All slots that take a pointer to typeName as the first argument will be callable from Python on |
|
478 | All slots that take a pointer to typeName as the first argument will be callable from Python on | |
443 | a variant object that contains such a type. |
|
479 | a variant object that contains such a type. | |
444 | */ |
|
480 | */ | |
445 | void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL); |
|
481 | void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0); | |
446 |
|
482 | |||
447 | //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes |
|
483 | //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes | |
448 | //! and it will register the classes when it first sees a pointer to such a derived class |
|
484 | //! and it will register the classes when it first sees a pointer to such a derived class |
@@ -57,6 +57,7 PythonQtClassInfo::PythonQtClassInfo() { | |||||
57 | _pythonQtClassWrapper = NULL; |
|
57 | _pythonQtClassWrapper = NULL; | |
58 | _shellSetInstanceWrapperCB = NULL; |
|
58 | _shellSetInstanceWrapperCB = NULL; | |
59 | _metaTypeId = -1; |
|
59 | _metaTypeId = -1; | |
|
60 | _typeSlots = 0; | |||
60 | _isQObject = false; |
|
61 | _isQObject = false; | |
61 | _enumsCreated = false; |
|
62 | _enumsCreated = false; | |
62 | } |
|
63 | } |
@@ -104,6 +104,11 public: | |||||
104 | //! setup as a CPP (non-QObject), taking the classname |
|
104 | //! setup as a CPP (non-QObject), taking the classname | |
105 | void setupCPPObject(const QByteArray& classname); |
|
105 | void setupCPPObject(const QByteArray& classname); | |
106 |
|
106 | |||
|
107 | //! set the type capabilities | |||
|
108 | void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; } | |||
|
109 | //! get the type capabilities | |||
|
110 | int typeSlots() const { return _typeSlots; } | |||
|
111 | ||||
107 | //! get the Python method definition for a given slot name (without return type and signature) |
|
112 | //! get the Python method definition for a given slot name (without return type and signature) | |
108 | PythonQtMemberInfo member(const char* member); |
|
113 | PythonQtMemberInfo member(const char* member); | |
109 |
|
114 | |||
@@ -244,6 +249,7 private: | |||||
244 | PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB; |
|
249 | PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB; | |
245 |
|
250 | |||
246 | int _metaTypeId; |
|
251 | int _metaTypeId; | |
|
252 | int _typeSlots; | |||
247 |
|
253 | |||
248 | bool _isQObject; |
|
254 | bool _isQObject; | |
249 | bool _enumsCreated; |
|
255 | bool _enumsCreated; |
@@ -48,6 +48,167 | |||||
48 | #include "PythonQtConversion.h" |
|
48 | #include "PythonQtConversion.h" | |
49 | #include "PythonQtInstanceWrapper.h" |
|
49 | #include "PythonQtInstanceWrapper.h" | |
50 |
|
50 | |||
|
51 | static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper) | |||
|
52 | { | |||
|
53 | PyObject* result = NULL; | |||
|
54 | static QByteArray memberName = "__invert__"; | |||
|
55 | PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName); | |||
|
56 | if (opSlot._type == PythonQtMemberInfo::Slot) { | |||
|
57 | result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr); | |||
|
58 | } | |||
|
59 | return result; | |||
|
60 | } | |||
|
61 | ||||
|
62 | static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper) | |||
|
63 | { | |||
|
64 | int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1; | |||
|
65 | if (result) { | |||
|
66 | static QByteArray memberName = "__nonzero__"; | |||
|
67 | PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName); | |||
|
68 | if (opSlot._type == PythonQtMemberInfo::Slot) { | |||
|
69 | PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr); | |||
|
70 | if (resultObj == Py_False) { | |||
|
71 | result = 0; | |||
|
72 | } | |||
|
73 | Py_XDECREF(resultObj); | |||
|
74 | } | |||
|
75 | } | |||
|
76 | return result; | |||
|
77 | } | |||
|
78 | ||||
|
79 | ||||
|
80 | static PyObject* PythonQtInstanceWrapper_binaryfunc(PythonQtInstanceWrapper* wrapper, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray()) | |||
|
81 | { | |||
|
82 | PyObject* result = NULL; | |||
|
83 | PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName); | |||
|
84 | if (opSlot._type == PythonQtMemberInfo::Slot) { | |||
|
85 | // TODO get rid of tuple | |||
|
86 | PyObject* args = PyTuple_New(1); | |||
|
87 | Py_INCREF(other); | |||
|
88 | PyTuple_SET_ITEM(args, 0, other); | |||
|
89 | result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr); | |||
|
90 | Py_DECREF(args); | |||
|
91 | if (!result && !fallbackOpName.isEmpty()) { | |||
|
92 | // try fallback if we did not get a result | |||
|
93 | result = PythonQtInstanceWrapper_binaryfunc(wrapper, other, fallbackOpName); | |||
|
94 | } | |||
|
95 | } | |||
|
96 | return result; | |||
|
97 | } | |||
|
98 | ||||
|
99 | #define BINARY_OP(NAME) \ | |||
|
100 | static PyObject* PythonQtInstanceWrapper_ ## NAME(PythonQtInstanceWrapper* wrapper, PyObject* other) \ | |||
|
101 | { \ | |||
|
102 | static const QByteArray opName("__" #NAME "__"); \ | |||
|
103 | return PythonQtInstanceWrapper_binaryfunc(wrapper, other, opName); \ | |||
|
104 | } | |||
|
105 | ||||
|
106 | #define BINARY_OP_INPLACE(NAME) \ | |||
|
107 | static PyObject* PythonQtInstanceWrapper_i ## NAME(PythonQtInstanceWrapper* wrapper, PyObject* other) \ | |||
|
108 | { \ | |||
|
109 | static const QByteArray opName("__i" #NAME "__"); \ | |||
|
110 | static const QByteArray fallbackName("__" #NAME "__"); \ | |||
|
111 | return PythonQtInstanceWrapper_binaryfunc(wrapper, other, opName, fallbackName); \ | |||
|
112 | } | |||
|
113 | ||||
|
114 | BINARY_OP(add) | |||
|
115 | BINARY_OP(sub) | |||
|
116 | BINARY_OP(mul) | |||
|
117 | BINARY_OP(div) | |||
|
118 | BINARY_OP(and) | |||
|
119 | BINARY_OP(or) | |||
|
120 | BINARY_OP(xor) | |||
|
121 | BINARY_OP(mod) | |||
|
122 | BINARY_OP(lshift) | |||
|
123 | BINARY_OP(rshift) | |||
|
124 | ||||
|
125 | BINARY_OP_INPLACE(add) | |||
|
126 | BINARY_OP_INPLACE(sub) | |||
|
127 | BINARY_OP_INPLACE(mul) | |||
|
128 | BINARY_OP_INPLACE(div) | |||
|
129 | BINARY_OP_INPLACE(and) | |||
|
130 | BINARY_OP_INPLACE(or) | |||
|
131 | BINARY_OP_INPLACE(xor) | |||
|
132 | BINARY_OP_INPLACE(mod) | |||
|
133 | BINARY_OP_INPLACE(lshift) | |||
|
134 | BINARY_OP_INPLACE(rshift) | |||
|
135 | ||||
|
136 | static void initializeSlots(PythonQtClassWrapper* wrap) | |||
|
137 | { | |||
|
138 | int typeSlots = wrap->classInfo()->typeSlots(); | |||
|
139 | if (typeSlots) { | |||
|
140 | if (typeSlots & PythonQt::Type_Add) { | |||
|
141 | wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_add; | |||
|
142 | } | |||
|
143 | if (typeSlots & PythonQt::Type_Subtract) { | |||
|
144 | wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_sub; | |||
|
145 | } | |||
|
146 | if (typeSlots & PythonQt::Type_Multiply) { | |||
|
147 | wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul; | |||
|
148 | } | |||
|
149 | if (typeSlots & PythonQt::Type_Divide) { | |||
|
150 | wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div; | |||
|
151 | wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div; | |||
|
152 | } | |||
|
153 | if (typeSlots & PythonQt::Type_And) { | |||
|
154 | wrap->_base.as_number.nb_and = (binaryfunc)PythonQtInstanceWrapper_and; | |||
|
155 | } | |||
|
156 | if (typeSlots & PythonQt::Type_Or) { | |||
|
157 | wrap->_base.as_number.nb_or = (binaryfunc)PythonQtInstanceWrapper_or; | |||
|
158 | } | |||
|
159 | if (typeSlots & PythonQt::Type_Xor) { | |||
|
160 | wrap->_base.as_number.nb_xor = (binaryfunc)PythonQtInstanceWrapper_xor; | |||
|
161 | } | |||
|
162 | if (typeSlots & PythonQt::Type_Mod) { | |||
|
163 | wrap->_base.as_number.nb_remainder = (binaryfunc)PythonQtInstanceWrapper_mod; | |||
|
164 | } | |||
|
165 | if (typeSlots & PythonQt::Type_LShift) { | |||
|
166 | wrap->_base.as_number.nb_lshift = (binaryfunc)PythonQtInstanceWrapper_lshift; | |||
|
167 | } | |||
|
168 | if (typeSlots & PythonQt::Type_RShift) { | |||
|
169 | wrap->_base.as_number.nb_rshift = (binaryfunc)PythonQtInstanceWrapper_rshift; | |||
|
170 | } | |||
|
171 | ||||
|
172 | if (typeSlots & PythonQt::Type_InplaceAdd) { | |||
|
173 | wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_iadd; | |||
|
174 | } | |||
|
175 | if (typeSlots & PythonQt::Type_InplaceSubtract) { | |||
|
176 | wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_isub; | |||
|
177 | } | |||
|
178 | if (typeSlots & PythonQt::Type_InplaceMultiply) { | |||
|
179 | wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul; | |||
|
180 | } | |||
|
181 | if (typeSlots & PythonQt::Type_InplaceDivide) { | |||
|
182 | wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv; | |||
|
183 | wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv; | |||
|
184 | } | |||
|
185 | if (typeSlots & PythonQt::Type_InplaceAnd) { | |||
|
186 | wrap->_base.as_number.nb_inplace_and = (binaryfunc)PythonQtInstanceWrapper_iand; | |||
|
187 | } | |||
|
188 | if (typeSlots & PythonQt::Type_InplaceOr) { | |||
|
189 | wrap->_base.as_number.nb_inplace_or = (binaryfunc)PythonQtInstanceWrapper_ior; | |||
|
190 | } | |||
|
191 | if (typeSlots & PythonQt::Type_InplaceXor) { | |||
|
192 | wrap->_base.as_number.nb_inplace_xor = (binaryfunc)PythonQtInstanceWrapper_ixor; | |||
|
193 | } | |||
|
194 | if (typeSlots & PythonQt::Type_InplaceMod) { | |||
|
195 | wrap->_base.as_number.nb_inplace_remainder = (binaryfunc)PythonQtInstanceWrapper_imod; | |||
|
196 | } | |||
|
197 | if (typeSlots & PythonQt::Type_InplaceLShift) { | |||
|
198 | wrap->_base.as_number.nb_inplace_lshift = (binaryfunc)PythonQtInstanceWrapper_ilshift; | |||
|
199 | } | |||
|
200 | if (typeSlots & PythonQt::Type_InplaceRShift) { | |||
|
201 | wrap->_base.as_number.nb_inplace_rshift = (binaryfunc)PythonQtInstanceWrapper_irshift; | |||
|
202 | } | |||
|
203 | if (typeSlots & PythonQt::Type_Invert) { | |||
|
204 | wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert; | |||
|
205 | } | |||
|
206 | if (typeSlots & PythonQt::Type_NonZero) { | |||
|
207 | wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero; | |||
|
208 | } | |||
|
209 | } | |||
|
210 | } | |||
|
211 | ||||
51 | static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems) |
|
212 | static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems) | |
52 | { |
|
213 | { | |
53 | // call the default type alloc |
|
214 | // call the default type alloc | |
@@ -56,6 +217,7 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitem | |||||
56 | // take current class type, if we are called via newPythonQtClassWrapper() |
|
217 | // take current class type, if we are called via newPythonQtClassWrapper() | |
57 | PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj; |
|
218 | PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj; | |
58 | wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation(); |
|
219 | wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation(); | |
|
220 | initializeSlots(wrap); | |||
59 |
|
221 | |||
60 | return obj; |
|
222 | return obj; | |
61 | } |
|
223 | } |
@@ -183,6 +183,106 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args | |||||
183 | return 0; |
|
183 | return 0; | |
184 | } |
|
184 | } | |
185 |
|
185 | |||
|
186 | static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code) | |||
|
187 | { | |||
|
188 | bool validPtrs = false; | |||
|
189 | bool areSamePtrs = false; | |||
|
190 | if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) { | |||
|
191 | if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) { | |||
|
192 | validPtrs = true; | |||
|
193 | PythonQtInstanceWrapper* w1 = wrapper; | |||
|
194 | PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other; | |||
|
195 | // check pointers directly | |||
|
196 | if (w1->_wrappedPtr != NULL) { | |||
|
197 | if (w1->_wrappedPtr == w2->_wrappedPtr) { | |||
|
198 | areSamePtrs = true; | |||
|
199 | } | |||
|
200 | } else if (w1->_obj == w2->_obj) { | |||
|
201 | areSamePtrs = true; | |||
|
202 | } | |||
|
203 | } else if (other == Py_None) { | |||
|
204 | validPtrs = true; | |||
|
205 | if (wrapper->_obj || wrapper->_wrappedPtr) { | |||
|
206 | areSamePtrs = false; | |||
|
207 | } else { | |||
|
208 | areSamePtrs = true; | |||
|
209 | } | |||
|
210 | } | |||
|
211 | } | |||
|
212 | ||||
|
213 | if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) { | |||
|
214 | // shortcut if richcompare is not supported: | |||
|
215 | if (validPtrs && code == Py_EQ) { | |||
|
216 | return PythonQtConv::GetPyBool(areSamePtrs); | |||
|
217 | } else if (validPtrs && code == Py_NE) { | |||
|
218 | return PythonQtConv::GetPyBool(!areSamePtrs); | |||
|
219 | } | |||
|
220 | Py_INCREF(Py_NotImplemented); | |||
|
221 | return Py_NotImplemented; | |||
|
222 | } | |||
|
223 | ||||
|
224 | QByteArray memberName; | |||
|
225 | switch (code) { | |||
|
226 | case Py_LT: | |||
|
227 | { | |||
|
228 | static QByteArray name = "__lt__"; | |||
|
229 | memberName = name; | |||
|
230 | } | |||
|
231 | break; | |||
|
232 | ||||
|
233 | case Py_LE: | |||
|
234 | { | |||
|
235 | static QByteArray name = "__le__"; | |||
|
236 | memberName = name; | |||
|
237 | } | |||
|
238 | break; | |||
|
239 | ||||
|
240 | case Py_EQ: | |||
|
241 | { | |||
|
242 | static QByteArray name = "__eq__"; | |||
|
243 | memberName = name; | |||
|
244 | } | |||
|
245 | break; | |||
|
246 | ||||
|
247 | case Py_NE: | |||
|
248 | { | |||
|
249 | static QByteArray name = "__ne__"; | |||
|
250 | memberName = name; | |||
|
251 | } | |||
|
252 | break; | |||
|
253 | ||||
|
254 | case Py_GT: | |||
|
255 | { | |||
|
256 | static QByteArray name = "__gt__"; | |||
|
257 | memberName = name; | |||
|
258 | } | |||
|
259 | break; | |||
|
260 | ||||
|
261 | case Py_GE: | |||
|
262 | { | |||
|
263 | static QByteArray name = "__ge__"; | |||
|
264 | memberName = name; | |||
|
265 | } | |||
|
266 | break; | |||
|
267 | } | |||
|
268 | ||||
|
269 | PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName); | |||
|
270 | if (opSlot._type == PythonQtMemberInfo::Slot) { | |||
|
271 | // TODO get rid of tuple | |||
|
272 | PyObject* args = PyTuple_New(1); | |||
|
273 | Py_INCREF(other); | |||
|
274 | PyTuple_SET_ITEM(args, 0, other); | |||
|
275 | PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr); | |||
|
276 | Py_DECREF(args); | |||
|
277 | return result; | |||
|
278 | } else { | |||
|
279 | // not implemented, let python try something else! | |||
|
280 | Py_INCREF(Py_NotImplemented); | |||
|
281 | return Py_NotImplemented; | |||
|
282 | } | |||
|
283 | } | |||
|
284 | ||||
|
285 | ||||
186 | static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj) |
|
286 | static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj) | |
187 | { |
|
287 | { | |
188 | return PyString_FromString(obj->ob_type->tp_name); |
|
288 | return PyString_FromString(obj->ob_type->tp_name); | |
@@ -508,63 +608,7 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj) | |||||
508 | } |
|
608 | } | |
509 | } |
|
609 | } | |
510 |
|
610 | |||
511 |
static int PythonQtInstanceWrapper_ |
|
611 | static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj) | |
512 | { |
|
|||
513 | if (PyObject_TypeCheck(obj1, &PythonQtInstanceWrapper_Type) && |
|
|||
514 | PyObject_TypeCheck(obj2, &PythonQtInstanceWrapper_Type)) { |
|
|||
515 |
|
||||
516 | PythonQtInstanceWrapper* w1 = (PythonQtInstanceWrapper*)obj1; |
|
|||
517 | PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)obj2; |
|
|||
518 | // check pointers directly first: |
|
|||
519 | if (w1->_wrappedPtr != NULL) { |
|
|||
520 | if (w1->_wrappedPtr == w2->_wrappedPtr) { |
|
|||
521 | return 0; |
|
|||
522 | } |
|
|||
523 | } else if (w1->_obj == w2->_obj) { |
|
|||
524 | return 0; |
|
|||
525 | } |
|
|||
526 | const char* class1 = w1->classInfo()->className(); |
|
|||
527 | const char* class2 = w2->classInfo()->className(); |
|
|||
528 | if (strcmp(class1, class2) == 0) { |
|
|||
529 | // same class names, so we can try the operator_equal |
|
|||
530 | PythonQtMemberInfo info = w1->classInfo()->member("operator_equal"); |
|
|||
531 | if (info._type == PythonQtMemberInfo::Slot) { |
|
|||
532 | bool result = false; |
|
|||
533 | void* obj1 = w1->_wrappedPtr; |
|
|||
534 | if (!obj1) { |
|
|||
535 | obj1 = w1->_obj; |
|
|||
536 | } |
|
|||
537 | if (!obj1) { return -1; } |
|
|||
538 | void* obj2 = w2->_wrappedPtr; |
|
|||
539 | if (!obj2) { |
|
|||
540 | obj2 = w2->_obj; |
|
|||
541 | } |
|
|||
542 | if (!obj2) { return -1; } |
|
|||
543 | if (info._slot->isInstanceDecorator()) { |
|
|||
544 | // call on decorator QObject |
|
|||
545 | void* args[3]; |
|
|||
546 | args[0] = &result; |
|
|||
547 | args[1] = &obj1; // this is a pointer, so it needs a pointer to a pointer |
|
|||
548 | args[2] = obj2; // this is a reference, so it needs the direct pointer |
|
|||
549 | info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args); |
|
|||
550 | return result?0:-1; |
|
|||
551 | } else { |
|
|||
552 | // call directly on QObject |
|
|||
553 | if (w1->_obj && w2->_obj) { |
|
|||
554 | void* args[2]; |
|
|||
555 | args[0] = &result; |
|
|||
556 | args[1] = obj2; // this is a reference, so it needs the direct pointer |
|
|||
557 | w1->_obj->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args); |
|
|||
558 | return result?0:-1; |
|
|||
559 | } |
|
|||
560 | } |
|
|||
561 | } |
|
|||
562 | } |
|
|||
563 | } |
|
|||
564 | return -1; |
|
|||
565 | } |
|
|||
566 |
|
||||
567 | static int PythonQtInstanceWrapper_nonzero(PyObject *obj) |
|
|||
568 | { |
|
612 | { | |
569 | PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj; |
|
613 | PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj; | |
570 | return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1; |
|
614 | return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1; | |
@@ -595,7 +639,7 static PyNumberMethods PythonQtInstanceWrapper_as_number = { | |||||
595 | 0, /* nb_negative */ |
|
639 | 0, /* nb_negative */ | |
596 | 0, /* nb_positive */ |
|
640 | 0, /* nb_positive */ | |
597 | 0, /* nb_absolute */ |
|
641 | 0, /* nb_absolute */ | |
598 | PythonQtInstanceWrapper_nonzero, /* nb_nonzero */ |
|
642 | PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */ | |
599 | 0, /* nb_invert */ |
|
643 | 0, /* nb_invert */ | |
600 | 0, /* nb_lshift */ |
|
644 | 0, /* nb_lshift */ | |
601 | 0, /* nb_rshift */ |
|
645 | 0, /* nb_rshift */ | |
@@ -635,7 +679,7 PyTypeObject PythonQtInstanceWrapper_Type = { | |||||
635 | 0, /*tp_print*/ |
|
679 | 0, /*tp_print*/ | |
636 | 0, /*tp_getattr*/ |
|
680 | 0, /*tp_getattr*/ | |
637 | 0, /*tp_setattr*/ |
|
681 | 0, /*tp_setattr*/ | |
638 | PythonQtInstanceWrapper_compare, /*tp_compare*/ |
|
682 | 0, /*tp_compare*/ | |
639 | PythonQtInstanceWrapper_repr, /*tp_repr*/ |
|
683 | PythonQtInstanceWrapper_repr, /*tp_repr*/ | |
640 | &PythonQtInstanceWrapper_as_number, /*tp_as_number*/ |
|
684 | &PythonQtInstanceWrapper_as_number, /*tp_as_number*/ | |
641 | 0, /*tp_as_sequence*/ |
|
685 | 0, /*tp_as_sequence*/ | |
@@ -646,11 +690,11 PyTypeObject PythonQtInstanceWrapper_Type = { | |||||
646 | PythonQtInstanceWrapper_getattro, /*tp_getattro*/ |
|
690 | PythonQtInstanceWrapper_getattro, /*tp_getattro*/ | |
647 | PythonQtInstanceWrapper_setattro, /*tp_setattro*/ |
|
691 | PythonQtInstanceWrapper_setattro, /*tp_setattro*/ | |
648 | 0, /*tp_as_buffer*/ |
|
692 | 0, /*tp_as_buffer*/ | |
649 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ |
|
693 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ | |
650 | "PythonQtInstanceWrapper object", /* tp_doc */ |
|
694 | "PythonQtInstanceWrapper object", /* tp_doc */ | |
651 | 0, /* tp_traverse */ |
|
695 | 0, /* tp_traverse */ | |
652 | 0, /* tp_clear */ |
|
696 | 0, /* tp_clear */ | |
653 |
|
|
697 | (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */ | |
654 | 0, /* tp_weaklistoffset */ |
|
698 | 0, /* tp_weaklistoffset */ | |
655 | 0, /* tp_iter */ |
|
699 | 0, /* tp_iter */ | |
656 | 0, /* tp_iternext */ |
|
700 | 0, /* tp_iternext */ |
General Comments 0
You need to be logged in to leave comments.
Login now