aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Lima <hugo.lima@openbossa.org>2009-12-15 19:24:30 -0200
committerHugo Lima <hugo.lima@openbossa.org>2009-12-16 15:02:42 -0200
commitc8e908097207d8852e17e99585ae88a17e3af144 (patch)
treed9aaf4d99ad3711654c98ef5ae6af8da2d4b9e9f
parentd90b6ba47409c7cc461bb6c200f8e41b9a917088 (diff)
Initial port of signal slots infrastructure from PySide to the Shiboken version.
-rw-r--r--CMakeLists.txt3
-rw-r--r--PySide/QtCore/CMakeLists.txt2
-rw-r--r--PySide/QtCore/typesystem_core.xml29
-rw-r--r--libpyside/CMakeLists.txt21
-rw-r--r--libpyside/abstractqobjectconnection.cpp57
-rw-r--r--libpyside/abstractqobjectconnection.h91
-rw-r--r--libpyside/proxyslot.cpp88
-rw-r--r--libpyside/proxyslot.h81
-rw-r--r--libpyside/pysidemacros.h52
-rw-r--r--libpyside/signalmanager.cpp172
-rw-r--r--libpyside/signalmanager.h70
-rw-r--r--libpyside/signalsignalconnection.cpp43
-rw-r--r--libpyside/signalsignalconnection.h50
-rw-r--r--libpyside/signalslotconnection.cpp84
-rw-r--r--libpyside/signalslotconnection.h58
-rw-r--r--libpyside/typeresolver.cpp118
-rw-r--r--libpyside/typeresolver.h118
17 files changed, 1135 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fb6958134..cb78ea0e5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,10 +59,11 @@ if (NOT SITE_PACKAGE)
message(FATAL_ERROR "Could not detect Python module installation directory.")
endif (NOT SITE_PACKAGE)
-set(GENERATOR_EXTRA_FLAGS --generatorSet=shiboken --enable-parent-ctor-heuristic)
+set(GENERATOR_EXTRA_FLAGS --generatorSet=shiboken --enable-parent-ctor-heuristic --enable-pyside-extensions)
enable_testing()
+add_subdirectory(libpyside)
# project directories
add_subdirectory(${BINDING_NAME})
add_subdirectory(tests)
diff --git a/PySide/QtCore/CMakeLists.txt b/PySide/QtCore/CMakeLists.txt
index 03bef4792..3bdec2010 100644
--- a/PySide/QtCore/CMakeLists.txt
+++ b/PySide/QtCore/CMakeLists.txt
@@ -104,11 +104,13 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}/${BINDING_NAME}/QtCore/
${QT_INCLUDE_DIR}
${SHIBOKEN_INCLUDE_DIR}
+ ${libpyside_SOURCE_DIR}
${PYTHON_INCLUDE_PATH}
)
add_library(QtCore MODULE ${QtCore_SRC})
set_property(TARGET QtCore PROPERTY PREFIX "")
target_link_libraries(QtCore
+ pyside
${PYTHON_LIBRARIES}
${SHIBOKEN_LIBRARY}
${QT_QTCORE_LIBRARY}
diff --git a/PySide/QtCore/typesystem_core.xml b/PySide/QtCore/typesystem_core.xml
index 7a5b880dd..88a054537 100644
--- a/PySide/QtCore/typesystem_core.xml
+++ b/PySide/QtCore/typesystem_core.xml
@@ -1255,6 +1255,7 @@
<extra-includes>
<include file-name="QThread" location="global"/>
<include file-name="QCoreApplication" location="global"/>
+ <include file-name="signalmanager.h" location="local" />
</extra-includes>
<modify-function signature="deleteLater()">
@@ -1291,7 +1292,33 @@
</modify-function>
<modify-function signature="thread() const" remove="all"/>
<modify-function signature="connect(const QObject*, const char*, const char *, Qt::ConnectionType) const" remove="all"/>
- <modify-function signature="connect(const QObject*, const char*, const QObject*, const char *, Qt::ConnectionType)" remove="all"/>
+ <modify-function signature="connect(const QObject*, const char*, const QObject*, const char *, Qt::ConnectionType)">
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = %CONVERTTOPYTHON[bool](PySide::SignalManager::instance().connect(%1, %2, %3, %4, %5));
+ </inject-code>
+ </modify-function>
+ <add-function signature="connect(const QObject*, const char*, PyCallable*, Qt::ConnectionType)" return-type="bool">
+ <modify-argument index="4">
+ <replace-default-expression with="Qt::AutoConnection" />
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = %CONVERTTOPYTHON[bool](PySide::SignalManager::instance().connect(%1, %2, %PYARG_3, %4));
+ </inject-code>
+ </add-function>
+ <!-- static version -->
+ <add-function signature="connect(const char*, PyCallable*, Qt::ConnectionType)" return-type="bool">
+ <modify-argument index="3">
+ <replace-default-expression with="Qt::AutoConnection" />
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = %CONVERTTOPYTHON[bool](PySide::SignalManager::instance().connect(%CPPSELF, %1, %PYARG_2, %3));
+ </inject-code>
+ </add-function>
+ <add-function signature="emit(const char*, PySequence*)" return-type="bool">
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = %CONVERTTOPYTHON[bool](PySide::SignalManager::instance().emitSignal(%CPPSELF, %1, %PYARG_2));
+ </inject-code>
+ </add-function>
<modify-function signature="disconnect(const QObject*, const char*)" remove="all"/>
<modify-function signature="disconnect(const char*, const QObject*, const char*)" remove="all"/>
<modify-function signature="disconnect(const QObject*, const char*, const QObject*, const char *)" remove="all"/>
diff --git a/libpyside/CMakeLists.txt b/libpyside/CMakeLists.txt
new file mode 100644
index 000000000..ad1ebffce
--- /dev/null
+++ b/libpyside/CMakeLists.txt
@@ -0,0 +1,21 @@
+project(libpyside)
+
+set(libpyside_SRC
+typeresolver.cpp
+proxyslot.cpp
+abstractqobjectconnection.cpp
+signalmanager.cpp
+signalsignalconnection.cpp
+signalslotconnection.cpp
+)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}
+ ${SHIBOKEN_INCLUDE_DIR}
+ ${PYTHON_INCLUDE_PATH}
+ )
+
+add_library(pyside SHARED ${libpyside_SRC})
+target_link_libraries(pyside
+ ${PYTHON_LIBRARIES}
+ ${SHIBOKEN_LIBRARY}
+)
diff --git a/libpyside/abstractqobjectconnection.cpp b/libpyside/abstractqobjectconnection.cpp
new file mode 100644
index 000000000..0f5a1b63a
--- /dev/null
+++ b/libpyside/abstractqobjectconnection.cpp
@@ -0,0 +1,57 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#include "abstractqobjectconnection.h"
+#include "typeresolver.h"
+#include "signalmanager.h"
+
+using namespace PySide;
+
+AbstractQObjectConnection::AbstractQObjectConnection(QObject* source, const char* signal, Qt::ConnectionType connectionType)
+ : m_source(source), m_connectionType(connectionType), m_slotIndex(-1)
+{
+ m_signalArgs = getArgsFromSignature(signal);
+ m_signalIndex = source->metaObject()->indexOfSignal(signal);
+}
+
+void AbstractQObjectConnection::trigger(void** args)
+{
+ int numArgs = m_signalArgs.count();
+ PyObject* pyArgs = PyTuple_New(numArgs);
+ for (int i = 0; i < numArgs; ++i) {
+ PyObject* arg = TypeResolver::get(m_signalArgs[i])->toPython(args[i+1]);
+ PyTuple_SET_ITEM(pyArgs, i, arg);
+ }
+ trigger(pyArgs);
+}
diff --git a/libpyside/abstractqobjectconnection.h b/libpyside/abstractqobjectconnection.h
new file mode 100644
index 000000000..5ba43194c
--- /dev/null
+++ b/libpyside/abstractqobjectconnection.h
@@ -0,0 +1,91 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#ifndef ABSTRACTQOBJECTCONNECTION_H
+#define ABSTRACTQOBJECTCONNECTION_H
+#include <Python.h>
+#include <Qt>
+#include <QStringList>
+
+class QObject;
+
+namespace PySide
+{
+class AbstractQObjectConnection
+{
+public:
+ AbstractQObjectConnection(QObject* source, const char* signal, Qt::ConnectionType connectionType);
+ virtual ~AbstractQObjectConnection() {}
+
+ QObject* source() const
+ {
+ return m_source;
+ }
+ void setSignalIndex(int signalIndex)
+ {
+ m_signalIndex = signalIndex;
+ }
+
+ int signalIndex() const
+ {
+ return m_signalIndex;
+ }
+
+ void setSlotIndex(int slotIndex)
+ {
+ m_slotIndex = slotIndex;
+ }
+
+ int slotIndex() const
+ {
+ return m_slotIndex;
+ }
+
+ Qt::ConnectionType type() const
+ {
+ return m_connectionType;
+ }
+
+ void trigger(void** args);
+ virtual void trigger(PyObject* args) = 0;
+private:
+ QObject* m_source;
+ QStringList m_signalArgs;
+ Qt::ConnectionType m_connectionType;
+ int m_signalIndex;
+ int m_slotIndex;
+};
+}
+
+#endif
diff --git a/libpyside/proxyslot.cpp b/libpyside/proxyslot.cpp
new file mode 100644
index 000000000..59467056f
--- /dev/null
+++ b/libpyside/proxyslot.cpp
@@ -0,0 +1,88 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#include <Python.h>
+#include <QDebug>
+#include "proxyslot.h"
+#include "abstractqobjectconnection.h"
+#include "signalmanager.h"
+
+using namespace PySide;
+
+ProxySlot::ProxySlot(QObject* signalSource) : m_signalSource(signalSource)
+{
+ m_nextSlotIndex = m_signalSource->metaObject()->methodCount()-1;
+}
+
+bool ProxySlot::connect(AbstractQObjectConnection* connection)
+{
+ QObject* source = connection->source();
+ attachAbstractConnection(connection);
+ int slotIndex = connection->slotIndex();
+ int signalIndex = connection->signalIndex();
+
+ qDebug() << "conectando" << signalIndex << "em" << slotIndex;
+ if (signalIndex >= 0) {
+ return QMetaObject::connect(source, signalIndex, this, slotIndex, connection->type());
+ } else { // dynamic signals!
+ // TODO: Register dynamic signal
+ }
+ return true;
+
+}
+
+void ProxySlot::attachAbstractConnection(AbstractQObjectConnection* connection)
+{
+ m_nextSlotIndex++;
+ m_connections[m_nextSlotIndex] = connection;
+ connection->setSlotIndex(m_nextSlotIndex);
+}
+
+int ProxySlot::qt_metacall(QMetaObject::Call callType, int slotIndex, void** args)
+{
+ // 2 is the index of deleteLater slot
+ if (slotIndex == 2) {
+ deleteLater();
+ SignalManager::instance().removeProxySlot(m_signalSource);
+ }
+
+ if (m_connections.contains(slotIndex)) {
+// thread_locker lock;
+ m_connections[slotIndex]->trigger(args);
+ return -1;
+ }
+
+ return QObject::qt_metacall(callType, slotIndex, args);
+}
+
diff --git a/libpyside/proxyslot.h b/libpyside/proxyslot.h
new file mode 100644
index 000000000..8e45eff6f
--- /dev/null
+++ b/libpyside/proxyslot.h
@@ -0,0 +1,81 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#include <QObject>
+#include <QHash>
+
+namespace PySide
+{
+
+class AbstractQObjectConnection;
+
+class ProxySlot : public QObject
+{
+public:
+ ProxySlot(QObject* signalSource);
+ bool connect(AbstractQObjectConnection* connection);
+protected:
+ /**
+ * Qt's meta-object system uses the qt_metacall() function to access the
+ * meta-information for a particular QObject object (its signals, slots,
+ * properties, etc.).
+ *
+ * About the implemmentation
+ *
+ * The call may indicate access to the meta-object of the QObject base
+ * class, we need to take care of this use case.
+ * If the QObject::qt_metacall() call returns -1, this means that the
+ * metacall has been handled by QObject and that there is nothing to do.
+ * In that case, we return immediately. Similarly, if the metacall isn't
+ * a slot invocation, we follow QObject's convention and return an
+ * identifier that can be handled by a subclass.
+ *
+ * If all goes well, we invoke the specified slot and return -1 to
+ * indicate that the metacall has been processed.
+ *
+ * \see \link http://doc.trolltech.com/qq/qq16-dynamicqobject.html
+ */
+ int qt_metacall(QMetaObject::Call call, int id, void **args);
+
+private:
+ QObject* m_signalSource;
+ int m_nextSlotIndex;
+ // slot_index => connection_info, used by qt_metacall
+ // to recover the connection_info
+ QHash<int, AbstractQObjectConnection*> m_connections;
+
+ void attachAbstractConnection(AbstractQObjectConnection* connection);
+};
+
+} \ No newline at end of file
diff --git a/libpyside/pysidemacros.h b/libpyside/pysidemacros.h
new file mode 100644
index 000000000..c9e1e11de
--- /dev/null
+++ b/libpyside/pysidemacros.h
@@ -0,0 +1,52 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#ifndef PYSIDEMACROS_H
+#define PYSIDEMACROS_H
+
+#if defined _WIN32 || defined __CYGWIN__
+ #if PYSIDE_BUILD
+ #define PYSIDE_API __declspec(dllexport)
+ #else
+ #define PYSIDE_API __declspec(dllimport)
+ #endif
+#else
+ #if __GNUC__ >= 4
+ #define PYSIDE_API __attribute__ ((visibility("default")))
+ #else
+ #define PYSIDE_API
+ #endif
+#endif
+
+#endif
diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp
new file mode 100644
index 000000000..711465549
--- /dev/null
+++ b/libpyside/signalmanager.cpp
@@ -0,0 +1,172 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#include "signalmanager.h"
+#include "proxyslot.h"
+#include <QHash>
+#include <QStringList>
+#include <QDebug>
+
+#if QSLOT_CODE != 1 || QSIGNAL_CODE != 2
+#error QSLOT_CODE and/or QSIGNAL_CODE changed! change the hardcoded stuff to the correct value!
+#endif
+#define PYSIDE_SLOT '1'
+#define PYSIDE_SIGNAL '2'
+#include "typeresolver.h"
+#include "signalslotconnection.h"
+
+using namespace PySide;
+
+static bool checkSignal(const char* signal)
+{
+ if (signal[0] != PYSIDE_SIGNAL) {
+ PyErr_SetString(PyExc_TypeError, "Use the function PySide.QtCore.SIGNAL on signals");
+ return false;
+ }
+ return true;
+}
+
+QStringList PySide::getArgsFromSignature(const char* signature)
+{
+ QString qsignature(signature);
+ QStringList result;
+ QRegExp splitRegex("\\s*,\\s*");
+
+ if (qsignature.contains("()") || qsignature.contains("(void)")) {
+ return result;
+ } else if (qsignature.contains('(')) {
+ //get args types
+ QString types = qsignature.replace(QRegExp(".+\\((.*)\\)"), "\\1");
+ result = types.split(splitRegex);
+ }
+ return result;
+}
+
+struct SignalManager::SignalManagerPrivate
+{
+ QHash<QObject*, ProxySlot*> m_proxies;
+
+ ProxySlot* findProxy(QObject* signalSource)
+ {
+ ProxySlot* proxy = m_proxies.value(signalSource);
+ if (!proxy) {
+ proxy = new ProxySlot(signalSource);
+ m_proxies[signalSource] = proxy;
+ QObject::connect(signalSource, SIGNAL(destroyed()), proxy, SLOT(deleteLater()));
+ }
+ return proxy;
+ }
+};
+
+SignalManager::SignalManager() : m_d(new SignalManagerPrivate)
+{
+}
+
+SignalManager::~SignalManager()
+{
+ delete m_d;
+}
+
+SignalManager& SignalManager::instance()
+{
+ static SignalManager me;
+ return me;
+}
+
+bool SignalManager::connect(QObject* source, const char* signal, PyObject* callback, Qt::ConnectionType type)
+{
+ if (!checkSignal(signal))
+ return false;
+ signal++;
+
+ ProxySlot* proxy = m_d->findProxy(source);
+ AbstractQObjectConnection* connection = new SignalSlotConnection(source, signal, callback, type);
+ return proxy->connect(connection);
+}
+
+bool SignalManager::connect(QObject* source, const char* signal, QObject* receiver, const char* slot, Qt::ConnectionType type)
+{
+ if (!checkSignal(signal))
+ return false;
+
+ if (!QMetaObject::checkConnectArgs(signal, slot))
+ return false;
+ int signal_index = source->metaObject()->indexOfSignal(signal);
+ int slot_index = receiver->metaObject()->indexOfSlot(slot);
+
+ bool retval;
+ if (signal_index != -1 && slot_index != -1) {
+ // C++ -> C++ connection
+ retval = QMetaObject::connect(source, signal_index,
+ receiver, slot_index, type);
+ } else {
+ // We have a python slot or signal
+ ProxySlot* proxy = m_d->findProxy(source);
+ AbstractQObjectConnection* connection = 0;
+ retval = proxy->connect(connection);
+ }
+ return retval;
+
+}
+
+bool SignalManager::emitSignal(QObject* source, const char* signal, PyObject* args)
+{
+ if (checkSignal(signal))
+ return false;
+
+ int argsGiven = PySequence_Size(args);
+
+ //search native signal
+ int signalIndex = source->metaObject()->indexOfSignal(signal+1);
+ if (signalIndex == -1) {
+ // dynamic signal
+ qDebug() << "Dynamic signal not implemented yet!";
+ } else {
+ // a C++ signal
+ QStringList argTypes = getArgsFromSignature(signal);
+ void* signalArgs[argsGiven+1];
+
+ for (int i = 0; i < argsGiven; i++)
+ signalArgs[i] = TypeResolver::get(argTypes[i])->toCpp(PySequence_GetItem(args, i));
+
+ QMetaObject::activate(source, signalIndex, signalArgs);
+ return true;
+ }
+ return false;
+}
+
+void PySide::SignalManager::removeProxySlot(QObject* signalSource)
+{
+ m_d->m_proxies.remove(signalSource);
+}
diff --git a/libpyside/signalmanager.h b/libpyside/signalmanager.h
new file mode 100644
index 000000000..515ac6153
--- /dev/null
+++ b/libpyside/signalmanager.h
@@ -0,0 +1,70 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#ifndef SIGNALMANAGER_H
+#define SIGNALMANAGER_H
+
+#include "pysidemacros.h"
+#include <Python.h>
+#include <Qt>
+#include <QStringList>
+
+class QObject;
+
+namespace PySide
+{
+
+QStringList getArgsFromSignature(const char* signature);
+
+class PYSIDE_API SignalManager
+{
+public:
+ static SignalManager& instance();
+ bool connect(QObject* source, const char* signal, PyObject* callback, Qt::ConnectionType type = Qt::AutoConnection);
+ bool connect(QObject* source, const char* signal, QObject* receiver, const char* slot, Qt::ConnectionType type = Qt::AutoConnection);
+ bool emitSignal(QObject* source, const char* signal, PyObject* args);
+ void removeProxySlot(QObject* signalSource);
+private:
+ struct SignalManagerPrivate;
+ SignalManagerPrivate* m_d;
+ SignalManager();
+ ~SignalManager();
+
+ // disable copy
+ SignalManager(const SignalManager&);
+ SignalManager operator=(const SignalManager&);
+};
+
+}
+#endif
diff --git a/libpyside/signalsignalconnection.cpp b/libpyside/signalsignalconnection.cpp
new file mode 100644
index 000000000..2797a0778
--- /dev/null
+++ b/libpyside/signalsignalconnection.cpp
@@ -0,0 +1,43 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#include "signalsignalconnection.h"
+
+using namespace PySide;
+
+void SignalSignalConnection::trigger(PyObject* args)
+{
+
+}
+
diff --git a/libpyside/signalsignalconnection.h b/libpyside/signalsignalconnection.h
new file mode 100644
index 000000000..c5896cc21
--- /dev/null
+++ b/libpyside/signalsignalconnection.h
@@ -0,0 +1,50 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#ifndef SIGNALSIGNALCONNECTION_H
+#define SIGNALSIGNALCONNECTION_H
+#include "abstractqobjectconnection.h"
+
+namespace PySide
+{
+
+class SignalSignalConnection : public AbstractQObjectConnection
+{
+public:
+ virtual void trigger(PyObject* args);
+};
+
+}
+
+#endif
diff --git a/libpyside/signalslotconnection.cpp b/libpyside/signalslotconnection.cpp
new file mode 100644
index 000000000..8f7ddf17c
--- /dev/null
+++ b/libpyside/signalslotconnection.cpp
@@ -0,0 +1,84 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#include "signalslotconnection.h"
+#include <QDebug>
+
+using namespace PySide;
+
+SignalSlotConnection::SignalSlotConnection(QObject* source, const char* signal, PyObject* callback, Qt::ConnectionType connectionType)
+ : AbstractQObjectConnection(source, signal, connectionType), m_receiver(0)
+{
+ if (PyMethod_Check(callback)) {
+ m_function = PyMethod_GET_FUNCTION(callback);
+ if (PyObject* self = PyMethod_GET_SELF(callback))
+ m_receiver = self;
+ } else {
+ m_function = callback;
+ }
+ Py_INCREF(m_function);
+ PyCodeObject* objCode = reinterpret_cast<PyCodeObject*>(PyFunction_GET_CODE(m_function));
+ m_numSlotArgs = objCode->co_flags & CO_VARARGS ? -1 : objCode->co_argcount;
+}
+
+SignalSlotConnection::~SignalSlotConnection()
+{
+ Py_DECREF(m_function);
+}
+
+void SignalSlotConnection::trigger(PyObject* args)
+{
+ int useSelf = m_receiver ? 1 : 0;
+ int numArgs = PySequence_Size(args);
+ PyObject* preparedArgs = PyTuple_New(numArgs + useSelf);
+ if (m_receiver)
+ PyTuple_SetItem(preparedArgs, 0, m_receiver);
+ for (int i = 0; i < numArgs; ++i)
+ PyTuple_SET_ITEM(preparedArgs, i + useSelf, PyTuple_GET_ITEM(args, i));
+
+ qDebug() << "num args: " << m_numSlotArgs;
+ // sliceamento
+// if (m_num_slot_args != -1 && m_num_slot_args < python::len(args)) {
+// args = python::list(args.slice(0, m_num_slot_args));
+// }
+ qDebug() << "Receiver" << m_receiver;
+ qDebug() << "numargs" << numArgs;
+ PyObject* retval = PyObject_CallObject(m_function, preparedArgs);
+ if (retval) {
+ Py_DECREF(retval);
+ } else {
+ qWarning(qPrintable(QString("Error calling slot ")+
+ PyString_AS_STRING(reinterpret_cast<PyCodeObject*>(PyFunction_GET_CODE(m_function))->co_name)));
+ }
+}
diff --git a/libpyside/signalslotconnection.h b/libpyside/signalslotconnection.h
new file mode 100644
index 000000000..4c9015c98
--- /dev/null
+++ b/libpyside/signalslotconnection.h
@@ -0,0 +1,58 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#ifndef SIGNALSLOTCONNECTION_H
+#define SIGNALSLOTCONNECTION_H
+
+#include "abstractqobjectconnection.h"
+
+class QObject;
+
+namespace PySide
+{
+
+class SignalSlotConnection : public AbstractQObjectConnection
+{
+public:
+ SignalSlotConnection(QObject* source, const char* signal, PyObject* callback, Qt::ConnectionType connectionType);
+ ~SignalSlotConnection();
+ void trigger(PyObject* args);
+private:
+ PyObject* m_receiver;
+ PyObject* m_function;
+ int m_numSlotArgs;
+};
+
+}
+#endif
diff --git a/libpyside/typeresolver.cpp b/libpyside/typeresolver.cpp
new file mode 100644
index 000000000..d4c704ab9
--- /dev/null
+++ b/libpyside/typeresolver.cpp
@@ -0,0 +1,118 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#include "typeresolver.h"
+#include <QHash>
+#include <cstdlib>
+#include <QDebug>
+
+using namespace PySide;
+
+static QHash<QLatin1String, TypeResolver*> typeResolverMap;
+
+struct TypeResolver::TypeResolverPrivate
+{
+ const char* typeName; // maybe this is not needed anymore
+ CppToPythonFunc cppToPython;
+ PythonToCppFunc pythonToCpp;
+ DeleteObjectFunc deleteObject;
+};
+
+static void deinitTypeResolver()
+{
+ qDeleteAll(typeResolverMap);
+ typeResolverMap.clear();
+}
+
+static void registerTypeResolver(TypeResolver* resolver)
+{
+ static bool initied = false;
+ if (!initied) {
+ Q_ASSERT(typeResolverMap.isEmpty());
+ initied = true;
+ std::atexit(deinitTypeResolver);
+ TypeResolver::createValueTypeResolver<double>("double");
+ TypeResolver::createValueTypeResolver<float>("float");
+ TypeResolver::createValueTypeResolver<qreal>("qreal");
+ TypeResolver::createValueTypeResolver<bool>("bool");
+ TypeResolver::createValueTypeResolver<int>("int");
+ TypeResolver::createValueTypeResolver<qint64>("qint64");
+ }
+ Q_ASSERT(!typeResolverMap.contains(QLatin1String(resolver->typeName())));
+ typeResolverMap[QLatin1String(resolver->typeName())] = resolver;
+}
+
+TypeResolver::TypeResolver(const char* typeName, TypeResolver::CppToPythonFunc cppToPy, TypeResolver::PythonToCppFunc pyToCpp, TypeResolver::DeleteObjectFunc deleter)
+{
+ m_d = new TypeResolverPrivate;
+ m_d->typeName = typeName;
+ m_d->cppToPython = cppToPy;
+ m_d->pythonToCpp = pyToCpp;
+ m_d->deleteObject = deleter;
+
+ registerTypeResolver(this);
+}
+
+TypeResolver::~TypeResolver()
+{
+ delete m_d;
+}
+
+PySide::TypeResolver* TypeResolver::get(const QString& typeName)
+{
+ QByteArray data = typeName.toAscii();
+ return get(data.constData());
+}
+
+PySide::TypeResolver* TypeResolver::get(const char* typeName)
+{
+ Q_ASSERT(typeResolverMap.contains(QLatin1String(typeName)));
+ return typeResolverMap.value(QLatin1String(typeName));
+}
+
+const char* TypeResolver::typeName() const
+{
+ return m_d->typeName;
+}
+
+void* TypeResolver::toCpp(PyObject* pyObj)
+{
+ return m_d->pythonToCpp(pyObj);
+}
+
+PyObject* TypeResolver::toPython(void* cppObj)
+{
+ return m_d->cppToPython(cppObj);
+}
+
diff --git a/libpyside/typeresolver.h b/libpyside/typeresolver.h
new file mode 100644
index 000000000..b3af959c4
--- /dev/null
+++ b/libpyside/typeresolver.h
@@ -0,0 +1,118 @@
+/*
+* This file is part of the Shiboken Python Bindings Generator project.
+*
+* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+*
+* Contact: PySide team <contact@pyside.org>
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public License
+* version 2.1 as published by the Free Software Foundation. Please
+* review the following information to ensure the GNU Lesser General
+* Public License version 2.1 requirements will be met:
+* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+*
+* As a special exception to the GNU Lesser General Public License
+* version 2.1, the object code form of a "work that uses the Library"
+* may incorporate material from a header file that is part of the
+* Library. You may distribute such object code under terms of your
+* choice, provided that the incorporated material (i) does not exceed
+* more than 5% of the total size of the Library; and (ii) is limited to
+* numerical parameters, data structure layouts, accessors, macros,
+* inline functions and templates.
+*
+* This program is distributed 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
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA
+*/
+
+#ifndef TYPERESOLVER_H
+#define TYPERESOLVER_H
+
+#include "pysidemacros.h"
+#include "conversions.h"
+#include <Python.h>
+#include <QGenericArgument>
+
+namespace PySide
+{
+
+/* value type convertion functions */
+template <class T>
+inline PyObject* objectToPython(void* p)
+{
+ return Shiboken::SbkBaseWrapper_New(reinterpret_cast<Shiboken::SbkBaseWrapperType*>(Shiboken::SbkType<T>()), p);
+}
+
+template <>
+inline PyObject* objectToPython<int>(void* p)
+{
+ return PyInt_FromLong(*reinterpret_cast<int*>(p));
+}
+
+template <class T>
+inline void* pythonToValueType(PyObject* pyobj)
+{
+ return new T(Shiboken::Converter<T>::toCpp(pyobj));
+}
+
+template <class T>
+inline void* pythonToObjectType(PyObject* pyobj)
+{
+ // TODO: Check if we could just check if this type is a shibotype and use the ptr
+ // buuuuut.... what if it's a primitive type!?
+ return Shiboken::Converter<T*>::toCpp(pyobj);
+}
+
+template <class T>
+inline void objectDeleter(void *data)
+{
+ delete reinterpret_cast<T*>(data);
+}
+
+class PYSIDE_API TypeResolver
+{
+public:
+ typedef PyObject* (*CppToPythonFunc)(void*);
+ typedef void* (*PythonToCppFunc)(PyObject*);
+ typedef void (*DeleteObjectFunc)(void*);
+
+ ~TypeResolver();
+
+ template<typename T>
+ static TypeResolver* createValueTypeResolver(const char* typeName)
+ {
+ return new TypeResolver(typeName, &objectToPython<T>, &pythonToValueType<T>, &objectDeleter<T>);
+ }
+
+ template<typename T>
+ static TypeResolver* createObjectTypeResolver(const char* typeName)
+ {
+ return new TypeResolver(typeName, &objectToPython<T>, &pythonToObjectType<T>, &objectDeleter<T>);
+ }
+
+ static TypeResolver* get(const char* typeName);
+ static TypeResolver* get(const QString& typeName);
+
+ const char* typeName() const;
+ PyObject* toPython(void* cppObj);
+ void* toCpp(PyObject* pyObj);
+private:
+ struct TypeResolverPrivate;
+ TypeResolverPrivate* m_d;
+
+ // disable object copy
+ TypeResolver(const TypeResolver&);
+ TypeResolver& operator=(const TypeResolver&);
+
+ TypeResolver(const char* typeName, CppToPythonFunc cppToPy, PythonToCppFunc pyToCpp, DeleteObjectFunc deleter);
+};
+}
+
+#endif