@@ -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("~", "__ |
|
|
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("<", " |
|
|
110 |
operator_names->insert(">", " |
|
|
111 |
operator_names->insert("<=", "le |
|
|
112 |
operator_names->insert(">=", "g |
|
|
113 |
operator_names->insert("!=", " |
|
|
114 |
operator_names->insert("==", " |
|
|
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> ®isteredTypeNames); |
|
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 | } |
@@ -54,11 +54,11 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo() | |||
|
54 | 54 | } |
|
55 | 55 | |
|
56 | 56 | static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) { |
|
57 | ||
|
57 | ||
|
58 | 58 | // is this a C++ wrapper? |
|
59 | 59 | if (self->_wrappedPtr) { |
|
60 | 60 | //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1()); |
|
61 | ||
|
61 | ||
|
62 | 62 | PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr); |
|
63 | 63 | // we own our qobject, so we delete it now: |
|
64 | 64 | delete self->_obj; |
@@ -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); |
@@ -242,7 +342,7 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name) | |||
|
242 | 342 | } |
|
243 | 343 | } |
|
244 | 344 | |
|
245 |
QList<QByteArray> |
|
|
345 | QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames(); | |
|
246 | 346 | foreach (QByteArray name, dynamicProps) { |
|
247 | 347 | PyObject* o = PyObject_GetAttrString(obj, name.data()); |
|
248 | 348 | if (o) { |
@@ -362,7 +462,7 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec | |||
|
362 | 462 | PyErr_SetString(PyExc_AttributeError, error.toLatin1().data()); |
|
363 | 463 | return -1; |
|
364 | 464 | } |
|
365 | ||
|
465 | ||
|
366 | 466 | QMetaProperty prop = member._property; |
|
367 | 467 | if (prop.isWritable()) { |
|
368 | 468 | QVariant v; |
@@ -395,7 +495,7 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObjec | |||
|
395 | 495 | error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object"; |
|
396 | 496 | } else if (member._type == PythonQtMemberInfo::NotFound) { |
|
397 | 497 | // check for a setter slot |
|
398 |
static const QByteArray setterString("py_set_"); |
|
|
498 | static const QByteArray setterString("py_set_"); | |
|
399 | 499 | PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName); |
|
400 | 500 | if (setter._type == PythonQtMemberInfo::Slot) { |
|
401 | 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 | 528 | // if we are a derived python class, we allow setting attributes. |
|
429 | 529 | // if we are a direct CPP wrapper, we do NOT allow it, since |
|
430 | 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 | 588 | PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj; |
|
489 | 589 | const char* typeName = obj->ob_type->tp_name; |
|
490 | ||
|
590 | ||
|
491 | 591 | QObject *qobj = wrapper->_obj; |
|
492 | 592 | QString str = getStringFromObject(wrapper); |
|
493 | 593 | if (!str.isEmpty()) { |
@@ -508,63 +608,7 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj) | |||
|
508 | 608 | } |
|
509 | 609 | } |
|
510 | 610 | |
|
511 |
static int PythonQtInstanceWrapper_ |
|
|
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 |
|
|
|
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