Fraxinus  17.12
An IGT application
cxTreeRepository.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 #include "cxTreeRepository.h"
33 #include "cxPatientModelService.h"
34 #include "cxDefinitions.h"
35 #include "cxData.h"
36 #include "cxTreeNode.h"
37 #include "cxDataTreeNode.h"
38 #include "cxSpaceTreeNode.h"
39 #include "cxGroupTreeNode.h"
40 #include "cxTopTreeNode.h"
41 #include "cxToolTreeNode.h"
42 #include "cxLogger.h"
43 #include "cxTrackingService.h"
44 #include "cxActiveData.h"
45 #include "cxVisServices.h"
46 #include "cxShowDataTreeNode.h"
47 #include "cxViewServiceTreeNode.h"
48 #include "cxViewGroupTreeNode.h"
49 #include "cxViewService.h"
50 #include "cxStringListProperty.h"
51 #include "cxStringProperty.h"
52 
53 namespace cx
54 {
55 
56 boost::shared_ptr<QWidget> WidgetTypeRepository::findMetricWidget(DataPtr data)
57 {
58  for (unsigned i=0; i<mWidgets.size(); ++i)
59  {
60  boost::shared_ptr<SingleMetricWidget> w = boost::dynamic_pointer_cast<SingleMetricWidget>(mWidgets[i]);
61  if(w && w->getData() && data && w->getData()->getUid() == data->getUid())
62  return w;
63  }
64  return boost::shared_ptr<QWidget>();
65 }
66 
67 void WidgetTypeRepository::add(boost::shared_ptr<QWidget> widget)
68 {
69  mWidgets.push_back(widget);
70 }
71 
72 //---------------------------------------------------------
73 //---------------------------------------------------------
74 //---------------------------------------------------------
75 
77 {
78  TreeRepositoryPtr retval(new TreeRepository(options, services));
79  retval->mSelf = retval;
80  retval->insertTopNode();
81  return retval;
82 }
83 
84 TreeRepository::TreeRepository(XmlOptionFile options, VisServicesPtr services) :
85  mInvalid(true),
86  mServices(services),
87  mOptions(options)
88 {
89  this->createVisibilityProperty();
90  this->createModeProperty();
91 
92  mWidgetTypeRepository.reset(new WidgetTypeRepository());
93 
94  this->startListen();
95 }
96 
97 void TreeRepository::createVisibilityProperty()
98 {
99  QStringList allNodeTypes = QStringList() << "data" << "metric" << "image" << "model" << "tool" << "view";
100  mVisibilityProperty = StringListProperty::initialize("visible_node_types",
101  "Visibility",
102  "Select visible node types",
103  allNodeTypes,
104  allNodeTypes,
105  mOptions.getElement());
106  connect(mVisibilityProperty.get(), &StringListProperty::changed, this, &TreeRepository::invalidate);
107 }
108 
109 void TreeRepository::createModeProperty()
110 {
111  QStringList allModes = QStringList() << "spaces" << "flat";
112 
113  mModeProperty = StringProperty::initialize("mode",
114  "mode",
115  "Node display mode",
116  allModes.front(),
117  allModes,
118  mOptions.getElement());
119  connect(mModeProperty.get(), &Property::changed, this, &TreeRepository::loaded);
120 }
121 
123 {
124  this->stopListen();
125 }
126 
128 {
129 // CX_LOG_CHANNEL_DEBUG("CA") << "TreeRepository::update(), invalid=" << mInvalid;
130  if (mInvalid)
131  this->rebuild();
132  mInvalid = true;
133 }
134 
136 {
137 // CX_LOG_CHANNEL_DEBUG("CA") << "TreeRepository::invalidate()";
138  mInvalid = true;
139  emit invalidated();
140 }
141 
142 void TreeRepository::startListen()
143 {
144  connect(this->getServices()->patient().get(), &PatientModelService::patientChanged, this, &TreeRepository::loaded);
145  connect(this->getServices()->patient().get(), &PatientModelService::dataAddedOrRemoved, this, &TreeRepository::invalidate);
146  connect(this->getServices()->tracking().get(), &TrackingService::stateChanged, this, &TreeRepository::loaded);
147  connect(this->getServices()->patient()->getActiveData().get(), &ActiveData::activeDataChanged, this, &TreeRepository::onChanged);
148 }
149 
150 void TreeRepository::stopListen()
151 {
152  disconnect(this->getServices()->patient().get(), &PatientModelService::patientChanged, this, &TreeRepository::loaded);
153  disconnect(this->getServices()->patient().get(), &PatientModelService::dataAddedOrRemoved, this, &TreeRepository::invalidate);
154  disconnect(this->getServices()->tracking().get(), &TrackingService::stateChanged, this, &TreeRepository::loaded);
155  disconnect(this->getServices()->patient()->getActiveData().get(), &ActiveData::activeDataChanged, this, &TreeRepository::onChanged);
156 }
157 
158 std::vector<TreeNodePtr> TreeRepository::getNodes()
159 {
160  return mNodes;
161 }
162 
164 {
165  for (unsigned i=0; i<mNodes.size(); ++i)
166  {
167  if (mNodes[i]->getUid()==uid)
168  return mNodes[i];
169  }
170  return TreeNodePtr();
171 }
172 
174 {
175  std::vector<TreeNodePtr> all = this->getNodes();
176  for (unsigned i=0; i<all.size(); ++i)
177  if (all[i]->getUid() == "node::invisible_top")
178  return all[i];
179  CX_LOG_CHANNEL_DEBUG("CA") << "invalid tree - did not find top node";
180  return TreeNodePtr();
181 }
182 
184 {
185  return mServices;
186 }
187 
189 {
190  return mWidgetTypeRepository;
191 }
192 
193 QString TreeRepository::getMode() const
194 {
195  return mModeProperty->getValue();
196 }
197 
199 {
200  return mVisibilityProperty->getValue();
201 }
202 
204 {
205  return mVisibilityProperty->getValueRange();
206 }
207 
208 void TreeRepository::insertTopNode()
209 {
210  // TreeNodePtr topnode(new TopTreeNode(mSelf));
211 // mNodes.push_back(topnode);
212  this->appendNode(new TopTreeNode(mSelf));
213 // CX_LOG_CHANNEL_DEBUG("CA") << " - built topnode";
214 }
215 
216 void TreeRepository::rebuild()
217 {
218 // CX_LOG_CHANNEL_DEBUG("CA") << " reuild tree...";
219  for (unsigned i=0; i<mNodes.size(); ++i)
220  disconnect(mNodes[i].get(), &TreeNode::changed, this, &TreeRepository::onChanged);
221  mNodes.clear();
222 
223  this->insertTopNode();
224 
225  QStringList groups = QStringList() << "tool" << "data" << "space" << "view";
226  for (unsigned i=0; i<groups.size(); ++i)
227  this->insertGroupNode(groups[i]);
228 
229  this->insertSpaceNode(CoordinateSystem(csREF));
230 
231  std::map<QString, DataPtr> source = this->getServices()->patient()->getDatas();
232  for (std::map<QString, DataPtr>::const_iterator iter = source.begin(); iter != source.end(); ++iter)
233  {
234  this->insertDataNode(iter->second);
235  }
236  for (std::map<QString, DataPtr>::const_iterator iter = source.begin(); iter != source.end(); ++iter)
237  {
238  QString space = iter->second->getParentSpace();
239  if (space.isEmpty())
240  continue;
241  if (source.count(space))
242  continue;
243  this->insertSpaceNode(CoordinateSystem(csDATA, space));
244  }
245 
246  this->insertSpaceNode(CoordinateSystem(csPATIENTREF));
247 
248  std::map<QString, ToolPtr> tools = this->getServices()->tracking()->getTools();
249  for (std::map<QString, ToolPtr>::const_iterator iter = tools.begin(); iter != tools.end(); ++iter)
250  {
251  this->insertToolNode(iter->second);
252  }
253 
254  for (unsigned i=0; i<this->getServices()->view()->groupCount(); ++i)
255  {
256  this->appendNode(new ViewGroupTreeNode(mSelf, i));
257  }
258 
259 // for (unsigned i=0; i<mNodes.size(); ++i)
260 // CX_LOG_CHANNEL_DEBUG("CA") << " node: " << mNodes[i]->getUid();
261 }
262 
263 void TreeRepository::insertGroupNode(QString groupname)
264 {
265  if (this->getNodeForGroup(groupname))
266  return;
267  if (groupname=="view")
268  this->appendNode(new ViewServiceTreeNode(mSelf));
269  else
270  this->appendNode(new GroupTreeNode(mSelf, groupname));
271 }
272 
274 {
275  return this->getNode(QString("group_%1").arg(groupname));
276 }
277 
278 void TreeRepository::insertToolNode(ToolPtr tool)
279 {
280  if (this->getNode(tool->getUid()))
281  return;
282  this->appendNode(new ToolTreeNode(mSelf, tool));
283 }
284 
285 void TreeRepository::insertDataNode(DataPtr data)
286 {
287  if (this->getNode(data->getUid()))
288  return;
289 
290  this->appendNode(new DataTreeNode(mSelf, data));
291 
292  this->appendNode(new ShowVolumeDataTreeNode(mSelf, data));
293  this->appendNode(new ShowSlice2DDataTreeNode(mSelf, data));
294  this->appendNode(new ShowSlice3DDataTreeNode(mSelf, data));
295 }
296 
297 void TreeRepository::appendNode(TreeNode* rawNode)
298 {
299  TreeNodePtr bnode(rawNode);
300  TreeNodePtr node(new CachedTreeNode(bnode));
301 
302  if (!this->getNode(node->getUid()))
303  {
304  // TODO need a more detailed change policy: invalidate only when parent/childe
305  // structure is changed.
306 // connect(node.get(), &TreeNode::changed, this, &TreeRepository::invalidated);
307  connect(node.get(), &TreeNode::changed, this, &TreeRepository::onChanged);
308  mNodes.push_back(node);
309  }
310 }
311 
312 void TreeRepository::onChanged()
313 {
314  TreeNode* node = dynamic_cast<TreeNode*>(sender());
315 // CX_LOG_CHANNEL_DEBUG("CA") << " TreeRepository::onChanged() node=" << ((node)?node->getName():"-");
316  emit changed(node);
317 }
318 
319 void TreeRepository::insertSpaceNode(CoordinateSystem space)
320 {
321  if (this->getNode(space.toString()) || this->getNode(space.mRefObject))
322  return;
323  this->appendNode(new SpaceTreeNode(mSelf, space));
324 }
325 
326 
327 } // namespace cx
boost::shared_ptr< class TreeRepository > TreeRepositoryPtr
TreeNodePtr getNodeForGroup(QString groupname)
boost::shared_ptr< TreeNode > TreeNodePtr
void changed()
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:61
csREF
the data reference space (r) using LPS (left-posterior-superior) coordinates.
csDATA
a datas space (d)
static StringListPropertyPtr initialize(const QString &uid, QString name, QString help, QStringList value, QStringList range, QDomNode root=QDomNode())
csPATIENTREF
the patient/tool reference space (pr)
boost::shared_ptr< class Data > DataPtr
QStringList getVisibleNodeTypes() const
std::vector< TreeNodePtr > getNodes()
void activeDataChanged(const QString &uId)
TreeNodePtr getTopNode()
QString getMode() const
#define CX_LOG_CHANNEL_DEBUG(channel)
Definition: cxLogger.h:128
boost::shared_ptr< class WidgetTypeRepository > WidgetTypeRepositoryPtr
Identification of a Coordinate system.
static TreeRepositoryPtr create(XmlOptionFile options, VisServicesPtr services)
void add(boost::shared_ptr< QWidget > widget)
QString mRefObject
for tool, sensor and data we need a object uid to define the coordinate system
void changed()
emit when the underlying data value is changed: The user interface will be updated.
static StringPropertyPtr initialize(const QString &uid, QString name, QString help, QString value, QStringList range, QDomNode root=QDomNode())
boost::shared_ptr< QWidget > findMetricWidget(DataPtr data)
QStringList getAllNodeTypes() const
VisServicesPtr getServices()
WidgetTypeRepositoryPtr getWidgetTypeRepository()
Helper class for xml files used to store ssc/cx data.
TreeNodePtr getNode(QString uid)
Namespace for all CustusX production code.
boost::shared_ptr< class Tool > ToolPtr