##// END OF EJS Templates
added support for operators and rich compare...
florianlink -
r119:609e1e5898f0
parent child
Show More
@@ -79,7 +79,7 QString rename_operator(const QString &oper)
79 79 operator_names->insert("&", "__and__");
80 80 operator_names->insert("|", "__or__");
81 81 operator_names->insert("^", "__xor__");
82 operator_names->insert("~", "__negate__");
82 operator_names->insert("~", "__invert__");
83 83 operator_names->insert("<<", "__lshift__");
84 84 operator_names->insert(">>", "__rshift__");
85 85
@@ -106,12 +106,12 QString rename_operator(const QString &oper)
106 106 operator_names->insert("--", "decrement");
107 107
108 108 // compare
109 operator_names->insert("<", "less");
110 operator_names->insert(">", "greater");
111 operator_names->insert("<=", "less_or_equal");
112 operator_names->insert(">=", "greater_or_equal");
113 operator_names->insert("!=", "not_equal");
114 operator_names->insert("==", "equal");
109 operator_names->insert("<", "__lt__");
110 operator_names->insert(">", "__gt__");
111 operator_names->insert("<=", "__le__");
112 operator_names->insert(">=", "__ge__");
113 operator_names->insert("!=", "__ne__");
114 operator_names->insert("==", "__eq__");
115 115
116 116 // other
117 117 operator_names->insert("[]", "subscript");
@@ -849,6 +849,16 AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &
849 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 863 * Returns all reference count modifications for any function in the class
854 864 */
@@ -796,6 +796,8 public:
796 796 void setHasCloneOperator(bool on) { m_has_clone_operator = on; }
797 797 bool hasCloneOperator() const { return m_has_clone_operator; }
798 798
799 bool hasDefaultIsNull() const;
800
799 801 void addPropertySpec(QPropertySpec *spec) { m_property_specs << spec; }
800 802 QList<QPropertySpec *> propertySpecs() const { return m_property_specs; }
801 803
@@ -55,6 +55,64 void maybeDeclareMetaType(QTextStream &stream, const QString &typeName,
55 55 QSet<QString> &registeredTypeNames);
56 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 116 void SetupGenerator::generate()
59 117 {
60 118 AbstractMetaClassList classes_with_polymorphic_id;
@@ -138,11 +196,15 void SetupGenerator::generate()
138 196 } else {
139 197 shellCreator = ", NULL";
140 198 }
199 QString operatorCodes = getOperatorCodes(cls).join("|");
200 if (operatorCodes.isEmpty()) {
201 operatorCodes = "0";
202 }
141 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 205 } else {
144 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 209 foreach(AbstractMetaClass* interface, cls->interfaces()) {
148 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 282 if (meta_class->hasDefaultToStringFunction() || meta_class->hasToStringCapability()) {
283 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 289 // Field accessors
287 290 foreach (const AbstractMetaField *field, meta_class->fields()) {
@@ -227,7 +227,7 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package,
227 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 232 // we register all classes in the hierarchy
233 233 const QMetaObject* m = metaobject;
@@ -235,6 +235,7 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* p
235 235 while (m) {
236 236 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
237 237 if (!info->pythonQtClassWrapper()) {
238 info->setTypeSlots(typeSlots);
238 239 info->setupQObject(m);
239 240 createPythonQtClassWrapper(info, package, module);
240 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 1136 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1136 1137 if (!info->pythonQtClassWrapper()) {
1138 info->setTypeSlots(typeSlots);
1137 1139 info->setupCPPObject(typeName);
1138 1140 createPythonQtClassWrapper(info, package, module);
1139 1141 }
@@ -96,6 +96,42 public:
96 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 135 //! initialize the python qt binding (flags are a or combination of InitFlags), if \c pythonQtModuleName is given
100 136 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
101 137 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
@@ -432,7 +468,7 public:
432 468 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
433 469 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
434 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 473 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
438 474 //! (ownership of wrapper is passed to PythonQt)
@@ -442,7 +478,7 public:
442 478 All slots that take a pointer to typeName as the first argument will be callable from Python on
443 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 483 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
448 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 57 _pythonQtClassWrapper = NULL;
58 58 _shellSetInstanceWrapperCB = NULL;
59 59 _metaTypeId = -1;
60 _typeSlots = 0;
60 61 _isQObject = false;
61 62 _enumsCreated = false;
62 63 }
@@ -104,6 +104,11 public:
104 104 //! setup as a CPP (non-QObject), taking the classname
105 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 112 //! get the Python method definition for a given slot name (without return type and signature)
108 113 PythonQtMemberInfo member(const char* member);
109 114
@@ -244,6 +249,7 private:
244 249 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
245 250
246 251 int _metaTypeId;
252 int _typeSlots;
247 253
248 254 bool _isQObject;
249 255 bool _enumsCreated;
@@ -48,6 +48,167
48 48 #include "PythonQtConversion.h"
49 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 212 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
52 213 {
53 214 // call the default type alloc
@@ -56,6 +217,7 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitem
56 217 // take current class type, if we are called via newPythonQtClassWrapper()
57 218 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
58 219 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
220 initializeSlots(wrap);
59 221
60 222 return obj;
61 223 }
@@ -183,6 +183,106 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args
183 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 286 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
187 287 {
188 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_compare(PyObject * obj1, PyObject * obj2)
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)
611 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
568 612 {
569 613 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
570 614 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
@@ -595,7 +639,7 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
595 639 0, /* nb_negative */
596 640 0, /* nb_positive */
597 641 0, /* nb_absolute */
598 PythonQtInstanceWrapper_nonzero, /* nb_nonzero */
642 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */
599 643 0, /* nb_invert */
600 644 0, /* nb_lshift */
601 645 0, /* nb_rshift */
@@ -635,7 +679,7 PyTypeObject PythonQtInstanceWrapper_Type = {
635 679 0, /*tp_print*/
636 680 0, /*tp_getattr*/
637 681 0, /*tp_setattr*/
638 PythonQtInstanceWrapper_compare, /*tp_compare*/
682 0, /*tp_compare*/
639 683 PythonQtInstanceWrapper_repr, /*tp_repr*/
640 684 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
641 685 0, /*tp_as_sequence*/
@@ -646,11 +690,11 PyTypeObject PythonQtInstanceWrapper_Type = {
646 690 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
647 691 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
648 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 694 "PythonQtInstanceWrapper object", /* tp_doc */
651 695 0, /* tp_traverse */
652 696 0, /* tp_clear */
653 0, /* tp_richcompare */
697 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
654 698 0, /* tp_weaklistoffset */
655 699 0, /* tp_iter */
656 700 0, /* tp_iternext */
General Comments 0
You need to be logged in to leave comments. Login now