![]() |
QxOrm
1.4.5
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 00368 virtual QSqlError qxInsert(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00369 { 00370 if (relation.count() > 0) { this->syncAllNestedModel(relation); } 00371 if (relation.count() == 0) { this->m_lastError = qx::dao::insert(m_model, this->database(pDatabase)); } 00372 else { this->m_lastError = qx::dao::insert_with_relation(relation, m_model, this->database(pDatabase)); } 00373 if (! this->m_lastError.isValid()) { this->updateAllKeys(); } 00374 return this->m_lastError; 00375 } 00376 00384 virtual QSqlError qxInsertRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00385 { 00386 type_ptr pItem = getRowItemAt(row); if (! pItem) { return QSqlError(); } 00387 if (relation.count() > 0) { this->syncNestedModel(row, relation); } 00388 if (relation.count() == 0) { this->m_lastError = qx::dao::insert((* pItem), this->database(pDatabase)); } 00389 else { this->m_lastError = qx::dao::insert_with_relation(relation, (* pItem), this->database(pDatabase)); } 00390 if (! this->m_lastError.isValid()) { updateKey(row); } 00391 return this->m_lastError; 00392 } 00393 00401 virtual QSqlError qxUpdate(const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00402 { 00403 if (relation.count() > 0) { this->syncAllNestedModel(relation); } 00404 if (relation.count() == 0) { this->m_lastError = qx::dao::update_by_query(query, m_model, this->database(pDatabase), this->m_lstColumns); } 00405 else { this->m_lastError = qx::dao::update_by_query_with_relation(relation, query, m_model, this->database(pDatabase)); } 00406 if (! this->m_lastError.isValid()) { this->updateAllKeys(); } 00407 return this->m_lastError; 00408 } 00409 00418 virtual QSqlError qxUpdateRow(int row, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00419 { 00420 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00421 if (relation.count() > 0) { this->syncNestedModel(row, relation); } 00422 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00423 if (relation.count() == 0) { this->m_lastError = qx::dao::update_by_query(query, (* pItem), this->database(pDatabase), this->m_lstColumns); } 00424 else { this->m_lastError = qx::dao::update_by_query_with_relation(relation, query, (* pItem), this->database(pDatabase)); } 00425 if (! this->m_lastError.isValid()) { updateKey(row); } 00426 return this->m_lastError; 00427 } 00428 00435 virtual QSqlError qxSave(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00436 { 00437 if (relation.count() > 0) { this->syncAllNestedModel(relation); } 00438 if (relation.count() == 0) { this->m_lastError = qx::dao::save(m_model, this->database(pDatabase)); } 00439 else { this->m_lastError = qx::dao::save_with_relation(relation, m_model, this->database(pDatabase)); } 00440 if (! this->m_lastError.isValid()) { this->updateAllKeys(); } 00441 return this->m_lastError; 00442 } 00443 00451 virtual QSqlError qxSaveRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00452 { 00453 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00454 if (relation.count() > 0) { this->syncNestedModel(row, relation); } 00455 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00456 if (relation.count() == 0) { this->m_lastError = qx::dao::save((* pItem), this->database(pDatabase)); } 00457 else { this->m_lastError = qx::dao::save_with_relation(relation, (* pItem), this->database(pDatabase)); } 00458 if (! this->m_lastError.isValid()) { updateKey(row); } 00459 return this->m_lastError; 00460 } 00461 00469 virtual QSqlError qxSaveRowData(int row, const QStringList & column = QStringList(), QSqlDatabase * pDatabase = NULL) 00470 { 00471 if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxSaveRowData()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; } 00472 type_ptr pItem = getRowItemAt(row); if (! pItem) { return QSqlError(); } 00473 QVariant id = this->m_pDataMemberId->toVariant(pItem.get()); 00474 bool bExist = qx::trait::is_valid_primary_key(id); 00475 if (bExist) { bExist = qx::dao::exist((* pItem), this->database(pDatabase)); } 00476 if (bExist) { this->m_lastError = qx::dao::update((* pItem), this->database(pDatabase), column); } 00477 else { this->m_lastError = qx::dao::insert((* pItem), this->database(pDatabase)); } 00478 return this->m_lastError; 00479 } 00480 00487 virtual QSqlError qxDeleteById(const QVariant & id, QSqlDatabase * pDatabase = NULL) 00488 { 00489 type_ptr pItem = type_ptr(new T()); 00490 if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); } 00491 if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; } 00492 this->m_pDataMemberId->fromVariant(pItem.get(), id); 00493 this->m_lastError = qx::dao::delete_by_id((* pItem), this->database(pDatabase)); 00494 return this->m_lastError; 00495 } 00496 00502 virtual QSqlError qxDeleteAll(QSqlDatabase * pDatabase = NULL) 00503 { 00504 this->m_lastError = qx::dao::delete_all<T>(this->database(pDatabase)); 00505 return this->m_lastError; 00506 } 00507 00514 virtual QSqlError qxDeleteByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) 00515 { 00516 this->m_lastError = qx::dao::delete_by_query<T>(query, this->database(pDatabase)); 00517 return this->m_lastError; 00518 } 00519 00526 virtual QSqlError qxDeleteRow(int row, QSqlDatabase * pDatabase = NULL) 00527 { 00528 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00529 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00530 this->m_lastError = qx::dao::delete_by_id((* pItem), this->database(pDatabase)); 00531 return this->m_lastError; 00532 } 00533 00540 virtual QSqlError qxDestroyById(const QVariant & id, QSqlDatabase * pDatabase = NULL) 00541 { 00542 type_ptr pItem = type_ptr(new T()); 00543 if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); } 00544 if (! this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; } 00545 this->m_pDataMemberId->fromVariant(pItem.get(), id); 00546 this->m_lastError = qx::dao::destroy_by_id((* pItem), this->database(pDatabase)); 00547 return this->m_lastError; 00548 } 00549 00555 virtual QSqlError qxDestroyAll(QSqlDatabase * pDatabase = NULL) 00556 { 00557 this->m_lastError = qx::dao::destroy_all<T>(this->database(pDatabase)); 00558 return this->m_lastError; 00559 } 00560 00567 virtual QSqlError qxDestroyByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) 00568 { 00569 this->m_lastError = qx::dao::destroy_by_query<T>(query, this->database(pDatabase)); 00570 return this->m_lastError; 00571 } 00572 00579 virtual QSqlError qxDestroyRow(int row, QSqlDatabase * pDatabase = NULL) 00580 { 00581 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00582 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00583 this->m_lastError = qx::dao::destroy_by_id((* pItem), this->database(pDatabase)); 00584 return this->m_lastError; 00585 } 00586 00587 virtual QSqlError qxExecuteQuery(qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) 00588 { 00589 this->clear(); 00590 type_collection tmp; 00591 this->m_lastError = qx::dao::execute_query(query, tmp, this->database(pDatabase)); 00592 00593 if (tmp.count() <= 0) { return this->m_lastError; } 00594 this->beginResetModel(); 00595 m_model = tmp; 00596 this->updateShowEmptyLine(); 00597 this->endResetModel(); 00598 return this->m_lastError; 00599 } 00600 00601 virtual qx_bool qxExist(const QVariant & id, QSqlDatabase * pDatabase = NULL) 00602 { 00603 type_ptr pItem = type_ptr(new T()); 00604 if (! this->m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxExist()' method : '%s'", "data member id not registered"); qAssert(false); } 00605 if (! this->m_pDataMemberId) { return qx_bool(false); } 00606 this->m_pDataMemberId->fromVariant(pItem.get(), id); 00607 return qx::dao::exist((* pItem), this->database(pDatabase)); 00608 } 00609 00610 virtual qx::QxInvalidValueX qxValidate(const QStringList & groups = QStringList()) 00611 { 00612 return qx::validate(m_model, groups); 00613 } 00614 00615 virtual qx::QxInvalidValueX qxValidateRow(int row, const QStringList & groups = QStringList()) 00616 { 00617 type_ptr pItem = getRowItemAt(row); if (! pItem) { return qx::QxInvalidValueX(); } 00618 return qx::validate((* pItem), groups); 00619 } 00620 00621 protected: 00622 00623 type_ptr getRowItemAt(int row) const 00624 { 00625 if ((row >= 0) && (row < m_model.count())) { return m_model.getByIndex(row); } 00626 if (m_pDirtyRow && (m_pDirtyRow->first == row)) { return m_pDirtyRow->second; } 00627 return type_ptr(); 00628 } 00629 00630 virtual void * getRowItemAsVoidPtr(int row) const { return getRowItemAt(row).get(); } 00631 00632 virtual void dumpModelImpl(bool bJsonFormat) const { qx::dump(m_model, bJsonFormat); } 00633 00634 virtual QObject * cloneModelImpl() 00635 { 00636 qx::QxModel<T, B> * pClone = new qx::QxModel<T, B>(this, NULL); 00637 std::shared_ptr<type_collection> pModel = qx::clone(pClone->m_model); 00638 if (pModel) { pClone->m_model = (* pModel); } 00639 return static_cast<QObject *>(pClone); 00640 } 00641 00642 virtual void updateShowEmptyLine() { if (m_pDirtyRow) { m_pDirtyRow->first = m_model.count(); } } 00643 00644 virtual bool isDirtyRow(int row) const { return (m_pDirtyRow && (m_pDirtyRow->first == row)); } 00645 00646 virtual void insertDirtyRowToModel() 00647 { 00648 if (! m_pDirtyRow) { return; } 00649 int row = m_pDirtyRow->first; 00650 insertItem(row, m_pDirtyRow->second); 00651 if (this->m_pParent) { this->m_pParent->saveChildRelations(this); } 00652 updateKey(row); 00653 addDirtyRow(); 00654 } 00655 00656 void addDirtyRow() 00657 { 00658 this->beginInsertRows(QModelIndex(), m_model.count(), m_model.count()); 00659 m_pDirtyRow.reset(new QPair<int, type_ptr>(m_model.count(), type_ptr(new T()))); 00660 IxSqlRelation * pRelationParent = (this->m_pDataMemberRelationToParent ? this->m_pDataMemberRelationToParent->getSqlRelation() : NULL); 00661 IxSqlRelation::relation_type eRelationParentType = (pRelationParent ? pRelationParent->getRelationType() : IxSqlRelation::no_relation); 00662 if (this->m_pParent && ((eRelationParentType == IxSqlRelation::many_to_many) || (eRelationParentType == IxSqlRelation::many_to_one))) 00663 { this->m_pDataMemberRelationToParent->fromVariant(m_pDirtyRow->second.get(), this->m_pParent->getIdFromChild(this)); } 00664 this->endInsertRows(); 00665 } 00666 00667 void insertItem(int row, const type_ptr & pItem) 00668 { 00669 if (! pItem) { return; } 00670 type_primary_key primaryKey; 00671 this->m_lManualInsertIndex = (this->m_lManualInsertIndex - 1); 00672 QVariant vNewId(static_cast<qlonglong>(this->m_lManualInsertIndex)); 00673 qx::cvt::from_variant(vNewId, primaryKey); 00674 m_model.insert(row, primaryKey, pItem); 00675 this->updateShowEmptyLine(); 00676 } 00677 00678 void updateKey(int row) 00679 { 00680 if ((row < 0) || (row >= m_model.count())) { return; } 00681 type_ptr pItem = m_model.getByIndex(row); if (! pItem || ! this->m_pDataMemberId) { return; } 00682 type_primary_key currPrimaryKey = m_model.getKeyByIndex(row); 00683 QVariant vCurrPrimaryKey = qx::cvt::to_variant(currPrimaryKey); 00684 QVariant vNextPrimaryKey = this->m_pDataMemberId->toVariant(pItem.get()); 00685 if ((vCurrPrimaryKey == vNextPrimaryKey) || (! vNextPrimaryKey.isValid())) { return; } 00686 if (! qx::trait::is_valid_primary_key(vNextPrimaryKey)) { return; } 00687 type_primary_key updatedPrimaryKey; 00688 qx::cvt::from_variant(vNextPrimaryKey, updatedPrimaryKey); 00689 if (m_model.exist(updatedPrimaryKey)) { return; } 00690 m_model.removeByIndex(row); 00691 m_model.insert(row, updatedPrimaryKey, pItem); 00692 } 00693 00694 void updateAllKeys() 00695 { 00696 for (long l = 0; l < m_model.count(); l++) 00697 { updateKey(l); } 00698 } 00699 00700 protected: 00701 00702 #ifndef _QX_NO_JSON 00703 00704 virtual QString toJson_Helper(int row) const 00705 { 00706 if (row == -1) { return qx::serialization::json::to_string(m_model); } 00707 type_ptr pItem = getRowItemAt(row); if (! pItem) { return QString(); } 00708 return qx::serialization::json::to_string(* pItem); 00709 } 00710 00711 virtual bool fromJson_Helper(const QString & json, int row) 00712 { 00713 if (row == -1) 00714 { 00715 this->clear(); 00716 type_collection tmp; 00717 if (! qx::serialization::json::from_string(tmp, json)) { return false; } 00718 this->beginResetModel(); 00719 m_model = tmp; 00720 this->updateShowEmptyLine(); 00721 this->endResetModel(); 00722 return true; 00723 } 00724 00725 type_ptr pItem = getRowItemAt(row); if (! pItem) { return false; } 00726 if (! qx::serialization::json::from_string((* pItem), json)) { return false; } 00727 00728 QModelIndex idxTopLeft = this->index(row, 0); 00729 QModelIndex idxBottomRight = this->index(row, (this->m_lstDataMember.count() - 1)); 00730 this->raiseEvent_dataChanged(idxTopLeft, idxBottomRight); 00731 updateKey(row); 00732 return true; 00733 } 00734 00735 virtual QVariant getRelationshipValues_Helper(int row, const QString & relation, bool bLoadFromDatabase, const QString & sAppendRelations) 00736 { 00737 if ((row < 0) || (row >= m_model.count())) { return QVariant(); } 00738 if (! this->m_pDataMemberId || ! this->m_pDataMemberX || ! this->m_pDataMemberX->exist(relation)) { return QVariant(); } 00739 IxDataMember * pDataMember = this->m_pDataMemberX->get_WithDaoStrategy(relation); if (! pDataMember) { return QVariant(); } 00740 IxSqlRelation * pRelation = (pDataMember->hasSqlRelation() ? pDataMember->getSqlRelation() : NULL); if (! pRelation) { return QVariant(); } 00741 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QVariant(); } 00742 type_ptr pItemTemp = pItem; 00743 00744 if (bLoadFromDatabase) 00745 { 00746 QString sRelation = relation; 00747 if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; } 00748 else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; } 00749 pItemTemp = type_ptr(new T()); 00750 QVariant id = this->m_pDataMemberId->toVariant(pItem.get()); 00751 this->m_pDataMemberId->fromVariant(pItemTemp.get(), id); 00752 QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, (* pItemTemp)); 00753 if (daoError.isValid()) { return QVariant(); } 00754 } 00755 00756 QJsonValue json = pDataMember->toJson(pItemTemp.get()); if (json.isNull()) { return QVariant(); } 00757 if (json.isArray()) { return json.toArray().toVariantList(); } 00758 return json.toObject().toVariantMap(); 00759 } 00760 00761 virtual bool setRelationshipValues_Helper(int row, const QString & relation, const QVariant & values) 00762 { 00763 if ((row < 0) || (row >= m_model.count())) { return false; } 00764 if ((values.type() != QVariant::List) && (values.type() != QVariant::Map)) { return false; } 00765 if (! this->m_pDataMemberId || ! this->m_pDataMemberX || ! this->m_pDataMemberX->exist(relation)) { return false; } 00766 IxDataMember * pDataMember = this->m_pDataMemberX->get_WithDaoStrategy(relation); if (! pDataMember) { return false; } 00767 IxSqlRelation * pRelation = (pDataMember->hasSqlRelation() ? pDataMember->getSqlRelation() : NULL); if (! pRelation) { return false; } 00768 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return false; } 00769 00770 QJsonValue json; 00771 if (values.type() == QVariant::List) { json = QJsonArray::fromVariantList(values.toList()); } 00772 else if (values.type() == QVariant::Map) { json = QJsonObject::fromVariantMap(values.toMap()); } 00773 if (! pDataMember->fromJson(pItem.get(), json)) { return false; } 00774 00775 QModelIndex idxTopLeft = this->index(row, 0); 00776 QModelIndex idxBottomRight = this->index(row, (this->m_lstDataMember.count() - 1)); 00777 this->raiseEvent_dataChanged(idxTopLeft, idxBottomRight); 00778 return true; 00779 } 00780 00781 #endif // _QX_NO_JSON 00782 00783 }; 00784 00785 } // namespace qx 00786 00787 #endif // _QX_MODEL_H_