// This is the SIP interface definition for TQObject. // // Copyright (c) 2007 // Riverbank Computing Limited // // This file is part of PyTQt. // // This copy of PyTQt is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2, or (at your option) any later // version. // // PyTQt is supplied in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // You should have received a copy of the GNU General Public License along with // PyTQt; see the file LICENSE. If not, write to the Free Software Foundation, // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. %ExportedDoc TQObject bool disconnect const TQObject *receiver const char *member = 0 Not yet implemented. bool disconnect const char *signal = 0 const TQObject *receiver = 0 const char *member = 0 Not yet implemented. static bool disconnect const TQObject *sender const char *signal const TQObject *receiver const char *member At the moment PyTQt does not support the full behaviour of the corresponding TQt method. In particular, specifying None (ie. 0 in C++) for the signal and receiver parameters is not yet supported. %End class TQObject : TQt { %TypeHeaderCode #include #include %End public: TQObject(TQObject * /TransferThis/ = 0,const char * = 0); %ConvertToSubClassCode static struct class_graph { const char *name; sipWrapperType **type; int yes, no; } graph[] = { {sipName_TQWidget, &sipClass_TQWidget, 25, 1}, #if defined(SIP_FEATURE_TQt_ASSISTANTCLIENT) {sipName_TQAssistantClient, &sipClass_TQAssistantClient, -1, 2}, #else {NULL, NULL, -1, 2}, #endif {sipName_TQSessionManager, &sipClass_TQSessionManager, -1, 3}, {sipName_TQTranslator, &sipClass_TQTranslator, -1, 4}, {sipName_TQProcess, &sipClass_TQProcess, -1, 5}, {sipName_TQToolTipGroup, &sipClass_TQToolTipGroup, -1, 6}, #if defined(SIP_FEATURE_TQt_FILEDIALOG) {sipName_TQFileIconProvider, &sipClass_TQFileIconProvider, -1, 7}, #else {NULL, NULL, -1, 7}, #endif #if defined(SIP_FEATURE_TQt_ACTION) {sipName_TQAction, &sipClass_TQAction, 89, 8}, #else {NULL, NULL, -1, 8}, #endif {sipName_TQObjectCleanupHandler, &sipClass_TQObjectCleanupHandler, -1, 9}, {sipName_TQTimer, &sipClass_TQTimer, -1, 10}, {sipName_TQLayout, &sipClass_TQLayout, 90, 11}, #if defined(SIP_FEATURE_TQt_NETWORKPROTOCOL) {sipName_TQUrlOperator, &sipClass_TQUrlOperator, -1, 12}, #else {NULL, NULL, -1, 12}, #endif {sipName_TQStyleSheet, &sipClass_TQStyleSheet, -1, 13}, {sipName_TQValidator, &sipClass_TQValidator, 94, 14}, #if defined(SIP_FEATURE_TQt_NETWORKPROTOCOL) {sipName_TQNetworkOperation, &sipClass_TQNetworkOperation, -1, 15}, #else {NULL, NULL, -1, 15}, #endif {sipName_TQAccel, &sipClass_TQAccel, -1, 16}, {sipName_TQEventLoop, &sipClass_TQEventLoop, -1, 17}, #if defined(SIP_FEATURE_TQt_NETWORKPROTOCOL) {sipName_TQNetworkProtocol, &sipClass_TQNetworkProtocol, -1, 18}, #else {NULL, NULL, -1, 18}, #endif #if defined(SIP_FEATURE_TQt_SOUND) {sipName_TQSound, &sipClass_TQSound, -1, 19}, #else {NULL, NULL, -1, 19}, #endif {sipName_TQApplication, &sipClass_TQApplication, -1, 20}, {sipName_TQDragObject, &sipClass_TQDragObject, 97, 21}, {sipName_TQSocketNotifier, &sipClass_TQSocketNotifier, -1, 22}, {sipName_TQStyle, &sipClass_TQStyle, 103, 23}, {sipName_TQSignalMapper, &sipClass_TQSignalMapper, -1, 24}, #if defined(SIP_FEATURE_TQt_CLIPBOARD) {sipName_TQClipboard, &sipClass_TQClipboard, -1, -1}, #else {NULL, NULL, -1, -1}, #endif {sipName_TQStatusBar, &sipClass_TQStatusBar, -1, 26}, #if defined(SIP_FEATURE_TQt_SIZEGRIP) {sipName_TQSizeGrip, &sipClass_TQSizeGrip, -1, 27}, #else {NULL, NULL, -1, 27}, #endif {sipName_TQTabWidget, &sipClass_TQTabWidget, -1, 28}, {sipName_TQDateEdit, &sipClass_TQDateEdit, -1, 29}, {sipName_TQMainWindow, &sipClass_TQMainWindow, -1, 30}, {sipName_TQDateTimeEdit, &sipClass_TQDateTimeEdit, -1, 31}, {sipName_TQTimeEdit, &sipClass_TQTimeEdit, -1, 32}, {sipName_TQFrame, &sipClass_TQFrame, 46, 33}, {sipName_TQScrollBar, &sipClass_TQScrollBar, -1, 34}, #if defined(SIP_FEATURE_TQt_DIAL) {sipName_TQDial, &sipClass_TQDial, -1, 35}, #else {NULL, NULL, -1, 35}, #endif {sipName_TQButton, &sipClass_TQButton, 75, 36}, {sipName_TQTabBar, &sipClass_TQTabBar, -1, 37}, {sipName_TQDialog, &sipClass_TQDialog, 79, 38}, {sipName_TQComboBox, &sipClass_TQComboBox, -1, 39}, {sipName_TQHeader, &sipClass_TQHeader, -1, 40}, {sipName_TQDockArea, &sipClass_TQDockArea, -1, 41}, {sipName_TQSplashScreen, &sipClass_TQSplashScreen, -1, 42}, {sipName_TQSlider, &sipClass_TQSlider, -1, 43}, {sipName_TQSpinBox, &sipClass_TQSpinBox, -1, 44}, #if defined(SIP_FEATURE_TQt_WORKSPACE) {sipName_TQWorkspace, &sipClass_TQWorkspace, -1, 45}, #else {NULL, NULL, -1, 45}, #endif {sipName_TQDesktopWidget, &sipClass_TQDesktopWidget, -1, -1}, {sipName_TQGrid, &sipClass_TQGrid, -1, 47}, {sipName_TQLineEdit, &sipClass_TQLineEdit, -1, 48}, {sipName_TQToolBox, &sipClass_TQToolBox, -1, 49}, {sipName_TQWidgetStack, &sipClass_TQWidgetStack, -1, 50}, {sipName_TQDockWindow, &sipClass_TQDockWindow, 60, 51}, {sipName_TQMenuBar, &sipClass_TQMenuBar, -1, 52}, {sipName_TQLabel, &sipClass_TQLabel, -1, 53}, {sipName_TQGroupBox, &sipClass_TQGroupBox, 61, 54}, {sipName_TQPopupMenu, &sipClass_TQPopupMenu, -1, 55}, #if defined(SIP_FEATURE_TQt_SPLITTER) {sipName_TQSplitter, &sipClass_TQSplitter, -1, 56}, #else {NULL, NULL, -1, 56}, #endif {sipName_TQProgressBar, &sipClass_TQProgressBar, -1, 57}, {sipName_TQScrollView, &sipClass_TQScrollView, 66, 58}, {sipName_TQHBox, &sipClass_TQHBox, 74, 59}, {sipName_TQLCDNumber, &sipClass_TQLCDNumber, -1, -1}, {sipName_TQToolBar, &sipClass_TQToolBar, -1, -1}, {sipName_TQButtonGroup, &sipClass_TQButtonGroup, 64, 62}, {sipName_TQHGroupBox, &sipClass_TQHGroupBox, -1, 63}, {sipName_TQVGroupBox, &sipClass_TQVGroupBox, -1, -1}, {sipName_TQVButtonGroup, &sipClass_TQVButtonGroup, -1, 65}, {sipName_TQHButtonGroup, &sipClass_TQHButtonGroup, -1, -1}, #if defined(SIP_FEATURE_TQt_ICONVIEW) {sipName_TQIconView, &sipClass_TQIconView, -1, 67}, #else {NULL, NULL, -1, 67}, #endif {sipName_TQListView, &sipClass_TQListView, -1, 68}, {sipName_TQListBox, &sipClass_TQListBox, -1, 69}, {sipName_TQGridView, &sipClass_TQGridView, -1, 70}, {sipName_TQTextEdit, &sipClass_TQTextEdit, 71, -1}, {sipName_TQTextBrowser, &sipClass_TQTextBrowser, -1, 72}, {sipName_TQMultiLineEdit, &sipClass_TQMultiLineEdit, -1, 73}, {sipName_TQTextView, &sipClass_TQTextView, -1, -1}, {sipName_TQVBox, &sipClass_TQVBox, -1, -1}, {sipName_TQToolButton, &sipClass_TQToolButton, -1, 76}, {sipName_TQRadioButton, &sipClass_TQRadioButton, -1, 77}, {sipName_TQPushButton, &sipClass_TQPushButton, -1, 78}, {sipName_TQCheckBox, &sipClass_TQCheckBox, -1, -1}, #if defined(WS_X11) && defined(SIP_FEATURE_TQt_PRINTDIALOG) {sipName_TQPrintDialog, &sipClass_TQPrintDialog, -1, 80}, #else {NULL, NULL, -1, 80}, #endif {sipName_TQErrorMessage, &sipClass_TQErrorMessage, -1, 81}, #if defined(SIP_FEATURE_TQt_INPUTDIALOG) {sipName_TQInputDialog, &sipClass_TQInputDialog, -1, 82}, #else {NULL, NULL, -1, 82}, #endif #if defined(SIP_FEATURE_TQt_MESSAGEBOX) {sipName_TQMessageBox, &sipClass_TQMessageBox, -1, 83}, #else {NULL, NULL, -1, 83}, #endif #if defined(SIP_FEATURE_TQt_WIZARD) {sipName_TQWizard, &sipClass_TQWizard, -1, 84}, #else {NULL, NULL, -1, 84}, #endif #if defined(SIP_FEATURE_TQt_COLORDIALOG) {sipName_TQColorDialog, &sipClass_TQColorDialog, -1, 85}, #else {NULL, NULL, -1, 85}, #endif #if defined(SIP_FEATURE_TQt_FONTDIALOG) {sipName_TQFontDialog, &sipClass_TQFontDialog, -1, 86}, #else {NULL, NULL, -1, 86}, #endif #if defined(SIP_FEATURE_TQt_FILEDIALOG) {sipName_TQFileDialog, &sipClass_TQFileDialog, -1, 87}, #else {NULL, NULL, -1, 87}, #endif #if defined(SIP_FEATURE_TQt_PROGRESSDIALOG) {sipName_TQProgressDialog, &sipClass_TQProgressDialog, -1, 88}, #else {NULL, NULL, -1, 88}, #endif #if defined(SIP_FEATURE_TQt_TABDIALOG) {sipName_TQTabDialog, &sipClass_TQTabDialog, -1, -1}, #else {NULL, NULL, -1, -1}, #endif #if defined(SIP_FEATURE_TQt_ACTION) {sipName_TQActionGroup, &sipClass_TQActionGroup, -1, -1}, #else {NULL, NULL, -1, -1}, #endif {sipName_TQGridLayout, &sipClass_TQGridLayout, -1, 91}, {sipName_TQBoxLayout, &sipClass_TQBoxLayout, 92, -1}, {sipName_TQHBoxLayout, &sipClass_TQHBoxLayout, -1, 93}, {sipName_TQVBoxLayout, &sipClass_TQVBoxLayout, -1, -1}, {sipName_TQDoubleValidator, &sipClass_TQDoubleValidator, -1, 95}, {sipName_TQIntValidator, &sipClass_TQIntValidator, -1, 96}, {sipName_TQRegExpValidator, &sipClass_TQRegExpValidator, -1, -1}, {sipName_TQTextDrag, &sipClass_TQTextDrag, -1, 98}, {sipName_TQStoredDrag, &sipClass_TQStoredDrag, 101, 99}, #if defined(SIP_FEATURE_TQt_ICONVIEW) && defined(SIP_FEATURE_TQt_DRAGANDDROP) {sipName_TQIconDrag, &sipClass_TQIconDrag, -1, 100}, #else {NULL, NULL, -1, 100}, #endif {sipName_TQImageDrag, &sipClass_TQImageDrag, -1, -1}, {sipName_TQColorDrag, &sipClass_TQColorDrag, -1, 102}, {sipName_TQUriDrag, &sipClass_TQUriDrag, -1, -1}, {sipName_TQCommonStyle, &sipClass_TQCommonStyle, 104, -1}, #if defined(SIP_FEATURE_TQt_STYLE_WINDOWS) {sipName_TQWindowsStyle, &sipClass_TQWindowsStyle, 106, 105}, #else {NULL, NULL, -1, 105}, #endif #if defined(SIP_FEATURE_TQt_STYLE_MOTIF) {sipName_TQMotifStyle, &sipClass_TQMotifStyle, 107, -1}, #else {NULL, NULL, -1, -1}, #endif #if defined(SIP_FEATURE_TQt_STYLE_PLATINUM) {sipName_TQPlatinumStyle, &sipClass_TQPlatinumStyle, -1, 110}, #else {NULL, NULL, -1, 110}, #endif #if defined(SIP_FEATURE_TQt_STYLE_CDE) {sipName_TQCDEStyle, &sipClass_TQCDEStyle, -1, 108}, #else {NULL, NULL, -1, 108}, #endif #if defined(SIP_FEATURE_TQt_STYLE_MOTIFPLUS) {sipName_TQMotifPlusStyle, &sipClass_TQMotifPlusStyle, -1, 109}, #else {NULL, NULL, -1, 109}, #endif #if defined(SIP_FEATURE_TQt_STYLE_SGI) {sipName_TQSGIStyle, &sipClass_TQSGIStyle, -1, -1}, #else {NULL, NULL, -1, -1}, #endif #if defined(PYQT_STYLE_WINDOWSXP) {sipName_TQWindowsXPStyle, &sipClass_TQWindowsXPStyle, -1, -1}, #else {NULL, NULL, -1, -1}, #endif }; int i = 0; sipClass = NULL; do { struct class_graph *cg = &graph[i]; if (cg->name != NULL && sipCpp->inherits(cg->name)) { sipClass = *cg->type; i = cg->yes; } else i = cg->no; } while (i >= 0); %End // This is really virtual. With the way we are implementing it doesn't // need to be and has the advantage that the C++ implementation can be // used in %ConvertToSubClassCode to get the C++ name for Python // sub-classes. However, it is also means that C++ plugins can't get // the true (Python) class name. SIP_PYOBJECT className() const; %MethodCode #if PY_MAJOR_VERSION >= 3 sipRes = PyUnicode_FromString(sipSelf->ob_type->tp_name); #else sipRes = sipClassName(sipSelf); #endif %End // Note that tr() and trUtf8() are really static methods. We pretend // they aren't so that we can use self to get hold of the class name. // We could mimic moc's behaviour more accurately by creating tr() and // trUtf8() methods for a Python sub-class instance in the sub-class's // ctor. TQString tr(SIP_PYOBJECT sourceText /TypeHint="str"/,const char * = 0); %MethodCode if (tqApp) { const char *source = PyTQt_qt_encode(&a0, TQApplication::DefaultCodec); if (source) { sipRes = new TQString(tqApp->translate(Py_TYPE(sipSelf)->tp_name, source, a1, TQApplication::DefaultCodec)); Py_DECREF(a0); } else { sipIsErr = 1; } } else { const char *source = sipString_AsUTF8String(&a0); if (source) { sipRes = new TQString(QString::fromUtf8(source)); Py_DECREF(a0); } else { sipIsErr = 1; } } %End TQString trUtf8(SIP_PYOBJECT sourceText /TypeHint="str"/,const char * = 0); %MethodCode if (tqApp) { const char *source = PyTQt_qt_encode(&a0, TQApplication::DefaultCodec); if (source) { sipRes = new TQString(tqApp->translate(Py_TYPE(sipSelf)->tp_name, source, a1, TQApplication::UnicodeUTF8)); Py_DECREF(a0); } else { sipIsErr = 1; } } else { const char *source = sipString_AsUTF8String(&a0); if (source) { sipRes = new TQString(TQString::fromUtf8(source)); Py_DECREF(a0); } else { sipIsErr = 1; } } %End virtual TQMetaObject *metaObject() const /AutoGen/; virtual bool event(TQEvent *); virtual bool eventFilter(TQObject *,TQEvent *); bool isA(const char *) const; %MethodCode // The TQt implementation doesn't know anything about Python // sub-classes. For SIP v4 we use the Python type's name. For // SIP v3 we use the broken TQt behaviour as it's deprecated and // we want to keep things simple. #if SIP_VERSION >= 0x040000 sipRes = (strcmp(sipSelf -> ob_type -> tp_name,a0) == 0); #else Py_BEGIN_ALLOW_THREADS sipRes = sipCpp -> TQObject::isA(a0); Py_END_ALLOW_THREADS #endif %End bool inherits(const char *) const; %MethodCode // The TQt implementation doesn't know anything about Python // sub-classes. For SIP v4 we use the Python type's MRO. For // SIP v3 we use the broken TQt behaviour as it's deprecated and // we want to keep things simple. #if SIP_VERSION >= 0x040000 PyObject *mro = sipSelf -> ob_type -> tp_mro; sipRes = 0; for (int i = 0; i < PyTuple_GET_SIZE(mro); ++i) if (strcmp(((PyTypeObject *)PyTuple_GET_ITEM(mro,i)) -> tp_name,a0) == 0) { sipRes = 1; break; } #else Py_BEGIN_ALLOW_THREADS sipRes = sipCpp -> TQObject::inherits(a0); Py_END_ALLOW_THREADS #endif %End const char *name() const; const char *name(const char *) const; virtual void setName(const char *); bool isWidgetType() const; bool highPriority() const; bool signalsBlocked() const; void blockSignals(bool); int startTimer(int); void killTimer(int); void killTimers(); TQObject *child(const char *,const char * = 0,bool = 1); const TQObjectList *children() const; static const TQObjectList *objectTrees(); TQObjectList *queryList(char * = 0,char * = 0,bool = 1,bool = 1) const; %MethodCode // The TQt implementation doesn't know anything about Python // sub-classes. For SIP v4 we get all classes and then use the // Python type's MRO to weed out those we don't want. For SIP // v3 we use the broken TQt behaviour as it's deprecated and we // want to keep things simple. #if SIP_VERSION >= 0x040000 sipRes = sipCpp -> TQObject::queryList(0, a1, a2, a3); if (a0 && sipRes) { TQObject *o = sipRes -> first(); while (o) { bool remove = TRUE; PyObject *pyo = sipConvertFromInstance(o, sipClass_TQObject, 0); if (pyo) { PyObject *mro = pyo -> ob_type -> tp_mro; for (int i = 0; i < PyTuple_GET_SIZE(mro); ++i) if (strcmp(((PyTypeObject *)PyTuple_GET_ITEM(mro,i)) -> tp_name,a0) == 0) { remove = FALSE; break; } Py_DECREF(pyo); } if (remove) { sipRes -> remove(); o = sipRes -> current(); } else o = sipRes -> next(); } } #else Py_BEGIN_ALLOW_THREADS sipRes = sipCpp -> TQObject::queryList(a0, a1, a2, a3); Py_END_ALLOW_THREADS #endif %End virtual void insertChild(TQObject * /Transfer/); virtual void removeChild(TQObject * /TransferBack/); void installEventFilter(const TQObject *); void removeEventFilter(const TQObject *); static SIP_PYOBJECT connect(SIP_QOBJECT,SIP_SIGNAL,SIP_QOBJECT,SIP_SLOT); %MethodCode sipRes = sipConnectRx(a0,a1,a2,a3,0); %End static SIP_PYOBJECT connect(SIP_QOBJECT,SIP_SIGNAL,SIP_PYCALLABLE); %MethodCode sipRes = sipConnectRx(a0,a1,a2,0,0); %End SIP_PYOBJECT connect(SIP_QOBJECT,SIP_SIGNAL,SIP_SLOT) const; %MethodCode sipRes = sipConnectRx(a0,a1,sipSelf,a2,0); %End static SIP_PYOBJECT disconnect(SIP_QOBJECT,SIP_SIGNAL,SIP_QOBJECT,SIP_SLOT); %MethodCode sipRes = sipDisconnectRx(a0,a1,a2,a3); %End static SIP_PYOBJECT disconnect(SIP_QOBJECT,SIP_SIGNAL,SIP_PYCALLABLE); %MethodCode sipRes = sipDisconnectRx(a0,a1,a2,0); %End // bool disconnect(const char * = 0,const TQObject * = 0,const char * = 0); // bool disconnect(const TQObject *,const char * = 0); void dumpObjectTree(); void dumpObjectInfo(); TQObject *parent() const; void emit(SIP_SIGNAL,SIP_PYTUPLE); %MethodCode if (pyqt3EmitSignal(sipSelf, a0, a1) < 0) sipIsErr = 1; %End %If (TQt_PROPERTIES) virtual bool setProperty(const char *,const TQVariant &); virtual TQVariant property(const char *) const; %End signals: void destroyed(); void destroyed(TQObject *); public slots: void deleteLater(); public: // This is actually protected, but we never need to call the real // method. SIP_PYOBJECT sender(); %MethodCode sipRes = pyqt3GetSender(); %End protected: virtual void timerEvent(TQTimerEvent *); virtual void childEvent(TQChildEvent *); virtual void customEvent(TQCustomEvent *); private: TQObject(const TQObject &); }; SIP_PYOBJECT QT_TR_NOOP(SIP_PYOBJECT); %MethodCode Py_INCREF(a0); sipRes = a0; %End SIP_PYOBJECT QT_TRANSLATE_NOOP(SIP_PYOBJECT,SIP_PYOBJECT); %MethodCode Py_INCREF(a1); sipRes = a1; %End SIP_PYOBJECT SLOT(const char * /Encoding="ASCII"/) /TypeHint="QT_SLOT"/; %MethodCode if (!a0) { PyErr_Format(PyExc_TypeError,"qt.SLOT() slot name cannot be None"); sipIsErr = 1; } else { int len = strlen(a0); if ((sipRes = SIPBytes_FromStringAndSize(NULL,1 + len)) == NULL) sipIsErr = 1; else { char *dp = SIPBytes_AS_STRING(sipRes); *dp++ = '1'; memcpy(dp,a0,len + 1); } } %End SIP_PYOBJECT SIGNAL(const char * /Encoding="ASCII"/) /TypeHint="QT_SIGNAL"/; %MethodCode if (!a0) { PyErr_Format(PyExc_TypeError,"qt.SIGNAL() signal cannot be None"); sipIsErr = 1; } else { int len = strlen(a0); if ((sipRes = SIPBytes_FromStringAndSize(NULL,1 + len)) == NULL) sipIsErr = 1; else { char *dp = SIPBytes_AS_STRING(sipRes); *dp++ = '2'; memcpy(dp,a0,len + 1); } } %End SIP_PYOBJECT PYSIGNAL(const char * /Encoding="ASCII"/); %MethodCode if (!a0) { PyErr_Format(PyExc_TypeError,"qt.PYSIGNAL() signal cannot be None"); sipIsErr = 1; } else { int len = strlen(a0); if ((sipRes = SIPBytes_FromStringAndSize(NULL,1 + len)) == NULL) sipIsErr = 1; else { char *dp = SIPBytes_AS_STRING(sipRes); *dp++ = '9'; memcpy(dp,a0,len + 1); } } %End %ModuleHeaderCode int pyqt3EmitSignal(PyObject *self, const char *sig, PyObject *sigargs); PyObject *pyqt3GetSender(); %End // This is the TQt support code for SIP v4.4 and later. %ModuleCode #include #include #include #include #include #include // These optional parts of the legacy TQt support API for SIP are implemented. #undef sipTQtEmitSignal #undef sipTQtConnectPySignal #undef sipTQtDisconnectPySignal // Declare explicit C linkage. extern "C" { static void *sipTQtCreateUniversalSlot(sipWrapper *, const char *, PyObject *, const char *, const char **, int); static void sipTQtDestroyUniversalSlot(void *); static void *sipTQtFindSlot(void *, const char *, PyObject *, const char *, const char **); static int sipTQtConnect(void *, const char *, void *, const char *, int); static int sipTQtDisconnect(void *, const char *, void *, const char *); static int sipTQtSameSignalSlotName(const char *, const char *); static sipSlot *sipTQtFindSipslot(void *, void **); static int sipTQtEmitSignal(PyObject *, const char *, PyObject *); static int sipTQtConnectPySignal(PyObject *, const char *, PyObject *, const char *); static void sipTQtDisconnectPySignal(PyObject *, const char *, PyObject *, const char *); } extern "C" { // The meta-type for PyTQt classes. It is just a marker type so that we can // safely cast to get access to PyTQt3-specific data structures. PyTypeObject pyqtWrapperType_Type = { #if PY_MAJOR_VERSION >= 3 PyVarObject_HEAD_INIT(NULL, 0) #else PyObject_HEAD_INIT(NULL) 0, /* ob_size */ #endif "qt.pyqtWrapperType", /* tp_name */ sizeof (sipWrapperType), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall_offset */ #else 0, /* tp_print */ #endif 0, /* tp_getattr */ 0, /* tp_setattr */ #if PY_VERSION_HEX >= 0x03050000 0, /* tp_as_async */ #elif PY_VERSION_HEX >= 0x03010000 0, /* tp_reserved */ #else 0, /* tp_compare */ #endif 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ #if PY_VERSION_HEX >= 0x02060000 0, /* tp_version_tag */ #endif #if PY_VERSION_HEX >= 0x03040000 0, /* tp_finalize */ #endif #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall */ #endif #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 8 0, /* tp_print (deprecated) */ #endif }; /* * An entry in a linked list of slots. */ typedef struct _pyqt3SlotList { /* The receiver. */ sipSlot rx; /* Next in the list. */ struct _pyqt3SlotList *next; } pyqt3SlotList; /* * A Python signal. */ typedef struct _pyqt3PySig { /* The name of the signal. */ char *name; /* The list of receivers. */ pyqt3SlotList *rxlist; /* Next in the list. */ struct _pyqt3PySig *next; } pyqt3PySig; /* * The C++ wrapper object used by PyTQt3. */ typedef struct _pyqtWrapper { /* The super-type. */ sipWrapper super; /* The list of Python signals. */ pyqt3PySig *pySigList; } pyqtWrapper; /* * Clear any slots connected to any Python signals. */ static void clear_py_signals_slots(pyqtWrapper *pw) { pyqt3PySig *ps; for (ps = pw->pySigList; ps != NULL; ps = ps->next) { pyqt3SlotList *psrx; for (psrx = ps->rxlist; psrx != NULL; psrx = psrx->next) sipClearAnySlotReference(&psrx->rx); } } /* * Find the given Python signal. */ static pyqt3PySig *find_py_signal(pyqtWrapper *pw, const char *sig) { pyqt3PySig *ps; for (ps = pw->pySigList; ps != NULL; ps = ps->next) if (sipTQtSameSignalSlotName(ps->name, sig)) return ps; return 0; } /* * Free an slot list entry. */ static void free_slot_list(pyqt3SlotList *sl) { sipFreeSipslot(&sl->rx); sipFree(sl); } /* * The instance clear slot. */ static int pyqtWrapper_clear(pyqtWrapper *self) { clear_py_signals_slots(self); return sipWrapper_Type->tp_clear((PyObject *)self); } /* * The instance dealloc slot. */ static void pyqtWrapper_dealloc(pyqtWrapper *self) { clear_py_signals_slots(self); while (self->pySigList != NULL) { pyqt3PySig *ps; pyqt3SlotList *psrx; /* Take this one out of the list. */ ps = self->pySigList; self->pySigList = ps->next; while ((psrx = ps->rxlist) != NULL) { ps->rxlist = psrx->next; free_slot_list(psrx); } sipFree(ps->name); sipFree(ps); } sipWrapper_Type->tp_dealloc((PyObject *)self); } /* * The instance traverse slot. */ static int pyqtWrapper_traverse(pyqtWrapper *self, visitproc visit, void *arg) { int vret; pyqt3PySig *ps; if ((vret = sipWrapper_Type->tp_traverse((PyObject *)self, visit, arg)) != 0) return vret; for (ps = self->pySigList; ps != NULL; ps = ps->next) { pyqt3SlotList *psrx; for (psrx = ps->rxlist; psrx != NULL; psrx = psrx->next) if ((vret = sipVisitSlot(&psrx->rx, visit, arg)) != 0) return vret; } return 0; } static sipWrapperType pyqtWrapper_Type = { #if !defined(STACKLESS) { #endif { #if PY_MAJOR_VERSION >= 3 PyVarObject_HEAD_INIT(&pyqtWrapperType_Type, 0) #else PyObject_HEAD_INIT(&pyqtWrapperType_Type) 0, /* ob_size */ #endif "qt.pyqtWrapper", /* tp_name */ sizeof (pyqtWrapper), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pyqtWrapper_dealloc, /* tp_dealloc */ #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall_offset */ #else 0, /* tp_print */ #endif 0, /* tp_getattr */ 0, /* tp_setattr */ #if PY_VERSION_HEX >= 0x03050000 0, /* tp_as_async */ #elif PY_VERSION_HEX >= 0x03010000 0, /* tp_reserved */ #else 0, /* tp_compare */ #endif 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ (traverseproc)pyqtWrapper_traverse, /* tp_traverse */ (inquiry)pyqtWrapper_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ #if PY_VERSION_HEX >= 0x02060000 0, /* tp_version_tag */ #endif #if PY_VERSION_HEX >= 0x03040000 0, /* tp_finalize */ #endif #if PY_VERSION_HEX >= 0x03080000 0, /* tp_vectorcall */ #endif #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 8 0, /* tp_print (deprecated) */ #endif }, #if !defined(STACKLESS) }, #endif 0, 0, 0 }; }; // This enumerates the different dynamic signal argument types. enum pyqt3SigArgType { unknown_sat, char_sat, uchar_sat, string_sat, ustring_sat, short_sat, ushort_sat, int_sat, uint_sat, long_sat, ulong_sat, longlong_sat, ulonglong_sat, float_sat, double_sat, enum_sat, bool_sat, void_sat, class_sat, classp_sat, mtype_sat, mtypep_sat, qvariant_sat, qvariantp_sat, pyobject_sat, schar_sat, sstring_sat, wchar_sat, wstring_sat }; // This defines a single dynamic signal argument type. struct pyqt3SigArg { // The type. pyqt3SigArgType atype; union { // The Python type for classes. sipWrapperType *wt; // The data for mapped types. const sipTypeDef *mt; // The Python type for named enums. PyTypeObject *et; } u; }; // A parsed signal signature. struct pyqt3Signature { // The number of arguments. int sg_nrargs; // The parsed arguments (heap). pyqt3SigArg *sg_args; // The unparsed signature (heap). char *sg_signature; // The next in the list. pyqt3Signature *sg_next; }; // A connection to a universal slot. struct pyqt3SlotConnection { // The transmitter TQObject. void *sc_transmitter; // The parsed signature. const pyqt3Signature *sc_signature; // The slot. sipSlot sc_slot; }; // This class is used as a slot on behalf of connections to a Python callable. // It is derived from TQObject but is not run through moc. Instead the normal // moc-generated methods are handwritten in order to implement a universal // slot. This requires some knowledge of the internal implementation of // signals and slots but it is likely that they will only change between major // TQt versions. class UniversalSlot : public TQObject { public: UniversalSlot(TQObject *qtx, pyqt3SlotConnection *conn, const char **member); ~UniversalSlot(); virtual TQMetaObject *metaObject() const { return staticMetaObject(); } virtual bool tqt_invoke(int, TQUObject *args); static TQMetaObject *staticMetaObject(); static TQObject *lastSender; static UniversalSlot *unislots; UniversalSlot *nextus, *prevus; pyqt3SlotConnection conn; private: static TQMetaObject *metaObj; }; // Create a universal slot. Note that this will leak if there is no signal // transmitter (ie. no parent) - TQTimer.singleShot() for example. UniversalSlot::UniversalSlot(TQObject *qtx, pyqt3SlotConnection *connection, const char **member) : TQObject() { // Save the connection. conn = *connection; // Detect when the transmitter is destroyed. if (qtx) connect(qtx, SIGNAL(destroyed(TQObject *)), SLOT(deleteLater())); // Return the slot to connect to. *member = SLOT(unislot()); // Add this one to the global list. nextus = unislots; if (nextus) nextus -> prevus = this; prevus = 0; unislots = this; } // Destroy a universal slot. UniversalSlot::~UniversalSlot() { SIP_BLOCK_THREADS sipFreeSipslot(&conn.sc_slot); SIP_UNBLOCK_THREADS // Remove this one from the global list. if (nextus) nextus -> prevus = prevus; if (prevus) prevus -> nextus = nextus; else unislots = nextus; } // The last Python signal sender. static PyObject *py_sender = 0; TQMetaObject *UniversalSlot::metaObj = 0; static TQMetaObjectCleanUp cleanUp_UniversalSlot("UniversalSlot", &UniversalSlot::staticMetaObject); TQObject *UniversalSlot::lastSender = 0; UniversalSlot *UniversalSlot::unislots = 0; TQMetaObject *UniversalSlot::staticMetaObject() { if (metaObj) return metaObj; // Define a single slot that takes no arguments and so will accept any // connection. static const TQUMethod slot = {"unislot", 0, 0}; static const TQMetaData slot_tbl[] = { {"unislot()", &slot, TQMetaData::Public} }; metaObj = TQMetaObject::new_metaobject( "UniversalSlot", TQObject::staticMetaObject(), slot_tbl, 1, 0, 0, #ifndef TQT_NO_PROPERTIES 0, 0, 0, 0, #endif 0, 0); cleanUp_UniversalSlot.setMetaObject(metaObj); return metaObj; } bool UniversalSlot::tqt_invoke(int id, TQUObject *qargs) { if (id - staticMetaObject()->slotOffset() != 0) return TQObject::tqt_invoke(id, qargs); bool ok = TRUE; const pyqt3Signature *psig = conn.sc_signature; TQVariant *qv; // Save in case it is asked for later. lastSender = const_cast(sender()); // If the sender was a TQSignal then the single argument will be wrapped // in a TQVariant instance. At the moment we handle int argument as // that is all that is needed by PyTQt (and PyKDE). if (lastSender->inherits("TQSignal")) qv = &static_QUType_TQVariant.get(qargs + 1); else qv = 0; #ifdef WITH_THREAD PyGILState_STATE state = PyGILState_Ensure(); #endif PyObject *argtup = PyTuple_New(psig->sg_nrargs); if (!argtup) ok = FALSE; else { for (int a = 0; a < psig->sg_nrargs; ++a) { PyObject *arg; ++qargs; switch (psig->sg_args[a].atype) { case char_sat: case schar_sat: case uchar_sat: arg = SIPBytes_FromStringAndSize((char *)static_QUType_ptr.get(qargs), 1); break; case string_sat: case sstring_sat: case ustring_sat: arg = SIPBytes_FromString((char *)static_QUType_ptr.get(qargs)); break; case short_sat: arg = PyLong_FromLong(*(short *)static_QUType_ptr.get(qargs)); break; case ushort_sat: arg = PyLong_FromUnsignedLong(*(unsigned short *)static_QUType_ptr.get(qargs)); break; case int_sat: if (qv) arg = PyLong_FromLong(qv -> asInt()); else arg = PyLong_FromLong(static_QUType_int.get(qargs)); break; case uint_sat: arg = PyLong_FromUnsignedLong(*(unsigned *)static_QUType_ptr.get(qargs)); break; case long_sat: arg = PyLong_FromLong(*(long *)static_QUType_ptr.get(qargs)); break; case ulong_sat: arg = PyLong_FromUnsignedLong(*(unsigned long *)static_QUType_ptr.get(qargs)); break; case longlong_sat: arg = PyLong_FromLongLong(*(PY_LONG_LONG *)static_QUType_ptr.get(qargs)); break; case ulonglong_sat: arg = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)static_QUType_ptr.get(qargs)); break; case float_sat: arg = PyFloat_FromDouble(*(float *)static_QUType_ptr.get(qargs)); break; case double_sat: arg = PyFloat_FromDouble(static_QUType_double.get(qargs)); break; case enum_sat: arg = sipConvertFromNamedEnum(*(int *)static_QUType_ptr.get(qargs), psig->sg_args[a].u.et); break; case bool_sat: arg = PyLong_FromLong(static_QUType_bool.get(qargs)); break; case void_sat: arg = sipConvertFromVoidPtr((void *)static_QUType_ptr.get(qargs)); break; case class_sat: case classp_sat: arg = sipConvertFromInstance((void *)static_QUType_ptr.get(qargs),psig->sg_args[a].u.wt,0); break; case mtype_sat: case mtypep_sat: arg = sipConvertFromMappedType((void *)static_QUType_ptr.get(qargs),psig->sg_args[a].u.mt,0); break; case qvariant_sat: case qvariantp_sat: arg = sipConvertFromInstance((void *)&static_QUType_TQVariant.get(qargs),sipClass_TQVariant,0); break; case pyobject_sat: arg = (PyObject *)static_QUType_ptr.get(qargs); break; default: arg = Py_NotImplemented; Py_INCREF(Py_NotImplemented); } PyTuple_SET_ITEM(argtup, a, arg); } // Dispatch to the real slot. if (ok) { PyObject *res = sipInvokeSlot(&conn.sc_slot, argtup); if (res) Py_DECREF(res); else ok = FALSE; } Py_DECREF(argtup); } if (!ok) PyErr_Print(); #ifdef WITH_THREAD PyGILState_Release(state); #endif return ok; } static pyqt3Signature *parseSignature(const char *sig); static void parseType(const char *type, pyqt3SigArg *arg); // Factory function to create a universal slot instance. Returns a pointer to // the instance or 0 if there was an error. static void *sipTQtCreateUniversalSlot(sipWrapper *tx, const char *sig, PyObject *rxObj, const char *slot, const char **member, int) { pyqt3SlotConnection conn; /* Initialise the connection. */ if (tx && sipGetAddress(&tx->super) == NULL) { conn.sc_transmitter = 0; } else { conn.sc_transmitter = (tx ? sipGetCppPtr(&tx->super, 0) : 0); } /* Save the real slot. */ if (sipSaveSlot(&conn.sc_slot, rxObj, slot) < 0) return 0; /* Parse the signature and create the universal slot. */ if ((conn.sc_signature = parseSignature(sig)) == NULL) { sipFreeSipslot(&conn.sc_slot); return 0; } TQObject *qtx = 0; // See if the transmitter is a TQObject in which case we will connect // to it's destroyed signal so that the universal slot can be destroyed // at the same time. (Note that we used to do this by making the // universal slot a child of the transmitter. This doesn't work as // expected because TQWidget destroys its children before emitting the // destroyed signal.) if (tx && PyObject_TypeCheck((PyObject *)tx, (PyTypeObject *)sipClass_TQObject)) qtx = reinterpret_cast(conn.sc_transmitter); return new UniversalSlot(qtx, &conn, member); } // Parse the signal arguments for a connection. static pyqt3Signature *parseSignature(const char *sig) { static pyqt3Signature *psig_list = NULL; pyqt3Signature *psig; const char *sp, *ep; // First see if it has already been parsed. Note that both sides of a // connection will probably be parsed twice because the function names will // be different even though the signatures will probably be the same. We // could be more clever, the most saving is when repeatedly emitting a // signal for which this is sufficient. for (psig = psig_list; psig != NULL; psig = psig->sg_next) if (sipTQtSameSignalSlotName(psig->sg_signature, sig)) return psig; // Create a new one including space for the copy of the signature. if ((psig = (pyqt3Signature *)sipMalloc(sizeof (pyqt3Signature) + strlen(sig) + 1)) == NULL) return NULL; psig->sg_signature = (char *)&psig[1]; psig->sg_nrargs = 0; psig->sg_args = 0; // Find the start and end of the arguments. sp = strchr(sig, '('); ep = strrchr(sig, ')'); // If the signal isn't well formed we assume TQt will pick it up. if (sp && ep && sp < ep) { // Copy the signature arguments while counting them and removing // non-significant spaces. Each argument is left as a '\0' terminated // string. char *dp = psig->sg_signature; int depth = 0, nrcommas = 0, argstart = TRUE; for (;;) { char ch = *++sp; if (strchr(",*&)<>", ch)) { // Backup over any previous trailing space. if (dp > psig->sg_signature && dp[-1] == ' ') --dp; if (sp == ep) { *dp = '\0'; break; } if (ch == ',' && depth == 0) { *dp++ = '\0'; ++nrcommas; argstart = TRUE; } else { *dp++ = ch; // Make sure commas in template arguments are ignored. if (ch == '<') ++depth; else if (ch == '>') --depth; } } else if (ch == ' ') { // Ignore leading and multiple spaces. if (!argstart && dp[-1] != ' ') *dp++ = ch; } else { *dp++ = ch; argstart = FALSE; } } // Handle the arguments now they are in a normal form. if (*psig->sg_signature) { char *arg = psig->sg_signature; int a; // Allocate the space. psig->sg_nrargs = nrcommas + 1; if ((psig->sg_args = (pyqt3SigArg *)sipMalloc(sizeof (pyqt3SigArg) * psig->sg_nrargs)) == NULL) { sipFree(psig); return NULL; } for (a = 0; a < psig->sg_nrargs; ++a) { parseType(arg, &psig->sg_args[a]); // Move to the start of the next argument. arg += strlen(arg) + 1; } } } // Make a deep copy of the signal. strcpy(psig->sg_signature, sig); // Add it to the list so it can be re-used. psig->sg_next = psig_list; psig_list = psig; return psig; } // Parse a single type. static void parseType(const char *type, pyqt3SigArg *arg) { size_t btlen = 0; int unsup, isref = FALSE, indir = 0; const char *ep; pyqt3SigArgType sat = unknown_sat; // Find the start of the significant part of the type. if (strncmp(type, "const ", 6) == 0) type += 6; // Find the length of the base type, the number of indirections and if it // is a reference. for (ep = type; *ep; ++ep) if (*ep == '&') isref = TRUE; else if (*ep == '*') ++indir; else ++btlen; // Extract the base type as a separate string. char type_str[btlen + 1]; strncpy(type_str, type, btlen); type_str[btlen] = '\0'; // Resolve any typedef which may mean more indirection. type = sipResolveTypedef(type_str); // See if we need to make another copy. bool copy = false; if (type) { btlen = strlen(type); // Remove any additional indirection. while (btlen) { if (type[--btlen] == '*') { copy = true; ++indir; } } } else type = type_str; // Make sure this doesn't go out of scope while it is being used. char base_type_str[btlen + 1]; if (copy) { // Extract the base type again. strncpy(base_type_str, type, btlen); base_type_str[btlen] = '\0'; type = base_type_str; } // Assume that anything other than a base type is unsupported. unsup = (isref || indir); // Parse the base type. switch (btlen) { case 3: if (strcmp(type, "int") == 0) sat = int_sat; break; case 4: if (strcmp(type, "bool") == 0) sat = bool_sat; else if (strcmp(type, "long") == 0) sat = long_sat; else if (strcmp(type, "char") == 0) { sat = (indir ? string_sat : char_sat); unsup = (isref || indir > 1); } else if (strcmp(type, "void") == 0) { sat = void_sat; unsup = (isref || indir != 1); } break; case 5: if (strcmp(type, "float") == 0) sat = float_sat; else if (strcmp(type, "short") == 0) sat = short_sat; break; case 6: if (strcmp(type, "double") == 0) sat = double_sat; break; case 7: if (strcmp(type, "__int64") == 0) sat = longlong_sat; else if (strcmp(type, "wchar_t") == 0) { sat = (indir ? wstring_sat : wchar_sat); unsup = (isref || indir > 1); } break; case 8: if (strcmp(type, "unsigned") == 0) sat = uint_sat; else if (strcmp(type, "TQVariant") == 0) { if (indir == 0) { sat = qvariant_sat; unsup = FALSE; } else if (indir == 1) { sat = qvariantp_sat; unsup = FALSE; } } break; case 9: if (strcmp(type, "long long") == 0) sat = longlong_sat; break; case 11: if (strcmp(type, "signed char") == 0) { sat = (indir ? sstring_sat : schar_sat); unsup = (isref || indir > 1); } break; case 12: if (strcmp(type, "unsigned int") == 0) sat = uint_sat; break; case 13: if (strcmp(type, "unsigned long") == 0) sat = ulong_sat; else if (strcmp(type, "unsigned char") == 0) { sat = (indir ? ustring_sat : uchar_sat); unsup = (isref || indir > 1); } else if (strcmp(type, "PyTQt_PyObject") == 0 && indir == 0) { sat = pyobject_sat; unsup = FALSE; } break; case 14: if (strcmp(type, "unsigned short") == 0) sat = ushort_sat; break; case 16: if (strcmp(type, "unsigned __int64") == 0) sat = ulonglong_sat; break; case 18: if (strcmp(type, "unsigned long long") == 0) sat = ulonglong_sat; break; } if (sat == unknown_sat) { const sipTypeDef *td = sipFindType(type); if (td) { if (sipTypeIsClass(td)) { if (indir == 0) sat = class_sat; else if (indir == 1) sat = classp_sat; arg->u.wt = (sipWrapperType *)sipTypeAsPyTypeObject(td); } else if (sipTypeIsMapped(td)) { if (indir == 0) sat = mtype_sat; else if (indir == 1) sat = mtypep_sat; arg->u.mt = td; } else if (sipTypeIsEnum(td)) { if (indir == 0) sat = enum_sat; arg->u.et = sipTypeAsPyTypeObject(td); } } } else if (unsup) sat = unknown_sat; arg->atype = sat; } // Dispose of a receiver that might be a universal slot. static void sipTQtDestroyUniversalSlot(void *rx) { for (UniversalSlot *us = UniversalSlot::unislots; us; us = us->nextus) if (us == reinterpret_cast(rx)) { delete us; break; } } // Search for the universal slot connected to a particular TQt signal. static void *sipTQtFindSlot(void *tx, const char *sig, PyObject *rxObj, const char *slot, const char **member) { for (UniversalSlot *us = UniversalSlot::unislots; us; us = us->nextus) { pyqt3SlotConnection *conn = &us->conn; if (conn->sc_transmitter != tx) continue; if (!sipTQtSameSignalSlotName(conn->sc_signature->sg_signature, sig)) continue; if (sipSameSlot(&conn->sc_slot, rxObj, slot)) { *member = SLOT(unislot()); return us; } } return 0; } // Connect a TQt signal to a TQt slot. static int sipTQtConnect(void *tx, const char *sig, void *rx, const char *slot, int) { return TQObject::connect(reinterpret_cast(tx), sig, reinterpret_cast(rx), slot); } // Disconnect a TQt signal from a TQt slot. static int sipTQtDisconnect(void *tx, const char *sig, void *rx, const char *slot) { return TQObject::disconnect(reinterpret_cast(tx), sig, reinterpret_cast(rx), slot); } // See if two signal or slot names are the same. static int sipTQtSameSignalSlotName(const char *s1, const char *s2) { // moc formats signal names, so we should first convert the supplied // string to the same format before comparing them. Instead we just // compare them as they are, but ignoring all spaces - this will have // the same result. do { // Skip any spaces. while (*s1 == ' ') ++s1; while (*s2 == ' ') ++s2; if (*s1++ != *s2) return 0; } while (*s2++ != '\0'); return 1; } // Return the next slot for a particular transmitter. This will be called with // the GIL locked. static sipSlot *sipTQtFindSipslot(void *tx, void **context) { UniversalSlot *us = *reinterpret_cast(context); if (!us) us = UniversalSlot::unislots; sipSlot *slot = 0; while (us) { pyqt3SlotConnection *this_conn = &us->conn; us = us->nextus; if (this_conn->sc_transmitter == tx) { slot = &this_conn->sc_slot; break; } } *context = us; return slot; } // Connect a slot from a Python signal. static int sipTQtConnectPySignal(PyObject *txObj, const char *sig, PyObject *rxObj, const char *slot) { pyqt3PySig *ps; pyqt3SlotList *psrx; pyqtWrapper *pw = (pyqtWrapper *)txObj; /* Create a new one if necessary. */ if ((ps = find_py_signal(pw, sig)) == NULL) { if ((ps = (pyqt3PySig *)sipMalloc(sizeof (pyqt3PySig))) == NULL) return -1; if ((ps->name = (char *)sipMalloc(strlen(sig) + 1)) == NULL) { sipFree(ps); return -1; } strcpy(ps->name, sig); ps->rxlist = NULL; ps->next = pw->pySigList; pw->pySigList = ps; } /* Create the new receiver. */ if ((psrx = (pyqt3SlotList *)sipMalloc(sizeof (pyqt3SlotList))) == NULL) return -1; if (sipSaveSlot(&psrx->rx, rxObj, slot) < 0) { sipFree(psrx); return -1; } psrx->next = ps->rxlist; ps->rxlist = psrx; return 0; } // Disconnect a slot from a Python signal. static void sipTQtDisconnectPySignal(PyObject *txObj, const char *sig, PyObject *rxObj, const char *slot) { pyqt3PySig *ps; if ((ps = find_py_signal((pyqtWrapper *)txObj, sig)) != NULL) { pyqt3SlotList **psrxp; for (psrxp = &ps->rxlist; *psrxp != NULL; psrxp = &(*psrxp)->next) { pyqt3SlotList *psrx = *psrxp; if (sipSameSlot(&psrx->rx, rxObj, slot)) { *psrxp = psrx->next; free_slot_list(psrx); break; } } } } // Emit a signal for the sip module. static int sipTQtEmitSignal(PyObject *self, const char *sig, PyObject *sigargs) { return pyqt3EmitSignal(self, sig, sigargs); } // Emit a Python or TQt signal. int pyqt3EmitSignal(PyObject *self, const char *sig, PyObject *sigargs) { // Don't do anything if signals are blocked. TQt signals would be blocked // anyway, but this blocks Python signals as well. void *tx = sipGetCppPtr((sipSimpleWrapper *)self, sipType_TQObject); if (!tx) return 0; if (reinterpret_cast(tx)->signalsBlocked()) return 0; // See if it is a TQt signal. if (*sig == '2') { pyqt3QtSignal *tab; // Search the table. for (tab = ((pyqt3ClassTypeDef *)((sipWrapperType *)(self->ob_type))->type)->qt3_emit; tab->st_name != NULL; ++tab) { const char *sp, *tp; bool found; // Compare only the base name. sp = &sig[1]; tp = tab->st_name; found = true; while (*sp != '\0' && *sp != '(' && *tp != '\0') if (*sp++ != *tp++) { found = false; break; } if (found) return (*tab->st_emitfunc)((sipSimpleWrapper *)self, sigargs); } // It wasn't found if we got this far. PyErr_Format(PyExc_NameError, "Invalid signal %s", &sig[1]); return -1; } pyqt3PySig *ps = find_py_signal((pyqtWrapper *)self, sig); if (ps) { int rc = 0; pyqt3SlotList *rxlist = ps->rxlist; // Forget the last TQt sender and remember this one. UniversalSlot::lastSender = 0; py_sender = self; // Apply the arguments to each slot method. while (rxlist && rc >= 0) { pyqt3SlotList *next; PyObject *res; // We get the next in the list before calling the slot in case the // list gets changed by the slot - usually because the slot // disconnects itself. next = rxlist->next; res = sipInvokeSlot(&rxlist->rx, sigargs); if (res) Py_DECREF(res); else rc = -1; rxlist = next; } // Forget this as a sender. py_sender = NULL; return rc; } return 0; } // Return the most recent signal sender. PyObject *pyqt3GetSender() { PyObject *sender; // If there is a TQt sender then it is more recent than the last Python // sender, so use it instead. if (UniversalSlot::lastSender) { sender = sipConvertFromType(UniversalSlot::lastSender, sipType_TQObject, NULL); } else { sender = (py_sender ? py_sender : Py_None); Py_INCREF(sender); } return sender; } %End %InitialisationCode // Initialise the meta-type. pyqtWrapperType_Type.tp_base = sipWrapperType_Type; if (PyType_Ready(&pyqtWrapperType_Type) < 0) Py_FatalError("qt: Failed to initialise pyqtWrapperType type"); // Register the meta-type. if (sipRegisterPyType((PyTypeObject *)&pyqtWrapperType_Type) < 0) Py_FatalError("qt: Failed to register pyqtWrapperType type"); // Initialise the super-type. #if PY_VERSION_HEX >= 0x02050000 pyqtWrapper_Type.super.ht_type.tp_base = sipWrapper_Type; #else pyqtWrapper_Type.super.type.tp_base = sipWrapper_Type; #endif if (PyType_Ready((PyTypeObject *)&pyqtWrapper_Type) < 0) Py_FatalError("qt: Failed to initialise pyqtWrapper type"); // Register the super-type. if (sipRegisterPyType((PyTypeObject *)&pyqtWrapper_Type) < 0) Py_FatalError("qt: Failed to register pyqtWrapper type"); %End