Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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