![]() |
QxOrm
1.3.2
C++ Object Relational Mapping library
|
00001 /**************************************************************************** 00002 ** 00003 ** http://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 00048 #include <QxCollection/QxCollection.h> 00049 00050 #include <QxRegister/QxClass.h> 00051 00052 #include <QxTraits/get_primary_key.h> 00053 #include <QxTraits/is_qx_registered.h> 00054 #include <QxTraits/is_valid_primary_key.h> 00055 00056 namespace qx { 00057 namespace model_view { 00058 namespace detail { 00059 00060 template <class T> struct QxNestedModel; 00061 template <class T> struct QxNestedModel_Generic; 00062 template <class T> struct QxNestedModel_Container; 00063 00064 } // namespace detail 00065 } // namespace model_view 00066 } // namespace qx 00067 00068 namespace qx { 00069 00153 template <class T> 00154 class QxModel : public qx::IxModel 00155 { 00156 00157 friend struct qx::model_view::detail::QxNestedModel<T>; 00158 friend struct qx::model_view::detail::QxNestedModel_Generic<T>; 00159 template <typename U> friend struct qx::model_view::detail::QxNestedModel_Container; 00160 00161 public: 00162 00163 typedef boost::shared_ptr<T> type_ptr; 00164 typedef typename qx::trait::get_primary_key<T>::type type_primary_key; 00165 typedef qx::QxCollection<type_primary_key, type_ptr> type_collection; 00166 00167 enum { qx_is_valid = qx::trait::is_qx_registered<T>::value }; 00168 00169 protected: 00170 00171 type_collection m_model; 00172 long m_lManualInsertIndex; 00173 00174 public: 00175 00176 QxModel(QObject * parent = 0) : qx::IxModel(parent), m_lManualInsertIndex(0) { qx::QxModel<T>::init(); } 00177 QxModel(qx::IxModel * other, QObject * parent) : qx::IxModel(parent), m_lManualInsertIndex(0) { qx::QxModel<T>::initFrom(other); } 00178 virtual ~QxModel() { ; } 00179 00180 protected: 00181 00182 void init() 00183 { 00184 BOOST_STATIC_ASSERT(qx_is_valid); 00185 m_pClass = qx::QxClass<T>::getSingleton(); qAssert(m_pClass != NULL); 00186 m_pDataMemberX = (m_pClass ? m_pClass->getDataMemberX() : NULL); qAssert(m_pDataMemberX != NULL); 00187 m_pDataMemberId = (m_pDataMemberX ? m_pDataMemberX->getId_WithDaoStrategy() : NULL); 00188 m_pCollection = (& m_model); 00189 generateRoleNames(); 00190 } 00191 00192 void initFrom(qx::IxModel * pOther) 00193 { 00194 init(); 00195 qx::QxModel<T> * pOtherWrk = static_cast<qx::QxModel<T> *>(pOther); 00196 this->m_model = pOtherWrk->m_model; 00197 this->m_lManualInsertIndex = pOtherWrk->m_lManualInsertIndex; 00198 this->m_pParent = pOtherWrk->m_pParent; 00199 if (this->m_pParent) { this->m_eAutoUpdateDatabase = this->m_pParent->getAutoUpdateDatabase(); } 00200 } 00201 00202 public: 00203 00204 virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const 00205 { 00206 if (! index.isValid()) { return QVariant(); } 00207 if ((role == Qt::DisplayRole) || (role == Qt::EditRole)) 00208 { 00209 if ((index.column() < 0) || (index.column() >= m_lstDataMember.count())) { return QVariant(); } 00210 else if ((index.row() < 0) || (index.row() >= m_model.count())) { return QVariant(); } 00211 IxDataMember * pDataMember = m_lstDataMember.at(index.column()); 00212 type_ptr pItem = m_model.getByIndex(index.row()); 00213 if (! pDataMember || ! pItem) { return QVariant(); } 00214 return pDataMember->toVariant(pItem.get()); 00215 } 00216 else if (role >= (Qt::UserRole + 1)) 00217 { 00218 QModelIndex idx = this->index(index.row(), (role - Qt::UserRole - 1), QModelIndex()); 00219 return data(idx, Qt::DisplayRole); 00220 } 00221 return QVariant(); 00222 } 00223 00224 virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) 00225 { 00226 if (! index.isValid()) { return false; } 00227 if (role == Qt::EditRole) 00228 { 00229 if ((index.column() < 0) || (index.column() >= m_lstDataMember.count())) { return false; } 00230 else if ((index.row() < 0) || (index.row() >= m_model.count())) { return false; } 00231 IxDataMember * pDataMember = m_lstDataMember.at(index.column()); 00232 type_ptr pItem = m_model.getByIndex(index.row()); 00233 if (! pDataMember || ! pItem) { return false; } 00234 QVariant vCurrentValue = pDataMember->toVariant(pItem.get()); 00235 if (vCurrentValue == value) { return true; } 00236 qx_bool bSetData = pDataMember->fromVariant(pItem.get(), value); 00237 if (bSetData) { raiseEvent_dataChanged(index, index); } 00238 if (bSetData && (m_eAutoUpdateDatabase == qx::IxModel::e_auto_update_on_field_change) && m_pDataMemberId) 00239 { 00240 QVariant vId = m_pDataMemberId->toVariant(pItem.get()); 00241 bool bExist = qx::trait::is_valid_primary_key(vId); 00242 if (bExist) { bExist = qx::dao::exist((* pItem), database(NULL)); } 00243 if (bExist) { m_lastError = qx::dao::update((* pItem), database(NULL), (QStringList() << pDataMember->getKey())); } 00244 else { m_lastError = qx::dao::insert((* pItem), database(NULL)); } 00245 } 00246 return bSetData; 00247 } 00248 else if (role >= (Qt::UserRole + 1)) 00249 { 00250 QModelIndex idx = this->index(index.row(), (role - Qt::UserRole - 1), QModelIndex()); 00251 return setData(idx, value, Qt::EditRole); 00252 } 00253 return false; 00254 } 00255 00256 virtual bool insertRows(int row, int count, const QModelIndex & parent = QModelIndex()) 00257 { 00258 if (parent.isValid()) { return false; } 00259 if ((row < 0) || (count <= 0)) { return false; } 00260 beginInsertRows(QModelIndex(), row, (row + count - 1)); 00261 for (int i = 0; i < count; ++i) 00262 { 00263 type_primary_key primaryKey; 00264 m_lManualInsertIndex = (m_lManualInsertIndex - 1); 00265 QVariant vNewId(static_cast<qlonglong>(m_lManualInsertIndex)); 00266 qx::cvt::from_variant(vNewId, primaryKey); 00267 type_ptr pItem = type_ptr(new T()); 00268 m_model.insert(row, primaryKey, pItem); 00269 } 00270 endInsertRows(); 00271 return true; 00272 } 00273 00274 public: 00275 00281 virtual long qxCount(const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL) 00282 { 00283 return qx::dao::count<T>(query, database(pDatabase)); 00284 } 00285 00292 virtual QSqlError qxCount(long & lCount, const qx::QxSqlQuery & query = qx::QxSqlQuery(), QSqlDatabase * pDatabase = NULL) 00293 { 00294 m_lastError = qx::dao::count<T>(lCount, query, database(pDatabase)); 00295 return m_lastError; 00296 } 00297 00305 virtual QSqlError qxFetchById(const QVariant & id, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00306 { 00307 clear(); 00308 type_ptr pItem = type_ptr(new T()); 00309 if (! m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxFetchById()' method : '%s'", "data member id not registered"); qAssert(false); } 00310 if (! m_pDataMemberId) { m_lastError = QSqlError("[QxOrm] problem with 'qxFetchById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return m_lastError; } 00311 m_pDataMemberId->fromVariant(pItem.get(), id); 00312 00313 type_primary_key primaryKey; 00314 qx::cvt::from_variant(id, primaryKey); 00315 beginInsertRows(QModelIndex(), 0, 0); 00316 m_model.insert(primaryKey, pItem); 00317 00318 if (relation.count() == 0) { m_lastError = qx::dao::fetch_by_id((* pItem), database(pDatabase), m_lstColumns); } 00319 else { m_lastError = qx::dao::fetch_by_id_with_relation(relation, (* pItem), database(pDatabase)); } 00320 endInsertRows(); 00321 return m_lastError; 00322 } 00323 00330 virtual QSqlError qxFetchAll(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00331 { 00332 clear(); 00333 type_collection tmp; 00334 if (relation.count() == 0) { m_lastError = qx::dao::fetch_all(tmp, database(pDatabase), m_lstColumns); } 00335 else { m_lastError = qx::dao::fetch_all_with_relation(relation, tmp, database(pDatabase)); } 00336 00337 if (tmp.count() <= 0) { return m_lastError; } 00338 beginInsertRows(QModelIndex(), 0, (tmp.count() - 1)); 00339 m_model = tmp; 00340 endInsertRows(); 00341 return m_lastError; 00342 } 00343 00351 virtual QSqlError qxFetchByQuery(const qx::QxSqlQuery & query, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00352 { 00353 clear(); 00354 type_collection tmp; 00355 if (relation.count() == 0) { m_lastError = qx::dao::fetch_by_query(query, tmp, database(pDatabase), m_lstColumns); } 00356 else { m_lastError = qx::dao::fetch_by_query_with_relation(relation, query, tmp, database(pDatabase)); } 00357 00358 if (tmp.count() <= 0) { return m_lastError; } 00359 beginInsertRows(QModelIndex(), 0, (tmp.count() - 1)); 00360 m_model = tmp; 00361 endInsertRows(); 00362 return m_lastError; 00363 } 00364 00372 virtual QSqlError qxFetchRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00373 { 00374 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00375 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00376 if (relation.count() == 0) { m_lastError = qx::dao::fetch_by_id((* pItem), database(pDatabase), m_lstColumns); } 00377 else { m_lastError = qx::dao::fetch_by_id_with_relation(relation, (* pItem), database(pDatabase)); } 00378 if (m_lastError.isValid()) { return m_lastError; } 00379 00380 QModelIndex idxTopLeft = this->index(row, 0); 00381 QModelIndex idxBottomRight = this->index(row, (m_lstDataMember.count() - 1)); 00382 this->raiseEvent_dataChanged(idxTopLeft, idxBottomRight); 00383 this->updateKey(row); 00384 return m_lastError; 00385 } 00386 00393 virtual QSqlError qxInsert(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00394 { 00395 if (relation.count() > 0) { this->syncAllNestedModel(relation); } 00396 if (relation.count() == 0) { m_lastError = qx::dao::insert(m_model, database(pDatabase)); } 00397 else { m_lastError = qx::dao::insert_with_relation(relation, m_model, database(pDatabase)); } 00398 if (! m_lastError.isValid()) { this->updateAllKeys(); } 00399 return m_lastError; 00400 } 00401 00409 virtual QSqlError qxInsertRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00410 { 00411 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00412 if (relation.count() > 0) { this->syncNestedModel(row, relation); } 00413 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00414 if (relation.count() == 0) { m_lastError = qx::dao::insert((* pItem), database(pDatabase)); } 00415 else { m_lastError = qx::dao::insert_with_relation(relation, (* pItem), database(pDatabase)); } 00416 if (! m_lastError.isValid()) { this->updateKey(row); } 00417 return m_lastError; 00418 } 00419 00427 virtual QSqlError qxUpdate(const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00428 { 00429 if (relation.count() > 0) { this->syncAllNestedModel(relation); } 00430 if (relation.count() == 0) { m_lastError = qx::dao::update_by_query(query, m_model, database(pDatabase), m_lstColumns); } 00431 else { m_lastError = qx::dao::update_by_query_with_relation(relation, query, m_model, database(pDatabase)); } 00432 if (! m_lastError.isValid()) { this->updateAllKeys(); } 00433 return m_lastError; 00434 } 00435 00444 virtual QSqlError qxUpdateRow(int row, const qx::QxSqlQuery & query = qx::QxSqlQuery(), const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00445 { 00446 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00447 if (relation.count() > 0) { this->syncNestedModel(row, relation); } 00448 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00449 if (relation.count() == 0) { m_lastError = qx::dao::update_by_query(query, (* pItem), database(pDatabase), m_lstColumns); } 00450 else { m_lastError = qx::dao::update_by_query_with_relation(relation, query, (* pItem), database(pDatabase)); } 00451 if (! m_lastError.isValid()) { this->updateKey(row); } 00452 return m_lastError; 00453 } 00454 00461 virtual QSqlError qxSave(const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00462 { 00463 if (relation.count() > 0) { this->syncAllNestedModel(relation); } 00464 if (relation.count() == 0) { m_lastError = qx::dao::save(m_model, database(pDatabase)); } 00465 else { m_lastError = qx::dao::save_with_relation(relation, m_model, database(pDatabase)); } 00466 if (! m_lastError.isValid()) { this->updateAllKeys(); } 00467 return m_lastError; 00468 } 00469 00477 virtual QSqlError qxSaveRow(int row, const QStringList & relation = QStringList(), QSqlDatabase * pDatabase = NULL) 00478 { 00479 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00480 if (relation.count() > 0) { this->syncNestedModel(row, relation); } 00481 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00482 if (relation.count() == 0) { m_lastError = qx::dao::save((* pItem), database(pDatabase)); } 00483 else { m_lastError = qx::dao::save_with_relation(relation, (* pItem), database(pDatabase)); } 00484 if (! m_lastError.isValid()) { this->updateKey(row); } 00485 return m_lastError; 00486 } 00487 00494 virtual QSqlError qxDeleteById(const QVariant & id, QSqlDatabase * pDatabase = NULL) 00495 { 00496 type_ptr pItem = type_ptr(new T()); 00497 if (! m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); } 00498 if (! m_pDataMemberId) { m_lastError = QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return m_lastError; } 00499 m_pDataMemberId->fromVariant(pItem.get(), id); 00500 m_lastError = qx::dao::delete_by_id((* pItem), database(pDatabase)); 00501 return m_lastError; 00502 } 00503 00509 virtual QSqlError qxDeleteAll(QSqlDatabase * pDatabase = NULL) 00510 { 00511 m_lastError = qx::dao::delete_all<T>(database(pDatabase)); 00512 return m_lastError; 00513 } 00514 00521 virtual QSqlError qxDeleteByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) 00522 { 00523 m_lastError = qx::dao::delete_by_query<T>(query, database(pDatabase)); 00524 return m_lastError; 00525 } 00526 00533 virtual QSqlError qxDeleteRow(int row, QSqlDatabase * pDatabase = NULL) 00534 { 00535 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00536 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00537 m_lastError = qx::dao::delete_by_id((* pItem), database(pDatabase)); 00538 return m_lastError; 00539 } 00540 00547 virtual QSqlError qxDestroyById(const QVariant & id, QSqlDatabase * pDatabase = NULL) 00548 { 00549 type_ptr pItem = type_ptr(new T()); 00550 if (! m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxDeleteById()' method : '%s'", "data member id not registered"); qAssert(false); } 00551 if (! m_pDataMemberId) { m_lastError = QSqlError("[QxOrm] problem with 'qxDeleteById()' method : 'data member id not registered'", "", QSqlError::UnknownError); return m_lastError; } 00552 m_pDataMemberId->fromVariant(pItem.get(), id); 00553 m_lastError = qx::dao::destroy_by_id((* pItem), database(pDatabase)); 00554 return m_lastError; 00555 } 00556 00562 virtual QSqlError qxDestroyAll(QSqlDatabase * pDatabase = NULL) 00563 { 00564 m_lastError = qx::dao::destroy_all<T>(database(pDatabase)); 00565 return m_lastError; 00566 } 00567 00574 virtual QSqlError qxDestroyByQuery(const qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) 00575 { 00576 m_lastError = qx::dao::destroy_by_query<T>(query, database(pDatabase)); 00577 return m_lastError; 00578 } 00579 00586 virtual QSqlError qxDestroyRow(int row, QSqlDatabase * pDatabase = NULL) 00587 { 00588 if ((row < 0) || (row >= m_model.count())) { return QSqlError(); } 00589 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return QSqlError(); } 00590 m_lastError = qx::dao::destroy_by_id((* pItem), database(pDatabase)); 00591 return m_lastError; 00592 } 00593 00594 virtual QSqlError qxExecuteQuery(qx::QxSqlQuery & query, QSqlDatabase * pDatabase = NULL) 00595 { 00596 clear(); 00597 type_collection tmp; 00598 m_lastError = qx::dao::execute_query(query, tmp, database(pDatabase)); 00599 00600 if (tmp.count() <= 0) { return m_lastError; } 00601 beginInsertRows(QModelIndex(), 0, (tmp.count() - 1)); 00602 m_model = tmp; 00603 endInsertRows(); 00604 return m_lastError; 00605 } 00606 00607 virtual qx_bool qxExist(const QVariant & id, QSqlDatabase * pDatabase = NULL) 00608 { 00609 type_ptr pItem = type_ptr(new T()); 00610 if (! m_pDataMemberId) { qDebug("[QxOrm] problem with 'qxExist()' method : '%s'", "data member id not registered"); qAssert(false); } 00611 if (! m_pDataMemberId) { return qx_bool(false); } 00612 m_pDataMemberId->fromVariant(pItem.get(), id); 00613 return qx::dao::exist((* pItem), database(pDatabase)); 00614 } 00615 00616 virtual qx::QxInvalidValueX qxValidate(const QStringList & groups = QStringList()) 00617 { 00618 return qx::validate(m_model, groups); 00619 } 00620 00621 virtual qx::QxInvalidValueX qxValidateRow(int row, const QStringList & groups = QStringList()) 00622 { 00623 if ((row < 0) || (row >= m_model.count())) { return qx::QxInvalidValueX(); } 00624 type_ptr pItem = m_model.getByIndex(row); if (! pItem) { return qx::QxInvalidValueX(); } 00625 return qx::validate((* pItem), groups); 00626 } 00627 00628 protected: 00629 00630 void updateKey(int row) 00631 { 00632 if ((row < 0) || (row >= m_model.count())) { return; } 00633 type_ptr pItem = m_model.getByIndex(row); if (! pItem || ! m_pDataMemberId) { return; } 00634 type_primary_key currPrimaryKey = m_model.getKeyByIndex(row); 00635 QVariant vCurrPrimaryKey = qx::cvt::to_variant(currPrimaryKey); 00636 QVariant vNextPrimaryKey = m_pDataMemberId->toVariant(pItem.get()); 00637 if ((vCurrPrimaryKey == vNextPrimaryKey) || (! vNextPrimaryKey.isValid())) { return; } 00638 if (! qx::trait::is_valid_primary_key(vNextPrimaryKey)) { return; } 00639 type_primary_key updatedPrimaryKey; 00640 qx::cvt::from_variant(vNextPrimaryKey, updatedPrimaryKey); 00641 if (m_model.exist(updatedPrimaryKey)) { return; } 00642 m_model.removeByIndex(row); 00643 m_model.insert(row, updatedPrimaryKey, pItem); 00644 } 00645 00646 void updateAllKeys() 00647 { 00648 for (long l = 0; l < m_model.count(); l++) 00649 { this->updateKey(l); } 00650 } 00651 00652 }; 00653 00654 } // namespace qx 00655 00656 #endif // _QX_MODEL_H_