qCTKDCMTKModel.cxx 12 KB

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