qCTKDCMTKModel.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. #include <QStringList>
  2. #include <QSqlDriver>
  3. #include <QSqlError>
  4. #include <QSqlQuery>
  5. #include <QSqlQueryModel>
  6. #include <QSqlRecord>
  7. #include <QTime>
  8. #include <QDebug>
  9. #include "qCTKDCMTKModel.h"
  10. struct Node;
  11. //------------------------------------------------------------------------------
  12. class qCTKDCMTKModelPrivate:public qCTKPrivate<qCTKDCMTKModel>
  13. {
  14. public:
  15. qCTKDCMTKModelPrivate();
  16. ~qCTKDCMTKModelPrivate();
  17. void init();
  18. enum IndexType{
  19. RootType,
  20. PatientType,
  21. StudyType,
  22. SeriesType,
  23. ImageType
  24. };
  25. void fetch(const QModelIndex& index, int limit);
  26. Node* createNode(int row, int column, const QModelIndex& parent)const;
  27. Node* nodeFromIndex(const QModelIndex& index)const;
  28. QVariant value(const QModelIndex& index, int row, int field)const;
  29. QString generateQuery(const QString& fields, const QString& table, const QString& conditions = QString())const;
  30. void updateQueries(Node* node)const;
  31. Node* RootNode;
  32. QSqlDatabase DataBase;
  33. QStringList Headers;
  34. QString Sort;
  35. };
  36. //------------------------------------------------------------------------------
  37. struct Node
  38. {
  39. ~Node()
  40. {
  41. foreach(Node* node, this->Children)
  42. {
  43. delete node;
  44. }
  45. this->Children.clear();
  46. }
  47. qCTKDCMTKModelPrivate::IndexType Type;
  48. Node* Parent;
  49. QVector<Node*> Children;
  50. int Row;
  51. int Column;
  52. QSqlQuery Query;
  53. QString UID;
  54. int RowCount;
  55. bool End;
  56. bool Fetching;
  57. };
  58. //------------------------------------------------------------------------------
  59. qCTKDCMTKModelPrivate::qCTKDCMTKModelPrivate()
  60. {
  61. this->RootNode = 0;
  62. }
  63. //------------------------------------------------------------------------------
  64. qCTKDCMTKModelPrivate::~qCTKDCMTKModelPrivate()
  65. {
  66. delete this->RootNode;
  67. this->RootNode = 0;
  68. }
  69. //------------------------------------------------------------------------------
  70. void qCTKDCMTKModelPrivate::init()
  71. {
  72. QCTK_P(qCTKDCMTKModel);
  73. this->Headers = QStringList() << "Name" << "Age" << "Scan" << "Date" << "Subject ID"
  74. << "Number" << "Institution" << "Referrer" << "Performer";
  75. }
  76. //------------------------------------------------------------------------------
  77. Node* qCTKDCMTKModelPrivate::nodeFromIndex(const QModelIndex& index)const
  78. {
  79. return index.isValid() ? reinterpret_cast<Node*>(index.internalPointer()) : this->RootNode;
  80. }
  81. //------------------------------------------------------------------------------
  82. Node* qCTKDCMTKModelPrivate::createNode(int row, int column, const QModelIndex& parent)const
  83. {
  84. QCTK_P(const qCTKDCMTKModel);
  85. Node* node = new Node;
  86. Node* nodeParent = 0;
  87. if (row == -1 || column == -1)
  88. {// root node
  89. node->Type = qCTKDCMTKModelPrivate::RootType;
  90. node->Parent = 0;
  91. }
  92. else
  93. {
  94. nodeParent = this->nodeFromIndex(parent);
  95. nodeParent->Children.push_back(node);
  96. node->Parent = (nodeParent == this->RootNode ? 0: nodeParent);
  97. node->Type = qCTKDCMTKModelPrivate::IndexType(nodeParent->Type + 1);
  98. }
  99. node->Row = row;
  100. node->Column = column;
  101. if (node->Type != qCTKDCMTKModelPrivate::RootType)
  102. {
  103. int field = nodeParent->Query.record().indexOf("UID");
  104. node->UID = this->value(parent, row, field).toString();
  105. }
  106. node->RowCount = 0;
  107. node->End = false;
  108. node->Fetching = false;
  109. this->updateQueries(node);
  110. return node;
  111. }
  112. //------------------------------------------------------------------------------
  113. QVariant qCTKDCMTKModelPrivate::value(const QModelIndex& parent, int row, int column) const
  114. {
  115. Node* node = this->nodeFromIndex(parent);
  116. if (row >= node->RowCount)
  117. {
  118. const_cast<qCTKDCMTKModelPrivate *>(this)->fetch(parent, row + 256);
  119. }
  120. if (!node->Query.seek(row))
  121. {
  122. qDebug() << node->Query.lastError();
  123. return QVariant();
  124. }
  125. return node->Query.value(column);
  126. }
  127. //------------------------------------------------------------------------------
  128. QString qCTKDCMTKModelPrivate::generateQuery(const QString& fields, const QString& table, const QString& conditions)const
  129. {
  130. QString res = QString("SELECT ") + fields + QString(" FROM ") + table;
  131. if (!conditions.isEmpty())
  132. {
  133. res += QString(" WHERE ") + conditions;
  134. }
  135. if (!this->Sort.isEmpty())
  136. {
  137. res += QString(" ORDER BY ") + this->Sort;
  138. }
  139. return res;
  140. }
  141. //------------------------------------------------------------------------------
  142. void qCTKDCMTKModelPrivate::updateQueries(Node* node)const
  143. {
  144. // are you kidding me, it should be virtualized here :-)
  145. QString query;
  146. switch(node->Type)
  147. {
  148. default:
  149. Q_ASSERT(node->Type == qCTKDCMTKModelPrivate::RootType);
  150. break;
  151. case qCTKDCMTKModelPrivate::RootType:
  152. //query = QString("SELECT FROM ");
  153. query = this->generateQuery("UID as UID, PatientsName as Name, PatientsAge as Age, PatientsBirthDate as Date, PatientID as \"Subject ID\"","Patients");
  154. break;
  155. case qCTKDCMTKModelPrivate::PatientType:
  156. //query = QString("SELECT FROM Studies WHERE PatientsUID='%1'").arg(node->UID);
  157. query = this->generateQuery("StudyInstanceUID as UID, StudyDescription as Name, ModalitiesInStudy as Scan, StudyDate as Date, AccessionNumber as Number, ReferringPhysician as Institution, ReferringPhysician as Referrer, PerformingPysiciansName as Performer", "Studies",QString("PatientsUID='%1'").arg(node->UID));
  158. break;
  159. case qCTKDCMTKModelPrivate::StudyType:
  160. //query = QString("SELECT SeriesInstanceUID as UID, SeriesDescription as Name, BodyPartExamined as Scan, SeriesDate as Date, AcquisitionNumber as Number FROM Series WHERE StudyInstanceUID='%1'").arg(node->UID);
  161. query = this->generateQuery("SeriesInstanceUID as UID, SeriesDescription as Name, BodyPartExamined as Scan, SeriesDate as Date, AcquisitionNumber as Number","Series",QString("StudyInstanceUID='%1'").arg(node->UID));
  162. break;
  163. case qCTKDCMTKModelPrivate::SeriesType:
  164. //query = QString("SELECT Filename as UID, Filename as Name, SeriesInstanceUID as Date FROM Images WHERE SeriesInstanceUID='%1'").arg(node->UID);
  165. query = this->generateQuery("Filename as UID, Filename as Name, SeriesInstanceUID as Date", "Images", QString("SeriesInstanceUID='%1'").arg(node->UID));
  166. break;
  167. case qCTKDCMTKModelPrivate::ImageType:
  168. break;
  169. }
  170. node->Query = QSqlQuery(query, this->DataBase);
  171. foreach(Node* child, node->Children)
  172. {
  173. this->updateQueries(child);
  174. }
  175. }
  176. //------------------------------------------------------------------------------
  177. void qCTKDCMTKModelPrivate::fetch(const QModelIndex& index, int limit)
  178. {
  179. QCTK_P(qCTKDCMTKModel);
  180. Node* node = this->nodeFromIndex(index);
  181. if (node->End || limit <= node->RowCount || node->Fetching/*|| bottom.column() == -1*/)
  182. {
  183. return;
  184. }
  185. node->Fetching = true;
  186. int newRowCount;
  187. const int oldRowCount = node->RowCount;
  188. // try to seek directly
  189. if (node->Query.seek(limit - 1))
  190. {
  191. newRowCount = limit;
  192. }
  193. else
  194. {
  195. newRowCount = qMax(oldRowCount, 1);
  196. if (node->Query.seek(newRowCount - 1))
  197. {
  198. while (node->Query.next())
  199. {
  200. ++newRowCount;
  201. }
  202. }
  203. else
  204. {
  205. // empty or invalid query
  206. newRowCount = 0;
  207. }
  208. node->End = true; // this is the end.
  209. }
  210. if (newRowCount > 0 && newRowCount > node->RowCount)
  211. {
  212. p->beginInsertRows(index, node->RowCount, newRowCount - 1);
  213. node->RowCount = newRowCount;
  214. node->Fetching = false;
  215. p->endInsertRows();
  216. }
  217. else
  218. {
  219. node->RowCount = newRowCount;
  220. node->Fetching = false;
  221. }
  222. }
  223. //------------------------------------------------------------------------------
  224. qCTKDCMTKModel::qCTKDCMTKModel(QObject* parent)
  225. {
  226. QCTK_INIT_PRIVATE(qCTKDCMTKModel);
  227. qctk_d()->init();
  228. }
  229. //------------------------------------------------------------------------------
  230. qCTKDCMTKModel::~qCTKDCMTKModel()
  231. {
  232. }
  233. //------------------------------------------------------------------------------
  234. bool qCTKDCMTKModel::canFetchMore ( const QModelIndex & parent ) const
  235. {
  236. QCTK_D(const qCTKDCMTKModel);
  237. Node* node = d->nodeFromIndex(parent);
  238. return !node->End;
  239. }
  240. //------------------------------------------------------------------------------
  241. int qCTKDCMTKModel::columnCount ( const QModelIndex & _parent ) const
  242. {
  243. QCTK_D(const qCTKDCMTKModel);
  244. Q_UNUSED(_parent);
  245. return d->Headers.size();
  246. }
  247. //------------------------------------------------------------------------------
  248. QVariant qCTKDCMTKModel::data ( const QModelIndex & index, int role ) const
  249. {
  250. QCTK_D(const qCTKDCMTKModel);
  251. if (role & ~(Qt::DisplayRole | Qt::EditRole))
  252. {
  253. return QVariant();
  254. }
  255. QModelIndex indexParent = this->parent(index);
  256. Node* node = d->nodeFromIndex(indexParent);
  257. Q_ASSERT(node->Row == indexParent.row());
  258. if (index.row() >= node->RowCount)
  259. {
  260. const_cast<qCTKDCMTKModelPrivate *>(d)->fetch(index, index.row());
  261. }
  262. /*
  263. if (!node->Query.seek(index.row()))
  264. {
  265. qDebug() << node->Query.lastError();
  266. return QVariant();
  267. }
  268. */
  269. int field = node->Query.record().indexOf(d->Headers[index.column()]);
  270. if (field < 0)
  271. {
  272. return QVariant();
  273. }
  274. return d->value(indexParent, index.row(), field);
  275. //return node->Query.value(field);
  276. }
  277. //------------------------------------------------------------------------------
  278. void qCTKDCMTKModel::fetchMore ( const QModelIndex & parent )
  279. {
  280. QCTK_D(qCTKDCMTKModel);
  281. Node* node = d->nodeFromIndex(parent);
  282. d->fetch(parent, qMax(node->RowCount, 0) + 256);
  283. }
  284. //------------------------------------------------------------------------------
  285. Qt::ItemFlags qCTKDCMTKModel::flags ( const QModelIndex & index ) const
  286. {
  287. return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
  288. }
  289. //------------------------------------------------------------------------------
  290. bool qCTKDCMTKModel::hasChildren ( const QModelIndex & parent ) const
  291. {
  292. QCTK_D(const qCTKDCMTKModel);
  293. Node* node = d->nodeFromIndex(parent);
  294. return node->RowCount > 0 || (!node->End && node->Query.seek(0));
  295. }
  296. //------------------------------------------------------------------------------
  297. QVariant qCTKDCMTKModel::headerData(int section, Qt::Orientation orientation, int role)const
  298. {
  299. QCTK_D(const qCTKDCMTKModel);
  300. if (role & ~(Qt::DisplayRole | Qt::EditRole))
  301. {
  302. return QVariant();
  303. }
  304. if (orientation == Qt::Vertical)
  305. {
  306. return section;
  307. }
  308. Q_ASSERT(orientation == Qt::Horizontal);
  309. Q_ASSERT(section < d->Headers.size());
  310. return d->Headers[section];
  311. }
  312. //------------------------------------------------------------------------------
  313. QModelIndex qCTKDCMTKModel::index ( int row, int column, const QModelIndex & parent ) const
  314. {
  315. QCTK_D(const qCTKDCMTKModel);
  316. Node* parentNode = d->nodeFromIndex(parent);
  317. Node* node = 0;
  318. foreach(Node* tmpNode, parentNode->Children)
  319. {
  320. if (tmpNode->Row == row &&
  321. tmpNode->Column == column)
  322. {
  323. node = tmpNode;
  324. break;
  325. }
  326. }
  327. if (node == 0)
  328. {
  329. node = d->createNode(row, column, parent);
  330. }
  331. return this->createIndex(row, column, node);
  332. }
  333. //------------------------------------------------------------------------------
  334. QModelIndex qCTKDCMTKModel::parent ( const QModelIndex & index ) const
  335. {
  336. QCTK_D(const qCTKDCMTKModel);
  337. Node* node = d->nodeFromIndex(index);
  338. if (node == 0 || node->Parent == 0)
  339. {
  340. return QModelIndex();
  341. }
  342. return this->createIndex(node->Parent->Row, node->Parent->Column, node->Parent);
  343. }
  344. //------------------------------------------------------------------------------
  345. int qCTKDCMTKModel::rowCount ( const QModelIndex & parent ) const
  346. {
  347. QCTK_D(const qCTKDCMTKModel);
  348. Node* node = d->nodeFromIndex(parent);
  349. if (node->RowCount == 0 && node->End)
  350. {
  351. const_cast<qCTKDCMTKModelPrivate*>(d)->fetch(parent, 256);
  352. }
  353. return node->RowCount;
  354. }
  355. //------------------------------------------------------------------------------
  356. void qCTKDCMTKModel::setDatabase(const QSqlDatabase &db)
  357. {
  358. QCTK_D(qCTKDCMTKModel);
  359. this->beginResetModel();
  360. d->DataBase = db;
  361. delete d->RootNode;
  362. d->RootNode = 0;
  363. if (d->DataBase.tables().empty())
  364. {
  365. Q_ASSERT(d->DataBase.isOpen());
  366. return;
  367. }
  368. d->RootNode = d->createNode(-1, -1, QModelIndex());
  369. this->endResetModel();
  370. bool hasQuerySize = d->RootNode->Query.driver()->hasFeature(QSqlDriver::QuerySize);
  371. if (hasQuerySize && d->RootNode->Query.size() > 0)
  372. {
  373. int newRowCount= d->RootNode->Query.size();
  374. beginInsertRows(QModelIndex(), 0, qMax(0, newRowCount - 1));
  375. d->RootNode->RowCount = newRowCount;
  376. d->RootNode->End = true;
  377. endInsertRows();
  378. }
  379. else
  380. {
  381. d->RootNode->RowCount = 0;
  382. }
  383. d->fetch(QModelIndex(), 256);
  384. }
  385. //------------------------------------------------------------------------------
  386. void qCTKDCMTKModel::sort(int column, Qt::SortOrder order)
  387. {
  388. QCTK_D(qCTKDCMTKModel);
  389. emit layoutAboutToBeChanged();
  390. d->Sort = QString("\"%1\" %2")
  391. .arg(d->Headers[column])
  392. .arg(order == Qt::AscendingOrder ? "ASC" : "DESC");
  393. d->updateQueries(d->RootNode);
  394. emit layoutChanged();
  395. }
  396. //------------------------------------------------------------------------------
  397. bool qCTKDCMTKModel::setHeaderData ( int section, Qt::Orientation orientation, const QVariant & value, int role)
  398. {
  399. QCTK_D(qCTKDCMTKModel);
  400. if (role & ~(Qt::DisplayRole | Qt::EditRole))
  401. {
  402. return false;
  403. }
  404. if (orientation == Qt::Vertical)
  405. {
  406. return false;
  407. }
  408. if (value.toString() == d->Headers[section])
  409. {
  410. return false;
  411. }
  412. d->Headers[section] = value.toString();
  413. emit this->headerDataChanged(orientation, section, section);
  414. return true;
  415. }