diff --git a/cmake_templates/Doxyfile.in b/cmake_templates/Doxyfile.in index 1704adf86df..c174ca8494b 100644 --- a/cmake_templates/Doxyfile.in +++ b/cmake_templates/Doxyfile.in @@ -2439,7 +2439,8 @@ EXPAND_AS_DEFINED = "SIP_ABSTRACT" \ "SIP_MONKEYPATCH_COMPAT_NAME" \ "SIP_MONKEYPATCH_SCOPEENUM" \ "SIP_MONKEYPATCH_SCOPEENUM_UNNEST" \ - "SIP_MONKEYPATCH_FLAGS_UNNEST" + "SIP_MONKEYPATCH_FLAGS_UNNEST" \ + "SIP_INSERT_QLIST_ENUM_CONVERSION_CODE" # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have diff --git a/python/PyQt6/core/auto_generated/auth/qgsauthconfig.sip.in b/python/PyQt6/core/auto_generated/auth/qgsauthconfig.sip.in index 8d728d64ae2..7938c9194ef 100644 --- a/python/PyQt6/core/auto_generated/auth/qgsauthconfig.sip.in +++ b/python/PyQt6/core/auto_generated/auth/qgsauthconfig.sip.in @@ -391,11 +391,10 @@ setCaChain set the CA chain -%MappedType QList -/ TypeHintIn = "Iterable[QSslError.SslError]", - TypeHintOut = "List[QSslError.SslError]", TypeHintValue = "[]" / +%MappedType QList /TypeHintIn = "Iterable[QSslError.SslError]",TypeHintOut = "List[QSslError.SslError]", TypeHintValue = "[]"/ { %TypeHeaderCode +#include #include %End @@ -407,8 +406,7 @@ setCaChain set the CA chain for ( int i = 0; i < sipCpp->size(); ++i ) { - PyObject *eobj = sipConvertFromEnum( static_cast( sipCpp->at( i ) ), - sipType_QSslError_SslError ); + PyObject *eobj = sipConvertFromEnum( static_cast( sipCpp->at( i ) ), sipType_QSslError_SslError ); if ( !eobj ) { @@ -443,7 +441,7 @@ setCaChain set the CA chain QList *ql = new QList; - for ( Py_ssize_t i = 0; ; ++i ) + for ( Py_ssize_t i = 0;; ++i ) { PyErr_Clear(); PyObject *itm = PyIter_Next( iter ); @@ -466,9 +464,7 @@ setCaChain set the CA chain if ( PyErr_Occurred() ) { - PyErr_Format( PyExc_TypeError, - "index %zd has type '%s' but 'QSslError.SslError' is expected", - i, sipPyTypeName( Py_TYPE( itm ) ) ); + PyErr_Format( PyExc_TypeError, "index %zd has type '%s' but 'QSslError.SslError' is expected", i, sipPyTypeName( Py_TYPE( itm ) ) ); Py_DECREF( itm ); delete ql; @@ -492,7 +488,6 @@ setCaChain set the CA chain }; - class QgsAuthConfigSslServer { %Docstring(signature="appended") diff --git a/python/PyQt6/gui/auto_generated/editorwidgets/core/qgssearchwidgetwrapper.sip.in b/python/PyQt6/gui/auto_generated/editorwidgets/core/qgssearchwidgetwrapper.sip.in index 1c83a836ee2..318ea3322ad 100644 --- a/python/PyQt6/gui/auto_generated/editorwidgets/core/qgssearchwidgetwrapper.sip.in +++ b/python/PyQt6/gui/auto_generated/editorwidgets/core/qgssearchwidgetwrapper.sip.in @@ -10,6 +10,7 @@ + %MappedType QList /TypeHintIn = "Iterable[QgsSearchWidgetWrapper.FilterFlag]",TypeHintOut = "List[QgsSearchWidgetWrapper.FilterFlag]", TypeHintValue = "[]"/ { %TypeHeaderCode @@ -104,6 +105,8 @@ return sipGetState( sipTransferObj ); %End }; + + class QgsSearchWidgetWrapper : QgsWidgetWrapper { %Docstring(signature="appended") diff --git a/python/core/auto_generated/auth/qgsauthconfig.sip.in b/python/core/auto_generated/auth/qgsauthconfig.sip.in index 8d728d64ae2..7938c9194ef 100644 --- a/python/core/auto_generated/auth/qgsauthconfig.sip.in +++ b/python/core/auto_generated/auth/qgsauthconfig.sip.in @@ -391,11 +391,10 @@ setCaChain set the CA chain -%MappedType QList -/ TypeHintIn = "Iterable[QSslError.SslError]", - TypeHintOut = "List[QSslError.SslError]", TypeHintValue = "[]" / +%MappedType QList /TypeHintIn = "Iterable[QSslError.SslError]",TypeHintOut = "List[QSslError.SslError]", TypeHintValue = "[]"/ { %TypeHeaderCode +#include #include %End @@ -407,8 +406,7 @@ setCaChain set the CA chain for ( int i = 0; i < sipCpp->size(); ++i ) { - PyObject *eobj = sipConvertFromEnum( static_cast( sipCpp->at( i ) ), - sipType_QSslError_SslError ); + PyObject *eobj = sipConvertFromEnum( static_cast( sipCpp->at( i ) ), sipType_QSslError_SslError ); if ( !eobj ) { @@ -443,7 +441,7 @@ setCaChain set the CA chain QList *ql = new QList; - for ( Py_ssize_t i = 0; ; ++i ) + for ( Py_ssize_t i = 0;; ++i ) { PyErr_Clear(); PyObject *itm = PyIter_Next( iter ); @@ -466,9 +464,7 @@ setCaChain set the CA chain if ( PyErr_Occurred() ) { - PyErr_Format( PyExc_TypeError, - "index %zd has type '%s' but 'QSslError.SslError' is expected", - i, sipPyTypeName( Py_TYPE( itm ) ) ); + PyErr_Format( PyExc_TypeError, "index %zd has type '%s' but 'QSslError.SslError' is expected", i, sipPyTypeName( Py_TYPE( itm ) ) ); Py_DECREF( itm ); delete ql; @@ -492,7 +488,6 @@ setCaChain set the CA chain }; - class QgsAuthConfigSslServer { %Docstring(signature="appended") diff --git a/python/gui/auto_generated/editorwidgets/core/qgssearchwidgetwrapper.sip.in b/python/gui/auto_generated/editorwidgets/core/qgssearchwidgetwrapper.sip.in index 78db296533b..4dcee387efb 100644 --- a/python/gui/auto_generated/editorwidgets/core/qgssearchwidgetwrapper.sip.in +++ b/python/gui/auto_generated/editorwidgets/core/qgssearchwidgetwrapper.sip.in @@ -10,6 +10,7 @@ + %MappedType QList /TypeHintIn = "Iterable[QgsSearchWidgetWrapper.FilterFlag]",TypeHintOut = "List[QgsSearchWidgetWrapper.FilterFlag]", TypeHintValue = "[]"/ { %TypeHeaderCode @@ -104,6 +105,8 @@ return sipGetState( sipTransferObj ); %End }; + + class QgsSearchWidgetWrapper : QgsWidgetWrapper { %Docstring(signature="appended") diff --git a/scripts/cppcheck.sh b/scripts/cppcheck.sh index 7916474f590..4e385d4646f 100755 --- a/scripts/cppcheck.sh +++ b/scripts/cppcheck.sh @@ -36,6 +36,7 @@ cppcheck --library=qt.cfg --inline-suppr \ -DSIP_FACTORY= \ -DSIP_PYNAME= \ -DSIP_THROW= \ + -DSIP_INSERT_QLIST_ENUM_CONVERSION_CODE= \ -DFINAL="final" \ -DCMAKE_SOURCE_DIR="/foo/bar" \ -DQ_NOWARN_DEPRECATED_PUSH= \ diff --git a/scripts/sipify.py b/scripts/sipify.py index 9a9661cda3d..3dbca9885ff 100755 --- a/scripts/sipify.py +++ b/scripts/sipify.py @@ -555,6 +555,103 @@ CLASS_HEADERFILES = { "QgsSettingsEntryBaseTemplate": "qgssettingsentry.h", } +QLIST_ENUM_CONVERSION_CODE = """ +%MappedType QList<{class_name}::{enum_name}> /TypeHintIn = "Iterable[{class_name}.{enum_name}]",TypeHintOut = "List[{class_name}.{enum_name}]", TypeHintValue = "[]"/ +{{ +%TypeHeaderCode +#include {extra_includes} +%End + +%ConvertFromTypeCode + PyObject *l = PyList_New( sipCpp->size() ); + + if ( !l ) + return 0; + + for ( int i = 0; i < sipCpp->size(); ++i ) + {{ + PyObject *eobj = sipConvertFromEnum( static_cast( sipCpp->at( i ) ), sipType_{class_name}_{enum_name} ); + + if ( !eobj ) + {{ + Py_DECREF( l ); + + return 0; + }} + + PyList_SetItem( l, i, eobj ); + }} + + return l; +%End + +%ConvertToTypeCode + PyObject *iter = PyObject_GetIter( sipPy ); + + if ( !sipIsErr ) + {{ + PyErr_Clear(); + Py_XDECREF( iter ); + + return ( iter && !PyBytes_Check( sipPy ) && !PyUnicode_Check( sipPy ) ); + }} + + if ( !iter ) + {{ + *sipIsErr = 1; + + return 0; + }} + + QList<{class_name}::{enum_name}> *ql = new QList<{class_name}::{enum_name}>; + + for ( Py_ssize_t i = 0;; ++i ) + {{ + PyErr_Clear(); + PyObject *itm = PyIter_Next( iter ); + + if ( !itm ) + {{ + if ( PyErr_Occurred() ) + {{ + delete ql; + Py_DECREF( iter ); + *sipIsErr = 1; + + return 0; + }} + + break; + }} + + int v = sipConvertToEnum( itm, sipType_{class_name}_{enum_name} ); + + if ( PyErr_Occurred() ) + {{ + PyErr_Format( PyExc_TypeError, "index %zd has type '%s' but '{class_name}.{enum_name}' is expected", i, sipPyTypeName( Py_TYPE( itm ) ) ); + + Py_DECREF( itm ); + delete ql; + Py_DECREF( iter ); + *sipIsErr = 1; + + return 0; + }} + + ql->append( static_cast<{class_name}::{enum_name}>( v ) ); + + Py_DECREF( itm ); + }} + + Py_DECREF( iter ); + + *sipCppPtr = ql; + + return sipGetState( sipTransferObj ); +%End +}}; +""" + def replace_macros(line): line = re.sub(r"\bTRUE\b", "``True``", line) @@ -1649,6 +1746,23 @@ def try_process_sip_directive(): dbg_info("found SIP_WHEN_FEATURE") CONTEXT.if_feature_condition = match.group(1) + match = re.search( + r"^\s*SIP_INSERT_QLIST_ENUM_CONVERSION_CODE\(\s*(.*?)::(.*?)\s*,\s*\"(.*?)\"\s*\)\s*;?\s*$", + CONTEXT.current_line, + ) + + if match: + class_name = match.group(1) + enum_name = match.group(2) + extra_includes = match.group(3) + if extra_includes: + extra_includes = f"\n#include {extra_includes}" + sip_convert_code = QLIST_ENUM_CONVERSION_CODE.format( + class_name=class_name, enum_name=enum_name, extra_includes=extra_includes + ) + write_output("SCC", sip_convert_code) + CONTEXT.current_line = "" + match = re.search(r'SIP_TYPEHEADER_INCLUDE\(\s*"(.*?)"\s*\)', CONTEXT.current_line) if match: dbg_info("found SIP_TYPEHEADER_INCLUDE") diff --git a/src/core/auth/qgsauthconfig.h b/src/core/auth/qgsauthconfig.h index f4ec8744900..d0d0f7f5401 100644 --- a/src/core/auth/qgsauthconfig.h +++ b/src/core/auth/qgsauthconfig.h @@ -330,110 +330,7 @@ class CORE_EXPORT QgsPkiConfigBundle }; - -#ifdef SIP_RUN -% MappedType QList -/ TypeHintIn = "Iterable[QSslError.SslError]", - TypeHintOut = "List[QSslError.SslError]", TypeHintValue = "[]" / -{ - % TypeHeaderCode -#include - % End - - % ConvertFromTypeCode - PyObject *l = PyList_New( sipCpp->size() ); - - if ( !l ) - return 0; - - for ( int i = 0; i < sipCpp->size(); ++i ) - { - PyObject *eobj = sipConvertFromEnum( static_cast( sipCpp->at( i ) ), - sipType_QSslError_SslError ); - - if ( !eobj ) - { - Py_DECREF( l ); - - return 0; - } - - PyList_SetItem( l, i, eobj ); - } - - return l; - % End - - % ConvertToTypeCode - PyObject *iter = PyObject_GetIter( sipPy ); - - if ( !sipIsErr ) - { - PyErr_Clear(); - Py_XDECREF( iter ); - - return ( iter && !PyBytes_Check( sipPy ) && !PyUnicode_Check( sipPy ) ); - } - - if ( !iter ) - { - *sipIsErr = 1; - - return 0; - } - - QList *ql = new QList; - - for ( Py_ssize_t i = 0; ; ++i ) - { - PyErr_Clear(); - PyObject *itm = PyIter_Next( iter ); - - if ( !itm ) - { - if ( PyErr_Occurred() ) - { - delete ql; - Py_DECREF( iter ); - *sipIsErr = 1; - - return 0; - } - - break; - } - - int v = sipConvertToEnum( itm, sipType_QSslError_SslError ); - - if ( PyErr_Occurred() ) - { - PyErr_Format( PyExc_TypeError, - "index %zd has type '%s' but 'QSslError.SslError' is expected", - i, sipPyTypeName( Py_TYPE( itm ) ) ); - - Py_DECREF( itm ); - delete ql; - Py_DECREF( iter ); - *sipIsErr = 1; - - return 0; - } - - ql->append( static_cast( v ) ); - - Py_DECREF( itm ); - } - - Py_DECREF( iter ); - - *sipCppPtr = ql; - - return sipGetState( sipTransferObj ); - % End -}; -#endif - - +SIP_INSERT_QLIST_ENUM_CONVERSION_CODE( QSslError::SslError, "" ); /** * \ingroup core diff --git a/src/core/qgis_sip.h b/src/core/qgis_sip.h index 22d8d20db91..c1d14167317 100644 --- a/src/core/qgis_sip.h +++ b/src/core/qgis_sip.h @@ -300,4 +300,11 @@ */ #define SIP_TYPEHEADER_INCLUDE(file) +/* + * Inserts sip conversion code for QList, where class_name::enum_name is a c++ enum. + * + * extra_includes is an optional argument containing extra headers to include in the conversion code. Set to "" if not required. + */ +#define SIP_INSERT_QLIST_ENUM_CONVERSION_CODE(class_name, extra_includes) + #endif // QGIS_SIP_H diff --git a/src/gui/editorwidgets/core/qgssearchwidgetwrapper.h b/src/gui/editorwidgets/core/qgssearchwidgetwrapper.h index 87107fce13a..895671072f6 100644 --- a/src/gui/editorwidgets/core/qgssearchwidgetwrapper.h +++ b/src/gui/editorwidgets/core/qgssearchwidgetwrapper.h @@ -28,102 +28,8 @@ class QgsField; #include "qgswidgetwrapper.h" #include "qgis_gui.h" -#ifdef SIP_RUN -//%MappedType QList /TypeHintIn = "Iterable[QgsSearchWidgetWrapper.FilterFlag]",TypeHintOut = "List[QgsSearchWidgetWrapper.FilterFlag]", TypeHintValue = "[]"/ -{ - //%TypeHeaderCode -#include - //%End +SIP_INSERT_QLIST_ENUM_CONVERSION_CODE( QgsSearchWidgetWrapper::FilterFlag, "" ); - //%ConvertFromTypeCode - PyObject *l = PyList_New( sipCpp->size() ); - - if ( !l ) - return 0; - - for ( int i = 0; i < sipCpp->size(); ++i ) - { - PyObject *eobj = sipConvertFromEnum( static_cast( sipCpp->at( i ) ), sipType_QgsSearchWidgetWrapper_FilterFlag ); - - if ( !eobj ) - { - Py_DECREF( l ); - - return 0; - } - - PyList_SetItem( l, i, eobj ); - } - - return l; - //%End - - //%ConvertToTypeCode - PyObject *iter = PyObject_GetIter( sipPy ); - - if ( !sipIsErr ) - { - PyErr_Clear(); - Py_XDECREF( iter ); - - return ( iter && !PyBytes_Check( sipPy ) && !PyUnicode_Check( sipPy ) ); - } - - if ( !iter ) - { - *sipIsErr = 1; - - return 0; - } - - QList *ql = new QList; - - for ( Py_ssize_t i = 0;; ++i ) - { - PyErr_Clear(); - PyObject *itm = PyIter_Next( iter ); - - if ( !itm ) - { - if ( PyErr_Occurred() ) - { - delete ql; - Py_DECREF( iter ); - *sipIsErr = 1; - - return 0; - } - - break; - } - - int v = sipConvertToEnum( itm, sipType_QgsSearchWidgetWrapper_FilterFlag ); - - if ( PyErr_Occurred() ) - { - PyErr_Format( PyExc_TypeError, "index %zd has type '%s' but 'QgsSearchWidgetWrapper.FilterFlag' is expected", i, sipPyTypeName( Py_TYPE( itm ) ) ); - - Py_DECREF( itm ); - delete ql; - Py_DECREF( iter ); - *sipIsErr = 1; - - return 0; - } - - ql->append( static_cast( v ) ); - - Py_DECREF( itm ); - } - - Py_DECREF( iter ); - - *sipCppPtr = ql; - - return sipGetState( sipTransferObj ); - //%End -}; -#endif /** * \ingroup gui *