diff options
Diffstat (limited to 'sip/tqt/tqobject.sip')
-rw-r--r-- | sip/tqt/tqobject.sip | 2086 |
1 files changed, 2086 insertions, 0 deletions
diff --git a/sip/tqt/tqobject.sip b/sip/tqt/tqobject.sip new file mode 100644 index 0000000..2fb2ac2 --- /dev/null +++ b/sip/tqt/tqobject.sip @@ -0,0 +1,2086 @@ +// This is the SIP interface definition for TQObject. +// +// Copyright (c) 2007 +// Riverbank Computing Limited <info@riverbankcomputing.co.uk> +// +// 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 +<Sect2><Title>TQObject</Title> +<FuncSynopsis> + <FuncDef>bool <Function>disconnect</Function></FuncDef> + <ParamDef>const TQObject *<Parameter>receiver</Parameter></ParamDef> + <ParamDef>const char *<Parameter>member</Parameter> = 0</ParamDef> +</FuncSynopsis> +<Para> +Not yet implemented. +</Para> + +<FuncSynopsis> + <FuncDef>bool <Function>disconnect</Function></FuncDef> + <ParamDef>const char *<Parameter>signal</Parameter> = 0</ParamDef> + <ParamDef>const TQObject *<Parameter>receiver</Parameter> = 0</ParamDef> + <ParamDef>const char *<Parameter>member</Parameter> = 0</ParamDef> +</FuncSynopsis> +<Para> +Not yet implemented. +</Para> + +<FuncSynopsis> + <FuncDef>static bool <Function>disconnect</Function></FuncDef> + <ParamDef>const TQObject *<Parameter>sender</Parameter></ParamDef> + <ParamDef>const char *<Parameter>signal</Parameter></ParamDef> + <ParamDef>const TQObject *<Parameter>receiver</Parameter></ParamDef> + <ParamDef>const char *<Parameter>member</Parameter></ParamDef> +</FuncSynopsis> +<Para> +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 +<Literal>signal</Literal> and <Literal>receiver</Literal> parameters is not yet +supported. +</Para> +</Sect2> +%End + + +class TQObject : TQt +{ +%TypeHeaderCode +#include <tqobject.h> +#include <tqapplication.h> +%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(PYTQT_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 + sipRes = PyUnicode_FromString(sipSelf->ob_type->tp_name); +%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_tqt_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(TQString::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_tqt_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_TQOBJECT,SIP_SIGNAL,SIP_TQOBJECT,SIP_SLOT); +%MethodCode + sipRes = sipConnectRx(a0,a1,a2,a3,0); +%End + + static SIP_PYOBJECT connect(SIP_TQOBJECT,SIP_SIGNAL,SIP_PYCALLABLE); +%MethodCode + sipRes = sipConnectRx(a0,a1,a2,0,0); +%End + + SIP_PYOBJECT connect(SIP_TQOBJECT,SIP_SIGNAL,SIP_SLOT) const; +%MethodCode + sipRes = sipConnectRx(a0,a1,sipSelf,a2,0); +%End + + static SIP_PYOBJECT disconnect(SIP_TQOBJECT,SIP_SIGNAL,SIP_TQOBJECT,SIP_SLOT); +%MethodCode + sipRes = sipDisconnectRx(a0,a1,a2,a3); +%End + + static SIP_PYOBJECT disconnect(SIP_TQOBJECT,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 (pytqtEmitSignal(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 = pytqt3GetSender(); +%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="TQT_SLOT"/; +%MethodCode + if (!a0) + { + PyErr_Format(PyExc_TypeError,"tqt.SLOT() slot name cannot be None"); + sipIsErr = 1; + } + else + { + int len = strlen(a0); + + if ((sipRes = PyBytes_FromStringAndSize(NULL,1 + len)) == NULL) + sipIsErr = 1; + else + { + char *dp = PyBytes_AS_STRING(sipRes); + + *dp++ = '1'; + + memcpy(dp,a0,len + 1); + } + } +%End + + +SIP_PYOBJECT SIGNAL(const char * /Encoding="ASCII"/) /TypeHint="TQT_SIGNAL"/; +%MethodCode + if (!a0) + { + PyErr_Format(PyExc_TypeError,"tqt.SIGNAL() signal cannot be None"); + sipIsErr = 1; + } + else + { + int len = strlen(a0); + + if ((sipRes = PyBytes_FromStringAndSize(NULL,1 + len)) == NULL) + sipIsErr = 1; + else + { + char *dp = PyBytes_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,"tqt.PYSIGNAL() signal cannot be None"); + sipIsErr = 1; + } + else + { + int len = strlen(a0); + + if ((sipRes = PyBytes_FromStringAndSize(NULL,1 + len)) == NULL) + sipIsErr = 1; + else + { + char *dp = PyBytes_AS_STRING(sipRes); + + *dp++ = '9'; + + memcpy(dp,a0,len + 1); + } + } +%End + + +%ModuleHeaderCode + +int pytqtEmitSignal(PyObject *self, const char *sig, PyObject *sigargs); +PyObject *pytqt3GetSender(); + +%End + + +// This is the TQt support code for SIP v4.4 and later. +%ModuleCode + +#include <string.h> + +#include <tqobject.h> +#include <tqvariant.h> +#include <tqmetaobject.h> +#include <private/qucom_p.h> +#include <private/qucomextra_p.h> + + +// 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 pytqtWrapperType_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "tqt.pytqtWrapperType", /* 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 */ +#else + 0, /* tp_reserved */ +#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 */ + 0, /* tp_version_tag */ +#if PY_VERSION_HEX >= 0x03040000 + 0, /* tp_finalize */ +#endif +#if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall */ +#endif +#if PY_VERSION_HEX == 0x03080000 + 0, /* tp_print (deprecated) */ +#endif +}; + + +/* + * An entry in a linked list of slots. + */ +typedef struct _pytqt3SlotList { + /* The receiver. */ + sipSlot rx; + + /* Next in the list. */ + struct _pytqt3SlotList *next; +} pytqt3SlotList; + + +/* + * A Python signal. + */ +typedef struct _pytqt3PySig { + /* The name of the signal. */ + char *name; + + /* The list of receivers. */ + pytqt3SlotList *rxlist; + + /* Next in the list. */ + struct _pytqt3PySig *next; +} pytqt3PySig; + + +/* + * The C++ wrapper object used by PyTQt3. + */ +typedef struct _pytqtWrapper { + /* The super-type. */ + sipWrapper super; + + /* The list of Python signals. */ + pytqt3PySig *pySigList; +} pytqtWrapper; + + +/* + * Clear any slots connected to any Python signals. + */ +static void clear_py_signals_slots(pytqtWrapper *pw) +{ + pytqt3PySig *ps; + + for (ps = pw->pySigList; ps != NULL; ps = ps->next) + { + pytqt3SlotList *psrx; + + for (psrx = ps->rxlist; psrx != NULL; psrx = psrx->next) + sipClearAnySlotReference(&psrx->rx); + } +} + + +/* + * Find the given Python signal. + */ +static pytqt3PySig *find_py_signal(pytqtWrapper *pw, const char *sig) +{ + pytqt3PySig *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(pytqt3SlotList *sl) +{ + sipFreeSipslot(&sl->rx); + sipFree(sl); +} + + +/* + * The instance clear slot. + */ +static int pytqtWrapper_clear(pytqtWrapper *self) +{ + clear_py_signals_slots(self); + + return sipWrapper_Type->tp_clear((PyObject *)self); +} + + +/* + * The instance dealloc slot. + */ +static void pytqtWrapper_dealloc(pytqtWrapper *self) +{ + clear_py_signals_slots(self); + + while (self->pySigList != NULL) + { + pytqt3PySig *ps; + pytqt3SlotList *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 pytqtWrapper_traverse(pytqtWrapper *self, visitproc visit, void *arg) +{ + int vret; + pytqt3PySig *ps; + + if ((vret = sipWrapper_Type->tp_traverse((PyObject *)self, visit, arg)) != 0) + return vret; + + for (ps = self->pySigList; ps != NULL; ps = ps->next) + { + pytqt3SlotList *psrx; + + for (psrx = ps->rxlist; psrx != NULL; psrx = psrx->next) + if ((vret = sipVisitSlot(&psrx->rx, visit, arg)) != 0) + return vret; + } + + return 0; +} + + +static sipWrapperType pytqtWrapper_Type = { +#if !defined(STACKLESS) + { +#endif + { + PyVarObject_HEAD_INIT(&pytqtWrapperType_Type, 0) + "tqt.pytqtWrapper", /* tp_name */ + sizeof (pytqtWrapper), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)pytqtWrapper_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 */ +#else + 0, /* tp_reserved */ +#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)pytqtWrapper_traverse, /* tp_traverse */ + (inquiry)pytqtWrapper_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 */ + 0, /* tp_version_tag */ +#if PY_VERSION_HEX >= 0x03040000 + 0, /* tp_finalize */ +#endif +#if PY_VERSION_HEX >= 0x03080000 + 0, /* tp_vectorcall */ +#endif +#if PY_VERSION_HEX == 0x03080000 + 0, /* tp_print (deprecated) */ +#endif + }, +#if !defined(STACKLESS) + }, +#endif + 0, + 0, + 0 +}; + +}; + + +// This enumerates the different dynamic signal argument types. +enum pytqt3SigArgType { + 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 pytqt3SigArg +{ + // The type. + pytqt3SigArgType 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 pytqt3Signature { + // The number of arguments. + int sg_nrargs; + + // The parsed arguments (heap). + pytqt3SigArg *sg_args; + + // The unparsed signature (heap). + char *sg_signature; + + // The next in the list. + pytqt3Signature *sg_next; +}; + + +// A connection to a universal slot. +struct pytqt3SlotConnection +{ + // The transmitter TQObject. + void *sc_transmitter; + + // The parsed signature. + const pytqt3Signature *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 *tqtx, pytqt3SlotConnection *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; + pytqt3SlotConnection 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 *tqtx, pytqt3SlotConnection *connection, const char **member) : TQObject() +{ + // Save the connection. + conn = *connection; + + // Detect when the transmitter is destroyed. + if (tqtx) + connect(tqtx, 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 pytqt3Signature *psig = conn.sc_signature; + TQVariant *qv; + + // Save in case it is asked for later. + lastSender = const_cast<TQObject *>(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 = PyBytes_FromStringAndSize((char *)static_QUType_ptr.get(qargs), 1); + break; + + case string_sat: + case sstring_sat: + case ustring_sat: + arg = PyBytes_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 pytqt3Signature *parseSignature(const char *sig); +static void parseType(const char *type, pytqt3SigArg *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) +{ + pytqt3SlotConnection 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 *tqtx = 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)) + tqtx = reinterpret_cast<TQObject *>(conn.sc_transmitter); + + return new UniversalSlot(tqtx, &conn, member); +} + + +// Parse the signal arguments for a connection. +static pytqt3Signature *parseSignature(const char *sig) +{ + static pytqt3Signature *psig_list = NULL; + pytqt3Signature *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 = (pytqt3Signature *)sipMalloc(sizeof (pytqt3Signature) + 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 = (pytqt3SigArg *)sipMalloc(sizeof (pytqt3SigArg) * 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, pytqt3SigArg *arg) +{ + size_t btlen = 0; + int unsup, isref = FALSE, indir = 0; + const char *ep; + pytqt3SigArgType 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<TQObject *>(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) + { + pytqt3SlotConnection *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<TQObject *>(tx), sig, + reinterpret_cast<TQObject *>(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<TQObject *>(tx), sig, + reinterpret_cast<TQObject *>(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<UniversalSlot **>(context); + + if (!us) + us = UniversalSlot::unislots; + + sipSlot *slot = 0; + + while (us) + { + pytqt3SlotConnection *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) +{ + pytqt3PySig *ps; + pytqt3SlotList *psrx; + pytqtWrapper *pw = (pytqtWrapper *)txObj; + + /* Create a new one if necessary. */ + if ((ps = find_py_signal(pw, sig)) == NULL) + { + if ((ps = (pytqt3PySig *)sipMalloc(sizeof (pytqt3PySig))) == 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 = (pytqt3SlotList *)sipMalloc(sizeof (pytqt3SlotList))) == 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) +{ + pytqt3PySig *ps; + + if ((ps = find_py_signal((pytqtWrapper *)txObj, sig)) != NULL) + { + pytqt3SlotList **psrxp; + + for (psrxp = &ps->rxlist; *psrxp != NULL; psrxp = &(*psrxp)->next) + { + pytqt3SlotList *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 pytqtEmitSignal(self, sig, sigargs); +} + + +// Emit a Python or TQt signal. +int pytqtEmitSignal(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<TQObject *>(tx)->signalsBlocked()) + return 0; + + // See if it is a TQt signal. + if (*sig == '2') + { + pytqtTQtSignal *tab; + + // Search the table. + for (tab = ((pytqtClassTypeDef *)((sipWrapperType *)(self->ob_type))->type)->tqt_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; + } + + pytqt3PySig *ps = find_py_signal((pytqtWrapper *)self, sig); + + if (ps) + { + int rc = 0; + pytqt3SlotList *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) + { + pytqt3SlotList *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 *pytqt3GetSender() +{ + 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. + pytqtWrapperType_Type.tp_base = sipWrapperType_Type; + + if (PyType_Ready(&pytqtWrapperType_Type) < 0) + Py_FatalError("tqt: Failed to initialise pytqtWrapperType type"); + + // Register the meta-type. + if (sipRegisterPyType((PyTypeObject *)&pytqtWrapperType_Type) < 0) + Py_FatalError("tqt: Failed to register pytqtWrapperType type"); + + // Initialise the super-type. + pytqtWrapper_Type.super.ht_type.tp_base = sipWrapper_Type; + + if (PyType_Ready((PyTypeObject *)&pytqtWrapper_Type) < 0) + Py_FatalError("tqt: Failed to initialise pytqtWrapper type"); + + // Register the super-type. + if (sipRegisterPyType((PyTypeObject *)&pytqtWrapper_Type) < 0) + Py_FatalError("tqt: Failed to register pytqtWrapper type"); +%End |