template <class Object, template<class> class Container = std::shared_ptr> class QmlCppSmartPtr : public Container<QObject> { };
template <typename Object, template<class> class Container = std::shared_ptr> class QmlCppSmartPtr : public Container<Object> { public: explicit QmlCppSmartPtr(Object* object) : Container<Object>(object, std::bind(&QmlCppSmartPtr::deleteObject, this, std::placeholders::_1)) { object->setParent(new QObject()); QQmlEngine::setObjectOwnership(object, QQmlEngine::JavaScriptOwnership); } private: void deleteObject(Object* object) { object->parent()->deleteLater(); object->setParent(nullptr); } };
template <typename Object, template<class> class Container = std::shared_ptr> class QmlCppSmartPtr : public Container<Object> { public: explicit QmlCppSmartPtr(Object* object) : Container<Object>(object, std::bind(&QmlCppSmartPtr::deleteObject, this, std::placeholders::_1)) { QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership); } private: void deleteObject(Object* object) { QQmlEngine::setObjectOwnership(object, QQmlEngine::JavaScriptOwnership); } };
template <class Object> struct SimpleOwnershipPolicy { static void init(Object* object) { QQmlEngine::setObjectOwnership(object, QQmlEngine::CppOwnership); } static void destroy(Object* object) { QQmlEngine::setObjectOwnership(object, QQmlEngine::JavaScriptOwnership); } }; template <class Object> struct ParentOwnershipPolicy { void init(Object* object) { object->setParent(new QObject()); QQmlEngine::setObjectOwnership(object, QQmlEngine::JavaScriptOwnership); } void destroy(Object* object) { object->parent()->deleteLater(); object->setParent(nullptr); } }; template <typename Object, template<class, class...> class Container> struct SmartPointer { using type = Container<Object>; }; template <typename Object> struct SmartPointer<Object, std::unique_ptr> { using type = std::unique_ptr<Object, std::function<void(Object*)>>; }; template <typename Object, template<class, class...> class Container = std::unique_ptr, template<class> class OwnershipPolicy = SimpleOwnershipPolicy> class QmlCppSmartPtr : public SmartPointer<Object, Container>::type { public: explicit QmlCppSmartPtr(Object* object, OwnershipPolicy<Object> && ownershipPolicy = OwnershipPolicy<Object>()) : SmartPointer<Object, Container>::type(object, std::bind(&QmlCppSmartPtr::deleteObject, this, std::placeholders::_1)) , m_ownershipPolicy(std::move(ownershipPolicy)) { m_ownershipPolicy.init(object); } private: void deleteObject(Object* object) { m_ownershipPolicy.destroy(object); } OwnershipPolicy<Object> m_ownershipPolicy; };
class SomeObject : public QObject // C++-QML { Q_OBJECT public: Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged) SomeObject(QString const& name, int val); virtual ~SomeObject() override; explicit SomeObject(QObject *parent = 0); QString name() const; void setName(QString const& name); int value() const; void setValue(int val); signals: void valueChanged(); void nameChanged(); private: QString m_name; int m_val; }; class QmlObjectProvider : public QObject { Q_OBJECT public: Q_INVOKABLE SomeObject* createObject(QString const& name, int value) { m_cppObjects.emplace_back(new SomeObject(name, value)); return m_cppObjects.back().data(); } Q_INVOKABLE void removeObjectsFromCppSide() { m_cppObjects.clear(); } private: std::vector<QmlCppSmartPtr<SomeObject, QSharedPointer, ParentOwnershipPolicy>> m_cppObjects; }; ... // QML qmlRegisterType<QmlObjectProvider>("com.provider", 1, 0, "QmlObjectProvider"); qmlRegisterType<SomeObject>("com.provider", 1, 0, "SomeObject"); engine.rootContext()->setContextProperty("qmlObjectProvider", &qmlObjectProvider);
... import com.provider 1.0 Button { onClicked: { var obj = qmlObjectProvider.createObject("SomeObjectName", 42); qmlObjectProvider.removeObjectsFromCppSide(); // C++ text = obj.name; // QML , gc } }
QmlCppSmartPtr<SomeObject> object; // unique_ptr SimpleOwnershipPolicy . ... QmlCppSmartPtr<SomeObject, std::shared_ptr> object; // shared_ptr ... return object.get();
Source: https://habr.com/ru/post/274915/
All Articles