/**************************************************************************** ** ** https://www.qxorm.com/ ** Copyright (C) 2013 Lionel Marty (contact@qxorm.com) ** ** This file is part of the QxOrm library ** ** This software is provided 'as-is', without any express or implied ** warranty. In no event will the authors be held liable for any ** damages arising from the use of this software ** ** Commercial Usage ** Licensees holding valid commercial QxOrm 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 Lionel Marty ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file 'license.gpl3.txt' included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met : http://www.gnu.org/copyleft/gpl.html ** ** If you are unsure which license is appropriate for your use, or ** if you have questions regarding the use of this file, please contact : ** contact@qxorm.com ** ****************************************************************************/ #ifndef _QX_MODEL_SERVICE_H_ #define _QX_MODEL_SERVICE_H_ #ifdef _MSC_VER #pragma once #endif /*! * \file QxModelService.h * \author Lionel Marty * \ingroup QxModelView * \brief qx::QxModelService provides an easy way to connect your model to the QxService module (all queries are executed over network using client/server communication) */ #include namespace qx { /*! * \ingroup QxModelView * \brief qx::QxModelService : provides an easy way to connect your model to the QxService module (all queries are executed over network using client/server communication) * * T template parameter is a persistent class registered into QxOrm context * S template parameter is a service class generated by QxEntityEditor (or your own service class providing all methods) */ template class QxModelService : public qx::QxModel { public: typedef typename qx::QxModel::type_ptr type_ptr; typedef typename qx::QxModel::type_primary_key type_primary_key; typedef typename qx::QxModel::type_collection type_collection; typedef std::shared_ptr type_collection_ptr; typedef B type_base_class; public: QxModelService(QObject * parent = 0) : qx::QxModel(parent) { ; } QxModelService(qx::IxModel * other, QObject * parent) : qx::QxModel(other, parent) { ; } virtual ~QxModelService() { ; } virtual long qxCount(const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL) { long lCount = 0; this->qxCount(lCount, query, pDatabase); return lCount; } virtual QSqlError qxCount(long & lCount, const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); S services; this->m_lastError = services.count(lCount, query); return this->m_lastError; } virtual QSqlError qxFetchById(const QVariant & id, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); this->clear(); type_ptr pItem = type_ptr(new T()); if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxFetchById()' method : '%s'", "data member id not registered"); qAssert(false); } if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxFetchById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; } this->m_pDataMemberId->fromVariant(pItem.get(), id); type_primary_key primaryKey; qx::cvt::from_variant(id, primaryKey); this->beginInsertRows(QModelIndex(), 0, 0); this->m_model.insert(primaryKey, pItem); S services; this->m_lastError = services.fetchById(pItem, this->m_lstColumns, relation); this->updateShowEmptyLine(); this->endInsertRows(); return this->m_lastError; } virtual QSqlError qxFetchAll(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); this->clear(); S services; type_collection_ptr tmp = std::make_shared(); this->m_lastError = services.fetchAll(tmp, this->m_lstColumns, relation); if (tmp->count() <= 0) { return this->m_lastError; } this->beginResetModel(); this->m_model = (* tmp); this->updateShowEmptyLine(); this->endResetModel(); return this->m_lastError; } virtual QSqlError qxFetchByQuery(const qx::QxSqlQuery & query, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); this->clear(); S services; type_collection_ptr tmp = std::make_shared(); this->m_lastError = services.fetchByQuery(query, tmp, this->m_lstColumns, relation); if (tmp->count() <= 0) { return this->m_lastError; } this->beginResetModel(); this->m_model = (* tmp); this->updateShowEmptyLine(); this->endResetModel(); return this->m_lastError; } virtual QSqlError qxFetchRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); } type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); } S services; this->m_lastError = services.fetchById(pItem, this->m_lstColumns, relation); if (this->m_lastError.isValid()) { return this->m_lastError; } QModelIndex idxTopLeft = this->index(row, 0); QModelIndex idxBottomRight = this->index(row, (this->m_lstDataMember.count() - 1)); this->raiseEvent_dataChanged(idxTopLeft, idxBottomRight); this->updateKey(row); return this->m_lastError; } virtual QSqlError qxInsert(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); if (relation.count() > 0) { this->syncAllNestedModel(relation); } type_collection_ptr tmp = std::make_shared(); (* tmp) = this->m_model; S services; this->m_lastError = services.insert(tmp, relation); if (! this->m_lastError.isValid()) { this->updateAllKeys(); } return this->m_lastError; } virtual QSqlError qxInsertRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); } if (relation.count() > 0) { this->syncNestedModel(row, relation); } type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); } S services; this->m_lastError = services.insert(pItem, relation); if (! this->m_lastError.isValid()) { this->updateKey(row); } return this->m_lastError; } virtual QSqlError qxUpdate(const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); if (relation.count() > 0) { this->syncAllNestedModel(relation); } type_collection_ptr tmp = std::make_shared(); (* tmp) = this->m_model; S services; this->m_lastError = services.update(tmp, query, this->m_lstColumns, relation); if (! this->m_lastError.isValid()) { this->updateAllKeys(); } return this->m_lastError; } virtual QSqlError qxUpdateRow(int row, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); } if (relation.count() > 0) { this->syncNestedModel(row, relation); } type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); } S services; this->m_lastError = services.update(pItem, query, this->m_lstColumns, relation); if (! this->m_lastError.isValid()) { this->updateKey(row); } return this->m_lastError; } virtual QSqlError qxSave(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); if (relation.count() > 0) { this->syncAllNestedModel(relation); } type_collection_ptr tmp = std::make_shared(); (* tmp) = this->m_model; S services; this->m_lastError = services.save(tmp, relation); if (! this->m_lastError.isValid()) { this->updateAllKeys(); } return this->m_lastError; } virtual QSqlError qxSaveRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); } if (relation.count() > 0) { this->syncNestedModel(row, relation); } type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); } S services; this->m_lastError = services.save(pItem, relation); if (! this->m_lastError.isValid()) { this->updateKey(row); } return this->m_lastError; } virtual QSqlError qxDeleteById(const QVariant & id, QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); type_ptr pItem = type_ptr(new T()); if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); } if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; } this->m_pDataMemberId->fromVariant(pItem.get(), id); S services; this->m_lastError = services.deleteById(pItem); return this->m_lastError; } virtual QSqlError qxDeleteAll(QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); S services; this->m_lastError = services.deleteAll(); return this->m_lastError; } virtual QSqlError qxDeleteByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); S services; this->m_lastError = services.deleteByQuery(query); return this->m_lastError; } virtual QSqlError qxDeleteRow(int row, QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); } type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); } S services; this->m_lastError = services.deleteById(pItem); return this->m_lastError; } virtual QSqlError qxDestroyById(const QVariant & id, QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); type_ptr pItem = type_ptr(new T()); if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); } if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; } this->m_pDataMemberId->fromVariant(pItem.get(), id); S services; this->m_lastError = services.destroyById(pItem); return this->m_lastError; } virtual QSqlError qxDestroyAll(QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); S services; this->m_lastError = services.destroyAll(); return this->m_lastError; } virtual QSqlError qxDestroyByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); S services; this->m_lastError = services.destroyByQuery(query); return this->m_lastError; } virtual QSqlError qxDestroyRow(int row, QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); } type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); } S services; this->m_lastError = services.destroyById(pItem); return this->m_lastError; } virtual QSqlError qxExecuteQuery(qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); this->clear(); S services; type_collection_ptr tmp = std::make_shared(); this->m_lastError = services.executeQuery(query, tmp); if (tmp->count() <= 0) { return this->m_lastError; } this->beginResetModel(); this->m_model = (* tmp); this->updateShowEmptyLine(); this->endResetModel(); return this->m_lastError; } virtual qx_bool qxExist(const QVariant & id, QSqlDatabase * pDatabase = NULL) { Q_UNUSED(pDatabase); type_ptr pItem = type_ptr(new T()); if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxExist()' method : '%s'", "data member id not registered"); qAssert(false); } if (! this->m_pDataMemberId) { return qx_bool(false); } this->m_pDataMemberId->fromVariant(pItem.get(), id); S services; return services.exist(pItem); } virtual qx::QxInvalidValueX qxValidate(const QStringList & groups = QStringList()) { Q_UNUSED(groups); S services; type_collection_ptr tmp = std::make_shared(); (* tmp) = this->m_model; return services.isValid(tmp); } virtual qx::QxInvalidValueX qxValidateRow(int row, const QStringList & groups = QStringList()) { Q_UNUSED(groups); if ((row < 0) || (row >= this->m_model.count())) { return qx::QxInvalidValueX(); } type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return qx::QxInvalidValueX(); } S services; return services.isValid(pItem); } protected: #ifndef _QX_NO_JSON virtual QVariant getRelationshipValues_Helper(int row, const QString & relation, bool bLoadFromDatabase, const QString & sAppendRelations) { if ((row < 0) || (row >= this->m_model.count())) { return QVariant(); } if (! this->m_pDataMemberId || ! this->m_pDataMemberX || ! this->m_pDataMemberX->exist(relation)) { return QVariant(); } IxDataMember * pDataMember = this->m_pDataMemberX->get_WithDaoStrategy(relation); if (! pDataMember) { return QVariant(); } IxSqlRelation * pRelation = (pDataMember->hasSqlRelation() ? pDataMember->getSqlRelation() : NULL); if (! pRelation) { return QVariant(); } type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QVariant(); } type_ptr pItemTemp = pItem; if (bLoadFromDatabase) { QString sRelation = relation; if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; } else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; } pItemTemp = type_ptr(new T()); QVariant id = this->m_pDataMemberId->toVariant(pItem.get()); this->m_pDataMemberId->fromVariant(pItemTemp.get(), id); S services; QStringList columns; QSqlError daoError = services.fetchById(pItemTemp, columns, QStringList() << sRelation); if (daoError.isValid()) { return QVariant(); } } QJsonValue json = pDataMember->toJson(pItemTemp.get()); if (json.isNull()) { return QVariant(); } if (json.isArray()) { return json.toArray().toVariantList(); } return json.toObject().toVariantMap(); } #endif // _QX_NO_JSON }; } // namespace qx #endif // _QX_MODEL_SERVICE_H_