<?xml version="1.0" encoding="UTF-8"?>
<!--
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt for Python.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
-->
<typesystem>

    <template name="tuple_ok_retval">
        %PYARG_0 = PyTuple_New(2);
        PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[bool](ok_));
        PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[%RETURN_TYPE](retval_));
    </template>

    <template name="bool*_fix,arg">
        bool ok_;
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(&amp;ok_, %2);
        <insert-template name="tuple_ok_retval"/>
    </template>

    <template name="bool*_fix,arg,arg,arg,arg">
        bool ok_;
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(&amp;ok_, %2, %3, %4, %5);
        <insert-template name="tuple_ok_retval"/>
    </template>

    <!-- Templates to fix bool* parameters -->
    <template name="tuple_retval_ok">
        %PYARG_0 = PyTuple_New(2);
        PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%RETURN_TYPE](retval_));
        PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[bool](ok_));
    </template>

    <template name="fix_bool*">
        bool ok_;
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(&amp;ok_);
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_args,bool*">
        bool ok_;
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, &amp;ok_);
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_args,arg,bool*">
        bool ok_;
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(%1, &amp;ok_);
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_arg,bool*,arg">
        bool ok_;
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(%1, &amp;ok_, %3);
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_bool*,arg">
        bool ok_;
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(&amp;ok_, %2);
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_bool*,arg,arg">
        bool ok_;
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(&amp;ok_, %2, %3);
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_bool*,arg,arg,arg">
        bool ok_;
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(&amp;ok_, %2, %3, %4);
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_bool*,arg,arg,arg,arg">
        bool ok_;
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(&amp;ok_, %2, %3, %4, %5);
        <insert-template name="tuple_retval_ok"/>
    </template>

    <!-- QInputDialog: these should allow threads -->
    <template name="fix_arg,arg,arg,arg,arg,arg,arg,bool*,arg">
        bool ok_;
        %RETURN_TYPE retval_;
        Py_BEGIN_ALLOW_THREADS
        retval_ = %CPPSELF.%FUNCTION_NAME(%1, %2, %3, %4, %5, %6, %7, &amp;ok_, %9);
        Py_END_ALLOW_THREADS
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_arg,arg,arg,arg,arg,arg,arg,bool*,arg,arg">
        bool ok_;
        %RETURN_TYPE retval_;
        Py_BEGIN_ALLOW_THREADS
        retval_ = %CPPSELF.%FUNCTION_NAME(%1, %2, %3, %4, %5, %6, %7, &amp;ok_, %9, %10);
        Py_END_ALLOW_THREADS
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_arg,arg,arg,arg,arg,arg,bool*,arg">
        bool ok_;
        %RETURN_TYPE retval_;
        Py_BEGIN_ALLOW_THREADS
        retval_ = %CPPSELF.%FUNCTION_NAME(%1, %2, %3, %4, %5, %6, &amp;ok_, %8);
        Py_END_ALLOW_THREADS
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_arg,arg,arg,arg,arg,bool*,arg">
        bool ok_;
        %RETURN_TYPE retval_;
        Py_BEGIN_ALLOW_THREADS
        retval_ = %CPPSELF.%FUNCTION_NAME(%1, %2, %3, %4, %5, &amp;ok_, %7);
        Py_END_ALLOW_THREADS
        <insert-template name="tuple_retval_ok"/>
    </template>

    <template name="fix_arg,arg,arg,arg,bool*,arg,arg">
        bool ok_;
        %RETURN_TYPE retval_;
        Py_BEGIN_ALLOW_THREADS
        retval_ = %CPPSELF.%FUNCTION_NAME(%1, %2, %3, %4, &amp;ok_, %6, %7);
        Py_END_ALLOW_THREADS
        <insert-template name="tuple_retval_ok"/>
    </template>
    <!-- End of QInputDialog templates -->

    <template name="fix_char*">
        char val_{};
        %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(&amp;val_);
        %PYARG_0 = PyTuple_New(2);
        PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%RETURN_TYPE](retval_));
        PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[char](val_));
    </template>

    <template name="tuple_abcd_same_type">
        %PYARG_0 = PyTuple_New(4);
        PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[$TYPE](a));
        PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[$TYPE](b));
        PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[$TYPE](c));
        PyTuple_SET_ITEM(%PYARG_0, 3, %CONVERTTOPYTHON[$TYPE](d));
    </template>

    <template name="fix_number*,number*,number*,number*">
        $TYPE a, b, c, d;
        %CPPSELF->::%TYPE::%FUNCTION_NAME(&amp;a, &amp;b, &amp;c, &amp;d);
        <insert-template name="tuple_abcd_same_type"/>
    </template>

    <template name="fix_number*,number*,number*,number*,args">
        $TYPE a, b, c, d;
        %CPPSELF->::%TYPE::%FUNCTION_NAME(&amp;a, &amp;b, &amp;c, &amp;d, %ARGUMENT_NAMES);
        <insert-template name="tuple_abcd_same_type"/>
    </template>

    <template name="fix_native_return_number*,number*,number*,number*">
        PyObject* _obj = %PYARG_0.object();
        if (!PySequence_Check(_obj)
            || PySequence_Fast_GET_SIZE(_obj) != 4
            || !PyNumber_Check(PySequence_Fast_GET_ITEM(_obj, 0))
            || !PyNumber_Check(PySequence_Fast_GET_ITEM(_obj, 1))
            || !PyNumber_Check(PySequence_Fast_GET_ITEM(_obj, 2))
            || !PyNumber_Check(PySequence_Fast_GET_ITEM(_obj, 3))) {
            PyErr_SetString(PyExc_TypeError, "Sequence of 4 numbers expected");
        } else {
            *%1 = %CONVERTTOCPP[$TYPE](PySequence_Fast_GET_ITEM(_obj, 0));
            *%2 = %CONVERTTOCPP[$TYPE](PySequence_Fast_GET_ITEM(_obj, 1));
            *%3 = %CONVERTTOCPP[$TYPE](PySequence_Fast_GET_ITEM(_obj, 2));
            *%4 = %CONVERTTOCPP[$TYPE](PySequence_Fast_GET_ITEM(_obj, 3));
        }
    </template>

    <template name="fix_number*,number*,number*,number*,number*">
        $TYPE a, b, c, d, e;
        %CPPSELF.%FUNCTION_NAME(&amp;a, &amp;b, &amp;c, &amp;d, &amp;e);
        %PYARG_0 = PyTuple_New(5);
        PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[$TYPE](a));
        PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[$TYPE](b));
        PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[$TYPE](c));
        PyTuple_SET_ITEM(%PYARG_0, 3, %CONVERTTOPYTHON[$TYPE](d));
        PyTuple_SET_ITEM(%PYARG_0, 4, %CONVERTTOPYTHON[$TYPE](e));
    </template>

    <template name="fix_args,number*,number*">
        $TYPE a, b;
        %CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, &amp;a, &amp;b);
        %PYARG_0 = PyTuple_New(2);
        PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[$TYPE](a));
        PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[$TYPE](b));
    </template>

    <template name="fix_arg,int*,int*">
    %RETURN_TYPE _ret;
    int a, b;
    _ret = %CPPSELF.%FUNCTION_NAME(%1, &amp;a, &amp;b);
    %PYARG_0 = PyTuple_New(3);
    PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%RETURN_TYPE](_ret));
    PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[int](a));
    PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[int](b));
    </template>

    <template name="return_tuple_QValidator_QString_int">
        %RETURN_TYPE retval_ = %RETURN_TYPE(%CPPSELF.%FUNCTION_NAME(%1, %2));
        %PYARG_0 = PyTuple_New(3);
        PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%RETURN_TYPE](retval_));
        PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[%ARG1_TYPE](%1));
        PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[%ARG2_TYPE](%2));
    </template>

    <template name="repr_code">
        QString format = QString::asprintf("%s(%REPR_FORMAT)",
            Py_TYPE(%PYSELF)->tp_name, %REPR_ARGS);
        %PYARG_0 = Shiboken::String::fromCString(qPrintable(format));
    </template>

    <template name="repr_qdebug">
        QString result;
        QDebug(&amp;result).nospace() &lt;&lt; "&lt;PySide6.MODULE." &lt;&lt; %CPPSELF &lt;&lt; '>';
        %PYARG_0 = Shiboken::String::fromCString(qPrintable(result));
    </template>

   <template name="repr_qdebug_gui">
       <insert-template name="repr_qdebug">
           <replace from="MODULE" to="QtGui"/>
       </insert-template>
   </template>

    <template name="return_internal_pointer">
        %PYARG_0 = reinterpret_cast&lt;PyObject*>(%CPPSELF.%FUNCTION_NAME());
        if (!%PYARG_0)
            %PYARG_0 = Py_None;
        Py_INCREF(%PYARG_0);
    </template>

    <!-- Helpers for modifying "bool nativeEventFilter(QByteArray, void*, long *result)"
         to return a tuple of bool,long -->
    <template name="return_native_eventfilter_conversion_variables">
        qintptr resultVar{0};
        qintptr *%out = &amp;resultVar;
    </template>
    <template name="return_native_eventfilter_conversion">
        %RETURN_TYPE %out = false;
        if (PySequence_Check(%PYARG_0) &amp;&amp; (PySequence_Size(%PYARG_0) == 2)) {
            Shiboken::AutoDecRef pyItem(PySequence_GetItem(%PYARG_0, 0));
            %out = %CONVERTTOCPP[bool](pyItem);
            if (result) {
                Shiboken::AutoDecRef pyResultItem(PySequence_GetItem(pyResult, 1));
                *result = %CONVERTTOCPP[long](pyResultItem);
            }
        }
    </template>

    <template name="return_native_eventfilter">
        %PYARG_0 = PyTuple_New(2);
        PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%RETURN_TYPE](%0));
        PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[long](*result_out));
    </template>

    <!-- templates for __reduce__ -->
    <template name="reduce_code">
        %PYARG_0 = Py_BuildValue("(N(%REDUCE_FORMAT))", PyObject_Type(%PYSELF), %REDUCE_ARGS);
    </template>

    <!-- Replace '#' for the argument number you want. -->
    <template name="return_argument">
        Py_INCREF(%PYARG_#);
        %PYARG_0 = %PYARG_#;
    </template>

    <!-- Iterator -->
    <template name="__iter__">
        Py_INCREF(%PYSELF);
        %PYARG_0 = %PYSELF;
    </template>

    <template name="to_tuple">
        %PYARG_0 = Py_BuildValue("%TT_FORMAT", %TT_ARGS);
    </template>

    <template name="cpplist_to_pylist_conversion">
    PyObject *%out = PyList_New(Py_ssize_t(%in.size()));
    Py_ssize_t idx = 0;
    for (auto it = %in.cbegin(), end = %in.cend(); it != end; ++it, ++idx) {
        const auto &amp;cppItem = *it;
        PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem));
    }
    return %out;
    </template>

    <template name="pyseq_to_cpplist_conversion">
    // PYSIDE-795: Turn all sequences into iterables.
    if (PyList_Check(%in)) {
        const Py_ssize_t size = PySequence_Size(%in);
        if (size &gt; 10)
            (%out).reserve(size);
    }

    Shiboken::AutoDecRef it(PyObject_GetIter(%in));
    PyObject *(*iternext)(PyObject *) = *Py_TYPE(it)->tp_iternext;
    for (;;) {
        Shiboken::AutoDecRef pyItem(iternext(it));
        if (pyItem.isNull()) {
            if (PyErr_Occurred() &amp;&amp; PyErr_ExceptionMatches(PyExc_StopIteration))
                PyErr_Clear();
            break;
        }
        %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem);
        %out &lt;&lt; cppItem;
    }
    </template>

    <template name="checkPyCapsuleOrPyCObject_func">
    static bool checkPyCapsuleOrPyCObject(PyObject* pyObj)
    {
        return PyCapsule_CheckExact(pyObj);
    }
    </template>

    <template name="cppmap_to_pymap_conversion">
      PyObject *%out = PyDict_New();
      for (auto it = %in.cbegin(), end = %in.cend(); it != end; ++it) {
          const auto &amp;key = it.key();
          const auto &amp;value = it.value();
          PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key);
          PyObject *pyValue = %CONVERTTOPYTHON[%INTYPE_1](value);
          PyDict_SetItem(%out, pyKey, pyValue);
          Py_DECREF(pyKey);
          Py_DECREF(pyValue);
      }
      return %out;
    </template>

    <template name="pydict_to_cppmap_conversion">
      PyObject *key;
      PyObject *value;
      Py_ssize_t pos = 0;
      while (PyDict_Next(%in, &amp;pos, &amp;key, &amp;value)) {
          %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
          %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value);
          %out.insert(cppKey, cppValue);
      }
    </template>

    <template name="cppmultimap_to_pymap_conversion">
      PyObject *%out = PyDict_New();
      for (auto it = %in.cbegin(), end = %in.cend(); it != end; ) {
          const auto &amp;key = it.key();
          PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key);
          %INTYPE::const_iterator keyEnd = %in.upperBound(key);
          const auto count = Py_ssize_t(std::distance(it, keyEnd));
          PyObject *pyValues = PyList_New(count);
          Py_ssize_t idx = 0;
          for ( ; it != keyEnd; ++it, ++idx) {
              const auto &amp;cppItem = it.value();
              PyList_SET_ITEM(pyValues, idx, %CONVERTTOPYTHON[%INTYPE_1](cppItem));
          }
          PyDict_SetItem(%out, pyKey, pyValues);
          Py_DECREF(pyKey);
      }
      return %out;
    </template>

    <template name="cppmultihash_to_pymap_conversion">
      PyObject *%out = PyDict_New();
      for (auto kit = %in.keyBegin(), end = %in.keyEnd(); kit != end; ++kit) {
          const auto &amp;key = *kit;
          PyObject *pyKey = %CONVERTTOPYTHON[%INTYPE_0](key);
          auto range = %in.equal_range(key);
          const auto count = Py_ssize_t(std::distance(range.first, range.second));
          PyObject *pyValues = PyList_New(count);
          Py_ssize_t idx = 0;
          for (auto it = range.first; it != range.second; ++it, ++idx) {
              const auto &amp;cppItem = it.value();
              PyList_SET_ITEM(pyValues, idx, %CONVERTTOPYTHON[%INTYPE_1](cppItem));
          }
          PyDict_SetItem(%out, pyKey, pyValues);
          Py_DECREF(pyKey);
      }
      return %out;
    </template>

    <template name="pydict_to_cppmultimap_conversion">
      PyObject *key;
      PyObject *values;
      Py_ssize_t pos = 0;
      while (PyDict_Next(%in, &amp;pos, &amp;key, &amp;values)) {
          %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
          const Py_ssize_t size = PySequence_Size(values);
          for (Py_ssize_t i = 0; i &lt; size; ++i) {
              Shiboken::AutoDecRef value(PySequence_GetItem(values, i));
              %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value);
              %out.insert(cppKey, cppValue);
          }
      }
    </template>

    <template name="pydatetime_importandcheck_function">
        static bool PyDateTime_ImportAndCheck(PyObject *pyIn)
        {
            if (!PyDateTimeAPI)
                PyDateTime_IMPORT;
            return $DATETIMETYPE_Check(pyIn);
        }
    </template>

</typesystem>
