QxOrm
1.5.0
C++ Object Relational Mapping library
|
00001 /**************************************************************************** 00002 ** 00003 ** https://www.qxorm.com/ 00004 ** Copyright (C) 2013 Lionel Marty (contact@qxorm.com) 00005 ** 00006 ** This file is part of the QxOrm library 00007 ** 00008 ** This software is provided 'as-is', without any express or implied 00009 ** warranty. In no event will the authors be held liable for any 00010 ** damages arising from the use of this software 00011 ** 00012 ** Commercial Usage 00013 ** Licensees holding valid commercial QxOrm licenses may use this file in 00014 ** accordance with the commercial license agreement provided with the 00015 ** Software or, alternatively, in accordance with the terms contained in 00016 ** a written agreement between you and Lionel Marty 00017 ** 00018 ** GNU General Public License Usage 00019 ** Alternatively, this file may be used under the terms of the GNU 00020 ** General Public License version 3.0 as published by the Free Software 00021 ** Foundation and appearing in the file 'license.gpl3.txt' included in the 00022 ** packaging of this file. Please review the following information to 00023 ** ensure the GNU General Public License version 3.0 requirements will be 00024 ** met : http://www.gnu.org/copyleft/gpl.html 00025 ** 00026 ** If you are unsure which license is appropriate for your use, or 00027 ** if you have questions regarding the use of this file, please contact : 00028 ** contact@qxorm.com 00029 ** 00030 ****************************************************************************/ 00031 00032 #ifndef _QX_MODEL_H_ 00033 #define _QX_MODEL_H_ 00034 00035 #ifdef _MSC_VER 00036 #pragma once 00037 #endif 00038 00046 #include <QxModelView/IxModel.h> 00047 #include <QxModelView/QxModelRowCompare.h> 00048 00049 #include <QxCollection/QxCollection.h> 00050 00051 #include <QxRegister/QxClass.h> 00052 00053 #include <QxTraits/get_primary_key.h> 00054 #include <QxTraits/is_qx_registered.h> 00055 #include <QxTraits/is_valid_primary_key.h> 00056 00057 #include <QxSerialize/QxDump.h> 00058 #include <QxSerialize/QxClone.h> 00059 00060 #ifndef _QX_NO_JSON 00061 #include <QxSerialize/QJson/QxSerializeQJson_QxCollection.h> 00062 #include <QxSerialize/QxSerializeQJson.h> 00063 #endif // _QX_NO_JSON 00064 00065 namespace qx { 00066 namespace model_view { 00067 namespace detail { 00068 00069 template <class T, class M> struct QxNestedModel; 00070 template <class T, class M> struct QxNestedModel_Generic; 00071 template <class T, class M> struct QxNestedModel_Container; 00072 00073 } // namespace detail 00074 } // namespace model_view 00075 } // namespace qx 00076 00077 namespace qx { 00078 00162 template <class T, class B = qx::IxModel> 00163 class QxModel : public B // B type must inherit from qx::IxModel and must not define new data-members (use 'm_hCustomProperties' or QObject dynamic properties if you need new properties in your derived class) 00164 { 00165 00166 template <typename U, typename V> friend struct qx::model_view::detail::QxNestedModel; 00167 template <typename U, typename V> friend struct qx::model_view::detail::QxNestedModel_Generic; 00168 template <typename U, typename V> friend struct qx::model_view::detail::QxNestedModel_Container; 00169 00170 public: 00171 00172 typedef std::shared_ptr<T> type_ptr; 00173 typedef typename qx::trait::get_primary_key<T>::type type_primary_key; 00174 typedef qx::QxCollection<type_primary_key, type_ptr> type_collection; 00175 typedef B type_base_class; 00176 00177 enum { qx_is_valid = (qx::trait::is_qx_registered<T>::value && std::is_base_of<qx::IxModel, B>::value) }; 00178 00179 protected: 00180 00181 type_collection m_model; 00182 std::shared_ptr<QPair<int, type_ptr> > m_pDirtyRow; 00183 00184 public: 00185 00186 QxModel(QObject * parent = 0) : B(parent) { qx::QxModel<T, B>::init(); } 00187 QxModel(qx::IxModel * other, QObject * parent) : B(parent) { qx::QxModel<T, B>::initFrom(other); } 00188 virtual ~QxModel() { ; } 00189 00190 protected: 00191 00192 void init() 00193 { 00194 static_assert(qx_is_valid, "qx_is_valid"); 00195 this->m_pClass = qx::QxClass<T>::getSingleton(); qAssert(this->m_pClass != NULL); 00196 this->m_pDataMemberX = (this->m_pClass ? this->m_pClass->getDataMemberX() : NULL); qAssert(this->m_pDataMemberX != NULL); 00197 this->m_pDataMemberId = (this->m_pDataMemberX ? this->m_pDataMemberX->getId_WithDaoStrategy() : NULL); 00198 this->m_pCollection = (& m_model); 00199 this->generateRoleNames(); 00200 } 00201 00202 void initFrom(qx::IxModel * pOther) 00203 { 00204 init(); 00205 qx::QxModel<T, B> * pOtherWrk = static_cast<qx::QxModel<T, B> *>(pOther); 00206 m_model = pOtherWrk->m_model; 00207 this->m_lManualInsertIndex = pOtherWrk->m_lManualInsertIndex; 00208 this->setParentModel(pOtherWrk->m_pParent); 00209 if (this->m_pParent) { this->m_eAutoUpdateDatabase = this->m_pParent->getAutoUpdateDatabase(); } 00210 this->m_hCustomProperties = pOtherWrk->m_hCustomProperties; 00211 } 00212 00213 public: 00214 00215 virtual bool insertRows(int row, int count, const QModelIndex & parent = QModelIndex()) 00216 { 00217 if (parent.isValid()) { return false; } 00218 if ((row < 0) || (count <= 0)) { return false; } 00219 this->beginInsertRows(QModelIndex(), row, (row + count - 1)); 00220 for (int i = 0; i < count; ++i) 00221 { 00222 type_ptr pItem = type_ptr(new T()); 00223 insertItem(row, pItem); 00224 } 00225 this->endInsertRows(); 00226 return true; 00227 } 00228 00229 virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) 00230 { 00231 IxDataMember * pDataMember = this->getDataMember(column); if (! pDataMember) { return; } 00232 m_model.sort(qx::model_view::QxModelRowCompare<typename type_collection::type_pair_key_value>((order == Qt::AscendingOrder), pDataMember)); 00233 this->raiseEvent_layoutChanged(); 00234 } 00235 00236 virtual bool getShowEmptyLine() const { return m_pDirtyRow.get(); } 00237 00238 virtual void setShowEmptyLine(bool b) 00239 { 00240 if (b == getShowEmptyLine()) { return; } 00241 if (b) { addDirtyRow(); return; } 00242 this->beginRemoveRows(QModelIndex(), this->rowCount(), this->rowCount()); 00243 m_pDirtyRow.reset(); 00244 this->endRemoveRows(); 00245 } 00246 00247 public: 00248 00254 virtual long qxCount(const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL) 00255 { 00256 return qx::dao::count<T>(query, this->database(pDatabase)); 00257 } 00258 00265 virtual QSqlError qxCount(long & lCount, const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL) 00266 { 00267 this->m_lastError = qx::dao::count<T>(lCount, query, this->database(pDatabase)); 00268 return this->m_lastError; 00269 } 00270 00278 virtual QSqlError qxFetchById(const QVariant & id, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00279 { 00280 this->clear(); 00281 type_ptr pItem = type_ptr(new T()); 00282 if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxFetchById()' method : '%s'", "data member id not registered"); qAssert(false); } 00283 if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxFetchById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; } 00284 this->m_pDataMemberId->fromVariant(pItem.get(), id); 00285 00286 type_primary_key primaryKey; 00287 qx::cvt::from_variant(id, primaryKey); 00288 this->beginInsertRows(QModelIndex(), 0, 0); 00289 m_model.insert(primaryKey, pItem); 00290 00291 if (relation.count() == 0) { this->m_lastError = qx::dao::fetch_by_id((* pItem), this->database(pDatabase), this->m_lstColumns); } 00292 else { this->m_lastError = qx::dao::fetch_by_id_with_relation(relation, (* pItem), this->database(pDatabase)); } 00293 this->updateShowEmptyLine(); 00294 this->endInsertRows(); 00295 return this->m_lastError; 00296 } 00297 00304 virtual QSqlError qxFetchAll(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00305 { 00306 this->clear(); 00307 type_collection tmp; 00308 if (relation.count() == 0) { this->m_lastError = qx::dao::fetch_all(tmp, this->database(pDatabase), this->m_lstColumns); } 00309 else { this->m_lastError = qx::dao::fetch_all_with_relation(relation, tmp, this->database(pDatabase)); } 00310 00311 if (tmp.count() <= 0) { return this->m_lastError; } 00312 this->beginResetModel(); 00313 m_model = tmp; 00314 this->updateShowEmptyLine(); 00315 this->endResetModel(); 00316 return this->m_lastError; 00317 } 00318 00326 virtual QSqlError qxFetchByQuery(const qx::QxSqlQuery & query, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00327 { 00328 this->clear(); 00329 type_collection tmp; 00330 if (relation.count() == 0) { this->m_lastError = qx::dao::fetch_by_query(query, tmp, this->database(pDatabase), this->m_lstColumns); } 00331 else { this->m_lastError = qx::dao::fetch_by_query_with_relation(relation, query, tmp, this->database(pDatabase)); } 00332 00333 if (tmp.count() <= 0) { return this->m_lastError; } 00334 this->beginResetModel(); 00335 m_model = tmp; 00336 this->updateShowEmptyLine(); 00337 this->endResetModel(); 00338 return this->m_lastError; 00339 } 00340 00348 virtual QSqlError qxFetchRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00349 { 00350 type_ptr pItem = getRowItemAt(row); if (! pItem) { return QSqlError(); } 00351 if (relation.count() == 0) { this->m_lastError = qx::dao::fetch_by_id((* pItem), this->database(pDatabase), this->m_lstColumns); } 00352 else { this->m_lastError = qx::dao::fetch_by_id_with_relation(relation, (* pItem), this->database(pDatabase)); } 00353 if (this->m_lastError.isValid()) { return this->m_lastError; } 00354 00355 QModelIndex idxTopLeft = this->index(row, 0); 00356 QModelIndex idxBottomRight = this->index(row, (this->m_lstDataMember.count() - 1)); 00357 this->raiseEvent_dataChanged(idxTopLeft, idxBottomRight); 00358 updateKey(row); 00359 return this->m_lastError; 00360 } 00361 00369 virtual QSqlError qxInsert(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL, bool bUseExecBatch = false) 00370 { 00371 if (relation.count() > 0) { this->syncAllNestedModel(relation); } 00372 if (relation.count() == 0) { this->m_lastError = qx::dao::insert(m_model, this->database(pDatabase), bUseExecBatch); } 00373 else { this->m_lastError = qx::dao::insert_with_relation(relation, m_model, this->database(pDatabase)); } 00374 if (! this->m_lastError.isValid()) { this->updateAllKeys(); } 00375 return this->m_lastError; 00376 } 00377 00385 virtual QSqlError qxInsertRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00386 { 00387 type_ptr pItem = getRowItemAt(row); if (! pItem) { return QSqlError(); } 00388 if (relation.count() > 0) { this->syncNestedModel(row, relation); } 00389 if (relation.count() == 0) { this->m_lastError = qx::dao::insert((* pItem), this->database(pDatabase)); } 00390 else { this->m_lastError = qx::dao::insert_with_relation(relation, (* pItem), this->database(pDatabase)); } 00391 if (! this->m_lastError.isValid()) { updateKey(row); } 00392 return this->m_lastError; 00393 } 00394 00403 virtual QSqlError qxUpdate(const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL, bool bUseExecBatch = false) 00404 { 00405 if (relation.count() > 0) { this->syncAllNestedModel(relation); } 00406 if (relation.count() == 0) { this->m_lastError = qx::dao::update_by_query(query, m_model, this->database(pDatabase), this->m_lstColumns, bUseExecBatch); } 00407 else { this->m_lastError = qx::dao::update_by_query_with_relation(relation, query, m_model, this->database(pDatabase)); } 00408 if (! this->m_lastError.isValid()) { this->updateAllKeys(); } 00409 return this->m_lastError; 00410 } 00411 00420 virtual QSqlError qxUpdateRow(int row, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00421 { 00422 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00423 if (relation.count() > 0) { this->syncNestedModel(row, relation); } 00424 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00425 if (relation.count() == 0) { this->m_lastError = qx::dao::update_by_query(query, (* pItem), this->database(pDatabase), this->m_lstColumns); } 00426 else { this->m_lastError = qx::dao::update_by_query_with_relation(relation, query, (* pItem), this->database(pDatabase)); } 00427 if (! this->m_lastError.isValid()) { updateKey(row); } 00428 return this->m_lastError; 00429 } 00430 00437 virtual QSqlError qxSave(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00438 { 00439 if (relation.count() > 0) { this->syncAllNestedModel(relation); } 00440 if (relation.count() == 0) { this->m_lastError = qx::dao::save(m_model, this->database(pDatabase)); } 00441 else { this->m_lastError = qx::dao::save_with_relation(relation, m_model, this->database(pDatabase)); } 00442 if (! this->m_lastError.isValid()) { this->updateAllKeys(); } 00443 return this->m_lastError; 00444 } 00445 00453 virtual QSqlError qxSaveRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00454 { 00455 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00456 if (relation.count() > 0) { this->syncNestedModel(row, relation); } 00457 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00458 if (relation.count() == 0) { this->m_lastError = qx::dao::save((* pItem), this->database(pDatabase)); } 00459 else { this->m_lastError = qx::dao::save_with_relation(relation, (* pItem), this->database(pDatabase)); } 00460 if (! this->m_lastError.isValid()) { updateKey(row); } 00461 return this->m_lastError; 00462 } 00463 00471 virtual QSqlError qxSaveRowData(int row, const QStringList & column = QStringList(), QSqlDatabase * pDatabase = NULL) 00472 { 00473 if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxSaveRowData()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; } 00474 type_ptr pItem = getRowItemAt(row); if (! pItem) { return QSqlError(); } 00475 QVariant id = this->m_pDataMemberId->toVariant(pItem.get()); 00476 bool bExist = qx::trait::is_valid_primary_key(id); 00477 if (bExist) { bExist = qx::dao::exist((* pItem), this->database(pDatabase)); } 00478 if (bExist) { this->m_lastError = qx::dao::update((* pItem), this->database(pDatabase), column); } 00479 else { this->m_lastError = qx::dao::insert((* pItem), this->database(pDatabase)); } 00480 return this->m_lastError; 00481 } 00482 00489 virtual QSqlError qxDeleteById(const QVariant & id, QSqlDatabase * pDatabase = NULL) 00490 { 00491 type_ptr pItem = type_ptr(new T()); 00492 if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); } 00493 if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; } 00494 this->m_pDataMemberId->fromVariant(pItem.get(), id); 00495 this->m_lastError = qx::dao::delete_by_id((* pItem), this->database(pDatabase)); 00496 return this->m_lastError; 00497 } 00498 00504 virtual QSqlError qxDeleteAll(QSqlDatabase * pDatabase = NULL) 00505 { 00506 this->m_lastError = qx::dao::delete_all<T>(this->database(pDatabase)); 00507 return this->m_lastError; 00508 } 00509 00516 virtual QSqlError qxDeleteByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) 00517 { 00518 this->m_lastError = qx::dao::delete_by_query<T>(query, this->database(pDatabase)); 00519 return this->m_lastError; 00520 } 00521 00528 virtual QSqlError qxDeleteRow(int row, QSqlDatabase * pDatabase = NULL) 00529 { 00530 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00531 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00532 this->m_lastError = qx::dao::delete_by_id((* pItem), this->database(pDatabase)); 00533 return this->m_lastError; 00534 } 00535 00542 virtual QSqlError qxDestroyById(const QVariant & id, QSqlDatabase * pDatabase = NULL) 00543 { 00544 type_ptr pItem = type_ptr(new T()); 00545 if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); } 00546 if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; } 00547 this->m_pDataMemberId->fromVariant(pItem.get(), id); 00548 this->m_lastError = qx::dao::destroy_by_id((* pItem), this->database(pDatabase)); 00549 return this->m_lastError; 00550 } 00551 00557 virtual QSqlError qxDestroyAll(QSqlDatabase * pDatabase = NULL) 00558 { 00559 this->m_lastError = qx::dao::destroy_all<T>(this->database(pDatabase)); 00560 return this->m_lastError; 00561 } 00562 00569 virtual QSqlError qxDestroyByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) 00570 { 00571 this->m_lastError = qx::dao::destroy_by_query<T>(query, this->database(pDatabase)); 00572 return this->m_lastError; 00573 } 00574 00581 virtual QSqlError qxDestroyRow(int row, QSqlDatabase * pDatabase = NULL) 00582 { 00583 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00584 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00585 this->m_lastError = qx::dao::destroy_by_id((* pItem), this->database(pDatabase)); 00586 return this->m_lastError; 00587 } 00588 00589 virtual QSqlError qxExecuteQuery(qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) 00590 { 00591 this->clear(); 00592 type_collection tmp; 00593 this->m_lastError = qx::dao::execute_query(query, tmp, this->database(pDatabase)); 00594 00595 if (tmp.count() <= 0) { return this->m_lastError; } 00596 this->beginResetModel(); 00597 m_model = tmp; 00598 this->updateShowEmptyLine(); 00599 this->endResetModel(); 00600 return this->m_lastError; 00601 } 00602 00603 virtual qx_bool qxExist(const QVariant & id, QSqlDatabase * pDatabase = NULL) 00604 { 00605 type_ptr pItem = type_ptr(new T()); 00606 if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxExist()' method : '%s'", "data member id not registered"); qAssert(false); } 00607 if (! this->m_pDataMemberId) { return qx_bool(false); } 00608 this->m_pDataMemberId->fromVariant(pItem.get(), id); 00609 return qx::dao::exist((* pItem), this->database(pDatabase)); 00610 } 00611 00612 virtual qx::QxInvalidValueX qxValidate(const QStringList & groups = QStringList()) 00613 { 00614 return qx::validate(m_model, groups); 00615 } 00616 00617 virtual qx::QxInvalidValueX qxValidateRow(int row, const QStringList & groups = QStringList()) 00618 { 00619 type_ptr pItem = getRowItemAt(row); if (! pItem) { return qx::QxInvalidValueX(); } 00620 return qx::validate((* pItem), groups); 00621 } 00622 00623 protected: 00624 00625 type_ptr getRowItemAt(int row) const 00626 { 00627 if ((row >= 0) && (row < m_model.count())) { return m_model.getByIndex(row); } 00628 if (m_pDirtyRow && (m_pDirtyRow->first == row)) { return m_pDirtyRow->second; } 00629 return type_ptr(); 00630 } 00631 00632 virtual void * getRowItemAsVoidPtr(int row) const { return getRowItemAt(row).get(); } 00633 00634 virtual void dumpModelImpl(bool bJsonFormat) const { qx::dump(m_model, bJsonFormat); } 00635 00636 virtual QObject * cloneModelImpl() 00637 { 00638 qx::QxModel<T, B> * pClone = new qx::QxModel<T, B>(this, NULL); 00639 std::shared_ptr<type_collection> pModel = qx::clone(pClone->m_model); 00640 if (pModel) { pClone->m_model = (* pModel); } 00641 return static_cast<QObject *>(pClone); 00642 } 00643 00644 virtual void updateShowEmptyLine() { if (m_pDirtyRow) { m_pDirtyRow->first = m_model.count(); } } 00645 00646 virtual bool isDirtyRow(int row) const { return (m_pDirtyRow && (m_pDirtyRow->first == row)); } 00647 00648 virtual void insertDirtyRowToModel() 00649 { 00650 if (! m_pDirtyRow) { return; } 00651 int row = m_pDirtyRow->first; 00652 insertItem(row, m_pDirtyRow->second); 00653 if (this->m_pParent) { this->m_pParent->saveChildRelations(this); } 00654 updateKey(row); 00655 addDirtyRow(); 00656 } 00657 00658 void addDirtyRow() 00659 { 00660 this->beginInsertRows(QModelIndex(), m_model.count(), m_model.count()); 00661 m_pDirtyRow.reset(new QPair<int, type_ptr>(m_model.count(), type_ptr(new T()))); 00662 IxSqlRelation * pRelationParent = (this->m_pDataMemberRelationToParent ? this->m_pDataMemberRelationToParent->getSqlRelation() : NULL); 00663 IxSqlRelation::relation_type eRelationParentType = (pRelationParent ? pRelationParent->getRelationType() : IxSqlRelation::no_relation); 00664 if (this->m_pParent && ((eRelationParentType == IxSqlRelation::many_to_many) || (eRelationParentType == IxSqlRelation::many_to_one))) 00665 { this->m_pDataMemberRelationToParent->fromVariant(m_pDirtyRow->second.get(), this->m_pParent->getIdFromChild(this)); } 00666 this->endInsertRows(); 00667 } 00668 00669 void insertItem(int row, const type_ptr & pItem) 00670 { 00671 if (! pItem) { return; } 00672 type_primary_key primaryKey; 00673 this->m_lManualInsertIndex = (this->m_lManualInsertIndex - 1); 00674 QVariant vNewId(static_cast<qlonglong>(this->m_lManualInsertIndex)); 00675 qx::cvt::from_variant(vNewId, primaryKey); 00676 m_model.insert(row, primaryKey, pItem); 00677 this->updateShowEmptyLine(); 00678 } 00679 00680 void updateKey(int row) 00681 { 00682 if ((row < 0) || (row >= m_model.count())) { return; } 00683 type_ptr pItem = m_model.getByIndex(row); if (! pItem || ! this->m_pDataMemberId) { return; } 00684 type_primary_key currPrimaryKey = m_model.getKeyByIndex(row); 00685 QVariant vCurrPrimaryKey = qx::cvt::to_variant(currPrimaryKey); 00686 QVariant vNextPrimaryKey = this->m_pDataMemberId->toVariant(pItem.get()); 00687 if ((vCurrPrimaryKey == vNextPrimaryKey) || (! vNextPrimaryKey.isValid())) { return; } 00688 if (! qx::trait::is_valid_primary_key(vNextPrimaryKey)) { return; } 00689 type_primary_key updatedPrimaryKey; 00690 qx::cvt::from_variant(vNextPrimaryKey, updatedPrimaryKey); 00691 if (m_model.exist(updatedPrimaryKey)) { return; } 00692 m_model.removeByIndex(row); 00693 m_model.insert(row, updatedPrimaryKey, pItem); 00694 } 00695 00696 void updateAllKeys() 00697 { 00698 for (long l = 0; l < m_model.count(); l++) 00699 { updateKey(l); } 00700 } 00701 00702 protected: 00703 00704 #ifndef _QX_NO_JSON 00705 00706 virtual QString toJson_Helper(int row) const 00707 { 00708 if (row == -1) { return qx::serialization::json::to_string(m_model); } 00709 type_ptr pItem = getRowItemAt(row); if (! pItem) { return QString(); } 00710 return qx::serialization::json::to_string(* pItem); 00711 } 00712 00713 virtual bool fromJson_Helper(const QString & json, int row) 00714 { 00715 if (row == -1) 00716 { 00717 this->clear(); 00718 type_collection tmp; 00719 if (! qx::serialization::json::from_string(tmp, json)) { return false; } 00720 this->beginResetModel(); 00721 m_model = tmp; 00722 this->updateShowEmptyLine(); 00723 this->endResetModel(); 00724 return true; 00725 } 00726 00727 type_ptr pItem = getRowItemAt(row); if (! pItem) { return false; } 00728 if (! qx::serialization::json::from_string((* pItem), json)) { return false; } 00729 00730 QModelIndex idxTopLeft = this->index(row, 0); 00731 QModelIndex idxBottomRight = this->index(row, (this->m_lstDataMember.count() - 1)); 00732 this->raiseEvent_dataChanged(idxTopLeft, idxBottomRight); 00733 updateKey(row); 00734 return true; 00735 } 00736 00737 virtual QVariant getRelationshipValues_Helper(int row, const QString & relation, bool bLoadFromDatabase, const QString & sAppendRelations) 00738 { 00739 if ((row < 0) || (row >= m_model.count())) { return QVariant(); } 00740 if (! this->m_pDataMemberId || ! this->m_pDataMemberX || ! this->m_pDataMemberX->exist(relation)) { return QVariant(); } 00741 IxDataMember * pDataMember = this->m_pDataMemberX->get_WithDaoStrategy(relation); if (! pDataMember) { return QVariant(); } 00742 IxSqlRelation * pRelation = (pDataMember->hasSqlRelation() ? pDataMember->getSqlRelation() : NULL); if (! pRelation) { return QVariant(); } 00743 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QVariant(); } 00744 type_ptr pItemTemp = pItem; 00745 00746 if (bLoadFromDatabase) 00747 { 00748 QString sRelation = relation; 00749 if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; } 00750 else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; } 00751 pItemTemp = type_ptr(new T()); 00752 QVariant id = this->m_pDataMemberId->toVariant(pItem.get()); 00753 this->m_pDataMemberId->fromVariant(pItemTemp.get(), id); 00754 QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, (* pItemTemp)); 00755 if (daoError.isValid()) { return QVariant(); } 00756 } 00757 00758 QJsonValue json = pDataMember->toJson(pItemTemp.get()); if (json.isNull()) { return QVariant(); } 00759 if (json.isArray()) { return json.toArray().toVariantList(); } 00760 return json.toObject().toVariantMap(); 00761 } 00762 00763 virtual bool setRelationshipValues_Helper(int row, const QString & relation, const QVariant & values) 00764 { 00765 if ((row < 0) || (row >= m_model.count())) { return false; } 00766 if ((values.type() != QVariant::List) && (values.type() != QVariant::Map)) { return false; } 00767 if (! this->m_pDataMemberId || ! this->m_pDataMemberX || ! this->m_pDataMemberX->exist(relation)) { return false; } 00768 IxDataMember * pDataMember = this->m_pDataMemberX->get_WithDaoStrategy(relation); if (! pDataMember) { return false; } 00769 IxSqlRelation * pRelation = (pDataMember->hasSqlRelation() ? pDataMember->getSqlRelation() : NULL); if (! pRelation) { return false; } 00770 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return false; } 00771 00772 QJsonValue json; 00773 if (values.type() == QVariant::List) { json = QJsonArray::fromVariantList(values.toList()); } 00774 else if (values.type() == QVariant::Map) { json = QJsonObject::fromVariantMap(values.toMap()); } 00775 if (! pDataMember->fromJson(pItem.get(), json)) { return false; } 00776 00777 QModelIndex idxTopLeft = this->index(row, 0); 00778 QModelIndex idxBottomRight = this->index(row, (this->m_lstDataMember.count() - 1)); 00779 this->raiseEvent_dataChanged(idxTopLeft, idxBottomRight); 00780 return true; 00781 } 00782 00783 #endif // _QX_NO_JSON 00784 00785 }; 00786 00787 } // namespace qx 00788 00789 #endif // _QX_MODEL_H_