##// 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 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("~", "__negate__");
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("<", "less");
109 operator_names->insert("<", "__lt__");
110 operator_names->insert(">", "greater");
110 operator_names->insert(">", "__gt__");
111 operator_names->insert("<=", "less_or_equal");
111 operator_names->insert("<=", "__le__");
112 operator_names->insert(">=", "greater_or_equal");
112 operator_names->insert(">=", "__ge__");
113 operator_names->insert("!=", "not_equal");
113 operator_names->insert("!=", "__ne__");
114 operator_names->insert("==", "equal");
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> &registeredTypeNames);
55 QSet<QString> &registeredTypeNames);
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 }
@@ -54,11 +54,11 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
54 }
54 }
55
55
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
57
57
58 // is this a C++ wrapper?
58 // is this a C++ wrapper?
59 if (self->_wrappedPtr) {
59 if (self->_wrappedPtr) {
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
61
61
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
63 // we own our qobject, so we delete it now:
63 // we own our qobject, so we delete it now:
64 delete self->_obj;
64 delete self->_obj;
@@ -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);
@@ -242,7 +342,7 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
242 }
342 }
243 }
343 }
244
344
245 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
345 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
246 foreach (QByteArray name, dynamicProps) {
346 foreach (QByteArray name, dynamicProps) {
247 PyObject* o = PyObject_GetAttrString(obj, name.data());
347 PyObject* o = PyObject_GetAttrString(obj, name.data());
248 if (o) {
348 if (o) {
@@ -362,7 +462,7 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec
362 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
462 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
363 return -1;
463 return -1;
364 }
464 }
365
465
366 QMetaProperty prop = member._property;
466 QMetaProperty prop = member._property;
367 if (prop.isWritable()) {
467 if (prop.isWritable()) {
368 QVariant v;
468 QVariant v;
@@ -395,7 +495,7 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec
395 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
495 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
396 } else if (member._type == PythonQtMemberInfo::NotFound) {
496 } else if (member._type == PythonQtMemberInfo::NotFound) {
397 // check for a setter slot
497 // check for a setter slot
398 static const QByteArray setterString("py_set_");
498 static const QByteArray setterString("py_set_");
399 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
499 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
400 if (setter._type == PythonQtMemberInfo::Slot) {
500 if (setter._type == PythonQtMemberInfo::Slot) {
401 // call the setter and ignore the result value
501 // call the setter and ignore the result value
@@ -424,7 +524,7 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec
424 }
524 }
425 }
525 }
426 }
526 }
427
527
428 // if we are a derived python class, we allow setting attributes.
528 // if we are a derived python class, we allow setting attributes.
429 // if we are a direct CPP wrapper, we do NOT allow it, since
529 // if we are a direct CPP wrapper, we do NOT allow it, since
430 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
530 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
@@ -487,7 +587,7 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
487 {
587 {
488 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
588 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
489 const char* typeName = obj->ob_type->tp_name;
589 const char* typeName = obj->ob_type->tp_name;
490
590
491 QObject *qobj = wrapper->_obj;
591 QObject *qobj = wrapper->_obj;
492 QString str = getStringFromObject(wrapper);
592 QString str = getStringFromObject(wrapper);
493 if (!str.isEmpty()) {
593 if (!str.isEmpty()) {
@@ -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)
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 0, /* tp_richcompare */
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