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