Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
QmitkXnatTreeModel.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "QmitkXnatTreeModel.h"
19 
20 #include <QmitkMimeTypes.h>
21 
22 #include <QIcon>
23 
24 #include <ctkXnatDataModel.h>
25 #include <ctkXnatExperiment.h>
26 #include <ctkXnatFile.h>
27 #include <ctkXnatProject.h>
28 #include <ctkXnatResource.h>
29 #include <ctkXnatResourceCatalogXmlParser.h>
30 #include <ctkXnatResourceFolder.h>
31 #include <ctkXnatScan.h>
32 #include <ctkXnatScanFolder.h>
33 #include <ctkXnatSubject.h>
34 
35 #include <iostream>
36 
38 {
39 }
40 
41 QModelIndexList QmitkXnatTreeModel::match(
42  const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const
43 {
44  QModelIndexList result;
45  uint matchType = flags & 0x0F;
46  Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
47  bool recurse = flags & Qt::MatchRecursive;
48  bool wrap = flags & Qt::MatchWrap;
49  bool allHits = (hits == -1);
50  QString text; // only convert to a string if it is needed
51  QModelIndex p = parent(start);
52  int from = start.row();
53  int to = rowCount(p);
54 
55  // iterates twice if wrapping
56  for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i)
57  {
58  for (int r = from; (r < to) && (allHits || result.count() < hits); ++r)
59  {
60  QModelIndex idx = index(r, start.column(), p);
61  if (!idx.isValid())
62  continue;
63  QVariant v = data(idx, role);
64  // QVariant based matching
65  if (matchType == Qt::MatchExactly)
66  {
67  if (value != v)
68  result.append(idx);
69  }
70  else
71  { // QString based matching
72  if (text.isEmpty()) // lazy conversion
73  text = value.toString();
74  QString t = v.toString();
75  switch (matchType)
76  {
77  case Qt::MatchRegExp:
78  if (!QRegExp(text, cs).exactMatch(t))
79  result.append(idx);
80  break;
81  case Qt::MatchWildcard:
82  if (!QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t))
83  result.append(idx);
84  break;
85  case Qt::MatchStartsWith:
86  if (!t.startsWith(text, cs))
87  result.append(idx);
88  break;
89  case Qt::MatchEndsWith:
90  if (!t.endsWith(text, cs))
91  result.append(idx);
92  break;
93  case Qt::MatchFixedString:
94  if (!t.compare(text, cs) == 0)
95  result.append(idx);
96  break;
97  case Qt::MatchContains:
98  default:
99  if (!t.contains(text, cs))
100  result.append(idx);
101  }
102  }
103  if (recurse && hasChildren(idx))
104  { // search the hierarchy
105  result += match(index(0, idx.column(), idx),
106  role,
107  (text.isEmpty() ? value : text),
108  (allHits ? -1 : hits - result.count()),
109  flags);
110  }
111  }
112  // prepare for the next iteration
113  from = 0;
114  to = start.row();
115  }
116  return result;
117 }
118 
119 void QmitkXnatTreeModel::fetchMore(const QModelIndex &index)
120 {
121  try
122  {
123  ctkXnatTreeModel::fetchMore(index);
124  }
125  catch (ctkRuntimeException e)
126  {
128  emit Error(index);
129  }
130 }
131 
132 QVariant QmitkXnatTreeModel::data(const QModelIndex &index, int role) const
133 {
134  if (!index.isValid())
135  {
136  return QVariant();
137  }
138 
139  if (role == Qt::DecorationRole)
140  {
141  ctkXnatObject *xnatObject = this->xnatObject(index);
142  QString path;
143 
144  if (dynamic_cast<ctkXnatDataModel *>(xnatObject))
145  {
146  path = ":/xnat-module/xnat-server.png";
147  }
148  else if (dynamic_cast<ctkXnatProject *>(xnatObject))
149  {
150  path = ":/xnat-module/xnat-project.png";
151  }
152  else if (dynamic_cast<ctkXnatSubject *>(xnatObject))
153  {
154  path = ":/xnat-module/xnat-subject.png";
155  }
156  else if (dynamic_cast<ctkXnatExperiment *>(xnatObject))
157  {
158  path = ":/xnat-module/xnat-experiment.png";
159  }
160  else if (dynamic_cast<ctkXnatResourceFolder *>(xnatObject))
161  {
162  path = ":/xnat-module/xnat-folder.png";
163  }
164  else if (dynamic_cast<ctkXnatResource *>(xnatObject))
165  {
166  path = ":/xnat-module/xnat-resource.png";
167  }
168  else if (dynamic_cast<ctkXnatScanFolder *>(xnatObject))
169  {
170  path = ":/xnat-module/xnat-folder.png";
171  }
172  else if (dynamic_cast<ctkXnatScan *>(xnatObject))
173  {
174  path = ":/xnat-module/xnat-scan.png";
175  }
176  else if (dynamic_cast<ctkXnatFile *>(xnatObject))
177  {
178  path = ":/xnat-module/xnat-file.png";
179  }
180  return QIcon(path);
181  }
182  return ctkXnatTreeModel::data(index, role);
183 }
184 
186  const QMimeData *data, Qt::DropAction action, int /*row*/, int /*column*/, const QModelIndex &parent)
187 {
188  if (action == Qt::IgnoreAction)
189  return true;
190 
191  // Return true if data can be handled
192  bool returnVal(false);
193 
194  if (data->hasFormat(QmitkMimeTypes::DataNodePtrs))
195  {
196  returnVal = true;
197  QList<mitk::DataNode *> droppedNodes = QmitkMimeTypes::ToDataNodePtrList(data);
198  ctkXnatObject *parentXnatObj = this->xnatObject(parent);
199  emit ResourceDropped(droppedNodes, parentXnatObj, parent);
200  }
201  return returnVal;
202 }
203 
205 {
206  return Qt::CopyAction;
207 }
208 
209 Qt::ItemFlags QmitkXnatTreeModel::flags(const QModelIndex &index) const
210 {
211  Qt::ItemFlags defaultFlags = ctkXnatTreeModel::flags(index);
212 
213  if (index.isValid())
214  {
215  bool droppingAllowed = dynamic_cast<ctkXnatSubject *>(this->xnatObject(index)) != nullptr;
216  droppingAllowed |= dynamic_cast<ctkXnatExperiment *>(this->xnatObject(index)) != nullptr;
217  droppingAllowed |= dynamic_cast<ctkXnatResource *>(this->xnatObject(index)) != nullptr;
218  droppingAllowed |= dynamic_cast<ctkXnatResourceFolder *>(this->xnatObject(index)) != nullptr;
219 
220  // No dropping at project, session or data model level allowed
221  if (droppingAllowed)
222  {
223  return Qt::ItemIsDropEnabled | defaultFlags;
224  }
225  else
226  {
227  return defaultFlags;
228  }
229  }
230  else
231  return defaultFlags;
232 }
233 
234 ctkXnatObject *QmitkXnatTreeModel::InternalGetXnatObjectFromUrl(const QString &xnatObjectType,
235  const QString &url,
236  ctkXnatObject *parent)
237 {
238  // 1. Find project
239  int start = url.lastIndexOf(xnatObjectType);
240  if (start == -1)
241  return nullptr;
242 
243  start += xnatObjectType.length();
244  int length = url.indexOf("/", start);
245  length -= start;
246 
247  parent->fetch();
248  QList<ctkXnatObject *> children = parent->children();
249  foreach (ctkXnatObject *child, children)
250  {
251  if (url.indexOf(child->resourceUri()) != -1)
252  {
253  return child;
254  }
255  }
256  return nullptr;
257 }
258 
259 ctkXnatObject *QmitkXnatTreeModel::GetXnatObjectFromUrl(const QString &url)
260 {
261  QModelIndex index = this->index(0, 0, QModelIndex());
262  ctkXnatObject *currentXnatObject = nullptr;
263  currentXnatObject = this->xnatObject(index);
264  if (currentXnatObject != nullptr)
265  {
266  // 1. Find project
267  ctkXnatObject *project = nullptr;
268  project = this->InternalGetXnatObjectFromUrl("projects/", url, currentXnatObject);
269 
270  // 2. Find subject
271  ctkXnatObject *subject = nullptr;
272  if (project != nullptr)
273  {
274  currentXnatObject = project;
275  subject = this->InternalGetXnatObjectFromUrl("subjects/", url, project);
276  }
277 
278  // 3. Find experiment
279  ctkXnatObject *experiment = nullptr;
280  if (subject != nullptr)
281  {
282  currentXnatObject = subject;
283  experiment = this->InternalGetXnatObjectFromUrl("experiments/", url, subject);
284  }
285 
286  // 4. Find scan
287  ctkXnatObject *scan = nullptr;
288  if (experiment != nullptr)
289  {
290  currentXnatObject = experiment;
291  scan = this->InternalGetXnatObjectFromUrl("scans/", url, experiment);
292  }
293 
294  if (scan != nullptr)
295  {
296  scan->fetch();
297  QList<ctkXnatObject *> scans = scan->children();
298  foreach (ctkXnatObject *child, scans)
299  {
300  if (url.indexOf(child->resourceUri()) != -1)
301  {
302  return child;
303  }
304  }
305  }
306 
307  currentXnatObject->fetch();
308  QList<ctkXnatObject *> bla = currentXnatObject->children();
309  foreach (ctkXnatObject *child, bla)
310  {
311  if (child->name() == "Resources")
312  return child;
313  }
314  }
315  return nullptr;
316 }
void Error(const QModelIndex &idx)
ctkXnatObject * GetXnatObjectFromUrl(const QString &)
virtual Qt::DropActions supportedDropActions()
static QList< mitk::DataNode * > ToDataNodePtrList(const QByteArray &ba)
static const QString DataNodePtrs
QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const override
unsigned int uint
virtual Qt::ItemFlags flags(const QModelIndex &index) const
void fetchMore(const QModelIndex &index) override
static bool HandleErrorMessage(const char *_errorMsg)
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
void ResourceDropped(const QList< mitk::DataNode * > &, ctkXnatObject *, const QModelIndex &)
virtual QVariant data(const QModelIndex &index, int role) const