/* Copyright (C) 2019 Filippo Cucchetto. Contact: https://github.com/filcuc/dotherside This file is part of the DOtherSide library. The DOtherSide library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the license, or (at your opinion) any later version. The DOtherSide library 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 the DOtherSide library. If not, see . */ #pragma once #include "DOtherSide/DosQAbstractItemModel.h" #include "DOtherSide/DosQMetaObject.h" namespace DOS { template class DosQAbstractItemModelWrapper : public QAbstractItemModel, public DosIQObjectImpl { public: static const QMetaObject staticMetaObject; /// Constructor DosQAbstractItemModelWrapper(QObject *parent = nullptr); /// Destructor ~DosQAbstractItemModelWrapper() override; /// @see DosIQObjectImpl::metaObject const QMetaObject *metaObject() const override; /// @see DosIQObjectImpl::qt_metacall int qt_metacall(QMetaObject::Call, int, void **) override; /// @see DosIQObjectImpl::emitSignal bool emitSignal(QObject *emitter, const QString &name, const std::vector &argumentsValues) override; /// Return the qml registration type static const QmlRegisterType &qmlRegisterType(); /// Sets the qml registration type static void setQmlRegisterType(QmlRegisterType data); /// Sets the static metaobject static void setStaticMetaObject(const QMetaObject &metaObject); /// Sets the qmlRegisterType id static void setId(int id); /// @see QAbstractItemModel::rowCount int rowCount(const QModelIndex &parent = QModelIndex()) const override; /// @see QAbstractItemModel::columnCount int columnCount(const QModelIndex &parent = QModelIndex()) const override; /// @see QAbstractItemModel::data QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; /// @see QAbstractItemModel::setData bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; /// @see QAbstractItemModel::flags Qt::ItemFlags flags(const QModelIndex &index) const override; /// @see QAbstractItemModel::headerData QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; /// @see QAbstractItemModel::roleNames QHash roleNames() const override; /// @see QAbstractItemModel::index QModelIndex index(int row, int column, const QModelIndex &parent) const override; /// @see QAbstractItemModel::parent QModelIndex parent(const QModelIndex &child) const override; private: void *m_dObject; QAbstractItemModel *m_impl; static int m_id; static QmlRegisterType m_data; }; template const QMetaObject DosQAbstractItemModelWrapper::staticMetaObject = QAbstractItemModel::staticMetaObject; template QmlRegisterType DosQAbstractItemModelWrapper::m_data; template int DosQAbstractItemModelWrapper::m_id = -1; template DosQAbstractItemModelWrapper::DosQAbstractItemModelWrapper(QObject *parent) : QAbstractItemModel(parent) , m_dObject(nullptr) , m_impl(nullptr) { void *impl = nullptr; m_data.createDObject(m_id, static_cast(this), &m_dObject, &impl); beginResetModel(); m_impl = dynamic_cast(static_cast(impl)); QObject::connect(m_impl, &QAbstractItemModel::rowsAboutToBeInserted, this, &DosQAbstractItemModelWrapper::beginInsertRows); QObject::connect(m_impl, &QAbstractItemModel::rowsInserted, this, &DosQAbstractItemModelWrapper::endInsertRows); QObject::connect(m_impl, &QAbstractItemModel::rowsAboutToBeRemoved, this, &DosQAbstractItemModelWrapper::beginRemoveRows); QObject::connect(m_impl, &QAbstractItemModel::rowsRemoved, this, &DosQAbstractItemModelWrapper::endRemoveRows); QObject::connect(m_impl, &QAbstractItemModel::rowsAboutToBeMoved, this, &DosQAbstractItemModelWrapper::beginMoveRows); QObject::connect(m_impl, &QAbstractItemModel::rowsMoved, this, &DosQAbstractItemModelWrapper::endMoveRows); QObject::connect(m_impl, &QAbstractItemModel::columnsAboutToBeInserted, this, &DosQAbstractItemModelWrapper::beginInsertColumns); QObject::connect(m_impl, &QAbstractItemModel::columnsInserted, this, &DosQAbstractItemModelWrapper::endInsertColumns); QObject::connect(m_impl, &QAbstractItemModel::columnsAboutToBeRemoved, this, &DosQAbstractItemModelWrapper::beginRemoveColumns); QObject::connect(m_impl, &QAbstractItemModel::columnsRemoved, this, &DosQAbstractItemModelWrapper::endRemoveColumns); QObject::connect(m_impl, &QAbstractItemModel::columnsAboutToBeMoved, this, &DosQAbstractItemModelWrapper::beginMoveColumns); QObject::connect(m_impl, &QAbstractItemModel::columnsMoved, this, &DosQAbstractItemModelWrapper::endMoveColumns); QObject::connect(m_impl, &QAbstractItemModel::modelAboutToBeReset, this, &DosQAbstractItemModelWrapper::beginResetModel); QObject::connect(m_impl, &QAbstractItemModel::modelReset, this, &DosQAbstractItemModelWrapper::endResetModel); QObject::connect(m_impl, &QAbstractItemModel::dataChanged, this, &DosQAbstractItemModelWrapper::dataChanged); QObject::connect(m_impl, &QAbstractItemModel::layoutAboutToBeChanged, this, &DosQAbstractItemModelWrapper::layoutAboutToBeChanged); QObject::connect(m_impl, &QAbstractItemModel::layoutChanged, this, &DosQAbstractItemModelWrapper::layoutChanged); endResetModel(); Q_ASSERT(m_dObject); Q_ASSERT(m_impl); } template DosQAbstractItemModelWrapper::~DosQAbstractItemModelWrapper() { m_data.deleteDObject(m_id, m_dObject); m_dObject = nullptr; delete m_impl; m_impl = nullptr; } template const QMetaObject *DosQAbstractItemModelWrapper::metaObject() const { Q_ASSERT(m_impl); return m_impl->metaObject(); } template int DosQAbstractItemModelWrapper::qt_metacall(QMetaObject::Call call, int index, void **args) { Q_ASSERT(m_impl); return m_impl->qt_metacall(call, index, args); } template bool DosQAbstractItemModelWrapper::emitSignal(QObject *emitter, const QString &name, const std::vector &argumentsValues) { Q_ASSERT(m_impl); return dynamic_cast(this)->emitSignal(this, name, argumentsValues); } template void DosQAbstractItemModelWrapper::setQmlRegisterType(QmlRegisterType data) { m_data = std::move(data); } template void DosQAbstractItemModelWrapper::setStaticMetaObject(const QMetaObject &metaObject) { *(const_cast(&staticMetaObject)) = metaObject; } template void DosQAbstractItemModelWrapper::setId(int id) { m_id = id; } template int DosQAbstractItemModelWrapper::rowCount(const QModelIndex &parent) const { Q_ASSERT(m_impl); return m_impl->rowCount(parent); } template int DosQAbstractItemModelWrapper::columnCount(const QModelIndex &parent) const { Q_ASSERT(m_impl); return m_impl->columnCount(parent); } template QVariant DosQAbstractItemModelWrapper::data(const QModelIndex &index, int role) const { Q_ASSERT(m_impl); return m_impl->data(index, role); } template bool DosQAbstractItemModelWrapper::setData(const QModelIndex &index, const QVariant &value, int role) { Q_ASSERT(m_impl); return m_impl->setData(index, value, role); } template Qt::ItemFlags DosQAbstractItemModelWrapper::flags(const QModelIndex &index) const { Q_ASSERT(m_impl); return m_impl->flags(index); } template QVariant DosQAbstractItemModelWrapper::headerData(int section, Qt::Orientation orientation, int role) const { Q_ASSERT(m_impl); return m_impl->headerData(section, orientation, role); } template QHash DosQAbstractItemModelWrapper::roleNames() const { Q_ASSERT(m_impl); return m_impl->roleNames(); } template QModelIndex DosQAbstractItemModelWrapper::index(int row, int column, const QModelIndex &parent) const { Q_ASSERT(m_impl); return m_impl->index(row, column, parent); } template QModelIndex DosQAbstractItemModelWrapper::parent(const QModelIndex &child) const { Q_ASSERT(m_impl); return m_impl->parent(child); } template const QmlRegisterType &DosQAbstractItemModelWrapper::qmlRegisterType() { return m_data; } namespace DQAIMW { template using RegisterTypeQObject = DosQAbstractItemModelWrapper; template int dosQmlRegisterType(QmlRegisterType args) { RegisterTypeQObject::setQmlRegisterType(std::move(args)); const QmlRegisterType &type = RegisterTypeQObject::qmlRegisterType(); RegisterTypeQObject::setStaticMetaObject(*(type.staticMetaObject->metaObject())); int result = qmlRegisterType>(type.uri.c_str(), type.major, type.minor, type.qml.c_str()); RegisterTypeQObject::setId(result); return result; } template struct DosQmlRegisterHelper { static int Register(int i, QmlRegisterType args) { if (i > N) return -1; else if (i == N) return dosQmlRegisterType(std::move(args)); else return DosQmlRegisterHelper < N - 1 >::Register(i, std::move(args)); } }; template<> struct DosQmlRegisterHelper<0> { static int Register(int i, QmlRegisterType args) { return i == 0 ? dosQmlRegisterType<0>(std::move(args)) : -1; } }; int dosQmlRegisterType(QmlRegisterType args) { static int i = 0; return DosQmlRegisterHelper<35>::Register(i++, std::move(args)); } template using RegisterSingletonTypeQObject = DosQAbstractItemModelWrapper; template QObject *singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine) { return new RegisterSingletonTypeQObject(); } template int dosQmlRegisterSingletonType(QmlRegisterType args) { using Func = QObject * (*)(QQmlEngine *, QJSEngine *); Func f = singletontype_provider; RegisterSingletonTypeQObject::setQmlRegisterType(std::move(args)); const QmlRegisterType &type = RegisterSingletonTypeQObject::qmlRegisterType(); RegisterSingletonTypeQObject::setStaticMetaObject(*(type.staticMetaObject->metaObject())); int result = qmlRegisterSingletonType>(type.uri.c_str(), type.major, type.minor, type.qml.c_str(), f); RegisterSingletonTypeQObject::setId(result); return result; } template struct DosQmlRegisterSingletonHelper { static int Register(int i, QmlRegisterType args) { if (i > N) return -1; else if (i == N) return dosQmlRegisterSingletonType(std::move(args)); else return DosQmlRegisterSingletonHelper < N - 1 >::Register(i, std::move(args)); } }; template<> struct DosQmlRegisterSingletonHelper<0> { static int Register(int i, QmlRegisterType args) { return i == 0 ? dosQmlRegisterSingletonType<0>(std::move(args)) : -1; } }; int dosQmlRegisterSingletonType(QmlRegisterType args) { static int i = 0; return DosQmlRegisterSingletonHelper<35>::Register(i++, std::move(args)); } } }