QxModelService.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /****************************************************************************
  2. **
  3. ** https://www.qxorm.com/
  4. ** Copyright (C) 2013 Lionel Marty (contact@qxorm.com)
  5. **
  6. ** This file is part of the QxOrm library
  7. **
  8. ** This software is provided 'as-is', without any express or implied
  9. ** warranty. In no event will the authors be held liable for any
  10. ** damages arising from the use of this software
  11. **
  12. ** Commercial Usage
  13. ** Licensees holding valid commercial QxOrm licenses may use this file in
  14. ** accordance with the commercial license agreement provided with the
  15. ** Software or, alternatively, in accordance with the terms contained in
  16. ** a written agreement between you and Lionel Marty
  17. **
  18. ** GNU General Public License Usage
  19. ** Alternatively, this file may be used under the terms of the GNU
  20. ** General Public License version 3.0 as published by the Free Software
  21. ** Foundation and appearing in the file 'license.gpl3.txt' included in the
  22. ** packaging of this file. Please review the following information to
  23. ** ensure the GNU General Public License version 3.0 requirements will be
  24. ** met : http://www.gnu.org/copyleft/gpl.html
  25. **
  26. ** If you are unsure which license is appropriate for your use, or
  27. ** if you have questions regarding the use of this file, please contact :
  28. ** contact@qxorm.com
  29. **
  30. ****************************************************************************/
  31. #ifndef _QX_MODEL_SERVICE_H_
  32. #define _QX_MODEL_SERVICE_H_
  33. #ifdef _MSC_VER
  34. #pragma once
  35. #endif
  36. /*!
  37. * \file QxModelService.h
  38. * \author Lionel Marty
  39. * \ingroup QxModelView
  40. * \brief qx::QxModelService<T, S> provides an easy way to connect your model to the QxService module (all queries are executed over network using client/server communication)
  41. */
  42. #include <QxModelView/QxModel.h>
  43. namespace qx {
  44. /*!
  45. * \ingroup QxModelView
  46. * \brief qx::QxModelService<T, S> : provides an easy way to connect your model to the QxService module (all queries are executed over network using client/server communication)
  47. *
  48. * T template parameter is a persistent class registered into QxOrm context
  49. * S template parameter is a service class generated by QxEntityEditor (or your own service class providing all methods)
  50. */
  51. template <class T, class S, class B = qx::IxModel>
  52. class QxModelService : public qx::QxModel<T, B>
  53. {
  54. public:
  55. typedef typename qx::QxModel<T, B>::type_ptr type_ptr;
  56. typedef typename qx::QxModel<T, B>::type_primary_key type_primary_key;
  57. typedef typename qx::QxModel<T, B>::type_collection type_collection;
  58. typedef std::shared_ptr<type_collection> type_collection_ptr;
  59. typedef B type_base_class;
  60. public:
  61. QxModelService(QObject * parent = 0) : qx::QxModel<T, B>(parent) { ; }
  62. QxModelService(qx::IxModel * other, QObject * parent) : qx::QxModel<T, B>(other, parent) { ; }
  63. virtual ~QxModelService() { ; }
  64. virtual long qxCount(const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL)
  65. {
  66. long lCount = 0;
  67. this->qxCount(lCount, query, pDatabase);
  68. return lCount;
  69. }
  70. virtual QSqlError qxCount(long & lCount, const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL)
  71. {
  72. Q_UNUSED(pDatabase);
  73. S services;
  74. this->m_lastError = services.count(lCount, query);
  75. return this->m_lastError;
  76. }
  77. virtual QSqlError qxFetchById(const QVariant & id, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL)
  78. {
  79. Q_UNUSED(pDatabase);
  80. this->clear();
  81. type_ptr pItem = type_ptr(new T());
  82. if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxFetchById()' method : '%s'", "data member id not registered"); qAssert(false); }
  83. if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxFetchById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; }
  84. this->m_pDataMemberId->fromVariant(pItem.get(), id);
  85. type_primary_key primaryKey;
  86. qx::cvt::from_variant(id, primaryKey);
  87. this->beginInsertRows(QModelIndex(), 0, 0);
  88. this->m_model.insert(primaryKey, pItem);
  89. S services;
  90. this->m_lastError = services.fetchById(pItem, this->m_lstColumns, relation);
  91. this->updateShowEmptyLine();
  92. this->endInsertRows();
  93. return this->m_lastError;
  94. }
  95. virtual QSqlError qxFetchAll(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL)
  96. {
  97. Q_UNUSED(pDatabase);
  98. this->clear();
  99. S services;
  100. type_collection_ptr tmp = std::make_shared<type_collection>();
  101. this->m_lastError = services.fetchAll(tmp, this->m_lstColumns, relation);
  102. if (tmp->count() <= 0) { return this->m_lastError; }
  103. this->beginResetModel();
  104. this->m_model = (* tmp);
  105. this->updateShowEmptyLine();
  106. this->endResetModel();
  107. return this->m_lastError;
  108. }
  109. virtual QSqlError qxFetchByQuery(const qx::QxSqlQuery & query, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL)
  110. {
  111. Q_UNUSED(pDatabase);
  112. this->clear();
  113. S services;
  114. type_collection_ptr tmp = std::make_shared<type_collection>();
  115. this->m_lastError = services.fetchByQuery(query, tmp, this->m_lstColumns, relation);
  116. if (tmp->count() <= 0) { return this->m_lastError; }
  117. this->beginResetModel();
  118. this->m_model = (* tmp);
  119. this->updateShowEmptyLine();
  120. this->endResetModel();
  121. return this->m_lastError;
  122. }
  123. virtual QSqlError qxFetchRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL)
  124. {
  125. Q_UNUSED(pDatabase);
  126. if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); }
  127. type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); }
  128. S services;
  129. this->m_lastError = services.fetchById(pItem, this->m_lstColumns, relation);
  130. if (this->m_lastError.isValid()) { return this->m_lastError; }
  131. QModelIndex idxTopLeft = this->index(row, 0);
  132. QModelIndex idxBottomRight = this->index(row, (this->m_lstDataMember.count() - 1));
  133. this->raiseEvent_dataChanged(idxTopLeft, idxBottomRight);
  134. this->updateKey(row);
  135. return this->m_lastError;
  136. }
  137. virtual QSqlError qxInsert(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL)
  138. {
  139. Q_UNUSED(pDatabase);
  140. if (relation.count() > 0) { this->syncAllNestedModel(relation); }
  141. type_collection_ptr tmp = std::make_shared<type_collection>();
  142. (* tmp) = this->m_model;
  143. S services;
  144. this->m_lastError = services.insert(tmp, relation);
  145. if (! this->m_lastError.isValid()) { this->updateAllKeys(); }
  146. return this->m_lastError;
  147. }
  148. virtual QSqlError qxInsertRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL)
  149. {
  150. Q_UNUSED(pDatabase);
  151. if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); }
  152. if (relation.count() > 0) { this->syncNestedModel(row, relation); }
  153. type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); }
  154. S services;
  155. this->m_lastError = services.insert(pItem, relation);
  156. if (! this->m_lastError.isValid()) { this->updateKey(row); }
  157. return this->m_lastError;
  158. }
  159. virtual QSqlError qxUpdate(const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL)
  160. {
  161. Q_UNUSED(pDatabase);
  162. if (relation.count() > 0) { this->syncAllNestedModel(relation); }
  163. type_collection_ptr tmp = std::make_shared<type_collection>();
  164. (* tmp) = this->m_model;
  165. S services;
  166. this->m_lastError = services.update(tmp, query, this->m_lstColumns, relation);
  167. if (! this->m_lastError.isValid()) { this->updateAllKeys(); }
  168. return this->m_lastError;
  169. }
  170. virtual QSqlError qxUpdateRow(int row, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL)
  171. {
  172. Q_UNUSED(pDatabase);
  173. if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); }
  174. if (relation.count() > 0) { this->syncNestedModel(row, relation); }
  175. type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); }
  176. S services;
  177. this->m_lastError = services.update(pItem, query, this->m_lstColumns, relation);
  178. if (! this->m_lastError.isValid()) { this->updateKey(row); }
  179. return this->m_lastError;
  180. }
  181. virtual QSqlError qxSave(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL)
  182. {
  183. Q_UNUSED(pDatabase);
  184. if (relation.count() > 0) { this->syncAllNestedModel(relation); }
  185. type_collection_ptr tmp = std::make_shared<type_collection>();
  186. (* tmp) = this->m_model;
  187. S services;
  188. this->m_lastError = services.save(tmp, relation);
  189. if (! this->m_lastError.isValid()) { this->updateAllKeys(); }
  190. return this->m_lastError;
  191. }
  192. virtual QSqlError qxSaveRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL)
  193. {
  194. Q_UNUSED(pDatabase);
  195. if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); }
  196. if (relation.count() > 0) { this->syncNestedModel(row, relation); }
  197. type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); }
  198. S services;
  199. this->m_lastError = services.save(pItem, relation);
  200. if (! this->m_lastError.isValid()) { this->updateKey(row); }
  201. return this->m_lastError;
  202. }
  203. virtual QSqlError qxDeleteById(const QVariant & id, QSqlDatabase * pDatabase = NULL)
  204. {
  205. Q_UNUSED(pDatabase);
  206. type_ptr pItem = type_ptr(new T());
  207. if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); }
  208. if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; }
  209. this->m_pDataMemberId->fromVariant(pItem.get(), id);
  210. S services;
  211. this->m_lastError = services.deleteById(pItem);
  212. return this->m_lastError;
  213. }
  214. virtual QSqlError qxDeleteAll(QSqlDatabase * pDatabase = NULL)
  215. {
  216. Q_UNUSED(pDatabase);
  217. S services;
  218. this->m_lastError = services.deleteAll();
  219. return this->m_lastError;
  220. }
  221. virtual QSqlError qxDeleteByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL)
  222. {
  223. Q_UNUSED(pDatabase);
  224. S services;
  225. this->m_lastError = services.deleteByQuery(query);
  226. return this->m_lastError;
  227. }
  228. virtual QSqlError qxDeleteRow(int row, QSqlDatabase * pDatabase = NULL)
  229. {
  230. Q_UNUSED(pDatabase);
  231. if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); }
  232. type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); }
  233. S services;
  234. this->m_lastError = services.deleteById(pItem);
  235. return this->m_lastError;
  236. }
  237. virtual QSqlError qxDestroyById(const QVariant & id, QSqlDatabase * pDatabase = NULL)
  238. {
  239. Q_UNUSED(pDatabase);
  240. type_ptr pItem = type_ptr(new T());
  241. if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); }
  242. if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; }
  243. this->m_pDataMemberId->fromVariant(pItem.get(), id);
  244. S services;
  245. this->m_lastError = services.destroyById(pItem);
  246. return this->m_lastError;
  247. }
  248. virtual QSqlError qxDestroyAll(QSqlDatabase * pDatabase = NULL)
  249. {
  250. Q_UNUSED(pDatabase);
  251. S services;
  252. this->m_lastError = services.destroyAll();
  253. return this->m_lastError;
  254. }
  255. virtual QSqlError qxDestroyByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL)
  256. {
  257. Q_UNUSED(pDatabase);
  258. S services;
  259. this->m_lastError = services.destroyByQuery(query);
  260. return this->m_lastError;
  261. }
  262. virtual QSqlError qxDestroyRow(int row, QSqlDatabase * pDatabase = NULL)
  263. {
  264. Q_UNUSED(pDatabase);
  265. if ((row < 0) || (row >= this->m_model.count())) { return QSqlError(); }
  266. type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QSqlError(); }
  267. S services;
  268. this->m_lastError = services.destroyById(pItem);
  269. return this->m_lastError;
  270. }
  271. virtual QSqlError qxExecuteQuery(qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL)
  272. {
  273. Q_UNUSED(pDatabase);
  274. this->clear();
  275. S services;
  276. type_collection_ptr tmp = std::make_shared<type_collection>();
  277. this->m_lastError = services.executeQuery(query, tmp);
  278. if (tmp->count() <= 0) { return this->m_lastError; }
  279. this->beginResetModel();
  280. this->m_model = (* tmp);
  281. this->updateShowEmptyLine();
  282. this->endResetModel();
  283. return this->m_lastError;
  284. }
  285. virtual qx_bool qxExist(const QVariant & id, QSqlDatabase * pDatabase = NULL)
  286. {
  287. Q_UNUSED(pDatabase);
  288. type_ptr pItem = type_ptr(new T());
  289. if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxExist()' method : '%s'", "data member id not registered"); qAssert(false); }
  290. if (! this->m_pDataMemberId) { return qx_bool(false); }
  291. this->m_pDataMemberId->fromVariant(pItem.get(), id);
  292. S services;
  293. return services.exist(pItem);
  294. }
  295. virtual qx::QxInvalidValueX qxValidate(const QStringList & groups = QStringList())
  296. {
  297. Q_UNUSED(groups);
  298. S services;
  299. type_collection_ptr tmp = std::make_shared<type_collection>();
  300. (* tmp) = this->m_model;
  301. return services.isValid(tmp);
  302. }
  303. virtual qx::QxInvalidValueX qxValidateRow(int row, const QStringList & groups = QStringList())
  304. {
  305. Q_UNUSED(groups);
  306. if ((row < 0) || (row >= this->m_model.count())) { return qx::QxInvalidValueX(); }
  307. type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return qx::QxInvalidValueX(); }
  308. S services;
  309. return services.isValid(pItem);
  310. }
  311. protected:
  312. #ifndef _QX_NO_JSON
  313. virtual QVariant getRelationshipValues_Helper(int row, const QString & relation, bool bLoadFromDatabase, const QString & sAppendRelations)
  314. {
  315. if ((row < 0) || (row >= this->m_model.count())) { return QVariant(); }
  316. if (! this->m_pDataMemberId || ! this->m_pDataMemberX || ! this->m_pDataMemberX->exist(relation)) { return QVariant(); }
  317. IxDataMember * pDataMember = this->m_pDataMemberX->get_WithDaoStrategy(relation); if (! pDataMember) { return QVariant(); }
  318. IxSqlRelation * pRelation = (pDataMember->hasSqlRelation() ? pDataMember->getSqlRelation() : NULL); if (! pRelation) { return QVariant(); }
  319. type_ptr pItem = this->m_model.getByIndex(row); if (! pItem) { return QVariant(); }
  320. type_ptr pItemTemp = pItem;
  321. if (bLoadFromDatabase)
  322. {
  323. QString sRelation = relation;
  324. if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
  325. else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
  326. pItemTemp = type_ptr(new T());
  327. QVariant id = this->m_pDataMemberId->toVariant(pItem.get());
  328. this->m_pDataMemberId->fromVariant(pItemTemp.get(), id);
  329. S services; QStringList columns;
  330. QSqlError daoError = services.fetchById(pItemTemp, columns, QStringList() << sRelation);
  331. if (daoError.isValid()) { return QVariant(); }
  332. }
  333. QJsonValue json = pDataMember->toJson(pItemTemp.get()); if (json.isNull()) { return QVariant(); }
  334. if (json.isArray()) { return json.toArray().toVariantList(); }
  335. return json.toObject().toVariantMap();
  336. }
  337. #endif // _QX_NO_JSON
  338. };
  339. } // namespace qx
  340. #endif // _QX_MODEL_SERVICE_H_